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