mirror of
https://github.com/simdjson/simdjson
synced 2026-06-08 17:27:07 +00:00
Compare commits
4 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 7e1d07ee86 | |||
| 9de1b45e30 | |||
| 7a73230459 | |||
| 667f488c2c |
@@ -22,6 +22,7 @@ public:
|
|||||||
) const noexcept final;
|
) const noexcept final;
|
||||||
simdjson_warn_unused error_code minify(const uint8_t *buf, size_t len, uint8_t *dst, size_t &dst_len) const noexcept final;
|
simdjson_warn_unused error_code minify(const uint8_t *buf, size_t len, uint8_t *dst, size_t &dst_len) const noexcept final;
|
||||||
simdjson_warn_unused bool validate_utf8(const char *buf, size_t len) const noexcept final;
|
simdjson_warn_unused bool validate_utf8(const char *buf, size_t len) const noexcept final;
|
||||||
|
simdjson_warn_unused uint8_t *parse_string(const uint8_t *src, uint8_t *dst) const noexcept final;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace arm64
|
} // namespace arm64
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ public:
|
|||||||
) const noexcept final;
|
) const noexcept final;
|
||||||
simdjson_warn_unused error_code minify(const uint8_t *buf, size_t len, uint8_t *dst, size_t &dst_len) const noexcept final;
|
simdjson_warn_unused error_code minify(const uint8_t *buf, size_t len, uint8_t *dst, size_t &dst_len) const noexcept final;
|
||||||
simdjson_warn_unused bool validate_utf8(const char *buf, size_t len) const noexcept final;
|
simdjson_warn_unused bool validate_utf8(const char *buf, size_t len) const noexcept final;
|
||||||
|
simdjson_warn_unused uint8_t *parse_string(const uint8_t *src, uint8_t *dst) const noexcept final;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace fallback
|
} // namespace fallback
|
||||||
|
|||||||
@@ -89,6 +89,7 @@ simdjson_really_inline simdjson_result<std::string_view> array::raw_json() noexc
|
|||||||
return std::string_view(reinterpret_cast<const char*>(starting_point), size_t(final_point - starting_point));
|
return std::string_view(reinterpret_cast<const char*>(starting_point), size_t(final_point - starting_point));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SIMDJSON_PUSH_DISABLE_WARNINGS
|
||||||
SIMDJSON_DISABLE_STRICT_OVERFLOW_WARNING
|
SIMDJSON_DISABLE_STRICT_OVERFLOW_WARNING
|
||||||
simdjson_really_inline simdjson_result<size_t> array::count_elements() & noexcept {
|
simdjson_really_inline simdjson_result<size_t> array::count_elements() & noexcept {
|
||||||
size_t count{0};
|
size_t count{0};
|
||||||
@@ -101,6 +102,7 @@ simdjson_really_inline simdjson_result<size_t> array::count_elements() & noexcep
|
|||||||
iter.reset_array();
|
iter.reset_array();
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
SIMDJSON_POP_DISABLE_WARNINGS
|
||||||
|
|
||||||
simdjson_really_inline simdjson_result<bool> array::is_empty() & noexcept {
|
simdjson_really_inline simdjson_result<bool> array::is_empty() & noexcept {
|
||||||
bool is_not_empty;
|
bool is_not_empty;
|
||||||
|
|||||||
@@ -26,6 +26,8 @@ simdjson_really_inline bool object_iterator::operator!=(const object_iterator &)
|
|||||||
return iter.is_open();
|
return iter.is_open();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SIMDJSON_PUSH_DISABLE_WARNINGS
|
||||||
|
SIMDJSON_DISABLE_STRICT_OVERFLOW_WARNING
|
||||||
simdjson_really_inline object_iterator &object_iterator::operator++() noexcept {
|
simdjson_really_inline object_iterator &object_iterator::operator++() noexcept {
|
||||||
// TODO this is a safety rail ... users should exit loops as soon as they receive an error.
|
// TODO this is a safety rail ... users should exit loops as soon as they receive an error.
|
||||||
// Nonetheless, let's see if performance is OK with this if statement--the compiler may give it to us for free.
|
// Nonetheless, let's see if performance is OK with this if statement--the compiler may give it to us for free.
|
||||||
@@ -38,6 +40,7 @@ simdjson_really_inline object_iterator &object_iterator::operator++() noexcept {
|
|||||||
if ((error = iter.has_next_field().get(has_value) )) { return *this; };
|
if ((error = iter.has_next_field().get(has_value) )) { return *this; };
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
SIMDJSON_POP_DISABLE_WARNINGS
|
||||||
|
|
||||||
//
|
//
|
||||||
// ### Live States
|
// ### Live States
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ simdjson_really_inline raw_json_string::raw_json_string(const uint8_t * _buf) no
|
|||||||
|
|
||||||
simdjson_really_inline const char * raw_json_string::raw() const noexcept { return reinterpret_cast<const char *>(buf); }
|
simdjson_really_inline const char * raw_json_string::raw() const noexcept { return reinterpret_cast<const char *>(buf); }
|
||||||
simdjson_really_inline simdjson_warn_unused simdjson_result<std::string_view> raw_json_string::unescape(uint8_t *&dst) const noexcept {
|
simdjson_really_inline simdjson_warn_unused simdjson_result<std::string_view> raw_json_string::unescape(uint8_t *&dst) const noexcept {
|
||||||
uint8_t *end = stringparsing::parse_string(buf, dst);
|
uint8_t *end = parse_string(buf, dst);
|
||||||
if (!end) { return STRING_ERROR; }
|
if (!end) { return STRING_ERROR; }
|
||||||
std::string_view result(reinterpret_cast<const char *>(dst), end-dst);
|
std::string_view result(reinterpret_cast<const char *>(dst), end-dst);
|
||||||
dst = end;
|
dst = end;
|
||||||
|
|||||||
@@ -116,6 +116,26 @@ public:
|
|||||||
static simdjson_really_inline bool is_free_from_unescaped_quote(std::string_view target) noexcept;
|
static simdjson_really_inline bool is_free_from_unescaped_quote(std::string_view target) noexcept;
|
||||||
static simdjson_really_inline bool is_free_from_unescaped_quote(const char* target) noexcept;
|
static simdjson_really_inline bool is_free_from_unescaped_quote(const char* target) noexcept;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unescape this JSON string, replacing \\ with \, \n with newline, etc. to a user-provided buffer.
|
||||||
|
* The provided pointer is advanced to the end of the string by reference, and a string_view instance
|
||||||
|
* is returned. You can ensure that your buffer is large enough by allocating a block of memory at least
|
||||||
|
* as large as the input JSON plus SIMDJSON_PADDING and then unescape all strings to this one buffer.
|
||||||
|
*
|
||||||
|
* This unescape function is a low-level function. If you want a more user-friendly approach, you should
|
||||||
|
* avoid raw_json_string instances (e.g., by calling unescaped_key() instead of key() or get_string()
|
||||||
|
* instead of get_raw_json_string()).
|
||||||
|
*
|
||||||
|
* ## IMPORTANT: string_view lifetime
|
||||||
|
*
|
||||||
|
* The string_view is only valid as long as the bytes in dst.
|
||||||
|
*
|
||||||
|
* @param dst A pointer to a buffer at least large enough to write this string as well as
|
||||||
|
* an additional SIMDJSON_PADDING bytes.
|
||||||
|
* @return A string_view pointing at the unescaped string in dst
|
||||||
|
* @error STRING_ERROR if escapes are incorrect.
|
||||||
|
*/
|
||||||
|
simdjson_really_inline simdjson_result<std::string_view> unescape(uint8_t *&dst) const noexcept;
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
|
||||||
@@ -130,20 +150,6 @@ private:
|
|||||||
*/
|
*/
|
||||||
simdjson_really_inline simdjson_warn_unused bool alive() const noexcept { return buf != nullptr; }
|
simdjson_really_inline simdjson_warn_unused bool alive() const noexcept { return buf != nullptr; }
|
||||||
|
|
||||||
/**
|
|
||||||
* Unescape this JSON string, replacing \\ with \, \n with newline, etc.
|
|
||||||
*
|
|
||||||
* ## IMPORTANT: string_view lifetime
|
|
||||||
*
|
|
||||||
* The string_view is only valid as long as the bytes in dst.
|
|
||||||
*
|
|
||||||
* @param dst A pointer to a buffer at least large enough to write this string as well as a \0.
|
|
||||||
* dst will be updated to the next unused location (just after the \0 written out at
|
|
||||||
* the end of this string).
|
|
||||||
* @return A string_view pointing at the unescaped string in dst
|
|
||||||
* @error STRING_ERROR if escapes are incorrect.
|
|
||||||
*/
|
|
||||||
simdjson_really_inline simdjson_warn_unused simdjson_result<std::string_view> unescape(uint8_t *&dst) const noexcept;
|
|
||||||
/**
|
/**
|
||||||
* Unescape this JSON string, replacing \\ with \, \n with newline, etc.
|
* Unescape this JSON string, replacing \\ with \, \n with newline, etc.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -180,6 +180,8 @@ simdjson_warn_unused simdjson_really_inline simdjson_result<bool> value_iterator
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SIMDJSON_PUSH_DISABLE_WARNINGS
|
||||||
|
SIMDJSON_DISABLE_STRICT_OVERFLOW_WARNING
|
||||||
simdjson_warn_unused simdjson_really_inline simdjson_result<bool> value_iterator::find_field_unordered_raw(const std::string_view key) noexcept {
|
simdjson_warn_unused simdjson_really_inline simdjson_result<bool> value_iterator::find_field_unordered_raw(const std::string_view key) noexcept {
|
||||||
/**
|
/**
|
||||||
* When find_field_unordered_raw is called, we can either be pointing at the
|
* When find_field_unordered_raw is called, we can either be pointing at the
|
||||||
@@ -367,6 +369,7 @@ simdjson_warn_unused simdjson_really_inline simdjson_result<bool> value_iterator
|
|||||||
// never reach this point.
|
// never reach this point.
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
SIMDJSON_POP_DISABLE_WARNINGS
|
||||||
|
|
||||||
simdjson_warn_unused simdjson_really_inline simdjson_result<raw_json_string> value_iterator::field_key() noexcept {
|
simdjson_warn_unused simdjson_really_inline simdjson_result<raw_json_string> value_iterator::field_key() noexcept {
|
||||||
assert_at_next();
|
assert_at_next();
|
||||||
|
|||||||
@@ -1,138 +0,0 @@
|
|||||||
// This file contains the common code every implementation uses
|
|
||||||
// It is intended to be included multiple times and compiled multiple times
|
|
||||||
|
|
||||||
namespace simdjson {
|
|
||||||
namespace SIMDJSON_IMPLEMENTATION {
|
|
||||||
namespace {
|
|
||||||
/// @private
|
|
||||||
namespace stringparsing {
|
|
||||||
|
|
||||||
// begin copypasta
|
|
||||||
// These chars yield themselves: " \ /
|
|
||||||
// b -> backspace, f -> formfeed, n -> newline, r -> cr, t -> horizontal tab
|
|
||||||
// u not handled in this table as it's complex
|
|
||||||
static const uint8_t escape_map[256] = {
|
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0x0.
|
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
||||||
0, 0, 0x22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x2f,
|
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
||||||
|
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0x4.
|
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x5c, 0, 0, 0, // 0x5.
|
|
||||||
0, 0, 0x08, 0, 0, 0, 0x0c, 0, 0, 0, 0, 0, 0, 0, 0x0a, 0, // 0x6.
|
|
||||||
0, 0, 0x0d, 0, 0x09, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0x7.
|
|
||||||
|
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
||||||
|
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
||||||
};
|
|
||||||
|
|
||||||
// handle a unicode codepoint
|
|
||||||
// write appropriate values into dest
|
|
||||||
// src will advance 6 bytes or 12 bytes
|
|
||||||
// dest will advance a variable amount (return via pointer)
|
|
||||||
// return true if the unicode codepoint was valid
|
|
||||||
// We work in little-endian then swap at write time
|
|
||||||
simdjson_warn_unused
|
|
||||||
simdjson_really_inline bool handle_unicode_codepoint(const uint8_t **src_ptr,
|
|
||||||
uint8_t **dst_ptr) {
|
|
||||||
// jsoncharutils::hex_to_u32_nocheck fills high 16 bits of the return value with 1s if the
|
|
||||||
// conversion isn't valid; we defer the check for this to inside the
|
|
||||||
// multilingual plane check
|
|
||||||
uint32_t code_point = jsoncharutils::hex_to_u32_nocheck(*src_ptr + 2);
|
|
||||||
*src_ptr += 6;
|
|
||||||
// check for low surrogate for characters outside the Basic
|
|
||||||
// Multilingual Plane.
|
|
||||||
if (code_point >= 0xd800 && code_point < 0xdc00) {
|
|
||||||
if (((*src_ptr)[0] != '\\') || (*src_ptr)[1] != 'u') {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
uint32_t code_point_2 = jsoncharutils::hex_to_u32_nocheck(*src_ptr + 2);
|
|
||||||
|
|
||||||
// if the first code point is invalid we will get here, as we will go past
|
|
||||||
// the check for being outside the Basic Multilingual plane. If we don't
|
|
||||||
// find a \u immediately afterwards we fail out anyhow, but if we do,
|
|
||||||
// this check catches both the case of the first code point being invalid
|
|
||||||
// or the second code point being invalid.
|
|
||||||
if ((code_point | code_point_2) >> 16) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
code_point =
|
|
||||||
(((code_point - 0xd800) << 10) | (code_point_2 - 0xdc00)) + 0x10000;
|
|
||||||
*src_ptr += 6;
|
|
||||||
}
|
|
||||||
size_t offset = jsoncharutils::codepoint_to_utf8(code_point, *dst_ptr);
|
|
||||||
*dst_ptr += offset;
|
|
||||||
return offset > 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Unescape a string from src to dst, stopping at a final unescaped quote. E.g., if src points at 'joe"', then
|
|
||||||
* dst needs to have four free bytes.
|
|
||||||
*/
|
|
||||||
simdjson_warn_unused simdjson_really_inline uint8_t *parse_string(const uint8_t *src, uint8_t *dst) {
|
|
||||||
while (1) {
|
|
||||||
// Copy the next n bytes, and find the backslash and quote in them.
|
|
||||||
auto bs_quote = backslash_and_quote::copy_and_find(src, dst);
|
|
||||||
// If the next thing is the end quote, copy and return
|
|
||||||
if (bs_quote.has_quote_first()) {
|
|
||||||
// we encountered quotes first. Move dst to point to quotes and exit
|
|
||||||
return dst + bs_quote.quote_index();
|
|
||||||
}
|
|
||||||
if (bs_quote.has_backslash()) {
|
|
||||||
/* find out where the backspace is */
|
|
||||||
auto bs_dist = bs_quote.backslash_index();
|
|
||||||
uint8_t escape_char = src[bs_dist + 1];
|
|
||||||
/* we encountered backslash first. Handle backslash */
|
|
||||||
if (escape_char == 'u') {
|
|
||||||
/* move src/dst up to the start; they will be further adjusted
|
|
||||||
within the unicode codepoint handling code. */
|
|
||||||
src += bs_dist;
|
|
||||||
dst += bs_dist;
|
|
||||||
if (!handle_unicode_codepoint(&src, &dst)) {
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
/* simple 1:1 conversion. Will eat bs_dist+2 characters in input and
|
|
||||||
* write bs_dist+1 characters to output
|
|
||||||
* note this may reach beyond the part of the buffer we've actually
|
|
||||||
* seen. I think this is ok */
|
|
||||||
uint8_t escape_result = escape_map[escape_char];
|
|
||||||
if (escape_result == 0u) {
|
|
||||||
return nullptr; /* bogus escape value is an error */
|
|
||||||
}
|
|
||||||
dst[bs_dist] = escape_result;
|
|
||||||
src += bs_dist + 2;
|
|
||||||
dst += bs_dist + 1;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
/* they are the same. Since they can't co-occur, it means we
|
|
||||||
* encountered neither. */
|
|
||||||
src += backslash_and_quote::BYTES_PROCESSED;
|
|
||||||
dst += backslash_and_quote::BYTES_PROCESSED;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* can't be reached */
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
simdjson_unused simdjson_warn_unused simdjson_really_inline error_code parse_string_to_buffer(const uint8_t *src, uint8_t *¤t_string_buf_loc, std::string_view &s) {
|
|
||||||
if (*(src++) != '"') { return STRING_ERROR; }
|
|
||||||
auto end = stringparsing::parse_string(src, current_string_buf_loc);
|
|
||||||
if (!end) { return STRING_ERROR; }
|
|
||||||
s = std::string_view(reinterpret_cast<const char *>(current_string_buf_loc), end-current_string_buf_loc);
|
|
||||||
current_string_buf_loc = end;
|
|
||||||
return SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace stringparsing
|
|
||||||
} // unnamed namespace
|
|
||||||
} // namespace SIMDJSON_IMPLEMENTATION
|
|
||||||
} // namespace simdjson
|
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ public:
|
|||||||
) const noexcept final;
|
) const noexcept final;
|
||||||
simdjson_warn_unused error_code minify(const uint8_t *buf, size_t len, uint8_t *dst, size_t &dst_len) const noexcept final;
|
simdjson_warn_unused error_code minify(const uint8_t *buf, size_t len, uint8_t *dst, size_t &dst_len) const noexcept final;
|
||||||
simdjson_warn_unused bool validate_utf8(const char *buf, size_t len) const noexcept final;
|
simdjson_warn_unused bool validate_utf8(const char *buf, size_t len) const noexcept final;
|
||||||
|
simdjson_warn_unused uint8_t *parse_string(const uint8_t *src, uint8_t *dst) const noexcept final;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace haswell
|
} // namespace haswell
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ public:
|
|||||||
) const noexcept final;
|
) const noexcept final;
|
||||||
simdjson_warn_unused error_code minify(const uint8_t *buf, size_t len, uint8_t *dst, size_t &dst_len) const noexcept final;
|
simdjson_warn_unused error_code minify(const uint8_t *buf, size_t len, uint8_t *dst, size_t &dst_len) const noexcept final;
|
||||||
simdjson_warn_unused bool validate_utf8(const char *buf, size_t len) const noexcept final;
|
simdjson_warn_unused bool validate_utf8(const char *buf, size_t len) const noexcept final;
|
||||||
|
simdjson_warn_unused uint8_t *parse_string(const uint8_t *src, uint8_t *dst) const noexcept final;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace icelake
|
} // namespace icelake
|
||||||
|
|||||||
@@ -18,8 +18,6 @@ namespace simdjson {
|
|||||||
* @return true if the string is valid UTF-8.
|
* @return true if the string is valid UTF-8.
|
||||||
*/
|
*/
|
||||||
simdjson_warn_unused bool validate_utf8(const char * buf, size_t len) noexcept;
|
simdjson_warn_unused bool validate_utf8(const char * buf, size_t len) noexcept;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Validate the UTF-8 string.
|
* Validate the UTF-8 string.
|
||||||
*
|
*
|
||||||
@@ -40,6 +38,20 @@ simdjson_really_inline simdjson_warn_unused bool validate_utf8(const std::string
|
|||||||
return validate_utf8(s.data(), s.size());
|
return validate_utf8(s.data(), s.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unescape a valid UTF-8 string from src to dst, stopping at a final unescaped quote. There
|
||||||
|
* must be an unescaped quote terminating the string. It returns the final output
|
||||||
|
* position as pointer. In case of error (e.g., the string has bad escaped codes),
|
||||||
|
* then null_nullptrptr is returned. It is assumed that the output buffer is large
|
||||||
|
* enough. E.g., if src points at 'joe"', then dst needs to have four free bytes +
|
||||||
|
* SIMDJSON_PADDING bytes.
|
||||||
|
*
|
||||||
|
* @param str pointer to the beginning of a valid UTF-8 JSON string, must end with an unescaped quote.
|
||||||
|
* @param dst pointer to a destination buffer, it must point a region in memory of sufficient size.
|
||||||
|
* @return end of the of the written region (exclusive) or nullptr in case of error.
|
||||||
|
*/
|
||||||
|
simdjson_warn_unused uint8_t *parse_string(const uint8_t *src, uint8_t *dst) noexcept;
|
||||||
|
|
||||||
namespace dom {
|
namespace dom {
|
||||||
class document;
|
class document;
|
||||||
} // namespace dom
|
} // namespace dom
|
||||||
@@ -136,6 +148,22 @@ public:
|
|||||||
*/
|
*/
|
||||||
simdjson_warn_unused virtual bool validate_utf8(const char *buf, size_t len) const noexcept = 0;
|
simdjson_warn_unused virtual bool validate_utf8(const char *buf, size_t len) const noexcept = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unescape a valid UTF-8 string from src to dst, stopping at a final unescaped quote. There
|
||||||
|
* must be an unescaped quote terminating the string. It returns the final output
|
||||||
|
* position as pointer. In case of error (e.g., the string has bad escaped codes),
|
||||||
|
* then null_nullptrptr is returned. It is assumed that the output buffer is large
|
||||||
|
* enough. E.g., if src points at 'joe"', then dst needs to have four free bytes +
|
||||||
|
* SIMDJSON_PADDING bytes.
|
||||||
|
*
|
||||||
|
* Overridden by each implementation.
|
||||||
|
*
|
||||||
|
* @param str pointer to the beginning of a valid UTF-8 JSON string, must end with an unescaped quote.
|
||||||
|
* @param dst pointer to a destination buffer, it must point a region in memory of sufficient size.
|
||||||
|
* @return end of the of the written region (exclusive) or nullptr in case of error.
|
||||||
|
*/
|
||||||
|
simdjson_warn_unused virtual uint8_t *parse_string(const uint8_t *src, uint8_t *dst) const noexcept = 0;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
/** @private Construct an implementation with the given name and description. For subclasses. */
|
/** @private Construct an implementation with the given name and description. For subclasses. */
|
||||||
simdjson_really_inline implementation(
|
simdjson_really_inline implementation(
|
||||||
|
|||||||
@@ -163,6 +163,7 @@ public:
|
|||||||
*/
|
*/
|
||||||
simdjson_warn_unused inline error_code allocate(size_t capacity, size_t max_depth) noexcept;
|
simdjson_warn_unused inline error_code allocate(size_t capacity, size_t max_depth) noexcept;
|
||||||
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
/**
|
/**
|
||||||
* The maximum document length this parser supports.
|
* The maximum document length this parser supports.
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ public:
|
|||||||
size_t &dst_len) const noexcept final;
|
size_t &dst_len) const noexcept final;
|
||||||
simdjson_warn_unused bool validate_utf8(const char *buf,
|
simdjson_warn_unused bool validate_utf8(const char *buf,
|
||||||
size_t len) const noexcept final;
|
size_t len) const noexcept final;
|
||||||
|
simdjson_warn_unused uint8_t *parse_string(const uint8_t *src, uint8_t *dst) const noexcept final;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace ppc64
|
} // namespace ppc64
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ public:
|
|||||||
) const noexcept final;
|
) const noexcept final;
|
||||||
simdjson_warn_unused error_code minify(const uint8_t *buf, size_t len, uint8_t *dst, size_t &dst_len) const noexcept final;
|
simdjson_warn_unused error_code minify(const uint8_t *buf, size_t len, uint8_t *dst, size_t &dst_len) const noexcept final;
|
||||||
simdjson_warn_unused bool validate_utf8(const char *buf, size_t len) const noexcept final;
|
simdjson_warn_unused bool validate_utf8(const char *buf, size_t len) const noexcept final;
|
||||||
|
simdjson_warn_unused uint8_t *parse_string(const uint8_t *src, uint8_t *dst) const noexcept final;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace westmere
|
} // namespace westmere
|
||||||
|
|||||||
@@ -109,6 +109,7 @@ simdjson_really_inline simd8<bool> must_be_2_3_continuation(const simd8<uint8_t>
|
|||||||
// Stage 2
|
// Stage 2
|
||||||
//
|
//
|
||||||
|
|
||||||
|
#include "generic/stage2/stringparsing.h"
|
||||||
#include "generic/stage2/tape_builder.h"
|
#include "generic/stage2/tape_builder.h"
|
||||||
|
|
||||||
//
|
//
|
||||||
@@ -151,6 +152,11 @@ simdjson_warn_unused error_code dom_parser_implementation::stage2_next(dom::docu
|
|||||||
return stage2::tape_builder::parse_document<true>(*this, _doc);
|
return stage2::tape_builder::parse_document<true>(*this, _doc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
simdjson_warn_unused uint8_t *implementation::parse_string(const uint8_t *src, uint8_t *dst) const noexcept {
|
||||||
|
return arm64::stringparsing::parse_string(src, dst);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
simdjson_warn_unused error_code dom_parser_implementation::parse(const uint8_t *_buf, size_t _len, dom::document &_doc) noexcept {
|
simdjson_warn_unused error_code dom_parser_implementation::parse(const uint8_t *_buf, size_t _len, dom::document &_doc) noexcept {
|
||||||
auto error = stage1(_buf, _len, stage1_mode::regular);
|
auto error = stage1(_buf, _len, stage1_mode::regular);
|
||||||
if (error) { return error; }
|
if (error) { return error; }
|
||||||
|
|||||||
@@ -346,6 +346,7 @@ simdjson_warn_unused bool implementation::validate_utf8(const char *buf, size_t
|
|||||||
//
|
//
|
||||||
// Stage 2
|
// Stage 2
|
||||||
//
|
//
|
||||||
|
#include "generic/stage2/stringparsing.h"
|
||||||
#include "generic/stage2/tape_builder.h"
|
#include "generic/stage2/tape_builder.h"
|
||||||
|
|
||||||
namespace simdjson {
|
namespace simdjson {
|
||||||
@@ -359,6 +360,10 @@ simdjson_warn_unused error_code dom_parser_implementation::stage2_next(dom::docu
|
|||||||
return stage2::tape_builder::parse_document<true>(*this, _doc);
|
return stage2::tape_builder::parse_document<true>(*this, _doc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
simdjson_warn_unused uint8_t *implementation::parse_string(const uint8_t *src, uint8_t *dst) const noexcept {
|
||||||
|
return fallback::stringparsing::parse_string(src, dst);
|
||||||
|
}
|
||||||
|
|
||||||
simdjson_warn_unused error_code dom_parser_implementation::parse(const uint8_t *_buf, size_t _len, dom::document &_doc) noexcept {
|
simdjson_warn_unused error_code dom_parser_implementation::parse(const uint8_t *_buf, size_t _len, dom::document &_doc) noexcept {
|
||||||
auto error = stage1(_buf, _len, stage1_mode::regular);
|
auto error = stage1(_buf, _len, stage1_mode::regular);
|
||||||
if (error) { return error; }
|
if (error) { return error; }
|
||||||
|
|||||||
@@ -0,0 +1,142 @@
|
|||||||
|
// This file contains the common code every implementation uses
|
||||||
|
// It is intended to be included multiple times and compiled multiple times
|
||||||
|
|
||||||
|
namespace simdjson {
|
||||||
|
namespace SIMDJSON_IMPLEMENTATION {
|
||||||
|
namespace {
|
||||||
|
/// @private
|
||||||
|
namespace stringparsing {
|
||||||
|
|
||||||
|
// begin copypasta
|
||||||
|
// These chars yield themselves: " \ /
|
||||||
|
// b -> backspace, f -> formfeed, n -> newline, r -> cr, t -> horizontal tab
|
||||||
|
// u not handled in this table as it's complex
|
||||||
|
static const uint8_t escape_map[256] = {
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0x0.
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
0, 0, 0x22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x2f,
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0x4.
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x5c, 0, 0, 0, // 0x5.
|
||||||
|
0, 0, 0x08, 0, 0, 0, 0x0c, 0, 0, 0, 0, 0, 0, 0, 0x0a, 0, // 0x6.
|
||||||
|
0, 0, 0x0d, 0, 0x09, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0x7.
|
||||||
|
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
// handle a unicode codepoint
|
||||||
|
// write appropriate values into dest
|
||||||
|
// src will advance 6 bytes or 12 bytes
|
||||||
|
// dest will advance a variable amount (return via pointer)
|
||||||
|
// return true if the unicode codepoint was valid
|
||||||
|
// We work in little-endian then swap at write time
|
||||||
|
simdjson_warn_unused
|
||||||
|
simdjson_really_inline bool handle_unicode_codepoint(const uint8_t **src_ptr,
|
||||||
|
uint8_t **dst_ptr) {
|
||||||
|
// jsoncharutils::hex_to_u32_nocheck fills high 16 bits of the return value with 1s if the
|
||||||
|
// conversion isn't valid; we defer the check for this to inside the
|
||||||
|
// multilingual plane check
|
||||||
|
uint32_t code_point = jsoncharutils::hex_to_u32_nocheck(*src_ptr + 2);
|
||||||
|
*src_ptr += 6;
|
||||||
|
// check for low surrogate for characters outside the Basic
|
||||||
|
// Multilingual Plane.
|
||||||
|
if (code_point >= 0xd800 && code_point < 0xdc00) {
|
||||||
|
if (((*src_ptr)[0] != '\\') || (*src_ptr)[1] != 'u') {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
uint32_t code_point_2 = jsoncharutils::hex_to_u32_nocheck(*src_ptr + 2);
|
||||||
|
|
||||||
|
// if the first code point is invalid we will get here, as we will go past
|
||||||
|
// the check for being outside the Basic Multilingual plane. If we don't
|
||||||
|
// find a \u immediately afterwards we fail out anyhow, but if we do,
|
||||||
|
// this check catches both the case of the first code point being invalid
|
||||||
|
// or the second code point being invalid.
|
||||||
|
if ((code_point | code_point_2) >> 16) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
code_point =
|
||||||
|
(((code_point - 0xd800) << 10) | (code_point_2 - 0xdc00)) + 0x10000;
|
||||||
|
*src_ptr += 6;
|
||||||
|
}
|
||||||
|
size_t offset = jsoncharutils::codepoint_to_utf8(code_point, *dst_ptr);
|
||||||
|
*dst_ptr += offset;
|
||||||
|
return offset > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unescape a valid UTF-8 string from src to dst, stopping at a final unescaped quote. There
|
||||||
|
* must be an unescaped quote terminating the string. It returns the final output
|
||||||
|
* position as pointer. In case of error (e.g., the string has bad escaped codes),
|
||||||
|
* then null_nullptrptr is returned. It is assumed that the output buffer is large
|
||||||
|
* enough. E.g., if src points at 'joe"', then dst needs to have four free bytes +
|
||||||
|
* SIMDJSON_PADDING bytes.
|
||||||
|
*/
|
||||||
|
simdjson_warn_unused simdjson_really_inline uint8_t *parse_string(const uint8_t *src, uint8_t *dst) {
|
||||||
|
while (1) {
|
||||||
|
// Copy the next n bytes, and find the backslash and quote in them.
|
||||||
|
auto bs_quote = backslash_and_quote::copy_and_find(src, dst);
|
||||||
|
// If the next thing is the end quote, copy and return
|
||||||
|
if (bs_quote.has_quote_first()) {
|
||||||
|
// we encountered quotes first. Move dst to point to quotes and exit
|
||||||
|
return dst + bs_quote.quote_index();
|
||||||
|
}
|
||||||
|
if (bs_quote.has_backslash()) {
|
||||||
|
/* find out where the backspace is */
|
||||||
|
auto bs_dist = bs_quote.backslash_index();
|
||||||
|
uint8_t escape_char = src[bs_dist + 1];
|
||||||
|
/* we encountered backslash first. Handle backslash */
|
||||||
|
if (escape_char == 'u') {
|
||||||
|
/* move src/dst up to the start; they will be further adjusted
|
||||||
|
within the unicode codepoint handling code. */
|
||||||
|
src += bs_dist;
|
||||||
|
dst += bs_dist;
|
||||||
|
if (!handle_unicode_codepoint(&src, &dst)) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/* simple 1:1 conversion. Will eat bs_dist+2 characters in input and
|
||||||
|
* write bs_dist+1 characters to output
|
||||||
|
* note this may reach beyond the part of the buffer we've actually
|
||||||
|
* seen. I think this is ok */
|
||||||
|
uint8_t escape_result = escape_map[escape_char];
|
||||||
|
if (escape_result == 0u) {
|
||||||
|
return nullptr; /* bogus escape value is an error */
|
||||||
|
}
|
||||||
|
dst[bs_dist] = escape_result;
|
||||||
|
src += bs_dist + 2;
|
||||||
|
dst += bs_dist + 1;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/* they are the same. Since they can't co-occur, it means we
|
||||||
|
* encountered neither. */
|
||||||
|
src += backslash_and_quote::BYTES_PROCESSED;
|
||||||
|
dst += backslash_and_quote::BYTES_PROCESSED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* can't be reached */
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
simdjson_unused simdjson_warn_unused simdjson_really_inline error_code parse_string_to_buffer(const uint8_t *src, uint8_t *¤t_string_buf_loc, std::string_view &s) {
|
||||||
|
if (*(src++) != '"') { return STRING_ERROR; }
|
||||||
|
auto end = stringparsing::parse_string(src, current_string_buf_loc);
|
||||||
|
if (!end) { return STRING_ERROR; }
|
||||||
|
s = std::string_view(reinterpret_cast<const char *>(current_string_buf_loc), end-current_string_buf_loc);
|
||||||
|
current_string_buf_loc = end;
|
||||||
|
return SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace stringparsing
|
||||||
|
} // unnamed namespace
|
||||||
|
} // namespace SIMDJSON_IMPLEMENTATION
|
||||||
|
} // namespace simdjson
|
||||||
@@ -112,6 +112,7 @@ simdjson_really_inline simd8<bool> must_be_2_3_continuation(const simd8<uint8_t>
|
|||||||
//
|
//
|
||||||
// Stage 2
|
// Stage 2
|
||||||
//
|
//
|
||||||
|
#include "generic/stage2/stringparsing.h"
|
||||||
#include "generic/stage2/tape_builder.h"
|
#include "generic/stage2/tape_builder.h"
|
||||||
|
|
||||||
//
|
//
|
||||||
@@ -152,6 +153,10 @@ simdjson_warn_unused error_code dom_parser_implementation::stage2_next(dom::docu
|
|||||||
return stage2::tape_builder::parse_document<true>(*this, _doc);
|
return stage2::tape_builder::parse_document<true>(*this, _doc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
simdjson_warn_unused uint8_t *implementation::parse_string(const uint8_t *src, uint8_t *dst) const noexcept {
|
||||||
|
return haswell::stringparsing::parse_string(src, dst);
|
||||||
|
}
|
||||||
|
|
||||||
simdjson_warn_unused error_code dom_parser_implementation::parse(const uint8_t *_buf, size_t _len, dom::document &_doc) noexcept {
|
simdjson_warn_unused error_code dom_parser_implementation::parse(const uint8_t *_buf, size_t _len, dom::document &_doc) noexcept {
|
||||||
auto error = stage1(_buf, _len, stage1_mode::regular);
|
auto error = stage1(_buf, _len, stage1_mode::regular);
|
||||||
if (error) { return error; }
|
if (error) { return error; }
|
||||||
|
|||||||
@@ -158,6 +158,7 @@ SIMDJSON_POP_DISABLE_WARNINGS
|
|||||||
//
|
//
|
||||||
// Stage 2
|
// Stage 2
|
||||||
//
|
//
|
||||||
|
#include "generic/stage2/stringparsing.h"
|
||||||
#include "generic/stage2/tape_builder.h"
|
#include "generic/stage2/tape_builder.h"
|
||||||
|
|
||||||
//
|
//
|
||||||
@@ -198,6 +199,10 @@ simdjson_warn_unused error_code dom_parser_implementation::stage2_next(dom::docu
|
|||||||
return stage2::tape_builder::parse_document<true>(*this, _doc);
|
return stage2::tape_builder::parse_document<true>(*this, _doc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
simdjson_warn_unused uint8_t *implementation::parse_string(const uint8_t *src, uint8_t *dst) const noexcept {
|
||||||
|
return icelake::stringparsing::parse_string(src, dst);
|
||||||
|
}
|
||||||
|
|
||||||
simdjson_warn_unused error_code dom_parser_implementation::parse(const uint8_t *_buf, size_t _len, dom::document &_doc) noexcept {
|
simdjson_warn_unused error_code dom_parser_implementation::parse(const uint8_t *_buf, size_t _len, dom::document &_doc) noexcept {
|
||||||
auto error = stage1(_buf, _len, stage1_mode::regular);
|
auto error = stage1(_buf, _len, stage1_mode::regular);
|
||||||
if (error) { return error; }
|
if (error) { return error; }
|
||||||
|
|||||||
@@ -72,6 +72,9 @@ public:
|
|||||||
simdjson_warn_unused bool validate_utf8(const char * buf, size_t len) const noexcept final override {
|
simdjson_warn_unused bool validate_utf8(const char * buf, size_t len) const noexcept final override {
|
||||||
return set_best()->validate_utf8(buf, len);
|
return set_best()->validate_utf8(buf, len);
|
||||||
}
|
}
|
||||||
|
simdjson_warn_unused uint8_t *parse_string(const uint8_t *src, uint8_t *dst) const noexcept final override {
|
||||||
|
return set_best()->parse_string(src, dst);
|
||||||
|
}
|
||||||
simdjson_really_inline detect_best_supported_implementation_on_first_use() noexcept : implementation("best_supported_detector", "Detects the best supported implementation and sets it", 0) {}
|
simdjson_really_inline detect_best_supported_implementation_on_first_use() noexcept : implementation("best_supported_detector", "Detects the best supported implementation and sets it", 0) {}
|
||||||
private:
|
private:
|
||||||
const implementation *set_best() const noexcept;
|
const implementation *set_best() const noexcept;
|
||||||
@@ -124,6 +127,9 @@ public:
|
|||||||
// what are the chances that the programmer has a fallback? Given that *we* provide the
|
// what are the chances that the programmer has a fallback? Given that *we* provide the
|
||||||
// fallback, it implies that the programmer would need a fallback for our fallback.
|
// fallback, it implies that the programmer would need a fallback for our fallback.
|
||||||
}
|
}
|
||||||
|
simdjson_warn_unused uint8_t *parse_string(const uint8_t *, uint8_t *) const noexcept final override {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
unsupported_implementation() : implementation("unsupported", "Unsupported CPU (no detected SIMD instructions)", 0) {}
|
unsupported_implementation() : implementation("unsupported", "Unsupported CPU (no detected SIMD instructions)", 0) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -188,7 +194,9 @@ simdjson_warn_unused error_code minify(const char *buf, size_t len, char *dst, s
|
|||||||
simdjson_warn_unused bool validate_utf8(const char *buf, size_t len) noexcept {
|
simdjson_warn_unused bool validate_utf8(const char *buf, size_t len) noexcept {
|
||||||
return get_active_implementation()->validate_utf8(buf, len);
|
return get_active_implementation()->validate_utf8(buf, len);
|
||||||
}
|
}
|
||||||
|
simdjson_warn_unused uint8_t *parse_string(const uint8_t *src, uint8_t *dst) noexcept {
|
||||||
|
return get_active_implementation()->parse_string(src, dst);
|
||||||
|
}
|
||||||
const implementation * builtin_implementation() {
|
const implementation * builtin_implementation() {
|
||||||
static const implementation * builtin_impl = get_available_implementations()[SIMDJSON_STRINGIFY(SIMDJSON_BUILTIN_IMPLEMENTATION)];
|
static const implementation * builtin_impl = get_available_implementations()[SIMDJSON_STRINGIFY(SIMDJSON_BUILTIN_IMPLEMENTATION)];
|
||||||
assert(builtin_impl);
|
assert(builtin_impl);
|
||||||
|
|||||||
@@ -79,7 +79,7 @@ simdjson_really_inline simd8<bool> must_be_2_3_continuation(const simd8<uint8_t>
|
|||||||
//
|
//
|
||||||
// Stage 2
|
// Stage 2
|
||||||
//
|
//
|
||||||
|
#include "generic/stage2/stringparsing.h"
|
||||||
#include "generic/stage2/tape_builder.h"
|
#include "generic/stage2/tape_builder.h"
|
||||||
|
|
||||||
//
|
//
|
||||||
@@ -122,6 +122,10 @@ simdjson_warn_unused error_code dom_parser_implementation::stage2_next(dom::docu
|
|||||||
return stage2::tape_builder::parse_document<true>(*this, _doc);
|
return stage2::tape_builder::parse_document<true>(*this, _doc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
simdjson_warn_unused uint8_t *implementation::parse_string(const uint8_t *src, uint8_t *dst) const noexcept {
|
||||||
|
return ppc64::stringparsing::parse_string(src, dst);
|
||||||
|
}
|
||||||
|
|
||||||
simdjson_warn_unused error_code dom_parser_implementation::parse(const uint8_t *_buf, size_t _len, dom::document &_doc) noexcept {
|
simdjson_warn_unused error_code dom_parser_implementation::parse(const uint8_t *_buf, size_t _len, dom::document &_doc) noexcept {
|
||||||
auto error = stage1(_buf, _len, stage1_mode::regular);
|
auto error = stage1(_buf, _len, stage1_mode::regular);
|
||||||
if (error) { return error; }
|
if (error) { return error; }
|
||||||
|
|||||||
@@ -110,6 +110,7 @@ simdjson_really_inline simd8<bool> must_be_2_3_continuation(const simd8<uint8_t>
|
|||||||
//
|
//
|
||||||
// Stage 2
|
// Stage 2
|
||||||
//
|
//
|
||||||
|
#include "generic/stage2/stringparsing.h"
|
||||||
#include "generic/stage2/tape_builder.h"
|
#include "generic/stage2/tape_builder.h"
|
||||||
|
|
||||||
//
|
//
|
||||||
@@ -151,6 +152,10 @@ simdjson_warn_unused error_code dom_parser_implementation::stage2_next(dom::docu
|
|||||||
return stage2::tape_builder::parse_document<true>(*this, _doc);
|
return stage2::tape_builder::parse_document<true>(*this, _doc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
simdjson_warn_unused uint8_t *implementation::parse_string(const uint8_t *src, uint8_t *dst) const noexcept {
|
||||||
|
return westmere::stringparsing::parse_string(src, dst);
|
||||||
|
}
|
||||||
|
|
||||||
simdjson_warn_unused error_code dom_parser_implementation::parse(const uint8_t *_buf, size_t _len, dom::document &_doc) noexcept {
|
simdjson_warn_unused error_code dom_parser_implementation::parse(const uint8_t *_buf, size_t _len, dom::document &_doc) noexcept {
|
||||||
auto error = stage1(_buf, _len, stage1_mode::regular);
|
auto error = stage1(_buf, _len, stage1_mode::regular);
|
||||||
if (error) { return error; }
|
if (error) { return error; }
|
||||||
|
|||||||
Reference in New Issue
Block a user