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