Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 : #include <tools/debug.hxx>
21 : #include <tools/pstm.hxx>
22 : #include <rtl/strbuf.hxx>
23 :
24 : #define STOR_NO_OPTIMIZE
25 :
26 0 : void SvClassManager::Register( sal_Int32 nClassId, SvCreateInstancePersist pFunc )
27 : {
28 : #ifdef DBG_UTIL
29 : SvCreateInstancePersist p;
30 : p = Get( nClassId );
31 : DBG_ASSERT( !p || p == pFunc, "register class with same id" );
32 : #endif
33 0 : aAssocTable.insert(Map::value_type(nClassId, pFunc));
34 0 : }
35 :
36 0 : SvCreateInstancePersist SvClassManager::Get( sal_Int32 nClassId )
37 : {
38 0 : Map::const_iterator i(aAssocTable.find(nClassId));
39 0 : return i == aAssocTable.end() ? 0 : i->second;
40 : }
41 :
42 : // SvRttiBase
43 0 : TYPEINIT0( SvRttiBase );
44 :
45 : // SvPersistBaseMemberList
46 :
47 : #define PERSIST_LIST_VER (sal_uInt8)0
48 : #define PERSIST_LIST_DBGUTIL (sal_uInt8)0x80
49 :
50 0 : void TOOLS_DLLPUBLIC WritePersistListObjects(const SvPersistListWriteable& rList, SvPersistStream & rStm, bool bOnlyStreamed )
51 : {
52 : #ifdef STOR_NO_OPTIMIZE
53 0 : rStm.WriteUChar( (sal_uInt8)(PERSIST_LIST_VER | PERSIST_LIST_DBGUTIL) );
54 0 : sal_uInt32 nObjPos = rStm.WriteDummyLen();
55 : #else
56 : sal_uInt8 bTmp = PERSIST_LIST_VER;
57 : rStm << bTmp;
58 : #endif
59 0 : sal_uInt32 nCountMember = rList.size();
60 0 : sal_uIntPtr nCountPos = rStm.Tell();
61 0 : sal_uInt32 nWriteCount = 0;
62 0 : rStm.WriteUInt32( nCountMember );
63 : // Don't change the list, as it causes side-effects while saving
64 0 : for( sal_uIntPtr n = 0; n < nCountMember; n++ )
65 : {
66 0 : SvPersistBase * pObj = rList.GetPersistBase( n );
67 0 : if( !bOnlyStreamed || rStm.IsStreamed( pObj ) )
68 : { // Object should be stored
69 0 : WriteSvPersistBase(rStm, pObj);
70 0 : nWriteCount++;
71 : }
72 : }
73 0 : if( nWriteCount != nCountMember )
74 : {
75 : // Didn't write all members, adjust count
76 0 : sal_uIntPtr nPos = rStm.Tell();
77 0 : rStm.Seek( nCountPos );
78 0 : rStm.WriteUInt32( nWriteCount );
79 0 : rStm.Seek( nPos );
80 : }
81 : #ifdef STOR_NO_OPTIMIZE
82 0 : rStm.WriteLen( nObjPos );
83 : #endif
84 0 : }
85 :
86 0 : void TOOLS_DLLPUBLIC ReadObjects( SvPersistListReadable& rLst, SvPersistStream & rStm )
87 : {
88 : sal_uInt8 nVer;
89 0 : rStm.ReadUChar( nVer );
90 :
91 0 : if( (nVer & ~PERSIST_LIST_DBGUTIL) != PERSIST_LIST_VER )
92 : {
93 0 : rStm.SetError( SVSTREAM_GENERALERROR );
94 : OSL_FAIL( "persist list, false version" );
95 : }
96 :
97 0 : sal_uInt32 nObjLen(0), nObjPos(0);
98 0 : if( nVer & PERSIST_LIST_DBGUTIL )
99 0 : nObjLen = rStm.ReadLen( &nObjPos );
100 :
101 : sal_uInt32 nCount;
102 0 : rStm.ReadUInt32( nCount );
103 0 : for( sal_uIntPtr n = 0; n < nCount && rStm.GetError() == SVSTREAM_OK; n++ )
104 : {
105 : SvPersistBase * pObj;
106 0 : rStm >> pObj;
107 0 : if( pObj )
108 0 : rLst.push_back( pObj );
109 : }
110 : #ifdef DBG_UTIL
111 : if( nObjLen + nObjPos != rStm.Tell() )
112 : {
113 : OStringBuffer aStr("false list len: read = ");
114 : aStr.append(static_cast<sal_Int64>(rStm.Tell() - nObjPos));
115 : aStr.append(", should = ");
116 : aStr.append(static_cast<sal_Int64>(nObjLen));
117 : OSL_FAIL(aStr.getStr());
118 : }
119 : #else
120 : (void)nObjLen;
121 : #endif
122 0 : }
123 :
124 : /** Constructor
125 :
126 : @param rMgr Stores factories for objects that can persisted
127 : @param pStream This stream is used as the medium for PersistStream
128 : @param nStartIdxP Start value for object identifier (set > 0 )
129 :
130 : @warning Objects rMgr and pStream must not be manipulated while used in
131 : SvPersistStream. An Exception to this is pvStream
132 : (cf. <SvPersistStream::SetStream>).
133 : @see SvPersistStream::SetStream
134 : */
135 0 : SvPersistStream::SvPersistStream( SvClassManager & rMgr, SvStream * pStream, sal_uInt32 nStartIdxP )
136 : : rClassMgr( rMgr )
137 : , pStm( pStream )
138 : , aPUIdx( nStartIdxP )
139 : , nStartIdx( nStartIdxP )
140 : , pRefStm( NULL )
141 0 : , nFlags( 0 )
142 : {
143 : DBG_ASSERT( nStartIdx != 0, "zero index not allowed" );
144 0 : bIsWritable = true;
145 0 : if( pStm )
146 : {
147 0 : SetVersion( pStm->GetVersion() );
148 0 : SetError( pStm->GetError() );
149 0 : SyncSvStream( pStm->Tell() );
150 : }
151 0 : }
152 :
153 0 : SvPersistStream::~SvPersistStream()
154 : {
155 0 : SetStream( NULL );
156 0 : }
157 :
158 : /**
159 :
160 : @param pStream This stream is used as the medium for PersistStream
161 :
162 : @warning pStream is used as the medium for PersistStream.
163 : It must not be manipulated while used in SvPersistStream.
164 : An Exception to this is pvStream (cf. <SvPersistStream::SetStream>).
165 : */
166 0 : void SvPersistStream::SetStream( SvStream * pStream )
167 : {
168 0 : if( pStm != pStream )
169 : {
170 0 : if( pStm )
171 : {
172 0 : SyncSysStream();
173 0 : pStm->SetError( GetError() );
174 : }
175 0 : pStm = pStream;
176 : }
177 0 : if( pStm )
178 : {
179 0 : SetVersion( pStm->GetVersion() );
180 0 : SetError( pStm->GetError() );
181 0 : SyncSvStream( pStm->Tell() );
182 : }
183 0 : }
184 :
185 0 : void SvPersistStream::ResetError()
186 : {
187 0 : SvStream::ResetError();
188 : DBG_ASSERT( pStm, "stream not set" );
189 0 : pStm->ResetError();
190 0 : }
191 :
192 0 : sal_uIntPtr SvPersistStream::GetData( void* pData, sal_uIntPtr nSize )
193 : {
194 : DBG_ASSERT( pStm, "stream not set" );
195 0 : sal_uIntPtr nRet = pStm->Read( pData, nSize );
196 0 : SetError( pStm->GetError() );
197 0 : return nRet;
198 : }
199 :
200 0 : sal_uIntPtr SvPersistStream::PutData( const void* pData, sal_uIntPtr nSize )
201 : {
202 : DBG_ASSERT( pStm, "stream not set" );
203 0 : sal_uIntPtr nRet = pStm->Write( pData, nSize );
204 0 : SetError( pStm->GetError() );
205 0 : return nRet;
206 : }
207 :
208 0 : sal_uInt64 SvPersistStream::SeekPos(sal_uInt64 const nPos)
209 : {
210 : DBG_ASSERT( pStm, "stream not set" );
211 0 : sal_uInt64 nRet = pStm->Seek( nPos );
212 0 : SetError( pStm->GetError() );
213 0 : return nRet;
214 : }
215 :
216 0 : void SvPersistStream::FlushData()
217 : {
218 0 : }
219 :
220 0 : sal_uIntPtr SvPersistStream::GetIndex( SvPersistBase * pObj ) const
221 : {
222 0 : PersistBaseMap::const_iterator it = aPTable.find( pObj );
223 0 : if( it == aPTable.end() )
224 : {
225 0 : if ( pRefStm )
226 0 : return pRefStm->GetIndex( pObj );
227 : else
228 0 : return 0;
229 : }
230 0 : return it->second;
231 : }
232 :
233 0 : SvPersistBase * SvPersistStream::GetObject( sal_uIntPtr nIdx ) const
234 : {
235 0 : if( nIdx >= nStartIdx )
236 0 : return aPUIdx.Get( nIdx );
237 0 : else if( pRefStm )
238 0 : return pRefStm->GetObject( nIdx );
239 0 : return NULL;
240 : }
241 :
242 : #define LEN_1 0x80
243 : #define LEN_2 0x40
244 : #define LEN_4 0x20
245 : #define LEN_5 0x10
246 :
247 : /** Reads a compressed word from the stream.
248 :
249 : For details on what format is used for compression, see
250 : <SvPersistStream::WriteCompressed>.
251 :
252 : @param rStm Source to read compressed data from
253 :
254 : @return Uncompressed word
255 : @see SvPersistStream::WriteCompressed
256 : */
257 0 : sal_uInt32 SvPersistStream::ReadCompressed( SvStream & rStm )
258 : {
259 0 : sal_uInt32 nRet(0);
260 : sal_uInt8 nMask;
261 0 : rStm.ReadUChar( nMask );
262 0 : if( nMask & LEN_1 )
263 0 : nRet = ~LEN_1 & nMask;
264 0 : else if( nMask & LEN_2 )
265 : {
266 0 : nRet = ~LEN_2 & nMask;
267 0 : nRet <<= 8;
268 0 : rStm.ReadUChar( nMask );
269 0 : nRet |= nMask;
270 : }
271 0 : else if( nMask & LEN_4 )
272 : {
273 0 : nRet = ~LEN_4 & nMask;
274 0 : nRet <<= 8;
275 0 : rStm.ReadUChar( nMask );
276 0 : nRet |= nMask;
277 0 : nRet <<= 16;
278 : sal_uInt16 n;
279 0 : rStm.ReadUInt16( n );
280 0 : nRet |= n;
281 : }
282 0 : else if( nMask & LEN_5 )
283 : {
284 0 : if( nMask & 0x0F )
285 : {
286 0 : rStm.SetError( SVSTREAM_FILEFORMAT_ERROR );
287 : OSL_FAIL( "format error" );
288 : }
289 0 : rStm.ReadUInt32( nRet );
290 : }
291 : else
292 : {
293 0 : rStm.SetError( SVSTREAM_FILEFORMAT_ERROR );
294 : OSL_FAIL( "format error" );
295 : }
296 0 : return nRet;
297 : }
298 :
299 : /** Writes compressed stream
300 :
301 : @param rStm Source for writing compressed data
302 : @param nVal This value will be compressed and written
303 :
304 : nVal is compressed and written to stream using the following algorithm
305 : nVal < 0x80 => 0x80 + nVal of size 1 Byte.
306 : nVal < 0x4000 => 0x4000 + nVal of size 2 Byte.
307 : nVal < 0x20000000 => 0x20000000 + nVal of size 4 Byte.
308 : nVal > 0x1FFFFFFF => 0x1000000000+ nVal of size 5 Byte.
309 :
310 : @see SvPersistStream::ReadCompressed
311 : */
312 0 : void SvPersistStream::WriteCompressed( SvStream & rStm, sal_uInt32 nVal )
313 : {
314 : #ifdef STOR_NO_OPTIMIZE
315 0 : if( nVal < 0x80 )
316 0 : rStm.WriteUChar( (sal_uInt8)(LEN_1 | nVal) );
317 0 : else if( nVal < 0x4000 )
318 : {
319 0 : rStm.WriteUChar( (sal_uInt8)(LEN_2 | (nVal >> 8)) );
320 0 : rStm.WriteUChar( (sal_uInt8)nVal );
321 : }
322 0 : else if( nVal < 0x20000000 )
323 : {
324 : // highest sal_uInt8
325 0 : rStm.WriteUChar( (sal_uInt8)(LEN_4 | (nVal >> 24)) );
326 : // 2nd highest sal_uInt8
327 0 : rStm.WriteUChar( (sal_uInt8)(nVal >> 16) );
328 0 : rStm.WriteUInt16( (sal_uInt16)(nVal) );
329 : }
330 : else
331 : #endif
332 : {
333 0 : rStm.WriteUChar( (sal_uInt8)LEN_5 );
334 0 : rStm.WriteUInt32( nVal );
335 : }
336 0 : }
337 :
338 : /** This method writes length value of 4 Bytes to the stream and returns the
339 : stream position.
340 :
341 : Example:
342 : @code
343 : sal_uInt32 nObjPos = rStm.WriteDummyLen();
344 : ...
345 : // write data
346 : ...
347 : rStm.WriteLen( nObjPos );
348 : @endcode
349 :
350 : @return Position of stream behind length value
351 :
352 : @see SvPersistStream::ReadLen
353 : @see SvPersistStream::WriteLen
354 : */
355 0 : sal_uInt32 SvPersistStream::WriteDummyLen()
356 : {
357 : #ifdef DBG_UTIL
358 : sal_uInt32 nPos = Tell();
359 : #endif
360 0 : sal_uInt32 n0 = 0;
361 0 : WriteUInt32( n0 ); // Because of Sun sp
362 : // Don't assert on stream error
363 : DBG_ASSERT( GetError() != SVSTREAM_OK
364 : || (sizeof( sal_uInt32 ) == Tell() -nPos),
365 : "No 4 byte as length parameter" );
366 0 : return Tell();
367 : }
368 :
369 : /** Write difference between current position and nObjPos
370 : as sal_uInt32 to position nObjPos-4 in the stream.
371 :
372 : Afterwards, reset stream to old position.
373 :
374 : Example: Difference does not contain length value
375 : @code
376 : sal_uInt32 nObjPos = rStm.WriteDummyLen();
377 : ...
378 : // write data
379 : ...
380 : rStm.WriteLen( nObjPos );
381 : // write more data
382 : @endcode
383 :
384 : @param nObjPos Position+4, on which length is written to
385 :
386 : @see SvPersistStream::ReadLen
387 : @see SvPersistStream::WriteDummyLen
388 : */
389 0 : void SvPersistStream::WriteLen( sal_uInt32 nObjPos )
390 : {
391 0 : sal_uInt32 nPos = Tell();
392 0 : sal_uInt32 nLen = nPos - nObjPos;
393 : // Length in stream must be 4 Bytes
394 0 : Seek( nObjPos - sizeof( sal_uInt32 ) );
395 : // write length
396 0 : WriteUInt32( nLen );
397 0 : Seek( nPos );
398 0 : }
399 :
400 : /** Read a length value written to stream
401 :
402 : @param pTestPos Position of the stream after reading length. May be NULL.
403 :
404 : @see SvPersistStream::WriteDummyLen
405 : @see SvPersistStream::WriteLen
406 : */
407 0 : sal_uInt32 SvPersistStream::ReadLen( sal_uInt32 * pTestPos )
408 : {
409 : sal_uInt32 nLen;
410 0 : ReadUInt32( nLen );
411 0 : if( pTestPos )
412 0 : *pTestPos = Tell();
413 0 : return nLen;
414 : }
415 :
416 : // File format backward-compatible
417 : #ifdef STOR_NO_OPTIMIZE
418 : #define P_VER (sal_uInt8)0x00
419 : #else
420 : #define P_VER (sal_uInt8)0x01
421 : #endif
422 : #define P_VER_MASK (sal_uInt8)0x0F
423 : #define P_ID_0 (sal_uInt8)0x80
424 : #define P_OBJ (sal_uInt8)0x40
425 : #define P_DBGUTIL (sal_uInt8)0x20
426 : #define P_ID (sal_uInt8)0x10
427 : #ifdef STOR_NO_OPTIMIZE
428 : #define P_STD P_DBGUTIL
429 : #else
430 : #define P_STD 0
431 : #endif
432 :
433 0 : static void WriteId
434 : (
435 : SvStream & rStm,
436 : sal_uInt8 nHdr,
437 : sal_uInt32 nId,
438 : sal_uInt16 nClassId
439 : )
440 : {
441 : #ifdef STOR_NO_OPTIMIZE
442 0 : nHdr |= P_ID;
443 : #endif
444 0 : nHdr |= P_VER;
445 0 : if( nHdr & P_ID )
446 : {
447 0 : if( (nHdr & P_OBJ) || nId != 0 )
448 : { // Id set only for pointers or DBGUTIL
449 0 : rStm.WriteUChar( (sal_uInt8)(nHdr) );
450 0 : SvPersistStream::WriteCompressed( rStm, nId );
451 : }
452 : else
453 : { // NULL Pointer
454 0 : rStm.WriteUChar( (sal_uInt8)(nHdr | P_ID_0) );
455 0 : return;
456 : }
457 : }
458 : else
459 0 : rStm.WriteUChar( nHdr );
460 :
461 0 : if( (nHdr & P_DBGUTIL) || (nHdr & P_OBJ) )
462 : // Objects always have a class id
463 : // Pointers only for DBG_UTIL and != NULL
464 0 : SvPersistStream::WriteCompressed( rStm, nClassId );
465 : }
466 :
467 0 : static void ReadId
468 : (
469 : SvStream & rStm,
470 : sal_uInt8 & nHdr,
471 : sal_uInt32 & nId,
472 : sal_uInt16 & nClassId
473 : )
474 : {
475 0 : nClassId = 0;
476 0 : rStm.ReadUChar( nHdr );
477 0 : if( nHdr & P_ID_0 )
478 0 : nId = 0;
479 : else
480 : {
481 0 : if( (nHdr & P_VER_MASK) == 0 )
482 : {
483 0 : if( (nHdr & P_DBGUTIL) || !(nHdr & P_OBJ) )
484 0 : nId = SvPersistStream::ReadCompressed( rStm );
485 : else
486 0 : nId = 0;
487 : }
488 0 : else if( nHdr & P_ID )
489 0 : nId = SvPersistStream::ReadCompressed( rStm );
490 :
491 0 : if( (nHdr & P_DBGUTIL) || (nHdr & P_OBJ) )
492 0 : nClassId = (sal_uInt16)SvPersistStream::ReadCompressed( rStm );
493 : }
494 0 : }
495 :
496 0 : void SvPersistStream::WriteObj
497 : (
498 : sal_uInt8 nHdr,
499 : SvPersistBase * pObj
500 : )
501 : {
502 : #ifdef STOR_NO_OPTIMIZE
503 0 : sal_uInt32 nObjPos = 0;
504 0 : if( nHdr & P_DBGUTIL )
505 : // remember position for length value
506 0 : nObjPos = WriteDummyLen();
507 : #endif
508 0 : pObj->Save( *this );
509 : #ifdef STOR_NO_OPTIMIZE
510 0 : if( nHdr & P_DBGUTIL )
511 0 : WriteLen( nObjPos );
512 : #endif
513 0 : }
514 :
515 0 : SvPersistStream& SvPersistStream::WritePointer
516 : (
517 : SvPersistBase * pObj
518 : )
519 : {
520 0 : sal_uInt8 nP = P_STD;
521 :
522 0 : if( pObj )
523 : {
524 0 : sal_uIntPtr nId = GetIndex( pObj );
525 0 : if( nId )
526 0 : nP |= P_ID;
527 : else
528 : {
529 0 : nId = aPUIdx.Insert( pObj );
530 0 : aPTable[ pObj ] = nId;
531 0 : nP |= P_OBJ;
532 : }
533 0 : WriteId( *this, nP, nId, pObj->GetClassId() );
534 0 : if( nP & P_OBJ )
535 0 : WriteObj( nP, pObj );
536 : }
537 : else
538 : { // NULL Pointer
539 0 : WriteId( *this, nP | P_ID, 0, 0 );
540 : }
541 0 : return *this;
542 : }
543 :
544 0 : sal_uInt32 SvPersistStream::ReadObj
545 : (
546 : SvPersistBase * & rpObj,
547 : bool bRegister
548 : )
549 : {
550 : sal_uInt8 nHdr;
551 0 : sal_uInt32 nId = 0;
552 : sal_uInt16 nClassId;
553 :
554 0 : rpObj = NULL; // specification: 0 in case of error
555 0 : ReadId( *this, nHdr, nId, nClassId );
556 :
557 : // get version nummer through masking
558 0 : if( P_VER < (nHdr & P_VER_MASK) )
559 : {
560 0 : SetError( SVSTREAM_FILEFORMAT_ERROR );
561 : OSL_FAIL( "false version" );
562 : }
563 :
564 0 : if( !(nHdr & P_ID_0) && GetError() == SVSTREAM_OK )
565 : {
566 0 : if( P_OBJ & nHdr )
567 : { // read object, nId only set for P_DBGUTIL
568 : DBG_ASSERT( !(nHdr & P_DBGUTIL) || NULL == aPUIdx.Get( nId ),
569 : "object already exist" );
570 0 : SvCreateInstancePersist pFunc = rClassMgr.Get( nClassId );
571 :
572 0 : sal_uInt32 nObjLen(0), nObjPos(0);
573 0 : if( nHdr & P_DBGUTIL )
574 0 : nObjLen = ReadLen( &nObjPos );
575 0 : if( !pFunc )
576 : {
577 : #ifdef DBG_UTIL
578 : OStringBuffer aStr("no class with id: " );
579 : aStr.append(static_cast<sal_Int32>(nClassId));
580 : aStr.append(" registered");
581 : DBG_WARNING(aStr.getStr());
582 : #else
583 : (void)nObjLen;
584 : #endif
585 0 : SetError( ERRCODE_IO_NOFACTORY );
586 0 : return 0;
587 : }
588 0 : pFunc( &rpObj );
589 : // Save reference
590 0 : rpObj->AddRef();
591 :
592 0 : if( bRegister )
593 : {
594 : // insert into table
595 0 : sal_uIntPtr nNewId = aPUIdx.Insert( rpObj );
596 : // in order to restore state after saving
597 0 : aPTable[ rpObj ] = nNewId;
598 : DBG_ASSERT( !(nHdr & P_DBGUTIL) || nId == nNewId,
599 : "read write id conflict: not the same" );
600 : }
601 0 : rpObj->Load( *this );
602 : #ifdef DBG_UTIL
603 : if( nObjLen + nObjPos != Tell() )
604 : {
605 : OStringBuffer aStr("false object len: read = ");
606 : aStr.append(static_cast<sal_Int64>((long)(Tell() - nObjPos)));
607 : aStr.append(", should = ");
608 : aStr.append(static_cast<sal_Int32>(nObjLen));
609 : OSL_FAIL(aStr.getStr());
610 : }
611 : #endif
612 0 : rpObj->RestoreNoDelete();
613 0 : rpObj->ReleaseRef();
614 : }
615 : else
616 : {
617 0 : rpObj = GetObject( nId );
618 : DBG_ASSERT( rpObj != NULL, "object does not exist" );
619 : DBG_ASSERT( rpObj->GetClassId() == nClassId, "class mismatch" );
620 : }
621 : }
622 0 : return nId;
623 : }
624 :
625 0 : SvPersistStream& SvPersistStream::ReadPointer
626 : (
627 : SvPersistBase * & rpObj
628 : )
629 : {
630 0 : ReadObj( rpObj, true );
631 0 : return *this;
632 : }
633 :
634 0 : SvPersistStream& WriteSvPersistBase
635 : (
636 : SvPersistStream & rStm,
637 : SvPersistBase * pObj
638 : )
639 : {
640 0 : return rStm.WritePointer( pObj );
641 : }
642 :
643 0 : SvPersistStream& operator >>
644 : (
645 : SvPersistStream & rStm,
646 : SvPersistBase * & rpObj
647 : )
648 : {
649 0 : return rStm.ReadPointer( rpObj );
650 : }
651 :
652 0 : SvStream& WriteSvPersistStream
653 : (
654 : SvStream & rStm,
655 : SvPersistStream & rThis
656 : )
657 : {
658 0 : SvStream * pOldStm = rThis.GetStream();
659 0 : rThis.SetStream( &rStm );
660 :
661 0 : sal_uInt8 bTmp = 0;
662 0 : rThis.WriteUChar( bTmp ); // Version
663 0 : sal_uInt32 nCount = (sal_uInt32)rThis.aPUIdx.Count();
664 0 : rThis.WriteUInt32( nCount );
665 0 : sal_uIntPtr aIndex = rThis.aPUIdx.FirstIndex();
666 0 : for( sal_uInt32 i = 0; i < nCount; i++ )
667 : {
668 0 : SvPersistBase * pEle = rThis.aPUIdx.Get(aIndex);
669 0 : sal_uInt8 nP = P_OBJ | P_ID | P_STD;
670 0 : WriteId( rThis, nP, aIndex, pEle->GetClassId() );
671 0 : rThis.WriteObj( nP, pEle );
672 0 : aIndex = rThis.aPUIdx.NextIndex( aIndex );
673 : }
674 0 : rThis.SetStream( pOldStm );
675 0 : return rStm;
676 : }
677 :
678 0 : SvStream& operator >>
679 : (
680 : SvStream & rStm,
681 : SvPersistStream & rThis
682 : )
683 : {
684 0 : SvStream * pOldStm = rThis.GetStream();
685 0 : rThis.SetStream( &rStm );
686 :
687 : sal_uInt8 nVers;
688 0 : rThis.ReadUChar( nVers ); // Version
689 0 : if( 0 == nVers )
690 : {
691 0 : sal_uInt32 nCount = 0;
692 0 : rThis.ReadUInt32( nCount );
693 0 : for( sal_uInt32 i = 0; i < nCount; i++ )
694 : {
695 : SvPersistBase * pEle;
696 : // read, but don't insert into table
697 0 : sal_uIntPtr nId = rThis.ReadObj( pEle, false );
698 0 : if( rThis.GetError() )
699 0 : break;
700 :
701 : // Id of object is never modified
702 0 : rThis.aPUIdx.Insert( nId, pEle );
703 0 : rThis.aPTable[ pEle ] = nId;
704 : }
705 : }
706 : else
707 0 : rThis.SetError( SVSTREAM_FILEFORMAT_ERROR );
708 :
709 0 : rThis.SetStream( pOldStm );
710 0 : return rStm;
711 : }
712 :
713 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|