1 /************************************************************** 2 * 3 * Licensed to the Apache Software Foundation (ASF) under one 4 * or more contributor license agreements. See the NOTICE file 5 * distributed with this work for additional information 6 * regarding copyright ownership. The ASF licenses this file 7 * to you under the Apache License, Version 2.0 (the 8 * "License"); you may not use this file except in compliance 9 * with the License. You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, 14 * software distributed under the License is distributed on an 15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 * KIND, either express or implied. See the License for the 17 * specific language governing permissions and limitations 18 * under the License. 19 * 20 *************************************************************/ 21 22 23 24 #ifndef OOX_XLS_BIFFOUTPUTSTREAM_HXX 25 #define OOX_XLS_BIFFOUTPUTSTREAM_HXX 26 27 #include <vector> 28 #include "oox/helper/binaryoutputstream.hxx" 29 #include "oox/xls/biffhelper.hxx" 30 31 namespace oox { class BinaryOutputStream; } 32 33 namespace oox { 34 namespace xls { 35 36 // ============================================================================ 37 38 namespace prv { 39 40 /** Buffers the contents of a raw record. */ 41 class BiffOutputRecordBuffer 42 { 43 public: 44 explicit BiffOutputRecordBuffer( 45 BinaryOutputStream& rOutStrm, 46 sal_uInt16 nMaxRecSize ); 47 48 /** Returns the wrapped binary base stream. */ getBaseStream() const49 inline const BinaryOutputStream& getBaseStream() const { return mrOutStrm; } 50 51 /** Starts a new record. */ 52 void startRecord( sal_uInt16 nRecId ); 53 /** Finishes the current record. Must be called for every started record. */ 54 void endRecord(); 55 56 /** Returns the number of remaining bytes in the current record body. */ getRecLeft() const57 inline sal_uInt16 getRecLeft() const { return static_cast< sal_uInt16 >( mnMaxRecSize - maData.size() ); } 58 59 /** Writes nBytes bytes from the existing buffer pData. Must NOT overwrite the destination buffer. */ 60 void write( const void* pData, sal_uInt16 nBytes ); 61 /** Writes a sequence of nBytes bytes with the passed value. */ 62 void fill( sal_uInt8 nValue, sal_uInt16 nBytes ); 63 64 private: 65 typedef ::std::vector< sal_uInt8 > DataBuffer; 66 67 BinaryOutputStream& mrOutStrm; /// Core ouput stream. 68 DataBuffer maData; /// Record data buffer. 69 sal_uInt16 mnMaxRecSize; /// Maximum size of record contents. 70 sal_uInt16 mnRecId; /// Current record identifier. 71 bool mbInRec; /// True = currently writing inside of a record. 72 }; 73 74 } // namespace prv 75 76 // ============================================================================ 77 78 /** This class is used to write BIFF record streams. 79 80 An instance is constructed with a BinaryOutputStream object and the 81 maximum size of BIFF record contents (e.g. 2080 bytes in BIFF2-BIFF5, or 82 8224 bytes in BIFF8). 83 84 To start writing a record, call startRecord() with the record identifier. 85 Each record must be closed by calling endRecord(). 86 87 If some data exceeds the record size limit, a CONTINUE record will be 88 started automatically and the new data will be written to this record. If 89 specific data pieces must not be split into the current and a following 90 CONTINUE record, use setPortionSize(). Example: To write a sequence of 91 16-bit values where 4 values form a unit and cannot be split, call 92 setPortionSize(8) first (4*2 bytes == 8). 93 */ 94 class BiffOutputStream : public BinaryOutputStream 95 { 96 public: 97 explicit BiffOutputStream( 98 BinaryOutputStream& rOutStream, 99 sal_uInt16 nMaxRecSize ); 100 101 // record control --------------------------------------------------------- 102 103 /** Starts a new record. */ 104 void startRecord( sal_uInt16 nRecId ); 105 106 /** Finishes the current record. Must be called for every started record. */ 107 void endRecord(); 108 109 /** Sets size of data portion in bytes. 0 or 1 means no portions are used. */ 110 void setPortionSize( sal_uInt8 nSize ); 111 112 // BinaryStreamBase interface (seeking) ----------------------------------- 113 114 /** Returns the absolute position in the wrapped binary stream. */ 115 sal_Int64 tellBase() const; 116 /** Returns the total size of the wrapped binary stream. */ 117 sal_Int64 sizeBase() const; 118 119 // BinaryOutputStream interface (stream write access) --------------------- 120 121 /** Writes the passed data sequence. */ 122 virtual void writeData( const StreamDataSequence& rData, size_t nAtomSize = 1 ); 123 /** Writes nBytes bytes from the passed buffer pMem. */ 124 virtual void writeMemory( const void* pMem, sal_Int32 nBytes, size_t nAtomSize = 1 ); 125 126 /** Writes a sequence of nBytes bytes with the passed value. */ 127 void fill( sal_uInt8 nValue, sal_Int32 nBytes, size_t nAtomSize = 1 ); 128 129 /** Stream operator for all data types supported by the writeValue() function. */ 130 template< typename Type > operator <<(Type nValue)131 inline BiffOutputStream& operator<<( Type nValue ) { writeValue( nValue ); return *this; } 132 133 // ------------------------------------------------------------------------ 134 private: 135 /** Checks the remaining size in the current record, creates CONTINUE record if needed. */ 136 void ensureRawBlock( sal_uInt16 nSize ); 137 138 /** Checks the remaining size in the current record and creates a CONTINUE 139 record if needed. 140 @return Maximum size left for writing to current record. */ 141 sal_uInt16 prepareWriteBlock( sal_Int32 nTotalSize, size_t nAtomSize ); 142 143 private: 144 prv::BiffOutputRecordBuffer maRecBuffer; /// Raw record data buffer. 145 sal_uInt8 mnPortionSize; /// Size of data portions. 146 sal_uInt8 mnPortionPos; /// Position in current portion. 147 }; 148 149 // ============================================================================ 150 151 } // namespace xls 152 } // namespace oox 153 154 #endif 155