LibreOffice Module io (master) 1
odata.cxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 */
19
20#include <string.h>
21#include <unordered_map>
22#include <vector>
23
24#include <cppuhelper/weak.hxx>
27#include <osl/endian.h>
28
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>
40
41using namespace ::cppu;
42using namespace ::osl;
43using namespace ::com::sun::star::io;
44using namespace ::com::sun::star::uno;
45using namespace ::com::sun::star::lang;
46
47namespace io_stm {
48
49namespace {
50
51class ODataInputStream :
52 public WeakImplHelper <
53 XDataInputStream,
54 XActiveDataSink,
55 XConnectable,
56 XServiceInfo
57 >
58{
59public:
60 ODataInputStream( )
61 : m_bValidStream( false )
62 {
63 }
64
65public: // 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;
71
72public: // 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;
82
83
84public: // XActiveDataSink
85 virtual void SAL_CALL setInputStream(const Reference< XInputStream > & aStream) override;
86 virtual Reference< XInputStream > SAL_CALL getInputStream() override;
87
88public: // 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 ;
93
94
95public: // XServiceInfo
96 OUString SAL_CALL getImplementationName() override;
97 Sequence< OUString > SAL_CALL getSupportedServiceNames() override;
98 sal_Bool SAL_CALL supportsService(const OUString& ServiceName) override;
99
100protected:
101
102 Reference < XConnectable > m_pred;
103 Reference < XConnectable > m_succ;
104 Reference < XInputStream > m_input;
106};
107
108}
109
110// XInputStream
111sal_Int32 ODataInputStream::readBytes(Sequence< sal_Int8 >& aData, sal_Int32 nBytesToRead)
112{
113 if( !m_bValidStream )
114 {
115 throw NotConnectedException( );
116 }
117 sal_Int32 nRead = m_input->readBytes( aData , nBytesToRead );
118 return nRead;
119}
120
121sal_Int32 ODataInputStream::readSomeBytes(Sequence< sal_Int8 >& aData, sal_Int32 nMaxBytesToRead)
122{
123 if( !m_bValidStream )
124 throw NotConnectedException( );
125 sal_Int32 nRead = m_input->readSomeBytes( aData , nMaxBytesToRead );
126 return nRead;
127}
128void ODataInputStream::skipBytes(sal_Int32 nBytesToSkip)
129{
130 if( !m_bValidStream )
131 throw NotConnectedException( );
132 m_input->skipBytes( nBytesToSkip );
133}
134
135
136sal_Int32 ODataInputStream::available()
137{
138 if( !m_bValidStream )
139 throw NotConnectedException( );
140 sal_Int32 nAvail = m_input->available( );
141 return nAvail;
142}
143
144void ODataInputStream::closeInput()
145{
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;
153}
154
155
156//== XDataInputStream ===========================================
157
158// XDataInputStream
159sal_Int8 ODataInputStream::readBoolean()
160{
161 return readByte();
162}
163
164sal_Int8 ODataInputStream::readByte()
165{
166 Sequence<sal_Int8> aTmp(1);
167 if( 1 != readBytes( aTmp, 1 ) )
168 {
169 throw UnexpectedEOFException();
170 }
171 return aTmp.getConstArray()[0];
172}
173
174sal_Unicode ODataInputStream::readChar()
175{
176 Sequence<sal_Int8> aTmp(2);
177 if( 2 != readBytes( aTmp, 2 ) )
178 {
179 throw UnexpectedEOFException();
180 }
181
182 const sal_uInt8 * pBytes = reinterpret_cast<const sal_uInt8 *>(aTmp.getConstArray());
183 return (static_cast<sal_Unicode>(pBytes[0]) << 8) + pBytes[1];
184}
185
186sal_Int16 ODataInputStream::readShort()
187{
188 Sequence<sal_Int8> aTmp(2);
189 if( 2 != readBytes( aTmp, 2 ) )
190 {
191 throw UnexpectedEOFException();
192 }
193
194 const sal_uInt8 * pBytes = reinterpret_cast<const sal_uInt8 *>(aTmp.getConstArray());
195 return (static_cast<sal_Int16>(pBytes[0]) << 8) + pBytes[1];
196}
197
198
199sal_Int32 ODataInputStream::readLong()
200{
201 Sequence<sal_Int8> aTmp(4);
202 if( 4 != readBytes( aTmp, 4 ) )
203 {
204 throw UnexpectedEOFException( );
205 }
206
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];
209}
210
211
212sal_Int64 ODataInputStream::readHyper()
213{
214 Sequence<sal_Int8> aTmp(8);
215 if( 8 != readBytes( aTmp, 8 ) )
216 {
217 throw UnexpectedEOFException( );
218 }
219
220 const sal_uInt8 * pBytes = reinterpret_cast<const sal_uInt8 *>(aTmp.getConstArray());
221 return
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) +
229 pBytes[7];
230}
231
232float ODataInputStream::readFloat()
233{
234 union { float f; sal_uInt32 n; } a;
235 a.n = readLong();
236 return a.f;
237}
238
239double ODataInputStream::readDouble()
240{
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();
245#else
246 a.ad.n1 = readLong();
247 a.ad.n2 = readLong();
248#endif
249 return a.d;
250}
251
252OUString ODataInputStream::readUTF()
253{
254 sal_uInt16 nShortLen = static_cast<sal_uInt16>(readShort());
255 sal_Int32 nUTFLen;
256
257 if( (sal_uInt16(0xffff)) == nShortLen )
258 {
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();
262 }
263 else
264 {
265 nUTFLen = static_cast<sal_Int32>(nShortLen);
266 }
267
268 Sequence<sal_Unicode> aBuffer( nUTFLen );
269 sal_Unicode * pStr = aBuffer.getArray();
270
271 sal_Int32 nCount = 0;
272 sal_Int32 nStrLen = 0;
273 while( nCount < nUTFLen )
274 {
275 sal_uInt8 c = static_cast<sal_uInt8>(readByte());
276 sal_uInt8 char2, char3;
277 switch( c >> 4 )
278 {
279 case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7:
280 // 0xxxxxxx
281 nCount++;
282 pStr[nStrLen++] = c;
283 break;
284
285 case 12: case 13:
286 // 110x xxxx 10xx xxxx
287 nCount += 2;
288 if( nCount > nUTFLen )
289 {
290 throw WrongFormatException( );
291 }
292
293 char2 = static_cast<sal_uInt8>(readByte());
294 if( (char2 & 0xC0) != 0x80 )
295 {
296 throw WrongFormatException( );
297 }
298
299 pStr[nStrLen++] = (sal_Unicode(c & 0x1F) << 6) | (char2 & 0x3F);
300 break;
301
302 case 14:
303 // 1110 xxxx 10xx xxxx 10xx xxxx
304 nCount += 3;
305 if( nCount > nUTFLen )
306 {
307 throw WrongFormatException( );
308 }
309
310 char2 = static_cast<sal_uInt8>(readByte());
311 char3 = static_cast<sal_uInt8>(readByte());
312
313 if( ((char2 & 0xC0) != 0x80) || ((char3 & 0xC0) != 0x80) ) {
314 throw WrongFormatException( );
315 }
316 pStr[nStrLen++] = (sal_Unicode(c & 0x0F) << 12) |
317 (sal_Unicode(char2 & 0x3F) << 6) |
318 (char3 & 0x3F);
319 break;
320
321 default:
322 // 10xx xxxx, 1111 xxxx
323 throw WrongFormatException();
324 //throw new UTFDataFormatException();
325 }
326 }
327 return OUString( pStr, nStrLen );
328}
329
330
331// XActiveDataSource
332void ODataInputStream::setInputStream(const Reference< XInputStream > & aStream)
333{
334
335 if( m_input != aStream ) {
336 m_input = aStream;
337
338 Reference < XConnectable > pred( m_input , UNO_QUERY );
339 setPredecessor( pred );
340 }
341
342 m_bValidStream = m_input.is();
343}
344
345Reference< XInputStream > ODataInputStream::getInputStream()
346{
347 return m_input;
348}
349
350
351// XDataSink
352void ODataInputStream::setSuccessor( const Reference < XConnectable > &r )
353{
355 if( m_succ != r ) {
357 m_succ = r;
358
359 if( m_succ.is() ) {
361 m_succ->setPredecessor( Reference< XConnectable > (
362 static_cast< XConnectable * >(this) ) );
363 }
364 }
365}
366
367Reference < XConnectable > ODataInputStream::getSuccessor()
368{
369 return m_succ;
370}
371
372
373// XDataSource
374void ODataInputStream::setPredecessor( const Reference < XConnectable > &r )
375{
376 if( r != m_pred ) {
377 m_pred = r;
378 if( m_pred.is() ) {
379 m_pred->setSuccessor( Reference< XConnectable > (
380 static_cast< XConnectable * >(this) ) );
381 }
382 }
383}
384Reference < XConnectable > ODataInputStream::getPredecessor()
385{
386 return m_pred;
387}
388
389// XServiceInfo
390OUString ODataInputStream::getImplementationName()
391{
392 return "com.sun.star.comp.io.stm.DataInputStream";
393}
394
395// XServiceInfo
396sal_Bool ODataInputStream::supportsService(const OUString& ServiceName)
397{
398 return cppu::supportsService(this, ServiceName);
399}
400
401// XServiceInfo
402Sequence< OUString > ODataInputStream::getSupportedServiceNames()
403{
404 return { "com.sun.star.io.DataInputStream" };
405}
406
407extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
409 css::uno::XComponentContext* , css::uno::Sequence<css::uno::Any> const&)
410{
411 return cppu::acquire(new ODataInputStream());
412}
413
414namespace {
415
416class ODataOutputStream :
417 public WeakImplHelper <
418 XDataOutputStream,
419 XActiveDataSource,
420 XConnectable,
421 XServiceInfo >
422{
423public:
424 ODataOutputStream()
425 : m_bValidStream( false )
426 {
427 }
428
429public: // 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;
433
434public: // 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;
444
445public: // XActiveDataSource
446 virtual void SAL_CALL setOutputStream(const Reference< XOutputStream > & aStream) override;
447 virtual Reference < XOutputStream > SAL_CALL getOutputStream() override;
448
449public: // 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;
454
455public: // XServiceInfo
456 OUString SAL_CALL getImplementationName() override;
457 Sequence< OUString > SAL_CALL getSupportedServiceNames() override;
458 sal_Bool SAL_CALL supportsService(const OUString& ServiceName) override;
459
460protected:
461 Reference < XConnectable > m_succ;
462 Reference < XConnectable > m_pred;
463 Reference< XOutputStream > m_output;
464 bool m_bValidStream;
465};
466
467}
468
469// XOutputStream
470void ODataOutputStream::writeBytes(const Sequence< sal_Int8 >& aData)
471{
472 if( !m_bValidStream )
473 throw NotConnectedException( );
474 m_output->writeBytes( aData );
475}
476
477void ODataOutputStream::flush()
478{
479 if( !m_bValidStream )
480 throw NotConnectedException();
481 m_output->flush();
482}
483
484
485void ODataOutputStream::closeOutput()
486{
487 if( !m_bValidStream )
488 throw NotConnectedException();
489 m_output->closeOutput();
490 setOutputStream( Reference< XOutputStream > () );
491 setPredecessor( Reference < XConnectable >() );
492 setSuccessor( Reference < XConnectable >() );
493}
494
495// XDataOutputStream
496void ODataOutputStream::writeBoolean(sal_Bool Value)
497{
498 if( Value )
499 {
500 writeByte( 1 );
501 }
502 else
503 {
504 writeByte( 0 );
505 }
506}
507
508
509void ODataOutputStream::writeByte(sal_Int8 Value)
510{
511 writeBytes( { Value } );
512}
513
514void ODataOutputStream::writeChar(sal_Unicode Value)
515{
516 writeBytes( { sal_Int8(Value >> 8),
517 sal_Int8(Value) } );
518}
519
520
521void ODataOutputStream::writeShort(sal_Int16 Value)
522{
523 writeBytes( { sal_Int8(Value >> 8),
524 sal_Int8(Value) } );
525}
526
527void ODataOutputStream::writeLong(sal_Int32 Value)
528{
529 writeBytes( { sal_Int8(Value >> 24),
530 sal_Int8(Value >> 16),
531 sal_Int8(Value >> 8),
532 sal_Int8(Value) } );
533}
534
535void ODataOutputStream::writeHyper(sal_Int64 Value)
536{
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),
544 sal_Int8(Value) } );
545}
546
547
548void ODataOutputStream::writeFloat(float Value)
549{
550 union { float f; sal_uInt32 n; } a;
551 a.f = Value;
552 writeLong( a.n );
553}
554
555void ODataOutputStream::writeDouble(double Value)
556{
557 union { double d; struct { sal_uInt32 n1; sal_uInt32 n2; } ad; } a;
558 a.d = Value;
559#if defined OSL_LITENDIAN
560 writeLong( a.ad.n2 );
561 writeLong( a.ad.n1 );
562#else
563 writeLong( a.ad.n1 );
564 writeLong( a.ad.n2 );
565#endif
566}
567
568void ODataOutputStream::writeUTF(const OUString& Value)
569{
570 sal_Int32 nStrLen = Value.getLength();
571 const sal_Unicode * pStr = Value.getStr();
572 sal_Int32 nUTFLen = 0;
573 sal_Int32 i;
574
575 for( i = 0 ; i < nStrLen ; i++ )
576 {
577 sal_uInt16 c = pStr[i];
578 if( (c >= 0x0001) && (c <= 0x007F) )
579 {
580 nUTFLen++;
581 }
582 else if( c > 0x07FF )
583 {
584 nUTFLen += 3;
585 }
586 else
587 {
588 nUTFLen += 2;
589 }
590 }
591
592
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 );
600 }
601 else {
602 writeShort( static_cast<sal_uInt16>(nUTFLen) );
603 }
604 for( i = 0 ; i < nStrLen ; i++ )
605 {
606 sal_uInt16 c = pStr[i];
607 if( (c >= 0x0001) && (c <= 0x007F) )
608 {
609 writeByte(sal_Int8(c));
610 }
611 else if( c > 0x07FF )
612 {
613 writeByte(sal_Int8(0xE0 | ((c >> 12) & 0x0F)));
614 writeByte(sal_Int8(0x80 | ((c >> 6) & 0x3F)));
615 writeByte(sal_Int8(0x80 | ((c >> 0) & 0x3F)));
616 }
617 else
618 {
619 writeByte(sal_Int8(0xC0 | ((c >> 6) & 0x1F)));
620 writeByte(sal_Int8(0x80 | ((c >> 0) & 0x3F)));
621 }
622 }
623}
624
625// XActiveDataSource
626void ODataOutputStream::setOutputStream(const Reference< XOutputStream > & aStream)
627{
628 if( m_output != aStream ) {
629 m_output = aStream;
631
632 Reference < XConnectable > succ( m_output , UNO_QUERY );
633 setSuccessor( succ );
634 }
635}
636
637Reference< XOutputStream > ODataOutputStream::getOutputStream()
638{
639 return m_output;
640}
641
642
643// XDataSink
644void ODataOutputStream::setSuccessor( const Reference < XConnectable > &r )
645{
647 if( m_succ != r )
648 {
650 m_succ = r;
651
652 if( m_succ.is() )
653 {
655 m_succ->setPredecessor( Reference < XConnectable > (
656 static_cast< XConnectable * >(this) ));
657 }
658 }
659}
660Reference < XConnectable > ODataOutputStream::getSuccessor()
661{
662 return m_succ;
663}
664
665
666// XDataSource
667void ODataOutputStream::setPredecessor( const Reference < XConnectable > &r )
668{
669 if( r != m_pred ) {
670 m_pred = r;
671 if( m_pred.is() ) {
672 m_pred->setSuccessor( Reference< XConnectable > (
673 static_cast< XConnectable * >(this) ));
674 }
675 }
676}
677Reference < XConnectable > ODataOutputStream::getPredecessor()
678{
679 return m_pred;
680}
681
682
683// XServiceInfo
684OUString ODataOutputStream::getImplementationName()
685{
686 return "com.sun.star.comp.io.stm.DataOutputStream";
687}
688
689// XServiceInfo
690sal_Bool ODataOutputStream::supportsService(const OUString& ServiceName)
691{
692 return cppu::supportsService(this, ServiceName);
693}
694
695// XServiceInfo
696Sequence< OUString > ODataOutputStream::getSupportedServiceNames()
697{
698 return { "com.sun.star.io.DataOutputStream" };
699}
700
701extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
703 css::uno::XComponentContext* , css::uno::Sequence<css::uno::Any> const&)
704{
705 return cppu::acquire(new ODataOutputStream());
706}
707
708namespace {
709
710struct equalObjectContainer_Impl
711{
712 bool operator()(const Reference< XInterface > & s1,
713 const Reference< XInterface > & s2) const
714 {
715 return s1 == s2;
716 }
717};
718
719
720struct hashObjectContainer_Impl
721{
722 size_t operator()(const Reference< XInterface > & xRef) const
723 {
724 return reinterpret_cast<size_t>(xRef.get());
725 }
726};
727
728}
729
730typedef std::unordered_map
731<
732 Reference< XInterface >,
733 sal_Int32,
734 hashObjectContainer_Impl,
735 equalObjectContainer_Impl
737
738namespace {
739
740class OObjectOutputStream:
741 public ImplInheritanceHelper<
742 ODataOutputStream, /* parent */
743 XObjectOutputStream, XMarkableStream >
744{
745public:
746 OObjectOutputStream()
747 : m_nMaxId(0) ,
748 m_bValidMarkable(false)
749 {
750 }
751
752public:
753 // XOutputStream
754 virtual void SAL_CALL writeBytes(const Sequence< sal_Int8 >& aData) override
755 { ODataOutputStream::writeBytes( aData ); }
756
757 virtual void SAL_CALL flush() override
758 { ODataOutputStream::flush(); }
759
760 virtual void SAL_CALL closeOutput() override
761 { ODataOutputStream::closeOutput(); }
762
763public:
764 // XDataOutputStream
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 );}
783
784 // XObjectOutputStream
785 virtual void SAL_CALL writeObject( const Reference< XPersistObject > & r ) override;
786
787public: // 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;
793
794public: // XServiceInfo
795 OUString SAL_CALL getImplementationName() override;
796 Sequence< OUString > SAL_CALL getSupportedServiceNames() override;
797 sal_Bool SAL_CALL supportsService(const OUString& ServiceName) override;
798
799private:
800 void connectToMarkable();
801private:
803 sal_Int32 m_nMaxId;
804 Reference< XMarkableStream > m_rMarkable;
806};
807
808}
809
810void OObjectOutputStream::writeObject( const Reference< XPersistObject > & xPObj )
811{
812
813 connectToMarkable();
814 bool bWriteObj = false;
815 // create Mark to write length of info
816 sal_uInt32 nInfoLenMark = m_rMarkable->createMark();
817
818 // length of the info data (is later rewritten)
819 OObjectOutputStream::writeShort( 0 );
820
821 // write the object identifier
822 if( xPObj.is() )
823 {
824 Reference< XInterface > rX( xPObj , UNO_QUERY );
825
826 ObjectContainer_Impl::const_iterator aIt
827 = m_mapObject.find( rX );
828 if( aIt == m_mapObject.end() )
829 {
830 // insert new object in hash table
831 m_mapObject[ rX ] = ++m_nMaxId;
832 ODataOutputStream::writeLong( m_nMaxId );
833 ODataOutputStream::writeUTF( xPObj->getServiceName() );
834 bWriteObj = true;
835 }
836 else
837 {
838 ODataOutputStream::writeLong( (*aIt).second );
839 ODataOutputStream::writeUTF( OUString() );
840 }
841 }
842 else
843 {
844 ODataOutputStream::writeLong( 0 );
845 ODataOutputStream::writeUTF( OUString() );
846 }
847
848 sal_uInt32 nObjLenMark = m_rMarkable->createMark();
849 ODataOutputStream::writeLong( 0 );
850
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();
857
858 if( bWriteObj )
859 xPObj->write( Reference< XObjectOutputStream > (
860 static_cast< XObjectOutputStream * >(this) ) );
861
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();
868
869 m_rMarkable->deleteMark( nObjLenMark );
870 m_rMarkable->deleteMark( nInfoLenMark );
871}
872
873
874void OObjectOutputStream::connectToMarkable()
875{
876 if( m_bValidMarkable )
877 return;
878
879 if( ! m_bValidStream )
880 throw NotConnectedException();
881
882 // find the markable stream !
883 Reference< XInterface > rTry(m_output);
884 while( true ) {
885 if( ! rTry.is() )
886 {
887 throw NotConnectedException();
888 }
889 Reference < XMarkableStream > markable( rTry , UNO_QUERY );
890 if( markable.is() )
891 {
892 m_rMarkable = markable;
893 break;
894 }
895 Reference < XActiveDataSource > source( rTry , UNO_QUERY );
896 rTry = source;
897 }
898 m_bValidMarkable = true;
899}
900
901
902sal_Int32 OObjectOutputStream::createMark()
903{
904 connectToMarkable(); // throws an exception, if a markable is not connected !
905
906 return m_rMarkable->createMark();
907}
908
909void OObjectOutputStream::deleteMark(sal_Int32 Mark)
910{
911 if( ! m_bValidMarkable )
912 {
913 throw NotConnectedException();
914 }
915 m_rMarkable->deleteMark( Mark );
916}
917
918void OObjectOutputStream::jumpToMark(sal_Int32 nMark)
919{
920 if( ! m_bValidMarkable )
921 {
922 throw NotConnectedException();
923 }
924 m_rMarkable->jumpToMark( nMark );
925}
926
927
928void OObjectOutputStream::jumpToFurthest()
929{
930 connectToMarkable();
931 m_rMarkable->jumpToFurthest();
932}
933
934sal_Int32 OObjectOutputStream::offsetToMark(sal_Int32 nMark)
935{
936 if( ! m_bValidMarkable )
937 {
938 throw NotConnectedException();
939 }
940 return m_rMarkable->offsetToMark( nMark );
941}
942
943// XServiceInfo
944OUString OObjectOutputStream::getImplementationName()
945{
946 return "com.sun.star.comp.io.stm.ObjectOutputStream";
947}
948
949// XServiceInfo
950sal_Bool OObjectOutputStream::supportsService(const OUString& ServiceName)
951{
952 return cppu::supportsService(this, ServiceName);
953}
954
955// XServiceInfo
956Sequence< OUString > OObjectOutputStream::getSupportedServiceNames()
957{
958 return { "com.sun.star.io.ObjectOutputStream" };
959}
960
961extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
963 css::uno::XComponentContext* , css::uno::Sequence<css::uno::Any> const&)
964{
965 return cppu::acquire(new OObjectOutputStream());
966}
967
968namespace {
969
970class OObjectInputStream:
971 public ImplInheritanceHelper<
972 ODataInputStream, /* parent */
973 XObjectInputStream, XMarkableStream >
974{
975public:
976 explicit OObjectInputStream( const Reference < XComponentContext > &r)
977 : m_rSMgr( r->getServiceManager() )
978 , m_rCxt( r )
979 , m_bValidMarkable(false)
980 {
981 }
982
983public: // XInputStream
984 virtual sal_Int32 SAL_CALL readBytes(Sequence< sal_Int8 >& aData, sal_Int32 nBytesToRead) override
985 { return ODataInputStream::readBytes( aData , nBytesToRead ); }
986
987 virtual sal_Int32 SAL_CALL readSomeBytes(Sequence< sal_Int8 >& aData, sal_Int32 nMaxBytesToRead) override
988 { return ODataInputStream::readSomeBytes( aData, nMaxBytesToRead ); }
989
990 virtual void SAL_CALL skipBytes(sal_Int32 nBytesToSkip) override
991 { ODataInputStream::skipBytes( nBytesToSkip ); }
992
993 virtual sal_Int32 SAL_CALL available() override
994 { return ODataInputStream::available(); }
995
996 virtual void SAL_CALL closeInput() override
997 { ODataInputStream::closeInput(); }
998
999public: // 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(); }
1018
1019public: // XObjectInputStream
1020 virtual Reference< XPersistObject > SAL_CALL readObject( ) override;
1021
1022public: // 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;
1028
1029public: // XServiceInfo
1030 OUString SAL_CALL getImplementationName() override;
1031 Sequence< OUString > SAL_CALL getSupportedServiceNames() override;
1032 sal_Bool SAL_CALL supportsService(const OUString& ServiceName) override;
1033
1034private:
1035 void connectToMarkable();
1036private:
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;
1042
1043};
1044
1045}
1046
1047Reference< XPersistObject > OObjectInputStream::readObject()
1048{
1049 // check if chain contains a XMarkableStream
1050 connectToMarkable();
1051
1052 Reference< XPersistObject > xLoadedObj;
1053
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());
1058 if( nLen < 0xc )
1059 {
1060 throw WrongFormatException();
1061 }
1062
1063 // read the object identifier
1064 sal_uInt32 nId = readLong();
1065
1066 // the name of the persist model
1067 // MM ???
1068 OUString aName = readUTF();
1069
1070 // Read the length of the object
1071 sal_Int32 nObjLen = readLong();
1072 if( 0 == nId && 0 != nObjLen )
1073 {
1074 throw WrongFormatException();
1075 }
1076
1077 // skip data of new version
1078 skipBytes( nLen - m_rMarkable->offsetToMark( nMark ) );
1079
1080 bool bLoadSuccessful = true;
1081 if( nId )
1082 {
1083 if( !aName.isEmpty() )
1084 {
1085 // load the object
1086 Reference< XInterface > x = m_rSMgr->createInstanceWithContext( aName, m_rCxt );
1087 xLoadedObj.set( x, UNO_QUERY );
1088 if( xLoadedObj.is() )
1089 {
1090 sal_uInt32 nSize = m_aPersistVector.size();
1091 if( nSize <= nId )
1092 {
1093 // grow to the right size
1094 Reference< XPersistObject > xEmpty;
1095 m_aPersistVector.insert( m_aPersistVector.end(), nId - nSize + 1, xEmpty );
1096 }
1097
1098 m_aPersistVector[nId] = xLoadedObj;
1099 xLoadedObj->read( Reference< XObjectInputStream >(
1100 static_cast< XObjectInputStream * >(this) ) );
1101 }
1102 else
1103 {
1104 // no service with this name could be instantiated
1105 bLoadSuccessful = false;
1106 }
1107 }
1108 else {
1109 if (nId >= m_aPersistVector.size())
1110 {
1111 // id unknown, load failure !
1112 bLoadSuccessful = false;
1113 }
1114 else
1115 {
1116 // Object has already been read,
1117 xLoadedObj = m_aPersistVector[nId];
1118 }
1119 }
1120 }
1121
1122 // skip to the position behind the object
1123 skipBytes( nObjLen + nLen - m_rMarkable->offsetToMark( nMark ) );
1124 m_rMarkable->deleteMark( nMark );
1125
1126 if( ! bLoadSuccessful )
1127 {
1128 throw WrongFormatException();
1129 }
1130 return xLoadedObj;
1131}
1132
1133
1134void OObjectInputStream::connectToMarkable()
1135{
1136 if( m_bValidMarkable ) return;
1137
1138 if( ! m_bValidStream )
1139 {
1140 throw NotConnectedException( );
1141 }
1142
1143 // find the markable stream !
1144 Reference< XInterface > rTry(m_input);
1145 while( true ) {
1146 if( ! rTry.is() )
1147 {
1148 throw NotConnectedException( );
1149 }
1150 Reference< XMarkableStream > markable( rTry , UNO_QUERY );
1151 if( markable.is() )
1152 {
1153 m_rMarkable = markable;
1154 break;
1155 }
1156 Reference < XActiveDataSink > sink( rTry , UNO_QUERY );
1157 rTry = sink;
1158 }
1159 m_bValidMarkable = true;
1160}
1161
1162sal_Int32 OObjectInputStream::createMark()
1163{
1164 connectToMarkable(); // throws an exception, if a markable is not connected !
1165
1166 return m_rMarkable->createMark();
1167}
1168
1169void OObjectInputStream::deleteMark(sal_Int32 Mark)
1170{
1171 if( ! m_bValidMarkable )
1172 {
1173 throw NotConnectedException();
1174 }
1175 m_rMarkable->deleteMark( Mark );
1176}
1177
1178void OObjectInputStream::jumpToMark(sal_Int32 nMark)
1179{
1180 if( ! m_bValidMarkable )
1181 {
1182 throw NotConnectedException();
1183 }
1184 m_rMarkable->jumpToMark( nMark );
1185}
1186void OObjectInputStream::jumpToFurthest()
1187{
1188 connectToMarkable();
1189 m_rMarkable->jumpToFurthest();
1190}
1191
1192sal_Int32 OObjectInputStream::offsetToMark(sal_Int32 nMark)
1193{
1194 if( ! m_bValidMarkable )
1195 {
1196 throw NotConnectedException();
1197 }
1198 return m_rMarkable->offsetToMark( nMark );
1199}
1200
1201// XServiceInfo
1202OUString OObjectInputStream::getImplementationName()
1203{
1204 return "com.sun.star.comp.io.stm.ObjectInputStream";
1205}
1206
1207// XServiceInfo
1208sal_Bool OObjectInputStream::supportsService(const OUString& ServiceName)
1209{
1210 return cppu::supportsService(this, ServiceName);
1211}
1212
1213// XServiceInfo
1214Sequence< OUString > OObjectInputStream::getSupportedServiceNames()
1215{
1216 return { "com.sun.star.io.ObjectInputStream" };
1217}
1218
1219extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
1221 css::uno::XComponentContext* context, css::uno::Sequence<css::uno::Any> const&)
1222{
1223 return cppu::acquire(new OObjectInputStream(context));
1224}
1225
1226}
1227
1228
1229/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
double d
int nCount
float x
OUString aName
sal_Int64 n
uno_Any a
int n2
int n1
constexpr OUStringLiteral aData
css::uno::Sequence< OUString > getSupportedServiceNames()
OUString getImplementationName()
bool CPPUHELPER_DLLPUBLIC supportsService(css::lang::XServiceInfo *implementation, rtl::OUString const &name)
Value
int i
Definition: odata.cxx:47
SAL_DLLPUBLIC_EXPORT css::uno::XInterface * io_OObjectInputStream_get_implementation(css::uno::XComponentContext *context, css::uno::Sequence< css::uno::Any > const &)
Definition: odata.cxx:1220
SAL_DLLPUBLIC_EXPORT css::uno::XInterface * io_ODataInputStream_get_implementation(css::uno::XComponentContext *, css::uno::Sequence< css::uno::Any > const &)
Definition: odata.cxx:408
std::unordered_map< Reference< XInterface >, sal_Int32, hashObjectContainer_Impl, equalObjectContainer_Impl > ObjectContainer_Impl
Definition: odata.cxx:736
SAL_DLLPUBLIC_EXPORT css::uno::XInterface * io_ODataOutputStream_get_implementation(css::uno::XComponentContext *, css::uno::Sequence< css::uno::Any > const &)
Definition: odata.cxx:702
SAL_DLLPUBLIC_EXPORT css::uno::XInterface * io_OObjectOutputStream_get_implementation(css::uno::XComponentContext *, css::uno::Sequence< css::uno::Any > const &)
Definition: odata.cxx:962
bool getOutputStream(ProgramOptions const &options, OString const &extension, std::ostream **ppOutputStream, OString &targetSourceFileName, OString &tmpSourceFileName)
sal_Int32 m_nMaxId
Definition: odata.cxx:803
Reference< XConnectable > m_succ
Definition: odata.cxx:103
bool m_bValidMarkable
Definition: odata.cxx:805
std::vector< Reference< XPersistObject > > m_aPersistVector
Definition: odata.cxx:1041
Reference< XOutputStream > m_output
Definition: odata.cxx:463
Reference< XConnectable > m_pred
Definition: odata.cxx:102
bool m_bValidStream
Definition: odata.cxx:105
Reference< XInputStream > m_input
Definition: odata.cxx:104
Reference< XMarkableStream > m_rMarkable
Definition: odata.cxx:804
Reference< XMultiComponentFactory > m_rSMgr
Definition: odata.cxx:1037
ObjectContainer_Impl m_mapObject
Definition: odata.cxx:802
Reference< XComponentContext > m_rCxt
Definition: odata.cxx:1038
sal_Int16 nId
unsigned char sal_uInt8
unsigned char sal_Bool
sal_uInt16 sal_Unicode
signed char sal_Int8
std::unique_ptr< char[]> aBuffer