LCOV - code coverage report
Current view: top level - unoidl/source - unoidl-write.cxx (source / functions) Hit Total Coverage
Test: commit 10e77ab3ff6f4314137acd6e2702a6e5c1ce1fae Lines: 556 650 85.5 %
Date: 2014-11-03 Functions: 29 30 96.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 <cassert>
      13             : #include <cstddef>
      14             : #include <cstdlib>
      15             : #include <iostream>
      16             : #include <map>
      17             : #include <utility>
      18             : #include <vector>
      19             : 
      20             : #include "config_version.h"
      21             : #include "osl/endian.h"
      22             : #include "osl/file.h"
      23             : #include "osl/file.hxx"
      24             : #include "osl/process.h"
      25             : #include "rtl/process.h"
      26             : #include "rtl/string.h"
      27             : #include "rtl/string.hxx"
      28             : #include "rtl/textenc.h"
      29             : #include "rtl/textcvt.h"
      30             : #include "rtl/ustring.hxx"
      31             : #include "sal/macros.h"
      32             : #include "sal/main.h"
      33             : #include "unoidl/unoidl.hxx"
      34             : 
      35             : namespace {
      36             : 
      37           0 : void badUsage() {
      38             :     std::cerr
      39           0 :         << "Usage:" << std::endl << std::endl
      40           0 :         << "  unoidl-write [<registries>] [@<entities file>] <unoidl file>"
      41           0 :         << std::endl << std::endl
      42             :         << ("where each <registry> is either a new- or legacy-format .rdb file,"
      43           0 :             " a single .idl")
      44           0 :         << std::endl
      45             :         << ("file, or a root directory of an .idl file tree; and the UTF-8"
      46           0 :             " encoded <entities")
      47           0 :         << std::endl
      48             :         << ("file> contains zero or more space-separated names of (non-module)"
      49           0 :             " entities to")
      50           0 :         << std::endl
      51             :         << ("include in the output, and, if omitted, defaults to the complete"
      52           0 :             " content of the")
      53           0 :         << std::endl << "last <registry>, if any." << std::endl;
      54           0 :     std::exit(EXIT_FAILURE);
      55             : }
      56             : 
      57        1640 : OUString getArgumentUri(sal_uInt32 argument, bool * entities) {
      58        1640 :     OUString arg;
      59        1640 :     rtl_getAppCommandArg(argument, &arg.pData);
      60        1640 :     if (arg.startsWith("@", &arg)) {
      61           5 :         if (entities == 0) {
      62           0 :             badUsage();
      63             :         }
      64           5 :         *entities = true;
      65        1635 :     } else if (entities != 0) {
      66         663 :         *entities = false;
      67             :     }
      68        3280 :     OUString url;
      69        1640 :     osl::FileBase::RC e1 = osl::FileBase::getFileURLFromSystemPath(arg, url);
      70        1640 :     if (e1 != osl::FileBase::E_None) {
      71             :         std::cerr
      72           0 :             << "Cannot convert \"" << arg << "\" to file URL, error code "
      73           0 :             << +e1 << std::endl;
      74           0 :         std::exit(EXIT_FAILURE);
      75             :     }
      76        3280 :     OUString cwd;
      77        1640 :     oslProcessError e2 = osl_getProcessWorkingDir(&cwd.pData);
      78        1640 :     if (e2 != osl_Process_E_None) {
      79             :         std::cerr
      80           0 :             << "Cannot obtain working directory, error code " << +e2
      81           0 :             << std::endl;
      82           0 :         std::exit(EXIT_FAILURE);
      83             :     }
      84        1640 :     OUString abs;
      85        1640 :     e1 = osl::FileBase::getAbsoluteFileURL(cwd, url, abs);
      86        1640 :     if (e1 != osl::FileBase::E_None) {
      87             :         std::cerr
      88           0 :             << "Cannot make \"" << url
      89           0 :             << "\" into an absolute file URL, error code " << +e1 << std::endl;
      90           0 :         std::exit(EXIT_FAILURE);
      91             :     }
      92        3280 :     return abs;
      93             : }
      94             : 
      95       53971 : sal_uInt64 getOffset(osl::File & file) {
      96             :     sal_uInt64 off;
      97       53971 :     osl::FileBase::RC e = file.getPos(off);
      98       53971 :     if (e != osl::FileBase::E_None) {
      99             :         std::cerr
     100           0 :             << "Cannot determine current position in <" << file.getURL()
     101           0 :             << ">, error code " << +e << std::endl;
     102           0 :         std::exit(EXIT_FAILURE);
     103             :     }
     104       53971 :     return off;
     105             : }
     106             : 
     107      203784 : void write(osl::File & file, void const * buffer, sal_uInt64 size) {
     108             :     sal_uInt64 n;
     109      203784 :     osl::FileBase::RC e = file.write(buffer, size, n);
     110      203784 :     if (e != osl::FileBase::E_None) {
     111             :         std::cerr
     112           0 :             << "Cannot write to <" << file.getURL() << ">, error code " << +e
     113           0 :             << std::endl;
     114           0 :         std::exit(EXIT_FAILURE);
     115             :     }
     116      203784 :     if (n != size) {
     117             :         std::cerr
     118           0 :             << "Bad write of " << n << " instead of " << size << " bytes to <"
     119           0 :             << file.getURL() << '>' << std::endl;
     120           0 :         std::exit(EXIT_FAILURE);
     121             :     }
     122      203784 : }
     123             : 
     124       27810 : void write8(osl::File & file, sal_uInt64 value) {
     125       27810 :     if (value > 0xFF) {
     126             :         std::cerr
     127           0 :             << "Cannot write value >= 2^8; input is too large" << std::endl;
     128           0 :         std::exit(EXIT_FAILURE);
     129             :     }
     130             :     unsigned char buf[1];
     131       27810 :     buf[0] = value & 0xFF;
     132       27810 :     write(file, buf, SAL_N_ELEMENTS(buf));
     133       27810 : }
     134             : 
     135        5233 : void write16(osl::File & file, sal_uInt64 value) {
     136        5233 :     if (value > 0xFFFF) {
     137             :         std::cerr
     138           0 :             << "Cannot write value >= 2^16; input is too large" << std::endl;
     139           0 :         std::exit(EXIT_FAILURE);
     140             :     }
     141             :     unsigned char buf[2];
     142        5233 :     buf[0] = value & 0xFF;
     143        5233 :     buf[1] = (value >> 8) & 0xFF;
     144        5233 :     write(file, buf, SAL_N_ELEMENTS(buf));
     145        5233 : }
     146             : 
     147      135311 : void write32(osl::File & file, sal_uInt64 value) {
     148      135311 :     if (value > 0xFFFFFFFF) {
     149             :         std::cerr
     150           0 :             << "Cannot write value >= 2^32; input is too large" << std::endl;
     151           0 :         std::exit(EXIT_FAILURE);
     152             :     }
     153             :     unsigned char buf[4];
     154      135311 :     buf[0] = value & 0xFF;
     155      135311 :     buf[1] = (value >> 8) & 0xFF;
     156      135311 :     buf[2] = (value >> 16) & 0xFF;
     157      135311 :     buf[3] = (value >> 24) & 0xFF;
     158      135311 :     write(file, buf, SAL_N_ELEMENTS(buf));
     159      135311 : }
     160             : 
     161          59 : void write64(osl::File & file, sal_uInt64 value) {
     162             :     unsigned char buf[8];
     163          59 :     buf[0] = value & 0xFF;
     164          59 :     buf[1] = (value >> 8) & 0xFF;
     165          59 :     buf[2] = (value >> 16) & 0xFF;
     166          59 :     buf[3] = (value >> 24) & 0xFF;
     167          59 :     buf[4] = (value >> 32) & 0xFF;
     168          59 :     buf[5] = (value >> 40) & 0xFF;
     169          59 :     buf[6] = (value >> 48) & 0xFF;
     170          59 :     buf[7] = (value >> 56) & 0xFF;
     171          59 :     write(file, buf, SAL_N_ELEMENTS(buf));
     172          59 : }
     173             : 
     174          22 : void writeIso60599Binary32(osl::File & file, float value) {
     175             :     union {
     176             :         unsigned char buf[4];
     177             :         float f; // assuming float is ISO 60599 binary32
     178             :     } sa;
     179          22 :     sa.f = value;
     180             : #if defined OSL_BIGENDIAN
     181             :     std::swap(sa.buf[0], sa.buf[3]);
     182             :     std::swap(sa.buf[1], sa.buf[2]);
     183             : #endif
     184          22 :     write(file, sa.buf, SAL_N_ELEMENTS(sa.buf));
     185          22 : }
     186             : 
     187           2 : void writeIso60599Binary64(osl::File & file, double value) {
     188             :     union {
     189             :         unsigned char buf[8];
     190             :         float d; // assuming double is ISO 60599 binary64
     191             :     } sa;
     192           2 :     sa.d = value;
     193             : #if defined OSL_BIGENDIAN
     194             :     std::swap(sa.buf[0], sa.buf[7]);
     195             :     std::swap(sa.buf[1], sa.buf[6]);
     196             :     std::swap(sa.buf[2], sa.buf[5]);
     197             :     std::swap(sa.buf[3], sa.buf[4]);
     198             : #endif
     199           2 :     write(file, sa.buf, SAL_N_ELEMENTS(sa.buf));
     200           2 : }
     201             : 
     202       70333 : OString toAscii(OUString const & name) {
     203       70333 :     OString ascii;
     204       70333 :     if (!name.convertToString(
     205             :             &ascii, RTL_TEXTENCODING_ASCII_US,
     206             :             (RTL_UNICODETOTEXT_FLAGS_UNDEFINED_ERROR
     207       70333 :              | RTL_UNICODETOTEXT_FLAGS_INVALID_ERROR)))
     208             :     {
     209             :         std::cerr
     210           0 :             << "Cannot convert \"" << name << "\" to US ASCII" << std::endl;
     211           0 :         std::exit(EXIT_FAILURE);
     212             :     }
     213       70333 :     return ascii;
     214             : }
     215             : 
     216         281 : OString toUtf8(OUString const & string) {
     217         281 :     OString ascii;
     218         281 :     if (!string.convertToString(
     219             :             &ascii, RTL_TEXTENCODING_UTF8,
     220             :             (RTL_UNICODETOTEXT_FLAGS_UNDEFINED_ERROR
     221         281 :              | RTL_UNICODETOTEXT_FLAGS_INVALID_ERROR)))
     222             :     {
     223             :         std::cerr
     224           0 :             << "Cannot convert \"" << string << "\" to UTF-8" << std::endl;
     225           0 :         std::exit(EXIT_FAILURE);
     226             :     }
     227         281 :     return ascii;
     228             : }
     229             : 
     230       18624 : sal_uInt64 writeNulName(osl::File & file, OUString const & name) {
     231       18624 :     OString ascii(toAscii(name));
     232       18624 :     if (ascii.indexOf('\0') != -1) {
     233             :         std::cerr
     234           0 :             << "Name \"" << ascii << "\" contains NUL characters" << std::endl;
     235           0 :         std::exit(EXIT_FAILURE);
     236             :     }
     237       18624 :     sal_uInt64 off = getOffset(file);
     238       18624 :     write(file, ascii.getStr(), ascii.getLength() + 1);
     239       18624 :     return off;
     240             : }
     241             : 
     242       51990 : void writeIdxString(osl::File & file, OString const & string) {
     243       51990 :     static std::map< OString, sal_uInt64 > reuse;
     244       51990 :     std::map< OString, sal_uInt64 >::iterator i(reuse.find(string));
     245       51990 :     if (i == reuse.end()) {
     246       16127 :         reuse.insert(std::make_pair(string, getOffset(file)));
     247             :         assert(
     248             :             (static_cast< sal_uInt64 >(string.getLength()) & 0x80000000) == 0);
     249       16127 :         write32(file, static_cast< sal_uInt64 >(string.getLength()));
     250       16127 :         write(file, string.getStr(), string.getLength());
     251             :     } else {
     252       35863 :         if ((i->second & 0x80000000) != 0) {
     253             :             std::cerr
     254           0 :                 << "Cannot write index 0x" << std::hex << i->second << std::dec
     255           0 :                 << " of \"" << string << "\"; input is too large" << std::endl;
     256           0 :             std::exit(EXIT_FAILURE);
     257             :         }
     258       35863 :         write32(file, i->second | 0x80000000);
     259             :     }
     260       51990 : }
     261             : 
     262       51709 : void writeIdxName(osl::File & file, OUString const & name) {
     263       51709 :     writeIdxString(file, toAscii(name));
     264       51709 : }
     265             : 
     266       37690 : void writeAnnotations(
     267             :     osl::File & file, bool annotate,
     268             :     std::vector< OUString > const & annotations)
     269             : {
     270             :     assert(annotate || annotations.empty());
     271       37690 :     if (annotate) {
     272        1392 :         write32(file, annotations.size());
     273             :             // overflow from std::vector::size_type -> sal_uInt64 is unrealistic
     274        5019 :         for (std::vector< OUString >::const_iterator i(annotations.begin());
     275        3346 :              i != annotations.end(); ++i)
     276             :         {
     277         281 :             writeIdxString(file, toUtf8(*i));
     278             :         }
     279             :     }
     280       37690 : }
     281             : 
     282        6347 : void writeKind(
     283             :     osl::File & file,
     284             :     rtl::Reference< unoidl::PublishableEntity > const & entity,
     285             :     bool annotated, bool flag = false)
     286             : {
     287             :     assert(entity.is());
     288        6347 :     sal_uInt64 v = entity->getSort();
     289        6347 :     if (entity->isPublished()) {
     290        2874 :         v |= 0x80;
     291             :     }
     292        6347 :     if (annotated) {
     293         228 :         v |= 0x40;
     294             :     }
     295        6347 :     if (flag) {
     296         608 :         v |= 0x20;
     297             :     }
     298        6347 :     write8(file, v);
     299        6347 : }
     300             : 
     301       33380 : struct Item {
     302        6676 :     explicit Item(rtl::Reference< unoidl::Entity > const & theEntity):
     303        6676 :         entity(theEntity), nameOffset(0), dataOffset(0)
     304        6676 :     {}
     305             : 
     306             :     rtl::Reference< unoidl::Entity > entity;
     307             :     std::map< OUString, Item > module;
     308             :     sal_uInt64 nameOffset;
     309             :     sal_uInt64 dataOffset;
     310             : };
     311             : 
     312       59740 : struct ConstItem {
     313       11948 :     ConstItem(
     314             :         unoidl::ConstantValue const & theConstant,
     315             :         std::vector< OUString > const & theAnnotations):
     316             :         constant(theConstant), annotations(theAnnotations), nameOffset(0),
     317       11948 :         dataOffset(0)
     318       11948 :     {}
     319             : 
     320             :     unoidl::ConstantValue constant;
     321             :     std::vector< OUString > annotations;
     322             :     sal_uInt64 nameOffset;
     323             :     sal_uInt64 dataOffset;
     324             : };
     325             : 
     326           5 : void mapEntities(
     327             :     rtl::Reference< unoidl::Manager > const & manager, OUString const & uri,
     328             :     std::map< OUString, Item > & map)
     329             : {
     330             :     assert(manager.is());
     331           5 :     osl::File f(uri);
     332           5 :     osl::FileBase::RC e = f.open(osl_File_OpenFlag_Read);
     333           5 :     if (e != osl::FileBase::E_None) {
     334             :         std::cerr
     335           0 :             << "Cannot open <" << f.getURL() << "> for reading, error code "
     336           0 :             << +e << std::endl;
     337           0 :         std::exit(EXIT_FAILURE);
     338             :     }
     339             :     for (;;) {
     340             :         sal_Bool eof;
     341          10 :         e = f.isEndOfFile(&eof);
     342          10 :         if (e != osl::FileBase::E_None) {
     343             :             std::cerr
     344           0 :                 << "Cannot check <" << f.getURL() << "> for EOF, error code "
     345           0 :                 << +e << std::endl;
     346           0 :             std::exit(EXIT_FAILURE);
     347             :         }
     348          10 :         if (eof) {
     349           5 :             break;
     350             :         }
     351           5 :         rtl::ByteSequence s1;
     352           5 :         e = f.readLine(s1);
     353           5 :         if (e != osl::FileBase::E_None) {
     354             :             std::cerr
     355           0 :                 << "Cannot read from <" << f.getURL() << ">, error code "
     356           0 :                 << +e << std::endl;
     357           0 :             std::exit(EXIT_FAILURE);
     358             :         }
     359          10 :         OUString s2;
     360           5 :         if (!rtl_convertStringToUString(
     361           5 :                 &s2.pData, reinterpret_cast< char const * >(s1.getConstArray()),
     362             :                 s1.getLength(), RTL_TEXTENCODING_UTF8,
     363             :                 (RTL_TEXTTOUNICODE_FLAGS_UNDEFINED_ERROR
     364             :                  | RTL_TEXTTOUNICODE_FLAGS_MBUNDEFINED_ERROR
     365          10 :                  | RTL_TEXTTOUNICODE_FLAGS_INVALID_ERROR)))
     366             :         {
     367             :             std::cerr
     368           0 :                 << "Cannot interpret line read from <" << f.getURL()
     369           0 :                 << "> as UTF-8" << std::endl;
     370           0 :             std::exit(EXIT_FAILURE);
     371             :         }
     372        5330 :         for (sal_Int32 i = 0; i != -1;) {
     373        5320 :             OUString t(s2.getToken(0, ' ', i));
     374        5320 :             if (!t.isEmpty()) {
     375        5315 :                 rtl::Reference< unoidl::Entity > ent(manager->findEntity(t));
     376        5315 :                 if (!ent.is()) {
     377             :                     std::cerr
     378           0 :                         << "Unknown entity \"" << t << "\" read from <"
     379           0 :                         << f.getURL() << ">" << std::endl;
     380           0 :                     std::exit(EXIT_FAILURE);
     381             :                 }
     382        5315 :                 if (ent->getSort() == unoidl::Entity::SORT_MODULE) {
     383             :                     std::cerr
     384           0 :                         << "Module entity \"" << t << "\" read from <"
     385           0 :                         << f.getURL() << ">" << std::endl;
     386           0 :                     std::exit(EXIT_FAILURE);
     387             :                 }
     388        5315 :                 std::map< OUString, Item > * map2 = &map;
     389        5315 :                 for (sal_Int32 j = 0;;) {
     390       26228 :                     OUString id(t.getToken(0, '.', j));
     391       26228 :                     if (j == -1) {
     392        5315 :                         map2->insert(std::make_pair(id, Item(ent)));
     393        5315 :                         break;
     394             :                     }
     395       20913 :                     std::map< OUString, Item >::iterator k(map2->find(id));
     396       20913 :                     if (k == map2->end()) {
     397             :                         rtl::Reference< unoidl::Entity > ent2(
     398         149 :                             manager->findEntity(t.copy(0, j - 1)));
     399             :                         assert(ent2.is());
     400         149 :                         k = map2->insert(std::make_pair(id, Item(ent2))).first;
     401             :                     }
     402             :                     assert(
     403             :                         k->second.entity->getSort()
     404             :                         == unoidl::Entity::SORT_MODULE);
     405       20913 :                     map2 = &k->second.module;
     406       20913 :                 }
     407             :             }
     408        5320 :         }
     409           5 :     }
     410          10 :     e = f.close();
     411           5 :     if (e != osl::FileBase::E_None) {
     412             :         std::cerr
     413           0 :             << "Cannot close <" << f.getURL() << "> after reading, error code "
     414           0 :             << +e << std::endl;
     415           0 :         std::exit(EXIT_FAILURE);
     416           5 :     }
     417           5 : }
     418             : 
     419         473 : void mapCursor(
     420             :     rtl::Reference< unoidl::MapCursor > const & cursor,
     421             :     std::map< OUString, Item > & map)
     422             : {
     423         473 :     if (cursor.is()) {
     424             :         for (;;) {
     425        1685 :             OUString name;
     426        2897 :             rtl::Reference< unoidl::Entity > ent(cursor->getNext(&name));
     427        1685 :             if (!ent.is()) {
     428         473 :                 break;
     429             :             }
     430             :             std::pair< std::map< OUString, Item >::iterator, bool > i(
     431        1212 :                 map.insert(std::make_pair(name, Item(ent))));
     432        1212 :             if (!i.second) {
     433           0 :                 std::cout << "Duplicate name \"" << name << '"' << std::endl;
     434           0 :                 std::exit(EXIT_FAILURE);
     435             :             }
     436        1212 :             if (i.first->second.entity->getSort()
     437             :                 == unoidl::Entity::SORT_MODULE)
     438             :             {
     439             :                 mapCursor(
     440             :                     rtl::Reference< unoidl::ModuleEntity >(
     441             :                         static_cast< unoidl::ModuleEntity * >(
     442         360 :                             i.first->second.entity.get()))->createCursor(),
     443         360 :                     i.first->second.module);
     444             :             }
     445        1212 :         }
     446             :     }
     447         473 : }
     448             : 
     449         627 : sal_uInt64 writeMap(
     450             :     osl::File & file, std::map< OUString, Item > & map, std::size_t * rootSize)
     451             : {
     452        7303 :     for (std::map< OUString, Item >::iterator i(map.begin()); i != map.end();
     453             :          ++i)
     454             :     {
     455        6676 :         switch (i->second.entity->getSort()) {
     456             :         case unoidl::Entity::SORT_MODULE:
     457         329 :             i->second.dataOffset = writeMap(file, i->second.module, 0);
     458         329 :             break;
     459             :         case unoidl::Entity::SORT_ENUM_TYPE:
     460             :             {
     461             :                 rtl::Reference< unoidl::EnumTypeEntity > ent2(
     462             :                     static_cast< unoidl::EnumTypeEntity * >(
     463         254 :                         i->second.entity.get()));
     464         254 :                 bool ann = !ent2->getAnnotations().empty();
     465        4783 :                 for (std::vector< unoidl::EnumTypeEntity::Member >::
     466         254 :                          const_iterator j(ent2->getMembers().begin());
     467        4751 :                      !ann && j != ent2->getMembers().end(); ++j)
     468             :                 {
     469        1335 :                     ann = !j->annotations.empty();
     470             :                 }
     471         254 :                 i->second.dataOffset = getOffset(file);
     472         254 :                 writeKind(file, ent2.get(), ann);
     473         254 :                 write32(file, ent2->getMembers().size());
     474        4953 :                 for (std::vector< unoidl::EnumTypeEntity::Member >::
     475         254 :                          const_iterator j(ent2->getMembers().begin());
     476        3302 :                      j != ent2->getMembers().end(); ++j)
     477             :                 {
     478        1397 :                     writeIdxName(file, j->name);
     479        1397 :                     write32(file, static_cast< sal_uInt32 >(j->value));
     480        1397 :                     writeAnnotations(file, ann, j->annotations);
     481             :                 }
     482         254 :                 writeAnnotations(file, ann, ent2->getAnnotations());
     483         254 :                 break;
     484             :             }
     485             :         case unoidl::Entity::SORT_PLAIN_STRUCT_TYPE:
     486             :             {
     487             :                 rtl::Reference< unoidl::PlainStructTypeEntity > ent2(
     488             :                     static_cast< unoidl::PlainStructTypeEntity * >(
     489         471 :                         i->second.entity.get()));
     490         471 :                 bool ann = !ent2->getAnnotations().empty();
     491        5886 :                 for (std::vector< unoidl::PlainStructTypeEntity::Member >::
     492         471 :                          const_iterator j(ent2->getDirectMembers().begin());
     493        5856 :                      !ann && j != ent2->getDirectMembers().end(); ++j)
     494             :                 {
     495        1486 :                     ann = !j->annotations.empty();
     496             :                 }
     497         471 :                 i->second.dataOffset = getOffset(file);
     498             :                 writeKind(
     499         471 :                     file, ent2.get(), ann, !ent2->getDirectBase().isEmpty());
     500         471 :                 if (!ent2->getDirectBase().isEmpty()) {
     501         111 :                     writeIdxName(file, ent2->getDirectBase());
     502             :                 }
     503         471 :                 write32(file, ent2->getDirectMembers().size());
     504        6036 :                 for (std::vector< unoidl::PlainStructTypeEntity::Member >::
     505         471 :                          const_iterator j(ent2->getDirectMembers().begin());
     506        4024 :                      j != ent2->getDirectMembers().end(); ++j)
     507             :                 {
     508        1541 :                     writeIdxName(file, j->name);
     509        1541 :                     writeIdxName(file, j->type);
     510        1541 :                     writeAnnotations(file, ann, j->annotations);
     511             :                 }
     512         471 :                 writeAnnotations(file, ann, ent2->getAnnotations());
     513         471 :                 break;
     514             :             }
     515             :         case unoidl::Entity::SORT_POLYMORPHIC_STRUCT_TYPE_TEMPLATE:
     516             :             {
     517             :                 rtl::Reference< unoidl::PolymorphicStructTypeTemplateEntity >
     518             :                     ent2(
     519             :                         static_cast<
     520             :                         unoidl::PolymorphicStructTypeTemplateEntity * >(
     521          58 :                             i->second.entity.get()));
     522          58 :                 bool ann = !ent2->getAnnotations().empty();
     523         366 :                 for (std::vector<
     524             :                          unoidl::PolymorphicStructTypeTemplateEntity::Member >::
     525             :                          const_iterator j(
     526          58 :                              ent2->getMembers().begin());
     527         366 :                      !ann && j != ent2->getMembers().end(); ++j)
     528             :                 {
     529          64 :                     ann = !j->annotations.empty();
     530             :                 }
     531          58 :                 i->second.dataOffset = getOffset(file);
     532          58 :                 writeKind(file, ent2.get(), ann);
     533          58 :                 write32(file, ent2->getTypeParameters().size());
     534         357 :                 for (std::vector< OUString >::const_iterator j(
     535          58 :                          ent2->getTypeParameters().begin());
     536         238 :                      j != ent2->getTypeParameters().end(); ++j)
     537             :                 {
     538          61 :                     writeIdxName(file, *j);
     539             :                 }
     540          58 :                 write32(file, ent2->getMembers().size());
     541         366 :                 for (std::vector<
     542             :                          unoidl::PolymorphicStructTypeTemplateEntity::Member >::
     543             :                          const_iterator j(
     544          58 :                              ent2->getMembers().begin());
     545         244 :                      j != ent2->getMembers().end(); ++j)
     546             :                 {
     547          64 :                     sal_uInt64 f = 0;
     548          64 :                     if (j->parameterized) {
     549          39 :                         f |= 0x01;
     550             :                     }
     551          64 :                     write8(file, f);
     552          64 :                     writeIdxName(file, j->name);
     553          64 :                     writeIdxName(file, j->type);
     554          64 :                     writeAnnotations(file, ann, j->annotations);
     555             :                 }
     556          58 :                 writeAnnotations(file, ann, ent2->getAnnotations());
     557          58 :                 break;
     558             :             }
     559             :         case unoidl::Entity::SORT_EXCEPTION_TYPE:
     560             :             {
     561             :                 rtl::Reference< unoidl::ExceptionTypeEntity > ent2(
     562             :                     static_cast< unoidl::ExceptionTypeEntity * >(
     563         303 :                         i->second.entity.get()));
     564         303 :                 bool ann = !ent2->getAnnotations().empty();
     565        1400 :                 for (std::vector< unoidl::ExceptionTypeEntity::Member >::
     566         303 :                          const_iterator j(ent2->getDirectMembers().begin());
     567        1396 :                      !ann && j != ent2->getDirectMembers().end(); ++j)
     568             :                 {
     569         163 :                     ann = !j->annotations.empty();
     570             :                 }
     571         303 :                 i->second.dataOffset = getOffset(file);
     572             :                 writeKind(
     573         303 :                     file, ent2.get(), ann, !ent2->getDirectBase().isEmpty());
     574         303 :                 if (!ent2->getDirectBase().isEmpty()) {
     575         254 :                     writeIdxName(file, ent2->getDirectBase());
     576             :                 }
     577         303 :                 write32(file, ent2->getDirectMembers().size());
     578        1401 :                 for (std::vector< unoidl::ExceptionTypeEntity::Member >::
     579         303 :                          const_iterator j(ent2->getDirectMembers().begin());
     580         934 :                      j != ent2->getDirectMembers().end(); ++j)
     581             :                 {
     582         164 :                     writeIdxName(file, j->name);
     583         164 :                     writeIdxName(file, j->type);
     584         164 :                     writeAnnotations(file, ann, j->annotations);
     585             :                 }
     586         303 :                 writeAnnotations(file, ann, ent2->getAnnotations());
     587         303 :                 break;
     588             :             }
     589             :         case unoidl::Entity::SORT_INTERFACE_TYPE:
     590             :             {
     591             :                 rtl::Reference< unoidl::InterfaceTypeEntity > ent2(
     592             :                     static_cast< unoidl::InterfaceTypeEntity * >(
     593        2172 :                         i->second.entity.get()));
     594        2172 :                 bool ann = !ent2->getAnnotations().empty();
     595       13593 :                 for (std::vector< unoidl::AnnotatedReference >::const_iterator
     596        2172 :                          j(ent2->getDirectMandatoryBases().begin());
     597       13401 :                      !ann && j != ent2->getDirectMandatoryBases().end(); ++j)
     598             :                 {
     599        2327 :                     ann = !j->annotations.empty();
     600             :                 }
     601        6789 :                 for (std::vector< unoidl::AnnotatedReference >::const_iterator
     602        2172 :                          j(ent2->getDirectOptionalBases().begin());
     603        6597 :                      !ann && j != ent2->getDirectOptionalBases().end(); ++j)
     604             :                 {
     605          59 :                     ann = !j->annotations.empty();
     606             :                 }
     607       10304 :                 for (std::vector< unoidl::InterfaceTypeEntity::Attribute >::
     608        2172 :                          const_iterator j(ent2->getDirectAttributes().begin());
     609       10108 :                      !ann && j != ent2->getDirectAttributes().end(); ++j)
     610             :                 {
     611        1230 :                     ann = !j->annotations.empty();
     612             :                 }
     613       24777 :                 for (std::vector< unoidl::InterfaceTypeEntity::Method >::
     614        2172 :                          const_iterator j(ent2->getDirectMethods().begin());
     615       24567 :                      !ann && j != ent2->getDirectMethods().end(); ++j)
     616             :                 {
     617        6052 :                     ann = !j->annotations.empty();
     618             :                 }
     619        2172 :                 i->second.dataOffset = getOffset(file);
     620        2172 :                 writeKind(file, ent2.get(), ann);
     621        2172 :                 write32(file, ent2->getDirectMandatoryBases().size());
     622       13788 :                 for (std::vector< unoidl::AnnotatedReference >::const_iterator
     623        2172 :                          j(ent2->getDirectMandatoryBases().begin());
     624        9192 :                      j != ent2->getDirectMandatoryBases().end(); ++j)
     625             :                 {
     626        2424 :                     writeIdxName(file, j->name);
     627        2424 :                     writeAnnotations(file, ann, j->annotations);
     628             :                 }
     629        2172 :                 write32(file, ent2->getDirectOptionalBases().size());
     630        6693 :                 for (std::vector< unoidl::AnnotatedReference >::const_iterator
     631        2172 :                          j(ent2->getDirectOptionalBases().begin());
     632        4462 :                      j != ent2->getDirectOptionalBases().end(); ++j)
     633             :                 {
     634          59 :                     writeIdxName(file, j->name);
     635          59 :                     writeAnnotations(file, ann, j->annotations);
     636             :                 }
     637        2172 :                 write32(file, ent2->getDirectAttributes().size());
     638       10254 :                 for (std::vector< unoidl::InterfaceTypeEntity::Attribute >::
     639        2172 :                          const_iterator j(ent2->getDirectAttributes().begin());
     640        6836 :                      j != ent2->getDirectAttributes().end(); ++j)
     641             :                 {
     642        1246 :                     sal_uInt64 f = 0;
     643        1246 :                     if (j->bound) {
     644         161 :                         f |= 0x01;
     645             :                     }
     646        1246 :                     if (j->readOnly) {
     647         275 :                         f |= 0x02;
     648             :                     }
     649        1246 :                     write8(file, f);
     650        1246 :                     writeIdxName(file, j->name);
     651        1246 :                     writeIdxName(file, j->type);
     652        1246 :                     write32(file, j->getExceptions.size());
     653        4065 :                     for (std::vector< OUString >::const_iterator k(
     654        1246 :                              j->getExceptions.begin());
     655        2710 :                          k != j->getExceptions.end(); ++k)
     656             :                     {
     657         109 :                         writeIdxName(file, *k);
     658             :                     }
     659        1246 :                     if (!j->readOnly) {
     660         971 :                         write32(file, j->setExceptions.size());
     661        3300 :                         for (std::vector< OUString >::const_iterator k(
     662         971 :                                  j->setExceptions.begin());
     663        2200 :                              k != j->setExceptions.end(); ++k)
     664             :                         {
     665         129 :                             writeIdxName(file, *k);
     666             :                         }
     667             :                     }
     668        1246 :                     writeAnnotations(file, ann, j->annotations);
     669             :                 }
     670        2172 :                 write32(file, ent2->getDirectMethods().size());
     671       25662 :                 for (std::vector< unoidl::InterfaceTypeEntity::Method >::
     672        2172 :                          const_iterator j(ent2->getDirectMethods().begin());
     673       17108 :                      j != ent2->getDirectMethods().end(); ++j)
     674             :                 {
     675        6382 :                     writeIdxName(file, j->name);
     676        6382 :                     writeIdxName(file, j->returnType);
     677        6382 :                     write32(file, j->parameters.size());
     678       40389 :                     for (std::vector<
     679             :                              unoidl::InterfaceTypeEntity::Method::Parameter >::
     680        6382 :                              const_iterator k(j->parameters.begin());
     681       26926 :                          k != j->parameters.end(); ++k)
     682             :                     {
     683        7081 :                         write8(file, k->direction);
     684        7081 :                         writeIdxName(file, k->name);
     685        7081 :                         writeIdxName(file, k->type);
     686             :                     }
     687        6382 :                     write32(file, j->exceptions.size());
     688       28158 :                     for (std::vector< OUString >::const_iterator k(
     689        6382 :                              j->exceptions.begin());
     690       18772 :                          k != j->exceptions.end(); ++k)
     691             :                     {
     692        3004 :                         writeIdxName(file, *k);
     693             :                     }
     694        6382 :                     writeAnnotations(file, ann, j->annotations);
     695             :                 }
     696        2172 :                 writeAnnotations(file, ann, ent2->getAnnotations());
     697        2172 :                 break;
     698             :             }
     699             :         case unoidl::Entity::SORT_TYPEDEF:
     700             :             {
     701             :                 rtl::Reference< unoidl::TypedefEntity > ent2(
     702             :                     static_cast< unoidl::TypedefEntity * >(
     703          88 :                         i->second.entity.get()));
     704          88 :                 bool ann = !ent2->getAnnotations().empty();
     705          88 :                 i->second.dataOffset = getOffset(file);
     706          88 :                 writeKind(file, ent2.get(), ann);
     707          88 :                 writeIdxName(file, ent2->getType());
     708          88 :                 writeAnnotations(file, ann, ent2->getAnnotations());
     709          88 :                 break;
     710             :             }
     711             :         case unoidl::Entity::SORT_CONSTANT_GROUP:
     712             :             {
     713             :                 rtl::Reference< unoidl::ConstantGroupEntity > ent2(
     714             :                     static_cast< unoidl::ConstantGroupEntity * >(
     715        1211 :                         i->second.entity.get()));
     716        2422 :                 std::map< OUString, ConstItem > cmap;
     717       39477 :                 for (std::vector< unoidl::ConstantGroupEntity::Member >::
     718        1211 :                          const_iterator j(ent2->getMembers().begin());
     719       26318 :                      j != ent2->getMembers().end(); ++j)
     720             :                 {
     721       23896 :                     if (!cmap.insert(
     722             :                             std::make_pair(
     723       23896 :                                 j->name, ConstItem(j->value, j->annotations))).
     724       11948 :                         second)
     725             :                     {
     726             :                         std::cout
     727           0 :                             << "Duplicate constant group member name \""
     728           0 :                             << j->name << '"' << std::endl;
     729           0 :                         std::exit(EXIT_FAILURE);
     730             :                     }
     731             :                 }
     732       39477 :                 for (std::map< OUString, ConstItem >::iterator j(cmap.begin());
     733       26318 :                      j != cmap.end(); ++j)
     734             :                 {
     735       11948 :                     j->second.dataOffset = getOffset(file);
     736       11948 :                     sal_uInt64 v = j->second.constant.type;
     737       11948 :                     if (!j->second.annotations.empty()) {
     738          14 :                         v |= 0x80;
     739             :                     }
     740       11948 :                     write8(file, v);
     741       11948 :                     switch (j->second.constant.type) {
     742             :                     case unoidl::ConstantValue::TYPE_BOOLEAN:
     743           2 :                         write8(file, j->second.constant.booleanValue ? 1 : 0);
     744           2 :                         break;
     745             :                     case unoidl::ConstantValue::TYPE_BYTE:
     746             :                         write8(
     747             :                             file,
     748             :                             static_cast< sal_uInt8 >(
     749         261 :                                 j->second.constant.byteValue));
     750         261 :                         break;
     751             :                     case unoidl::ConstantValue::TYPE_SHORT:
     752             :                         write16(
     753             :                             file,
     754             :                             static_cast< sal_uInt16 >(
     755        2082 :                                 j->second.constant.shortValue));
     756        2082 :                         break;
     757             :                     case unoidl::ConstantValue::TYPE_UNSIGNED_SHORT:
     758          14 :                         write16(file, j->second.constant.unsignedShortValue);
     759          14 :                         break;
     760             :                     case unoidl::ConstantValue::TYPE_LONG:
     761             :                         write32(
     762             :                             file,
     763             :                             static_cast< sal_uInt32 >(
     764        9492 :                                 j->second.constant.longValue));
     765        9492 :                         break;
     766             :                     case unoidl::ConstantValue::TYPE_UNSIGNED_LONG:
     767          14 :                         write32(file, j->second.constant.unsignedLongValue);
     768          14 :                         break;
     769             :                     case unoidl::ConstantValue::TYPE_HYPER:
     770             :                         write64(
     771             :                             file,
     772             :                             static_cast< sal_uInt64 >(
     773          45 :                                 j->second.constant.hyperValue));
     774          45 :                         break;
     775             :                     case unoidl::ConstantValue::TYPE_UNSIGNED_HYPER:
     776          14 :                         write64(file, j->second.constant.unsignedHyperValue);
     777          14 :                         break;
     778             :                     case unoidl::ConstantValue::TYPE_FLOAT:
     779             :                         writeIso60599Binary32(
     780          22 :                             file, j->second.constant.floatValue);
     781          22 :                         break;
     782             :                     case unoidl::ConstantValue::TYPE_DOUBLE:
     783             :                         writeIso60599Binary64(
     784           2 :                             file, j->second.constant.doubleValue);
     785           2 :                         break;
     786             :                     default:
     787           0 :                         for (;;) { std::abort(); } // this cannot happen
     788             :                     }
     789             :                     writeAnnotations(
     790       11948 :                         file, !j->second.annotations.empty(),
     791       23896 :                         j->second.annotations);
     792             :                 }
     793       39477 :                 for (std::map< OUString, ConstItem >::iterator j(
     794        1211 :                          cmap.begin());
     795       26318 :                      j != cmap.end(); ++j)
     796             :                 {
     797       11948 :                     j->second.nameOffset = writeNulName(file, j->first);
     798             :                 }
     799        1211 :                 bool ann = !ent2->getAnnotations().empty();
     800        1211 :                 i->second.dataOffset = getOffset(file);
     801        1211 :                 writeKind(file, ent2.get(), ann);
     802        1211 :                 write32(file, cmap.size());
     803             :                     // overflow from std::map::size_type -> sal_uInt64 is
     804             :                     // unrealistic
     805       39477 :                 for (std::map< OUString, ConstItem >::iterator j(
     806        1211 :                          cmap.begin());
     807       26318 :                      j != cmap.end(); ++j)
     808             :                 {
     809       11948 :                     write32(file, j->second.nameOffset);
     810       11948 :                     write32(file, j->second.dataOffset);
     811             :                 }
     812        1211 :                 writeAnnotations(file, ann, ent2->getAnnotations());
     813        2422 :                 break;
     814             :             }
     815             :         case unoidl::Entity::SORT_SINGLE_INTERFACE_BASED_SERVICE:
     816             :             {
     817             :                 rtl::Reference< unoidl::SingleInterfaceBasedServiceEntity >
     818             :                     ent2(
     819             :                         static_cast<
     820             :                             unoidl::SingleInterfaceBasedServiceEntity * >(
     821         532 :                                 i->second.entity.get()));
     822         532 :                 bool dfltCtor = ent2->getConstructors().size() == 1
     823         532 :                     && ent2->getConstructors()[0].defaultConstructor;
     824         532 :                 bool ann = !ent2->getAnnotations().empty();
     825         532 :                 if (!dfltCtor) {
     826        1833 :                     for (std::vector<
     827             :                              unoidl::SingleInterfaceBasedServiceEntity::
     828             :                              Constructor >::const_iterator j(
     829         289 :                                  ent2->getConstructors().begin());
     830        1833 :                          !ann && j != ent2->getConstructors().end(); ++j)
     831             :                     {
     832         322 :                         ann = !j->annotations.empty();
     833             :                     }
     834             :                 }
     835         532 :                 i->second.dataOffset = getOffset(file);
     836         532 :                 writeKind(file, ent2.get(), ann, dfltCtor);
     837         532 :                 writeIdxName(file, ent2->getBase());
     838         532 :                 if (!dfltCtor) {
     839         289 :                     write32(file, ent2->getConstructors().size());
     840        1833 :                     for (std::vector<
     841             :                              unoidl::SingleInterfaceBasedServiceEntity::
     842             :                              Constructor >::const_iterator j(
     843         289 :                                  ent2->getConstructors().begin());
     844        1222 :                          j != ent2->getConstructors().end(); ++j)
     845             :                     {
     846         322 :                         if (j->defaultConstructor) {
     847             :                             std::cout
     848           0 :                                 << "Unexpected default constructor \""
     849           0 :                                 << j->name << '"' << std::endl;
     850           0 :                             std::exit(EXIT_FAILURE);
     851             :                         }
     852         322 :                         writeIdxName(file, j->name);
     853         322 :                         write32(file, j->parameters.size());
     854        2562 :                         for (std::vector<
     855             :                                  unoidl::SingleInterfaceBasedServiceEntity::
     856             :                                  Constructor::Parameter >::const_iterator k(
     857         322 :                                      j->parameters.begin());
     858        1708 :                              k != j->parameters.end(); ++k)
     859             :                         {
     860         532 :                             sal_uInt64 f = 0;
     861         532 :                             if (k->rest) {
     862          10 :                                 f |= 0x04;
     863             :                             }
     864         532 :                             write8(file, f);
     865         532 :                             writeIdxName(file, k->name);
     866         532 :                             writeIdxName(file, k->type);
     867             :                         }
     868         322 :                         write32(file, j->exceptions.size());
     869        1170 :                         for (std::vector< OUString >::const_iterator k(
     870         322 :                                  j->exceptions.begin());
     871         780 :                              k != j->exceptions.end(); ++k)
     872             :                         {
     873          68 :                             writeIdxName(file, *k);
     874             :                         }
     875         322 :                         writeAnnotations(file, ann, j->annotations);
     876             :                     }
     877             :                 }
     878         532 :                 writeAnnotations(file, ann, ent2->getAnnotations());
     879         532 :                 break;
     880             :             }
     881             :         case unoidl::Entity::SORT_ACCUMULATION_BASED_SERVICE:
     882             :             {
     883             :                 rtl::Reference< unoidl::AccumulationBasedServiceEntity > ent2(
     884             :                     static_cast< unoidl::AccumulationBasedServiceEntity * >(
     885        1060 :                         i->second.entity.get()));
     886        1060 :                 bool ann = !ent2->getAnnotations().empty();
     887        5414 :                 for (std::vector< unoidl::AnnotatedReference >::const_iterator
     888        1060 :                          j(ent2->getDirectMandatoryBaseServices().begin());
     889        5332 :                      !ann && j != ent2->getDirectMandatoryBaseServices().end();
     890             :                      ++j)
     891             :                 {
     892         731 :                     ann = !j->annotations.empty();
     893             :                 }
     894        3405 :                 for (std::vector< unoidl::AnnotatedReference >::const_iterator
     895        1060 :                          j(ent2->getDirectOptionalBaseServices().begin());
     896        3321 :                      !ann && j != ent2->getDirectOptionalBaseServices().end();
     897             :                      ++j)
     898             :                 {
     899          61 :                     ann = !j->annotations.empty();
     900             :                 }
     901        7691 :                 for (std::vector< unoidl::AnnotatedReference >::const_iterator
     902        1060 :                          j(ent2->getDirectMandatoryBaseInterfaces().begin());
     903        2549 :                      (!ann
     904       10152 :                       && j != ent2->getDirectMandatoryBaseInterfaces().end());
     905             :                      ++j)
     906             :                 {
     907        1489 :                     ann = !j->annotations.empty();
     908             :                 }
     909        4052 :                 for (std::vector< unoidl::AnnotatedReference >::const_iterator
     910        1060 :                          j(ent2->getDirectOptionalBaseInterfaces().begin());
     911        3958 :                      !ann && j != ent2->getDirectOptionalBaseInterfaces().end();
     912             :                      ++j)
     913             :                 {
     914         275 :                     ann = !j->annotations.empty();
     915             :                 }
     916       11982 :                 for (std::vector<
     917             :                          unoidl::AccumulationBasedServiceEntity::Property >::
     918             :                          const_iterator j(
     919        1060 :                              ent2->getDirectProperties().begin());
     920       11862 :                      !ann && j != ent2->getDirectProperties().end(); ++j)
     921             :                 {
     922        2914 :                     ann = !j->annotations.empty();
     923             :                 }
     924        1060 :                 i->second.dataOffset = getOffset(file);
     925        1060 :                 writeKind(file, ent2.get(), ann);
     926        1060 :                 write32(file, ent2->getDirectMandatoryBaseServices().size());
     927        5400 :                 for (std::vector< unoidl::AnnotatedReference >::const_iterator
     928        1060 :                          j(ent2->getDirectMandatoryBaseServices().begin());
     929        3600 :                      j != ent2->getDirectMandatoryBaseServices().end(); ++j)
     930             :                 {
     931         740 :                     writeIdxName(file, j->name);
     932         740 :                     writeAnnotations(file, ann, j->annotations);
     933             :                 }
     934        1060 :                 write32(file, ent2->getDirectOptionalBaseServices().size());
     935        3366 :                 for (std::vector< unoidl::AnnotatedReference >::const_iterator
     936        1060 :                          j(ent2->getDirectOptionalBaseServices().begin());
     937        2244 :                      j != ent2->getDirectOptionalBaseServices().end(); ++j)
     938             :                 {
     939          62 :                     writeIdxName(file, j->name);
     940          62 :                     writeAnnotations(file, ann, j->annotations);
     941             :                 }
     942        1060 :                 write32(file, ent2->getDirectMandatoryBaseInterfaces().size());
     943        7869 :                 for (std::vector< unoidl::AnnotatedReference >::const_iterator
     944        1060 :                          j(ent2->getDirectMandatoryBaseInterfaces().begin());
     945        5246 :                      j != ent2->getDirectMandatoryBaseInterfaces().end(); ++j)
     946             :                 {
     947        1563 :                     writeIdxName(file, j->name);
     948        1563 :                     writeAnnotations(file, ann, j->annotations);
     949             :                 }
     950        1060 :                 write32(file, ent2->getDirectOptionalBaseInterfaces().size());
     951        4062 :                 for (std::vector< unoidl::AnnotatedReference >::const_iterator
     952        1060 :                          j(ent2->getDirectOptionalBaseInterfaces().begin());
     953        2708 :                      j != ent2->getDirectOptionalBaseInterfaces().end(); ++j)
     954             :                 {
     955         294 :                     writeIdxName(file, j->name);
     956         294 :                     writeAnnotations(file, ann, j->annotations);
     957             :                 }
     958        1060 :                 write32(file, ent2->getDirectProperties().size());
     959       12591 :                 for (std::vector<
     960             :                          unoidl::AccumulationBasedServiceEntity::Property >::
     961             :                          const_iterator j(
     962        1060 :                              ent2->getDirectProperties().begin());
     963        8394 :                      j != ent2->getDirectProperties().end(); ++j)
     964             :                 {
     965        3137 :                     write16(file, static_cast< sal_uInt16 >(j->attributes));
     966        3137 :                     writeIdxName(file, j->name);
     967        3137 :                     writeIdxName(file, j->type);
     968        3137 :                     writeAnnotations(file, ann, j->annotations);
     969             :                 }
     970        1060 :                 writeAnnotations(file, ann, ent2->getAnnotations());
     971        1060 :                 break;
     972             :             }
     973             :         case unoidl::Entity::SORT_INTERFACE_BASED_SINGLETON:
     974             :             {
     975             :                 rtl::Reference< unoidl::InterfaceBasedSingletonEntity > ent2(
     976             :                     static_cast< unoidl::InterfaceBasedSingletonEntity * >(
     977         187 :                         i->second.entity.get()));
     978         187 :                 bool ann = !ent2->getAnnotations().empty();
     979         187 :                 i->second.dataOffset = getOffset(file);
     980         187 :                 writeKind(file, ent2.get(), ann);
     981         187 :                 writeIdxName(file, ent2->getBase());
     982         187 :                 writeAnnotations(file, ann, ent2->getAnnotations());
     983         187 :                 break;
     984             :             }
     985             :         case unoidl::Entity::SORT_SERVICE_BASED_SINGLETON:
     986             :             {
     987             :                 rtl::Reference< unoidl::ServiceBasedSingletonEntity > ent2(
     988             :                     static_cast< unoidl::ServiceBasedSingletonEntity * >(
     989          11 :                         i->second.entity.get()));
     990          11 :                 bool ann = !ent2->getAnnotations().empty();
     991          11 :                 i->second.dataOffset = getOffset(file);
     992          11 :                 writeKind(file, ent2.get(), ann);
     993          11 :                 writeIdxName(file, ent2->getBase());
     994          11 :                 writeAnnotations(file, ann, ent2->getAnnotations());
     995          11 :                 break;
     996             :             }
     997             :         }
     998             :     }
     999        7303 :     for (std::map< OUString, Item >::iterator i(map.begin()); i != map.end();
    1000             :          ++i)
    1001             :     {
    1002        6676 :         i->second.nameOffset = writeNulName(file, i->first);
    1003             :     }
    1004         627 :     sal_uInt64 off = getOffset(file);
    1005         627 :     if (rootSize == 0) {
    1006         329 :         write8(file, 0); // SORT_MODULE
    1007         329 :         write32(file, map.size());
    1008             :             // overflow from std::map::size_type -> sal_uInt64 is unrealistic
    1009             :     } else {
    1010         298 :         *rootSize = map.size();
    1011             :             // overflow from std::map::size_type -> std::size_t is unrealistic
    1012             :     }
    1013        7303 :     for (std::map< OUString, Item >::iterator i(map.begin()); i != map.end();
    1014             :          ++i)
    1015             :     {
    1016        6676 :         write32(file, i->second.nameOffset);
    1017        6676 :         write32(file, i->second.dataOffset);
    1018             :     }
    1019         627 :     return off;
    1020             : }
    1021             : 
    1022             : }
    1023             : 
    1024        1336 : SAL_IMPLEMENT_MAIN() {
    1025             :     try {
    1026         668 :         sal_uInt32 args = rtl_getAppCommandArgCount();
    1027         668 :         if (args == 0) {
    1028           0 :             badUsage();
    1029             :         }
    1030         668 :         rtl::Reference< unoidl::Manager > mgr(new unoidl::Manager);
    1031         668 :         bool entities = false;
    1032        1336 :         rtl::Reference< unoidl::Provider > prov;
    1033        1336 :         std::map< OUString, Item > map;
    1034        1640 :         for (sal_uInt32 i = 0; i != args - 1; ++i) {
    1035             :             assert(args > 1);
    1036        1342 :             OUString uri(getArgumentUri(i, i == args - 2 ? &entities : 0));
    1037        1342 :             if (entities) {
    1038           5 :                 mapEntities(mgr, uri, map);
    1039             :             } else {
    1040             :                 try {
    1041        1337 :                     prov = mgr->addProvider(uri);
    1042           0 :                 } catch (unoidl::NoSuchFileException &) {
    1043             :                     std::cerr
    1044           0 :                         << "Input <" << uri << "> does not exist" << std::endl;
    1045           0 :                     std::exit(EXIT_FAILURE);
    1046             :                 }
    1047             :             }
    1048        1342 :         }
    1049         298 :         if (!entities) {
    1050             :             mapCursor(
    1051         293 :                 (prov.is()
    1052         293 :                  ? prov->createRootCursor()
    1053             :                  : rtl::Reference< unoidl::MapCursor >()),
    1054         586 :                 map);
    1055             :         }
    1056         596 :         osl::File f(getArgumentUri(args - 1, 0));
    1057         298 :         osl::FileBase::RC e = f.open(osl_File_OpenFlag_Write);
    1058         298 :         if (e == osl::FileBase::E_NOENT) {
    1059          11 :             e = f.open(osl_File_OpenFlag_Write | osl_File_OpenFlag_Create);
    1060             :         }
    1061         298 :         if (e != osl::FileBase::E_None) {
    1062             :             std::cerr
    1063           0 :                 << "Cannot open <" << f.getURL() << "> for writing, error code "
    1064           0 :                 << +e << std::endl;
    1065           0 :             std::exit(EXIT_FAILURE);
    1066             :         }
    1067         298 :         write(f, "UNOIDL\xFF\0", 8);
    1068         298 :         write32(f, 0); // root map offset
    1069         298 :         write32(f, 0); // root map size
    1070             :         write(
    1071             :             f,
    1072         298 :             RTL_CONSTASCII_STRINGPARAM(
    1073             :                 "\0** Created by LibreOffice " LIBO_VERSION_DOTTED
    1074         298 :                 " unoidl-write **\0"));
    1075             :         std::size_t size;
    1076         298 :         sal_uInt64 off = writeMap(f, map, &size);
    1077         298 :         e = f.setSize(getOffset(f)); // truncate in case it already existed
    1078         298 :         if (e != osl::FileBase::E_None) {
    1079             :             std::cerr
    1080           0 :                 << "Cannot set size of <" << f.getURL() << ">, error code "
    1081           0 :                 << +e << std::endl;
    1082           0 :             std::exit(EXIT_FAILURE);
    1083             :         }
    1084         298 :         e = f.setPos(osl_Pos_Absolut, 8);
    1085         298 :         if (e != osl::FileBase::E_None) {
    1086             :             std::cerr
    1087           0 :                 << "Cannot rewind current position in <" << f.getURL()
    1088           0 :                 << ">, error code " << +e << std::endl;
    1089           0 :             std::exit(EXIT_FAILURE);
    1090             :         }
    1091         298 :         write32(f, off);
    1092         298 :         write32(f, size);
    1093             :             // overflow from std::map::size_type -> sal_uInt64 is unrealistic
    1094         298 :         e = f.close();
    1095         298 :         if (e != osl::FileBase::E_None) {
    1096             :             std::cerr
    1097           0 :                 << "Cannot close <" << f.getURL()
    1098           0 :                 << "> after writing, error code " << +e << std::endl;
    1099           0 :             std::exit(EXIT_FAILURE);
    1100             :         }
    1101         966 :         return EXIT_SUCCESS;
    1102           0 :     } catch (unoidl::FileFormatException & e1) {
    1103             :         std::cerr
    1104         740 :             << "Bad input <" << e1.getUri() << ">: " << e1.getDetail()
    1105         370 :             << std::endl;
    1106         370 :         std::exit(EXIT_FAILURE);
    1107             :     }
    1108        2004 : }
    1109             : 
    1110             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10