Branch data 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 : : * 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 : : #ifndef OOX_HELPER_HELPER_HXX
21 : : #define OOX_HELPER_HELPER_HXX
22 : :
23 : : #include <algorithm>
24 : : #include <limits>
25 : : #include <boost/static_assert.hpp>
26 : : #include <osl/endian.h>
27 : : #include <rtl/math.hxx>
28 : : #include <rtl/string.hxx>
29 : : #include <rtl/ustring.hxx>
30 : : #include <string.h>
31 : :
32 : : namespace oox {
33 : :
34 : : // Helper macros ==============================================================
35 : :
36 : : /** Expands to the number of elements in a STATIC data array. */
37 : : #define STATIC_ARRAY_SIZE( array ) \
38 : : (sizeof(array)/sizeof(*(array)))
39 : :
40 : : /** Expands to a pointer behind the last element of a STATIC data array (like
41 : : STL end()). */
42 : : #define STATIC_ARRAY_END( array ) \
43 : : ((array)+STATIC_ARRAY_SIZE(array))
44 : :
45 : : /** Expands to the 'index'-th element of a STATIC data array, or to 'def', if
46 : : 'index' is out of the array limits. */
47 : : #define STATIC_ARRAY_SELECT( array, index, def ) \
48 : : ((static_cast<size_t>(index) < STATIC_ARRAY_SIZE(array)) ? ((array)[static_cast<size_t>(index)]) : (def))
49 : :
50 : : /** Expands to a temporary ::rtl::OString, created from a literal(!) character
51 : : array. */
52 : : #define CREATE_OSTRING( ascii ) \
53 : : ::rtl::OString( RTL_CONSTASCII_STRINGPARAM( ascii ) )
54 : :
55 : : /** Expands to a temporary ::rtl::OUString, created from a literal(!) ASCII(!)
56 : : character array. */
57 : : #define CREATE_OUSTRING( ascii ) \
58 : : ::rtl::OUString::intern( RTL_CONSTASCII_USTRINGPARAM( ascii ) )
59 : :
60 : : /** Convert an OUString to an ASCII C string. Use for debug purposes only. */
61 : : #define OUSTRING_TO_CSTR( str ) \
62 : : ::rtl::OUStringToOString( str, RTL_TEXTENCODING_ASCII_US ).getStr()
63 : :
64 : : // Common constants ===========================================================
65 : :
66 : : const sal_uInt8 WINDOWS_CHARSET_ANSI = 0;
67 : : const sal_uInt8 WINDOWS_CHARSET_DEFAULT = 1;
68 : : const sal_uInt8 WINDOWS_CHARSET_SYMBOL = 2;
69 : : const sal_uInt8 WINDOWS_CHARSET_APPLE_ROMAN = 77;
70 : : const sal_uInt8 WINDOWS_CHARSET_SHIFTJIS = 128;
71 : : const sal_uInt8 WINDOWS_CHARSET_HANGEUL = 129;
72 : : const sal_uInt8 WINDOWS_CHARSET_JOHAB = 130;
73 : : const sal_uInt8 WINDOWS_CHARSET_GB2312 = 134;
74 : : const sal_uInt8 WINDOWS_CHARSET_BIG5 = 136;
75 : : const sal_uInt8 WINDOWS_CHARSET_GREEK = 161;
76 : : const sal_uInt8 WINDOWS_CHARSET_TURKISH = 162;
77 : : const sal_uInt8 WINDOWS_CHARSET_VIETNAMESE = 163;
78 : : const sal_uInt8 WINDOWS_CHARSET_HEBREW = 177;
79 : : const sal_uInt8 WINDOWS_CHARSET_ARABIC = 178;
80 : : const sal_uInt8 WINDOWS_CHARSET_BALTIC = 186;
81 : : const sal_uInt8 WINDOWS_CHARSET_RUSSIAN = 204;
82 : : const sal_uInt8 WINDOWS_CHARSET_THAI = 222;
83 : : const sal_uInt8 WINDOWS_CHARSET_EASTERN = 238;
84 : : const sal_uInt8 WINDOWS_CHARSET_OEM = 255;
85 : :
86 : : // ----------------------------------------------------------------------------
87 : :
88 : : const sal_Int32 API_RGB_TRANSPARENT = -1; /// Transparent color for API calls.
89 : : const sal_Int32 API_RGB_BLACK = 0x000000; /// Black color for API calls.
90 : : const sal_Int32 API_RGB_WHITE = 0xFFFFFF; /// White color for API calls.
91 : :
92 : : const sal_Int16 API_LINE_SOLID = 0;
93 : : const sal_Int16 API_LINE_DOTTED = 1;
94 : : const sal_Int16 API_LINE_DASHED = 2;
95 : :
96 : : const sal_Int16 API_LINE_NONE = 0;
97 : : const sal_Int16 API_LINE_HAIR = 2;
98 : : const sal_Int16 API_LINE_THIN = 35;
99 : : const sal_Int16 API_LINE_MEDIUM = 88;
100 : : const sal_Int16 API_LINE_THICK = 141;
101 : :
102 : : const sal_Int16 API_ESCAPE_NONE = 0; /// No escapement.
103 : : const sal_Int16 API_ESCAPE_SUPERSCRIPT = 101; /// Superscript: raise characters automatically (magic value 101).
104 : : const sal_Int16 API_ESCAPE_SUBSCRIPT = -101; /// Subscript: lower characters automatically (magic value -101).
105 : :
106 : : const sal_Int8 API_ESCAPEHEIGHT_NONE = 100; /// Relative character height if not escaped.
107 : : const sal_Int8 API_ESCAPEHEIGHT_DEFAULT = 58; /// Relative character height if escaped.
108 : :
109 : : // ============================================================================
110 : :
111 : : // Limitate values ------------------------------------------------------------
112 : :
113 : : template< typename ReturnType, typename Type >
114 : 73190 : inline ReturnType getLimitedValue( Type nValue, Type nMin, Type nMax )
115 : : {
116 : 73190 : return static_cast< ReturnType >( ::std::min( ::std::max( nValue, nMin ), nMax ) );
117 : : }
118 : :
119 : : template< typename ReturnType, typename Type >
120 : 0 : inline ReturnType getIntervalValue( Type nValue, Type nBegin, Type nEnd )
121 : : {
122 : : // this BOOST_STATIC_ASSERT fails with suncc
123 : : // BOOST_STATIC_ASSERT( ::std::numeric_limits< Type >::is_integer );
124 : 0 : Type nInterval = nEnd - nBegin;
125 [ # # ]: 0 : Type nCount = (nValue < nBegin) ? -((nBegin - nValue - 1) / nInterval + 1) : ((nValue - nBegin) / nInterval);
126 : 0 : return static_cast< ReturnType >( nValue - nCount * nInterval );
127 : : }
128 : :
129 : : template< typename ReturnType >
130 : 0 : inline ReturnType getDoubleIntervalValue( double fValue, double fBegin, double fEnd )
131 : : {
132 : 0 : double fInterval = fEnd - fBegin;
133 [ # # ]: 0 : double fCount = (fValue < fBegin) ? -(::rtl::math::approxFloor( (fBegin - fValue - 1.0) / fInterval ) + 1.0) : ::rtl::math::approxFloor( (fValue - fBegin) / fInterval );
134 : 0 : return static_cast< ReturnType >( fValue - fCount * fInterval );
135 : : }
136 : :
137 : : // Read from bitfields --------------------------------------------------------
138 : :
139 : : /** Returns true, if at least one of the bits set in nMask is set in nBitField. */
140 : : template< typename Type >
141 : 88956 : inline bool getFlag( Type nBitField, Type nMask )
142 : : {
143 : 88956 : return (nBitField & nMask) != 0;
144 : : }
145 : :
146 : : /** Returns nSet, if at least one bit of nMask is set in nBitField, otherwise nUnset. */
147 : : template< typename ReturnType, typename Type >
148 : 68 : inline ReturnType getFlagValue( Type nBitField, Type nMask, ReturnType nSet, ReturnType nUnset )
149 : : {
150 [ - + ][ - + ]: 68 : return getFlag( nBitField, nMask ) ? nSet : nUnset;
151 : : }
152 : :
153 : : /** Extracts a value from a bit field.
154 : :
155 : : Returns the data fragment from nBitField, that starts at bit nStartBit
156 : : (0-based, bit 0 is rightmost) with the width of nBitCount. The returned
157 : : value will be right-aligned (normalized).
158 : : For instance: extractValue<T>(0x4321,8,4) returns 3 (value in bits 8-11).
159 : : */
160 : : template< typename ReturnType, typename Type >
161 : 33878 : inline ReturnType extractValue( Type nBitField, sal_uInt8 nStartBit, sal_uInt8 nBitCount )
162 : : {
163 : 33878 : sal_uInt64 nMask = 1; nMask <<= nBitCount; --nMask;
164 : 33878 : return static_cast< ReturnType >( nMask & (nBitField >> nStartBit) );
165 : : }
166 : :
167 : : // Write to bitfields ---------------------------------------------------------
168 : :
169 : : /** Sets or clears (according to bSet) all set bits of nMask in ornBitField. */
170 : : template< typename Type >
171 : 21143 : inline void setFlag( Type& ornBitField, Type nMask, bool bSet = true )
172 : : {
173 [ + + ][ + + ]: 21143 : if( bSet ) ornBitField |= nMask; else ornBitField &= ~nMask;
174 : 21143 : }
175 : :
176 : : /** Inserts a value into a bitfield.
177 : :
178 : : Inserts the lower nBitCount bits of nValue into ornBitField, starting
179 : : there at bit nStartBit. Other contents of ornBitField keep unchanged.
180 : : */
181 : : template< typename Type, typename InsertType >
182 : : void insertValue( Type& ornBitField, InsertType nValue, sal_uInt8 nStartBit, sal_uInt8 nBitCount )
183 : : {
184 : : sal_uInt64 nMask = 1; nMask <<= nBitCount; --nMask;
185 : : Type nNewValue = static_cast< Type >( nValue & nMask );
186 : : (ornBitField &= ~(nMask << nStartBit)) |= (nNewValue << nStartBit);
187 : : }
188 : :
189 : : // ============================================================================
190 : :
191 : : /** Optional value, similar to ::boost::optional<>, with convenience accessors.
192 : : */
193 : : template< typename Type >
194 : 20601 : class OptValue
195 : : {
196 : : public:
197 : 215409 : inline explicit OptValue() : maValue(), mbHasValue( false ) {}
198 : 4815 : inline explicit OptValue( const Type& rValue ) : maValue( rValue ), mbHasValue( true ) {}
199 : 22014 : inline explicit OptValue( bool bHasValue, const Type& rValue ) : maValue( rValue ), mbHasValue( bHasValue ) {}
200 : :
201 : 7902 : inline bool has() const { return mbHasValue; }
202 : 57 : inline bool operator!() const { return !mbHasValue; }
203 [ + + ][ - + ]: 54 : inline bool differsFrom( const Type& rValue ) const { return mbHasValue && (maValue != rValue); }
204 : :
205 : 6399 : inline const Type& get() const { return maValue; }
206 [ + + ][ + + ]: 22122 : inline const Type& get( const Type& rDefValue ) const { return mbHasValue ? maValue : rDefValue; }
[ + + ][ + - ]
[ # # ][ + + ]
[ # # ]
207 : :
208 : : inline void reset() { mbHasValue = false; }
209 : 2343 : inline void set( const Type& rValue ) { maValue = rValue; mbHasValue = true; }
210 : : inline Type& use() { mbHasValue = true; return maValue; }
211 : :
212 : 1341 : inline OptValue& operator=( const Type& rValue ) { set( rValue ); return *this; }
213 : 39 : inline bool operator==( const OptValue& rValue ) const {
214 : : return ( ( mbHasValue == false && rValue.mbHasValue == false ) ||
215 [ + + ][ - + ]: 39 : ( mbHasValue == rValue.mbHasValue && maValue == rValue.maValue ) );
[ + + ][ - + ]
216 : : }
217 [ + + ][ + + ]: 44802 : inline void assignIfUsed( const OptValue& rValue ) { if( rValue.mbHasValue ) set( rValue.maValue ); }
[ + + ][ # # ]
[ # # ]
218 : :
219 : : private:
220 : : Type maValue;
221 : : bool mbHasValue;
222 : : };
223 : :
224 : : // ============================================================================
225 : :
226 : : /** Provides platform independent functions to convert from or to little-endian
227 : : byte order, e.g. for reading data from or writing data to memory or a
228 : : binary stream.
229 : :
230 : : On big-endian platforms, the byte order in the passed values is swapped,
231 : : this can be used for converting big-endian to and from little-endian data.
232 : :
233 : : On little-endian platforms, the conversion functions are implemented empty,
234 : : thus compilers should completely optimize away the function call.
235 : : */
236 : : class ByteOrderConverter
237 : : {
238 : : public:
239 : : #ifdef OSL_BIGENDIAN
240 : : inline static void convertLittleEndian( sal_Int8& ) {} // present for usage in templates
241 : : inline static void convertLittleEndian( sal_uInt8& ) {} // present for usage in templates
242 : : inline static void convertLittleEndian( sal_Int16& rnValue ) { swap2( reinterpret_cast< sal_uInt8* >( &rnValue ) ); }
243 : : inline static void convertLittleEndian( sal_uInt16& rnValue ) { swap2( reinterpret_cast< sal_uInt8* >( &rnValue ) ); }
244 : : inline static void convertLittleEndian( sal_Int32& rnValue ) { swap4( reinterpret_cast< sal_uInt8* >( &rnValue ) ); }
245 : : inline static void convertLittleEndian( sal_uInt32& rnValue ) { swap4( reinterpret_cast< sal_uInt8* >( &rnValue ) ); }
246 : : inline static void convertLittleEndian( sal_Int64& rnValue ) { swap8( reinterpret_cast< sal_uInt8* >( &rnValue ) ); }
247 : : inline static void convertLittleEndian( sal_uInt64& rnValue ) { swap8( reinterpret_cast< sal_uInt8* >( &rnValue ) ); }
248 : : inline static void convertLittleEndian( float& rfValue ) { swap4( reinterpret_cast< sal_uInt8* >( &rfValue ) ); }
249 : : inline static void convertLittleEndian( double& rfValue ) { swap8( reinterpret_cast< sal_uInt8* >( &rfValue ) ); }
250 : :
251 : : template< typename Type >
252 : : inline static void convertLittleEndianArray( Type* pnArray, size_t nElemCount );
253 : :
254 : : inline static void convertLittleEndianArray( sal_Int8*, size_t ) {}
255 : : inline static void convertLittleEndianArray( sal_uInt8*, size_t ) {}
256 : :
257 : : #else
258 : : template< typename Type >
259 : 36390 : inline static void convertLittleEndian( Type& ) {}
260 : :
261 : : template< typename Type >
262 : 243 : inline static void convertLittleEndianArray( Type*, size_t ) {}
263 : :
264 : : #endif
265 : :
266 : : /** Reads a value from memory, assuming memory buffer in little-endian.
267 : : @param ornValue (out-parameter) Contains the value read from memory.
268 : : @param pSrcBuffer The memory buffer to read the value from.
269 : : */
270 : : template< typename Type >
271 : : inline static void readLittleEndian( Type& ornValue, const void* pSrcBuffer );
272 : :
273 : : /** Writes a value to memory, while converting it to little-endian.
274 : : @param pDstBuffer The memory buffer to write the value to.
275 : : @param nValue The value to be written to memory in little-endian.
276 : : */
277 : : template< typename Type >
278 : : inline static void writeLittleEndian( void* pDstBuffer, Type nValue );
279 : :
280 : : #ifdef OSL_BIGENDIAN
281 : : private:
282 : : inline static void swap2( sal_uInt8* pnData );
283 : : inline static void swap4( sal_uInt8* pnData );
284 : : inline static void swap8( sal_uInt8* pnData );
285 : : #endif
286 : : };
287 : :
288 : : // ----------------------------------------------------------------------------
289 : :
290 : : template< typename Type >
291 : : inline void ByteOrderConverter::readLittleEndian( Type& ornValue, const void* pSrcBuffer )
292 : : {
293 : : memcpy( &ornValue, pSrcBuffer, sizeof( Type ) );
294 : : convertLittleEndian( ornValue );
295 : : }
296 : :
297 : : template< typename Type >
298 : 0 : inline void ByteOrderConverter::writeLittleEndian( void* pDstBuffer, Type nValue )
299 : : {
300 : 0 : convertLittleEndian( nValue );
301 : 0 : memcpy( pDstBuffer, &nValue, sizeof( Type ) );
302 : 0 : }
303 : :
304 : : #ifdef OSL_BIGENDIAN
305 : : template< typename Type >
306 : : inline void ByteOrderConverter::convertLittleEndianArray( Type* pnArray, size_t nElemCount )
307 : : {
308 : : for( Type* pnArrayEnd = pnArray + nElemCount; pnArray != pnArrayEnd; ++pnArray )
309 : : convertLittleEndian( *pnArray );
310 : : }
311 : :
312 : : inline void ByteOrderConverter::swap2( sal_uInt8* pnData )
313 : : {
314 : : ::std::swap( pnData[ 0 ], pnData[ 1 ] );
315 : : }
316 : :
317 : : inline void ByteOrderConverter::swap4( sal_uInt8* pnData )
318 : : {
319 : : ::std::swap( pnData[ 0 ], pnData[ 3 ] );
320 : : ::std::swap( pnData[ 1 ], pnData[ 2 ] );
321 : : }
322 : :
323 : : inline void ByteOrderConverter::swap8( sal_uInt8* pnData )
324 : : {
325 : : ::std::swap( pnData[ 0 ], pnData[ 7 ] );
326 : : ::std::swap( pnData[ 1 ], pnData[ 6 ] );
327 : : ::std::swap( pnData[ 2 ], pnData[ 5 ] );
328 : : ::std::swap( pnData[ 3 ], pnData[ 4 ] );
329 : : }
330 : : #endif
331 : :
332 : : // ============================================================================
333 : :
334 : : } // namespace oox
335 : :
336 : : #endif
337 : :
338 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|