1#ifndef SIMDJSON_PADDED_STRING_INL_H
2#define SIMDJSON_PADDED_STRING_INL_H
4#include "simdjson/padded_string.h"
5#include "simdjson/padded_string_view.h"
7#include "simdjson/error-inl.h"
8#include "simdjson/padded_string_view-inl.h"
13#if SIMDJSON_HAS_UNISTD_H
35inline char *allocate_padded_buffer(
size_t length)
noexcept {
37 if(totalpaddedlength<length) {
41#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
43 if (totalpaddedlength>(1UL<<20)) {
48 char *padded_buffer =
new (std::nothrow)
char[totalpaddedlength];
49 if (padded_buffer ==
nullptr) {
54 std::memset(padded_buffer + length, 0, totalpaddedlength - length);
63 : viable_size(length), data_ptr(internal::allocate_padded_buffer(length)) {
64 if (data_ptr ==
nullptr) { viable_size = 0; }
67 : viable_size(length), data_ptr(internal::allocate_padded_buffer(length)) {
68 if ((data !=
nullptr) && (data_ptr !=
nullptr)) {
69 std::memcpy(data_ptr, data, length);
71 if (data_ptr ==
nullptr) {
77 : viable_size(length), data_ptr(internal::allocate_padded_buffer(length)) {
78 if ((data !=
nullptr) && (data_ptr !=
nullptr)) {
79 std::memcpy(data_ptr,
reinterpret_cast<const char *
>(data), length);
81 if (data_ptr ==
nullptr) {
88 : viable_size(str_.size()), data_ptr(internal::allocate_padded_buffer(str_.size())) {
89 if (data_ptr ==
nullptr) {
92 std::memcpy(data_ptr, str_.data(), str_.size());
97 : viable_size(sv_.size()), data_ptr(internal::allocate_padded_buffer(sv_.size())) {
98 if(simdjson_unlikely(!data_ptr)) {
104 std::memcpy(data_ptr, sv_.data(), sv_.size());
108 : viable_size(o.viable_size), data_ptr(o.data_ptr) {
109 o.data_ptr =
nullptr;
115 data_ptr = o.data_ptr;
116 viable_size = o.viable_size;
117 o.data_ptr =
nullptr;
123 size_t tmp_viable_size = viable_size;
124 char *tmp_data_ptr = data_ptr;
125 viable_size = o.viable_size;
126 data_ptr = o.data_ptr;
127 o.data_ptr = tmp_data_ptr;
128 o.viable_size = tmp_viable_size;
131inline padded_string::~padded_string() noexcept {
147 size_t new_size = viable_size + length;
148 if (new_size < viable_size) {
152 char *new_data_ptr = internal::allocate_padded_buffer(new_size);
153 if (new_data_ptr ==
nullptr) {
158 if (viable_size > 0) {
159 std::memcpy(new_data_ptr, data_ptr, viable_size);
162 std::memcpy(new_data_ptr + viable_size, data, length);
165 data_ptr = new_data_ptr;
166 viable_size = new_size;
170inline padded_string::operator std::string_view() const simdjson_lifetime_bound {
return std::string_view(data(), length()); }
179 const std::string null_terminated_filename(filename);
181 SIMDJSON_PUSH_DISABLE_WARNINGS
182 SIMDJSON_DISABLE_DEPRECATED_WARNING
183 std::FILE *fp = std::fopen(null_terminated_filename.c_str(),
"rb");
184 SIMDJSON_POP_DISABLE_WARNINGS
192#if SIMDJSON_VISUAL_STUDIO && !SIMDJSON_IS_32BITS
193 ret = _fseeki64(fp, 0, SEEK_END);
195 ret = std::fseek(fp, 0, SEEK_END);
201#if SIMDJSON_VISUAL_STUDIO && !SIMDJSON_IS_32BITS
202 __int64 llen = _ftelli64(fp);
208 long llen = std::ftell(fp);
209 if((llen < 0) || (llen == LONG_MAX)) {
216 size_t len =
static_cast<size_t>(llen);
218 if (s.
data() ==
nullptr) {
225 size_t bytes_read = std::fread(s.
data(), 1, len, fp);
226 if (std::fclose(fp) != 0 || bytes_read != len) {
233#if defined(_WIN32) && SIMDJSON_CPLUSPLUS17
237 const std::wstring null_terminated_filename(filename);
239 SIMDJSON_PUSH_DISABLE_WARNINGS
240 SIMDJSON_DISABLE_DEPRECATED_WARNING
241 std::FILE *fp = _wfopen(null_terminated_filename.c_str(), L
"rb");
242 SIMDJSON_POP_DISABLE_WARNINGS
250#if SIMDJSON_VISUAL_STUDIO && !SIMDJSON_IS_32BITS
251 ret = _fseeki64(fp, 0, SEEK_END);
253 ret = std::fseek(fp, 0, SEEK_END);
259#if SIMDJSON_VISUAL_STUDIO && !SIMDJSON_IS_32BITS
260 __int64 llen = _ftelli64(fp);
266 long llen = std::ftell(fp);
267 if((llen < 0) || (llen == LONG_MAX)) {
274 size_t len =
static_cast<size_t>(llen);
275 padded_string s(len);
276 if (s.data() ==
nullptr) {
283 size_t bytes_read = std::fread(s.data(), 1, len, fp);
284 if (std::fclose(fp) != 0 || bytes_read != len) {
297 if (new_capacity > 0) {
298 data = internal::allocate_padded_buffer(new_capacity);
299 if (data !=
nullptr) {
300 this->capacity = new_capacity;
306 : size(o.size), capacity(o.capacity), data(o.data) {
316 capacity = o.capacity;
333 if (!reserve(length)) {
336 std::memcpy(data + size, newdata, length);
342 return append(sv.data(), sv.size());
355 result.data_ptr = data;
356 result.viable_size = size;
363inline bool padded_string_builder::reserve(
size_t additional)
noexcept {
364 if (simdjson_unlikely(additional + size < size)) {
367 size_t needed = size + additional;
368 if (needed <= capacity) {
371 size_t new_capacity = needed;
374 if (new_capacity < 4096) {
377 }
else if (new_capacity + new_capacity / 2 > new_capacity) {
378 new_capacity += new_capacity / 2;
380 char *new_data = internal::allocate_padded_buffer(new_capacity);
381 if (new_data ==
nullptr) {
385 std::memcpy(new_data, data, size);
389 capacity = new_capacity;
394#if SIMDJSON_HAS_PADDED_MEMORY_MAP
396#if SIMDJSON_HAS_UNISTD_H
397simdjson_inline padded_memory_map::padded_memory_map(
const char *filename)
noexcept {
399 int fd = open(filename, O_RDONLY);
404 if (fstat(fd, &st) == -1) {
408 size =
static_cast<size_t>(st.st_size);
411 mmap(NULL, total_size, PROT_READ, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
412 if (anon_map == MAP_FAILED) {
417 mmap(anon_map, size, PROT_READ, MAP_SHARED | MAP_FIXED, fd, 0);
418 if (file_map == MAP_FAILED) {
419 munmap(anon_map, total_size);
423 data =
static_cast<const char *
>(file_map);
427simdjson_inline padded_memory_map::~padded_memory_map() noexcept {
428 if (data !=
nullptr) {
447simdjson_inline padded_memory_map::padded_memory_map(
const char *filename)
noexcept {
448 HANDLE file_handle = ::CreateFileA(
449 filename, GENERIC_READ,
450 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
451 NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
452 if (file_handle == INVALID_HANDLE_VALUE) {
455 LARGE_INTEGER file_size_li;
456 if (!::GetFileSizeEx(file_handle, &file_size_li) || file_size_li.QuadPart < 0) {
457 ::CloseHandle(file_handle);
460#if SIMDJSON_IS_32BITS
461 if (
static_cast<unsigned long long>(file_size_li.QuadPart) >
463 ::CloseHandle(file_handle);
467 size =
static_cast<size_t>(file_size_li.QuadPart);
469 ::CloseHandle(file_handle);
473 HANDLE section = ::CreateFileMapping2(
474 file_handle, NULL, FILE_MAP_READ, PAGE_READONLY,
475 0, 0, NULL, NULL, 0);
476 ::CloseHandle(file_handle);
477 if (section == NULL) {
482 ::GetSystemInfo(&si);
483 const size_t granularity =
static_cast<size_t>(si.dwAllocationGranularity);
484 const size_t file_region = (size + granularity - 1) & ~(granularity - 1);
487 if (file_region >= total_needed) {
489 PVOID view = ::MapViewOfFile3(
490 section, ::GetCurrentProcess(), NULL, 0, 0,
491 0, PAGE_READONLY, NULL, 0);
492 ::CloseHandle(section);
494 data =
static_cast<const char *
>(view);
502 const size_t padding_region =
503 ((total_needed - file_region) + granularity - 1) & ~(granularity - 1);
504 const size_t reserve_size = file_region + padding_region;
507 PVOID placeholder = ::VirtualAlloc2(
508 ::GetCurrentProcess(), NULL, reserve_size,
509 MEM_RESERVE | MEM_RESERVE_PLACEHOLDER, PAGE_NOACCESS, NULL, 0);
510 if (placeholder == NULL) {
511 ::CloseHandle(section);
516 if (!::VirtualFree(placeholder, file_region,
517 MEM_RELEASE | MEM_PRESERVE_PLACEHOLDER)) {
518 ::VirtualFree(placeholder, 0, MEM_RELEASE);
519 ::CloseHandle(section);
524 PVOID file_view = ::MapViewOfFile3(
525 section, ::GetCurrentProcess(), placeholder, 0, file_region,
526 MEM_REPLACE_PLACEHOLDER, PAGE_READONLY, NULL, 0);
527 ::CloseHandle(section);
528 if (file_view == NULL) {
529 ::VirtualFree(placeholder, 0, MEM_RELEASE);
530 ::VirtualFree(
static_cast<char *
>(placeholder) + file_region,
536 void *
pad =
static_cast<char *
>(placeholder) + file_region;
537 PVOID padding_ptr = ::VirtualAlloc2(
538 ::GetCurrentProcess(),
pad, padding_region,
539 MEM_REPLACE_PLACEHOLDER | MEM_COMMIT, PAGE_READONLY, NULL, 0);
540 if (padding_ptr == NULL) {
541 ::UnmapViewOfFile(file_view);
542 ::VirtualFree(
pad, 0, MEM_RELEASE);
546 data =
static_cast<const char *
>(file_view);
547 padding_view_ = padding_ptr;
550simdjson_inline padded_memory_map::~padded_memory_map() noexcept {
551 if (data ==
nullptr) {
return; }
552 ::UnmapViewOfFile(data);
553 if (padding_view_ !=
nullptr) {
554 ::VirtualFree(padding_view_, 0, MEM_RELEASE);
566simdjson_inline
bool padded_memory_map::is_valid() const noexcept {
567 return data !=
nullptr;
Builder for constructing padded_string incrementally.
padded_string convert() noexcept
Convert the current content into a padded_string.
padded_string_builder & operator=(padded_string_builder &&o) noexcept
Move assignment.
~padded_string_builder() noexcept
Destructor.
size_t length() const noexcept
Get the current length of the built string.
padded_string build() const noexcept
Build a padded_string from the current content.
bool append(const char *newdata, size_t length) noexcept
Append data to the builder.
padded_string_builder() noexcept
Create a new, empty padded string builder.
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.
@ MEMALLOC
Error allocating memory, most likely out of memory.
@ IO_ERROR
Error reading a file.
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.
String with extra allocation for ease of use with parser::parse()
size_t size() const noexcept
The length of the string.
bool append(const char *data, size_t length) noexcept
Append data to the padded 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.