simdjson 5.0.2
Ridiculously Fast JSON
Loading...
Searching...
No Matches
padded_string_view-inl.h
1#ifndef SIMDJSON_PADDED_STRING_VIEW_INL_H
2#define SIMDJSON_PADDED_STRING_VIEW_INL_H
3
4#include "simdjson/padded_string_view.h"
5#include "simdjson/error-inl.h"
6
7#include <cstring> /* memcmp */
8
9// for page size computation.
10#if SIMDJSON_HAS_UNISTD_H
11 #include <unistd.h>
12 #if defined(__APPLE__)
13 #include <sys/sysctl.h>
14 #endif
15#endif
16
17
18namespace simdjson {
19
20inline padded_string_view::padded_string_view(const char* s, size_t len, size_t capacity) noexcept
21 : std::string_view(s, len), _capacity(capacity)
22{
23 if(_capacity < len) { _capacity = len; }
24}
25
26inline padded_string_view::padded_string_view(const uint8_t* s, size_t len, size_t capacity) noexcept
27 : padded_string_view(reinterpret_cast<const char*>(s), len, capacity)
28{
29}
30#ifdef __cpp_char8_t
31inline padded_string_view::padded_string_view(const char8_t* s, size_t len, size_t capacity) noexcept
32 : padded_string_view(reinterpret_cast<const char*>(s), len, capacity)
33{
34}
35#endif
36inline padded_string_view::padded_string_view(const std::string &s) noexcept
37 : std::string_view(s), _capacity(s.capacity())
38{
39}
40
41inline padded_string_view::padded_string_view(std::string_view s, size_t capacity) noexcept
42 : std::string_view(s), _capacity(capacity)
43{
44 if(_capacity < s.length()) { _capacity = s.length(); }
45}
46
47inline bool padded_string_view::has_sufficient_padding() const noexcept {
48 if (padding() >= SIMDJSON_PADDING) {
49 return true;
50 }
51 size_t missing_padding = SIMDJSON_PADDING - padding();
52 if(length() < missing_padding) { return false; }
53
54 for (size_t i = length() - missing_padding; i < length(); i++) {
55 char c = data()[i];
56 if (c != ' ' && c != '\t' && c != '\n' && c != '\r') {
57 return false;
58 }
59 }
60 return true;
61}
62
63inline size_t padded_string_view::capacity() const noexcept { return _capacity; }
64
65inline size_t padded_string_view::padding() const noexcept { return capacity() - length(); }
66
68 if(length() < 3) { return false; }
69 if (std::memcmp(data(), "\xEF\xBB\xBF", 3) == 0) {
70 remove_prefix(3);
71 _capacity -= 3;
72 return true;
73 }
74 return false;
75}
76
77#if SIMDJSON_EXCEPTIONS
78inline std::ostream& operator<<(std::ostream& out, simdjson_result<padded_string_view> &s) noexcept(false) { return out << s.value(); }
79#endif
80
81inline padded_string_view pad(std::string& s) noexcept {
82 size_t existing_padding = 0;
83 for (size_t i = s.size(); i > 0; i--) {
84 char c = s[i - 1];
85 if (c == ' ' || c == '\t' || c == '\n' || c == '\r') {
86 existing_padding++;
87 } else {
88 break;
89 }
90 }
91 size_t needed_padding = 0;
92 if (existing_padding < SIMDJSON_PADDING) {
93 needed_padding = SIMDJSON_PADDING - existing_padding;
94 s.append(needed_padding, ' ');
95 }
96
97 return padded_string_view(s.data(), s.size() - needed_padding, s.size());
98}
99
100inline padded_string_view pad_with_reserve(std::string& s) noexcept {
101 if (s.capacity() - s.size() < SIMDJSON_PADDING) {
102 s.reserve(s.size() + SIMDJSON_PADDING );
103 }
104 return padded_string_view(s.data(), s.size(), s.capacity());
105}
106
107inline uint32_t get_page_size() noexcept {
108#if defined(_WINDOWS_) // if and only if someone loaded Windows.h, we can get the page size from there.
109// Otherwise, we assume 4096.
110 static const uint32_t cached = []() -> uint32_t {
111 SYSTEM_INFO si;
112 GetSystemInfo(&si);
113 return static_cast<std::uint32_t>(si.dwPageSize);
114 }();
115 return cached;
116#elif SIMDJSON_HAS_UNISTD_H
117 static const uint32_t cached = []() -> uint32_t {
118 long page_size = sysconf(_SC_PAGESIZE);
119 if (page_size > 0) {
120 return static_cast<uint32_t>(page_size);
121 }
122 return 4096; // fallback
123 }();
124 return cached;
125#else
126 return 4096; // fallback
127#endif
128}
129#if SIMDJSON_CPLUSPLUS17
130
131inline padded_input::padded_input(std::string_view sv)
132 : storage(simdjson::padded_string_view{}) {
133 if (needs_allocation(sv.data(), sv.size())) {
134 storage = simdjson::padded_string(sv);
135 } else {
137 sv.data(), sv.size(), sv.size() + simdjson::SIMDJSON_PADDING);
138 }
139}
140
141inline padded_input::padded_input(const char *data, size_t length)
142 : storage(simdjson::padded_string_view{}) {
143 if (needs_allocation(data, length)) {
144 storage = simdjson::padded_string(data, length);
145 } else {
147 data, length, length + simdjson::SIMDJSON_PADDING);
148 }
149}
150
151inline padded_input::padded_input(const std::string &s)
152 : storage(simdjson::padded_string_view{}) {
153 const size_t len = s.size();
154 const size_t cap = s.capacity();
155 // Here we have the string content from data() to data() + size(),
156 // but the memory is accessible from data() to data() + capacity().
157 const size_t needed_padding = (cap - len) < simdjson::SIMDJSON_PADDING
158 ? simdjson::SIMDJSON_PADDING - (cap - len) : 0;
159 if (needed_padding > 0 && needs_allocation(s.data(), cap, needed_padding)) {
160 storage = simdjson::padded_string(s);
161 } else {
163 s.data(), len, len + simdjson::SIMDJSON_PADDING);
164 }
165}
166
167inline bool padded_input::is_view() const noexcept {
168 return std::holds_alternative<simdjson::padded_string_view>(storage);
169}
170
171inline padded_input::operator simdjson::padded_string_view() const noexcept {
172 return std::visit([](const auto& p) -> simdjson::padded_string_view {
173 return p;
174 }, storage);
175}
176
177inline bool padded_input::needs_allocation(const char* buf, size_t len, size_t padding) noexcept {
178 if(len == 0) { return false; }
179 const auto page_size = get_page_size();
180 return ((reinterpret_cast<uintptr_t>(buf + len - 1) % page_size)
181 + padding >= static_cast<uintptr_t>(page_size));
182}
183#endif // SIMDJSON_CPLUSPLUS17
184
186 size_t block_size, size_t index) noexcept {
187 if (block_size == 0 || index > data.size() / block_size) { return {}; }
188 const size_t raw_begin = index * block_size;
189 if (raw_begin >= data.size()) { return {}; }
190
191 auto snap = [&](size_t want) -> size_t {
192 if (want >= data.size()) { return data.size(); }
193 const void *p = std::memchr(data.data() + want, delimiter, data.size() - want);
194 return p ? size_t(static_cast<const char *>(p) - data.data()) + 1 : data.size();
195 };
196
197 const size_t begin = (raw_begin == 0) ? 0 : snap(raw_begin);
198 const size_t end = snap(raw_begin + block_size);
199 if (begin >= end) { return {}; }
200 return padded_string_view(data.data() + begin, end - begin,
201 data.capacity() - begin);
202}
203
204} // namespace simdjson
205
206
207#endif // SIMDJSON_PADDED_STRING_VIEW_INL_H
User-provided string that promises it has extra padded bytes at the end for use with parser::parse().
bool remove_utf8_bom() noexcept
Remove the UTF-8 Byte Order Mark (BOM) if it exists.
size_t padding() const noexcept
The amount of padding on the string (capacity() - length())
size_t capacity() const noexcept
The number of allocated bytes.
padded_string_view() noexcept=default
Create an empty padded_string_view.
bool has_sufficient_padding() const noexcept
check that the view has sufficient padding
The top level simdjson namespace, containing everything the library provides.
Definition base.h:8
padded_string_view slice_at(padded_string_view data, char delimiter, size_t block_size, size_t index) noexcept
Return the index-th document-aligned slice of a delimited stream.
padded_string_view pad_with_reserve(std::string &s) noexcept
Create a padded_string_view from a string.
uint32_t get_page_size() noexcept
Get the system's memory page size.
padded_string_view pad(std::string &s) noexcept
Create a padded_string_view from a string.
constexpr size_t SIMDJSON_PADDING
The amount of padding needed in a buffer to parse JSON.
Definition base.h:42
String with extra allocation for ease of use with parser::parse()
The result of a simdjson operation that could fail.
Definition error.h:281