1#ifndef SIMDJSON_PARSER_INL_H
2#define SIMDJSON_PARSER_INL_H
4#include "simdjson/dom/base.h"
5#include "simdjson/dom/document_stream.h"
6#include "simdjson/implementation.h"
7#include "simdjson/internal/dom_parser_implementation.h"
9#include "simdjson/error-inl.h"
10#include "simdjson/padded_string-inl.h"
11#include "simdjson/dom/document_stream-inl.h"
12#include "simdjson/dom/element-inl.h"
24 : _max_capacity{max_capacity},
25 loaded_bytes(
nullptr) {
30inline bool parser::is_valid() const noexcept {
return valid; }
31inline int parser::get_error_code() const noexcept {
return error; }
32inline std::string parser::get_error_message() const noexcept {
return error_message(error); }
34inline bool parser::dump_raw_tape(std::ostream &os)
const noexcept {
35 return valid ? doc.dump_raw_tape(os) :
false;
38inline simdjson_result<size_t> parser::read_file(std::string_view path)
noexcept {
39 const std::string path_copy(path);
41 SIMDJSON_PUSH_DISABLE_WARNINGS
42 SIMDJSON_DISABLE_DEPRECATED_WARNING
43 std::FILE *fp = std::fopen(path_copy.c_str(),
"rb");
44 SIMDJSON_POP_DISABLE_WARNINGS
52#if SIMDJSON_VISUAL_STUDIO && !SIMDJSON_IS_32BITS
53 ret = _fseeki64(fp, 0, SEEK_END);
55 ret = std::fseek(fp, 0, SEEK_END);
61#if SIMDJSON_VISUAL_STUDIO && !SIMDJSON_IS_32BITS
62 __int64 len = _ftelli64(fp);
68 long len = std::ftell(fp);
69 if((len < 0) || (len == LONG_MAX)) {
76 if (_loaded_bytes_capacity <
size_t(len)) {
77 loaded_bytes.reset( internal::allocate_padded_buffer(len) );
82 _loaded_bytes_capacity = len;
87 size_t bytes_read = std::fread(loaded_bytes.get(), 1, len, fp);
88 if (std::fclose(fp) != 0 || bytes_read !=
size_t(len)) {
96 return load_into_document(doc, path);
101 auto _error = read_file(path).
get(len);
102 if (_error) {
return _error; }
103 return parse_into_document(provided_doc, loaded_bytes.get(), len,
false);
108 auto _error = read_file(path).
get(len);
109 if (_error) {
return _error; }
110 if(batch_size < MINIMAL_BATCH_SIZE) { batch_size = MINIMAL_BATCH_SIZE; }
111 return document_stream(*
this,
reinterpret_cast<const uint8_t*
>(loaded_bytes.get()), len, batch_size);
117 error_code _error = ensure_capacity(provided_doc, len);
118 if (_error) {
return _error; }
119 if (realloc_if_needed) {
121 if (!loaded_bytes || _loaded_bytes_capacity < len) {
122 loaded_bytes.reset( internal::allocate_padded_buffer(len) );
126 _loaded_bytes_capacity = len;
128 std::memcpy(
static_cast<void *
>(loaded_bytes.get()), buf, len);
129 buf =
reinterpret_cast<const uint8_t*
>(loaded_bytes.get());
132 if((len >= 3) && (std::memcmp(buf,
"\xEF\xBB\xBF", 3) == 0)) {
139 if (_error) {
return _error; }
141 return provided_doc.root();
150 error_code _error = ensure_capacity(provided_doc, len);
151 if (_error) {
return _error; }
153 if((len >= 3) && (std::memcmp(buf,
"\xEF\xBB\xBF", 3) == 0)) {
162 if (_error) {
return _error; }
164 return provided_doc.root();
168 return parse_into_document(provided_doc,
reinterpret_cast<const uint8_t *
>(buf), len, realloc_if_needed);
171 return parse_into_document(provided_doc, s.data(), s.length(), s.capacity() - s.length() <
SIMDJSON_PADDING);
174 return parse_into_document(provided_doc, s.data(), s.length(),
false);
179 return parse_into_document(doc, buf, len, realloc_if_needed);
183 return parse(
reinterpret_cast<const uint8_t *
>(buf), len, realloc_if_needed);
186 return parse(s.data(), s.length(), s.capacity() - s.length() <
SIMDJSON_PADDING);
188simdjson_inline simdjson_result<element>
parser::parse(
const padded_string &s) &
noexcept {
189 return parse(s.data(), s.length(),
false);
191simdjson_inline simdjson_result<element>
parser::parse(
const padded_string_view &v) &
noexcept {
192 return parse(v.data(), v.length(),
false);
196 return parse_into_document_unpadded(doc, buf, len);
199 return parse_unpadded(
reinterpret_cast<const uint8_t *
>(buf), len);
202 return parse_unpadded(
reinterpret_cast<const uint8_t *
>(s.data()), s.size());
209 return parse_many(
reinterpret_cast<const uint8_t *
>(buf), len, batch_size);
212 return parse_many(s.data(), s.length(), batch_size);
214inline simdjson_result<document_stream>
parser::parse_many(
const padded_string &s,
size_t batch_size)
noexcept {
215 return parse_many(s.data(), s.length(), batch_size);
217inline simdjson_result<document_stream>
parser::parse_many(
const padded_string_view &v,
size_t batch_size)
noexcept {
218 return parse_many(v.data(), v.length(), batch_size);
222 if(batch_size < MINIMAL_BATCH_SIZE) { batch_size = MINIMAL_BATCH_SIZE; }
223 if((len >= 3) && (std::memcmp(buf,
"\xEF\xBB\xBF", 3) == 0)) {
229 while (len > 0 && (buf[0] ==
' ' || buf[0] ==
'\t' || buf[0] ==
'\n' || buf[0] ==
'\r')) {
233 if (len == 0 || buf[0] !=
'[') {
return TAPE_ERROR; }
236 while (len > 0 && (buf[len-1] ==
' ' || buf[len-1] ==
'\t' || buf[len-1] ==
'\n' || buf[len-1] ==
'\r')) {
240 if (len == 0 || buf[len-1] !=
']') {
return TAPE_ERROR; }
248 return parse_many(
reinterpret_cast<const uint8_t *
>(buf), len, batch_size, format);
251 return parse_many(s.data(), s.length(), batch_size, format);
254 return parse_many(s.data(), s.length(), batch_size, format);
257 return parse_many(v.data(), v.length(), batch_size, format);
264 return _max_capacity;
281 if (err) {
return err; }
285#ifndef SIMDJSON_DISABLE_DEPRECATED_API
287inline bool parser::allocate_capacity(
size_t capacity,
size_t max_depth)
noexcept {
288 return !allocate(capacity, max_depth);
292inline error_code parser::ensure_capacity(
size_t desired_capacity)
noexcept {
293 return ensure_capacity(doc, desired_capacity);
297inline error_code parser::ensure_capacity(document& target_document,
size_t desired_capacity)
noexcept {
300 if(desired_capacity < MINIMAL_DOCUMENT_CAPACITY) { desired_capacity = MINIMAL_DOCUMENT_CAPACITY; }
307 if (simdjson_unlikely(capacity() < desired_capacity || target_document.capacity() < desired_capacity)) {
308 if (desired_capacity > max_capacity()) {
311 error_code err1 = target_document.capacity() < desired_capacity ? target_document.allocate(desired_capacity) :
SUCCESS;
312 error_code err2 = capacity() < desired_capacity ? allocate(desired_capacity, max_depth()) :
SUCCESS;
313 if(err1 !=
SUCCESS) {
return error = err1; }
314 if(err2 !=
SUCCESS) {
return error = err2; }
320 if(max_capacity > MINIMAL_DOCUMENT_CAPACITY) {
321 _max_capacity = max_capacity;
323 _max_capacity = MINIMAL_DOCUMENT_CAPACITY;
A forward-only stream of documents.
simdjson_inline parser(size_t max_capacity=SIMDJSON_MAXSIZE_BYTES) noexcept
Create a JSON parser.
simdjson_result< element > parse(const uint8_t *buf, size_t len, bool realloc_if_needed=true) &noexcept
Parse a JSON document and return a temporary reference to it.
simdjson_result< element > parse_into_document(document &doc, const uint8_t *buf, size_t len, bool realloc_if_needed=true) &noexcept
Parse a JSON document into a provide document instance and return a temporary reference to it.
simdjson_inline void set_max_capacity(size_t max_capacity) noexcept
Set max_capacity.
simdjson_result< element > parse_unpadded(const uint8_t *buf, size_t len) &noexcept
Parse a JSON document whose buffer is not padded, in place and without copying it.
simdjson_result< element > parse_into_document_unpadded(document &doc, const uint8_t *buf, size_t len) &noexcept
Parse a non-padded JSON document into a caller-provided document instance, in place and without copyi...
simdjson_inline size_t max_capacity() const noexcept
The largest document this parser can automatically support.
simdjson_result< document_stream > load_many(std::string_view path, size_t batch_size=dom::DEFAULT_BATCH_SIZE) noexcept
Load a file containing many JSON documents.
simdjson_result< element > load_into_document(document &doc, std::string_view path) &noexcept
Load a JSON document from a file into a provide document instance and return a temporary reference to...
simdjson_pure simdjson_inline size_t max_depth() const noexcept
The maximum level of nested object and arrays supported by this parser.
simdjson_result< element > load(std::string_view path) &noexcept
Load a JSON document from a file and return a reference to it.
simdjson_inline size_t capacity() const noexcept
The largest document this parser can support without reallocating.
simdjson_inline parser & operator=(parser &&other) noexcept
Take another parser's buffers and state.
simdjson_warn_unused error_code allocate(size_t capacity, size_t max_depth=DEFAULT_MAX_DEPTH) noexcept
Ensure this parser has enough memory to process JSON documents up to capacity bytes in length and max...
simdjson_result< document_stream > parse_many(const uint8_t *buf, size_t len, size_t batch_size=dom::DEFAULT_BATCH_SIZE) noexcept
Parse a buffer containing many JSON documents.
An implementation of simdjson for a particular CPU architecture.
The top level simdjson namespace, containing everything the library provides.
SIMDJSON_DLLIMPORTEXPORT internal::atomic_ptr< const implementation > & get_active_implementation()
The active implementation.
stream_format
Stream format for parse_many/iterate_many.
@ comma_delimited
Comma-separated JSON documents (e.g., {...},{...},{...})
@ whitespace_delimited
Whitespace-delimited JSON documents (default, includes NDJSON/JSONL)
@ comma_delimited_array
A single JSON array whose elements are iterated as comma-separated documents (e.g....
const char * error_message(error_code error) noexcept
It is the convention throughout the code that the macro SIMDJSON_DEVELOPMENT_CHECKS determines whethe...
constexpr size_t DEFAULT_MAX_DEPTH
By default, simdjson supports this many nested objects and arrays.
error_code
All possible errors returned by simdjson.
@ CAPACITY
This parser can't support a document that big.
@ TAPE_ERROR
Something went wrong, this is a generic error. Fatal/unrecoverable error.
@ MEMALLOC
Error allocating memory, most likely out of memory.
@ IO_ERROR
Error reading a file.
constexpr size_t SIMDJSON_PADDING
The amount of padding needed in a buffer to parse JSON.
The result of a simdjson operation that could fail.
simdjson_warn_unused simdjson_inline error_code get(T &value) &&noexcept
Move the value to the provided variable.