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 1021 : 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 1021 : aAssocTable.insert(Map::value_type(nClassId, pFunc));
34 1021 : }
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 36160 : TYPEINIT0( SvRttiBase );
44 :
45 : // SvPersistBaseMemberList
46 :
47 : #define PERSIST_LIST_VER (sal_uInt8)0
48 : #define PERSIST_LIST_DBGUTIL (sal_uInt8)0x80
49 :
50 2248 : void TOOLS_DLLPUBLIC WritePersistListObjects(const SvPersistListWriteable& rList, SvPersistStream & rStm, bool bOnlyStreamed )
51 : {
52 : #ifdef STOR_NO_OPTIMIZE
53 2248 : rStm << (sal_uInt8)(PERSIST_LIST_VER | PERSIST_LIST_DBGUTIL);
54 2248 : sal_uInt32 nObjPos = rStm.WriteDummyLen();
55 : #else
56 : sal_uInt8 bTmp = PERSIST_LIST_VER;
57 : rStm << bTmp;
58 : #endif
59 2248 : sal_uInt32 nCountMember = rList.size();
60 2248 : sal_uIntPtr nCountPos = rStm.Tell();
61 2248 : sal_uInt32 nWriteCount = 0;
62 2248 : rStm << nCountMember;
63 : // Don't change the list, as it causes side-effects while saving
64 33057 : for( sal_uIntPtr n = 0; n < nCountMember; n++ )
65 : {
66 30809 : SvPersistBase * pObj = rList.GetPersistBase( n );
67 30809 : if( !bOnlyStreamed || rStm.IsStreamed( pObj ) )
68 : { // Object should be stored
69 30809 : rStm << pObj;
70 30809 : nWriteCount++;
71 : }
72 : }
73 2248 : 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 << nWriteCount;
79 0 : rStm.Seek( nPos );
80 : }
81 : #ifdef STOR_NO_OPTIMIZE
82 2248 : rStm.WriteLen( nObjPos );
83 : #endif
84 2248 : }
85 :
86 0 : void TOOLS_DLLPUBLIC ReadObjects( SvPersistListReadable& rLst, SvPersistStream & rStm )
87 : {
88 : sal_uInt8 nVer;
89 0 : rStm >> 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 >> 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 252 : 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 252 : , nFlags( 0 )
142 : {
143 : DBG_ASSERT( nStartIdx != 0, "zero index not allowed" );
144 252 : bIsWritable = true;
145 252 : if( pStm )
146 : {
147 244 : SetVersion( pStm->GetVersion() );
148 244 : SetError( pStm->GetError() );
149 244 : SyncSvStream( pStm->Tell() );
150 : }
151 252 : }
152 :
153 504 : SvPersistStream::~SvPersistStream()
154 : {
155 252 : SetStream( NULL );
156 252 : }
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 252 : void SvPersistStream::SetStream( SvStream * pStream )
167 : {
168 252 : if( pStm != pStream )
169 : {
170 244 : if( pStm )
171 : {
172 244 : SyncSysStream();
173 244 : pStm->SetError( GetError() );
174 : }
175 244 : pStm = pStream;
176 : }
177 252 : if( pStm )
178 : {
179 0 : SetVersion( pStm->GetVersion() );
180 0 : SetError( pStm->GetError() );
181 0 : SyncSvStream( pStm->Tell() );
182 : }
183 252 : }
184 :
185 : /** Returns the identifier of this stream class.
186 :
187 : @return ID_PERSISTSTREAM
188 :
189 : @see SvStream::IsA
190 : */
191 0 : sal_uInt16 SvPersistStream::IsA() const
192 : {
193 0 : return ID_PERSISTSTREAM;
194 : }
195 :
196 0 : void SvPersistStream::ResetError()
197 : {
198 0 : SvStream::ResetError();
199 : DBG_ASSERT( pStm, "stream not set" );
200 0 : pStm->ResetError();
201 0 : }
202 :
203 0 : sal_uIntPtr SvPersistStream::GetData( void* pData, sal_uIntPtr nSize )
204 : {
205 : DBG_ASSERT( pStm, "stream not set" );
206 0 : sal_uIntPtr nRet = pStm->Read( pData, nSize );
207 0 : SetError( pStm->GetError() );
208 0 : return nRet;
209 : }
210 :
211 714737 : sal_uIntPtr SvPersistStream::PutData( const void* pData, sal_uIntPtr nSize )
212 : {
213 : DBG_ASSERT( pStm, "stream not set" );
214 714737 : sal_uIntPtr nRet = pStm->Write( pData, nSize );
215 714737 : SetError( pStm->GetError() );
216 714737 : return nRet;
217 : }
218 :
219 55488 : sal_uIntPtr SvPersistStream::SeekPos( sal_uIntPtr nPos )
220 : {
221 : DBG_ASSERT( pStm, "stream not set" );
222 55488 : sal_uIntPtr nRet = pStm->Seek( nPos );
223 55488 : SetError( pStm->GetError() );
224 55488 : return nRet;
225 : }
226 :
227 244 : void SvPersistStream::FlushData()
228 : {
229 244 : }
230 :
231 56764 : sal_uIntPtr SvPersistStream::GetIndex( SvPersistBase * pObj ) const
232 : {
233 56764 : PersistBaseMap::const_iterator it = aPTable.find( pObj );
234 56764 : if( it == aPTable.end() )
235 : {
236 25366 : if ( pRefStm )
237 0 : return pRefStm->GetIndex( pObj );
238 : else
239 25366 : return 0;
240 : }
241 31398 : return it->second;
242 : }
243 :
244 0 : SvPersistBase * SvPersistStream::GetObject( sal_uIntPtr nIdx ) const
245 : {
246 0 : if( nIdx >= nStartIdx )
247 0 : return aPUIdx.Get( nIdx );
248 0 : else if( pRefStm )
249 0 : return pRefStm->GetObject( nIdx );
250 0 : return NULL;
251 : }
252 :
253 : #define LEN_1 0x80
254 : #define LEN_2 0x40
255 : #define LEN_4 0x20
256 : #define LEN_5 0x10
257 :
258 : /** Reads a compressed word from the stream.
259 :
260 : For details on what format is used for compression, see
261 : <SvPersistStream::WriteCompressed>.
262 :
263 : @param rStm Source to read compressed data from
264 :
265 : @return Uncompressed word
266 : @see SvPersistStream::WriteCompressed
267 : */
268 0 : sal_uInt32 SvPersistStream::ReadCompressed( SvStream & rStm )
269 : {
270 0 : sal_uInt32 nRet(0);
271 : sal_uInt8 nMask;
272 0 : rStm >> nMask;
273 0 : if( nMask & LEN_1 )
274 0 : nRet = ~LEN_1 & nMask;
275 0 : else if( nMask & LEN_2 )
276 : {
277 0 : nRet = ~LEN_2 & nMask;
278 0 : nRet <<= 8;
279 0 : rStm >> nMask;
280 0 : nRet |= nMask;
281 : }
282 0 : else if( nMask & LEN_4 )
283 : {
284 0 : nRet = ~LEN_4 & nMask;
285 0 : nRet <<= 8;
286 0 : rStm >> nMask;
287 0 : nRet |= nMask;
288 0 : nRet <<= 16;
289 : sal_uInt16 n;
290 0 : rStm >> n;
291 0 : nRet |= n;
292 : }
293 0 : else if( nMask & LEN_5 )
294 : {
295 0 : if( nMask & 0x0F )
296 : {
297 0 : rStm.SetError( SVSTREAM_FILEFORMAT_ERROR );
298 : OSL_FAIL( "format error" );
299 : }
300 0 : rStm >> nRet;
301 : }
302 : else
303 : {
304 0 : rStm.SetError( SVSTREAM_FILEFORMAT_ERROR );
305 : OSL_FAIL( "format error" );
306 : }
307 0 : return nRet;
308 : }
309 :
310 : /** Writes compressed stream
311 :
312 : @param rStm Source for writing compressed data
313 : @param nVal This value will be compressed and written
314 :
315 : nVal is compressed and written to stream using the following algorithm
316 : nVal < 0x80 => 0x80 + nVal of size 1 Byte.
317 : nVal < 0x4000 => 0x4000 + nVal of size 2 Byte.
318 : nVal < 0x20000000 => 0x20000000 + nVal of size 4 Byte.
319 : nVal > 0x1FFFFFFF => 0x1000000000+ nVal of size 5 Byte.
320 :
321 : @see SvPersistStream::ReadCompressed
322 : */
323 126641 : void SvPersistStream::WriteCompressed( SvStream & rStm, sal_uInt32 nVal )
324 : {
325 : #ifdef STOR_NO_OPTIMIZE
326 126641 : if( nVal < 0x80 )
327 73397 : rStm << (sal_uInt8)(LEN_1 | nVal);
328 53244 : else if( nVal < 0x4000 )
329 : {
330 49466 : rStm << (sal_uInt8)(LEN_2 | (nVal >> 8));
331 49466 : rStm << (sal_uInt8)nVal;
332 : }
333 3778 : else if( nVal < 0x20000000 )
334 : {
335 : // highest sal_uInt8
336 3778 : rStm << (sal_uInt8)(LEN_4 | (nVal >> 24));
337 : // 2nd highest sal_uInt8
338 3778 : rStm << (sal_uInt8)(nVal >> 16);
339 3778 : rStm << (sal_uInt16)(nVal);
340 : }
341 : else
342 : #endif
343 : {
344 0 : rStm << (sal_uInt8)LEN_5;
345 0 : rStm << nVal;
346 : }
347 126641 : }
348 :
349 : /** This method writes length value of 4 Bytes to the stream and returns the
350 : stream position.
351 :
352 : Example:
353 : @code
354 : sal_uInt32 nObjPos = rStm.WriteDummyLen();
355 : ...
356 : // write data
357 : ...
358 : rStm.WriteLen( nObjPos );
359 : @endcode
360 :
361 : @return Position of stream behind length value
362 :
363 : @see SvPersistStream::ReadLen
364 : @see SvPersistStream::WriteLen
365 : */
366 27614 : sal_uInt32 SvPersistStream::WriteDummyLen()
367 : {
368 : #ifdef DBG_UTIL
369 : sal_uInt32 nPos = Tell();
370 : #endif
371 27614 : sal_uInt32 n0 = 0;
372 27614 : *this << n0; // Because of Sun sp
373 : // Don't assert on stream error
374 : DBG_ASSERT( GetError() != SVSTREAM_OK
375 : || (sizeof( sal_uInt32 ) == Tell() -nPos),
376 : "No 4 byte as length parameter" );
377 27614 : return Tell();
378 : }
379 :
380 : /** Write difference between current position and nObjPos
381 : as sal_uInt32 to position nObjPos-4 in the stream.
382 :
383 : Afterwards, reset stream to old position.
384 :
385 : Example: Difference does not contain length value
386 : @code
387 : sal_uInt32 nObjPos = rStm.WriteDummyLen();
388 : ...
389 : // write data
390 : ...
391 : rStm.WriteLen( nObjPos );
392 : // write more data
393 : @endcode
394 :
395 : @param nObjPos Position+4, on which length is written to
396 :
397 : @see SvPersistStream::ReadLen
398 : @see SvPersistStream::WriteDummyLen
399 : */
400 27614 : void SvPersistStream::WriteLen( sal_uInt32 nObjPos )
401 : {
402 27614 : sal_uInt32 nPos = Tell();
403 27614 : sal_uInt32 nLen = nPos - nObjPos;
404 : // Length in stream must be 4 Bytes
405 27614 : Seek( nObjPos - sizeof( sal_uInt32 ) );
406 : // write length
407 27614 : *this << nLen;
408 27614 : Seek( nPos );
409 27614 : }
410 :
411 : /** Read a length value written to stream
412 :
413 : @param pTestPos Position of the stream after reading length. May be NULL.
414 :
415 : @see SvPersistStream::WriteDummyLen
416 : @see SvPersistStream::WriteLen
417 : */
418 0 : sal_uInt32 SvPersistStream::ReadLen( sal_uInt32 * pTestPos )
419 : {
420 : sal_uInt32 nLen;
421 0 : *this >> nLen;
422 0 : if( pTestPos )
423 0 : *pTestPos = Tell();
424 0 : return nLen;
425 : }
426 :
427 : // File format backward-compatible
428 : #ifdef STOR_NO_OPTIMIZE
429 : #define P_VER (sal_uInt8)0x00
430 : #else
431 : #define P_VER (sal_uInt8)0x01
432 : #endif
433 : #define P_VER_MASK (sal_uInt8)0x0F
434 : #define P_ID_0 (sal_uInt8)0x80
435 : #define P_OBJ (sal_uInt8)0x40
436 : #define P_DBGUTIL (sal_uInt8)0x20
437 : #define P_ID (sal_uInt8)0x10
438 : #ifdef STOR_NO_OPTIMIZE
439 : #define P_STD P_DBGUTIL
440 : #else
441 : #define P_STD 0
442 : #endif
443 :
444 56764 : static void WriteId
445 : (
446 : SvStream & rStm,
447 : sal_uInt8 nHdr,
448 : sal_uInt32 nId,
449 : sal_uInt16 nClassId
450 : )
451 : {
452 : #ifdef STOR_NO_OPTIMIZE
453 56764 : nHdr |= P_ID;
454 : #endif
455 56764 : nHdr |= P_VER;
456 56764 : if( nHdr & P_ID )
457 : {
458 56764 : if( (nHdr & P_OBJ) || nId != 0 )
459 : { // Id set only for pointers or DBGUTIL
460 56764 : rStm << (sal_uInt8)(nHdr);
461 56764 : SvPersistStream::WriteCompressed( rStm, nId );
462 : }
463 : else
464 : { // NULL Pointer
465 0 : rStm << (sal_uInt8)(nHdr | P_ID_0);
466 56764 : return;
467 : }
468 : }
469 : else
470 0 : rStm << nHdr;
471 :
472 56764 : if( (nHdr & P_DBGUTIL) || (nHdr & P_OBJ) )
473 : // Objects always have a class id
474 : // Pointers only for DBG_UTIL and != NULL
475 56764 : SvPersistStream::WriteCompressed( rStm, nClassId );
476 : }
477 :
478 0 : static void ReadId
479 : (
480 : SvStream & rStm,
481 : sal_uInt8 & nHdr,
482 : sal_uInt32 & nId,
483 : sal_uInt16 & nClassId
484 : )
485 : {
486 0 : nClassId = 0;
487 0 : rStm >> nHdr;
488 0 : if( nHdr & P_ID_0 )
489 0 : nId = 0;
490 : else
491 : {
492 0 : if( (nHdr & P_VER_MASK) == 0 )
493 : {
494 0 : if( (nHdr & P_DBGUTIL) || !(nHdr & P_OBJ) )
495 0 : nId = SvPersistStream::ReadCompressed( rStm );
496 : else
497 0 : nId = 0;
498 : }
499 0 : else if( nHdr & P_ID )
500 0 : nId = SvPersistStream::ReadCompressed( rStm );
501 :
502 0 : if( (nHdr & P_DBGUTIL) || (nHdr & P_OBJ) )
503 0 : nClassId = (sal_uInt16)SvPersistStream::ReadCompressed( rStm );
504 : }
505 0 : }
506 :
507 25366 : void SvPersistStream::WriteObj
508 : (
509 : sal_uInt8 nHdr,
510 : SvPersistBase * pObj
511 : )
512 : {
513 : #ifdef STOR_NO_OPTIMIZE
514 25366 : sal_uInt32 nObjPos = 0;
515 25366 : if( nHdr & P_DBGUTIL )
516 : // remember position for length value
517 25366 : nObjPos = WriteDummyLen();
518 : #endif
519 25366 : pObj->Save( *this );
520 : #ifdef STOR_NO_OPTIMIZE
521 25366 : if( nHdr & P_DBGUTIL )
522 25366 : WriteLen( nObjPos );
523 : #endif
524 25366 : }
525 :
526 56764 : SvPersistStream& SvPersistStream::WritePointer
527 : (
528 : SvPersistBase * pObj
529 : )
530 : {
531 56764 : sal_uInt8 nP = P_STD;
532 :
533 56764 : if( pObj )
534 : {
535 56764 : sal_uIntPtr nId = GetIndex( pObj );
536 56764 : if( nId )
537 31398 : nP |= P_ID;
538 : else
539 : {
540 25366 : nId = aPUIdx.Insert( pObj );
541 25366 : aPTable[ pObj ] = nId;
542 25366 : nP |= P_OBJ;
543 : }
544 56764 : WriteId( *this, nP, nId, pObj->GetClassId() );
545 56764 : if( nP & P_OBJ )
546 25366 : WriteObj( nP, pObj );
547 : }
548 : else
549 : { // NULL Pointer
550 0 : WriteId( *this, nP | P_ID, 0, 0 );
551 : }
552 56764 : return *this;
553 : }
554 :
555 0 : sal_uInt32 SvPersistStream::ReadObj
556 : (
557 : SvPersistBase * & rpObj,
558 : bool bRegister
559 : )
560 : {
561 : sal_uInt8 nHdr;
562 0 : sal_uInt32 nId = 0;
563 : sal_uInt16 nClassId;
564 :
565 0 : rpObj = NULL; // specification: 0 in case of error
566 0 : ReadId( *this, nHdr, nId, nClassId );
567 :
568 : // get version nummer through masking
569 0 : if( P_VER < (nHdr & P_VER_MASK) )
570 : {
571 0 : SetError( SVSTREAM_FILEFORMAT_ERROR );
572 : OSL_FAIL( "false version" );
573 : }
574 :
575 0 : if( !(nHdr & P_ID_0) && GetError() == SVSTREAM_OK )
576 : {
577 0 : if( P_OBJ & nHdr )
578 : { // read object, nId only set for P_DBGUTIL
579 : DBG_ASSERT( !(nHdr & P_DBGUTIL) || NULL == aPUIdx.Get( nId ),
580 : "object already exist" );
581 0 : SvCreateInstancePersist pFunc = rClassMgr.Get( nClassId );
582 :
583 0 : sal_uInt32 nObjLen(0), nObjPos(0);
584 0 : if( nHdr & P_DBGUTIL )
585 0 : nObjLen = ReadLen( &nObjPos );
586 0 : if( !pFunc )
587 : {
588 : #ifdef DBG_UTIL
589 : OStringBuffer aStr("no class with id: " );
590 : aStr.append(static_cast<sal_Int32>(nClassId));
591 : aStr.append(" registered");
592 : DBG_WARNING(aStr.getStr());
593 : #else
594 : (void)nObjLen;
595 : #endif
596 0 : SetError( ERRCODE_IO_NOFACTORY );
597 0 : return 0;
598 : }
599 0 : pFunc( &rpObj );
600 : // Save reference
601 0 : rpObj->AddRef();
602 :
603 0 : if( bRegister )
604 : {
605 : // insert into table
606 0 : sal_uIntPtr nNewId = aPUIdx.Insert( rpObj );
607 : // in order to restore state after saving
608 0 : aPTable[ rpObj ] = nNewId;
609 : DBG_ASSERT( !(nHdr & P_DBGUTIL) || nId == nNewId,
610 : "read write id conflict: not the same" );
611 : }
612 0 : rpObj->Load( *this );
613 : #ifdef DBG_UTIL
614 : if( nObjLen + nObjPos != Tell() )
615 : {
616 : OStringBuffer aStr("false object len: read = ");
617 : aStr.append(static_cast<sal_Int64>((long)(Tell() - nObjPos)));
618 : aStr.append(", should = ");
619 : aStr.append(static_cast<sal_Int32>(nObjLen));
620 : OSL_FAIL(aStr.getStr());
621 : }
622 : #endif
623 0 : rpObj->RestoreNoDelete();
624 0 : rpObj->ReleaseRef();
625 : }
626 : else
627 : {
628 0 : rpObj = GetObject( nId );
629 : DBG_ASSERT( rpObj != NULL, "object does not exist" );
630 : DBG_ASSERT( rpObj->GetClassId() == nClassId, "class mismatch" );
631 : }
632 : }
633 0 : return nId;
634 : }
635 :
636 0 : SvPersistStream& SvPersistStream::ReadPointer
637 : (
638 : SvPersistBase * & rpObj
639 : )
640 : {
641 0 : ReadObj( rpObj, true );
642 0 : return *this;
643 : }
644 :
645 56764 : SvPersistStream& operator <<
646 : (
647 : SvPersistStream & rStm,
648 : SvPersistBase * pObj
649 : )
650 : {
651 56764 : return rStm.WritePointer( pObj );
652 : }
653 :
654 0 : SvPersistStream& operator >>
655 : (
656 : SvPersistStream & rStm,
657 : SvPersistBase * & rpObj
658 : )
659 : {
660 0 : return rStm.ReadPointer( rpObj );
661 : }
662 :
663 0 : SvStream& operator <<
664 : (
665 : SvStream & rStm,
666 : SvPersistStream & rThis
667 : )
668 : {
669 0 : SvStream * pOldStm = rThis.GetStream();
670 0 : rThis.SetStream( &rStm );
671 :
672 0 : sal_uInt8 bTmp = 0;
673 0 : rThis << bTmp; // Version
674 0 : sal_uInt32 nCount = (sal_uInt32)rThis.aPUIdx.Count();
675 0 : rThis << nCount;
676 0 : sal_uIntPtr aIndex = rThis.aPUIdx.FirstIndex();
677 0 : for( sal_uInt32 i = 0; i < nCount; i++ )
678 : {
679 0 : SvPersistBase * pEle = rThis.aPUIdx.Get(aIndex);
680 0 : sal_uInt8 nP = P_OBJ | P_ID | P_STD;
681 0 : WriteId( rThis, nP, aIndex, pEle->GetClassId() );
682 0 : rThis.WriteObj( nP, pEle );
683 0 : aIndex = rThis.aPUIdx.NextIndex( aIndex );
684 : }
685 0 : rThis.SetStream( pOldStm );
686 0 : return rStm;
687 : }
688 :
689 0 : SvStream& operator >>
690 : (
691 : SvStream & rStm,
692 : SvPersistStream & rThis
693 : )
694 : {
695 0 : SvStream * pOldStm = rThis.GetStream();
696 0 : rThis.SetStream( &rStm );
697 :
698 : sal_uInt8 nVers;
699 0 : rThis >> nVers; // Version
700 0 : if( 0 == nVers )
701 : {
702 0 : sal_uInt32 nCount = 0;
703 0 : rThis >> nCount;
704 0 : for( sal_uInt32 i = 0; i < nCount; i++ )
705 : {
706 : SvPersistBase * pEle;
707 : // read, but don't insert into table
708 0 : sal_uIntPtr nId = rThis.ReadObj( pEle, false );
709 0 : if( rThis.GetError() )
710 0 : break;
711 :
712 : // Id of object is never modified
713 0 : rThis.aPUIdx.Insert( nId, pEle );
714 0 : rThis.aPTable[ pEle ] = nId;
715 : }
716 : }
717 : else
718 0 : rThis.SetError( SVSTREAM_FILEFORMAT_ERROR );
719 :
720 0 : rThis.SetStream( pOldStm );
721 0 : return rStm;
722 : }
723 :
724 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|