LCOV - code coverage report
Current view: top level - usr/local/src/libreoffice/unoidl/source - unoidlprovider.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 470 605 77.7 %
Date: 2013-07-09 Functions: 41 46 89.1 %
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             : #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: */

Generated by: LCOV version 1.10