1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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 .
21 #include <unordered_map>
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 #include <services.hxx>
52 class ODataInputStream
:
53 public WeakImplHelper
<
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
;
103 Reference
< XConnectable
> m_pred
;
104 Reference
< XConnectable
> m_succ
;
105 Reference
< XInputStream
> m_input
;
110 sal_Int32
ODataInputStream::readBytes(Sequence
< sal_Int8
>& aData
, sal_Int32 nBytesToRead
)
112 if( !m_bValidStream
)
114 throw NotConnectedException( );
116 sal_Int32 nRead
= m_input
->readBytes( aData
, nBytesToRead
);
120 sal_Int32
ODataInputStream::readSomeBytes(Sequence
< sal_Int8
>& aData
, sal_Int32 nMaxBytesToRead
)
122 if( !m_bValidStream
)
123 throw NotConnectedException( );
124 sal_Int32 nRead
= m_input
->readSomeBytes( aData
, nMaxBytesToRead
);
127 void ODataInputStream::skipBytes(sal_Int32 nBytesToSkip
)
129 if( !m_bValidStream
)
130 throw NotConnectedException( );
131 m_input
->skipBytes( nBytesToSkip
);
135 sal_Int32
ODataInputStream::available()
137 if( !m_bValidStream
)
138 throw NotConnectedException( );
139 sal_Int32 nAvail
= m_input
->available( );
143 void ODataInputStream::closeInput()
145 if( !m_bValidStream
)
146 throw NotConnectedException( );
147 m_input
->closeInput( );
148 setInputStream( Reference
< XInputStream
> () );
149 setPredecessor( Reference
< XConnectable
>() );
150 setSuccessor( Reference
< XConnectable
>() );
151 m_bValidStream
= false;
155 //== XDataInputStream ===========================================
158 sal_Int8
ODataInputStream::readBoolean()
163 sal_Int8
ODataInputStream::readByte()
165 Sequence
<sal_Int8
> aTmp(1);
166 if( 1 != readBytes( aTmp
, 1 ) )
168 throw UnexpectedEOFException();
170 return aTmp
.getConstArray()[0];
173 sal_Unicode
ODataInputStream::readChar()
175 Sequence
<sal_Int8
> aTmp(2);
176 if( 2 != readBytes( aTmp
, 2 ) )
178 throw UnexpectedEOFException();
181 const sal_uInt8
* pBytes
= reinterpret_cast<const sal_uInt8
*>(aTmp
.getConstArray());
182 return (static_cast<sal_Unicode
>(pBytes
[0]) << 8) + pBytes
[1];
185 sal_Int16
ODataInputStream::readShort()
187 Sequence
<sal_Int8
> aTmp(2);
188 if( 2 != readBytes( aTmp
, 2 ) )
190 throw UnexpectedEOFException();
193 const sal_uInt8
* pBytes
= reinterpret_cast<const sal_uInt8
*>(aTmp
.getConstArray());
194 return (static_cast<sal_Int16
>(pBytes
[0]) << 8) + pBytes
[1];
198 sal_Int32
ODataInputStream::readLong()
200 Sequence
<sal_Int8
> aTmp(4);
201 if( 4 != readBytes( aTmp
, 4 ) )
203 throw UnexpectedEOFException( );
206 const sal_uInt8
* pBytes
= reinterpret_cast<const sal_uInt8
*>(aTmp
.getConstArray());
207 return (static_cast<sal_Int32
>(pBytes
[0]) << 24) + (static_cast<sal_Int32
>(pBytes
[1]) << 16) + (static_cast<sal_Int32
>(pBytes
[2]) << 8) + pBytes
[3];
211 sal_Int64
ODataInputStream::readHyper()
213 Sequence
<sal_Int8
> aTmp(8);
214 if( 8 != readBytes( aTmp
, 8 ) )
216 throw UnexpectedEOFException( );
219 const sal_uInt8
* pBytes
= reinterpret_cast<const sal_uInt8
*>(aTmp
.getConstArray());
221 (static_cast<sal_Int64
>(pBytes
[0]) << 56) +
222 (static_cast<sal_Int64
>(pBytes
[1]) << 48) +
223 (static_cast<sal_Int64
>(pBytes
[2]) << 40) +
224 (static_cast<sal_Int64
>(pBytes
[3]) << 32) +
225 (static_cast<sal_Int64
>(pBytes
[4]) << 24) +
226 (static_cast<sal_Int64
>(pBytes
[5]) << 16) +
227 (static_cast<sal_Int64
>(pBytes
[6]) << 8) +
231 float ODataInputStream::readFloat()
233 union { float f
; sal_uInt32 n
; } a
;
238 double ODataInputStream::readDouble()
240 union { double d
; struct { sal_uInt32 n1
; sal_uInt32 n2
; } ad
; } a
;
241 #if defined OSL_LITENDIAN
242 a
.ad
.n2
= readLong();
243 a
.ad
.n1
= readLong();
245 a
.ad
.n1
= readLong();
246 a
.ad
.n2
= readLong();
251 OUString
ODataInputStream::readUTF()
253 sal_uInt16 nShortLen
= static_cast<sal_uInt16
>(readShort());
256 if( (sal_uInt16(0xffff)) == nShortLen
)
258 // is interpreted as a sign, that string is longer than 64k
259 // incompatible to older XDataInputStream-routines, when strings are exactly 64k
260 nUTFLen
= readLong();
264 nUTFLen
= static_cast<sal_Int32
>(nShortLen
);
267 Sequence
<sal_Unicode
> aBuffer( nUTFLen
);
268 sal_Unicode
* pStr
= aBuffer
.getArray();
270 sal_Int32 nCount
= 0;
271 sal_Int32 nStrLen
= 0;
272 while( nCount
< nUTFLen
)
274 sal_uInt8 c
= static_cast<sal_uInt8
>(readByte());
275 sal_uInt8 char2
, char3
;
278 case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7:
285 // 110x xxxx 10xx xxxx
287 if( nCount
> nUTFLen
)
289 throw WrongFormatException( );
292 char2
= static_cast<sal_uInt8
>(readByte());
293 if( (char2
& 0xC0) != 0x80 )
295 throw WrongFormatException( );
298 pStr
[nStrLen
++] = (sal_Unicode(c
& 0x1F) << 6) | (char2
& 0x3F);
302 // 1110 xxxx 10xx xxxx 10xx xxxx
304 if( nCount
> nUTFLen
)
306 throw WrongFormatException( );
309 char2
= static_cast<sal_uInt8
>(readByte());
310 char3
= static_cast<sal_uInt8
>(readByte());
312 if( ((char2
& 0xC0) != 0x80) || ((char3
& 0xC0) != 0x80) ) {
313 throw WrongFormatException( );
315 pStr
[nStrLen
++] = (sal_Unicode(c
& 0x0F) << 12) |
316 (sal_Unicode(char2
& 0x3F) << 6) |
321 // 10xx xxxx, 1111 xxxx
322 throw WrongFormatException();
323 //throw new UTFDataFormatException();
326 return OUString( pStr
, nStrLen
);
331 void ODataInputStream::setInputStream(const Reference
< XInputStream
> & aStream
)
334 if( m_input
!= aStream
) {
337 Reference
< XConnectable
> pred( m_input
, UNO_QUERY
);
338 setPredecessor( pred
);
341 m_bValidStream
= m_input
.is();
344 Reference
< XInputStream
> ODataInputStream::getInputStream()
351 void ODataInputStream::setSuccessor( const Reference
< XConnectable
> &r
)
353 /// if the references match, nothing needs to be done
355 /// store the reference for later use
359 /// set this instance as the sink !
360 m_succ
->setPredecessor( Reference
< XConnectable
> (
361 static_cast< XConnectable
* >(this) ) );
366 Reference
< XConnectable
> ODataInputStream::getSuccessor()
373 void ODataInputStream::setPredecessor( const Reference
< XConnectable
> &r
)
378 m_pred
->setSuccessor( Reference
< XConnectable
> (
379 static_cast< XConnectable
* >(this) ) );
383 Reference
< XConnectable
> ODataInputStream::getPredecessor()
389 OUString
ODataInputStream::getImplementationName()
391 return ODataInputStream_getImplementationName();
395 sal_Bool
ODataInputStream::supportsService(const OUString
& ServiceName
)
397 return cppu::supportsService(this, ServiceName
);
401 Sequence
< OUString
> ODataInputStream::getSupportedServiceNames()
403 return ODataInputStream_getSupportedServiceNames();
408 * registration information
413 Reference
< XInterface
> ODataInputStream_CreateInstance(
414 SAL_UNUSED_PARAMETER
const Reference
< XComponentContext
> & )
416 ODataInputStream
*p
= new ODataInputStream
;
417 return Reference
< XInterface
> ( static_cast<OWeakObject
*>(p
) );
420 OUString
ODataInputStream_getImplementationName()
422 return "com.sun.star.comp.io.stm.DataInputStream";
425 Sequence
<OUString
> ODataInputStream_getSupportedServiceNames()
427 Sequence
<OUString
> aRet
{ "com.sun.star.io.DataInputStream" };
432 class ODataOutputStream
:
433 public WeakImplHelper
<
441 : m_bValidStream( false )
445 public: // XOutputStream
446 virtual void SAL_CALL
writeBytes(const Sequence
< sal_Int8
>& aData
) override
;
447 virtual void SAL_CALL
flush() override
;
448 virtual void SAL_CALL
closeOutput() override
;
450 public: // XDataOutputStream
451 virtual void SAL_CALL
writeBoolean(sal_Bool Value
) override
;
452 virtual void SAL_CALL
writeByte(sal_Int8 Value
) override
;
453 virtual void SAL_CALL
writeChar(sal_Unicode Value
) override
;
454 virtual void SAL_CALL
writeShort(sal_Int16 Value
) override
;
455 virtual void SAL_CALL
writeLong(sal_Int32 Value
) override
;
456 virtual void SAL_CALL
writeHyper(sal_Int64 Value
) override
;
457 virtual void SAL_CALL
writeFloat(float Value
) override
;
458 virtual void SAL_CALL
writeDouble(double Value
) override
;
459 virtual void SAL_CALL
writeUTF(const OUString
& Value
) override
;
461 public: // XActiveDataSource
462 virtual void SAL_CALL
setOutputStream(const Reference
< XOutputStream
> & aStream
) override
;
463 virtual Reference
< XOutputStream
> SAL_CALL
getOutputStream() override
;
465 public: // XConnectable
466 virtual void SAL_CALL
setPredecessor(const Reference
< XConnectable
>& aPredecessor
) override
;
467 virtual Reference
< XConnectable
> SAL_CALL
getPredecessor() override
;
468 virtual void SAL_CALL
setSuccessor(const Reference
< XConnectable
>& aSuccessor
) override
;
469 virtual Reference
< XConnectable
> SAL_CALL
getSuccessor() override
;
471 public: // XServiceInfo
472 OUString SAL_CALL
getImplementationName() override
;
473 Sequence
< OUString
> SAL_CALL
getSupportedServiceNames() override
;
474 sal_Bool SAL_CALL
supportsService(const OUString
& ServiceName
) override
;
477 Reference
< XConnectable
> m_succ
;
478 Reference
< XConnectable
> m_pred
;
479 Reference
< XOutputStream
> m_output
;
484 void ODataOutputStream::writeBytes(const Sequence
< sal_Int8
>& aData
)
486 if( !m_bValidStream
)
487 throw NotConnectedException( );
488 m_output
->writeBytes( aData
);
491 void ODataOutputStream::flush()
493 if( !m_bValidStream
)
494 throw NotConnectedException();
499 void ODataOutputStream::closeOutput()
501 if( !m_bValidStream
)
502 throw NotConnectedException();
503 m_output
->closeOutput();
504 setOutputStream( Reference
< XOutputStream
> () );
505 setPredecessor( Reference
< XConnectable
>() );
506 setSuccessor( Reference
< XConnectable
>() );
510 void ODataOutputStream::writeBoolean(sal_Bool Value
)
523 void ODataOutputStream::writeByte(sal_Int8 Value
)
525 writeBytes( { Value
} );
528 void ODataOutputStream::writeChar(sal_Unicode Value
)
530 writeBytes( { sal_Int8(Value
>> 8),
535 void ODataOutputStream::writeShort(sal_Int16 Value
)
537 writeBytes( { sal_Int8(Value
>> 8),
541 void ODataOutputStream::writeLong(sal_Int32 Value
)
543 writeBytes( { sal_Int8(Value
>> 24),
544 sal_Int8(Value
>> 16),
545 sal_Int8(Value
>> 8),
549 void ODataOutputStream::writeHyper(sal_Int64 Value
)
551 writeBytes( { sal_Int8(Value
>> 56),
552 sal_Int8(Value
>> 48),
553 sal_Int8(Value
>> 40),
554 sal_Int8(Value
>> 32),
555 sal_Int8(Value
>> 24),
556 sal_Int8(Value
>> 16),
557 sal_Int8(Value
>> 8),
562 void ODataOutputStream::writeFloat(float Value
)
564 union { float f
; sal_uInt32 n
; } a
;
569 void ODataOutputStream::writeDouble(double Value
)
571 union { double d
; struct { sal_uInt32 n1
; sal_uInt32 n2
; } ad
; } a
;
573 #if defined OSL_LITENDIAN
574 writeLong( a
.ad
.n2
);
575 writeLong( a
.ad
.n1
);
577 writeLong( a
.ad
.n1
);
578 writeLong( a
.ad
.n2
);
582 void ODataOutputStream::writeUTF(const OUString
& Value
)
584 sal_Int32 nStrLen
= Value
.getLength();
585 const sal_Unicode
* pStr
= Value
.getStr();
586 sal_Int32 nUTFLen
= 0;
589 for( i
= 0 ; i
< nStrLen
; i
++ )
591 sal_uInt16 c
= pStr
[i
];
592 if( (c
>= 0x0001) && (c
<= 0x007F) )
596 else if( c
> 0x07FF )
607 // compatibility mode for older implementations, where it was not possible
608 // to write blocks bigger than 64 k. Note that there is a tradeoff. Blocks,
609 // that are exactly 64k long can not be read by older routines when written
610 // with these routines and the other way round !!!!!
611 if( nUTFLen
>= 0xFFFF ) {
612 writeShort( sal_Int16(-1) );
613 writeLong( nUTFLen
);
616 writeShort( static_cast<sal_uInt16
>(nUTFLen
) );
618 for( i
= 0 ; i
< nStrLen
; i
++ )
620 sal_uInt16 c
= pStr
[i
];
621 if( (c
>= 0x0001) && (c
<= 0x007F) )
623 writeByte(sal_Int8(c
));
625 else if( c
> 0x07FF )
627 writeByte(sal_Int8(0xE0 | ((c
>> 12) & 0x0F)));
628 writeByte(sal_Int8(0x80 | ((c
>> 6) & 0x3F)));
629 writeByte(sal_Int8(0x80 | ((c
>> 0) & 0x3F)));
633 writeByte(sal_Int8(0xC0 | ((c
>> 6) & 0x1F)));
634 writeByte(sal_Int8(0x80 | ((c
>> 0) & 0x3F)));
640 void ODataOutputStream::setOutputStream(const Reference
< XOutputStream
> & aStream
)
642 if( m_output
!= aStream
) {
644 m_bValidStream
= m_output
.is();
646 Reference
< XConnectable
> succ( m_output
, UNO_QUERY
);
647 setSuccessor( succ
);
651 Reference
< XOutputStream
> ODataOutputStream::getOutputStream()
658 void ODataOutputStream::setSuccessor( const Reference
< XConnectable
> &r
)
660 /// if the references match, nothing needs to be done
663 /// store the reference for later use
668 /// set this instance as the sink !
669 m_succ
->setPredecessor( Reference
< XConnectable
> (
670 static_cast< XConnectable
* >(this) ));
674 Reference
< XConnectable
> ODataOutputStream::getSuccessor()
681 void ODataOutputStream::setPredecessor( const Reference
< XConnectable
> &r
)
686 m_pred
->setSuccessor( Reference
< XConnectable
> (
687 static_cast< XConnectable
* >(this) ));
691 Reference
< XConnectable
> ODataOutputStream::getPredecessor()
698 OUString
ODataOutputStream::getImplementationName()
700 return ODataOutputStream_getImplementationName();
704 sal_Bool
ODataOutputStream::supportsService(const OUString
& ServiceName
)
706 return cppu::supportsService(this, ServiceName
);
710 Sequence
< OUString
> ODataOutputStream::getSupportedServiceNames()
712 return ODataOutputStream_getSupportedServiceNames();
715 Reference
< XInterface
> ODataOutputStream_CreateInstance(
716 SAL_UNUSED_PARAMETER
const Reference
< XComponentContext
> & )
718 ODataOutputStream
*p
= new ODataOutputStream
;
719 Reference
< XInterface
> xService
= *p
;
724 OUString
ODataOutputStream_getImplementationName()
726 return "com.sun.star.comp.io.stm.DataOutputStream";
729 Sequence
<OUString
> ODataOutputStream_getSupportedServiceNames()
731 Sequence
<OUString
> aRet
{ "com.sun.star.io.DataOutputStream" };
736 struct equalObjectContainer_Impl
738 bool operator()(const Reference
< XInterface
> & s1
,
739 const Reference
< XInterface
> & s2
) const
746 struct hashObjectContainer_Impl
748 size_t operator()(const Reference
< XInterface
> & xRef
) const
750 return reinterpret_cast<size_t>(xRef
.get());
754 typedef std::unordered_map
756 Reference
< XInterface
>,
758 hashObjectContainer_Impl
,
759 equalObjectContainer_Impl
760 > ObjectContainer_Impl
;
762 class OObjectOutputStream
:
763 public ImplInheritanceHelper
<
764 ODataOutputStream
, /* parent */
765 XObjectOutputStream
, XMarkableStream
>
768 OObjectOutputStream()
770 m_bValidMarkable(false)
776 virtual void SAL_CALL
writeBytes(const Sequence
< sal_Int8
>& aData
) override
777 { ODataOutputStream::writeBytes( aData
); }
779 virtual void SAL_CALL
flush() override
780 { ODataOutputStream::flush(); }
782 virtual void SAL_CALL
closeOutput() override
783 { ODataOutputStream::closeOutput(); }
787 virtual void SAL_CALL
writeBoolean(sal_Bool Value
) override
788 { ODataOutputStream::writeBoolean( Value
); }
789 virtual void SAL_CALL
writeByte(sal_Int8 Value
) override
790 { ODataOutputStream::writeByte( Value
); }
791 virtual void SAL_CALL
writeChar(sal_Unicode Value
) override
792 { ODataOutputStream::writeChar( Value
); }
793 virtual void SAL_CALL
writeShort(sal_Int16 Value
) override
794 { ODataOutputStream::writeShort( Value
); }
795 virtual void SAL_CALL
writeLong(sal_Int32 Value
) override
796 { ODataOutputStream::writeLong( Value
); }
797 virtual void SAL_CALL
writeHyper(sal_Int64 Value
) override
798 { ODataOutputStream::writeHyper( Value
); }
799 virtual void SAL_CALL
writeFloat(float Value
) override
800 { ODataOutputStream::writeFloat( Value
); }
801 virtual void SAL_CALL
writeDouble(double Value
) override
802 { ODataOutputStream::writeDouble( Value
); }
803 virtual void SAL_CALL
writeUTF(const OUString
& Value
) override
804 { ODataOutputStream::writeUTF( Value
);}
806 // XObjectOutputStream
807 virtual void SAL_CALL
writeObject( const Reference
< XPersistObject
> & r
) override
;
809 public: // XMarkableStream
810 virtual sal_Int32 SAL_CALL
createMark() override
;
811 virtual void SAL_CALL
deleteMark(sal_Int32 Mark
) override
;
812 virtual void SAL_CALL
jumpToMark(sal_Int32 nMark
) override
;
813 virtual void SAL_CALL
jumpToFurthest() override
;
814 virtual sal_Int32 SAL_CALL
offsetToMark(sal_Int32 nMark
) override
;
816 public: // XServiceInfo
817 OUString SAL_CALL
getImplementationName() override
;
818 Sequence
< OUString
> SAL_CALL
getSupportedServiceNames() override
;
819 sal_Bool SAL_CALL
supportsService(const OUString
& ServiceName
) override
;
822 void connectToMarkable();
824 ObjectContainer_Impl m_mapObject
;
826 Reference
< XMarkableStream
> m_rMarkable
;
827 bool m_bValidMarkable
;
830 void OObjectOutputStream::writeObject( const Reference
< XPersistObject
> & xPObj
)
834 bool bWriteObj
= false;
835 // create Mark to write length of info
836 sal_uInt32 nInfoLenMark
= m_rMarkable
->createMark();
838 // length of the info data (is later rewritten)
839 OObjectOutputStream::writeShort( 0 );
841 // write the object identifier
844 Reference
< XInterface
> rX( xPObj
, UNO_QUERY
);
846 ObjectContainer_Impl::const_iterator aIt
847 = m_mapObject
.find( rX
);
848 if( aIt
== m_mapObject
.end() )
850 // insert new object in hash table
851 m_mapObject
[ rX
] = ++m_nMaxId
;
852 ODataOutputStream::writeLong( m_nMaxId
);
853 ODataOutputStream::writeUTF( xPObj
->getServiceName() );
858 ODataOutputStream::writeLong( (*aIt
).second
);
859 ODataOutputStream::writeUTF( OUString() );
864 ODataOutputStream::writeLong( 0 );
865 ODataOutputStream::writeUTF( OUString() );
868 sal_uInt32 nObjLenMark
= m_rMarkable
->createMark();
869 ODataOutputStream::writeLong( 0 );
871 sal_Int32 nInfoLen
= m_rMarkable
->offsetToMark( nInfoLenMark
);
872 m_rMarkable
->jumpToMark( nInfoLenMark
);
873 // write length of the info data
874 ODataOutputStream::writeShort( static_cast<sal_Int16
>(nInfoLen
) );
875 // jump to the end of the stream
876 m_rMarkable
->jumpToFurthest();
879 xPObj
->write( Reference
< XObjectOutputStream
> (
880 static_cast< XObjectOutputStream
* >(this) ) );
882 sal_Int32 nObjLen
= m_rMarkable
->offsetToMark( nObjLenMark
) -4;
883 m_rMarkable
->jumpToMark( nObjLenMark
);
884 // write length of the info data
885 ODataOutputStream::writeLong( nObjLen
);
886 // jump to the end of the stream
887 m_rMarkable
->jumpToFurthest();
889 m_rMarkable
->deleteMark( nObjLenMark
);
890 m_rMarkable
->deleteMark( nInfoLenMark
);
894 void OObjectOutputStream::connectToMarkable()
896 if( ! m_bValidMarkable
) {
897 if( ! m_bValidStream
)
899 throw NotConnectedException();
902 // find the markable stream !
903 Reference
< XInterface
> rTry(m_output
);
907 throw NotConnectedException();
909 Reference
< XMarkableStream
> markable( rTry
, UNO_QUERY
);
912 m_rMarkable
= markable
;
915 Reference
< XActiveDataSource
> source( rTry
, UNO_QUERY
);
918 m_bValidMarkable
= true;
923 sal_Int32
OObjectOutputStream::createMark()
925 connectToMarkable(); // throws an exception, if a markable is not connected !
927 return m_rMarkable
->createMark();
930 void OObjectOutputStream::deleteMark(sal_Int32 Mark
)
932 if( ! m_bValidMarkable
)
934 throw NotConnectedException();
936 m_rMarkable
->deleteMark( Mark
);
939 void OObjectOutputStream::jumpToMark(sal_Int32 nMark
)
941 if( ! m_bValidMarkable
)
943 throw NotConnectedException();
945 m_rMarkable
->jumpToMark( nMark
);
949 void OObjectOutputStream::jumpToFurthest()
952 m_rMarkable
->jumpToFurthest();
955 sal_Int32
OObjectOutputStream::offsetToMark(sal_Int32 nMark
)
957 if( ! m_bValidMarkable
)
959 throw NotConnectedException();
961 return m_rMarkable
->offsetToMark( nMark
);
965 Reference
< XInterface
> OObjectOutputStream_CreateInstance(
966 SAL_UNUSED_PARAMETER
const Reference
< XComponentContext
> & )
968 OObjectOutputStream
*p
= new OObjectOutputStream
;
969 return Reference
< XInterface
> ( static_cast< OWeakObject
* >(p
) );
972 OUString
OObjectOutputStream_getImplementationName()
974 return "com.sun.star.comp.io.stm.ObjectOutputStream";
977 Sequence
<OUString
> OObjectOutputStream_getSupportedServiceNames()
979 Sequence
<OUString
> aRet
{ "com.sun.star.io.ObjectOutputStream" };
984 OUString
OObjectOutputStream::getImplementationName()
986 return OObjectOutputStream_getImplementationName();
990 sal_Bool
OObjectOutputStream::supportsService(const OUString
& ServiceName
)
992 return cppu::supportsService(this, ServiceName
);
996 Sequence
< OUString
> OObjectOutputStream::getSupportedServiceNames()
998 return OObjectOutputStream_getSupportedServiceNames();
1001 class OObjectInputStream
:
1002 public ImplInheritanceHelper
<
1003 ODataInputStream
, /* parent */
1004 XObjectInputStream
, XMarkableStream
>
1007 explicit OObjectInputStream( const Reference
< XComponentContext
> &r
)
1008 : m_rSMgr( r
->getServiceManager() )
1010 , m_bValidMarkable(false)
1014 public: // XInputStream
1015 virtual sal_Int32 SAL_CALL
readBytes(Sequence
< sal_Int8
>& aData
, sal_Int32 nBytesToRead
) override
1016 { return ODataInputStream::readBytes( aData
, nBytesToRead
); }
1018 virtual sal_Int32 SAL_CALL
readSomeBytes(Sequence
< sal_Int8
>& aData
, sal_Int32 nMaxBytesToRead
) override
1019 { return ODataInputStream::readSomeBytes( aData
, nMaxBytesToRead
); }
1021 virtual void SAL_CALL
skipBytes(sal_Int32 nBytesToSkip
) override
1022 { ODataInputStream::skipBytes( nBytesToSkip
); }
1024 virtual sal_Int32 SAL_CALL
available() override
1025 { return ODataInputStream::available(); }
1027 virtual void SAL_CALL
closeInput() override
1028 { ODataInputStream::closeInput(); }
1030 public: // XDataInputStream
1031 virtual sal_Int8 SAL_CALL
readBoolean() override
1032 { return ODataInputStream::readBoolean(); }
1033 virtual sal_Int8 SAL_CALL
readByte() override
1034 { return ODataInputStream::readByte(); }
1035 virtual sal_Unicode SAL_CALL
readChar() override
1036 { return ODataInputStream::readChar(); }
1037 virtual sal_Int16 SAL_CALL
readShort() override
1038 { return ODataInputStream::readShort(); }
1039 virtual sal_Int32 SAL_CALL
readLong() override
1040 { return ODataInputStream::readLong(); }
1041 virtual sal_Int64 SAL_CALL
readHyper() override
1042 { return ODataInputStream::readHyper(); }
1043 virtual float SAL_CALL
readFloat() override
1044 { return ODataInputStream::readFloat(); }
1045 virtual double SAL_CALL
readDouble() override
1046 { return ODataInputStream::readDouble(); }
1047 virtual OUString SAL_CALL
readUTF() override
1048 { return ODataInputStream::readUTF(); }
1050 public: // XObjectInputStream
1051 virtual Reference
< XPersistObject
> SAL_CALL
readObject( ) override
;
1053 public: // XMarkableStream
1054 virtual sal_Int32 SAL_CALL
createMark() override
;
1055 virtual void SAL_CALL
deleteMark(sal_Int32 Mark
) override
;
1056 virtual void SAL_CALL
jumpToMark(sal_Int32 nMark
) override
;
1057 virtual void SAL_CALL
jumpToFurthest() override
;
1058 virtual sal_Int32 SAL_CALL
offsetToMark(sal_Int32 nMark
) override
;
1060 public: // XServiceInfo
1061 OUString SAL_CALL
getImplementationName() override
;
1062 Sequence
< OUString
> SAL_CALL
getSupportedServiceNames() override
;
1063 sal_Bool SAL_CALL
supportsService(const OUString
& ServiceName
) override
;
1066 void connectToMarkable();
1068 Reference
< XMultiComponentFactory
> m_rSMgr
;
1069 Reference
< XComponentContext
> m_rCxt
;
1070 bool m_bValidMarkable
;
1071 Reference
< XMarkableStream
> m_rMarkable
;
1072 vector
< Reference
< XPersistObject
> > m_aPersistVector
;
1076 Reference
< XPersistObject
> OObjectInputStream::readObject()
1078 // check if chain contains a XMarkableStream
1079 connectToMarkable();
1081 Reference
< XPersistObject
> xLoadedObj
;
1083 // create Mark to skip newer versions
1084 sal_uInt32 nMark
= m_rMarkable
->createMark();
1085 // length of the data
1086 sal_Int32 nLen
= static_cast<sal_uInt16
>(ODataInputStream::readShort());
1089 throw WrongFormatException();
1092 // read the object identifier
1093 sal_uInt32 nId
= readLong();
1095 // the name of the persist model
1097 OUString aName
= readUTF();
1099 // Read the length of the object
1100 sal_Int32 nObjLen
= readLong();
1101 if( 0 == nId
&& 0 != nObjLen
)
1103 throw WrongFormatException();
1106 // skip data of new version
1107 skipBytes( nLen
- m_rMarkable
->offsetToMark( nMark
) );
1109 bool bLoadSuccessful
= true;
1112 if( !aName
.isEmpty() )
1115 Reference
< XInterface
> x
= m_rSMgr
->createInstanceWithContext( aName
, m_rCxt
);
1116 xLoadedObj
.set( x
, UNO_QUERY
);
1117 if( xLoadedObj
.is() )
1119 sal_uInt32 nSize
= m_aPersistVector
.size();
1122 // grow to the right size
1123 Reference
< XPersistObject
> xEmpty
;
1124 m_aPersistVector
.insert( m_aPersistVector
.end(), static_cast<long>(nId
- nSize
+ 1), xEmpty
);
1127 m_aPersistVector
[nId
] = xLoadedObj
;
1128 xLoadedObj
->read( Reference
< XObjectInputStream
>(
1129 static_cast< XObjectInputStream
* >(this) ) );
1133 // no service with this name could be instantiated
1134 bLoadSuccessful
= false;
1138 if (nId
>= m_aPersistVector
.size())
1140 // id unknown, load failure !
1141 bLoadSuccessful
= false;
1145 // Object has already been read,
1146 xLoadedObj
= m_aPersistVector
[nId
];
1151 // skip to the position behind the object
1152 skipBytes( nObjLen
+ nLen
- m_rMarkable
->offsetToMark( nMark
) );
1153 m_rMarkable
->deleteMark( nMark
);
1155 if( ! bLoadSuccessful
)
1157 throw WrongFormatException();
1163 void OObjectInputStream::connectToMarkable()
1165 if( ! m_bValidMarkable
) {
1166 if( ! m_bValidStream
)
1168 throw NotConnectedException( );
1171 // find the markable stream !
1172 Reference
< XInterface
> rTry(m_input
);
1176 throw NotConnectedException( );
1178 Reference
< XMarkableStream
> markable( rTry
, UNO_QUERY
);
1181 m_rMarkable
= markable
;
1184 Reference
< XActiveDataSink
> sink( rTry
, UNO_QUERY
);
1187 m_bValidMarkable
= true;
1191 sal_Int32
OObjectInputStream::createMark()
1193 connectToMarkable(); // throws an exception, if a markable is not connected !
1195 return m_rMarkable
->createMark();
1198 void OObjectInputStream::deleteMark(sal_Int32 Mark
)
1200 if( ! m_bValidMarkable
)
1202 throw NotConnectedException();
1204 m_rMarkable
->deleteMark( Mark
);
1207 void OObjectInputStream::jumpToMark(sal_Int32 nMark
)
1209 if( ! m_bValidMarkable
)
1211 throw NotConnectedException();
1213 m_rMarkable
->jumpToMark( nMark
);
1215 void OObjectInputStream::jumpToFurthest()
1217 connectToMarkable();
1218 m_rMarkable
->jumpToFurthest();
1221 sal_Int32
OObjectInputStream::offsetToMark(sal_Int32 nMark
)
1223 if( ! m_bValidMarkable
)
1225 throw NotConnectedException();
1227 return m_rMarkable
->offsetToMark( nMark
);
1231 OUString
OObjectInputStream::getImplementationName()
1233 return OObjectInputStream_getImplementationName();
1237 sal_Bool
OObjectInputStream::supportsService(const OUString
& ServiceName
)
1239 return cppu::supportsService(this, ServiceName
);
1243 Sequence
< OUString
> OObjectInputStream::getSupportedServiceNames()
1245 return OObjectInputStream_getSupportedServiceNames();
1248 Reference
< XInterface
> OObjectInputStream_CreateInstance( const Reference
< XComponentContext
> & rCtx
)
1250 OObjectInputStream
*p
= new OObjectInputStream( rCtx
);
1251 return Reference
< XInterface
> ( static_cast< OWeakObject
* >(p
) );
1254 OUString
OObjectInputStream_getImplementationName()
1256 return "com.sun.star.comp.io.stm.ObjectInputStream";
1259 Sequence
<OUString
> OObjectInputStream_getSupportedServiceNames()
1261 Sequence
<OUString
> aRet
{ "com.sun.star.io.ObjectInputStream" };
1267 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */