LibreOffice Module unoidl (master) 1
unoidl-write.cxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 */
9
10#include <sal/config.h>
11
12#include <algorithm>
13#include <cassert>
14#include <cstdlib>
15#include <iostream>
16#include <map>
17#include <utility>
18#include <vector>
19
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/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>
33#include <sal/main.h>
34#include <unoidl/unoidl.hxx>
35
36namespace {
37
38void badUsage() {
39 std::cerr
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,"
44 " a single .idl")
45 << std::endl
46 << ("file, or a root directory of an .idl file tree; and the UTF-8"
47 " encoded <entities")
48 << std::endl
49 << ("file> contains zero or more space-separated names of (non-module)"
50 " entities to")
51 << std::endl
52 << ("include in the output, and, if omitted, defaults to the complete"
53 " content of the")
54 << std::endl << "last <registry>, if any." << std::endl;
55 std::exit(EXIT_FAILURE);
56}
57
58OUString getArgumentUri(sal_uInt32 argument, bool * entities) {
59 OUString arg;
60 rtl_getAppCommandArg(argument, &arg.pData);
61 if (arg.startsWith("@", &arg)) {
62 if (entities == nullptr) {
63 badUsage();
64 }
65 *entities = true;
66 } else if (entities != nullptr) {
67 *entities = false;
68 }
69 OUString url;
70 osl::FileBase::RC e1 = osl::FileBase::getFileURLFromSystemPath(arg, url);
71 if (e1 != osl::FileBase::E_None) {
72 std::cerr
73 << "Cannot convert \"" << arg << "\" to file URL, error code "
74 << +e1 << std::endl;
75 std::exit(EXIT_FAILURE);
76 }
77 OUString cwd;
78 oslProcessError e2 = osl_getProcessWorkingDir(&cwd.pData);
79 if (e2 != osl_Process_E_None) {
80 std::cerr
81 << "Cannot obtain working directory, error code " << +e2
82 << std::endl;
83 std::exit(EXIT_FAILURE);
84 }
85 OUString abs;
86 e1 = osl::FileBase::getAbsoluteFileURL(cwd, url, abs);
87 if (e1 != osl::FileBase::E_None) {
88 std::cerr
89 << "Cannot make \"" << url
90 << "\" into an absolute file URL, error code " << +e1 << std::endl;
91 std::exit(EXIT_FAILURE);
92 }
93 return abs;
94}
95
96sal_uInt64 getOffset(osl::File & file) {
97 sal_uInt64 off;
98 osl::FileBase::RC e = file.getPos(off);
99 if (e != osl::FileBase::E_None) {
100 std::cerr
101 << "Cannot determine current position in <" << file.getURL()
102 << ">, error code " << +e << std::endl;
103 std::exit(EXIT_FAILURE);
104 }
105 return off;
106}
107
108void write(osl::File & file, void const * buffer, sal_uInt64 size) {
109 sal_uInt64 n;
110 osl::FileBase::RC e = file.write(buffer, size, n);
111 if (e != osl::FileBase::E_None) {
112 std::cerr
113 << "Cannot write to <" << file.getURL() << ">, error code " << +e
114 << std::endl;
115 std::exit(EXIT_FAILURE);
116 }
117 if (n != size) {
118 std::cerr
119 << "Bad write of " << n << " instead of " << size << " bytes to <"
120 << file.getURL() << '>' << std::endl;
121 std::exit(EXIT_FAILURE);
122 }
123}
124
125void write8(osl::File & file, sal_uInt64 value) {
126 if (value > 0xFF) {
127 std::cerr
128 << "Cannot write value >= 2^8; input is too large" << std::endl;
129 std::exit(EXIT_FAILURE);
130 }
131 unsigned char buf[1];
132 buf[0] = value & 0xFF;
133 write(file, buf, std::size(buf));
134}
135
136void write16(osl::File & file, sal_uInt64 value) {
137 if (value > 0xFFFF) {
138 std::cerr
139 << "Cannot write value >= 2^16; input is too large" << std::endl;
140 std::exit(EXIT_FAILURE);
141 }
142 unsigned char buf[2];
143 buf[0] = value & 0xFF;
144 buf[1] = (value >> 8) & 0xFF;
145 write(file, buf, std::size(buf));
146}
147
148void write32(osl::File & file, sal_uInt64 value) {
149 if (value > 0xFFFFFFFF) {
150 std::cerr
151 << "Cannot write value >= 2^32; input is too large" << std::endl;
152 std::exit(EXIT_FAILURE);
153 }
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));
160}
161
162void 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));
173}
174
175void writeIso60599Binary32(osl::File & file, float value) {
176 union {
177 unsigned char buf[4];
178 float f; // assuming float is ISO 60599 binary32
179 } sa;
180 sa.f = value;
181#if defined OSL_BIGENDIAN
182 std::swap(sa.buf[0], sa.buf[3]);
183 std::swap(sa.buf[1], sa.buf[2]);
184#endif
185 write(file, sa.buf, std::size(sa.buf));
186}
187
188void writeIso60599Binary64(osl::File & file, double value) {
189 union {
190 unsigned char buf[8];
191 float d; // assuming double is ISO 60599 binary64
192 } sa;
193 sa.d = value;
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]);
199#endif
200 write(file, sa.buf, std::size(sa.buf));
201}
202
203OString toAscii(OUString const & name) {
204 OString ascii;
205 if (!name.convertToString(
206 &ascii, RTL_TEXTENCODING_ASCII_US,
207 (RTL_UNICODETOTEXT_FLAGS_UNDEFINED_ERROR
208 | RTL_UNICODETOTEXT_FLAGS_INVALID_ERROR)))
209 {
210 std::cerr
211 << "Cannot convert \"" << name << "\" to US ASCII" << std::endl;
212 std::exit(EXIT_FAILURE);
213 }
214 return ascii;
215}
216
217OString toUtf8(OUString const & string) {
218 OString ascii;
219 if (!string.convertToString(
220 &ascii, RTL_TEXTENCODING_UTF8,
221 (RTL_UNICODETOTEXT_FLAGS_UNDEFINED_ERROR
222 | RTL_UNICODETOTEXT_FLAGS_INVALID_ERROR)))
223 {
224 std::cerr
225 << "Cannot convert \"" << string << "\" to UTF-8" << std::endl;
226 std::exit(EXIT_FAILURE);
227 }
228 return ascii;
229}
230
231sal_uInt64 writeNulName(osl::File & file, OUString const & name) {
232 OString ascii(toAscii(name));
233 if (ascii.indexOf('\0') != -1) {
234 std::cerr
235 << "Name \"" << ascii << "\" contains NUL characters" << std::endl;
236 std::exit(EXIT_FAILURE);
237 }
238 sal_uInt64 off = getOffset(file);
239 write(file, ascii.getStr(), ascii.getLength() + 1);
240 return off;
241}
242
243void 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)));
248 assert(
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());
252 } else {
253 if ((i->second & 0x80000000) != 0) {
254 std::cerr
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);
258 }
259 write32(file, i->second | 0x80000000);
260 }
261}
262
263void writeIdxName(osl::File & file, OUString const & name) {
264 writeIdxString(file, toAscii(name));
265}
266
267void writeAnnotations(
268 osl::File & file, bool annotate,
269 std::vector< OUString > const & annotations)
270{
271 assert(annotate || annotations.empty());
272 if (annotate) {
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));
277 }
278 }
279}
280
281void writeKind(
282 osl::File & file,
284 bool annotated, bool flag = false)
285{
286 assert(entity.is());
287 sal_uInt64 v = entity->getSort();
288 if (entity->isPublished()) {
289 v |= 0x80;
290 }
291 if (annotated) {
292 v |= 0x40;
293 }
294 if (flag) {
295 v |= 0x20;
296 }
297 write8(file, v);
298}
299
300struct Item {
301 explicit Item(rtl::Reference< unoidl::Entity > theEntity):
302 entity(std::move(theEntity)), nameOffset(0), dataOffset(0)
303 {}
304
306 std::map< OUString, Item > module;
307 sal_uInt64 nameOffset;
308 sal_uInt64 dataOffset;
309};
310
311struct ConstItem {
312 ConstItem(
313 unoidl::ConstantValue const & theConstant,
314 std::vector< OUString >&& theAnnotations):
315 constant(theConstant), annotations(std::move(theAnnotations)), nameOffset(0),
316 dataOffset(0)
317 {}
318
319 unoidl::ConstantValue constant;
320 std::vector< OUString > annotations;
321 sal_uInt64 nameOffset;
322 sal_uInt64 dataOffset;
323};
324
325void mapEntities(
326 rtl::Reference< unoidl::Manager > const & manager, OUString const & uri,
327 std::map< OUString, Item > & map)
328{
329 assert(manager.is());
330 osl::File f(uri);
331 osl::FileBase::RC e = f.open(osl_File_OpenFlag_Read);
332 if (e != osl::FileBase::E_None) {
333 std::cerr
334 << "Cannot open <" << f.getURL() << "> for reading, error code "
335 << +e << std::endl;
336 std::exit(EXIT_FAILURE);
337 }
338 for (;;) {
339 sal_Bool eof;
340 e = f.isEndOfFile(&eof);
341 if (e != osl::FileBase::E_None) {
342 std::cerr
343 << "Cannot check <" << f.getURL() << "> for EOF, error code "
344 << +e << std::endl;
345 std::exit(EXIT_FAILURE);
346 }
347 if (eof) {
348 break;
349 }
350 rtl::ByteSequence s1;
351 e = f.readLine(s1);
352 if (e != osl::FileBase::E_None) {
353 std::cerr
354 << "Cannot read from <" << f.getURL() << ">, error code "
355 << +e << std::endl;
356 std::exit(EXIT_FAILURE);
357 }
358 OUString s2;
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)))
365 {
366 std::cerr
367 << "Cannot interpret line read from <" << f.getURL()
368 << "> as UTF-8" << std::endl;
369 std::exit(EXIT_FAILURE);
370 }
371 for (sal_Int32 i = 0; i != -1;) {
372 OUString t(s2.getToken(0, ' ', i));
373 if (!t.isEmpty()) {
374 rtl::Reference< unoidl::Entity > ent(manager->findEntity(t));
375 if (!ent.is()) {
376 std::cerr
377 << "Unknown entity \"" << t << "\" read from <"
378 << f.getURL() << ">" << std::endl;
379 std::exit(EXIT_FAILURE);
380 }
381 if (ent->getSort() == unoidl::Entity::SORT_MODULE) {
382 std::cerr
383 << "Module entity \"" << t << "\" read from <"
384 << f.getURL() << ">" << std::endl;
385 std::exit(EXIT_FAILURE);
386 }
387 std::map< OUString, Item > * map2 = &map;
388 for (sal_Int32 j = 0;;) {
389 OUString id(t.getToken(0, '.', j));
390 if (j == -1) {
391 map2->insert(std::make_pair(id, Item(ent)));
392 break;
393 }
394 std::map< OUString, Item >::iterator k(map2->find(id));
395 if (k == map2->end()) {
397 manager->findEntity(t.copy(0, j - 1)));
398 assert(ent2.is());
399 k = map2->insert(std::make_pair(id, Item(ent2))).first;
400 }
401 assert(
402 k->second.entity->getSort()
404 map2 = &k->second.module;
405 }
406 }
407 }
408 }
409 e = f.close();
410 if (e != osl::FileBase::E_None) {
411 std::cerr
412 << "Cannot close <" << f.getURL() << "> after reading, error code "
413 << +e << std::endl;
414 std::exit(EXIT_FAILURE);
415 }
416}
417
418void mapCursor(
420 std::map< OUString, Item > & map)
421{
422 if (!cursor.is())
423 return;
424
425 for (;;) {
426 OUString name;
427 rtl::Reference< unoidl::Entity > ent(cursor->getNext(&name));
428 if (!ent.is()) {
429 break;
430 }
431 std::pair< std::map< OUString, Item >::iterator, bool > i(
432 map.insert(std::make_pair(name, Item(ent))));
433 if (!i.second) {
434 std::cout << "Duplicate name \"" << name << '"' << std::endl;
435 std::exit(EXIT_FAILURE);
436 }
437 if (i.first->second.entity->getSort()
439 {
440 mapCursor(
442 static_cast< unoidl::ModuleEntity * >(
443 i.first->second.entity.get()))->createCursor(),
444 i.first->second.module);
445 }
446 }
447}
448
449template<typename T>
450bool hasNotEmptyAnnotations(const std::vector<T>& v)
451{
452 return std::any_of(v.begin(), v.end(), [](const T& rItem) { return !rItem.annotations.empty(); });
453}
454
455sal_uInt64 writeMap(
456 osl::File & file, std::map< OUString, Item > & map, std::size_t * rootSize)
457{
458 for (auto & i: map) {
459 switch (i.second.entity->getSort()) {
461 i.second.dataOffset = writeMap(file, i.second.module, nullptr);
462 break;
464 {
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);
477 }
478 writeAnnotations(file, ann, ent2->getAnnotations());
479 break;
480 }
482 {
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);
489 writeKind(
490 file, ent2, ann, !ent2->getDirectBase().isEmpty());
491 if (!ent2->getDirectBase().isEmpty()) {
492 writeIdxName(file, ent2->getDirectBase());
493 }
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);
499 }
500 writeAnnotations(file, ann, ent2->getAnnotations());
501 break;
502 }
504 {
506 ent2(
507 static_cast<
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);
517 }
518 write32(file, ent2->getMembers().size());
519 for (auto & j: ent2->getMembers()) {
520 sal_uInt64 f = 0;
521 if (j.parameterized) {
522 f |= 0x01;
523 }
524 write8(file, f);
525 writeIdxName(file, j.name);
526 writeIdxName(file, j.type);
527 writeAnnotations(file, ann, j.annotations);
528 }
529 writeAnnotations(file, ann, ent2->getAnnotations());
530 break;
531 }
533 {
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);
540 writeKind(
541 file, ent2, ann, !ent2->getDirectBase().isEmpty());
542 if (!ent2->getDirectBase().isEmpty()) {
543 writeIdxName(file, ent2->getDirectBase());
544 }
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);
550 }
551 writeAnnotations(file, ann, ent2->getAnnotations());
552 break;
553 }
555 {
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);
570 }
571 write32(file, ent2->getDirectOptionalBases().size());
572 for (auto & j: ent2->getDirectOptionalBases()) {
573 writeIdxName(file, j.name);
574 writeAnnotations(file, ann, j.annotations);
575 }
576 write32(file, ent2->getDirectAttributes().size());
577 for (auto & j: ent2->getDirectAttributes()) {
578 sal_uInt64 f = 0;
579 if (j.bound) {
580 f |= 0x01;
581 }
582 if (j.readOnly) {
583 f |= 0x02;
584 }
585 write8(file, f);
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);
591 }
592 if (!j.readOnly) {
593 write32(file, j.setExceptions.size());
594 for (auto & k: j.setExceptions) {
595 writeIdxName(file, k);
596 }
597 }
598 writeAnnotations(file, ann, j.annotations);
599 }
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);
609 }
610 write32(file, j.exceptions.size());
611 for (auto & k: j.exceptions) {
612 writeIdxName(file, k);
613 }
614 writeAnnotations(file, ann, j.annotations);
615 }
616 writeAnnotations(file, ann, ent2->getAnnotations());
617 break;
618 }
620 {
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());
629 break;
630 }
632 {
634 static_cast< unoidl::ConstantGroupEntity * >(
635 i.second.entity.get()));
636 std::map< OUString, ConstItem > cmap;
637 for (auto & j: ent2->getMembers()) {
638 if (!cmap.insert(
639 std::make_pair(
640 j.name, ConstItem(j.value, std::vector(j.annotations)))).
641 second)
642 {
643 std::cout
644 << "Duplicate constant group member name \""
645 << j.name << '"' << std::endl;
646 std::exit(EXIT_FAILURE);
647 }
648 }
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()) {
653 v |= 0x80;
654 }
655 write8(file, v);
656 switch (j.second.constant.type) {
658 write8(file, j.second.constant.booleanValue ? 1 : 0);
659 break;
661 write8(
662 file,
663 static_cast< sal_uInt8 >(
664 j.second.constant.byteValue));
665 break;
667 write16(
668 file,
669 static_cast< sal_uInt16 >(
670 j.second.constant.shortValue));
671 break;
673 write16(file, j.second.constant.unsignedShortValue);
674 break;
676 write32(
677 file,
678 static_cast< sal_uInt32 >(
679 j.second.constant.longValue));
680 break;
682 write32(file, j.second.constant.unsignedLongValue);
683 break;
685 write64(
686 file,
687 static_cast< sal_uInt64 >(
688 j.second.constant.hyperValue));
689 break;
691 write64(file, j.second.constant.unsignedHyperValue);
692 break;
694 writeIso60599Binary32(
695 file, j.second.constant.floatValue);
696 break;
698 writeIso60599Binary64(
699 file, j.second.constant.doubleValue);
700 break;
701 default:
702 for (;;) { std::abort(); } // this cannot happen
703 }
704 writeAnnotations(
705 file, !j.second.annotations.empty(),
706 j.second.annotations);
707 }
708 for (auto & j: cmap) {
709 j.second.nameOffset = writeNulName(file, j.first);
710 }
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
716 // unrealistic
717 for (const auto & j: cmap) {
718 write32(file, j.second.nameOffset);
719 write32(file, j.second.dataOffset);
720 }
721 writeAnnotations(file, ann, ent2->getAnnotations());
722 break;
723 }
725 {
727 ent2(
728 static_cast<
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());
739 if (!dfltCtor) {
740 write32(file, ent2->getConstructors().size());
741 for (auto & j: ent2->getConstructors()) {
742 if (j.defaultConstructor) {
743 std::cout
744 << "Unexpected default constructor \""
745 << j.name << '"' << std::endl;
746 std::exit(EXIT_FAILURE);
747 }
748 writeIdxName(file, j.name);
749 write32(file, j.parameters.size());
750 for (auto & k: j.parameters) {
751 sal_uInt64 f = 0;
752 if (k.rest) {
753 f |= 0x04;
754 }
755 write8(file, f);
756 writeIdxName(file, k.name);
757 writeIdxName(file, k.type);
758 }
759 write32(file, j.exceptions.size());
760 for (auto & k: j.exceptions) {
761 writeIdxName(file, k);
762 }
763 writeAnnotations(file, ann, j.annotations);
764 }
765 }
766 writeAnnotations(file, ann, ent2->getAnnotations());
767 break;
768 }
770 {
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);
786 }
787 write32(file, ent2->getDirectOptionalBaseServices().size());
788 for (auto & j: ent2->getDirectOptionalBaseServices()) {
789 writeIdxName(file, j.name);
790 writeAnnotations(file, ann, j.annotations);
791 }
792 write32(file, ent2->getDirectMandatoryBaseInterfaces().size());
793 for (auto & j: ent2->getDirectMandatoryBaseInterfaces()) {
794 writeIdxName(file, j.name);
795 writeAnnotations(file, ann, j.annotations);
796 }
797 write32(file, ent2->getDirectOptionalBaseInterfaces().size());
798 for (auto & j: ent2->getDirectOptionalBaseInterfaces()) {
799 writeIdxName(file, j.name);
800 writeAnnotations(file, ann, j.annotations);
801 }
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);
808 }
809 writeAnnotations(file, ann, ent2->getAnnotations());
810 break;
811 }
813 {
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());
822 break;
823 }
825 {
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());
834 break;
835 }
836 }
837 }
838 for (auto & i: map) {
839 i.second.nameOffset = writeNulName(file, i.first);
840 }
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
846 } else {
847 *rootSize = map.size();
848 // overflow from std::map::size_type -> std::size_t is unrealistic
849 }
850 for (const auto & i: map) {
851 write32(file, i.second.nameOffset);
852 write32(file, i.second.dataOffset);
853 }
854 return off;
855}
856
857}
858
860 try {
861 sal_uInt32 args = rtl_getAppCommandArgCount();
862 if (args == 0) {
863 badUsage();
864 }
866 bool entities = false;
868 std::map< OUString, Item > map;
869 for (sal_uInt32 i = 0; i != args - 1; ++i) {
870 assert(args > 1);
871 OUString uri(getArgumentUri(i, i == args - 2 ? &entities : nullptr));
872 if (entities) {
873 mapEntities(mgr, uri, map);
874 } else {
875 try {
876 prov = mgr->addProvider(uri);
877 } catch (unoidl::NoSuchFileException &) {
878 std::cerr
879 << "Input <" << uri << "> does not exist" << std::endl;
880 std::exit(EXIT_FAILURE);
881 }
882 }
883 }
884 if (!entities) {
885 mapCursor(
886 (prov.is()
887 ? prov->createRootCursor()
889 map);
890 }
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);
895 }
896 if (e != osl::FileBase::E_None) {
897 std::cerr
898 << "Cannot open <" << f.getURL() << "> for writing, error code "
899 << +e << std::endl;
900 std::exit(EXIT_FAILURE);
901 }
902 write(f, "UNOIDL\xFF\0", 8);
903 write32(f, 0); // root map offset
904 write32(f, 0); // root map size
905 write(
906 f,
907 RTL_CONSTASCII_STRINGPARAM(
908 "\0** Created by LibreOffice " LIBO_VERSION_DOTTED
909 " unoidl-write **\0"));
910 std::size_t size;
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) {
914 std::cerr
915 << "Cannot set size of <" << f.getURL() << ">, error code "
916 << +e << std::endl;
917 std::exit(EXIT_FAILURE);
918 }
919 e = f.setPos(osl_Pos_Absolut, 8);
920 if (e != osl::FileBase::E_None) {
921 std::cerr
922 << "Cannot rewind current position in <" << f.getURL()
923 << ">, error code " << +e << std::endl;
924 std::exit(EXIT_FAILURE);
925 }
926 write32(f, off);
927 write32(f, size);
928 // overflow from std::map::size_type -> sal_uInt64 is unrealistic
929 e = f.close();
930 if (e != osl::FileBase::E_None) {
931 std::cerr
932 << "Cannot close <" << f.getURL()
933 << "> after writing, error code " << +e << std::endl;
934 std::exit(EXIT_FAILURE);
935 }
936 return EXIT_SUCCESS;
937 } catch (unoidl::FileFormatException & e1) {
938 std::cerr
939 << "Bad input <" << e1.getUri() << ">: " << e1.getDetail()
940 << std::endl;
941 std::exit(EXIT_FAILURE);
942 } catch (std::exception & e1) {
943 std::cerr
944 << "Failure: " << e1.what()
945 << std::endl;
946 std::exit(EXIT_FAILURE);
947 }
948
949}
950
951/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
XPropertyListType t
double d
@ SORT_PLAIN_STRUCT_TYPE
Definition: unoidl.hxx:84
@ SORT_ACCUMULATION_BASED_SERVICE
Definition: unoidl.hxx:87
@ SORT_SINGLE_INTERFACE_BASED_SERVICE
Definition: unoidl.hxx:87
@ SORT_POLYMORPHIC_STRUCT_TYPE_TEMPLATE
Definition: unoidl.hxx:85
@ SORT_INTERFACE_TYPE
Definition: unoidl.hxx:86
@ SORT_CONSTANT_GROUP
Definition: unoidl.hxx:86
@ SORT_EXCEPTION_TYPE
Definition: unoidl.hxx:85
@ SORT_INTERFACE_BASED_SINGLETON
Definition: unoidl.hxx:88
@ SORT_SERVICE_BASED_SINGLETON
Definition: unoidl.hxx:88
const OUString & getDetail() const
Definition: unoidl.hxx:60
const OUString & getUri() const
Definition: unoidl.hxx:58
Any value
rtl::Reference< ParseManager > manager
float v
const char * name
sal_Int64 n
double getLength(const B2DPolygon &rCandidate)
size
int i
module
args
SwNodeOffset abs(const SwNodeOffset &a)
std::map< OUString, rtl::Reference< Entity > > map
unsigned char sal_uInt8
unsigned char sal_Bool
SAL_IMPLEMENT_MAIN()