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