xref: /aoo42x/main/svl/source/filerec/filerec.cxx (revision 40df464e)
1*40df464eSAndrew Rist /**************************************************************
2cdf0e10cSrcweir  *
3*40df464eSAndrew Rist  * Licensed to the Apache Software Foundation (ASF) under one
4*40df464eSAndrew Rist  * or more contributor license agreements.  See the NOTICE file
5*40df464eSAndrew Rist  * distributed with this work for additional information
6*40df464eSAndrew Rist  * regarding copyright ownership.  The ASF licenses this file
7*40df464eSAndrew Rist  * to you under the Apache License, Version 2.0 (the
8*40df464eSAndrew Rist  * "License"); you may not use this file except in compliance
9*40df464eSAndrew Rist  * with the License.  You may obtain a copy of the License at
10*40df464eSAndrew Rist  *
11*40df464eSAndrew Rist  *   http://www.apache.org/licenses/LICENSE-2.0
12*40df464eSAndrew Rist  *
13*40df464eSAndrew Rist  * Unless required by applicable law or agreed to in writing,
14*40df464eSAndrew Rist  * software distributed under the License is distributed on an
15*40df464eSAndrew Rist  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16*40df464eSAndrew Rist  * KIND, either express or implied.  See the License for the
17*40df464eSAndrew Rist  * specific language governing permissions and limitations
18*40df464eSAndrew Rist  * under the License.
19*40df464eSAndrew Rist  *
20*40df464eSAndrew Rist  *************************************************************/
21*40df464eSAndrew Rist 
22*40df464eSAndrew Rist 
23cdf0e10cSrcweir 
24cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove
25cdf0e10cSrcweir #include "precompiled_svl.hxx"
26cdf0e10cSrcweir #include <svl/filerec.hxx>
27cdf0e10cSrcweir #include <osl/endian.h>
28cdf0e10cSrcweir 
29cdf0e10cSrcweir //========================================================================
30cdf0e10cSrcweir 
31cdf0e10cSrcweir SV_IMPL_VARARR( SfxUINT32s, sal_uInt32 );
32cdf0e10cSrcweir 
33cdf0e10cSrcweir //========================================================================
34cdf0e10cSrcweir 
35cdf0e10cSrcweir /*	Die folgenden Makros extrahieren Teilbereiche aus einem sal_uInt32 Wert.
36cdf0e10cSrcweir 	Diese sal_uInt32-Werte werden anstelle der einzelnen Werte gestreamt,
37cdf0e10cSrcweir 	um Calls zu sparen.
38cdf0e10cSrcweir */
39cdf0e10cSrcweir 
40cdf0e10cSrcweir #define SFX_REC_PRE(n) ( ((n) & 0x000000FF) )
41cdf0e10cSrcweir #define SFX_REC_OFS(n) ( ((n) & 0xFFFFFF00) >> 8 )
42cdf0e10cSrcweir #define SFX_REC_TYP(n) ( ((n) & 0x000000FF) )
43cdf0e10cSrcweir #define SFX_REC_VER(n) ( ((n) & 0x0000FF00) >> 8 )
44cdf0e10cSrcweir #define SFX_REC_TAG(n) ( ((n) & 0xFFFF0000) >> 16 )
45cdf0e10cSrcweir 
46cdf0e10cSrcweir #define SFX_REC_CONTENT_VER(n) ( ((n) & 0x000000FF) )
47cdf0e10cSrcweir #define SFX_REC_CONTENT_OFS(n) ( ((n) & 0xFFFFFF00) >> 8 )
48cdf0e10cSrcweir 
49cdf0e10cSrcweir //-------------------------------------------------------------------------
50cdf0e10cSrcweir 
51cdf0e10cSrcweir /*	Die folgenden Makros setzen Teilbereiche zu einem sal_uInt32 Wert zusammen.
52cdf0e10cSrcweir 	Diese sal_uInt32-Werte werden anstelle der einzelnen Werte gestreamt,
53cdf0e10cSrcweir 	um Calls zu sparen.
54cdf0e10cSrcweir */
55cdf0e10cSrcweir 
56cdf0e10cSrcweir #define SFX_REC_MINI_HEADER(nPreTag,nStartPos,nEndPos) \
57cdf0e10cSrcweir 					( sal_uInt32(nPreTag) | \
58cdf0e10cSrcweir 					  sal_uInt32(nEndPos-nStartPos-SFX_REC_HEADERSIZE_MINI) << 8 )
59cdf0e10cSrcweir 
60cdf0e10cSrcweir #define SFX_REC_HEADER(nRecType,nContentTag,nContentVer) \
61cdf0e10cSrcweir 					( sal_uInt32(nRecType) | \
62cdf0e10cSrcweir 					  ( sal_uInt32(nContentVer) << 8 ) | \
63cdf0e10cSrcweir 					  ( sal_uInt32(nContentTag) << 16 ) )
64cdf0e10cSrcweir 
65cdf0e10cSrcweir #define SFX_REC_CONTENT_HEADER(nContentVer,n1StStartPos,nCurStartPos) \
66cdf0e10cSrcweir 					( sal_uInt32(nContentVer) | \
67cdf0e10cSrcweir 					  sal_uInt32( nCurStartPos - n1StStartPos ) << 8 )
68cdf0e10cSrcweir 
69cdf0e10cSrcweir //=========================================================================
70cdf0e10cSrcweir 
Close(FASTBOOL bSeekToEndOfRec)71cdf0e10cSrcweir sal_uInt32 SfxMiniRecordWriter::Close
72cdf0e10cSrcweir (
73cdf0e10cSrcweir 	FASTBOOL	bSeekToEndOfRec 	/*	sal_True (default)
74cdf0e10cSrcweir 										Der Stream wird an das Ende des Records
75cdf0e10cSrcweir 										positioniert.
76cdf0e10cSrcweir 
77cdf0e10cSrcweir 										sal_False
78cdf0e10cSrcweir 										Der Stream wird an den Anfang des
79cdf0e10cSrcweir 										Contents (also hinter den Header)
80cdf0e10cSrcweir 										positioniert.
81cdf0e10cSrcweir 									*/
82cdf0e10cSrcweir )
83cdf0e10cSrcweir 
84cdf0e10cSrcweir /*	[Beschreibung]
85cdf0e10cSrcweir 
86cdf0e10cSrcweir 	Diese Methode schlie\st den Record. Dabei wird haupts"achlich der
87cdf0e10cSrcweir 	Header geschrieben.
88cdf0e10cSrcweir 
89cdf0e10cSrcweir 	Wurde der Header bereits geschrieben, hat der Aufruf keine Wirkung.
90cdf0e10cSrcweir 
91cdf0e10cSrcweir 
92cdf0e10cSrcweir 	[R"uckgabewert]
93cdf0e10cSrcweir 
94cdf0e10cSrcweir 	sal_uInt32		!= 0
95cdf0e10cSrcweir 				Position im Stream, die direkt hinter dem Record liegt.
96cdf0e10cSrcweir 				'bSeekToEndOfRecord==sal_True'
97cdf0e10cSrcweir 				=> R"uckgabewert == aktuelle Stream-Position nach Aufruf
98cdf0e10cSrcweir 
99cdf0e10cSrcweir 				== 0
100cdf0e10cSrcweir 				Der Header war bereits geschrieben worden.
101cdf0e10cSrcweir */
102cdf0e10cSrcweir 
103cdf0e10cSrcweir {
104cdf0e10cSrcweir 	// wurde der Header noch nicht geschrieben?
105cdf0e10cSrcweir 	if ( !_bHeaderOk )
106cdf0e10cSrcweir 	{
107cdf0e10cSrcweir 		// Header an den Anfang des Records schreiben
108cdf0e10cSrcweir 		sal_uInt32 nEndPos = _pStream->Tell();
109cdf0e10cSrcweir 		_pStream->Seek( _nStartPos );
110cdf0e10cSrcweir 		*_pStream << SFX_REC_MINI_HEADER( _nPreTag, _nStartPos, nEndPos );
111cdf0e10cSrcweir 
112cdf0e10cSrcweir 		// je nachdem ans Ende des Records seeken oder hinter Header bleiben
113cdf0e10cSrcweir 		if ( bSeekToEndOfRec )
114cdf0e10cSrcweir 			_pStream->Seek( nEndPos );
115cdf0e10cSrcweir 
116cdf0e10cSrcweir 		// Header wurde JETZT geschrieben
117cdf0e10cSrcweir 		_bHeaderOk = sal_True;
118cdf0e10cSrcweir 		return nEndPos;
119cdf0e10cSrcweir 	}
120cdf0e10cSrcweir #ifdef DBG_UTIL
121cdf0e10cSrcweir 	// mu\s Fix-Size-Record gepr"uft werden?
122cdf0e10cSrcweir 	else if ( SFX_BOOL_DONTCARE == _bHeaderOk )
123cdf0e10cSrcweir 	{
124cdf0e10cSrcweir 		// Header auslesen, um Soll-Gr"o\se zu bestimmen
125cdf0e10cSrcweir 		sal_uInt32 nEndPos = _pStream->Tell();
126cdf0e10cSrcweir 		_pStream->Seek( _nStartPos );
127cdf0e10cSrcweir 		sal_uInt32 nHeader;
128cdf0e10cSrcweir 		*_pStream >> nHeader;
129cdf0e10cSrcweir 		_pStream->Seek( nEndPos );
130cdf0e10cSrcweir 
131cdf0e10cSrcweir 		// Soll-Gr"o\se mit Ist-Gr"o\se vergleichen
132cdf0e10cSrcweir 		DBG_ASSERT( nEndPos - SFX_REC_OFS(nHeader) == _nStartPos + sizeof(sal_uInt32),
133cdf0e10cSrcweir 					"fixed record size incorrect" );
134cdf0e10cSrcweir 		DbgOutf( "SfxFileRec: written record until %ul", nEndPos );
135cdf0e10cSrcweir 	}
136cdf0e10cSrcweir #endif
137cdf0e10cSrcweir 
138cdf0e10cSrcweir 	// Record war bereits geschlossen
139cdf0e10cSrcweir 	return 0;
140cdf0e10cSrcweir }
141cdf0e10cSrcweir 
142cdf0e10cSrcweir //=========================================================================
143cdf0e10cSrcweir 
ScanRecordType(SvStream * pStream)144cdf0e10cSrcweir sal_uInt16 SfxMiniRecordReader::ScanRecordType
145cdf0e10cSrcweir (
146cdf0e10cSrcweir 	SvStream*	pStream 		/*	<SvStream> an dessen aktueller Position
147cdf0e10cSrcweir 									ein Record liegt, dessen Typ erkannt werden
148cdf0e10cSrcweir 									soll.
149cdf0e10cSrcweir 								*/
150cdf0e10cSrcweir )
151cdf0e10cSrcweir 
152cdf0e10cSrcweir /*	[Beschreibung]
153cdf0e10cSrcweir 
154cdf0e10cSrcweir 	Mit dieser statischen Methode kann ermittelt werden, ob sich an der
155cdf0e10cSrcweir 	aktuellen Position in einem Stream ein Record befindet, und der Typ
156cdf0e10cSrcweir 	des Records kann ermittelt werden.
157cdf0e10cSrcweir 
158cdf0e10cSrcweir 	Die Position im Stream ist nach dem Aufruf aufver"andert.
159cdf0e10cSrcweir 
160cdf0e10cSrcweir 
161cdf0e10cSrcweir 	[Anmerkung]
162cdf0e10cSrcweir 
163cdf0e10cSrcweir 	Die Record-Typen k"onnen zwar (abgesehen vom Drawing-Enginge-Record)
164cdf0e10cSrcweir 	untereinander eindeutig erkannt werden, es besteht jedoch die Gefahr
165cdf0e10cSrcweir 	der Verwechslung von Records mit normalen Daten. File-Formate sollten
166cdf0e10cSrcweir 	darauf R"ucksicht nehmen. Handelt es sich um keinen Record, wird
167cdf0e10cSrcweir 	am wahrscheinlichsten SFX_REC_TYPE_MINI zur"uckgeliefert, da dieser
168cdf0e10cSrcweir 	Typ sich aufgrund seines sparsam kurzen Headers durch die k"urzeste
169cdf0e10cSrcweir 	Kennung auszeichnet.
170cdf0e10cSrcweir 
171cdf0e10cSrcweir 
172cdf0e10cSrcweir 	[R"uckgabewert]
173cdf0e10cSrcweir 
174cdf0e10cSrcweir 	sal_uInt16							SFX_REC_TYPE_EOR
175cdf0e10cSrcweir 									An der aktuellen Position des Streams
176cdf0e10cSrcweir 									steht eine End-Of-Records-Kennung.
177cdf0e10cSrcweir 
178cdf0e10cSrcweir 									SFX_REC_TYPE_MINI
179cdf0e10cSrcweir 									Es handelt sich um einen SW3 kompatiblen
180cdf0e10cSrcweir 									Mini-Record, dessen einzige Kennung sein
181cdf0e10cSrcweir 									'Mini-Tag' ist.
182cdf0e10cSrcweir 
183cdf0e10cSrcweir 									SFX_REC_TYPE_SINGLE
184cdf0e10cSrcweir 									Es handelt sich um einen Extended-Record
185cdf0e10cSrcweir 									mit einem einzigen Content, der durch eine
186cdf0e10cSrcweir 									Version und ein Tag n"aher gekennzeichnet
187cdf0e10cSrcweir 									ist.
188cdf0e10cSrcweir 
189cdf0e10cSrcweir 									SFX_REC_TYPE_FIXSIZE
190cdf0e10cSrcweir 									Es handelt sich um einen Extended-Record
191cdf0e10cSrcweir 									mit mehreren Contents gleicher Gr"o\se,
192cdf0e10cSrcweir 									die gemeinsam durch eine einzige Version
193cdf0e10cSrcweir 									und ein einziges gemeinsames Tag n"aher
194cdf0e10cSrcweir 									gekennzeichnet sind.
195cdf0e10cSrcweir 
196cdf0e10cSrcweir 									SFX_REC_TYPE_VARSIZE
197cdf0e10cSrcweir 									Es handelt sich um einen Extended-Record
198cdf0e10cSrcweir 									mit mehreren Contents variabler Gr"o\se,
199cdf0e10cSrcweir 									die gemeinsam durch eine einzige Version
200cdf0e10cSrcweir 									und ein einziges gemeinsames Tag n"aher
201cdf0e10cSrcweir 									gekennzeichnet sind.
202cdf0e10cSrcweir 
203cdf0e10cSrcweir 									SFX_REC_TYPE_MIXTAGS
204cdf0e10cSrcweir 									Es handelt sich um einen Extended-Record
205cdf0e10cSrcweir 									mit mehreren Contents variabler Gr"o\se,
206cdf0e10cSrcweir 									die jeweils durch ein eignes Tag und
207cdf0e10cSrcweir 									eine eigene Versions-Nummer n"aher
208cdf0e10cSrcweir 									gekennzeichnet sind.
209cdf0e10cSrcweir 
210cdf0e10cSrcweir 									SFX_REC_TYPE_DRAWENG
211cdf0e10cSrcweir 									Es handelt sich wahrscheinlich um einen
212cdf0e10cSrcweir 									Drawing-Engine-Record. Dieser Record-Typ
213cdf0e10cSrcweir 									kann von den Klassen dieser Gruppe nicht
214cdf0e10cSrcweir 									interpretiert werden.
215cdf0e10cSrcweir */
216cdf0e10cSrcweir 
217cdf0e10cSrcweir {
218cdf0e10cSrcweir 	// die ersten 4 Bytes als Mini-Header lesen
219cdf0e10cSrcweir 	sal_uInt32 nHeader;
220cdf0e10cSrcweir 	*pStream >> nHeader;
221cdf0e10cSrcweir 
222cdf0e10cSrcweir 	// k"onnte es sich um einen extended-Record handeln?
223cdf0e10cSrcweir 	sal_uInt16 nPreTag = sal::static_int_cast< sal_uInt16 >(SFX_REC_PRE(nHeader));
224cdf0e10cSrcweir 	if ( SFX_REC_PRETAG_EXT == nPreTag )
225cdf0e10cSrcweir 	{
226cdf0e10cSrcweir 		// die n"achsten 4 Bytes als extended-Header lesen
227cdf0e10cSrcweir 		*pStream >> nHeader;
228cdf0e10cSrcweir 
229cdf0e10cSrcweir 		// Stream-Position restaurieren
230cdf0e10cSrcweir 		pStream->SeekRel(-8);
231cdf0e10cSrcweir 
232cdf0e10cSrcweir 		// liegt eine g"ultige Record-Kennung vor?
233cdf0e10cSrcweir 		sal_uInt16 nType = sal::static_int_cast< sal_uInt16 >(SFX_REC_TYP(nHeader));
234cdf0e10cSrcweir 		if ( nType >= SFX_REC_TYPE_FIRST && nType <= SFX_REC_TYPE_LAST )
235cdf0e10cSrcweir 			// entsprechenden extended-Record-Typ zur"uckliefern
236cdf0e10cSrcweir 			return nType;
237cdf0e10cSrcweir 
238cdf0e10cSrcweir 		// sonst ist der Record-Typ unbekannt
239cdf0e10cSrcweir 		return SFX_REC_TYPE_NONE;
240cdf0e10cSrcweir 	}
241cdf0e10cSrcweir 
242cdf0e10cSrcweir 	// Stream-Position restaurieren
243cdf0e10cSrcweir 	pStream->SeekRel(-4);
244cdf0e10cSrcweir 
245cdf0e10cSrcweir 	// liegt eine End-Of-Record-Kennung vor?
246cdf0e10cSrcweir 	if ( SFX_REC_PRETAG_EOR == nPreTag )
247cdf0e10cSrcweir 		return nPreTag;
248cdf0e10cSrcweir 
249cdf0e10cSrcweir 	// liegt ein Drawin-Engine-Record vor?
250cdf0e10cSrcweir 	if ( nHeader == sal_uInt32(*"DRMD") || nHeader == sal_uInt32(*"DRVW") )
251cdf0e10cSrcweir 		return SFX_REC_TYPE_DRAWENG;
252cdf0e10cSrcweir 
253cdf0e10cSrcweir 	// alle anderen sind grunds"atzlich g"ultige Mini-Records
254cdf0e10cSrcweir 	return SFX_REC_TYPE_MINI;
255cdf0e10cSrcweir }
256cdf0e10cSrcweir 
257cdf0e10cSrcweir //-------------------------------------------------------------------------
258cdf0e10cSrcweir 
SetHeader_Impl(sal_uInt32 nHeader)259cdf0e10cSrcweir FASTBOOL SfxMiniRecordReader::SetHeader_Impl( sal_uInt32 nHeader )
260cdf0e10cSrcweir 
261cdf0e10cSrcweir /*	[Beschreibung]
262cdf0e10cSrcweir 
263cdf0e10cSrcweir 	Interne Methode zum nachtr"aglichen Verarbeiten eines extern gelesenen
264cdf0e10cSrcweir 	Headers. Falls der Header eine End-Of-Records-Kennung darstellt,
265cdf0e10cSrcweir 	wird am Stream ein Errorcode gesetzt und sal_False zur"uckgeliefert. Im
266cdf0e10cSrcweir 	Fehlerfall wird der Stream jedoch nicht auf den Record-Anfang zur"uck-
267cdf0e10cSrcweir 	gesetzt.
268cdf0e10cSrcweir */
269cdf0e10cSrcweir 
270cdf0e10cSrcweir {
271cdf0e10cSrcweir 	FASTBOOL bRet = sal_True;
272cdf0e10cSrcweir 
273cdf0e10cSrcweir 	// Record-Ende und Pre-Tag aus dem Header ermitteln
274cdf0e10cSrcweir 	_nEofRec = _pStream->Tell() + SFX_REC_OFS(nHeader);
275cdf0e10cSrcweir 	_nPreTag = sal::static_int_cast< sal_uInt8 >(SFX_REC_PRE(nHeader));
276cdf0e10cSrcweir 
277cdf0e10cSrcweir 	// wenn End-Of-Record-Kennung, dann Fehler
278cdf0e10cSrcweir 	if ( _nPreTag == SFX_REC_PRETAG_EOR )
279cdf0e10cSrcweir 	{
280cdf0e10cSrcweir 		_pStream->SetError( ERRCODE_IO_WRONGFORMAT );
281cdf0e10cSrcweir 		bRet = sal_False;
282cdf0e10cSrcweir 	}
283cdf0e10cSrcweir 	return bRet;
284cdf0e10cSrcweir }
285cdf0e10cSrcweir 
286cdf0e10cSrcweir //-------------------------------------------------------------------------
287cdf0e10cSrcweir 
SfxMiniRecordReader(SvStream * pStream)288cdf0e10cSrcweir SfxMiniRecordReader::SfxMiniRecordReader
289cdf0e10cSrcweir (
290cdf0e10cSrcweir 	SvStream*		pStream 		/*	<SvStream>, an dessen aktueller
291cdf0e10cSrcweir 										Position sich ein <SfxMiniRecord>
292cdf0e10cSrcweir 										befindet.
293cdf0e10cSrcweir 									*/
294cdf0e10cSrcweir )
295cdf0e10cSrcweir 
296cdf0e10cSrcweir /*	[Beschreibung]
297cdf0e10cSrcweir 
298cdf0e10cSrcweir 	Dieser Ctor liest den Header eines <SfxMiniRecord> ab der aktuellen
299cdf0e10cSrcweir 	Position von 'pStream'. Da grunds"atzlich fast 4-Byte Kombination ein
300cdf0e10cSrcweir 	g"ultiger SfxMiniRecord-Header ist, bleiben die einzig m"oglichen
301cdf0e10cSrcweir 	Fehler der EOF-Status des Streams, und ein SFX_REC_PRETAG_EOR
302cdf0e10cSrcweir 	als Pre-Tag. Ein entsprechender Error-Code (ERRCODE_IO_EOF bzw.
303cdf0e10cSrcweir 	ERRCODE_IO_WRONGFORMAT) ist dann am Stream gesetzt, dessen Position
304cdf0e10cSrcweir 	dann au\serdem unver"andert ist.
305cdf0e10cSrcweir */
306cdf0e10cSrcweir 
307cdf0e10cSrcweir :	_pStream( pStream ),
308cdf0e10cSrcweir 	_bSkipped( sal_False )
309cdf0e10cSrcweir {
310cdf0e10cSrcweir 	// Header einlesen
311cdf0e10cSrcweir 	sal_uInt32 nStartPos = pStream->Tell(); // um im Fehlerfall zur"uck zu-seeken
312cdf0e10cSrcweir 	DBG( DbgOutf( "SfxFileRec: reading record at %ul", nStartPos ) );
313cdf0e10cSrcweir 	sal_uInt32 nHeader;
314cdf0e10cSrcweir 	*pStream >> nHeader;
315cdf0e10cSrcweir 
316cdf0e10cSrcweir 	// Headerdaten extrahieren
317cdf0e10cSrcweir 	SetHeader_Impl( nHeader );
318cdf0e10cSrcweir 
319cdf0e10cSrcweir 	// Fehlerbehandlung
320cdf0e10cSrcweir 	if ( pStream->IsEof() )
321cdf0e10cSrcweir 		_nPreTag = SFX_REC_PRETAG_EOR;
322cdf0e10cSrcweir 	else if ( _nPreTag == SFX_REC_PRETAG_EOR )
323cdf0e10cSrcweir 		pStream->SetError( ERRCODE_IO_WRONGFORMAT );
324cdf0e10cSrcweir 	if ( !IsValid() )
325cdf0e10cSrcweir 		pStream->Seek( nStartPos );
326cdf0e10cSrcweir }
327cdf0e10cSrcweir 
328cdf0e10cSrcweir //-------------------------------------------------------------------------
329cdf0e10cSrcweir 
SfxMiniRecordReader(SvStream * pStream,sal_uInt8 nTag)330cdf0e10cSrcweir SfxMiniRecordReader::SfxMiniRecordReader
331cdf0e10cSrcweir (
332cdf0e10cSrcweir 	SvStream*		pStream,		/*	<SvStream>, an dessen aktueller
333cdf0e10cSrcweir 										Position sich ein <SfxMiniRecord>
334cdf0e10cSrcweir 										befindet.
335cdf0e10cSrcweir 									*/
336cdf0e10cSrcweir 	sal_uInt8			nTag			//	Pre-Tag des gew"unschten Records
337cdf0e10cSrcweir )
338cdf0e10cSrcweir 
339cdf0e10cSrcweir /*	[Beschreibung]
340cdf0e10cSrcweir 
341cdf0e10cSrcweir 	Dieser Ctor interpretiert 'pStream' ab der aktuellen Position als
342cdf0e10cSrcweir 	eine l"uckenlose Folge von, von dieser Klassen-Gruppe interpretierbaren,
343cdf0e10cSrcweir 	Records. Der in dieser Folge erste als <SfxMiniRecord> interpretierbare
344cdf0e10cSrcweir 	(also ggf. auch ein extended-Record) mit dem PreTag 'nTag' wird ge"offnet
345cdf0e10cSrcweir 	und durch diese Instanz repr"asentiert.
346cdf0e10cSrcweir 
347cdf0e10cSrcweir 	Wird das Ende des Streams oder die Kennung SFX_REC_PRETAG_EOR
348cdf0e10cSrcweir 	erreicht, bevor ein Record mit dem ge"unschten Pre-Tag gefunden wird,
349cdf0e10cSrcweir 	ist die erzeugte Instanz ung"ultig ('IsValid() == sal_False'). Ein ent-
350cdf0e10cSrcweir 	sprechender Error-Code (ERRCODE_IO_EOF bzw. ERRCODE_IO_WRONGFORMAT)
351cdf0e10cSrcweir 	ist dann am Stream gesetzt, dessen Position ist dann au\serdem unver-
352cdf0e10cSrcweir 	"andert.
353cdf0e10cSrcweir 
354cdf0e10cSrcweir 	Bei 'nTag==SFX_FILEREC_PRETAG_EOR' wird nicht versucht, einen Record
355cdf0e10cSrcweir 	zu lesen, es wird sofort 'IsValid()' auf sal_False gesetzt und kein Error-Code
356cdf0e10cSrcweir 	am Stream gesetzt. Dies ist dauzu gedacht, ohne 'new' und 'delete'
357cdf0e10cSrcweir 	abw"rtskompatibel SfxMiniRecords einbauen zu k"onnen. Siehe dazu
358cdf0e10cSrcweir 	<SfxItemSet::Load()>.
359cdf0e10cSrcweir 
360cdf0e10cSrcweir 
361cdf0e10cSrcweir 	[Anwendungsvorschlag]
362cdf0e10cSrcweir 
363cdf0e10cSrcweir 	Wird dieser Ctor in einer bereits ausgelieferten Programmversion
364cdf0e10cSrcweir 	verwendet, k"onnen in das File-Format jeweils davor kompatibel neue
365cdf0e10cSrcweir 	Records mit einer anderen Kennung eingef"ugt werden. Diese werden
366cdf0e10cSrcweir 	schlie\slich automatisch "uberlesen. Erkauft wird diese M"oglichkeit
367cdf0e10cSrcweir 	allerdings mit etwas schlechterem Laufzeitverhalten im Vergleich mit
368cdf0e10cSrcweir 	direktem 'drauf-los-lesen', der sich jedoch auf einen Vergleich zweier
369cdf0e10cSrcweir 	Bytes reduziert, falls der gesuchte Record der erste in der Folge ist.
370cdf0e10cSrcweir */
371cdf0e10cSrcweir 
372cdf0e10cSrcweir :   _pStream( pStream ),
373cdf0e10cSrcweir 	_bSkipped( nTag == SFX_REC_PRETAG_EOR )
374cdf0e10cSrcweir {
375cdf0e10cSrcweir 	// ggf. ignorieren (s.o.)
376cdf0e10cSrcweir 	if ( _bSkipped )
377cdf0e10cSrcweir 	{
378cdf0e10cSrcweir 		_nPreTag = nTag;
379cdf0e10cSrcweir 		return;
380cdf0e10cSrcweir 	}
381cdf0e10cSrcweir 
382cdf0e10cSrcweir 	// StartPos merken, um im Fehlerfall zur"uck-seeken zu k"onnen
383cdf0e10cSrcweir 	sal_uInt32 nStartPos = pStream->Tell();
384cdf0e10cSrcweir 
385cdf0e10cSrcweir 	// passenden Record suchen
386cdf0e10cSrcweir 	while(sal_True)
387cdf0e10cSrcweir 	{
388cdf0e10cSrcweir 		// Header lesen
389cdf0e10cSrcweir 		DBG( DbgOutf( "SfxFileRec: searching record at %ul", pStream->Tell() ) );
390cdf0e10cSrcweir 		sal_uInt32 nHeader;
391cdf0e10cSrcweir 		*pStream >> nHeader;
392cdf0e10cSrcweir 
393cdf0e10cSrcweir 		// Headerdaten von Basisklasse extrahieren lassen
394cdf0e10cSrcweir 		SetHeader_Impl( nHeader );
395cdf0e10cSrcweir 
396cdf0e10cSrcweir 		// ggf. Fehler behandeln
397cdf0e10cSrcweir 		if ( pStream->IsEof() )
398cdf0e10cSrcweir 			_nPreTag = SFX_REC_PRETAG_EOR;
399cdf0e10cSrcweir 		else if ( _nPreTag == SFX_REC_PRETAG_EOR )
400cdf0e10cSrcweir 			pStream->SetError( ERRCODE_IO_WRONGFORMAT );
401cdf0e10cSrcweir 		else
402cdf0e10cSrcweir 		{
403cdf0e10cSrcweir 			// wenn gefunden, dann Schleife abbrechen
404cdf0e10cSrcweir 			if ( _nPreTag == nTag )
405cdf0e10cSrcweir 				break;
406cdf0e10cSrcweir 
407cdf0e10cSrcweir 			// sonst skippen und weitersuchen
408cdf0e10cSrcweir 			pStream->Seek( _nEofRec );
409cdf0e10cSrcweir 			continue;
410cdf0e10cSrcweir 		}
411cdf0e10cSrcweir 
412cdf0e10cSrcweir 		// Fehler => zur"uck-seeken
413cdf0e10cSrcweir 		pStream->Seek( nStartPos );
414cdf0e10cSrcweir 		break;
415cdf0e10cSrcweir 	}
416cdf0e10cSrcweir }
417cdf0e10cSrcweir 
418cdf0e10cSrcweir //=========================================================================
419cdf0e10cSrcweir 
SfxSingleRecordWriter(sal_uInt8 nRecordType,SvStream * pStream,sal_uInt16 nContentTag,sal_uInt8 nContentVer)420cdf0e10cSrcweir SfxSingleRecordWriter::SfxSingleRecordWriter
421cdf0e10cSrcweir (
422cdf0e10cSrcweir 	sal_uInt8			nRecordType,	// f"ur Subklassen
423cdf0e10cSrcweir 	SvStream*		pStream,		// Stream, in dem der Record angelegt wird
424cdf0e10cSrcweir 	sal_uInt16			nContentTag,	// Inhalts-Art-Kennung
425cdf0e10cSrcweir 	sal_uInt8			nContentVer 	// Inhalts-Versions-Kennung
426cdf0e10cSrcweir )
427cdf0e10cSrcweir 
428cdf0e10cSrcweir /*	[Beschreibung]
429cdf0e10cSrcweir 
430cdf0e10cSrcweir 	Interner Ctor f"ur Subklassen.
431cdf0e10cSrcweir */
432cdf0e10cSrcweir 
433cdf0e10cSrcweir :	SfxMiniRecordWriter( pStream, SFX_REC_PRETAG_EXT )
434cdf0e10cSrcweir {
435cdf0e10cSrcweir 	// Erweiterten Header hiner den des SfxMiniRec schreiben
436cdf0e10cSrcweir 	*pStream << SFX_REC_HEADER(nRecordType, nContentTag, nContentVer);
437cdf0e10cSrcweir }
438cdf0e10cSrcweir 
439cdf0e10cSrcweir //-------------------------------------------------------------------------
440cdf0e10cSrcweir 
SfxSingleRecordWriter(SvStream * pStream,sal_uInt16 nContentTag,sal_uInt8 nContentVer)441cdf0e10cSrcweir SfxSingleRecordWriter::SfxSingleRecordWriter
442cdf0e10cSrcweir (
443cdf0e10cSrcweir 	SvStream*		pStream,		// Stream, in dem der Record angelegt wird
444cdf0e10cSrcweir 	sal_uInt16			nContentTag,	// Inhalts-Art-Kennung
445cdf0e10cSrcweir 	sal_uInt8			nContentVer 	// Inhalts-Versions-Kennung
446cdf0e10cSrcweir )
447cdf0e10cSrcweir 
448cdf0e10cSrcweir /*	[Beschreibung]
449cdf0e10cSrcweir 
450cdf0e10cSrcweir 	Legt in 'pStream' einen 'SfxSingleRecord' an, dessen Content-Gr"o\se
451cdf0e10cSrcweir 	nicht bekannt ist, sondern nach dam Streamen des Contents errechnet
452cdf0e10cSrcweir 	werden soll.
453cdf0e10cSrcweir */
454cdf0e10cSrcweir 
455cdf0e10cSrcweir :	SfxMiniRecordWriter( pStream, SFX_REC_PRETAG_EXT )
456cdf0e10cSrcweir {
457cdf0e10cSrcweir 	// Erweiterten Header hiner den des SfxMiniRec schreiben
458cdf0e10cSrcweir 	*pStream << SFX_REC_HEADER( SFX_REC_TYPE_SINGLE, nContentTag, nContentVer);
459cdf0e10cSrcweir }
460cdf0e10cSrcweir 
461cdf0e10cSrcweir //-------------------------------------------------------------------------
462cdf0e10cSrcweir 
SfxSingleRecordWriter(SvStream * pStream,sal_uInt16 nContentTag,sal_uInt8 nContentVer,sal_uInt32 nContentSize)463cdf0e10cSrcweir SfxSingleRecordWriter::SfxSingleRecordWriter
464cdf0e10cSrcweir (
465cdf0e10cSrcweir 	SvStream*		pStream,		// Stream, in dem der Record angelegt wird
466cdf0e10cSrcweir 	sal_uInt16			nContentTag,	// Inhalts-Art-Kennung
467cdf0e10cSrcweir 	sal_uInt8			nContentVer,	// Inhalts-Versions-Kennung
468cdf0e10cSrcweir 	sal_uInt32			nContentSize	// Gr"o\se des Inhalts in Bytes
469cdf0e10cSrcweir )
470cdf0e10cSrcweir 
471cdf0e10cSrcweir /*  [Beschreibung]
472cdf0e10cSrcweir 
473cdf0e10cSrcweir 	Legt in 'pStream' einen 'SfxSingleRecord' an, dessen Content-Gr"o\se
474cdf0e10cSrcweir 	von vornherein bekannt ist.
475cdf0e10cSrcweir */
476cdf0e10cSrcweir 
477cdf0e10cSrcweir :	SfxMiniRecordWriter( pStream, SFX_REC_PRETAG_EXT,
478cdf0e10cSrcweir 						 nContentSize + SFX_REC_HEADERSIZE_SINGLE )
479cdf0e10cSrcweir {
480cdf0e10cSrcweir 	// Erweiterten Header hinter den des SfxMiniRec schreiben
481cdf0e10cSrcweir 	*pStream << SFX_REC_HEADER( SFX_REC_TYPE_SINGLE, nContentTag, nContentVer);
482cdf0e10cSrcweir }
483cdf0e10cSrcweir 
484cdf0e10cSrcweir //=========================================================================
485cdf0e10cSrcweir 
ReadHeader_Impl(sal_uInt16 nTypes)486cdf0e10cSrcweir inline FASTBOOL SfxSingleRecordReader::ReadHeader_Impl( sal_uInt16 nTypes )
487cdf0e10cSrcweir 
488cdf0e10cSrcweir /*  [Beschreibung]
489cdf0e10cSrcweir 
490cdf0e10cSrcweir 	Interne Methode zum Einlesen eines SfxMultiRecord-Headers, nachdem
491cdf0e10cSrcweir 	die Basisklasse bereits initialisiert und deren Header gelesen ist.
492cdf0e10cSrcweir 	Ggf. ist ein Error-Code am Stream gesetzt, im Fehlerfall wird jedoch
493cdf0e10cSrcweir 	nicht zur"uckge-seekt.
494cdf0e10cSrcweir */
495cdf0e10cSrcweir 
496cdf0e10cSrcweir {
497cdf0e10cSrcweir 	FASTBOOL bRet;
498cdf0e10cSrcweir 
499cdf0e10cSrcweir 	// Basisklassen-Header einlesen
500cdf0e10cSrcweir 	sal_uInt32 nHeader=0;
501cdf0e10cSrcweir 	*_pStream >> nHeader;
502cdf0e10cSrcweir 	if ( !SetHeader_Impl( nHeader ) )
503cdf0e10cSrcweir 		bRet = sal_False;
504cdf0e10cSrcweir 	else
505cdf0e10cSrcweir 	{
506cdf0e10cSrcweir 		// eigenen Header einlesen
507cdf0e10cSrcweir 		*_pStream >> nHeader;
508cdf0e10cSrcweir 		_nRecordVer = sal::static_int_cast< sal_uInt8 >(SFX_REC_VER(nHeader));
509cdf0e10cSrcweir 		_nRecordTag = sal::static_int_cast< sal_uInt16 >(SFX_REC_TAG(nHeader));
510cdf0e10cSrcweir 
511cdf0e10cSrcweir 		// falscher Record-Typ?
512cdf0e10cSrcweir 		_nRecordType = sal::static_int_cast< sal_uInt8 >(SFX_REC_TYP(nHeader));
513cdf0e10cSrcweir 		bRet = 0 != ( nTypes & _nRecordType);
514cdf0e10cSrcweir 	}
515cdf0e10cSrcweir 	return bRet;
516cdf0e10cSrcweir }
517cdf0e10cSrcweir 
518cdf0e10cSrcweir //-------------------------------------------------------------------------
519cdf0e10cSrcweir 
SfxSingleRecordReader(SvStream * pStream)520cdf0e10cSrcweir SfxSingleRecordReader::SfxSingleRecordReader( SvStream *pStream )
521cdf0e10cSrcweir :	SfxMiniRecordReader()
522cdf0e10cSrcweir {
523cdf0e10cSrcweir 	// Startposition merken, um im Fehlerfall zur"uck-seeken zu k"onnen
524cdf0e10cSrcweir     #ifdef DBG_UTIL
525cdf0e10cSrcweir 	sal_uInt32 nStartPos = pStream->Tell();
526cdf0e10cSrcweir 	DBG( DbgOutf( "SfxFileRec: reading record at %ul", nStartPos ) );
527cdf0e10cSrcweir     #endif
528cdf0e10cSrcweir 
529cdf0e10cSrcweir 	// Basisklasse initialisieren (nicht via Ctor, da der nur MiniRecs akzept.)
530cdf0e10cSrcweir 	Construct_Impl( pStream );
531cdf0e10cSrcweir 
532cdf0e10cSrcweir 	// nur Header mit korrektem Record-Type akzeptieren
533cdf0e10cSrcweir 	if ( !ReadHeader_Impl( SFX_REC_TYPE_SINGLE ) )
534cdf0e10cSrcweir 	{
535cdf0e10cSrcweir 		// Error-Code setzen und zur"uck-seeken
536cdf0e10cSrcweir 		pStream->SeekRel( - SFX_REC_HEADERSIZE_SINGLE );
537cdf0e10cSrcweir 		pStream->SetError( ERRCODE_IO_WRONGFORMAT );
538cdf0e10cSrcweir 	}
539cdf0e10cSrcweir }
540cdf0e10cSrcweir 
541cdf0e10cSrcweir //-------------------------------------------------------------------------
542cdf0e10cSrcweir 
SfxSingleRecordReader(SvStream * pStream,sal_uInt16 nTag)543cdf0e10cSrcweir SfxSingleRecordReader::SfxSingleRecordReader( SvStream *pStream, sal_uInt16 nTag )
544cdf0e10cSrcweir {
545cdf0e10cSrcweir 	// StartPos merken, um im Fehlerfall zur"uck-seeken zu k"onnen
546cdf0e10cSrcweir 	sal_uInt32 nStartPos = pStream->Tell();
547cdf0e10cSrcweir 
548cdf0e10cSrcweir 	// richtigen Record suchen, ggf. Error-Code setzen und zur"uck-seeken
549cdf0e10cSrcweir 	Construct_Impl( pStream );
550cdf0e10cSrcweir 	if ( !FindHeader_Impl( SFX_REC_TYPE_SINGLE, nTag ) )
551cdf0e10cSrcweir 	{
552cdf0e10cSrcweir 		// Error-Code setzen und zur"uck-seeken
553cdf0e10cSrcweir 		pStream->Seek( nStartPos );
554cdf0e10cSrcweir 		pStream->SetError( ERRCODE_IO_WRONGFORMAT );
555cdf0e10cSrcweir 	}
556cdf0e10cSrcweir }
557cdf0e10cSrcweir 
558cdf0e10cSrcweir //-------------------------------------------------------------------------
559cdf0e10cSrcweir 
FindHeader_Impl(sal_uInt16 nTypes,sal_uInt16 nTag)560cdf0e10cSrcweir FASTBOOL SfxSingleRecordReader::FindHeader_Impl
561cdf0e10cSrcweir (
562cdf0e10cSrcweir 	sal_uInt16		nTypes, 	// arithm. Veroderung erlaubter Record-Typen
563cdf0e10cSrcweir 	sal_uInt16		nTag		// zu findende Record-Art-Kennung
564cdf0e10cSrcweir )
565cdf0e10cSrcweir 
566cdf0e10cSrcweir /*	[Beschreibung]
567cdf0e10cSrcweir 
568cdf0e10cSrcweir 	Interne Methode zum lesen des Headers des ersten Record, der einem
569cdf0e10cSrcweir 	der Typen in 'nTypes' entspricht und mit der Art-Kennung 'nTag'
570cdf0e10cSrcweir 	gekennzeichnet ist.
571cdf0e10cSrcweir 
572cdf0e10cSrcweir 	Kann ein solcher Record nicht gefunden werden, wird am Stream ein
573cdf0e10cSrcweir 	Errorcode gesetzt, zur"uck-geseekt und sal_False zur"uckgeliefert.
574cdf0e10cSrcweir */
575cdf0e10cSrcweir 
576cdf0e10cSrcweir {
577cdf0e10cSrcweir 	// StartPos merken, um im Fehlerfall zur"uck-seeken zu k"onnen
578cdf0e10cSrcweir 	sal_uInt32 nStartPos = _pStream->Tell();
579cdf0e10cSrcweir 
580cdf0e10cSrcweir 	// richtigen Record suchen
581cdf0e10cSrcweir 	while ( !_pStream->IsEof() )
582cdf0e10cSrcweir 	{
583cdf0e10cSrcweir 		// Header lesen
584cdf0e10cSrcweir 		sal_uInt32 nHeader;
585cdf0e10cSrcweir 		DBG( DbgOutf( "SfxFileRec: searching record at %ul", _pStream->Tell() ) );
586cdf0e10cSrcweir 		*_pStream >> nHeader;
587cdf0e10cSrcweir 		if ( !SetHeader_Impl( nHeader ) )
588cdf0e10cSrcweir 			// EOR => Such-Schleife abbreichen
589cdf0e10cSrcweir 			break;
590cdf0e10cSrcweir 
591cdf0e10cSrcweir 		// Extended Record gefunden?
592cdf0e10cSrcweir 		if ( _nPreTag == SFX_REC_PRETAG_EXT )
593cdf0e10cSrcweir 		{
594cdf0e10cSrcweir 			// Extended Header lesen
595cdf0e10cSrcweir 			*_pStream >> nHeader;
596cdf0e10cSrcweir 			_nRecordTag = sal::static_int_cast< sal_uInt16 >(SFX_REC_TAG(nHeader));
597cdf0e10cSrcweir 
598cdf0e10cSrcweir 			// richtigen Record gefunden?
599cdf0e10cSrcweir 			if ( _nRecordTag == nTag )
600cdf0e10cSrcweir 			{
601cdf0e10cSrcweir 				// gefundener Record-Typ passend?
602cdf0e10cSrcweir 				_nRecordType = sal::static_int_cast< sal_uInt8 >(
603cdf0e10cSrcweir                     SFX_REC_TYP(nHeader));
604cdf0e10cSrcweir 				if ( nTypes & _nRecordType )
605cdf0e10cSrcweir 					// ==> gefunden
606cdf0e10cSrcweir 					return sal_True;
607cdf0e10cSrcweir 
608cdf0e10cSrcweir 				// error => Such-Schleife abbrechen
609cdf0e10cSrcweir 				break;
610cdf0e10cSrcweir 			}
611cdf0e10cSrcweir 		}
612cdf0e10cSrcweir 
613cdf0e10cSrcweir 		// sonst skippen
614cdf0e10cSrcweir 		if ( !_pStream->IsEof() )
615cdf0e10cSrcweir 			_pStream->Seek( _nEofRec );
616cdf0e10cSrcweir 	}
617cdf0e10cSrcweir 
618cdf0e10cSrcweir 	// Fehler setzen und zur"uck-seeken
619cdf0e10cSrcweir 	_pStream->SetError( ERRCODE_IO_WRONGFORMAT );
620cdf0e10cSrcweir 	_pStream->Seek( nStartPos );
621cdf0e10cSrcweir 	return sal_False;
622cdf0e10cSrcweir }
623cdf0e10cSrcweir 
624cdf0e10cSrcweir //=========================================================================
625cdf0e10cSrcweir 
SfxMultiFixRecordWriter(sal_uInt8 nRecordType,SvStream * pStream,sal_uInt16 nContentTag,sal_uInt8 nContentVer,sal_uInt32)626cdf0e10cSrcweir SfxMultiFixRecordWriter::SfxMultiFixRecordWriter
627cdf0e10cSrcweir (
628cdf0e10cSrcweir 	sal_uInt8			nRecordType,	// Subklassen Record-Kennung
629cdf0e10cSrcweir 	SvStream*		pStream,		// Stream, in dem der Record angelegt wird
630cdf0e10cSrcweir 	sal_uInt16			nContentTag,	// Content-Art-Kennung
631cdf0e10cSrcweir 	sal_uInt8			nContentVer,	// Content-Versions-Kennung
632cdf0e10cSrcweir 	sal_uInt32			              	// Gr"o\se jedes einzelnen Contents in Bytes
633cdf0e10cSrcweir )
634cdf0e10cSrcweir 
635cdf0e10cSrcweir /*  [Beschreibung]
636cdf0e10cSrcweir 
637cdf0e10cSrcweir 	Interne Methode f"ur Subklassen.
638cdf0e10cSrcweir */
639cdf0e10cSrcweir 
640cdf0e10cSrcweir :   SfxSingleRecordWriter( nRecordType, pStream, nContentTag, nContentVer ),
641cdf0e10cSrcweir 	_nContentCount( 0 )
642cdf0e10cSrcweir {
643cdf0e10cSrcweir 	// Platz f"ur eigenen Header
644cdf0e10cSrcweir 	pStream->SeekRel( + SFX_REC_HEADERSIZE_MULTI );
645cdf0e10cSrcweir }
646cdf0e10cSrcweir 
647cdf0e10cSrcweir //------------------------------------------------------------------------
648cdf0e10cSrcweir 
SfxMultiFixRecordWriter(SvStream * pStream,sal_uInt16 nContentTag,sal_uInt8 nContentVer,sal_uInt32)649cdf0e10cSrcweir SfxMultiFixRecordWriter::SfxMultiFixRecordWriter
650cdf0e10cSrcweir (
651cdf0e10cSrcweir 	SvStream*		pStream,		// Stream, in dem der Record angelegt wird
652cdf0e10cSrcweir 	sal_uInt16			nContentTag,	// Content-Art-Kennung
653cdf0e10cSrcweir 	sal_uInt8			nContentVer,	// Content-Versions-Kennung
654cdf0e10cSrcweir 	sal_uInt32			             	// Gr"o\se jedes einzelnen Contents in Bytes
655cdf0e10cSrcweir )
656cdf0e10cSrcweir 
657cdf0e10cSrcweir /*  [Beschreibung]
658cdf0e10cSrcweir 
659cdf0e10cSrcweir 	Legt in 'pStream' einen 'SfxMultiFixRecord' an, dessen Content-Gr"o\se
660cdf0e10cSrcweir 	konstant und von vornherein bekannt ist.
661cdf0e10cSrcweir */
662cdf0e10cSrcweir 
663cdf0e10cSrcweir :   SfxSingleRecordWriter( SFX_REC_TYPE_FIXSIZE,
664cdf0e10cSrcweir 						   pStream, nContentTag, nContentVer ),
665cdf0e10cSrcweir 	_nContentCount( 0 )
666cdf0e10cSrcweir {
667cdf0e10cSrcweir 	// Platz f"ur eigenen Header
668cdf0e10cSrcweir 	pStream->SeekRel( + SFX_REC_HEADERSIZE_MULTI );
669cdf0e10cSrcweir }
670cdf0e10cSrcweir 
671cdf0e10cSrcweir //------------------------------------------------------------------------
672cdf0e10cSrcweir 
Close(FASTBOOL bSeekToEndOfRec)673cdf0e10cSrcweir sal_uInt32 SfxMultiFixRecordWriter::Close( FASTBOOL bSeekToEndOfRec )
674cdf0e10cSrcweir 
675cdf0e10cSrcweir //	siehe <SfxMiniRecordWriter>
676cdf0e10cSrcweir 
677cdf0e10cSrcweir {
678cdf0e10cSrcweir 	// Header noch nicht geschrieben?
679cdf0e10cSrcweir 	if ( !_bHeaderOk )
680cdf0e10cSrcweir 	{
681cdf0e10cSrcweir 		// Position hinter Record merken, um sie restaurieren zu k"onnen
682cdf0e10cSrcweir 		sal_uInt32 nEndPos = SfxSingleRecordWriter::Close( sal_False );
683cdf0e10cSrcweir 
684cdf0e10cSrcweir 		// gegen"uber SfxSingleRecord erweiterten Header schreiben
685cdf0e10cSrcweir 		*_pStream << _nContentCount;
686cdf0e10cSrcweir 		*_pStream << _nContentSize;
687cdf0e10cSrcweir 
688cdf0e10cSrcweir 		// je nachdem ans Ende des Records seeken oder hinter Header bleiben
689cdf0e10cSrcweir 		if ( bSeekToEndOfRec )
690cdf0e10cSrcweir 			_pStream->Seek(nEndPos);
691cdf0e10cSrcweir 		return nEndPos;
692cdf0e10cSrcweir 	}
693cdf0e10cSrcweir 
694cdf0e10cSrcweir 	// Record war bereits geschlossen
695cdf0e10cSrcweir 	return 0;
696cdf0e10cSrcweir }
697cdf0e10cSrcweir 
698cdf0e10cSrcweir //=========================================================================
699cdf0e10cSrcweir 
SfxMultiVarRecordWriter(sal_uInt8 nRecordType,SvStream * pStream,sal_uInt16 nRecordTag,sal_uInt8 nRecordVer)700cdf0e10cSrcweir SfxMultiVarRecordWriter::SfxMultiVarRecordWriter
701cdf0e10cSrcweir (
702cdf0e10cSrcweir 	sal_uInt8			nRecordType,	// Record-Kennung der Subklasse
703cdf0e10cSrcweir 	SvStream*       pStream,        // Stream, in dem der Record angelegt wird
704cdf0e10cSrcweir 	sal_uInt16			nRecordTag, 	// Gesamt-Art-Kennung
705cdf0e10cSrcweir 	sal_uInt8			nRecordVer		// Gesamt-Versions-Kennung
706cdf0e10cSrcweir )
707cdf0e10cSrcweir 
708cdf0e10cSrcweir /*  [Beschreibung]
709cdf0e10cSrcweir 
710cdf0e10cSrcweir 	Interner Ctor f"ur Subklassen.
711cdf0e10cSrcweir */
712cdf0e10cSrcweir 
713cdf0e10cSrcweir :   SfxMultiFixRecordWriter( nRecordType, pStream, nRecordTag, nRecordVer, 0 ),
714cdf0e10cSrcweir 	_nContentVer( 0 )
715cdf0e10cSrcweir {
716cdf0e10cSrcweir }
717cdf0e10cSrcweir 
718cdf0e10cSrcweir //-------------------------------------------------------------------------
719cdf0e10cSrcweir 
SfxMultiVarRecordWriter(SvStream * pStream,sal_uInt16 nRecordTag,sal_uInt8 nRecordVer)720cdf0e10cSrcweir SfxMultiVarRecordWriter::SfxMultiVarRecordWriter
721cdf0e10cSrcweir (
722cdf0e10cSrcweir 	SvStream*       pStream,        // Stream, in dem der Record angelegt wird
723cdf0e10cSrcweir 	sal_uInt16			nRecordTag, 	// Gesamt-Art-Kennung
724cdf0e10cSrcweir 	sal_uInt8			nRecordVer		// Gesamt-Versions-Kennung
725cdf0e10cSrcweir )
726cdf0e10cSrcweir 
727cdf0e10cSrcweir /*  [Beschreibung]
728cdf0e10cSrcweir 
729cdf0e10cSrcweir 	Legt in 'pStream' einen 'SfxMultiVarRecord' an, dessen Content-Gr"o\sen
730cdf0e10cSrcweir 	weder bekannt sind noch identisch sein m"ussen, sondern jeweils nach dem
731cdf0e10cSrcweir 	Streamen jedes einzelnen Contents errechnet werden sollen.
732cdf0e10cSrcweir 
733cdf0e10cSrcweir 
734cdf0e10cSrcweir 	[Anmerkung]
735cdf0e10cSrcweir 
736cdf0e10cSrcweir 	Diese Methode ist nicht inline, da f"ur die Initialisierung eines
737cdf0e10cSrcweir 	<SvULongs>-Members zu viel Code generiert werden w"urde.
738cdf0e10cSrcweir */
739cdf0e10cSrcweir 
740cdf0e10cSrcweir :   SfxMultiFixRecordWriter( SFX_REC_TYPE_VARSIZE,
741cdf0e10cSrcweir 							 pStream, nRecordTag, nRecordVer, 0 ),
742cdf0e10cSrcweir 	_nContentVer( 0 )
743cdf0e10cSrcweir {
744cdf0e10cSrcweir }
745cdf0e10cSrcweir 
746cdf0e10cSrcweir //-------------------------------------------------------------------------
747cdf0e10cSrcweir 
~SfxMultiVarRecordWriter()748cdf0e10cSrcweir SfxMultiVarRecordWriter::~SfxMultiVarRecordWriter()
749cdf0e10cSrcweir 
750cdf0e10cSrcweir /*	[Beschreibung]
751cdf0e10cSrcweir 
752cdf0e10cSrcweir 	Der Dtor der Klasse <SfxMultiVarRecordWriter> schlie\st den Record
753cdf0e10cSrcweir 	automatisch, falls <SfxMultiVarRecordWriter::Close()> nicht bereits
754cdf0e10cSrcweir 	explizit gerufen wurde.
755cdf0e10cSrcweir */
756cdf0e10cSrcweir 
757cdf0e10cSrcweir {
758cdf0e10cSrcweir 	// wurde der Header noch nicht geschrieben oder mu\s er gepr"uft werden
759cdf0e10cSrcweir 	if ( !_bHeaderOk )
760cdf0e10cSrcweir 		Close();
761cdf0e10cSrcweir }
762cdf0e10cSrcweir 
763cdf0e10cSrcweir //-------------------------------------------------------------------------
764cdf0e10cSrcweir 
FlushContent_Impl()765cdf0e10cSrcweir void SfxMultiVarRecordWriter::FlushContent_Impl()
766cdf0e10cSrcweir 
767cdf0e10cSrcweir /*	[Beschreibung]
768cdf0e10cSrcweir 
769cdf0e10cSrcweir 	Interne Methode zum Abschlie\sen eines einzelnen Contents.
770cdf0e10cSrcweir */
771cdf0e10cSrcweir 
772cdf0e10cSrcweir {
773cdf0e10cSrcweir 	// Versions-Kennung und Positions-Offset des aktuellen Contents merken;
774cdf0e10cSrcweir 	// das Positions-Offset ist relativ zur Startposition des ersten Contents
775cdf0e10cSrcweir 	_aContentOfs.Insert(
776cdf0e10cSrcweir 			SFX_REC_CONTENT_HEADER(_nContentVer,_nStartPos,_nContentStartPos),
777cdf0e10cSrcweir 			_nContentCount-1 );
778cdf0e10cSrcweir }
779cdf0e10cSrcweir 
780cdf0e10cSrcweir //-------------------------------------------------------------------------
781cdf0e10cSrcweir 
NewContent()782cdf0e10cSrcweir void SfxMultiVarRecordWriter::NewContent()
783cdf0e10cSrcweir 
784cdf0e10cSrcweir // siehe <SfxMultiFixRecordWriter>
785cdf0e10cSrcweir 
786cdf0e10cSrcweir {
787cdf0e10cSrcweir 	// schon ein Content geschrieben?
788cdf0e10cSrcweir 	if ( _nContentCount )
789cdf0e10cSrcweir 		FlushContent_Impl();
790cdf0e10cSrcweir 
791cdf0e10cSrcweir 	// neuen Content beginnen
792cdf0e10cSrcweir 	_nContentStartPos = _pStream->Tell();
793cdf0e10cSrcweir 	++_nContentCount;
794cdf0e10cSrcweir }
795cdf0e10cSrcweir 
796cdf0e10cSrcweir //-------------------------------------------------------------------------
797cdf0e10cSrcweir 
Close(FASTBOOL bSeekToEndOfRec)798cdf0e10cSrcweir sal_uInt32 SfxMultiVarRecordWriter::Close( FASTBOOL bSeekToEndOfRec )
799cdf0e10cSrcweir 
800cdf0e10cSrcweir // siehe <SfxMiniRecordWriter>
801cdf0e10cSrcweir 
802cdf0e10cSrcweir {
803cdf0e10cSrcweir 	// Header noch nicht geschrieben?
804cdf0e10cSrcweir 	if ( !_bHeaderOk )
805cdf0e10cSrcweir 	{
806cdf0e10cSrcweir 		// ggf. letzten Content abschlie\sen
807cdf0e10cSrcweir 		if ( _nContentCount )
808cdf0e10cSrcweir 			FlushContent_Impl();
809cdf0e10cSrcweir 
810cdf0e10cSrcweir 		// Content-Offset-Tabelle schreiben
811cdf0e10cSrcweir 		sal_uInt32 nContentOfsPos = _pStream->Tell();
812cdf0e10cSrcweir 		//! darf man das so einr"ucken?
813cdf0e10cSrcweir 		#if defined(OSL_LITENDIAN)
814cdf0e10cSrcweir 			_pStream->Write( _aContentOfs.GetData(),
815cdf0e10cSrcweir 							 sizeof(sal_uInt32)*_nContentCount );
816cdf0e10cSrcweir 		#else
817cdf0e10cSrcweir 			for ( sal_uInt16 n = 0; n < _nContentCount; ++n )
818cdf0e10cSrcweir 				*_pStream << sal_uInt32(_aContentOfs[n]);
819cdf0e10cSrcweir 		#endif
820cdf0e10cSrcweir 
821cdf0e10cSrcweir 		// SfxMultiFixRecordWriter::Close() "uberspringen!
822cdf0e10cSrcweir 		sal_uInt32 nEndPos = SfxSingleRecordWriter::Close( sal_False );
823cdf0e10cSrcweir 
824cdf0e10cSrcweir 		// eigenen Header schreiben
825cdf0e10cSrcweir 		*_pStream << _nContentCount;
826cdf0e10cSrcweir 		if ( SFX_REC_TYPE_VARSIZE_RELOC == _nPreTag ||
827cdf0e10cSrcweir 			 SFX_REC_TYPE_MIXTAGS_RELOC == _nPreTag )
828cdf0e10cSrcweir 			*_pStream << static_cast<sal_uInt32>(nContentOfsPos - ( _pStream->Tell() + sizeof(sal_uInt32) ));
829cdf0e10cSrcweir 		else
830cdf0e10cSrcweir 			*_pStream << nContentOfsPos;
831cdf0e10cSrcweir 
832cdf0e10cSrcweir 		// ans Ende des Records seeken bzw. am Ende des Headers bleiben
833cdf0e10cSrcweir 		if ( bSeekToEndOfRec )
834cdf0e10cSrcweir 			 _pStream->Seek(nEndPos);
835cdf0e10cSrcweir 		return nEndPos;
836cdf0e10cSrcweir 	}
837cdf0e10cSrcweir 
838cdf0e10cSrcweir 	// Record war bereits vorher geschlossen
839cdf0e10cSrcweir 	return 0;
840cdf0e10cSrcweir }
841cdf0e10cSrcweir 
842cdf0e10cSrcweir //=========================================================================
843cdf0e10cSrcweir 
NewContent(sal_uInt16 nContentTag,sal_uInt8 nContentVer)844cdf0e10cSrcweir void SfxMultiMixRecordWriter::NewContent
845cdf0e10cSrcweir (
846cdf0e10cSrcweir 	sal_uInt16		nContentTag,	// Kennung f"ur die Art des Contents
847cdf0e10cSrcweir 	sal_uInt8		nContentVer 	// Kennung f"ur die Version des Contents
848cdf0e10cSrcweir )
849cdf0e10cSrcweir 
850cdf0e10cSrcweir /*	[Beschreibung]
851cdf0e10cSrcweir 
852cdf0e10cSrcweir 	Mit dieser Methode wird in den Record ein neuer Content eingef"ugt
853cdf0e10cSrcweir 	und dessen Content-Tag sowie dessen Content-Version angegeben. Jeder,
854cdf0e10cSrcweir 	auch der 1. Record mu\s durch Aufruf dieser Methode eingeleitet werden.
855cdf0e10cSrcweir */
856cdf0e10cSrcweir 
857cdf0e10cSrcweir {
858cdf0e10cSrcweir 	// ggf. vorherigen Record abschlie\sen
859cdf0e10cSrcweir 	if ( _nContentCount )
860cdf0e10cSrcweir 		FlushContent_Impl();
861cdf0e10cSrcweir 
862cdf0e10cSrcweir 	// Tag vor den Content schreiben, Version und Startposition merken
863cdf0e10cSrcweir 	_nContentStartPos = _pStream->Tell();
864cdf0e10cSrcweir 	++_nContentCount;
865cdf0e10cSrcweir 	*_pStream << nContentTag;
866cdf0e10cSrcweir 	_nContentVer = nContentVer;
867cdf0e10cSrcweir }
868cdf0e10cSrcweir 
869cdf0e10cSrcweir //=========================================================================
870cdf0e10cSrcweir 
ReadHeader_Impl()871cdf0e10cSrcweir FASTBOOL SfxMultiRecordReader::ReadHeader_Impl()
872cdf0e10cSrcweir 
873cdf0e10cSrcweir /*  [Beschreibung]
874cdf0e10cSrcweir 
875cdf0e10cSrcweir 	Interne Methode zum Einlesen eines SfxMultiRecord-Headers, nachdem
876cdf0e10cSrcweir 	die Basisklasse bereits initialisiert und deren Header gelesen ist.
877cdf0e10cSrcweir 	Ggf. ist ein Error-Code am Stream gesetzt, im Fehlerfall wird jedoch
878cdf0e10cSrcweir 	nicht zur"uckge-seekt.
879cdf0e10cSrcweir */
880cdf0e10cSrcweir 
881cdf0e10cSrcweir {
882cdf0e10cSrcweir 	// eigenen Header lesen
883cdf0e10cSrcweir 	*_pStream >> _nContentCount;
884cdf0e10cSrcweir 	*_pStream >> _nContentSize; // Fix: jedes einzelnen, Var|Mix: Tabellen-Pos.
885cdf0e10cSrcweir 
886cdf0e10cSrcweir 	// mu\s noch eine Tabelle mit Content-Offsets geladen werden?
887cdf0e10cSrcweir 	if ( _nRecordType != SFX_REC_TYPE_FIXSIZE )
888cdf0e10cSrcweir 	{
889cdf0e10cSrcweir 		// Tabelle aus dem Stream einlesen
890cdf0e10cSrcweir 		sal_uInt32 nContentPos = _pStream->Tell();
891cdf0e10cSrcweir 		if ( _nRecordType == SFX_REC_TYPE_VARSIZE_RELOC ||
892cdf0e10cSrcweir 			 _nRecordType == SFX_REC_TYPE_MIXTAGS_RELOC )
893cdf0e10cSrcweir 			_pStream->SeekRel( + _nContentSize );
894cdf0e10cSrcweir 		else
895cdf0e10cSrcweir 			_pStream->Seek( _nContentSize );
896cdf0e10cSrcweir 		_pContentOfs = new sal_uInt32[_nContentCount];
8976fb30688SEike Rathke         memset(_pContentOfs, 0, _nContentCount*sizeof(sal_uInt32));
8986fb30688SEike Rathke 	//! darf man jetzt so einr"ucken
899cdf0e10cSrcweir 		#if defined(OSL_LITENDIAN)
900cdf0e10cSrcweir 			_pStream->Read( _pContentOfs, sizeof(sal_uInt32)*_nContentCount );
901cdf0e10cSrcweir 		#else
902cdf0e10cSrcweir 			for ( sal_uInt16 n = 0; n < _nContentCount; ++n )
903cdf0e10cSrcweir 				*_pStream >> _pContentOfs[n];
904cdf0e10cSrcweir 		#endif
905cdf0e10cSrcweir 		_pStream->Seek( nContentPos );
906cdf0e10cSrcweir 	}
907cdf0e10cSrcweir 
908cdf0e10cSrcweir 	// Header konnte gelesen werden, wenn am Stream kein Error gesetzt ist
909cdf0e10cSrcweir 	return !_pStream->GetError();
910cdf0e10cSrcweir }
911cdf0e10cSrcweir 
912cdf0e10cSrcweir //-------------------------------------------------------------------------
913cdf0e10cSrcweir 
SfxMultiRecordReader(SvStream * pStream)914cdf0e10cSrcweir SfxMultiRecordReader::SfxMultiRecordReader( SvStream *pStream )
9156fb30688SEike Rathke     : _pContentOfs(0)
9166fb30688SEike Rathke     , _nContentSize(0)
9176fb30688SEike Rathke     , _nContentCount(0)
9186fb30688SEike Rathke     , _nContentNo(0)
919cdf0e10cSrcweir {
920cdf0e10cSrcweir 	// Position im Stream merken, um im Fehlerfall zur"uck-seeken zu k"onnen
921cdf0e10cSrcweir 	_nStartPos = pStream->Tell();
922cdf0e10cSrcweir 
923cdf0e10cSrcweir 	// Basisklasse konstruieren (normaler Ctor w"urde nur SingleRecs lesen)
924cdf0e10cSrcweir 	SfxSingleRecordReader::Construct_Impl( pStream );
925cdf0e10cSrcweir 
926cdf0e10cSrcweir 	// Header der Basisklasse lesen
927cdf0e10cSrcweir 	if ( !SfxSingleRecordReader::ReadHeader_Impl( SFX_REC_TYPE_FIXSIZE |
928cdf0e10cSrcweir 				SFX_REC_TYPE_VARSIZE | SFX_REC_TYPE_VARSIZE_RELOC |
929cdf0e10cSrcweir 				SFX_REC_TYPE_MIXTAGS | SFX_REC_TYPE_MIXTAGS_RELOC ) ||
930cdf0e10cSrcweir 		 !ReadHeader_Impl() )
931cdf0e10cSrcweir 		// als ung"ultig markieren und zur"uck-seeken
932cdf0e10cSrcweir 		SetInvalid_Impl( _nStartPos );
933cdf0e10cSrcweir }
934cdf0e10cSrcweir 
935cdf0e10cSrcweir //-------------------------------------------------------------------------
936cdf0e10cSrcweir 
SfxMultiRecordReader(SvStream * pStream,sal_uInt16 nTag)937cdf0e10cSrcweir SfxMultiRecordReader::SfxMultiRecordReader( SvStream *pStream, sal_uInt16 nTag )
938cdf0e10cSrcweir :	_nContentNo(0)
939cdf0e10cSrcweir {
940cdf0e10cSrcweir 	// Position im Stream merken, um im Fehlerfall zur"uck-seeken zu k"onnen
941cdf0e10cSrcweir 	_nStartPos = pStream->Tell();
942cdf0e10cSrcweir 
943cdf0e10cSrcweir 	// passenden Record suchen und Basisklasse initialisieren
944cdf0e10cSrcweir 	SfxSingleRecordReader::Construct_Impl( pStream );
945cdf0e10cSrcweir 	if ( SfxSingleRecordReader::FindHeader_Impl( SFX_REC_TYPE_FIXSIZE |
946cdf0e10cSrcweir 			SFX_REC_TYPE_VARSIZE | SFX_REC_TYPE_VARSIZE_RELOC |
947cdf0e10cSrcweir 			SFX_REC_TYPE_MIXTAGS | SFX_REC_TYPE_MIXTAGS_RELOC,
948cdf0e10cSrcweir 			nTag ) )
949cdf0e10cSrcweir 	{
950cdf0e10cSrcweir 		// eigenen Header dazu-lesen
951cdf0e10cSrcweir 		if ( !ReadHeader_Impl() )
952cdf0e10cSrcweir 			// nicht lesbar => als ung"ultig markieren und zur"uck-seeken
953cdf0e10cSrcweir 			SetInvalid_Impl( _nStartPos);
954cdf0e10cSrcweir 	}
955cdf0e10cSrcweir }
956cdf0e10cSrcweir 
957cdf0e10cSrcweir //-------------------------------------------------------------------------
958cdf0e10cSrcweir 
~SfxMultiRecordReader()959cdf0e10cSrcweir SfxMultiRecordReader::~SfxMultiRecordReader()
960cdf0e10cSrcweir {
961cdf0e10cSrcweir 	delete[] _pContentOfs;
962cdf0e10cSrcweir }
963cdf0e10cSrcweir 
964cdf0e10cSrcweir //-------------------------------------------------------------------------
965cdf0e10cSrcweir 
GetContent()966cdf0e10cSrcweir FASTBOOL SfxMultiRecordReader::GetContent()
967cdf0e10cSrcweir 
968cdf0e10cSrcweir /*	[Beschreibung]
969cdf0e10cSrcweir 
970cdf0e10cSrcweir 	Positioniert den Stream an den Anfang des n"chsten bzw. beim 1. Aufruf
971cdf0e10cSrcweir 	auf den Anfang des ersten Contents im Record und liest ggf. dessen
972cdf0e10cSrcweir 	Header ein.
973cdf0e10cSrcweir 
974cdf0e10cSrcweir 	Liegt laut Record-Header kein Content mehr vor, wird sal_False zur"uck-
975cdf0e10cSrcweir 	gegeben. Trotz einem sal_True-Returnwert kann am Stream ein Fehlercode
976cdf0e10cSrcweir 	gesetzt sein, z.B. falls er unvorhergesehenerweise (kaputtes File)
977cdf0e10cSrcweir 	zuende ist.
978cdf0e10cSrcweir */
979cdf0e10cSrcweir 
980cdf0e10cSrcweir {
981cdf0e10cSrcweir 	// noch ein Content vorhanden?
982cdf0e10cSrcweir 	if ( _nContentNo < _nContentCount )
983cdf0e10cSrcweir 	{
984cdf0e10cSrcweir 		// den Stream an den Anfang des Contents positionieren
985cdf0e10cSrcweir 		sal_uInt32 nOffset = _nRecordType == SFX_REC_TYPE_FIXSIZE
986cdf0e10cSrcweir 					? _nContentNo * _nContentSize
987cdf0e10cSrcweir 					: SFX_REC_CONTENT_OFS(_pContentOfs[_nContentNo]);
988cdf0e10cSrcweir 		sal_uInt32 nNewPos = _nStartPos + nOffset;
989cdf0e10cSrcweir 		DBG_ASSERT( nNewPos >= _pStream->Tell(), "SfxMultiRecordReader::GetContent() - New position before current, to much data red!" );
990cdf0e10cSrcweir 
991cdf0e10cSrcweir 		// #99366#: correct stream pos in every case;
992cdf0e10cSrcweir         // the if clause was added by MT  a long time ago,
993cdf0e10cSrcweir         // maybe to 'repair' other corrupt documents; but this
994cdf0e10cSrcweir         // gives errors when writing with 5.1 and reading with current
995cdf0e10cSrcweir         // versions, so we decided to remove the if clause (KA-05/17/2002)
996cdf0e10cSrcweir         // if ( nNewPos > _pStream->Tell() )
997cdf0e10cSrcweir 		_pStream->Seek( nNewPos );
998cdf0e10cSrcweir 
999cdf0e10cSrcweir 		// ggf. Content-Header lesen
1000cdf0e10cSrcweir 		if ( _nRecordType == SFX_REC_TYPE_MIXTAGS ||
1001cdf0e10cSrcweir 			 _nRecordType == SFX_REC_TYPE_MIXTAGS_RELOC )
1002cdf0e10cSrcweir 		{
1003cdf0e10cSrcweir 			_nContentVer = sal::static_int_cast< sal_uInt8 >(
1004cdf0e10cSrcweir                 SFX_REC_CONTENT_VER(_pContentOfs[_nContentNo]));
1005cdf0e10cSrcweir 			*_pStream >> _nContentTag;
1006cdf0e10cSrcweir 		}
1007cdf0e10cSrcweir 
1008cdf0e10cSrcweir 		// ContentNo weiterz"ahlen
1009cdf0e10cSrcweir 		++_nContentNo;
1010cdf0e10cSrcweir 		return sal_True;
1011cdf0e10cSrcweir 	}
1012cdf0e10cSrcweir 
1013cdf0e10cSrcweir 	return sal_False;
1014cdf0e10cSrcweir }
1015cdf0e10cSrcweir 
1016cdf0e10cSrcweir 
1017