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