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