Line data Source code
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 : #include "oox/ole/axbinarywriter.hxx"
10 :
11 : #include "oox/ole/olehelper.hxx"
12 :
13 : namespace oox {
14 : namespace ole {
15 :
16 : namespace {
17 :
18 : const sal_uInt32 AX_STRING_COMPRESSED = 0x80000000;
19 :
20 : } // namespace
21 :
22 2 : AxAlignedOutputStream::AxAlignedOutputStream( BinaryOutputStream& rOutStrm ) :
23 : BinaryStreamBase( false ),
24 : mpOutStrm( &rOutStrm ),
25 : mnStrmPos( 0 ),
26 2 : mnStrmSize( rOutStrm.getRemaining() ),
27 4 : mnWrappedBeginPos( rOutStrm.tell() )
28 : {
29 2 : mbEof = mbEof || rOutStrm.isEof();
30 2 : }
31 :
32 0 : sal_Int64 AxAlignedOutputStream::size() const
33 : {
34 0 : return mpOutStrm ? mnStrmSize : -1;
35 : }
36 :
37 6 : sal_Int64 AxAlignedOutputStream::tell() const
38 : {
39 6 : return mpOutStrm ? mnStrmPos : -1;
40 : }
41 :
42 4 : void AxAlignedOutputStream::seek( sal_Int64 nPos )
43 : {
44 4 : mbEof = (nPos < 0);
45 4 : if( !mbEof )
46 : {
47 4 : mpOutStrm->seek( static_cast< sal_Int32 >( mnWrappedBeginPos + nPos ) );
48 4 : mnStrmPos = mpOutStrm->tell() - mnWrappedBeginPos;
49 : }
50 4 : }
51 :
52 0 : void AxAlignedOutputStream::close()
53 : {
54 0 : mpOutStrm = 0;
55 0 : mbEof = true;
56 0 : }
57 :
58 0 : void AxAlignedOutputStream::writeData( const StreamDataSequence& orData, size_t nAtomSize )
59 : {
60 0 : mpOutStrm->writeData( orData, nAtomSize );
61 0 : mnStrmPos = mpOutStrm->tell() - mnWrappedBeginPos;
62 0 : }
63 :
64 26 : void AxAlignedOutputStream::writeMemory( const void* opMem, sal_Int32 nBytes, size_t nAtomSize )
65 : {
66 26 : mpOutStrm->writeMemory( opMem, nBytes, nAtomSize );
67 26 : mnStrmPos = mpOutStrm->tell() - mnWrappedBeginPos;
68 26 : }
69 :
70 17 : void AxAlignedOutputStream::pad( sal_Int32 nBytes, size_t nAtomSize )
71 : {
72 : //PRESUMABLY we need to pad with 0's here as appropriate
73 17 : com::sun::star::uno::Sequence< sal_Int8 > aData( nBytes );
74 : // ok we could be padding with rubbish here, but really that shouldn't matter
75 : // set to 0(s), easier to not get fooled by 0's when looking at
76 : // binary content......
77 17 : memset( static_cast<void*>( aData.getArray() ), 0, nBytes );
78 17 : mpOutStrm->writeData( aData, nAtomSize );
79 17 : mnStrmPos = mpOutStrm->tell() - mnWrappedBeginPos;
80 17 : }
81 :
82 17 : void AxAlignedOutputStream::align( size_t nSize )
83 : {
84 17 : pad( static_cast< sal_Int32 >( (nSize - (mnStrmPos % nSize)) % nSize ) );
85 17 : }
86 :
87 : namespace {
88 :
89 2 : void lclWriteString( AxAlignedOutputStream& rOutStrm, OUString& rValue, sal_uInt32 nSize, bool bArrayString )
90 : {
91 2 : bool bCompressed = getFlag( nSize, AX_STRING_COMPRESSED );
92 2 : rOutStrm.writeCompressedUnicodeArray( rValue, bCompressed || bArrayString );
93 2 : }
94 :
95 : } // namespace
96 :
97 3 : AxBinaryPropertyWriter::ComplexProperty::~ComplexProperty()
98 : {
99 3 : }
100 :
101 1 : bool AxBinaryPropertyWriter::PairProperty::writeProperty( AxAlignedOutputStream& rOutStrm )
102 : {
103 1 : rOutStrm.WriteInt32(mrPairData.first).WriteInt32(mrPairData.second);
104 1 : return true;
105 : }
106 :
107 2 : bool AxBinaryPropertyWriter::StringProperty::writeProperty( AxAlignedOutputStream& rOutStrm )
108 : {
109 2 : lclWriteString( rOutStrm, mrValue, mnSize, false );
110 2 : return true;
111 : }
112 :
113 2 : AxBinaryPropertyWriter::AxBinaryPropertyWriter( BinaryOutputStream& rOutStrm, bool b64BitPropFlags ) :
114 : maOutStrm( rOutStrm ),
115 : mnPropFlags( 0x0 ),
116 : mbValid( true ),
117 2 : mb64BitPropFlags( b64BitPropFlags )
118 : {
119 2 : sal_uInt16 nId( 0x0200 );
120 2 : maOutStrm.WriteUInt16(nId);
121 2 : mnBlockSize = 0; // will be filled in the finalize method
122 :
123 2 : maOutStrm.WriteUInt16(nId);
124 2 : mnPropFlagsStart = maOutStrm.tell();
125 :
126 2 : if( mb64BitPropFlags )
127 1 : maOutStrm.WriteInt64( mnPropFlags );
128 : else
129 1 : maOutStrm.WriteUInt32( mnPropFlags );
130 2 : mnNextProp = 1;
131 2 : }
132 :
133 1 : void AxBinaryPropertyWriter::writeBoolProperty( bool orbValue, bool bReverse )
134 : {
135 : // orbValue == bReverse false then we want to set the bit, e.g. don't skip
136 1 : startNextProperty( orbValue == bReverse );
137 1 : }
138 :
139 1 : void AxBinaryPropertyWriter::writePairProperty( AxPairData& orPairData )
140 : {
141 1 : if( startNextProperty() )
142 1 : maLargeProps.push_back( ComplexPropVector::value_type( new PairProperty( orPairData ) ) );
143 1 : }
144 :
145 2 : void AxBinaryPropertyWriter::writeStringProperty( OUString& orValue, bool bCompressed )
146 : {
147 2 : sal_uInt32 nSize = orValue.getLength();
148 2 : if ( bCompressed )
149 2 : setFlag( nSize, AX_STRING_COMPRESSED );
150 : else
151 0 : nSize *= 2;
152 2 : maOutStrm.writeAligned< sal_uInt32 >( nSize );
153 2 : maLargeProps.push_back( ComplexPropVector::value_type( new StringProperty( orValue, nSize ) ) );
154 2 : startNextProperty();
155 2 : }
156 :
157 2 : bool AxBinaryPropertyWriter::finalizeExport()
158 : {
159 : // write large properties
160 2 : maOutStrm.align( 4 );
161 2 : if( !maLargeProps.empty() )
162 : {
163 5 : for( ComplexPropVector::iterator aIt = maLargeProps.begin(), aEnd = maLargeProps.end(); ensureValid() && (aIt != aEnd); ++aIt )
164 : {
165 3 : (*aIt)->writeProperty( maOutStrm );
166 3 : maOutStrm.align( 4 );
167 : }
168 : }
169 :
170 2 : mnBlockSize = maOutStrm.tell() - mnPropFlagsStart;
171 :
172 : // write stream properties (no stream alignment between properties!)
173 2 : if( !maStreamProps.empty() )
174 0 : for( ComplexPropVector::iterator aIt = maStreamProps.begin(), aEnd = maStreamProps.end(); ensureValid() && (aIt != aEnd); ++aIt )
175 0 : (*aIt)->writeProperty( maOutStrm );
176 :
177 2 : sal_Int64 nPos = maOutStrm.tell();
178 2 : maOutStrm.seek( mnPropFlagsStart - sizeof( mnBlockSize ) );
179 :
180 2 : maOutStrm.WriteInt16( mnBlockSize );
181 :
182 2 : if( mb64BitPropFlags )
183 1 : maOutStrm.WriteInt64( mnPropFlags );
184 : else
185 1 : maOutStrm.WriteUInt32( mnPropFlags );
186 :
187 2 : maOutStrm.seek( nPos );
188 2 : return true;
189 : }
190 :
191 5 : bool AxBinaryPropertyWriter::ensureValid( bool bCondition )
192 : {
193 5 : mbValid = mbValid && bCondition && !maOutStrm.isEof();
194 5 : return mbValid;
195 : }
196 :
197 41 : bool AxBinaryPropertyWriter::startNextProperty( bool bSkip )
198 : {
199 : // if we are skipping then we clear the flag
200 41 : setFlag( mnPropFlags, mnNextProp, !bSkip );
201 41 : mnNextProp <<= 1;
202 41 : return true;
203 : }
204 :
205 : } // namespace exp
206 246 : } // namespace ole
207 :
208 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|