1 //
2 // (C) Jan de Vaan 2007-2010, all rights reserved. See the accompanying "License.txt" for licensed use.
3 //
4 
5 
6 #ifndef CHARLS_UTIL
7 #define CHARLS_UTIL
8 
9 #include "publictypes.h"
10 #include <vector>
11 #include <system_error>
12 #include <memory>
13 
14 // ReSharper disable once CppUnusedIncludeDirective
15 #include <cassert>
16 
17 // Use an uppercase alias for assert to make it clear that it is a pre-processor macro.
18 #define ASSERT(t) assert(t)
19 
20 //https://github.com/team-charls/charls/issues/38
21 #if __cplusplus == 201103L
22 template<typename T, typename... Args>
make_unique(Args &&...args)23 std::unique_ptr<T> make_unique(Args&&... args)
24 {
25     return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
26 }
27 #endif
28 
29 // Only use __forceinline for the Microsoft C++ compiler in release mode (verified scenario)
30 // Use the build-in optimizer for all other C++ compilers.
31 // Note: usage of FORCE_INLINE may be reduced in the future as the latest generation of C++ compilers
32 // can handle optimization by themselves.
33 #ifndef FORCE_INLINE
34 #  ifdef _MSC_VER
35 #    ifdef NDEBUG
36 #      define FORCE_INLINE __forceinline
37 #    else
38 #      define FORCE_INLINE
39 #    endif
40 #  else
41 #    define FORCE_INLINE
42 #  endif
43 #endif
44 
45 #ifdef _MSC_VER
46 #define WARNING_SUPPRESS(x) __pragma(warning(push)) __pragma(warning(disable : x))
47 #define WARNING_UNSUPPRESS() __pragma(warning(pop))
48 #else
49 #define WARNING_SUPPRESS(x)
50 #define WARNING_UNSUPPRESS()
51 #endif
52 
53 
54 constexpr size_t int32_t_bit_count = sizeof(int32_t) * 8;
55 
56 
push_back(std::vector<uint8_t> & values,uint16_t value)57 inline void push_back(std::vector<uint8_t>& values, uint16_t value)
58 {
59     values.push_back(uint8_t(value / 0x100));
60     values.push_back(uint8_t(value % 0x100));
61 }
62 
63 
log_2(int32_t n)64 inline int32_t log_2(int32_t n) noexcept
65 {
66     int32_t x = 0;
67     while (n > (static_cast<int32_t>(1) << x))
68     {
69         ++x;
70     }
71     return x;
72 }
73 
74 
Sign(int32_t n)75 inline int32_t Sign(int32_t n) noexcept
76 {
77     return (n >> (int32_t_bit_count - 1)) | 1;
78 }
79 
80 
BitWiseSign(int32_t i)81 inline int32_t BitWiseSign(int32_t i) noexcept
82 {
83     return i >> (int32_t_bit_count - 1);
84 }
85 
86 
87 template<typename T>
88 struct Triplet
89 {
TripletTriplet90     Triplet() noexcept :
91         v1(0),
92         v2(0),
93         v3(0)
94     {}
95 
TripletTriplet96     Triplet(int32_t x1, int32_t x2, int32_t x3) noexcept :
97         v1(static_cast<T>(x1)),
98         v2(static_cast<T>(x2)),
99         v3(static_cast<T>(x3))
100     {}
101 
102     union
103     {
104         T v1;
105         T R;
106     };
107     union
108     {
109         T v2;
110         T G;
111     };
112     union
113     {
114         T v3;
115         T B;
116     };
117 };
118 
119 
120 inline bool operator==(const Triplet<uint8_t>& lhs, const Triplet<uint8_t>& rhs) noexcept
121 {
122     return lhs.v1 == rhs.v1 && lhs.v2 == rhs.v2 && lhs.v3 == rhs.v3;
123 }
124 
125 
126 inline bool operator!=(const Triplet<uint8_t>& lhs, const Triplet<uint8_t>& rhs) noexcept
127 {
128     return !(lhs == rhs);
129 }
130 
131 
132 template<typename sample>
133 struct Quad : Triplet<sample>
134 {
QuadQuad135     Quad() :
136         v4(0)
137         {}
138 
139     WARNING_SUPPRESS(26495) // false warning that v4 is unintialized
QuadQuad140     Quad(Triplet<sample> triplet, int32_t alpha) noexcept
141             :
142         Triplet<sample>(triplet),
143         A(static_cast<sample>(alpha))
144         {}
145     WARNING_UNSUPPRESS()
146 
147     union
148     {
149         sample v4;
150         sample A;
151     };
152 };
153 
154 
155 template<int size>
156 struct FromBigEndian
157 {
158 };
159 
160 
161 template<>
162 struct FromBigEndian<4>
163 {
164     FORCE_INLINE static unsigned int Read(const uint8_t* pbyte) noexcept
165     {
166         return (pbyte[0] << 24u) + (pbyte[1] << 16u) + (pbyte[2] << 8u) + (pbyte[3] << 0u);
167     }
168 };
169 
170 
171 template<>
172 struct FromBigEndian<8>
173 {
174     FORCE_INLINE static uint64_t Read(const uint8_t* pbyte) noexcept
175     {
176         return (static_cast<uint64_t>(pbyte[0]) << 56u) + (static_cast<uint64_t>(pbyte[1]) << 48u) +
177                (static_cast<uint64_t>(pbyte[2]) << 40u) + (static_cast<uint64_t>(pbyte[3]) << 32u) +
178                (static_cast<uint64_t>(pbyte[4]) << 24u) + (static_cast<uint64_t>(pbyte[5]) << 16u) +
179                (static_cast<uint64_t>(pbyte[6]) <<  8u) + (static_cast<uint64_t>(pbyte[7]) << 0u);
180     }
181 };
182 
183 
184 class charls_error : public std::system_error
185 {
186 public:
187     explicit charls_error(charls::ApiResult errorCode)
188         : system_error(static_cast<int>(errorCode), CharLSCategoryInstance())
189     {
190     }
191 
192 
193     charls_error(charls::ApiResult errorCode, const std::string& message)
194         : system_error(static_cast<int>(errorCode), CharLSCategoryInstance(), message)
195     {
196     }
197 
198 private:
199     static const std::error_category& CharLSCategoryInstance() noexcept;
200 };
201 
202 
203 inline void SkipBytes(ByteStreamInfo& streamInfo, std::size_t count) noexcept
204 {
205     if (!streamInfo.rawData)
206         return;
207 
208     streamInfo.rawData += count;
209     streamInfo.count -= count;
210 }
211 
212 
213 template<typename T>
214 std::ostream& operator<<(typename std::enable_if<std::is_enum<T>::value, std::ostream>::type& stream, const T& e)
215 {
216     return stream << static_cast<typename std::underlying_type<T>::type>(e);
217 }
218 
219 #endif
220