simdjson  3.11.0
Ridiculously Fast JSON
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 
12 namespace simdjson {
13 namespace 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[] (...)).
21 inline 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 
47 inline padded_string::padded_string() noexcept = default;
48 inline padded_string::padded_string(size_t length) noexcept
49  : viable_size(length), data_ptr(internal::allocate_padded_buffer(length)) {
50 }
51 inline 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
61 inline 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
72 inline 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
81 inline 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 
107 inline 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 
116 inline padded_string::~padded_string() noexcept {
117  delete[] data_ptr;
118 }
119 
120 inline size_t padded_string::size() const noexcept { return viable_size; }
121 
122 inline size_t padded_string::length() const noexcept { return viable_size; }
123 
124 inline const char *padded_string::data() const noexcept { return data_ptr; }
125 
126 inline char *padded_string::data() noexcept { return data_ptr; }
127 
128 inline padded_string::operator std::string_view() const { return std::string_view(data(), length()); }
129 
130 inline padded_string::operator padded_string_view() const noexcept {
131  return padded_string_view(data(), length(), length() + SIMDJSON_PADDING);
132 }
133 
134 inline 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 
190 inline simdjson::padded_string operator ""_padded(const char *str, size_t len) {
191  return simdjson::padded_string(str, len);
192 }
193 #ifdef __cpp_char8_t
194 inline 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:32
String with extra allocation for ease of use with parser::parse()
Definition: padded_string.h:23
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:215