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