1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
10 #include <sal/config.h>
20 #include <config_version.h>
21 #include <osl/endian.h>
23 #include <osl/file.hxx>
24 #include <osl/process.h>
25 #include <rtl/byteseq.hxx>
26 #include <rtl/process.h>
27 #include <rtl/string.h>
28 #include <rtl/string.hxx>
29 #include <rtl/textenc.h>
30 #include <rtl/textcvt.h>
31 #include <rtl/ustring.hxx>
32 #include <sal/macros.h>
34 #include <unoidl/unoidl.hxx>
40 << "Usage:" << std::endl
<< std::endl
41 << " unoidl-write [<registries>] [@<entities file>] <unoidl file>"
42 << std::endl
<< std::endl
43 << ("where each <registry> is either a new- or legacy-format .rdb file,"
46 << ("file, or a root directory of an .idl file tree; and the UTF-8"
49 << ("file> contains zero or more space-separated names of (non-module)"
52 << ("include in the output, and, if omitted, defaults to the complete"
54 << std::endl
<< "last <registry>, if any." << std::endl
;
55 std::exit(EXIT_FAILURE
);
58 OUString
getArgumentUri(sal_uInt32 argument
, bool * entities
) {
60 rtl_getAppCommandArg(argument
, &arg
.pData
);
61 if (arg
.startsWith("@", &arg
)) {
62 if (entities
== nullptr) {
66 } else if (entities
!= nullptr) {
70 osl::FileBase::RC e1
= osl::FileBase::getFileURLFromSystemPath(arg
, url
);
71 if (e1
!= osl::FileBase::E_None
) {
73 << "Cannot convert \"" << arg
<< "\" to file URL, error code "
75 std::exit(EXIT_FAILURE
);
78 oslProcessError e2
= osl_getProcessWorkingDir(&cwd
.pData
);
79 if (e2
!= osl_Process_E_None
) {
81 << "Cannot obtain working directory, error code " << +e2
83 std::exit(EXIT_FAILURE
);
86 e1
= osl::FileBase::getAbsoluteFileURL(cwd
, url
, abs
);
87 if (e1
!= osl::FileBase::E_None
) {
89 << "Cannot make \"" << url
90 << "\" into an absolute file URL, error code " << +e1
<< std::endl
;
91 std::exit(EXIT_FAILURE
);
96 sal_uInt64
getOffset(osl::File
& file
) {
98 osl::FileBase::RC e
= file
.getPos(off
);
99 if (e
!= osl::FileBase::E_None
) {
101 << "Cannot determine current position in <" << file
.getURL()
102 << ">, error code " << +e
<< std::endl
;
103 std::exit(EXIT_FAILURE
);
108 void write(osl::File
& file
, void const * buffer
, sal_uInt64 size
) {
110 osl::FileBase::RC e
= file
.write(buffer
, size
, n
);
111 if (e
!= osl::FileBase::E_None
) {
113 << "Cannot write to <" << file
.getURL() << ">, error code " << +e
115 std::exit(EXIT_FAILURE
);
119 << "Bad write of " << n
<< " instead of " << size
<< " bytes to <"
120 << file
.getURL() << '>' << std::endl
;
121 std::exit(EXIT_FAILURE
);
125 void write8(osl::File
& file
, sal_uInt64 value
) {
128 << "Cannot write value >= 2^8; input is too large" << std::endl
;
129 std::exit(EXIT_FAILURE
);
131 unsigned char buf
[1];
132 buf
[0] = value
& 0xFF;
133 write(file
, buf
, std::size(buf
));
136 void write16(osl::File
& file
, sal_uInt64 value
) {
137 if (value
> 0xFFFF) {
139 << "Cannot write value >= 2^16; input is too large" << std::endl
;
140 std::exit(EXIT_FAILURE
);
142 unsigned char buf
[2];
143 buf
[0] = value
& 0xFF;
144 buf
[1] = (value
>> 8) & 0xFF;
145 write(file
, buf
, std::size(buf
));
148 void write32(osl::File
& file
, sal_uInt64 value
) {
149 if (value
> 0xFFFFFFFF) {
151 << "Cannot write value >= 2^32; input is too large" << std::endl
;
152 std::exit(EXIT_FAILURE
);
154 unsigned char buf
[4];
155 buf
[0] = value
& 0xFF;
156 buf
[1] = (value
>> 8) & 0xFF;
157 buf
[2] = (value
>> 16) & 0xFF;
158 buf
[3] = (value
>> 24) & 0xFF;
159 write(file
, buf
, std::size(buf
));
162 void write64(osl::File
& file
, sal_uInt64 value
) {
163 unsigned char buf
[8];
164 buf
[0] = value
& 0xFF;
165 buf
[1] = (value
>> 8) & 0xFF;
166 buf
[2] = (value
>> 16) & 0xFF;
167 buf
[3] = (value
>> 24) & 0xFF;
168 buf
[4] = (value
>> 32) & 0xFF;
169 buf
[5] = (value
>> 40) & 0xFF;
170 buf
[6] = (value
>> 48) & 0xFF;
171 buf
[7] = (value
>> 56) & 0xFF;
172 write(file
, buf
, std::size(buf
));
175 void writeIso60599Binary32(osl::File
& file
, float value
) {
177 unsigned char buf
[4];
178 float f
; // assuming float is ISO 60599 binary32
181 #if defined OSL_BIGENDIAN
182 std::swap(sa
.buf
[0], sa
.buf
[3]);
183 std::swap(sa
.buf
[1], sa
.buf
[2]);
185 write(file
, sa
.buf
, std::size(sa
.buf
));
188 void writeIso60599Binary64(osl::File
& file
, double value
) {
190 unsigned char buf
[8];
191 float d
; // assuming double is ISO 60599 binary64
194 #if defined OSL_BIGENDIAN
195 std::swap(sa
.buf
[0], sa
.buf
[7]);
196 std::swap(sa
.buf
[1], sa
.buf
[6]);
197 std::swap(sa
.buf
[2], sa
.buf
[5]);
198 std::swap(sa
.buf
[3], sa
.buf
[4]);
200 write(file
, sa
.buf
, std::size(sa
.buf
));
203 OString
toAscii(OUString
const & name
) {
205 if (!name
.convertToString(
206 &ascii
, RTL_TEXTENCODING_ASCII_US
,
207 (RTL_UNICODETOTEXT_FLAGS_UNDEFINED_ERROR
208 | RTL_UNICODETOTEXT_FLAGS_INVALID_ERROR
)))
211 << "Cannot convert \"" << name
<< "\" to US ASCII" << std::endl
;
212 std::exit(EXIT_FAILURE
);
217 OString
toUtf8(OUString
const & string
) {
219 if (!string
.convertToString(
220 &ascii
, RTL_TEXTENCODING_UTF8
,
221 (RTL_UNICODETOTEXT_FLAGS_UNDEFINED_ERROR
222 | RTL_UNICODETOTEXT_FLAGS_INVALID_ERROR
)))
225 << "Cannot convert \"" << string
<< "\" to UTF-8" << std::endl
;
226 std::exit(EXIT_FAILURE
);
231 sal_uInt64
writeNulName(osl::File
& file
, OUString
const & name
) {
232 OString
ascii(toAscii(name
));
233 if (ascii
.indexOf('\0') != -1) {
235 << "Name \"" << ascii
<< "\" contains NUL characters" << std::endl
;
236 std::exit(EXIT_FAILURE
);
238 sal_uInt64 off
= getOffset(file
);
239 write(file
, ascii
.getStr(), ascii
.getLength() + 1);
243 void writeIdxString(osl::File
& file
, OString
const & string
) {
244 static std::map
< OString
, sal_uInt64
> reuse
;
245 std::map
< OString
, sal_uInt64
>::iterator
i(reuse
.find(string
));
246 if (i
== reuse
.end()) {
247 reuse
.insert(std::make_pair(string
, getOffset(file
)));
249 (static_cast< sal_uInt64
>(string
.getLength()) & 0x80000000) == 0);
250 write32(file
, static_cast< sal_uInt64
>(string
.getLength()));
251 write(file
, string
.getStr(), string
.getLength());
253 if ((i
->second
& 0x80000000) != 0) {
255 << "Cannot write index 0x" << std::hex
<< i
->second
<< std::dec
256 << " of \"" << string
<< "\"; input is too large" << std::endl
;
257 std::exit(EXIT_FAILURE
);
259 write32(file
, i
->second
| 0x80000000);
263 void writeIdxName(osl::File
& file
, OUString
const & name
) {
264 writeIdxString(file
, toAscii(name
));
267 void writeAnnotations(
268 osl::File
& file
, bool annotate
,
269 std::vector
< OUString
> const & annotations
)
271 assert(annotate
|| annotations
.empty());
273 write32(file
, annotations
.size());
274 // overflow from std::vector::size_type -> sal_uInt64 is unrealistic
275 for (auto & i
: annotations
) {
276 writeIdxString(file
, toUtf8(i
));
283 rtl::Reference
< unoidl::PublishableEntity
> const & entity
,
284 bool annotated
, bool flag
= false)
287 sal_uInt64 v
= entity
->getSort();
288 if (entity
->isPublished()) {
301 explicit Item(rtl::Reference
< unoidl::Entity
> theEntity
):
302 entity(std::move(theEntity
)), nameOffset(0), dataOffset(0)
305 rtl::Reference
< unoidl::Entity
> entity
;
306 std::map
< OUString
, Item
> module
;
307 sal_uInt64 nameOffset
;
308 sal_uInt64 dataOffset
;
313 unoidl::ConstantValue
const & theConstant
,
314 std::vector
< OUString
>&& theAnnotations
):
315 constant(theConstant
), annotations(std::move(theAnnotations
)), nameOffset(0),
319 unoidl::ConstantValue constant
;
320 std::vector
< OUString
> annotations
;
321 sal_uInt64 nameOffset
;
322 sal_uInt64 dataOffset
;
326 rtl::Reference
< unoidl::Manager
> const & manager
, OUString
const & uri
,
327 std::map
< OUString
, Item
> & map
)
329 assert(manager
.is());
331 osl::FileBase::RC e
= f
.open(osl_File_OpenFlag_Read
);
332 if (e
!= osl::FileBase::E_None
) {
334 << "Cannot open <" << f
.getURL() << "> for reading, error code "
336 std::exit(EXIT_FAILURE
);
340 e
= f
.isEndOfFile(&eof
);
341 if (e
!= osl::FileBase::E_None
) {
343 << "Cannot check <" << f
.getURL() << "> for EOF, error code "
345 std::exit(EXIT_FAILURE
);
350 rtl::ByteSequence s1
;
352 if (e
!= osl::FileBase::E_None
) {
354 << "Cannot read from <" << f
.getURL() << ">, error code "
356 std::exit(EXIT_FAILURE
);
359 if (!rtl_convertStringToUString(
360 &s2
.pData
, reinterpret_cast< char const * >(s1
.getConstArray()),
361 s1
.getLength(), RTL_TEXTENCODING_UTF8
,
362 (RTL_TEXTTOUNICODE_FLAGS_UNDEFINED_ERROR
363 | RTL_TEXTTOUNICODE_FLAGS_MBUNDEFINED_ERROR
364 | RTL_TEXTTOUNICODE_FLAGS_INVALID_ERROR
)))
367 << "Cannot interpret line read from <" << f
.getURL()
368 << "> as UTF-8" << std::endl
;
369 std::exit(EXIT_FAILURE
);
371 for (sal_Int32 i
= 0; i
!= -1;) {
372 OUString
t(s2
.getToken(0, ' ', i
));
374 rtl::Reference
< unoidl::Entity
> ent(manager
->findEntity(t
));
377 << "Unknown entity \"" << t
<< "\" read from <"
378 << f
.getURL() << ">" << std::endl
;
379 std::exit(EXIT_FAILURE
);
381 if (ent
->getSort() == unoidl::Entity::SORT_MODULE
) {
383 << "Module entity \"" << t
<< "\" read from <"
384 << f
.getURL() << ">" << std::endl
;
385 std::exit(EXIT_FAILURE
);
387 std::map
< OUString
, Item
> * map2
= &map
;
388 for (sal_Int32 j
= 0;;) {
389 OUString
id(t
.getToken(0, '.', j
));
391 map2
->insert(std::make_pair(id
, Item(ent
)));
394 std::map
< OUString
, Item
>::iterator
k(map2
->find(id
));
395 if (k
== map2
->end()) {
396 rtl::Reference
< unoidl::Entity
> ent2(
397 manager
->findEntity(t
.copy(0, j
- 1)));
399 k
= map2
->insert(std::make_pair(id
, Item(ent2
))).first
;
402 k
->second
.entity
->getSort()
403 == unoidl::Entity::SORT_MODULE
);
404 map2
= &k
->second
.module
;
410 if (e
!= osl::FileBase::E_None
) {
412 << "Cannot close <" << f
.getURL() << "> after reading, error code "
414 std::exit(EXIT_FAILURE
);
419 rtl::Reference
< unoidl::MapCursor
> const & cursor
,
420 std::map
< OUString
, Item
> & map
)
427 rtl::Reference
< unoidl::Entity
> ent(cursor
->getNext(&name
));
431 std::pair
< std::map
< OUString
, Item
>::iterator
, bool > i(
432 map
.insert(std::make_pair(name
, Item(ent
))));
434 std::cout
<< "Duplicate name \"" << name
<< '"' << std::endl
;
435 std::exit(EXIT_FAILURE
);
437 if (i
.first
->second
.entity
->getSort()
438 == unoidl::Entity::SORT_MODULE
)
441 rtl::Reference
< unoidl::ModuleEntity
>(
442 static_cast< unoidl::ModuleEntity
* >(
443 i
.first
->second
.entity
.get()))->createCursor(),
444 i
.first
->second
.module
);
450 bool hasNotEmptyAnnotations(const std::vector
<T
>& v
)
452 return std::any_of(v
.begin(), v
.end(), [](const T
& rItem
) { return !rItem
.annotations
.empty(); });
456 osl::File
& file
, std::map
< OUString
, Item
> & map
, std::size_t * rootSize
)
458 for (auto & i
: map
) {
459 switch (i
.second
.entity
->getSort()) {
460 case unoidl::Entity::SORT_MODULE
:
461 i
.second
.dataOffset
= writeMap(file
, i
.second
.module
, nullptr);
463 case unoidl::Entity::SORT_ENUM_TYPE
:
465 rtl::Reference
< unoidl::EnumTypeEntity
> ent2(
466 static_cast< unoidl::EnumTypeEntity
* >(
467 i
.second
.entity
.get()));
468 bool ann
= !ent2
->getAnnotations().empty() ||
469 hasNotEmptyAnnotations(ent2
->getMembers());
470 i
.second
.dataOffset
= getOffset(file
);
471 writeKind(file
, ent2
, ann
);
472 write32(file
, ent2
->getMembers().size());
473 for (auto & j
: ent2
->getMembers()) {
474 writeIdxName(file
, j
.name
);
475 write32(file
, static_cast< sal_uInt32
>(j
.value
));
476 writeAnnotations(file
, ann
, j
.annotations
);
478 writeAnnotations(file
, ann
, ent2
->getAnnotations());
481 case unoidl::Entity::SORT_PLAIN_STRUCT_TYPE
:
483 rtl::Reference
< unoidl::PlainStructTypeEntity
> ent2(
484 static_cast< unoidl::PlainStructTypeEntity
* >(
485 i
.second
.entity
.get()));
486 bool ann
= !ent2
->getAnnotations().empty() ||
487 hasNotEmptyAnnotations(ent2
->getDirectMembers());
488 i
.second
.dataOffset
= getOffset(file
);
490 file
, ent2
, ann
, !ent2
->getDirectBase().isEmpty());
491 if (!ent2
->getDirectBase().isEmpty()) {
492 writeIdxName(file
, ent2
->getDirectBase());
494 write32(file
, ent2
->getDirectMembers().size());
495 for (auto & j
: ent2
->getDirectMembers()) {
496 writeIdxName(file
, j
.name
);
497 writeIdxName(file
, j
.type
);
498 writeAnnotations(file
, ann
, j
.annotations
);
500 writeAnnotations(file
, ann
, ent2
->getAnnotations());
503 case unoidl::Entity::SORT_POLYMORPHIC_STRUCT_TYPE_TEMPLATE
:
505 rtl::Reference
< unoidl::PolymorphicStructTypeTemplateEntity
>
508 unoidl::PolymorphicStructTypeTemplateEntity
* >(
509 i
.second
.entity
.get()));
510 bool ann
= !ent2
->getAnnotations().empty() ||
511 hasNotEmptyAnnotations(ent2
->getMembers());
512 i
.second
.dataOffset
= getOffset(file
);
513 writeKind(file
, ent2
, ann
);
514 write32(file
, ent2
->getTypeParameters().size());
515 for (auto & j
: ent2
->getTypeParameters()) {
516 writeIdxName(file
, j
);
518 write32(file
, ent2
->getMembers().size());
519 for (auto & j
: ent2
->getMembers()) {
521 if (j
.parameterized
) {
525 writeIdxName(file
, j
.name
);
526 writeIdxName(file
, j
.type
);
527 writeAnnotations(file
, ann
, j
.annotations
);
529 writeAnnotations(file
, ann
, ent2
->getAnnotations());
532 case unoidl::Entity::SORT_EXCEPTION_TYPE
:
534 rtl::Reference
< unoidl::ExceptionTypeEntity
> ent2(
535 static_cast< unoidl::ExceptionTypeEntity
* >(
536 i
.second
.entity
.get()));
537 bool ann
= !ent2
->getAnnotations().empty() ||
538 hasNotEmptyAnnotations(ent2
->getDirectMembers());
539 i
.second
.dataOffset
= getOffset(file
);
541 file
, ent2
, ann
, !ent2
->getDirectBase().isEmpty());
542 if (!ent2
->getDirectBase().isEmpty()) {
543 writeIdxName(file
, ent2
->getDirectBase());
545 write32(file
, ent2
->getDirectMembers().size());
546 for (auto & j
: ent2
->getDirectMembers()) {
547 writeIdxName(file
, j
.name
);
548 writeIdxName(file
, j
.type
);
549 writeAnnotations(file
, ann
, j
.annotations
);
551 writeAnnotations(file
, ann
, ent2
->getAnnotations());
554 case unoidl::Entity::SORT_INTERFACE_TYPE
:
556 rtl::Reference
< unoidl::InterfaceTypeEntity
> ent2(
557 static_cast< unoidl::InterfaceTypeEntity
* >(
558 i
.second
.entity
.get()));
559 bool ann
= !ent2
->getAnnotations().empty() ||
560 hasNotEmptyAnnotations(ent2
->getDirectMandatoryBases()) ||
561 hasNotEmptyAnnotations(ent2
->getDirectOptionalBases()) ||
562 hasNotEmptyAnnotations(ent2
->getDirectAttributes()) ||
563 hasNotEmptyAnnotations(ent2
->getDirectMethods());
564 i
.second
.dataOffset
= getOffset(file
);
565 writeKind(file
, ent2
, ann
);
566 write32(file
, ent2
->getDirectMandatoryBases().size());
567 for (auto & j
: ent2
->getDirectMandatoryBases()) {
568 writeIdxName(file
, j
.name
);
569 writeAnnotations(file
, ann
, j
.annotations
);
571 write32(file
, ent2
->getDirectOptionalBases().size());
572 for (auto & j
: ent2
->getDirectOptionalBases()) {
573 writeIdxName(file
, j
.name
);
574 writeAnnotations(file
, ann
, j
.annotations
);
576 write32(file
, ent2
->getDirectAttributes().size());
577 for (auto & j
: ent2
->getDirectAttributes()) {
586 writeIdxName(file
, j
.name
);
587 writeIdxName(file
, j
.type
);
588 write32(file
, j
.getExceptions
.size());
589 for (auto & k
: j
.getExceptions
) {
590 writeIdxName(file
, k
);
593 write32(file
, j
.setExceptions
.size());
594 for (auto & k
: j
.setExceptions
) {
595 writeIdxName(file
, k
);
598 writeAnnotations(file
, ann
, j
.annotations
);
600 write32(file
, ent2
->getDirectMethods().size());
601 for (auto & j
: ent2
->getDirectMethods()) {
602 writeIdxName(file
, j
.name
);
603 writeIdxName(file
, j
.returnType
);
604 write32(file
, j
.parameters
.size());
605 for (auto & k
: j
.parameters
) {
606 write8(file
, k
.direction
);
607 writeIdxName(file
, k
.name
);
608 writeIdxName(file
, k
.type
);
610 write32(file
, j
.exceptions
.size());
611 for (auto & k
: j
.exceptions
) {
612 writeIdxName(file
, k
);
614 writeAnnotations(file
, ann
, j
.annotations
);
616 writeAnnotations(file
, ann
, ent2
->getAnnotations());
619 case unoidl::Entity::SORT_TYPEDEF
:
621 rtl::Reference
< unoidl::TypedefEntity
> ent2(
622 static_cast< unoidl::TypedefEntity
* >(
623 i
.second
.entity
.get()));
624 bool ann
= !ent2
->getAnnotations().empty();
625 i
.second
.dataOffset
= getOffset(file
);
626 writeKind(file
, ent2
, ann
);
627 writeIdxName(file
, ent2
->getType());
628 writeAnnotations(file
, ann
, ent2
->getAnnotations());
631 case unoidl::Entity::SORT_CONSTANT_GROUP
:
633 rtl::Reference
< unoidl::ConstantGroupEntity
> ent2(
634 static_cast< unoidl::ConstantGroupEntity
* >(
635 i
.second
.entity
.get()));
636 std::map
< OUString
, ConstItem
> cmap
;
637 for (auto & j
: ent2
->getMembers()) {
640 j
.name
, ConstItem(j
.value
, std::vector(j
.annotations
)))).
644 << "Duplicate constant group member name \""
645 << j
.name
<< '"' << std::endl
;
646 std::exit(EXIT_FAILURE
);
649 for (auto & j
: cmap
) {
650 j
.second
.dataOffset
= getOffset(file
);
651 sal_uInt64 v
= j
.second
.constant
.type
;
652 if (!j
.second
.annotations
.empty()) {
656 switch (j
.second
.constant
.type
) {
657 case unoidl::ConstantValue::TYPE_BOOLEAN
:
658 write8(file
, j
.second
.constant
.booleanValue
? 1 : 0);
660 case unoidl::ConstantValue::TYPE_BYTE
:
663 static_cast< sal_uInt8
>(
664 j
.second
.constant
.byteValue
));
666 case unoidl::ConstantValue::TYPE_SHORT
:
669 static_cast< sal_uInt16
>(
670 j
.second
.constant
.shortValue
));
672 case unoidl::ConstantValue::TYPE_UNSIGNED_SHORT
:
673 write16(file
, j
.second
.constant
.unsignedShortValue
);
675 case unoidl::ConstantValue::TYPE_LONG
:
678 static_cast< sal_uInt32
>(
679 j
.second
.constant
.longValue
));
681 case unoidl::ConstantValue::TYPE_UNSIGNED_LONG
:
682 write32(file
, j
.second
.constant
.unsignedLongValue
);
684 case unoidl::ConstantValue::TYPE_HYPER
:
687 static_cast< sal_uInt64
>(
688 j
.second
.constant
.hyperValue
));
690 case unoidl::ConstantValue::TYPE_UNSIGNED_HYPER
:
691 write64(file
, j
.second
.constant
.unsignedHyperValue
);
693 case unoidl::ConstantValue::TYPE_FLOAT
:
694 writeIso60599Binary32(
695 file
, j
.second
.constant
.floatValue
);
697 case unoidl::ConstantValue::TYPE_DOUBLE
:
698 writeIso60599Binary64(
699 file
, j
.second
.constant
.doubleValue
);
702 for (;;) { std::abort(); } // this cannot happen
705 file
, !j
.second
.annotations
.empty(),
706 j
.second
.annotations
);
708 for (auto & j
: cmap
) {
709 j
.second
.nameOffset
= writeNulName(file
, j
.first
);
711 bool ann
= !ent2
->getAnnotations().empty();
712 i
.second
.dataOffset
= getOffset(file
);
713 writeKind(file
, ent2
, ann
);
714 write32(file
, cmap
.size());
715 // overflow from std::map::size_type -> sal_uInt64 is
717 for (const auto & j
: cmap
) {
718 write32(file
, j
.second
.nameOffset
);
719 write32(file
, j
.second
.dataOffset
);
721 writeAnnotations(file
, ann
, ent2
->getAnnotations());
724 case unoidl::Entity::SORT_SINGLE_INTERFACE_BASED_SERVICE
:
726 rtl::Reference
< unoidl::SingleInterfaceBasedServiceEntity
>
729 unoidl::SingleInterfaceBasedServiceEntity
* >(
730 i
.second
.entity
.get()));
731 bool dfltCtor
= ent2
->getConstructors().size() == 1
732 && ent2
->getConstructors()[0].defaultConstructor
;
733 bool ann
= !ent2
->getAnnotations().empty();
734 if (!dfltCtor
&& !ann
)
735 ann
= hasNotEmptyAnnotations(ent2
->getConstructors());
736 i
.second
.dataOffset
= getOffset(file
);
737 writeKind(file
, ent2
, ann
, dfltCtor
);
738 writeIdxName(file
, ent2
->getBase());
740 write32(file
, ent2
->getConstructors().size());
741 for (auto & j
: ent2
->getConstructors()) {
742 if (j
.defaultConstructor
) {
744 << "Unexpected default constructor \""
745 << j
.name
<< '"' << std::endl
;
746 std::exit(EXIT_FAILURE
);
748 writeIdxName(file
, j
.name
);
749 write32(file
, j
.parameters
.size());
750 for (auto & k
: j
.parameters
) {
756 writeIdxName(file
, k
.name
);
757 writeIdxName(file
, k
.type
);
759 write32(file
, j
.exceptions
.size());
760 for (auto & k
: j
.exceptions
) {
761 writeIdxName(file
, k
);
763 writeAnnotations(file
, ann
, j
.annotations
);
766 writeAnnotations(file
, ann
, ent2
->getAnnotations());
769 case unoidl::Entity::SORT_ACCUMULATION_BASED_SERVICE
:
771 rtl::Reference
< unoidl::AccumulationBasedServiceEntity
> ent2(
772 static_cast< unoidl::AccumulationBasedServiceEntity
* >(
773 i
.second
.entity
.get()));
774 bool ann
= !ent2
->getAnnotations().empty() ||
775 hasNotEmptyAnnotations(ent2
->getDirectMandatoryBaseServices()) ||
776 hasNotEmptyAnnotations(ent2
->getDirectOptionalBaseServices()) ||
777 hasNotEmptyAnnotations(ent2
->getDirectMandatoryBaseInterfaces()) ||
778 hasNotEmptyAnnotations(ent2
->getDirectOptionalBaseInterfaces()) ||
779 hasNotEmptyAnnotations(ent2
->getDirectProperties());
780 i
.second
.dataOffset
= getOffset(file
);
781 writeKind(file
, ent2
, ann
);
782 write32(file
, ent2
->getDirectMandatoryBaseServices().size());
783 for (auto & j
: ent2
->getDirectMandatoryBaseServices()) {
784 writeIdxName(file
, j
.name
);
785 writeAnnotations(file
, ann
, j
.annotations
);
787 write32(file
, ent2
->getDirectOptionalBaseServices().size());
788 for (auto & j
: ent2
->getDirectOptionalBaseServices()) {
789 writeIdxName(file
, j
.name
);
790 writeAnnotations(file
, ann
, j
.annotations
);
792 write32(file
, ent2
->getDirectMandatoryBaseInterfaces().size());
793 for (auto & j
: ent2
->getDirectMandatoryBaseInterfaces()) {
794 writeIdxName(file
, j
.name
);
795 writeAnnotations(file
, ann
, j
.annotations
);
797 write32(file
, ent2
->getDirectOptionalBaseInterfaces().size());
798 for (auto & j
: ent2
->getDirectOptionalBaseInterfaces()) {
799 writeIdxName(file
, j
.name
);
800 writeAnnotations(file
, ann
, j
.annotations
);
802 write32(file
, ent2
->getDirectProperties().size());
803 for (auto & j
: ent2
->getDirectProperties()) {
804 write16(file
, static_cast< sal_uInt16
>(j
.attributes
));
805 writeIdxName(file
, j
.name
);
806 writeIdxName(file
, j
.type
);
807 writeAnnotations(file
, ann
, j
.annotations
);
809 writeAnnotations(file
, ann
, ent2
->getAnnotations());
812 case unoidl::Entity::SORT_INTERFACE_BASED_SINGLETON
:
814 rtl::Reference
< unoidl::InterfaceBasedSingletonEntity
> ent2(
815 static_cast< unoidl::InterfaceBasedSingletonEntity
* >(
816 i
.second
.entity
.get()));
817 bool ann
= !ent2
->getAnnotations().empty();
818 i
.second
.dataOffset
= getOffset(file
);
819 writeKind(file
, ent2
, ann
);
820 writeIdxName(file
, ent2
->getBase());
821 writeAnnotations(file
, ann
, ent2
->getAnnotations());
824 case unoidl::Entity::SORT_SERVICE_BASED_SINGLETON
:
826 rtl::Reference
< unoidl::ServiceBasedSingletonEntity
> ent2(
827 static_cast< unoidl::ServiceBasedSingletonEntity
* >(
828 i
.second
.entity
.get()));
829 bool ann
= !ent2
->getAnnotations().empty();
830 i
.second
.dataOffset
= getOffset(file
);
831 writeKind(file
, ent2
, ann
);
832 writeIdxName(file
, ent2
->getBase());
833 writeAnnotations(file
, ann
, ent2
->getAnnotations());
838 for (auto & i
: map
) {
839 i
.second
.nameOffset
= writeNulName(file
, i
.first
);
841 sal_uInt64 off
= getOffset(file
);
842 if (rootSize
== nullptr) {
843 write8(file
, 0); // SORT_MODULE
844 write32(file
, map
.size());
845 // overflow from std::map::size_type -> sal_uInt64 is unrealistic
847 *rootSize
= map
.size();
848 // overflow from std::map::size_type -> std::size_t is unrealistic
850 for (const auto & i
: map
) {
851 write32(file
, i
.second
.nameOffset
);
852 write32(file
, i
.second
.dataOffset
);
859 SAL_IMPLEMENT_MAIN() {
861 sal_uInt32 args
= rtl_getAppCommandArgCount();
865 rtl::Reference
< unoidl::Manager
> mgr(new unoidl::Manager
);
866 bool entities
= false;
867 rtl::Reference
< unoidl::Provider
> prov
;
868 std::map
< OUString
, Item
> map
;
869 for (sal_uInt32 i
= 0; i
!= args
- 1; ++i
) {
871 OUString
uri(getArgumentUri(i
, i
== args
- 2 ? &entities
: nullptr));
873 mapEntities(mgr
, uri
, map
);
876 prov
= mgr
->addProvider(uri
);
877 } catch (unoidl::NoSuchFileException
&) {
879 << "Input <" << uri
<< "> does not exist" << std::endl
;
880 std::exit(EXIT_FAILURE
);
887 ? prov
->createRootCursor()
888 : rtl::Reference
< unoidl::MapCursor
>()),
891 osl::File
f(getArgumentUri(args
- 1, nullptr));
892 osl::FileBase::RC e
= f
.open(osl_File_OpenFlag_Write
);
893 if (e
== osl::FileBase::E_NOENT
) {
894 e
= f
.open(osl_File_OpenFlag_Write
| osl_File_OpenFlag_Create
);
896 if (e
!= osl::FileBase::E_None
) {
898 << "Cannot open <" << f
.getURL() << "> for writing, error code "
900 std::exit(EXIT_FAILURE
);
902 write(f
, "UNOIDL\xFF\0", 8);
903 write32(f
, 0); // root map offset
904 write32(f
, 0); // root map size
907 RTL_CONSTASCII_STRINGPARAM(
908 "\0** Created by LibreOffice " LIBO_VERSION_DOTTED
909 " unoidl-write **\0"));
911 sal_uInt64 off
= writeMap(f
, map
, &size
);
912 e
= f
.setSize(getOffset(f
)); // truncate in case it already existed
913 if (e
!= osl::FileBase::E_None
) {
915 << "Cannot set size of <" << f
.getURL() << ">, error code "
917 std::exit(EXIT_FAILURE
);
919 e
= f
.setPos(osl_Pos_Absolut
, 8);
920 if (e
!= osl::FileBase::E_None
) {
922 << "Cannot rewind current position in <" << f
.getURL()
923 << ">, error code " << +e
<< std::endl
;
924 std::exit(EXIT_FAILURE
);
928 // overflow from std::map::size_type -> sal_uInt64 is unrealistic
930 if (e
!= osl::FileBase::E_None
) {
932 << "Cannot close <" << f
.getURL()
933 << "> after writing, error code " << +e
<< std::endl
;
934 std::exit(EXIT_FAILURE
);
937 } catch (unoidl::FileFormatException
& e1
) {
939 << "Bad input <" << e1
.getUri() << ">: " << e1
.getDetail()
941 std::exit(EXIT_FAILURE
);
942 } catch (std::exception
& e1
) {
944 << "Failure: " << e1
.what()
946 std::exit(EXIT_FAILURE
);
951 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */