simdjson  3.11.0
Ridiculously Fast JSON
tape_ref-inl.h
1 #ifndef SIMDJSON_TAPE_REF_INL_H
2 #define SIMDJSON_TAPE_REF_INL_H
3 
4 #include "simdjson/dom/document.h"
5 #include "simdjson/internal/tape_ref.h"
6 #include "simdjson/internal/tape_type.h"
7 
8 #include <cstring>
9 
10 namespace simdjson {
11 namespace internal {
12 
13 constexpr const uint64_t JSON_VALUE_MASK = 0x00FFFFFFFFFFFFFF;
14 constexpr const uint32_t JSON_COUNT_MASK = 0xFFFFFF;
15 
16 //
17 // tape_ref inline implementation
18 //
19 simdjson_inline tape_ref::tape_ref() noexcept : doc{nullptr}, json_index{0} {}
20 simdjson_inline tape_ref::tape_ref(const dom::document *_doc, size_t _json_index) noexcept : doc{_doc}, json_index{_json_index} {}
21 
22 
23 simdjson_inline bool tape_ref::is_document_root() const noexcept {
24  return json_index == 1; // should we ever change the structure of the tape, this should get updated.
25 }
26 simdjson_inline bool tape_ref::usable() const noexcept {
27  return doc != nullptr; // when the document pointer is null, this tape_ref is uninitialized (should not be accessed).
28 }
29 // Some value types have a specific on-tape word value. It can be faster
30 // to check the type by doing a word-to-word comparison instead of extracting the
31 // most significant 8 bits.
32 
33 simdjson_inline bool tape_ref::is_double() const noexcept {
34  constexpr uint64_t tape_double = uint64_t(tape_type::DOUBLE)<<56;
35  return doc->tape[json_index] == tape_double;
36 }
37 simdjson_inline bool tape_ref::is_int64() const noexcept {
38  constexpr uint64_t tape_int64 = uint64_t(tape_type::INT64)<<56;
39  return doc->tape[json_index] == tape_int64;
40 }
41 simdjson_inline bool tape_ref::is_uint64() const noexcept {
42  constexpr uint64_t tape_uint64 = uint64_t(tape_type::UINT64)<<56;
43  return doc->tape[json_index] == tape_uint64;
44 }
45 simdjson_inline bool tape_ref::is_false() const noexcept {
46  constexpr uint64_t tape_false = uint64_t(tape_type::FALSE_VALUE)<<56;
47  return doc->tape[json_index] == tape_false;
48 }
49 simdjson_inline bool tape_ref::is_true() const noexcept {
50  constexpr uint64_t tape_true = uint64_t(tape_type::TRUE_VALUE)<<56;
51  return doc->tape[json_index] == tape_true;
52 }
53 simdjson_inline bool tape_ref::is_null_on_tape() const noexcept {
54  constexpr uint64_t tape_null = uint64_t(tape_type::NULL_VALUE)<<56;
55  return doc->tape[json_index] == tape_null;
56 }
57 
58 inline size_t tape_ref::after_element() const noexcept {
59  switch (tape_ref_type()) {
60  case tape_type::START_ARRAY:
61  case tape_type::START_OBJECT:
62  return matching_brace_index();
63  case tape_type::UINT64:
64  case tape_type::INT64:
65  case tape_type::DOUBLE:
66  return json_index + 2;
67  default:
68  return json_index + 1;
69  }
70 }
71 simdjson_inline tape_type tape_ref::tape_ref_type() const noexcept {
72  return static_cast<tape_type>(doc->tape[json_index] >> 56);
73 }
74 simdjson_inline uint64_t internal::tape_ref::tape_value() const noexcept {
75  return doc->tape[json_index] & internal::JSON_VALUE_MASK;
76 }
77 simdjson_inline uint32_t internal::tape_ref::matching_brace_index() const noexcept {
78  return uint32_t(doc->tape[json_index]);
79 }
80 simdjson_inline uint32_t internal::tape_ref::scope_count() const noexcept {
81  return uint32_t((doc->tape[json_index] >> 32) & internal::JSON_COUNT_MASK);
82 }
83 
84 template<typename T>
85 simdjson_inline T tape_ref::next_tape_value() const noexcept {
86  static_assert(sizeof(T) == sizeof(uint64_t), "next_tape_value() template parameter must be 64-bit");
87  // Though the following is tempting...
88  // return *reinterpret_cast<const T*>(&doc->tape[json_index + 1]);
89  // It is not generally safe. It is safer, and often faster to rely
90  // on memcpy. Yes, it is uglier, but it is also encapsulated.
91  T x;
92  std::memcpy(&x,&doc->tape[json_index + 1],sizeof(uint64_t));
93  return x;
94 }
95 
96 simdjson_inline uint32_t internal::tape_ref::get_string_length() const noexcept {
97  size_t string_buf_index = size_t(tape_value());
98  uint32_t len;
99  std::memcpy(&len, &doc->string_buf[string_buf_index], sizeof(len));
100  return len;
101 }
102 
103 simdjson_inline const char * internal::tape_ref::get_c_str() const noexcept {
104  size_t string_buf_index = size_t(tape_value());
105  return reinterpret_cast<const char *>(&doc->string_buf[string_buf_index + sizeof(uint32_t)]);
106 }
107 
108 inline std::string_view internal::tape_ref::get_string_view() const noexcept {
109  return std::string_view(
110  get_c_str(),
111  get_string_length()
112  );
113 }
114 
115 } // namespace internal
116 } // namespace simdjson
117 
118 #endif // SIMDJSON_TAPE_REF_INL_H
The top level simdjson namespace, containing everything the library provides.
Definition: base.h:8