simdjson 4.0.7
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
12namespace simdjson {
13namespace internal {
14
15// The allocate_padded_buffer function is a low-level function to allocate memory
16// with padding so we can read past the "length" bytes safely. It is used by
17// the padded_string class automatically. It returns nullptr in case
18// of error: the caller should check for a null pointer.
19// The length parameter is the maximum size in bytes of the string.
20// The caller is responsible to free the memory (e.g., delete[] (...)).
21inline char *allocate_padded_buffer(size_t length) noexcept {
22 const size_t totalpaddedlength = length + SIMDJSON_PADDING;
23 if(totalpaddedlength<length) {
24 // overflow
25 return nullptr;
26 }
27#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
28 // avoid getting out of memory
29 if (totalpaddedlength>(1UL<<20)) {
30 return nullptr;
31 }
32#endif
33
34 char *padded_buffer = new (std::nothrow) char[totalpaddedlength];
35 if (padded_buffer == nullptr) {
36 return nullptr;
37 }
38 // We write nulls in the padded region to avoid having uninitialized
39 // content which may trigger warning for some sanitizers
40 std::memset(padded_buffer + length, 0, totalpaddedlength - length);
41 return padded_buffer;
42} // allocate_padded_buffer()
43
44} // namespace internal
45
46
47inline padded_string::padded_string() noexcept = default;
48inline padded_string::padded_string(size_t length) noexcept
49 : viable_size(length), data_ptr(internal::allocate_padded_buffer(length)) {
50}
51inline padded_string::padded_string(const char *data, size_t length) noexcept
52 : viable_size(length), data_ptr(internal::allocate_padded_buffer(length)) {
53 if ((data != nullptr) && (data_ptr != nullptr)) {
54 std::memcpy(data_ptr, data, length);
55 }
56 if (data_ptr == nullptr) {
57 viable_size = 0;
58 }
59}
60#ifdef __cpp_char8_t
61inline padded_string::padded_string(const char8_t *data, size_t length) noexcept
62 : viable_size(length), data_ptr(internal::allocate_padded_buffer(length)) {
63 if ((data != nullptr) && (data_ptr != nullptr)) {
64 std::memcpy(data_ptr, reinterpret_cast<const char *>(data), length);
65 }
66 if (data_ptr == nullptr) {
67 viable_size = 0;
68 }
69}
70#endif
71// note: do not pass std::string arguments by value
72inline padded_string::padded_string(const std::string & str_ ) noexcept
73 : viable_size(str_.size()), data_ptr(internal::allocate_padded_buffer(str_.size())) {
74 if (data_ptr == nullptr) {
75 viable_size = 0;
76 } else {
77 std::memcpy(data_ptr, str_.data(), str_.size());
78 }
79}
80// note: do pass std::string_view arguments by value
81inline padded_string::padded_string(std::string_view sv_) noexcept
82 : viable_size(sv_.size()), data_ptr(internal::allocate_padded_buffer(sv_.size())) {
83 if(simdjson_unlikely(!data_ptr)) {
84 //allocation failed or zero size
85 viable_size = 0;
86 return;
87 }
88 if (sv_.size()) {
89 std::memcpy(data_ptr, sv_.data(), sv_.size());
90 }
91}
93 : viable_size(o.viable_size), data_ptr(o.data_ptr) {
94 o.data_ptr = nullptr; // we take ownership
95 o.viable_size = 0;
96}
97
99 delete[] data_ptr;
100 data_ptr = o.data_ptr;
101 viable_size = o.viable_size;
102 o.data_ptr = nullptr; // we take ownership
103 o.viable_size = 0;
104 return *this;
105}
106
107inline void padded_string::swap(padded_string &o) noexcept {
108 size_t tmp_viable_size = viable_size;
109 char *tmp_data_ptr = data_ptr;
110 viable_size = o.viable_size;
111 data_ptr = o.data_ptr;
112 o.data_ptr = tmp_data_ptr;
113 o.viable_size = tmp_viable_size;
114}
115
116inline padded_string::~padded_string() noexcept {
117 delete[] data_ptr;
118}
119
120inline size_t padded_string::size() const noexcept { return viable_size; }
121
122inline size_t padded_string::length() const noexcept { return viable_size; }
123
124inline const char *padded_string::data() const noexcept { return data_ptr; }
125
126inline char *padded_string::data() noexcept { return data_ptr; }
127
128inline padded_string::operator std::string_view() const simdjson_lifetime_bound { return std::string_view(data(), length()); }
129
130inline padded_string::operator padded_string_view() const noexcept simdjson_lifetime_bound {
131 return padded_string_view(data(), length(), length() + SIMDJSON_PADDING);
132}
133
134inline simdjson_result<padded_string> padded_string::load(std::string_view filename) noexcept {
135 // Open the file
136 SIMDJSON_PUSH_DISABLE_WARNINGS
137 SIMDJSON_DISABLE_DEPRECATED_WARNING // Disable CRT_SECURE warning on MSVC: manually verified this is safe
138 std::FILE *fp = std::fopen(filename.data(), "rb");
139 SIMDJSON_POP_DISABLE_WARNINGS
140
141 if (fp == nullptr) {
142 return IO_ERROR;
143 }
144
145 // Get the file size
146 int ret;
147#if SIMDJSON_VISUAL_STUDIO && !SIMDJSON_IS_32BITS
148 ret = _fseeki64(fp, 0, SEEK_END);
149#else
150 ret = std::fseek(fp, 0, SEEK_END);
151#endif // _WIN64
152 if(ret < 0) {
153 std::fclose(fp);
154 return IO_ERROR;
155 }
156#if SIMDJSON_VISUAL_STUDIO && !SIMDJSON_IS_32BITS
157 __int64 llen = _ftelli64(fp);
158 if(llen == -1L) {
159 std::fclose(fp);
160 return IO_ERROR;
161 }
162#else
163 long llen = std::ftell(fp);
164 if((llen < 0) || (llen == LONG_MAX)) {
165 std::fclose(fp);
166 return IO_ERROR;
167 }
168#endif
169
170 // Allocate the padded_string
171 size_t len = static_cast<size_t>(llen);
172 padded_string s(len);
173 if (s.data() == nullptr) {
174 std::fclose(fp);
175 return MEMALLOC;
176 }
177
178 // Read the padded_string
179 std::rewind(fp);
180 size_t bytes_read = std::fread(s.data(), 1, len, fp);
181 if (std::fclose(fp) != 0 || bytes_read != len) {
182 return IO_ERROR;
183 }
184
185 return s;
186}
187
188} // namespace simdjson
189
190inline simdjson::padded_string operator ""_padded(const char *str, size_t len) {
191 return simdjson::padded_string(str, len);
192}
193#ifdef __cpp_char8_t
194inline simdjson::padded_string operator ""_padded(const char8_t *str, size_t len) {
195 return simdjson::padded_string(reinterpret_cast<const char8_t *>(str), len);
196}
197#endif
198#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:278