bump product version to 5.0.4.1
[LibreOffice.git] / unoidl / source / unoidl-write.cxx
blob3ea09d3840a7dc5b7072aec1422709ba69645111
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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/.
8 */
10 #include "sal/config.h"
12 #include <cassert>
13 #include <cstddef>
14 #include <cstdlib>
15 #include <iostream>
16 #include <map>
17 #include <utility>
18 #include <vector>
20 #include "config_version.h"
21 #include "osl/endian.h"
22 #include "osl/file.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"
32 #include "sal/main.h"
33 #include "unoidl/unoidl.hxx"
35 namespace {
37 void badUsage() {
38 std::cerr
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,"
43 " a single .idl")
44 << std::endl
45 << ("file, or a root directory of an .idl file tree; and the UTF-8"
46 " encoded <entities")
47 << std::endl
48 << ("file> contains zero or more space-separated names of (non-module)"
49 " entities to")
50 << std::endl
51 << ("include in the output, and, if omitted, defaults to the complete"
52 " content of the")
53 << std::endl << "last <registry>, if any." << std::endl;
54 std::exit(EXIT_FAILURE);
57 OUString getArgumentUri(sal_uInt32 argument, bool * entities) {
58 OUString arg;
59 rtl_getAppCommandArg(argument, &arg.pData);
60 if (arg.startsWith("@", &arg)) {
61 if (entities == 0) {
62 badUsage();
64 *entities = true;
65 } else if (entities != 0) {
66 *entities = false;
68 OUString url;
69 osl::FileBase::RC e1 = osl::FileBase::getFileURLFromSystemPath(arg, url);
70 if (e1 != osl::FileBase::E_None) {
71 std::cerr
72 << "Cannot convert \"" << arg << "\" to file URL, error code "
73 << +e1 << std::endl;
74 std::exit(EXIT_FAILURE);
76 OUString cwd;
77 oslProcessError e2 = osl_getProcessWorkingDir(&cwd.pData);
78 if (e2 != osl_Process_E_None) {
79 std::cerr
80 << "Cannot obtain working directory, error code " << +e2
81 << std::endl;
82 std::exit(EXIT_FAILURE);
84 OUString abs;
85 e1 = osl::FileBase::getAbsoluteFileURL(cwd, url, abs);
86 if (e1 != osl::FileBase::E_None) {
87 std::cerr
88 << "Cannot make \"" << url
89 << "\" into an absolute file URL, error code " << +e1 << std::endl;
90 std::exit(EXIT_FAILURE);
92 return abs;
95 sal_uInt64 getOffset(osl::File & file) {
96 sal_uInt64 off;
97 osl::FileBase::RC e = file.getPos(off);
98 if (e != osl::FileBase::E_None) {
99 std::cerr
100 << "Cannot determine current position in <" << file.getURL()
101 << ">, error code " << +e << std::endl;
102 std::exit(EXIT_FAILURE);
104 return off;
107 void write(osl::File & file, void const * buffer, sal_uInt64 size) {
108 sal_uInt64 n;
109 osl::FileBase::RC e = file.write(buffer, size, n);
110 if (e != osl::FileBase::E_None) {
111 std::cerr
112 << "Cannot write to <" << file.getURL() << ">, error code " << +e
113 << std::endl;
114 std::exit(EXIT_FAILURE);
116 if (n != size) {
117 std::cerr
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) {
125 if (value > 0xFF) {
126 std::cerr
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) {
137 std::cerr
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) {
149 std::cerr
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) {
175 union {
176 unsigned char buf[4];
177 float f; // assuming float is ISO 60599 binary32
178 } sa;
179 sa.f = value;
180 #if defined OSL_BIGENDIAN
181 std::swap(sa.buf[0], sa.buf[3]);
182 std::swap(sa.buf[1], sa.buf[2]);
183 #endif
184 write(file, sa.buf, SAL_N_ELEMENTS(sa.buf));
187 void writeIso60599Binary64(osl::File & file, double value) {
188 union {
189 unsigned char buf[8];
190 float d; // assuming double is ISO 60599 binary64
191 } sa;
192 sa.d = value;
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]);
198 #endif
199 write(file, sa.buf, SAL_N_ELEMENTS(sa.buf));
202 OString toAscii(OUString const & name) {
203 OString ascii;
204 if (!name.convertToString(
205 &ascii, RTL_TEXTENCODING_ASCII_US,
206 (RTL_UNICODETOTEXT_FLAGS_UNDEFINED_ERROR
207 | RTL_UNICODETOTEXT_FLAGS_INVALID_ERROR)))
209 std::cerr
210 << "Cannot convert \"" << name << "\" to US ASCII" << std::endl;
211 std::exit(EXIT_FAILURE);
213 return ascii;
216 OString toUtf8(OUString const & string) {
217 OString ascii;
218 if (!string.convertToString(
219 &ascii, RTL_TEXTENCODING_UTF8,
220 (RTL_UNICODETOTEXT_FLAGS_UNDEFINED_ERROR
221 | RTL_UNICODETOTEXT_FLAGS_INVALID_ERROR)))
223 std::cerr
224 << "Cannot convert \"" << string << "\" to UTF-8" << std::endl;
225 std::exit(EXIT_FAILURE);
227 return ascii;
230 sal_uInt64 writeNulName(osl::File & file, OUString const & name) {
231 OString ascii(toAscii(name));
232 if (ascii.indexOf('\0') != -1) {
233 std::cerr
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);
239 return off;
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)));
247 assert(
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());
251 } else {
252 if ((i->second & 0x80000000) != 0) {
253 std::cerr
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());
271 if (annotate) {
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));
282 void writeKind(
283 osl::File & file,
284 rtl::Reference< unoidl::PublishableEntity > const & entity,
285 bool annotated, bool flag = false)
287 assert(entity.is());
288 sal_uInt64 v = entity->getSort();
289 if (entity->isPublished()) {
290 v |= 0x80;
292 if (annotated) {
293 v |= 0x40;
295 if (flag) {
296 v |= 0x20;
298 write8(file, v);
301 struct Item {
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;
312 struct ConstItem {
313 ConstItem(
314 unoidl::ConstantValue const & theConstant,
315 std::vector< OUString > const & theAnnotations):
316 constant(theConstant), annotations(theAnnotations), nameOffset(0),
317 dataOffset(0)
320 unoidl::ConstantValue constant;
321 std::vector< OUString > annotations;
322 sal_uInt64 nameOffset;
323 sal_uInt64 dataOffset;
326 void mapEntities(
327 rtl::Reference< unoidl::Manager > const & manager, OUString const & uri,
328 std::map< OUString, Item > & map)
330 assert(manager.is());
331 osl::File f(uri);
332 osl::FileBase::RC e = f.open(osl_File_OpenFlag_Read);
333 if (e != osl::FileBase::E_None) {
334 std::cerr
335 << "Cannot open <" << f.getURL() << "> for reading, error code "
336 << +e << std::endl;
337 std::exit(EXIT_FAILURE);
339 for (;;) {
340 sal_Bool eof;
341 e = f.isEndOfFile(&eof);
342 if (e != osl::FileBase::E_None) {
343 std::cerr
344 << "Cannot check <" << f.getURL() << "> for EOF, error code "
345 << +e << std::endl;
346 std::exit(EXIT_FAILURE);
348 if (eof) {
349 break;
351 rtl::ByteSequence s1;
352 e = f.readLine(s1);
353 if (e != osl::FileBase::E_None) {
354 std::cerr
355 << "Cannot read from <" << f.getURL() << ">, error code "
356 << +e << std::endl;
357 std::exit(EXIT_FAILURE);
359 OUString s2;
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)))
367 std::cerr
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));
374 if (!t.isEmpty()) {
375 rtl::Reference< unoidl::Entity > ent(manager->findEntity(t));
376 if (!ent.is()) {
377 std::cerr
378 << "Unknown entity \"" << t << "\" read from <"
379 << f.getURL() << ">" << std::endl;
380 std::exit(EXIT_FAILURE);
382 if (ent->getSort() == unoidl::Entity::SORT_MODULE) {
383 std::cerr
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));
391 if (j == -1) {
392 map2->insert(std::make_pair(id, Item(ent)));
393 break;
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)));
399 assert(ent2.is());
400 k = map2->insert(std::make_pair(id, Item(ent2))).first;
402 assert(
403 k->second.entity->getSort()
404 == unoidl::Entity::SORT_MODULE);
405 map2 = &k->second.module;
410 e = f.close();
411 if (e != osl::FileBase::E_None) {
412 std::cerr
413 << "Cannot close <" << f.getURL() << "> after reading, error code "
414 << +e << std::endl;
415 std::exit(EXIT_FAILURE);
419 void mapCursor(
420 rtl::Reference< unoidl::MapCursor > const & cursor,
421 std::map< OUString, Item > & map)
423 if (cursor.is()) {
424 for (;;) {
425 OUString name;
426 rtl::Reference< unoidl::Entity > ent(cursor->getNext(&name));
427 if (!ent.is()) {
428 break;
430 std::pair< std::map< OUString, Item >::iterator, bool > i(
431 map.insert(std::make_pair(name, Item(ent))));
432 if (!i.second) {
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)
439 mapCursor(
440 rtl::Reference< unoidl::ModuleEntity >(
441 static_cast< unoidl::ModuleEntity * >(
442 i.first->second.entity.get()))->createCursor(),
443 i.first->second.module);
449 sal_uInt64 writeMap(
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();
453 ++i)
455 switch (i->second.entity->getSort()) {
456 case unoidl::Entity::SORT_MODULE:
457 i->second.dataOffset = writeMap(file, i->second.module, 0);
458 break;
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());
483 break;
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);
498 writeKind(
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());
513 break;
515 case unoidl::Entity::SORT_POLYMORPHIC_STRUCT_TYPE_TEMPLATE:
517 rtl::Reference< unoidl::PolymorphicStructTypeTemplateEntity >
518 ent2(
519 static_cast<
520 unoidl::PolymorphicStructTypeTemplateEntity * >(
521 i->second.entity.get()));
522 bool ann = !ent2->getAnnotations().empty();
523 for (std::vector<
524 unoidl::PolymorphicStructTypeTemplateEntity::Member >::
525 const_iterator j(
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());
541 for (std::vector<
542 unoidl::PolymorphicStructTypeTemplateEntity::Member >::
543 const_iterator j(
544 ent2->getMembers().begin());
545 j != ent2->getMembers().end(); ++j)
547 sal_uInt64 f = 0;
548 if (j->parameterized) {
549 f |= 0x01;
551 write8(file, f);
552 writeIdxName(file, j->name);
553 writeIdxName(file, j->type);
554 writeAnnotations(file, ann, j->annotations);
556 writeAnnotations(file, ann, ent2->getAnnotations());
557 break;
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);
572 writeKind(
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());
587 break;
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)
642 sal_uInt64 f = 0;
643 if (j->bound) {
644 f |= 0x01;
646 if (j->readOnly) {
647 f |= 0x02;
649 write8(file, f);
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);
659 if (!j->readOnly) {
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());
678 for (std::vector<
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());
697 break;
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());
709 break;
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)
721 if (!cmap.insert(
722 std::make_pair(
723 j->name, ConstItem(j->value, j->annotations))).
724 second)
726 std::cout
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()) {
738 v |= 0x80;
740 write8(file, v);
741 switch (j->second.constant.type) {
742 case unoidl::ConstantValue::TYPE_BOOLEAN:
743 write8(file, j->second.constant.booleanValue ? 1 : 0);
744 break;
745 case unoidl::ConstantValue::TYPE_BYTE:
746 write8(
747 file,
748 static_cast< sal_uInt8 >(
749 j->second.constant.byteValue));
750 break;
751 case unoidl::ConstantValue::TYPE_SHORT:
752 write16(
753 file,
754 static_cast< sal_uInt16 >(
755 j->second.constant.shortValue));
756 break;
757 case unoidl::ConstantValue::TYPE_UNSIGNED_SHORT:
758 write16(file, j->second.constant.unsignedShortValue);
759 break;
760 case unoidl::ConstantValue::TYPE_LONG:
761 write32(
762 file,
763 static_cast< sal_uInt32 >(
764 j->second.constant.longValue));
765 break;
766 case unoidl::ConstantValue::TYPE_UNSIGNED_LONG:
767 write32(file, j->second.constant.unsignedLongValue);
768 break;
769 case unoidl::ConstantValue::TYPE_HYPER:
770 write64(
771 file,
772 static_cast< sal_uInt64 >(
773 j->second.constant.hyperValue));
774 break;
775 case unoidl::ConstantValue::TYPE_UNSIGNED_HYPER:
776 write64(file, j->second.constant.unsignedHyperValue);
777 break;
778 case unoidl::ConstantValue::TYPE_FLOAT:
779 writeIso60599Binary32(
780 file, j->second.constant.floatValue);
781 break;
782 case unoidl::ConstantValue::TYPE_DOUBLE:
783 writeIso60599Binary64(
784 file, j->second.constant.doubleValue);
785 break;
786 default:
787 for (;;) { std::abort(); } // this cannot happen
789 writeAnnotations(
790 file, !j->second.annotations.empty(),
791 j->second.annotations);
793 for (std::map< OUString, ConstItem >::iterator j(
794 cmap.begin());
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
804 // unrealistic
805 for (std::map< OUString, ConstItem >::iterator j(
806 cmap.begin());
807 j != cmap.end(); ++j)
809 write32(file, j->second.nameOffset);
810 write32(file, j->second.dataOffset);
812 writeAnnotations(file, ann, ent2->getAnnotations());
813 break;
815 case unoidl::Entity::SORT_SINGLE_INTERFACE_BASED_SERVICE:
817 rtl::Reference< unoidl::SingleInterfaceBasedServiceEntity >
818 ent2(
819 static_cast<
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();
825 if (!dfltCtor) {
826 for (std::vector<
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());
838 if (!dfltCtor) {
839 write32(file, ent2->getConstructors().size());
840 for (std::vector<
841 unoidl::SingleInterfaceBasedServiceEntity::
842 Constructor >::const_iterator j(
843 ent2->getConstructors().begin());
844 j != ent2->getConstructors().end(); ++j)
846 if (j->defaultConstructor) {
847 std::cout
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());
854 for (std::vector<
855 unoidl::SingleInterfaceBasedServiceEntity::
856 Constructor::Parameter >::const_iterator k(
857 j->parameters.begin());
858 k != j->parameters.end(); ++k)
860 sal_uInt64 f = 0;
861 if (k->rest) {
862 f |= 0x04;
864 write8(file, f);
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());
879 break;
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();
890 ++j)
892 ann = !j->annotations.empty();
894 for (std::vector< unoidl::AnnotatedReference >::const_iterator
895 j(ent2->getDirectOptionalBaseServices().begin());
896 !ann && j != ent2->getDirectOptionalBaseServices().end();
897 ++j)
899 ann = !j->annotations.empty();
901 for (std::vector< unoidl::AnnotatedReference >::const_iterator
902 j(ent2->getDirectMandatoryBaseInterfaces().begin());
903 (!ann
904 && j != ent2->getDirectMandatoryBaseInterfaces().end());
905 ++j)
907 ann = !j->annotations.empty();
909 for (std::vector< unoidl::AnnotatedReference >::const_iterator
910 j(ent2->getDirectOptionalBaseInterfaces().begin());
911 !ann && j != ent2->getDirectOptionalBaseInterfaces().end();
912 ++j)
914 ann = !j->annotations.empty();
916 for (std::vector<
917 unoidl::AccumulationBasedServiceEntity::Property >::
918 const_iterator j(
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());
959 for (std::vector<
960 unoidl::AccumulationBasedServiceEntity::Property >::
961 const_iterator j(
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());
971 break;
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());
983 break;
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());
995 break;
999 for (std::map< OUString, Item >::iterator i(map.begin()); i != map.end();
1000 ++i)
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
1009 } else {
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();
1014 ++i)
1016 write32(file, i->second.nameOffset);
1017 write32(file, i->second.dataOffset);
1019 return off;
1024 SAL_IMPLEMENT_MAIN() {
1025 try {
1026 sal_uInt32 args = rtl_getAppCommandArgCount();
1027 if (args == 0) {
1028 badUsage();
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) {
1035 assert(args > 1);
1036 OUString uri(getArgumentUri(i, i == args - 2 ? &entities : 0));
1037 if (entities) {
1038 mapEntities(mgr, uri, map);
1039 } else {
1040 try {
1041 prov = mgr->addProvider(uri);
1042 } catch (unoidl::NoSuchFileException &) {
1043 std::cerr
1044 << "Input <" << uri << "> does not exist" << std::endl;
1045 std::exit(EXIT_FAILURE);
1049 if (!entities) {
1050 mapCursor(
1051 (prov.is()
1052 ? prov->createRootCursor()
1053 : rtl::Reference< unoidl::MapCursor >()),
1054 map);
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) {
1062 std::cerr
1063 << "Cannot open <" << f.getURL() << "> for writing, error code "
1064 << +e << std::endl;
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
1070 write(
1072 RTL_CONSTASCII_STRINGPARAM(
1073 "\0** Created by LibreOffice " LIBO_VERSION_DOTTED
1074 " unoidl-write **\0"));
1075 std::size_t size;
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) {
1079 std::cerr
1080 << "Cannot set size of <" << f.getURL() << ">, error code "
1081 << +e << std::endl;
1082 std::exit(EXIT_FAILURE);
1084 e = f.setPos(osl_Pos_Absolut, 8);
1085 if (e != osl::FileBase::E_None) {
1086 std::cerr
1087 << "Cannot rewind current position in <" << f.getURL()
1088 << ">, error code " << +e << std::endl;
1089 std::exit(EXIT_FAILURE);
1091 write32(f, off);
1092 write32(f, size);
1093 // overflow from std::map::size_type -> sal_uInt64 is unrealistic
1094 e = f.close();
1095 if (e != osl::FileBase::E_None) {
1096 std::cerr
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) {
1103 std::cerr
1104 << "Bad input <" << e1.getUri() << ">: " << e1.getDetail()
1105 << std::endl;
1106 std::exit(EXIT_FAILURE);
1110 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */