summaryrefslogtreecommitdiff
path: root/include/svl/filerec.hxx
diff options
context:
space:
mode:
Diffstat (limited to 'include/svl/filerec.hxx')
-rw-r--r--include/svl/filerec.hxx1031
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: */