update credits
[LibreOffice.git] / include / svl / filerec.hxx
blobafc5f4632fd7109b402a9e729496012134c922cb
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #ifndef _SFXFILEREC_HXX
21 #define _SFXFILEREC_HXX
23 //=========================================================================
25 #include "svl/svldllapi.h"
26 #include <tools/debug.hxx>
27 #include <tools/stream.hxx>
28 #include <vector>
30 //------------------------------------------------------------------------
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
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
48 //------------------------------------------------------------------------
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
54 //------------------------------------------------------------------------
56 #ifndef DBG
57 #ifdef DBG_UTIL
58 #define DBG(x) x
59 #else
60 #define DBG(x)
61 #endif
62 #endif
64 //------------------------------------------------------------------------
66 /* [Fileformat]
68 Jeder Record beginnt mit einem Byte, dem sogenannten 'Pre-Tag'.
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:
74 0x01: SfxSingleRecord
75 0x02: SfxMultiFixRecord
76 0x03+0x04: SfxMultiVarRecord
77 0x07+0x08: SfxMultiMixRecord
78 (Alle weiteren Record-Typ-Kennungen sind reserviert.)
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.
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.
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.
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.
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.
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.
113 Struktur des Mini-Records:
115 1 sal_uInt8 Pre-Tag
116 3 sal_uInt8 OffsetToEndOfRec
117 OffsetToEndOfRec* 1 sal_uInt8 Content
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.
123 Struktur des Extended-Records:
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
133 (ContentSize = OffsetToEndOfRec - 8)
135 [Anmerkung]
137 Der Aufbau der Records wird wie folgt begr"undet:
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
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
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.
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.
162 [Erweiterungen]
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.
175 //------------------------------------------------------------------------
177 class SVL_DLLPUBLIC SfxMiniRecordWriter
179 /* [Beschreibung]
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.
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.
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!
195 [Fileformat]
197 1* sal_uInt8 Content-Tag (!= 0)
198 1* 3-sal_uInt8 OffsetToEndOfRec in Bytes
199 SizeOfContent* sal_uInt8 Content
201 [Beispiel]
204 SfxMiniRecordWriter aRecord( pStream, MY_TAG_X );
205 *aRecord << aMember1;
206 *aRecord << aMember2;
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'
217 public:
218 inline SfxMiniRecordWriter( SvStream *pStream,
219 sal_uInt8 nTag );
220 inline SfxMiniRecordWriter( SvStream *pStream, sal_uInt8 nTag,
221 sal_uInt32 nSize );
223 inline ~SfxMiniRecordWriter();
225 inline SvStream& operator*() const;
227 inline void Reset();
229 sal_uInt32 Close( bool bSeekToEndOfRec = true );
231 private:
232 // not implementend, not allowed
233 SfxMiniRecordWriter( const SfxMiniRecordWriter& );
234 SfxMiniRecordWriter& operator=(const SfxMiniRecordWriter&);
237 //------------------------------------------------------------------------
239 class SVL_DLLPUBLIC SfxMiniRecordReader
241 /* [Beschreibung]
243 Mit Instanzen dieser Klasse kann ein einfacher Record aus einem Stream
244 gelesen werden, der mit der Klasse <SfxRecordWriter> geschrieben wurde.
246 Es ist auch m"oglich, den Record zu "uberspringen, ohne sein internes
247 Format zu kennen.
249 [Beispiel]
252 SfxMiniRecordReader aRecord( pStream );
253 switch ( aRecord.GetTag() )
255 case MY_TAG_X:
256 *aRecord >> aMember1;
257 *aRecord >> aMember2;
258 break;
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
272 // Drei-Phasen-Ctor f"ur Subklassen
273 SfxMiniRecordReader() {}
274 void Construct_Impl( SvStream *pStream, sal_uInt8 nTag )
276 _pStream = pStream;
277 _bSkipped = sal_False;
278 _nPreTag = nTag;
280 inline bool SetHeader_Impl( sal_uInt32 nHeader );
282 // als ung"ultig markieren und zur"uck-seeken
283 void SetInvalid_Impl( sal_uInt32 nRecordStartPos )
285 _nPreTag = SFX_REC_PRETAG_EOR;
286 _pStream->Seek( nRecordStartPos );
289 public:
290 SfxMiniRecordReader( SvStream *pStream, sal_uInt8 nTag );
291 inline ~SfxMiniRecordReader();
293 inline sal_uInt8 GetTag() const;
294 inline bool IsValid() const;
296 inline SvStream& operator*() const;
298 inline void Skip();
300 private:
301 // not implementend, not allowed
302 SfxMiniRecordReader( const SfxMiniRecordReader& );
303 SfxMiniRecordReader& operator=(const SfxMiniRecordReader&);
306 //------------------------------------------------------------------------
308 class SVL_DLLPUBLIC SfxSingleRecordWriter: public SfxMiniRecordWriter
310 /* [Beschreibung]
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.
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.
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!
326 [Fileformat]
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
337 protected:
338 SfxSingleRecordWriter( sal_uInt8 nRecordType,
339 SvStream *pStream,
340 sal_uInt16 nTag, sal_uInt8 nCurVer );
342 public:
343 inline void Reset();
345 sal_uInt32 Close( bool bSeekToEndOfRec = true );
348 //------------------------------------------------------------------------
350 class SVL_DLLPUBLIC SfxSingleRecordReader: public SfxMiniRecordReader
352 /* [Beschreibung]
354 Mit Instanzen dieser Klasse kann ein einfacher Record aus einem Stream
355 gelesen werden, der mit der Klasse <SfxSingleRecordWriter> geschrieben
356 wurde.
358 Es ist auch m"oglich, den Record zu "uberspringen, ohne sein internes
359 Format zu kennen.
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
368 // Drei-Phasen-Ctor f"ur Subklassen
369 SfxSingleRecordReader() {}
370 void Construct_Impl( SvStream *pStream )
372 SfxMiniRecordReader::Construct_Impl(
373 pStream, SFX_REC_PRETAG_EXT );
375 bool FindHeader_Impl( sal_uInt16 nTypes, sal_uInt16 nTag );
376 bool ReadHeader_Impl( sal_uInt16 nTypes );
378 public:
380 inline sal_uInt16 GetTag() const;
382 inline sal_uInt8 GetVersion() const;
383 inline bool HasVersion( sal_uInt16 nVersion ) const;
386 //------------------------------------------------------------------------
388 class SVL_DLLPUBLIC SfxMultiFixRecordWriter: public SfxSingleRecordWriter
390 /* [Beschreibung]
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.
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.
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.
409 [Fileformat]
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
422 [Beispiel]
425 SfxMultiFixRecordWriter aRecord( pStream, MY_TAG_X, MY_VERSION );
426 for ( sal_uInt16 n = 0; n < Count(); ++n )
428 aRecord.NewContent();
429 *aRecord << aMember1[n];
430 *aRecord << aMember2[n];
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
443 SfxMultiFixRecordWriter( sal_uInt8 nRecordType,
444 SvStream *pStream,
445 sal_uInt16 nTag,
446 sal_uInt8 nCurVer );
448 public:
449 inline ~SfxMultiFixRecordWriter();
451 inline void NewContent();
453 inline void Reset();
455 sal_uInt32 Close( bool bSeekToEndOfRec = true );
458 //------------------------------------------------------------------------
460 class SVL_DLLPUBLIC SfxMultiVarRecordWriter: public SfxMultiFixRecordWriter
462 /* [Beschreibung]
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.
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.
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!
479 [Fileformat]
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
491 NumberOfContents* sal_uInt32 ContentOfs (je per <<8 verschoben)
493 [Beispiel]
496 SfxMultiVarRecordWriter aRecord( pStream, MY_TAG_X, MY_VERSION );
497 for ( sal_uInt16 n = 0; n < Count(); ++n )
499 aRecord.NewContent();
500 *aRecord << aMember1[n];
501 *aRecord << aMember2[n];
507 protected:
508 std::vector<sal_uInt32> _aContentOfs;
509 sal_uInt16 _nContentVer; // nur f"ur SfxMultiMixRecordWriter
511 SfxMultiVarRecordWriter( sal_uInt8 nRecordType,
512 SvStream *pStream,
513 sal_uInt16 nRecordTag,
514 sal_uInt8 nRecordVer );
516 void FlushContent_Impl();
518 public:
519 SfxMultiVarRecordWriter( SvStream *pStream,
520 sal_uInt16 nRecordTag,
521 sal_uInt8 nRecordVer );
522 virtual ~SfxMultiVarRecordWriter();
524 void NewContent();
526 virtual sal_uInt32 Close( bool bSeekToEndOfRec = true );
529 //------------------------------------------------------------------------
531 class SVL_DLLPUBLIC SfxMultiMixRecordWriter: public SfxMultiVarRecordWriter
533 /* [Beschreibung]
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.
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.
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!
549 [Fileformat]
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
562 NumberOfContents* sal_uInt32 ( ContentOfs << 8 + Version )
566 public:
567 inline SfxMultiMixRecordWriter( SvStream *pStream,
568 sal_uInt16 nRecordTag,
569 sal_uInt8 nRecordVer );
571 void NewContent( sal_uInt16 nTag, sal_uInt8 nVersion );
573 // private: geht nicht, da einige Compiler dann auch vorherige privat machen
574 void NewContent()
575 { OSL_FAIL( "NewContent() only allowed with args" ); }
578 //------------------------------------------------------------------------
580 class SVL_DLLPUBLIC SfxMultiRecordReader: public SfxSingleRecordReader
582 /* [Beschreibung]
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.
589 Es ist auch m"oglich, den Record oder einzelne Contents zu "uberspringen,
590 ohne das jeweilis interne Format zu kennen.
592 [Beispiel]
595 SfxMultiRecordReader aRecord( pStream );
596 for ( sal_uInt16 nRecNo = 0; aRecord.GetContent(); ++nRecNo )
598 switch ( aRecord.GetTag() )
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;
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
626 bool ReadHeader_Impl();
628 public:
629 SfxMultiRecordReader( SvStream *pStream, sal_uInt16 nTag );
630 ~SfxMultiRecordReader();
632 bool GetContent();
633 inline sal_uInt16 GetContentTag();
634 inline sal_uInt8 GetContentVersion() const;
635 inline bool HasContentVersion( sal_uInt16 nVersion ) const;
637 inline sal_uInt32 ContentCount() const;
640 //=========================================================================
642 inline SfxMiniRecordWriter::SfxMiniRecordWriter
644 SvStream* pStream, // Stream, in dem der Record angelegt wird
645 sal_uInt8 nTag // Record-Tag zwischen 0x01 und 0xFE
648 /* [Beschreibung]
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.
655 : _pStream( pStream ),
656 _nStartPos( pStream->Tell() ),
657 _bHeaderOk(false),
658 _nPreTag( nTag )
660 DBG_ASSERT( _nPreTag != 0xFF, "invalid Tag" );
661 DBG( DbgOutf( "SfxFileRec: writing record to %ul", pStream->Tell() ) );
663 pStream->SeekRel( + SFX_REC_HEADERSIZE_MINI );
666 //-------------------------------------------------------------------------
668 inline SfxMiniRecordWriter::SfxMiniRecordWriter
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
675 /* [Beschreibung]
677 Legt in 'pStream' einen 'SfxMiniRecord' an, dessen Content-Gr"o\se
678 von vornherein bekannt ist.
681 : _pStream( pStream ),
682 // _nTag( uninitialized ),
683 // _nStarPos( uninitialized ),
684 _bHeaderOk(true)
686 DBG_ASSERT( nTag != 0 && nTag != 0xFF, "invalid Tag" );
687 DBG(_nStartPos = pStream->Tell());
688 DBG( DbgOutf( "SfxFileRec: writing record to %ul", _nStartPos ) );
690 *pStream << ( ( nTag << 24 ) | nSize );
693 //-------------------------------------------------------------------------
695 inline SfxMiniRecordWriter::~SfxMiniRecordWriter()
697 /* [Beschreibung]
699 Der Dtor der Klasse <SfxMiniRecordWriter> schlie\st den Record
700 automatisch, falls <SfxMiniRecordWriter::Close()> nicht bereits
701 explizit gerufen wurde.
705 // wurde der Header noch nicht geschrieben oder mu\s er gepr"uft werden
706 if ( !_bHeaderOk )
707 Close();
710 //-------------------------------------------------------------------------
712 inline SvStream& SfxMiniRecordWriter::operator*() const
714 /* [Beschreibung]
716 Dieser Operator liefert den Stream, in dem der Record liegt.
717 Der Record darf noch nicht geschlossen worden sein.
721 DBG_ASSERT( !_bHeaderOk, "getting Stream of closed record" );
722 return *_pStream;
725 //-------------------------------------------------------------------------
727 inline void SfxMiniRecordWriter::Reset()
729 _pStream->Seek( _nStartPos + SFX_REC_HEADERSIZE_MINI );
730 _bHeaderOk = false;
733 //=========================================================================
735 inline SfxMiniRecordReader::~SfxMiniRecordReader()
737 /* [Beschreibung]
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.
745 // noch nicht explizit ans Ende gesprungen?
746 if ( !_bSkipped )
747 Skip();
750 //-------------------------------------------------------------------------
752 inline void SfxMiniRecordReader::Skip()
754 /* [Beschreibung]
756 Mit dieser Methode wird der Stream direkt hinter das Ende des Records
757 positioniert.
761 _pStream->Seek(_nEofRec);
762 _bSkipped = sal_True;
765 //-------------------------------------------------------------------------
767 inline sal_uInt8 SfxMiniRecordReader::GetTag() const
769 /* [Beschreibung]
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.
779 return _nPreTag;
782 //-------------------------------------------------------------------------
784 inline bool SfxMiniRecordReader::IsValid() const
786 /* [Beschreibung]
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.
794 return _nPreTag != SFX_REC_PRETAG_EOR;
797 //-------------------------------------------------------------------------
799 inline SvStream& SfxMiniRecordReader::operator*() const
801 /* [Beschreibung]
803 Dieser Operator liefert den Stream in dem der Record liegt.
804 Die aktuelle Position des Streams mu\s innerhalb des Records liegen.
808 DBG_ASSERT( _pStream->Tell() < _nEofRec, "read behind record" );
809 return *_pStream;
812 //=========================================================================
814 inline sal_uInt32 SfxSingleRecordWriter::Close( bool bSeekToEndOfRec )
816 // siehe <SfxMiniRecordWriter::Close(bool)>
819 sal_uInt32 nRet = 0;
821 // wurde der Header noch nicht geschrieben?
822 if ( !_bHeaderOk )
824 // Basisklassen-Header schreiben
825 sal_uInt32 nEndPos = SfxMiniRecordWriter::Close( bSeekToEndOfRec );
827 // ggf. ans Ende des eigenen Headers seeken oder hinter Rec bleiben
828 if ( !bSeekToEndOfRec )
829 _pStream->SeekRel( SFX_REC_HEADERSIZE_SINGLE );
830 nRet = nEndPos;
832 #ifdef DBG_UTIL
833 else
834 // Basisklassen-Header pr"ufen
835 SfxMiniRecordWriter::Close( bSeekToEndOfRec );
836 #endif
838 // Record war bereits geschlossen
839 // nRet = 0;
840 return nRet;
843 //-------------------------------------------------------------------------
845 inline void SfxSingleRecordWriter::Reset()
847 _pStream->Seek( _nStartPos + SFX_REC_HEADERSIZE_MINI +
848 SFX_REC_HEADERSIZE_SINGLE );
849 _bHeaderOk = false;
852 //=========================================================================
854 inline sal_uInt16 SfxSingleRecordReader::GetTag() const
856 /* [Beschreibung]
858 Liefert des aus dem Header gelesene Tag f"ur den Gesamt-Record.
862 return _nRecordTag;
865 //-------------------------------------------------------------------------
867 inline sal_uInt8 SfxSingleRecordReader::GetVersion() const
869 /* [Beschreibung]
871 Liefert die Version des aus dem Stream gelesenen Records.
875 return _nRecordVer;
878 //-------------------------------------------------------------------------
880 inline bool SfxSingleRecordReader::HasVersion( sal_uInt16 nVersion ) const
882 /* [Beschreibung]
884 Stellt fest, ob der aus dem Stream gelese Record in der Version
885 'nVersion' oder h"oher vorliegt.
889 return _nRecordVer >= nVersion;
892 //=========================================================================
894 inline SfxMultiFixRecordWriter::~SfxMultiFixRecordWriter()
896 /* [Beschreibung]
898 Der Dtor der Klasse <SfxMultiFixRecordWriter> schlie\st den Record
899 automatisch, falls <SfxMutiFixRecordWriter::Close()> nicht bereits
900 explizit gerufen wurde.
904 // wurde der Header noch nicht geschrieben oder mu\s er gepr"uft werden
905 if ( !_bHeaderOk )
906 Close();
909 //-------------------------------------------------------------------------
911 inline void SfxMultiFixRecordWriter::NewContent()
913 /* [Beschreibung]
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.
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();
928 #ifdef DBG_UTIL
929 // ist ein vorhergehender Content vorhanden?
930 if ( _nContentCount )
932 // pr"ufen, ob der vorhergehende die Soll-Gr"o\se eingehalten hat
933 DBG_ASSERT( _nContentStartPos - nOldStartPos == _nContentSize,
934 "wrong content size detected" );
936 #endif
938 // Anzahl mitz"ahlen
939 ++_nContentCount;
942 //=========================================================================
944 inline SfxMultiMixRecordWriter::SfxMultiMixRecordWriter
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
951 /* [Beschreibung]
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.
958 : SfxMultiVarRecordWriter( SFX_REC_TYPE_MIXTAGS,
959 pStream, nRecordTag, nRecordVer )
963 //=========================================================================
965 inline void SfxMultiFixRecordWriter::Reset()
967 _pStream->Seek( _nStartPos + SFX_REC_HEADERSIZE_MINI +
968 SFX_REC_HEADERSIZE_SINGLE +
969 SFX_REC_HEADERSIZE_MULTI );
970 _bHeaderOk = false;
973 //=========================================================================
975 inline sal_uInt16 SfxMultiRecordReader::GetContentTag()
977 /* [Beschreibung]
979 Diese Methode liefert die Art-Kennung des zuletzt mit der Methode
980 <SfxMultiRecordReder::GetContent()> ge"offneten Contents.
984 return _nContentTag;
987 //-------------------------------------------------------------------------
989 inline sal_uInt8 SfxMultiRecordReader::GetContentVersion() const
991 /* [Beschreibung]
993 Diese Methode liefert die Version-Kennung des zuletzt mit der Methode
994 <SfxMultiRecordReder::GetContent()> ge"offneten Contents.
998 return _nContentVer;
1001 //-------------------------------------------------------------------------
1003 inline bool SfxMultiRecordReader::HasContentVersion( sal_uInt16 nVersion ) const
1005 /* [Beschreibung]
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.
1013 return _nContentVer >= nVersion;
1016 //-------------------------------------------------------------------------
1018 inline sal_uInt32 SfxMultiRecordReader::ContentCount() const
1020 /* [Beschreibung]
1022 Diese Methode liefert die Anzahl im Record befindlichen Contents.
1026 return _nContentCount;
1029 #endif
1031 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */