1 | #ifndef SIMDJSON_COMMON_DEFS_H |
2 | #define SIMDJSON_COMMON_DEFS_H |
3 | |
4 | #include <cassert> |
5 | #include "simdjson/portability.h" |
6 | |
7 | namespace simdjson { |
8 | |
9 | namespace internal { |
10 | /** |
11 | * @private |
12 | * Our own implementation of the C++17 to_chars function. |
13 | * Defined in src/to_chars |
14 | */ |
15 | char *to_chars(char *first, const char *last, double value); |
16 | /** |
17 | * @private |
18 | * A number parsing routine. |
19 | * Defined in src/from_chars |
20 | */ |
21 | double from_chars(const char *first) noexcept; |
22 | double from_chars(const char *first, const char* end) noexcept; |
23 | |
24 | } |
25 | |
26 | #ifndef SIMDJSON_EXCEPTIONS |
27 | #if __cpp_exceptions |
28 | #define SIMDJSON_EXCEPTIONS 1 |
29 | #else |
30 | #define SIMDJSON_EXCEPTIONS 0 |
31 | #endif |
32 | #endif |
33 | |
34 | /** The maximum document size supported by simdjson. */ |
35 | constexpr size_t SIMDJSON_MAXSIZE_BYTES = 0xFFFFFFFF; |
36 | |
37 | /** |
38 | * The amount of padding needed in a buffer to parse JSON. |
39 | * |
40 | * The input buf should be readable up to buf + SIMDJSON_PADDING |
41 | * this is a stopgap; there should be a better description of the |
42 | * main loop and its behavior that abstracts over this |
43 | * See https://github.com/simdjson/simdjson/issues/174 |
44 | */ |
45 | constexpr size_t SIMDJSON_PADDING = 64; |
46 | |
47 | /** |
48 | * By default, simdjson supports this many nested objects and arrays. |
49 | * |
50 | * This is the default for parser::max_depth(). |
51 | */ |
52 | constexpr size_t DEFAULT_MAX_DEPTH = 1024; |
53 | |
54 | } // namespace simdjson |
55 | |
56 | #if defined(__GNUC__) |
57 | // Marks a block with a name so that MCA analysis can see it. |
58 | #define SIMDJSON_BEGIN_DEBUG_BLOCK(name) __asm volatile("# LLVM-MCA-BEGIN " #name); |
59 | #define SIMDJSON_END_DEBUG_BLOCK(name) __asm volatile("# LLVM-MCA-END " #name); |
60 | #define SIMDJSON_DEBUG_BLOCK(name, block) BEGIN_DEBUG_BLOCK(name); block; END_DEBUG_BLOCK(name); |
61 | #else |
62 | #define SIMDJSON_BEGIN_DEBUG_BLOCK(name) |
63 | #define SIMDJSON_END_DEBUG_BLOCK(name) |
64 | #define SIMDJSON_DEBUG_BLOCK(name, block) |
65 | #endif |
66 | |
67 | // Align to N-byte boundary |
68 | #define SIMDJSON_ROUNDUP_N(a, n) (((a) + ((n)-1)) & ~((n)-1)) |
69 | #define SIMDJSON_ROUNDDOWN_N(a, n) ((a) & ~((n)-1)) |
70 | |
71 | #define SIMDJSON_ISALIGNED_N(ptr, n) (((uintptr_t)(ptr) & ((n)-1)) == 0) |
72 | |
73 | #if SIMDJSON_REGULAR_VISUAL_STUDIO |
74 | |
75 | #define simdjson_really_inline __forceinline |
76 | #define simdjson_never_inline __declspec(noinline) |
77 | |
78 | #define simdjson_unused |
79 | #define simdjson_warn_unused |
80 | |
81 | #ifndef simdjson_likely |
82 | #define simdjson_likely(x) x |
83 | #endif |
84 | #ifndef simdjson_unlikely |
85 | #define simdjson_unlikely(x) x |
86 | #endif |
87 | |
88 | #define SIMDJSON_PUSH_DISABLE_WARNINGS __pragma(warning( push )) |
89 | #define SIMDJSON_PUSH_DISABLE_ALL_WARNINGS __pragma(warning( push, 0 )) |
90 | #define SIMDJSON_DISABLE_VS_WARNING(WARNING_NUMBER) __pragma(warning( disable : WARNING_NUMBER )) |
91 | // Get rid of Intellisense-only warnings (Code Analysis) |
92 | // Though __has_include is C++17, it is supported in Visual Studio 2017 or better (_MSC_VER>=1910). |
93 | #ifdef __has_include |
94 | #if __has_include(<CppCoreCheck\Warnings.h>) |
95 | #include <CppCoreCheck\Warnings.h> |
96 | #define SIMDJSON_DISABLE_UNDESIRED_WARNINGS SIMDJSON_DISABLE_VS_WARNING(ALL_CPPCORECHECK_WARNINGS) |
97 | #endif |
98 | #endif |
99 | |
100 | #ifndef SIMDJSON_DISABLE_UNDESIRED_WARNINGS |
101 | #define SIMDJSON_DISABLE_UNDESIRED_WARNINGS |
102 | #endif |
103 | |
104 | #define SIMDJSON_DISABLE_DEPRECATED_WARNING SIMDJSON_DISABLE_VS_WARNING(4996) |
105 | #define SIMDJSON_DISABLE_STRICT_OVERFLOW_WARNING |
106 | #define SIMDJSON_POP_DISABLE_WARNINGS __pragma(warning( pop )) |
107 | |
108 | #else // SIMDJSON_REGULAR_VISUAL_STUDIO |
109 | |
110 | #define simdjson_really_inline inline __attribute__((always_inline)) |
111 | #define simdjson_never_inline inline __attribute__((noinline)) |
112 | |
113 | #define simdjson_unused __attribute__((unused)) |
114 | #define simdjson_warn_unused __attribute__((warn_unused_result)) |
115 | |
116 | #ifndef simdjson_likely |
117 | #define simdjson_likely(x) __builtin_expect(!!(x), 1) |
118 | #endif |
119 | #ifndef simdjson_unlikely |
120 | #define simdjson_unlikely(x) __builtin_expect(!!(x), 0) |
121 | #endif |
122 | |
123 | #define SIMDJSON_PUSH_DISABLE_WARNINGS _Pragma("GCC diagnostic push") |
124 | // gcc doesn't seem to disable all warnings with all and extra, add warnings here as necessary |
125 | // We do it separately for clang since it has different warnings. |
126 | #ifdef __clang__ |
127 | // clang is missing -Wmaybe-uninitialized. |
128 | #define SIMDJSON_PUSH_DISABLE_ALL_WARNINGS SIMDJSON_PUSH_DISABLE_WARNINGS \ |
129 | SIMDJSON_DISABLE_GCC_WARNING(-Weffc++) \ |
130 | SIMDJSON_DISABLE_GCC_WARNING(-Wall) \ |
131 | SIMDJSON_DISABLE_GCC_WARNING(-Wconversion) \ |
132 | SIMDJSON_DISABLE_GCC_WARNING(-Wextra) \ |
133 | SIMDJSON_DISABLE_GCC_WARNING(-Wattributes) \ |
134 | SIMDJSON_DISABLE_GCC_WARNING(-Wimplicit-fallthrough) \ |
135 | SIMDJSON_DISABLE_GCC_WARNING(-Wnon-virtual-dtor) \ |
136 | SIMDJSON_DISABLE_GCC_WARNING(-Wreturn-type) \ |
137 | SIMDJSON_DISABLE_GCC_WARNING(-Wshadow) \ |
138 | SIMDJSON_DISABLE_GCC_WARNING(-Wunused-parameter) \ |
139 | SIMDJSON_DISABLE_GCC_WARNING(-Wunused-variable) |
140 | #else // __clang__ |
141 | #define SIMDJSON_PUSH_DISABLE_ALL_WARNINGS SIMDJSON_PUSH_DISABLE_WARNINGS \ |
142 | SIMDJSON_DISABLE_GCC_WARNING(-Weffc++) \ |
143 | SIMDJSON_DISABLE_GCC_WARNING(-Wall) \ |
144 | SIMDJSON_DISABLE_GCC_WARNING(-Wconversion) \ |
145 | SIMDJSON_DISABLE_GCC_WARNING(-Wextra) \ |
146 | SIMDJSON_DISABLE_GCC_WARNING(-Wattributes) \ |
147 | SIMDJSON_DISABLE_GCC_WARNING(-Wimplicit-fallthrough) \ |
148 | SIMDJSON_DISABLE_GCC_WARNING(-Wnon-virtual-dtor) \ |
149 | SIMDJSON_DISABLE_GCC_WARNING(-Wreturn-type) \ |
150 | SIMDJSON_DISABLE_GCC_WARNING(-Wshadow) \ |
151 | SIMDJSON_DISABLE_GCC_WARNING(-Wunused-parameter) \ |
152 | SIMDJSON_DISABLE_GCC_WARNING(-Wunused-variable) \ |
153 | SIMDJSON_DISABLE_GCC_WARNING(-Wmaybe-uninitialized) |
154 | #endif // __clang__ |
155 | |
156 | #define SIMDJSON_PRAGMA(P) _Pragma(#P) |
157 | #define SIMDJSON_DISABLE_GCC_WARNING(WARNING) SIMDJSON_PRAGMA(GCC diagnostic ignored #WARNING) |
158 | #if SIMDJSON_CLANG_VISUAL_STUDIO |
159 | #define SIMDJSON_DISABLE_UNDESIRED_WARNINGS SIMDJSON_DISABLE_GCC_WARNING(-Wmicrosoft-include) |
160 | #else |
161 | #define SIMDJSON_DISABLE_UNDESIRED_WARNINGS |
162 | #endif |
163 | #define SIMDJSON_DISABLE_DEPRECATED_WARNING SIMDJSON_DISABLE_GCC_WARNING(-Wdeprecated-declarations) |
164 | #define SIMDJSON_DISABLE_STRICT_OVERFLOW_WARNING SIMDJSON_DISABLE_GCC_WARNING(-Wstrict-overflow) |
165 | #define SIMDJSON_POP_DISABLE_WARNINGS _Pragma("GCC diagnostic pop") |
166 | |
167 | |
168 | |
169 | #endif // MSC_VER |
170 | |
171 | #if defined(simdjson_inline) |
172 | // Prefer the user's definition of simdjson_inline; don't define it ourselves. |
173 | #elif defined(__GNUC__) && !defined(__OPTIMIZE__) |
174 | // If optimizations are disabled, forcing inlining can lead to significant |
175 | // code bloat and high compile times. Don't use simdjson_really_inline for |
176 | // unoptimized builds. |
177 | #define simdjson_inline inline |
178 | #else |
179 | // Force inlining for most simdjson functions. |
180 | #define simdjson_inline simdjson_really_inline |
181 | #endif |
182 | |
183 | #if SIMDJSON_VISUAL_STUDIO |
184 | /** |
185 | * Windows users need to do some extra work when building |
186 | * or using a dynamic library (DLL). When building, we need |
187 | * to set SIMDJSON_DLLIMPORTEXPORT to __declspec(dllexport). |
188 | * When *using* the DLL, the user needs to set |
189 | * SIMDJSON_DLLIMPORTEXPORT __declspec(dllimport). |
190 | * |
191 | * Static libraries not need require such work. |
192 | * |
193 | * It does not matter here whether you are using |
194 | * the regular visual studio or clang under visual |
195 | * studio, you still need to handle these issues. |
196 | * |
197 | * Non-Windows systems do not have this complexity. |
198 | */ |
199 | #if SIMDJSON_BUILDING_WINDOWS_DYNAMIC_LIBRARY |
200 | // We set SIMDJSON_BUILDING_WINDOWS_DYNAMIC_LIBRARY when we build a DLL under Windows. |
201 | // It should never happen that both SIMDJSON_BUILDING_WINDOWS_DYNAMIC_LIBRARY and |
202 | // SIMDJSON_USING_WINDOWS_DYNAMIC_LIBRARY are set. |
203 | #define SIMDJSON_DLLIMPORTEXPORT __declspec(dllexport) |
204 | #elif SIMDJSON_USING_WINDOWS_DYNAMIC_LIBRARY |
205 | // Windows user who call a dynamic library should set SIMDJSON_USING_WINDOWS_DYNAMIC_LIBRARY to 1. |
206 | #define SIMDJSON_DLLIMPORTEXPORT __declspec(dllimport) |
207 | #else |
208 | // We assume by default static linkage |
209 | #define SIMDJSON_DLLIMPORTEXPORT |
210 | #endif |
211 | |
212 | /** |
213 | * Workaround for the vcpkg package manager. Only vcpkg should |
214 | * ever touch the next line. The SIMDJSON_USING_LIBRARY macro is otherwise unused. |
215 | */ |
216 | #if SIMDJSON_USING_LIBRARY |
217 | #define SIMDJSON_DLLIMPORTEXPORT __declspec(dllimport) |
218 | #endif |
219 | /** |
220 | * End of workaround for the vcpkg package manager. |
221 | */ |
222 | #else |
223 | #define SIMDJSON_DLLIMPORTEXPORT |
224 | #endif |
225 | |
226 | // C++17 requires string_view. |
227 | #if SIMDJSON_CPLUSPLUS17 |
228 | #define SIMDJSON_HAS_STRING_VIEW |
229 | #include <string_view> // by the standard, this has to be safe. |
230 | #endif |
231 | |
232 | // This macro (__cpp_lib_string_view) has to be defined |
233 | // for C++17 and better, but if it is otherwise defined, |
234 | // we are going to assume that string_view is available |
235 | // even if we do not have C++17 support. |
236 | #ifdef __cpp_lib_string_view |
237 | #define SIMDJSON_HAS_STRING_VIEW |
238 | #endif |
239 | |
240 | // Some systems have string_view even if we do not have C++17 support, |
241 | // and even if __cpp_lib_string_view is undefined, it is the case |
242 | // with Apple clang version 11. |
243 | // We must handle it. *This is important.* |
244 | #ifndef SIMDJSON_HAS_STRING_VIEW |
245 | #if defined __has_include |
246 | // do not combine the next #if with the previous one (unsafe) |
247 | #if __has_include (<string_view>) |
248 | // now it is safe to trigger the include |
249 | #include <string_view> // though the file is there, it does not follow that we got the implementation |
250 | #if defined(_LIBCPP_STRING_VIEW) |
251 | // Ah! So we under libc++ which under its Library Fundamentals Technical Specification, which preceded C++17, |
252 | // included string_view. |
253 | // This means that we have string_view *even though* we may not have C++17. |
254 | #define SIMDJSON_HAS_STRING_VIEW |
255 | #endif // _LIBCPP_STRING_VIEW |
256 | #endif // __has_include (<string_view>) |
257 | #endif // defined __has_include |
258 | #endif // def SIMDJSON_HAS_STRING_VIEW |
259 | // end of complicated but important routine to try to detect string_view. |
260 | |
261 | // |
262 | // Backfill std::string_view using nonstd::string_view on systems where |
263 | // we expect that string_view is missing. Important: if we get this wrong, |
264 | // we will end up with two string_view definitions and potential trouble. |
265 | // That is why we work so hard above to avoid it. |
266 | // |
267 | #ifndef SIMDJSON_HAS_STRING_VIEW |
268 | SIMDJSON_PUSH_DISABLE_ALL_WARNINGS |
269 | #include "simdjson/nonstd/string_view.hpp" |
270 | SIMDJSON_POP_DISABLE_WARNINGS |
271 | |
272 | namespace std { |
273 | using string_view = nonstd::string_view; |
274 | } |
275 | #endif // SIMDJSON_HAS_STRING_VIEW |
276 | #undef SIMDJSON_HAS_STRING_VIEW // We are not going to need this macro anymore. |
277 | |
278 | /// If EXPR is an error, returns it. |
279 | #define SIMDJSON_TRY(EXPR) { auto _err = (EXPR); if (_err) { return _err; } } |
280 | |
281 | // Unless the programmer has already set SIMDJSON_DEVELOPMENT_CHECKS, |
282 | // we want to set it under debug builds. We detect a debug build |
283 | // under Visual Studio when the _DEBUG macro is set. Under the other |
284 | // compilers, we use the fact that they define __OPTIMIZE__ whenever |
285 | // they allow optimizations. |
286 | // It is possible that this could miss some cases where SIMDJSON_DEVELOPMENT_CHECKS |
287 | // is helpful, but the programmer can set the macro SIMDJSON_DEVELOPMENT_CHECKS. |
288 | // It could also wrongly set SIMDJSON_DEVELOPMENT_CHECKS (e.g., if the programmer |
289 | // sets _DEBUG in a release build under Visual Studio, or if some compiler fails to |
290 | // set the __OPTIMIZE__ macro). |
291 | #ifndef SIMDJSON_DEVELOPMENT_CHECKS |
292 | #ifdef _MSC_VER |
293 | // Visual Studio seems to set _DEBUG for debug builds. |
294 | #ifdef _DEBUG |
295 | #define SIMDJSON_DEVELOPMENT_CHECKS 1 |
296 | #endif // _DEBUG |
297 | #else // _MSC_VER |
298 | // All other compilers appear to set __OPTIMIZE__ to a positive integer |
299 | // when the compiler is optimizing. |
300 | #ifndef __OPTIMIZE__ |
301 | #define SIMDJSON_DEVELOPMENT_CHECKS 1 |
302 | #endif // __OPTIMIZE__ |
303 | #endif // _MSC_VER |
304 | #endif // SIMDJSON_DEVELOPMENT_CHECKS |
305 | |
306 | // The SIMDJSON_CHECK_EOF macro is a feature flag for the "don't require padding" |
307 | // feature. |
308 | |
309 | #if SIMDJSON_CPLUSPLUS17 |
310 | // if we have C++, then fallthrough is a default attribute |
311 | # define simdjson_fallthrough [[fallthrough]] |
312 | // check if we have __attribute__ support |
313 | #elif defined(__has_attribute) |
314 | // check if we have the __fallthrough__ attribute |
315 | #if __has_attribute(__fallthrough__) |
316 | // we are good to go: |
317 | # define simdjson_fallthrough __attribute__((__fallthrough__)) |
318 | #endif // __has_attribute(__fallthrough__) |
319 | #endif // SIMDJSON_CPLUSPLUS17 |
320 | // on some systems, we simply do not have support for fallthrough, so use a default: |
321 | #ifndef simdjson_fallthrough |
322 | # define simdjson_fallthrough do {} while (0) /* fallthrough */ |
323 | #endif // simdjson_fallthrough |
324 | |
325 | |
326 | #if SIMDJSON_DEVELOPMENT_CHECKS |
327 | #define SIMDJSON_DEVELOPMENT_ASSERT(expr) do { assert ((expr)); } while (0) |
328 | #else |
329 | #define SIMDJSON_DEVELOPMENT_ASSERT(expr) do { } while (0) |
330 | #endif |
331 | |
332 | #ifndef SIMDJSON_UTF8VALIDATION |
333 | #define SIMDJSON_UTF8VALIDATION 1 |
334 | #endif |
335 | |
336 | #endif // SIMDJSON_COMMON_DEFS_H |
337 | |