| 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 | |