Bump version to 6.4-15
[LibreOffice.git] / io / source / stm / odata.cxx
blob0c1dd29f9bb19222703e48b7bfab68ae66891eed
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 #include <services.hxx>
50 namespace io_stm {
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;
109 // XInputStream
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 );
117 return nRead;
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 );
125 return nRead;
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( );
140 return nAvail;
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 ===========================================
157 // XDataInputStream
158 sal_Int8 ODataInputStream::readBoolean()
160 return readByte();
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());
220 return
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) +
228 pBytes[7];
231 float ODataInputStream::readFloat()
233 union { float f; sal_uInt32 n; } a;
234 a.n = readLong();
235 return a.f;
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();
244 #else
245 a.ad.n1 = readLong();
246 a.ad.n2 = readLong();
247 #endif
248 return a.d;
251 OUString ODataInputStream::readUTF()
253 sal_uInt16 nShortLen = static_cast<sal_uInt16>(readShort());
254 sal_Int32 nUTFLen;
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();
262 else
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;
276 switch( c >> 4 )
278 case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7:
279 // 0xxxxxxx
280 nCount++;
281 pStr[nStrLen++] = c;
282 break;
284 case 12: case 13:
285 // 110x xxxx 10xx xxxx
286 nCount += 2;
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);
299 break;
301 case 14:
302 // 1110 xxxx 10xx xxxx 10xx xxxx
303 nCount += 3;
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) |
317 (char3 & 0x3F);
318 break;
320 default:
321 // 10xx xxxx, 1111 xxxx
322 throw WrongFormatException();
323 //throw new UTFDataFormatException();
326 return OUString( pStr, nStrLen );
330 // XActiveDataSource
331 void ODataInputStream::setInputStream(const Reference< XInputStream > & aStream)
334 if( m_input != aStream ) {
335 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()
346 return m_input;
350 // XDataSink
351 void ODataInputStream::setSuccessor( const Reference < XConnectable > &r )
353 /// if the references match, nothing needs to be done
354 if( m_succ != r ) {
355 /// store the reference for later use
356 m_succ = r;
358 if( m_succ.is() ) {
359 /// set this instance as the sink !
360 m_succ->setPredecessor( Reference< XConnectable > (
361 static_cast< XConnectable * >(this) ) );
366 Reference < XConnectable > ODataInputStream::getSuccessor()
368 return m_succ;
372 // XDataSource
373 void ODataInputStream::setPredecessor( const Reference < XConnectable > &r )
375 if( r != m_pred ) {
376 m_pred = r;
377 if( m_pred.is() ) {
378 m_pred->setSuccessor( Reference< XConnectable > (
379 static_cast< XConnectable * >(this) ) );
383 Reference < XConnectable > ODataInputStream::getPredecessor()
385 return m_pred;
388 // XServiceInfo
389 OUString ODataInputStream::getImplementationName()
391 return ODataInputStream_getImplementationName();
394 // XServiceInfo
395 sal_Bool ODataInputStream::supportsService(const OUString& ServiceName)
397 return cppu::supportsService(this, ServiceName);
400 // XServiceInfo
401 Sequence< OUString > ODataInputStream::getSupportedServiceNames()
403 return ODataInputStream_getSupportedServiceNames();
406 /***
408 * registration information
411 ****/
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" };
428 return aRet;
432 class ODataOutputStream :
433 public WeakImplHelper <
434 XDataOutputStream,
435 XActiveDataSource,
436 XConnectable,
437 XServiceInfo >
439 public:
440 ODataOutputStream()
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;
476 protected:
477 Reference < XConnectable > m_succ;
478 Reference < XConnectable > m_pred;
479 Reference< XOutputStream > m_output;
480 bool m_bValidStream;
483 // XOutputStream
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();
495 m_output->flush();
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 >() );
509 // XDataOutputStream
510 void ODataOutputStream::writeBoolean(sal_Bool Value)
512 if( Value )
514 writeByte( 1 );
516 else
518 writeByte( 0 );
523 void ODataOutputStream::writeByte(sal_Int8 Value)
525 writeBytes( { Value } );
528 void ODataOutputStream::writeChar(sal_Unicode Value)
530 writeBytes( { sal_Int8(Value >> 8),
531 sal_Int8(Value) } );
535 void ODataOutputStream::writeShort(sal_Int16 Value)
537 writeBytes( { sal_Int8(Value >> 8),
538 sal_Int8(Value) } );
541 void ODataOutputStream::writeLong(sal_Int32 Value)
543 writeBytes( { sal_Int8(Value >> 24),
544 sal_Int8(Value >> 16),
545 sal_Int8(Value >> 8),
546 sal_Int8(Value) } );
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),
558 sal_Int8(Value) } );
562 void ODataOutputStream::writeFloat(float Value)
564 union { float f; sal_uInt32 n; } a;
565 a.f = Value;
566 writeLong( a.n );
569 void ODataOutputStream::writeDouble(double Value)
571 union { double d; struct { sal_uInt32 n1; sal_uInt32 n2; } ad; } a;
572 a.d = Value;
573 #if defined OSL_LITENDIAN
574 writeLong( a.ad.n2 );
575 writeLong( a.ad.n1 );
576 #else
577 writeLong( a.ad.n1 );
578 writeLong( a.ad.n2 );
579 #endif
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;
587 sal_Int32 i;
589 for( i = 0 ; i < nStrLen ; i++ )
591 sal_uInt16 c = pStr[i];
592 if( (c >= 0x0001) && (c <= 0x007F) )
594 nUTFLen++;
596 else if( c > 0x07FF )
598 nUTFLen += 3;
600 else
602 nUTFLen += 2;
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 );
615 else {
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)));
631 else
633 writeByte(sal_Int8(0xC0 | ((c >> 6) & 0x1F)));
634 writeByte(sal_Int8(0x80 | ((c >> 0) & 0x3F)));
639 // XActiveDataSource
640 void ODataOutputStream::setOutputStream(const Reference< XOutputStream > & aStream)
642 if( m_output != aStream ) {
643 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()
653 return m_output;
657 // XDataSink
658 void ODataOutputStream::setSuccessor( const Reference < XConnectable > &r )
660 /// if the references match, nothing needs to be done
661 if( m_succ != r )
663 /// store the reference for later use
664 m_succ = r;
666 if( m_succ.is() )
668 /// set this instance as the sink !
669 m_succ->setPredecessor( Reference < XConnectable > (
670 static_cast< XConnectable * >(this) ));
674 Reference < XConnectable > ODataOutputStream::getSuccessor()
676 return m_succ;
680 // XDataSource
681 void ODataOutputStream::setPredecessor( const Reference < XConnectable > &r )
683 if( r != m_pred ) {
684 m_pred = r;
685 if( m_pred.is() ) {
686 m_pred->setSuccessor( Reference< XConnectable > (
687 static_cast< XConnectable * >(this) ));
691 Reference < XConnectable > ODataOutputStream::getPredecessor()
693 return m_pred;
697 // XServiceInfo
698 OUString ODataOutputStream::getImplementationName()
700 return ODataOutputStream_getImplementationName();
703 // XServiceInfo
704 sal_Bool ODataOutputStream::supportsService(const OUString& ServiceName)
706 return cppu::supportsService(this, ServiceName);
709 // XServiceInfo
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;
720 return xService;
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" };
732 return aRet;
736 struct equalObjectContainer_Impl
738 bool operator()(const Reference< XInterface > & s1,
739 const Reference< XInterface > & s2) const
741 return s1 == s2;
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 >,
757 sal_Int32,
758 hashObjectContainer_Impl,
759 equalObjectContainer_Impl
760 > ObjectContainer_Impl;
762 class OObjectOutputStream:
763 public ImplInheritanceHelper<
764 ODataOutputStream, /* parent */
765 XObjectOutputStream, XMarkableStream >
767 public:
768 OObjectOutputStream()
769 : m_nMaxId(0) ,
770 m_bValidMarkable(false)
774 public:
775 // XOutputStream
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(); }
785 public:
786 // XDataOutputStream
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;
821 private:
822 void connectToMarkable();
823 private:
824 ObjectContainer_Impl m_mapObject;
825 sal_Int32 m_nMaxId;
826 Reference< XMarkableStream > m_rMarkable;
827 bool m_bValidMarkable;
830 void OObjectOutputStream::writeObject( const Reference< XPersistObject > & xPObj )
833 connectToMarkable();
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
842 if( xPObj.is() )
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() );
854 bWriteObj = true;
856 else
858 ODataOutputStream::writeLong( (*aIt).second );
859 ODataOutputStream::writeUTF( OUString() );
862 else
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();
878 if( bWriteObj )
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);
904 while( true ) {
905 if( ! rTry.is() )
907 throw NotConnectedException();
909 Reference < XMarkableStream > markable( rTry , UNO_QUERY );
910 if( markable.is() )
912 m_rMarkable = markable;
913 break;
915 Reference < XActiveDataSource > source( rTry , UNO_QUERY );
916 rTry = source;
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()
951 connectToMarkable();
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" };
980 return aRet;
983 // XServiceInfo
984 OUString OObjectOutputStream::getImplementationName()
986 return OObjectOutputStream_getImplementationName();
989 // XServiceInfo
990 sal_Bool OObjectOutputStream::supportsService(const OUString& ServiceName)
992 return cppu::supportsService(this, ServiceName);
995 // XServiceInfo
996 Sequence< OUString > OObjectOutputStream::getSupportedServiceNames()
998 return OObjectOutputStream_getSupportedServiceNames();
1001 class OObjectInputStream:
1002 public ImplInheritanceHelper<
1003 ODataInputStream, /* parent */
1004 XObjectInputStream, XMarkableStream >
1006 public:
1007 explicit OObjectInputStream( const Reference < XComponentContext > &r)
1008 : m_rSMgr( r->getServiceManager() )
1009 , m_rCxt( r )
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;
1065 private:
1066 void connectToMarkable();
1067 private:
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());
1087 if( nLen < 0xc )
1089 throw WrongFormatException();
1092 // read the object identifier
1093 sal_uInt32 nId = readLong();
1095 // the name of the persist model
1096 // MM ???
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;
1110 if( nId )
1112 if( !aName.isEmpty() )
1114 // load the object
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();
1120 if( nSize <= nId )
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) ) );
1131 else
1133 // no service with this name could be instantiated
1134 bLoadSuccessful = false;
1137 else {
1138 if (nId >= m_aPersistVector.size())
1140 // id unknown, load failure !
1141 bLoadSuccessful = false;
1143 else
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();
1159 return xLoadedObj;
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);
1173 while( true ) {
1174 if( ! rTry.is() )
1176 throw NotConnectedException( );
1178 Reference< XMarkableStream > markable( rTry , UNO_QUERY );
1179 if( markable.is() )
1181 m_rMarkable = markable;
1182 break;
1184 Reference < XActiveDataSink > sink( rTry , UNO_QUERY );
1185 rTry = sink;
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 );
1230 // XServiceInfo
1231 OUString OObjectInputStream::getImplementationName()
1233 return OObjectInputStream_getImplementationName();
1236 // XServiceInfo
1237 sal_Bool OObjectInputStream::supportsService(const OUString& ServiceName)
1239 return cppu::supportsService(this, ServiceName);
1242 // XServiceInfo
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" };
1262 return aRet;
1267 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */