LibreOffice Module stoc (master) 1
UriReferenceFactory.cxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 */
19
20#include <sal/config.h>
21
22#include <algorithm>
23#include <cassert>
24#include <cstddef>
25#include <string_view>
26#include <utility>
27#include <vector>
28
29#include <com/sun/star/lang/WrappedTargetRuntimeException.hpp>
30#include <com/sun/star/lang/XMultiComponentFactory.hpp>
31#include <com/sun/star/lang/XServiceInfo.hpp>
32#include <com/sun/star/uno/Any.hxx>
33#include <com/sun/star/uno/Exception.hpp>
34#include <com/sun/star/uno/Reference.hxx>
35#include <com/sun/star/uno/RuntimeException.hpp>
36#include <com/sun/star/uno/Sequence.hxx>
37#include <com/sun/star/uno/XComponentContext.hpp>
38#include <com/sun/star/uno/XInterface.hpp>
39#include <com/sun/star/uri/RelativeUriExcessParentSegments.hpp>
40#include <com/sun/star/uri/XUriReference.hpp>
41#include <com/sun/star/uri/XUriReferenceFactory.hpp>
42#include <com/sun/star/uri/XUriSchemeParser.hpp>
46#include <cppuhelper/weak.hxx>
47#include <rtl/character.hxx>
48#include <rtl/ustrbuf.hxx>
49#include <rtl/ustring.hxx>
50#include <sal/types.h>
51
52#include "UriReference.hxx"
53
54namespace {
55
56bool equalIgnoreEscapeCase(std::u16string_view s1, std::u16string_view s2) {
57 if (s1.size() == s2.size()) {
58 for (size_t i = 0; i < s1.size();) {
59 if (s1[i] == '%' && s2[i] == '%' && s1.size() - i > 2
60 && rtl::isAsciiHexDigit(s1[i + 1])
61 && rtl::isAsciiHexDigit(s1[i + 2])
62 && rtl::isAsciiHexDigit(s2[i + 1])
63 && rtl::isAsciiHexDigit(s2[i + 2])
64 && rtl::compareIgnoreAsciiCase(s1[i + 1], s2[i + 1]) == 0
65 && rtl::compareIgnoreAsciiCase(s1[i + 2], s2[i + 2]) == 0)
66 {
67 i += 3;
68 } else if (s1[i] != s2[i]) {
69 return false;
70 } else {
71 ++i;
72 }
73 }
74 return true;
75 } else {
76 return false;
77 }
78}
79
80sal_Int32 parseScheme(std::u16string_view uriReference) {
81 if (uriReference.size() >= 2 && rtl::isAsciiAlpha(uriReference[0])) {
82 for (size_t i = 0; i < uriReference.size(); ++i) {
83 sal_Unicode c = uriReference[i];
84 if (c == ':') {
85 return i;
86 } else if (!rtl::isAsciiAlpha(c) && !rtl::isAsciiDigit(c)
87 && c != '+' && c != '-' && c != '.')
88 {
89 break;
90 }
91 }
92 }
93 return -1;
94}
95
96class UriReference:
97 public cppu::WeakImplHelper<css::uri::XUriReference>
98{
99public:
100 UriReference(
101 OUString const & scheme, bool bHasAuthority,
102 OUString const & authority, OUString const & path,
103 bool bHasQuery, OUString const & query):
104 m_base(
105 scheme, bHasAuthority, authority, path, bHasQuery,
106 query)
107 {}
108
109 UriReference(const UriReference&) = delete;
110 UriReference& operator=(const UriReference&) = delete;
111
112 virtual OUString SAL_CALL getUriReference() override
113 { return m_base.getUriReference(); }
114
115 virtual sal_Bool SAL_CALL isAbsolute() override
116 { return m_base.isAbsolute(); }
117
118 virtual OUString SAL_CALL getScheme() override
119 { return m_base.getScheme(); }
120
121 virtual OUString SAL_CALL getSchemeSpecificPart() override
122 { return m_base.getSchemeSpecificPart(); }
123
124 virtual sal_Bool SAL_CALL isHierarchical() override
125 { return m_base.isHierarchical(); }
126
127 virtual sal_Bool SAL_CALL hasAuthority() override
128 { return m_base.hasAuthority(); }
129
130 virtual OUString SAL_CALL getAuthority() override
131 { return m_base.getAuthority(); }
132
133 virtual OUString SAL_CALL getPath() override
134 { return m_base.getPath(); }
135
136 virtual sal_Bool SAL_CALL hasRelativePath() override
137 { return m_base.hasRelativePath(); }
138
139 virtual sal_Int32 SAL_CALL getPathSegmentCount() override
140 { return m_base.getPathSegmentCount(); }
141
142 virtual OUString SAL_CALL getPathSegment(sal_Int32 index) override
143 { return m_base.getPathSegment(index); }
144
145 virtual sal_Bool SAL_CALL hasQuery() override
146 { return m_base.hasQuery(); }
147
148 virtual OUString SAL_CALL getQuery() override
149 { return m_base.getQuery(); }
150
151 virtual sal_Bool SAL_CALL hasFragment() override
152 { return m_base.hasFragment(); }
153
154 virtual OUString SAL_CALL getFragment() override
155 { return m_base.getFragment(); }
156
157 virtual void SAL_CALL setFragment(OUString const & fragment) override
158 { m_base.setFragment(fragment); }
159
160 virtual void SAL_CALL clearFragment() override
161 { m_base.clearFragment(); }
162
163private:
164 virtual ~UriReference() override {}
165
167};
168
169css::uno::Reference< css::uri::XUriReference > parseGeneric(
170 OUString const & scheme, OUString const & schemeSpecificPart)
171{
172 sal_Int32 len = schemeSpecificPart.getLength();
173 sal_Int32 i = 0;
174 bool hasAuthority = false;
175 OUString authority;
176 if (len - i >= 2 && schemeSpecificPart[i] == '/'
177 && schemeSpecificPart[i + 1] == '/')
178 {
179 i += 2;
180 sal_Int32 n = i;
181 while (i < len && schemeSpecificPart[i] != '/'
182 && schemeSpecificPart[i] != '?') {
183 ++i;
184 }
185 hasAuthority = true;
186 authority = schemeSpecificPart.copy(n, i - n);
187 }
188 sal_Int32 n = i;
189 i = schemeSpecificPart.indexOf('?', i);
190 if (i == -1) {
191 i = len;
192 }
193 OUString path = schemeSpecificPart.copy(n, i - n);
194 bool hasQuery = false;
195 OUString query;
196 if (i != len) {
197 hasQuery = true;
198 query = schemeSpecificPart.copy(i + 1);
199 }
200 return new UriReference(
201 scheme, hasAuthority, authority, path, hasQuery, query);
202}
203
204struct Segment {
205 bool leadingSlash;
206 bool excessParent;
207 std::u16string_view segment;
208
209 Segment(bool theLeadingSlash, bool theExcessParent, std::u16string_view theSegment):
210 leadingSlash(theLeadingSlash), excessParent(theExcessParent), segment(theSegment) {}
211};
212
213std::pair<std::vector<Segment>, bool> processSegments(
214 std::u16string_view first, std::u16string_view second, bool processSpecialSegments)
215{
216 std::vector<Segment> segments;
217 bool processed = false;
218 std::u16string_view const * half = &first;
219 // later checks for `half == &first` and `half == &second` rely on the fact that `first` and
220 // `second` are passed by value, in case a caller passes the same object for both arguments
221 std::size_t index = 0;
222 bool slash = false;
223 if (index == half->length()) {
224 half = &second;
225 index = 0;
226 }
227 if (index != half->length()) {
228 if ((*half)[index] == u'/') {
229 slash = true;
230 ++index;
231 }
232 for (;;) {
233 if (index == half->length() && half == &first) {
234 half = &second;
235 index = 0;
236 }
237 if (index == half->length()) {
238 if (slash) {
239 segments.emplace_back(true, false, std::u16string_view());
240 }
241 break;
242 }
243 auto const n = std::min(half->find(u'/', index), half->length());
244 auto const leadingSlash = slash;
245 auto const segment = half->substr(index, n - index);
246 auto const process = processSpecialSegments || half == &second;
247 index = n;
248 slash = false;
249 if (index == half->length() && half == &first) {
250 half = &second;
251 index = 0;
252 }
253 if (index != half->length() && (*half)[index] == u'/') {
254 slash = true;
255 ++index;
256 }
257 if (process) {
258 if (segment == u".") {
259 slash = leadingSlash;
260 processed = true;
261 continue;
262 } else if (segment == u"..") {
263 if (segments.empty() || segments.back().excessParent) {
264 segments.emplace_back(leadingSlash, true, segment);
265 } else {
266 if (leadingSlash) {
267 segments.pop_back();
268 }
269 slash = leadingSlash;
270 }
271 processed = true;
272 continue;
273 }
274 }
275 segments.emplace_back(leadingSlash, false, segment);
276 }
277 }
278 return {segments, processed};
279}
280
281class Factory:
282 public cppu::WeakImplHelper<
283 css::lang::XServiceInfo, css::uri::XUriReferenceFactory>
284{
285public:
286 explicit Factory(
287 css::uno::Reference< css::uno::XComponentContext > context):
288 m_context(std::move(context)) {}
289
290 Factory(const Factory&) = delete;
291 Factory& operator=(const Factory&) = delete;
292
293 virtual OUString SAL_CALL getImplementationName() override;
294
295 virtual sal_Bool SAL_CALL supportsService(OUString const & serviceName) override;
296
297 virtual css::uno::Sequence< OUString > SAL_CALL
298 getSupportedServiceNames() override;
299
300 virtual css::uno::Reference< css::uri::XUriReference > SAL_CALL
301 parse(OUString const & uriReference) override;
302
303 virtual css::uno::Reference< css::uri::XUriReference > SAL_CALL
304 makeAbsolute(
305 css::uno::Reference< css::uri::XUriReference > const & baseUriReference,
306 css::uno::Reference< css::uri::XUriReference > const & uriReference,
307 sal_Bool processAdditionalSpecialSegments,
308 css::uri::RelativeUriExcessParentSegments excessParentSegments) override;
309
310 virtual css::uno::Reference< css::uri::XUriReference > SAL_CALL
311 makeRelative(
312 css::uno::Reference< css::uri::XUriReference > const & baseUriReference,
313 css::uno::Reference< css::uri::XUriReference > const & uriReference,
314 sal_Bool preferAuthorityOverRelativePath,
315 sal_Bool preferAbsoluteOverRelativePath,
316 sal_Bool encodeRetainedSpecialSegments) override;
317
318private:
319 virtual ~Factory() override {}
320
321 css::uno::Reference< css::uri::XUriReference > clone(
322 css::uno::Reference< css::uri::XUriReference > const & uriReference)
323 { return parse(uriReference->getUriReference()); }
324
325 css::uno::Reference< css::uno::XComponentContext > m_context;
326};
327
328OUString Factory::getImplementationName()
329{
330 return "com.sun.star.comp.uri.UriReferenceFactory";
331}
332
333sal_Bool Factory::supportsService(OUString const & serviceName)
334{
335 return cppu::supportsService(this, serviceName);
336}
337
338css::uno::Sequence< OUString > Factory::getSupportedServiceNames()
339{
340 css::uno::Sequence< OUString > s { "com.sun.star.uri.UriReferenceFactory" };
341 return s;
342}
343
344css::uno::Reference< css::uri::XUriReference > Factory::parse(
345 OUString const & uriReference)
346{
347 sal_Int32 fragment = uriReference.indexOf('#');
348 if (fragment == -1) {
349 fragment = uriReference.getLength();
350 }
351 OUString scheme;
352 OUString schemeSpecificPart;
353 OUString serviceName;
354 sal_Int32 n = parseScheme(uriReference);
355 assert(n < fragment);
356 if (n >= 0) {
357 scheme = uriReference.copy(0, n);
358 schemeSpecificPart = uriReference.copy(n + 1, fragment - (n + 1));
359 OUStringBuffer buf(128);
360 buf.append("com.sun.star.uri.UriSchemeParser_");
361 for (sal_Int32 i = 0; i < scheme.getLength(); ++i) {
362 sal_Unicode c = scheme[i];
363 if (rtl::isAsciiUpperCase(c)) {
364 buf.append(static_cast<sal_Unicode>(rtl::toAsciiLowerCase(c)));
365 } else if (c == '+') {
366 buf.append("PLUS");
367 } else if (c == '-') {
368 buf.append("HYPHEN");
369 } else if (c == '.') {
370 buf.append("DOT");
371 } else {
372 assert(rtl::isAsciiLowerCase(c) || rtl::isAsciiDigit(c));
373 buf.append(c);
374 }
375 }
376 serviceName = buf.makeStringAndClear();
377 } else {
378 schemeSpecificPart = uriReference.copy(0, fragment);
379 }
380 css::uno::Reference< css::uri::XUriSchemeParser > parser;
381 if (!serviceName.isEmpty()) {
382 css::uno::Reference< css::lang::XMultiComponentFactory > factory(
383 m_context->getServiceManager());
384 if (factory.is()) {
385 css::uno::Reference< css::uno::XInterface > service;
386 try {
387 service = factory->createInstanceWithContext(
388 serviceName, m_context);
389 } catch (css::uno::RuntimeException &) {
390 throw;
391 } catch (const css::uno::Exception &) {
392 css::uno::Any anyEx = cppu::getCaughtException();
393 throw css::lang::WrappedTargetRuntimeException(
394 "creating service " + serviceName,
395 getXWeak(),
396 anyEx);
397 }
398 if (service.is()) {
399 parser.set( service, css::uno::UNO_QUERY_THROW);
400 }
401 }
402 }
403 css::uno::Reference< css::uri::XUriReference > uriRef(
404 parser.is()
405 ? parser->parse(scheme, schemeSpecificPart)
406 : parseGeneric(scheme, schemeSpecificPart));
407 if (uriRef.is() && fragment != uriReference.getLength()) {
408 uriRef->setFragment(uriReference.copy(fragment + 1));
409 }
410 return uriRef;
411}
412
413css::uno::Reference< css::uri::XUriReference > Factory::makeAbsolute(
414 css::uno::Reference< css::uri::XUriReference > const & baseUriReference,
415 css::uno::Reference< css::uri::XUriReference > const & uriReference,
416 sal_Bool processAdditionalSpecialSegments,
417 css::uri::RelativeUriExcessParentSegments excessParentSegments)
418{
419 if (!baseUriReference.is() || !baseUriReference->isAbsolute()
420 || !uriReference.is()) {
421 return nullptr;
422 } else if (uriReference->isAbsolute()) {
423 if (processAdditionalSpecialSegments) {
424 auto const path = uriReference->getPath();
425 auto [segments, proc] = processSegments(path, {}, true);
426 if (proc) {
427 OUStringBuffer abs(uriReference->getScheme() + ":");
428 if (uriReference->hasAuthority()) {
429 abs.append("//" + uriReference->getAuthority());
430 }
431 for (auto const & i : segments)
432 {
433 if (i.excessParent) {
434 switch (excessParentSegments) {
435 case css::uri::RelativeUriExcessParentSegments_ERROR:
436 return nullptr;
437
438 case css::uri::RelativeUriExcessParentSegments_RETAIN:
439 assert(i.segment == u"..");
440 break;
441
442 case css::uri::RelativeUriExcessParentSegments_REMOVE:
443 continue;
444
445 default:
446 assert(false);
447 break;
448 }
449 }
450 if (i.leadingSlash) {
451 abs.append('/');
452 }
453 abs.append(i.segment);
454 }
455 if (uriReference->hasQuery()) {
456 abs.append("?" + uriReference->getQuery());
457 }
458 if (uriReference->hasFragment()) {
459 abs.append("#" + uriReference->getFragment());
460 }
461 return parse(abs.makeStringAndClear());
462 }
463 }
464 return clone(uriReference);
465 } else if (!uriReference->hasAuthority()
466 && uriReference->getPath().isEmpty()) {
467 OUStringBuffer abs(baseUriReference->getScheme() + ":");
468 if (baseUriReference->hasAuthority()) {
469 abs.append("//" + baseUriReference->getAuthority());
470 }
471 abs.append(baseUriReference->getPath());
472 if (uriReference->hasQuery()) {
473 abs.append("?" + uriReference->getQuery());
474 } else if (baseUriReference->hasQuery()) {
475 abs.append("?" + baseUriReference->getQuery());
476 }
477 if (uriReference->hasFragment()) {
478 abs.append("#" + uriReference->getFragment());
479 }
480 return parse(abs.makeStringAndClear());
481 } else {
482 OUStringBuffer abs(128);
483 abs.append(baseUriReference->getScheme() + ":");
484 if (uriReference->hasAuthority()) {
485 abs.append("//" + uriReference->getAuthority());
486 } else if (baseUriReference->hasAuthority()) {
487 abs.append("//" + baseUriReference->getAuthority());
488 }
489 if (uriReference->hasRelativePath()) {
490 auto path1 = baseUriReference->getPath();
491 if (path1.isEmpty()) {
492 if (baseUriReference->hasAuthority()) {
493 path1 = "/";
494 }
495 } else {
496 path1 = path1.copy(0, path1.lastIndexOf('/') + 1);
497 }
498 auto const path2 = uriReference->getPath();
499 auto [segments, _] = processSegments(path1, path2, processAdditionalSpecialSegments);
500 (void)_;
501 for (auto const & i : segments)
502 {
503 if (i.excessParent) {
504 switch (excessParentSegments) {
505 case css::uri::RelativeUriExcessParentSegments_ERROR:
506 return nullptr;
507
508 case css::uri::RelativeUriExcessParentSegments_RETAIN:
509 assert(i.segment == u"..");
510 break;
511
512 case css::uri::RelativeUriExcessParentSegments_REMOVE:
513 continue;
514
515 default:
516 assert(false);
517 break;
518 }
519 }
520 if (i.leadingSlash) {
521 abs.append('/');
522 }
523 abs.append(i.segment);
524 }
525 } else {
526 bool processed = false;
527 if (processAdditionalSpecialSegments) {
528 auto const path = uriReference->getPath();
529 auto [segments, proc] = processSegments(path, {}, true);
530 if (proc) {
531 for (auto const & i : segments)
532 {
533 if (i.excessParent) {
534 switch (excessParentSegments) {
535 case css::uri::RelativeUriExcessParentSegments_ERROR:
536 return nullptr;
537
538 case css::uri::RelativeUriExcessParentSegments_RETAIN:
539 assert(i.segment == u"..");
540 break;
541
542 case css::uri::RelativeUriExcessParentSegments_REMOVE:
543 continue;
544
545 default:
546 assert(false);
547 break;
548 }
549 }
550 if (i.leadingSlash) {
551 abs.append('/');
552 }
553 abs.append(i.segment);
554 }
555 processed = true;
556 }
557 }
558 if (!processed) {
559 abs.append(uriReference->getPath());
560 }
561 }
562 if (uriReference->hasQuery()) {
563 abs.append("?" + uriReference->getQuery());
564 }
565 if (uriReference->hasFragment()) {
566 abs.append("#" + uriReference->getFragment());
567 }
568 return parse(abs.makeStringAndClear());
569 }
570}
571
572css::uno::Reference< css::uri::XUriReference > Factory::makeRelative(
573 css::uno::Reference< css::uri::XUriReference > const & baseUriReference,
574 css::uno::Reference< css::uri::XUriReference > const & uriReference,
575 sal_Bool preferAuthorityOverRelativePath,
576 sal_Bool preferAbsoluteOverRelativePath,
577 sal_Bool encodeRetainedSpecialSegments)
578{
579 if (!baseUriReference.is() || !baseUriReference->isAbsolute()
580 || !uriReference.is()) {
581 return nullptr;
582 } else if (!uriReference->isAbsolute() || uriReference->hasRelativePath()
583 || !baseUriReference->getScheme().equalsIgnoreAsciiCase(
584 uriReference->getScheme())) {
585 return clone(uriReference);
586 } else {
587 OUStringBuffer rel(128);
588 bool omitQuery = false;
589 if ((baseUriReference->hasAuthority() != uriReference->hasAuthority())
590 || !equalIgnoreEscapeCase(
591 baseUriReference->getAuthority(),
592 uriReference->getAuthority()))
593 {
594 if (uriReference->hasAuthority()) {
595 rel.append("//" + uriReference->getAuthority());
596 }
597 rel.append(uriReference->getPath());
598 } else if ((equalIgnoreEscapeCase(
599 baseUriReference->getPath(), uriReference->getPath())
600 || (baseUriReference->getPath() == "/"
601 && uriReference->getPath().isEmpty()))
602 && baseUriReference->hasQuery() == uriReference->hasQuery()
603 && equalIgnoreEscapeCase(
604 baseUriReference->getQuery(), uriReference->getQuery()))
605 {
606 omitQuery = true;
607 } else {
608 sal_Int32 count1 = std::max< sal_Int32 >(
609 baseUriReference->getPathSegmentCount(), 1);
610 sal_Int32 count2 = std::max< sal_Int32 >(
611 uriReference->getPathSegmentCount(), 1);
612 sal_Int32 i = 0;
613 for (; i < std::min(count1, count2) - 1; ++i) {
614 if (!equalIgnoreEscapeCase(
615 baseUriReference->getPathSegment(i),
616 uriReference->getPathSegment(i)))
617 {
618 break;
619 }
620 }
621 if (i == 0
622 && (preferAbsoluteOverRelativePath || uriReference->hasQuery())
623 && (preferAuthorityOverRelativePath
624 || !uriReference->getPath().startsWith("//")))
625 {
626 if (uriReference->getPath().isEmpty()) {
627 if (!baseUriReference->getPath().isEmpty()
628 && baseUriReference->getPath() != "/")
629 {
630 rel.append('/');
631 }
632 } else if (uriReference->getPath() == "/") {
633 if (baseUriReference->getPath().isEmpty()
634 || baseUriReference->getPath() != "/")
635 {
636 rel.append('/');
637 }
638 } else {
639 if (uriReference->getPath().startsWith("//")) {
640 assert(uriReference->hasAuthority());
641 rel.append("//" + uriReference->getAuthority());
642 }
643 rel.append(uriReference->getPath());
644 }
645 } else {
646 bool segments = false;
647 for (sal_Int32 j = i; j < count1 - 1; ++j) {
648 if (segments) {
649 rel.append('/');
650 }
651 rel.append("..");
652 segments = true;
653 }
654 if (i < count2 - 1
655 || (!uriReference->getPathSegment(count2 - 1).isEmpty()))
656 {
657 if (!segments
658 && (uriReference->getPathSegment(i).isEmpty()
659 || (parseScheme(uriReference->getPathSegment(i))
660 >= 0)))
661 {
662 rel.append('.');
663 segments = true;
664 }
665 for (; i < count2; ++i) {
666 if (segments) {
667 rel.append('/');
668 }
669 OUString s(uriReference->getPathSegment(i));
670 if (encodeRetainedSpecialSegments && s == ".") {
671 rel.append("%2E");
672 } else if (encodeRetainedSpecialSegments && s == "..") {
673 rel.append("%2E%2E");
674 } else {
675 rel.append(s);
676 }
677 segments = true;
678 }
679 }
680 }
681 }
682 if (!omitQuery && uriReference->hasQuery()) {
683 rel.append("?" + uriReference->getQuery());
684 }
685 if (uriReference->hasFragment()) {
686 rel.append("#" + uriReference->getFragment());
687 }
688 return parse(rel.makeStringAndClear());
689 }
690}
691
692}
693
694extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
696 css::uno::Sequence<css::uno::Any> const &)
697{
698 return ::cppu::acquire(new Factory(rxContext));
699}
700
701/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
SAL_DLLPUBLIC_EXPORT css::uno::XInterface * com_sun_star_comp_uri_UriReferenceFactory_get_implementation(css::uno::XComponentContext *rxContext, css::uno::Sequence< css::uno::Any > const &)
T * clone(T *const other)
sal_Int64 n
css::uno::Sequence< OUString > getSupportedServiceNames()
OUString getImplementationName()
bool CPPUHELPER_DLLPUBLIC supportsService(css::lang::XServiceInfo *implementation, rtl::OUString const &name)
Any SAL_CALL getCaughtException()
int i
constexpr OUStringLiteral first
index
int fragment
parser
store_handle_type *SAL_CALL query(OStoreObject *pHandle, store_handle_type *)
bool parse(OUString const &uri, SourceProviderScannerData *data)
SwNodeOffset abs(const SwNodeOffset &a)
unsigned char sal_Bool
sal_uInt16 sal_Unicode