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