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 8978 : 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 8978 : if ( !_bHeaderOk )
96 : {
97 : // Header an den Anfang des Records schreiben
98 8978 : sal_uInt32 nEndPos = _pStream->Tell();
99 8978 : _pStream->Seek( _nStartPos );
100 8978 : *_pStream << SFX_REC_MINI_HEADER( _nPreTag, _nStartPos, nEndPos );
101 :
102 : // je nachdem ans Ende des Records seeken oder hinter Header bleiben
103 8978 : if ( bSeekToEndOfRec )
104 1776 : _pStream->Seek( nEndPos );
105 :
106 : // Header wurde JETZT geschrieben
107 8978 : _bHeaderOk = true;
108 8978 : return nEndPos;
109 : }
110 :
111 : // Record war bereits geschlossen
112 0 : 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 7202 : 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 7202 : : SfxMiniRecordWriter( pStream, SFX_REC_PRETAG_EXT )
246 : {
247 : // Erweiterten Header hiner den des SfxMiniRec schreiben
248 7202 : *pStream << SFX_REC_HEADER(nRecordType, nContentTag, nContentVer);
249 7202 : }
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 7202 : 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 7202 : _nContentCount( 0 )
368 : {
369 : // Platz f"ur eigenen Header
370 7202 : pStream->SeekRel( + SFX_REC_HEADERSIZE_MULTI );
371 7202 : }
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 6314 : 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 6314 : _nContentVer( 0 )
417 : {
418 6314 : }
419 :
420 : //-------------------------------------------------------------------------
421 :
422 888 : 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 888 : _nContentVer( 0 )
445 : {
446 888 : }
447 :
448 : //-------------------------------------------------------------------------
449 :
450 14404 : 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 7202 : if ( !_bHeaderOk )
462 7202 : Close();
463 7202 : }
464 :
465 : //-------------------------------------------------------------------------
466 :
467 13786 : 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 13786 : _aContentOfs.resize(_nContentCount-1);
479 : _aContentOfs.push_back(
480 13786 : SFX_REC_CONTENT_HEADER(_nContentVer,_nStartPos,_nContentStartPos));
481 13786 : }
482 :
483 : //-------------------------------------------------------------------------
484 :
485 4440 : void SfxMultiVarRecordWriter::NewContent()
486 :
487 : // siehe <SfxMultiFixRecordWriter>
488 :
489 : {
490 : // schon ein Content geschrieben?
491 4440 : if ( _nContentCount )
492 3552 : FlushContent_Impl();
493 :
494 : // neuen Content beginnen
495 4440 : _nContentStartPos = _pStream->Tell();
496 4440 : ++_nContentCount;
497 4440 : }
498 :
499 : //-------------------------------------------------------------------------
500 :
501 7202 : sal_uInt32 SfxMultiVarRecordWriter::Close( bool bSeekToEndOfRec )
502 :
503 : // siehe <SfxMiniRecordWriter>
504 :
505 : {
506 : // Header noch nicht geschrieben?
507 7202 : if ( !_bHeaderOk )
508 : {
509 : // ggf. letzten Content abschlie\sen
510 7202 : if ( _nContentCount )
511 5614 : FlushContent_Impl();
512 :
513 : // Content-Offset-Tabelle schreiben
514 7202 : sal_uInt32 nContentOfsPos = _pStream->Tell();
515 : //! darf man das so einr"ucken?
516 20988 : for ( sal_uInt16 n = 0; n < _nContentCount; ++n )
517 13786 : *_pStream << _aContentOfs[n];
518 :
519 : // SfxMultiFixRecordWriter::Close() "uberspringen!
520 7202 : sal_uInt32 nEndPos = SfxSingleRecordWriter::Close( sal_False );
521 :
522 : // eigenen Header schreiben
523 7202 : *_pStream << _nContentCount;
524 7202 : 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 7202 : *_pStream << nContentOfsPos;
529 :
530 : // ans Ende des Records seeken bzw. am Ende des Headers bleiben
531 7202 : if ( bSeekToEndOfRec )
532 7202 : _pStream->Seek(nEndPos);
533 7202 : return nEndPos;
534 : }
535 :
536 : // Record war bereits vorher geschlossen
537 0 : return 0;
538 : }
539 :
540 : //=========================================================================
541 :
542 9346 : 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 9346 : if ( _nContentCount )
558 4620 : FlushContent_Impl();
559 :
560 : // Tag vor den Content schreiben, Version und Startposition merken
561 9346 : _nContentStartPos = _pStream->Tell();
562 9346 : ++_nContentCount;
563 9346 : *_pStream << nContentTag;
564 9346 : _nContentVer = nContentVer;
565 9346 : }
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: */
|