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