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