Branch data Line data Source code
1 : : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : : /*
3 : : * This file is part of the LibreOffice project.
4 : : *
5 : : * This Source Code Form is subject to the terms of the Mozilla Public
6 : : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : : *
9 : : * This file incorporates work covered by the following license notice:
10 : : *
11 : : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : : * contributor license agreements. See the NOTICE file distributed
13 : : * with this work for additional information regarding copyright
14 : : * ownership. The ASF licenses this file to you under the Apache
15 : : * License, Version 2.0 (the "License"); you may not use this file
16 : : * except in compliance with the License. You may obtain a copy of
17 : : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : : */
19 : :
20 : : #include <svl/filerec.hxx>
21 : : #include <osl/endian.h>
22 : :
23 : : //========================================================================
24 : :
25 : : /* Die folgenden Makros extrahieren Teilbereiche aus einem sal_uInt32 Wert.
26 : : Diese sal_uInt32-Werte werden anstelle der einzelnen Werte gestreamt,
27 : : um Calls zu sparen.
28 : : */
29 : :
30 : : #define SFX_REC_PRE(n) ( ((n) & 0x000000FF) )
31 : : #define SFX_REC_OFS(n) ( ((n) & 0xFFFFFF00) >> 8 )
32 : : #define SFX_REC_TYP(n) ( ((n) & 0x000000FF) )
33 : : #define SFX_REC_VER(n) ( ((n) & 0x0000FF00) >> 8 )
34 : : #define SFX_REC_TAG(n) ( ((n) & 0xFFFF0000) >> 16 )
35 : :
36 : : #define SFX_REC_CONTENT_VER(n) ( ((n) & 0x000000FF) )
37 : : #define SFX_REC_CONTENT_OFS(n) ( ((n) & 0xFFFFFF00) >> 8 )
38 : :
39 : : //-------------------------------------------------------------------------
40 : :
41 : : /* Die folgenden Makros setzen Teilbereiche zu einem sal_uInt32 Wert zusammen.
42 : : Diese sal_uInt32-Werte werden anstelle der einzelnen Werte gestreamt,
43 : : um Calls zu sparen.
44 : : */
45 : :
46 : : #define SFX_REC_MINI_HEADER(nPreTag,nStartPos,nEndPos) \
47 : : ( sal_uInt32(nPreTag) | \
48 : : sal_uInt32(nEndPos-nStartPos-SFX_REC_HEADERSIZE_MINI) << 8 )
49 : :
50 : : #define SFX_REC_HEADER(nRecType,nContentTag,nContentVer) \
51 : : ( sal_uInt32(nRecType) | \
52 : : ( sal_uInt32(nContentVer) << 8 ) | \
53 : : ( sal_uInt32(nContentTag) << 16 ) )
54 : :
55 : : #define SFX_REC_CONTENT_HEADER(nContentVer,n1StStartPos,nCurStartPos) \
56 : : ( sal_uInt32(nContentVer) | \
57 : : sal_uInt32( nCurStartPos - n1StStartPos ) << 8 )
58 : :
59 : : //=========================================================================
60 : :
61 : 46996 : sal_uInt32 SfxMiniRecordWriter::Close
62 : : (
63 : : bool bSeekToEndOfRec /* true (default)
64 : : Der Stream wird an das Ende des Records
65 : : positioniert.
66 : :
67 : : false
68 : : Der Stream wird an den Anfang des
69 : : Contents (also hinter den Header)
70 : : positioniert.
71 : : */
72 : : )
73 : :
74 : : /* [Beschreibung]
75 : :
76 : : Diese Methode schlie\st den Record. Dabei wird haupts"achlich der
77 : : Header geschrieben.
78 : :
79 : : Wurde der Header bereits geschrieben, hat der Aufruf keine Wirkung.
80 : :
81 : :
82 : : [R"uckgabewert]
83 : :
84 : : sal_uInt32 != 0
85 : : Position im Stream, die direkt hinter dem Record liegt.
86 : : 'bSeekToEndOfRecord==sal_True'
87 : : => R"uckgabewert == aktuelle Stream-Position nach Aufruf
88 : :
89 : : == 0
90 : : Der Header war bereits geschrieben worden.
91 : : */
92 : :
93 : : {
94 : : // wurde der Header noch nicht geschrieben?
95 [ + - ]: 46996 : if ( !_bHeaderOk )
96 : : {
97 : : // Header an den Anfang des Records schreiben
98 : 46996 : sal_uInt32 nEndPos = _pStream->Tell();
99 : 46996 : _pStream->Seek( _nStartPos );
100 : 46996 : *_pStream << SFX_REC_MINI_HEADER( _nPreTag, _nStartPos, nEndPos );
101 : :
102 : : // je nachdem ans Ende des Records seeken oder hinter Header bleiben
103 [ + + ]: 46996 : if ( bSeekToEndOfRec )
104 : 10260 : _pStream->Seek( nEndPos );
105 : :
106 : : // Header wurde JETZT geschrieben
107 : 46996 : _bHeaderOk = true;
108 : 46996 : return nEndPos;
109 : : }
110 : :
111 : : // Record war bereits geschlossen
112 : 46996 : return 0;
113 : : }
114 : :
115 : 0 : bool SfxMiniRecordReader::SetHeader_Impl( sal_uInt32 nHeader )
116 : :
117 : : /* [Beschreibung]
118 : :
119 : : Interne Methode zum nachtr"aglichen Verarbeiten eines extern gelesenen
120 : : Headers. Falls der Header eine End-Of-Records-Kennung darstellt,
121 : : wird am Stream ein Errorcode gesetzt und sal_False zur"uckgeliefert. Im
122 : : Fehlerfall wird der Stream jedoch nicht auf den Record-Anfang zur"uck-
123 : : gesetzt.
124 : : */
125 : :
126 : : {
127 : 0 : bool bRet = true;
128 : :
129 : : // Record-Ende und Pre-Tag aus dem Header ermitteln
130 : 0 : _nEofRec = _pStream->Tell() + SFX_REC_OFS(nHeader);
131 : 0 : _nPreTag = sal::static_int_cast< sal_uInt8 >(SFX_REC_PRE(nHeader));
132 : :
133 : : // wenn End-Of-Record-Kennung, dann Fehler
134 [ # # ]: 0 : if ( _nPreTag == SFX_REC_PRETAG_EOR )
135 : : {
136 : 0 : _pStream->SetError( ERRCODE_IO_WRONGFORMAT );
137 : 0 : bRet = true;
138 : : }
139 : 0 : return bRet;
140 : : }
141 : :
142 : 0 : SfxMiniRecordReader::SfxMiniRecordReader
143 : : (
144 : : SvStream* pStream, /* <SvStream>, an dessen aktueller
145 : : Position sich ein <SfxMiniRecord>
146 : : befindet.
147 : : */
148 : : sal_uInt8 nTag // Pre-Tag des gew"unschten Records
149 : : )
150 : :
151 : : /* [Beschreibung]
152 : :
153 : : Dieser Ctor interpretiert 'pStream' ab der aktuellen Position als
154 : : eine l"uckenlose Folge von, von dieser Klassen-Gruppe interpretierbaren,
155 : : Records. Der in dieser Folge erste als <SfxMiniRecord> interpretierbare
156 : : (also ggf. auch ein extended-Record) mit dem PreTag 'nTag' wird ge"offnet
157 : : und durch diese Instanz repr"asentiert.
158 : :
159 : : Wird das Ende des Streams oder die Kennung SFX_REC_PRETAG_EOR
160 : : erreicht, bevor ein Record mit dem ge"unschten Pre-Tag gefunden wird,
161 : : ist die erzeugte Instanz ung"ultig ('IsValid() == sal_False'). Ein ent-
162 : : sprechender Error-Code (ERRCODE_IO_EOF bzw. ERRCODE_IO_WRONGFORMAT)
163 : : ist dann am Stream gesetzt, dessen Position ist dann au\serdem unver-
164 : : "andert.
165 : :
166 : : Bei 'nTag==SFX_FILEREC_PRETAG_EOR' wird nicht versucht, einen Record
167 : : zu lesen, es wird sofort 'IsValid()' auf sal_False gesetzt und kein Error-Code
168 : : am Stream gesetzt. Dies ist dauzu gedacht, ohne 'new' und 'delete'
169 : : abw"rtskompatibel SfxMiniRecords einbauen zu k"onnen. Siehe dazu
170 : : <SfxItemSet::Load()>.
171 : :
172 : :
173 : : [Anwendungsvorschlag]
174 : :
175 : : Wird dieser Ctor in einer bereits ausgelieferten Programmversion
176 : : verwendet, k"onnen in das File-Format jeweils davor kompatibel neue
177 : : Records mit einer anderen Kennung eingef"ugt werden. Diese werden
178 : : schlie\slich automatisch "uberlesen. Erkauft wird diese M"oglichkeit
179 : : allerdings mit etwas schlechterem Laufzeitverhalten im Vergleich mit
180 : : direktem 'drauf-los-lesen', der sich jedoch auf einen Vergleich zweier
181 : : Bytes reduziert, falls der gesuchte Record der erste in der Folge ist.
182 : : */
183 : :
184 : : : _pStream( pStream ),
185 : 0 : _bSkipped( nTag == SFX_REC_PRETAG_EOR )
186 : : {
187 : : // ggf. ignorieren (s.o.)
188 [ # # ]: 0 : if ( _bSkipped )
189 : : {
190 : 0 : _nPreTag = nTag;
191 : 0 : return;
192 : : }
193 : :
194 : : // StartPos merken, um im Fehlerfall zur"uck-seeken zu k"onnen
195 : 0 : sal_uInt32 nStartPos = pStream->Tell();
196 : :
197 : : // passenden Record suchen
198 : 0 : while(sal_True)
199 : : {
200 : : // Header lesen
201 : : DBG( DbgOutf( "SfxFileRec: searching record at %ul", pStream->Tell() ) );
202 : : sal_uInt32 nHeader;
203 [ # # ]: 0 : *pStream >> nHeader;
204 : :
205 : : // Headerdaten von Basisklasse extrahieren lassen
206 [ # # ]: 0 : SetHeader_Impl( nHeader );
207 : :
208 : : // ggf. Fehler behandeln
209 [ # # ]: 0 : if ( pStream->IsEof() )
210 : 0 : _nPreTag = SFX_REC_PRETAG_EOR;
211 [ # # ]: 0 : else if ( _nPreTag == SFX_REC_PRETAG_EOR )
212 [ # # ]: 0 : pStream->SetError( ERRCODE_IO_WRONGFORMAT );
213 : : else
214 : : {
215 : : // wenn gefunden, dann Schleife abbrechen
216 [ # # ]: 0 : if ( _nPreTag == nTag )
217 : : break;
218 : :
219 : : // sonst skippen und weitersuchen
220 [ # # ]: 0 : pStream->Seek( _nEofRec );
221 : 0 : continue;
222 : : }
223 : :
224 : : // Fehler => zur"uck-seeken
225 [ # # ]: 0 : pStream->Seek( nStartPos );
226 : : break;
227 : : }
228 : : }
229 : :
230 : : //=========================================================================
231 : :
232 : 36736 : SfxSingleRecordWriter::SfxSingleRecordWriter
233 : : (
234 : : sal_uInt8 nRecordType, // f"ur Subklassen
235 : : SvStream* pStream, // Stream, in dem der Record angelegt wird
236 : : sal_uInt16 nContentTag, // Inhalts-Art-Kennung
237 : : sal_uInt8 nContentVer // Inhalts-Versions-Kennung
238 : : )
239 : :
240 : : /* [Beschreibung]
241 : :
242 : : Interner Ctor f"ur Subklassen.
243 : : */
244 : :
245 : 36736 : : SfxMiniRecordWriter( pStream, SFX_REC_PRETAG_EXT )
246 : : {
247 : : // Erweiterten Header hiner den des SfxMiniRec schreiben
248 [ + - ]: 36736 : *pStream << SFX_REC_HEADER(nRecordType, nContentTag, nContentVer);
249 : 36736 : }
250 : :
251 : : //=========================================================================
252 : :
253 : : inline bool SfxSingleRecordReader::ReadHeader_Impl( sal_uInt16 nTypes )
254 : :
255 : : /* [Beschreibung]
256 : :
257 : : Interne Methode zum Einlesen eines SfxMultiRecord-Headers, nachdem
258 : : die Basisklasse bereits initialisiert und deren Header gelesen ist.
259 : : Ggf. ist ein Error-Code am Stream gesetzt, im Fehlerfall wird jedoch
260 : : nicht zur"uckge-seekt.
261 : : */
262 : :
263 : : {
264 : : bool bRet;
265 : :
266 : : // Basisklassen-Header einlesen
267 : : sal_uInt32 nHeader=0;
268 : : *_pStream >> nHeader;
269 : : if ( !SetHeader_Impl( nHeader ) )
270 : : bRet = false;
271 : : else
272 : : {
273 : : // eigenen Header einlesen
274 : : *_pStream >> nHeader;
275 : : _nRecordVer = sal::static_int_cast< sal_uInt8 >(SFX_REC_VER(nHeader));
276 : : _nRecordTag = sal::static_int_cast< sal_uInt16 >(SFX_REC_TAG(nHeader));
277 : :
278 : : // falscher Record-Typ?
279 : : _nRecordType = sal::static_int_cast< sal_uInt8 >(SFX_REC_TYP(nHeader));
280 : : bRet = 0 != ( nTypes & _nRecordType);
281 : : }
282 : : return bRet;
283 : : }
284 : :
285 : : //-------------------------------------------------------------------------
286 : :
287 : 0 : bool SfxSingleRecordReader::FindHeader_Impl
288 : : (
289 : : sal_uInt16 nTypes, // arithm. Veroderung erlaubter Record-Typen
290 : : sal_uInt16 nTag // zu findende Record-Art-Kennung
291 : : )
292 : :
293 : : /* [Beschreibung]
294 : :
295 : : Interne Methode zum lesen des Headers des ersten Record, der einem
296 : : der Typen in 'nTypes' entspricht und mit der Art-Kennung 'nTag'
297 : : gekennzeichnet ist.
298 : :
299 : : Kann ein solcher Record nicht gefunden werden, wird am Stream ein
300 : : Errorcode gesetzt, zur"uck-geseekt und sal_False zur"uckgeliefert.
301 : : */
302 : :
303 : : {
304 : : // StartPos merken, um im Fehlerfall zur"uck-seeken zu k"onnen
305 : 0 : sal_uInt32 nStartPos = _pStream->Tell();
306 : :
307 : : // richtigen Record suchen
308 [ # # ]: 0 : while ( !_pStream->IsEof() )
309 : : {
310 : : // Header lesen
311 : : sal_uInt32 nHeader;
312 : : DBG( DbgOutf( "SfxFileRec: searching record at %ul", _pStream->Tell() ) );
313 [ # # ]: 0 : *_pStream >> nHeader;
314 [ # # ][ # # ]: 0 : if ( !SetHeader_Impl( nHeader ) )
315 : : // EOR => Such-Schleife abbreichen
316 : : break;
317 : :
318 : : // Extended Record gefunden?
319 [ # # ]: 0 : if ( _nPreTag == SFX_REC_PRETAG_EXT )
320 : : {
321 : : // Extended Header lesen
322 [ # # ]: 0 : *_pStream >> nHeader;
323 : 0 : _nRecordTag = sal::static_int_cast< sal_uInt16 >(SFX_REC_TAG(nHeader));
324 : :
325 : : // richtigen Record gefunden?
326 [ # # ]: 0 : if ( _nRecordTag == nTag )
327 : : {
328 : : // gefundener Record-Typ passend?
329 : : _nRecordType = sal::static_int_cast< sal_uInt8 >(
330 : 0 : SFX_REC_TYP(nHeader));
331 [ # # ]: 0 : if ( nTypes & _nRecordType )
332 : : // ==> gefunden
333 : 0 : return sal_True;
334 : :
335 : : // error => Such-Schleife abbrechen
336 : : break;
337 : : }
338 : : }
339 : :
340 : : // sonst skippen
341 [ # # ]: 0 : if ( !_pStream->IsEof() )
342 [ # # ]: 0 : _pStream->Seek( _nEofRec );
343 : : }
344 : :
345 : : // Fehler setzen und zur"uck-seeken
346 : 0 : _pStream->SetError( ERRCODE_IO_WRONGFORMAT );
347 : 0 : _pStream->Seek( nStartPos );
348 : 0 : return sal_False;
349 : : }
350 : :
351 : : //=========================================================================
352 : :
353 : 36736 : SfxMultiFixRecordWriter::SfxMultiFixRecordWriter
354 : : (
355 : : sal_uInt8 nRecordType, // Subklassen Record-Kennung
356 : : SvStream* pStream, // Stream, in dem der Record angelegt wird
357 : : sal_uInt16 nContentTag, // Content-Art-Kennung
358 : : sal_uInt8 nContentVer // Content-Versions-Kennung
359 : : )
360 : :
361 : : /* [Beschreibung]
362 : :
363 : : Interne Methode f"ur Subklassen.
364 : : */
365 : :
366 : : : SfxSingleRecordWriter( nRecordType, pStream, nContentTag, nContentVer ),
367 : 36736 : _nContentCount( 0 )
368 : : {
369 : : // Platz f"ur eigenen Header
370 [ + - ]: 36736 : pStream->SeekRel( + SFX_REC_HEADERSIZE_MULTI );
371 : 36736 : }
372 : :
373 : : //------------------------------------------------------------------------
374 : :
375 : 0 : sal_uInt32 SfxMultiFixRecordWriter::Close( bool bSeekToEndOfRec )
376 : :
377 : : // siehe <SfxMiniRecordWriter>
378 : :
379 : : {
380 : : // Header noch nicht geschrieben?
381 [ # # ]: 0 : if ( !_bHeaderOk )
382 : : {
383 : : // Position hinter Record merken, um sie restaurieren zu k"onnen
384 : 0 : sal_uInt32 nEndPos = SfxSingleRecordWriter::Close( sal_False );
385 : :
386 : : // gegen"uber SfxSingleRecord erweiterten Header schreiben
387 : 0 : *_pStream << _nContentCount;
388 : 0 : *_pStream << _nContentSize;
389 : :
390 : : // je nachdem ans Ende des Records seeken oder hinter Header bleiben
391 [ # # ]: 0 : if ( bSeekToEndOfRec )
392 : 0 : _pStream->Seek(nEndPos);
393 : 0 : return nEndPos;
394 : : }
395 : :
396 : : // Record war bereits geschlossen
397 : 0 : return 0;
398 : : }
399 : :
400 : : //=========================================================================
401 : :
402 : 31606 : SfxMultiVarRecordWriter::SfxMultiVarRecordWriter
403 : : (
404 : : sal_uInt8 nRecordType, // Record-Kennung der Subklasse
405 : : SvStream* pStream, // Stream, in dem der Record angelegt wird
406 : : sal_uInt16 nRecordTag, // Gesamt-Art-Kennung
407 : : sal_uInt8 nRecordVer // Gesamt-Versions-Kennung
408 : : )
409 : :
410 : : /* [Beschreibung]
411 : :
412 : : Interner Ctor f"ur Subklassen.
413 : : */
414 : :
415 : : : SfxMultiFixRecordWriter( nRecordType, pStream, nRecordTag, nRecordVer ),
416 [ + - ]: 31606 : _nContentVer( 0 )
417 : : {
418 : 31606 : }
419 : :
420 : : //-------------------------------------------------------------------------
421 : :
422 : 5130 : SfxMultiVarRecordWriter::SfxMultiVarRecordWriter
423 : : (
424 : : SvStream* pStream, // Stream, in dem der Record angelegt wird
425 : : sal_uInt16 nRecordTag, // Gesamt-Art-Kennung
426 : : sal_uInt8 nRecordVer // Gesamt-Versions-Kennung
427 : : )
428 : :
429 : : /* [Beschreibung]
430 : :
431 : : Legt in 'pStream' einen 'SfxMultiVarRecord' an, dessen Content-Gr"o\sen
432 : : weder bekannt sind noch identisch sein m"ussen, sondern jeweils nach dem
433 : : Streamen jedes einzelnen Contents errechnet werden sollen.
434 : :
435 : :
436 : : [Anmerkung]
437 : :
438 : : Diese Methode ist nicht inline, da f"ur die Initialisierung eines
439 : : <SvULongs>-Members zu viel Code generiert werden w"urde.
440 : : */
441 : :
442 : : : SfxMultiFixRecordWriter( SFX_REC_TYPE_VARSIZE,
443 : : pStream, nRecordTag, nRecordVer ),
444 [ + - ]: 5130 : _nContentVer( 0 )
445 : : {
446 : 5130 : }
447 : :
448 : : //-------------------------------------------------------------------------
449 : :
450 : 36736 : SfxMultiVarRecordWriter::~SfxMultiVarRecordWriter()
451 : :
452 : : /* [Beschreibung]
453 : :
454 : : Der Dtor der Klasse <SfxMultiVarRecordWriter> schlie\st den Record
455 : : automatisch, falls <SfxMultiVarRecordWriter::Close()> nicht bereits
456 : : explizit gerufen wurde.
457 : : */
458 : :
459 : : {
460 : : // wurde der Header noch nicht geschrieben oder mu\s er gepr"uft werden
461 [ + - ]: 36736 : if ( !_bHeaderOk )
462 [ + - ]: 36736 : Close();
463 [ - + ]: 36736 : }
464 : :
465 : : //-------------------------------------------------------------------------
466 : :
467 : 69708 : void SfxMultiVarRecordWriter::FlushContent_Impl()
468 : :
469 : : /* [Beschreibung]
470 : :
471 : : Interne Methode zum Abschlie\sen eines einzelnen Contents.
472 : : */
473 : :
474 : : {
475 : : // Versions-Kennung und Positions-Offset des aktuellen Contents merken;
476 : : // das Positions-Offset ist relativ zur Startposition des ersten Contents
477 : : assert(_aContentOfs.size() == static_cast<size_t>(_nContentCount)-1);
478 : 69708 : _aContentOfs.resize(_nContentCount-1);
479 : : _aContentOfs.push_back(
480 [ + - ]: 69708 : SFX_REC_CONTENT_HEADER(_nContentVer,_nStartPos,_nContentStartPos));
481 : 69708 : }
482 : :
483 : : //-------------------------------------------------------------------------
484 : :
485 : 25650 : void SfxMultiVarRecordWriter::NewContent()
486 : :
487 : : // siehe <SfxMultiFixRecordWriter>
488 : :
489 : : {
490 : : // schon ein Content geschrieben?
491 [ + + ]: 25650 : if ( _nContentCount )
492 : 20520 : FlushContent_Impl();
493 : :
494 : : // neuen Content beginnen
495 : 25650 : _nContentStartPos = _pStream->Tell();
496 : 25650 : ++_nContentCount;
497 : 25650 : }
498 : :
499 : : //-------------------------------------------------------------------------
500 : :
501 : 36736 : sal_uInt32 SfxMultiVarRecordWriter::Close( bool bSeekToEndOfRec )
502 : :
503 : : // siehe <SfxMiniRecordWriter>
504 : :
505 : : {
506 : : // Header noch nicht geschrieben?
507 [ + - ]: 36736 : if ( !_bHeaderOk )
508 : : {
509 : : // ggf. letzten Content abschlie\sen
510 [ + + ]: 36736 : if ( _nContentCount )
511 : 27372 : FlushContent_Impl();
512 : :
513 : : // Content-Offset-Tabelle schreiben
514 : 36736 : sal_uInt32 nContentOfsPos = _pStream->Tell();
515 : : //! darf man das so einr"ucken?
516 [ + + ]: 106444 : for ( sal_uInt16 n = 0; n < _nContentCount; ++n )
517 : 69708 : *_pStream << _aContentOfs[n];
518 : :
519 : : // SfxMultiFixRecordWriter::Close() "uberspringen!
520 : 36736 : sal_uInt32 nEndPos = SfxSingleRecordWriter::Close( sal_False );
521 : :
522 : : // eigenen Header schreiben
523 : 36736 : *_pStream << _nContentCount;
524 [ - + ][ + - ]: 36736 : if ( SFX_REC_TYPE_VARSIZE_RELOC == _nPreTag ||
525 : : SFX_REC_TYPE_MIXTAGS_RELOC == _nPreTag )
526 : 0 : *_pStream << static_cast<sal_uInt32>(nContentOfsPos - ( _pStream->Tell() + sizeof(sal_uInt32) ));
527 : : else
528 : 36736 : *_pStream << nContentOfsPos;
529 : :
530 : : // ans Ende des Records seeken bzw. am Ende des Headers bleiben
531 [ + - ]: 36736 : if ( bSeekToEndOfRec )
532 : 36736 : _pStream->Seek(nEndPos);
533 : 36736 : return nEndPos;
534 : : }
535 : :
536 : : // Record war bereits vorher geschlossen
537 : 36736 : return 0;
538 : : }
539 : :
540 : : //=========================================================================
541 : :
542 : 44058 : void SfxMultiMixRecordWriter::NewContent
543 : : (
544 : : sal_uInt16 nContentTag, // Kennung f"ur die Art des Contents
545 : : sal_uInt8 nContentVer // Kennung f"ur die Version des Contents
546 : : )
547 : :
548 : : /* [Beschreibung]
549 : :
550 : : Mit dieser Methode wird in den Record ein neuer Content eingef"ugt
551 : : und dessen Content-Tag sowie dessen Content-Version angegeben. Jeder,
552 : : auch der 1. Record mu\s durch Aufruf dieser Methode eingeleitet werden.
553 : : */
554 : :
555 : : {
556 : : // ggf. vorherigen Record abschlie\sen
557 [ + + ]: 44058 : if ( _nContentCount )
558 : 21816 : FlushContent_Impl();
559 : :
560 : : // Tag vor den Content schreiben, Version und Startposition merken
561 : 44058 : _nContentStartPos = _pStream->Tell();
562 : 44058 : ++_nContentCount;
563 : 44058 : *_pStream << nContentTag;
564 : 44058 : _nContentVer = nContentVer;
565 : 44058 : }
566 : :
567 : : //=========================================================================
568 : :
569 : 0 : bool SfxMultiRecordReader::ReadHeader_Impl()
570 : :
571 : : /* [Beschreibung]
572 : :
573 : : Interne Methode zum Einlesen eines SfxMultiRecord-Headers, nachdem
574 : : die Basisklasse bereits initialisiert und deren Header gelesen ist.
575 : : Ggf. ist ein Error-Code am Stream gesetzt, im Fehlerfall wird jedoch
576 : : nicht zur"uckge-seekt.
577 : : */
578 : :
579 : : {
580 : : // eigenen Header lesen
581 : 0 : *_pStream >> _nContentCount;
582 : 0 : *_pStream >> _nContentSize; // Fix: jedes einzelnen, Var|Mix: Tabellen-Pos.
583 : :
584 : : // mu\s noch eine Tabelle mit Content-Offsets geladen werden?
585 [ # # ]: 0 : if ( _nRecordType != SFX_REC_TYPE_FIXSIZE )
586 : : {
587 : : // Tabelle aus dem Stream einlesen
588 : 0 : sal_uInt32 nContentPos = _pStream->Tell();
589 [ # # ][ # # ]: 0 : if ( _nRecordType == SFX_REC_TYPE_VARSIZE_RELOC ||
590 : : _nRecordType == SFX_REC_TYPE_MIXTAGS_RELOC )
591 : 0 : _pStream->SeekRel( + _nContentSize );
592 : : else
593 : 0 : _pStream->Seek( _nContentSize );
594 : 0 : _pContentOfs = new sal_uInt32[_nContentCount];
595 : 0 : memset(_pContentOfs, 0, _nContentCount*sizeof(sal_uInt32));
596 : : //! darf man jetzt so einr"ucken
597 : : #if defined(OSL_LITENDIAN)
598 : 0 : _pStream->Read( _pContentOfs, sizeof(sal_uInt32)*_nContentCount );
599 : : #else
600 : : for ( sal_uInt16 n = 0; n < _nContentCount; ++n )
601 : : *_pStream >> _pContentOfs[n];
602 : : #endif
603 : 0 : _pStream->Seek( nContentPos );
604 : : }
605 : :
606 : : // Header konnte gelesen werden, wenn am Stream kein Error gesetzt ist
607 : 0 : return !_pStream->GetError();
608 : : }
609 : :
610 : : //-------------------------------------------------------------------------
611 : :
612 : 0 : SfxMultiRecordReader::SfxMultiRecordReader( SvStream *pStream, sal_uInt16 nTag )
613 : : : _pContentOfs(0)
614 : : , _nContentSize(0)
615 : : , _nContentCount(0)
616 : 0 : , _nContentNo(0)
617 : : {
618 : : // Position im Stream merken, um im Fehlerfall zur"uck-seeken zu k"onnen
619 : 0 : _nStartPos = pStream->Tell();
620 : :
621 : : // passenden Record suchen und Basisklasse initialisieren
622 : 0 : SfxSingleRecordReader::Construct_Impl( pStream );
623 [ # # ][ # # ]: 0 : if ( SfxSingleRecordReader::FindHeader_Impl( SFX_REC_TYPE_FIXSIZE |
624 : : SFX_REC_TYPE_VARSIZE | SFX_REC_TYPE_VARSIZE_RELOC |
625 : : SFX_REC_TYPE_MIXTAGS | SFX_REC_TYPE_MIXTAGS_RELOC,
626 : 0 : nTag ) )
627 : : {
628 : : // eigenen Header dazu-lesen
629 [ # # ][ # # ]: 0 : if ( !ReadHeader_Impl() )
630 : : // nicht lesbar => als ung"ultig markieren und zur"uck-seeken
631 [ # # ]: 0 : SetInvalid_Impl( _nStartPos);
632 : : }
633 : 0 : }
634 : :
635 : : //-------------------------------------------------------------------------
636 : :
637 : 0 : SfxMultiRecordReader::~SfxMultiRecordReader()
638 : : {
639 [ # # ]: 0 : delete[] _pContentOfs;
640 : 0 : }
641 : :
642 : : //-------------------------------------------------------------------------
643 : :
644 : 0 : bool SfxMultiRecordReader::GetContent()
645 : :
646 : : /* [Beschreibung]
647 : :
648 : : Positioniert den Stream an den Anfang des n"chsten bzw. beim 1. Aufruf
649 : : auf den Anfang des ersten Contents im Record und liest ggf. dessen
650 : : Header ein.
651 : :
652 : : Liegt laut Record-Header kein Content mehr vor, wird sal_False zur"uck-
653 : : gegeben. Trotz einem sal_True-Returnwert kann am Stream ein Fehlercode
654 : : gesetzt sein, z.B. falls er unvorhergesehenerweise (kaputtes File)
655 : : zuende ist.
656 : : */
657 : :
658 : : {
659 : : // noch ein Content vorhanden?
660 [ # # ]: 0 : if ( _nContentNo < _nContentCount )
661 : : {
662 : : // den Stream an den Anfang des Contents positionieren
663 : : sal_uInt32 nOffset = _nRecordType == SFX_REC_TYPE_FIXSIZE
664 : : ? _nContentNo * _nContentSize
665 [ # # ]: 0 : : SFX_REC_CONTENT_OFS(_pContentOfs[_nContentNo]);
666 : 0 : sal_uInt32 nNewPos = _nStartPos + nOffset;
667 : : DBG_ASSERT( nNewPos >= _pStream->Tell(), "SfxMultiRecordReader::GetContent() - New position before current, to much data red!" );
668 : :
669 : : // #99366#: correct stream pos in every case;
670 : : // the if clause was added by MT a long time ago,
671 : : // maybe to 'repair' other corrupt documents; but this
672 : : // gives errors when writing with 5.1 and reading with current
673 : : // versions, so we decided to remove the if clause (KA-05/17/2002)
674 : : // if ( nNewPos > _pStream->Tell() )
675 : 0 : _pStream->Seek( nNewPos );
676 : :
677 : : // ggf. Content-Header lesen
678 [ # # ][ # # ]: 0 : if ( _nRecordType == SFX_REC_TYPE_MIXTAGS ||
679 : : _nRecordType == SFX_REC_TYPE_MIXTAGS_RELOC )
680 : : {
681 : : _nContentVer = sal::static_int_cast< sal_uInt8 >(
682 : 0 : SFX_REC_CONTENT_VER(_pContentOfs[_nContentNo]));
683 : 0 : *_pStream >> _nContentTag;
684 : : }
685 : :
686 : : // ContentNo weiterz"ahlen
687 : 0 : ++_nContentNo;
688 : 0 : return sal_True;
689 : : }
690 : :
691 : 0 : return sal_False;
692 : : }
693 : :
694 : :
695 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|