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