LibreOffice Module unoidl (master) 1
unoidlprovider.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 <cstring>
15#include <set>
16#include <string_view>
17#include <utility>
18#include <vector>
19
20#include <o3tl/string_view.hxx>
21#include <osl/endian.h>
22#include <osl/file.h>
23#include <rtl/character.hxx>
24#include <rtl/ref.hxx>
25#include <rtl/textenc.h>
26#include <rtl/textcvt.h>
27#include <rtl/ustring.hxx>
28#include <sal/log.hxx>
29#include <sal/types.h>
31#include <unoidl/unoidl.hxx>
32
33#include "unoidlprovider.hxx"
34
35namespace unoidl::detail {
36
38public:
39 explicit MappedFile(OUString fileUrl);
40
41 sal_uInt8 read8(sal_uInt32 offset) const;
42
43 sal_uInt16 read16(sal_uInt32 offset) const;
44
45 sal_uInt32 read32(sal_uInt32 offset) const;
46
47 sal_uInt64 read64(sal_uInt32 offset) const;
48
49 float readIso60599Binary32(sal_uInt32 offset) const;
50
51 double readIso60599Binary64(sal_uInt32 offset) const;
52
53 OUString readNulName(sal_uInt32 offset) /*const*/;
54
55 OUString readIdxName(sal_uInt32 * offset) const
56 { return readIdxString(offset, RTL_TEXTENCODING_ASCII_US); }
57
58 OUString readIdxString(sal_uInt32 * offset) const
59 { return readIdxString(offset, RTL_TEXTENCODING_UTF8); }
60
61 OUString uri;
62 oslFileHandle handle;
63 sal_uInt64 size;
64 void * address;
65
66private:
67 virtual ~MappedFile() override;
68
69 sal_uInt8 get8(sal_uInt32 offset) const;
70
71 sal_uInt16 get16(sal_uInt32 offset) const;
72
73 sal_uInt32 get32(sal_uInt32 offset) const;
74
75 sal_uInt64 get64(sal_uInt32 offset) const;
76
77 float getIso60599Binary32(sal_uInt32 offset) const;
78
79 double getIso60599Binary64(sal_uInt32 offset) const;
80
81 OUString readIdxString(sal_uInt32 * offset, rtl_TextEncoding encoding)
82 const;
83};
84
85namespace {
86
87// sizeof (Memory16) == 2
88struct Memory16 {
89 unsigned char byte[2];
90
91 sal_uInt16 getUnsigned16() const {
92 return static_cast< sal_uInt16 >(byte[0])
93 | (static_cast< sal_uInt16 >(byte[1]) << 8);
94 }
95};
96
97// sizeof (Memory32) == 4
98struct Memory32 {
99 unsigned char byte[4];
100
101 sal_uInt32 getUnsigned32() const {
102 return static_cast< sal_uInt32 >(byte[0])
103 | (static_cast< sal_uInt32 >(byte[1]) << 8)
104 | (static_cast< sal_uInt32 >(byte[2]) << 16)
105 | (static_cast< sal_uInt32 >(byte[3]) << 24);
106 }
107
108 float getIso60599Binary32() const {
109 union {
110 unsigned char buf[4];
111 float f; // assuming float is ISO 60599 binary32
112 } sa;
113#if defined OSL_LITENDIAN
114 sa.buf[0] = byte[0];
115 sa.buf[1] = byte[1];
116 sa.buf[2] = byte[2];
117 sa.buf[3] = byte[3];
118#else
119 sa.buf[0] = byte[3];
120 sa.buf[1] = byte[2];
121 sa.buf[2] = byte[1];
122 sa.buf[3] = byte[0];
123#endif
124 return sa.f;
125 }
126};
127
128// sizeof (Memory64) == 8
129struct Memory64 {
130 unsigned char byte[8];
131
132 sal_uInt64 getUnsigned64() const {
133 return static_cast< sal_uInt64 >(byte[0])
134 | (static_cast< sal_uInt64 >(byte[1]) << 8)
135 | (static_cast< sal_uInt64 >(byte[2]) << 16)
136 | (static_cast< sal_uInt64 >(byte[3]) << 24)
137 | (static_cast< sal_uInt64 >(byte[4]) << 32)
138 | (static_cast< sal_uInt64 >(byte[5]) << 40)
139 | (static_cast< sal_uInt64 >(byte[6]) << 48)
140 | (static_cast< sal_uInt64 >(byte[7]) << 56);
141 }
142
143 double getIso60599Binary64() const {
144 union {
145 unsigned char buf[8];
146 double d; // assuming double is ISO 60599 binary64
147 } sa;
148#if defined OSL_LITENDIAN
149 sa.buf[0] = byte[0];
150 sa.buf[1] = byte[1];
151 sa.buf[2] = byte[2];
152 sa.buf[3] = byte[3];
153 sa.buf[4] = byte[4];
154 sa.buf[5] = byte[5];
155 sa.buf[6] = byte[6];
156 sa.buf[7] = byte[7];
157#else
158 sa.buf[0] = byte[7];
159 sa.buf[1] = byte[6];
160 sa.buf[2] = byte[5];
161 sa.buf[3] = byte[4];
162 sa.buf[4] = byte[3];
163 sa.buf[5] = byte[2];
164 sa.buf[6] = byte[1];
165 sa.buf[7] = byte[0];
166#endif
167 return sa.d;
168 }
169};
170
171bool isSimpleType(std::u16string_view type) {
172 return type == u"void" || type == u"boolean" || type == u"byte"
173 || type == u"short" || type == u"unsigned short" || type == u"long"
174 || type == u"unsigned long" || type == u"hyper"
175 || type == u"unsigned hyper" || type == u"float" || type == u"double"
176 || type == u"char" || type == u"string" || type == u"type"
177 || type == u"any";
178}
179
180// For backwards compatibility, does not strictly check segments to match
181//
182// <segment> ::= <blocks> | <block>
183// <blocks> ::= <capital> <other>* ("_" <block>)*
184// <block> ::= <other>+
185// <other> ::= <capital> | "a"--"z" | "0"--"9"
186// <capital> ::= "A"--"Z"
187//
188bool isIdentifier(std::u16string_view type, bool scoped) {
189 if (type.empty()) {
190 return false;
191 }
192 for (size_t i = 0; i != type.size(); ++i) {
193 sal_Unicode c = type[i];
194 if (c == '.') {
195 if (!scoped || i == 0 || i == type.size() - 1
196 || type[i - 1] == '.')
197 {
198 return false;
199 }
200 } else if (!rtl::isAsciiAlphanumeric(c) && c != '_') {
201 return false;
202 }
203 }
204 return true;
205}
206
207void checkTypeName(
208 rtl::Reference< MappedFile > const & file, std::u16string_view type)
209{
210 std::u16string_view nucl(type);
211 bool args = false;
212 while (o3tl::starts_with(nucl, u"[]", &nucl)) {}
213 size_t i = nucl.find('<');
214 if (i != std::u16string_view::npos) {
215 std::u16string_view tmpl(nucl.substr(0, i));
216 do {
217 ++i; // skip '<' or ','
218 size_t j = i;
219 for (size_t level = 0; j != nucl.size(); ++j) {
220 sal_Unicode c = nucl[j];
221 if (c == ',') {
222 if (level == 0) {
223 break;
224 }
225 } else if (c == '<') {
226 ++level;
227 } else if (c == '>') {
228 if (level == 0) {
229 break;
230 }
231 --level;
232 }
233 }
234 if (j != nucl.size()) {
235 checkTypeName(file, nucl.substr(i, j - i));
236 args = true;
237 }
238 i = j;
239 } while (i != nucl.size() && nucl[i] != '>');
240 if (i != nucl.size() - 1 || nucl[i] != '>' || !args) {
241 tmpl = {}; // bad input
242 }
243 nucl = tmpl;
244 }
245 if (isSimpleType(nucl) ? args : !isIdentifier(nucl, true)) {
246 throw FileFormatException(
247 file->uri, OUString::Concat("UNOIDL format: bad type \"") + type + "\"");
248 }
249}
250
251void checkEntityName(
252 rtl::Reference< MappedFile > const & file, std::u16string_view name)
253{
254 if (isSimpleType(name) || !isIdentifier(name, false)) {
255 throw FileFormatException(
256 file->uri, OUString::Concat("UNOIDL format: bad entity name \"") + name + "\"");
257 }
258}
259
260}
261
262MappedFile::MappedFile(OUString fileUrl): uri(std::move(fileUrl)), handle(nullptr) {
263 oslFileError e = osl_openFile(uri.pData, &handle, osl_File_OpenFlag_Read);
264 switch (e) {
265 case osl_File_E_None:
266 break;
267 case osl_File_E_NOENT:
269 default:
270 throw FileFormatException(uri, "cannot open: " + OUString::number(e));
271 }
272 e = osl_getFileSize(handle, &size);
273 if (e == osl_File_E_None) {
274 e = osl_mapFile(
275 handle, &address, size, 0, osl_File_MapFlag_RandomAccess);
276 }
277 if (e != osl_File_E_None) {
278 oslFileError e2 = osl_closeFile(handle);
280 e2 != osl_File_E_None, "unoidl",
281 "cannot close " << uri << ": " << +e2);
282 throw FileFormatException(uri, "cannot mmap: " + OUString::number(e));
283 }
284}
285
286sal_uInt8 MappedFile::read8(sal_uInt32 offset) const {
287 assert(size >= 8);
288 if (offset > size - 1) {
290 uri, "UNOIDL format: offset for 8-bit value too large");
291 }
292 return get8(offset);
293}
294
295sal_uInt16 MappedFile::read16(sal_uInt32 offset) const {
296 assert(size >= 8);
297 if (offset > size - 2) {
299 uri, "UNOIDL format: offset for 16-bit value too large");
300 }
301 return get16(offset);
302}
303
304sal_uInt32 MappedFile::read32(sal_uInt32 offset) const {
305 assert(size >= 8);
306 if (offset > size - 4) {
308 uri, "UNOIDL format: offset for 32-bit value too large");
309 }
310 return get32(offset);
311}
312
313sal_uInt64 MappedFile::read64(sal_uInt32 offset) const {
314 assert(size >= 8);
315 if (offset > size - 8) {
317 uri, "UNOIDL format: offset for 64-bit value too large");
318 }
319 return get64(offset);
320}
321
322float MappedFile::readIso60599Binary32(sal_uInt32 offset) const {
323 assert(size >= 8);
324 if (offset > size - 4) {
326 uri, "UNOIDL format: offset for 32-bit value too large");
327 }
328 return getIso60599Binary32(offset);
329}
330
331double MappedFile::readIso60599Binary64(sal_uInt32 offset) const {
332 assert(size >= 8);
333 if (offset > size - 8) {
335 uri, "UNOIDL format: offset for 64-bit value too large");
336 }
337 return getIso60599Binary64(offset);
338}
339
340OUString MappedFile::readNulName(sal_uInt32 offset) {
341 if (offset > size) {
343 uri, "UNOIDL format: offset for string too large");
344 }
345 sal_uInt64 end = offset;
346 for (;; ++end) {
347 if (end == size) {
349 uri, "UNOIDL format: string misses trailing NUL");
350 }
351 if (static_cast< char const * >(address)[end] == 0) {
352 break;
353 }
354 }
355 if (end - offset > SAL_MAX_INT32) {
356 throw FileFormatException(uri, "UNOIDL format: string too long");
357 }
358 OUString name;
359 if (!rtl_convertStringToUString(
360 &name.pData, static_cast< char const * >(address) + offset,
361 end - offset, RTL_TEXTENCODING_ASCII_US,
362 (RTL_TEXTTOUNICODE_FLAGS_UNDEFINED_ERROR
363 | RTL_TEXTTOUNICODE_FLAGS_MBUNDEFINED_ERROR
364 | RTL_TEXTTOUNICODE_FLAGS_INVALID_ERROR)))
365 {
366 throw FileFormatException(uri, "UNOIDL format: name is not ASCII");
367 }
368 checkEntityName(this, name);
369 return name;
370}
371
373 oslFileError e = osl_unmapMappedFile(handle, address, size);
374 SAL_WARN_IF(e != osl_File_E_None, "unoidl", "cannot unmap: " << +e);
375 e = osl_closeFile(handle);
376 SAL_WARN_IF(e != osl_File_E_None, "unoidl", "cannot close: " << +e);
377}
378
379sal_uInt8 MappedFile::get8(sal_uInt32 offset) const {
380 assert(size >= 8);
381 assert(offset <= size - 1);
382 return static_cast< char const * >(address)[offset];
383}
384
385sal_uInt16 MappedFile::get16(sal_uInt32 offset) const {
386 assert(size >= 8);
387 assert(offset <= size - 2);
388 return reinterpret_cast< Memory16 const * >(
389 static_cast< char const * >(address) + offset)->getUnsigned16();
390}
391
392sal_uInt32 MappedFile::get32(sal_uInt32 offset) const {
393 assert(size >= 8);
394 assert(offset <= size - 4);
395 return reinterpret_cast< Memory32 const * >(
396 static_cast< char const * >(address) + offset)->getUnsigned32();
397}
398
399sal_uInt64 MappedFile::get64(sal_uInt32 offset) const {
400 assert(size >= 8);
401 assert(offset <= size - 8);
402 return reinterpret_cast< Memory64 const * >(
403 static_cast< char const * >(address) + offset)->getUnsigned64();
404}
405
406float MappedFile::getIso60599Binary32(sal_uInt32 offset) const {
407 assert(size >= 8);
408 assert(offset <= size - 4);
409 return reinterpret_cast< Memory32 const * >(
410 static_cast< char const * >(address) + offset)->getIso60599Binary32();
411}
412
413double MappedFile::getIso60599Binary64(sal_uInt32 offset) const {
414 assert(size >= 8);
415 assert(offset <= size - 8);
416 return reinterpret_cast< Memory64 const * >(
417 static_cast< char const * >(address) + offset)->getIso60599Binary64();
418}
419
421 sal_uInt32 * offset, rtl_TextEncoding encoding) const
422{
423 assert(offset != nullptr);
424 sal_uInt32 len = read32(*offset);
425 sal_uInt32 off;
426 if ((len & 0x80000000) == 0) {
427 off = *offset;
428 *offset += 4 + len;
429 } else {
430 *offset += 4;
431 off = len & ~0x80000000;
432 len = read32(off);
433 if ((len & 0x80000000) != 0) {
435 uri, "UNOIDL format: string length high bit set");
436 }
437 }
438 if (len > SAL_MAX_INT32 || len > size - off - 4) {
440 uri, "UNOIDL format: size of string is too large");
441 }
442 OUString name;
443 if (!rtl_convertStringToUString(
444 &name.pData, static_cast< char const * >(address) + off + 4, len,
445 encoding,
446 (RTL_TEXTTOUNICODE_FLAGS_UNDEFINED_ERROR
447 | RTL_TEXTTOUNICODE_FLAGS_MBUNDEFINED_ERROR
448 | RTL_TEXTTOUNICODE_FLAGS_INVALID_ERROR)))
449 {
451 uri, "UNOIDL format: string bytes do not match encoding");
452 }
453 return name;
454}
455
456// sizeof (MapEntry) == 8
457struct MapEntry {
458 Memory32 name;
459 Memory32 data;
460};
461
462static bool operator <(const Map& map1, const Map& map2) {
463 return map1.begin < map2.begin
464 || (map1.begin == map2.begin && map1.size < map2.size);
465}
466
467namespace {
468
469enum Compare { COMPARE_LESS, COMPARE_GREATER, COMPARE_EQUAL };
470
471Compare compare(
472 rtl::Reference< MappedFile > const & file, std::u16string_view name,
473 sal_Int32 nameOffset, sal_Int32 nameLength, MapEntry const * entry)
474{
475 assert(file.is());
476 assert(entry != nullptr);
477 sal_uInt32 off = entry->name.getUnsigned32();
478 if (off > file->size - 1) { // at least a trailing NUL
479 throw FileFormatException(
480 file->uri, "UNOIDL format: string offset too large");
481 }
482 assert(nameLength >= 0);
483 sal_uInt64 min = std::min(
484 static_cast< sal_uInt64 >(nameLength), file->size - off);
485 for (sal_uInt64 i = 0; i != min; ++i) {
486 sal_Unicode c1 = name[nameOffset + i];
487 sal_Unicode c2 = static_cast< unsigned char const * >(file->address)[
488 off + i];
489 if (c1 < c2) {
490 return COMPARE_LESS;
491 } else if (c1 > c2 || c2 == 0) {
492 // ...the "|| c2 == 0" is for the odd case where name erroneously
493 // contains NUL characters
494 return COMPARE_GREATER;
495 }
496 }
497 if (static_cast< sal_uInt64 >(nameLength) == min) {
498 if (file->size - off == min) {
499 throw FileFormatException(
500 file->uri, "UNOIDL format: string misses trailing NUL");
501 }
502 return
503 static_cast< unsigned char const * >(file->address)[off + min] == 0
504 ? COMPARE_EQUAL : COMPARE_LESS;
505 } else {
506 return COMPARE_GREATER;
507 }
508}
509
510sal_uInt32 findInMap(
511 rtl::Reference< MappedFile > const & file, MapEntry const * mapBegin,
512 sal_uInt32 mapSize, OUString const & name, sal_Int32 nameOffset,
513 sal_Int32 nameLength)
514{
515 if (mapSize == 0) {
516 return 0;
517 }
518 sal_uInt32 n = mapSize / 2;
519 MapEntry const * p = mapBegin + n;
520 switch (compare(file, name, nameOffset, nameLength, p)) {
521 case COMPARE_LESS:
522 return findInMap(file, mapBegin, n, name, nameOffset, nameLength);
523 case COMPARE_GREATER:
524 return findInMap(
525 file, p + 1, mapSize - n - 1, name, nameOffset, nameLength);
526 default: // COMPARE_EQUAL
527 break;
528 }
529 sal_uInt32 off = mapBegin[n].data.getUnsigned32();
530 if (off == 0) {
531 throw FileFormatException(
532 file->uri, "UNOIDL format: map entry data offset is null");
533 }
534 return off;
535}
536
537#if defined(__COVERITY__)
538extern "C" void __coverity_tainted_data_sanitize__(void *);
539#endif
540
541std::vector< OUString > readAnnotations(
542 bool annotated, rtl::Reference< MappedFile > const & file,
543 sal_uInt32 offset, sal_uInt32 * newOffset = nullptr)
544{
545 std::vector< OUString > ans;
546 if (annotated) {
547 sal_uInt32 n = file->read32(offset);
548#if defined(__COVERITY__)
549 __coverity_tainted_data_sanitize__(&n);
550#endif
551 offset += 4;
552 for (sal_uInt32 i = 0; i != n; ++i) {
553 ans.push_back(file->readIdxString(&offset));
554 }
555 }
556 if (newOffset != nullptr) {
557 *newOffset = offset;
558 }
559 return ans;
560}
561
562ConstantValue readConstant(
563 rtl::Reference< MappedFile > const & file, sal_uInt32 offset,
564 sal_uInt32 * newOffset, bool * annotated)
565{
566 assert(file.is());
567 int v = file->read8(offset);
568 int type = v & 0x7F;
569 if (annotated != nullptr) {
570 *annotated = (v & 0x80) != 0;
571 }
572 switch (type) {
573 case 0: // BOOLEAN
574 v = file->read8(offset + 1);
575 if (newOffset != nullptr) {
576 *newOffset = offset + 2;
577 }
578 switch (v) {
579 case 0:
580 return ConstantValue(false);
581 case 1:
582 return ConstantValue(true);
583 default:
584 throw FileFormatException(
585 file->uri,
586 ("UNOIDL format: bad boolean constant value "
587 + OUString::number(v)));
588 }
589 case 1: // BYTE
590 if (newOffset != nullptr) {
591 *newOffset = offset + 2;
592 }
593 return ConstantValue(static_cast< sal_Int8 >(file->read8(offset + 1)));
594 //TODO: implementation-defined behavior of conversion from sal_uInt8
595 // to sal_Int8 relies on two's complement representation
596 case 2: // SHORT
597 if (newOffset != nullptr) {
598 *newOffset = offset + 3;
599 }
600 return ConstantValue(
601 static_cast< sal_Int16 >(file->read16(offset + 1)));
602 //TODO: implementation-defined behavior of conversion from
603 // sal_uInt16 to sal_Int16 relies on two's complement representation
604 case 3: // UNSIGNED SHORT
605 if (newOffset != nullptr) {
606 *newOffset = offset + 3;
607 }
608 return ConstantValue(file->read16(offset + 1));
609 case 4: // LONG
610 if (newOffset != nullptr) {
611 *newOffset = offset + 5;
612 }
613 return ConstantValue(
614 static_cast< sal_Int32 >(file->read32(offset + 1)));
615 //TODO: implementation-defined behavior of conversion from
616 // sal_uInt32 to sal_Int32 relies on two's complement representation
617 case 5: // UNSIGNED LONG
618 if (newOffset != nullptr) {
619 *newOffset = offset + 5;
620 }
621 return ConstantValue(file->read32(offset + 1));
622 case 6: // HYPER
623 if (newOffset != nullptr) {
624 *newOffset = offset + 9;
625 }
626 return ConstantValue(
627 static_cast< sal_Int64 >(file->read64(offset + 1)));
628 //TODO: implementation-defined behavior of conversion from
629 // sal_uInt64 to sal_Int64 relies on two's complement representation
630 case 7: // UNSIGNED HYPER
631 if (newOffset != nullptr) {
632 *newOffset = offset + 9;
633 }
634 return ConstantValue(file->read64(offset + 1));
635 case 8: // FLOAT
636 if (newOffset != nullptr) {
637 *newOffset = offset + 5;
638 }
639 return ConstantValue(file->readIso60599Binary32(offset + 1));
640 case 9: // DOUBLE
641 if (newOffset != nullptr) {
642 *newOffset = offset + 9;
643 }
644 return ConstantValue(file->readIso60599Binary64(offset + 1));
645 default:
646 throw FileFormatException(
647 file->uri,
648 "UNOIDL format: bad constant type byte " + OUString::number(v));
649 }
650}
651
652rtl::Reference< Entity > readEntity(
653 rtl::Reference< MappedFile > const & file, sal_uInt32 offset,
654 std::set<Map> && trace);
655
656class UnoidlModuleEntity;
657
658class UnoidlCursor: public MapCursor {
659public:
660 UnoidlCursor(
664 NestedMap const & map):
665 file_(std::move(file)), reference1_(std::move(reference1)), reference2_(std::move(reference2)),
666 map_(map), index_(0)
667 {}
668
669private:
670 virtual ~UnoidlCursor() noexcept override {}
671
672 virtual rtl::Reference< Entity > getNext(OUString * name) override;
673
675 rtl::Reference<UnoidlProvider> reference1_; // HACK to keep alive whatever
677 NestedMap const & map_;
678 sal_uInt32 index_;
679};
680
681rtl::Reference< Entity > UnoidlCursor::getNext(OUString * name) {
682 assert(name != nullptr);
684 if (index_ != map_.map.size) {
685 *name = file_->readNulName(map_.map.begin[index_].name.getUnsigned32());
686 ent = readEntity(
687 file_, map_.map.begin[index_].data.getUnsigned32(), std::set(map_.trace));
688 ++index_;
689 }
690 return ent;
691}
692
693class UnoidlModuleEntity: public ModuleEntity {
694public:
695 UnoidlModuleEntity(
696 rtl::Reference< MappedFile > const & file, sal_uInt32 mapOffset,
697 sal_uInt32 mapSize, std::set<Map> && trace):
698 file_(file)
699 {
700 assert(file.is());
701 map_.map.begin = reinterpret_cast<MapEntry const *>(
702 static_cast<char const *>(file_->address) + mapOffset);
703 map_.map.size = mapSize;
704 map_.trace = std::move(trace);
705 if (!map_.trace.insert(map_.map).second) {
706 throw FileFormatException(
707 file_->uri, "UNOIDL format: recursive map");
708 }
709 }
710
711private:
712 virtual ~UnoidlModuleEntity() noexcept override {}
713
714 virtual std::vector< OUString > getMemberNames() const override;
715
716 virtual rtl::Reference< MapCursor > createCursor() const override {
717 return new UnoidlCursor(
719 const_cast<UnoidlModuleEntity *>(this), map_);
720 }
721
723 NestedMap map_;
724};
725
726std::vector< OUString > UnoidlModuleEntity::getMemberNames() const {
727 std::vector< OUString > names;
728 for (sal_uInt32 i = 0; i != map_.map.size; ++i) {
729 names.push_back(
730 file_->readNulName(map_.map.begin[i].name.getUnsigned32()));
731 }
732 return names;
733}
734
735rtl::Reference< Entity > readEntity(
736 rtl::Reference< MappedFile > const & file, sal_uInt32 offset,
737 std::set<Map> && trace)
738{
739 assert(file.is());
740 int v = file->read8(offset);
741 int type = v & 0x3F;
742 bool published = (v & 0x80) != 0;
743 bool annotated = (v & 0x40) != 0;
744 bool flag = (v & 0x20) != 0;
745 switch (type) {
746 case 0: // module
747 {
748 if (v != 0) {
749 throw FileFormatException(
750 file->uri,
751 ("UNOIDL format: bad module type byte "
752 + OUString::number(v)));
753 }
754 sal_uInt32 n = file->read32(offset + 1);
755 if (n > SAL_MAX_INT32) {
756 throw FileFormatException(
757 file->uri, "UNOIDL format: too many items in module");
758 }
759 if (sal_uInt64(offset) + 5 + 8 * sal_uInt64(n) > file->size)
760 // cannot overflow
761 {
762 throw FileFormatException(
763 file->uri,
764 "UNOIDL format: module map offset + size too large");
765 }
766 return new UnoidlModuleEntity(file, offset + 5, n, std::move(trace));
767 }
768 case 1: // enum type
769 {
770 sal_uInt32 n = file->read32(offset + 1);
771 if (n == 0) {
772 throw FileFormatException(
773 file->uri, "UNOIDL format: enum type with no members");
774 }
775 if (n > SAL_MAX_INT32) {
776 throw FileFormatException(
777 file->uri, "UNOIDL format: too many members of enum type");
778 }
779 offset += 5;
780 std::vector< EnumTypeEntity::Member > mems;
781 mems.reserve(n);
782 for (sal_uInt32 i = 0; i != n; ++i) {
783 OUString memName(file->readIdxName(&offset));
784 checkEntityName(file, memName);
785 sal_Int32 memValue = static_cast< sal_Int32 >(
786 file->read32(offset));
787 //TODO: implementation-defined behavior of conversion from
788 // sal_uInt32 to sal_Int32 relies on two's complement
789 // representation
790 offset += 4;
791 mems.emplace_back(
792 memName, memValue,
793 readAnnotations(annotated, file, offset, &offset));
794 }
795 return new EnumTypeEntity(
796 published, std::move(mems), readAnnotations(annotated, file, offset));
797 }
798 case 2: // plain struct type without base
799 case 2 | 0x20: // plain struct type with base
800 {
801 ++offset;
802 OUString base;
803 if (flag) {
804 base = file->readIdxName(&offset);
805 if (base.isEmpty()) {
806 throw FileFormatException(
807 file->uri,
808 ("UNOIDL format: empty base type name of plain struct"
809 " type"));
810 }
811 checkTypeName(file, base);
812 }
813 sal_uInt32 n = file->read32(offset);
814 if (n > SAL_MAX_INT32) {
815 throw FileFormatException(
816 file->uri,
817 ("UNOIDL format: too many direct members of plain struct"
818 " type"));
819 }
820 offset += 4;
821 std::vector< PlainStructTypeEntity::Member > mems;
822 mems.reserve(n);
823 for (sal_uInt32 i = 0; i != n; ++i) {
824 OUString memName(file->readIdxName(&offset));
825 checkEntityName(file, memName);
826 OUString memType(file->readIdxName(&offset));
827 checkTypeName(file, memType);
828 mems.emplace_back(
829 memName, memType,
830 readAnnotations(annotated, file, offset, &offset));
831 }
832 return new PlainStructTypeEntity(
833 published, base, std::move(mems),
834 readAnnotations(annotated, file, offset));
835 }
836 case 3: // polymorphic struct type template
837 {
838 sal_uInt32 n = file->read32(offset + 1);
839 if (n > SAL_MAX_INT32) {
840 throw FileFormatException(
841 file->uri,
842 ("UNOIDL format: too many type parameters of polymorphic"
843 " struct type template"));
844 }
845 offset += 5;
846 std::vector< OUString > params;
847 params.reserve(n);
848 for (sal_uInt32 i = 0; i != n; ++i) {
849 OUString param(file->readIdxName(&offset));
850 checkEntityName(file, param);
851 params.push_back(param);
852 }
853 n = file->read32(offset);
854 if (n > SAL_MAX_INT32) {
855 throw FileFormatException(
856 file->uri,
857 ("UNOIDL format: too many members of polymorphic struct"
858 " type template"));
859 }
860 offset += 4;
861 std::vector< PolymorphicStructTypeTemplateEntity::Member > mems;
862 mems.reserve(n);
863 for (sal_uInt32 i = 0; i != n; ++i) {
864 v = file->read8(offset);
865 ++offset;
866 OUString memName(file->readIdxName(&offset));
867 checkEntityName(file, memName);
868 OUString memType(file->readIdxName(&offset));
869 checkTypeName(file, memType);
870 if (v > 1) {
871 throw FileFormatException(
872 file->uri,
873 ("UNOIDL format: bad flags " + OUString::number(v)
874 + " for member " + memName
875 + " of polymorphic struct type template"));
876 }
877 mems.emplace_back(
878 memName, memType, v == 1,
879 readAnnotations(annotated, file, offset, &offset));
880 }
881 return new PolymorphicStructTypeTemplateEntity(
882 published, std::move(params), std::move(mems),
883 readAnnotations(annotated, file, offset));
884 }
885 case 4: // exception type without base
886 case 4 | 0x20: // exception type with base
887 {
888 ++offset;
889 OUString base;
890 if (flag) {
891 base = file->readIdxName(&offset);
892 if (base.isEmpty()) {
893 throw FileFormatException(
894 file->uri,
895 ("UNOIDL format: empty base type name of exception"
896 " type"));
897 }
898 checkTypeName(file, base);
899 }
900 sal_uInt32 n = file->read32(offset);
901 if (n > SAL_MAX_INT32) {
902 throw FileFormatException(
903 file->uri,
904 "UNOIDL format: too many direct members of exception type");
905 }
906 offset += 4;
907 std::vector< ExceptionTypeEntity::Member > mems;
908 mems.reserve(n);
909 for (sal_uInt32 i = 0; i != n; ++i) {
910 OUString memName(file->readIdxName(&offset));
911 checkEntityName(file, memName);
912 OUString memType(file->readIdxName(&offset));
913 checkTypeName(file, memType);
914 mems.emplace_back(
915 memName, memType,
916 readAnnotations(annotated, file, offset, &offset));
917 }
918 return new ExceptionTypeEntity(
919 published, base, std::move(mems),
920 readAnnotations(annotated, file, offset));
921 }
922 case 5: // interface type
923 {
924 sal_uInt32 n = file->read32(offset + 1);
925 if (n > SAL_MAX_INT32) {
926 throw FileFormatException(
927 file->uri,
928 ("UNOIDL format: too many direct mandatory bases of"
929 " interface type"));
930 }
931 offset += 5;
932 std::vector< AnnotatedReference > mandBases;
933 mandBases.reserve(n);
934 for (sal_uInt32 i = 0; i != n; ++i) {
935 OUString base(file->readIdxName(&offset));
936 checkTypeName(file, base);
937 mandBases.emplace_back(
938 base, readAnnotations(annotated, file, offset, &offset));
939 }
940 n = file->read32(offset);
941 if (n > SAL_MAX_INT32) {
942 throw FileFormatException(
943 file->uri,
944 ("UNOIDL format: too many direct optional bases of"
945 " interface type"));
946 }
947 offset += 4;
948 std::vector< AnnotatedReference > optBases;
949 optBases.reserve(n);
950 for (sal_uInt32 i = 0; i != n; ++i) {
951 OUString base(file->readIdxName(&offset));
952 checkTypeName(file, base);
953 optBases.emplace_back(
954 base, readAnnotations(annotated, file, offset, &offset));
955 }
956 sal_uInt32 nAttrs = file->read32(offset);
957 if (nAttrs > SAL_MAX_INT32) {
958 throw FileFormatException(
959 file->uri,
960 ("UNOIDL format: too many direct attributes of interface"
961 " type"));
962 }
963 offset += 4;
964 std::vector< InterfaceTypeEntity::Attribute > attrs;
965 attrs.reserve(nAttrs);
966 for (sal_uInt32 i = 0; i != nAttrs; ++i) {
967 v = file->read8(offset);
968 ++offset;
969 OUString attrName(file->readIdxName(&offset));
970 checkEntityName(file, attrName);
971 OUString attrType(file->readIdxName(&offset));
972 checkTypeName(file, attrType);
973 if (v > 0x03) {
974 throw FileFormatException(
975 file->uri,
976 ("UNOIDL format: bad flags for direct attribute "
977 + attrName + " of interface type"));
978 }
979 std::vector< OUString > getExcs;
980 sal_uInt32 m = file->read32(offset);
981 if (m > SAL_MAX_INT32) {
982 throw FileFormatException(
983 file->uri,
984 ("UNOIDL format: too many getter exceptions for direct"
985 " attribute " + attrName + " of interface type"));
986 }
987 offset += 4;
988 getExcs.reserve(m);
989 for (sal_uInt32 j = 0; j != m; ++j) {
990 OUString exc(file->readIdxName(&offset));
991 checkTypeName(file, exc);
992 getExcs.push_back(exc);
993 }
994 std::vector< OUString > setExcs;
995 if ((v & 0x02) == 0) {
996 m = file->read32(offset);
997 if (m > SAL_MAX_INT32) {
998 throw FileFormatException(
999 file->uri,
1000 ("UNOIDL format: too many setter exceptions for"
1001 " direct attribute " + attrName
1002 + " of interface type"));
1003 }
1004 offset += 4;
1005 setExcs.reserve(m);
1006 for (sal_uInt32 j = 0; j != m; ++j) {
1007 OUString exc(file->readIdxName(&offset));
1008 checkTypeName(file, exc);
1009 setExcs.push_back(exc);
1010 }
1011 }
1012 attrs.emplace_back(
1013 attrName, attrType, (v & 0x01) != 0, (v & 0x02) != 0,
1014 std::move(getExcs), std::move(setExcs),
1015 readAnnotations(annotated, file, offset, &offset));
1016 }
1017 sal_uInt32 nMeths = file->read32(offset);
1018 if (nMeths > SAL_MAX_INT32 - nAttrs) {
1019 throw FileFormatException(
1020 file->uri,
1021 ("UNOIDL format: too many direct attributes and methods of"
1022 " interface type"));
1023 }
1024 offset += 4;
1025 std::vector< InterfaceTypeEntity::Method > meths;
1026 meths.reserve(nMeths);
1027 for (sal_uInt32 i = 0; i != nMeths; ++i) {
1028 OUString methName(file->readIdxName(&offset));
1029 checkEntityName(file, methName);
1030 OUString methType(file->readIdxName(&offset));
1031 checkTypeName(file, methType);
1032 sal_uInt32 m = file->read32(offset);
1033 if (m > SAL_MAX_INT32) {
1034 throw FileFormatException(
1035 file->uri,
1036 ("UNOIDL format: too many parameters for method "
1037 + methName + " of interface type"));
1038 }
1039 offset += 4;
1040 std::vector< InterfaceTypeEntity::Method::Parameter > params;
1041 params.reserve(m);
1042 for (sal_uInt32 j = 0; j != m; ++j) {
1043 v = file->read8(offset);
1044 ++offset;
1045 OUString paramName(file->readIdxName(&offset));
1046 checkEntityName(file, paramName);
1047 OUString paramType(file->readIdxName(&offset));
1048 checkTypeName(file, paramType);
1050 switch (v) {
1051 case 0:
1054 break;
1055 case 1:
1058 break;
1059 case 2:
1062 break;
1063 default:
1064 throw FileFormatException(
1065 file->uri,
1066 ("UNOIDL format: bad direction "
1067 + OUString::number(v) + " of parameter "
1068 + paramName + " for method " + methName
1069 + " of interface type"));
1070 }
1071 params.emplace_back(paramName, paramType, dir);
1072 }
1073 std::vector< OUString > excs;
1074 m = file->read32(offset);
1075 if (m > SAL_MAX_INT32) {
1076 throw FileFormatException(
1077 file->uri,
1078 ("UNOIDL format: too many exceptions for method "
1079 + methName + " of interface type"));
1080 }
1081 offset += 4;
1082 excs.reserve(m);
1083 for (sal_uInt32 j = 0; j != m; ++j) {
1084 OUString exc(file->readIdxName(&offset));
1085 checkTypeName(file, exc);
1086 excs.push_back(exc);
1087 }
1088 meths.emplace_back(
1089 methName, methType, std::move(params), std::move(excs),
1090 readAnnotations(annotated, file, offset, &offset));
1091 }
1092 return new InterfaceTypeEntity(
1093 published, std::move(mandBases), std::move(optBases), std::move(attrs), std::move(meths),
1094 readAnnotations(annotated, file, offset));
1095 }
1096 case 6: // typedef
1097 {
1098 ++offset;
1099 OUString base(file->readIdxName(&offset));
1100 checkTypeName(file, base);
1101 return new TypedefEntity(
1102 published, base, readAnnotations(annotated, file, offset));
1103 }
1104 case 7: // constant group
1105 {
1106 sal_uInt32 n = file->read32(offset + 1);
1107 if (n > SAL_MAX_INT32) {
1108 throw FileFormatException(
1109 file->uri,
1110 "UNOIDL format: too many constants in constant group");
1111 }
1112 if (sal_uInt64(offset) + 5 + 8 * sal_uInt64(n) > file->size)
1113 // cannot overflow
1114 {
1115 throw FileFormatException(
1116 file->uri,
1117 ("UNOIDL format: constant group map offset + size too"
1118 " large"));
1119 }
1120 MapEntry const * p = reinterpret_cast< MapEntry const * >(
1121 static_cast< char const * >(file->address) + offset + 5);
1122 std::vector< ConstantGroupEntity::Member > mems;
1123 mems.reserve(n);
1124 for (sal_uInt32 i = 0; i != n; ++i) {
1125 sal_uInt32 off = p[i].data.getUnsigned32();
1126 bool ann;
1127 ConstantValue val(readConstant(file, off, &off, &ann));
1128 mems.emplace_back(
1129 file->readNulName(p[i].name.getUnsigned32()), val,
1130 readAnnotations(ann, file, off));
1131 }
1132 return new ConstantGroupEntity(
1133 published, std::move(mems),
1134 readAnnotations(annotated, file, offset + 5 + 8 * n));
1135 }
1136 case 8: // single-interface--based service without default constructor
1137 case 8 | 0x20: // single-interface--based service with default constructor
1138 {
1139 ++offset;
1140 OUString base(file->readIdxName(&offset));
1141 checkTypeName(file, base);
1142 std::vector< SingleInterfaceBasedServiceEntity::Constructor > ctors;
1143 if (flag) {
1144 ctors.push_back(
1145 SingleInterfaceBasedServiceEntity::Constructor());
1146 } else {
1147 sal_uInt32 n = file->read32(offset);
1148 if (n > SAL_MAX_INT32) {
1149 throw FileFormatException(
1150 file->uri,
1151 ("UNOIDL format: too many constructors of"
1152 " single-interface--based service"));
1153 }
1154 offset += 4;
1155 ctors.reserve(n);
1156 for (sal_uInt32 i = 0; i != n; ++i) {
1157 OUString ctorName(file->readIdxName(&offset));
1158 checkEntityName(file, ctorName);
1159 sal_uInt32 m = file->read32(offset);
1160 if (m > SAL_MAX_INT32) {
1161 throw FileFormatException(
1162 file->uri,
1163 ("UNOIDL format: too many parameters for"
1164 " constructor " + ctorName
1165 + " of single-interface--based service"));
1166 }
1167 offset += 4;
1168 std::vector<
1169 SingleInterfaceBasedServiceEntity::Constructor::
1170 Parameter > params;
1171 params.reserve(m);
1172 for (sal_uInt32 j = 0; j != m; ++j) {
1173 v = file->read8(offset);
1174 ++offset;
1175 OUString paramName(file->readIdxName(&offset));
1176 checkEntityName(file, paramName);
1177 OUString paramType(file->readIdxName(&offset));
1178 checkTypeName(file, paramType);
1179 bool rest;
1180 switch (v) {
1181 case 0:
1182 rest = false;
1183 break;
1184 case 0x04:
1185 rest = true;
1186 break;
1187 default:
1188 throw FileFormatException(
1189 file->uri,
1190 ("UNOIDL format: bad mode "
1191 + OUString::number(v) + " of parameter "
1192 + paramName + " for constructor " + ctorName
1193 + " of single-interface--based service"));
1194 }
1195 params.emplace_back(paramName, paramType, rest);
1196 }
1197 std::vector< OUString > excs;
1198 m = file->read32(offset);
1199 if (m > SAL_MAX_INT32) {
1200 throw FileFormatException(
1201 file->uri,
1202 ("UNOIDL format: too many exceptions for"
1203 " constructor " + ctorName
1204 + " of single-interface--based service"));
1205 }
1206 offset += 4;
1207 excs.reserve(m);
1208 for (sal_uInt32 j = 0; j != m; ++j) {
1209 OUString exc(file->readIdxName(&offset));
1210 checkTypeName(file, exc);
1211 excs.push_back(exc);
1212 }
1213 ctors.push_back(
1214 SingleInterfaceBasedServiceEntity::Constructor(
1215 ctorName, std::move(params), std::move(excs),
1216 readAnnotations(annotated, file, offset, &offset)));
1217 }
1218 }
1219 return new SingleInterfaceBasedServiceEntity(
1220 published, base, std::move(ctors),
1221 readAnnotations(annotated, file, offset));
1222 }
1223 case 9: // accumulation-based service
1224 {
1225 sal_uInt32 n = file->read32(offset + 1);
1226 if (n > SAL_MAX_INT32) {
1227 throw FileFormatException(
1228 file->uri,
1229 ("UNOIDL format: too many direct mandatory service bases of"
1230 " accumulation-based service"));
1231 }
1232 offset += 5;
1233 std::vector< AnnotatedReference > mandServs;
1234 mandServs.reserve(n);
1235 for (sal_uInt32 i = 0; i != n; ++i) {
1236 OUString base(file->readIdxName(&offset));
1237 checkTypeName(file, base);
1238 mandServs.emplace_back(
1239 base, readAnnotations(annotated, file, offset, &offset));
1240 }
1241 n = file->read32(offset);
1242 if (n > SAL_MAX_INT32) {
1243 throw FileFormatException(
1244 file->uri,
1245 ("UNOIDL format: too many direct optional service bases of"
1246 " accumulation-based service"));
1247 }
1248 offset += 4;
1249 std::vector< AnnotatedReference > optServs;
1250 optServs.reserve(n);
1251 for (sal_uInt32 i = 0; i != n; ++i) {
1252 OUString base(file->readIdxName(&offset));
1253 checkTypeName(file, base);
1254 optServs.emplace_back(
1255 base, readAnnotations(annotated, file, offset, &offset));
1256 }
1257 n = file->read32(offset);
1258 if (n > SAL_MAX_INT32) {
1259 throw FileFormatException(
1260 file->uri,
1261 ("UNOIDL format: too many direct mandatory interface bases"
1262 " of accumulation-based service"));
1263 }
1264 offset += 4;
1265 std::vector< AnnotatedReference > mandIfcs;
1266 mandIfcs.reserve(n);
1267 for (sal_uInt32 i = 0; i != n; ++i) {
1268 OUString base(file->readIdxName(&offset));
1269 checkTypeName(file, base);
1270 mandIfcs.emplace_back(
1271 base, readAnnotations(annotated, file, offset, &offset));
1272 }
1273 n = file->read32(offset);
1274 if (n > SAL_MAX_INT32) {
1275 throw FileFormatException(
1276 file->uri,
1277 ("UNOIDL format: too many direct optional interface bases"
1278 " of accumulation-based service"));
1279 }
1280 offset += 4;
1281 std::vector< AnnotatedReference > optIfcs;
1282 optIfcs.reserve(n);
1283 for (sal_uInt32 i = 0; i != n; ++i) {
1284 OUString base(file->readIdxName(&offset));
1285 checkTypeName(file, base);
1286 optIfcs.emplace_back(
1287 base, readAnnotations(annotated, file, offset, &offset));
1288 }
1289 n = file->read32(offset);
1290 if (n > SAL_MAX_INT32) {
1291 throw FileFormatException(
1292 file->uri,
1293 ("UNOIDL format: too many direct properties of"
1294 " accumulation-based service"));
1295 }
1296 offset += 4;
1297 std::vector< AccumulationBasedServiceEntity::Property > props;
1298 props.reserve(n);
1299 for (sal_uInt32 i = 0; i != n; ++i) {
1300 sal_uInt16 attrs = file->read16(offset);
1301 offset += 2;
1302 OUString propName(file->readIdxName(&offset));
1303 checkEntityName(file, propName);
1304 OUString propType(file->readIdxName(&offset));
1305 checkTypeName(file, propType);
1306 if (attrs > 0x01FF) { // see css.beans.PropertyAttribute
1307 throw FileFormatException(
1308 file->uri,
1309 ("UNOIDL format: bad mode " + OUString::number(v)
1310 + " of property " + propName
1311 + " for accumulation-based service"));
1312 }
1313 props.emplace_back(
1314 propName, propType,
1315 static_cast<
1317 attrs),
1318 readAnnotations(annotated, file, offset, &offset));
1319 }
1320 return new AccumulationBasedServiceEntity(
1321 published, std::move(mandServs), std::move(optServs), std::move(mandIfcs), std::move(optIfcs), std::move(props),
1322 readAnnotations(annotated, file, offset));
1323 }
1324 case 10: // interface-based singleton
1325 {
1326 ++offset;
1327 OUString base(file->readIdxName(&offset));
1328 checkTypeName(file, base);
1329 return new InterfaceBasedSingletonEntity(
1330 published, base, readAnnotations(annotated, file, offset));
1331 }
1332 case 11: // service-based singleton
1333 {
1334 ++offset;
1335 OUString base(file->readIdxName(&offset));
1336 checkTypeName(file, base);
1337 return new ServiceBasedSingletonEntity(
1338 published, base, readAnnotations(annotated, file, offset));
1339 }
1340 default:
1341 throw FileFormatException(
1342 file->uri, "UNOIDL format: bad type byte " + OUString::number(v));
1343 }
1344}
1345
1346}
1347
1348UnoidlProvider::UnoidlProvider(OUString const & uri): file_(new MappedFile(uri))
1349{
1350 if (file_->size < 8 || std::memcmp(file_->address, "UNOIDL\xFF\0", 8) != 0)
1351 {
1352 throw FileFormatException(
1353 file_->uri,
1354 "UNOIDL format: does not begin with magic UNOIDL\\xFF and version"
1355 " 0");
1356 }
1357 sal_uInt32 off = file_->read32(8);
1358 map_.map.size = file_->read32(12);
1359 if (off + 8 * sal_uInt64(map_.map.size) > file_->size) { // cannot overflow
1360 throw FileFormatException(
1361 file_->uri, "UNOIDL format: root map offset + size too large");
1362 }
1363 map_.map.begin = reinterpret_cast< MapEntry const * >(
1364 static_cast< char const * >(file_->address) + off);
1365 map_.trace.insert(map_.map);
1366}
1367
1369 return new UnoidlCursor(
1370 file_, const_cast<UnoidlProvider *>(this),
1372}
1373
1375{
1377 bool cgroup = false;
1378 for (sal_Int32 i = 0;;) {
1379 sal_Int32 j = name.indexOf('.', i);
1380 if (j == -1) {
1381 j = name.getLength();
1382 }
1383 sal_Int32 off = findInMap(
1384 file_, map.map.begin, map.map.size, name, i, j - i);
1385 if (off == 0) {
1386 return rtl::Reference< Entity >();
1387 }
1388 if (j == name.getLength()) {
1389 return cgroup
1391 : readEntity(file_, off, std::set(map.trace));
1392 }
1393 if (cgroup) {
1394 return rtl::Reference< Entity >();
1395 //TODO: throw an exception instead here, where the segments of a
1396 // constant's name are a prefix of the requested name's
1397 // segments?
1398 }
1399 int v = file_->read8(off);
1400 if (v != 0) { // module
1401 if ((v & 0x3F) == 7) { // constant group
1402 cgroup = true;
1403 } else {
1404 return rtl::Reference< Entity >();
1405 //TODO: throw an exception instead here, where the segments
1406 // of a non-module, non-constant-group entity's name are a
1407 // prefix of the requested name's segments?
1408 }
1409 }
1410 map.map.size = file_->read32(off + 1);
1411 if (sal_uInt64(off) + 5 + 8 * sal_uInt64(map.map.size) > file_->size)
1412 // cannot overflow
1413 {
1414 throw FileFormatException(
1415 file_->uri, "UNOIDL format: map offset + size too large");
1416 }
1417 map.map.begin = reinterpret_cast< MapEntry const * >(
1418 static_cast< char const * >(file_->address) + off + 5);
1419 if (!map.trace.insert(map.map).second) {
1420 throw FileFormatException(
1421 file_->uri, "UNOIDL format: recursive map");
1422 }
1423 i = j + 1;
1424 }
1425}
1426
1428
1429}
1430
1431/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
double d
sal_uInt64 get64(sal_uInt32 offset) const
MappedFile(OUString fileUrl)
sal_uInt16 read16(sal_uInt32 offset) const
float readIso60599Binary32(sal_uInt32 offset) const
OUString readNulName(sal_uInt32 offset)
sal_uInt32 get32(sal_uInt32 offset) const
sal_uInt8 read8(sal_uInt32 offset) const
OUString readIdxName(sal_uInt32 *offset) const
float getIso60599Binary32(sal_uInt32 offset) const
sal_uInt32 read32(sal_uInt32 offset) const
sal_uInt64 read64(sal_uInt32 offset) const
double readIso60599Binary64(sal_uInt32 offset) const
double getIso60599Binary64(sal_uInt32 offset) const
sal_uInt8 get8(sal_uInt32 offset) const
sal_uInt16 get16(sal_uInt32 offset) const
virtual ~MappedFile() override
OUString readIdxString(sal_uInt32 *offset) const
UnoidlProvider(OUString const &uri)
virtual rtl::Reference< MapCursor > createRootCursor() const override
virtual ~UnoidlProvider() noexcept override
virtual rtl::Reference< Entity > findEntity(OUString const &name) const override
rtl::Reference< detail::MappedFile > file_
float v
float u
void const * base
const char * name
void * p
sal_Int64 n
#define SAL_WARN_IF(condition, area, stream)
const char * attrName
bool isSimpleType(typelib_TypeClass typeClass)
int i
m
constexpr bool starts_with(std::basic_string_view< charT, traits > sv, std::basic_string_view< charT, traits > x) noexcept
end
args
dictionary props
static bool operator<(const Map &map1, const Map &map2)
SwNodeOffset min(const SwNodeOffset &a, const SwNodeOffset &b)
SbxDecimal::CmpResult compare(SAL_UNUSED_PARAMETER const SbxDecimal &, SAL_UNUSED_PARAMETER const SbxDecimal &)
std::map< OUString, rtl::Reference< Entity > > map
MapEntry const * begin
unsigned char sal_uInt8
#define SAL_MAX_INT32
sal_uInt16 sal_Unicode
signed char sal_Int8
ResultType type
rtl::Reference< UnoidlModuleEntity > reference2_
rtl::Reference< MappedFile > file_
sal_uInt32 index_
NestedMap const & map_
rtl::Reference< UnoidlProvider > reference1_