| 1 | namespace simdjson { |
| 2 | namespace SIMDJSON_IMPLEMENTATION { |
| 3 | namespace { |
| 4 | /// @private |
| 5 | namespace atomparsing { |
| 6 | |
| 7 | // The string_to_uint32 is exclusively used to map literal strings to 32-bit values. |
| 8 | // We use memcpy instead of a pointer cast to avoid undefined behaviors since we cannot |
| 9 | // be certain that the character pointer will be properly aligned. |
| 10 | // You might think that using memcpy makes this function expensive, but you'd be wrong. |
| 11 | // All decent optimizing compilers (GCC, clang, Visual Studio) will compile string_to_uint32("false"); |
| 12 | // to the compile-time constant 1936482662. |
| 13 | simdjson_inline uint32_t string_to_uint32(const char* str) { uint32_t val; std::memcpy(dest: &val, src: str, n: sizeof(uint32_t)); return val; } |
| 14 | |
| 15 | |
| 16 | // Again in str4ncmp we use a memcpy to avoid undefined behavior. The memcpy may appear expensive. |
| 17 | // Yet all decent optimizing compilers will compile memcpy to a single instruction, just about. |
| 18 | simdjson_warn_unused |
| 19 | simdjson_inline uint32_t str4ncmp(const uint8_t *src, const char* atom) { |
| 20 | uint32_t srcval; // we want to avoid unaligned 32-bit loads (undefined in C/C++) |
| 21 | static_assert(sizeof(uint32_t) <= SIMDJSON_PADDING, "SIMDJSON_PADDING must be larger than 4 bytes" ); |
| 22 | std::memcpy(dest: &srcval, src: src, n: sizeof(uint32_t)); |
| 23 | return srcval ^ string_to_uint32(str: atom); |
| 24 | } |
| 25 | |
| 26 | simdjson_warn_unused |
| 27 | simdjson_inline bool is_valid_true_atom(const uint8_t *src) { |
| 28 | return (str4ncmp(src, atom: "true" ) | jsoncharutils::is_not_structural_or_whitespace(c: src[4])) == 0; |
| 29 | } |
| 30 | |
| 31 | simdjson_warn_unused |
| 32 | simdjson_inline bool is_valid_true_atom(const uint8_t *src, size_t len) { |
| 33 | if (len > 4) { return is_valid_true_atom(src); } |
| 34 | else if (len == 4) { return !str4ncmp(src, atom: "true" ); } |
| 35 | else { return false; } |
| 36 | } |
| 37 | |
| 38 | simdjson_warn_unused |
| 39 | simdjson_inline bool is_valid_false_atom(const uint8_t *src) { |
| 40 | return (str4ncmp(src: src+1, atom: "alse" ) | jsoncharutils::is_not_structural_or_whitespace(c: src[5])) == 0; |
| 41 | } |
| 42 | |
| 43 | simdjson_warn_unused |
| 44 | simdjson_inline bool is_valid_false_atom(const uint8_t *src, size_t len) { |
| 45 | if (len > 5) { return is_valid_false_atom(src); } |
| 46 | else if (len == 5) { return !str4ncmp(src: src+1, atom: "alse" ); } |
| 47 | else { return false; } |
| 48 | } |
| 49 | |
| 50 | simdjson_warn_unused |
| 51 | simdjson_inline bool is_valid_null_atom(const uint8_t *src) { |
| 52 | return (str4ncmp(src, atom: "null" ) | jsoncharutils::is_not_structural_or_whitespace(c: src[4])) == 0; |
| 53 | } |
| 54 | |
| 55 | simdjson_warn_unused |
| 56 | simdjson_inline bool is_valid_null_atom(const uint8_t *src, size_t len) { |
| 57 | if (len > 4) { return is_valid_null_atom(src); } |
| 58 | else if (len == 4) { return !str4ncmp(src, atom: "null" ); } |
| 59 | else { return false; } |
| 60 | } |
| 61 | |
| 62 | } // namespace atomparsing |
| 63 | } // unnamed namespace |
| 64 | } // namespace SIMDJSON_IMPLEMENTATION |
| 65 | } // namespace simdjson |
| 66 | |