diff options
Diffstat (limited to 'include/svl/filerec.hxx')
-rw-r--r-- | include/svl/filerec.hxx | 1031 |
1 files changed, 1031 insertions, 0 deletions
diff --git a/include/svl/filerec.hxx b/include/svl/filerec.hxx new file mode 100644 index 000000000000..afc5f4632fd7 --- /dev/null +++ b/include/svl/filerec.hxx @@ -0,0 +1,1031 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#ifndef _SFXFILEREC_HXX +#define _SFXFILEREC_HXX + +//========================================================================= + +#include "svl/svldllapi.h" +#include <tools/debug.hxx> +#include <tools/stream.hxx> +#include <vector> + +//------------------------------------------------------------------------ + +#define SFX_REC_PRETAG_EXT sal_uInt8(0x00) // Pre-Tag f"ur Extended-Records +#define SFX_REC_PRETAG_EOR sal_uInt8(0xFF) // Pre-Tag f"ur End-Of-Records + +#define SFX_REC_TYPE_NONE sal_uInt8(0x00) // unbekannter Record-Typ +#define SFX_REC_TYPE_FIRST sal_uInt8(0x01) +#define SFX_REC_TYPE_SINGLE sal_uInt8(0x01) // Single-Content-Record +#define SFX_REC_TYPE_FIXSIZE sal_uInt8(0x02) // Fix-Size-Multi-Content-Record +#define SFX_REC_TYPE_VARSIZE_RELOC sal_uInt8(0x03) // variable Rec-Size +#define SFX_REC_TYPE_VARSIZE sal_uInt8(0x04) // alt (nicht verschiebbar) +#define SFX_REC_TYPE_MIXTAGS_RELOC sal_uInt8(0x07) // Mixed Tag Content-Record +#define SFX_REC_TYPE_MIXTAGS sal_uInt8(0x08) // alt (nicht verschiebbar) +#define SFX_REC_TYPE_LAST sal_uInt8(0x08) +#define SFX_REC_TYPE_MINI 0x100 // Mini-Record +#define SFX_REC_TYPE_DRAWENG 0x400 // Drawing-Engine-Record +#define SFX_REC_TYPE_EOR 0xF00 // End-Of-Records + +//------------------------------------------------------------------------ + +#define SFX_REC_HEADERSIZE_MINI 4 // Gr"o\se des Mini-Record-Headers +#define SFX_REC_HEADERSIZE_SINGLE 4 // zzgl. HEADERSIZE_MINI => 8 +#define SFX_REC_HEADERSIZE_MULTI 6 // zzgl. HEADERSIZE_SINGLE => 14 + +//------------------------------------------------------------------------ + +#ifndef DBG +#ifdef DBG_UTIL +#define DBG(x) x +#else +#define DBG(x) +#endif +#endif + +//------------------------------------------------------------------------ + +/* [Fileformat] + + Jeder Record beginnt mit einem Byte, dem sogenannten 'Pre-Tag'. + + Ist dieses 'Pre-Tag' == 0x00, dann handelt es sich um einen Extended- + Record, dessen Typ durch ein weiteres Byte an Position 5 n�her + beschrieben wird: + + 0x01: SfxSingleRecord + 0x02: SfxMultiFixRecord + 0x03+0x04: SfxMultiVarRecord + 0x07+0x08: SfxMultiMixRecord + (Alle weiteren Record-Typ-Kennungen sind reserviert.) + + I.d.R. werden File-Formate schon aus Performance-Gr"unden so aufgebaut, + da\s beim Lesen jeweils vorher schon feststeht, welcher Record-Typ + vorliegt. Diese Kennung dient daher hautps"achlich der "Uberpr"ufung + und File-Viewern, die das genaue File-Format (unterhalb der Records) + nicht kennen. + + Der 'SfxMiniRecordReader' verf"ugt dazu auch "uber eine statische + Methode 'ScanRecordType()', mit der festgestellt werden kann, welcher + Record-Typ in dem "ubergebenen Stream zu finden ist. + + Ein 'Pre-Tag' mit dem Wert 0xFF ist als Terminator reserviert. + Terminatoren werden verwendet, um das Suchen nach einem speziellen + Record zu terminieren, d.h. ist er bis dorthin nicht gefunden, wird + auch nicht weitergesucht. + + Bei allen anderen Werten des 'Pre-Tags' (also von 0x01 bis 0xFE) + handelt es sich um einen zum SW3 kompatbilen Record, der hier + 'SfxMiniRecord' genannt wird, er kann daher mit einem <SfxMiniRecordReader> + gelesen werden. + + Beginnt ein Record mit 0x44 k"onnte es sich um einen Drawing-Engine- + Record handeln. Dies ist dann der Fall, wenn die folgenden drei Bytes + die Zeichenkette 'RMD' bzw. 'RVW' ergeben (zusammen mit 'D'==0x44 + ergibt dies die K"urzel f"ur 'DRaw-MoDel' bzw. 'DRaw-VieW'). Records + dieser Art k"onnen von den hier dargestellten Klassen weder gelesen, + noch in irgendeiner Weise interpretiert werden. Einzig die Methode + 'ScanRecordType()' kann sie erkennen - weitere Behandlung obliegt + jedoch der Anwendungsprogrammierung. + + Diese drei Bytes an den Positionen 2 bis 4 enthalten normalerweise + die Gr"o\se des Records ohne Pre-Tag und Gr"o\sen-Bytes selbst, + also die Restgr"o\se nach diesem 4-Byte-Header. + + Struktur des Mini-Records: + + 1 sal_uInt8 Pre-Tag + 3 sal_uInt8 OffsetToEndOfRec + OffsetToEndOfRec* 1 sal_uInt8 Content + + Bei den Extended-Reords folgt auf diesen 4-Byte-Header ein erweiterter + Header, der zun"achst den o.g. Record-Typ, dann eine Versions-Kennung + sowie ein Tag enth"alt, welches den Inhalt kennzeichnet. + + Struktur des Extended-Records: + + 1 sal_uInt8 Pre-Tag (==0x00) + 3 sal_uInt8 OffsetToEndOfRec + OffsetToEndOfRec* 1 sal_uInt8 Content + 1 sal_uInt8 Record-Type + 1 sal_uInt8 Version + 2 sal_uInt8 Tag + ContentSize* 1 sal_uInt8 Content + + (ContentSize = OffsetToEndOfRec - 8) + + [Anmerkung] + + Der Aufbau der Records wird wie folgt begr"undet: + + Der SW-Record-Typ war zuerst vorhanden, mu\ste also 1:1 "ubernommen + werden. Zum Gl"uck wurden einige Record-Tags nicht verwendet, (Z.B. + 0x00 und 0xFF). + => 1. Byte 0x00 kann als Kennung f"ur erweiterten Record verwendet werden + => 1. Byte 0xFF kann f"ur besondere Zwecke verwendet werden + + Egal welcher Record-Typ vorliegt, sollte eine Erkennung des Typs, ein + Auslesen des Headers und ein "uberpspringen des Records m"oglich sein, + ohne zu"uck-seeken zu m"ussen und ohne "uberfl"ussige Daten lesen zu + m"ussen. + => die Bytes 2-4 werden bei allen Records als Offset zum Ende des + Records interpretiert, so da\s die Gesamt-Recors-Size sich wie + folgt berechnet: sizeof(sal_uInt32) + OffsetToEndOfRec + + Die Records sollten einfach zu parsen un einheitlich aufgebaut sein. + => Sie bauen aufeinander auf, so ist z.B. der SfxMiniRecord in jedem + anderen enthalten. + + Die Records sollten auch von denen der Drawing Enginge unterscheidbar + sein. Diese beginnen mit 'DRMD' und 'DRVW'. + => Mini-Records mit dem Pre-Tag 'D' d"urfen maximal 4MB gro\s sein, + um nicht in diesen Kennungs-Bereich zu reichen. + + [Erweiterungen] + + Es ist geplant das File-Format so zu erweitern, da\s das High-Nibble + des Record-Typs der erweiterten Records besondere Aufgaben "ubernehmen + soll. Zum Beispiel ist geplant, Record-Contents als 'nur aus Records + bestehend' zu kennzeichnen. Ein File-Viewer k"onnte sich dann automatisch + durch solche Strukturen 'hangeln', ohne Gefahr zu laufen, auf Daten + zu sto\sen, die sich zwar als Records interpretieren lassen, aber + tats"achlis als 'flache' Daten geschrieben wurden. Die m"ogliche + Erweiterung wird schon jetzt insofern vorbereitet, als da\s das + High-Nibble des Typs bei Vergleichen nicht ber"ucksichtigt wird. +*/ + +//------------------------------------------------------------------------ + +class SVL_DLLPUBLIC SfxMiniRecordWriter + +/* [Beschreibung] + + Mit Instanzen dieser Klasse kann ein einfacher Record in einen Stream + geschrieben werden, der sich durch ein sal_uInt8-Tag identifiziert, sowie + seine eigene L"ange speichert und somit auch von "alteren Versionen + bzw. Readern, die diesen Record-Type (Tag) nicht kennen, "ubersprungen + werden kann. Es wird keine Version-Nummer gespeichert. + + Alternativ kann die Gr"o\se fest angegeben werden oder sie wird + automatisch aus der Differenz der Tell()-Angaben vor und nach dem + Streamen des Inhalts ermittelt. + + Um Auf- und Abw"artskompatiblit"at gew"ahrleisten zu k"onnen, m"ussen + neue Versionen die Daten der "alteren immer komplett enthalten, + es d"urfen allenfalls neue Daten hintenan geh"angt werden! + + [Fileformat] + + 1* sal_uInt8 Content-Tag (!= 0) + 1* 3-sal_uInt8 OffsetToEndOfRec in Bytes + SizeOfContent* sal_uInt8 Content + + [Beispiel] + + { + SfxMiniRecordWriter aRecord( pStream, MY_TAG_X ); + *aRecord << aMember1; + *aRecord << aMember2; + } +*/ + +{ +protected: + SvStream* _pStream; // <SvStream>, in dem der Record liegt + sal_uInt32 _nStartPos; // Start-Position des Gesamt-Records im Stream + bool _bHeaderOk; /* TRUE, wenn der Header schon geschrieben ist; */ + sal_uInt8 _nPreTag; // in den Header zu schreibendes 'Pre-Tag' + +public: + inline SfxMiniRecordWriter( SvStream *pStream, + sal_uInt8 nTag ); + inline SfxMiniRecordWriter( SvStream *pStream, sal_uInt8 nTag, + sal_uInt32 nSize ); + + inline ~SfxMiniRecordWriter(); + + inline SvStream& operator*() const; + + inline void Reset(); + + sal_uInt32 Close( bool bSeekToEndOfRec = true ); + +private: + // not implementend, not allowed + SfxMiniRecordWriter( const SfxMiniRecordWriter& ); + SfxMiniRecordWriter& operator=(const SfxMiniRecordWriter&); +}; + +//------------------------------------------------------------------------ + +class SVL_DLLPUBLIC SfxMiniRecordReader + +/* [Beschreibung] + + Mit Instanzen dieser Klasse kann ein einfacher Record aus einem Stream + gelesen werden, der mit der Klasse <SfxRecordWriter> geschrieben wurde. + + Es ist auch m"oglich, den Record zu "uberspringen, ohne sein internes + Format zu kennen. + + [Beispiel] + + { + SfxMiniRecordReader aRecord( pStream ); + switch ( aRecord.GetTag() ) + { + case MY_TAG_X: + *aRecord >> aMember1; + *aRecord >> aMember2; + break; + + ... + } + } +*/ + +{ +protected: + SvStream* _pStream; // <SvStream>, aus dem gelesen wird + sal_uInt32 _nEofRec; // Position direkt hinter dem Record + bool _bSkipped; // TRUE: der Record wurde explizit geskippt + sal_uInt8 _nPreTag; // aus dem Header gelesenes Pre-Tag + + // Drei-Phasen-Ctor f"ur Subklassen + SfxMiniRecordReader() {} + void Construct_Impl( SvStream *pStream, sal_uInt8 nTag ) + { + _pStream = pStream; + _bSkipped = sal_False; + _nPreTag = nTag; + } + inline bool SetHeader_Impl( sal_uInt32 nHeader ); + + // als ung"ultig markieren und zur"uck-seeken + void SetInvalid_Impl( sal_uInt32 nRecordStartPos ) + { + _nPreTag = SFX_REC_PRETAG_EOR; + _pStream->Seek( nRecordStartPos ); + } + +public: + SfxMiniRecordReader( SvStream *pStream, sal_uInt8 nTag ); + inline ~SfxMiniRecordReader(); + + inline sal_uInt8 GetTag() const; + inline bool IsValid() const; + + inline SvStream& operator*() const; + + inline void Skip(); + +private: + // not implementend, not allowed + SfxMiniRecordReader( const SfxMiniRecordReader& ); + SfxMiniRecordReader& operator=(const SfxMiniRecordReader&); +}; + +//------------------------------------------------------------------------ + +class SVL_DLLPUBLIC SfxSingleRecordWriter: public SfxMiniRecordWriter + +/* [Beschreibung] + + Mit Instanzen dieser Klasse kann ein Record in einen Stream geschrieben + werden, dessen einziger Inhalt sich durch ein sal_uInt16-Tag und eine + sal_uInt8-Versions-Nummer identifiziert, sowie seine eigene L"ange speichert + und somit auch von "alteren Versionen bzw. Readern, die diesen + Record-Type (Tag) nicht kennen, "ubersprungen werden kann. + + Alternativ kann die Gr"o\se fest angegeben werden oder sie wird + automatisch aus der Differenz der Tell()-Angaben vor und nach dem + Streamen des Inhalts ermittelt. + + Um Auf- und Abw"artskompatiblit"at gew"ahrleisten zu k"onnen, m"ussen + neue Versionen die Daten der "alteren immer komplett enthalten, + es d"urfen allenfalls neue Daten hintenan geh"angt werden! + + [Fileformat] + + 1* sal_uInt8 Pre-Tag (!= 0) + 1* 3-sal_uInt8 OffsetToEndOfRec in Bytes + 1* sal_uInt8 Record-Type (==SFX_REC_TYPE_SINGLE) + 1* sal_uInt8 Content-Version + 1* sal_uInt16 Content-Tag + SizeOfContent* sal_uInt8 Content +*/ + +{ +protected: + SfxSingleRecordWriter( sal_uInt8 nRecordType, + SvStream *pStream, + sal_uInt16 nTag, sal_uInt8 nCurVer ); + +public: + inline void Reset(); + + sal_uInt32 Close( bool bSeekToEndOfRec = true ); +}; + +//------------------------------------------------------------------------ + +class SVL_DLLPUBLIC SfxSingleRecordReader: public SfxMiniRecordReader + +/* [Beschreibung] + + Mit Instanzen dieser Klasse kann ein einfacher Record aus einem Stream + gelesen werden, der mit der Klasse <SfxSingleRecordWriter> geschrieben + wurde. + + Es ist auch m"oglich, den Record zu "uberspringen, ohne sein internes + Format zu kennen. +*/ + +{ +protected: + sal_uInt16 _nRecordTag; // Art des Gesamt-Inhalts + sal_uInt8 _nRecordVer; // Version des Gesamt-Inhalts + sal_uInt8 _nRecordType; // Record Type aus dem Header + + // Drei-Phasen-Ctor f"ur Subklassen + SfxSingleRecordReader() {} + void Construct_Impl( SvStream *pStream ) + { + SfxMiniRecordReader::Construct_Impl( + pStream, SFX_REC_PRETAG_EXT ); + } + bool FindHeader_Impl( sal_uInt16 nTypes, sal_uInt16 nTag ); + bool ReadHeader_Impl( sal_uInt16 nTypes ); + +public: + + inline sal_uInt16 GetTag() const; + + inline sal_uInt8 GetVersion() const; + inline bool HasVersion( sal_uInt16 nVersion ) const; +}; + +//------------------------------------------------------------------------ + +class SVL_DLLPUBLIC SfxMultiFixRecordWriter: public SfxSingleRecordWriter + +/* [Beschreibung] + + Mit Instanzen dieser Klasse kann ein Record in einen Stream geschrieben + werden, der seine eigene L"ange speichert und somit auch von "alteren + Versionen bzw. Readern, die diesen Record-Type (Tag) nicht kennen, + "ubersprungen werden kann. + + Er enth"alt mehrere Inhalte von demselben Typ (Tag) und derselben + Version, die einmalig (stellvertretend f"ur alle) im Header des Records + identifiziert werden. Alle Inhalte haben eine vorher bekannte und + identische L"ange. + + Um Auf- und Abw"artskompatiblit"at gew"ahrleisten zu k"onnen, m"ussen + neue Versionen die Daten der "alteren immer komplett enthalten, + es d"urfen allenfalls neue Daten hinten angeh"angt werden! Hier sind + damit selbstverst"andlich nur die Daten der einzelnen Inhalte gemeint, + die Anzahl der Inhalte ist selbstverst"andlich variabel und sollte + von lesenden Applikationen auch so behandelt werden. + + [Fileformat] + + 1* sal_uInt8 Pre-Tag (==0) + 1* 3-sal_uInt8 OffsetToEndOfRec in Bytes + 1* sal_uInt8 Record-Type (==SFX_REC_TYPE_FIXSIZE) + 1* sal_uInt8 Content-Version + 1* sal_uInt16 Content-Tag + 1* sal_uInt16 NumberOfContents + 1* sal_uInt32 SizeOfEachContent + NumberOfContents* ( + SizeOfEachContent sal_uInt8 Content + ) + + [Beispiel] + + { + SfxMultiFixRecordWriter aRecord( pStream, MY_TAG_X, MY_VERSION ); + for ( sal_uInt16 n = 0; n < Count(); ++n ) + { + aRecord.NewContent(); + *aRecord << aMember1[n]; + *aRecord << aMember2[n]; + } + } +*/ + +{ +protected: + sal_uInt32 _nContentStartPos; /* Startposition des jeweiligen + Contents - nur bei DBG_UTIL + und f"ur Subklassen */ + sal_uInt32 _nContentSize; // Gr"o\se jedes Contents + sal_uInt16 _nContentCount; // jeweilige Anzahl der Contents + + SfxMultiFixRecordWriter( sal_uInt8 nRecordType, + SvStream *pStream, + sal_uInt16 nTag, + sal_uInt8 nCurVer ); + +public: + inline ~SfxMultiFixRecordWriter(); + + inline void NewContent(); + + inline void Reset(); + + sal_uInt32 Close( bool bSeekToEndOfRec = true ); +}; + +//------------------------------------------------------------------------ + +class SVL_DLLPUBLIC SfxMultiVarRecordWriter: public SfxMultiFixRecordWriter + +/* [Beschreibung] + + Mit Instanzen dieser Klasse kann ein Record in einen Stream geschrieben + werden, der seine eigene L"ange speichert und somit auch von "alteren + Versionen bzw. Readern, die diesen Record-Type (Tag) nicht kennen, + "ubersprungen werden kann. + + Er enth"alt mehrere Inhalte von demselben Typ (Tag) und derselben + Version, die einmalig (stellvertretend f"ur alle) im Header des Records + identifiziert werden. Die L"ange f"ur jeden einzelnen Inhalt wird + automatisch berechnet und gespeichert, so da\s auch einzelne Inhalte + "ubersprungen werden k"onnen, ohne sie interpretieren zu m"ussen. + + Um Auf- und Abw"artskompatiblit"at gew"ahrleisten zu k"onnen, m"ussen + neue Versionen die Daten der "alteren immer komplett enthalten, + es d"urfen allenfalls neue Daten hinten angeh"angt werden! + + [Fileformat] + + 1* sal_uInt8 Pre-Tag (==0) + 1* 3-sal_uInt8 OffsetToEndOfRec in Bytes + 1* sal_uInt8 Record-Type (==SFX_FILETYPE_TYPE_VARSIZE) + 1* sal_uInt8 Content-Version + 1* sal_uInt16 Content-Tag + 1* sal_uInt16 NumberOfContents + 1* sal_uInt32 OffsetToOfsTable + NumberOfContents* ( + ContentSize* sal_uInt8 Content + ) + NumberOfContents* sal_uInt32 ContentOfs (je per <<8 verschoben) + + [Beispiel] + + { + SfxMultiVarRecordWriter aRecord( pStream, MY_TAG_X, MY_VERSION ); + for ( sal_uInt16 n = 0; n < Count(); ++n ) + { + aRecord.NewContent(); + *aRecord << aMember1[n]; + *aRecord << aMember2[n]; + } + } +*/ + +{ +protected: + std::vector<sal_uInt32> _aContentOfs; + sal_uInt16 _nContentVer; // nur f"ur SfxMultiMixRecordWriter + + SfxMultiVarRecordWriter( sal_uInt8 nRecordType, + SvStream *pStream, + sal_uInt16 nRecordTag, + sal_uInt8 nRecordVer ); + + void FlushContent_Impl(); + +public: + SfxMultiVarRecordWriter( SvStream *pStream, + sal_uInt16 nRecordTag, + sal_uInt8 nRecordVer ); + virtual ~SfxMultiVarRecordWriter(); + + void NewContent(); + + virtual sal_uInt32 Close( bool bSeekToEndOfRec = true ); +}; + +//------------------------------------------------------------------------ + +class SVL_DLLPUBLIC SfxMultiMixRecordWriter: public SfxMultiVarRecordWriter + +/* [Beschreibung] + + Mit Instanzen dieser Klasse kann ein Record in einen Stream geschrieben + werden, der seine eigene L"ange speichert und somit auch von "alteren + Versionen bzw. Readern, die diesen Record-Type (Tag) nicht kennen, + "ubersprungen werden kann. + + Er enth"alt mehrere Inhalte von demselben Typ (Tag) und derselben + Version, die einmalig (stellvertretend f"ur alle) im Header des Records + identifiziert werden. Alle Inhalte haben eine vorher bekannte und + identische L"ange. + + Um Auf- und Abw"artskompatiblit"at gew"ahrleisten zu k"onnen, m"ussen + neue Versionen die Daten der "alteren immer komplett enthalten, + es d"urfen allenfalls neue Daten hinten angeh"angt werden! + + [Fileformat] + + 1* sal_uInt8 Pre-Tag (==0) + 1* 3-sal_uInt8 OffsetToEndOfRec in Bytes + 1* sal_uInt8 Record-Type (==SFX_REC_TYPE_MIXTAGS) + 1* sal_uInt8 Content-Version + 1* sal_uInt16 Record-Tag + 1* sal_uInt16 NumberOfContents + 1* sal_uInt32 OffsetToOfsTable + NumberOfContents* ( + 1* sal_uInt16 Content-Tag + ContentSize* sal_uInt8 Content + ) + NumberOfContents* sal_uInt32 ( ContentOfs << 8 + Version ) +*/ + +{ +public: + inline SfxMultiMixRecordWriter( SvStream *pStream, + sal_uInt16 nRecordTag, + sal_uInt8 nRecordVer ); + + void NewContent( sal_uInt16 nTag, sal_uInt8 nVersion ); + +// private: geht nicht, da einige Compiler dann auch vorherige privat machen + void NewContent() + { OSL_FAIL( "NewContent() only allowed with args" ); } +}; + +//------------------------------------------------------------------------ + +class SVL_DLLPUBLIC SfxMultiRecordReader: public SfxSingleRecordReader + +/* [Beschreibung] + + Mit Instanzen dieser Klasse kann ein aus mehreren Contents bestehender + Record aus einem Stream gelesen werden, der mit einer der Klassen + <SfxMultiFixRecordWriter>, <SfxMultiVarRecordWriter> oder + <SfxMultiMixRecordWriter> geschrieben wurde. + + Es ist auch m"oglich, den Record oder einzelne Contents zu "uberspringen, + ohne das jeweilis interne Format zu kennen. + + [Beispiel] + + { + SfxMultiRecordReader aRecord( pStream ); + for ( sal_uInt16 nRecNo = 0; aRecord.GetContent(); ++nRecNo ) + { + switch ( aRecord.GetTag() ) + { + case MY_TAG_X: + X *pObj = new X; + *aRecord >> pObj.>aMember1; + if ( aRecord.HasVersion(2) ) + *aRecord >> pObj->aMember2; + Append( pObj ); + break; + + ... + } + } + } +*/ + +{ + sal_uInt32 _nStartPos; // Start-Position des Records + sal_uInt32* _pContentOfs; // Offsets der Startpositionen + sal_uInt32 _nContentSize; // Size jedes einzelnen / Tabellen-Pos + sal_uInt16 _nContentCount; // Anzahl der Contents im Record + sal_uInt16 _nContentNo; /* der Index des aktuellen Contents + enth"alt jeweils den Index des + Contents, der beim n"achsten + GetContent() geholt wird */ + sal_uInt16 _nContentTag; // Art-Kennung des aktuellen Contents + sal_uInt8 _nContentVer; // Versions-Kennung des akt. Contents + + bool ReadHeader_Impl(); + +public: + SfxMultiRecordReader( SvStream *pStream, sal_uInt16 nTag ); + ~SfxMultiRecordReader(); + + bool GetContent(); + inline sal_uInt16 GetContentTag(); + inline sal_uInt8 GetContentVersion() const; + inline bool HasContentVersion( sal_uInt16 nVersion ) const; + + inline sal_uInt32 ContentCount() const; +}; + +//========================================================================= + +inline SfxMiniRecordWriter::SfxMiniRecordWriter +( + SvStream* pStream, // Stream, in dem der Record angelegt wird + sal_uInt8 nTag // Record-Tag zwischen 0x01 und 0xFE +) + +/* [Beschreibung] + + Legt in 'pStream' einen 'SfxMiniRecord' an, dessen Content-Gr"o\se + nicht bekannt ist, sondern nach dam Streamen des Contents errechnet + werden soll. +*/ + +: _pStream( pStream ), + _nStartPos( pStream->Tell() ), + _bHeaderOk(false), + _nPreTag( nTag ) +{ + DBG_ASSERT( _nPreTag != 0xFF, "invalid Tag" ); + DBG( DbgOutf( "SfxFileRec: writing record to %ul", pStream->Tell() ) ); + + pStream->SeekRel( + SFX_REC_HEADERSIZE_MINI ); +} + +//------------------------------------------------------------------------- + +inline SfxMiniRecordWriter::SfxMiniRecordWriter +( + SvStream* pStream, // Stream, in dem der Record angelegt wird + sal_uInt8 nTag, // Record-Tag zwischen 0x01 und 0xFE + sal_uInt32 nSize // Gr"o\se der Daten in Bytes +) + +/* [Beschreibung] + + Legt in 'pStream' einen 'SfxMiniRecord' an, dessen Content-Gr"o\se + von vornherein bekannt ist. +*/ + +: _pStream( pStream ), + // _nTag( uninitialized ), + // _nStarPos( uninitialized ), + _bHeaderOk(true) +{ + DBG_ASSERT( nTag != 0 && nTag != 0xFF, "invalid Tag" ); + DBG(_nStartPos = pStream->Tell()); + DBG( DbgOutf( "SfxFileRec: writing record to %ul", _nStartPos ) ); + + *pStream << ( ( nTag << 24 ) | nSize ); +} + +//------------------------------------------------------------------------- + +inline SfxMiniRecordWriter::~SfxMiniRecordWriter() + +/* [Beschreibung] + + Der Dtor der Klasse <SfxMiniRecordWriter> schlie\st den Record + automatisch, falls <SfxMiniRecordWriter::Close()> nicht bereits + explizit gerufen wurde. +*/ + +{ + // wurde der Header noch nicht geschrieben oder mu\s er gepr"uft werden + if ( !_bHeaderOk ) + Close(); +} + +//------------------------------------------------------------------------- + +inline SvStream& SfxMiniRecordWriter::operator*() const + +/* [Beschreibung] + + Dieser Operator liefert den Stream, in dem der Record liegt. + Der Record darf noch nicht geschlossen worden sein. +*/ + +{ + DBG_ASSERT( !_bHeaderOk, "getting Stream of closed record" ); + return *_pStream; +} + +//------------------------------------------------------------------------- + +inline void SfxMiniRecordWriter::Reset() +{ + _pStream->Seek( _nStartPos + SFX_REC_HEADERSIZE_MINI ); + _bHeaderOk = false; +} + +//========================================================================= + +inline SfxMiniRecordReader::~SfxMiniRecordReader() + +/* [Beschreibung] + + Der Dtor der Klasse <SfxMiniRecordReader> positioniert den Stream + automatisch auf die Position direkt hinter dem Record, falls nicht + <SfxMiniRecordReader::Skip()> bereits explizit gerufen wurde. +*/ + +{ + // noch nicht explizit ans Ende gesprungen? + if ( !_bSkipped ) + Skip(); +} + +//------------------------------------------------------------------------- + +inline void SfxMiniRecordReader::Skip() + +/* [Beschreibung] + + Mit dieser Methode wird der Stream direkt hinter das Ende des Records + positioniert. +*/ + +{ + _pStream->Seek(_nEofRec); + _bSkipped = sal_True; +} + +//------------------------------------------------------------------------- + +inline sal_uInt8 SfxMiniRecordReader::GetTag() const + +/* [Beschreibung] + + Liefert des aus dem Header gelesene Pre-Tag des Records. Dieses kann + auch SFX_REC_PRETAG_EXT oder SFX_REC_PRETAG_EOR sein, im + letzteren Fall ist am Stream der Fehlercode ERRCODE_IO_WRONGFORMAT + gesetzt. SFX_REC_PRETAG_EXT ist g"ultig, da diese extended-Records + nur eine Erweiterung des SfxMiniRecord darstellen. +*/ + +{ + return _nPreTag; +} + +//------------------------------------------------------------------------- + +inline bool SfxMiniRecordReader::IsValid() const + +/* [Beschreibung] + + Hiermit kann abgefragt werden, ob der Record erfolgreich aus dem + Stream konstruiert werden konnte, der Header also f"ur diesen Record-Typ + passend war. +*/ + +{ + return _nPreTag != SFX_REC_PRETAG_EOR; +} + +//------------------------------------------------------------------------- + +inline SvStream& SfxMiniRecordReader::operator*() const + +/* [Beschreibung] + + Dieser Operator liefert den Stream in dem der Record liegt. + Die aktuelle Position des Streams mu\s innerhalb des Records liegen. +*/ + +{ + DBG_ASSERT( _pStream->Tell() < _nEofRec, "read behind record" ); + return *_pStream; +} + +//========================================================================= + +inline sal_uInt32 SfxSingleRecordWriter::Close( bool bSeekToEndOfRec ) + +// siehe <SfxMiniRecordWriter::Close(bool)> + +{ + sal_uInt32 nRet = 0; + + // wurde der Header noch nicht geschrieben? + if ( !_bHeaderOk ) + { + // Basisklassen-Header schreiben + sal_uInt32 nEndPos = SfxMiniRecordWriter::Close( bSeekToEndOfRec ); + + // ggf. ans Ende des eigenen Headers seeken oder hinter Rec bleiben + if ( !bSeekToEndOfRec ) + _pStream->SeekRel( SFX_REC_HEADERSIZE_SINGLE ); + nRet = nEndPos; + } +#ifdef DBG_UTIL + else + // Basisklassen-Header pr"ufen + SfxMiniRecordWriter::Close( bSeekToEndOfRec ); +#endif + + // Record war bereits geschlossen +// nRet = 0; + return nRet; +} + +//------------------------------------------------------------------------- + +inline void SfxSingleRecordWriter::Reset() +{ + _pStream->Seek( _nStartPos + SFX_REC_HEADERSIZE_MINI + + SFX_REC_HEADERSIZE_SINGLE ); + _bHeaderOk = false; +} + +//========================================================================= + +inline sal_uInt16 SfxSingleRecordReader::GetTag() const + +/* [Beschreibung] + + Liefert des aus dem Header gelesene Tag f"ur den Gesamt-Record. +*/ + +{ + return _nRecordTag; +} + +//------------------------------------------------------------------------- + +inline sal_uInt8 SfxSingleRecordReader::GetVersion() const + +/* [Beschreibung] + + Liefert die Version des aus dem Stream gelesenen Records. +*/ + +{ + return _nRecordVer; +} + +//------------------------------------------------------------------------- + +inline bool SfxSingleRecordReader::HasVersion( sal_uInt16 nVersion ) const + +/* [Beschreibung] + + Stellt fest, ob der aus dem Stream gelese Record in der Version + 'nVersion' oder h"oher vorliegt. +*/ + +{ + return _nRecordVer >= nVersion; +} + +//========================================================================= + +inline SfxMultiFixRecordWriter::~SfxMultiFixRecordWriter() + +/* [Beschreibung] + + Der Dtor der Klasse <SfxMultiFixRecordWriter> schlie\st den Record + automatisch, falls <SfxMutiFixRecordWriter::Close()> nicht bereits + explizit gerufen wurde. +*/ + +{ + // wurde der Header noch nicht geschrieben oder mu\s er gepr"uft werden + if ( !_bHeaderOk ) + Close(); +} + +//------------------------------------------------------------------------- + +inline void SfxMultiFixRecordWriter::NewContent() + +/* [Beschreibung] + + Mit dieser Methode wird in den Record ein neuer Content eingef"ugt. + Jeder, auch der 1. Record mu\s durch Aufruf dieser Methode eingeleitet + werden. +*/ + +{ + #ifdef DBG_UTIL + sal_uLong nOldStartPos; + // Startposition des aktuellen Contents merken - Achtung Subklassen! + nOldStartPos = _nContentStartPos; + #endif + _nContentStartPos = _pStream->Tell(); + +#ifdef DBG_UTIL + // ist ein vorhergehender Content vorhanden? + if ( _nContentCount ) + { + // pr"ufen, ob der vorhergehende die Soll-Gr"o\se eingehalten hat + DBG_ASSERT( _nContentStartPos - nOldStartPos == _nContentSize, + "wrong content size detected" ); + } +#endif + + // Anzahl mitz"ahlen + ++_nContentCount; +} + +//========================================================================= + +inline SfxMultiMixRecordWriter::SfxMultiMixRecordWriter +( + SvStream* pStream, // Stream, in dem der Record angelegt wird + sal_uInt16 nRecordTag, // Gesamt-Record-Art-Kennung + sal_uInt8 nRecordVer // Gesamt-Record-Versions-Kennung +) + +/* [Beschreibung] + + Legt in 'pStream' einen 'SfxMultiMixRecord' an, f"ur dessen Contents + je eine separate Kennung f"ur Art (Tag) und Version gespeichert wird. + Die Gr"o\sen der einzelnen Contents werden automatisch ermittelt. +*/ + +: SfxMultiVarRecordWriter( SFX_REC_TYPE_MIXTAGS, + pStream, nRecordTag, nRecordVer ) +{ +} + +//========================================================================= + +inline void SfxMultiFixRecordWriter::Reset() +{ + _pStream->Seek( _nStartPos + SFX_REC_HEADERSIZE_MINI + + SFX_REC_HEADERSIZE_SINGLE + + SFX_REC_HEADERSIZE_MULTI ); + _bHeaderOk = false; +} + +//========================================================================= + +inline sal_uInt16 SfxMultiRecordReader::GetContentTag() + +/* [Beschreibung] + + Diese Methode liefert die Art-Kennung des zuletzt mit der Methode + <SfxMultiRecordReder::GetContent()> ge"offneten Contents. +*/ + +{ + return _nContentTag; +} + +//------------------------------------------------------------------------- + +inline sal_uInt8 SfxMultiRecordReader::GetContentVersion() const + +/* [Beschreibung] + + Diese Methode liefert die Version-Kennung des zuletzt mit der Methode + <SfxMultiRecordReder::GetContent()> ge"offneten Contents. +*/ + +{ + return _nContentVer; +} + +//------------------------------------------------------------------------- + +inline bool SfxMultiRecordReader::HasContentVersion( sal_uInt16 nVersion ) const + +/* [Beschreibung] + + Diese Methode stellt fest, ob die Version 'nVersion' in der Version des + zuletzt mit der Methode <SfxMultiRecordReder::GetContent()> ge"offneten + Contents enthalten ist. +*/ + +{ + return _nContentVer >= nVersion; +} + +//------------------------------------------------------------------------- + +inline sal_uInt32 SfxMultiRecordReader::ContentCount() const + +/* [Beschreibung] + + Diese Methode liefert die Anzahl im Record befindlichen Contents. +*/ + +{ + return _nContentCount; +} + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |