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