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 <vector>
16 :
17 : #include "osl/endian.h"
18 : #include "osl/file.h"
19 : #include "rtl/ref.hxx"
20 : #include "rtl/textenc.h"
21 : #include "rtl/textcvt.h"
22 : #include "rtl/ustring.hxx"
23 : #include "sal/log.hxx"
24 : #include "sal/types.h"
25 : #include "salhelper/simplereferenceobject.hxx"
26 : #include "unoidl/unoidl.hxx"
27 :
28 : #include "unoidlprovider.hxx"
29 :
30 : namespace unoidl { namespace detail {
31 :
32 : namespace {
33 :
34 : // sizeof (Memory16) == 2
35 : struct Memory16 {
36 : unsigned char byte[2];
37 :
38 62707 : sal_uInt16 getUnsigned16() const {
39 62707 : return static_cast< sal_uInt16 >(byte[0])
40 62707 : | (static_cast< sal_uInt16 >(byte[1]) << 8);
41 : }
42 : };
43 :
44 : // sizeof (Memory32) == 4
45 : struct Memory32 {
46 : unsigned char byte[4];
47 :
48 40117459 : sal_uInt32 getUnsigned32() const {
49 40117459 : return static_cast< sal_uInt32 >(byte[0])
50 40117459 : | (static_cast< sal_uInt32 >(byte[1]) << 8)
51 40117459 : | (static_cast< sal_uInt32 >(byte[2]) << 16)
52 40117459 : | (static_cast< sal_uInt32 >(byte[3]) << 24);
53 : }
54 :
55 280 : float getIso60599Binary32() const {
56 : union {
57 : unsigned char buf[4];
58 : float f; // assuming float is ISO 60599 binary32
59 : } sa;
60 : #if defined OSL_LITENDIAN
61 280 : sa.buf[0] = byte[0];
62 280 : sa.buf[1] = byte[1];
63 280 : sa.buf[2] = byte[2];
64 280 : sa.buf[3] = byte[3];
65 : #else
66 : sa.buf[0] = byte[3];
67 : sa.buf[1] = byte[2];
68 : sa.buf[2] = byte[1];
69 : sa.buf[3] = byte[0];
70 : #endif
71 280 : return sa.f;
72 : }
73 : };
74 :
75 : // sizeof (Memory64) == 8
76 : struct Memory64 {
77 : unsigned char byte[8];
78 :
79 426 : sal_uInt64 getUnsigned64() const {
80 426 : return static_cast< sal_uInt64 >(byte[0])
81 426 : | (static_cast< sal_uInt64 >(byte[1]) << 8)
82 426 : | (static_cast< sal_uInt64 >(byte[2]) << 16)
83 426 : | (static_cast< sal_uInt64 >(byte[3]) << 24)
84 426 : | (static_cast< sal_uInt64 >(byte[4]) << 32)
85 426 : | (static_cast< sal_uInt64 >(byte[5]) << 40)
86 426 : | (static_cast< sal_uInt64 >(byte[6]) << 48)
87 426 : | (static_cast< sal_uInt64 >(byte[7]) << 56);
88 : }
89 :
90 0 : double getIso60599Binary64() const {
91 : union {
92 : unsigned char buf[8];
93 : double d; // assuming double is ISO 60599 binary64
94 : } sa;
95 : #if defined OSL_LITENDIAN
96 0 : sa.buf[0] = byte[0];
97 0 : sa.buf[1] = byte[1];
98 0 : sa.buf[2] = byte[2];
99 0 : sa.buf[3] = byte[3];
100 0 : sa.buf[4] = byte[4];
101 0 : sa.buf[5] = byte[5];
102 0 : sa.buf[6] = byte[6];
103 0 : sa.buf[7] = byte[7];
104 : #else
105 : sa.buf[0] = byte[7];
106 : sa.buf[1] = byte[6];
107 : sa.buf[2] = byte[5];
108 : sa.buf[3] = byte[4];
109 : sa.buf[4] = byte[3];
110 : sa.buf[5] = byte[2];
111 : sa.buf[6] = byte[1];
112 : sa.buf[7] = byte[0];
113 : #endif
114 0 : return sa.d;
115 : }
116 : };
117 :
118 : }
119 :
120 : class MappedFile: public salhelper::SimpleReferenceObject {
121 : public:
122 : explicit MappedFile(OUString const & fileUrl);
123 :
124 : sal_uInt8 read8(sal_uInt32 offset) const;
125 :
126 : sal_uInt16 read16(sal_uInt32 offset) const;
127 :
128 : sal_uInt32 read32(sal_uInt32 offset) const;
129 :
130 : sal_uInt64 read64(sal_uInt32 offset) const;
131 :
132 : float readIso60599Binary32(sal_uInt32 offset) const;
133 :
134 : double readIso60599Binary64(sal_uInt32 offset) const;
135 :
136 : OUString readNulName(sal_uInt32 offset) const;
137 :
138 7488549 : OUString readIdxName(sal_uInt32 * offset) const
139 7488549 : { return readIdxString(offset, RTL_TEXTENCODING_ASCII_US); }
140 :
141 15699 : OUString readIdxString(sal_uInt32 * offset) const
142 15699 : { return readIdxString(offset, RTL_TEXTENCODING_UTF8); }
143 :
144 : OUString uri;
145 : oslFileHandle handle;
146 : sal_uInt64 size;
147 : void * address;
148 :
149 : private:
150 : virtual ~MappedFile();
151 :
152 : sal_uInt8 get8(sal_uInt32 offset) const;
153 :
154 : sal_uInt16 get16(sal_uInt32 offset) const;
155 :
156 : sal_uInt32 get32(sal_uInt32 offset) const;
157 :
158 : sal_uInt64 get64(sal_uInt32 offset) const;
159 :
160 : float getIso60599Binary32(sal_uInt32 offset) const;
161 :
162 : double getIso60599Binary64(sal_uInt32 offset) const;
163 :
164 : OUString readIdxString(sal_uInt32 * offset, rtl_TextEncoding encoding)
165 : const;
166 : };
167 :
168 745 : MappedFile::MappedFile(OUString const & fileUrl): uri(fileUrl) {
169 745 : oslFileError e = osl_openFile(uri.pData, &handle, osl_File_OpenFlag_Read);
170 745 : switch (e) {
171 : case osl_File_E_None:
172 745 : break;
173 : case osl_File_E_NOENT:
174 0 : throw NoSuchFileException(uri);
175 : default:
176 0 : throw FileFormatException(uri, "cannot open: " + OUString::number(e));
177 : }
178 745 : e = osl_getFileSize(handle, &size);
179 745 : if (e == osl_File_E_None) {
180 : e = osl_mapFile(
181 745 : handle, &address, size, 0, osl_File_MapFlag_RandomAccess);
182 : }
183 745 : if (e != osl_File_E_None) {
184 0 : oslFileError e2 = osl_closeFile(handle);
185 : SAL_WARN_IF(
186 : e2 != osl_File_E_None, "unoidl",
187 : "cannot close " << uri << ": " << +e2);
188 0 : throw FileFormatException(uri, "cannot mmap: " + OUString::number(e));
189 : }
190 745 : }
191 :
192 6157985 : sal_uInt8 MappedFile::read8(sal_uInt32 offset) const {
193 : assert(size >= 8);
194 6157985 : if (offset > size - 1) {
195 : throw FileFormatException(
196 0 : uri, "UNOIDL format: offset for 8-bit value too large");
197 : }
198 6157985 : return get8(offset);
199 : }
200 :
201 62707 : sal_uInt16 MappedFile::read16(sal_uInt32 offset) const {
202 : assert(size >= 8);
203 62707 : if (offset > size - 2) {
204 : throw FileFormatException(
205 0 : uri, "UNOIDL format: offset for 16-bit value too large");
206 : }
207 62707 : return get16(offset);
208 : }
209 :
210 22908235 : sal_uInt32 MappedFile::read32(sal_uInt32 offset) const {
211 : assert(size >= 8);
212 22908235 : if (offset > size - 4) {
213 : throw FileFormatException(
214 0 : uri, "UNOIDL format: offset for 32-bit value too large");
215 : }
216 22908235 : return get32(offset);
217 : }
218 :
219 426 : sal_uInt64 MappedFile::read64(sal_uInt32 offset) const {
220 : assert(size >= 8);
221 426 : if (offset > size - 8) {
222 : throw FileFormatException(
223 0 : uri, "UNOIDL format: offset for 64-bit value too large");
224 : }
225 426 : return get64(offset);
226 : }
227 :
228 280 : float MappedFile::readIso60599Binary32(sal_uInt32 offset) const {
229 : assert(size >= 8);
230 280 : if (offset > size - 4) {
231 : throw FileFormatException(
232 0 : uri, "UNOIDL format: offset for 32-bit value too large");
233 : }
234 280 : return getIso60599Binary32(offset);
235 : }
236 :
237 0 : double MappedFile::readIso60599Binary64(sal_uInt32 offset) const {
238 : assert(size >= 8);
239 0 : if (offset > size - 8) {
240 : throw FileFormatException(
241 0 : uri, "UNOIDL format: offset for 64-bit value too large");
242 : }
243 0 : return getIso60599Binary64(offset);
244 : }
245 :
246 141336 : OUString MappedFile::readNulName(sal_uInt32 offset) const {
247 141336 : if (offset > size) {
248 : throw FileFormatException(
249 0 : uri, "UNOIDL format: offset for string too large");
250 : }
251 141336 : sal_uInt64 end = offset;
252 2170521 : for (;; ++end) {
253 2311857 : if (end == size) {
254 : throw FileFormatException(
255 0 : uri, "UNOIDL format: string misses trailing NUL");
256 : }
257 2311857 : if (static_cast< char const * >(address)[end] == 0) {
258 141336 : break;
259 : }
260 : }
261 141336 : if (end - offset > SAL_MAX_INT32) {
262 0 : throw FileFormatException(uri, "UNOIDL format: string too long");
263 : }
264 141336 : OUString name;
265 141336 : if (!rtl_convertStringToUString(
266 : &name.pData, static_cast< char const * >(address) + offset,
267 : end - offset, RTL_TEXTENCODING_ASCII_US,
268 : (RTL_TEXTTOUNICODE_FLAGS_UNDEFINED_ERROR
269 : | RTL_TEXTTOUNICODE_FLAGS_MBUNDEFINED_ERROR
270 141336 : | RTL_TEXTTOUNICODE_FLAGS_INVALID_ERROR)))
271 : {
272 0 : throw FileFormatException(uri, "UNOIDL format: name is not ASCII");
273 : }
274 2311857 : return name;
275 : }
276 :
277 1308 : MappedFile::~MappedFile() {
278 436 : oslFileError e = osl_unmapMappedFile(handle, address, size);
279 : SAL_WARN_IF(e != osl_File_E_None, "unoidl", "cannot unmap: " << +e);
280 436 : e = osl_closeFile(handle);
281 : SAL_WARN_IF(e != osl_File_E_None, "unoidl", "cannot close: " << +e);
282 872 : }
283 :
284 6157985 : sal_uInt8 MappedFile::get8(sal_uInt32 offset) const {
285 : assert(size >= 8);
286 : assert(offset <= size - 1);
287 6157985 : return static_cast< char const * >(address)[offset];
288 : }
289 :
290 62707 : sal_uInt16 MappedFile::get16(sal_uInt32 offset) const {
291 : assert(size >= 8);
292 : assert(offset <= size - 2);
293 : return reinterpret_cast< Memory16 const * >(
294 62707 : static_cast< char const * >(address) + offset)->getUnsigned16();
295 : }
296 :
297 22908235 : sal_uInt32 MappedFile::get32(sal_uInt32 offset) const {
298 : assert(size >= 8);
299 : assert(offset <= size - 4);
300 : return reinterpret_cast< Memory32 const * >(
301 22908235 : static_cast< char const * >(address) + offset)->getUnsigned32();
302 : }
303 :
304 426 : sal_uInt64 MappedFile::get64(sal_uInt32 offset) const {
305 : assert(size >= 8);
306 : assert(offset <= size - 8);
307 : return reinterpret_cast< Memory64 const * >(
308 426 : static_cast< char const * >(address) + offset)->getUnsigned64();
309 : }
310 :
311 280 : float MappedFile::getIso60599Binary32(sal_uInt32 offset) const {
312 : assert(size >= 8);
313 : assert(offset <= size - 4);
314 : return reinterpret_cast< Memory32 const * >(
315 280 : static_cast< char const * >(address) + offset)->getIso60599Binary32();
316 : }
317 :
318 0 : double MappedFile::getIso60599Binary64(sal_uInt32 offset) const {
319 : assert(size >= 8);
320 : assert(offset <= size - 8);
321 : return reinterpret_cast< Memory64 const * >(
322 0 : static_cast< char const * >(address) + offset)->getIso60599Binary64();
323 : }
324 :
325 7504248 : OUString MappedFile::readIdxString(
326 : sal_uInt32 * offset, rtl_TextEncoding encoding) const
327 : {
328 : assert(offset != 0);
329 7504248 : sal_uInt32 len = read32(*offset);
330 : sal_uInt32 off;
331 7504248 : if ((len & 0x80000000) == 0) {
332 2252047 : off = *offset;
333 2252047 : *offset += 4 + len;
334 : } else {
335 5252201 : *offset += 4;
336 5252201 : off = len & ~0x80000000;
337 5252201 : len = read32(off);
338 5252201 : if ((len & 0x80000000) != 0) {
339 : throw FileFormatException(
340 0 : uri, "UNOIDL format: string length high bit set");
341 : }
342 : }
343 7504248 : if (len > SAL_MAX_INT32 || len > size - off - 4) {
344 : throw FileFormatException(
345 0 : uri, "UNOIDL format: size of string is too large");
346 : }
347 7504248 : OUString name;
348 7504248 : if (!rtl_convertStringToUString(
349 7504248 : &name.pData, static_cast< char const * >(address) + off + 4, len,
350 : encoding,
351 : (RTL_TEXTTOUNICODE_FLAGS_UNDEFINED_ERROR
352 : | RTL_TEXTTOUNICODE_FLAGS_MBUNDEFINED_ERROR
353 15008496 : | RTL_TEXTTOUNICODE_FLAGS_INVALID_ERROR)))
354 : {
355 : throw FileFormatException(
356 0 : uri, "UNOIDL format: string bytes do not match encoding");
357 : }
358 7504248 : return name;
359 : }
360 :
361 : // sizeof (MapEntry) == 8
362 : struct MapEntry {
363 : Memory32 name;
364 : Memory32 data;
365 : };
366 :
367 : namespace {
368 :
369 : enum Compare { COMPARE_LESS, COMPARE_GREATER, COMPARE_EQUAL };
370 :
371 12188997 : Compare compare(
372 : rtl::Reference< MappedFile > const & file, OUString const & name,
373 : sal_Int32 nameOffset, sal_Int32 nameLength, MapEntry const * entry)
374 : {
375 : assert(file.is());
376 : assert(entry != 0);
377 12188997 : sal_uInt32 off = entry->name.getUnsigned32();
378 12188997 : if (off > file->size - 1) { // at least a trailing NUL
379 : throw FileFormatException(
380 0 : file->uri, "UNOIDL format: string offset too large");
381 : }
382 : assert(nameLength >= 0);
383 : sal_uInt64 min = std::min(
384 12188997 : static_cast< sal_uInt64 >(nameLength), file->size - off);
385 41027930 : for (sal_uInt64 i = 0; i != min; ++i) {
386 36191374 : sal_Unicode c1 = name[nameOffset + i];
387 36191374 : sal_Unicode c2 = static_cast< unsigned char const * >(file->address)[
388 36191374 : off + i];
389 36191374 : if (c1 < c2) {
390 3538245 : return COMPARE_LESS;
391 32653129 : } else if (c1 > c2 || c2 == 0) {
392 : // ...the "|| c2 == 0" is for the odd case where name erroneously
393 : // contains NUL characters
394 3814196 : return COMPARE_GREATER;
395 : }
396 : }
397 4836556 : if (static_cast< sal_uInt64 >(nameLength) == min) {
398 4836556 : if (file->size - off == min) {
399 : throw FileFormatException(
400 0 : file->uri, "UNOIDL format: string misses trailing NUL");
401 : }
402 : return
403 4836556 : static_cast< unsigned char const * >(file->address)[off + min] == 0
404 4836556 : ? COMPARE_EQUAL : COMPARE_LESS;
405 : } else {
406 0 : return COMPARE_GREATER;
407 : }
408 : }
409 :
410 12784189 : sal_uInt32 findInMap(
411 : rtl::Reference< MappedFile > const & file, MapEntry const * mapBegin,
412 : sal_uInt32 mapSize, OUString const & name, sal_Int32 nameOffset,
413 : sal_Int32 nameLength)
414 : {
415 12784189 : if (mapSize == 0) {
416 595192 : return 0;
417 : }
418 12188997 : sal_uInt32 n = mapSize / 2;
419 12188997 : MapEntry const * p = mapBegin + n;
420 12188997 : switch (compare(file, name, nameOffset, nameLength, p)) {
421 : case COMPARE_LESS:
422 3637246 : return findInMap(file, mapBegin, n, name, nameOffset, nameLength);
423 : case COMPARE_GREATER:
424 : return findInMap(
425 3814196 : file, p + 1, mapSize - n - 1, name, nameOffset, nameLength);
426 : default: // COMPARE_EQUAL
427 4737555 : break;
428 : }
429 4737555 : sal_uInt32 off = mapBegin[n].data.getUnsigned32();
430 4737555 : if (off == 0) {
431 : throw FileFormatException(
432 0 : file->uri, "UNOIDL format: map entry data offset is null");
433 : }
434 4737555 : return off;
435 : }
436 :
437 3259380 : std::vector< OUString > readAnnotations(
438 : bool annotated, rtl::Reference< MappedFile > const & file,
439 : sal_uInt32 offset, sal_uInt32 * newOffset = 0)
440 : {
441 3259380 : std::vector< OUString > ans;
442 3259380 : if (annotated) {
443 82497 : sal_uInt32 n = file->read32(offset);
444 82497 : offset += 4;
445 98196 : for (sal_uInt32 i = 0; i != n; ++i) {
446 15699 : ans.push_back(file->readIdxString(&offset));
447 : }
448 : }
449 3259380 : if (newOffset != 0) {
450 2491956 : *newOffset = offset;
451 : }
452 3259380 : return ans;
453 : }
454 :
455 123218 : ConstantValue readConstant(
456 : rtl::Reference< MappedFile > const & file, sal_uInt32 offset,
457 : sal_uInt32 * newOffset = 0, bool * annotated = 0)
458 : {
459 : assert(file.is());
460 123218 : int v = file->read8(offset);
461 123218 : int type = v & 0x7F;
462 123218 : if (annotated != 0) {
463 123218 : *annotated = (v & 0x80) != 0;
464 : }
465 123218 : switch (type) {
466 : case 0: // BOOLEAN
467 0 : v = file->read8(offset + 1);
468 0 : if (newOffset != 0) {
469 0 : *newOffset = offset + 2;
470 : }
471 0 : switch (v) {
472 : case 0:
473 0 : return ConstantValue(false);
474 : case 1:
475 0 : return ConstantValue(true);
476 : default:
477 : throw FileFormatException(
478 0 : file->uri,
479 : ("UNOIDL format: bad boolean constant value "
480 0 : + OUString::number(v)));
481 : }
482 : case 1: // BYTE
483 3207 : if (newOffset != 0) {
484 3207 : *newOffset = offset + 2;
485 : }
486 3207 : return ConstantValue(static_cast< sal_Int8 >(file->read8(offset + 1)));
487 : //TODO: implementation-defined behavior of conversion from sal_uInt8
488 : // to sal_Int8 relies on two's complement representation
489 : case 2: // SHORT
490 29070 : if (newOffset != 0) {
491 29070 : *newOffset = offset + 3;
492 : }
493 : return ConstantValue(
494 29070 : static_cast< sal_Int16 >(file->read16(offset + 1)));
495 : //TODO: implementation-defined behavior of conversion from
496 : // sal_uInt16 to sal_Int16 relies on two's complement representation
497 : case 3: // UNSIGNED SHORT
498 10 : if (newOffset != 0) {
499 10 : *newOffset = offset + 3;
500 : }
501 10 : return ConstantValue(file->read16(offset + 1));
502 : case 4: // LONG
503 90215 : if (newOffset != 0) {
504 90215 : *newOffset = offset + 5;
505 : }
506 : return ConstantValue(
507 90215 : static_cast< sal_Int32 >(file->read32(offset + 1)));
508 : //TODO: implementation-defined behavior of conversion from
509 : // sal_uInt32 to sal_Int32 relies on two's complement representation
510 : case 5: // UNSIGNED LONG
511 10 : if (newOffset != 0) {
512 10 : *newOffset = offset + 5;
513 : }
514 10 : return ConstantValue(file->read32(offset + 1));
515 : case 6: // HYPER
516 416 : if (newOffset != 0) {
517 416 : *newOffset = offset + 9;
518 : }
519 : return ConstantValue(
520 416 : static_cast< sal_Int64 >(file->read64(offset + 1)));
521 : //TODO: implementation-defined behavior of conversion from
522 : // sal_uInt64 to sal_Int64 relies on two's complement representation
523 : case 7: // UNSIGNED HYPER
524 10 : if (newOffset != 0) {
525 10 : *newOffset = offset + 9;
526 : }
527 10 : return ConstantValue(file->read64(offset + 1));
528 : case 8: // FLOAT
529 280 : if (newOffset != 0) {
530 280 : *newOffset = offset + 5;
531 : }
532 280 : return ConstantValue(file->readIso60599Binary32(offset + 1));
533 : case 9: // DOUBLE
534 0 : if (newOffset != 0) {
535 0 : *newOffset = offset + 9;
536 : }
537 0 : return ConstantValue(file->readIso60599Binary64(offset + 1));
538 : default:
539 : throw FileFormatException(
540 0 : file->uri,
541 0 : "UNOIDL format: bad constant type byte " + OUString::number(v));
542 : }
543 : }
544 :
545 : rtl::Reference< Entity > readEntity(
546 : rtl::Reference< MappedFile > const & file, sal_uInt32 offset);
547 :
548 : class UnoidlCursor: public MapCursor {
549 : public:
550 553 : UnoidlCursor(
551 : rtl::Reference< MappedFile > file, MapEntry const * mapBegin,
552 : sal_uInt32 mapSize):
553 553 : file_(file), mapIndex_(mapBegin), mapEnd_(mapBegin + mapSize)
554 553 : {}
555 :
556 : private:
557 1106 : virtual ~UnoidlCursor() throw () {}
558 :
559 : virtual rtl::Reference< Entity > getNext(OUString * name) SAL_OVERRIDE;
560 :
561 : rtl::Reference< MappedFile > file_;
562 : MapEntry const * mapIndex_;
563 : MapEntry const * mapEnd_;
564 : };
565 :
566 18671 : rtl::Reference< Entity > UnoidlCursor::getNext(OUString * name) {
567 : assert(name != 0);
568 18671 : rtl::Reference< Entity > ent;
569 18671 : if (mapIndex_ != mapEnd_) {
570 18118 : *name = file_->readNulName(mapIndex_->name.getUnsigned32());
571 18118 : ent = readEntity(file_, mapIndex_->data.getUnsigned32());
572 18118 : ++mapIndex_;
573 : }
574 18671 : return ent;
575 : }
576 :
577 : class UnoidlModuleEntity: public ModuleEntity {
578 : public:
579 2444 : UnoidlModuleEntity(
580 : rtl::Reference< MappedFile > const & file, sal_uInt32 mapOffset,
581 : sal_uInt32 mapSize):
582 : file_(file),
583 : mapBegin_(
584 : reinterpret_cast< MapEntry const * >(
585 2444 : static_cast< char const * >(file_->address) + mapOffset)),
586 4888 : mapSize_(mapSize)
587 2444 : { assert(file.is()); }
588 :
589 : private:
590 4888 : virtual ~UnoidlModuleEntity() throw () {}
591 :
592 : virtual std::vector< OUString > getMemberNames() const SAL_OVERRIDE;
593 :
594 522 : virtual rtl::Reference< MapCursor > createCursor() const SAL_OVERRIDE
595 522 : { return new UnoidlCursor(file_, mapBegin_, mapSize_); }
596 :
597 : rtl::Reference< MappedFile > file_;
598 : MapEntry const * mapBegin_;
599 : sal_uInt32 mapSize_;
600 : };
601 :
602 0 : std::vector< OUString > UnoidlModuleEntity::getMemberNames() const {
603 0 : std::vector< OUString > names;
604 0 : for (sal_uInt32 i = 0; i != mapSize_; ++i) {
605 0 : names.push_back(file_->readNulName(mapBegin_[i].name.getUnsigned32()));
606 : }
607 0 : return names;
608 : }
609 :
610 646650 : rtl::Reference< Entity > readEntity(
611 : rtl::Reference< MappedFile > const & file, sal_uInt32 offset)
612 : {
613 : assert(file.is());
614 646650 : int v = file->read8(offset);
615 646650 : int type = v & 0x3F;
616 646650 : bool published = (v & 0x80) != 0;
617 646650 : bool annotated = (v & 0x40) != 0;
618 646650 : bool flag = (v & 0x20) != 0;
619 646650 : switch (type) {
620 : case 0: // module
621 : {
622 2444 : if (v != 0) {
623 : throw FileFormatException(
624 0 : file->uri,
625 : ("UNOIDL format: bad module type byte "
626 0 : + OUString::number(v)));
627 : }
628 2444 : sal_uInt32 n = file->read32(offset + 1);
629 2444 : if (n > SAL_MAX_INT32) {
630 : throw FileFormatException(
631 0 : file->uri, "UNOIDL format: too many items in module");
632 : }
633 2444 : if (offset + 5 + 8 * n > file->size) { //TODO: overflow
634 : throw FileFormatException(
635 0 : file->uri,
636 0 : "UNOIDL format: module map offset + size too large");
637 : }
638 2444 : return new UnoidlModuleEntity(file, offset + 5, n);
639 : }
640 : case 1: // enum type
641 : {
642 13487 : sal_uInt32 n = file->read32(offset + 1);
643 13487 : if (n > SAL_MAX_INT32) {
644 : throw FileFormatException(
645 0 : file->uri, "UNOIDL format: too many members of enum type");
646 : }
647 13487 : offset += 5;
648 13487 : std::vector< EnumTypeEntity::Member > mems;
649 111445 : for (sal_uInt32 i = 0; i != n; ++i) {
650 97958 : OUString memName(file->readIdxName(&offset));
651 : sal_Int32 memValue = static_cast< sal_Int32 >(
652 97958 : file->read32(offset));
653 : //TODO: implementation-defined behavior of conversion from
654 : // sal_uInt32 to sal_Int32 relies on two's complement
655 : // representation
656 97958 : offset += 4;
657 : mems.push_back(
658 : EnumTypeEntity::Member(
659 : memName, memValue,
660 97958 : readAnnotations(annotated, file, offset, &offset)));
661 97958 : }
662 : return new EnumTypeEntity(
663 13487 : published, mems, readAnnotations(annotated, file, offset));
664 : }
665 : case 2: // plain struct type without base
666 : case 2 | 0x20: // plain struct type with base
667 : {
668 43527 : ++offset;
669 43527 : OUString base;
670 43527 : if (flag) {
671 7636 : base = file->readIdxName(&offset);
672 7636 : if (base.isEmpty()) {
673 : throw FileFormatException(
674 0 : file->uri,
675 : ("UNOIDL format: empty base type name of plain struct"
676 0 : " type"));
677 : }
678 : }
679 43527 : sal_uInt32 n = file->read32(offset);
680 43527 : if (n > SAL_MAX_INT32) {
681 : throw FileFormatException(
682 0 : file->uri,
683 : ("UNOIDL format: too many direct members of plain struct"
684 0 : " type"));
685 : }
686 43527 : offset += 4;
687 87054 : std::vector< PlainStructTypeEntity::Member > mems;
688 196731 : for (sal_uInt32 i = 0; i != n; ++i) {
689 153204 : OUString memName(file->readIdxName(&offset));
690 306408 : OUString memType(file->readIdxName(&offset));
691 : mems.push_back(
692 : PlainStructTypeEntity::Member(
693 : memName, memType,
694 153204 : readAnnotations(annotated, file, offset, &offset)));
695 153204 : }
696 : return new PlainStructTypeEntity(
697 : published, base, mems,
698 87054 : readAnnotations(annotated, file, offset));
699 : }
700 : case 3: // polymorphic struct type template
701 : {
702 1128 : sal_uInt32 n = file->read32(offset + 1);
703 1128 : if (n > SAL_MAX_INT32) {
704 : throw FileFormatException(
705 0 : file->uri,
706 : ("UNOIDL format: too many type parameters of polymorphic"
707 0 : " struct type template"));
708 : }
709 1128 : offset += 5;
710 1128 : std::vector< OUString > params;
711 2581 : for (sal_uInt32 i = 0; i != n; ++i) {
712 1453 : params.push_back(file->readIdxName(&offset));
713 : }
714 1128 : n = file->read32(offset);
715 1128 : if (n > SAL_MAX_INT32) {
716 : throw FileFormatException(
717 0 : file->uri,
718 : ("UNOIDL format: too many members of polymorphic struct"
719 0 : " type template"));
720 : }
721 1128 : offset += 4;
722 2256 : std::vector< PolymorphicStructTypeTemplateEntity::Member > mems;
723 3021 : for (sal_uInt32 i = 0; i != n; ++i) {
724 1893 : v = file->read8(offset);
725 1893 : ++offset;
726 1893 : OUString memName(file->readIdxName(&offset));
727 3786 : OUString memType(file->readIdxName(&offset));
728 1893 : if (v > 1) {
729 : throw FileFormatException(
730 0 : file->uri,
731 0 : ("UNOIDL format: bad flags " + OUString::number(v)
732 0 : + " for member " + memName
733 0 : + " of polymorphic struct type template"));
734 : }
735 : mems.push_back(
736 : PolymorphicStructTypeTemplateEntity::Member(
737 : memName, memType, v == 1,
738 1893 : readAnnotations(annotated, file, offset, &offset)));
739 1893 : }
740 : return new PolymorphicStructTypeTemplateEntity(
741 : published, params, mems,
742 2256 : readAnnotations(annotated, file, offset));
743 : }
744 : case 4: // exception type without base
745 : case 4 | 0x20: // exception type with base
746 : {
747 60480 : ++offset;
748 60480 : OUString base;
749 60480 : if (flag) {
750 53866 : base = file->readIdxName(&offset);
751 53866 : if (base.isEmpty()) {
752 : throw FileFormatException(
753 0 : file->uri,
754 : ("UNOIDL format: empty base type name of exception"
755 0 : " type"));
756 : }
757 : }
758 60480 : sal_uInt32 n = file->read32(offset);
759 60480 : if (n > SAL_MAX_INT32) {
760 : throw FileFormatException(
761 0 : file->uri,
762 0 : "UNOIDL format: too many direct members of exception type");
763 : }
764 60480 : offset += 4;
765 120960 : std::vector< ExceptionTypeEntity::Member > mems;
766 97793 : for (sal_uInt32 i = 0; i != n; ++i) {
767 37313 : OUString memName(file->readIdxName(&offset));
768 74626 : OUString memType(file->readIdxName(&offset));
769 : mems.push_back(
770 : ExceptionTypeEntity::Member(
771 : memName, memType,
772 37313 : readAnnotations(annotated, file, offset, &offset)));
773 37313 : }
774 : return new ExceptionTypeEntity(
775 : published, base, mems,
776 120960 : readAnnotations(annotated, file, offset));
777 : }
778 : case 5: // interface type
779 : {
780 492739 : sal_uInt32 n = file->read32(offset + 1);
781 492739 : if (n > SAL_MAX_INT32) {
782 : throw FileFormatException(
783 0 : file->uri,
784 : ("UNOIDL format: too many direct mandatory bases of"
785 0 : " interface type"));
786 : }
787 492739 : offset += 5;
788 492739 : std::vector< AnnotatedReference > mandBases;
789 801740 : for (sal_uInt32 i = 0; i != n; ++i) {
790 309001 : OUString base(file->readIdxName(&offset));
791 : mandBases.push_back(
792 : AnnotatedReference(
793 : base,
794 309001 : readAnnotations(annotated, file, offset, &offset)));
795 309001 : }
796 492739 : n = file->read32(offset);
797 492739 : if (n > SAL_MAX_INT32) {
798 : throw FileFormatException(
799 0 : file->uri,
800 : ("UNOIDL format: too many direct optional bases of"
801 0 : " interface type"));
802 : }
803 492739 : offset += 4;
804 985478 : std::vector< AnnotatedReference > optBases;
805 493410 : for (sal_uInt32 i = 0; i != n; ++i) {
806 671 : OUString base(file->readIdxName(&offset));
807 : optBases.push_back(
808 : AnnotatedReference(
809 : base,
810 671 : readAnnotations(annotated, file, offset, &offset)));
811 671 : }
812 492739 : sal_uInt32 nAttrs = file->read32(offset);
813 492739 : if (nAttrs > SAL_MAX_INT32) {
814 : throw FileFormatException(
815 0 : file->uri,
816 : ("UNOIDL format: too many direct attributes of interface"
817 0 : " type"));
818 : }
819 492739 : offset += 4;
820 985478 : std::vector< InterfaceTypeEntity::Attribute > attrs;
821 666516 : for (sal_uInt32 i = 0; i != nAttrs; ++i) {
822 173777 : v = file->read8(offset);
823 173777 : ++offset;
824 173777 : OUString attrName(file->readIdxName(&offset));
825 347554 : OUString attrType(file->readIdxName(&offset));
826 173777 : if (v > 0x03) {
827 : throw FileFormatException(
828 0 : file->uri,
829 : ("UNOIDL format: bad flags for direct attribute "
830 0 : + attrName + " of interface type"));
831 : }
832 347554 : std::vector< OUString > getExcs;
833 173777 : sal_uInt32 m = file->read32(offset);
834 173777 : if (m > SAL_MAX_INT32) {
835 : throw FileFormatException(
836 0 : file->uri,
837 : ("UNOIDL format: too many getter exceptions for direct"
838 0 : " attribute " + attrName + " of interface type"));
839 : }
840 173777 : offset += 4;
841 189380 : for (sal_uInt32 j = 0; j != m; ++j) {
842 15603 : getExcs.push_back(file->readIdxName(&offset));
843 : }
844 347554 : std::vector< OUString > setExcs;
845 173777 : if ((v & 0x02) == 0) {
846 122017 : m = file->read32(offset);
847 122017 : if (m > SAL_MAX_INT32) {
848 : throw FileFormatException(
849 0 : file->uri,
850 : ("UNOIDL format: too many setter exceptions for"
851 0 : " direct attribute " + attrName
852 0 : + " of interface type"));
853 : }
854 122017 : offset += 4;
855 145952 : for (sal_uInt32 j = 0; j != m; ++j) {
856 23935 : setExcs.push_back(file->readIdxName(&offset));
857 : }
858 : }
859 : attrs.push_back(
860 : InterfaceTypeEntity::Attribute(
861 347554 : attrName, attrType, (v & 0x01) != 0, (v & 0x02) != 0,
862 : getExcs, setExcs,
863 521331 : readAnnotations(annotated, file, offset, &offset)));
864 173777 : }
865 492739 : sal_uInt32 nMeths = file->read32(offset);
866 492739 : if (nMeths > SAL_MAX_INT32 - nAttrs) {
867 : throw FileFormatException(
868 0 : file->uri,
869 : ("UNOIDL format: too many direct attributes and methods of"
870 0 : " interface type"));
871 : }
872 492739 : offset += 4;
873 985478 : std::vector< InterfaceTypeEntity::Method > meths;
874 2146916 : for (sal_uInt32 i = 0; i != nMeths; ++i) {
875 1654177 : OUString methName(file->readIdxName(&offset));
876 3308354 : OUString methType(file->readIdxName(&offset));
877 1654177 : sal_uInt32 m = file->read32(offset);
878 1654177 : if (m > SAL_MAX_INT32) {
879 : throw FileFormatException(
880 0 : file->uri,
881 : ("UNOIDL format: too many parameters for method "
882 0 : + methName + " of interface type"));
883 : }
884 1654177 : offset += 4;
885 3308354 : std::vector< InterfaceTypeEntity::Method::Parameter > params;
886 2750477 : for (sal_uInt32 j = 0; j != m; ++j) {
887 1096300 : v = file->read8(offset);
888 1096300 : ++offset;
889 1096300 : OUString paramName(file->readIdxName(&offset));
890 2192600 : OUString paramType(file->readIdxName(&offset));
891 : InterfaceTypeEntity::Method::Parameter::Direction dir;
892 1096300 : switch (v) {
893 : case 0:
894 : dir = InterfaceTypeEntity::Method::Parameter::
895 1081106 : DIRECTION_IN;
896 1081106 : break;
897 : case 1:
898 : dir = InterfaceTypeEntity::Method::Parameter::
899 10903 : DIRECTION_OUT;
900 10903 : break;
901 : case 2:
902 : dir = InterfaceTypeEntity::Method::Parameter::
903 4291 : DIRECTION_IN_OUT;
904 4291 : break;
905 : default:
906 : throw FileFormatException(
907 0 : file->uri,
908 : ("UNOIDL format: bad direction "
909 0 : + OUString::number(v) + " of parameter "
910 0 : + paramName + " for method " + methName
911 0 : + " of interface type"));
912 : }
913 : params.push_back(
914 : InterfaceTypeEntity::Method::Parameter(
915 1096300 : paramName, paramType, dir));
916 1096300 : }
917 1654177 : std::vector< OUString > excs;
918 1654177 : m = file->read32(offset);
919 1654177 : if (m > SAL_MAX_INT32) {
920 : throw FileFormatException(
921 0 : file->uri,
922 : ("UNOIDL format: too many exceptions for method "
923 0 : + methName + " of interface type"));
924 : }
925 1654177 : offset += 4;
926 2283414 : for (sal_uInt32 j = 0; j != m; ++j) {
927 629237 : excs.push_back(file->readIdxName(&offset));
928 : }
929 : meths.push_back(
930 : InterfaceTypeEntity::Method(
931 : methName, methType, params, excs,
932 1654177 : readAnnotations(annotated, file, offset, &offset)));
933 3308354 : }
934 : return new InterfaceTypeEntity(
935 : published, mandBases, optBases, attrs, meths,
936 985478 : readAnnotations(annotated, file, offset));
937 : }
938 : case 6: // typedef
939 : {
940 3350 : ++offset;
941 3350 : OUString base(file->readIdxName(&offset));
942 : return new TypedefEntity(
943 3350 : published, base, readAnnotations(annotated, file, offset));
944 : }
945 : case 7: // constant group
946 : {
947 12414 : sal_uInt32 n = file->read32(offset + 1);
948 12414 : if (n > SAL_MAX_INT32) {
949 : throw FileFormatException(
950 0 : file->uri,
951 0 : "UNOIDL format: too many constants in constant group");
952 : }
953 12414 : if (offset + 5 + 8 * n > file->size) { //TODO: overflow
954 : throw FileFormatException(
955 0 : file->uri,
956 : ("UNOIDL format: constant group map offset + size too"
957 0 : " large"));
958 : }
959 : MapEntry const * p = reinterpret_cast< MapEntry const * >(
960 12414 : static_cast< char const * >(file->address) + offset + 5);
961 12414 : std::vector< ConstantGroupEntity::Member > mems;
962 135632 : for (sal_uInt32 i = 0; i != n; ++i) {
963 123218 : sal_uInt32 off = p[i].data.getUnsigned32();
964 : bool ann;
965 123218 : ConstantValue val(readConstant(file, off, &off, &ann));
966 : mems.push_back(
967 : ConstantGroupEntity::Member(
968 123218 : file->readNulName(p[i].name.getUnsigned32()), val,
969 246436 : readAnnotations(ann, file, off)));
970 : }
971 : return new ConstantGroupEntity(
972 : published, mems,
973 12414 : readAnnotations(annotated, file, offset + 5 + 8 * n));
974 : }
975 : case 8: // single-interface--based service without default constructor
976 : case 8 | 0x20: // single-interface--based service with default constructor
977 : {
978 5281 : ++offset;
979 5281 : OUString base(file->readIdxName(&offset));
980 10562 : std::vector< SingleInterfaceBasedServiceEntity::Constructor > ctors;
981 5281 : if (flag) {
982 : ctors.push_back(
983 3274 : SingleInterfaceBasedServiceEntity::Constructor());
984 : } else {
985 2007 : sal_uInt32 n = file->read32(offset);
986 2007 : if (n > SAL_MAX_INT32) {
987 : throw FileFormatException(
988 0 : file->uri,
989 : ("UNOIDL format: too many constructors of"
990 0 : " single-interface--based service"));
991 : }
992 2007 : offset += 4;
993 4376 : for (sal_uInt32 i = 0; i != n; ++i) {
994 2369 : OUString ctorName(file->readIdxName(&offset));
995 2369 : sal_uInt32 m = file->read32(offset);
996 2369 : if (m > SAL_MAX_INT32) {
997 : throw FileFormatException(
998 0 : file->uri,
999 : ("UNOIDL format: too many parameters for"
1000 0 : " constructor " + ctorName
1001 0 : + " of single-interface--based service"));
1002 : }
1003 2369 : offset += 4;
1004 : std::vector<
1005 : SingleInterfaceBasedServiceEntity::Constructor::
1006 4738 : Parameter > params;
1007 6343 : for (sal_uInt32 j = 0; j != m; ++j) {
1008 3974 : v = file->read8(offset);
1009 3974 : ++offset;
1010 3974 : OUString paramName(file->readIdxName(&offset));
1011 7948 : OUString paramType(file->readIdxName(&offset));
1012 : bool rest;
1013 3974 : switch (v) {
1014 : case 0:
1015 3963 : rest = false;
1016 3963 : break;
1017 : case 0x04:
1018 11 : rest = true;
1019 11 : break;
1020 : default:
1021 : throw FileFormatException(
1022 0 : file->uri,
1023 : ("UNOIDL format: bad mode "
1024 0 : + OUString::number(v) + " of parameter "
1025 0 : + paramName + " for constructor " + ctorName
1026 0 : + " of single-interface--based service"));
1027 : }
1028 : params.push_back(
1029 : SingleInterfaceBasedServiceEntity::Constructor::
1030 : Parameter(
1031 3974 : paramName, paramType, rest));
1032 3974 : }
1033 2369 : std::vector< OUString > excs;
1034 2369 : m = file->read32(offset);
1035 2369 : if (m > SAL_MAX_INT32) {
1036 : throw FileFormatException(
1037 0 : file->uri,
1038 : ("UNOIDL format: too many exceptions for"
1039 0 : " constructor " + ctorName
1040 0 : + " of single-interface--based service"));
1041 : }
1042 2369 : offset += 4;
1043 3103 : for (sal_uInt32 j = 0; j != m; ++j) {
1044 734 : excs.push_back(file->readIdxName(&offset));
1045 : }
1046 : ctors.push_back(
1047 : SingleInterfaceBasedServiceEntity::Constructor(
1048 : ctorName, params, excs,
1049 2369 : readAnnotations(annotated, file, offset, &offset)));
1050 4738 : }
1051 : }
1052 : return new SingleInterfaceBasedServiceEntity(
1053 : published, base, ctors,
1054 10562 : readAnnotations(annotated, file, offset));
1055 : }
1056 : case 9: // accumulation-based service
1057 : {
1058 10841 : sal_uInt32 n = file->read32(offset + 1);
1059 10841 : if (n > SAL_MAX_INT32) {
1060 : throw FileFormatException(
1061 0 : file->uri,
1062 : ("UNOIDL format: too many direct mandatory service bases of"
1063 0 : " accumulation-based service"));
1064 : }
1065 10841 : offset += 5;
1066 10841 : std::vector< AnnotatedReference > mandServs;
1067 18553 : for (sal_uInt32 i = 0; i != n; ++i) {
1068 7712 : OUString base(file->readIdxName(&offset));
1069 : mandServs.push_back(
1070 : AnnotatedReference(
1071 : base,
1072 7712 : readAnnotations(annotated, file, offset, &offset)));
1073 7712 : }
1074 10841 : n = file->read32(offset);
1075 10841 : if (n > SAL_MAX_INT32) {
1076 : throw FileFormatException(
1077 0 : file->uri,
1078 : ("UNOIDL format: too many direct optional service bases of"
1079 0 : " accumulation-based service"));
1080 : }
1081 10841 : offset += 4;
1082 21682 : std::vector< AnnotatedReference > optServs;
1083 11483 : for (sal_uInt32 i = 0; i != n; ++i) {
1084 642 : OUString base(file->readIdxName(&offset));
1085 : optServs.push_back(
1086 : AnnotatedReference(
1087 : base,
1088 642 : readAnnotations(annotated, file, offset, &offset)));
1089 642 : }
1090 10841 : n = file->read32(offset);
1091 10841 : if (n > SAL_MAX_INT32) {
1092 : throw FileFormatException(
1093 0 : file->uri,
1094 : ("UNOIDL format: too many direct mandatory interface bases"
1095 0 : " of accumulation-based service"));
1096 : }
1097 10841 : offset += 4;
1098 21682 : std::vector< AnnotatedReference > mandIfcs;
1099 27269 : for (sal_uInt32 i = 0; i != n; ++i) {
1100 16428 : OUString base(file->readIdxName(&offset));
1101 : mandIfcs.push_back(
1102 : AnnotatedReference(
1103 : base,
1104 16428 : readAnnotations(annotated, file, offset, &offset)));
1105 16428 : }
1106 10841 : n = file->read32(offset);
1107 10841 : if (n > SAL_MAX_INT32) {
1108 : throw FileFormatException(
1109 0 : file->uri,
1110 : ("UNOIDL format: too many direct optional interface bases"
1111 0 : " of accumulation-based service"));
1112 : }
1113 10841 : offset += 4;
1114 21682 : std::vector< AnnotatedReference > optIfcs;
1115 14025 : for (sal_uInt32 i = 0; i != n; ++i) {
1116 3184 : OUString base(file->readIdxName(&offset));
1117 : optIfcs.push_back(
1118 : AnnotatedReference(
1119 : base,
1120 3184 : readAnnotations(annotated, file, offset, &offset)));
1121 3184 : }
1122 10841 : n = file->read32(offset);
1123 10841 : if (n > SAL_MAX_INT32) {
1124 : throw FileFormatException(
1125 0 : file->uri,
1126 : ("UNOIDL format: too many direct properties of"
1127 0 : " accumulation-based service"));
1128 : }
1129 10841 : offset += 4;
1130 21682 : std::vector< AccumulationBasedServiceEntity::Property > props;
1131 44468 : for (sal_uInt32 i = 0; i != n; ++i) {
1132 33627 : sal_uInt16 attrs = file->read16(offset);
1133 33627 : offset += 2;
1134 33627 : OUString propName(file->readIdxName(&offset));
1135 67254 : OUString propType(file->readIdxName(&offset));
1136 33627 : if (attrs > 0x01FF) { // see css.beans.PropertyAttribute
1137 : throw FileFormatException(
1138 0 : file->uri,
1139 0 : ("UNOIDL format: bad mode " + OUString::number(v)
1140 0 : + " of property " + propName
1141 0 : + " for accumulation-based servcie"));
1142 : }
1143 : props.push_back(
1144 : AccumulationBasedServiceEntity::Property(
1145 : propName, propType,
1146 : static_cast<
1147 : AccumulationBasedServiceEntity::Property::
1148 : Attributes >(
1149 : attrs),
1150 33627 : readAnnotations(annotated, file, offset, &offset)));
1151 33627 : }
1152 : return new AccumulationBasedServiceEntity(
1153 : published, mandServs, optServs, mandIfcs, optIfcs, props,
1154 21682 : readAnnotations(annotated, file, offset));
1155 : }
1156 : case 10: // interface-based singleton
1157 : {
1158 956 : ++offset;
1159 956 : OUString base(file->readIdxName(&offset));
1160 : return new InterfaceBasedSingletonEntity(
1161 956 : published, base, readAnnotations(annotated, file, offset));
1162 : }
1163 : case 11: // service-based singleton
1164 : {
1165 3 : ++offset;
1166 3 : OUString base(file->readIdxName(&offset));
1167 : return new ServiceBasedSingletonEntity(
1168 3 : published, base, readAnnotations(annotated, file, offset));
1169 : }
1170 : default:
1171 : throw FileFormatException(
1172 0 : file->uri, "UNOIDL format: bad type byte " + OUString::number(v));
1173 : }
1174 : }
1175 :
1176 : }
1177 :
1178 745 : UnoidlProvider::UnoidlProvider(OUString const & uri): file_(new MappedFile(uri))
1179 : {
1180 745 : if (file_->size < 8 || std::memcmp(file_->address, "UNOIDL\xFF\0", 8) != 0)
1181 : {
1182 : throw FileFormatException(
1183 0 : file_->uri,
1184 : "UNOIDL format: does not begin with magic UNOIDL\\xFF and version"
1185 0 : " 0");
1186 : }
1187 745 : sal_uInt32 off = file_->read32(8);
1188 745 : mapSize_ = file_->read32(12);
1189 745 : if (off + 8 * mapSize_ > file_->size) { //TODO: overflow
1190 : throw FileFormatException(
1191 0 : file_->uri, "UNOIDL format: root map offset + size too large");
1192 : }
1193 : mapBegin_ = reinterpret_cast< MapEntry const * >(
1194 745 : static_cast< char const * >(file_->address) + off);
1195 745 : }
1196 :
1197 31 : rtl::Reference< MapCursor > UnoidlProvider::createRootCursor() const {
1198 31 : return new UnoidlCursor(file_, mapBegin_, mapSize_);
1199 : }
1200 :
1201 1223793 : rtl::Reference< Entity > UnoidlProvider::findEntity(OUString const & name) const
1202 : {
1203 1223793 : MapEntry const * mapBegin = mapBegin_;
1204 1223793 : sal_uInt32 mapSize = mapSize_;
1205 1223793 : bool cgroup = false;
1206 1223793 : for (sal_Int32 i = 0;;) {
1207 5332747 : sal_Int32 j = name.indexOf('.', i);
1208 5332747 : if (j == -1) {
1209 661117 : j = name.getLength();
1210 : }
1211 5332747 : sal_Int32 off = findInMap(file_, mapBegin, mapSize, name, i, j - i);
1212 5332747 : if (off == 0) {
1213 595192 : return rtl::Reference< Entity >();
1214 : }
1215 4737555 : if (j == name.getLength()) {
1216 628589 : return cgroup ? rtl::Reference< Entity >() : readEntity(file_, off);
1217 : }
1218 4108966 : if (cgroup) {
1219 0 : return rtl::Reference< Entity >();
1220 : //TODO: throw an exception instead here, where the segments of a
1221 : // constant's name are a prefix of the requested name's
1222 : // segments?
1223 : }
1224 4108966 : int v = file_->read8(off);
1225 4108966 : if (v != 0) { // module
1226 69 : if ((v & 0x3F) == 7) { // constant group
1227 57 : cgroup = true;
1228 : } else {
1229 12 : return rtl::Reference< Entity >();
1230 : //TODO: throw an exception instead here, where the segments
1231 : // of a non-module, non-constant-group entity's name are a
1232 : // prefix of the requested name's segments?
1233 : }
1234 : }
1235 4108954 : mapSize = file_->read32(off + 1);
1236 4108954 : if (8 * mapSize > file_->size - off - 5) { //TODO: overflow
1237 : throw FileFormatException(
1238 0 : file_->uri, "UNOIDL format: map offset + size too large");
1239 : }
1240 : mapBegin = reinterpret_cast< MapEntry const * >(
1241 4108954 : static_cast< char const * >(file_->address) + off + 5);
1242 4108954 : i = j + 1;
1243 4108954 : }
1244 : }
1245 :
1246 872 : UnoidlProvider::~UnoidlProvider() throw () {}
1247 :
1248 : } }
1249 :
1250 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|