Update ooo320-m1
[ooovba.git] / tools / source / ref / pstm.cxx
blob4e77cd84487f2a1da66e61a942130bc658f74a17
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: pstm.cxx,v $
10 * $Revision: 1.9 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_tools.hxx"
34 #include <tools/debug.hxx>
35 #include <tools/pstm.hxx>
37 #define STOR_NO_OPTIMIZE
39 /***********************************************************************/
40 /************************************************************************
41 |* SvClassManager::Register()
42 *************************************************************************/
43 void SvClassManager::Register( USHORT nClassId, SvCreateInstancePersist pFunc )
45 #ifdef DBG_UTIL
46 SvCreateInstancePersist p;
47 p = Get( nClassId );
48 DBG_ASSERT( !p || p == pFunc, "register class with same id" );
49 #endif
50 aAssocTable.insert(Map::value_type(nClassId, pFunc));
53 /************************************************************************
54 |* SvClassManager::Get()
55 *************************************************************************/
56 SvCreateInstancePersist SvClassManager::Get( USHORT nClassId )
58 Map::const_iterator i(aAssocTable.find(nClassId));
59 return i == aAssocTable.end() ? 0 : i->second;
62 /****************** SvRttiBase *******************************************/
63 TYPEINIT0( SvRttiBase );
65 /****************** SvPersistBaseMemberList ******************************/
67 SvPersistBaseMemberList::SvPersistBaseMemberList(){}
68 SvPersistBaseMemberList::SvPersistBaseMemberList(
69 USHORT nInitSz, USHORT nResize )
70 : SuperSvPersistBaseMemberList( nInitSz, nResize ){}
72 #define PERSIST_LIST_VER (BYTE)0
73 #define PERSIST_LIST_DBGUTIL (BYTE)0x80
75 /************************************************************************
76 |* SvPersistBaseMemberList::WriteOnlyStreamedObjects()
77 *************************************************************************/
78 void SvPersistBaseMemberList::WriteObjects( SvPersistStream & rStm,
79 BOOL bOnlyStreamed ) const
81 #ifdef STOR_NO_OPTIMIZE
82 rStm << (BYTE)(PERSIST_LIST_VER | PERSIST_LIST_DBGUTIL);
83 UINT32 nObjPos = rStm.WriteDummyLen();
84 #else
85 BYTE bTmp = PERSIST_LIST_VER;
86 rStm << bTmp;
87 #endif
88 UINT32 nCountMember = Count();
89 ULONG nCountPos = rStm.Tell();
90 UINT32 nWriteCount = 0;
91 rStm << nCountMember;
92 //bloss die Liste nicht veraendern,
93 //wegen Seiteneffekten beim Save
94 for( ULONG n = 0; n < nCountMember; n++ )
96 SvPersistBase * pObj = GetObject( n );
97 if( !bOnlyStreamed || rStm.IsStreamed( pObj ) )
98 { // Objekt soll geschrieben werden
99 rStm << GetObject( n );
100 nWriteCount++;
103 if( nWriteCount != nCountMember )
105 // nicht alle Objekte geschrieben, Count anpassen
106 ULONG nPos = rStm.Tell();
107 rStm.Seek( nCountPos );
108 rStm << nWriteCount;
109 rStm.Seek( nPos );
111 #ifdef STOR_NO_OPTIMIZE
112 rStm.WriteLen( nObjPos );
113 #endif
116 /************************************************************************
117 |* operator << ()
118 *************************************************************************/
119 SvPersistStream& operator << ( SvPersistStream & rStm,
120 const SvPersistBaseMemberList & rLst )
122 rLst.WriteObjects( rStm );
123 return rStm;
126 /************************************************************************
127 |* operator >> ()
128 *************************************************************************/
129 SvPersistStream& operator >> ( SvPersistStream & rStm,
130 SvPersistBaseMemberList & rLst )
132 BYTE nVer;
133 rStm >> nVer;
135 if( (nVer & ~PERSIST_LIST_DBGUTIL) != PERSIST_LIST_VER )
137 rStm.SetError( SVSTREAM_GENERALERROR );
138 DBG_ERROR( "persist list, false version" );
141 UINT32 nObjLen(0), nObjPos(0);
142 if( nVer & PERSIST_LIST_DBGUTIL )
143 nObjLen = rStm.ReadLen( &nObjPos );
145 sal_uInt32 nCount;
146 rStm >> nCount;
147 for( ULONG n = 0; n < nCount && rStm.GetError() == SVSTREAM_OK; n++ )
149 SvPersistBase * pObj;
150 rStm >> pObj;
151 if( pObj )
152 rLst.Append( pObj );
154 #ifdef DBG_UTIL
155 if( nObjLen + nObjPos != rStm.Tell() )
157 ByteString aStr( "false list len: read = " );
158 aStr += ByteString::CreateFromInt32( (long)(rStm.Tell() - nObjPos) );
159 aStr += ", should = ";
160 aStr += ByteString::CreateFromInt64(nObjLen);
161 DBG_ERROR( aStr.GetBuffer() );
163 #endif
164 return rStm;
167 //=========================================================================
168 SvPersistStream::SvPersistStream
170 SvClassManager & rMgr, /* Alle Factorys, deren Objekt geladen und
171 gespeichert werdn k"onnen */
172 SvStream * pStream, /* Dieser Stream wird als Medium genommen, auf
173 dem der PersistStream arbeitet */
174 UINT32 nStartIdxP /* Ab diesem Index werden die Id's f"ur
175 die Objekte vergeben, er muss gr"osser
176 als Null sein. */
178 : rClassMgr( rMgr )
179 , pStm( pStream )
180 , aPUIdx( nStartIdxP )
181 , nStartIdx( nStartIdxP )
182 , pRefStm( NULL )
183 , nFlags( 0 )
184 /* [Beschreibung]
186 Der Konstruktor der Klasse SvPersistStream. Die Objekte rMgr und
187 pStream d"urfen nicht ver"andert werden, solange sie in einem
188 SvPersistStream eingesetzt sind. Eine Aussnahme gibt es f"ur
189 pStream (siehe <SvPersistStream::SetStream>).
192 DBG_ASSERT( nStartIdx != 0, "zero index not allowed" );
193 bIsWritable = TRUE;
194 if( pStm )
196 SetVersion( pStm->GetVersion() );
197 SetError( pStm->GetError() );
198 SyncSvStream( pStm->Tell() );
202 //=========================================================================
203 SvPersistStream::SvPersistStream
205 SvClassManager & rMgr, /* Alle Factorys, deren Objekt geladen und
206 gespeichert werdn k"onnen */
207 SvStream * pStream, /* Dieser Stream wird als Medium genommen, auf
208 dem der PersistStream arbeitet */
209 const SvPersistStream & rPersStm
210 /* Wenn PersistStream's verschachtelt werden,
211 dann ist dies der Parent-Stream. */
213 : rClassMgr( rMgr )
214 , pStm( pStream )
215 // Bereiche nicht ueberschneiden, deshalb nur groessere Indexe
216 , aPUIdx( rPersStm.GetCurMaxIndex() +1 )
217 , nStartIdx( rPersStm.GetCurMaxIndex() +1 )
218 , pRefStm( &rPersStm )
219 , nFlags( 0 )
220 /* [Beschreibung]
222 Der Konstruktor der Klasse SvPersistStream. Die Objekte rMgr und
223 pStream d"urfen nicht ver"andert werden, solange sie in einem
224 SvPersistStream eingesetzt sind. Eine Aussnahme gibt es f"ur
225 pStream (siehe <SvPersistStream::SetStream>).
226 Durch diesen Konstruktor wird eine Hierarchiebildung unterst"utzt.
227 Alle Objekte aus einer Hierarchie m"ussen erst geladen werden,
228 wenn das erste aus dieser Hierarchie benutzt werden soll.
231 bIsWritable = TRUE;
232 if( pStm )
234 SetVersion( pStm->GetVersion() );
235 SetError( pStm->GetError() );
236 SyncSvStream( pStm->Tell() );
240 //=========================================================================
241 SvPersistStream::~SvPersistStream()
242 /* [Beschreibung]
244 Der Detruktor ruft die Methode <SvPersistStream::SetStream>
245 mit NULL.
248 SetStream( NULL );
251 //=========================================================================
252 void SvPersistStream::SetStream
254 SvStream * pStream /* auf diesem Stream arbeitet der PersistStream */
257 /* [Beschreibung]
259 Es wird ein Medium (pStream) eingesetzt, auf dem PersistStream arbeitet.
260 Dieses darf nicht von aussen modifiziert werden, solange es
261 eingesetzt ist. Es sei denn, w"ahrend auf dem Medium gearbeitet
262 wird, wird keine Methode von SvPersistStream gerufen, bevor
263 nicht <SvPersistStream::SetStream> mit demselben Medium gerufen
264 wurde.
267 if( pStm != pStream )
269 if( pStm )
271 SyncSysStream();
272 pStm->SetError( GetError() );
274 pStm = pStream;
276 if( pStm )
278 SetVersion( pStm->GetVersion() );
279 SetError( pStm->GetError() );
280 SyncSvStream( pStm->Tell() );
284 //=========================================================================
285 USHORT SvPersistStream::IsA() const
286 /* [Beschreibung]
288 Gibt den Identifier dieses Streamklasse zur"uck.
290 [R"uckgabewert]
292 USHORT ID_PERSISTSTREAM wird zur"uckgegeben.
295 [Querverweise]
297 <SvStream::IsA>
300 return ID_PERSISTSTREAM;
304 /*************************************************************************
305 |* SvPersistStream::ResetError()
306 *************************************************************************/
307 void SvPersistStream::ResetError()
309 SvStream::ResetError();
310 DBG_ASSERT( pStm, "stream not set" );
311 pStm->ResetError();
314 /*************************************************************************
315 |* SvPersistStream::GetData()
316 *************************************************************************/
317 ULONG SvPersistStream::GetData( void* pData, ULONG nSize )
319 DBG_ASSERT( pStm, "stream not set" );
320 ULONG nRet = pStm->Read( pData, nSize );
321 SetError( pStm->GetError() );
322 return nRet;
325 /*************************************************************************
326 |* SvPersistStream::PutData()
327 *************************************************************************/
328 ULONG SvPersistStream::PutData( const void* pData, ULONG nSize )
330 DBG_ASSERT( pStm, "stream not set" );
331 ULONG nRet = pStm->Write( pData, nSize );
332 SetError( pStm->GetError() );
333 return nRet;
336 /*************************************************************************
337 |* SvPersistStream::Seek()
338 *************************************************************************/
339 ULONG SvPersistStream::SeekPos( ULONG nPos )
341 DBG_ASSERT( pStm, "stream not set" );
342 ULONG nRet = pStm->Seek( nPos );
343 SetError( pStm->GetError() );
344 return nRet;
347 /*************************************************************************
348 |* SvPersistStream::FlushData()
349 *************************************************************************/
350 void SvPersistStream::FlushData()
354 /*************************************************************************
355 |* SvPersistStream::GetCurMaxIndex()
356 *************************************************************************/
357 ULONG SvPersistStream::GetCurMaxIndex( const SvPersistUIdx & rIdx ) const
359 // const bekomme ich nicht den hoechsten Index
360 SvPersistUIdx * p = (SvPersistUIdx *)&rIdx;
361 // alten merken
362 ULONG nCurIdx = p->GetCurIndex();
363 p->Last();
364 // Bereiche nicht ueberschneiden, deshalb nur groessere Indexe
365 ULONG nMaxIdx = p->GetCurIndex();
366 // wieder herstellen
367 p->Seek( nCurIdx );
368 return nMaxIdx;
371 /*************************************************************************
372 |* SvPersistStream::GetIndex()
373 *************************************************************************/
374 ULONG SvPersistStream::GetIndex( SvPersistBase * pObj ) const
376 ULONG nId = (ULONG)aPTable.Get( (ULONG)pObj );
377 if( !nId && pRefStm )
378 return pRefStm->GetIndex( pObj );
379 return nId;
382 /*************************************************************************
383 |* SvPersistStream::GetObject)
384 *************************************************************************/
385 SvPersistBase * SvPersistStream::GetObject( ULONG nIdx ) const
387 if( nIdx >= nStartIdx )
388 return aPUIdx.Get( nIdx );
389 else if( pRefStm )
390 return pRefStm->GetObject( nIdx );
391 return NULL;
394 //=========================================================================
395 #define LEN_1 0x80
396 #define LEN_2 0x40
397 #define LEN_4 0x20
398 #define LEN_5 0x10
399 UINT32 SvPersistStream::ReadCompressed
401 SvStream & rStm /* Aus diesem Stream werden die komprimierten Daten
402 gelesen */
404 /* [Beschreibung]
406 Ein im Stream komprimiert abgelegtes Wort wird gelesen. In welchem
407 Format komprimiert wird, siehe <SvPersistStream::WriteCompressed>.
409 [R"uckgabewert]
411 UINT32 Das nicht komprimierte Wort wird zur"uckgegeben.
413 [Querverweise]
417 UINT32 nRet(0);
418 BYTE nMask;
419 rStm >> nMask;
420 if( nMask & LEN_1 )
421 nRet = ~LEN_1 & nMask;
422 else if( nMask & LEN_2 )
424 nRet = ~LEN_2 & nMask;
425 nRet <<= 8;
426 rStm >> nMask;
427 nRet |= nMask;
429 else if( nMask & LEN_4 )
431 nRet = ~LEN_4 & nMask;
432 nRet <<= 8;
433 rStm >> nMask;
434 nRet |= nMask;
435 nRet <<= 16;
436 USHORT n;
437 rStm >> n;
438 nRet |= n;
440 else if( nMask & LEN_5 )
442 if( nMask & 0x0F )
444 rStm.SetError( SVSTREAM_FILEFORMAT_ERROR );
445 DBG_ERROR( "format error" );
447 rStm >> nRet;
449 else
451 rStm.SetError( SVSTREAM_FILEFORMAT_ERROR );
452 DBG_ERROR( "format error" );
454 return nRet;
457 //=========================================================================
458 void SvPersistStream::WriteCompressed
460 SvStream & rStm,/* Aus diesem Stream werden die komprimierten Daten
461 gelesen */
462 UINT32 nVal /* Dieser Wert wird komprimiert geschrieben */
464 /* [Beschreibung]
466 Das "ubergebene Wort wird komprimiert und in den Stream
467 geschrieben. Folgendermassen wir komprimiert.
468 nVal < 0x80 => 0x80 + nVal ist 1 Byte gross.
469 nVal < 0x4000 => 0x4000 + nVal ist 2 Byte gross.
470 nVal < 0x20000000 => 0x20000000 + nVal ist 4 Byte gross.
471 nVal > 0x1FFFFFFF => 0x1000000000+ nVal ist 5 Byte gross.
473 [Querverweise]
475 <SvPersistStream::ReadCompressed>
478 #ifdef STOR_NO_OPTIMIZE
479 if( nVal < 0x80 )
480 rStm << (BYTE)(LEN_1 | nVal);
481 else if( nVal < 0x4000 )
483 rStm << (BYTE)(LEN_2 | (nVal >> 8));
484 rStm << (BYTE)nVal;
486 else if( nVal < 0x20000000 )
488 // hoechstes BYTE
489 rStm << (BYTE)(LEN_4 | (nVal >> 24));
490 // 2. hoechstes BYTE
491 rStm << (BYTE)(nVal >> 16);
492 rStm << (USHORT)(nVal);
494 else
495 #endif
497 rStm << (BYTE)LEN_5;
498 rStm << nVal;
502 //=========================================================================
503 UINT32 SvPersistStream::WriteDummyLen()
504 /* [Beschreibung]
506 Die Methode schreibt 4 Byte in den Stream und gibt die Streamposition
507 zur"uck.
509 [R"uckgabewert]
511 UINT32 Die Position hinter der L"angenangabe wird zur"uckgegeben.
513 [Beispiel]
515 UINT32 nObjPos = rStm.WriteDummyLen();
517 // Daten schreiben
519 rStm.WriteLen( nObjPos );
521 [Querverweise]
523 <SvPersistStream::ReadLen>, <SvPersistStream::WriteLen>
527 #ifdef DBG_UTIL
528 UINT32 nPos = Tell();
529 #endif
530 UINT32 n0 = 0;
531 *this << n0; // wegen Sun sp
532 // keine Assertion bei Streamfehler
533 DBG_ASSERT( GetError() != SVSTREAM_OK
534 || (sizeof( UINT32 ) == Tell() -nPos),
535 "keine 4-Byte fuer Langenangabe" );
536 return Tell();
539 //=========================================================================
540 void SvPersistStream::WriteLen
542 UINT32 nObjPos /* die Position + 4, an der die L"ange geschrieben
543 wird. */
545 /* [Beschreibung]
547 Die Methode schreibt die Differenz zwischen der aktuellen und
548 nObjPos als UINT32 an die Position nObjPos -4 im Stream. Danach
549 wird der Stream wieder auf die alte Position gestellt.
551 [Beispiel]
553 Die Differenz enth"alt nicht die L"angenangabe.
555 UINT32 nObjPos = rStm.WriteDummyLen();
557 // Daten schreiben
559 rStm.WriteLen( nObjPos );
560 // weitere Daten schreiben
562 [Querverweise]
564 <SvPersistStream::ReadLen>, <SvPersistStream::WriteDummyLen>
567 UINT32 nPos = Tell();
568 UINT32 nLen = nPos - nObjPos;
569 // die Laenge mu� im stream 4-Byte betragen
570 Seek( nObjPos - sizeof( UINT32 ) );
571 // Laenge schreiben
572 *this << nLen;
573 Seek( nPos );
576 //=========================================================================
577 UINT32 SvPersistStream::ReadLen
579 UINT32 * pTestPos /* Die Position des Streams, nach dem Lesen der
580 L"ange, wird zur"uckgegeben. Es darf auch NULL
581 "ubergeben werden. */
583 /* [Beschreibung]
585 Liest die L"ange die vorher mit <SvPersistStream::WriteDummyLen>
586 und <SvPersistStream::WriteLen> geschrieben wurde.
589 UINT32 nLen;
590 *this >> nLen;
591 if( pTestPos )
592 *pTestPos = Tell();
593 return nLen;
596 //=========================================================================
597 // Dateirormat abw"arts kompatibel
598 #ifdef STOR_NO_OPTIMIZE
599 #define P_VER (BYTE)0x00
600 #else
601 #define P_VER (BYTE)0x01
602 #endif
603 #define P_VER_MASK (BYTE)0x0F
604 #define P_ID_0 (BYTE)0x80
605 #define P_OBJ (BYTE)0x40
606 #define P_DBGUTIL (BYTE)0x20
607 #define P_ID (BYTE)0x10
608 #ifdef STOR_NO_OPTIMIZE
609 #define P_STD P_DBGUTIL
610 #else
611 #define P_STD 0
612 #endif
614 static void WriteId
616 SvStream & rStm,
617 BYTE nHdr,
618 UINT32 nId,
619 USHORT nClassId
622 #ifdef STOR_NO_OPTIMIZE
623 nHdr |= P_ID;
624 #endif
625 nHdr |= P_VER;
626 if( nHdr & P_ID )
628 if( (nHdr & P_OBJ) || nId != 0 )
629 { // Id nur bei Zeiger, oder DBGUTIL
630 rStm << (BYTE)(nHdr);
631 SvPersistStream::WriteCompressed( rStm, nId );
633 else
634 { // NULL Pointer
635 rStm << (BYTE)(nHdr | P_ID_0);
636 return;
639 else
640 rStm << nHdr;
642 if( (nHdr & P_DBGUTIL) || (nHdr & P_OBJ) )
643 // Objekte haben immer eine Klasse,
644 // Pointer nur bei DBG_UTIL und != NULL
645 SvPersistStream::WriteCompressed( rStm, nClassId );
648 //=========================================================================
649 static void ReadId
651 SvStream & rStm,
652 BYTE & nHdr,
653 UINT32 & nId,
654 USHORT & nClassId
657 nClassId = 0;
658 rStm >> nHdr;
659 if( nHdr & P_ID_0 )
660 nId = 0;
661 else
663 if( (nHdr & P_VER_MASK) == 0 )
665 if( (nHdr & P_DBGUTIL) || !(nHdr & P_OBJ) )
666 nId = SvPersistStream::ReadCompressed( rStm );
667 else
668 nId = 0;
670 else if( nHdr & P_ID )
671 nId = SvPersistStream::ReadCompressed( rStm );
673 if( (nHdr & P_DBGUTIL) || (nHdr & P_OBJ) )
674 nClassId = (USHORT)SvPersistStream::ReadCompressed( rStm );
678 //=========================================================================
679 void SvPersistStream::WriteObj
681 BYTE nHdr,
682 SvPersistBase * pObj
685 #ifdef STOR_NO_OPTIMIZE
686 UINT32 nObjPos = 0;
687 if( nHdr & P_DBGUTIL )
688 // Position fuer Laenge merken
689 nObjPos = WriteDummyLen();
690 #endif
691 pObj->Save( *this );
692 #ifdef STOR_NO_OPTIMIZE
693 if( nHdr & P_DBGUTIL )
694 WriteLen( nObjPos );
695 #endif
698 //=========================================================================
699 SvPersistStream& SvPersistStream::WritePointer
701 SvPersistBase * pObj
704 BYTE nP = P_STD;
706 if( pObj )
708 ULONG nId = GetIndex( pObj );
709 if( nId )
710 nP |= P_ID;
711 else
713 nId = aPUIdx.Insert( pObj );
714 aPTable.Insert( (ULONG)pObj, (void *)nId );
715 nP |= P_OBJ;
717 WriteId( *this, nP, nId, pObj->GetClassId() );
718 if( nP & P_OBJ )
719 WriteObj( nP, pObj );
721 else
722 { // NULL Pointer
723 WriteId( *this, nP | P_ID, 0, 0 );
725 return *this;
728 //=========================================================================
729 UINT32 SvPersistStream::ReadObj
731 SvPersistBase * & rpObj,
732 BOOL bRegister
735 BYTE nHdr;
736 UINT32 nId = 0;
737 USHORT nClassId;
739 rpObj = NULL; // Spezifikation: Im Fehlerfall 0.
740 ReadId( *this, nHdr, nId, nClassId );
742 // reine Versionsnummer durch maskieren
743 if( P_VER < (nHdr & P_VER_MASK) )
745 SetError( SVSTREAM_FILEFORMAT_ERROR );
746 DBG_ERROR( "false version" );
749 if( !(nHdr & P_ID_0) && GetError() == SVSTREAM_OK )
751 if( P_OBJ & nHdr )
752 { // read object, nId nur bei P_DBGUTIL gesetzt
753 DBG_ASSERT( !(nHdr & P_DBGUTIL) || NULL == aPUIdx.Get( nId ),
754 "object already exist" );
755 SvCreateInstancePersist pFunc = rClassMgr.Get( nClassId );
757 UINT32 nObjLen(0), nObjPos(0);
758 if( nHdr & P_DBGUTIL )
759 nObjLen = ReadLen( &nObjPos );
760 if( !pFunc )
762 #ifdef DBG_UTIL
763 ByteString aStr( "no class with id: " );
764 aStr += ByteString::CreateFromInt32( nClassId );
765 aStr += " registered";
766 DBG_WARNING( aStr.GetBuffer() );
767 #endif
768 SetError( ERRCODE_IO_NOFACTORY );
769 return 0;
771 pFunc( &rpObj );
772 // Sichern
773 rpObj->AddRef();
775 if( bRegister )
777 // unbedingt erst in Tabelle eintragen
778 ULONG nNewId = aPUIdx.Insert( rpObj );
779 // um den gleichen Zustand, wie nach dem Speichern herzustellen
780 aPTable.Insert( (ULONG)rpObj, (void *)nNewId );
781 DBG_ASSERT( !(nHdr & P_DBGUTIL) || nId == nNewId,
782 "read write id conflict: not the same" );
784 // und dann Laden
785 rpObj->Load( *this );
786 #ifdef DBG_UTIL
787 if( nObjLen + nObjPos != Tell() )
789 ByteString aStr( "false object len: read = " );
790 aStr += ByteString::CreateFromInt32( (long)(Tell() - nObjPos) );
791 aStr += ", should = ";
792 aStr += ByteString::CreateFromInt32( nObjLen );
793 DBG_ERROR( aStr.GetBuffer() );
795 #endif
796 rpObj->RestoreNoDelete();
797 rpObj->ReleaseRef();
799 else
801 rpObj = GetObject( nId );
802 DBG_ASSERT( rpObj != NULL, "object does not exist" );
803 DBG_ASSERT( rpObj->GetClassId() == nClassId, "class mismatch" );
806 return nId;
809 //=========================================================================
810 SvPersistStream& SvPersistStream::ReadPointer
812 SvPersistBase * & rpObj
815 ReadObj( rpObj, TRUE );
816 return *this;
819 //=========================================================================
820 SvPersistStream& operator <<
822 SvPersistStream & rStm,
823 SvPersistBase * pObj
826 return rStm.WritePointer( pObj );
829 //=========================================================================
830 SvPersistStream& operator >>
832 SvPersistStream & rStm,
833 SvPersistBase * & rpObj
836 return rStm.ReadPointer( rpObj );
839 //=========================================================================
840 SvStream& operator <<
842 SvStream & rStm,
843 SvPersistStream & rThis
846 SvStream * pOldStm = rThis.GetStream();
847 rThis.SetStream( &rStm );
849 BYTE bTmp = 0;
850 rThis << bTmp; // Version
851 UINT32 nCount = (UINT32)rThis.aPUIdx.Count();
852 rThis << nCount;
853 SvPersistBase * pEle = rThis.aPUIdx.First();
854 for( UINT32 i = 0; i < nCount; i++ )
856 BYTE nP = P_OBJ | P_ID | P_STD;
857 WriteId( rThis, nP, rThis.aPUIdx.GetCurIndex(),
858 pEle->GetClassId() );
859 rThis.WriteObj( nP, pEle );
860 pEle = rThis.aPUIdx.Next();
862 rThis.SetStream( pOldStm );
863 return rStm;
866 //=========================================================================
867 SvStream& operator >>
869 SvStream & rStm,
870 SvPersistStream & rThis
873 SvStream * pOldStm = rThis.GetStream();
874 rThis.SetStream( &rStm );
876 BYTE nVers;
877 rThis >> nVers; // Version
878 if( 0 == nVers )
880 UINT32 nCount = 0;
881 rThis >> nCount;
882 for( UINT32 i = 0; i < nCount; i++ )
884 SvPersistBase * pEle;
885 // Lesen, ohne in die Tabellen einzutragen
886 UINT32 nId = rThis.ReadObj( pEle, FALSE );
887 if( rThis.GetError() )
888 break;
890 // Die Id eines Objektes wird nie modifiziert
891 rThis.aPUIdx.Insert( nId, pEle );
892 rThis.aPTable.Insert( (ULONG)pEle, (void *)nId );
895 else
896 rThis.SetError( SVSTREAM_FILEFORMAT_ERROR );
898 rThis.SetStream( pOldStm );
899 return rStm;
902 //=========================================================================
903 ULONG SvPersistStream::InsertObj( SvPersistBase * pObj )
905 ULONG nId = aPUIdx.Insert( pObj );
906 aPTable.Insert( (ULONG)pObj, (void *)nId );
907 return nId;
910 //=========================================================================
911 ULONG SvPersistStream::RemoveObj( SvPersistBase * pObj )
913 ULONG nIdx = GetIndex( pObj );
914 aPUIdx.Remove( nIdx );
915 aPTable.Remove( (ULONG)pObj );
916 return nIdx;