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