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/process.h>
26 #include <rtl/string.h>
27 #include <rtl/string.hxx>
28 #include <rtl/textenc.h>
29 #include <rtl/textcvt.h>
30 #include <rtl/ustring.hxx>
31 #include <sal/macros.h>
33 #include <unoidl/unoidl.hxx>
39 << "Usage:" << std::endl
<< std::endl
40 << " unoidl-write [<registries>] [@<entities file>] <unoidl file>"
41 << std::endl
<< std::endl
42 << ("where each <registry> is either a new- or legacy-format .rdb file,"
45 << ("file, or a root directory of an .idl file tree; and the UTF-8"
48 << ("file> contains zero or more space-separated names of (non-module)"
51 << ("include in the output, and, if omitted, defaults to the complete"
53 << std::endl
<< "last <registry>, if any." << std::endl
;
54 std::exit(EXIT_FAILURE
);
57 OUString
getArgumentUri(sal_uInt32 argument
, bool * entities
) {
59 rtl_getAppCommandArg(argument
, &arg
.pData
);
60 if (arg
.startsWith("@", &arg
)) {
61 if (entities
== nullptr) {
65 } else if (entities
!= nullptr) {
69 osl::FileBase::RC e1
= osl::FileBase::getFileURLFromSystemPath(arg
, url
);
70 if (e1
!= osl::FileBase::E_None
) {
72 << "Cannot convert \"" << arg
<< "\" to file URL, error code "
74 std::exit(EXIT_FAILURE
);
77 oslProcessError e2
= osl_getProcessWorkingDir(&cwd
.pData
);
78 if (e2
!= osl_Process_E_None
) {
80 << "Cannot obtain working directory, error code " << +e2
82 std::exit(EXIT_FAILURE
);
85 e1
= osl::FileBase::getAbsoluteFileURL(cwd
, url
, abs
);
86 if (e1
!= osl::FileBase::E_None
) {
88 << "Cannot make \"" << url
89 << "\" into an absolute file URL, error code " << +e1
<< std::endl
;
90 std::exit(EXIT_FAILURE
);
95 sal_uInt64
getOffset(osl::File
& file
) {
97 osl::FileBase::RC e
= file
.getPos(off
);
98 if (e
!= osl::FileBase::E_None
) {
100 << "Cannot determine current position in <" << file
.getURL()
101 << ">, error code " << +e
<< std::endl
;
102 std::exit(EXIT_FAILURE
);
107 void write(osl::File
& file
, void const * buffer
, sal_uInt64 size
) {
109 osl::FileBase::RC e
= file
.write(buffer
, size
, n
);
110 if (e
!= osl::FileBase::E_None
) {
112 << "Cannot write to <" << file
.getURL() << ">, error code " << +e
114 std::exit(EXIT_FAILURE
);
118 << "Bad write of " << n
<< " instead of " << size
<< " bytes to <"
119 << file
.getURL() << '>' << std::endl
;
120 std::exit(EXIT_FAILURE
);
124 void write8(osl::File
& file
, sal_uInt64 value
) {
127 << "Cannot write value >= 2^8; input is too large" << std::endl
;
128 std::exit(EXIT_FAILURE
);
130 unsigned char buf
[1];
131 buf
[0] = value
& 0xFF;
132 write(file
, buf
, SAL_N_ELEMENTS(buf
));
135 void write16(osl::File
& file
, sal_uInt64 value
) {
136 if (value
> 0xFFFF) {
138 << "Cannot write value >= 2^16; input is too large" << std::endl
;
139 std::exit(EXIT_FAILURE
);
141 unsigned char buf
[2];
142 buf
[0] = value
& 0xFF;
143 buf
[1] = (value
>> 8) & 0xFF;
144 write(file
, buf
, SAL_N_ELEMENTS(buf
));
147 void write32(osl::File
& file
, sal_uInt64 value
) {
148 if (value
> 0xFFFFFFFF) {
150 << "Cannot write value >= 2^32; input is too large" << std::endl
;
151 std::exit(EXIT_FAILURE
);
153 unsigned char buf
[4];
154 buf
[0] = value
& 0xFF;
155 buf
[1] = (value
>> 8) & 0xFF;
156 buf
[2] = (value
>> 16) & 0xFF;
157 buf
[3] = (value
>> 24) & 0xFF;
158 write(file
, buf
, SAL_N_ELEMENTS(buf
));
161 void write64(osl::File
& file
, sal_uInt64 value
) {
162 unsigned char buf
[8];
163 buf
[0] = value
& 0xFF;
164 buf
[1] = (value
>> 8) & 0xFF;
165 buf
[2] = (value
>> 16) & 0xFF;
166 buf
[3] = (value
>> 24) & 0xFF;
167 buf
[4] = (value
>> 32) & 0xFF;
168 buf
[5] = (value
>> 40) & 0xFF;
169 buf
[6] = (value
>> 48) & 0xFF;
170 buf
[7] = (value
>> 56) & 0xFF;
171 write(file
, buf
, SAL_N_ELEMENTS(buf
));
174 void writeIso60599Binary32(osl::File
& file
, float value
) {
176 unsigned char buf
[4];
177 float f
; // assuming float is ISO 60599 binary32
180 #if defined OSL_BIGENDIAN
181 std::swap(sa
.buf
[0], sa
.buf
[3]);
182 std::swap(sa
.buf
[1], sa
.buf
[2]);
184 write(file
, sa
.buf
, SAL_N_ELEMENTS(sa
.buf
));
187 void writeIso60599Binary64(osl::File
& file
, double value
) {
189 unsigned char buf
[8];
190 float d
; // assuming double is ISO 60599 binary64
193 #if defined OSL_BIGENDIAN
194 std::swap(sa
.buf
[0], sa
.buf
[7]);
195 std::swap(sa
.buf
[1], sa
.buf
[6]);
196 std::swap(sa
.buf
[2], sa
.buf
[5]);
197 std::swap(sa
.buf
[3], sa
.buf
[4]);
199 write(file
, sa
.buf
, SAL_N_ELEMENTS(sa
.buf
));
202 OString
toAscii(OUString
const & name
) {
204 if (!name
.convertToString(
205 &ascii
, RTL_TEXTENCODING_ASCII_US
,
206 (RTL_UNICODETOTEXT_FLAGS_UNDEFINED_ERROR
207 | RTL_UNICODETOTEXT_FLAGS_INVALID_ERROR
)))
210 << "Cannot convert \"" << name
<< "\" to US ASCII" << std::endl
;
211 std::exit(EXIT_FAILURE
);
216 OString
toUtf8(OUString
const & string
) {
218 if (!string
.convertToString(
219 &ascii
, RTL_TEXTENCODING_UTF8
,
220 (RTL_UNICODETOTEXT_FLAGS_UNDEFINED_ERROR
221 | RTL_UNICODETOTEXT_FLAGS_INVALID_ERROR
)))
224 << "Cannot convert \"" << string
<< "\" to UTF-8" << std::endl
;
225 std::exit(EXIT_FAILURE
);
230 sal_uInt64
writeNulName(osl::File
& file
, OUString
const & name
) {
231 OString
ascii(toAscii(name
));
232 if (ascii
.indexOf('\0') != -1) {
234 << "Name \"" << ascii
<< "\" contains NUL characters" << std::endl
;
235 std::exit(EXIT_FAILURE
);
237 sal_uInt64 off
= getOffset(file
);
238 write(file
, ascii
.getStr(), ascii
.getLength() + 1);
242 void writeIdxString(osl::File
& file
, OString
const & string
) {
243 static std::map
< OString
, sal_uInt64
> reuse
;
244 std::map
< OString
, sal_uInt64
>::iterator
i(reuse
.find(string
));
245 if (i
== reuse
.end()) {
246 reuse
.insert(std::make_pair(string
, getOffset(file
)));
248 (static_cast< sal_uInt64
>(string
.getLength()) & 0x80000000) == 0);
249 write32(file
, static_cast< sal_uInt64
>(string
.getLength()));
250 write(file
, string
.getStr(), string
.getLength());
252 if ((i
->second
& 0x80000000) != 0) {
254 << "Cannot write index 0x" << std::hex
<< i
->second
<< std::dec
255 << " of \"" << string
<< "\"; input is too large" << std::endl
;
256 std::exit(EXIT_FAILURE
);
258 write32(file
, i
->second
| 0x80000000);
262 void writeIdxName(osl::File
& file
, OUString
const & name
) {
263 writeIdxString(file
, toAscii(name
));
266 void writeAnnotations(
267 osl::File
& file
, bool annotate
,
268 std::vector
< OUString
> const & annotations
)
270 assert(annotate
|| annotations
.empty());
272 write32(file
, annotations
.size());
273 // overflow from std::vector::size_type -> sal_uInt64 is unrealistic
274 for (auto & i
: annotations
) {
275 writeIdxString(file
, toUtf8(i
));
282 rtl::Reference
< unoidl::PublishableEntity
> const & entity
,
283 bool annotated
, bool flag
= false)
286 sal_uInt64 v
= entity
->getSort();
287 if (entity
->isPublished()) {
300 explicit Item(rtl::Reference
< unoidl::Entity
> const & theEntity
):
301 entity(theEntity
), nameOffset(0), dataOffset(0)
304 rtl::Reference
< unoidl::Entity
> entity
;
305 std::map
< OUString
, Item
> module
;
306 sal_uInt64 nameOffset
;
307 sal_uInt64 dataOffset
;
312 unoidl::ConstantValue
const & theConstant
,
313 std::vector
< OUString
> const & theAnnotations
):
314 constant(theConstant
), annotations(theAnnotations
), nameOffset(0),
318 unoidl::ConstantValue constant
;
319 std::vector
< OUString
> annotations
;
320 sal_uInt64 nameOffset
;
321 sal_uInt64 dataOffset
;
325 rtl::Reference
< unoidl::Manager
> const & manager
, OUString
const & uri
,
326 std::map
< OUString
, Item
> & map
)
328 assert(manager
.is());
330 osl::FileBase::RC e
= f
.open(osl_File_OpenFlag_Read
);
331 if (e
!= osl::FileBase::E_None
) {
333 << "Cannot open <" << f
.getURL() << "> for reading, error code "
335 std::exit(EXIT_FAILURE
);
339 e
= f
.isEndOfFile(&eof
);
340 if (e
!= osl::FileBase::E_None
) {
342 << "Cannot check <" << f
.getURL() << "> for EOF, error code "
344 std::exit(EXIT_FAILURE
);
349 rtl::ByteSequence s1
;
351 if (e
!= osl::FileBase::E_None
) {
353 << "Cannot read from <" << f
.getURL() << ">, error code "
355 std::exit(EXIT_FAILURE
);
358 if (!rtl_convertStringToUString(
359 &s2
.pData
, reinterpret_cast< char const * >(s1
.getConstArray()),
360 s1
.getLength(), RTL_TEXTENCODING_UTF8
,
361 (RTL_TEXTTOUNICODE_FLAGS_UNDEFINED_ERROR
362 | RTL_TEXTTOUNICODE_FLAGS_MBUNDEFINED_ERROR
363 | RTL_TEXTTOUNICODE_FLAGS_INVALID_ERROR
)))
366 << "Cannot interpret line read from <" << f
.getURL()
367 << "> as UTF-8" << std::endl
;
368 std::exit(EXIT_FAILURE
);
370 for (sal_Int32 i
= 0; i
!= -1;) {
371 OUString
t(s2
.getToken(0, ' ', i
));
373 rtl::Reference
< unoidl::Entity
> ent(manager
->findEntity(t
));
376 << "Unknown entity \"" << t
<< "\" read from <"
377 << f
.getURL() << ">" << std::endl
;
378 std::exit(EXIT_FAILURE
);
380 if (ent
->getSort() == unoidl::Entity::SORT_MODULE
) {
382 << "Module entity \"" << t
<< "\" read from <"
383 << f
.getURL() << ">" << std::endl
;
384 std::exit(EXIT_FAILURE
);
386 std::map
< OUString
, Item
> * map2
= &map
;
387 for (sal_Int32 j
= 0;;) {
388 OUString
id(t
.getToken(0, '.', j
));
390 map2
->insert(std::make_pair(id
, Item(ent
)));
393 std::map
< OUString
, Item
>::iterator
k(map2
->find(id
));
394 if (k
== map2
->end()) {
395 rtl::Reference
< unoidl::Entity
> ent2(
396 manager
->findEntity(t
.copy(0, j
- 1)));
398 k
= map2
->insert(std::make_pair(id
, Item(ent2
))).first
;
401 k
->second
.entity
->getSort()
402 == unoidl::Entity::SORT_MODULE
);
403 map2
= &k
->second
.module
;
409 if (e
!= osl::FileBase::E_None
) {
411 << "Cannot close <" << f
.getURL() << "> after reading, error code "
413 std::exit(EXIT_FAILURE
);
418 rtl::Reference
< unoidl::MapCursor
> const & cursor
,
419 std::map
< OUString
, Item
> & map
)
424 rtl::Reference
< unoidl::Entity
> ent(cursor
->getNext(&name
));
428 std::pair
< std::map
< OUString
, Item
>::iterator
, bool > i(
429 map
.insert(std::make_pair(name
, Item(ent
))));
431 std::cout
<< "Duplicate name \"" << name
<< '"' << std::endl
;
432 std::exit(EXIT_FAILURE
);
434 if (i
.first
->second
.entity
->getSort()
435 == unoidl::Entity::SORT_MODULE
)
438 rtl::Reference
< unoidl::ModuleEntity
>(
439 static_cast< unoidl::ModuleEntity
* >(
440 i
.first
->second
.entity
.get()))->createCursor(),
441 i
.first
->second
.module
);
448 osl::File
& file
, std::map
< OUString
, Item
> & map
, std::size_t * rootSize
)
450 for (auto & i
: map
) {
451 switch (i
.second
.entity
->getSort()) {
452 case unoidl::Entity::SORT_MODULE
:
453 i
.second
.dataOffset
= writeMap(file
, i
.second
.module
, nullptr);
455 case unoidl::Entity::SORT_ENUM_TYPE
:
457 rtl::Reference
< unoidl::EnumTypeEntity
> ent2(
458 static_cast< unoidl::EnumTypeEntity
* >(
459 i
.second
.entity
.get()));
460 bool ann
= !ent2
->getAnnotations().empty();
461 for (auto j(ent2
->getMembers().begin());
462 !ann
&& j
!= ent2
->getMembers().end(); ++j
)
464 ann
= !j
->annotations
.empty();
466 i
.second
.dataOffset
= getOffset(file
);
467 writeKind(file
, ent2
.get(), ann
);
468 write32(file
, ent2
->getMembers().size());
469 for (auto & j
: ent2
->getMembers()) {
470 writeIdxName(file
, j
.name
);
471 write32(file
, static_cast< sal_uInt32
>(j
.value
));
472 writeAnnotations(file
, ann
, j
.annotations
);
474 writeAnnotations(file
, ann
, ent2
->getAnnotations());
477 case unoidl::Entity::SORT_PLAIN_STRUCT_TYPE
:
479 rtl::Reference
< unoidl::PlainStructTypeEntity
> ent2(
480 static_cast< unoidl::PlainStructTypeEntity
* >(
481 i
.second
.entity
.get()));
482 bool ann
= !ent2
->getAnnotations().empty();
483 for (auto j(ent2
->getDirectMembers().begin());
484 !ann
&& j
!= ent2
->getDirectMembers().end(); ++j
)
486 ann
= !j
->annotations
.empty();
488 i
.second
.dataOffset
= getOffset(file
);
490 file
, ent2
.get(), 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 for (auto j(ent2
->getMembers().begin());
512 !ann
&& j
!= ent2
->getMembers().end(); ++j
)
514 ann
= !j
->annotations
.empty();
516 i
.second
.dataOffset
= getOffset(file
);
517 writeKind(file
, ent2
.get(), ann
);
518 write32(file
, ent2
->getTypeParameters().size());
519 for (auto & j
: ent2
->getTypeParameters()) {
520 writeIdxName(file
, j
);
522 write32(file
, ent2
->getMembers().size());
523 for (auto & j
: ent2
->getMembers()) {
525 if (j
.parameterized
) {
529 writeIdxName(file
, j
.name
);
530 writeIdxName(file
, j
.type
);
531 writeAnnotations(file
, ann
, j
.annotations
);
533 writeAnnotations(file
, ann
, ent2
->getAnnotations());
536 case unoidl::Entity::SORT_EXCEPTION_TYPE
:
538 rtl::Reference
< unoidl::ExceptionTypeEntity
> ent2(
539 static_cast< unoidl::ExceptionTypeEntity
* >(
540 i
.second
.entity
.get()));
541 bool ann
= !ent2
->getAnnotations().empty();
542 for (auto j(ent2
->getDirectMembers().begin());
543 !ann
&& j
!= ent2
->getDirectMembers().end(); ++j
)
545 ann
= !j
->annotations
.empty();
547 i
.second
.dataOffset
= getOffset(file
);
549 file
, ent2
.get(), ann
, !ent2
->getDirectBase().isEmpty());
550 if (!ent2
->getDirectBase().isEmpty()) {
551 writeIdxName(file
, ent2
->getDirectBase());
553 write32(file
, ent2
->getDirectMembers().size());
554 for (auto & j
: ent2
->getDirectMembers()) {
555 writeIdxName(file
, j
.name
);
556 writeIdxName(file
, j
.type
);
557 writeAnnotations(file
, ann
, j
.annotations
);
559 writeAnnotations(file
, ann
, ent2
->getAnnotations());
562 case unoidl::Entity::SORT_INTERFACE_TYPE
:
564 rtl::Reference
< unoidl::InterfaceTypeEntity
> ent2(
565 static_cast< unoidl::InterfaceTypeEntity
* >(
566 i
.second
.entity
.get()));
567 bool ann
= !ent2
->getAnnotations().empty();
568 for (auto j(ent2
->getDirectMandatoryBases().begin());
569 !ann
&& j
!= ent2
->getDirectMandatoryBases().end(); ++j
)
571 ann
= !j
->annotations
.empty();
573 for (auto j(ent2
->getDirectOptionalBases().begin());
574 !ann
&& j
!= ent2
->getDirectOptionalBases().end(); ++j
)
576 ann
= !j
->annotations
.empty();
578 for (auto j(ent2
->getDirectAttributes().begin());
579 !ann
&& j
!= ent2
->getDirectAttributes().end(); ++j
)
581 ann
= !j
->annotations
.empty();
583 for (auto j(ent2
->getDirectMethods().begin());
584 !ann
&& j
!= ent2
->getDirectMethods().end(); ++j
)
586 ann
= !j
->annotations
.empty();
588 i
.second
.dataOffset
= getOffset(file
);
589 writeKind(file
, ent2
.get(), ann
);
590 write32(file
, ent2
->getDirectMandatoryBases().size());
591 for (auto & j
: ent2
->getDirectMandatoryBases()) {
592 writeIdxName(file
, j
.name
);
593 writeAnnotations(file
, ann
, j
.annotations
);
595 write32(file
, ent2
->getDirectOptionalBases().size());
596 for (auto & j
: ent2
->getDirectOptionalBases()) {
597 writeIdxName(file
, j
.name
);
598 writeAnnotations(file
, ann
, j
.annotations
);
600 write32(file
, ent2
->getDirectAttributes().size());
601 for (auto & j
: ent2
->getDirectAttributes()) {
610 writeIdxName(file
, j
.name
);
611 writeIdxName(file
, j
.type
);
612 write32(file
, j
.getExceptions
.size());
613 for (auto & k
: j
.getExceptions
) {
614 writeIdxName(file
, k
);
617 write32(file
, j
.setExceptions
.size());
618 for (auto & k
: j
.setExceptions
) {
619 writeIdxName(file
, k
);
622 writeAnnotations(file
, ann
, j
.annotations
);
624 write32(file
, ent2
->getDirectMethods().size());
625 for (auto & j
: ent2
->getDirectMethods()) {
626 writeIdxName(file
, j
.name
);
627 writeIdxName(file
, j
.returnType
);
628 write32(file
, j
.parameters
.size());
629 for (auto & k
: j
.parameters
) {
630 write8(file
, k
.direction
);
631 writeIdxName(file
, k
.name
);
632 writeIdxName(file
, k
.type
);
634 write32(file
, j
.exceptions
.size());
635 for (auto & k
: j
.exceptions
) {
636 writeIdxName(file
, k
);
638 writeAnnotations(file
, ann
, j
.annotations
);
640 writeAnnotations(file
, ann
, ent2
->getAnnotations());
643 case unoidl::Entity::SORT_TYPEDEF
:
645 rtl::Reference
< unoidl::TypedefEntity
> ent2(
646 static_cast< unoidl::TypedefEntity
* >(
647 i
.second
.entity
.get()));
648 bool ann
= !ent2
->getAnnotations().empty();
649 i
.second
.dataOffset
= getOffset(file
);
650 writeKind(file
, ent2
.get(), ann
);
651 writeIdxName(file
, ent2
->getType());
652 writeAnnotations(file
, ann
, ent2
->getAnnotations());
655 case unoidl::Entity::SORT_CONSTANT_GROUP
:
657 rtl::Reference
< unoidl::ConstantGroupEntity
> ent2(
658 static_cast< unoidl::ConstantGroupEntity
* >(
659 i
.second
.entity
.get()));
660 std::map
< OUString
, ConstItem
> cmap
;
661 for (auto & j
: ent2
->getMembers()) {
664 j
.name
, ConstItem(j
.value
, j
.annotations
))).
668 << "Duplicate constant group member name \""
669 << j
.name
<< '"' << std::endl
;
670 std::exit(EXIT_FAILURE
);
673 for (auto & j
: cmap
) {
674 j
.second
.dataOffset
= getOffset(file
);
675 sal_uInt64 v
= j
.second
.constant
.type
;
676 if (!j
.second
.annotations
.empty()) {
680 switch (j
.second
.constant
.type
) {
681 case unoidl::ConstantValue::TYPE_BOOLEAN
:
682 write8(file
, j
.second
.constant
.booleanValue
? 1 : 0);
684 case unoidl::ConstantValue::TYPE_BYTE
:
687 static_cast< sal_uInt8
>(
688 j
.second
.constant
.byteValue
));
690 case unoidl::ConstantValue::TYPE_SHORT
:
693 static_cast< sal_uInt16
>(
694 j
.second
.constant
.shortValue
));
696 case unoidl::ConstantValue::TYPE_UNSIGNED_SHORT
:
697 write16(file
, j
.second
.constant
.unsignedShortValue
);
699 case unoidl::ConstantValue::TYPE_LONG
:
702 static_cast< sal_uInt32
>(
703 j
.second
.constant
.longValue
));
705 case unoidl::ConstantValue::TYPE_UNSIGNED_LONG
:
706 write32(file
, j
.second
.constant
.unsignedLongValue
);
708 case unoidl::ConstantValue::TYPE_HYPER
:
711 static_cast< sal_uInt64
>(
712 j
.second
.constant
.hyperValue
));
714 case unoidl::ConstantValue::TYPE_UNSIGNED_HYPER
:
715 write64(file
, j
.second
.constant
.unsignedHyperValue
);
717 case unoidl::ConstantValue::TYPE_FLOAT
:
718 writeIso60599Binary32(
719 file
, j
.second
.constant
.floatValue
);
721 case unoidl::ConstantValue::TYPE_DOUBLE
:
722 writeIso60599Binary64(
723 file
, j
.second
.constant
.doubleValue
);
726 for (;;) { std::abort(); } // this cannot happen
729 file
, !j
.second
.annotations
.empty(),
730 j
.second
.annotations
);
732 for (auto & j
: cmap
) {
733 j
.second
.nameOffset
= writeNulName(file
, j
.first
);
735 bool ann
= !ent2
->getAnnotations().empty();
736 i
.second
.dataOffset
= getOffset(file
);
737 writeKind(file
, ent2
.get(), ann
);
738 write32(file
, cmap
.size());
739 // overflow from std::map::size_type -> sal_uInt64 is
741 for (auto & j
: cmap
) {
742 write32(file
, j
.second
.nameOffset
);
743 write32(file
, j
.second
.dataOffset
);
745 writeAnnotations(file
, ann
, ent2
->getAnnotations());
748 case unoidl::Entity::SORT_SINGLE_INTERFACE_BASED_SERVICE
:
750 rtl::Reference
< unoidl::SingleInterfaceBasedServiceEntity
>
753 unoidl::SingleInterfaceBasedServiceEntity
* >(
754 i
.second
.entity
.get()));
755 bool dfltCtor
= ent2
->getConstructors().size() == 1
756 && ent2
->getConstructors()[0].defaultConstructor
;
757 bool ann
= !ent2
->getAnnotations().empty();
759 for (auto j(ent2
->getConstructors().begin());
760 !ann
&& j
!= ent2
->getConstructors().end(); ++j
)
762 ann
= !j
->annotations
.empty();
765 i
.second
.dataOffset
= getOffset(file
);
766 writeKind(file
, ent2
.get(), ann
, dfltCtor
);
767 writeIdxName(file
, ent2
->getBase());
769 write32(file
, ent2
->getConstructors().size());
770 for (auto & j
: ent2
->getConstructors()) {
771 if (j
.defaultConstructor
) {
773 << "Unexpected default constructor \""
774 << j
.name
<< '"' << std::endl
;
775 std::exit(EXIT_FAILURE
);
777 writeIdxName(file
, j
.name
);
778 write32(file
, j
.parameters
.size());
779 for (auto & k
: j
.parameters
) {
785 writeIdxName(file
, k
.name
);
786 writeIdxName(file
, k
.type
);
788 write32(file
, j
.exceptions
.size());
789 for (auto & k
: j
.exceptions
) {
790 writeIdxName(file
, k
);
792 writeAnnotations(file
, ann
, j
.annotations
);
795 writeAnnotations(file
, ann
, ent2
->getAnnotations());
798 case unoidl::Entity::SORT_ACCUMULATION_BASED_SERVICE
:
800 rtl::Reference
< unoidl::AccumulationBasedServiceEntity
> ent2(
801 static_cast< unoidl::AccumulationBasedServiceEntity
* >(
802 i
.second
.entity
.get()));
803 bool ann
= !ent2
->getAnnotations().empty();
804 for (auto j(ent2
->getDirectMandatoryBaseServices().begin());
805 !ann
&& j
!= ent2
->getDirectMandatoryBaseServices().end();
808 ann
= !j
->annotations
.empty();
810 for (auto j(ent2
->getDirectOptionalBaseServices().begin());
811 !ann
&& j
!= ent2
->getDirectOptionalBaseServices().end();
814 ann
= !j
->annotations
.empty();
816 for (auto j(ent2
->getDirectMandatoryBaseInterfaces().begin());
818 && j
!= ent2
->getDirectMandatoryBaseInterfaces().end());
821 ann
= !j
->annotations
.empty();
823 for (auto j(ent2
->getDirectOptionalBaseInterfaces().begin());
824 !ann
&& j
!= ent2
->getDirectOptionalBaseInterfaces().end();
827 ann
= !j
->annotations
.empty();
829 for (auto j(ent2
->getDirectProperties().begin());
830 !ann
&& j
!= ent2
->getDirectProperties().end(); ++j
)
832 ann
= !j
->annotations
.empty();
834 i
.second
.dataOffset
= getOffset(file
);
835 writeKind(file
, ent2
.get(), ann
);
836 write32(file
, ent2
->getDirectMandatoryBaseServices().size());
837 for (auto & j
: ent2
->getDirectMandatoryBaseServices()) {
838 writeIdxName(file
, j
.name
);
839 writeAnnotations(file
, ann
, j
.annotations
);
841 write32(file
, ent2
->getDirectOptionalBaseServices().size());
842 for (auto & j
: ent2
->getDirectOptionalBaseServices()) {
843 writeIdxName(file
, j
.name
);
844 writeAnnotations(file
, ann
, j
.annotations
);
846 write32(file
, ent2
->getDirectMandatoryBaseInterfaces().size());
847 for (auto & j
: ent2
->getDirectMandatoryBaseInterfaces()) {
848 writeIdxName(file
, j
.name
);
849 writeAnnotations(file
, ann
, j
.annotations
);
851 write32(file
, ent2
->getDirectOptionalBaseInterfaces().size());
852 for (auto & j
: ent2
->getDirectOptionalBaseInterfaces()) {
853 writeIdxName(file
, j
.name
);
854 writeAnnotations(file
, ann
, j
.annotations
);
856 write32(file
, ent2
->getDirectProperties().size());
857 for (auto & j
: ent2
->getDirectProperties()) {
858 write16(file
, static_cast< sal_uInt16
>(j
.attributes
));
859 writeIdxName(file
, j
.name
);
860 writeIdxName(file
, j
.type
);
861 writeAnnotations(file
, ann
, j
.annotations
);
863 writeAnnotations(file
, ann
, ent2
->getAnnotations());
866 case unoidl::Entity::SORT_INTERFACE_BASED_SINGLETON
:
868 rtl::Reference
< unoidl::InterfaceBasedSingletonEntity
> ent2(
869 static_cast< unoidl::InterfaceBasedSingletonEntity
* >(
870 i
.second
.entity
.get()));
871 bool ann
= !ent2
->getAnnotations().empty();
872 i
.second
.dataOffset
= getOffset(file
);
873 writeKind(file
, ent2
.get(), ann
);
874 writeIdxName(file
, ent2
->getBase());
875 writeAnnotations(file
, ann
, ent2
->getAnnotations());
878 case unoidl::Entity::SORT_SERVICE_BASED_SINGLETON
:
880 rtl::Reference
< unoidl::ServiceBasedSingletonEntity
> ent2(
881 static_cast< unoidl::ServiceBasedSingletonEntity
* >(
882 i
.second
.entity
.get()));
883 bool ann
= !ent2
->getAnnotations().empty();
884 i
.second
.dataOffset
= getOffset(file
);
885 writeKind(file
, ent2
.get(), ann
);
886 writeIdxName(file
, ent2
->getBase());
887 writeAnnotations(file
, ann
, ent2
->getAnnotations());
892 for (auto & i
: map
) {
893 i
.second
.nameOffset
= writeNulName(file
, i
.first
);
895 sal_uInt64 off
= getOffset(file
);
896 if (rootSize
== nullptr) {
897 write8(file
, 0); // SORT_MODULE
898 write32(file
, map
.size());
899 // overflow from std::map::size_type -> sal_uInt64 is unrealistic
901 *rootSize
= map
.size();
902 // overflow from std::map::size_type -> std::size_t is unrealistic
904 for (auto & i
: map
) {
905 write32(file
, i
.second
.nameOffset
);
906 write32(file
, i
.second
.dataOffset
);
913 SAL_IMPLEMENT_MAIN() {
915 sal_uInt32 args
= rtl_getAppCommandArgCount();
919 rtl::Reference
< unoidl::Manager
> mgr(new unoidl::Manager
);
920 bool entities
= false;
921 rtl::Reference
< unoidl::Provider
> prov
;
922 std::map
< OUString
, Item
> map
;
923 for (sal_uInt32 i
= 0; i
!= args
- 1; ++i
) {
925 OUString
uri(getArgumentUri(i
, i
== args
- 2 ? &entities
: nullptr));
927 mapEntities(mgr
, uri
, map
);
930 prov
= mgr
->addProvider(uri
);
931 } catch (unoidl::NoSuchFileException
&) {
933 << "Input <" << uri
<< "> does not exist" << std::endl
;
934 std::exit(EXIT_FAILURE
);
941 ? prov
->createRootCursor()
942 : rtl::Reference
< unoidl::MapCursor
>()),
945 osl::File
f(getArgumentUri(args
- 1, nullptr));
946 osl::FileBase::RC e
= f
.open(osl_File_OpenFlag_Write
);
947 if (e
== osl::FileBase::E_NOENT
) {
948 e
= f
.open(osl_File_OpenFlag_Write
| osl_File_OpenFlag_Create
);
950 if (e
!= osl::FileBase::E_None
) {
952 << "Cannot open <" << f
.getURL() << "> for writing, error code "
954 std::exit(EXIT_FAILURE
);
956 write(f
, "UNOIDL\xFF\0", 8);
957 write32(f
, 0); // root map offset
958 write32(f
, 0); // root map size
961 RTL_CONSTASCII_STRINGPARAM(
962 "\0** Created by LibreOffice " LIBO_VERSION_DOTTED
963 " unoidl-write **\0"));
965 sal_uInt64 off
= writeMap(f
, map
, &size
);
966 e
= f
.setSize(getOffset(f
)); // truncate in case it already existed
967 if (e
!= osl::FileBase::E_None
) {
969 << "Cannot set size of <" << f
.getURL() << ">, error code "
971 std::exit(EXIT_FAILURE
);
973 e
= f
.setPos(osl_Pos_Absolut
, 8);
974 if (e
!= osl::FileBase::E_None
) {
976 << "Cannot rewind current position in <" << f
.getURL()
977 << ">, error code " << +e
<< std::endl
;
978 std::exit(EXIT_FAILURE
);
982 // overflow from std::map::size_type -> sal_uInt64 is unrealistic
984 if (e
!= osl::FileBase::E_None
) {
986 << "Cannot close <" << f
.getURL()
987 << "> after writing, error code " << +e
<< std::endl
;
988 std::exit(EXIT_FAILURE
);
991 } catch (unoidl::FileFormatException
& e1
) {
993 << "Bad input <" << e1
.getUri() << ">: " << e1
.getDetail()
995 std::exit(EXIT_FAILURE
);
996 } catch (std::exception
& e1
) {
998 << "Failure: " << e1
.what()
1000 std::exit(EXIT_FAILURE
);
1005 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */