Branch data 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 : 2423 : 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 [ + - ]: 2423 : aAssocTable.insert(Map::value_type(nClassId, pFunc));
34 : 2423 : }
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 [ - + ]: 82370 : TYPEINIT0( SvRttiBase );
44 : :
45 : : // SvPersistBaseMemberList
46 : :
47 : : #define PERSIST_LIST_VER (sal_uInt8)0
48 : : #define PERSIST_LIST_DBGUTIL (sal_uInt8)0x80
49 : :
50 : 4394 : void TOOLS_DLLPUBLIC WritePersistListObjects(const SvPersistListWriteable& rList, SvPersistStream & rStm, bool bOnlyStreamed )
51 : : {
52 : : #ifdef STOR_NO_OPTIMIZE
53 : 4394 : rStm << (sal_uInt8)(PERSIST_LIST_VER | PERSIST_LIST_DBGUTIL);
54 : 4394 : sal_uInt32 nObjPos = rStm.WriteDummyLen();
55 : : #else
56 : : sal_uInt8 bTmp = PERSIST_LIST_VER;
57 : : rStm << bTmp;
58 : : #endif
59 : 4394 : sal_uInt32 nCountMember = rList.size();
60 : 4394 : sal_uIntPtr nCountPos = rStm.Tell();
61 : 4394 : sal_uInt32 nWriteCount = 0;
62 : 4394 : rStm << nCountMember;
63 : : // Don't change the list, as it causes side-effects while saving
64 [ + + ]: 64118 : for( sal_uIntPtr n = 0; n < nCountMember; n++ )
65 : : {
66 : 59724 : SvPersistBase * pObj = rList.GetPersistBase( n );
67 [ # # ][ + - ]: 59724 : if( !bOnlyStreamed || rStm.IsStreamed( pObj ) )
[ - + ]
68 : : { // Object should be stored
69 : 59724 : rStm << pObj;
70 : 59724 : nWriteCount++;
71 : : }
72 : : }
73 [ - + ]: 4394 : 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 : 4394 : rStm.WriteLen( nObjPos );
83 : : #endif
84 : 4394 : }
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 : 928 : 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 [ + - ][ + - ]: 928 : , nFlags( 0 )
143 : : {
144 : : DBG_ASSERT( nStartIdx != 0, "zero index not allowed" );
145 : 928 : bIsWritable = sal_True;
146 [ + + ]: 928 : if( pStm )
147 : : {
148 : 912 : SetVersion( pStm->GetVersion() );
149 [ + - ]: 912 : SetError( pStm->GetError() );
150 [ + - ]: 912 : SyncSvStream( pStm->Tell() );
151 : : }
152 : 928 : }
153 : :
154 : 928 : SvPersistStream::~SvPersistStream()
155 : : {
156 [ + - ]: 928 : SetStream( NULL );
157 [ - + ]: 928 : }
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 : 928 : void SvPersistStream::SetStream( SvStream * pStream )
168 : : {
169 [ + + ]: 928 : if( pStm != pStream )
170 : : {
171 [ + - ]: 912 : if( pStm )
172 : : {
173 : 912 : SyncSysStream();
174 : 912 : pStm->SetError( GetError() );
175 : : }
176 : 912 : pStm = pStream;
177 : : }
178 [ - + ]: 928 : if( pStm )
179 : : {
180 : 0 : SetVersion( pStm->GetVersion() );
181 : 0 : SetError( pStm->GetError() );
182 : 0 : SyncSvStream( pStm->Tell() );
183 : : }
184 : 928 : }
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 : 1389080 : sal_uIntPtr SvPersistStream::PutData( const void* pData, sal_uIntPtr nSize )
213 : : {
214 : : DBG_ASSERT( pStm, "stream not set" );
215 : 1389080 : sal_uIntPtr nRet = pStm->Write( pData, nSize );
216 : 1389080 : SetError( pStm->GetError() );
217 : 1389080 : return nRet;
218 : : }
219 : :
220 : 109180 : sal_uIntPtr SvPersistStream::SeekPos( sal_uIntPtr nPos )
221 : : {
222 : : DBG_ASSERT( pStm, "stream not set" );
223 : 109180 : sal_uIntPtr nRet = pStm->Seek( nPos );
224 : 109180 : SetError( pStm->GetError() );
225 : 109180 : return nRet;
226 : : }
227 : :
228 : 912 : void SvPersistStream::FlushData()
229 : : {
230 : 912 : }
231 : :
232 : 110652 : sal_uIntPtr SvPersistStream::GetIndex( SvPersistBase * pObj ) const
233 : : {
234 [ + - ]: 110652 : PersistBaseMap::const_iterator it = aPTable.find( pObj );
235 [ + + ]: 110652 : if( it == aPTable.end() )
236 : : {
237 [ - + ]: 49724 : if ( pRefStm )
238 [ # # ]: 0 : return pRefStm->GetIndex( pObj );
239 : : else
240 : 49724 : return 0;
241 : : }
242 : 110652 : 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 : 246836 : void SvPersistStream::WriteCompressed( SvStream & rStm, sal_uInt32 nVal )
325 : : {
326 : : #ifdef STOR_NO_OPTIMIZE
327 [ + + ]: 246836 : if( nVal < 0x80 )
328 : 143796 : rStm << (sal_uInt8)(LEN_1 | nVal);
329 [ + + ]: 103040 : else if( nVal < 0x4000 )
330 : : {
331 : 95420 : rStm << (sal_uInt8)(LEN_2 | (nVal >> 8));
332 : 95420 : rStm << (sal_uInt8)nVal;
333 : : }
334 [ + - ]: 7620 : else if( nVal < 0x20000000 )
335 : : {
336 : : // highest sal_uInt8
337 : 7620 : rStm << (sal_uInt8)(LEN_4 | (nVal >> 24));
338 : : // 2nd highest sal_uInt8
339 : 7620 : rStm << (sal_uInt8)(nVal >> 16);
340 : 7620 : rStm << (sal_uInt16)(nVal);
341 : : }
342 : : else
343 : : #endif
344 : : {
345 : 0 : rStm << (sal_uInt8)LEN_5;
346 : 0 : rStm << nVal;
347 : : }
348 : 246836 : }
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 : 54118 : sal_uInt32 SvPersistStream::WriteDummyLen()
368 : : {
369 : : #ifdef DBG_UTIL
370 : : sal_uInt32 nPos = Tell();
371 : : #endif
372 : 54118 : sal_uInt32 n0 = 0;
373 : 54118 : *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 : 54118 : 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 : 54118 : void SvPersistStream::WriteLen( sal_uInt32 nObjPos )
402 : : {
403 : 54118 : sal_uInt32 nPos = Tell();
404 : 54118 : sal_uInt32 nLen = nPos - nObjPos;
405 : : // Length in stream must be 4 Bytes
406 : 54118 : Seek( nObjPos - sizeof( sal_uInt32 ) );
407 : : // write length
408 : 54118 : *this << nLen;
409 : 54118 : Seek( nPos );
410 : 54118 : }
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 : 110652 : 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 : 110652 : nHdr |= P_ID;
455 : : #endif
456 : 110652 : nHdr |= P_VER;
457 [ + - ]: 110652 : if( nHdr & P_ID )
458 : : {
459 [ + + ][ + - ]: 110652 : if( (nHdr & P_OBJ) || nId != 0 )
460 : : { // Id set only for pointers or DBGUTIL
461 : 110652 : rStm << (sal_uInt8)(nHdr);
462 : 110652 : SvPersistStream::WriteCompressed( rStm, nId );
463 : : }
464 : : else
465 : : { // NULL Pointer
466 : 0 : rStm << (sal_uInt8)(nHdr | P_ID_0);
467 : 110652 : return;
468 : : }
469 : : }
470 : : else
471 : 0 : rStm << nHdr;
472 : :
473 [ - + ][ # # ]: 110652 : if( (nHdr & P_DBGUTIL) || (nHdr & P_OBJ) )
474 : : // Objects always have a class id
475 : : // Pointers only for DBG_UTIL and != NULL
476 : 110652 : 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 : 49724 : void SvPersistStream::WriteObj
509 : : (
510 : : sal_uInt8 nHdr,
511 : : SvPersistBase * pObj
512 : : )
513 : : {
514 : : #ifdef STOR_NO_OPTIMIZE
515 : 49724 : sal_uInt32 nObjPos = 0;
516 [ + - ]: 49724 : if( nHdr & P_DBGUTIL )
517 : : // remember position for length value
518 : 49724 : nObjPos = WriteDummyLen();
519 : : #endif
520 : 49724 : pObj->Save( *this );
521 : : #ifdef STOR_NO_OPTIMIZE
522 [ + - ]: 49724 : if( nHdr & P_DBGUTIL )
523 : 49724 : WriteLen( nObjPos );
524 : : #endif
525 : 49724 : }
526 : :
527 : 110652 : SvPersistStream& SvPersistStream::WritePointer
528 : : (
529 : : SvPersistBase * pObj
530 : : )
531 : : {
532 : 110652 : sal_uInt8 nP = P_STD;
533 : :
534 [ + - ]: 110652 : if( pObj )
535 : : {
536 : 110652 : sal_uIntPtr nId = GetIndex( pObj );
537 [ + + ]: 110652 : if( nId )
538 : 60928 : nP |= P_ID;
539 : : else
540 : : {
541 : 49724 : nId = aPUIdx.Insert( pObj );
542 : 49724 : aPTable[ pObj ] = nId;
543 : 49724 : nP |= P_OBJ;
544 : : }
545 : 110652 : WriteId( *this, nP, nId, pObj->GetClassId() );
546 [ + + ]: 110652 : if( nP & P_OBJ )
547 : 49724 : WriteObj( nP, pObj );
548 : : }
549 : : else
550 : : { // NULL Pointer
551 : 0 : WriteId( *this, nP | P_ID, 0, 0 );
552 : : }
553 : 110652 : 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 : 110652 : SvPersistStream& operator <<
649 : : (
650 : : SvPersistStream & rStm,
651 : : SvPersistBase * pObj
652 : : )
653 : : {
654 : 110652 : 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: */
|