simdjson  3.11.0
Ridiculously Fast JSON
portability.h
1 #ifndef SIMDJSON_PORTABILITY_H
2 #define SIMDJSON_PORTABILITY_H
3 
4 #include <cstddef>
5 #include <cstdint>
6 #include <cstdlib>
7 #include <cfloat>
8 #include <cassert>
9 #ifndef _WIN32
10 // strcasecmp, strncasecmp
11 #include <strings.h>
12 #endif
13 
14 // We are using size_t without namespace std:: throughout the project
15 using std::size_t;
16 
17 #ifdef _MSC_VER
18 #define SIMDJSON_VISUAL_STUDIO 1
29 #ifdef __clang__
30 // clang under visual studio
31 #define SIMDJSON_CLANG_VISUAL_STUDIO 1
32 #else
33 // just regular visual studio (best guess)
34 #define SIMDJSON_REGULAR_VISUAL_STUDIO 1
35 #endif // __clang__
36 #endif // _MSC_VER
37 
38 #if (defined(__x86_64__) || defined(_M_AMD64)) && !defined(_M_ARM64EC)
39 #define SIMDJSON_IS_X86_64 1
40 #elif defined(__aarch64__) || defined(_M_ARM64) || defined(_M_ARM64EC)
41 #define SIMDJSON_IS_ARM64 1
42 #elif defined(__riscv) && __riscv_xlen == 64
43 #define SIMDJSON_IS_RISCV64 1
44 #elif defined(__loongarch_lp64)
45 #define SIMDJSON_IS_LOONGARCH64 1
46 #elif defined(__PPC64__) || defined(_M_PPC64)
47 #if defined(__ALTIVEC__)
48 #define SIMDJSON_IS_PPC64_VMX 1
49 #endif // defined(__ALTIVEC__)
50 #else
51 #define SIMDJSON_IS_32BITS 1
52 
53 #if defined(_M_IX86) || defined(__i386__)
54 #define SIMDJSON_IS_X86_32BITS 1
55 #elif defined(__arm__) || defined(_M_ARM)
56 #define SIMDJSON_IS_ARM_32BITS 1
57 #elif defined(__PPC__) || defined(_M_PPC)
58 #define SIMDJSON_IS_PPC_32BITS 1
59 #endif
60 
61 #endif // defined(__x86_64__) || defined(_M_AMD64)
62 #ifndef SIMDJSON_IS_32BITS
63 #define SIMDJSON_IS_32BITS 0
64 #endif
65 
66 #if SIMDJSON_IS_32BITS
67 #ifndef SIMDJSON_NO_PORTABILITY_WARNING
68 // In the future, we should allow programmers
69 // to get warning.
70 #endif // SIMDJSON_NO_PORTABILITY_WARNING
71 #endif // SIMDJSON_IS_32BITS
72 
73 #define SIMDJSON_CAT_IMPLEMENTATION_(a,...) a ## __VA_ARGS__
74 #define SIMDJSON_CAT(a,...) SIMDJSON_CAT_IMPLEMENTATION_(a, __VA_ARGS__)
75 
76 #define SIMDJSON_STRINGIFY_IMPLEMENTATION_(a,...) #a SIMDJSON_STRINGIFY(__VA_ARGS__)
77 #define SIMDJSON_STRINGIFY(a,...) SIMDJSON_CAT_IMPLEMENTATION_(a, __VA_ARGS__)
78 
79 // this is almost standard?
80 #undef SIMDJSON_STRINGIFY_IMPLEMENTATION_
81 #undef SIMDJSON_STRINGIFY
82 #define SIMDJSON_STRINGIFY_IMPLEMENTATION_(a) #a
83 #define SIMDJSON_STRINGIFY(a) SIMDJSON_STRINGIFY_IMPLEMENTATION_(a)
84 
85 // Our fast kernels require 64-bit systems.
86 //
87 // On 32-bit x86, we lack 64-bit popcnt, lzcnt, blsr instructions.
88 // Furthermore, the number of SIMD registers is reduced.
89 //
90 // On 32-bit ARM, we would have smaller registers.
91 //
92 // The simdjson users should still have the fallback kernel. It is
93 // slower, but it should run everywhere.
94 
95 //
96 // Enable valid runtime implementations, and select SIMDJSON_BUILTIN_IMPLEMENTATION
97 //
98 
99 // We are going to use runtime dispatch.
100 #if SIMDJSON_IS_X86_64
101 #ifdef __clang__
102 // clang does not have GCC push pop
103 // warning: clang attribute push can't be used within a namespace in clang up
104 // til 8.0 so SIMDJSON_TARGET_REGION and SIMDJSON_UNTARGET_REGION must be *outside* of a
105 // namespace.
106 #define SIMDJSON_TARGET_REGION(T) \
107  _Pragma(SIMDJSON_STRINGIFY( \
108  clang attribute push(__attribute__((target(T))), apply_to = function)))
109 #define SIMDJSON_UNTARGET_REGION _Pragma("clang attribute pop")
110 #elif defined(__GNUC__)
111 // GCC is easier
112 #define SIMDJSON_TARGET_REGION(T) \
113  _Pragma("GCC push_options") _Pragma(SIMDJSON_STRINGIFY(GCC target(T)))
114 #define SIMDJSON_UNTARGET_REGION _Pragma("GCC pop_options")
115 #endif // clang then gcc
116 
117 #endif // x86
118 
119 // Default target region macros don't do anything.
120 #ifndef SIMDJSON_TARGET_REGION
121 #define SIMDJSON_TARGET_REGION(T)
122 #define SIMDJSON_UNTARGET_REGION
123 #endif
124 
125 // Is threading enabled?
126 #if defined(_REENTRANT) || defined(_MT)
127 #ifndef SIMDJSON_THREADS_ENABLED
128 #define SIMDJSON_THREADS_ENABLED
129 #endif
130 #endif
131 
132 // workaround for large stack sizes under -O0.
133 // https://github.com/simdjson/simdjson/issues/691
134 #ifdef __APPLE__
135 #ifndef __OPTIMIZE__
136 // Apple systems have small stack sizes in secondary threads.
137 // Lack of compiler optimization may generate high stack usage.
138 // Users may want to disable threads for safety, but only when
139 // in debug mode which we detect by the fact that the __OPTIMIZE__
140 // macro is not defined.
141 #undef SIMDJSON_THREADS_ENABLED
142 #endif
143 #endif
144 
145 
146 #if defined(__clang__)
147 #define SIMDJSON_NO_SANITIZE_UNDEFINED __attribute__((no_sanitize("undefined")))
148 #elif defined(__GNUC__)
149 #define SIMDJSON_NO_SANITIZE_UNDEFINED __attribute__((no_sanitize_undefined))
150 #else
151 #define SIMDJSON_NO_SANITIZE_UNDEFINED
152 #endif
153 
154 #if defined(__clang__) || defined(__GNUC__)
155 #define simdjson_pure [[gnu::pure]]
156 #else
157 #define simdjson_pure
158 #endif
159 
160 #if defined(__clang__) || defined(__GNUC__)
161 #if defined(__has_feature)
162 # if __has_feature(memory_sanitizer)
163 #define SIMDJSON_NO_SANITIZE_MEMORY __attribute__((no_sanitize("memory")))
164 # endif // if __has_feature(memory_sanitizer)
165 #endif // defined(__has_feature)
166 #endif
167 // make sure it is defined as 'nothing' if it is unapplicable.
168 #ifndef SIMDJSON_NO_SANITIZE_MEMORY
169 #define SIMDJSON_NO_SANITIZE_MEMORY
170 #endif
171 
172 #if SIMDJSON_VISUAL_STUDIO
173 // This is one case where we do not distinguish between
174 // regular visual studio and clang under visual studio.
175 // clang under Windows has _stricmp (like visual studio) but not strcasecmp (as clang normally has)
176 #define simdjson_strcasecmp _stricmp
177 #define simdjson_strncasecmp _strnicmp
178 #else
179 // The strcasecmp, strncasecmp, and strcasestr functions do not work with multibyte strings (e.g. UTF-8).
180 // So they are only useful for ASCII in our context.
181 // https://www.gnu.org/software/libunistring/manual/libunistring.html#char-_002a-strings
182 #define simdjson_strcasecmp strcasecmp
183 #define simdjson_strncasecmp strncasecmp
184 #endif
185 
186 #if defined(NDEBUG) || defined(__OPTIMIZE__) || (defined(_MSC_VER) && !defined(_DEBUG))
187 // If NDEBUG is set, or __OPTIMIZE__ is set, or we are under MSVC in release mode,
188 // then do away with asserts and use __assume.
189 #if SIMDJSON_VISUAL_STUDIO
190 #define SIMDJSON_UNREACHABLE() __assume(0)
191 #define SIMDJSON_ASSUME(COND) __assume(COND)
192 #else
193 #define SIMDJSON_UNREACHABLE() __builtin_unreachable();
194 #define SIMDJSON_ASSUME(COND) do { if (!(COND)) __builtin_unreachable(); } while (0)
195 #endif
196 
197 #else // defined(NDEBUG) || defined(__OPTIMIZE__) || (defined(_MSC_VER) && !defined(_DEBUG))
198 // This should only ever be enabled in debug mode.
199 #define SIMDJSON_UNREACHABLE() assert(0);
200 #define SIMDJSON_ASSUME(COND) assert(COND)
201 
202 #endif
203 
204 
205 
206 #if defined __BYTE_ORDER__ && defined __ORDER_BIG_ENDIAN__
207 #define SIMDJSON_IS_BIG_ENDIAN (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)
208 #elif defined _WIN32
209 #define SIMDJSON_IS_BIG_ENDIAN 0
210 #else
211 #if defined(__APPLE__) || defined(__FreeBSD__)
212 #include <machine/endian.h>
213 #elif defined(sun) || defined(__sun)
214 #include <sys/byteorder.h>
215 #elif defined(__MVS__)
216 #include <sys/endian.h>
217 #else
218 #ifdef __has_include
219 #if __has_include(<endian.h>)
220 #include <endian.h>
221 #endif //__has_include(<endian.h>)
222 #endif //__has_include
223 #endif
224 #
225 #ifndef __BYTE_ORDER__
226 // safe choice
227 #define SIMDJSON_IS_BIG_ENDIAN 0
228 #endif
229 #
230 #ifndef __ORDER_LITTLE_ENDIAN__
231 // safe choice
232 #define SIMDJSON_IS_BIG_ENDIAN 0
233 #endif
234 #
235 #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
236 #define SIMDJSON_IS_BIG_ENDIAN 0
237 #else
238 #define SIMDJSON_IS_BIG_ENDIAN 1
239 #endif
240 #endif
241 
242 
243 #endif // SIMDJSON_PORTABILITY_H