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
)) {
65 } else if (entities
!= 0) {
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 (std::vector
< OUString
>::const_iterator
i(annotations
.begin());
275 i
!= annotations
.end(); ++i
)
277 writeIdxString(file
, toUtf8(*i
));
284 rtl::Reference
< unoidl::PublishableEntity
> const & entity
,
285 bool annotated
, bool flag
= false)
288 sal_uInt64 v
= entity
->getSort();
289 if (entity
->isPublished()) {
302 explicit Item(rtl::Reference
< unoidl::Entity
> const & theEntity
):
303 entity(theEntity
), nameOffset(0), dataOffset(0)
306 rtl::Reference
< unoidl::Entity
> entity
;
307 std::map
< OUString
, Item
> module
;
308 sal_uInt64 nameOffset
;
309 sal_uInt64 dataOffset
;
314 unoidl::ConstantValue
const & theConstant
,
315 std::vector
< OUString
> const & theAnnotations
):
316 constant(theConstant
), annotations(theAnnotations
), nameOffset(0),
320 unoidl::ConstantValue constant
;
321 std::vector
< OUString
> annotations
;
322 sal_uInt64 nameOffset
;
323 sal_uInt64 dataOffset
;
327 rtl::Reference
< unoidl::Manager
> const & manager
, OUString
const & uri
,
328 std::map
< OUString
, Item
> & map
)
330 assert(manager
.is());
332 osl::FileBase::RC e
= f
.open(osl_File_OpenFlag_Read
);
333 if (e
!= osl::FileBase::E_None
) {
335 << "Cannot open <" << f
.getURL() << "> for reading, error code "
337 std::exit(EXIT_FAILURE
);
341 e
= f
.isEndOfFile(&eof
);
342 if (e
!= osl::FileBase::E_None
) {
344 << "Cannot check <" << f
.getURL() << "> for EOF, error code "
346 std::exit(EXIT_FAILURE
);
351 rtl::ByteSequence s1
;
353 if (e
!= osl::FileBase::E_None
) {
355 << "Cannot read from <" << f
.getURL() << ">, error code "
357 std::exit(EXIT_FAILURE
);
360 if (!rtl_convertStringToUString(
361 &s2
.pData
, reinterpret_cast< char const * >(s1
.getConstArray()),
362 s1
.getLength(), RTL_TEXTENCODING_UTF8
,
363 (RTL_TEXTTOUNICODE_FLAGS_UNDEFINED_ERROR
364 | RTL_TEXTTOUNICODE_FLAGS_MBUNDEFINED_ERROR
365 | RTL_TEXTTOUNICODE_FLAGS_INVALID_ERROR
)))
368 << "Cannot interpret line read from <" << f
.getURL()
369 << "> as UTF-8" << std::endl
;
370 std::exit(EXIT_FAILURE
);
372 for (sal_Int32 i
= 0; i
!= -1;) {
373 OUString
t(s2
.getToken(0, ' ', i
));
375 rtl::Reference
< unoidl::Entity
> ent(manager
->findEntity(t
));
378 << "Unknown entity \"" << t
<< "\" read from <"
379 << f
.getURL() << ">" << std::endl
;
380 std::exit(EXIT_FAILURE
);
382 if (ent
->getSort() == unoidl::Entity::SORT_MODULE
) {
384 << "Module entity \"" << t
<< "\" read from <"
385 << f
.getURL() << ">" << std::endl
;
386 std::exit(EXIT_FAILURE
);
388 std::map
< OUString
, Item
> * map2
= &map
;
389 for (sal_Int32 j
= 0;;) {
390 OUString
id(t
.getToken(0, '.', j
));
392 map2
->insert(std::make_pair(id
, Item(ent
)));
395 std::map
< OUString
, Item
>::iterator
k(map2
->find(id
));
396 if (k
== map2
->end()) {
397 rtl::Reference
< unoidl::Entity
> ent2(
398 manager
->findEntity(t
.copy(0, j
- 1)));
400 k
= map2
->insert(std::make_pair(id
, Item(ent2
))).first
;
403 k
->second
.entity
->getSort()
404 == unoidl::Entity::SORT_MODULE
);
405 map2
= &k
->second
.module
;
411 if (e
!= osl::FileBase::E_None
) {
413 << "Cannot close <" << f
.getURL() << "> after reading, error code "
415 std::exit(EXIT_FAILURE
);
420 rtl::Reference
< unoidl::MapCursor
> const & cursor
,
421 std::map
< OUString
, Item
> & map
)
426 rtl::Reference
< unoidl::Entity
> ent(cursor
->getNext(&name
));
430 std::pair
< std::map
< OUString
, Item
>::iterator
, bool > i(
431 map
.insert(std::make_pair(name
, Item(ent
))));
433 std::cout
<< "Duplicate name \"" << name
<< '"' << std::endl
;
434 std::exit(EXIT_FAILURE
);
436 if (i
.first
->second
.entity
->getSort()
437 == unoidl::Entity::SORT_MODULE
)
440 rtl::Reference
< unoidl::ModuleEntity
>(
441 static_cast< unoidl::ModuleEntity
* >(
442 i
.first
->second
.entity
.get()))->createCursor(),
443 i
.first
->second
.module
);
450 osl::File
& file
, std::map
< OUString
, Item
> & map
, std::size_t * rootSize
)
452 for (std::map
< OUString
, Item
>::iterator
i(map
.begin()); i
!= map
.end();
455 switch (i
->second
.entity
->getSort()) {
456 case unoidl::Entity::SORT_MODULE
:
457 i
->second
.dataOffset
= writeMap(file
, i
->second
.module
, 0);
459 case unoidl::Entity::SORT_ENUM_TYPE
:
461 rtl::Reference
< unoidl::EnumTypeEntity
> ent2(
462 static_cast< unoidl::EnumTypeEntity
* >(
463 i
->second
.entity
.get()));
464 bool ann
= !ent2
->getAnnotations().empty();
465 for (std::vector
< unoidl::EnumTypeEntity::Member
>::
466 const_iterator
j(ent2
->getMembers().begin());
467 !ann
&& j
!= ent2
->getMembers().end(); ++j
)
469 ann
= !j
->annotations
.empty();
471 i
->second
.dataOffset
= getOffset(file
);
472 writeKind(file
, ent2
.get(), ann
);
473 write32(file
, ent2
->getMembers().size());
474 for (std::vector
< unoidl::EnumTypeEntity::Member
>::
475 const_iterator
j(ent2
->getMembers().begin());
476 j
!= ent2
->getMembers().end(); ++j
)
478 writeIdxName(file
, j
->name
);
479 write32(file
, static_cast< sal_uInt32
>(j
->value
));
480 writeAnnotations(file
, ann
, j
->annotations
);
482 writeAnnotations(file
, ann
, ent2
->getAnnotations());
485 case unoidl::Entity::SORT_PLAIN_STRUCT_TYPE
:
487 rtl::Reference
< unoidl::PlainStructTypeEntity
> ent2(
488 static_cast< unoidl::PlainStructTypeEntity
* >(
489 i
->second
.entity
.get()));
490 bool ann
= !ent2
->getAnnotations().empty();
491 for (std::vector
< unoidl::PlainStructTypeEntity::Member
>::
492 const_iterator
j(ent2
->getDirectMembers().begin());
493 !ann
&& j
!= ent2
->getDirectMembers().end(); ++j
)
495 ann
= !j
->annotations
.empty();
497 i
->second
.dataOffset
= getOffset(file
);
499 file
, ent2
.get(), ann
, !ent2
->getDirectBase().isEmpty());
500 if (!ent2
->getDirectBase().isEmpty()) {
501 writeIdxName(file
, ent2
->getDirectBase());
503 write32(file
, ent2
->getDirectMembers().size());
504 for (std::vector
< unoidl::PlainStructTypeEntity::Member
>::
505 const_iterator
j(ent2
->getDirectMembers().begin());
506 j
!= ent2
->getDirectMembers().end(); ++j
)
508 writeIdxName(file
, j
->name
);
509 writeIdxName(file
, j
->type
);
510 writeAnnotations(file
, ann
, j
->annotations
);
512 writeAnnotations(file
, ann
, ent2
->getAnnotations());
515 case unoidl::Entity::SORT_POLYMORPHIC_STRUCT_TYPE_TEMPLATE
:
517 rtl::Reference
< unoidl::PolymorphicStructTypeTemplateEntity
>
520 unoidl::PolymorphicStructTypeTemplateEntity
* >(
521 i
->second
.entity
.get()));
522 bool ann
= !ent2
->getAnnotations().empty();
524 unoidl::PolymorphicStructTypeTemplateEntity::Member
>::
526 ent2
->getMembers().begin());
527 !ann
&& j
!= ent2
->getMembers().end(); ++j
)
529 ann
= !j
->annotations
.empty();
531 i
->second
.dataOffset
= getOffset(file
);
532 writeKind(file
, ent2
.get(), ann
);
533 write32(file
, ent2
->getTypeParameters().size());
534 for (std::vector
< OUString
>::const_iterator
j(
535 ent2
->getTypeParameters().begin());
536 j
!= ent2
->getTypeParameters().end(); ++j
)
538 writeIdxName(file
, *j
);
540 write32(file
, ent2
->getMembers().size());
542 unoidl::PolymorphicStructTypeTemplateEntity::Member
>::
544 ent2
->getMembers().begin());
545 j
!= ent2
->getMembers().end(); ++j
)
548 if (j
->parameterized
) {
552 writeIdxName(file
, j
->name
);
553 writeIdxName(file
, j
->type
);
554 writeAnnotations(file
, ann
, j
->annotations
);
556 writeAnnotations(file
, ann
, ent2
->getAnnotations());
559 case unoidl::Entity::SORT_EXCEPTION_TYPE
:
561 rtl::Reference
< unoidl::ExceptionTypeEntity
> ent2(
562 static_cast< unoidl::ExceptionTypeEntity
* >(
563 i
->second
.entity
.get()));
564 bool ann
= !ent2
->getAnnotations().empty();
565 for (std::vector
< unoidl::ExceptionTypeEntity::Member
>::
566 const_iterator
j(ent2
->getDirectMembers().begin());
567 !ann
&& j
!= ent2
->getDirectMembers().end(); ++j
)
569 ann
= !j
->annotations
.empty();
571 i
->second
.dataOffset
= getOffset(file
);
573 file
, ent2
.get(), ann
, !ent2
->getDirectBase().isEmpty());
574 if (!ent2
->getDirectBase().isEmpty()) {
575 writeIdxName(file
, ent2
->getDirectBase());
577 write32(file
, ent2
->getDirectMembers().size());
578 for (std::vector
< unoidl::ExceptionTypeEntity::Member
>::
579 const_iterator
j(ent2
->getDirectMembers().begin());
580 j
!= ent2
->getDirectMembers().end(); ++j
)
582 writeIdxName(file
, j
->name
);
583 writeIdxName(file
, j
->type
);
584 writeAnnotations(file
, ann
, j
->annotations
);
586 writeAnnotations(file
, ann
, ent2
->getAnnotations());
589 case unoidl::Entity::SORT_INTERFACE_TYPE
:
591 rtl::Reference
< unoidl::InterfaceTypeEntity
> ent2(
592 static_cast< unoidl::InterfaceTypeEntity
* >(
593 i
->second
.entity
.get()));
594 bool ann
= !ent2
->getAnnotations().empty();
595 for (std::vector
< unoidl::AnnotatedReference
>::const_iterator
596 j(ent2
->getDirectMandatoryBases().begin());
597 !ann
&& j
!= ent2
->getDirectMandatoryBases().end(); ++j
)
599 ann
= !j
->annotations
.empty();
601 for (std::vector
< unoidl::AnnotatedReference
>::const_iterator
602 j(ent2
->getDirectOptionalBases().begin());
603 !ann
&& j
!= ent2
->getDirectOptionalBases().end(); ++j
)
605 ann
= !j
->annotations
.empty();
607 for (std::vector
< unoidl::InterfaceTypeEntity::Attribute
>::
608 const_iterator
j(ent2
->getDirectAttributes().begin());
609 !ann
&& j
!= ent2
->getDirectAttributes().end(); ++j
)
611 ann
= !j
->annotations
.empty();
613 for (std::vector
< unoidl::InterfaceTypeEntity::Method
>::
614 const_iterator
j(ent2
->getDirectMethods().begin());
615 !ann
&& j
!= ent2
->getDirectMethods().end(); ++j
)
617 ann
= !j
->annotations
.empty();
619 i
->second
.dataOffset
= getOffset(file
);
620 writeKind(file
, ent2
.get(), ann
);
621 write32(file
, ent2
->getDirectMandatoryBases().size());
622 for (std::vector
< unoidl::AnnotatedReference
>::const_iterator
623 j(ent2
->getDirectMandatoryBases().begin());
624 j
!= ent2
->getDirectMandatoryBases().end(); ++j
)
626 writeIdxName(file
, j
->name
);
627 writeAnnotations(file
, ann
, j
->annotations
);
629 write32(file
, ent2
->getDirectOptionalBases().size());
630 for (std::vector
< unoidl::AnnotatedReference
>::const_iterator
631 j(ent2
->getDirectOptionalBases().begin());
632 j
!= ent2
->getDirectOptionalBases().end(); ++j
)
634 writeIdxName(file
, j
->name
);
635 writeAnnotations(file
, ann
, j
->annotations
);
637 write32(file
, ent2
->getDirectAttributes().size());
638 for (std::vector
< unoidl::InterfaceTypeEntity::Attribute
>::
639 const_iterator
j(ent2
->getDirectAttributes().begin());
640 j
!= ent2
->getDirectAttributes().end(); ++j
)
650 writeIdxName(file
, j
->name
);
651 writeIdxName(file
, j
->type
);
652 write32(file
, j
->getExceptions
.size());
653 for (std::vector
< OUString
>::const_iterator
k(
654 j
->getExceptions
.begin());
655 k
!= j
->getExceptions
.end(); ++k
)
657 writeIdxName(file
, *k
);
660 write32(file
, j
->setExceptions
.size());
661 for (std::vector
< OUString
>::const_iterator
k(
662 j
->setExceptions
.begin());
663 k
!= j
->setExceptions
.end(); ++k
)
665 writeIdxName(file
, *k
);
668 writeAnnotations(file
, ann
, j
->annotations
);
670 write32(file
, ent2
->getDirectMethods().size());
671 for (std::vector
< unoidl::InterfaceTypeEntity::Method
>::
672 const_iterator
j(ent2
->getDirectMethods().begin());
673 j
!= ent2
->getDirectMethods().end(); ++j
)
675 writeIdxName(file
, j
->name
);
676 writeIdxName(file
, j
->returnType
);
677 write32(file
, j
->parameters
.size());
679 unoidl::InterfaceTypeEntity::Method::Parameter
>::
680 const_iterator
k(j
->parameters
.begin());
681 k
!= j
->parameters
.end(); ++k
)
683 write8(file
, k
->direction
);
684 writeIdxName(file
, k
->name
);
685 writeIdxName(file
, k
->type
);
687 write32(file
, j
->exceptions
.size());
688 for (std::vector
< OUString
>::const_iterator
k(
689 j
->exceptions
.begin());
690 k
!= j
->exceptions
.end(); ++k
)
692 writeIdxName(file
, *k
);
694 writeAnnotations(file
, ann
, j
->annotations
);
696 writeAnnotations(file
, ann
, ent2
->getAnnotations());
699 case unoidl::Entity::SORT_TYPEDEF
:
701 rtl::Reference
< unoidl::TypedefEntity
> ent2(
702 static_cast< unoidl::TypedefEntity
* >(
703 i
->second
.entity
.get()));
704 bool ann
= !ent2
->getAnnotations().empty();
705 i
->second
.dataOffset
= getOffset(file
);
706 writeKind(file
, ent2
.get(), ann
);
707 writeIdxName(file
, ent2
->getType());
708 writeAnnotations(file
, ann
, ent2
->getAnnotations());
711 case unoidl::Entity::SORT_CONSTANT_GROUP
:
713 rtl::Reference
< unoidl::ConstantGroupEntity
> ent2(
714 static_cast< unoidl::ConstantGroupEntity
* >(
715 i
->second
.entity
.get()));
716 std::map
< OUString
, ConstItem
> cmap
;
717 for (std::vector
< unoidl::ConstantGroupEntity::Member
>::
718 const_iterator
j(ent2
->getMembers().begin());
719 j
!= ent2
->getMembers().end(); ++j
)
723 j
->name
, ConstItem(j
->value
, j
->annotations
))).
727 << "Duplicate constant group member name \""
728 << j
->name
<< '"' << std::endl
;
729 std::exit(EXIT_FAILURE
);
732 for (std::map
< OUString
, ConstItem
>::iterator
j(cmap
.begin());
733 j
!= cmap
.end(); ++j
)
735 j
->second
.dataOffset
= getOffset(file
);
736 sal_uInt64 v
= j
->second
.constant
.type
;
737 if (!j
->second
.annotations
.empty()) {
741 switch (j
->second
.constant
.type
) {
742 case unoidl::ConstantValue::TYPE_BOOLEAN
:
743 write8(file
, j
->second
.constant
.booleanValue
? 1 : 0);
745 case unoidl::ConstantValue::TYPE_BYTE
:
748 static_cast< sal_uInt8
>(
749 j
->second
.constant
.byteValue
));
751 case unoidl::ConstantValue::TYPE_SHORT
:
754 static_cast< sal_uInt16
>(
755 j
->second
.constant
.shortValue
));
757 case unoidl::ConstantValue::TYPE_UNSIGNED_SHORT
:
758 write16(file
, j
->second
.constant
.unsignedShortValue
);
760 case unoidl::ConstantValue::TYPE_LONG
:
763 static_cast< sal_uInt32
>(
764 j
->second
.constant
.longValue
));
766 case unoidl::ConstantValue::TYPE_UNSIGNED_LONG
:
767 write32(file
, j
->second
.constant
.unsignedLongValue
);
769 case unoidl::ConstantValue::TYPE_HYPER
:
772 static_cast< sal_uInt64
>(
773 j
->second
.constant
.hyperValue
));
775 case unoidl::ConstantValue::TYPE_UNSIGNED_HYPER
:
776 write64(file
, j
->second
.constant
.unsignedHyperValue
);
778 case unoidl::ConstantValue::TYPE_FLOAT
:
779 writeIso60599Binary32(
780 file
, j
->second
.constant
.floatValue
);
782 case unoidl::ConstantValue::TYPE_DOUBLE
:
783 writeIso60599Binary64(
784 file
, j
->second
.constant
.doubleValue
);
787 for (;;) { std::abort(); } // this cannot happen
790 file
, !j
->second
.annotations
.empty(),
791 j
->second
.annotations
);
793 for (std::map
< OUString
, ConstItem
>::iterator
j(
795 j
!= cmap
.end(); ++j
)
797 j
->second
.nameOffset
= writeNulName(file
, j
->first
);
799 bool ann
= !ent2
->getAnnotations().empty();
800 i
->second
.dataOffset
= getOffset(file
);
801 writeKind(file
, ent2
.get(), ann
);
802 write32(file
, cmap
.size());
803 // overflow from std::map::size_type -> sal_uInt64 is
805 for (std::map
< OUString
, ConstItem
>::iterator
j(
807 j
!= cmap
.end(); ++j
)
809 write32(file
, j
->second
.nameOffset
);
810 write32(file
, j
->second
.dataOffset
);
812 writeAnnotations(file
, ann
, ent2
->getAnnotations());
815 case unoidl::Entity::SORT_SINGLE_INTERFACE_BASED_SERVICE
:
817 rtl::Reference
< unoidl::SingleInterfaceBasedServiceEntity
>
820 unoidl::SingleInterfaceBasedServiceEntity
* >(
821 i
->second
.entity
.get()));
822 bool dfltCtor
= ent2
->getConstructors().size() == 1
823 && ent2
->getConstructors()[0].defaultConstructor
;
824 bool ann
= !ent2
->getAnnotations().empty();
827 unoidl::SingleInterfaceBasedServiceEntity::
828 Constructor
>::const_iterator
j(
829 ent2
->getConstructors().begin());
830 !ann
&& j
!= ent2
->getConstructors().end(); ++j
)
832 ann
= !j
->annotations
.empty();
835 i
->second
.dataOffset
= getOffset(file
);
836 writeKind(file
, ent2
.get(), ann
, dfltCtor
);
837 writeIdxName(file
, ent2
->getBase());
839 write32(file
, ent2
->getConstructors().size());
841 unoidl::SingleInterfaceBasedServiceEntity::
842 Constructor
>::const_iterator
j(
843 ent2
->getConstructors().begin());
844 j
!= ent2
->getConstructors().end(); ++j
)
846 if (j
->defaultConstructor
) {
848 << "Unexpected default constructor \""
849 << j
->name
<< '"' << std::endl
;
850 std::exit(EXIT_FAILURE
);
852 writeIdxName(file
, j
->name
);
853 write32(file
, j
->parameters
.size());
855 unoidl::SingleInterfaceBasedServiceEntity::
856 Constructor::Parameter
>::const_iterator
k(
857 j
->parameters
.begin());
858 k
!= j
->parameters
.end(); ++k
)
865 writeIdxName(file
, k
->name
);
866 writeIdxName(file
, k
->type
);
868 write32(file
, j
->exceptions
.size());
869 for (std::vector
< OUString
>::const_iterator
k(
870 j
->exceptions
.begin());
871 k
!= j
->exceptions
.end(); ++k
)
873 writeIdxName(file
, *k
);
875 writeAnnotations(file
, ann
, j
->annotations
);
878 writeAnnotations(file
, ann
, ent2
->getAnnotations());
881 case unoidl::Entity::SORT_ACCUMULATION_BASED_SERVICE
:
883 rtl::Reference
< unoidl::AccumulationBasedServiceEntity
> ent2(
884 static_cast< unoidl::AccumulationBasedServiceEntity
* >(
885 i
->second
.entity
.get()));
886 bool ann
= !ent2
->getAnnotations().empty();
887 for (std::vector
< unoidl::AnnotatedReference
>::const_iterator
888 j(ent2
->getDirectMandatoryBaseServices().begin());
889 !ann
&& j
!= ent2
->getDirectMandatoryBaseServices().end();
892 ann
= !j
->annotations
.empty();
894 for (std::vector
< unoidl::AnnotatedReference
>::const_iterator
895 j(ent2
->getDirectOptionalBaseServices().begin());
896 !ann
&& j
!= ent2
->getDirectOptionalBaseServices().end();
899 ann
= !j
->annotations
.empty();
901 for (std::vector
< unoidl::AnnotatedReference
>::const_iterator
902 j(ent2
->getDirectMandatoryBaseInterfaces().begin());
904 && j
!= ent2
->getDirectMandatoryBaseInterfaces().end());
907 ann
= !j
->annotations
.empty();
909 for (std::vector
< unoidl::AnnotatedReference
>::const_iterator
910 j(ent2
->getDirectOptionalBaseInterfaces().begin());
911 !ann
&& j
!= ent2
->getDirectOptionalBaseInterfaces().end();
914 ann
= !j
->annotations
.empty();
917 unoidl::AccumulationBasedServiceEntity::Property
>::
919 ent2
->getDirectProperties().begin());
920 !ann
&& j
!= ent2
->getDirectProperties().end(); ++j
)
922 ann
= !j
->annotations
.empty();
924 i
->second
.dataOffset
= getOffset(file
);
925 writeKind(file
, ent2
.get(), ann
);
926 write32(file
, ent2
->getDirectMandatoryBaseServices().size());
927 for (std::vector
< unoidl::AnnotatedReference
>::const_iterator
928 j(ent2
->getDirectMandatoryBaseServices().begin());
929 j
!= ent2
->getDirectMandatoryBaseServices().end(); ++j
)
931 writeIdxName(file
, j
->name
);
932 writeAnnotations(file
, ann
, j
->annotations
);
934 write32(file
, ent2
->getDirectOptionalBaseServices().size());
935 for (std::vector
< unoidl::AnnotatedReference
>::const_iterator
936 j(ent2
->getDirectOptionalBaseServices().begin());
937 j
!= ent2
->getDirectOptionalBaseServices().end(); ++j
)
939 writeIdxName(file
, j
->name
);
940 writeAnnotations(file
, ann
, j
->annotations
);
942 write32(file
, ent2
->getDirectMandatoryBaseInterfaces().size());
943 for (std::vector
< unoidl::AnnotatedReference
>::const_iterator
944 j(ent2
->getDirectMandatoryBaseInterfaces().begin());
945 j
!= ent2
->getDirectMandatoryBaseInterfaces().end(); ++j
)
947 writeIdxName(file
, j
->name
);
948 writeAnnotations(file
, ann
, j
->annotations
);
950 write32(file
, ent2
->getDirectOptionalBaseInterfaces().size());
951 for (std::vector
< unoidl::AnnotatedReference
>::const_iterator
952 j(ent2
->getDirectOptionalBaseInterfaces().begin());
953 j
!= ent2
->getDirectOptionalBaseInterfaces().end(); ++j
)
955 writeIdxName(file
, j
->name
);
956 writeAnnotations(file
, ann
, j
->annotations
);
958 write32(file
, ent2
->getDirectProperties().size());
960 unoidl::AccumulationBasedServiceEntity::Property
>::
962 ent2
->getDirectProperties().begin());
963 j
!= ent2
->getDirectProperties().end(); ++j
)
965 write16(file
, static_cast< sal_uInt16
>(j
->attributes
));
966 writeIdxName(file
, j
->name
);
967 writeIdxName(file
, j
->type
);
968 writeAnnotations(file
, ann
, j
->annotations
);
970 writeAnnotations(file
, ann
, ent2
->getAnnotations());
973 case unoidl::Entity::SORT_INTERFACE_BASED_SINGLETON
:
975 rtl::Reference
< unoidl::InterfaceBasedSingletonEntity
> ent2(
976 static_cast< unoidl::InterfaceBasedSingletonEntity
* >(
977 i
->second
.entity
.get()));
978 bool ann
= !ent2
->getAnnotations().empty();
979 i
->second
.dataOffset
= getOffset(file
);
980 writeKind(file
, ent2
.get(), ann
);
981 writeIdxName(file
, ent2
->getBase());
982 writeAnnotations(file
, ann
, ent2
->getAnnotations());
985 case unoidl::Entity::SORT_SERVICE_BASED_SINGLETON
:
987 rtl::Reference
< unoidl::ServiceBasedSingletonEntity
> ent2(
988 static_cast< unoidl::ServiceBasedSingletonEntity
* >(
989 i
->second
.entity
.get()));
990 bool ann
= !ent2
->getAnnotations().empty();
991 i
->second
.dataOffset
= getOffset(file
);
992 writeKind(file
, ent2
.get(), ann
);
993 writeIdxName(file
, ent2
->getBase());
994 writeAnnotations(file
, ann
, ent2
->getAnnotations());
999 for (std::map
< OUString
, Item
>::iterator
i(map
.begin()); i
!= map
.end();
1002 i
->second
.nameOffset
= writeNulName(file
, i
->first
);
1004 sal_uInt64 off
= getOffset(file
);
1005 if (rootSize
== 0) {
1006 write8(file
, 0); // SORT_MODULE
1007 write32(file
, map
.size());
1008 // overflow from std::map::size_type -> sal_uInt64 is unrealistic
1010 *rootSize
= map
.size();
1011 // overflow from std::map::size_type -> std::size_t is unrealistic
1013 for (std::map
< OUString
, Item
>::iterator
i(map
.begin()); i
!= map
.end();
1016 write32(file
, i
->second
.nameOffset
);
1017 write32(file
, i
->second
.dataOffset
);
1024 SAL_IMPLEMENT_MAIN() {
1026 sal_uInt32 args
= rtl_getAppCommandArgCount();
1030 rtl::Reference
< unoidl::Manager
> mgr(new unoidl::Manager
);
1031 bool entities
= false;
1032 rtl::Reference
< unoidl::Provider
> prov
;
1033 std::map
< OUString
, Item
> map
;
1034 for (sal_uInt32 i
= 0; i
!= args
- 1; ++i
) {
1036 OUString
uri(getArgumentUri(i
, i
== args
- 2 ? &entities
: 0));
1038 mapEntities(mgr
, uri
, map
);
1041 prov
= mgr
->addProvider(uri
);
1042 } catch (unoidl::NoSuchFileException
&) {
1044 << "Input <" << uri
<< "> does not exist" << std::endl
;
1045 std::exit(EXIT_FAILURE
);
1052 ? prov
->createRootCursor()
1053 : rtl::Reference
< unoidl::MapCursor
>()),
1056 osl::File
f(getArgumentUri(args
- 1, 0));
1057 osl::FileBase::RC e
= f
.open(osl_File_OpenFlag_Write
);
1058 if (e
== osl::FileBase::E_NOENT
) {
1059 e
= f
.open(osl_File_OpenFlag_Write
| osl_File_OpenFlag_Create
);
1061 if (e
!= osl::FileBase::E_None
) {
1063 << "Cannot open <" << f
.getURL() << "> for writing, error code "
1065 std::exit(EXIT_FAILURE
);
1067 write(f
, "UNOIDL\xFF\0", 8);
1068 write32(f
, 0); // root map offset
1069 write32(f
, 0); // root map size
1072 RTL_CONSTASCII_STRINGPARAM(
1073 "\0** Created by LibreOffice " LIBO_VERSION_DOTTED
1074 " unoidl-write **\0"));
1076 sal_uInt64 off
= writeMap(f
, map
, &size
);
1077 e
= f
.setSize(getOffset(f
)); // truncate in case it already existed
1078 if (e
!= osl::FileBase::E_None
) {
1080 << "Cannot set size of <" << f
.getURL() << ">, error code "
1082 std::exit(EXIT_FAILURE
);
1084 e
= f
.setPos(osl_Pos_Absolut
, 8);
1085 if (e
!= osl::FileBase::E_None
) {
1087 << "Cannot rewind current position in <" << f
.getURL()
1088 << ">, error code " << +e
<< std::endl
;
1089 std::exit(EXIT_FAILURE
);
1093 // overflow from std::map::size_type -> sal_uInt64 is unrealistic
1095 if (e
!= osl::FileBase::E_None
) {
1097 << "Cannot close <" << f
.getURL()
1098 << "> after writing, error code " << +e
<< std::endl
;
1099 std::exit(EXIT_FAILURE
);
1101 return EXIT_SUCCESS
;
1102 } catch (unoidl::FileFormatException
& e1
) {
1104 << "Bad input <" << e1
.getUri() << ">: " << e1
.getDetail()
1106 std::exit(EXIT_FAILURE
);
1110 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */