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