calc: on editing invalidation of view with different zoom is wrong
[LibreOffice.git] / io / source / stm / odata.cxx
blob7d39a5835852865fa0e8614332b0d177061895c1
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <string.h>
21 #include <unordered_map>
22 #include <vector>
24 #include <cppuhelper/weak.hxx>
25 #include <cppuhelper/implbase.hxx>
26 #include <cppuhelper/supportsservice.hxx>
27 #include <osl/endian.h>
29 #include <com/sun/star/io/NotConnectedException.hpp>
30 #include <com/sun/star/io/XObjectInputStream.hpp>
31 #include <com/sun/star/io/XObjectOutputStream.hpp>
32 #include <com/sun/star/io/XActiveDataSource.hpp>
33 #include <com/sun/star/io/XActiveDataSink.hpp>
34 #include <com/sun/star/io/XMarkableStream.hpp>
35 #include <com/sun/star/io/XConnectable.hpp>
36 #include <com/sun/star/io/UnexpectedEOFException.hpp>
37 #include <com/sun/star/io/WrongFormatException.hpp>
38 #include <com/sun/star/lang/XServiceInfo.hpp>
39 #include <com/sun/star/uno/XComponentContext.hpp>
41 using namespace ::cppu;
42 using namespace ::osl;
43 using namespace ::std;
44 using namespace ::com::sun::star::io;
45 using namespace ::com::sun::star::uno;
46 using namespace ::com::sun::star::lang;
48 namespace io_stm {
50 namespace {
52 class ODataInputStream :
53 public WeakImplHelper <
54 XDataInputStream,
55 XActiveDataSink,
56 XConnectable,
57 XServiceInfo
60 public:
61 ODataInputStream( )
62 : m_bValidStream( false )
66 public: // XInputStream
67 virtual sal_Int32 SAL_CALL readBytes(Sequence< sal_Int8 >& aData, sal_Int32 nBytesToRead) override;
68 virtual sal_Int32 SAL_CALL readSomeBytes(Sequence< sal_Int8 >& aData, sal_Int32 nMaxBytesToRead) override;
69 virtual void SAL_CALL skipBytes(sal_Int32 nBytesToSkip) override;
70 virtual sal_Int32 SAL_CALL available() override;
71 virtual void SAL_CALL closeInput() override;
73 public: // XDataInputStream
74 virtual sal_Int8 SAL_CALL readBoolean() override;
75 virtual sal_Int8 SAL_CALL readByte() override;
76 virtual sal_Unicode SAL_CALL readChar() override;
77 virtual sal_Int16 SAL_CALL readShort() override;
78 virtual sal_Int32 SAL_CALL readLong() override;
79 virtual sal_Int64 SAL_CALL readHyper() override;
80 virtual float SAL_CALL readFloat() override;
81 virtual double SAL_CALL readDouble() override;
82 virtual OUString SAL_CALL readUTF() override;
85 public: // XActiveDataSink
86 virtual void SAL_CALL setInputStream(const Reference< XInputStream > & aStream) override;
87 virtual Reference< XInputStream > SAL_CALL getInputStream() override;
89 public: // XConnectable
90 virtual void SAL_CALL setPredecessor(const Reference < XConnectable >& aPredecessor) override;
91 virtual Reference < XConnectable > SAL_CALL getPredecessor() override;
92 virtual void SAL_CALL setSuccessor(const Reference < XConnectable >& aSuccessor) override;
93 virtual Reference < XConnectable > SAL_CALL getSuccessor() override ;
96 public: // XServiceInfo
97 OUString SAL_CALL getImplementationName() override;
98 Sequence< OUString > SAL_CALL getSupportedServiceNames() override;
99 sal_Bool SAL_CALL supportsService(const OUString& ServiceName) override;
101 protected:
103 Reference < XConnectable > m_pred;
104 Reference < XConnectable > m_succ;
105 Reference < XInputStream > m_input;
106 bool m_bValidStream;
111 // XInputStream
112 sal_Int32 ODataInputStream::readBytes(Sequence< sal_Int8 >& aData, sal_Int32 nBytesToRead)
114 if( !m_bValidStream )
116 throw NotConnectedException( );
118 sal_Int32 nRead = m_input->readBytes( aData , nBytesToRead );
119 return nRead;
122 sal_Int32 ODataInputStream::readSomeBytes(Sequence< sal_Int8 >& aData, sal_Int32 nMaxBytesToRead)
124 if( !m_bValidStream )
125 throw NotConnectedException( );
126 sal_Int32 nRead = m_input->readSomeBytes( aData , nMaxBytesToRead );
127 return nRead;
129 void ODataInputStream::skipBytes(sal_Int32 nBytesToSkip)
131 if( !m_bValidStream )
132 throw NotConnectedException( );
133 m_input->skipBytes( nBytesToSkip );
137 sal_Int32 ODataInputStream::available()
139 if( !m_bValidStream )
140 throw NotConnectedException( );
141 sal_Int32 nAvail = m_input->available( );
142 return nAvail;
145 void ODataInputStream::closeInput()
147 if( !m_bValidStream )
148 throw NotConnectedException( );
149 m_input->closeInput( );
150 setInputStream( Reference< XInputStream > () );
151 setPredecessor( Reference < XConnectable >() );
152 setSuccessor( Reference < XConnectable >() );
153 m_bValidStream = false;
157 //== XDataInputStream ===========================================
159 // XDataInputStream
160 sal_Int8 ODataInputStream::readBoolean()
162 return readByte();
165 sal_Int8 ODataInputStream::readByte()
167 Sequence<sal_Int8> aTmp(1);
168 if( 1 != readBytes( aTmp, 1 ) )
170 throw UnexpectedEOFException();
172 return aTmp.getConstArray()[0];
175 sal_Unicode ODataInputStream::readChar()
177 Sequence<sal_Int8> aTmp(2);
178 if( 2 != readBytes( aTmp, 2 ) )
180 throw UnexpectedEOFException();
183 const sal_uInt8 * pBytes = reinterpret_cast<const sal_uInt8 *>(aTmp.getConstArray());
184 return (static_cast<sal_Unicode>(pBytes[0]) << 8) + pBytes[1];
187 sal_Int16 ODataInputStream::readShort()
189 Sequence<sal_Int8> aTmp(2);
190 if( 2 != readBytes( aTmp, 2 ) )
192 throw UnexpectedEOFException();
195 const sal_uInt8 * pBytes = reinterpret_cast<const sal_uInt8 *>(aTmp.getConstArray());
196 return (static_cast<sal_Int16>(pBytes[0]) << 8) + pBytes[1];
200 sal_Int32 ODataInputStream::readLong()
202 Sequence<sal_Int8> aTmp(4);
203 if( 4 != readBytes( aTmp, 4 ) )
205 throw UnexpectedEOFException( );
208 const sal_uInt8 * pBytes = reinterpret_cast<const sal_uInt8 *>(aTmp.getConstArray());
209 return (static_cast<sal_Int32>(pBytes[0]) << 24) + (static_cast<sal_Int32>(pBytes[1]) << 16) + (static_cast<sal_Int32>(pBytes[2]) << 8) + pBytes[3];
213 sal_Int64 ODataInputStream::readHyper()
215 Sequence<sal_Int8> aTmp(8);
216 if( 8 != readBytes( aTmp, 8 ) )
218 throw UnexpectedEOFException( );
221 const sal_uInt8 * pBytes = reinterpret_cast<const sal_uInt8 *>(aTmp.getConstArray());
222 return
223 (static_cast<sal_Int64>(pBytes[0]) << 56) +
224 (static_cast<sal_Int64>(pBytes[1]) << 48) +
225 (static_cast<sal_Int64>(pBytes[2]) << 40) +
226 (static_cast<sal_Int64>(pBytes[3]) << 32) +
227 (static_cast<sal_Int64>(pBytes[4]) << 24) +
228 (static_cast<sal_Int64>(pBytes[5]) << 16) +
229 (static_cast<sal_Int64>(pBytes[6]) << 8) +
230 pBytes[7];
233 float ODataInputStream::readFloat()
235 union { float f; sal_uInt32 n; } a;
236 a.n = readLong();
237 return a.f;
240 double ODataInputStream::readDouble()
242 union { double d; struct { sal_uInt32 n1; sal_uInt32 n2; } ad; } a;
243 #if defined OSL_LITENDIAN
244 a.ad.n2 = readLong();
245 a.ad.n1 = readLong();
246 #else
247 a.ad.n1 = readLong();
248 a.ad.n2 = readLong();
249 #endif
250 return a.d;
253 OUString ODataInputStream::readUTF()
255 sal_uInt16 nShortLen = static_cast<sal_uInt16>(readShort());
256 sal_Int32 nUTFLen;
258 if( (sal_uInt16(0xffff)) == nShortLen )
260 // is interpreted as a sign, that string is longer than 64k
261 // incompatible to older XDataInputStream-routines, when strings are exactly 64k
262 nUTFLen = readLong();
264 else
266 nUTFLen = static_cast<sal_Int32>(nShortLen);
269 Sequence<sal_Unicode> aBuffer( nUTFLen );
270 sal_Unicode * pStr = aBuffer.getArray();
272 sal_Int32 nCount = 0;
273 sal_Int32 nStrLen = 0;
274 while( nCount < nUTFLen )
276 sal_uInt8 c = static_cast<sal_uInt8>(readByte());
277 sal_uInt8 char2, char3;
278 switch( c >> 4 )
280 case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7:
281 // 0xxxxxxx
282 nCount++;
283 pStr[nStrLen++] = c;
284 break;
286 case 12: case 13:
287 // 110x xxxx 10xx xxxx
288 nCount += 2;
289 if( nCount > nUTFLen )
291 throw WrongFormatException( );
294 char2 = static_cast<sal_uInt8>(readByte());
295 if( (char2 & 0xC0) != 0x80 )
297 throw WrongFormatException( );
300 pStr[nStrLen++] = (sal_Unicode(c & 0x1F) << 6) | (char2 & 0x3F);
301 break;
303 case 14:
304 // 1110 xxxx 10xx xxxx 10xx xxxx
305 nCount += 3;
306 if( nCount > nUTFLen )
308 throw WrongFormatException( );
311 char2 = static_cast<sal_uInt8>(readByte());
312 char3 = static_cast<sal_uInt8>(readByte());
314 if( ((char2 & 0xC0) != 0x80) || ((char3 & 0xC0) != 0x80) ) {
315 throw WrongFormatException( );
317 pStr[nStrLen++] = (sal_Unicode(c & 0x0F) << 12) |
318 (sal_Unicode(char2 & 0x3F) << 6) |
319 (char3 & 0x3F);
320 break;
322 default:
323 // 10xx xxxx, 1111 xxxx
324 throw WrongFormatException();
325 //throw new UTFDataFormatException();
328 return OUString( pStr, nStrLen );
332 // XActiveDataSource
333 void ODataInputStream::setInputStream(const Reference< XInputStream > & aStream)
336 if( m_input != aStream ) {
337 m_input = aStream;
339 Reference < XConnectable > pred( m_input , UNO_QUERY );
340 setPredecessor( pred );
343 m_bValidStream = m_input.is();
346 Reference< XInputStream > ODataInputStream::getInputStream()
348 return m_input;
352 // XDataSink
353 void ODataInputStream::setSuccessor( const Reference < XConnectable > &r )
355 /// if the references match, nothing needs to be done
356 if( m_succ != r ) {
357 /// store the reference for later use
358 m_succ = r;
360 if( m_succ.is() ) {
361 /// set this instance as the sink !
362 m_succ->setPredecessor( Reference< XConnectable > (
363 static_cast< XConnectable * >(this) ) );
368 Reference < XConnectable > ODataInputStream::getSuccessor()
370 return m_succ;
374 // XDataSource
375 void ODataInputStream::setPredecessor( const Reference < XConnectable > &r )
377 if( r != m_pred ) {
378 m_pred = r;
379 if( m_pred.is() ) {
380 m_pred->setSuccessor( Reference< XConnectable > (
381 static_cast< XConnectable * >(this) ) );
385 Reference < XConnectable > ODataInputStream::getPredecessor()
387 return m_pred;
390 // XServiceInfo
391 OUString ODataInputStream::getImplementationName()
393 return "com.sun.star.comp.io.stm.DataInputStream";
396 // XServiceInfo
397 sal_Bool ODataInputStream::supportsService(const OUString& ServiceName)
399 return cppu::supportsService(this, ServiceName);
402 // XServiceInfo
403 Sequence< OUString > ODataInputStream::getSupportedServiceNames()
405 return { "com.sun.star.io.DataInputStream" };
408 extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
409 io_ODataInputStream_get_implementation(
410 css::uno::XComponentContext* , css::uno::Sequence<css::uno::Any> const&)
412 return cppu::acquire(new ODataInputStream());
415 namespace {
417 class ODataOutputStream :
418 public WeakImplHelper <
419 XDataOutputStream,
420 XActiveDataSource,
421 XConnectable,
422 XServiceInfo >
424 public:
425 ODataOutputStream()
426 : m_bValidStream( false )
430 public: // XOutputStream
431 virtual void SAL_CALL writeBytes(const Sequence< sal_Int8 >& aData) override;
432 virtual void SAL_CALL flush() override;
433 virtual void SAL_CALL closeOutput() override;
435 public: // XDataOutputStream
436 virtual void SAL_CALL writeBoolean(sal_Bool Value) override;
437 virtual void SAL_CALL writeByte(sal_Int8 Value) override;
438 virtual void SAL_CALL writeChar(sal_Unicode Value) override;
439 virtual void SAL_CALL writeShort(sal_Int16 Value) override;
440 virtual void SAL_CALL writeLong(sal_Int32 Value) override;
441 virtual void SAL_CALL writeHyper(sal_Int64 Value) override;
442 virtual void SAL_CALL writeFloat(float Value) override;
443 virtual void SAL_CALL writeDouble(double Value) override;
444 virtual void SAL_CALL writeUTF(const OUString& Value) override;
446 public: // XActiveDataSource
447 virtual void SAL_CALL setOutputStream(const Reference< XOutputStream > & aStream) override;
448 virtual Reference < XOutputStream > SAL_CALL getOutputStream() override;
450 public: // XConnectable
451 virtual void SAL_CALL setPredecessor(const Reference < XConnectable >& aPredecessor) override;
452 virtual Reference < XConnectable > SAL_CALL getPredecessor() override;
453 virtual void SAL_CALL setSuccessor(const Reference < XConnectable >& aSuccessor) override;
454 virtual Reference < XConnectable > SAL_CALL getSuccessor() override;
456 public: // XServiceInfo
457 OUString SAL_CALL getImplementationName() override;
458 Sequence< OUString > SAL_CALL getSupportedServiceNames() override;
459 sal_Bool SAL_CALL supportsService(const OUString& ServiceName) override;
461 protected:
462 Reference < XConnectable > m_succ;
463 Reference < XConnectable > m_pred;
464 Reference< XOutputStream > m_output;
465 bool m_bValidStream;
470 // XOutputStream
471 void ODataOutputStream::writeBytes(const Sequence< sal_Int8 >& aData)
473 if( !m_bValidStream )
474 throw NotConnectedException( );
475 m_output->writeBytes( aData );
478 void ODataOutputStream::flush()
480 if( !m_bValidStream )
481 throw NotConnectedException();
482 m_output->flush();
486 void ODataOutputStream::closeOutput()
488 if( !m_bValidStream )
489 throw NotConnectedException();
490 m_output->closeOutput();
491 setOutputStream( Reference< XOutputStream > () );
492 setPredecessor( Reference < XConnectable >() );
493 setSuccessor( Reference < XConnectable >() );
496 // XDataOutputStream
497 void ODataOutputStream::writeBoolean(sal_Bool Value)
499 if( Value )
501 writeByte( 1 );
503 else
505 writeByte( 0 );
510 void ODataOutputStream::writeByte(sal_Int8 Value)
512 writeBytes( { Value } );
515 void ODataOutputStream::writeChar(sal_Unicode Value)
517 writeBytes( { sal_Int8(Value >> 8),
518 sal_Int8(Value) } );
522 void ODataOutputStream::writeShort(sal_Int16 Value)
524 writeBytes( { sal_Int8(Value >> 8),
525 sal_Int8(Value) } );
528 void ODataOutputStream::writeLong(sal_Int32 Value)
530 writeBytes( { sal_Int8(Value >> 24),
531 sal_Int8(Value >> 16),
532 sal_Int8(Value >> 8),
533 sal_Int8(Value) } );
536 void ODataOutputStream::writeHyper(sal_Int64 Value)
538 writeBytes( { sal_Int8(Value >> 56),
539 sal_Int8(Value >> 48),
540 sal_Int8(Value >> 40),
541 sal_Int8(Value >> 32),
542 sal_Int8(Value >> 24),
543 sal_Int8(Value >> 16),
544 sal_Int8(Value >> 8),
545 sal_Int8(Value) } );
549 void ODataOutputStream::writeFloat(float Value)
551 union { float f; sal_uInt32 n; } a;
552 a.f = Value;
553 writeLong( a.n );
556 void ODataOutputStream::writeDouble(double Value)
558 union { double d; struct { sal_uInt32 n1; sal_uInt32 n2; } ad; } a;
559 a.d = Value;
560 #if defined OSL_LITENDIAN
561 writeLong( a.ad.n2 );
562 writeLong( a.ad.n1 );
563 #else
564 writeLong( a.ad.n1 );
565 writeLong( a.ad.n2 );
566 #endif
569 void ODataOutputStream::writeUTF(const OUString& Value)
571 sal_Int32 nStrLen = Value.getLength();
572 const sal_Unicode * pStr = Value.getStr();
573 sal_Int32 nUTFLen = 0;
574 sal_Int32 i;
576 for( i = 0 ; i < nStrLen ; i++ )
578 sal_uInt16 c = pStr[i];
579 if( (c >= 0x0001) && (c <= 0x007F) )
581 nUTFLen++;
583 else if( c > 0x07FF )
585 nUTFLen += 3;
587 else
589 nUTFLen += 2;
594 // compatibility mode for older implementations, where it was not possible
595 // to write blocks bigger than 64 k. Note that there is a tradeoff. Blocks,
596 // that are exactly 64k long can not be read by older routines when written
597 // with these routines and the other way round !!!!!
598 if( nUTFLen >= 0xFFFF ) {
599 writeShort( sal_Int16(-1) );
600 writeLong( nUTFLen );
602 else {
603 writeShort( static_cast<sal_uInt16>(nUTFLen) );
605 for( i = 0 ; i < nStrLen ; i++ )
607 sal_uInt16 c = pStr[i];
608 if( (c >= 0x0001) && (c <= 0x007F) )
610 writeByte(sal_Int8(c));
612 else if( c > 0x07FF )
614 writeByte(sal_Int8(0xE0 | ((c >> 12) & 0x0F)));
615 writeByte(sal_Int8(0x80 | ((c >> 6) & 0x3F)));
616 writeByte(sal_Int8(0x80 | ((c >> 0) & 0x3F)));
618 else
620 writeByte(sal_Int8(0xC0 | ((c >> 6) & 0x1F)));
621 writeByte(sal_Int8(0x80 | ((c >> 0) & 0x3F)));
626 // XActiveDataSource
627 void ODataOutputStream::setOutputStream(const Reference< XOutputStream > & aStream)
629 if( m_output != aStream ) {
630 m_output = aStream;
631 m_bValidStream = m_output.is();
633 Reference < XConnectable > succ( m_output , UNO_QUERY );
634 setSuccessor( succ );
638 Reference< XOutputStream > ODataOutputStream::getOutputStream()
640 return m_output;
644 // XDataSink
645 void ODataOutputStream::setSuccessor( const Reference < XConnectable > &r )
647 /// if the references match, nothing needs to be done
648 if( m_succ != r )
650 /// store the reference for later use
651 m_succ = r;
653 if( m_succ.is() )
655 /// set this instance as the sink !
656 m_succ->setPredecessor( Reference < XConnectable > (
657 static_cast< XConnectable * >(this) ));
661 Reference < XConnectable > ODataOutputStream::getSuccessor()
663 return m_succ;
667 // XDataSource
668 void ODataOutputStream::setPredecessor( const Reference < XConnectable > &r )
670 if( r != m_pred ) {
671 m_pred = r;
672 if( m_pred.is() ) {
673 m_pred->setSuccessor( Reference< XConnectable > (
674 static_cast< XConnectable * >(this) ));
678 Reference < XConnectable > ODataOutputStream::getPredecessor()
680 return m_pred;
684 // XServiceInfo
685 OUString ODataOutputStream::getImplementationName()
687 return "com.sun.star.comp.io.stm.DataOutputStream";
690 // XServiceInfo
691 sal_Bool ODataOutputStream::supportsService(const OUString& ServiceName)
693 return cppu::supportsService(this, ServiceName);
696 // XServiceInfo
697 Sequence< OUString > ODataOutputStream::getSupportedServiceNames()
699 return { "com.sun.star.io.DataOutputStream" };
702 extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
703 io_ODataOutputStream_get_implementation(
704 css::uno::XComponentContext* , css::uno::Sequence<css::uno::Any> const&)
706 return cppu::acquire(new ODataOutputStream());
709 namespace {
711 struct equalObjectContainer_Impl
713 bool operator()(const Reference< XInterface > & s1,
714 const Reference< XInterface > & s2) const
716 return s1 == s2;
721 struct hashObjectContainer_Impl
723 size_t operator()(const Reference< XInterface > & xRef) const
725 return reinterpret_cast<size_t>(xRef.get());
731 typedef std::unordered_map
733 Reference< XInterface >,
734 sal_Int32,
735 hashObjectContainer_Impl,
736 equalObjectContainer_Impl
737 > ObjectContainer_Impl;
739 namespace {
741 class OObjectOutputStream:
742 public ImplInheritanceHelper<
743 ODataOutputStream, /* parent */
744 XObjectOutputStream, XMarkableStream >
746 public:
747 OObjectOutputStream()
748 : m_nMaxId(0) ,
749 m_bValidMarkable(false)
753 public:
754 // XOutputStream
755 virtual void SAL_CALL writeBytes(const Sequence< sal_Int8 >& aData) override
756 { ODataOutputStream::writeBytes( aData ); }
758 virtual void SAL_CALL flush() override
759 { ODataOutputStream::flush(); }
761 virtual void SAL_CALL closeOutput() override
762 { ODataOutputStream::closeOutput(); }
764 public:
765 // XDataOutputStream
766 virtual void SAL_CALL writeBoolean(sal_Bool Value) override
767 { ODataOutputStream::writeBoolean( Value ); }
768 virtual void SAL_CALL writeByte(sal_Int8 Value) override
769 { ODataOutputStream::writeByte( Value ); }
770 virtual void SAL_CALL writeChar(sal_Unicode Value) override
771 { ODataOutputStream::writeChar( Value ); }
772 virtual void SAL_CALL writeShort(sal_Int16 Value) override
773 { ODataOutputStream::writeShort( Value ); }
774 virtual void SAL_CALL writeLong(sal_Int32 Value) override
775 { ODataOutputStream::writeLong( Value ); }
776 virtual void SAL_CALL writeHyper(sal_Int64 Value) override
777 { ODataOutputStream::writeHyper( Value ); }
778 virtual void SAL_CALL writeFloat(float Value) override
779 { ODataOutputStream::writeFloat( Value ); }
780 virtual void SAL_CALL writeDouble(double Value) override
781 { ODataOutputStream::writeDouble( Value ); }
782 virtual void SAL_CALL writeUTF(const OUString& Value) override
783 { ODataOutputStream::writeUTF( Value );}
785 // XObjectOutputStream
786 virtual void SAL_CALL writeObject( const Reference< XPersistObject > & r ) override;
788 public: // XMarkableStream
789 virtual sal_Int32 SAL_CALL createMark() override;
790 virtual void SAL_CALL deleteMark(sal_Int32 Mark) override;
791 virtual void SAL_CALL jumpToMark(sal_Int32 nMark) override;
792 virtual void SAL_CALL jumpToFurthest() override;
793 virtual sal_Int32 SAL_CALL offsetToMark(sal_Int32 nMark) override;
795 public: // XServiceInfo
796 OUString SAL_CALL getImplementationName() override;
797 Sequence< OUString > SAL_CALL getSupportedServiceNames() override;
798 sal_Bool SAL_CALL supportsService(const OUString& ServiceName) override;
800 private:
801 void connectToMarkable();
802 private:
803 ObjectContainer_Impl m_mapObject;
804 sal_Int32 m_nMaxId;
805 Reference< XMarkableStream > m_rMarkable;
806 bool m_bValidMarkable;
811 void OObjectOutputStream::writeObject( const Reference< XPersistObject > & xPObj )
814 connectToMarkable();
815 bool bWriteObj = false;
816 // create Mark to write length of info
817 sal_uInt32 nInfoLenMark = m_rMarkable->createMark();
819 // length of the info data (is later rewritten)
820 OObjectOutputStream::writeShort( 0 );
822 // write the object identifier
823 if( xPObj.is() )
825 Reference< XInterface > rX( xPObj , UNO_QUERY );
827 ObjectContainer_Impl::const_iterator aIt
828 = m_mapObject.find( rX );
829 if( aIt == m_mapObject.end() )
831 // insert new object in hash table
832 m_mapObject[ rX ] = ++m_nMaxId;
833 ODataOutputStream::writeLong( m_nMaxId );
834 ODataOutputStream::writeUTF( xPObj->getServiceName() );
835 bWriteObj = true;
837 else
839 ODataOutputStream::writeLong( (*aIt).second );
840 ODataOutputStream::writeUTF( OUString() );
843 else
845 ODataOutputStream::writeLong( 0 );
846 ODataOutputStream::writeUTF( OUString() );
849 sal_uInt32 nObjLenMark = m_rMarkable->createMark();
850 ODataOutputStream::writeLong( 0 );
852 sal_Int32 nInfoLen = m_rMarkable->offsetToMark( nInfoLenMark );
853 m_rMarkable->jumpToMark( nInfoLenMark );
854 // write length of the info data
855 ODataOutputStream::writeShort( static_cast<sal_Int16>(nInfoLen) );
856 // jump to the end of the stream
857 m_rMarkable->jumpToFurthest();
859 if( bWriteObj )
860 xPObj->write( Reference< XObjectOutputStream > (
861 static_cast< XObjectOutputStream * >(this) ) );
863 sal_Int32 nObjLen = m_rMarkable->offsetToMark( nObjLenMark ) -4;
864 m_rMarkable->jumpToMark( nObjLenMark );
865 // write length of the info data
866 ODataOutputStream::writeLong( nObjLen );
867 // jump to the end of the stream
868 m_rMarkable->jumpToFurthest();
870 m_rMarkable->deleteMark( nObjLenMark );
871 m_rMarkable->deleteMark( nInfoLenMark );
875 void OObjectOutputStream::connectToMarkable()
877 if( m_bValidMarkable )
878 return;
880 if( ! m_bValidStream )
881 throw NotConnectedException();
883 // find the markable stream !
884 Reference< XInterface > rTry(m_output);
885 while( true ) {
886 if( ! rTry.is() )
888 throw NotConnectedException();
890 Reference < XMarkableStream > markable( rTry , UNO_QUERY );
891 if( markable.is() )
893 m_rMarkable = markable;
894 break;
896 Reference < XActiveDataSource > source( rTry , UNO_QUERY );
897 rTry = source;
899 m_bValidMarkable = true;
903 sal_Int32 OObjectOutputStream::createMark()
905 connectToMarkable(); // throws an exception, if a markable is not connected !
907 return m_rMarkable->createMark();
910 void OObjectOutputStream::deleteMark(sal_Int32 Mark)
912 if( ! m_bValidMarkable )
914 throw NotConnectedException();
916 m_rMarkable->deleteMark( Mark );
919 void OObjectOutputStream::jumpToMark(sal_Int32 nMark)
921 if( ! m_bValidMarkable )
923 throw NotConnectedException();
925 m_rMarkable->jumpToMark( nMark );
929 void OObjectOutputStream::jumpToFurthest()
931 connectToMarkable();
932 m_rMarkable->jumpToFurthest();
935 sal_Int32 OObjectOutputStream::offsetToMark(sal_Int32 nMark)
937 if( ! m_bValidMarkable )
939 throw NotConnectedException();
941 return m_rMarkable->offsetToMark( nMark );
944 // XServiceInfo
945 OUString OObjectOutputStream::getImplementationName()
947 return "com.sun.star.comp.io.stm.ObjectOutputStream";
950 // XServiceInfo
951 sal_Bool OObjectOutputStream::supportsService(const OUString& ServiceName)
953 return cppu::supportsService(this, ServiceName);
956 // XServiceInfo
957 Sequence< OUString > OObjectOutputStream::getSupportedServiceNames()
959 return { "com.sun.star.io.ObjectOutputStream" };
962 extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
963 io_OObjectOutputStream_get_implementation(
964 css::uno::XComponentContext* , css::uno::Sequence<css::uno::Any> const&)
966 return cppu::acquire(new OObjectOutputStream());
969 namespace {
971 class OObjectInputStream:
972 public ImplInheritanceHelper<
973 ODataInputStream, /* parent */
974 XObjectInputStream, XMarkableStream >
976 public:
977 explicit OObjectInputStream( const Reference < XComponentContext > &r)
978 : m_rSMgr( r->getServiceManager() )
979 , m_rCxt( r )
980 , m_bValidMarkable(false)
984 public: // XInputStream
985 virtual sal_Int32 SAL_CALL readBytes(Sequence< sal_Int8 >& aData, sal_Int32 nBytesToRead) override
986 { return ODataInputStream::readBytes( aData , nBytesToRead ); }
988 virtual sal_Int32 SAL_CALL readSomeBytes(Sequence< sal_Int8 >& aData, sal_Int32 nMaxBytesToRead) override
989 { return ODataInputStream::readSomeBytes( aData, nMaxBytesToRead ); }
991 virtual void SAL_CALL skipBytes(sal_Int32 nBytesToSkip) override
992 { ODataInputStream::skipBytes( nBytesToSkip ); }
994 virtual sal_Int32 SAL_CALL available() override
995 { return ODataInputStream::available(); }
997 virtual void SAL_CALL closeInput() override
998 { ODataInputStream::closeInput(); }
1000 public: // XDataInputStream
1001 virtual sal_Int8 SAL_CALL readBoolean() override
1002 { return ODataInputStream::readBoolean(); }
1003 virtual sal_Int8 SAL_CALL readByte() override
1004 { return ODataInputStream::readByte(); }
1005 virtual sal_Unicode SAL_CALL readChar() override
1006 { return ODataInputStream::readChar(); }
1007 virtual sal_Int16 SAL_CALL readShort() override
1008 { return ODataInputStream::readShort(); }
1009 virtual sal_Int32 SAL_CALL readLong() override
1010 { return ODataInputStream::readLong(); }
1011 virtual sal_Int64 SAL_CALL readHyper() override
1012 { return ODataInputStream::readHyper(); }
1013 virtual float SAL_CALL readFloat() override
1014 { return ODataInputStream::readFloat(); }
1015 virtual double SAL_CALL readDouble() override
1016 { return ODataInputStream::readDouble(); }
1017 virtual OUString SAL_CALL readUTF() override
1018 { return ODataInputStream::readUTF(); }
1020 public: // XObjectInputStream
1021 virtual Reference< XPersistObject > SAL_CALL readObject( ) override;
1023 public: // XMarkableStream
1024 virtual sal_Int32 SAL_CALL createMark() override;
1025 virtual void SAL_CALL deleteMark(sal_Int32 Mark) override;
1026 virtual void SAL_CALL jumpToMark(sal_Int32 nMark) override;
1027 virtual void SAL_CALL jumpToFurthest() override;
1028 virtual sal_Int32 SAL_CALL offsetToMark(sal_Int32 nMark) override;
1030 public: // XServiceInfo
1031 OUString SAL_CALL getImplementationName() override;
1032 Sequence< OUString > SAL_CALL getSupportedServiceNames() override;
1033 sal_Bool SAL_CALL supportsService(const OUString& ServiceName) override;
1035 private:
1036 void connectToMarkable();
1037 private:
1038 Reference < XMultiComponentFactory > m_rSMgr;
1039 Reference < XComponentContext > m_rCxt;
1040 bool m_bValidMarkable;
1041 Reference < XMarkableStream > m_rMarkable;
1042 vector < Reference< XPersistObject > > m_aPersistVector;
1048 Reference< XPersistObject > OObjectInputStream::readObject()
1050 // check if chain contains a XMarkableStream
1051 connectToMarkable();
1053 Reference< XPersistObject > xLoadedObj;
1055 // create Mark to skip newer versions
1056 sal_uInt32 nMark = m_rMarkable->createMark();
1057 // length of the data
1058 sal_Int32 nLen = static_cast<sal_uInt16>(ODataInputStream::readShort());
1059 if( nLen < 0xc )
1061 throw WrongFormatException();
1064 // read the object identifier
1065 sal_uInt32 nId = readLong();
1067 // the name of the persist model
1068 // MM ???
1069 OUString aName = readUTF();
1071 // Read the length of the object
1072 sal_Int32 nObjLen = readLong();
1073 if( 0 == nId && 0 != nObjLen )
1075 throw WrongFormatException();
1078 // skip data of new version
1079 skipBytes( nLen - m_rMarkable->offsetToMark( nMark ) );
1081 bool bLoadSuccessful = true;
1082 if( nId )
1084 if( !aName.isEmpty() )
1086 // load the object
1087 Reference< XInterface > x = m_rSMgr->createInstanceWithContext( aName, m_rCxt );
1088 xLoadedObj.set( x, UNO_QUERY );
1089 if( xLoadedObj.is() )
1091 sal_uInt32 nSize = m_aPersistVector.size();
1092 if( nSize <= nId )
1094 // grow to the right size
1095 Reference< XPersistObject > xEmpty;
1096 m_aPersistVector.insert( m_aPersistVector.end(), nId - nSize + 1, xEmpty );
1099 m_aPersistVector[nId] = xLoadedObj;
1100 xLoadedObj->read( Reference< XObjectInputStream >(
1101 static_cast< XObjectInputStream * >(this) ) );
1103 else
1105 // no service with this name could be instantiated
1106 bLoadSuccessful = false;
1109 else {
1110 if (nId >= m_aPersistVector.size())
1112 // id unknown, load failure !
1113 bLoadSuccessful = false;
1115 else
1117 // Object has already been read,
1118 xLoadedObj = m_aPersistVector[nId];
1123 // skip to the position behind the object
1124 skipBytes( nObjLen + nLen - m_rMarkable->offsetToMark( nMark ) );
1125 m_rMarkable->deleteMark( nMark );
1127 if( ! bLoadSuccessful )
1129 throw WrongFormatException();
1131 return xLoadedObj;
1135 void OObjectInputStream::connectToMarkable()
1137 if( m_bValidMarkable ) return;
1139 if( ! m_bValidStream )
1141 throw NotConnectedException( );
1144 // find the markable stream !
1145 Reference< XInterface > rTry(m_input);
1146 while( true ) {
1147 if( ! rTry.is() )
1149 throw NotConnectedException( );
1151 Reference< XMarkableStream > markable( rTry , UNO_QUERY );
1152 if( markable.is() )
1154 m_rMarkable = markable;
1155 break;
1157 Reference < XActiveDataSink > sink( rTry , UNO_QUERY );
1158 rTry = sink;
1160 m_bValidMarkable = true;
1163 sal_Int32 OObjectInputStream::createMark()
1165 connectToMarkable(); // throws an exception, if a markable is not connected !
1167 return m_rMarkable->createMark();
1170 void OObjectInputStream::deleteMark(sal_Int32 Mark)
1172 if( ! m_bValidMarkable )
1174 throw NotConnectedException();
1176 m_rMarkable->deleteMark( Mark );
1179 void OObjectInputStream::jumpToMark(sal_Int32 nMark)
1181 if( ! m_bValidMarkable )
1183 throw NotConnectedException();
1185 m_rMarkable->jumpToMark( nMark );
1187 void OObjectInputStream::jumpToFurthest()
1189 connectToMarkable();
1190 m_rMarkable->jumpToFurthest();
1193 sal_Int32 OObjectInputStream::offsetToMark(sal_Int32 nMark)
1195 if( ! m_bValidMarkable )
1197 throw NotConnectedException();
1199 return m_rMarkable->offsetToMark( nMark );
1202 // XServiceInfo
1203 OUString OObjectInputStream::getImplementationName()
1205 return "com.sun.star.comp.io.stm.ObjectInputStream";
1208 // XServiceInfo
1209 sal_Bool OObjectInputStream::supportsService(const OUString& ServiceName)
1211 return cppu::supportsService(this, ServiceName);
1214 // XServiceInfo
1215 Sequence< OUString > OObjectInputStream::getSupportedServiceNames()
1217 return { "com.sun.star.io.ObjectInputStream" };
1220 extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
1221 io_OObjectInputStream_get_implementation(
1222 css::uno::XComponentContext* context, css::uno::Sequence<css::uno::Any> const&)
1224 return cppu::acquire(new OObjectInputStream(context));
1230 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */