1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 // MARKER(update_precomp.py): autogen include statement, do not remove 29 #include "precompiled_tools.hxx" 30 31 #include <tools/debug.hxx> 32 #include <tools/pstm.hxx> 33 34 #define STOR_NO_OPTIMIZE 35 36 /***********************************************************************/ 37 /************************************************************************ 38 |* SvClassManager::Register() 39 *************************************************************************/ 40 void SvClassManager::Register( sal_uInt16 nClassId, SvCreateInstancePersist pFunc ) 41 { 42 #ifdef DBG_UTIL 43 SvCreateInstancePersist p; 44 p = Get( nClassId ); 45 DBG_ASSERT( !p || p == pFunc, "register class with same id" ); 46 #endif 47 aAssocTable.insert(Map::value_type(nClassId, pFunc)); 48 } 49 50 /************************************************************************ 51 |* SvClassManager::Get() 52 *************************************************************************/ 53 SvCreateInstancePersist SvClassManager::Get( sal_uInt16 nClassId ) 54 { 55 Map::const_iterator i(aAssocTable.find(nClassId)); 56 return i == aAssocTable.end() ? 0 : i->second; 57 } 58 59 /****************** SvRttiBase *******************************************/ 60 TYPEINIT0( SvRttiBase ); 61 62 /****************** SvPersistBaseMemberList ******************************/ 63 64 SvPersistBaseMemberList::SvPersistBaseMemberList(){} 65 SvPersistBaseMemberList::SvPersistBaseMemberList( 66 sal_uInt16 nInitSz, sal_uInt16 nResize ) 67 : SuperSvPersistBaseMemberList( nInitSz, nResize ){} 68 69 #define PERSIST_LIST_VER (sal_uInt8)0 70 #define PERSIST_LIST_DBGUTIL (sal_uInt8)0x80 71 72 /************************************************************************ 73 |* SvPersistBaseMemberList::WriteOnlyStreamedObjects() 74 *************************************************************************/ 75 void SvPersistBaseMemberList::WriteObjects( SvPersistStream & rStm, 76 sal_Bool bOnlyStreamed ) const 77 { 78 #ifdef STOR_NO_OPTIMIZE 79 rStm << (sal_uInt8)(PERSIST_LIST_VER | PERSIST_LIST_DBGUTIL); 80 sal_uInt32 nObjPos = rStm.WriteDummyLen(); 81 #else 82 sal_uInt8 bTmp = PERSIST_LIST_VER; 83 rStm << bTmp; 84 #endif 85 sal_uInt32 nCountMember = Count(); 86 sal_uIntPtr nCountPos = rStm.Tell(); 87 sal_uInt32 nWriteCount = 0; 88 rStm << nCountMember; 89 //bloss die Liste nicht veraendern, 90 //wegen Seiteneffekten beim Save 91 for( sal_uIntPtr n = 0; n < nCountMember; n++ ) 92 { 93 SvPersistBase * pObj = GetObject( n ); 94 if( !bOnlyStreamed || rStm.IsStreamed( pObj ) ) 95 { // Objekt soll geschrieben werden 96 rStm << GetObject( n ); 97 nWriteCount++; 98 } 99 } 100 if( nWriteCount != nCountMember ) 101 { 102 // nicht alle Objekte geschrieben, Count anpassen 103 sal_uIntPtr nPos = rStm.Tell(); 104 rStm.Seek( nCountPos ); 105 rStm << nWriteCount; 106 rStm.Seek( nPos ); 107 } 108 #ifdef STOR_NO_OPTIMIZE 109 rStm.WriteLen( nObjPos ); 110 #endif 111 } 112 113 /************************************************************************ 114 |* operator << () 115 *************************************************************************/ 116 SvPersistStream& operator << ( SvPersistStream & rStm, 117 const SvPersistBaseMemberList & rLst ) 118 { 119 rLst.WriteObjects( rStm ); 120 return rStm; 121 } 122 123 /************************************************************************ 124 |* operator >> () 125 *************************************************************************/ 126 SvPersistStream& operator >> ( SvPersistStream & rStm, 127 SvPersistBaseMemberList & rLst ) 128 { 129 sal_uInt8 nVer; 130 rStm >> nVer; 131 132 if( (nVer & ~PERSIST_LIST_DBGUTIL) != PERSIST_LIST_VER ) 133 { 134 rStm.SetError( SVSTREAM_GENERALERROR ); 135 DBG_ERROR( "persist list, false version" ); 136 } 137 138 sal_uInt32 nObjLen(0), nObjPos(0); 139 if( nVer & PERSIST_LIST_DBGUTIL ) 140 nObjLen = rStm.ReadLen( &nObjPos ); 141 142 sal_uInt32 nCount; 143 rStm >> nCount; 144 for( sal_uIntPtr n = 0; n < nCount && rStm.GetError() == SVSTREAM_OK; n++ ) 145 { 146 SvPersistBase * pObj; 147 rStm >> pObj; 148 if( pObj ) 149 rLst.Append( pObj ); 150 } 151 #ifdef DBG_UTIL 152 if( nObjLen + nObjPos != rStm.Tell() ) 153 { 154 ByteString aStr( "false list len: read = " ); 155 aStr += ByteString::CreateFromInt32( (long)(rStm.Tell() - nObjPos) ); 156 aStr += ", should = "; 157 aStr += ByteString::CreateFromInt64(nObjLen); 158 DBG_ERROR( aStr.GetBuffer() ); 159 } 160 #endif 161 return rStm; 162 } 163 164 //========================================================================= 165 SvPersistStream::SvPersistStream 166 ( 167 SvClassManager & rMgr, /* Alle Factorys, deren Objekt geladen und 168 gespeichert werdn k"onnen */ 169 SvStream * pStream, /* Dieser Stream wird als Medium genommen, auf 170 dem der PersistStream arbeitet */ 171 sal_uInt32 nStartIdxP /* Ab diesem Index werden die Id's f"ur 172 die Objekte vergeben, er muss gr"osser 173 als Null sein. */ 174 ) 175 : rClassMgr( rMgr ) 176 , pStm( pStream ) 177 , aPUIdx( nStartIdxP ) 178 , nStartIdx( nStartIdxP ) 179 , pRefStm( NULL ) 180 , nFlags( 0 ) 181 /* [Beschreibung] 182 183 Der Konstruktor der Klasse SvPersistStream. Die Objekte rMgr und 184 pStream d"urfen nicht ver"andert werden, solange sie in einem 185 SvPersistStream eingesetzt sind. Eine Aussnahme gibt es f"ur 186 pStream (siehe <SvPersistStream::SetStream>). 187 */ 188 { 189 DBG_ASSERT( nStartIdx != 0, "zero index not allowed" ); 190 bIsWritable = sal_True; 191 if( pStm ) 192 { 193 SetVersion( pStm->GetVersion() ); 194 SetError( pStm->GetError() ); 195 SyncSvStream( pStm->Tell() ); 196 } 197 } 198 199 //========================================================================= 200 SvPersistStream::SvPersistStream 201 ( 202 SvClassManager & rMgr, /* Alle Factorys, deren Objekt geladen und 203 gespeichert werdn k"onnen */ 204 SvStream * pStream, /* Dieser Stream wird als Medium genommen, auf 205 dem der PersistStream arbeitet */ 206 const SvPersistStream & rPersStm 207 /* Wenn PersistStream's verschachtelt werden, 208 dann ist dies der Parent-Stream. */ 209 ) 210 : rClassMgr( rMgr ) 211 , pStm( pStream ) 212 // Bereiche nicht ueberschneiden, deshalb nur groessere Indexe 213 , aPUIdx( rPersStm.GetCurMaxIndex() +1 ) 214 , nStartIdx( rPersStm.GetCurMaxIndex() +1 ) 215 , pRefStm( &rPersStm ) 216 , nFlags( 0 ) 217 /* [Beschreibung] 218 219 Der Konstruktor der Klasse SvPersistStream. Die Objekte rMgr und 220 pStream d"urfen nicht ver"andert werden, solange sie in einem 221 SvPersistStream eingesetzt sind. Eine Aussnahme gibt es f"ur 222 pStream (siehe <SvPersistStream::SetStream>). 223 Durch diesen Konstruktor wird eine Hierarchiebildung unterst"utzt. 224 Alle Objekte aus einer Hierarchie m"ussen erst geladen werden, 225 wenn das erste aus dieser Hierarchie benutzt werden soll. 226 */ 227 { 228 bIsWritable = sal_True; 229 if( pStm ) 230 { 231 SetVersion( pStm->GetVersion() ); 232 SetError( pStm->GetError() ); 233 SyncSvStream( pStm->Tell() ); 234 } 235 } 236 237 //========================================================================= 238 SvPersistStream::~SvPersistStream() 239 /* [Beschreibung] 240 241 Der Detruktor ruft die Methode <SvPersistStream::SetStream> 242 mit NULL. 243 */ 244 { 245 SetStream( NULL ); 246 } 247 248 //========================================================================= 249 void SvPersistStream::SetStream 250 ( 251 SvStream * pStream /* auf diesem Stream arbeitet der PersistStream */ 252 253 ) 254 /* [Beschreibung] 255 256 Es wird ein Medium (pStream) eingesetzt, auf dem PersistStream arbeitet. 257 Dieses darf nicht von aussen modifiziert werden, solange es 258 eingesetzt ist. Es sei denn, w"ahrend auf dem Medium gearbeitet 259 wird, wird keine Methode von SvPersistStream gerufen, bevor 260 nicht <SvPersistStream::SetStream> mit demselben Medium gerufen 261 wurde. 262 */ 263 { 264 if( pStm != pStream ) 265 { 266 if( pStm ) 267 { 268 SyncSysStream(); 269 pStm->SetError( GetError() ); 270 } 271 pStm = pStream; 272 } 273 if( pStm ) 274 { 275 SetVersion( pStm->GetVersion() ); 276 SetError( pStm->GetError() ); 277 SyncSvStream( pStm->Tell() ); 278 } 279 } 280 281 //========================================================================= 282 sal_uInt16 SvPersistStream::IsA() const 283 /* [Beschreibung] 284 285 Gibt den Identifier dieses Streamklasse zur"uck. 286 287 [R"uckgabewert] 288 289 sal_uInt16 ID_PERSISTSTREAM wird zur"uckgegeben. 290 291 292 [Querverweise] 293 294 <SvStream::IsA> 295 */ 296 { 297 return ID_PERSISTSTREAM; 298 } 299 300 301 /************************************************************************* 302 |* SvPersistStream::ResetError() 303 *************************************************************************/ 304 void SvPersistStream::ResetError() 305 { 306 SvStream::ResetError(); 307 DBG_ASSERT( pStm, "stream not set" ); 308 pStm->ResetError(); 309 } 310 311 /************************************************************************* 312 |* SvPersistStream::GetData() 313 *************************************************************************/ 314 sal_uIntPtr SvPersistStream::GetData( void* pData, sal_uIntPtr nSize ) 315 { 316 DBG_ASSERT( pStm, "stream not set" ); 317 sal_uIntPtr nRet = pStm->Read( pData, nSize ); 318 SetError( pStm->GetError() ); 319 return nRet; 320 } 321 322 /************************************************************************* 323 |* SvPersistStream::PutData() 324 *************************************************************************/ 325 sal_uIntPtr SvPersistStream::PutData( const void* pData, sal_uIntPtr nSize ) 326 { 327 DBG_ASSERT( pStm, "stream not set" ); 328 sal_uIntPtr nRet = pStm->Write( pData, nSize ); 329 SetError( pStm->GetError() ); 330 return nRet; 331 } 332 333 /************************************************************************* 334 |* SvPersistStream::Seek() 335 *************************************************************************/ 336 sal_uIntPtr SvPersistStream::SeekPos( sal_uIntPtr nPos ) 337 { 338 DBG_ASSERT( pStm, "stream not set" ); 339 sal_uIntPtr nRet = pStm->Seek( nPos ); 340 SetError( pStm->GetError() ); 341 return nRet; 342 } 343 344 /************************************************************************* 345 |* SvPersistStream::FlushData() 346 *************************************************************************/ 347 void SvPersistStream::FlushData() 348 { 349 } 350 351 /************************************************************************* 352 |* SvPersistStream::GetCurMaxIndex() 353 *************************************************************************/ 354 sal_uIntPtr SvPersistStream::GetCurMaxIndex( const SvPersistUIdx & rIdx ) const 355 { 356 // const bekomme ich nicht den hoechsten Index 357 SvPersistUIdx * p = (SvPersistUIdx *)&rIdx; 358 // alten merken 359 sal_uIntPtr nCurIdx = p->GetCurIndex(); 360 p->Last(); 361 // Bereiche nicht ueberschneiden, deshalb nur groessere Indexe 362 sal_uIntPtr nMaxIdx = p->GetCurIndex(); 363 // wieder herstellen 364 p->Seek( nCurIdx ); 365 return nMaxIdx; 366 } 367 368 /************************************************************************* 369 |* SvPersistStream::GetIndex() 370 *************************************************************************/ 371 sal_uIntPtr SvPersistStream::GetIndex( SvPersistBase * pObj ) const 372 { 373 sal_uIntPtr nId = (sal_uIntPtr)aPTable.Get( (sal_uIntPtr)pObj ); 374 if( !nId && pRefStm ) 375 return pRefStm->GetIndex( pObj ); 376 return nId; 377 } 378 379 /************************************************************************* 380 |* SvPersistStream::GetObject) 381 *************************************************************************/ 382 SvPersistBase * SvPersistStream::GetObject( sal_uIntPtr nIdx ) const 383 { 384 if( nIdx >= nStartIdx ) 385 return aPUIdx.Get( nIdx ); 386 else if( pRefStm ) 387 return pRefStm->GetObject( nIdx ); 388 return NULL; 389 } 390 391 //========================================================================= 392 #define LEN_1 0x80 393 #define LEN_2 0x40 394 #define LEN_4 0x20 395 #define LEN_5 0x10 396 sal_uInt32 SvPersistStream::ReadCompressed 397 ( 398 SvStream & rStm /* Aus diesem Stream werden die komprimierten Daten 399 gelesen */ 400 ) 401 /* [Beschreibung] 402 403 Ein im Stream komprimiert abgelegtes Wort wird gelesen. In welchem 404 Format komprimiert wird, siehe <SvPersistStream::WriteCompressed>. 405 406 [R"uckgabewert] 407 408 sal_uInt32 Das nicht komprimierte Wort wird zur"uckgegeben. 409 410 [Querverweise] 411 412 */ 413 { 414 sal_uInt32 nRet(0); 415 sal_uInt8 nMask; 416 rStm >> nMask; 417 if( nMask & LEN_1 ) 418 nRet = ~LEN_1 & nMask; 419 else if( nMask & LEN_2 ) 420 { 421 nRet = ~LEN_2 & nMask; 422 nRet <<= 8; 423 rStm >> nMask; 424 nRet |= nMask; 425 } 426 else if( nMask & LEN_4 ) 427 { 428 nRet = ~LEN_4 & nMask; 429 nRet <<= 8; 430 rStm >> nMask; 431 nRet |= nMask; 432 nRet <<= 16; 433 sal_uInt16 n; 434 rStm >> n; 435 nRet |= n; 436 } 437 else if( nMask & LEN_5 ) 438 { 439 if( nMask & 0x0F ) 440 { 441 rStm.SetError( SVSTREAM_FILEFORMAT_ERROR ); 442 DBG_ERROR( "format error" ); 443 } 444 rStm >> nRet; 445 } 446 else 447 { 448 rStm.SetError( SVSTREAM_FILEFORMAT_ERROR ); 449 DBG_ERROR( "format error" ); 450 } 451 return nRet; 452 } 453 454 //========================================================================= 455 void SvPersistStream::WriteCompressed 456 ( 457 SvStream & rStm,/* Aus diesem Stream werden die komprimierten Daten 458 gelesen */ 459 sal_uInt32 nVal /* Dieser Wert wird komprimiert geschrieben */ 460 ) 461 /* [Beschreibung] 462 463 Das "ubergebene Wort wird komprimiert und in den Stream 464 geschrieben. Folgendermassen wir komprimiert. 465 nVal < 0x80 => 0x80 + nVal ist 1 Byte gross. 466 nVal < 0x4000 => 0x4000 + nVal ist 2 Byte gross. 467 nVal < 0x20000000 => 0x20000000 + nVal ist 4 Byte gross. 468 nVal > 0x1FFFFFFF => 0x1000000000+ nVal ist 5 Byte gross. 469 470 [Querverweise] 471 472 <SvPersistStream::ReadCompressed> 473 */ 474 { 475 #ifdef STOR_NO_OPTIMIZE 476 if( nVal < 0x80 ) 477 rStm << (sal_uInt8)(LEN_1 | nVal); 478 else if( nVal < 0x4000 ) 479 { 480 rStm << (sal_uInt8)(LEN_2 | (nVal >> 8)); 481 rStm << (sal_uInt8)nVal; 482 } 483 else if( nVal < 0x20000000 ) 484 { 485 // hoechstes sal_uInt8 486 rStm << (sal_uInt8)(LEN_4 | (nVal >> 24)); 487 // 2. hoechstes sal_uInt8 488 rStm << (sal_uInt8)(nVal >> 16); 489 rStm << (sal_uInt16)(nVal); 490 } 491 else 492 #endif 493 { 494 rStm << (sal_uInt8)LEN_5; 495 rStm << nVal; 496 } 497 } 498 499 //========================================================================= 500 sal_uInt32 SvPersistStream::WriteDummyLen() 501 /* [Beschreibung] 502 503 Die Methode schreibt 4 Byte in den Stream und gibt die Streamposition 504 zur"uck. 505 506 [R"uckgabewert] 507 508 sal_uInt32 Die Position hinter der L"angenangabe wird zur"uckgegeben. 509 510 [Beispiel] 511 512 sal_uInt32 nObjPos = rStm.WriteDummyLen(); 513 ... 514 // Daten schreiben 515 ... 516 rStm.WriteLen( nObjPos ); 517 518 [Querverweise] 519 520 <SvPersistStream::ReadLen>, <SvPersistStream::WriteLen> 521 522 */ 523 { 524 #ifdef DBG_UTIL 525 sal_uInt32 nPos = Tell(); 526 #endif 527 sal_uInt32 n0 = 0; 528 *this << n0; // wegen Sun sp 529 // keine Assertion bei Streamfehler 530 DBG_ASSERT( GetError() != SVSTREAM_OK 531 || (sizeof( sal_uInt32 ) == Tell() -nPos), 532 "keine 4-Byte fuer Langenangabe" ); 533 return Tell(); 534 } 535 536 //========================================================================= 537 void SvPersistStream::WriteLen 538 ( 539 sal_uInt32 nObjPos /* die Position + 4, an der die L"ange geschrieben 540 wird. */ 541 ) 542 /* [Beschreibung] 543 544 Die Methode schreibt die Differenz zwischen der aktuellen und 545 nObjPos als sal_uInt32 an die Position nObjPos -4 im Stream. Danach 546 wird der Stream wieder auf die alte Position gestellt. 547 548 [Beispiel] 549 550 Die Differenz enth"alt nicht die L"angenangabe. 551 552 sal_uInt32 nObjPos = rStm.WriteDummyLen(); 553 ... 554 // Daten schreiben 555 ... 556 rStm.WriteLen( nObjPos ); 557 // weitere Daten schreiben 558 559 [Querverweise] 560 561 <SvPersistStream::ReadLen>, <SvPersistStream::WriteDummyLen> 562 */ 563 { 564 sal_uInt32 nPos = Tell(); 565 sal_uInt32 nLen = nPos - nObjPos; 566 // die Laenge mu� im stream 4-Byte betragen 567 Seek( nObjPos - sizeof( sal_uInt32 ) ); 568 // Laenge schreiben 569 *this << nLen; 570 Seek( nPos ); 571 } 572 573 //========================================================================= 574 sal_uInt32 SvPersistStream::ReadLen 575 ( 576 sal_uInt32 * pTestPos /* Die Position des Streams, nach dem Lesen der 577 L"ange, wird zur"uckgegeben. Es darf auch NULL 578 "ubergeben werden. */ 579 ) 580 /* [Beschreibung] 581 582 Liest die L"ange die vorher mit <SvPersistStream::WriteDummyLen> 583 und <SvPersistStream::WriteLen> geschrieben wurde. 584 */ 585 { 586 sal_uInt32 nLen; 587 *this >> nLen; 588 if( pTestPos ) 589 *pTestPos = Tell(); 590 return nLen; 591 } 592 593 //========================================================================= 594 // Dateirormat abw"arts kompatibel 595 #ifdef STOR_NO_OPTIMIZE 596 #define P_VER (sal_uInt8)0x00 597 #else 598 #define P_VER (sal_uInt8)0x01 599 #endif 600 #define P_VER_MASK (sal_uInt8)0x0F 601 #define P_ID_0 (sal_uInt8)0x80 602 #define P_OBJ (sal_uInt8)0x40 603 #define P_DBGUTIL (sal_uInt8)0x20 604 #define P_ID (sal_uInt8)0x10 605 #ifdef STOR_NO_OPTIMIZE 606 #define P_STD P_DBGUTIL 607 #else 608 #define P_STD 0 609 #endif 610 611 static void WriteId 612 ( 613 SvStream & rStm, 614 sal_uInt8 nHdr, 615 sal_uInt32 nId, 616 sal_uInt16 nClassId 617 ) 618 { 619 #ifdef STOR_NO_OPTIMIZE 620 nHdr |= P_ID; 621 #endif 622 nHdr |= P_VER; 623 if( nHdr & P_ID ) 624 { 625 if( (nHdr & P_OBJ) || nId != 0 ) 626 { // Id nur bei Zeiger, oder DBGUTIL 627 rStm << (sal_uInt8)(nHdr); 628 SvPersistStream::WriteCompressed( rStm, nId ); 629 } 630 else 631 { // NULL Pointer 632 rStm << (sal_uInt8)(nHdr | P_ID_0); 633 return; 634 } 635 } 636 else 637 rStm << nHdr; 638 639 if( (nHdr & P_DBGUTIL) || (nHdr & P_OBJ) ) 640 // Objekte haben immer eine Klasse, 641 // Pointer nur bei DBG_UTIL und != NULL 642 SvPersistStream::WriteCompressed( rStm, nClassId ); 643 } 644 645 //========================================================================= 646 static void ReadId 647 ( 648 SvStream & rStm, 649 sal_uInt8 & nHdr, 650 sal_uInt32 & nId, 651 sal_uInt16 & nClassId 652 ) 653 { 654 nClassId = 0; 655 rStm >> nHdr; 656 if( nHdr & P_ID_0 ) 657 nId = 0; 658 else 659 { 660 if( (nHdr & P_VER_MASK) == 0 ) 661 { 662 if( (nHdr & P_DBGUTIL) || !(nHdr & P_OBJ) ) 663 nId = SvPersistStream::ReadCompressed( rStm ); 664 else 665 nId = 0; 666 } 667 else if( nHdr & P_ID ) 668 nId = SvPersistStream::ReadCompressed( rStm ); 669 670 if( (nHdr & P_DBGUTIL) || (nHdr & P_OBJ) ) 671 nClassId = (sal_uInt16)SvPersistStream::ReadCompressed( rStm ); 672 } 673 } 674 675 //========================================================================= 676 void SvPersistStream::WriteObj 677 ( 678 sal_uInt8 nHdr, 679 SvPersistBase * pObj 680 ) 681 { 682 #ifdef STOR_NO_OPTIMIZE 683 sal_uInt32 nObjPos = 0; 684 if( nHdr & P_DBGUTIL ) 685 // Position fuer Laenge merken 686 nObjPos = WriteDummyLen(); 687 #endif 688 pObj->Save( *this ); 689 #ifdef STOR_NO_OPTIMIZE 690 if( nHdr & P_DBGUTIL ) 691 WriteLen( nObjPos ); 692 #endif 693 } 694 695 //========================================================================= 696 SvPersistStream& SvPersistStream::WritePointer 697 ( 698 SvPersistBase * pObj 699 ) 700 { 701 sal_uInt8 nP = P_STD; 702 703 if( pObj ) 704 { 705 sal_uIntPtr nId = GetIndex( pObj ); 706 if( nId ) 707 nP |= P_ID; 708 else 709 { 710 nId = aPUIdx.Insert( pObj ); 711 aPTable.Insert( (sal_uIntPtr)pObj, (void *)nId ); 712 nP |= P_OBJ; 713 } 714 WriteId( *this, nP, nId, pObj->GetClassId() ); 715 if( nP & P_OBJ ) 716 WriteObj( nP, pObj ); 717 } 718 else 719 { // NULL Pointer 720 WriteId( *this, nP | P_ID, 0, 0 ); 721 } 722 return *this; 723 } 724 725 //========================================================================= 726 sal_uInt32 SvPersistStream::ReadObj 727 ( 728 SvPersistBase * & rpObj, 729 sal_Bool bRegister 730 ) 731 { 732 sal_uInt8 nHdr; 733 sal_uInt32 nId = 0; 734 sal_uInt16 nClassId; 735 736 rpObj = NULL; // Spezifikation: Im Fehlerfall 0. 737 ReadId( *this, nHdr, nId, nClassId ); 738 739 // reine Versionsnummer durch maskieren 740 if( P_VER < (nHdr & P_VER_MASK) ) 741 { 742 SetError( SVSTREAM_FILEFORMAT_ERROR ); 743 DBG_ERROR( "false version" ); 744 } 745 746 if( !(nHdr & P_ID_0) && GetError() == SVSTREAM_OK ) 747 { 748 if( P_OBJ & nHdr ) 749 { // read object, nId nur bei P_DBGUTIL gesetzt 750 DBG_ASSERT( !(nHdr & P_DBGUTIL) || NULL == aPUIdx.Get( nId ), 751 "object already exist" ); 752 SvCreateInstancePersist pFunc = rClassMgr.Get( nClassId ); 753 754 sal_uInt32 nObjLen(0), nObjPos(0); 755 if( nHdr & P_DBGUTIL ) 756 nObjLen = ReadLen( &nObjPos ); 757 if( !pFunc ) 758 { 759 #ifdef DBG_UTIL 760 ByteString aStr( "no class with id: " ); 761 aStr += ByteString::CreateFromInt32( nClassId ); 762 aStr += " registered"; 763 DBG_WARNING( aStr.GetBuffer() ); 764 #endif 765 SetError( ERRCODE_IO_NOFACTORY ); 766 return 0; 767 } 768 pFunc( &rpObj ); 769 // Sichern 770 rpObj->AddRef(); 771 772 if( bRegister ) 773 { 774 // unbedingt erst in Tabelle eintragen 775 sal_uIntPtr nNewId = aPUIdx.Insert( rpObj ); 776 // um den gleichen Zustand, wie nach dem Speichern herzustellen 777 aPTable.Insert( (sal_uIntPtr)rpObj, (void *)nNewId ); 778 DBG_ASSERT( !(nHdr & P_DBGUTIL) || nId == nNewId, 779 "read write id conflict: not the same" ); 780 } 781 // und dann Laden 782 rpObj->Load( *this ); 783 #ifdef DBG_UTIL 784 if( nObjLen + nObjPos != Tell() ) 785 { 786 ByteString aStr( "false object len: read = " ); 787 aStr += ByteString::CreateFromInt32( (long)(Tell() - nObjPos) ); 788 aStr += ", should = "; 789 aStr += ByteString::CreateFromInt32( nObjLen ); 790 DBG_ERROR( aStr.GetBuffer() ); 791 } 792 #endif 793 rpObj->RestoreNoDelete(); 794 rpObj->ReleaseRef(); 795 } 796 else 797 { 798 rpObj = GetObject( nId ); 799 DBG_ASSERT( rpObj != NULL, "object does not exist" ); 800 DBG_ASSERT( rpObj->GetClassId() == nClassId, "class mismatch" ); 801 } 802 } 803 return nId; 804 } 805 806 //========================================================================= 807 SvPersistStream& SvPersistStream::ReadPointer 808 ( 809 SvPersistBase * & rpObj 810 ) 811 { 812 ReadObj( rpObj, sal_True ); 813 return *this; 814 } 815 816 //========================================================================= 817 SvPersistStream& operator << 818 ( 819 SvPersistStream & rStm, 820 SvPersistBase * pObj 821 ) 822 { 823 return rStm.WritePointer( pObj ); 824 } 825 826 //========================================================================= 827 SvPersistStream& operator >> 828 ( 829 SvPersistStream & rStm, 830 SvPersistBase * & rpObj 831 ) 832 { 833 return rStm.ReadPointer( rpObj ); 834 } 835 836 //========================================================================= 837 SvStream& operator << 838 ( 839 SvStream & rStm, 840 SvPersistStream & rThis 841 ) 842 { 843 SvStream * pOldStm = rThis.GetStream(); 844 rThis.SetStream( &rStm ); 845 846 sal_uInt8 bTmp = 0; 847 rThis << bTmp; // Version 848 sal_uInt32 nCount = (sal_uInt32)rThis.aPUIdx.Count(); 849 rThis << nCount; 850 SvPersistBase * pEle = rThis.aPUIdx.First(); 851 for( sal_uInt32 i = 0; i < nCount; i++ ) 852 { 853 sal_uInt8 nP = P_OBJ | P_ID | P_STD; 854 WriteId( rThis, nP, rThis.aPUIdx.GetCurIndex(), 855 pEle->GetClassId() ); 856 rThis.WriteObj( nP, pEle ); 857 pEle = rThis.aPUIdx.Next(); 858 } 859 rThis.SetStream( pOldStm ); 860 return rStm; 861 } 862 863 //========================================================================= 864 SvStream& operator >> 865 ( 866 SvStream & rStm, 867 SvPersistStream & rThis 868 ) 869 { 870 SvStream * pOldStm = rThis.GetStream(); 871 rThis.SetStream( &rStm ); 872 873 sal_uInt8 nVers; 874 rThis >> nVers; // Version 875 if( 0 == nVers ) 876 { 877 sal_uInt32 nCount = 0; 878 rThis >> nCount; 879 for( sal_uInt32 i = 0; i < nCount; i++ ) 880 { 881 SvPersistBase * pEle; 882 // Lesen, ohne in die Tabellen einzutragen 883 sal_uInt32 nId = rThis.ReadObj( pEle, sal_False ); 884 if( rThis.GetError() ) 885 break; 886 887 // Die Id eines Objektes wird nie modifiziert 888 rThis.aPUIdx.Insert( nId, pEle ); 889 rThis.aPTable.Insert( (sal_uIntPtr)pEle, (void *)nId ); 890 } 891 } 892 else 893 rThis.SetError( SVSTREAM_FILEFORMAT_ERROR ); 894 895 rThis.SetStream( pOldStm ); 896 return rStm; 897 } 898 899 //========================================================================= 900 sal_uIntPtr SvPersistStream::InsertObj( SvPersistBase * pObj ) 901 { 902 sal_uIntPtr nId = aPUIdx.Insert( pObj ); 903 aPTable.Insert( (sal_uIntPtr)pObj, (void *)nId ); 904 return nId; 905 } 906 907 //========================================================================= 908 sal_uIntPtr SvPersistStream::RemoveObj( SvPersistBase * pObj ) 909 { 910 sal_uIntPtr nIdx = GetIndex( pObj ); 911 aPUIdx.Remove( nIdx ); 912 aPTable.Remove( (sal_uIntPtr)pObj ); 913 return nIdx; 914 } 915 916