1 /****************************************************************************
2 **
3 ** Copyright (C) 2015 Intel Corporation
4 **
5 ** Permission is hereby granted, free of charge, to any person obtaining a copy
6 ** of this software and associated documentation files (the "Software"), to deal
7 ** in the Software without restriction, including without limitation the rights
8 ** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 ** copies of the Software, and to permit persons to whom the Software is
10 ** furnished to do so, subject to the following conditions:
11 **
12 ** The above copyright notice and this permission notice shall be included in
13 ** all copies or substantial portions of the Software.
14 **
15 ** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 ** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 ** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 ** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 ** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 ** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 ** THE SOFTWARE.
22 **
23 ****************************************************************************/
24
25 #ifndef COMPILERSUPPORT_H
26 #define COMPILERSUPPORT_H
27
28 #include "cbor.h"
29
30 #ifdef __cplusplus
31 extern "C" {
32 #endif
33
34 #ifndef _BSD_SOURCE
35 # define _BSD_SOURCE
36 #endif
37 #ifndef _DEFAULT_SOURCE
38 # define _DEFAULT_SOURCE
39 #endif
40 #ifndef assert
41 # include <assert.h>
42 #endif
43 #include <float.h>
44 #ifndef CBOR_NO_HALF_FLOAT_TYPE
45 #include <math.h>
46 #endif
47 #include <stddef.h>
48 #include <stdint.h>
49 #include <string.h>
50
51 #ifndef __cplusplus
52 # include <stdbool.h>
53 #endif
54
55 #ifdef __F16C__
56 # include <immintrin.h>
57 #endif
58
59 #if __STDC_VERSION__ >= 201112L || __cplusplus >= 201103L || __cpp_static_assert >= 200410
60 # define cbor_static_assert(x) _Static_assert(x, #x)
61 #elif !defined(__cplusplus) && defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ >= 406)
62 # define cbor_static_assert(x) _Static_assert(x, #x)
63 #else
64 # define cbor_static_assert(x) ((void)sizeof(char[2*!!(x) - 1]))
65 #endif
66 #if __STDC_VERSION__ >= 199901L || defined(__cplusplus)
67 /* inline is a keyword */
68 #else
69 /* use the definition from cbor.h */
70 # define inline CBOR_INLINE
71 #endif
72
73 #ifndef STRINGIFY
74 #define STRINGIFY(x) STRINGIFY2(x)
75 #define STRINGIFY2(x) #x
76 #endif
77
78 #if !defined(UINT32_MAX) || !defined(INT64_MAX)
79 /* C89? We can define UINT32_MAX portably, but not INT64_MAX */
80 # error "Your system has stdint.h but that doesn't define UINT32_MAX or INT64_MAX"
81 #endif
82
83 #ifndef DBL_DECIMAL_DIG
84 /* DBL_DECIMAL_DIG is C11 */
85 # define DBL_DECIMAL_DIG 17
86 #endif
87 #define DBL_DECIMAL_DIG_STR STRINGIFY(DBL_DECIMAL_DIG)
88
89 #ifndef __has_builtin
90 # define __has_builtin(x) 0
91 #endif
92
93 #if (defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ >= 403)) || \
94 (__has_builtin(__builtin_bswap64) && __has_builtin(__builtin_bswap32))
95 # if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
96 # define cbor_ntohll __builtin_bswap64
97 # define cbor_htonll __builtin_bswap64
98 # define cbor_ntohl __builtin_bswap32
99 # define cbor_htonl __builtin_bswap32
100 # ifdef __INTEL_COMPILER
101 # define cbor_ntohs _bswap16
102 # define cbor_htons _bswap16
103 # elif (__GNUC__ * 100 + __GNUC_MINOR__ >= 608) || __has_builtin(__builtin_bswap16)
104 # define cbor_ntohs __builtin_bswap16
105 # define cbor_htons __builtin_bswap16
106 # else
107 # define cbor_ntohs(x) (((uint16_t)x >> 8) | ((uint16_t)x << 8))
108 # define cbor_htons cbor_ntohs
109 # endif
110 # else
111 # define cbor_ntohll
112 # define cbor_htonll
113 # define cbor_ntohl
114 # define cbor_htonl
115 # define cbor_ntohs
116 # define cbor_htons
117 # endif
118 #elif defined(__sun)
119 # include <sys/byteorder.h>
120 #elif defined(_MSC_VER)
121 /* MSVC, which implies Windows, which implies little-endian and sizeof(long) == 4 */
122 # define cbor_ntohll _byteswap_uint64
123 # define cbor_htonll _byteswap_uint64
124 # define cbor_ntohl _byteswap_ulong
125 # define cbor_htonl _byteswap_ulong
126 # define cbor_ntohs _byteswap_ushort
127 # define cbor_htons _byteswap_ushort
128 #endif
129 #ifndef cbor_ntohs
130 # include <arpa/inet.h>
131 # define cbor_ntohs ntohs
132 # define cbor_htons htons
133 #endif
134 #ifndef cbor_ntohl
135 # include <arpa/inet.h>
136 # define cbor_ntohl ntohl
137 # define cbor_htonl htonl
138 #endif
139 #ifndef cbor_ntohll
140 # define cbor_ntohll ntohll
141 # define cbor_htonll htonll
142 /* ntohll isn't usually defined */
143 # ifndef ntohll
144 # if defined(__BYTE_ORDER__) && defined(__ORDER_BIG_ENDIAN__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
145 # define ntohll
146 # define htonll
147 # elif defined(__BYTE_ORDER__) && defined(__ORDER_LITTLE_ENDIAN__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
148 # define ntohll(x) ((ntohl((uint32_t)(x)) * UINT64_C(0x100000000)) + (ntohl((x) >> 32)))
149 # define htonll ntohll
150 # else
151 # error "Unable to determine byte order!"
152 # endif
153 # endif
154 #endif
155
156
157 #ifdef __cplusplus
158 # define CONST_CAST(t, v) const_cast<t>(v)
159 #else
160 /* C-style const_cast without triggering a warning with -Wcast-qual */
161 # define CONST_CAST(t, v) (t)(uintptr_t)(v)
162 #endif
163
164 #ifdef __GNUC__
165 #ifndef likely
166 # define likely(x) __builtin_expect(!!(x), 1)
167 #endif
168 #ifndef unlikely
169 # define unlikely(x) __builtin_expect(!!(x), 0)
170 #endif
171 # define unreachable() __builtin_unreachable()
172 #elif defined(_MSC_VER)
173 # define likely(x) (x)
174 # define unlikely(x) (x)
175 # define unreachable() __assume(0)
176 #else
177 # define likely(x) (x)
178 # define unlikely(x) (x)
179 # define unreachable() do {} while (0)
180 #endif
181
add_check_overflow(size_t v1,size_t v2,size_t * r)182 static inline bool add_check_overflow(size_t v1, size_t v2, size_t *r)
183 {
184 #if ((defined(__GNUC__) && (__GNUC__ >= 5)) && !defined(__INTEL_COMPILER)) || __has_builtin(__builtin_add_overflow)
185 return __builtin_add_overflow(v1, v2, r);
186 #else
187 /* unsigned additions are well-defined */
188 *r = v1 + v2;
189 return v1 > v1 + v2;
190 #endif
191 }
192
193 #ifndef CBOR_NO_HALF_FLOAT_TYPE
encode_half(double val)194 static inline unsigned short encode_half(double val)
195 {
196 #ifdef __F16C__
197 return _cvtss_sh(val, 3);
198 #else
199 uint64_t v;
200 memcpy(&v, &val, sizeof(v));
201 int sign = v >> 63 << 15;
202 int exp = (v >> 52) & 0x7ff;
203 int mant = v << 12 >> 12 >> (53-11); /* keep only the 11 most significant bits of the mantissa */
204 exp -= 1023;
205 if (exp == 1024) {
206 /* infinity or NaN */
207 exp = 16;
208 mant >>= 1;
209 } else if (exp >= 16) {
210 /* overflow, as largest number */
211 exp = 15;
212 mant = 1023;
213 } else if (exp >= -14) {
214 /* regular normal */
215 } else if (exp >= -24) {
216 /* subnormal */
217 mant |= 1024;
218 mant >>= -(exp + 14);
219 exp = -15;
220 } else {
221 /* underflow, make zero */
222 return 0;
223 }
224 return sign | ((exp + 15) << 10) | mant;
225 #endif
226 }
227 #endif
228
229 #ifdef __cplusplus
230 }
231 #endif
232
233 #endif /* COMPILERSUPPORT_H */
234
235