#ifndef SIMDJSON_PADDED_STRING_INL_H #define SIMDJSON_PADDED_STRING_INL_H #include "simdjson/padded_string.h" #include "simdjson/padded_string_view.h" #include "simdjson/error-inl.h" #include "simdjson/padded_string_view-inl.h" #include namespace simdjson { namespace internal { // The allocate_padded_buffer function is a low-level function to allocate memory // with padding so we can read past the "length" bytes safely. It is used by // the padded_string class automatically. It returns nullptr in case // of error: the caller should check for a null pointer. // The length parameter is the maximum size in bytes of the string. // The caller is responsible to free the memory (e.g., delete[] (...)). inline char *allocate_padded_buffer(size_t length) noexcept { const size_t totalpaddedlength = length + SIMDJSON_PADDING; if(totalpaddedlength(1UL<<20)) { return nullptr; } #endif char *padded_buffer = new (std::nothrow) char[totalpaddedlength]; if (padded_buffer == nullptr) { return nullptr; } // We write nulls in the padded region to avoid having uninitialized // content which may trigger warning for some sanitizers std::memset(padded_buffer + length, 0, totalpaddedlength - length); return padded_buffer; } // allocate_padded_buffer() } // namespace internal inline padded_string::padded_string() noexcept = default; inline padded_string::padded_string(size_t length) noexcept : viable_size(length), data_ptr(internal::allocate_padded_buffer(length)) { } inline padded_string::padded_string(const char *data, size_t length) noexcept : viable_size(length), data_ptr(internal::allocate_padded_buffer(length)) { if ((data != nullptr) && (data_ptr != nullptr)) { std::memcpy(data_ptr, data, length); } if (data_ptr == nullptr) { viable_size = 0; } } #ifdef __cpp_char8_t inline padded_string::padded_string(const char8_t *data, size_t length) noexcept : viable_size(length), data_ptr(internal::allocate_padded_buffer(length)) { if ((data != nullptr) && (data_ptr != nullptr)) { std::memcpy(data_ptr, reinterpret_cast(data), length); } if (data_ptr == nullptr) { viable_size = 0; } } #endif // note: do not pass std::string arguments by value inline padded_string::padded_string(const std::string & str_ ) noexcept : viable_size(str_.size()), data_ptr(internal::allocate_padded_buffer(str_.size())) { if (data_ptr == nullptr) { viable_size = 0; } else { std::memcpy(data_ptr, str_.data(), str_.size()); } } // note: do pass std::string_view arguments by value inline padded_string::padded_string(std::string_view sv_) noexcept : viable_size(sv_.size()), data_ptr(internal::allocate_padded_buffer(sv_.size())) { if(simdjson_unlikely(!data_ptr)) { //allocation failed or zero size viable_size = 0; return; } if (sv_.size()) { std::memcpy(data_ptr, sv_.data(), sv_.size()); } } inline padded_string::padded_string(padded_string &&o) noexcept : viable_size(o.viable_size), data_ptr(o.data_ptr) { o.data_ptr = nullptr; // we take ownership o.viable_size = 0; } inline padded_string &padded_string::operator=(padded_string &&o) noexcept { delete[] data_ptr; data_ptr = o.data_ptr; viable_size = o.viable_size; o.data_ptr = nullptr; // we take ownership o.viable_size = 0; return *this; } inline void padded_string::swap(padded_string &o) noexcept { size_t tmp_viable_size = viable_size; char *tmp_data_ptr = data_ptr; viable_size = o.viable_size; data_ptr = o.data_ptr; o.data_ptr = tmp_data_ptr; o.viable_size = tmp_viable_size; } inline padded_string::~padded_string() noexcept { delete[] data_ptr; } inline size_t padded_string::size() const noexcept { return viable_size; } inline size_t padded_string::length() const noexcept { return viable_size; } inline const char *padded_string::data() const noexcept { return data_ptr; } inline char *padded_string::data() noexcept { return data_ptr; } inline padded_string::operator std::string_view() const simdjson_lifetime_bound { return std::string_view(data(), length()); } inline padded_string::operator padded_string_view() const noexcept simdjson_lifetime_bound { return padded_string_view(data(), length(), length() + SIMDJSON_PADDING); } inline simdjson_result padded_string::load(std::string_view filename) noexcept { // Open the file SIMDJSON_PUSH_DISABLE_WARNINGS SIMDJSON_DISABLE_DEPRECATED_WARNING // Disable CRT_SECURE warning on MSVC: manually verified this is safe std::FILE *fp = std::fopen(filename.data(), "rb"); SIMDJSON_POP_DISABLE_WARNINGS if (fp == nullptr) { return IO_ERROR; } // Get the file size int ret; #if SIMDJSON_VISUAL_STUDIO && !SIMDJSON_IS_32BITS ret = _fseeki64(fp, 0, SEEK_END); #else ret = std::fseek(fp, 0, SEEK_END); #endif // _WIN64 if(ret < 0) { std::fclose(fp); return IO_ERROR; } #if SIMDJSON_VISUAL_STUDIO && !SIMDJSON_IS_32BITS __int64 llen = _ftelli64(fp); if(llen == -1L) { std::fclose(fp); return IO_ERROR; } #else long llen = std::ftell(fp); if((llen < 0) || (llen == LONG_MAX)) { std::fclose(fp); return IO_ERROR; } #endif // Allocate the padded_string size_t len = static_cast(llen); padded_string s(len); if (s.data() == nullptr) { std::fclose(fp); return MEMALLOC; } // Read the padded_string std::rewind(fp); size_t bytes_read = std::fread(s.data(), 1, len, fp); if (std::fclose(fp) != 0 || bytes_read != len) { return IO_ERROR; } return s; } } // namespace simdjson inline simdjson::padded_string operator ""_padded(const char *str, size_t len) { return simdjson::padded_string(str, len); } #ifdef __cpp_char8_t inline simdjson::padded_string operator ""_padded(const char8_t *str, size_t len) { return simdjson::padded_string(reinterpret_cast(str), len); } #endif #endif // SIMDJSON_PADDED_STRING_INL_H