diff --git a/README.md b/README.md
index 25207470e..fae48a9f4 100644
--- a/README.md
+++ b/README.md
@@ -40,19 +40,11 @@ simdjson is easily consumable with a single .h and .cpp file.
100 results.
```
-## Real-world usage
+## How It Works
-- [Microsoft FishStore](https://github.com/microsoft/FishStore)
-- [Yandex ClickHouse](https://github.com/yandex/ClickHouse)
-- [Clang Build Analyzer](https://github.com/aras-p/ClangBuildAnalyzer)
+simdjson's startling speed is a result of research into the best ways to take advantage of modern superscalar architectures. The biggest factors are using parallel/vector algorithms and SIMD instructions to eliminate branches, reducing data dependency, and careful attention to cache.
-If you are planning to use simdjson in a product, please work from one of our releases.
-
-## Research article (VLDB Journal)
-
-A description of the design and implementation of simdjson is in our research article:
-
-* Geoff Langdale, Daniel Lemire, [Parsing Gigabytes of JSON per Second](https://arxiv.org/abs/1902.08318), VLDB Journal 28 (6), 2019appear)
+* A description of the design and implementation of simdjson is in our research article in VLDB journal: Geoff Langdale, Daniel Lemire, [Parsing Gigabytes of JSON per Second](https://arxiv.org/abs/1902.08318), VLDB Journal 28 (6), 2019appear)
We also have an informal [blog post providing some background and context](https://branchfree.org/2019/02/25/paper-parsing-gigabytes-of-json-per-second/).
@@ -60,14 +52,19 @@ Some people [enjoy reading our paper](https://arxiv.org/abs/1902.08318):
[](https://twitter.com/halvarflake/status/1118459536686362625)
-
## Talks
QCon San Francisco 2019 (best voted talk):
[](http://www.youtube.com/watch?v=wlvKAT7SZIQ)
+## Real-world usage
+- [Microsoft FishStore](https://github.com/microsoft/FishStore)
+- [Yandex ClickHouse](https://github.com/yandex/ClickHouse)
+- [Clang Build Analyzer](https://github.com/aras-p/ClangBuildAnalyzer)
+
+If you are planning to use simdjson in a product, please work from one of our releases.
## Performance results
diff --git a/include/simdjson/document.h b/include/simdjson/document.h
index d5a21b647..d1491e486 100644
--- a/include/simdjson/document.h
+++ b/include/simdjson/document.h
@@ -105,33 +105,6 @@ public:
operator object() const noexcept(false);
#endif // SIMDJSON_EXCEPTIONS
- /**
- * Get the value associated with the given key.
- *
- * The key will be matched against **unescaped** JSON:
- *
- * document::parse(R"({ "a\n": 1 })")["a\n"].as_uint64_t().value == 1
- * document::parse(R"({ "a\n": 1 })")["a\\n"].as_uint64_t().error == NO_SUCH_FIELD
- *
- * @return The value associated with the given key, or:
- * - NO_SUCH_FIELD if the field does not exist in the object
- * - UNEXPECTED_TYPE if the document is not an object
- */
- element_result operator[](const std::string_view &s) const noexcept;
- /**
- * Get the value associated with the given key.
- *
- * The key will be matched against **unescaped** JSON:
- *
- * document::parse(R"({ "a\n": 1 })")["a\n"].as_uint64_t().value == 1
- * document::parse(R"({ "a\n": 1 })")["a\\n"].as_uint64_t().error == NO_SUCH_FIELD
- *
- * @return The value associated with this field, or:
- * - NO_SUCH_FIELD if the field does not exist in the object
- * - UNEXPECTED_TYPE if the document is not an object
- */
- element_result operator[](const char *s) const noexcept;
-
/**
* Dump the raw tape for debugging.
*
@@ -215,6 +188,88 @@ public:
// We do not want to allow implicit conversion from C string to std::string.
doc_result parse(const char *buf, bool realloc_if_needed = true) noexcept = delete;
+ /**
+ * Get the value associated with the given JSON pointer.
+ *
+ * document doc = document::parse(R"({ "foo": { "a": [ 10, 20, 30 ] }})");
+ * doc["/foo/a/1"] == 20
+ * doc["/"]["foo"]["a"].at(1) == 20
+ * doc[""]["foo"]["a"].at(1) == 20
+ *
+ * @return The value associated with the given JSON pointer, or:
+ * - NO_SUCH_FIELD if a field does not exist in an object
+ * - INDEX_OUT_OF_BOUNDS if an array index is larger than an array length
+ * - INCORRECT_TYPE if a non-integer is used to access an array
+ * - INVALID_JSON_POINTER if the JSON pointer is invalid and cannot be parsed
+ */
+ inline element_result operator[](std::string_view json_pointer) const noexcept;
+
+ /**
+ * Get the value associated with the given JSON pointer.
+ *
+ * document doc = document::parse(R"({ "foo": { "a": [ 10, 20, 30 ] }})");
+ * doc["/foo/a/1"] == 20
+ * doc["/"]["foo"]["a"].at(1) == 20
+ * doc[""]["foo"]["a"].at(1) == 20
+ *
+ * @return The value associated with the given JSON pointer, or:
+ * - NO_SUCH_FIELD if a field does not exist in an object
+ * - INDEX_OUT_OF_BOUNDS if an array index is larger than an array length
+ * - INCORRECT_TYPE if a non-integer is used to access an array
+ * - INVALID_JSON_POINTER if the JSON pointer is invalid and cannot be parsed
+ */
+ inline element_result operator[](const char *json_pointer) const noexcept;
+
+ /**
+ * Get the value associated with the given JSON pointer.
+ *
+ * document doc = document::parse(R"({ "foo": { "a": [ 10, 20, 30 ] }})");
+ * doc.at("/foo/a/1") == 20
+ * doc.at("/")["foo"]["a"].at(1) == 20
+ * doc.at("")["foo"]["a"].at(1) == 20
+ *
+ * @return The value associated with the given JSON pointer, or:
+ * - NO_SUCH_FIELD if a field does not exist in an object
+ * - INDEX_OUT_OF_BOUNDS if an array index is larger than an array length
+ * - INCORRECT_TYPE if a non-integer is used to access an array
+ * - INVALID_JSON_POINTER if the JSON pointer is invalid and cannot be parsed
+ */
+ inline element_result at(std::string_view json_pointer) const noexcept;
+
+ /**
+ * Get the value at the given index.
+ *
+ * @return The value at the given index, or:
+ * - INDEX_OUT_OF_BOUNDS if the array index is larger than an array length
+ */
+ inline element_result at(size_t index) const noexcept;
+
+ /**
+ * Get the value associated with the given key.
+ *
+ * The key will be matched against **unescaped** JSON:
+ *
+ * document::parse(R"({ "a\n": 1 })")["a\n"].as_uint64_t().value == 1
+ * document::parse(R"({ "a\n": 1 })")["a\\n"].as_uint64_t().error == NO_SUCH_FIELD
+ *
+ * @return The value associated with this field, or:
+ * - NO_SUCH_FIELD if the field does not exist in the object
+ */
+ inline element_result at_key(std::string_view s) const noexcept;
+
+ /**
+ * Get the value associated with the given key.
+ *
+ * Note: The key will be matched against **unescaped** JSON:
+ *
+ * document::parse(R"({ "a\n": 1 })")["a\n"].as_uint64_t().value == 1
+ * document::parse(R"({ "a\n": 1 })")["a\\n"].as_uint64_t().error == NO_SUCH_FIELD
+ *
+ * @return The value associated with this field, or:
+ * - NO_SUCH_FIELD if the field does not exist in the object
+ */
+ inline element_result at_key(const char *s) const noexcept;
+
std::unique_ptr tape;
std::unique_ptr string_buf;// should be at least byte_capacity
@@ -269,18 +324,61 @@ public:
inline array_result as_array() const noexcept;
/**
- * Get the value associated with the given key.
+ * Get the value associated with the given JSON pointer.
*
- * The key will be matched against **unescaped** JSON:
+ * document doc = document::parse(R"({ "foo": { "a": [ 10, 20, 30 ] }})");
+ * doc["/foo/a/1"] == 20
+ * doc["/"]["foo"]["a"].at(1) == 20
+ * doc[""]["foo"]["a"].at(1) == 20
*
- * document::parse(R"({ "a\n": 1 })")["a\n"].as_uint64_t().value == 1
- * document::parse(R"({ "a\n": 1 })")["a\\n"].as_uint64_t().error == NO_SUCH_FIELD
- *
- * @return The value associated with this field, or:
- * - NO_SUCH_FIELD if the field does not exist in the object
- * - UNEXPECTED_TYPE if the document is not an object
+ * @return The value associated with the given JSON pointer, or:
+ * - NO_SUCH_FIELD if a field does not exist in an object
+ * - INDEX_OUT_OF_BOUNDS if an array index is larger than an array length
+ * - INCORRECT_TYPE if a non-integer is used to access an array
+ * - INVALID_JSON_POINTER if the JSON pointer is invalid and cannot be parsed
*/
- inline element_result operator[](const std::string_view &key) const noexcept;
+ inline element_result operator[](std::string_view json_pointer) const noexcept;
+
+ /**
+ * Get the value associated with the given JSON pointer.
+ *
+ * document doc = document::parse(R"({ "foo": { "a": [ 10, 20, 30 ] }})");
+ * doc["/foo/a/1"] == 20
+ * doc["/"]["foo"]["a"].at(1) == 20
+ * doc[""]["foo"]["a"].at(1) == 20
+ *
+ * @return The value associated with the given JSON pointer, or:
+ * - NO_SUCH_FIELD if a field does not exist in an object
+ * - INDEX_OUT_OF_BOUNDS if an array index is larger than an array length
+ * - INCORRECT_TYPE if a non-integer is used to access an array
+ * - INVALID_JSON_POINTER if the JSON pointer is invalid and cannot be parsed
+ */
+ inline element_result operator[](const char *json_pointer) const noexcept;
+
+ /**
+ * Get the value associated with the given JSON pointer.
+ *
+ * document doc = document::parse(R"({ "foo": { "a": [ 10, 20, 30 ] }})");
+ * doc.at("/foo/a/1") == 20
+ * doc.at("/")["foo"]["a"].at(1) == 20
+ * doc.at("")["foo"]["a"].at(1) == 20
+ *
+ * @return The value associated with the given JSON pointer, or:
+ * - NO_SUCH_FIELD if a field does not exist in an object
+ * - INDEX_OUT_OF_BOUNDS if an array index is larger than an array length
+ * - INCORRECT_TYPE if a non-integer is used to access an array
+ * - INVALID_JSON_POINTER if the JSON pointer is invalid and cannot be parsed
+ */
+ inline element_result at(std::string_view json_pointer) const noexcept;
+
+ /**
+ * Get the value at the given index.
+ *
+ * @return The value at the given index, or:
+ * - INDEX_OUT_OF_BOUNDS if the array index is larger than an array length
+ */
+ inline element_result at(size_t index) const noexcept;
+
/**
* Get the value associated with the given key.
*
@@ -291,9 +389,21 @@ public:
*
* @return The value associated with this field, or:
* - NO_SUCH_FIELD if the field does not exist in the object
- * - UNEXPECTED_TYPE if the document is not an object
*/
- inline element_result operator[](const char *key) const noexcept;
+ inline element_result at_key(std::string_view s) const noexcept;
+
+ /**
+ * Get the value associated with the given key.
+ *
+ * Note: The key will be matched against **unescaped** JSON:
+ *
+ * document::parse(R"({ "a\n": 1 })")["a\n"].as_uint64_t().value == 1
+ * document::parse(R"({ "a\n": 1 })")["a\\n"].as_uint64_t().error == NO_SUCH_FIELD
+ *
+ * @return The value associated with this field, or:
+ * - NO_SUCH_FIELD if the field does not exist in the object
+ */
+ inline element_result at_key(const char *s) const noexcept;
~doc_move_result() noexcept=default;
doc_move_result(document &&doc, error_code error) noexcept;
@@ -352,18 +462,60 @@ public:
inline array_result as_array() const noexcept;
/**
- * Get the value associated with the given key.
+ * Get the value associated with the given JSON pointer.
*
- * The key will be matched against **unescaped** JSON:
+ * document doc = document::parse(R"({ "foo": { "a": [ 10, 20, 30 ] }})");
+ * doc["/foo/a/1"] == 20
+ * doc["/"]["foo"]["a"].at(1) == 20
+ * doc[""]["foo"]["a"].at(1) == 20
*
- * document::parse(R"({ "a\n": 1 })")["a\n"].as_uint64_t().value == 1
- * document::parse(R"({ "a\n": 1 })")["a\\n"].as_uint64_t().error == NO_SUCH_FIELD
- *
- * @return The value associated with this field, or:
- * - NO_SUCH_FIELD if the field does not exist in the object
- * - UNEXPECTED_TYPE if the document is not an object
+ * @return The value associated with the given JSON pointer, or:
+ * - NO_SUCH_FIELD if a field does not exist in an object
+ * - INDEX_OUT_OF_BOUNDS if an array index is larger than an array length
+ * - INCORRECT_TYPE if a non-integer is used to access an array
+ * - INVALID_JSON_POINTER if the JSON pointer is invalid and cannot be parsed
*/
- inline element_result operator[](const std::string_view &key) const noexcept;
+ inline element_result operator[](std::string_view json_pointer) const noexcept;
+
+ /**
+ * Get the value associated with the given JSON pointer.
+ *
+ * document doc = document::parse(R"({ "foo": { "a": [ 10, 20, 30 ] }})");
+ * doc["/foo/a/1"] == 20
+ * doc["/"]["foo"]["a"].at(1) == 20
+ * doc[""]["foo"]["a"].at(1) == 20
+ *
+ * @return The value associated with the given JSON pointer, or:
+ * - NO_SUCH_FIELD if a field does not exist in an object
+ * - INDEX_OUT_OF_BOUNDS if an array index is larger than an array length
+ * - INCORRECT_TYPE if a non-integer is used to access an array
+ * - INVALID_JSON_POINTER if the JSON pointer is invalid and cannot be parsed
+ */
+ inline element_result operator[](const char *json_pointer) const noexcept;
+
+ /**
+ * Get the value associated with the given JSON pointer.
+ *
+ * document doc = document::parse(R"({ "foo": { "a": [ 10, 20, 30 ] }})");
+ * doc.at("/foo/a/1") == 20
+ * doc.at("/")["foo"]["a"].at(1) == 20
+ * doc.at("")["foo"]["a"].at(1) == 20
+ *
+ * @return The value associated with the given JSON pointer, or:
+ * - NO_SUCH_FIELD if a field does not exist in an object
+ * - INDEX_OUT_OF_BOUNDS if an array index is larger than an array length
+ * - INCORRECT_TYPE if a non-integer is used to access an array
+ * - INVALID_JSON_POINTER if the JSON pointer is invalid and cannot be parsed
+ */
+ inline element_result at(std::string_view json_pointer) const noexcept;
+
+ /**
+ * Get the value at the given index.
+ *
+ * @return The value at the given index, or:
+ * - INDEX_OUT_OF_BOUNDS if the array index is larger than an array length
+ */
+ inline element_result at(size_t index) const noexcept;
/**
* Get the value associated with the given key.
@@ -375,9 +527,21 @@ public:
*
* @return The value associated with this field, or:
* - NO_SUCH_FIELD if the field does not exist in the object
- * - UNEXPECTED_TYPE if the document is not an object
*/
- inline element_result operator[](const char *key) const noexcept;
+ inline element_result at_key(std::string_view s) const noexcept;
+
+ /**
+ * Get the value associated with the given key.
+ *
+ * Note: The key will be matched against **unescaped** JSON:
+ *
+ * document::parse(R"({ "a\n": 1 })")["a\n"].as_uint64_t().value == 1
+ * document::parse(R"({ "a\n": 1 })")["a\\n"].as_uint64_t().error == NO_SUCH_FIELD
+ *
+ * @return The value associated with this field, or:
+ * - NO_SUCH_FIELD if the field does not exist in the object
+ */
+ inline element_result at_key(const char *s) const noexcept;
~doc_result()=default;
doc_result(document &doc, error_code error) noexcept;
@@ -599,6 +763,62 @@ public:
inline operator document::object() const noexcept(false);
#endif // SIMDJSON_EXCEPTIONS
+ /**
+ * Get the value associated with the given JSON pointer.
+ *
+ * document doc = document::parse(R"({ "foo": { "a": [ 10, 20, 30 ] }})");
+ * doc["/foo/a/1"] == 20
+ * doc["/"]["foo"]["a"].at(1) == 20
+ * doc[""]["foo"]["a"].at(1) == 20
+ *
+ * @return The value associated with the given JSON pointer, or:
+ * - NO_SUCH_FIELD if a field does not exist in an object
+ * - INDEX_OUT_OF_BOUNDS if an array index is larger than an array length
+ * - INCORRECT_TYPE if a non-integer is used to access an array
+ * - INVALID_JSON_POINTER if the JSON pointer is invalid and cannot be parsed
+ */
+ inline element_result operator[](std::string_view json_pointer) const noexcept;
+
+ /**
+ * Get the value associated with the given JSON pointer.
+ *
+ * document doc = document::parse(R"({ "foo": { "a": [ 10, 20, 30 ] }})");
+ * doc["/foo/a/1"] == 20
+ * doc["/"]["foo"]["a"].at(1) == 20
+ * doc[""]["foo"]["a"].at(1) == 20
+ *
+ * @return The value associated with the given JSON pointer, or:
+ * - NO_SUCH_FIELD if a field does not exist in an object
+ * - INDEX_OUT_OF_BOUNDS if an array index is larger than an array length
+ * - INCORRECT_TYPE if a non-integer is used to access an array
+ * - INVALID_JSON_POINTER if the JSON pointer is invalid and cannot be parsed
+ */
+ inline element_result operator[](const char *json_pointer) const noexcept;
+
+ /**
+ * Get the value associated with the given JSON pointer.
+ *
+ * document doc = document::parse(R"({ "foo": { "a": [ 10, 20, 30 ] }})");
+ * doc.at("/foo/a/1") == 20
+ * doc.at("/")["foo"]["a"].at(1) == 20
+ * doc.at("")["foo"]["a"].at(1) == 20
+ *
+ * @return The value associated with the given JSON pointer, or:
+ * - NO_SUCH_FIELD if a field does not exist in an object
+ * - INDEX_OUT_OF_BOUNDS if an array index is larger than an array length
+ * - INCORRECT_TYPE if a non-integer is used to access an array
+ * - INVALID_JSON_POINTER if the JSON pointer is invalid and cannot be parsed
+ */
+ inline element_result at(std::string_view json_pointer) const noexcept;
+
+ /**
+ * Get the value at the given index.
+ *
+ * @return The value at the given index, or:
+ * - INDEX_OUT_OF_BOUNDS if the array index is larger than an array length
+ */
+ inline element_result at(size_t index) const noexcept;
+
/**
* Get the value associated with the given key.
*
@@ -609,9 +829,8 @@ public:
*
* @return The value associated with this field, or:
* - NO_SUCH_FIELD if the field does not exist in the object
- * - UNEXPECTED_TYPE if the document is not an object
*/
- inline element_result operator[](const std::string_view &s) const noexcept;
+ inline element_result at_key(std::string_view s) const noexcept;
/**
* Get the value associated with the given key.
@@ -623,9 +842,8 @@ public:
*
* @return The value associated with this field, or:
* - NO_SUCH_FIELD if the field does not exist in the object
- * - UNEXPECTED_TYPE if the document is not an object
*/
- inline element_result operator[](const char *s) const noexcept;
+ inline element_result at_key(const char *s) const noexcept;
private:
really_inline element(const document *_doc, size_t _json_index) noexcept;
@@ -679,6 +897,59 @@ public:
*/
inline iterator end() const noexcept;
+ /**
+ * Get the value associated with the given JSON pointer.
+ *
+ * document::array a = document::parse(R"([ { "foo": { "a": [ 10, 20, 30 ] }} ])");
+ * a.["0/foo/a/1"] == 20
+ * a.["0"]["foo"]["a"].at(1) == 20
+ *
+ * @return The value associated with the given JSON pointer, or:
+ * - NO_SUCH_FIELD if a field does not exist in an object
+ * - INDEX_OUT_OF_BOUNDS if an array index is larger than an array length
+ * - INCORRECT_TYPE if a non-integer is used to access an array
+ * - INVALID_JSON_POINTER if the JSON pointer is invalid and cannot be parsed
+ */
+ inline element_result operator[](std::string_view json_pointer) const noexcept;
+
+ /**
+ * Get the value associated with the given JSON pointer.
+ *
+ * document::array a = document::parse(R"([ { "foo": { "a": [ 10, 20, 30 ] }} ])");
+ * a.["0/foo/a/1"] == 20
+ * a.["0"]["foo"]["a"].at(1) == 20
+ *
+ * @return The value associated with the given JSON pointer, or:
+ * - NO_SUCH_FIELD if a field does not exist in an object
+ * - INDEX_OUT_OF_BOUNDS if an array index is larger than an array length
+ * - INCORRECT_TYPE if a non-integer is used to access an array
+ * - INVALID_JSON_POINTER if the JSON pointer is invalid and cannot be parsed
+ */
+ inline element_result operator[](const char *json_pointer) const noexcept;
+
+ /**
+ * Get the value associated with the given JSON pointer.
+ *
+ * document::array a = document::parse(R"([ { "foo": { "a": [ 10, 20, 30 ] }} ])");
+ * a.at("0/foo/a/1") == 20
+ * a.at("0")["foo"]["a"].at(1) == 20
+ *
+ * @return The value associated with the given JSON pointer, or:
+ * - NO_SUCH_FIELD if a field does not exist in an object
+ * - INDEX_OUT_OF_BOUNDS if an array index is larger than an array length
+ * - INCORRECT_TYPE if a non-integer is used to access an array
+ * - INVALID_JSON_POINTER if the JSON pointer is invalid and cannot be parsed
+ */
+ inline element_result at(std::string_view json_pointer) const noexcept;
+
+ /**
+ * Get the value at the given index.
+ *
+ * @return The value at the given index, or:
+ * - INDEX_OUT_OF_BOUNDS if the array index is larger than an array length
+ */
+ inline element_result at(size_t index) const noexcept;
+
private:
really_inline array(const document *_doc, size_t _json_index) noexcept;
friend class document::element;
@@ -743,6 +1014,51 @@ public:
*/
inline iterator end() const noexcept;
+ /**
+ * Get the value associated with the given JSON pointer.
+ *
+ * document::object obj = document::parse(R"({ "foo": { "a": [ 10, 20, 30 ] }})");
+ * obj["foo/a/1"] == 20
+ * obj["foo"]["a"].at(1) == 20
+ *
+ * @return The value associated with the given JSON pointer, or:
+ * - NO_SUCH_FIELD if a field does not exist in an object
+ * - INDEX_OUT_OF_BOUNDS if an array index is larger than an array length
+ * - INCORRECT_TYPE if a non-integer is used to access an array
+ * - INVALID_JSON_POINTER if the JSON pointer is invalid and cannot be parsed
+ */
+ inline element_result operator[](std::string_view json_pointer) const noexcept;
+
+ /**
+ * Get the value associated with the given JSON pointer.
+ *
+ * document::object obj = document::parse(R"({ "foo": { "a": [ 10, 20, 30 ] }})");
+ * obj["foo/a/1"] == 20
+ * obj["foo"]["a"].at(1) == 20
+ *
+ * @return The value associated with the given JSON pointer, or:
+ * - NO_SUCH_FIELD if a field does not exist in an object
+ * - INDEX_OUT_OF_BOUNDS if an array index is larger than an array length
+ * - INCORRECT_TYPE if a non-integer is used to access an array
+ * - INVALID_JSON_POINTER if the JSON pointer is invalid and cannot be parsed
+ */
+ inline element_result operator[](const char *json_pointer) const noexcept;
+
+ /**
+ * Get the value associated with the given JSON pointer.
+ *
+ * document::object obj = document::parse(R"({ "foo": { "a": [ 10, 20, 30 ] }})");
+ * obj.at("foo/a/1") == 20
+ * obj.at("foo")["a"].at(1) == 20
+ *
+ * @return The value associated with the given JSON pointer, or:
+ * - NO_SUCH_FIELD if a field does not exist in an object
+ * - INDEX_OUT_OF_BOUNDS if an array index is larger than an array length
+ * - INCORRECT_TYPE if a non-integer is used to access an array
+ * - INVALID_JSON_POINTER if the JSON pointer is invalid and cannot be parsed
+ */
+ inline element_result at(std::string_view json_pointer) const noexcept;
+
/**
* Get the value associated with the given key.
*
@@ -754,7 +1070,7 @@ public:
* @return The value associated with this field, or:
* - NO_SUCH_FIELD if the field does not exist in the object
*/
- inline element_result operator[](const std::string_view &s) const noexcept;
+ inline element_result at_key(std::string_view s) const noexcept;
/**
* Get the value associated with the given key.
@@ -767,7 +1083,7 @@ public:
* @return The value associated with this field, or:
* - NO_SUCH_FIELD if the field does not exist in the object
*/
- inline element_result operator[](const char *s) const noexcept;
+ inline element_result at_key(const char *s) const noexcept;
private:
really_inline object(const document *_doc, size_t _json_index) noexcept;
@@ -808,8 +1124,12 @@ public:
inline array_result as_array() const noexcept;
inline object_result as_object() const noexcept;
- inline element_result operator[](const std::string_view &s) const noexcept;
- inline element_result operator[](const char *s) const noexcept;
+ inline element_result operator[](std::string_view json_pointer) const noexcept;
+ inline element_result operator[](const char *json_pointer) const noexcept;
+ inline element_result at(std::string_view json_pointer) const noexcept;
+ inline element_result at(size_t index) const noexcept;
+ inline element_result at_key(std::string_view key) const noexcept;
+ inline element_result at_key(const char *key) const noexcept;
#if SIMDJSON_EXCEPTIONS
inline operator bool() const noexcept(false);
@@ -829,6 +1149,11 @@ public:
really_inline array_result(array value) noexcept;
really_inline array_result(error_code error) noexcept;
+ inline element_result operator[](std::string_view json_pointer) const noexcept;
+ inline element_result operator[](const char *json_pointer) const noexcept;
+ inline element_result at(std::string_view json_pointer) const noexcept;
+ inline element_result at(size_t index) const noexcept;
+
#if SIMDJSON_EXCEPTIONS
inline array::iterator begin() const noexcept(false);
inline array::iterator end() const noexcept(false);
@@ -841,8 +1166,11 @@ public:
really_inline object_result(object value) noexcept;
really_inline object_result(error_code error) noexcept;
- inline element_result operator[](const std::string_view &s) const noexcept;
- inline element_result operator[](const char *s) const noexcept;
+ inline element_result operator[](std::string_view json_pointer) const noexcept;
+ inline element_result operator[](const char *json_pointer) const noexcept;
+ inline element_result at(std::string_view json_pointer) const noexcept;
+ inline element_result at_key(std::string_view key) const noexcept;
+ inline element_result at_key(const char *key) const noexcept;
#if SIMDJSON_EXCEPTIONS
inline object::iterator begin() const noexcept(false);
diff --git a/include/simdjson/error.h b/include/simdjson/error.h
index d9163f9c9..b8a047e9d 100644
--- a/include/simdjson/error.h
+++ b/include/simdjson/error.h
@@ -30,8 +30,11 @@ enum error_code {
UNSUPPORTED_ARCHITECTURE, ///< unsupported architecture
INCORRECT_TYPE, ///< JSON element has a different type than user expected
NUMBER_OUT_OF_RANGE, ///< JSON number does not fit in 64 bits
+ INDEX_OUT_OF_BOUNDS, ///< JSON array index too large
NO_SUCH_FIELD, ///< JSON field not found in object
IO_ERROR, ///< Error reading a file
+ INVALID_JSON_POINTER, ///< Invalid JSON pointer reference
+ INVALID_URI_FRAGMENT, ///< Invalid URI fragment
UNEXPECTED_ERROR, ///< indicative of a bug in simdjson
/** @private Number of error codes */
NUM_ERROR_CODES
@@ -77,6 +80,7 @@ private:
*/
template
struct simdjson_result : public std::pair {
+
/**
* Move the value and the error to the provided variables.
*/
diff --git a/include/simdjson/inline/document.h b/include/simdjson/inline/document.h
index f3118feba..b56080e75 100644
--- a/include/simdjson/inline/document.h
+++ b/include/simdjson/inline/document.h
@@ -55,13 +55,28 @@ inline document::object_result document::element_result::as_object() const noexc
return first.as_object();
}
-inline document::element_result document::element_result::operator[](const std::string_view &key) const noexcept {
+inline document::element_result document::element_result::operator[](std::string_view key) const noexcept {
if (error()) { return *this; }
return first[key];
}
-inline document::element_result document::element_result::operator[](const char *key) const noexcept {
+inline document::element_result document::element_result::operator[](const char *json_pointer) const noexcept {
+ return (*this)[std::string_view(json_pointer)];
+}
+inline document::element_result document::element_result::at(std::string_view key) const noexcept {
if (error()) { return *this; }
- return first[key];
+ return first.at(key);
+}
+inline document::element_result document::element_result::at(size_t index) const noexcept {
+ if (error()) { return *this; }
+ return first.at(index);
+}
+inline document::element_result document::element_result::at_key(std::string_view key) const noexcept {
+ if (error()) { return *this; }
+ return first.at_key(key);
+}
+inline document::element_result document::element_result::at_key(const char *key) const noexcept {
+ if (error()) { return *this; }
+ return first.at_key(key);
}
#if SIMDJSON_EXCEPTIONS
@@ -112,19 +127,46 @@ inline document::array::iterator document::array_result::end() const noexcept(fa
#endif // SIMDJSON_EXCEPTIONS
+inline document::element_result document::array_result::operator[](std::string_view json_pointer) const noexcept {
+ if (error()) { return error(); }
+ return first.at(json_pointer);
+}
+inline document::element_result document::array_result::operator[](const char *json_pointer) const noexcept {
+ return (*this)[std::string_view(json_pointer)];
+}
+inline document::element_result document::array_result::at(std::string_view json_pointer) const noexcept {
+ if (error()) { return error(); }
+ return first.at(json_pointer);
+}
+inline document::element_result document::array_result::at(size_t index) const noexcept {
+ if (error()) { return error(); }
+ return first.at(index);
+}
+
//
// object_result inline implementation
//
really_inline document::object_result::object_result(object value) noexcept : simdjson_result