xref: /trunk/main/oox/inc/oox/xls/biffoutputstream.hxx (revision e3508121)
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