cid#1636693 COPY_INSTEAD_OF_MOVE
[LibreOffice.git] / include / oox / helper / helper.hxx
blob4099204c1a5d77233ae15e4e21c44ed0863dd0df
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #ifndef INCLUDED_OOX_HELPER_HELPER_HXX
21 #define INCLUDED_OOX_HELPER_HELPER_HXX
23 #include <sal/config.h>
25 #include <cstring>
26 #include <limits>
27 #include <optional>
29 #include <o3tl/safeint.hxx>
30 #include <osl/endian.h>
31 #include <rtl/math.hxx>
32 #include <sal/macros.h>
33 #include <sal/types.h>
34 #include <tools/color.hxx>
36 namespace oox {
38 // Helper macros ==============================================================
40 namespace detail {
42 //TODO: Temporary helper for STATIC_ARRAY_SELECT; ultimately, the latter should be replaced by a
43 // proper function (template):
44 template<typename T> constexpr std::make_unsigned_t<T> make_unsigned(T value) {
45 if constexpr (std::is_signed_v<T>) {
46 return o3tl::make_unsigned(value);
47 } else {
48 return value;
54 /** Expands to the 'index'-th element of a STATIC data array, or to 'def', if
55 'index' is out of the array limits. */
56 #define STATIC_ARRAY_SELECT( array, index, def ) \
57 ((detail::make_unsigned(index) < std::size(array)) ? ((array)[static_cast<size_t>(index)]) : (def))
59 // Common constants ===========================================================
61 const sal_uInt8 WINDOWS_CHARSET_ANSI = 0;
62 const sal_uInt8 WINDOWS_CHARSET_DEFAULT = 1;
63 const sal_uInt8 WINDOWS_CHARSET_SYMBOL = 2;
64 const sal_uInt8 WINDOWS_CHARSET_APPLE_ROMAN = 77;
65 const sal_uInt8 WINDOWS_CHARSET_SHIFTJIS = 128;
66 const sal_uInt8 WINDOWS_CHARSET_HANGEUL = 129;
67 const sal_uInt8 WINDOWS_CHARSET_JOHAB = 130;
68 const sal_uInt8 WINDOWS_CHARSET_GB2312 = 134;
69 const sal_uInt8 WINDOWS_CHARSET_BIG5 = 136;
70 const sal_uInt8 WINDOWS_CHARSET_GREEK = 161;
71 const sal_uInt8 WINDOWS_CHARSET_TURKISH = 162;
72 const sal_uInt8 WINDOWS_CHARSET_VIETNAMESE = 163;
73 const sal_uInt8 WINDOWS_CHARSET_HEBREW = 177;
74 const sal_uInt8 WINDOWS_CHARSET_ARABIC = 178;
75 const sal_uInt8 WINDOWS_CHARSET_BALTIC = 186;
76 const sal_uInt8 WINDOWS_CHARSET_RUSSIAN = 204;
77 const sal_uInt8 WINDOWS_CHARSET_THAI = 222;
78 const sal_uInt8 WINDOWS_CHARSET_EASTERN = 238;
79 const sal_uInt8 WINDOWS_CHARSET_OEM = 255;
82 const ::Color API_RGB_TRANSPARENT (ColorTransparency, 0xffffffff); ///< Transparent color for API calls.
83 const sal_uInt32 UNSIGNED_RGB_TRANSPARENT = static_cast<sal_uInt32>(-1); ///< Transparent color for unsigned int32 places.
84 const ::Color API_RGB_BLACK (0x000000); ///< Black color for API calls.
85 const ::Color API_RGB_GRAY (0x808080); ///< Gray color for API calls.
86 const ::Color API_RGB_WHITE (0xFFFFFF); ///< White color for API calls.
88 const sal_Int16 API_LINE_SOLID = 0;
89 const sal_Int16 API_LINE_DOTTED = 1;
90 const sal_Int16 API_LINE_DASHED = 2;
91 const sal_Int16 API_FINE_LINE_DASHED = 14;
93 const sal_Int16 API_LINE_NONE = 0;
94 const sal_Int16 API_LINE_HAIR = 2;
95 const sal_Int16 API_LINE_THIN = 35;
96 const sal_Int16 API_LINE_MEDIUM = 88;
97 const sal_Int16 API_LINE_THICK = 141;
99 const sal_Int16 API_ESCAPE_NONE = 0; ///< No escapement.
100 const sal_Int16 API_ESCAPE_SUPERSCRIPT = 101; ///< Superscript: raise characters automatically (magic value 101).
101 const sal_Int16 API_ESCAPE_SUBSCRIPT = -101; ///< Subscript: lower characters automatically (magic value -101).
103 const sal_Int8 API_ESCAPEHEIGHT_NONE = 100; ///< Relative character height if not escaped.
104 const sal_Int8 API_ESCAPEHEIGHT_DEFAULT = 58; ///< Relative character height if escaped.
107 // Limitate values ------------------------------------------------------------
109 template< typename ReturnType, typename Type >
110 inline ReturnType getLimitedValue( Type nValue, Type nMin, Type nMax )
112 return static_cast< ReturnType >( ::std::clamp( nValue, nMin, nMax ) );
115 template< typename ReturnType, typename Type >
116 inline ReturnType getIntervalValue( Type nValue, Type nBegin, Type nEnd )
118 static_assert(::std::numeric_limits< Type >::is_integer, "is integer");
119 Type nInterval = nEnd - nBegin;
120 Type nCount = (nValue < nBegin) ? -((nBegin - nValue - 1) / nInterval + 1) : ((nValue - nBegin) / nInterval);
121 return static_cast< ReturnType >( nValue - nCount * nInterval );
124 template< typename ReturnType >
125 inline ReturnType getDoubleIntervalValue( double fValue, double fBegin, double fEnd )
127 double fInterval = fEnd - fBegin;
128 double fCount = (fValue < fBegin) ? -(::rtl::math::approxFloor( (fBegin - fValue - 1.0) / fInterval ) + 1.0) : ::rtl::math::approxFloor( (fValue - fBegin) / fInterval );
129 return static_cast< ReturnType >( fValue - fCount * fInterval );
132 // Read from bitfields --------------------------------------------------------
134 /** Returns true, if at least one of the bits set in nMask is set in nBitField. */
135 template< typename Type >
136 inline bool getFlag( Type nBitField, Type nMask )
138 return (nBitField & nMask) != 0;
141 /** Returns nSet, if at least one bit of nMask is set in nBitField, otherwise nUnset. */
142 template< typename ReturnType, typename Type >
143 inline ReturnType getFlagValue( Type nBitField, Type nMask, ReturnType nSet, ReturnType nUnset )
145 return getFlag( nBitField, nMask ) ? nSet : nUnset;
148 /** Extracts a value from a bit field.
150 Returns the data fragment from nBitField, that starts at bit nStartBit
151 (0-based, bit 0 is rightmost) with the width of nBitCount. The returned
152 value will be right-aligned (normalized).
153 For instance: extractValue<T>(0x4321,8,4) returns 3 (value in bits 8-11).
155 template< typename ReturnType, typename Type >
156 inline ReturnType extractValue( Type nBitField, sal_uInt8 nStartBit, sal_uInt8 nBitCount )
158 sal_uInt64 nMask = 1; nMask <<= nBitCount; --nMask;
159 return static_cast< ReturnType >( nMask & (nBitField >> nStartBit) );
162 // Write to bitfields ---------------------------------------------------------
164 /** Sets or clears (according to bSet) all set bits of nMask in ornBitField. */
165 template< typename Type >
166 inline void setFlag( Type& ornBitField, Type nMask, bool bSet = true )
168 if( bSet ) ornBitField |= nMask; else ornBitField &= ~nMask;
172 template< typename Type >
173 void assignIfUsed( std::optional<Type>& rDestValue, const std::optional<Type>& rSourceValue )
175 if( rSourceValue.has_value() )
176 rDestValue = rSourceValue.value();
180 /** Provides platform independent functions to convert from or to little-endian
181 byte order, e.g. for reading data from or writing data to memory or a
182 binary stream.
184 On big-endian platforms, the byte order in the passed values is swapped,
185 this can be used for converting big-endian to and from little-endian data.
187 On little-endian platforms, the conversion functions are implemented empty,
188 thus compilers should completely optimize away the function call.
190 class ByteOrderConverter
192 public:
193 #ifdef OSL_BIGENDIAN
194 static void convertLittleEndian( sal_Int8& ) {} // present for usage in templates
195 static void convertLittleEndian( sal_uInt8& ) {} // present for usage in templates
196 static void convertLittleEndian( char16_t& rnValue ) { swap2( reinterpret_cast< sal_uInt8* >( &rnValue ) ); }
197 static void convertLittleEndian( sal_Int16& rnValue ) { swap2( reinterpret_cast< sal_uInt8* >( &rnValue ) ); }
198 static void convertLittleEndian( sal_uInt16& rnValue ) { swap2( reinterpret_cast< sal_uInt8* >( &rnValue ) ); }
199 static void convertLittleEndian( sal_Int32& rnValue ) { swap4( reinterpret_cast< sal_uInt8* >( &rnValue ) ); }
200 static void convertLittleEndian( sal_uInt32& rnValue ) { swap4( reinterpret_cast< sal_uInt8* >( &rnValue ) ); }
201 static void convertLittleEndian( sal_Int64& rnValue ) { swap8( reinterpret_cast< sal_uInt8* >( &rnValue ) ); }
202 static void convertLittleEndian( sal_uInt64& rnValue ) { swap8( reinterpret_cast< sal_uInt8* >( &rnValue ) ); }
203 static void convertLittleEndian( float& rfValue ) { swap4( reinterpret_cast< sal_uInt8* >( &rfValue ) ); }
204 static void convertLittleEndian( double& rfValue ) { swap8( reinterpret_cast< sal_uInt8* >( &rfValue ) ); }
206 template< typename Type >
207 inline static void convertLittleEndianArray( Type* pnArray, size_t nElemCount );
209 static void convertLittleEndianArray( sal_Int8*, size_t ) {}
210 static void convertLittleEndianArray( sal_uInt8*, size_t ) {}
212 #else
213 template< typename Type >
214 static void convertLittleEndian( Type& ) {}
216 template< typename Type >
217 static void convertLittleEndianArray( Type*, size_t ) {}
219 #endif
221 /** Writes a value to memory, while converting it to little-endian.
222 @param pDstBuffer The memory buffer to write the value to.
223 @param nValue The value to be written to memory in little-endian.
225 template< typename Type >
226 inline static void writeLittleEndian( void* pDstBuffer, Type nValue );
228 #ifdef OSL_BIGENDIAN
229 private:
230 inline static void swap2( sal_uInt8* pnData );
231 inline static void swap4( sal_uInt8* pnData );
232 inline static void swap8( sal_uInt8* pnData );
233 #endif
237 template< typename Type >
238 inline void ByteOrderConverter::writeLittleEndian( void* pDstBuffer, Type nValue )
240 convertLittleEndian( nValue );
241 memcpy( pDstBuffer, &nValue, sizeof( Type ) );
244 #ifdef OSL_BIGENDIAN
245 template< typename Type >
246 inline void ByteOrderConverter::convertLittleEndianArray( Type* pnArray, size_t nElemCount )
248 for( Type* pnArrayEnd = pnArray + nElemCount; pnArray != pnArrayEnd; ++pnArray )
249 convertLittleEndian( *pnArray );
252 inline void ByteOrderConverter::swap2( sal_uInt8* pnData )
254 ::std::swap( pnData[ 0 ], pnData[ 1 ] );
257 inline void ByteOrderConverter::swap4( sal_uInt8* pnData )
259 ::std::swap( pnData[ 0 ], pnData[ 3 ] );
260 ::std::swap( pnData[ 1 ], pnData[ 2 ] );
263 inline void ByteOrderConverter::swap8( sal_uInt8* pnData )
265 ::std::swap( pnData[ 0 ], pnData[ 7 ] );
266 ::std::swap( pnData[ 1 ], pnData[ 6 ] );
267 ::std::swap( pnData[ 2 ], pnData[ 5 ] );
268 ::std::swap( pnData[ 3 ], pnData[ 4 ] );
270 #endif
273 } // namespace oox
275 #endif
277 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */