merge the formfield patch from ooo-build
[ooovba.git] / configmgr / source / backend / binaryreader.cxx
blobfcf971a8ba35ba1cf63868bbd83b5e264d5995d2
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: binaryreader.cxx,v $
10 * $Revision: 1.10 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_configmgr.hxx"
34 #include "binaryreader.hxx"
35 #include "binarytype.hxx"
36 #include "valuenode.hxx"
37 #include "filehelper.hxx"
38 #include "oslstream.hxx"
41 #include <com/sun/star/uno/Type.hxx>
42 #include <com/sun/star/uno/Any.hxx>
43 #include <com/sun/star/io/IOException.hpp>
44 #include <com/sun/star/io/XOutputStream.hpp>
45 #include <com/sun/star/io/XActiveDataSource.hpp>
46 #include <com/sun/star/io/XDataInputStream.hpp>
47 #include <com/sun/star/io/XDataOutputStream.hpp>
48 #include <com/sun/star/io/BufferSizeExceededException.hpp>
49 #include <com/sun/star/io/UnexpectedEOFException.hpp>
51 #include <cppuhelper/implbase1.hxx>
52 #include <osl/file.hxx>
54 #ifndef INCLUDED_ALGORITHM
55 #include <algorithm>
56 #define INCLUDED_ALGORITHM
57 #endif
58 #include "tracer.hxx"
60 #define ASCII(x) rtl::OUString::createFromAscii(x)
62 namespace configmgr
64 // -----------------------------------------------------------------------------
65 namespace backend
67 namespace uno = com::sun::star::uno;
68 namespace io = com::sun::star::io;
71 // --------------------------------------------------------------------------
73 inline rtl::OUString ErrorToMessage_Impl (osl::FileBase::RC eError)
75 return FileHelper::createOSLErrorString (eError);
78 // --------------------------------------------------------------------------
80 class BinaryReader_Impl :
81 public cppu::WeakImplHelper1< com::sun::star::io::XDataInputStream >
83 public:
84 /** Construction.
86 explicit BinaryReader_Impl (rtl::OUString const & rFileUrl)
87 SAL_THROW( (io::IOException, uno::RuntimeException) );
89 /** XInputStream.
91 virtual sal_Int32 SAL_CALL readBytes (
92 uno::Sequence<sal_Int8> & rData, sal_Int32 nBytesToRead)
93 throw (
94 io::NotConnectedException,
95 io::BufferSizeExceededException,
96 io::IOException, uno::RuntimeException);
98 virtual sal_Int32 SAL_CALL readSomeBytes (
99 uno::Sequence<sal_Int8> & rData, sal_Int32 nBytesToRead)
100 throw (
101 io::NotConnectedException,
102 io::BufferSizeExceededException,
103 io::IOException, uno::RuntimeException);
105 virtual void SAL_CALL skipBytes (sal_Int32 nBytesToSkip)
106 throw (
107 io::NotConnectedException,
108 io::BufferSizeExceededException,
109 io::IOException, uno::RuntimeException);
111 virtual sal_Int32 SAL_CALL available()
112 throw (
113 io::NotConnectedException,
114 io::IOException, uno::RuntimeException);
116 virtual void SAL_CALL closeInput()
117 throw (
118 io::NotConnectedException,
119 io::IOException, uno::RuntimeException);
122 /** XDataInputStream.
124 virtual sal_Int8 SAL_CALL readBoolean()
125 throw (
126 io::IOException, uno::RuntimeException);
128 virtual sal_Int8 SAL_CALL readByte()
129 throw (
130 io::IOException, uno::RuntimeException);
132 virtual sal_Unicode SAL_CALL readChar()
133 throw (
134 io::IOException, uno::RuntimeException);
136 virtual sal_Int16 SAL_CALL readShort()
137 throw (
138 io::IOException, uno::RuntimeException);
140 virtual sal_Int32 SAL_CALL readLong()
141 throw (
142 io::IOException, uno::RuntimeException);
144 virtual sal_Int64 SAL_CALL readHyper()
145 throw (
146 io::IOException, uno::RuntimeException);
148 virtual float SAL_CALL readFloat()
149 throw (
150 io::IOException, uno::RuntimeException);
152 virtual double SAL_CALL readDouble()
153 throw (
154 io::IOException, uno::RuntimeException);
156 virtual rtl::OUString SAL_CALL readUTF()
157 throw (
158 io::IOException, uno::RuntimeException);
160 protected:
161 /** Destruction.
163 virtual ~BinaryReader_Impl();
165 private:
166 sal_uInt32 checkAvail(); // may throw NotConnectedException
167 sal_uInt32 getMaxAvail(sal_Int32 nRequest); // may throw NotConnectedException, BufferSizeExceededException
168 sal_uInt8 const * readBuffer(sal_uInt32 nRequired); // may throw NotConnectedException, UnexpectedEOFException
169 private:
170 /** Representation.
172 sal_uInt8 * m_pBuffer;
173 sal_uInt32 m_nLength;
174 sal_uInt32 m_nOffset;
176 /** Not implemented.
178 BinaryReader_Impl (const BinaryReader_Impl&);
179 BinaryReader_Impl& operator= (const BinaryReader_Impl&);
182 // --------------------------------------------------------------------------
183 static inline void checkIOError(osl::File::RC errcode)
185 if (errcode != osl::FileBase::E_None)
187 throw io::IOException (ErrorToMessage_Impl (errcode), NULL);
190 static void raiseBufferError()
192 rtl::OUString sMsg = rtl::OUString::createFromAscii("Cannot allocate Buffer: Too large");
193 throw io:: BufferSizeExceededException(sMsg, NULL);
195 // -------------------------------------------------------------------------
196 BinaryReader_Impl::BinaryReader_Impl (rtl::OUString const & rFileUrl)
197 SAL_THROW( (io::IOException, uno::RuntimeException) )
198 : m_pBuffer (0)
199 , m_nLength (0)
200 , m_nOffset (0)
202 osl::File aFile (rFileUrl);
204 checkIOError( aFile.open (OpenFlag_Read) );
205 sal_uInt64 nLength = 0;
206 checkIOError( aFile.getSize (nLength) );
207 if (nLength > 0xffffffff)
208 raiseBufferError();
209 m_nLength = sal_uInt32(nLength);
211 sal_uInt8 *pBuffer = static_cast<sal_uInt8*>(rtl_allocateMemory (m_nLength));
212 if (!pBuffer)
213 raiseBufferError();
215 sal_uInt64 nRead = 0;
216 osl::File::RC result = aFile.read (pBuffer, nLength, nRead);
217 if (result != osl::FileBase::E_None)
219 rtl_freeMemory (pBuffer);
220 checkIOError( result );
222 if (nRead != nLength)
224 rtl_freeMemory (pBuffer);
225 rtl::OUString sMsg = rtl::OUString::createFromAscii("BinaryCache - Could not read entire size of file: ");
226 throw io::UnexpectedEOFException(sMsg.concat(rFileUrl),NULL);
228 m_pBuffer = pBuffer;
231 // --------------------------------------------------------------------------
233 BinaryReader_Impl::~BinaryReader_Impl()
235 if (m_pBuffer) rtl_freeMemory (m_pBuffer);
238 // --------------------------------------------------------------------------
239 // XInputStream implementation.
240 // --------------------------------------------------------------------------
241 sal_uInt32 BinaryReader_Impl::checkAvail ()
243 if (!m_pBuffer)
245 rtl::OUString sMsg = rtl::OUString::createFromAscii("BinaryCache - Stream is not open. No data available for reading.");
246 throw io::NotConnectedException(sMsg,*this);
248 OSL_ASSERT(m_nLength >= m_nOffset);
249 return m_nLength - m_nOffset;
251 // --------------------------------------------------------------------------
253 sal_uInt32 BinaryReader_Impl::getMaxAvail (sal_Int32 nRequest)
255 if (nRequest < 0)
257 rtl::OUString sMsg = rtl::OUString::createFromAscii("BinaryCache - Invalid read request - negative byte count requested.");
258 throw io::BufferSizeExceededException(sMsg,*this);
260 sal_uInt32 const uRequest = sal_uInt32(nRequest);
261 sal_uInt32 const uAvail = checkAvail ();
262 return std::min(uRequest,uAvail);
264 // --------------------------------------------------------------------------
266 sal_uInt8 const * BinaryReader_Impl::readBuffer (sal_uInt32 nRequest)
268 sal_uInt32 const nAvail = checkAvail ();
269 if (nRequest > nAvail)
271 rtl::OUString sMsg = rtl::OUString::createFromAscii("BinaryCache - Invalid file format - read past end-of-file.");
272 throw io::UnexpectedEOFException(sMsg,*this);
274 sal_uInt8 const * pData = m_pBuffer + m_nOffset;
275 m_nOffset += nRequest;
276 return pData;
278 // --------------------------------------------------------------------------
280 sal_Int32 SAL_CALL BinaryReader_Impl::readBytes (
281 uno::Sequence<sal_Int8> & rData, sal_Int32 nBytesToRead)
282 throw (
283 io::NotConnectedException,
284 io::BufferSizeExceededException,
285 io::IOException, uno::RuntimeException)
287 sal_uInt32 nRead = getMaxAvail(nBytesToRead);
288 if (nRead > 0)
290 rData.realloc (nRead);
291 memcpy (rData.getArray(), readBuffer(nRead), nRead);
293 return sal_Int32(nRead);
296 // --------------------------------------------------------------------------
298 sal_Int32 SAL_CALL BinaryReader_Impl::readSomeBytes (
299 uno::Sequence<sal_Int8> & rData, sal_Int32 nBytesToRead)
300 throw (
301 io::NotConnectedException,
302 io::BufferSizeExceededException,
303 io::IOException, uno::RuntimeException)
305 return readBytes(rData,nBytesToRead);
308 // --------------------------------------------------------------------------
310 void SAL_CALL BinaryReader_Impl::skipBytes (sal_Int32 nBytesToSkip)
311 throw (
312 io::NotConnectedException,
313 io::BufferSizeExceededException,
314 io::IOException, uno::RuntimeException)
316 (void) readBuffer(sal_uInt32(nBytesToSkip));
319 // --------------------------------------------------------------------------
321 sal_Int32 SAL_CALL BinaryReader_Impl::available()
322 throw (
323 io::NotConnectedException,
324 io::IOException, uno::RuntimeException)
326 const sal_uInt32 nMaxAvail = 0x7FFFFFFF;
327 const sal_uInt32 nAvail = checkAvail();
328 return sal_Int32(std::min(nAvail,nMaxAvail));
331 // --------------------------------------------------------------------------
333 void SAL_CALL BinaryReader_Impl::closeInput()
334 throw (
335 io::NotConnectedException,
336 io::IOException, uno::RuntimeException)
338 OSL_ENSURE(m_pBuffer,"BinaryCache - Closing stream that is already closed");
339 if (m_pBuffer)
341 rtl_freeMemory (m_pBuffer);
342 m_pBuffer = 0;
346 // --------------------------------------------------------------------------
347 // XDataInputStream implementation.
348 // --------------------------------------------------------------------------
350 sal_Int8 SAL_CALL BinaryReader_Impl::readBoolean()
351 throw (io::IOException, uno::RuntimeException)
353 return this->readByte();
356 // --------------------------------------------------------------------------
358 sal_Int8 SAL_CALL BinaryReader_Impl::readByte()
359 throw (io::IOException, uno::RuntimeException)
361 sal_Int8 result = sal_Int8(*readBuffer(1));
363 return result;
366 // --------------------------------------------------------------------------
368 sal_Unicode SAL_CALL BinaryReader_Impl::readChar()
369 throw (io::IOException, uno::RuntimeException)
371 sal_Unicode result;
373 sal_uInt8 const * pData = readBuffer(sizeof result);
375 result = sal_Unicode(
376 (sal_uInt16(pData[0]) << 8) |
377 (sal_uInt16(pData[1]) << 0) );
379 return result;
382 // --------------------------------------------------------------------------
384 sal_Int16 SAL_CALL BinaryReader_Impl::readShort()
385 throw (io::IOException, uno::RuntimeException)
387 sal_Int16 result;
389 sal_uInt8 const * pData = readBuffer(sizeof result);
391 result = sal_Int16(
392 (sal_uInt16(pData[0]) << 8) |
393 (sal_uInt16(pData[1]) << 0) );
395 return result;
398 // --------------------------------------------------------------------------
400 sal_Int32 SAL_CALL BinaryReader_Impl::readLong()
401 throw (io::IOException, uno::RuntimeException)
403 sal_Int32 result;
405 sal_uInt8 const * pData = readBuffer(sizeof result);
407 result = sal_Int32(
408 (sal_uInt32(pData[0]) << 24) |
409 (sal_uInt32(pData[1]) << 16) |
410 (sal_uInt32(pData[2]) << 8) |
411 (sal_uInt32(pData[3]) << 0) );
413 return result;
416 // --------------------------------------------------------------------------
418 sal_Int64 SAL_CALL BinaryReader_Impl::readHyper()
419 throw (io::IOException, uno::RuntimeException)
421 sal_Int64 result;
423 sal_uInt8 const * pData = readBuffer(sizeof result);
425 result = sal_Int64(
426 (sal_uInt64(pData[0]) << 56) |
427 (sal_uInt64(pData[1]) << 48) |
428 (sal_uInt64(pData[2]) << 40) |
429 (sal_uInt64(pData[3]) << 32) |
430 (sal_uInt64(pData[4]) << 24) |
431 (sal_uInt64(pData[5]) << 16) |
432 (sal_uInt64(pData[6]) << 8) |
433 (sal_uInt64(pData[7]) << 0) );
435 return result;
438 // --------------------------------------------------------------------------
440 float SAL_CALL BinaryReader_Impl::readFloat()
441 throw (io::IOException, uno::RuntimeException)
443 union { float f; sal_uInt32 n; } result;
445 sal_uInt8 const * pData = readBuffer(sizeof result.n);
447 result.n = sal_uInt32(
448 (sal_uInt32(pData[0]) << 24) |
449 (sal_uInt32(pData[1]) << 16) |
450 (sal_uInt32(pData[2]) << 8) |
451 (sal_uInt32(pData[3]) << 0) );
453 return result.f;
456 // --------------------------------------------------------------------------
458 double SAL_CALL BinaryReader_Impl::readDouble()
459 throw (io::IOException, uno::RuntimeException)
461 union { double d; sal_uInt64 n; } result;
463 sal_uInt8 const * pData = readBuffer(sizeof result.n);
465 result.n = sal_uInt64(
466 (sal_uInt64(pData[0]) << 56) |
467 (sal_uInt64(pData[1]) << 48) |
468 (sal_uInt64(pData[2]) << 40) |
469 (sal_uInt64(pData[3]) << 32) |
470 (sal_uInt64(pData[4]) << 24) |
471 (sal_uInt64(pData[5]) << 16) |
472 (sal_uInt64(pData[6]) << 8) |
473 (sal_uInt64(pData[7]) << 0) );
475 return result.d;
478 // --------------------------------------------------------------------------
480 rtl::OUString SAL_CALL BinaryReader_Impl::readUTF()
481 throw (io::IOException, uno::RuntimeException)
483 sal_uInt32 nLength;
485 sal_uInt8 const * const pData = readBuffer(sizeof nLength);
487 nLength = sal_uInt32(
488 (sal_uInt32(pData[0]) << 24) |
489 (sal_uInt32(pData[1]) << 16) |
490 (sal_uInt32(pData[2]) << 8) |
491 (sal_uInt32(pData[3]) << 0) );
493 bool bIsAscii = (nLength & binary::STR_ASCII_MASK) == binary::STR_ASCII_MASK;
494 nLength &=~binary::STR_ASCII_MASK;
496 rtl::OUString result;
497 if (nLength != 0)
499 sal_Char const * const pUTF = reinterpret_cast<sal_Char const * >(readBuffer(nLength));
501 sal_Int32 const nStrLength = sal_Int32(nLength);
502 OSL_ASSERT(nStrLength >= 0);
504 rtl_TextEncoding const enc = bIsAscii ? RTL_TEXTENCODING_ASCII_US : RTL_TEXTENCODING_UTF8;
506 rtl_uString_internConvert(&result.pData, pUTF, nStrLength, enc,
507 OSTRING_TO_OUSTRING_CVTFLAGS, NULL);
510 return result;
513 // --------------------------------------------------------------------------
514 // BinaryReader implementation.
515 // --------------------------------------------------------------------------
517 BinaryReader::BinaryReader(rtl::OUString const & _sFileURL):
518 m_sFileURL(_sFileURL) {}
520 BinaryReader::~BinaryReader() {}
522 bool BinaryReader::open()
523 SAL_THROW( (io::IOException, uno::RuntimeException) )
525 OSL_PRECOND(!m_xDataInputStream.is(),"Binary Reader: already open");
526 if (m_xDataInputStream.is())
527 return false;
529 if (m_sFileURL.getLength() == 0)
530 return false;
532 if (!FileHelper::fileExists(m_sFileURL))
533 return false;
535 m_xDataInputStream.set(new BinaryReader_Impl (m_sFileURL));
536 return true;
539 // --------------------------------------------------------------------------
541 inline BinaryReader_Impl * BinaryReader::getDataInputStream()
543 OSL_ENSURE(m_xDataInputStream.is(),"Binary Cache: Reader was not opened - no input stream");
544 return m_xDataInputStream.get();
547 // --------------------------------------------------------------------------
549 void BinaryReader::read(sal_Bool &_bValue)
550 SAL_THROW( (io::IOException, uno::RuntimeException) )
552 _bValue = getDataInputStream()->readBoolean();
555 // --------------------------------------------------------------------------
557 void BinaryReader::read(sal_Int8 &_nValue)
558 SAL_THROW( (io::IOException, uno::RuntimeException) )
560 _nValue = getDataInputStream()->readByte();
563 // --------------------------------------------------------------------------
565 void BinaryReader::read(sal_Int16 &_nValue)
566 SAL_THROW( (io::IOException, uno::RuntimeException) )
568 _nValue = getDataInputStream()->readShort();
571 // --------------------------------------------------------------------------
573 void BinaryReader::read(sal_Int32 &_nValue)
574 SAL_THROW( (io::IOException, uno::RuntimeException) )
576 _nValue = getDataInputStream()->readLong();
579 // --------------------------------------------------------------------------
581 void BinaryReader::read(sal_Int64 &_nValue)
582 SAL_THROW( (io::IOException, uno::RuntimeException) )
584 _nValue = getDataInputStream()->readHyper();
587 // --------------------------------------------------------------------------
589 void BinaryReader::read(double &_nValue)
590 SAL_THROW( (io::IOException, uno::RuntimeException) )
592 _nValue = getDataInputStream()->readDouble();
595 // --------------------------------------------------------------------------
597 void BinaryReader::read(rtl::OUString& _aStr)
598 SAL_THROW( (io::IOException, uno::RuntimeException) )
600 _aStr = getDataInputStream()->readUTF();
603 // -----------------------------------------------------------------------------
604 template <class Element>
605 void readSequence(BinaryReader& _rReader, uno::Sequence< Element > & aSequence)
606 SAL_THROW( (io::IOException, uno::RuntimeException) )
608 // PRE: the Sequence must exist
609 sal_Int32 nLength;
610 _rReader.read(nLength);
612 aSequence.realloc(nLength);
614 Element* const pElement = aSequence.getArray(); // fill the hole array
615 for(sal_Int32 i=0; i<nLength; ++i)
617 _rReader.read(pElement[i]); // read one element
621 // --------------------------------------------------------------------------
623 void BinaryReader::read (uno::Sequence< sal_Int8 > &_aValue)
624 SAL_THROW( (io::IOException, uno::RuntimeException) )
626 readSequence(*this, _aValue);
629 // --------------------------------------------------------------------------
631 void BinaryReader::read (uno::Sequence< rtl::OUString > &_aValue)
632 SAL_THROW( (io::IOException, uno::RuntimeException) )
634 readSequence(*this, _aValue);
637 // --------------------------------------------------------------------------
639 uno::Sequence< sal_Int8 > const * const for_binary = 0;
641 #define CASE_READ_SEQUENCE(TYPE_CLASS, DATA_TYPE) \
642 case TYPE_CLASS: \
644 OSL_ENSURE( ::getCppuType(static_cast<DATA_TYPE const*>(0)).getTypeClass() == (TYPE_CLASS), "Typeclass does not match element type" ); \
645 uno::Sequence< DATA_TYPE > aData; \
646 readSequence(_rReader, aData); \
647 _aValue <<= aData; \
648 } break
650 bool readSequenceValue (
651 BinaryReader & _rReader,
652 uno::Any & _aValue,
653 uno::Type const & _aElementType)
654 SAL_THROW( (io::IOException, uno::RuntimeException) )
656 switch(_aElementType.getTypeClass())
658 CASE_READ_SEQUENCE( uno::TypeClass_BOOLEAN, sal_Bool );
660 CASE_READ_SEQUENCE( uno::TypeClass_SHORT, sal_Int16 );
662 CASE_READ_SEQUENCE( uno::TypeClass_LONG, sal_Int32 );
664 CASE_READ_SEQUENCE( uno::TypeClass_HYPER, sal_Int64 );
666 CASE_READ_SEQUENCE( uno::TypeClass_DOUBLE, double );
668 CASE_READ_SEQUENCE( uno::TypeClass_STRING, rtl::OUString );
670 case uno::TypeClass_SEQUENCE:
671 if (_aElementType == ::getCppuType(for_binary))
673 uno::Sequence< sal_Int8 > aData;
674 readSequence(_rReader, aData);
675 _aValue <<= aData;
676 break;
678 // else fall through
680 default:
681 OSL_ENSURE(false, "Unexpected type for sequence elements");
682 return false;
684 return true;
687 #undef CASE_READ_SEQUENCE
689 // --------------------------------------------------------------------------