LCOV - code coverage report
Current view: top level - usr/local/src/libreoffice/include/svl - filerec.hxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 25 51 49.0 %
Date: 2013-07-09 Functions: 7 17 41.2 %
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             : #ifndef _SFXFILEREC_HXX
      21             : #define _SFXFILEREC_HXX
      22             : 
      23             : //=========================================================================
      24             : 
      25             : #include "svl/svldllapi.h"
      26             : #include <tools/debug.hxx>
      27             : #include <tools/stream.hxx>
      28             : #include <vector>
      29             : 
      30             : //------------------------------------------------------------------------
      31             : 
      32             : #define SFX_REC_PRETAG_EXT              sal_uInt8(0x00) // Pre-Tag f"ur Extended-Records
      33             : #define SFX_REC_PRETAG_EOR              sal_uInt8(0xFF) // Pre-Tag f"ur End-Of-Records
      34             : 
      35             : #define SFX_REC_TYPE_NONE               sal_uInt8(0x00) // unbekannter Record-Typ
      36             : #define SFX_REC_TYPE_FIRST              sal_uInt8(0x01)
      37             : #define SFX_REC_TYPE_SINGLE             sal_uInt8(0x01) // Single-Content-Record
      38             : #define SFX_REC_TYPE_FIXSIZE            sal_uInt8(0x02) // Fix-Size-Multi-Content-Record
      39             : #define SFX_REC_TYPE_VARSIZE_RELOC      sal_uInt8(0x03) // variable Rec-Size
      40             : #define SFX_REC_TYPE_VARSIZE            sal_uInt8(0x04) // alt (nicht verschiebbar)
      41             : #define SFX_REC_TYPE_MIXTAGS_RELOC      sal_uInt8(0x07) // Mixed Tag Content-Record
      42             : #define SFX_REC_TYPE_MIXTAGS            sal_uInt8(0x08) // alt (nicht verschiebbar)
      43             : #define SFX_REC_TYPE_LAST               sal_uInt8(0x08)
      44             : #define SFX_REC_TYPE_MINI                   0x100   // Mini-Record
      45             : #define SFX_REC_TYPE_DRAWENG                0x400   // Drawing-Engine-Record
      46             : #define SFX_REC_TYPE_EOR                    0xF00   // End-Of-Records
      47             : 
      48             : //------------------------------------------------------------------------
      49             : 
      50             : #define SFX_REC_HEADERSIZE_MINI     4   // Gr"o\se des Mini-Record-Headers
      51             : #define SFX_REC_HEADERSIZE_SINGLE   4   // zzgl. HEADERSIZE_MINI => 8
      52             : #define SFX_REC_HEADERSIZE_MULTI    6   // zzgl. HEADERSIZE_SINGLE => 14
      53             : 
      54             : //------------------------------------------------------------------------
      55             : 
      56             : #ifndef DBG
      57             : #ifdef DBG_UTIL
      58             : #define DBG(x) x
      59             : #else
      60             : #define DBG(x)
      61             : #endif
      62             : #endif
      63             : 
      64             : //------------------------------------------------------------------------
      65             : 
      66             : /*  [Fileformat]
      67             : 
      68             :     Jeder Record beginnt mit einem Byte, dem sogenannten 'Pre-Tag'.
      69             : 
      70             :     Ist dieses 'Pre-Tag' == 0x00, dann handelt es sich um einen Extended-
      71             :     Record, dessen Typ durch ein weiteres Byte an Position 5 n�her
      72             :     beschrieben wird:
      73             : 
      74             :     0x01:       SfxSingleRecord
      75             :     0x02:       SfxMultiFixRecord
      76             :     0x03+0x04:  SfxMultiVarRecord
      77             :     0x07+0x08:  SfxMultiMixRecord
      78             :     (Alle weiteren Record-Typ-Kennungen sind reserviert.)
      79             : 
      80             :     I.d.R. werden File-Formate schon aus Performance-Gr"unden so aufgebaut,
      81             :     da\s beim Lesen jeweils vorher schon feststeht, welcher Record-Typ
      82             :     vorliegt. Diese Kennung dient daher hautps"achlich der "Uberpr"ufung
      83             :     und File-Viewern, die das genaue File-Format (unterhalb der Records)
      84             :     nicht kennen.
      85             : 
      86             :     Der 'SfxMiniRecordReader' verf"ugt dazu auch "uber eine statische
      87             :     Methode 'ScanRecordType()', mit der festgestellt werden kann, welcher
      88             :     Record-Typ in dem "ubergebenen Stream zu finden ist.
      89             : 
      90             :     Ein 'Pre-Tag' mit dem Wert 0xFF ist als Terminator reserviert.
      91             :     Terminatoren werden verwendet, um das Suchen nach einem speziellen
      92             :     Record zu terminieren, d.h. ist er bis dorthin nicht gefunden, wird
      93             :     auch nicht weitergesucht.
      94             : 
      95             :     Bei allen anderen Werten des 'Pre-Tags' (also von 0x01 bis 0xFE)
      96             :     handelt es sich um einen zum SW3 kompatbilen Record, der hier
      97             :     'SfxMiniRecord' genannt wird, er kann daher mit einem <SfxMiniRecordReader>
      98             :     gelesen werden.
      99             : 
     100             :     Beginnt ein Record mit 0x44 k"onnte es sich um einen Drawing-Engine-
     101             :     Record handeln. Dies ist dann der Fall, wenn die folgenden drei Bytes
     102             :     die Zeichenkette 'RMD' bzw. 'RVW' ergeben (zusammen mit 'D'==0x44
     103             :     ergibt dies die K"urzel f"ur 'DRaw-MoDel' bzw. 'DRaw-VieW'). Records
     104             :     dieser Art k"onnen von den hier dargestellten Klassen weder gelesen,
     105             :     noch in irgendeiner Weise interpretiert werden. Einzig die Methode
     106             :     'ScanRecordType()' kann sie erkennen - weitere Behandlung obliegt
     107             :     jedoch der Anwendungsprogrammierung.
     108             : 
     109             :     Diese drei Bytes an den Positionen 2 bis 4 enthalten normalerweise
     110             :     die Gr"o\se des Records ohne Pre-Tag und Gr"o\sen-Bytes selbst,
     111             :     also die Restgr"o\se nach diesem 4-Byte-Header.
     112             : 
     113             :         Struktur des Mini-Records:
     114             : 
     115             :                             1 sal_uInt8         Pre-Tag
     116             :                             3 sal_uInt8         OffsetToEndOfRec
     117             :         OffsetToEndOfRec*   1 sal_uInt8         Content
     118             : 
     119             :     Bei den Extended-Reords folgt auf diesen 4-Byte-Header ein erweiterter
     120             :     Header, der zun"achst den o.g. Record-Typ, dann eine Versions-Kennung
     121             :     sowie ein Tag enth"alt, welches den Inhalt kennzeichnet.
     122             : 
     123             :         Struktur des Extended-Records:
     124             : 
     125             :                             1 sal_uInt8         Pre-Tag (==0x00)
     126             :                             3 sal_uInt8         OffsetToEndOfRec
     127             :         OffsetToEndOfRec*   1 sal_uInt8         Content
     128             :                             1 sal_uInt8         Record-Type
     129             :                             1 sal_uInt8         Version
     130             :                             2 sal_uInt8         Tag
     131             :         ContentSize*        1 sal_uInt8         Content
     132             : 
     133             :         (ContentSize = OffsetToEndOfRec - 8)
     134             : 
     135             :     [Anmerkung]
     136             : 
     137             :     Der Aufbau der Records wird wie folgt begr"undet:
     138             : 
     139             :     Der SW-Record-Typ war zuerst vorhanden, mu\ste also 1:1 "ubernommen
     140             :     werden. Zum Gl"uck wurden einige Record-Tags nicht verwendet, (Z.B.
     141             :     0x00 und 0xFF).
     142             :     =>  1. Byte 0x00 kann als Kennung f"ur erweiterten Record verwendet werden
     143             :     =>  1. Byte 0xFF kann f"ur besondere Zwecke verwendet werden
     144             : 
     145             :     Egal welcher Record-Typ vorliegt, sollte eine Erkennung des Typs, ein
     146             :     Auslesen des Headers und ein "uberpspringen des Records m"oglich sein,
     147             :     ohne zu"uck-seeken zu m"ussen und ohne "uberfl"ussige Daten lesen zu
     148             :     m"ussen.
     149             :     =>  die Bytes 2-4 werden bei allen Records als Offset zum Ende des
     150             :         Records interpretiert, so da\s die Gesamt-Recors-Size sich wie
     151             :         folgt berechnet: sizeof(sal_uInt32) + OffsetToEndOfRec
     152             : 
     153             :     Die Records sollten einfach zu parsen un einheitlich aufgebaut sein.
     154             :     =>  Sie bauen aufeinander auf, so ist z.B. der SfxMiniRecord in jedem
     155             :         anderen enthalten.
     156             : 
     157             :     Die Records sollten auch von denen der Drawing Enginge unterscheidbar
     158             :     sein. Diese beginnen mit 'DRMD' und 'DRVW'.
     159             :     =>  Mini-Records mit dem Pre-Tag 'D' d"urfen maximal 4MB gro\s sein,
     160             :         um nicht in diesen Kennungs-Bereich zu reichen.
     161             : 
     162             :     [Erweiterungen]
     163             : 
     164             :     Es ist geplant das File-Format so zu erweitern, da\s das High-Nibble
     165             :     des Record-Typs der erweiterten Records besondere Aufgaben "ubernehmen
     166             :     soll. Zum Beispiel ist geplant, Record-Contents als 'nur aus Records
     167             :     bestehend' zu kennzeichnen. Ein File-Viewer k"onnte sich dann automatisch
     168             :     durch solche Strukturen 'hangeln', ohne Gefahr zu laufen, auf Daten
     169             :     zu sto\sen, die sich zwar als Records interpretieren lassen, aber
     170             :     tats"achlis als 'flache' Daten geschrieben wurden. Die m"ogliche
     171             :     Erweiterung wird schon jetzt insofern vorbereitet, als da\s das
     172             :     High-Nibble des Typs bei Vergleichen nicht ber"ucksichtigt wird.
     173             : */
     174             : 
     175             : //------------------------------------------------------------------------
     176             : 
     177             : class SVL_DLLPUBLIC SfxMiniRecordWriter
     178             : 
     179             : /*  [Beschreibung]
     180             : 
     181             :     Mit Instanzen dieser Klasse kann ein einfacher Record in einen Stream
     182             :     geschrieben werden, der sich durch ein sal_uInt8-Tag identifiziert, sowie
     183             :     seine eigene L"ange speichert und somit auch von "alteren Versionen
     184             :     bzw. Readern, die diesen Record-Type (Tag) nicht kennen, "ubersprungen
     185             :     werden kann. Es wird keine Version-Nummer gespeichert.
     186             : 
     187             :     Alternativ kann die Gr"o\se fest angegeben werden oder sie wird
     188             :     automatisch aus der Differenz der Tell()-Angaben vor und nach dem
     189             :     Streamen des Inhalts ermittelt.
     190             : 
     191             :     Um Auf- und Abw"artskompatiblit"at gew"ahrleisten zu k"onnen, m"ussen
     192             :     neue Versionen die Daten der "alteren immer komplett enthalten,
     193             :     es d"urfen allenfalls neue Daten hintenan geh"angt werden!
     194             : 
     195             :     [Fileformat]
     196             : 
     197             :     1*              sal_uInt8       Content-Tag (!= 0)
     198             :     1*              3-sal_uInt8     OffsetToEndOfRec in Bytes
     199             :     SizeOfContent*  sal_uInt8       Content
     200             : 
     201             :     [Beispiel]
     202             : 
     203             :     {
     204             :         SfxMiniRecordWriter aRecord( pStream, MY_TAG_X );
     205             :         *aRecord << aMember1;
     206             :         *aRecord << aMember2;
     207             :     }
     208             : */
     209             : 
     210             : {
     211             : protected:
     212             :     SvStream*       _pStream;   //  <SvStream>, in dem der Record liegt
     213             :     sal_uInt32          _nStartPos; //  Start-Position des Gesamt-Records im Stream
     214             :     bool             _bHeaderOk; /* TRUE, wenn der Header schon geschrieben ist; */
     215             :     sal_uInt8           _nPreTag;   //  in den Header zu schreibendes 'Pre-Tag'
     216             : 
     217             : public:
     218             :     inline          SfxMiniRecordWriter( SvStream *pStream,
     219             :                                          sal_uInt8 nTag );
     220             :     inline          SfxMiniRecordWriter( SvStream *pStream, sal_uInt8 nTag,
     221             :                                          sal_uInt32 nSize );
     222             : 
     223             :     inline          ~SfxMiniRecordWriter();
     224             : 
     225             :     inline SvStream& operator*() const;
     226             : 
     227             :     inline void     Reset();
     228             : 
     229             :     sal_uInt32          Close( bool bSeekToEndOfRec = true );
     230             : 
     231             : private:
     232             :                     // not implementend, not allowed
     233             :                     SfxMiniRecordWriter( const SfxMiniRecordWriter& );
     234             :     SfxMiniRecordWriter& operator=(const SfxMiniRecordWriter&);
     235             : };
     236             : 
     237             : //------------------------------------------------------------------------
     238             : 
     239             : class SVL_DLLPUBLIC SfxMiniRecordReader
     240             : 
     241             : /*  [Beschreibung]
     242             : 
     243             :     Mit Instanzen dieser Klasse kann ein einfacher Record aus einem Stream
     244             :     gelesen werden, der mit der Klasse <SfxRecordWriter> geschrieben wurde.
     245             : 
     246             :     Es ist auch m"oglich, den Record zu "uberspringen, ohne sein internes
     247             :     Format zu kennen.
     248             : 
     249             :     [Beispiel]
     250             : 
     251             :     {
     252             :         SfxMiniRecordReader aRecord( pStream );
     253             :         switch ( aRecord.GetTag() )
     254             :         {
     255             :             case MY_TAG_X:
     256             :                 *aRecord >> aMember1;
     257             :                 *aRecord >> aMember2;
     258             :                 break;
     259             : 
     260             :             ...
     261             :         }
     262             :     }
     263             : */
     264             : 
     265             : {
     266             : protected:
     267             :     SvStream*           _pStream;   //  <SvStream>, aus dem gelesen wird
     268             :     sal_uInt32              _nEofRec;   //  Position direkt hinter dem Record
     269             :     bool                _bSkipped;  //  TRUE: der Record wurde explizit geskippt
     270             :     sal_uInt8               _nPreTag;   //  aus dem Header gelesenes Pre-Tag
     271             : 
     272             :                         // Drei-Phasen-Ctor f"ur Subklassen
     273           0 :                         SfxMiniRecordReader() {}
     274           0 :    void                 Construct_Impl( SvStream *pStream, sal_uInt8 nTag )
     275             :                         {
     276           0 :                             _pStream = pStream;
     277           0 :                             _bSkipped = sal_False;
     278           0 :                             _nPreTag = nTag;
     279           0 :                         }
     280             :     inline bool         SetHeader_Impl( sal_uInt32 nHeader );
     281             : 
     282             :                         // als ung"ultig markieren und zur"uck-seeken
     283           0 :     void                SetInvalid_Impl( sal_uInt32 nRecordStartPos )
     284             :                         {
     285           0 :                             _nPreTag = SFX_REC_PRETAG_EOR;
     286           0 :                             _pStream->Seek( nRecordStartPos );
     287           0 :                         }
     288             : 
     289             : public:
     290             :     SfxMiniRecordReader( SvStream *pStream, sal_uInt8 nTag );
     291             :     inline              ~SfxMiniRecordReader();
     292             : 
     293             :     inline sal_uInt8        GetTag() const;
     294             :     inline bool         IsValid() const;
     295             : 
     296             :     inline SvStream&    operator*() const;
     297             : 
     298             :     inline void         Skip();
     299             : 
     300             : private:
     301             :                         // not implementend, not allowed
     302             :                         SfxMiniRecordReader( const SfxMiniRecordReader& );
     303             :     SfxMiniRecordReader& operator=(const SfxMiniRecordReader&);
     304             : };
     305             : 
     306             : //------------------------------------------------------------------------
     307             : 
     308       12986 : class SVL_DLLPUBLIC SfxSingleRecordWriter: public SfxMiniRecordWriter
     309             : 
     310             : /*  [Beschreibung]
     311             : 
     312             :     Mit Instanzen dieser Klasse kann ein Record in einen Stream geschrieben
     313             :     werden, dessen einziger Inhalt sich durch ein sal_uInt16-Tag und eine
     314             :     sal_uInt8-Versions-Nummer identifiziert, sowie seine eigene L"ange speichert
     315             :     und somit auch von "alteren Versionen bzw. Readern, die diesen
     316             :     Record-Type (Tag) nicht kennen, "ubersprungen werden kann.
     317             : 
     318             :     Alternativ kann die Gr"o\se fest angegeben werden oder sie wird
     319             :     automatisch aus der Differenz der Tell()-Angaben vor und nach dem
     320             :     Streamen des Inhalts ermittelt.
     321             : 
     322             :     Um Auf- und Abw"artskompatiblit"at gew"ahrleisten zu k"onnen, m"ussen
     323             :     neue Versionen die Daten der "alteren immer komplett enthalten,
     324             :     es d"urfen allenfalls neue Daten hintenan geh"angt werden!
     325             : 
     326             :     [Fileformat]
     327             : 
     328             :     1*              sal_uInt8       Pre-Tag (!= 0)
     329             :     1*              3-sal_uInt8     OffsetToEndOfRec in Bytes
     330             :     1*              sal_uInt8       Record-Type (==SFX_REC_TYPE_SINGLE)
     331             :     1*              sal_uInt8       Content-Version
     332             :     1*              sal_uInt16      Content-Tag
     333             :     SizeOfContent*  sal_uInt8       Content
     334             : */
     335             : 
     336             : {
     337             : protected:
     338             :                     SfxSingleRecordWriter( sal_uInt8 nRecordType,
     339             :                                            SvStream *pStream,
     340             :                                            sal_uInt16 nTag, sal_uInt8 nCurVer );
     341             : 
     342             : public:
     343             :     inline void     Reset();
     344             : 
     345             :     sal_uInt32          Close( bool bSeekToEndOfRec = true );
     346             : };
     347             : 
     348             : //------------------------------------------------------------------------
     349             : 
     350           0 : class SVL_DLLPUBLIC SfxSingleRecordReader: public SfxMiniRecordReader
     351             : 
     352             : /*  [Beschreibung]
     353             : 
     354             :     Mit Instanzen dieser Klasse kann ein einfacher Record aus einem Stream
     355             :     gelesen werden, der mit der Klasse <SfxSingleRecordWriter> geschrieben
     356             :     wurde.
     357             : 
     358             :     Es ist auch m"oglich, den Record zu "uberspringen, ohne sein internes
     359             :     Format zu kennen.
     360             : */
     361             : 
     362             : {
     363             : protected:
     364             :     sal_uInt16              _nRecordTag;    // Art des Gesamt-Inhalts
     365             :     sal_uInt8               _nRecordVer;    // Version des Gesamt-Inhalts
     366             :     sal_uInt8               _nRecordType;   // Record Type aus dem Header
     367             : 
     368             :                         // Drei-Phasen-Ctor f"ur Subklassen
     369           0 :                         SfxSingleRecordReader() {}
     370           0 :     void                Construct_Impl( SvStream *pStream )
     371             :                         {
     372             :                             SfxMiniRecordReader::Construct_Impl(
     373           0 :                                     pStream, SFX_REC_PRETAG_EXT );
     374           0 :                         }
     375             :     bool                FindHeader_Impl( sal_uInt16 nTypes, sal_uInt16 nTag );
     376             :     bool                ReadHeader_Impl( sal_uInt16 nTypes );
     377             : 
     378             : public:
     379             : 
     380             :     inline sal_uInt16       GetTag() const;
     381             : 
     382             :     inline sal_uInt8        GetVersion() const;
     383             :     inline bool         HasVersion( sal_uInt16 nVersion ) const;
     384             : };
     385             : 
     386             : //------------------------------------------------------------------------
     387             : 
     388             : class SVL_DLLPUBLIC SfxMultiFixRecordWriter: public SfxSingleRecordWriter
     389             : 
     390             : /*  [Beschreibung]
     391             : 
     392             :     Mit Instanzen dieser Klasse kann ein Record in einen Stream geschrieben
     393             :     werden, der seine eigene L"ange speichert und somit auch von "alteren
     394             :     Versionen bzw. Readern, die diesen Record-Type (Tag) nicht kennen,
     395             :     "ubersprungen werden kann.
     396             : 
     397             :     Er enth"alt mehrere Inhalte von demselben Typ (Tag) und derselben
     398             :     Version, die einmalig (stellvertretend f"ur alle) im Header des Records
     399             :     identifiziert werden. Alle Inhalte haben eine vorher bekannte und
     400             :     identische L"ange.
     401             : 
     402             :     Um Auf- und Abw"artskompatiblit"at gew"ahrleisten zu k"onnen, m"ussen
     403             :     neue Versionen die Daten der "alteren immer komplett enthalten,
     404             :     es d"urfen allenfalls neue Daten hinten angeh"angt werden! Hier sind
     405             :     damit selbstverst"andlich nur die Daten der einzelnen Inhalte gemeint,
     406             :     die Anzahl der Inhalte ist selbstverst"andlich variabel und sollte
     407             :     von lesenden Applikationen auch so behandelt werden.
     408             : 
     409             :     [Fileformat]
     410             : 
     411             :     1*                  sal_uInt8       Pre-Tag (==0)
     412             :     1*                  3-sal_uInt8     OffsetToEndOfRec in Bytes
     413             :     1*                  sal_uInt8       Record-Type (==SFX_REC_TYPE_FIXSIZE)
     414             :     1*                  sal_uInt8       Content-Version
     415             :     1*                  sal_uInt16      Content-Tag
     416             :     1*                  sal_uInt16      NumberOfContents
     417             :     1*                  sal_uInt32      SizeOfEachContent
     418             :     NumberOfContents*   (
     419             :     SizeOfEachContent   sal_uInt8       Content
     420             :                         )
     421             : 
     422             :     [Beispiel]
     423             : 
     424             :     {
     425             :         SfxMultiFixRecordWriter aRecord( pStream, MY_TAG_X, MY_VERSION );
     426             :         for ( sal_uInt16 n = 0; n < Count(); ++n )
     427             :         {
     428             :             aRecord.NewContent();
     429             :             *aRecord << aMember1[n];
     430             :             *aRecord << aMember2[n];
     431             :         }
     432             :     }
     433             : */
     434             : 
     435             : {
     436             : protected:
     437             :     sal_uInt32          _nContentStartPos;  /*  Startposition des jeweiligen
     438             :                                             Contents - nur bei DBG_UTIL
     439             :                                             und f"ur Subklassen */
     440             :     sal_uInt32          _nContentSize;      //  Gr"o\se jedes Contents
     441             :     sal_uInt16          _nContentCount;     //  jeweilige Anzahl der Contents
     442             : 
     443             :                     SfxMultiFixRecordWriter( sal_uInt8 nRecordType,
     444             :                                              SvStream *pStream,
     445             :                                              sal_uInt16 nTag,
     446             :                                              sal_uInt8 nCurVer );
     447             : 
     448             : public:
     449             :     inline          ~SfxMultiFixRecordWriter();
     450             : 
     451             :     inline void     NewContent();
     452             : 
     453             :     inline void     Reset();
     454             : 
     455             :     sal_uInt32          Close( bool bSeekToEndOfRec = true );
     456             : };
     457             : 
     458             : //------------------------------------------------------------------------
     459             : 
     460             : class SVL_DLLPUBLIC SfxMultiVarRecordWriter: public SfxMultiFixRecordWriter
     461             : 
     462             : /*  [Beschreibung]
     463             : 
     464             :     Mit Instanzen dieser Klasse kann ein Record in einen Stream geschrieben
     465             :     werden, der seine eigene L"ange speichert und somit auch von "alteren
     466             :     Versionen bzw. Readern, die diesen Record-Type (Tag) nicht kennen,
     467             :     "ubersprungen werden kann.
     468             : 
     469             :     Er enth"alt mehrere Inhalte von demselben Typ (Tag) und derselben
     470             :     Version, die einmalig (stellvertretend f"ur alle) im Header des Records
     471             :     identifiziert werden. Die L"ange f"ur jeden einzelnen Inhalt wird
     472             :     automatisch berechnet und gespeichert, so da\s auch einzelne Inhalte
     473             :     "ubersprungen werden k"onnen, ohne sie interpretieren zu m"ussen.
     474             : 
     475             :     Um Auf- und Abw"artskompatiblit"at gew"ahrleisten zu k"onnen, m"ussen
     476             :     neue Versionen die Daten der "alteren immer komplett enthalten,
     477             :     es d"urfen allenfalls neue Daten hinten angeh"angt werden!
     478             : 
     479             :     [Fileformat]
     480             : 
     481             :     1*                  sal_uInt8       Pre-Tag (==0)
     482             :     1*                  3-sal_uInt8     OffsetToEndOfRec in Bytes
     483             :     1*                  sal_uInt8       Record-Type (==SFX_FILETYPE_TYPE_VARSIZE)
     484             :     1*                  sal_uInt8       Content-Version
     485             :     1*                  sal_uInt16      Content-Tag
     486             :     1*                  sal_uInt16      NumberOfContents
     487             :     1*                  sal_uInt32      OffsetToOfsTable
     488             :     NumberOfContents*   (
     489             :     ContentSize*        sal_uInt8       Content
     490             :                         )
     491             :     NumberOfContents*   sal_uInt32      ContentOfs (je per <<8 verschoben)
     492             : 
     493             :     [Beispiel]
     494             : 
     495             :     {
     496             :         SfxMultiVarRecordWriter aRecord( pStream, MY_TAG_X, MY_VERSION );
     497             :         for ( sal_uInt16 n = 0; n < Count(); ++n )
     498             :         {
     499             :             aRecord.NewContent();
     500             :             *aRecord << aMember1[n];
     501             :             *aRecord << aMember2[n];
     502             :         }
     503             :     }
     504             : */
     505             : 
     506             : {
     507             : protected:
     508             :     std::vector<sal_uInt32> _aContentOfs;
     509             :     sal_uInt16              _nContentVer;   // nur f"ur SfxMultiMixRecordWriter
     510             : 
     511             :                         SfxMultiVarRecordWriter( sal_uInt8 nRecordType,
     512             :                                                  SvStream *pStream,
     513             :                                                  sal_uInt16 nRecordTag,
     514             :                                                  sal_uInt8 nRecordVer );
     515             : 
     516             :     void                FlushContent_Impl();
     517             : 
     518             : public:
     519             :                         SfxMultiVarRecordWriter( SvStream *pStream,
     520             :                                                  sal_uInt16 nRecordTag,
     521             :                                                  sal_uInt8 nRecordVer );
     522             :     virtual             ~SfxMultiVarRecordWriter();
     523             : 
     524             :     void                NewContent();
     525             : 
     526             :     virtual sal_uInt32      Close( bool bSeekToEndOfRec = true );
     527             : };
     528             : 
     529             : //------------------------------------------------------------------------
     530             : 
     531       10530 : class SVL_DLLPUBLIC SfxMultiMixRecordWriter: public SfxMultiVarRecordWriter
     532             : 
     533             : /*  [Beschreibung]
     534             : 
     535             :     Mit Instanzen dieser Klasse kann ein Record in einen Stream geschrieben
     536             :     werden, der seine eigene L"ange speichert und somit auch von "alteren
     537             :     Versionen bzw. Readern, die diesen Record-Type (Tag) nicht kennen,
     538             :     "ubersprungen werden kann.
     539             : 
     540             :     Er enth"alt mehrere Inhalte von demselben Typ (Tag) und derselben
     541             :     Version, die einmalig (stellvertretend f"ur alle) im Header des Records
     542             :     identifiziert werden. Alle Inhalte haben eine vorher bekannte und
     543             :     identische L"ange.
     544             : 
     545             :     Um Auf- und Abw"artskompatiblit"at gew"ahrleisten zu k"onnen, m"ussen
     546             :     neue Versionen die Daten der "alteren immer komplett enthalten,
     547             :     es d"urfen allenfalls neue Daten hinten angeh"angt werden!
     548             : 
     549             :     [Fileformat]
     550             : 
     551             :     1*                  sal_uInt8       Pre-Tag (==0)
     552             :     1*                  3-sal_uInt8     OffsetToEndOfRec in Bytes
     553             :     1*                  sal_uInt8       Record-Type (==SFX_REC_TYPE_MIXTAGS)
     554             :     1*                  sal_uInt8       Content-Version
     555             :     1*                  sal_uInt16      Record-Tag
     556             :     1*                  sal_uInt16      NumberOfContents
     557             :     1*                  sal_uInt32      OffsetToOfsTable
     558             :     NumberOfContents*   (
     559             :     1*                  sal_uInt16      Content-Tag
     560             :     ContentSize*        sal_uInt8        Content
     561             :                         )
     562             :     NumberOfContents*   sal_uInt32      ( ContentOfs << 8 + Version )
     563             : */
     564             : 
     565             : {
     566             : public:
     567             :     inline              SfxMultiMixRecordWriter( SvStream *pStream,
     568             :                                                  sal_uInt16 nRecordTag,
     569             :                                                  sal_uInt8 nRecordVer );
     570             : 
     571             :     void                NewContent( sal_uInt16 nTag, sal_uInt8 nVersion );
     572             : 
     573             : // private: geht nicht, da einige Compiler dann auch vorherige privat machen
     574             :     void                NewContent()
     575             :                         { OSL_FAIL( "NewContent() only allowed with args" ); }
     576             : };
     577             : 
     578             : //------------------------------------------------------------------------
     579             : 
     580             : class SVL_DLLPUBLIC SfxMultiRecordReader: public SfxSingleRecordReader
     581             : 
     582             : /*  [Beschreibung]
     583             : 
     584             :     Mit Instanzen dieser Klasse kann ein aus mehreren Contents bestehender
     585             :     Record aus einem Stream gelesen werden, der mit einer der Klassen
     586             :     <SfxMultiFixRecordWriter>, <SfxMultiVarRecordWriter> oder
     587             :     <SfxMultiMixRecordWriter> geschrieben wurde.
     588             : 
     589             :     Es ist auch m"oglich, den Record oder einzelne Contents zu "uberspringen,
     590             :     ohne das jeweilis interne Format zu kennen.
     591             : 
     592             :     [Beispiel]
     593             : 
     594             :     {
     595             :         SfxMultiRecordReader aRecord( pStream );
     596             :         for ( sal_uInt16 nRecNo = 0; aRecord.GetContent(); ++nRecNo )
     597             :         {
     598             :             switch ( aRecord.GetTag() )
     599             :             {
     600             :                 case MY_TAG_X:
     601             :                     X *pObj = new X;
     602             :                     *aRecord >> pObj.>aMember1;
     603             :                     if ( aRecord.HasVersion(2) )
     604             :                         *aRecord >> pObj->aMember2;
     605             :                     Append( pObj );
     606             :                     break;
     607             : 
     608             :                 ...
     609             :             }
     610             :         }
     611             :     }
     612             : */
     613             : 
     614             : {
     615             :     sal_uInt32              _nStartPos;     //  Start-Position des Records
     616             :     sal_uInt32*             _pContentOfs;   //  Offsets der Startpositionen
     617             :     sal_uInt32              _nContentSize;  //  Size jedes einzelnen / Tabellen-Pos
     618             :     sal_uInt16              _nContentCount; //  Anzahl der Contents im Record
     619             :     sal_uInt16              _nContentNo;    /*  der Index des aktuellen Contents
     620             :                                             enth"alt jeweils den Index des
     621             :                                             Contents, der beim n"achsten
     622             :                                             GetContent() geholt wird */
     623             :     sal_uInt16              _nContentTag;   //  Art-Kennung des aktuellen Contents
     624             :     sal_uInt8               _nContentVer;   //  Versions-Kennung des akt. Contents
     625             : 
     626             :     bool                ReadHeader_Impl();
     627             : 
     628             : public:
     629             :                         SfxMultiRecordReader( SvStream *pStream, sal_uInt16 nTag );
     630             :                         ~SfxMultiRecordReader();
     631             : 
     632             :     bool                GetContent();
     633             :     inline sal_uInt16       GetContentTag();
     634             :     inline sal_uInt8        GetContentVersion() const;
     635             :     inline bool         HasContentVersion( sal_uInt16 nVersion ) const;
     636             : 
     637             :     inline sal_uInt32       ContentCount() const;
     638             : };
     639             : 
     640             : //=========================================================================
     641             : 
     642       17898 : inline SfxMiniRecordWriter::SfxMiniRecordWriter
     643             : (
     644             :     SvStream*       pStream,        // Stream, in dem der Record angelegt wird
     645             :     sal_uInt8            nTag            // Record-Tag zwischen 0x01 und 0xFE
     646             : )
     647             : 
     648             : /*  [Beschreibung]
     649             : 
     650             :     Legt in 'pStream' einen 'SfxMiniRecord' an, dessen Content-Gr"o\se
     651             :     nicht bekannt ist, sondern nach dam Streamen des Contents errechnet
     652             :     werden soll.
     653             : */
     654             : 
     655             : :   _pStream( pStream ),
     656       17898 :     _nStartPos( pStream->Tell() ),
     657             :     _bHeaderOk(false),
     658       35796 :     _nPreTag( nTag )
     659             : {
     660             :     DBG_ASSERT( _nPreTag != 0xFF, "invalid Tag" );
     661             :     DBG( DbgOutf( "SfxFileRec: writing record to %ul", pStream->Tell() ) );
     662             : 
     663       17898 :     pStream->SeekRel( + SFX_REC_HEADERSIZE_MINI );
     664       17898 : }
     665             : 
     666             : //-------------------------------------------------------------------------
     667             : 
     668             : inline SfxMiniRecordWriter::SfxMiniRecordWriter
     669             : (
     670             :     SvStream*       pStream,        // Stream, in dem der Record angelegt wird
     671             :     sal_uInt8           nTag,           // Record-Tag zwischen 0x01 und 0xFE
     672             :     sal_uInt32          nSize           // Gr"o\se der Daten in Bytes
     673             : )
     674             : 
     675             : /*  [Beschreibung]
     676             : 
     677             :     Legt in 'pStream' einen 'SfxMiniRecord' an, dessen Content-Gr"o\se
     678             :     von vornherein bekannt ist.
     679             : */
     680             : 
     681             : :   _pStream( pStream ),
     682             :     // _nTag( uninitialized ),
     683             :     // _nStarPos( uninitialized ),
     684             :     _bHeaderOk(true)
     685             : {
     686             :     DBG_ASSERT( nTag != 0 && nTag != 0xFF, "invalid Tag" );
     687             :     DBG(_nStartPos = pStream->Tell());
     688             :     DBG( DbgOutf( "SfxFileRec: writing record to %ul", _nStartPos ) );
     689             : 
     690             :     *pStream << ( ( nTag << 24 ) | nSize );
     691             : }
     692             : 
     693             : //-------------------------------------------------------------------------
     694             : 
     695       17898 : inline SfxMiniRecordWriter::~SfxMiniRecordWriter()
     696             : 
     697             : /*  [Beschreibung]
     698             : 
     699             :     Der Dtor der Klasse <SfxMiniRecordWriter> schlie\st den Record
     700             :     automatisch, falls <SfxMiniRecordWriter::Close()> nicht bereits
     701             :     explizit gerufen wurde.
     702             : */
     703             : 
     704             : {
     705             :     // wurde der Header noch nicht geschrieben oder mu\s er gepr"uft werden
     706       17898 :     if ( !_bHeaderOk )
     707        2456 :         Close();
     708       17898 : }
     709             : 
     710             : //-------------------------------------------------------------------------
     711             : 
     712             : inline SvStream& SfxMiniRecordWriter::operator*() const
     713             : 
     714             : /*  [Beschreibung]
     715             : 
     716             :     Dieser Operator liefert den Stream, in dem der Record liegt.
     717             :     Der Record darf noch nicht geschlossen worden sein.
     718             : */
     719             : 
     720             : {
     721             :     DBG_ASSERT( !_bHeaderOk, "getting Stream of closed record" );
     722             :     return *_pStream;
     723             : }
     724             : 
     725             : //-------------------------------------------------------------------------
     726             : 
     727             : inline void SfxMiniRecordWriter::Reset()
     728             : {
     729             :     _pStream->Seek( _nStartPos + SFX_REC_HEADERSIZE_MINI );
     730             :     _bHeaderOk = false;
     731             : }
     732             : 
     733             : //=========================================================================
     734             : 
     735           0 : inline SfxMiniRecordReader::~SfxMiniRecordReader()
     736             : 
     737             : /*  [Beschreibung]
     738             : 
     739             :     Der Dtor der Klasse <SfxMiniRecordReader> positioniert den Stream
     740             :     automatisch auf die Position direkt hinter dem Record, falls nicht
     741             :     <SfxMiniRecordReader::Skip()> bereits explizit gerufen wurde.
     742             : */
     743             : 
     744             : {
     745             :     // noch nicht explizit ans Ende gesprungen?
     746           0 :     if ( !_bSkipped )
     747           0 :         Skip();
     748           0 : }
     749             : 
     750             : //-------------------------------------------------------------------------
     751             : 
     752           0 : inline void SfxMiniRecordReader::Skip()
     753             : 
     754             : /*  [Beschreibung]
     755             : 
     756             :     Mit dieser Methode wird der Stream direkt hinter das Ende des Records
     757             :     positioniert.
     758             : */
     759             : 
     760             : {
     761           0 :     _pStream->Seek(_nEofRec);
     762           0 :     _bSkipped = sal_True;
     763           0 : }
     764             : 
     765             : //-------------------------------------------------------------------------
     766             : 
     767             : inline sal_uInt8 SfxMiniRecordReader::GetTag() const
     768             : 
     769             : /*  [Beschreibung]
     770             : 
     771             :     Liefert des aus dem Header gelesene Pre-Tag des Records. Dieses kann
     772             :     auch SFX_REC_PRETAG_EXT oder SFX_REC_PRETAG_EOR sein, im
     773             :     letzteren Fall ist am Stream der Fehlercode ERRCODE_IO_WRONGFORMAT
     774             :     gesetzt. SFX_REC_PRETAG_EXT ist g"ultig, da diese extended-Records
     775             :     nur eine Erweiterung des SfxMiniRecord darstellen.
     776             : */
     777             : 
     778             : {
     779             :     return _nPreTag;
     780             : }
     781             : 
     782             : //-------------------------------------------------------------------------
     783             : 
     784             : inline bool SfxMiniRecordReader::IsValid() const
     785             : 
     786             : /*  [Beschreibung]
     787             : 
     788             :     Hiermit kann abgefragt werden, ob der Record erfolgreich aus dem
     789             :     Stream konstruiert werden konnte, der Header also f"ur diesen Record-Typ
     790             :     passend war.
     791             : */
     792             : 
     793             : {
     794             :     return _nPreTag != SFX_REC_PRETAG_EOR;
     795             : }
     796             : 
     797             : //-------------------------------------------------------------------------
     798             : 
     799             : inline SvStream& SfxMiniRecordReader::operator*() const
     800             : 
     801             : /*  [Beschreibung]
     802             : 
     803             :     Dieser Operator liefert den Stream in dem der Record liegt.
     804             :     Die aktuelle Position des Streams mu\s innerhalb des Records liegen.
     805             : */
     806             : 
     807             : {
     808             :     DBG_ASSERT( _pStream->Tell() < _nEofRec, "read behind record" );
     809             :     return *_pStream;
     810             : }
     811             : 
     812             : //=========================================================================
     813             : 
     814       12986 : inline sal_uInt32 SfxSingleRecordWriter::Close( bool bSeekToEndOfRec )
     815             : 
     816             : //  siehe <SfxMiniRecordWriter::Close(bool)>
     817             : 
     818             : {
     819       12986 :     sal_uInt32 nRet = 0;
     820             : 
     821             :     // wurde der Header noch nicht geschrieben?
     822       12986 :     if ( !_bHeaderOk )
     823             :     {
     824             :         // Basisklassen-Header schreiben
     825       12986 :         sal_uInt32 nEndPos = SfxMiniRecordWriter::Close( bSeekToEndOfRec );
     826             : 
     827             :         // ggf. ans Ende des eigenen Headers seeken oder hinter Rec bleiben
     828       12986 :         if ( !bSeekToEndOfRec )
     829       12986 :             _pStream->SeekRel( SFX_REC_HEADERSIZE_SINGLE );
     830       12986 :         nRet = nEndPos;
     831             :     }
     832             : #ifdef DBG_UTIL
     833             :     else
     834             :         // Basisklassen-Header pr"ufen
     835             :         SfxMiniRecordWriter::Close( bSeekToEndOfRec );
     836             : #endif
     837             : 
     838             :     // Record war bereits geschlossen
     839             : //  nRet = 0;
     840       12986 :     return nRet;
     841             : }
     842             : 
     843             : //-------------------------------------------------------------------------
     844             : 
     845             : inline void SfxSingleRecordWriter::Reset()
     846             : {
     847             :     _pStream->Seek( _nStartPos + SFX_REC_HEADERSIZE_MINI +
     848             :                                  SFX_REC_HEADERSIZE_SINGLE );
     849             :     _bHeaderOk = false;
     850             : }
     851             : 
     852             : //=========================================================================
     853             : 
     854             : inline sal_uInt16 SfxSingleRecordReader::GetTag() const
     855             : 
     856             : /*  [Beschreibung]
     857             : 
     858             :     Liefert des aus dem Header gelesene Tag f"ur den Gesamt-Record.
     859             : */
     860             : 
     861             : {
     862             :     return _nRecordTag;
     863             : }
     864             : 
     865             : //-------------------------------------------------------------------------
     866             : 
     867             : inline sal_uInt8 SfxSingleRecordReader::GetVersion() const
     868             : 
     869             : /*  [Beschreibung]
     870             : 
     871             :     Liefert die Version des aus dem Stream gelesenen Records.
     872             : */
     873             : 
     874             : {
     875             :     return _nRecordVer;
     876             : }
     877             : 
     878             : //-------------------------------------------------------------------------
     879             : 
     880             : inline bool SfxSingleRecordReader::HasVersion( sal_uInt16 nVersion ) const
     881             : 
     882             : /*  [Beschreibung]
     883             : 
     884             :     Stellt fest, ob der aus dem Stream gelese Record in der Version
     885             :     'nVersion' oder h"oher vorliegt.
     886             : */
     887             : 
     888             : {
     889             :     return _nRecordVer >= nVersion;
     890             : }
     891             : 
     892             : //=========================================================================
     893             : 
     894       25972 : inline SfxMultiFixRecordWriter::~SfxMultiFixRecordWriter()
     895             : 
     896             : /*  [Beschreibung]
     897             : 
     898             :     Der Dtor der Klasse <SfxMultiFixRecordWriter> schlie\st den Record
     899             :     automatisch, falls <SfxMutiFixRecordWriter::Close()> nicht bereits
     900             :     explizit gerufen wurde.
     901             : */
     902             : 
     903             : {
     904             :     // wurde der Header noch nicht geschrieben oder mu\s er gepr"uft werden
     905       12986 :     if ( !_bHeaderOk )
     906           0 :         Close();
     907       12986 : }
     908             : 
     909             : //-------------------------------------------------------------------------
     910             : 
     911             : inline void SfxMultiFixRecordWriter::NewContent()
     912             : 
     913             : /*  [Beschreibung]
     914             : 
     915             :     Mit dieser Methode wird in den Record ein neuer Content eingef"ugt.
     916             :     Jeder, auch der 1. Record mu\s durch Aufruf dieser Methode eingeleitet
     917             :     werden.
     918             : */
     919             : 
     920             : {
     921             :     #ifdef DBG_UTIL
     922             :     sal_uLong nOldStartPos;
     923             :     // Startposition des aktuellen Contents merken - Achtung Subklassen!
     924             :     nOldStartPos = _nContentStartPos;
     925             :     #endif
     926             :     _nContentStartPos = _pStream->Tell();
     927             : 
     928             : #ifdef DBG_UTIL
     929             :     // ist ein vorhergehender Content vorhanden?
     930             :     if ( _nContentCount )
     931             :     {
     932             :         // pr"ufen, ob der vorhergehende die Soll-Gr"o\se eingehalten hat
     933             :         DBG_ASSERT( _nContentStartPos - nOldStartPos == _nContentSize,
     934             :                     "wrong content size detected" );
     935             :     }
     936             : #endif
     937             : 
     938             :     // Anzahl mitz"ahlen
     939             :     ++_nContentCount;
     940             : }
     941             : 
     942             : //=========================================================================
     943             : 
     944       10530 : inline SfxMultiMixRecordWriter::SfxMultiMixRecordWriter
     945             : (
     946             :     SvStream*       pStream,    // Stream, in dem der Record angelegt wird
     947             :     sal_uInt16          nRecordTag, // Gesamt-Record-Art-Kennung
     948             :     sal_uInt8           nRecordVer  // Gesamt-Record-Versions-Kennung
     949             : )
     950             : 
     951             : /*  [Beschreibung]
     952             : 
     953             :     Legt in 'pStream' einen 'SfxMultiMixRecord' an, f"ur dessen Contents
     954             :     je eine separate Kennung f"ur Art (Tag) und Version gespeichert wird.
     955             :     Die Gr"o\sen der einzelnen Contents werden automatisch ermittelt.
     956             : */
     957             : 
     958             : :   SfxMultiVarRecordWriter( SFX_REC_TYPE_MIXTAGS,
     959       10530 :                              pStream, nRecordTag, nRecordVer )
     960             : {
     961       10530 : }
     962             : 
     963             : //=========================================================================
     964             : 
     965             : inline void SfxMultiFixRecordWriter::Reset()
     966             : {
     967             :     _pStream->Seek( _nStartPos + SFX_REC_HEADERSIZE_MINI +
     968             :                                  SFX_REC_HEADERSIZE_SINGLE +
     969             :                                  SFX_REC_HEADERSIZE_MULTI );
     970             :     _bHeaderOk = false;
     971             : }
     972             : 
     973             : //=========================================================================
     974             : 
     975           0 : inline sal_uInt16 SfxMultiRecordReader::GetContentTag()
     976             : 
     977             : /*  [Beschreibung]
     978             : 
     979             :     Diese Methode liefert die Art-Kennung des zuletzt mit der Methode
     980             :     <SfxMultiRecordReder::GetContent()> ge"offneten Contents.
     981             : */
     982             : 
     983             : {
     984           0 :     return _nContentTag;
     985             : }
     986             : 
     987             : //-------------------------------------------------------------------------
     988             : 
     989             : inline sal_uInt8 SfxMultiRecordReader::GetContentVersion() const
     990             : 
     991             : /*  [Beschreibung]
     992             : 
     993             :     Diese Methode liefert die Version-Kennung des zuletzt mit der Methode
     994             :     <SfxMultiRecordReder::GetContent()> ge"offneten Contents.
     995             : */
     996             : 
     997             : {
     998             :     return _nContentVer;
     999             : }
    1000             : 
    1001             : //-------------------------------------------------------------------------
    1002             : 
    1003             : inline bool SfxMultiRecordReader::HasContentVersion( sal_uInt16 nVersion ) const
    1004             : 
    1005             : /*  [Beschreibung]
    1006             : 
    1007             :     Diese Methode stellt fest, ob die Version 'nVersion' in der Version des
    1008             :     zuletzt mit der Methode <SfxMultiRecordReder::GetContent()> ge"offneten
    1009             :     Contents enthalten ist.
    1010             : */
    1011             : 
    1012             : {
    1013             :     return _nContentVer >= nVersion;
    1014             : }
    1015             : 
    1016             : //-------------------------------------------------------------------------
    1017             : 
    1018             : inline sal_uInt32 SfxMultiRecordReader::ContentCount() const
    1019             : 
    1020             : /*  [Beschreibung]
    1021             : 
    1022             :     Diese Methode liefert die Anzahl im Record befindlichen Contents.
    1023             : */
    1024             : 
    1025             : {
    1026             :     return _nContentCount;
    1027             : }
    1028             : 
    1029             : #endif
    1030             : 
    1031             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10