LCOV - code coverage report
Current view: top level - unoidl/source - unoidlprovider.cxx (source / functions) Hit Total Coverage
Test: commit 10e77ab3ff6f4314137acd6e2702a6e5c1ce1fae Lines: 460 595 77.3 %
Date: 2014-11-03 Functions: 39 43 90.7 %
Legend: Lines: hit not hit

          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: */

Generated by: LCOV version 1.10