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 70950 : sal_uInt16 getUnsigned16() const {
39 70950 : return static_cast< sal_uInt16 >(byte[0])
40 70950 : | (static_cast< sal_uInt16 >(byte[1]) << 8);
41 : }
42 : };
43 :
44 : // sizeof (Memory32) == 4
45 : struct Memory32 {
46 : unsigned char byte[4];
47 :
48 71613966 : sal_uInt32 getUnsigned32() const {
49 71613966 : return static_cast< sal_uInt32 >(byte[0])
50 71613966 : | (static_cast< sal_uInt32 >(byte[1]) << 8)
51 71613966 : | (static_cast< sal_uInt32 >(byte[2]) << 16)
52 71613966 : | (static_cast< sal_uInt32 >(byte[3]) << 24);
53 : }
54 :
55 300 : 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 300 : sa.buf[0] = byte[0];
62 300 : sa.buf[1] = byte[1];
63 300 : sa.buf[2] = byte[2];
64 300 : 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 300 : return sa.f;
72 : }
73 : };
74 :
75 : // sizeof (Memory64) == 8
76 : struct Memory64 {
77 : unsigned char byte[8];
78 :
79 455 : sal_uInt64 getUnsigned64() const {
80 455 : return static_cast< sal_uInt64 >(byte[0])
81 455 : | (static_cast< sal_uInt64 >(byte[1]) << 8)
82 455 : | (static_cast< sal_uInt64 >(byte[2]) << 16)
83 455 : | (static_cast< sal_uInt64 >(byte[3]) << 24)
84 455 : | (static_cast< sal_uInt64 >(byte[4]) << 32)
85 455 : | (static_cast< sal_uInt64 >(byte[5]) << 40)
86 455 : | (static_cast< sal_uInt64 >(byte[6]) << 48)
87 455 : | (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 13385741 : OUString readIdxName(sal_uInt32 * offset) const
139 13385741 : { return readIdxString(offset, RTL_TEXTENCODING_ASCII_US); }
140 :
141 20470 : OUString readIdxString(sal_uInt32 * offset) const
142 20470 : { 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 1323 : MappedFile::MappedFile(OUString const & fileUrl): uri(fileUrl), handle(0) {
169 1323 : oslFileError e = osl_openFile(uri.pData, &handle, osl_File_OpenFlag_Read);
170 1323 : switch (e) {
171 : case osl_File_E_None:
172 1323 : 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 1323 : e = osl_getFileSize(handle, &size);
179 1323 : if (e == osl_File_E_None) {
180 : e = osl_mapFile(
181 1323 : handle, &address, size, 0, osl_File_MapFlag_RandomAccess);
182 : }
183 1323 : 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 1323 : }
191 :
192 10717905 : sal_uInt8 MappedFile::read8(sal_uInt32 offset) const {
193 : assert(size >= 8);
194 10717905 : if (offset > size - 1) {
195 : throw FileFormatException(
196 0 : uri, "UNOIDL format: offset for 8-bit value too large");
197 : }
198 10717905 : return get8(offset);
199 : }
200 :
201 70950 : sal_uInt16 MappedFile::read16(sal_uInt32 offset) const {
202 : assert(size >= 8);
203 70950 : if (offset > size - 2) {
204 : throw FileFormatException(
205 0 : uri, "UNOIDL format: offset for 16-bit value too large");
206 : }
207 70950 : return get16(offset);
208 : }
209 :
210 41365406 : sal_uInt32 MappedFile::read32(sal_uInt32 offset) const {
211 : assert(size >= 8);
212 41365406 : if (offset > size - 4) {
213 : throw FileFormatException(
214 0 : uri, "UNOIDL format: offset for 32-bit value too large");
215 : }
216 41365406 : return get32(offset);
217 : }
218 :
219 455 : sal_uInt64 MappedFile::read64(sal_uInt32 offset) const {
220 : assert(size >= 8);
221 455 : if (offset > size - 8) {
222 : throw FileFormatException(
223 0 : uri, "UNOIDL format: offset for 64-bit value too large");
224 : }
225 455 : return get64(offset);
226 : }
227 :
228 300 : float MappedFile::readIso60599Binary32(sal_uInt32 offset) const {
229 : assert(size >= 8);
230 300 : if (offset > size - 4) {
231 : throw FileFormatException(
232 0 : uri, "UNOIDL format: offset for 32-bit value too large");
233 : }
234 300 : 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 186026 : OUString MappedFile::readNulName(sal_uInt32 offset) const {
247 186026 : if (offset > size) {
248 : throw FileFormatException(
249 0 : uri, "UNOIDL format: offset for string too large");
250 : }
251 186026 : sal_uInt64 end = offset;
252 2937644 : for (;; ++end) {
253 3123670 : if (end == size) {
254 : throw FileFormatException(
255 0 : uri, "UNOIDL format: string misses trailing NUL");
256 : }
257 3123670 : if (static_cast< char const * >(address)[end] == 0) {
258 186026 : break;
259 : }
260 : }
261 186026 : if (end - offset > SAL_MAX_INT32) {
262 0 : throw FileFormatException(uri, "UNOIDL format: string too long");
263 : }
264 186026 : OUString name;
265 186026 : 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 186026 : | RTL_TEXTTOUNICODE_FLAGS_INVALID_ERROR)))
271 : {
272 0 : throw FileFormatException(uri, "UNOIDL format: name is not ASCII");
273 : }
274 3123670 : return name;
275 : }
276 :
277 3570 : MappedFile::~MappedFile() {
278 1190 : oslFileError e = osl_unmapMappedFile(handle, address, size);
279 : SAL_WARN_IF(e != osl_File_E_None, "unoidl", "cannot unmap: " << +e);
280 1190 : e = osl_closeFile(handle);
281 : SAL_WARN_IF(e != osl_File_E_None, "unoidl", "cannot close: " << +e);
282 2380 : }
283 :
284 10717905 : sal_uInt8 MappedFile::get8(sal_uInt32 offset) const {
285 : assert(size >= 8);
286 : assert(offset <= size - 1);
287 10717905 : return static_cast< char const * >(address)[offset];
288 : }
289 :
290 70950 : sal_uInt16 MappedFile::get16(sal_uInt32 offset) const {
291 : assert(size >= 8);
292 : assert(offset <= size - 2);
293 : return reinterpret_cast< Memory16 const * >(
294 70950 : static_cast< char const * >(address) + offset)->getUnsigned16();
295 : }
296 :
297 41365406 : sal_uInt32 MappedFile::get32(sal_uInt32 offset) const {
298 : assert(size >= 8);
299 : assert(offset <= size - 4);
300 : return reinterpret_cast< Memory32 const * >(
301 41365406 : static_cast< char const * >(address) + offset)->getUnsigned32();
302 : }
303 :
304 455 : sal_uInt64 MappedFile::get64(sal_uInt32 offset) const {
305 : assert(size >= 8);
306 : assert(offset <= size - 8);
307 : return reinterpret_cast< Memory64 const * >(
308 455 : static_cast< char const * >(address) + offset)->getUnsigned64();
309 : }
310 :
311 300 : float MappedFile::getIso60599Binary32(sal_uInt32 offset) const {
312 : assert(size >= 8);
313 : assert(offset <= size - 4);
314 : return reinterpret_cast< Memory32 const * >(
315 300 : 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 13406211 : OUString MappedFile::readIdxString(
326 : sal_uInt32 * offset, rtl_TextEncoding encoding) const
327 : {
328 : assert(offset != 0);
329 13406211 : sal_uInt32 len = read32(*offset);
330 : sal_uInt32 off;
331 13406211 : if ((len & 0x80000000) == 0) {
332 4074863 : off = *offset;
333 4074863 : *offset += 4 + len;
334 : } else {
335 9331348 : *offset += 4;
336 9331348 : off = len & ~0x80000000;
337 9331348 : len = read32(off);
338 9331348 : if ((len & 0x80000000) != 0) {
339 : throw FileFormatException(
340 0 : uri, "UNOIDL format: string length high bit set");
341 : }
342 : }
343 13406211 : 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 13406211 : OUString name;
348 13406211 : if (!rtl_convertStringToUString(
349 13406211 : &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 26812422 : | RTL_TEXTTOUNICODE_FLAGS_INVALID_ERROR)))
354 : {
355 : throw FileFormatException(
356 0 : uri, "UNOIDL format: string bytes do not match encoding");
357 : }
358 13406211 : 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 21565307 : 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 21565307 : sal_uInt32 off = entry->name.getUnsigned32();
378 21565307 : 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 21565307 : static_cast< sal_uInt64 >(nameLength), file->size - off);
385 71332481 : for (sal_uInt64 i = 0; i != min; ++i) {
386 62862430 : sal_Unicode c1 = name[nameOffset + i];
387 62862430 : sal_Unicode c2 = static_cast< unsigned char const * >(file->address)[
388 62862430 : off + i];
389 62862430 : if (c1 < c2) {
390 6134271 : return COMPARE_LESS;
391 56728159 : } else if (c1 > c2 || c2 == 0) {
392 : // ...the "|| c2 == 0" is for the odd case where name erroneously
393 : // contains NUL characters
394 6960985 : return COMPARE_GREATER;
395 : }
396 : }
397 8470051 : if (static_cast< sal_uInt64 >(nameLength) == min) {
398 8470051 : if (file->size - off == min) {
399 : throw FileFormatException(
400 0 : file->uri, "UNOIDL format: string misses trailing NUL");
401 : }
402 : return
403 8470051 : static_cast< unsigned char const * >(file->address)[off + min] == 0
404 8470051 : ? COMPARE_EQUAL : COMPARE_LESS;
405 : } else {
406 0 : return COMPARE_GREATER;
407 : }
408 : }
409 :
410 22626091 : 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 22626091 : if (mapSize == 0) {
416 1060784 : return 0;
417 : }
418 21565307 : sal_uInt32 n = mapSize / 2;
419 21565307 : MapEntry const * p = mapBegin + n;
420 21565307 : switch (compare(file, name, nameOffset, nameLength, p)) {
421 : case COMPARE_LESS:
422 6293121 : return findInMap(file, mapBegin, n, name, nameOffset, nameLength);
423 : case COMPARE_GREATER:
424 : return findInMap(
425 6960985 : file, p + 1, mapSize - n - 1, name, nameOffset, nameLength);
426 : default: // COMPARE_EQUAL
427 8311201 : break;
428 : }
429 8311201 : sal_uInt32 off = mapBegin[n].data.getUnsigned32();
430 8311201 : if (off == 0) {
431 : throw FileFormatException(
432 0 : file->uri, "UNOIDL format: map entry data offset is null");
433 : }
434 8311201 : return off;
435 : }
436 :
437 5821211 : std::vector< OUString > readAnnotations(
438 : bool annotated, rtl::Reference< MappedFile > const & file,
439 : sal_uInt32 offset, sal_uInt32 * newOffset = 0)
440 : {
441 5821211 : std::vector< OUString > ans;
442 5821211 : if (annotated) {
443 109314 : sal_uInt32 n = file->read32(offset);
444 109314 : offset += 4;
445 129784 : for (sal_uInt32 i = 0; i != n; ++i) {
446 20470 : ans.push_back(file->readIdxString(&offset));
447 : }
448 : }
449 5821211 : if (newOffset != 0) {
450 4495450 : *newOffset = offset;
451 : }
452 5821211 : return ans;
453 : }
454 :
455 161407 : 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 161407 : int v = file->read8(offset);
461 161407 : int type = v & 0x7F;
462 161407 : if (annotated != 0) {
463 161407 : *annotated = (v & 0x80) != 0;
464 : }
465 161407 : 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 3452 : if (newOffset != 0) {
484 3452 : *newOffset = offset + 2;
485 : }
486 3452 : 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 32040 : if (newOffset != 0) {
491 32040 : *newOffset = offset + 3;
492 : }
493 : return ConstantValue(
494 32040 : 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 125140 : if (newOffset != 0) {
504 125140 : *newOffset = offset + 5;
505 : }
506 : return ConstantValue(
507 125140 : 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 445 : if (newOffset != 0) {
517 445 : *newOffset = offset + 9;
518 : }
519 : return ConstantValue(
520 445 : 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 300 : if (newOffset != 0) {
530 300 : *newOffset = offset + 5;
531 : }
532 300 : 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 706 : UnoidlCursor(
551 : rtl::Reference< MappedFile > file, MapEntry const * mapBegin,
552 : sal_uInt32 mapSize):
553 706 : file_(file), mapIndex_(mapBegin), mapEnd_(mapBegin + mapSize)
554 706 : {}
555 :
556 : private:
557 1412 : 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 25325 : rtl::Reference< Entity > UnoidlCursor::getNext(OUString * name) {
567 : assert(name != 0);
568 25325 : rtl::Reference< Entity > ent;
569 25325 : if (mapIndex_ != mapEnd_) {
570 24619 : *name = file_->readNulName(mapIndex_->name.getUnsigned32());
571 24619 : ent = readEntity(file_, mapIndex_->data.getUnsigned32());
572 24619 : ++mapIndex_;
573 : }
574 25325 : return ent;
575 : }
576 :
577 : class UnoidlModuleEntity: public ModuleEntity {
578 : public:
579 2775 : 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 2775 : static_cast< char const * >(file_->address) + mapOffset)),
586 5550 : mapSize_(mapSize)
587 2775 : { assert(file.is()); }
588 :
589 : private:
590 5550 : virtual ~UnoidlModuleEntity() throw () {}
591 :
592 : virtual std::vector< OUString > getMemberNames() const SAL_OVERRIDE;
593 :
594 673 : virtual rtl::Reference< MapCursor > createCursor() const SAL_OVERRIDE
595 673 : { 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 1167129 : rtl::Reference< Entity > readEntity(
611 : rtl::Reference< MappedFile > const & file, sal_uInt32 offset)
612 : {
613 : assert(file.is());
614 1167129 : int v = file->read8(offset);
615 1167129 : int type = v & 0x3F;
616 1167129 : bool published = (v & 0x80) != 0;
617 1167129 : bool annotated = (v & 0x40) != 0;
618 1167129 : bool flag = (v & 0x20) != 0;
619 1167129 : switch (type) {
620 : case 0: // module
621 : {
622 2775 : if (v != 0) {
623 : throw FileFormatException(
624 0 : file->uri,
625 : ("UNOIDL format: bad module type byte "
626 0 : + OUString::number(v)));
627 : }
628 2775 : sal_uInt32 n = file->read32(offset + 1);
629 2775 : if (n > SAL_MAX_INT32) {
630 : throw FileFormatException(
631 0 : file->uri, "UNOIDL format: too many items in module");
632 : }
633 2775 : 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 2775 : return new UnoidlModuleEntity(file, offset + 5, n);
639 : }
640 : case 1: // enum type
641 : {
642 15725 : sal_uInt32 n = file->read32(offset + 1);
643 15725 : if (n > SAL_MAX_INT32) {
644 : throw FileFormatException(
645 0 : file->uri, "UNOIDL format: too many members of enum type");
646 : }
647 15725 : offset += 5;
648 15725 : std::vector< EnumTypeEntity::Member > mems;
649 135981 : for (sal_uInt32 i = 0; i != n; ++i) {
650 120256 : OUString memName(file->readIdxName(&offset));
651 : sal_Int32 memValue = static_cast< sal_Int32 >(
652 120256 : 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 120256 : offset += 4;
657 : mems.push_back(
658 : EnumTypeEntity::Member(
659 : memName, memValue,
660 120256 : readAnnotations(annotated, file, offset, &offset)));
661 120256 : }
662 : return new EnumTypeEntity(
663 15725 : 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 51281 : ++offset;
669 51281 : OUString base;
670 51281 : if (flag) {
671 8528 : base = file->readIdxName(&offset);
672 8528 : 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 51281 : sal_uInt32 n = file->read32(offset);
680 51281 : 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 51281 : offset += 4;
687 102562 : std::vector< PlainStructTypeEntity::Member > mems;
688 234285 : for (sal_uInt32 i = 0; i != n; ++i) {
689 183004 : OUString memName(file->readIdxName(&offset));
690 366008 : OUString memType(file->readIdxName(&offset));
691 : mems.push_back(
692 : PlainStructTypeEntity::Member(
693 : memName, memType,
694 183004 : readAnnotations(annotated, file, offset, &offset)));
695 183004 : }
696 : return new PlainStructTypeEntity(
697 : published, base, mems,
698 102562 : readAnnotations(annotated, file, offset));
699 : }
700 : case 3: // polymorphic struct type template
701 : {
702 1516 : sal_uInt32 n = file->read32(offset + 1);
703 1516 : 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 1516 : offset += 5;
710 1516 : std::vector< OUString > params;
711 3464 : for (sal_uInt32 i = 0; i != n; ++i) {
712 1948 : params.push_back(file->readIdxName(&offset));
713 : }
714 1516 : n = file->read32(offset);
715 1516 : 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 1516 : offset += 4;
722 3032 : std::vector< PolymorphicStructTypeTemplateEntity::Member > mems;
723 4096 : for (sal_uInt32 i = 0; i != n; ++i) {
724 2580 : v = file->read8(offset);
725 2580 : ++offset;
726 2580 : OUString memName(file->readIdxName(&offset));
727 5160 : OUString memType(file->readIdxName(&offset));
728 2580 : 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 2580 : readAnnotations(annotated, file, offset, &offset)));
739 2580 : }
740 : return new PolymorphicStructTypeTemplateEntity(
741 : published, params, mems,
742 3032 : readAnnotations(annotated, file, offset));
743 : }
744 : case 4: // exception type without base
745 : case 4 | 0x20: // exception type with base
746 : {
747 75565 : ++offset;
748 75565 : OUString base;
749 75565 : if (flag) {
750 67140 : base = file->readIdxName(&offset);
751 67140 : 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 75565 : sal_uInt32 n = file->read32(offset);
759 75565 : 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 75565 : offset += 4;
765 151130 : std::vector< ExceptionTypeEntity::Member > mems;
766 125904 : for (sal_uInt32 i = 0; i != n; ++i) {
767 50339 : OUString memName(file->readIdxName(&offset));
768 100678 : OUString memType(file->readIdxName(&offset));
769 : mems.push_back(
770 : ExceptionTypeEntity::Member(
771 : memName, memType,
772 50339 : readAnnotations(annotated, file, offset, &offset)));
773 50339 : }
774 : return new ExceptionTypeEntity(
775 : published, base, mems,
776 151130 : readAnnotations(annotated, file, offset));
777 : }
778 : case 5: // interface type
779 : {
780 979788 : sal_uInt32 n = file->read32(offset + 1);
781 979788 : 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 979788 : offset += 5;
788 979788 : std::vector< AnnotatedReference > mandBases;
789 1522267 : for (sal_uInt32 i = 0; i != n; ++i) {
790 542479 : OUString base(file->readIdxName(&offset));
791 : mandBases.push_back(
792 : AnnotatedReference(
793 : base,
794 542479 : readAnnotations(annotated, file, offset, &offset)));
795 542479 : }
796 979788 : n = file->read32(offset);
797 979788 : 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 979788 : offset += 4;
804 1959576 : std::vector< AnnotatedReference > optBases;
805 980558 : for (sal_uInt32 i = 0; i != n; ++i) {
806 770 : OUString base(file->readIdxName(&offset));
807 : optBases.push_back(
808 : AnnotatedReference(
809 : base,
810 770 : readAnnotations(annotated, file, offset, &offset)));
811 770 : }
812 979788 : sal_uInt32 nAttrs = file->read32(offset);
813 979788 : 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 979788 : offset += 4;
820 1959576 : std::vector< InterfaceTypeEntity::Attribute > attrs;
821 1291410 : for (sal_uInt32 i = 0; i != nAttrs; ++i) {
822 311622 : v = file->read8(offset);
823 311622 : ++offset;
824 311622 : OUString attrName(file->readIdxName(&offset));
825 623244 : OUString attrType(file->readIdxName(&offset));
826 311622 : 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 623244 : std::vector< OUString > getExcs;
833 311622 : sal_uInt32 m = file->read32(offset);
834 311622 : 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 311622 : offset += 4;
841 337149 : for (sal_uInt32 j = 0; j != m; ++j) {
842 25527 : getExcs.push_back(file->readIdxName(&offset));
843 : }
844 623244 : std::vector< OUString > setExcs;
845 311622 : if ((v & 0x02) == 0) {
846 215262 : m = file->read32(offset);
847 215262 : 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 215262 : offset += 4;
855 255750 : for (sal_uInt32 j = 0; j != m; ++j) {
856 40488 : setExcs.push_back(file->readIdxName(&offset));
857 : }
858 : }
859 : attrs.push_back(
860 : InterfaceTypeEntity::Attribute(
861 623244 : attrName, attrType, (v & 0x01) != 0, (v & 0x02) != 0,
862 : getExcs, setExcs,
863 934866 : readAnnotations(annotated, file, offset, &offset)));
864 311622 : }
865 979788 : sal_uInt32 nMeths = file->read32(offset);
866 979788 : 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 979788 : offset += 4;
873 1959576 : std::vector< InterfaceTypeEntity::Method > meths;
874 4190498 : for (sal_uInt32 i = 0; i != nMeths; ++i) {
875 3210710 : OUString methName(file->readIdxName(&offset));
876 6421420 : OUString methType(file->readIdxName(&offset));
877 3210710 : sal_uInt32 m = file->read32(offset);
878 3210710 : 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 3210710 : offset += 4;
885 6421420 : std::vector< InterfaceTypeEntity::Method::Parameter > params;
886 5109307 : for (sal_uInt32 j = 0; j != m; ++j) {
887 1898597 : v = file->read8(offset);
888 1898597 : ++offset;
889 1898597 : OUString paramName(file->readIdxName(&offset));
890 3797194 : OUString paramType(file->readIdxName(&offset));
891 : InterfaceTypeEntity::Method::Parameter::Direction dir;
892 1898597 : switch (v) {
893 : case 0:
894 : dir = InterfaceTypeEntity::Method::Parameter::
895 1876182 : DIRECTION_IN;
896 1876182 : break;
897 : case 1:
898 : dir = InterfaceTypeEntity::Method::Parameter::
899 15674 : DIRECTION_OUT;
900 15674 : break;
901 : case 2:
902 : dir = InterfaceTypeEntity::Method::Parameter::
903 6741 : DIRECTION_IN_OUT;
904 6741 : 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 1898597 : paramName, paramType, dir));
916 1898597 : }
917 3210710 : std::vector< OUString > excs;
918 3210710 : m = file->read32(offset);
919 3210710 : 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 3210710 : offset += 4;
926 4341168 : for (sal_uInt32 j = 0; j != m; ++j) {
927 1130458 : excs.push_back(file->readIdxName(&offset));
928 : }
929 : meths.push_back(
930 : InterfaceTypeEntity::Method(
931 : methName, methType, params, excs,
932 3210710 : readAnnotations(annotated, file, offset, &offset)));
933 6421420 : }
934 : return new InterfaceTypeEntity(
935 : published, mandBases, optBases, attrs, meths,
936 1959576 : readAnnotations(annotated, file, offset));
937 : }
938 : case 6: // typedef
939 : {
940 4651 : ++offset;
941 4651 : OUString base(file->readIdxName(&offset));
942 : return new TypedefEntity(
943 4651 : published, base, readAnnotations(annotated, file, offset));
944 : }
945 : case 7: // constant group
946 : {
947 16179 : sal_uInt32 n = file->read32(offset + 1);
948 16179 : if (n > SAL_MAX_INT32) {
949 : throw FileFormatException(
950 0 : file->uri,
951 0 : "UNOIDL format: too many constants in constant group");
952 : }
953 16179 : 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 16179 : static_cast< char const * >(file->address) + offset + 5);
961 16179 : std::vector< ConstantGroupEntity::Member > mems;
962 177586 : for (sal_uInt32 i = 0; i != n; ++i) {
963 161407 : sal_uInt32 off = p[i].data.getUnsigned32();
964 : bool ann;
965 161407 : ConstantValue val(readConstant(file, off, &off, &ann));
966 : mems.push_back(
967 : ConstantGroupEntity::Member(
968 161407 : file->readNulName(p[i].name.getUnsigned32()), val,
969 322814 : readAnnotations(ann, file, off)));
970 : }
971 : return new ConstantGroupEntity(
972 : published, mems,
973 16179 : 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 6243 : ++offset;
979 6243 : OUString base(file->readIdxName(&offset));
980 12486 : std::vector< SingleInterfaceBasedServiceEntity::Constructor > ctors;
981 6243 : if (flag) {
982 : ctors.push_back(
983 3934 : SingleInterfaceBasedServiceEntity::Constructor());
984 : } else {
985 2309 : sal_uInt32 n = file->read32(offset);
986 2309 : 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 2309 : offset += 4;
993 5072 : for (sal_uInt32 i = 0; i != n; ++i) {
994 2763 : OUString ctorName(file->readIdxName(&offset));
995 2763 : sal_uInt32 m = file->read32(offset);
996 2763 : 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 2763 : offset += 4;
1004 : std::vector<
1005 : SingleInterfaceBasedServiceEntity::Constructor::
1006 5526 : Parameter > params;
1007 7304 : for (sal_uInt32 j = 0; j != m; ++j) {
1008 4541 : v = file->read8(offset);
1009 4541 : ++offset;
1010 4541 : OUString paramName(file->readIdxName(&offset));
1011 9082 : OUString paramType(file->readIdxName(&offset));
1012 : bool rest;
1013 4541 : switch (v) {
1014 : case 0:
1015 4530 : rest = false;
1016 4530 : 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 4541 : paramName, paramType, rest));
1032 4541 : }
1033 2763 : std::vector< OUString > excs;
1034 2763 : m = file->read32(offset);
1035 2763 : 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 2763 : offset += 4;
1043 3650 : for (sal_uInt32 j = 0; j != m; ++j) {
1044 887 : excs.push_back(file->readIdxName(&offset));
1045 : }
1046 : ctors.push_back(
1047 : SingleInterfaceBasedServiceEntity::Constructor(
1048 : ctorName, params, excs,
1049 2763 : readAnnotations(annotated, file, offset, &offset)));
1050 5526 : }
1051 : }
1052 : return new SingleInterfaceBasedServiceEntity(
1053 : published, base, ctors,
1054 12486 : readAnnotations(annotated, file, offset));
1055 : }
1056 : case 9: // accumulation-based service
1057 : {
1058 12416 : sal_uInt32 n = file->read32(offset + 1);
1059 12416 : 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 12416 : offset += 5;
1066 12416 : std::vector< AnnotatedReference > mandServs;
1067 21298 : for (sal_uInt32 i = 0; i != n; ++i) {
1068 8882 : OUString base(file->readIdxName(&offset));
1069 : mandServs.push_back(
1070 : AnnotatedReference(
1071 : base,
1072 8882 : readAnnotations(annotated, file, offset, &offset)));
1073 8882 : }
1074 12416 : n = file->read32(offset);
1075 12416 : 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 12416 : offset += 4;
1082 24832 : std::vector< AnnotatedReference > optServs;
1083 13140 : for (sal_uInt32 i = 0; i != n; ++i) {
1084 724 : OUString base(file->readIdxName(&offset));
1085 : optServs.push_back(
1086 : AnnotatedReference(
1087 : base,
1088 724 : readAnnotations(annotated, file, offset, &offset)));
1089 724 : }
1090 12416 : n = file->read32(offset);
1091 12416 : 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 12416 : offset += 4;
1098 24832 : std::vector< AnnotatedReference > mandIfcs;
1099 31183 : for (sal_uInt32 i = 0; i != n; ++i) {
1100 18767 : OUString base(file->readIdxName(&offset));
1101 : mandIfcs.push_back(
1102 : AnnotatedReference(
1103 : base,
1104 18767 : readAnnotations(annotated, file, offset, &offset)));
1105 18767 : }
1106 12416 : n = file->read32(offset);
1107 12416 : 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 12416 : offset += 4;
1114 24832 : std::vector< AnnotatedReference > optIfcs;
1115 16070 : for (sal_uInt32 i = 0; i != n; ++i) {
1116 3654 : OUString base(file->readIdxName(&offset));
1117 : optIfcs.push_back(
1118 : AnnotatedReference(
1119 : base,
1120 3654 : readAnnotations(annotated, file, offset, &offset)));
1121 3654 : }
1122 12416 : n = file->read32(offset);
1123 12416 : 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 12416 : offset += 4;
1130 24832 : std::vector< AccumulationBasedServiceEntity::Property > props;
1131 51316 : for (sal_uInt32 i = 0; i != n; ++i) {
1132 38900 : sal_uInt16 attrs = file->read16(offset);
1133 38900 : offset += 2;
1134 38900 : OUString propName(file->readIdxName(&offset));
1135 77800 : OUString propType(file->readIdxName(&offset));
1136 38900 : 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 38900 : readAnnotations(annotated, file, offset, &offset)));
1151 38900 : }
1152 : return new AccumulationBasedServiceEntity(
1153 : published, mandServs, optServs, mandIfcs, optIfcs, props,
1154 24832 : readAnnotations(annotated, file, offset));
1155 : }
1156 : case 10: // interface-based singleton
1157 : {
1158 987 : ++offset;
1159 987 : OUString base(file->readIdxName(&offset));
1160 : return new InterfaceBasedSingletonEntity(
1161 987 : 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 1323 : UnoidlProvider::UnoidlProvider(OUString const & uri): file_(new MappedFile(uri))
1179 : {
1180 1323 : 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 1323 : sal_uInt32 off = file_->read32(8);
1188 1323 : mapSize_ = file_->read32(12);
1189 1323 : 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 1323 : static_cast< char const * >(file_->address) + off);
1195 1323 : }
1196 :
1197 33 : rtl::Reference< MapCursor > UnoidlProvider::createRootCursor() const {
1198 33 : return new UnoidlCursor(file_, mapBegin_, mapSize_);
1199 : }
1200 :
1201 2203432 : rtl::Reference< Entity > UnoidlProvider::findEntity(OUString const & name) const
1202 : {
1203 2203432 : MapEntry const * mapBegin = mapBegin_;
1204 2203432 : sal_uInt32 mapSize = mapSize_;
1205 2203432 : bool cgroup = false;
1206 2203432 : for (sal_Int32 i = 0;;) {
1207 9371985 : sal_Int32 j = name.indexOf('.', i);
1208 9371985 : if (j == -1) {
1209 1184599 : j = name.getLength();
1210 : }
1211 9371985 : sal_Int32 off = findInMap(file_, mapBegin, mapSize, name, i, j - i);
1212 9371985 : if (off == 0) {
1213 1060784 : return rtl::Reference< Entity >();
1214 : }
1215 8311201 : if (j == name.getLength()) {
1216 1142624 : return cgroup ? rtl::Reference< Entity >() : readEntity(file_, off);
1217 : }
1218 7168577 : 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 7168577 : int v = file_->read8(off);
1225 7168577 : if (v != 0) { // module
1226 138 : if ((v & 0x3F) == 7) { // constant group
1227 114 : cgroup = true;
1228 : } else {
1229 24 : 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 7168553 : mapSize = file_->read32(off + 1);
1236 7168553 : 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 7168553 : static_cast< char const * >(file_->address) + off + 5);
1242 7168553 : i = j + 1;
1243 7168553 : }
1244 : }
1245 :
1246 2380 : UnoidlProvider::~UnoidlProvider() throw () {}
1247 :
1248 : } }
1249 :
1250 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|