LCOV - code coverage report
Current view: top level - svl/source/filerec - filerec.cxx (source / functions) Hit Total Coverage
Test: commit e02a6cb2c3e2b23b203b422e4e0680877f232636 Lines: 0 166 0.0 %
Date: 2014-04-14 Functions: 0 21 0.0 %
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             :  * This file incorporates work covered by the following license notice:
      10             :  *
      11             :  *   Licensed to the Apache Software Foundation (ASF) under one or more
      12             :  *   contributor license agreements. See the NOTICE file distributed
      13             :  *   with this work for additional information regarding copyright
      14             :  *   ownership. The ASF licenses this file to you under the Apache
      15             :  *   License, Version 2.0 (the "License"); you may not use this file
      16             :  *   except in compliance with the License. You may obtain a copy of
      17             :  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
      18             :  */
      19             : 
      20             : #include <svl/filerec.hxx>
      21             : #include <osl/endian.h>
      22             : 
      23             : 
      24             : /*  Die folgenden Makros extrahieren Teilbereiche aus einem sal_uInt32 Wert.
      25             :     Diese sal_uInt32-Werte werden anstelle der einzelnen Werte gestreamt,
      26             :     um Calls zu sparen.
      27             : */
      28             : 
      29             : #define SFX_REC_PRE(n) ( ((n) & 0x000000FF) )
      30             : #define SFX_REC_OFS(n) ( ((n) & 0xFFFFFF00) >> 8 )
      31             : #define SFX_REC_TYP(n) ( ((n) & 0x000000FF) )
      32             : #define SFX_REC_VER(n) ( ((n) & 0x0000FF00) >> 8 )
      33             : #define SFX_REC_TAG(n) ( ((n) & 0xFFFF0000) >> 16 )
      34             : 
      35             : #define SFX_REC_CONTENT_VER(n) ( ((n) & 0x000000FF) )
      36             : #define SFX_REC_CONTENT_OFS(n) ( ((n) & 0xFFFFFF00) >> 8 )
      37             : 
      38             : 
      39             : /*  Die folgenden Makros setzen Teilbereiche zu einem sal_uInt32 Wert zusammen.
      40             :     Diese sal_uInt32-Werte werden anstelle der einzelnen Werte gestreamt,
      41             :     um Calls zu sparen.
      42             : */
      43             : 
      44           0 : static void lclWriteMiniHeader(SvStream *p, sal_uInt32 nPreTag, sal_uInt32 nStartPos, sal_uInt32 nEndPos)
      45             : {
      46             :    (*p).WriteUInt32(  sal_uInt32(nPreTag) |
      47           0 :              sal_uInt32(nEndPos-nStartPos-SFX_REC_HEADERSIZE_MINI) << 8  );
      48           0 : }
      49             : 
      50           0 : static void lclWriteHeader(SvStream *p, sal_uInt32 nRecType, sal_uInt32 nContentTag, sal_uInt32 nContentVer)
      51             : {
      52           0 :     (*p).WriteUInt32(  sal_uInt32(nRecType) |
      53           0 :              ( sal_uInt32(nContentVer) << 8 ) |
      54           0 :              ( sal_uInt32(nContentTag) << 16 )  );
      55           0 : }
      56             : 
      57             : #define SFX_REC_CONTENT_HEADER(nContentVer,n1StStartPos,nCurStartPos) \
      58             :                     ( sal_uInt32(nContentVer) | \
      59             :                       sal_uInt32( nCurStartPos - n1StStartPos ) << 8 )
      60             : 
      61             : 
      62           0 : sal_uInt32 SfxMiniRecordWriter::Close
      63             : (
      64             :     bool         bSeekToEndOfRec    /*  true (default)
      65             :                                         Der Stream wird an das Ende des Records
      66             :                                         positioniert.
      67             : 
      68             :                                         false
      69             :                                         Der Stream wird an den Anfang des
      70             :                                         Contents (also hinter den Header)
      71             :                                         positioniert.
      72             :                                     */
      73             : )
      74             : 
      75             : /*  [Beschreibung]
      76             : 
      77             :     Diese Methode schlie\st den Record. Dabei wird haupts"achlich der
      78             :     Header geschrieben.
      79             : 
      80             :     Wurde der Header bereits geschrieben, hat der Aufruf keine Wirkung.
      81             : 
      82             : 
      83             :     [R"uckgabewert]
      84             : 
      85             :     sal_uInt32      != 0
      86             :                 Position im Stream, die direkt hinter dem Record liegt.
      87             :                 'bSeekToEndOfRecord==sal_True'
      88             :                 => R"uckgabewert == aktuelle Stream-Position nach Aufruf
      89             : 
      90             :                 == 0
      91             :                 Der Header war bereits geschrieben worden.
      92             : */
      93             : 
      94             : {
      95             :     // wurde der Header noch nicht geschrieben?
      96           0 :     if ( !_bHeaderOk )
      97             :     {
      98             :         // Header an den Anfang des Records schreiben
      99           0 :         sal_uInt32 nEndPos = _pStream->Tell();
     100           0 :         _pStream->Seek( _nStartPos );
     101           0 :         lclWriteMiniHeader(_pStream, _nPreTag, _nStartPos, nEndPos );
     102             : 
     103             :         // je nachdem ans Ende des Records seeken oder hinter Header bleiben
     104           0 :         if ( bSeekToEndOfRec )
     105           0 :             _pStream->Seek( nEndPos );
     106             : 
     107             :         // Header wurde JETZT geschrieben
     108           0 :         _bHeaderOk = true;
     109           0 :         return nEndPos;
     110             :     }
     111             : 
     112             :     // Record war bereits geschlossen
     113           0 :     return 0;
     114             : }
     115             : 
     116           0 : bool SfxMiniRecordReader::SetHeader_Impl( sal_uInt32 nHeader )
     117             : 
     118             : /*  [Beschreibung]
     119             : 
     120             :     Interne Methode zum nachtr"aglichen Verarbeiten eines extern gelesenen
     121             :     Headers. Falls der Header eine End-Of-Records-Kennung darstellt,
     122             :     wird am Stream ein Errorcode gesetzt und sal_False zur"uckgeliefert. Im
     123             :     Fehlerfall wird der Stream jedoch nicht auf den Record-Anfang zur"uck-
     124             :     gesetzt.
     125             : */
     126             : 
     127             : {
     128           0 :     bool bRet = true;
     129             : 
     130             :     // Record-Ende und Pre-Tag aus dem Header ermitteln
     131           0 :     _nEofRec = _pStream->Tell() + SFX_REC_OFS(nHeader);
     132           0 :     _nPreTag = sal::static_int_cast< sal_uInt8 >(SFX_REC_PRE(nHeader));
     133             : 
     134             :     // wenn End-Of-Record-Kennung, dann Fehler
     135           0 :     if ( _nPreTag == SFX_REC_PRETAG_EOR )
     136             :     {
     137           0 :         _pStream->SetError( ERRCODE_IO_WRONGFORMAT );
     138           0 :         bRet = true;
     139             :     }
     140           0 :     return bRet;
     141             : }
     142             : 
     143           0 : SfxMiniRecordReader::SfxMiniRecordReader
     144             : (
     145             :     SvStream*       pStream,        /*  <SvStream>, an dessen aktueller
     146             :                                         Position sich ein <SfxMiniRecord>
     147             :                                         befindet.
     148             :                                     */
     149             :     sal_uInt8           nTag            //  Pre-Tag des gew"unschten Records
     150             : )
     151             : 
     152             : /*  [Beschreibung]
     153             : 
     154             :     Dieser Ctor interpretiert 'pStream' ab der aktuellen Position als
     155             :     eine l"uckenlose Folge von, von dieser Klassen-Gruppe interpretierbaren,
     156             :     Records. Der in dieser Folge erste als <SfxMiniRecord> interpretierbare
     157             :     (also ggf. auch ein extended-Record) mit dem PreTag 'nTag' wird ge"offnet
     158             :     und durch diese Instanz repr"asentiert.
     159             : 
     160             :     Wird das Ende des Streams oder die Kennung SFX_REC_PRETAG_EOR
     161             :     erreicht, bevor ein Record mit dem ge"unschten Pre-Tag gefunden wird,
     162             :     ist die erzeugte Instanz ung"ultig ('IsValid() == sal_False'). Ein ent-
     163             :     sprechender Error-Code (ERRCODE_IO_EOF bzw. ERRCODE_IO_WRONGFORMAT)
     164             :     ist dann am Stream gesetzt, dessen Position ist dann au\serdem unver-
     165             :     "andert.
     166             : 
     167             :     Bei 'nTag==SFX_FILEREC_PRETAG_EOR' wird nicht versucht, einen Record
     168             :     zu lesen, es wird sofort 'IsValid()' auf sal_False gesetzt und kein Error-Code
     169             :     am Stream gesetzt. Dies ist dauzu gedacht, ohne 'new' und 'delete'
     170             :     abw"rtskompatibel SfxMiniRecords einbauen zu k"onnen. Siehe dazu
     171             :     <SfxItemSet::Load()>.
     172             : 
     173             : 
     174             :     [Anwendungsvorschlag]
     175             : 
     176             :     Wird dieser Ctor in einer bereits ausgelieferten Programmversion
     177             :     verwendet, k"onnen in das File-Format jeweils davor kompatibel neue
     178             :     Records mit einer anderen Kennung eingef"ugt werden. Diese werden
     179             :     schlie\slich automatisch "uberlesen. Erkauft wird diese M"oglichkeit
     180             :     allerdings mit etwas schlechterem Laufzeitverhalten im Vergleich mit
     181             :     direktem 'drauf-los-lesen', der sich jedoch auf einen Vergleich zweier
     182             :     Bytes reduziert, falls der gesuchte Record der erste in der Folge ist.
     183             : */
     184             : 
     185             :     : _pStream(pStream)
     186             :     , _nEofRec(0)
     187           0 :     , _bSkipped(nTag == SFX_REC_PRETAG_EOR)
     188             : {
     189             :     // ggf. ignorieren (s.o.)
     190           0 :     if ( _bSkipped )
     191             :     {
     192           0 :         _nPreTag = nTag;
     193           0 :         return;
     194             :     }
     195             : 
     196             :     // StartPos merken, um im Fehlerfall zur"uck-seeken zu k"onnen
     197           0 :     sal_uInt32 nStartPos = pStream->Tell();
     198             : 
     199             :     // passenden Record suchen
     200             :     while(true)
     201             :     {
     202             :         // Header lesen
     203             :         SAL_INFO("svl", "SfxFileRec: searching record at " << pStream->Tell());
     204             :         sal_uInt32 nHeader;
     205           0 :         pStream->ReadUInt32( nHeader );
     206             : 
     207             :         // Headerdaten von Basisklasse extrahieren lassen
     208           0 :         SetHeader_Impl( nHeader );
     209             : 
     210             :         // ggf. Fehler behandeln
     211           0 :         if ( pStream->IsEof() )
     212           0 :             _nPreTag = SFX_REC_PRETAG_EOR;
     213           0 :         else if ( _nPreTag == SFX_REC_PRETAG_EOR )
     214           0 :             pStream->SetError( ERRCODE_IO_WRONGFORMAT );
     215             :         else
     216             :         {
     217             :             // wenn gefunden, dann Schleife abbrechen
     218           0 :             if ( _nPreTag == nTag )
     219           0 :                 break;
     220             : 
     221             :             // sonst skippen und weitersuchen
     222           0 :             pStream->Seek( _nEofRec );
     223           0 :             continue;
     224             :         }
     225             : 
     226             :         // Fehler => zur"uck-seeken
     227           0 :         pStream->Seek( nStartPos );
     228           0 :         break;
     229           0 :     }
     230             : }
     231             : 
     232             : 
     233           0 : SfxSingleRecordWriter::SfxSingleRecordWriter
     234             : (
     235             :     sal_uInt8           nRecordType,    // f"ur Subklassen
     236             :     SvStream*       pStream,        // Stream, in dem der Record angelegt wird
     237             :     sal_uInt16          nContentTag,    // Inhalts-Art-Kennung
     238             :     sal_uInt8           nContentVer     // Inhalts-Versions-Kennung
     239             : )
     240             : 
     241             : /*  [Beschreibung]
     242             : 
     243             :     Interner Ctor f"ur Subklassen.
     244             : */
     245             : 
     246           0 : :   SfxMiniRecordWriter( pStream, SFX_REC_PRETAG_EXT )
     247             : {
     248             :     // Erweiterten Header hiner den des SfxMiniRec schreiben
     249           0 :     lclWriteHeader(pStream, nRecordType, nContentTag, nContentVer);
     250           0 : }
     251             : 
     252             : 
     253             : inline bool SfxSingleRecordReader::ReadHeader_Impl( sal_uInt16 nTypes )
     254             : 
     255             : /*  [Beschreibung]
     256             : 
     257             :     Interne Methode zum Einlesen eines SfxMultiRecord-Headers, nachdem
     258             :     die Basisklasse bereits initialisiert und deren Header gelesen ist.
     259             :     Ggf. ist ein Error-Code am Stream gesetzt, im Fehlerfall wird jedoch
     260             :     nicht zur"uckge-seekt.
     261             : */
     262             : 
     263             : {
     264             :     bool bRet;
     265             : 
     266             :     // Basisklassen-Header einlesen
     267             :     sal_uInt32 nHeader=0;
     268             :     _pStream->ReadUInt32( nHeader );
     269             :     if ( !SetHeader_Impl( nHeader ) )
     270             :         bRet = false;
     271             :     else
     272             :     {
     273             :         // eigenen Header einlesen
     274             :         _pStream->ReadUInt32( nHeader );
     275             :         _nRecordVer = sal::static_int_cast< sal_uInt8 >(SFX_REC_VER(nHeader));
     276             :         _nRecordTag = sal::static_int_cast< sal_uInt16 >(SFX_REC_TAG(nHeader));
     277             : 
     278             :         // falscher Record-Typ?
     279             :         _nRecordType = sal::static_int_cast< sal_uInt8 >(SFX_REC_TYP(nHeader));
     280             :         bRet = 0 != ( nTypes & _nRecordType);
     281             :     }
     282             :     return bRet;
     283             : }
     284             : 
     285             : 
     286           0 : bool SfxSingleRecordReader::FindHeader_Impl
     287             : (
     288             :     sal_uInt16      nTypes,     // arithm. Veroderung erlaubter Record-Typen
     289             :     sal_uInt16      nTag        // zu findende Record-Art-Kennung
     290             : )
     291             : 
     292             : /*  [Beschreibung]
     293             : 
     294             :     Interne Methode zum lesen des Headers des ersten Record, der einem
     295             :     der Typen in 'nTypes' entspricht und mit der Art-Kennung 'nTag'
     296             :     gekennzeichnet ist.
     297             : 
     298             :     Kann ein solcher Record nicht gefunden werden, wird am Stream ein
     299             :     Errorcode gesetzt, zur"uck-geseekt und sal_False zur"uckgeliefert.
     300             : */
     301             : 
     302             : {
     303             :     // StartPos merken, um im Fehlerfall zur"uck-seeken zu k"onnen
     304           0 :     sal_uInt32 nStartPos = _pStream->Tell();
     305             : 
     306             :     // richtigen Record suchen
     307           0 :     while ( !_pStream->IsEof() )
     308             :     {
     309             :         // Header lesen
     310             :         sal_uInt32 nHeader;
     311             :         SAL_INFO("svl", "SfxFileRec: searching record at " << _pStream->Tell());
     312           0 :         _pStream->ReadUInt32( nHeader );
     313           0 :         if ( !SetHeader_Impl( nHeader ) )
     314             :             // EOR => Such-Schleife abbreichen
     315           0 :             break;
     316             : 
     317             :         // Extended Record gefunden?
     318           0 :         if ( _nPreTag == SFX_REC_PRETAG_EXT )
     319             :         {
     320             :             // Extended Header lesen
     321           0 :             _pStream->ReadUInt32( nHeader );
     322           0 :             _nRecordTag = sal::static_int_cast< sal_uInt16 >(SFX_REC_TAG(nHeader));
     323             : 
     324             :             // richtigen Record gefunden?
     325           0 :             if ( _nRecordTag == nTag )
     326             :             {
     327             :                 // gefundener Record-Typ passend?
     328             :                 _nRecordType = sal::static_int_cast< sal_uInt8 >(
     329           0 :                     SFX_REC_TYP(nHeader));
     330           0 :                 if ( nTypes & _nRecordType )
     331             :                     // ==> gefunden
     332           0 :                     return true;
     333             : 
     334             :                 // error => Such-Schleife abbrechen
     335           0 :                 break;
     336             :             }
     337             :         }
     338             : 
     339             :         // sonst skippen
     340           0 :         if ( !_pStream->IsEof() )
     341           0 :             _pStream->Seek( _nEofRec );
     342             :     }
     343             : 
     344             :     // Fehler setzen und zur"uck-seeken
     345           0 :     _pStream->SetError( ERRCODE_IO_WRONGFORMAT );
     346           0 :     _pStream->Seek( nStartPos );
     347           0 :     return false;
     348             : }
     349             : 
     350             : 
     351           0 : SfxMultiFixRecordWriter::SfxMultiFixRecordWriter
     352             : (
     353             :     sal_uInt8           nRecordType,    // Subklassen Record-Kennung
     354             :     SvStream*       pStream,        // Stream, in dem der Record angelegt wird
     355             :     sal_uInt16          nContentTag,    // Content-Art-Kennung
     356             :     sal_uInt8           nContentVer     // Content-Versions-Kennung
     357             : )
     358             : 
     359             : /*  [Beschreibung]
     360             : 
     361             :     Interne Methode f"ur Subklassen.
     362             : */
     363             : 
     364             :     :  SfxSingleRecordWriter( nRecordType, pStream, nContentTag, nContentVer )
     365             :     , _nContentStartPos(0)
     366             :     , _nContentSize(0)
     367           0 :     , _nContentCount(0)
     368             : {
     369             :     // Platz f"ur eigenen Header
     370           0 :     pStream->SeekRel( + SFX_REC_HEADERSIZE_MULTI );
     371           0 : }
     372             : 
     373             : 
     374           0 : sal_uInt32 SfxMultiFixRecordWriter::Close( bool bSeekToEndOfRec )
     375             : 
     376             : //  siehe <SfxMiniRecordWriter>
     377             : 
     378             : {
     379             :     // Header noch nicht geschrieben?
     380           0 :     if ( !_bHeaderOk )
     381             :     {
     382             :         // Position hinter Record merken, um sie restaurieren zu k"onnen
     383           0 :         sal_uInt32 nEndPos = SfxSingleRecordWriter::Close( false );
     384             : 
     385             :         // gegen"uber SfxSingleRecord erweiterten Header schreiben
     386           0 :         _pStream->WriteUInt16( _nContentCount );
     387           0 :         _pStream->WriteUInt32( _nContentSize );
     388             : 
     389             :         // je nachdem ans Ende des Records seeken oder hinter Header bleiben
     390           0 :         if ( bSeekToEndOfRec )
     391           0 :             _pStream->Seek(nEndPos);
     392           0 :         return nEndPos;
     393             :     }
     394             : 
     395             :     // Record war bereits geschlossen
     396           0 :     return 0;
     397             : }
     398             : 
     399             : 
     400           0 : SfxMultiVarRecordWriter::SfxMultiVarRecordWriter
     401             : (
     402             :     sal_uInt8           nRecordType,    // Record-Kennung der Subklasse
     403             :     SvStream*       pStream,        // Stream, in dem der Record angelegt wird
     404             :     sal_uInt16          nRecordTag,     // Gesamt-Art-Kennung
     405             :     sal_uInt8           nRecordVer      // Gesamt-Versions-Kennung
     406             : )
     407             : 
     408             : /*  [Beschreibung]
     409             : 
     410             :     Interner Ctor f"ur Subklassen.
     411             : */
     412             : 
     413             : :   SfxMultiFixRecordWriter( nRecordType, pStream, nRecordTag, nRecordVer ),
     414           0 :     _nContentVer( 0 )
     415             : {
     416           0 : }
     417             : 
     418             : 
     419           0 : SfxMultiVarRecordWriter::SfxMultiVarRecordWriter
     420             : (
     421             :     SvStream*       pStream,        // Stream, in dem der Record angelegt wird
     422             :     sal_uInt16          nRecordTag,     // Gesamt-Art-Kennung
     423             :     sal_uInt8           nRecordVer      // Gesamt-Versions-Kennung
     424             : )
     425             : 
     426             : /*  [Beschreibung]
     427             : 
     428             :     Legt in 'pStream' einen 'SfxMultiVarRecord' an, dessen Content-Gr"o\sen
     429             :     weder bekannt sind noch identisch sein m"ussen, sondern jeweils nach dem
     430             :     Streamen jedes einzelnen Contents errechnet werden sollen.
     431             : 
     432             : 
     433             :     [Anmerkung]
     434             : 
     435             :     Diese Methode ist nicht inline, da f"ur die Initialisierung eines
     436             :     <SvULongs>-Members zu viel Code generiert werden w"urde.
     437             : */
     438             : 
     439             : :   SfxMultiFixRecordWriter( SFX_REC_TYPE_VARSIZE,
     440             :                              pStream, nRecordTag, nRecordVer ),
     441           0 :     _nContentVer( 0 )
     442             : {
     443           0 : }
     444             : 
     445             : 
     446           0 : SfxMultiVarRecordWriter::~SfxMultiVarRecordWriter()
     447             : 
     448             : /*  [Beschreibung]
     449             : 
     450             :     Der Dtor der Klasse <SfxMultiVarRecordWriter> schlie\st den Record
     451             :     automatisch, falls <SfxMultiVarRecordWriter::Close()> nicht bereits
     452             :     explizit gerufen wurde.
     453             : */
     454             : 
     455             : {
     456             :     // wurde der Header noch nicht geschrieben oder mu\s er gepr"uft werden
     457           0 :     if ( !_bHeaderOk )
     458           0 :         Close();
     459           0 : }
     460             : 
     461             : 
     462           0 : void SfxMultiVarRecordWriter::FlushContent_Impl()
     463             : 
     464             : /*  [Beschreibung]
     465             : 
     466             :     Interne Methode zum Abschlie\sen eines einzelnen Contents.
     467             : */
     468             : 
     469             : {
     470             :     // Versions-Kennung und Positions-Offset des aktuellen Contents merken;
     471             :     // das Positions-Offset ist relativ zur Startposition des ersten Contents
     472             :     assert(_aContentOfs.size() == static_cast<size_t>(_nContentCount)-1);
     473           0 :     _aContentOfs.resize(_nContentCount-1);
     474             :     _aContentOfs.push_back(
     475           0 :             SFX_REC_CONTENT_HEADER(_nContentVer,_nStartPos,_nContentStartPos));
     476           0 : }
     477             : 
     478             : 
     479           0 : void SfxMultiVarRecordWriter::NewContent()
     480             : 
     481             : // siehe <SfxMultiFixRecordWriter>
     482             : 
     483             : {
     484             :     // schon ein Content geschrieben?
     485           0 :     if ( _nContentCount )
     486           0 :         FlushContent_Impl();
     487             : 
     488             :     // neuen Content beginnen
     489           0 :     _nContentStartPos = _pStream->Tell();
     490           0 :     ++_nContentCount;
     491           0 : }
     492             : 
     493             : 
     494           0 : sal_uInt32 SfxMultiVarRecordWriter::Close( bool bSeekToEndOfRec )
     495             : 
     496             : // siehe <SfxMiniRecordWriter>
     497             : 
     498             : {
     499             :     // Header noch nicht geschrieben?
     500           0 :     if ( !_bHeaderOk )
     501             :     {
     502             :         // ggf. letzten Content abschlie\sen
     503           0 :         if ( _nContentCount )
     504           0 :             FlushContent_Impl();
     505             : 
     506             :         // Content-Offset-Tabelle schreiben
     507           0 :         sal_uInt32 nContentOfsPos = _pStream->Tell();
     508             :         //! darf man das so einr"ucken?
     509           0 :         for ( sal_uInt16 n = 0; n < _nContentCount; ++n )
     510           0 :             _pStream->WriteUInt32( _aContentOfs[n] );
     511             : 
     512             :         // SfxMultiFixRecordWriter::Close() "uberspringen!
     513           0 :         sal_uInt32 nEndPos = SfxSingleRecordWriter::Close( false );
     514             : 
     515             :         // eigenen Header schreiben
     516           0 :         _pStream->WriteUInt16( _nContentCount );
     517           0 :         if ( SFX_REC_TYPE_VARSIZE_RELOC == _nPreTag ||
     518           0 :              SFX_REC_TYPE_MIXTAGS_RELOC == _nPreTag )
     519           0 :             _pStream->WriteUInt32( static_cast<sal_uInt32>(nContentOfsPos - ( _pStream->Tell() + sizeof(sal_uInt32) )) );
     520             :         else
     521           0 :             _pStream->WriteUInt32( nContentOfsPos );
     522             : 
     523             :         // ans Ende des Records seeken bzw. am Ende des Headers bleiben
     524           0 :         if ( bSeekToEndOfRec )
     525           0 :              _pStream->Seek(nEndPos);
     526           0 :         return nEndPos;
     527             :     }
     528             : 
     529             :     // Record war bereits vorher geschlossen
     530           0 :     return 0;
     531             : }
     532             : 
     533             : 
     534           0 : void SfxMultiMixRecordWriter::NewContent
     535             : (
     536             :     sal_uInt16      nContentTag,    // Kennung f"ur die Art des Contents
     537             :     sal_uInt8       nContentVer     // Kennung f"ur die Version des Contents
     538             : )
     539             : 
     540             : /*  [Beschreibung]
     541             : 
     542             :     Mit dieser Methode wird in den Record ein neuer Content eingef"ugt
     543             :     und dessen Content-Tag sowie dessen Content-Version angegeben. Jeder,
     544             :     auch der 1. Record mu\s durch Aufruf dieser Methode eingeleitet werden.
     545             : */
     546             : 
     547             : {
     548             :     // ggf. vorherigen Record abschlie\sen
     549           0 :     if ( _nContentCount )
     550           0 :         FlushContent_Impl();
     551             : 
     552             :     // Tag vor den Content schreiben, Version und Startposition merken
     553           0 :     _nContentStartPos = _pStream->Tell();
     554           0 :     ++_nContentCount;
     555           0 :     _pStream->WriteUInt16( nContentTag );
     556           0 :     _nContentVer = nContentVer;
     557           0 : }
     558             : 
     559             : 
     560           0 : bool SfxMultiRecordReader::ReadHeader_Impl()
     561             : 
     562             : /*  [Beschreibung]
     563             : 
     564             :     Interne Methode zum Einlesen eines SfxMultiRecord-Headers, nachdem
     565             :     die Basisklasse bereits initialisiert und deren Header gelesen ist.
     566             :     Ggf. ist ein Error-Code am Stream gesetzt, im Fehlerfall wird jedoch
     567             :     nicht zur"uckge-seekt.
     568             : */
     569             : 
     570             : {
     571             :     // eigenen Header lesen
     572           0 :     _pStream->ReadUInt16( _nContentCount );
     573           0 :     _pStream->ReadUInt32( _nContentSize ); // Fix: jedes einzelnen, Var|Mix: Tabellen-Pos.
     574             : 
     575             :     // mu\s noch eine Tabelle mit Content-Offsets geladen werden?
     576           0 :     if ( _nRecordType != SFX_REC_TYPE_FIXSIZE )
     577             :     {
     578             :         // Tabelle aus dem Stream einlesen
     579           0 :         sal_uInt32 nContentPos = _pStream->Tell();
     580           0 :         if ( _nRecordType == SFX_REC_TYPE_VARSIZE_RELOC ||
     581           0 :              _nRecordType == SFX_REC_TYPE_MIXTAGS_RELOC )
     582           0 :             _pStream->SeekRel( + _nContentSize );
     583             :         else
     584           0 :             _pStream->Seek( _nContentSize );
     585           0 :         _pContentOfs = new sal_uInt32[_nContentCount];
     586           0 :         memset(_pContentOfs, 0, _nContentCount*sizeof(sal_uInt32));
     587             :         //! darf man jetzt so einr"ucken
     588             :         #if defined(OSL_LITENDIAN)
     589           0 :         _pStream->Read( _pContentOfs, sizeof(sal_uInt32)*_nContentCount );
     590             :         #else
     591             :         for ( sal_uInt16 n = 0; n < _nContentCount; ++n )
     592             :             _pStream->ReadUInt32( _pContentOfs[n] );
     593             :         #endif
     594           0 :         _pStream->Seek( nContentPos );
     595             :     }
     596             : 
     597             :     // Header konnte gelesen werden, wenn am Stream kein Error gesetzt ist
     598           0 :     return !_pStream->GetError();
     599             : }
     600             : 
     601             : 
     602           0 : SfxMultiRecordReader::SfxMultiRecordReader( SvStream *pStream, sal_uInt16 nTag )
     603             :     : _pContentOfs(0)
     604             :     , _nContentSize(0)
     605             :     , _nContentCount(0)
     606             :     , _nContentNo(0)
     607             :     , _nContentTag( 0 )
     608           0 :     , _nContentVer( 0 )
     609             : {
     610             :     // Position im Stream merken, um im Fehlerfall zur"uck-seeken zu k"onnen
     611           0 :     _nStartPos = pStream->Tell();
     612             : 
     613             :     // passenden Record suchen und Basisklasse initialisieren
     614           0 :     SfxSingleRecordReader::Construct_Impl( pStream );
     615           0 :     if ( SfxSingleRecordReader::FindHeader_Impl( SFX_REC_TYPE_FIXSIZE |
     616             :             SFX_REC_TYPE_VARSIZE | SFX_REC_TYPE_VARSIZE_RELOC |
     617             :             SFX_REC_TYPE_MIXTAGS | SFX_REC_TYPE_MIXTAGS_RELOC,
     618           0 :             nTag ) )
     619             :     {
     620             :         // eigenen Header dazu-lesen
     621           0 :         if ( !ReadHeader_Impl() )
     622             :             // nicht lesbar => als ung"ultig markieren und zur"uck-seeken
     623           0 :             SetInvalid_Impl( _nStartPos);
     624             :     }
     625           0 : }
     626             : 
     627             : 
     628           0 : SfxMultiRecordReader::~SfxMultiRecordReader()
     629             : {
     630           0 :     delete[] _pContentOfs;
     631           0 : }
     632             : 
     633             : 
     634           0 : bool SfxMultiRecordReader::GetContent()
     635             : 
     636             : /*  [Beschreibung]
     637             : 
     638             :     Positioniert den Stream an den Anfang des n"chsten bzw. beim 1. Aufruf
     639             :     auf den Anfang des ersten Contents im Record und liest ggf. dessen
     640             :     Header ein.
     641             : 
     642             :     Liegt laut Record-Header kein Content mehr vor, wird sal_False zur"uck-
     643             :     gegeben. Trotz einem sal_True-Returnwert kann am Stream ein Fehlercode
     644             :     gesetzt sein, z.B. falls er unvorhergesehenerweise (kaputtes File)
     645             :     zuende ist.
     646             : */
     647             : 
     648             : {
     649             :     // noch ein Content vorhanden?
     650           0 :     if ( _nContentNo < _nContentCount )
     651             :     {
     652             :         // den Stream an den Anfang des Contents positionieren
     653           0 :         sal_uInt32 nOffset = _nRecordType == SFX_REC_TYPE_FIXSIZE
     654           0 :                     ? _nContentNo * _nContentSize
     655           0 :                     : SFX_REC_CONTENT_OFS(_pContentOfs[_nContentNo]);
     656           0 :         sal_uInt32 nNewPos = _nStartPos + nOffset;
     657             :         DBG_ASSERT( nNewPos >= _pStream->Tell(), "SfxMultiRecordReader::GetContent() - New position before current, to much data red!" );
     658             : 
     659             :         // #99366#: correct stream pos in every case;
     660             :         // the if clause was added by MT  a long time ago,
     661             :         // maybe to 'repair' other corrupt documents; but this
     662             :         // gives errors when writing with 5.1 and reading with current
     663             :         // versions, so we decided to remove the if clause (KA-05/17/2002)
     664             :         // if ( nNewPos > _pStream->Tell() )
     665           0 :         _pStream->Seek( nNewPos );
     666             : 
     667             :         // ggf. Content-Header lesen
     668           0 :         if ( _nRecordType == SFX_REC_TYPE_MIXTAGS ||
     669           0 :              _nRecordType == SFX_REC_TYPE_MIXTAGS_RELOC )
     670             :         {
     671             :             _nContentVer = sal::static_int_cast< sal_uInt8 >(
     672           0 :                 SFX_REC_CONTENT_VER(_pContentOfs[_nContentNo]));
     673           0 :             _pStream->ReadUInt16( _nContentTag );
     674             :         }
     675             : 
     676             :         // ContentNo weiterz"ahlen
     677           0 :         ++_nContentNo;
     678           0 :         return true;
     679             :     }
     680             : 
     681           0 :     return false;
     682             : }
     683             : 
     684             : 
     685             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10