diff options
Diffstat (limited to 'svtools/source/filerec/filerec.cxx')
-rw-r--r-- | svtools/source/filerec/filerec.cxx | 1019 |
1 files changed, 0 insertions, 1019 deletions
diff --git a/svtools/source/filerec/filerec.cxx b/svtools/source/filerec/filerec.cxx deleted file mode 100644 index 262e5135572a..000000000000 --- a/svtools/source/filerec/filerec.cxx +++ /dev/null @@ -1,1019 +0,0 @@ -/************************************************************************* - * - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * Copyright 2008 by Sun Microsystems, Inc. - * - * OpenOffice.org - a multi-platform office productivity suite - * - * $RCSfile: filerec.cxx,v $ - * $Revision: 1.13 $ - * - * This file is part of OpenOffice.org. - * - * OpenOffice.org is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 3 - * only, as published by the Free Software Foundation. - * - * OpenOffice.org is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License version 3 for more details - * (a copy is included in the LICENSE file that accompanied this code). - * - * You should have received a copy of the GNU Lesser General Public License - * version 3 along with OpenOffice.org. If not, see - * <http://www.openoffice.org/license.html> - * for a copy of the LGPLv3 License. - * - ************************************************************************/ - -// MARKER(update_precomp.py): autogen include statement, do not remove -#include "precompiled_svtools.hxx" -#include <svtools/filerec.hxx> -#include <osl/endian.h> - -//======================================================================== - -SV_IMPL_VARARR( SfxUINT32s, UINT32 ); - -//======================================================================== - -/* Die folgenden Makros extrahieren Teilbereiche aus einem UINT32 Wert. - Diese UINT32-Werte werden anstelle der einzelnen Werte gestreamt, - um Calls zu sparen. -*/ - -#define SFX_REC_PRE(n) ( ((n) & 0x000000FF) ) -#define SFX_REC_OFS(n) ( ((n) & 0xFFFFFF00) >> 8 ) -#define SFX_REC_TYP(n) ( ((n) & 0x000000FF) ) -#define SFX_REC_VER(n) ( ((n) & 0x0000FF00) >> 8 ) -#define SFX_REC_TAG(n) ( ((n) & 0xFFFF0000) >> 16 ) - -#define SFX_REC_CONTENT_VER(n) ( ((n) & 0x000000FF) ) -#define SFX_REC_CONTENT_OFS(n) ( ((n) & 0xFFFFFF00) >> 8 ) - -//------------------------------------------------------------------------- - -/* Die folgenden Makros setzen Teilbereiche zu einem UINT32 Wert zusammen. - Diese UINT32-Werte werden anstelle der einzelnen Werte gestreamt, - um Calls zu sparen. -*/ - -#define SFX_REC_MINI_HEADER(nPreTag,nStartPos,nEndPos) \ - ( UINT32(nPreTag) | \ - UINT32(nEndPos-nStartPos-SFX_REC_HEADERSIZE_MINI) << 8 ) - -#define SFX_REC_HEADER(nRecType,nContentTag,nContentVer) \ - ( UINT32(nRecType) | \ - ( UINT32(nContentVer) << 8 ) | \ - ( UINT32(nContentTag) << 16 ) ) - -#define SFX_REC_CONTENT_HEADER(nContentVer,n1StStartPos,nCurStartPos) \ - ( UINT32(nContentVer) | \ - UINT32( nCurStartPos - n1StStartPos ) << 8 ) - -//========================================================================= - -UINT32 SfxMiniRecordWriter::Close -( - FASTBOOL bSeekToEndOfRec /* TRUE (default) - Der Stream wird an das Ende des Records - positioniert. - - FALSE - Der Stream wird an den Anfang des - Contents (also hinter den Header) - positioniert. - */ -) - -/* [Beschreibung] - - Diese Methode schlie\st den Record. Dabei wird haupts"achlich der - Header geschrieben. - - Wurde der Header bereits geschrieben, hat der Aufruf keine Wirkung. - - - [R"uckgabewert] - - UINT32 != 0 - Position im Stream, die direkt hinter dem Record liegt. - 'bSeekToEndOfRecord==TRUE' - => R"uckgabewert == aktuelle Stream-Position nach Aufruf - - == 0 - Der Header war bereits geschrieben worden. -*/ - -{ - // wurde der Header noch nicht geschrieben? - if ( !_bHeaderOk ) - { - // Header an den Anfang des Records schreiben - UINT32 nEndPos = _pStream->Tell(); - _pStream->Seek( _nStartPos ); - *_pStream << SFX_REC_MINI_HEADER( _nPreTag, _nStartPos, nEndPos ); - - // je nachdem ans Ende des Records seeken oder hinter Header bleiben - if ( bSeekToEndOfRec ) - _pStream->Seek( nEndPos ); - - // Header wurde JETZT geschrieben - _bHeaderOk = TRUE; - return nEndPos; - } -#ifdef DBG_UTIL - // mu\s Fix-Size-Record gepr"uft werden? - else if ( SFX_BOOL_DONTCARE == _bHeaderOk ) - { - // Header auslesen, um Soll-Gr"o\se zu bestimmen - UINT32 nEndPos = _pStream->Tell(); - _pStream->Seek( _nStartPos ); - UINT32 nHeader; - *_pStream >> nHeader; - _pStream->Seek( nEndPos ); - - // Soll-Gr"o\se mit Ist-Gr"o\se vergleichen - DBG_ASSERT( nEndPos - SFX_REC_OFS(nHeader) == _nStartPos + sizeof(UINT32), - "fixed record size incorrect" ); - DbgOutf( "SfxFileRec: written record until %ul", nEndPos ); - } -#endif - - // Record war bereits geschlossen - return 0; -} - -//========================================================================= - -USHORT SfxMiniRecordReader::ScanRecordType -( - SvStream* pStream /* <SvStream> an dessen aktueller Position - ein Record liegt, dessen Typ erkannt werden - soll. - */ -) - -/* [Beschreibung] - - Mit dieser statischen Methode kann ermittelt werden, ob sich an der - aktuellen Position in einem Stream ein Record befindet, und der Typ - des Records kann ermittelt werden. - - Die Position im Stream ist nach dem Aufruf aufver"andert. - - - [Anmerkung] - - Die Record-Typen k"onnen zwar (abgesehen vom Drawing-Enginge-Record) - untereinander eindeutig erkannt werden, es besteht jedoch die Gefahr - der Verwechslung von Records mit normalen Daten. File-Formate sollten - darauf R"ucksicht nehmen. Handelt es sich um keinen Record, wird - am wahrscheinlichsten SFX_REC_TYPE_MINI zur"uckgeliefert, da dieser - Typ sich aufgrund seines sparsam kurzen Headers durch die k"urzeste - Kennung auszeichnet. - - - [R"uckgabewert] - - USHORT SFX_REC_TYPE_EOR - An der aktuellen Position des Streams - steht eine End-Of-Records-Kennung. - - SFX_REC_TYPE_MINI - Es handelt sich um einen SW3 kompatiblen - Mini-Record, dessen einzige Kennung sein - 'Mini-Tag' ist. - - SFX_REC_TYPE_SINGLE - Es handelt sich um einen Extended-Record - mit einem einzigen Content, der durch eine - Version und ein Tag n"aher gekennzeichnet - ist. - - SFX_REC_TYPE_FIXSIZE - Es handelt sich um einen Extended-Record - mit mehreren Contents gleicher Gr"o\se, - die gemeinsam durch eine einzige Version - und ein einziges gemeinsames Tag n"aher - gekennzeichnet sind. - - SFX_REC_TYPE_VARSIZE - Es handelt sich um einen Extended-Record - mit mehreren Contents variabler Gr"o\se, - die gemeinsam durch eine einzige Version - und ein einziges gemeinsames Tag n"aher - gekennzeichnet sind. - - SFX_REC_TYPE_MIXTAGS - Es handelt sich um einen Extended-Record - mit mehreren Contents variabler Gr"o\se, - die jeweils durch ein eignes Tag und - eine eigene Versions-Nummer n"aher - gekennzeichnet sind. - - SFX_REC_TYPE_DRAWENG - Es handelt sich wahrscheinlich um einen - Drawing-Engine-Record. Dieser Record-Typ - kann von den Klassen dieser Gruppe nicht - interpretiert werden. -*/ - -{ - // die ersten 4 Bytes als Mini-Header lesen - sal_uInt32 nHeader; - *pStream >> nHeader; - - // k"onnte es sich um einen extended-Record handeln? - USHORT nPreTag = sal::static_int_cast< USHORT >(SFX_REC_PRE(nHeader)); - if ( SFX_REC_PRETAG_EXT == nPreTag ) - { - // die n"achsten 4 Bytes als extended-Header lesen - *pStream >> nHeader; - - // Stream-Position restaurieren - pStream->SeekRel(-8); - - // liegt eine g"ultige Record-Kennung vor? - USHORT nType = sal::static_int_cast< USHORT >(SFX_REC_TYP(nHeader)); - if ( nType >= SFX_REC_TYPE_FIRST && nType <= SFX_REC_TYPE_LAST ) - // entsprechenden extended-Record-Typ zur"uckliefern - return nType; - - // sonst ist der Record-Typ unbekannt - return SFX_REC_TYPE_NONE; - } - - // Stream-Position restaurieren - pStream->SeekRel(-4); - - // liegt eine End-Of-Record-Kennung vor? - if ( SFX_REC_PRETAG_EOR == nPreTag ) - return nPreTag; - - // liegt ein Drawin-Engine-Record vor? - if ( nHeader == UINT32(*"DRMD") || nHeader == UINT32(*"DRVW") ) - return SFX_REC_TYPE_DRAWENG; - - // alle anderen sind grunds"atzlich g"ultige Mini-Records - return SFX_REC_TYPE_MINI; -} - -//------------------------------------------------------------------------- - -FASTBOOL SfxMiniRecordReader::SetHeader_Impl( UINT32 nHeader ) - -/* [Beschreibung] - - Interne Methode zum nachtr"aglichen Verarbeiten eines extern gelesenen - Headers. Falls der Header eine End-Of-Records-Kennung darstellt, - wird am Stream ein Errorcode gesetzt und FALSE zur"uckgeliefert. Im - Fehlerfall wird der Stream jedoch nicht auf den Record-Anfang zur"uck- - gesetzt. -*/ - -{ - FASTBOOL bRet = TRUE; - - // Record-Ende und Pre-Tag aus dem Header ermitteln - _nEofRec = _pStream->Tell() + SFX_REC_OFS(nHeader); - _nPreTag = sal::static_int_cast< BYTE >(SFX_REC_PRE(nHeader)); - - // wenn End-Of-Record-Kennung, dann Fehler - if ( _nPreTag == SFX_REC_PRETAG_EOR ) - { - _pStream->SetError( ERRCODE_IO_WRONGFORMAT ); - bRet = FALSE; - } - return bRet; -} - -//------------------------------------------------------------------------- - -SfxMiniRecordReader::SfxMiniRecordReader -( - SvStream* pStream /* <SvStream>, an dessen aktueller - Position sich ein <SfxMiniRecord> - befindet. - */ -) - -/* [Beschreibung] - - Dieser Ctor liest den Header eines <SfxMiniRecord> ab der aktuellen - Position von 'pStream'. Da grunds"atzlich fast 4-Byte Kombination ein - g"ultiger SfxMiniRecord-Header ist, bleiben die einzig m"oglichen - Fehler der EOF-Status des Streams, und ein SFX_REC_PRETAG_EOR - als Pre-Tag. Ein entsprechender Error-Code (ERRCODE_IO_EOF bzw. - ERRCODE_IO_WRONGFORMAT) ist dann am Stream gesetzt, dessen Position - dann au\serdem unver"andert ist. -*/ - -: _pStream( pStream ), - _bSkipped( FALSE ) -{ - // Header einlesen - UINT32 nStartPos = pStream->Tell(); // um im Fehlerfall zur"uck zu-seeken - DBG( DbgOutf( "SfxFileRec: reading record at %ul", nStartPos ) ); - UINT32 nHeader; - *pStream >> nHeader; - - // Headerdaten extrahieren - SetHeader_Impl( nHeader ); - - // Fehlerbehandlung - if ( pStream->IsEof() ) - _nPreTag = SFX_REC_PRETAG_EOR; - else if ( _nPreTag == SFX_REC_PRETAG_EOR ) - pStream->SetError( ERRCODE_IO_WRONGFORMAT ); - if ( !IsValid() ) - pStream->Seek( nStartPos ); -} - -//------------------------------------------------------------------------- - -SfxMiniRecordReader::SfxMiniRecordReader -( - SvStream* pStream, /* <SvStream>, an dessen aktueller - Position sich ein <SfxMiniRecord> - befindet. - */ - BYTE nTag // Pre-Tag des gew"unschten Records -) - -/* [Beschreibung] - - Dieser Ctor interpretiert 'pStream' ab der aktuellen Position als - eine l"uckenlose Folge von, von dieser Klassen-Gruppe interpretierbaren, - Records. Der in dieser Folge erste als <SfxMiniRecord> interpretierbare - (also ggf. auch ein extended-Record) mit dem PreTag 'nTag' wird ge"offnet - und durch diese Instanz repr"asentiert. - - Wird das Ende des Streams oder die Kennung SFX_REC_PRETAG_EOR - erreicht, bevor ein Record mit dem ge"unschten Pre-Tag gefunden wird, - ist die erzeugte Instanz ung"ultig ('IsValid() == FALSE'). Ein ent- - sprechender Error-Code (ERRCODE_IO_EOF bzw. ERRCODE_IO_WRONGFORMAT) - ist dann am Stream gesetzt, dessen Position ist dann au\serdem unver- - "andert. - - Bei 'nTag==SFX_FILEREC_PRETAG_EOR' wird nicht versucht, einen Record - zu lesen, es wird sofort 'IsValid()' auf FALSE gesetzt und kein Error-Code - am Stream gesetzt. Dies ist dauzu gedacht, ohne 'new' und 'delete' - abw"rtskompatibel SfxMiniRecords einbauen zu k"onnen. Siehe dazu - <SfxItemSet::Load()>. - - - [Anwendungsvorschlag] - - Wird dieser Ctor in einer bereits ausgelieferten Programmversion - verwendet, k"onnen in das File-Format jeweils davor kompatibel neue - Records mit einer anderen Kennung eingef"ugt werden. Diese werden - schlie\slich automatisch "uberlesen. Erkauft wird diese M"oglichkeit - allerdings mit etwas schlechterem Laufzeitverhalten im Vergleich mit - direktem 'drauf-los-lesen', der sich jedoch auf einen Vergleich zweier - Bytes reduziert, falls der gesuchte Record der erste in der Folge ist. -*/ - -: _pStream( pStream ), - _bSkipped( nTag == SFX_REC_PRETAG_EOR ) -{ - // ggf. ignorieren (s.o.) - if ( _bSkipped ) - { - _nPreTag = nTag; - return; - } - - // StartPos merken, um im Fehlerfall zur"uck-seeken zu k"onnen - UINT32 nStartPos = pStream->Tell(); - - // passenden Record suchen - while(TRUE) - { - // Header lesen - DBG( DbgOutf( "SfxFileRec: searching record at %ul", pStream->Tell() ) ); - UINT32 nHeader; - *pStream >> nHeader; - - // Headerdaten von Basisklasse extrahieren lassen - SetHeader_Impl( nHeader ); - - // ggf. Fehler behandeln - if ( pStream->IsEof() ) - _nPreTag = SFX_REC_PRETAG_EOR; - else if ( _nPreTag == SFX_REC_PRETAG_EOR ) - pStream->SetError( ERRCODE_IO_WRONGFORMAT ); - else - { - // wenn gefunden, dann Schleife abbrechen - if ( _nPreTag == nTag ) - break; - - // sonst skippen und weitersuchen - pStream->Seek( _nEofRec ); - continue; - } - - // Fehler => zur"uck-seeken - pStream->Seek( nStartPos ); - break; - } -} - -//========================================================================= - -SfxSingleRecordWriter::SfxSingleRecordWriter -( - BYTE nRecordType, // f"ur Subklassen - SvStream* pStream, // Stream, in dem der Record angelegt wird - UINT16 nContentTag, // Inhalts-Art-Kennung - BYTE nContentVer // Inhalts-Versions-Kennung -) - -/* [Beschreibung] - - Interner Ctor f"ur Subklassen. -*/ - -: SfxMiniRecordWriter( pStream, SFX_REC_PRETAG_EXT ) -{ - // Erweiterten Header hiner den des SfxMiniRec schreiben - *pStream << SFX_REC_HEADER(nRecordType, nContentTag, nContentVer); -} - -//------------------------------------------------------------------------- - -SfxSingleRecordWriter::SfxSingleRecordWriter -( - SvStream* pStream, // Stream, in dem der Record angelegt wird - UINT16 nContentTag, // Inhalts-Art-Kennung - BYTE nContentVer // Inhalts-Versions-Kennung -) - -/* [Beschreibung] - - Legt in 'pStream' einen 'SfxSingleRecord' an, dessen Content-Gr"o\se - nicht bekannt ist, sondern nach dam Streamen des Contents errechnet - werden soll. -*/ - -: SfxMiniRecordWriter( pStream, SFX_REC_PRETAG_EXT ) -{ - // Erweiterten Header hiner den des SfxMiniRec schreiben - *pStream << SFX_REC_HEADER( SFX_REC_TYPE_SINGLE, nContentTag, nContentVer); -} - -//------------------------------------------------------------------------- - -SfxSingleRecordWriter::SfxSingleRecordWriter -( - SvStream* pStream, // Stream, in dem der Record angelegt wird - UINT16 nContentTag, // Inhalts-Art-Kennung - BYTE nContentVer, // Inhalts-Versions-Kennung - UINT32 nContentSize // Gr"o\se des Inhalts in Bytes -) - -/* [Beschreibung] - - Legt in 'pStream' einen 'SfxSingleRecord' an, dessen Content-Gr"o\se - von vornherein bekannt ist. -*/ - -: SfxMiniRecordWriter( pStream, SFX_REC_PRETAG_EXT, - nContentSize + SFX_REC_HEADERSIZE_SINGLE ) -{ - // Erweiterten Header hinter den des SfxMiniRec schreiben - *pStream << SFX_REC_HEADER( SFX_REC_TYPE_SINGLE, nContentTag, nContentVer); -} - -//========================================================================= - -inline FASTBOOL SfxSingleRecordReader::ReadHeader_Impl( USHORT nTypes ) - -/* [Beschreibung] - - Interne Methode zum Einlesen eines SfxMultiRecord-Headers, nachdem - die Basisklasse bereits initialisiert und deren Header gelesen ist. - Ggf. ist ein Error-Code am Stream gesetzt, im Fehlerfall wird jedoch - nicht zur"uckge-seekt. -*/ - -{ - FASTBOOL bRet; - - // Basisklassen-Header einlesen - UINT32 nHeader=0; - *_pStream >> nHeader; - if ( !SetHeader_Impl( nHeader ) ) - bRet = FALSE; - else - { - // eigenen Header einlesen - *_pStream >> nHeader; - _nRecordVer = sal::static_int_cast< BYTE >(SFX_REC_VER(nHeader)); - _nRecordTag = sal::static_int_cast< UINT16 >(SFX_REC_TAG(nHeader)); - - // falscher Record-Typ? - _nRecordType = sal::static_int_cast< BYTE >(SFX_REC_TYP(nHeader)); - bRet = 0 != ( nTypes & _nRecordType); - } - return bRet; -} - -//------------------------------------------------------------------------- - -SfxSingleRecordReader::SfxSingleRecordReader( SvStream *pStream ) -: SfxMiniRecordReader() -{ - // Startposition merken, um im Fehlerfall zur"uck-seeken zu k"onnen - #ifdef DBG_UTIL - UINT32 nStartPos = pStream->Tell(); - DBG( DbgOutf( "SfxFileRec: reading record at %ul", nStartPos ) ); - #endif - - // Basisklasse initialisieren (nicht via Ctor, da der nur MiniRecs akzept.) - Construct_Impl( pStream ); - - // nur Header mit korrektem Record-Type akzeptieren - if ( !ReadHeader_Impl( SFX_REC_TYPE_SINGLE ) ) - { - // Error-Code setzen und zur"uck-seeken - pStream->SeekRel( - SFX_REC_HEADERSIZE_SINGLE ); - pStream->SetError( ERRCODE_IO_WRONGFORMAT ); - } -} - -//------------------------------------------------------------------------- - -SfxSingleRecordReader::SfxSingleRecordReader( SvStream *pStream, USHORT nTag ) -{ - // StartPos merken, um im Fehlerfall zur"uck-seeken zu k"onnen - UINT32 nStartPos = pStream->Tell(); - - // richtigen Record suchen, ggf. Error-Code setzen und zur"uck-seeken - Construct_Impl( pStream ); - if ( !FindHeader_Impl( SFX_REC_TYPE_SINGLE, nTag ) ) - { - // Error-Code setzen und zur"uck-seeken - pStream->Seek( nStartPos ); - pStream->SetError( ERRCODE_IO_WRONGFORMAT ); - } -} - -//------------------------------------------------------------------------- - -FASTBOOL SfxSingleRecordReader::FindHeader_Impl -( - UINT16 nTypes, // arithm. Veroderung erlaubter Record-Typen - UINT16 nTag // zu findende Record-Art-Kennung -) - -/* [Beschreibung] - - Interne Methode zum lesen des Headers des ersten Record, der einem - der Typen in 'nTypes' entspricht und mit der Art-Kennung 'nTag' - gekennzeichnet ist. - - Kann ein solcher Record nicht gefunden werden, wird am Stream ein - Errorcode gesetzt, zur"uck-geseekt und FALSE zur"uckgeliefert. -*/ - -{ - // StartPos merken, um im Fehlerfall zur"uck-seeken zu k"onnen - UINT32 nStartPos = _pStream->Tell(); - - // richtigen Record suchen - while ( !_pStream->IsEof() ) - { - // Header lesen - UINT32 nHeader; - DBG( DbgOutf( "SfxFileRec: searching record at %ul", _pStream->Tell() ) ); - *_pStream >> nHeader; - if ( !SetHeader_Impl( nHeader ) ) - // EOR => Such-Schleife abbreichen - break; - - // Extended Record gefunden? - if ( _nPreTag == SFX_REC_PRETAG_EXT ) - { - // Extended Header lesen - *_pStream >> nHeader; - _nRecordTag = sal::static_int_cast< UINT16 >(SFX_REC_TAG(nHeader)); - - // richtigen Record gefunden? - if ( _nRecordTag == nTag ) - { - // gefundener Record-Typ passend? - _nRecordType = sal::static_int_cast< BYTE >( - SFX_REC_TYP(nHeader)); - if ( nTypes & _nRecordType ) - // ==> gefunden - return TRUE; - - // error => Such-Schleife abbrechen - break; - } - } - - // sonst skippen - if ( !_pStream->IsEof() ) - _pStream->Seek( _nEofRec ); - } - - // Fehler setzen und zur"uck-seeken - _pStream->SetError( ERRCODE_IO_WRONGFORMAT ); - _pStream->Seek( nStartPos ); - return FALSE; -} - -//========================================================================= - -SfxMultiFixRecordWriter::SfxMultiFixRecordWriter -( - BYTE nRecordType, // Subklassen Record-Kennung - SvStream* pStream, // Stream, in dem der Record angelegt wird - UINT16 nContentTag, // Content-Art-Kennung - BYTE nContentVer, // Content-Versions-Kennung - UINT32 // Gr"o\se jedes einzelnen Contents in Bytes -) - -/* [Beschreibung] - - Interne Methode f"ur Subklassen. -*/ - -: SfxSingleRecordWriter( nRecordType, pStream, nContentTag, nContentVer ), - _nContentCount( 0 ) -{ - // Platz f"ur eigenen Header - pStream->SeekRel( + SFX_REC_HEADERSIZE_MULTI ); -} - -//------------------------------------------------------------------------ - -SfxMultiFixRecordWriter::SfxMultiFixRecordWriter -( - SvStream* pStream, // Stream, in dem der Record angelegt wird - UINT16 nContentTag, // Content-Art-Kennung - BYTE nContentVer, // Content-Versions-Kennung - UINT32 // Gr"o\se jedes einzelnen Contents in Bytes -) - -/* [Beschreibung] - - Legt in 'pStream' einen 'SfxMultiFixRecord' an, dessen Content-Gr"o\se - konstant und von vornherein bekannt ist. -*/ - -: SfxSingleRecordWriter( SFX_REC_TYPE_FIXSIZE, - pStream, nContentTag, nContentVer ), - _nContentCount( 0 ) -{ - // Platz f"ur eigenen Header - pStream->SeekRel( + SFX_REC_HEADERSIZE_MULTI ); -} - -//------------------------------------------------------------------------ - -UINT32 SfxMultiFixRecordWriter::Close( FASTBOOL bSeekToEndOfRec ) - -// siehe <SfxMiniRecordWriter> - -{ - // Header noch nicht geschrieben? - if ( !_bHeaderOk ) - { - // Position hinter Record merken, um sie restaurieren zu k"onnen - UINT32 nEndPos = SfxSingleRecordWriter::Close( FALSE ); - - // gegen"uber SfxSingleRecord erweiterten Header schreiben - *_pStream << _nContentCount; - *_pStream << _nContentSize; - - // je nachdem ans Ende des Records seeken oder hinter Header bleiben - if ( bSeekToEndOfRec ) - _pStream->Seek(nEndPos); - return nEndPos; - } - - // Record war bereits geschlossen - return 0; -} - -//========================================================================= - -SfxMultiVarRecordWriter::SfxMultiVarRecordWriter -( - BYTE nRecordType, // Record-Kennung der Subklasse - SvStream* pStream, // Stream, in dem der Record angelegt wird - UINT16 nRecordTag, // Gesamt-Art-Kennung - BYTE nRecordVer // Gesamt-Versions-Kennung -) - -/* [Beschreibung] - - Interner Ctor f"ur Subklassen. -*/ - -: SfxMultiFixRecordWriter( nRecordType, pStream, nRecordTag, nRecordVer, 0 ), - _nContentVer( 0 ) -{ -} - -//------------------------------------------------------------------------- - -SfxMultiVarRecordWriter::SfxMultiVarRecordWriter -( - SvStream* pStream, // Stream, in dem der Record angelegt wird - UINT16 nRecordTag, // Gesamt-Art-Kennung - BYTE nRecordVer // Gesamt-Versions-Kennung -) - -/* [Beschreibung] - - Legt in 'pStream' einen 'SfxMultiVarRecord' an, dessen Content-Gr"o\sen - weder bekannt sind noch identisch sein m"ussen, sondern jeweils nach dem - Streamen jedes einzelnen Contents errechnet werden sollen. - - - [Anmerkung] - - Diese Methode ist nicht inline, da f"ur die Initialisierung eines - <SvULongs>-Members zu viel Code generiert werden w"urde. -*/ - -: SfxMultiFixRecordWriter( SFX_REC_TYPE_VARSIZE, - pStream, nRecordTag, nRecordVer, 0 ), - _nContentVer( 0 ) -{ -} - -//------------------------------------------------------------------------- - -SfxMultiVarRecordWriter::~SfxMultiVarRecordWriter() - -/* [Beschreibung] - - Der Dtor der Klasse <SfxMultiVarRecordWriter> schlie\st den Record - automatisch, falls <SfxMultiVarRecordWriter::Close()> nicht bereits - explizit gerufen wurde. -*/ - -{ - // wurde der Header noch nicht geschrieben oder mu\s er gepr"uft werden - if ( !_bHeaderOk ) - Close(); -} - -//------------------------------------------------------------------------- - -void SfxMultiVarRecordWriter::FlushContent_Impl() - -/* [Beschreibung] - - Interne Methode zum Abschlie\sen eines einzelnen Contents. -*/ - -{ - // Versions-Kennung und Positions-Offset des aktuellen Contents merken; - // das Positions-Offset ist relativ zur Startposition des ersten Contents - _aContentOfs.Insert( - SFX_REC_CONTENT_HEADER(_nContentVer,_nStartPos,_nContentStartPos), - _nContentCount-1 ); -} - -//------------------------------------------------------------------------- - -void SfxMultiVarRecordWriter::NewContent() - -// siehe <SfxMultiFixRecordWriter> - -{ - // schon ein Content geschrieben? - if ( _nContentCount ) - FlushContent_Impl(); - - // neuen Content beginnen - _nContentStartPos = _pStream->Tell(); - ++_nContentCount; -} - -//------------------------------------------------------------------------- - -UINT32 SfxMultiVarRecordWriter::Close( FASTBOOL bSeekToEndOfRec ) - -// siehe <SfxMiniRecordWriter> - -{ - // Header noch nicht geschrieben? - if ( !_bHeaderOk ) - { - // ggf. letzten Content abschlie\sen - if ( _nContentCount ) - FlushContent_Impl(); - - // Content-Offset-Tabelle schreiben - UINT32 nContentOfsPos = _pStream->Tell(); - //! darf man das so einr"ucken? - #if defined(OSL_LITENDIAN) - _pStream->Write( _aContentOfs.GetData(), - sizeof(UINT32)*_nContentCount ); - #else - for ( USHORT n = 0; n < _nContentCount; ++n ) - *_pStream << UINT32(_aContentOfs[n]); - #endif - - // SfxMultiFixRecordWriter::Close() "uberspringen! - UINT32 nEndPos = SfxSingleRecordWriter::Close( FALSE ); - - // eigenen Header schreiben - *_pStream << _nContentCount; - if ( SFX_REC_TYPE_VARSIZE_RELOC == _nPreTag || - SFX_REC_TYPE_MIXTAGS_RELOC == _nPreTag ) - *_pStream << static_cast<UINT32>(nContentOfsPos - ( _pStream->Tell() + sizeof(UINT32) )); - else - *_pStream << nContentOfsPos; - - // ans Ende des Records seeken bzw. am Ende des Headers bleiben - if ( bSeekToEndOfRec ) - _pStream->Seek(nEndPos); - return nEndPos; - } - - // Record war bereits vorher geschlossen - return 0; -} - -//========================================================================= - -void SfxMultiMixRecordWriter::NewContent -( - UINT16 nContentTag, // Kennung f"ur die Art des Contents - BYTE nContentVer // Kennung f"ur die Version des Contents -) - -/* [Beschreibung] - - Mit dieser Methode wird in den Record ein neuer Content eingef"ugt - und dessen Content-Tag sowie dessen Content-Version angegeben. Jeder, - auch der 1. Record mu\s durch Aufruf dieser Methode eingeleitet werden. -*/ - -{ - // ggf. vorherigen Record abschlie\sen - if ( _nContentCount ) - FlushContent_Impl(); - - // Tag vor den Content schreiben, Version und Startposition merken - _nContentStartPos = _pStream->Tell(); - ++_nContentCount; - *_pStream << nContentTag; - _nContentVer = nContentVer; -} - -//========================================================================= - -FASTBOOL SfxMultiRecordReader::ReadHeader_Impl() - -/* [Beschreibung] - - Interne Methode zum Einlesen eines SfxMultiRecord-Headers, nachdem - die Basisklasse bereits initialisiert und deren Header gelesen ist. - Ggf. ist ein Error-Code am Stream gesetzt, im Fehlerfall wird jedoch - nicht zur"uckge-seekt. -*/ - -{ - // eigenen Header lesen - *_pStream >> _nContentCount; - *_pStream >> _nContentSize; // Fix: jedes einzelnen, Var|Mix: Tabellen-Pos. - - // mu\s noch eine Tabelle mit Content-Offsets geladen werden? - if ( _nRecordType != SFX_REC_TYPE_FIXSIZE ) - { - // Tabelle aus dem Stream einlesen - UINT32 nContentPos = _pStream->Tell(); - if ( _nRecordType == SFX_REC_TYPE_VARSIZE_RELOC || - _nRecordType == SFX_REC_TYPE_MIXTAGS_RELOC ) - _pStream->SeekRel( + _nContentSize ); - else - _pStream->Seek( _nContentSize ); - _pContentOfs = new UINT32[_nContentCount]; - //! darf man jetzt so einr"ucken - #if defined(OSL_LITENDIAN) - _pStream->Read( _pContentOfs, sizeof(UINT32)*_nContentCount ); - #else - for ( USHORT n = 0; n < _nContentCount; ++n ) - *_pStream >> _pContentOfs[n]; - #endif - _pStream->Seek( nContentPos ); - } - - // Header konnte gelesen werden, wenn am Stream kein Error gesetzt ist - return !_pStream->GetError(); -} - -//------------------------------------------------------------------------- - -SfxMultiRecordReader::SfxMultiRecordReader( SvStream *pStream ) -: _pContentOfs( NULL ), _nContentNo(0) -{ - // Position im Stream merken, um im Fehlerfall zur"uck-seeken zu k"onnen - _nStartPos = pStream->Tell(); - - // Basisklasse konstruieren (normaler Ctor w"urde nur SingleRecs lesen) - SfxSingleRecordReader::Construct_Impl( pStream ); - - // Header der Basisklasse lesen - if ( !SfxSingleRecordReader::ReadHeader_Impl( SFX_REC_TYPE_FIXSIZE | - SFX_REC_TYPE_VARSIZE | SFX_REC_TYPE_VARSIZE_RELOC | - SFX_REC_TYPE_MIXTAGS | SFX_REC_TYPE_MIXTAGS_RELOC ) || - !ReadHeader_Impl() ) - // als ung"ultig markieren und zur"uck-seeken - SetInvalid_Impl( _nStartPos ); -} - -//------------------------------------------------------------------------- - -SfxMultiRecordReader::SfxMultiRecordReader( SvStream *pStream, UINT16 nTag ) -: _nContentNo(0) -{ - // Position im Stream merken, um im Fehlerfall zur"uck-seeken zu k"onnen - _nStartPos = pStream->Tell(); - - // passenden Record suchen und Basisklasse initialisieren - SfxSingleRecordReader::Construct_Impl( pStream ); - if ( SfxSingleRecordReader::FindHeader_Impl( SFX_REC_TYPE_FIXSIZE | - SFX_REC_TYPE_VARSIZE | SFX_REC_TYPE_VARSIZE_RELOC | - SFX_REC_TYPE_MIXTAGS | SFX_REC_TYPE_MIXTAGS_RELOC, - nTag ) ) - { - // eigenen Header dazu-lesen - if ( !ReadHeader_Impl() ) - // nicht lesbar => als ung"ultig markieren und zur"uck-seeken - SetInvalid_Impl( _nStartPos); - } -} - -//------------------------------------------------------------------------- - -SfxMultiRecordReader::~SfxMultiRecordReader() -{ - delete[] _pContentOfs; -} - -//------------------------------------------------------------------------- - -FASTBOOL SfxMultiRecordReader::GetContent() - -/* [Beschreibung] - - Positioniert den Stream an den Anfang des n"chsten bzw. beim 1. Aufruf - auf den Anfang des ersten Contents im Record und liest ggf. dessen - Header ein. - - Liegt laut Record-Header kein Content mehr vor, wird FALSE zur"uck- - gegeben. Trotz einem TRUE-Returnwert kann am Stream ein Fehlercode - gesetzt sein, z.B. falls er unvorhergesehenerweise (kaputtes File) - zuende ist. -*/ - -{ - // noch ein Content vorhanden? - if ( _nContentNo < _nContentCount ) - { - // den Stream an den Anfang des Contents positionieren - UINT32 nOffset = _nRecordType == SFX_REC_TYPE_FIXSIZE - ? _nContentNo * _nContentSize - : SFX_REC_CONTENT_OFS(_pContentOfs[_nContentNo]); - UINT32 nNewPos = _nStartPos + nOffset; - DBG_ASSERT( nNewPos >= _pStream->Tell(), "SfxMultiRecordReader::GetContent() - New position before current, to much data red!" ); - - // #99366#: correct stream pos in every case; - // the if clause was added by MT a long time ago, - // maybe to 'repair' other corrupt documents; but this - // gives errors when writing with 5.1 and reading with current - // versions, so we decided to remove the if clause (KA-05/17/2002) - // if ( nNewPos > _pStream->Tell() ) - _pStream->Seek( nNewPos ); - - // ggf. Content-Header lesen - if ( _nRecordType == SFX_REC_TYPE_MIXTAGS || - _nRecordType == SFX_REC_TYPE_MIXTAGS_RELOC ) - { - _nContentVer = sal::static_int_cast< BYTE >( - SFX_REC_CONTENT_VER(_pContentOfs[_nContentNo])); - *_pStream >> _nContentTag; - } - - // ContentNo weiterz"ahlen - ++_nContentNo; - return TRUE; - } - - return FALSE; -} - - |