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 ::com::sun::star::io
;
44 using namespace ::com::sun::star::uno
;
45 using namespace ::com::sun::star::lang
;
51 class ODataInputStream
:
52 public WeakImplHelper
<
61 : m_bValidStream( false )
65 public: // XInputStream
66 virtual sal_Int32 SAL_CALL
readBytes(Sequence
< sal_Int8
>& aData
, sal_Int32 nBytesToRead
) override
;
67 virtual sal_Int32 SAL_CALL
readSomeBytes(Sequence
< sal_Int8
>& aData
, sal_Int32 nMaxBytesToRead
) override
;
68 virtual void SAL_CALL
skipBytes(sal_Int32 nBytesToSkip
) override
;
69 virtual sal_Int32 SAL_CALL
available() override
;
70 virtual void SAL_CALL
closeInput() override
;
72 public: // XDataInputStream
73 virtual sal_Int8 SAL_CALL
readBoolean() override
;
74 virtual sal_Int8 SAL_CALL
readByte() override
;
75 virtual sal_Unicode SAL_CALL
readChar() override
;
76 virtual sal_Int16 SAL_CALL
readShort() override
;
77 virtual sal_Int32 SAL_CALL
readLong() override
;
78 virtual sal_Int64 SAL_CALL
readHyper() override
;
79 virtual float SAL_CALL
readFloat() override
;
80 virtual double SAL_CALL
readDouble() override
;
81 virtual OUString SAL_CALL
readUTF() override
;
84 public: // XActiveDataSink
85 virtual void SAL_CALL
setInputStream(const Reference
< XInputStream
> & aStream
) override
;
86 virtual Reference
< XInputStream
> SAL_CALL
getInputStream() override
;
88 public: // XConnectable
89 virtual void SAL_CALL
setPredecessor(const Reference
< XConnectable
>& aPredecessor
) override
;
90 virtual Reference
< XConnectable
> SAL_CALL
getPredecessor() override
;
91 virtual void SAL_CALL
setSuccessor(const Reference
< XConnectable
>& aSuccessor
) override
;
92 virtual Reference
< XConnectable
> SAL_CALL
getSuccessor() override
;
95 public: // XServiceInfo
96 OUString SAL_CALL
getImplementationName() override
;
97 Sequence
< OUString
> SAL_CALL
getSupportedServiceNames() override
;
98 sal_Bool SAL_CALL
supportsService(const OUString
& ServiceName
) override
;
102 Reference
< XConnectable
> m_pred
;
103 Reference
< XConnectable
> m_succ
;
104 Reference
< XInputStream
> m_input
;
111 sal_Int32
ODataInputStream::readBytes(Sequence
< sal_Int8
>& aData
, sal_Int32 nBytesToRead
)
113 if( !m_bValidStream
)
115 throw NotConnectedException( );
117 sal_Int32 nRead
= m_input
->readBytes( aData
, nBytesToRead
);
121 sal_Int32
ODataInputStream::readSomeBytes(Sequence
< sal_Int8
>& aData
, sal_Int32 nMaxBytesToRead
)
123 if( !m_bValidStream
)
124 throw NotConnectedException( );
125 sal_Int32 nRead
= m_input
->readSomeBytes( aData
, nMaxBytesToRead
);
128 void ODataInputStream::skipBytes(sal_Int32 nBytesToSkip
)
130 if( !m_bValidStream
)
131 throw NotConnectedException( );
132 m_input
->skipBytes( nBytesToSkip
);
136 sal_Int32
ODataInputStream::available()
138 if( !m_bValidStream
)
139 throw NotConnectedException( );
140 sal_Int32 nAvail
= m_input
->available( );
144 void ODataInputStream::closeInput()
146 if( !m_bValidStream
)
147 throw NotConnectedException( );
148 m_input
->closeInput( );
149 setInputStream( Reference
< XInputStream
> () );
150 setPredecessor( Reference
< XConnectable
>() );
151 setSuccessor( Reference
< XConnectable
>() );
152 m_bValidStream
= false;
156 //== XDataInputStream ===========================================
159 sal_Int8
ODataInputStream::readBoolean()
164 sal_Int8
ODataInputStream::readByte()
166 Sequence
<sal_Int8
> aTmp(1);
167 if( 1 != readBytes( aTmp
, 1 ) )
169 throw UnexpectedEOFException();
171 return aTmp
.getConstArray()[0];
174 sal_Unicode
ODataInputStream::readChar()
176 Sequence
<sal_Int8
> aTmp(2);
177 if( 2 != readBytes( aTmp
, 2 ) )
179 throw UnexpectedEOFException();
182 const sal_uInt8
* pBytes
= reinterpret_cast<const sal_uInt8
*>(aTmp
.getConstArray());
183 return (static_cast<sal_Unicode
>(pBytes
[0]) << 8) + pBytes
[1];
186 sal_Int16
ODataInputStream::readShort()
188 Sequence
<sal_Int8
> aTmp(2);
189 if( 2 != readBytes( aTmp
, 2 ) )
191 throw UnexpectedEOFException();
194 const sal_uInt8
* pBytes
= reinterpret_cast<const sal_uInt8
*>(aTmp
.getConstArray());
195 return (static_cast<sal_Int16
>(pBytes
[0]) << 8) + pBytes
[1];
199 sal_Int32
ODataInputStream::readLong()
201 Sequence
<sal_Int8
> aTmp(4);
202 if( 4 != readBytes( aTmp
, 4 ) )
204 throw UnexpectedEOFException( );
207 const sal_uInt8
* pBytes
= reinterpret_cast<const sal_uInt8
*>(aTmp
.getConstArray());
208 return (static_cast<sal_Int32
>(pBytes
[0]) << 24) + (static_cast<sal_Int32
>(pBytes
[1]) << 16) + (static_cast<sal_Int32
>(pBytes
[2]) << 8) + pBytes
[3];
212 sal_Int64
ODataInputStream::readHyper()
214 Sequence
<sal_Int8
> aTmp(8);
215 if( 8 != readBytes( aTmp
, 8 ) )
217 throw UnexpectedEOFException( );
220 const sal_uInt8
* pBytes
= reinterpret_cast<const sal_uInt8
*>(aTmp
.getConstArray());
222 (static_cast<sal_Int64
>(pBytes
[0]) << 56) +
223 (static_cast<sal_Int64
>(pBytes
[1]) << 48) +
224 (static_cast<sal_Int64
>(pBytes
[2]) << 40) +
225 (static_cast<sal_Int64
>(pBytes
[3]) << 32) +
226 (static_cast<sal_Int64
>(pBytes
[4]) << 24) +
227 (static_cast<sal_Int64
>(pBytes
[5]) << 16) +
228 (static_cast<sal_Int64
>(pBytes
[6]) << 8) +
232 float ODataInputStream::readFloat()
234 union { float f
; sal_uInt32 n
; } a
;
239 double ODataInputStream::readDouble()
241 union { double d
; struct { sal_uInt32 n1
; sal_uInt32 n2
; } ad
; } a
;
242 #if defined OSL_LITENDIAN
243 a
.ad
.n2
= readLong();
244 a
.ad
.n1
= readLong();
246 a
.ad
.n1
= readLong();
247 a
.ad
.n2
= readLong();
252 OUString
ODataInputStream::readUTF()
254 sal_uInt16 nShortLen
= static_cast<sal_uInt16
>(readShort());
257 if( (sal_uInt16(0xffff)) == nShortLen
)
259 // is interpreted as a sign, that string is longer than 64k
260 // incompatible to older XDataInputStream-routines, when strings are exactly 64k
261 nUTFLen
= readLong();
265 nUTFLen
= static_cast<sal_Int32
>(nShortLen
);
268 Sequence
<sal_Unicode
> aBuffer( nUTFLen
);
269 sal_Unicode
* pStr
= aBuffer
.getArray();
271 sal_Int32 nCount
= 0;
272 sal_Int32 nStrLen
= 0;
273 while( nCount
< nUTFLen
)
275 sal_uInt8 c
= static_cast<sal_uInt8
>(readByte());
276 sal_uInt8 char2
, char3
;
279 case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7:
286 // 110x xxxx 10xx xxxx
288 if( nCount
> nUTFLen
)
290 throw WrongFormatException( );
293 char2
= static_cast<sal_uInt8
>(readByte());
294 if( (char2
& 0xC0) != 0x80 )
296 throw WrongFormatException( );
299 pStr
[nStrLen
++] = (sal_Unicode(c
& 0x1F) << 6) | (char2
& 0x3F);
303 // 1110 xxxx 10xx xxxx 10xx xxxx
305 if( nCount
> nUTFLen
)
307 throw WrongFormatException( );
310 char2
= static_cast<sal_uInt8
>(readByte());
311 char3
= static_cast<sal_uInt8
>(readByte());
313 if( ((char2
& 0xC0) != 0x80) || ((char3
& 0xC0) != 0x80) ) {
314 throw WrongFormatException( );
316 pStr
[nStrLen
++] = (sal_Unicode(c
& 0x0F) << 12) |
317 (sal_Unicode(char2
& 0x3F) << 6) |
322 // 10xx xxxx, 1111 xxxx
323 throw WrongFormatException();
324 //throw new UTFDataFormatException();
327 return OUString( pStr
, nStrLen
);
332 void ODataInputStream::setInputStream(const Reference
< XInputStream
> & aStream
)
335 if( m_input
!= aStream
) {
338 Reference
< XConnectable
> pred( m_input
, UNO_QUERY
);
339 setPredecessor( pred
);
342 m_bValidStream
= m_input
.is();
345 Reference
< XInputStream
> ODataInputStream::getInputStream()
352 void ODataInputStream::setSuccessor( const Reference
< XConnectable
> &r
)
354 /// if the references match, nothing needs to be done
356 /// store the reference for later use
360 /// set this instance as the sink !
361 m_succ
->setPredecessor( Reference
< XConnectable
> (
362 static_cast< XConnectable
* >(this) ) );
367 Reference
< XConnectable
> ODataInputStream::getSuccessor()
374 void ODataInputStream::setPredecessor( const Reference
< XConnectable
> &r
)
379 m_pred
->setSuccessor( Reference
< XConnectable
> (
380 static_cast< XConnectable
* >(this) ) );
384 Reference
< XConnectable
> ODataInputStream::getPredecessor()
390 OUString
ODataInputStream::getImplementationName()
392 return "com.sun.star.comp.io.stm.DataInputStream";
396 sal_Bool
ODataInputStream::supportsService(const OUString
& ServiceName
)
398 return cppu::supportsService(this, ServiceName
);
402 Sequence
< OUString
> ODataInputStream::getSupportedServiceNames()
404 return { "com.sun.star.io.DataInputStream" };
407 extern "C" SAL_DLLPUBLIC_EXPORT
css::uno::XInterface
*
408 io_ODataInputStream_get_implementation(
409 css::uno::XComponentContext
* , css::uno::Sequence
<css::uno::Any
> const&)
411 return cppu::acquire(new ODataInputStream());
416 class ODataOutputStream
:
417 public WeakImplHelper
<
425 : m_bValidStream( false )
429 public: // XOutputStream
430 virtual void SAL_CALL
writeBytes(const Sequence
< sal_Int8
>& aData
) override
;
431 virtual void SAL_CALL
flush() override
;
432 virtual void SAL_CALL
closeOutput() override
;
434 public: // XDataOutputStream
435 virtual void SAL_CALL
writeBoolean(sal_Bool Value
) override
;
436 virtual void SAL_CALL
writeByte(sal_Int8 Value
) override
;
437 virtual void SAL_CALL
writeChar(sal_Unicode Value
) override
;
438 virtual void SAL_CALL
writeShort(sal_Int16 Value
) override
;
439 virtual void SAL_CALL
writeLong(sal_Int32 Value
) override
;
440 virtual void SAL_CALL
writeHyper(sal_Int64 Value
) override
;
441 virtual void SAL_CALL
writeFloat(float Value
) override
;
442 virtual void SAL_CALL
writeDouble(double Value
) override
;
443 virtual void SAL_CALL
writeUTF(const OUString
& Value
) override
;
445 public: // XActiveDataSource
446 virtual void SAL_CALL
setOutputStream(const Reference
< XOutputStream
> & aStream
) override
;
447 virtual Reference
< XOutputStream
> SAL_CALL
getOutputStream() override
;
449 public: // XConnectable
450 virtual void SAL_CALL
setPredecessor(const Reference
< XConnectable
>& aPredecessor
) override
;
451 virtual Reference
< XConnectable
> SAL_CALL
getPredecessor() override
;
452 virtual void SAL_CALL
setSuccessor(const Reference
< XConnectable
>& aSuccessor
) override
;
453 virtual Reference
< XConnectable
> SAL_CALL
getSuccessor() override
;
455 public: // XServiceInfo
456 OUString SAL_CALL
getImplementationName() override
;
457 Sequence
< OUString
> SAL_CALL
getSupportedServiceNames() override
;
458 sal_Bool SAL_CALL
supportsService(const OUString
& ServiceName
) override
;
461 Reference
< XConnectable
> m_succ
;
462 Reference
< XConnectable
> m_pred
;
463 Reference
< XOutputStream
> m_output
;
470 void ODataOutputStream::writeBytes(const Sequence
< sal_Int8
>& aData
)
472 if( !m_bValidStream
)
473 throw NotConnectedException( );
474 m_output
->writeBytes( aData
);
477 void ODataOutputStream::flush()
479 if( !m_bValidStream
)
480 throw NotConnectedException();
485 void ODataOutputStream::closeOutput()
487 if( !m_bValidStream
)
488 throw NotConnectedException();
489 m_output
->closeOutput();
490 setOutputStream( Reference
< XOutputStream
> () );
491 setPredecessor( Reference
< XConnectable
>() );
492 setSuccessor( Reference
< XConnectable
>() );
496 void ODataOutputStream::writeBoolean(sal_Bool Value
)
509 void ODataOutputStream::writeByte(sal_Int8 Value
)
511 writeBytes( { Value
} );
514 void ODataOutputStream::writeChar(sal_Unicode Value
)
516 writeBytes( { sal_Int8(Value
>> 8),
521 void ODataOutputStream::writeShort(sal_Int16 Value
)
523 writeBytes( { sal_Int8(Value
>> 8),
527 void ODataOutputStream::writeLong(sal_Int32 Value
)
529 writeBytes( { sal_Int8(Value
>> 24),
530 sal_Int8(Value
>> 16),
531 sal_Int8(Value
>> 8),
535 void ODataOutputStream::writeHyper(sal_Int64 Value
)
537 writeBytes( { sal_Int8(Value
>> 56),
538 sal_Int8(Value
>> 48),
539 sal_Int8(Value
>> 40),
540 sal_Int8(Value
>> 32),
541 sal_Int8(Value
>> 24),
542 sal_Int8(Value
>> 16),
543 sal_Int8(Value
>> 8),
548 void ODataOutputStream::writeFloat(float Value
)
550 union { float f
; sal_uInt32 n
; } a
;
555 void ODataOutputStream::writeDouble(double Value
)
557 union { double d
; struct { sal_uInt32 n1
; sal_uInt32 n2
; } ad
; } a
;
559 #if defined OSL_LITENDIAN
560 writeLong( a
.ad
.n2
);
561 writeLong( a
.ad
.n1
);
563 writeLong( a
.ad
.n1
);
564 writeLong( a
.ad
.n2
);
568 void ODataOutputStream::writeUTF(const OUString
& Value
)
570 sal_Int32 nStrLen
= Value
.getLength();
571 const sal_Unicode
* pStr
= Value
.getStr();
572 sal_Int32 nUTFLen
= 0;
575 for( i
= 0 ; i
< nStrLen
; i
++ )
577 sal_uInt16 c
= pStr
[i
];
578 if( (c
>= 0x0001) && (c
<= 0x007F) )
582 else if( c
> 0x07FF )
593 // compatibility mode for older implementations, where it was not possible
594 // to write blocks bigger than 64 k. Note that there is a tradeoff. Blocks,
595 // that are exactly 64k long can not be read by older routines when written
596 // with these routines and the other way round !!!!!
597 if( nUTFLen
>= 0xFFFF ) {
598 writeShort( sal_Int16(-1) );
599 writeLong( nUTFLen
);
602 writeShort( static_cast<sal_uInt16
>(nUTFLen
) );
604 for( i
= 0 ; i
< nStrLen
; i
++ )
606 sal_uInt16 c
= pStr
[i
];
607 if( (c
>= 0x0001) && (c
<= 0x007F) )
609 writeByte(sal_Int8(c
));
611 else if( c
> 0x07FF )
613 writeByte(sal_Int8(0xE0 | ((c
>> 12) & 0x0F)));
614 writeByte(sal_Int8(0x80 | ((c
>> 6) & 0x3F)));
615 writeByte(sal_Int8(0x80 | ((c
>> 0) & 0x3F)));
619 writeByte(sal_Int8(0xC0 | ((c
>> 6) & 0x1F)));
620 writeByte(sal_Int8(0x80 | ((c
>> 0) & 0x3F)));
626 void ODataOutputStream::setOutputStream(const Reference
< XOutputStream
> & aStream
)
628 if( m_output
!= aStream
) {
630 m_bValidStream
= m_output
.is();
632 Reference
< XConnectable
> succ( m_output
, UNO_QUERY
);
633 setSuccessor( succ
);
637 Reference
< XOutputStream
> ODataOutputStream::getOutputStream()
644 void ODataOutputStream::setSuccessor( const Reference
< XConnectable
> &r
)
646 /// if the references match, nothing needs to be done
649 /// store the reference for later use
654 /// set this instance as the sink !
655 m_succ
->setPredecessor( Reference
< XConnectable
> (
656 static_cast< XConnectable
* >(this) ));
660 Reference
< XConnectable
> ODataOutputStream::getSuccessor()
667 void ODataOutputStream::setPredecessor( const Reference
< XConnectable
> &r
)
672 m_pred
->setSuccessor( Reference
< XConnectable
> (
673 static_cast< XConnectable
* >(this) ));
677 Reference
< XConnectable
> ODataOutputStream::getPredecessor()
684 OUString
ODataOutputStream::getImplementationName()
686 return "com.sun.star.comp.io.stm.DataOutputStream";
690 sal_Bool
ODataOutputStream::supportsService(const OUString
& ServiceName
)
692 return cppu::supportsService(this, ServiceName
);
696 Sequence
< OUString
> ODataOutputStream::getSupportedServiceNames()
698 return { "com.sun.star.io.DataOutputStream" };
701 extern "C" SAL_DLLPUBLIC_EXPORT
css::uno::XInterface
*
702 io_ODataOutputStream_get_implementation(
703 css::uno::XComponentContext
* , css::uno::Sequence
<css::uno::Any
> const&)
705 return cppu::acquire(new ODataOutputStream());
710 struct equalObjectContainer_Impl
712 bool operator()(const Reference
< XInterface
> & s1
,
713 const Reference
< XInterface
> & s2
) const
720 struct hashObjectContainer_Impl
722 size_t operator()(const Reference
< XInterface
> & xRef
) const
724 return reinterpret_cast<size_t>(xRef
.get());
730 typedef std::unordered_map
732 Reference
< XInterface
>,
734 hashObjectContainer_Impl
,
735 equalObjectContainer_Impl
736 > ObjectContainer_Impl
;
740 class OObjectOutputStream
:
741 public ImplInheritanceHelper
<
742 ODataOutputStream
, /* parent */
743 XObjectOutputStream
, XMarkableStream
>
746 OObjectOutputStream()
748 m_bValidMarkable(false)
754 virtual void SAL_CALL
writeBytes(const Sequence
< sal_Int8
>& aData
) override
755 { ODataOutputStream::writeBytes( aData
); }
757 virtual void SAL_CALL
flush() override
758 { ODataOutputStream::flush(); }
760 virtual void SAL_CALL
closeOutput() override
761 { ODataOutputStream::closeOutput(); }
765 virtual void SAL_CALL
writeBoolean(sal_Bool Value
) override
766 { ODataOutputStream::writeBoolean( Value
); }
767 virtual void SAL_CALL
writeByte(sal_Int8 Value
) override
768 { ODataOutputStream::writeByte( Value
); }
769 virtual void SAL_CALL
writeChar(sal_Unicode Value
) override
770 { ODataOutputStream::writeChar( Value
); }
771 virtual void SAL_CALL
writeShort(sal_Int16 Value
) override
772 { ODataOutputStream::writeShort( Value
); }
773 virtual void SAL_CALL
writeLong(sal_Int32 Value
) override
774 { ODataOutputStream::writeLong( Value
); }
775 virtual void SAL_CALL
writeHyper(sal_Int64 Value
) override
776 { ODataOutputStream::writeHyper( Value
); }
777 virtual void SAL_CALL
writeFloat(float Value
) override
778 { ODataOutputStream::writeFloat( Value
); }
779 virtual void SAL_CALL
writeDouble(double Value
) override
780 { ODataOutputStream::writeDouble( Value
); }
781 virtual void SAL_CALL
writeUTF(const OUString
& Value
) override
782 { ODataOutputStream::writeUTF( Value
);}
784 // XObjectOutputStream
785 virtual void SAL_CALL
writeObject( const Reference
< XPersistObject
> & r
) override
;
787 public: // XMarkableStream
788 virtual sal_Int32 SAL_CALL
createMark() override
;
789 virtual void SAL_CALL
deleteMark(sal_Int32 Mark
) override
;
790 virtual void SAL_CALL
jumpToMark(sal_Int32 nMark
) override
;
791 virtual void SAL_CALL
jumpToFurthest() override
;
792 virtual sal_Int32 SAL_CALL
offsetToMark(sal_Int32 nMark
) override
;
794 public: // XServiceInfo
795 OUString SAL_CALL
getImplementationName() override
;
796 Sequence
< OUString
> SAL_CALL
getSupportedServiceNames() override
;
797 sal_Bool SAL_CALL
supportsService(const OUString
& ServiceName
) override
;
800 void connectToMarkable();
802 ObjectContainer_Impl m_mapObject
;
804 Reference
< XMarkableStream
> m_rMarkable
;
805 bool m_bValidMarkable
;
810 void OObjectOutputStream::writeObject( const Reference
< XPersistObject
> & xPObj
)
814 bool bWriteObj
= false;
815 // create Mark to write length of info
816 sal_uInt32 nInfoLenMark
= m_rMarkable
->createMark();
818 // length of the info data (is later rewritten)
819 OObjectOutputStream::writeShort( 0 );
821 // write the object identifier
824 Reference
< XInterface
> rX( xPObj
, UNO_QUERY
);
826 ObjectContainer_Impl::const_iterator aIt
827 = m_mapObject
.find( rX
);
828 if( aIt
== m_mapObject
.end() )
830 // insert new object in hash table
831 m_mapObject
[ rX
] = ++m_nMaxId
;
832 ODataOutputStream::writeLong( m_nMaxId
);
833 ODataOutputStream::writeUTF( xPObj
->getServiceName() );
838 ODataOutputStream::writeLong( (*aIt
).second
);
839 ODataOutputStream::writeUTF( OUString() );
844 ODataOutputStream::writeLong( 0 );
845 ODataOutputStream::writeUTF( OUString() );
848 sal_uInt32 nObjLenMark
= m_rMarkable
->createMark();
849 ODataOutputStream::writeLong( 0 );
851 sal_Int32 nInfoLen
= m_rMarkable
->offsetToMark( nInfoLenMark
);
852 m_rMarkable
->jumpToMark( nInfoLenMark
);
853 // write length of the info data
854 ODataOutputStream::writeShort( static_cast<sal_Int16
>(nInfoLen
) );
855 // jump to the end of the stream
856 m_rMarkable
->jumpToFurthest();
859 xPObj
->write( Reference
< XObjectOutputStream
> (
860 static_cast< XObjectOutputStream
* >(this) ) );
862 sal_Int32 nObjLen
= m_rMarkable
->offsetToMark( nObjLenMark
) -4;
863 m_rMarkable
->jumpToMark( nObjLenMark
);
864 // write length of the info data
865 ODataOutputStream::writeLong( nObjLen
);
866 // jump to the end of the stream
867 m_rMarkable
->jumpToFurthest();
869 m_rMarkable
->deleteMark( nObjLenMark
);
870 m_rMarkable
->deleteMark( nInfoLenMark
);
874 void OObjectOutputStream::connectToMarkable()
876 if( m_bValidMarkable
)
879 if( ! m_bValidStream
)
880 throw NotConnectedException();
882 // find the markable stream !
883 Reference
< XInterface
> rTry(m_output
);
887 throw NotConnectedException();
889 Reference
< XMarkableStream
> markable( rTry
, UNO_QUERY
);
892 m_rMarkable
= markable
;
895 Reference
< XActiveDataSource
> source( rTry
, UNO_QUERY
);
898 m_bValidMarkable
= true;
902 sal_Int32
OObjectOutputStream::createMark()
904 connectToMarkable(); // throws an exception, if a markable is not connected !
906 return m_rMarkable
->createMark();
909 void OObjectOutputStream::deleteMark(sal_Int32 Mark
)
911 if( ! m_bValidMarkable
)
913 throw NotConnectedException();
915 m_rMarkable
->deleteMark( Mark
);
918 void OObjectOutputStream::jumpToMark(sal_Int32 nMark
)
920 if( ! m_bValidMarkable
)
922 throw NotConnectedException();
924 m_rMarkable
->jumpToMark( nMark
);
928 void OObjectOutputStream::jumpToFurthest()
931 m_rMarkable
->jumpToFurthest();
934 sal_Int32
OObjectOutputStream::offsetToMark(sal_Int32 nMark
)
936 if( ! m_bValidMarkable
)
938 throw NotConnectedException();
940 return m_rMarkable
->offsetToMark( nMark
);
944 OUString
OObjectOutputStream::getImplementationName()
946 return "com.sun.star.comp.io.stm.ObjectOutputStream";
950 sal_Bool
OObjectOutputStream::supportsService(const OUString
& ServiceName
)
952 return cppu::supportsService(this, ServiceName
);
956 Sequence
< OUString
> OObjectOutputStream::getSupportedServiceNames()
958 return { "com.sun.star.io.ObjectOutputStream" };
961 extern "C" SAL_DLLPUBLIC_EXPORT
css::uno::XInterface
*
962 io_OObjectOutputStream_get_implementation(
963 css::uno::XComponentContext
* , css::uno::Sequence
<css::uno::Any
> const&)
965 return cppu::acquire(new OObjectOutputStream());
970 class OObjectInputStream
:
971 public ImplInheritanceHelper
<
972 ODataInputStream
, /* parent */
973 XObjectInputStream
, XMarkableStream
>
976 explicit OObjectInputStream( const Reference
< XComponentContext
> &r
)
977 : m_rSMgr( r
->getServiceManager() )
979 , m_bValidMarkable(false)
983 public: // XInputStream
984 virtual sal_Int32 SAL_CALL
readBytes(Sequence
< sal_Int8
>& aData
, sal_Int32 nBytesToRead
) override
985 { return ODataInputStream::readBytes( aData
, nBytesToRead
); }
987 virtual sal_Int32 SAL_CALL
readSomeBytes(Sequence
< sal_Int8
>& aData
, sal_Int32 nMaxBytesToRead
) override
988 { return ODataInputStream::readSomeBytes( aData
, nMaxBytesToRead
); }
990 virtual void SAL_CALL
skipBytes(sal_Int32 nBytesToSkip
) override
991 { ODataInputStream::skipBytes( nBytesToSkip
); }
993 virtual sal_Int32 SAL_CALL
available() override
994 { return ODataInputStream::available(); }
996 virtual void SAL_CALL
closeInput() override
997 { ODataInputStream::closeInput(); }
999 public: // XDataInputStream
1000 virtual sal_Int8 SAL_CALL
readBoolean() override
1001 { return ODataInputStream::readBoolean(); }
1002 virtual sal_Int8 SAL_CALL
readByte() override
1003 { return ODataInputStream::readByte(); }
1004 virtual sal_Unicode SAL_CALL
readChar() override
1005 { return ODataInputStream::readChar(); }
1006 virtual sal_Int16 SAL_CALL
readShort() override
1007 { return ODataInputStream::readShort(); }
1008 virtual sal_Int32 SAL_CALL
readLong() override
1009 { return ODataInputStream::readLong(); }
1010 virtual sal_Int64 SAL_CALL
readHyper() override
1011 { return ODataInputStream::readHyper(); }
1012 virtual float SAL_CALL
readFloat() override
1013 { return ODataInputStream::readFloat(); }
1014 virtual double SAL_CALL
readDouble() override
1015 { return ODataInputStream::readDouble(); }
1016 virtual OUString SAL_CALL
readUTF() override
1017 { return ODataInputStream::readUTF(); }
1019 public: // XObjectInputStream
1020 virtual Reference
< XPersistObject
> SAL_CALL
readObject( ) override
;
1022 public: // XMarkableStream
1023 virtual sal_Int32 SAL_CALL
createMark() override
;
1024 virtual void SAL_CALL
deleteMark(sal_Int32 Mark
) override
;
1025 virtual void SAL_CALL
jumpToMark(sal_Int32 nMark
) override
;
1026 virtual void SAL_CALL
jumpToFurthest() override
;
1027 virtual sal_Int32 SAL_CALL
offsetToMark(sal_Int32 nMark
) override
;
1029 public: // XServiceInfo
1030 OUString SAL_CALL
getImplementationName() override
;
1031 Sequence
< OUString
> SAL_CALL
getSupportedServiceNames() override
;
1032 sal_Bool SAL_CALL
supportsService(const OUString
& ServiceName
) override
;
1035 void connectToMarkable();
1037 Reference
< XMultiComponentFactory
> m_rSMgr
;
1038 Reference
< XComponentContext
> m_rCxt
;
1039 bool m_bValidMarkable
;
1040 Reference
< XMarkableStream
> m_rMarkable
;
1041 std::vector
< Reference
< XPersistObject
> > m_aPersistVector
;
1047 Reference
< XPersistObject
> OObjectInputStream::readObject()
1049 // check if chain contains a XMarkableStream
1050 connectToMarkable();
1052 Reference
< XPersistObject
> xLoadedObj
;
1054 // create Mark to skip newer versions
1055 sal_uInt32 nMark
= m_rMarkable
->createMark();
1056 // length of the data
1057 sal_Int32 nLen
= static_cast<sal_uInt16
>(ODataInputStream::readShort());
1060 throw WrongFormatException();
1063 // read the object identifier
1064 sal_uInt32 nId
= readLong();
1066 // the name of the persist model
1068 OUString aName
= readUTF();
1070 // Read the length of the object
1071 sal_Int32 nObjLen
= readLong();
1072 if( 0 == nId
&& 0 != nObjLen
)
1074 throw WrongFormatException();
1077 // skip data of new version
1078 skipBytes( nLen
- m_rMarkable
->offsetToMark( nMark
) );
1080 bool bLoadSuccessful
= true;
1083 if( !aName
.isEmpty() )
1086 Reference
< XInterface
> x
= m_rSMgr
->createInstanceWithContext( aName
, m_rCxt
);
1087 xLoadedObj
.set( x
, UNO_QUERY
);
1088 if( xLoadedObj
.is() )
1090 sal_uInt32 nSize
= m_aPersistVector
.size();
1093 // grow to the right size
1094 Reference
< XPersistObject
> xEmpty
;
1095 m_aPersistVector
.insert( m_aPersistVector
.end(), nId
- nSize
+ 1, xEmpty
);
1098 m_aPersistVector
[nId
] = xLoadedObj
;
1099 xLoadedObj
->read( Reference
< XObjectInputStream
>(
1100 static_cast< XObjectInputStream
* >(this) ) );
1104 // no service with this name could be instantiated
1105 bLoadSuccessful
= false;
1109 if (nId
>= m_aPersistVector
.size())
1111 // id unknown, load failure !
1112 bLoadSuccessful
= false;
1116 // Object has already been read,
1117 xLoadedObj
= m_aPersistVector
[nId
];
1122 // skip to the position behind the object
1123 skipBytes( nObjLen
+ nLen
- m_rMarkable
->offsetToMark( nMark
) );
1124 m_rMarkable
->deleteMark( nMark
);
1126 if( ! bLoadSuccessful
)
1128 throw WrongFormatException();
1134 void OObjectInputStream::connectToMarkable()
1136 if( m_bValidMarkable
) return;
1138 if( ! m_bValidStream
)
1140 throw NotConnectedException( );
1143 // find the markable stream !
1144 Reference
< XInterface
> rTry(m_input
);
1148 throw NotConnectedException( );
1150 Reference
< XMarkableStream
> markable( rTry
, UNO_QUERY
);
1153 m_rMarkable
= markable
;
1156 Reference
< XActiveDataSink
> sink( rTry
, UNO_QUERY
);
1159 m_bValidMarkable
= true;
1162 sal_Int32
OObjectInputStream::createMark()
1164 connectToMarkable(); // throws an exception, if a markable is not connected !
1166 return m_rMarkable
->createMark();
1169 void OObjectInputStream::deleteMark(sal_Int32 Mark
)
1171 if( ! m_bValidMarkable
)
1173 throw NotConnectedException();
1175 m_rMarkable
->deleteMark( Mark
);
1178 void OObjectInputStream::jumpToMark(sal_Int32 nMark
)
1180 if( ! m_bValidMarkable
)
1182 throw NotConnectedException();
1184 m_rMarkable
->jumpToMark( nMark
);
1186 void OObjectInputStream::jumpToFurthest()
1188 connectToMarkable();
1189 m_rMarkable
->jumpToFurthest();
1192 sal_Int32
OObjectInputStream::offsetToMark(sal_Int32 nMark
)
1194 if( ! m_bValidMarkable
)
1196 throw NotConnectedException();
1198 return m_rMarkable
->offsetToMark( nMark
);
1202 OUString
OObjectInputStream::getImplementationName()
1204 return "com.sun.star.comp.io.stm.ObjectInputStream";
1208 sal_Bool
OObjectInputStream::supportsService(const OUString
& ServiceName
)
1210 return cppu::supportsService(this, ServiceName
);
1214 Sequence
< OUString
> OObjectInputStream::getSupportedServiceNames()
1216 return { "com.sun.star.io.ObjectInputStream" };
1219 extern "C" SAL_DLLPUBLIC_EXPORT
css::uno::XInterface
*
1220 io_OObjectInputStream_get_implementation(
1221 css::uno::XComponentContext
* context
, css::uno::Sequence
<css::uno::Any
> const&)
1223 return cppu::acquire(new OObjectInputStream(context
));
1229 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */