Coverage Report

Created: 2023-06-07 06:07

/src/simdjson/include/simdjson/dom/document-inl.h
Line
Count
Source (jump to first uncovered line)
1
#ifndef SIMDJSON_INLINE_DOCUMENT_H
2
#define SIMDJSON_INLINE_DOCUMENT_H
3
4
// Inline implementations go in here.
5
6
#include "simdjson/dom/document.h"
7
#include "simdjson/dom/element.h"
8
#include "simdjson/internal/tape_ref.h"
9
#include "simdjson/internal/jsonformatutils.h"
10
#include <ostream>
11
#include <cstring>
12
13
namespace simdjson {
14
namespace dom {
15
16
//
17
// document inline implementation
18
//
19
184k
inline element document::root() const noexcept {
20
184k
  return element(internal::tape_ref(this, 1));
21
184k
}
22
simdjson_warn_unused
23
123k
inline size_t document::capacity() const noexcept {
24
123k
  return allocated_capacity;
25
123k
}
26
27
simdjson_warn_unused
28
114k
inline error_code document::allocate(size_t capacity) noexcept {
29
114k
  if (capacity == 0) {
30
0
    string_buf.reset();
31
0
    tape.reset();
32
0
    allocated_capacity = 0;
33
0
    return SUCCESS;
34
0
  }
35
36
  // a pathological input like "[[[[..." would generate capacity tape elements, so
37
  // need a capacity of at least capacity + 1, but it is also possible to do
38
  // worse with "[7,7,7,7,6,7,7,7,6,7,7,6,[7,7,7,7,6,7,7,7,6,7,7,6,7,7,7,7,7,7,6"
39
  //where capacity + 1 tape elements are
40
  // generated, see issue https://github.com/simdjson/simdjson/issues/345
41
114k
  size_t tape_capacity = SIMDJSON_ROUNDUP_N(capacity + 3, 64);
42
  // a document with only zero-length strings... could have capacity/3 string
43
  // and we would need capacity/3 * 5 bytes on the string buffer
44
114k
  size_t string_capacity = SIMDJSON_ROUNDUP_N(5 * capacity / 3 + SIMDJSON_PADDING, 64);
45
114k
  string_buf.reset( new (std::nothrow) uint8_t[string_capacity]);
46
114k
  tape.reset(new (std::nothrow) uint64_t[tape_capacity]);
47
114k
  if(!(string_buf && tape)) {
48
0
    allocated_capacity = 0;
49
0
    string_buf.reset();
50
0
    tape.reset();
51
0
    return MEMALLOC;
52
0
  }
53
  // Technically the allocated_capacity might be larger than capacity
54
  // so the next line is pessimistic.
55
114k
  allocated_capacity = capacity;
56
114k
  return SUCCESS;
57
114k
}
58
59
5.73k
inline bool document::dump_raw_tape(std::ostream &os) const noexcept {
60
5.73k
  uint32_t string_length;
61
5.73k
  size_t tape_idx = 0;
62
5.73k
  uint64_t tape_val = tape[tape_idx];
63
5.73k
  uint8_t type = uint8_t(tape_val >> 56);
64
5.73k
  os << tape_idx << " : " << type;
65
5.73k
  tape_idx++;
66
5.73k
  size_t how_many = 0;
67
5.73k
  if (type == 'r') {
68
5.73k
    how_many = size_t(tape_val & internal::JSON_VALUE_MASK);
69
5.73k
  } else {
70
    // Error: no starting root node?
71
0
    return false;
72
0
  }
73
5.73k
  os << "\t// pointing to " << how_many << " (right after last node)\n";
74
5.73k
  uint64_t payload;
75
2.69M
  for (; tape_idx < how_many; tape_idx++) {
76
2.69M
    os << tape_idx << " : ";
77
2.69M
    tape_val = tape[tape_idx];
78
2.69M
    payload = tape_val & internal::JSON_VALUE_MASK;
79
2.69M
    type = uint8_t(tape_val >> 56);
80
2.69M
    switch (type) {
81
73.1k
    case '"': // we have a string
82
73.1k
      os << "string \"";
83
73.1k
      std::memcpy(&string_length, string_buf.get() + payload, sizeof(uint32_t));
84
73.1k
      os << internal::escape_json_string(std::string_view(
85
73.1k
        reinterpret_cast<const char *>(string_buf.get() + payload + sizeof(uint32_t)),
86
73.1k
        string_length
87
73.1k
      ));
88
73.1k
      os << '"';
89
73.1k
      os << '\n';
90
73.1k
      break;
91
2.52M
    case 'l': // we have a long int
92
2.52M
      if (tape_idx + 1 >= how_many) {
93
0
        return false;
94
0
      }
95
2.52M
      os << "integer " << static_cast<int64_t>(tape[++tape_idx]) << "\n";
96
2.52M
      break;
97
1.11k
    case 'u': // we have a long uint
98
1.11k
      if (tape_idx + 1 >= how_many) {
99
0
        return false;
100
0
      }
101
1.11k
      os << "unsigned integer " << tape[++tape_idx] << "\n";
102
1.11k
      break;
103
74.4k
    case 'd': // we have a double
104
74.4k
      os << "float ";
105
74.4k
      if (tape_idx + 1 >= how_many) {
106
0
        return false;
107
0
      }
108
74.4k
      double answer;
109
74.4k
      std::memcpy(&answer, &tape[++tape_idx], sizeof(answer));
110
74.4k
      os << answer << '\n';
111
74.4k
      break;
112
650
    case 'n': // we have a null
113
650
      os << "null\n";
114
650
      break;
115
778
    case 't': // we have a true
116
778
      os << "true\n";
117
778
      break;
118
521
    case 'f': // we have a false
119
521
      os << "false\n";
120
521
      break;
121
2.46k
    case '{': // we have an object
122
2.46k
      os << "{\t// pointing to next tape location " << uint32_t(payload)
123
2.46k
         << " (first node after the scope), "
124
2.46k
         << " saturated count "
125
2.46k
         << ((payload >> 32) & internal::JSON_COUNT_MASK)<< "\n";
126
2.46k
      break;    case '}': // we end an object
127
2.46k
      os << "}\t// pointing to previous tape location " << uint32_t(payload)
128
2.46k
         << " (start of the scope)\n";
129
2.46k
      break;
130
4.00k
    case '[': // we start an array
131
4.00k
      os << "[\t// pointing to next tape location " << uint32_t(payload)
132
4.00k
         << " (first node after the scope), "
133
4.00k
         << " saturated count "
134
4.00k
         << ((payload >> 32) & internal::JSON_COUNT_MASK)<< "\n";
135
4.00k
      break;
136
4.00k
    case ']': // we end an array
137
4.00k
      os << "]\t// pointing to previous tape location " << uint32_t(payload)
138
4.00k
         << " (start of the scope)\n";
139
4.00k
      break;
140
5.73k
    case 'r': // we start and end with the root node
141
      // should we be hitting the root node?
142
5.73k
      return false;
143
0
    default:
144
0
      return false;
145
2.69M
    }
146
2.69M
  }
147
0
  tape_val = tape[tape_idx];
148
0
  payload = tape_val & internal::JSON_VALUE_MASK;
149
0
  type = uint8_t(tape_val >> 56);
150
0
  os << tape_idx << " : " << type << "\t// pointing to " << payload
151
0
     << " (start root)\n";
152
0
  return true;
153
5.73k
}
154
155
} // namespace dom
156
} // namespace simdjson
157
158
#endif // SIMDJSON_INLINE_DOCUMENT_H