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