simdjson 4.2.2
Ridiculously Fast JSON
Loading...
Searching...
No Matches
padded_string-inl.h
1#ifndef SIMDJSON_PADDED_STRING_INL_H
2#define SIMDJSON_PADDED_STRING_INL_H
3
4#include "simdjson/padded_string.h"
5#include "simdjson/padded_string_view.h"
6
7#include "simdjson/error-inl.h"
8#include "simdjson/padded_string_view-inl.h"
9
10#include <climits>
11#include <cwchar>
12
13namespace simdjson {
14namespace internal {
15
16// The allocate_padded_buffer function is a low-level function to allocate memory
17// with padding so we can read past the "length" bytes safely. It is used by
18// the padded_string class automatically. It returns nullptr in case
19// of error: the caller should check for a null pointer.
20// The length parameter is the maximum size in bytes of the string.
21// The caller is responsible to free the memory (e.g., delete[] (...)).
22inline char *allocate_padded_buffer(size_t length) noexcept {
23 const size_t totalpaddedlength = length + SIMDJSON_PADDING;
24 if(totalpaddedlength<length) {
25 // overflow
26 return nullptr;
27 }
28#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
29 // avoid getting out of memory
30 if (totalpaddedlength>(1UL<<20)) {
31 return nullptr;
32 }
33#endif
34
35 char *padded_buffer = new (std::nothrow) char[totalpaddedlength];
36 if (padded_buffer == nullptr) {
37 return nullptr;
38 }
39 // We write nulls in the padded region to avoid having uninitialized
40 // content which may trigger warning for some sanitizers
41 std::memset(padded_buffer + length, 0, totalpaddedlength - length);
42 return padded_buffer;
43} // allocate_padded_buffer()
44
45} // namespace internal
46
47
48inline padded_string::padded_string() noexcept = default;
49inline padded_string::padded_string(size_t length) noexcept
50 : viable_size(length), data_ptr(internal::allocate_padded_buffer(length)) {
51}
52inline padded_string::padded_string(const char *data, size_t length) noexcept
53 : viable_size(length), data_ptr(internal::allocate_padded_buffer(length)) {
54 if ((data != nullptr) && (data_ptr != nullptr)) {
55 std::memcpy(data_ptr, data, length);
56 }
57 if (data_ptr == nullptr) {
58 viable_size = 0;
59 }
60}
61#ifdef __cpp_char8_t
62inline padded_string::padded_string(const char8_t *data, size_t length) noexcept
63 : viable_size(length), data_ptr(internal::allocate_padded_buffer(length)) {
64 if ((data != nullptr) && (data_ptr != nullptr)) {
65 std::memcpy(data_ptr, reinterpret_cast<const char *>(data), length);
66 }
67 if (data_ptr == nullptr) {
68 viable_size = 0;
69 }
70}
71#endif
72// note: do not pass std::string arguments by value
73inline padded_string::padded_string(const std::string & str_ ) noexcept
74 : viable_size(str_.size()), data_ptr(internal::allocate_padded_buffer(str_.size())) {
75 if (data_ptr == nullptr) {
76 viable_size = 0;
77 } else {
78 std::memcpy(data_ptr, str_.data(), str_.size());
79 }
80}
81// note: do pass std::string_view arguments by value
82inline padded_string::padded_string(std::string_view sv_) noexcept
83 : viable_size(sv_.size()), data_ptr(internal::allocate_padded_buffer(sv_.size())) {
84 if(simdjson_unlikely(!data_ptr)) {
85 //allocation failed or zero size
86 viable_size = 0;
87 return;
88 }
89 if (sv_.size()) {
90 std::memcpy(data_ptr, sv_.data(), sv_.size());
91 }
92}
94 : viable_size(o.viable_size), data_ptr(o.data_ptr) {
95 o.data_ptr = nullptr; // we take ownership
96 o.viable_size = 0;
97}
98
100 delete[] data_ptr;
101 data_ptr = o.data_ptr;
102 viable_size = o.viable_size;
103 o.data_ptr = nullptr; // we take ownership
104 o.viable_size = 0;
105 return *this;
106}
107
108inline void padded_string::swap(padded_string &o) noexcept {
109 size_t tmp_viable_size = viable_size;
110 char *tmp_data_ptr = data_ptr;
111 viable_size = o.viable_size;
112 data_ptr = o.data_ptr;
113 o.data_ptr = tmp_data_ptr;
114 o.viable_size = tmp_viable_size;
115}
116
117inline padded_string::~padded_string() noexcept {
118 delete[] data_ptr;
119}
120
121inline size_t padded_string::size() const noexcept { return viable_size; }
122
123inline size_t padded_string::length() const noexcept { return viable_size; }
124
125inline const char *padded_string::data() const noexcept { return data_ptr; }
126
127inline char *padded_string::data() noexcept { return data_ptr; }
128
129inline padded_string::operator std::string_view() const simdjson_lifetime_bound { return std::string_view(data(), length()); }
130
131inline padded_string::operator padded_string_view() const noexcept simdjson_lifetime_bound {
132 return padded_string_view(data(), length(), length() + SIMDJSON_PADDING);
133}
134
135inline simdjson_result<padded_string> padded_string::load(std::string_view filename) noexcept {
136 // Open the file
137 SIMDJSON_PUSH_DISABLE_WARNINGS
138 SIMDJSON_DISABLE_DEPRECATED_WARNING // Disable CRT_SECURE warning on MSVC: manually verified this is safe
139 std::FILE *fp = std::fopen(filename.data(), "rb");
140 SIMDJSON_POP_DISABLE_WARNINGS
141
142 if (fp == nullptr) {
143 return IO_ERROR;
144 }
145
146 // Get the file size
147 int ret;
148#if SIMDJSON_VISUAL_STUDIO && !SIMDJSON_IS_32BITS
149 ret = _fseeki64(fp, 0, SEEK_END);
150#else
151 ret = std::fseek(fp, 0, SEEK_END);
152#endif // _WIN64
153 if(ret < 0) {
154 std::fclose(fp);
155 return IO_ERROR;
156 }
157#if SIMDJSON_VISUAL_STUDIO && !SIMDJSON_IS_32BITS
158 __int64 llen = _ftelli64(fp);
159 if(llen == -1L) {
160 std::fclose(fp);
161 return IO_ERROR;
162 }
163#else
164 long llen = std::ftell(fp);
165 if((llen < 0) || (llen == LONG_MAX)) {
166 std::fclose(fp);
167 return IO_ERROR;
168 }
169#endif
170
171 // Allocate the padded_string
172 size_t len = static_cast<size_t>(llen);
173 padded_string s(len);
174 if (s.data() == nullptr) {
175 std::fclose(fp);
176 return MEMALLOC;
177 }
178
179 // Read the padded_string
180 std::rewind(fp);
181 size_t bytes_read = std::fread(s.data(), 1, len, fp);
182 if (std::fclose(fp) != 0 || bytes_read != len) {
183 return IO_ERROR;
184 }
185
186 return s;
187}
188
189#if defined(_WIN32) && SIMDJSON_CPLUSPLUS17
190inline simdjson_result<padded_string> padded_string::load(std::wstring_view filename) noexcept {
191 // Open the file using the wide characters
192 SIMDJSON_PUSH_DISABLE_WARNINGS
193 SIMDJSON_DISABLE_DEPRECATED_WARNING // Disable CRT_SECURE warning on MSVC: manually verified this is safe
194 std::FILE *fp = _wfopen(filename.data(), L"rb");
195 SIMDJSON_POP_DISABLE_WARNINGS
196
197 if (fp == nullptr) {
198 return IO_ERROR;
199 }
200
201 // Get the file size
202 int ret;
203#if SIMDJSON_VISUAL_STUDIO && !SIMDJSON_IS_32BITS
204 ret = _fseeki64(fp, 0, SEEK_END);
205#else
206 ret = std::fseek(fp, 0, SEEK_END);
207#endif // _WIN64
208 if(ret < 0) {
209 std::fclose(fp);
210 return IO_ERROR;
211 }
212#if SIMDJSON_VISUAL_STUDIO && !SIMDJSON_IS_32BITS
213 __int64 llen = _ftelli64(fp);
214 if(llen == -1L) {
215 std::fclose(fp);
216 return IO_ERROR;
217 }
218#else
219 long llen = std::ftell(fp);
220 if((llen < 0) || (llen == LONG_MAX)) {
221 std::fclose(fp);
222 return IO_ERROR;
223 }
224#endif
225
226 // Allocate the padded_string
227 size_t len = static_cast<size_t>(llen);
228 padded_string s(len);
229 if (s.data() == nullptr) {
230 std::fclose(fp);
231 return MEMALLOC;
232 }
233
234 // Read the padded_string
235 std::rewind(fp);
236 size_t bytes_read = std::fread(s.data(), 1, len, fp);
237 if (std::fclose(fp) != 0 || bytes_read != len) {
238 return IO_ERROR;
239 }
240
241 return s;
242}
243#endif
244
245} // namespace simdjson
246
247inline simdjson::padded_string operator ""_padded(const char *str, size_t len) {
248 return simdjson::padded_string(str, len);
249}
250#ifdef __cpp_char8_t
251inline simdjson::padded_string operator ""_padded(const char8_t *str, size_t len) {
252 return simdjson::padded_string(reinterpret_cast<const char *>(str), len);
253}
254#endif
255#endif // SIMDJSON_PADDED_STRING_INL_H
User-provided string that promises it has extra padded bytes at the end for use with parser::parse().
The top level simdjson namespace, containing everything the library provides.
Definition base.h:8
@ MEMALLOC
Error allocating memory, most likely out of memory.
Definition error.h:22
@ IO_ERROR
Error reading a file.
Definition error.h:41
constexpr size_t SIMDJSON_PADDING
The amount of padding needed in a buffer to parse JSON.
Definition base.h:33
String with extra allocation for ease of use with parser::parse()
size_t size() const noexcept
The length of the string.
size_t length() const noexcept
The length of the string.
padded_string() noexcept
Create a new, empty padded string.
padded_string & operator=(padded_string &&o) noexcept
Move one padded string into another.
const char * data() const noexcept
The string data.
static simdjson_result< padded_string > load(std::string_view path) noexcept
Load this padded string from a file.
The result of a simdjson operation that could fail.
Definition error.h:280