xref: /AOO41X/main/tools/source/ref/pstm.cxx (revision 89b56da77b74925c286b3e777681ba8dda16bf41)
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 *************************************************************************/
Register(sal_uInt16 nClassId,SvCreateInstancePersist pFunc)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 *************************************************************************/
Get(sal_uInt16 nClassId)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 
SvPersistBaseMemberList()60 SvPersistBaseMemberList::SvPersistBaseMemberList(){}
SvPersistBaseMemberList(sal_uInt16 nInitSz,sal_uInt16 nResize)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 *************************************************************************/
WriteObjects(SvPersistStream & rStm,sal_Bool bOnlyStreamed) const71 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 *************************************************************************/
operator <<(SvPersistStream & rStm,const SvPersistBaseMemberList & rLst)112 SvPersistStream& operator << ( SvPersistStream & rStm,
113                                const SvPersistBaseMemberList & rLst )
114 {
115     rLst.WriteObjects( rStm );
116     return rStm;
117 }
118 
119 /************************************************************************
120 |*    operator >> ()
121 *************************************************************************/
operator >>(SvPersistStream & rStm,SvPersistBaseMemberList & rLst)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 //=========================================================================
SvPersistStream(SvClassManager & rMgr,SvStream * pStream,sal_uInt32 nStartIdxP)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 //=========================================================================
SvPersistStream(SvClassManager & rMgr,SvStream * pStream,const SvPersistStream & rPersStm)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 //=========================================================================
~SvPersistStream()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 //=========================================================================
SetStream(SvStream * pStream)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 //=========================================================================
IsA() const278 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 *************************************************************************/
ResetError()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 *************************************************************************/
GetData(void * pData,sal_uIntPtr nSize)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 *************************************************************************/
PutData(const void * pData,sal_uIntPtr nSize)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 *************************************************************************/
SeekPos(sal_uIntPtr nPos)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 *************************************************************************/
FlushData()343 void SvPersistStream::FlushData()
344 {
345 }
346 
347 /*************************************************************************
348 |*    SvPersistStream::GetCurMaxIndex()
349 *************************************************************************/
GetCurMaxIndex(const SvPersistUIdx & rIdx) const350 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 *************************************************************************/
GetIndex(SvPersistBase * pObj) const367 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 *************************************************************************/
GetObject(sal_uIntPtr nIdx) const378 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
ReadCompressed(SvStream & rStm)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 //=========================================================================
WriteCompressed(SvStream & rStm,sal_uInt32 nVal)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 //=========================================================================
WriteDummyLen()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 //=========================================================================
WriteLen(sal_uInt32 nObjPos)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 //=========================================================================
ReadLen(sal_uInt32 * pTestPos)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 
WriteId(SvStream & rStm,sal_uInt8 nHdr,sal_uInt32 nId,sal_uInt16 nClassId)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 //=========================================================================
ReadId(SvStream & rStm,sal_uInt8 & nHdr,sal_uInt32 & nId,sal_uInt16 & nClassId)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 //=========================================================================
WriteObj(sal_uInt8 nHdr,SvPersistBase * pObj)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 //=========================================================================
WritePointer(SvPersistBase * pObj)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 //=========================================================================
ReadObj(SvPersistBase * & rpObj,sal_Bool bRegister)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 //=========================================================================
ReadPointer(SvPersistBase * & rpObj)803 SvPersistStream& SvPersistStream::ReadPointer
804 (
805     SvPersistBase * & rpObj
806 )
807 {
808     ReadObj( rpObj, sal_True );
809     return *this;
810 }
811 
812 //=========================================================================
operator <<(SvPersistStream & rStm,SvPersistBase * pObj)813 SvPersistStream& operator <<
814 (
815     SvPersistStream & rStm,
816     SvPersistBase * pObj
817 )
818 {
819     return rStm.WritePointer( pObj );
820 }
821 
822 //=========================================================================
operator >>(SvPersistStream & rStm,SvPersistBase * & rpObj)823 SvPersistStream& operator >>
824 (
825     SvPersistStream & rStm,
826     SvPersistBase * & rpObj
827 )
828 {
829     return rStm.ReadPointer( rpObj );
830 }
831 
832 //=========================================================================
operator <<(SvStream & rStm,SvPersistStream & rThis)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 //=========================================================================
operator >>(SvStream & rStm,SvPersistStream & rThis)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 //=========================================================================
InsertObj(SvPersistBase * pObj)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 //=========================================================================
RemoveObj(SvPersistBase * pObj)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