diff --git a/doc/mkdocs/docs/api/json_pointer/back.md b/doc/mkdocs/docs/api/json_pointer/back.md
index 2b267bc588..240bc6e1e7 100644
--- a/doc/mkdocs/docs/api/json_pointer/back.md
+++ b/doc/mkdocs/docs/api/json_pointer/back.md
@@ -1,7 +1,7 @@
# nlohmann::json_pointer::back
```cpp
-const std::string& back() const;
+const string_t& back() const;
```
Return last reference token.
@@ -36,4 +36,5 @@ Constant.
## Version history
-Added in version 3.6.0.
+- Added in version 3.6.0.
+- Changed return type to `string_t` in version 3.11.0.
diff --git a/doc/mkdocs/docs/api/json_pointer/index.md b/doc/mkdocs/docs/api/json_pointer/index.md
index d95ed0ffb3..3504c9ff78 100644
--- a/doc/mkdocs/docs/api/json_pointer/index.md
+++ b/doc/mkdocs/docs/api/json_pointer/index.md
@@ -1,7 +1,7 @@
# nlohmann::json_pointer
```cpp
-template
+template
class json_pointer;
```
@@ -11,14 +11,18 @@ are the base for JSON patches.
## Template parameters
-`BasicJsonType`
-: a specialization of [`basic_json`](../basic_json/index.md)
+`RefStringType`
+: the string type used for the reference tokens making up the JSON pointer
+
+## Notes
+
+For backwards compatibility `RefStringType` may also be a specialization of [`basic_json`](../basic_json/index.md) in which case `string_t` will be deduced as [`basic_json::string_t`](../basic_json/string_t.md). This feature is deprecated and may be removed in a future major version.
## Member functions
- [(constructor)](json_pointer.md)
- [**to_string**](to_string.md) - return a string representation of the JSON pointer
-- [**operator std::string**](operator_string.md) - return a string representation of the JSON pointer
+- [**operator string_t**](operator_string.md) - return a string representation of the JSON pointer
- [**operator/=**](operator_slasheq.md) - append to the end of the JSON pointer
- [**operator/**](operator_slash.md) - create JSON Pointer by appending
- [**parent_pointer**](parent_pointer.md) - returns the parent of this JSON pointer
@@ -27,6 +31,10 @@ are the base for JSON patches.
- [**push_back**](push_back.md) - append an unescaped token at the end of the pointer
- [**empty**](empty.md) - return whether pointer points to the root document
+## Member types
+
+- [**string_t**](string_t.md) - the string type used for the reference tokens
+
## See also
- [operator""_json_pointer](../basic_json/operator_literal_json_pointer.md) - user-defined string literal for JSON pointers
@@ -34,4 +42,5 @@ are the base for JSON patches.
## Version history
-Added in version 2.0.0.
+- Added in version 2.0.0.
+- Changed template parameter from `basic_json` to string type in version 3.11.0.
diff --git a/doc/mkdocs/docs/api/json_pointer/json_pointer.md b/doc/mkdocs/docs/api/json_pointer/json_pointer.md
index 1e68a28f32..5e7057fc9d 100644
--- a/doc/mkdocs/docs/api/json_pointer/json_pointer.md
+++ b/doc/mkdocs/docs/api/json_pointer/json_pointer.md
@@ -1,7 +1,7 @@
# nlohmann::json_pointer::json_pointer
```cpp
-explicit json_pointer(const std::string& s = "");
+explicit json_pointer(const string_t& s = "");
```
Create a JSON pointer according to the syntax described in
@@ -37,4 +37,5 @@ Create a JSON pointer according to the syntax described in
## Version history
-Added in version 2.0.0.
+- Added in version 2.0.0.
+- Changed type of `s` to `string_t` in version 3.11.0.
diff --git a/doc/mkdocs/docs/api/json_pointer/operator_slash.md b/doc/mkdocs/docs/api/json_pointer/operator_slash.md
index c928754353..ed77b504bd 100644
--- a/doc/mkdocs/docs/api/json_pointer/operator_slash.md
+++ b/doc/mkdocs/docs/api/json_pointer/operator_slash.md
@@ -5,7 +5,7 @@
json_pointer operator/(const json_pointer& lhs, const json_pointer& rhs);
// (2)
-json_pointer operator/(const json_pointer& lhs, std::string token);
+json_pointer operator/(const json_pointer& lhs, string_t token);
// (3)
json_pointer operator/(const json_pointer& lhs, std::size_t array_idx);
@@ -60,5 +60,5 @@ json_pointer operator/(const json_pointer& lhs, std::size_t array_idx);
## Version history
1. Added in version 3.6.0.
-2. Added in version 3.6.0.
+2. Added in version 3.6.0. Changed type of `token` to `string_t` in version 3.11.0.
3. Added in version 3.6.0.
diff --git a/doc/mkdocs/docs/api/json_pointer/operator_slasheq.md b/doc/mkdocs/docs/api/json_pointer/operator_slasheq.md
index eb6c308610..3518557d50 100644
--- a/doc/mkdocs/docs/api/json_pointer/operator_slasheq.md
+++ b/doc/mkdocs/docs/api/json_pointer/operator_slasheq.md
@@ -5,7 +5,7 @@
json_pointer& operator/=(const json_pointer& ptr);
// (2)
-json_pointer& operator/=(std::string token);
+json_pointer& operator/=(string_t token);
// (3)
json_pointer& operator/=(std::size_t array_idx)
@@ -57,5 +57,5 @@ json_pointer& operator/=(std::size_t array_idx)
## Version history
1. Added in version 3.6.0.
-2. Added in version 3.6.0.
+2. Added in version 3.6.0. Changed type of `token` to `string_t` in version 3.11.0.
3. Added in version 3.6.0.
diff --git a/doc/mkdocs/docs/api/json_pointer/operator_string.md b/doc/mkdocs/docs/api/json_pointer/operator_string.md
index 56d8eebeb2..836728c18c 100644
--- a/doc/mkdocs/docs/api/json_pointer/operator_string.md
+++ b/doc/mkdocs/docs/api/json_pointer/operator_string.md
@@ -1,7 +1,7 @@
-# nlohmann::json_pointer::operator std::string
+# nlohmann::json_pointer::operator string_t
```cpp
-operator std::string() const
+operator string_t() const
```
Return a string representation of the JSON pointer.
@@ -13,7 +13,7 @@ A string representation of the JSON pointer
## Possible implementation
```cpp
-operator std::string() const
+operator string_t() const
{
return to_string();
}
@@ -21,4 +21,5 @@ operator std::string() const
## Version history
-Since version 2.0.0.
+- Since version 2.0.0.
+- Changed type to `string_t` in version 3.11.0.
diff --git a/doc/mkdocs/docs/api/json_pointer/push_back.md b/doc/mkdocs/docs/api/json_pointer/push_back.md
index 3ebcdbc5cb..c1c19cb8d1 100644
--- a/doc/mkdocs/docs/api/json_pointer/push_back.md
+++ b/doc/mkdocs/docs/api/json_pointer/push_back.md
@@ -1,9 +1,9 @@
# nlohmann::json_pointer::push_back
```cpp
-void push_back(const std::string& token);
+void push_back(const string_t& token);
-void push_back(std::string&& token);
+void push_back(string_t&& token);
```
Append an unescaped token at the end of the reference pointer.
@@ -35,4 +35,5 @@ Amortized constant.
## Version history
-Added in version 3.6.0.
+- Added in version 3.6.0.
+- Changed type of `token` to `string_t` in version 3.11.0.
diff --git a/doc/mkdocs/docs/api/json_pointer/string_t.md b/doc/mkdocs/docs/api/json_pointer/string_t.md
new file mode 100644
index 0000000000..f18b51b812
--- /dev/null
+++ b/doc/mkdocs/docs/api/json_pointer/string_t.md
@@ -0,0 +1,12 @@
+# nlohmann::json_pointer::string_t
+```cpp
+using string_t = RefStringType;
+```
+
+The string type used for the reference tokens making up the JSON pointer.
+
+See [`basic_json::string_t`](../basic_json/string_t.md) for more information.
+
+## Version history
+
+- Added in version 3.11.0.
diff --git a/doc/mkdocs/docs/api/json_pointer/to_string.md b/doc/mkdocs/docs/api/json_pointer/to_string.md
index 9287436e3e..fae3abe5fc 100644
--- a/doc/mkdocs/docs/api/json_pointer/to_string.md
+++ b/doc/mkdocs/docs/api/json_pointer/to_string.md
@@ -1,7 +1,7 @@
# nlohmann::json_pointer::to_string
```cpp
-std::string to_string() const;
+string_t to_string() const;
```
Return a string representation of the JSON pointer.
@@ -36,4 +36,5 @@ ptr == json_pointer(ptr.to_string());
## Version history
-Since version 2.0.0.
+- Since version 2.0.0.
+- Changed return type to `string_t` in version 3.11.0.
diff --git a/doc/mkdocs/mkdocs.yml b/doc/mkdocs/mkdocs.yml
index 618f7344b3..ddd55e5c95 100644
--- a/doc/mkdocs/mkdocs.yml
+++ b/doc/mkdocs/mkdocs.yml
@@ -211,6 +211,7 @@ nav:
- 'parent_pointer': api/json_pointer/parent_pointer.md
- 'pop_back': api/json_pointer/pop_back.md
- 'push_back': api/json_pointer/push_back.md
+ - 'string_t': api/json_pointer/string_t.md
- 'to_string': api/json_pointer/to_string.md
- json_sax:
- 'Overview': api/json_sax/index.md
diff --git a/include/nlohmann/detail/conversions/from_json.hpp b/include/nlohmann/detail/conversions/from_json.hpp
index cc06f198b4..079baa723d 100644
--- a/include/nlohmann/detail/conversions/from_json.hpp
+++ b/include/nlohmann/detail/conversions/from_json.hpp
@@ -17,6 +17,7 @@
#include
#include
#include
+#include
#include
#if JSON_HAS_EXPERIMENTAL_FILESYSTEM
@@ -42,7 +43,7 @@ void from_json(const BasicJsonType& j, typename std::nullptr_t& n)
{
if (JSON_HEDLEY_UNLIKELY(!j.is_null()))
{
- JSON_THROW(type_error::create(302, "type must be null, but is " + std::string(j.type_name()), j));
+ JSON_THROW(type_error::create(302, concat("type must be null, but is ", j.type_name()), &j));
}
n = nullptr;
}
@@ -80,7 +81,7 @@ void get_arithmetic_value(const BasicJsonType& j, ArithmeticType& val)
case value_t::binary:
case value_t::discarded:
default:
- JSON_THROW(type_error::create(302, "type must be number, but is " + std::string(j.type_name()), j));
+ JSON_THROW(type_error::create(302, concat("type must be number, but is ", j.type_name()), &j));
}
}
@@ -89,7 +90,7 @@ void from_json(const BasicJsonType& j, typename BasicJsonType::boolean_t& b)
{
if (JSON_HEDLEY_UNLIKELY(!j.is_boolean()))
{
- JSON_THROW(type_error::create(302, "type must be boolean, but is " + std::string(j.type_name()), j));
+ JSON_THROW(type_error::create(302, concat("type must be boolean, but is ", j.type_name()), &j));
}
b = *j.template get_ptr();
}
@@ -99,7 +100,7 @@ void from_json(const BasicJsonType& j, typename BasicJsonType::string_t& s)
{
if (JSON_HEDLEY_UNLIKELY(!j.is_string()))
{
- JSON_THROW(type_error::create(302, "type must be string, but is " + std::string(j.type_name()), j));
+ JSON_THROW(type_error::create(302, concat("type must be string, but is ", j.type_name()), &j));
}
s = *j.template get_ptr();
}
@@ -114,7 +115,7 @@ void from_json(const BasicJsonType& j, StringType& s)
{
if (JSON_HEDLEY_UNLIKELY(!j.is_string()))
{
- JSON_THROW(type_error::create(302, "type must be string, but is " + std::string(j.type_name()), j));
+ JSON_THROW(type_error::create(302, concat("type must be string, but is ", j.type_name()), &j));
}
s = *j.template get_ptr();
@@ -154,7 +155,7 @@ void from_json(const BasicJsonType& j, std::forward_list& l)
{
if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
{
- JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name()), j));
+ JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
}
l.clear();
std::transform(j.rbegin(), j.rend(),
@@ -171,7 +172,7 @@ void from_json(const BasicJsonType& j, std::valarray& l)
{
if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
{
- JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name()), j));
+ JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
}
l.resize(j.size());
std::transform(j.begin(), j.end(), std::begin(l),
@@ -268,7 +269,7 @@ void())
{
if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
{
- JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name()), j));
+ JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
}
from_json_array_impl(j, arr, priority_tag<3> {});
@@ -287,7 +288,7 @@ auto from_json(BasicJsonType&& j, identity_tag> tag)
{
if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
{
- JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name()), j));
+ JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
}
return from_json_inplace_array_impl(std::forward(j), tag, make_index_sequence {});
@@ -298,7 +299,7 @@ void from_json(const BasicJsonType& j, typename BasicJsonType::binary_t& bin)
{
if (JSON_HEDLEY_UNLIKELY(!j.is_binary()))
{
- JSON_THROW(type_error::create(302, "type must be binary, but is " + std::string(j.type_name()), j));
+ JSON_THROW(type_error::create(302, concat("type must be binary, but is ", j.type_name()), &j));
}
bin = *j.template get_ptr();
@@ -310,7 +311,7 @@ void from_json(const BasicJsonType& j, ConstructibleObjectType& obj)
{
if (JSON_HEDLEY_UNLIKELY(!j.is_object()))
{
- JSON_THROW(type_error::create(302, "type must be object, but is " + std::string(j.type_name()), j));
+ JSON_THROW(type_error::create(302, concat("type must be object, but is ", j.type_name()), &j));
}
ConstructibleObjectType ret;
@@ -370,7 +371,7 @@ void from_json(const BasicJsonType& j, ArithmeticType& val)
case value_t::binary:
case value_t::discarded:
default:
- JSON_THROW(type_error::create(302, "type must be number, but is " + std::string(j.type_name()), j));
+ JSON_THROW(type_error::create(302, concat("type must be number, but is ", j.type_name()), &j));
}
}
@@ -411,7 +412,7 @@ auto from_json(BasicJsonType&& j, TupleRelated&& t)
{
if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
{
- JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name()), j));
+ JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
}
return from_json_tuple_impl(std::forward(j), std::forward(t), priority_tag<3> {});
@@ -424,14 +425,14 @@ void from_json(const BasicJsonType& j, std::map&
{
if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
{
- JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name()), j));
+ JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
}
m.clear();
for (const auto& p : j)
{
if (JSON_HEDLEY_UNLIKELY(!p.is_array()))
{
- JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(p.type_name()), j));
+ JSON_THROW(type_error::create(302, concat("type must be array, but is ", p.type_name()), &j));
}
m.emplace(p.at(0).template get(), p.at(1).template get());
}
@@ -444,14 +445,14 @@ void from_json(const BasicJsonType& j, std::unordered_map(), p.at(1).template get());
}
@@ -463,7 +464,7 @@ void from_json(const BasicJsonType& j, std_fs::path& p)
{
if (JSON_HEDLEY_UNLIKELY(!j.is_string()))
{
- JSON_THROW(type_error::create(302, "type must be string, but is " + std::string(j.type_name()), j));
+ JSON_THROW(type_error::create(302, concat("type must be string, but is ", j.type_name()), &j));
}
p = *j.template get_ptr();
}
diff --git a/include/nlohmann/detail/exceptions.hpp b/include/nlohmann/detail/exceptions.hpp
index b4b1804963..4d61de4022 100644
--- a/include/nlohmann/detail/exceptions.hpp
+++ b/include/nlohmann/detail/exceptions.hpp
@@ -1,5 +1,6 @@
#pragma once
+#include // nullptr_t
#include // exception
#include // runtime_error
#include // to_string
@@ -9,6 +10,10 @@
#include
#include
#include
+#include
+#include
+#include
+
namespace nlohmann
{
@@ -38,15 +43,20 @@ class exception : public std::exception
static std::string name(const std::string& ename, int id_)
{
- return "[json.exception." + ename + "." + std::to_string(id_) + "] ";
+ return concat("[json.exception.", ename, '.', std::to_string(id_), "] ");
+ }
+
+ static std::string diagnostics(std::nullptr_t /*leaf_element*/)
+ {
+ return "";
}
template
- static std::string diagnostics(const BasicJsonType& leaf_element)
+ static std::string diagnostics(const BasicJsonType* leaf_element)
{
#if JSON_DIAGNOSTICS
std::vector tokens;
- for (const auto* current = &leaf_element; current->m_parent != nullptr; current = current->m_parent)
+ for (const auto* current = leaf_element; current != nullptr && current->m_parent != nullptr; current = current->m_parent)
{
switch (current->m_parent->type())
{
@@ -94,11 +104,12 @@ class exception : public std::exception
return "";
}
- return "(" + std::accumulate(tokens.rbegin(), tokens.rend(), std::string{},
- [](const std::string & a, const std::string & b)
+ auto str = std::accumulate(tokens.rbegin(), tokens.rend(), std::string{},
+ [](const std::string & a, const std::string & b)
{
- return a + "/" + detail::escape(b);
- }) + ") ";
+ return concat(a, '/', detail::escape(b));
+ });
+ return concat('(', str, ") ");
#else
static_cast(leaf_element);
return "";
@@ -124,20 +135,20 @@ class parse_error : public exception
@param[in] what_arg the explanatory string
@return parse_error object
*/
- template
- static parse_error create(int id_, const position_t& pos, const std::string& what_arg, const BasicJsonType& context)
+ template::value, int> = 0>
+ static parse_error create(int id_, const position_t& pos, const std::string& what_arg, BasicJsonContext context)
{
- std::string w = exception::name("parse_error", id_) + "parse error" +
- position_string(pos) + ": " + exception::diagnostics(context) + what_arg;
+ std::string w = concat(exception::name("parse_error", id_), "parse error",
+ position_string(pos), ": ", exception::diagnostics(context), what_arg);
return {id_, pos.chars_read_total, w.c_str()};
}
- template
- static parse_error create(int id_, std::size_t byte_, const std::string& what_arg, const BasicJsonType& context)
+ template::value, int> = 0>
+ static parse_error create(int id_, std::size_t byte_, const std::string& what_arg, BasicJsonContext context)
{
- std::string w = exception::name("parse_error", id_) + "parse error" +
- (byte_ != 0 ? (" at byte " + std::to_string(byte_)) : "") +
- ": " + exception::diagnostics(context) + what_arg;
+ std::string w = concat(exception::name("parse_error", id_), "parse error",
+ (byte_ != 0 ? (concat(" at byte ", std::to_string(byte_))) : ""),
+ ": ", exception::diagnostics(context), what_arg);
return {id_, byte_, w.c_str()};
}
@@ -158,8 +169,8 @@ class parse_error : public exception
static std::string position_string(const position_t& pos)
{
- return " at line " + std::to_string(pos.lines_read + 1) +
- ", column " + std::to_string(pos.chars_read_current_line);
+ return concat(" at line ", std::to_string(pos.lines_read + 1),
+ ", column ", std::to_string(pos.chars_read_current_line));
}
};
@@ -168,10 +179,10 @@ class parse_error : public exception
class invalid_iterator : public exception
{
public:
- template
- static invalid_iterator create(int id_, const std::string& what_arg, const BasicJsonType& context)
+ template::value, int> = 0>
+ static invalid_iterator create(int id_, const std::string& what_arg, BasicJsonContext context)
{
- std::string w = exception::name("invalid_iterator", id_) + exception::diagnostics(context) + what_arg;
+ std::string w = concat(exception::name("invalid_iterator", id_), exception::diagnostics(context), what_arg);
return {id_, w.c_str()};
}
@@ -186,10 +197,10 @@ class invalid_iterator : public exception
class type_error : public exception
{
public:
- template
- static type_error create(int id_, const std::string& what_arg, const BasicJsonType& context)
+ template::value, int> = 0>
+ static type_error create(int id_, const std::string& what_arg, BasicJsonContext context)
{
- std::string w = exception::name("type_error", id_) + exception::diagnostics(context) + what_arg;
+ std::string w = concat(exception::name("type_error", id_), exception::diagnostics(context), what_arg);
return {id_, w.c_str()};
}
@@ -203,10 +214,10 @@ class type_error : public exception
class out_of_range : public exception
{
public:
- template
- static out_of_range create(int id_, const std::string& what_arg, const BasicJsonType& context)
+ template::value, int> = 0>
+ static out_of_range create(int id_, const std::string& what_arg, BasicJsonContext context)
{
- std::string w = exception::name("out_of_range", id_) + exception::diagnostics(context) + what_arg;
+ std::string w = concat(exception::name("out_of_range", id_), exception::diagnostics(context), what_arg);
return {id_, w.c_str()};
}
@@ -220,10 +231,10 @@ class out_of_range : public exception
class other_error : public exception
{
public:
- template
- static other_error create(int id_, const std::string& what_arg, const BasicJsonType& context)
+ template::value, int> = 0>
+ static other_error create(int id_, const std::string& what_arg, BasicJsonContext context)
{
- std::string w = exception::name("other_error", id_) + exception::diagnostics(context) + what_arg;
+ std::string w = concat(exception::name("other_error", id_), exception::diagnostics(context), what_arg);
return {id_, w.c_str()};
}
diff --git a/include/nlohmann/detail/input/binary_reader.hpp b/include/nlohmann/detail/input/binary_reader.hpp
index 65e0047ac7..4041cedbaa 100644
--- a/include/nlohmann/detail/input/binary_reader.hpp
+++ b/include/nlohmann/detail/input/binary_reader.hpp
@@ -20,6 +20,7 @@
#include
#include
#include
+#include
#include
namespace nlohmann
@@ -139,8 +140,8 @@ class binary_reader
if (JSON_HEDLEY_UNLIKELY(current != std::char_traits::eof()))
{
- return sax->parse_error(chars_read, get_token_string(),
- parse_error::create(110, chars_read, exception_message(format, "expected end of input; last byte: 0x" + get_token_string(), "value"), BasicJsonType()));
+ return sax->parse_error(chars_read, get_token_string(), parse_error::create(110, chars_read,
+ exception_message(format, concat("expected end of input; last byte: 0x", get_token_string()), "value"), nullptr));
}
}
@@ -216,7 +217,8 @@ class binary_reader
if (JSON_HEDLEY_UNLIKELY(len < 1))
{
auto last_token = get_token_string();
- return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format_t::bson, "string length must be at least 1, is " + std::to_string(len), "string"), BasicJsonType()));
+ return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
+ exception_message(input_format_t::bson, concat("string length must be at least 1, is ", std::to_string(len)), "string"), nullptr));
}
return get_string(input_format_t::bson, len - static_cast(1), result) && get() != std::char_traits::eof();
@@ -237,7 +239,8 @@ class binary_reader
if (JSON_HEDLEY_UNLIKELY(len < 0))
{
auto last_token = get_token_string();
- return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format_t::bson, "byte array length cannot be negative, is " + std::to_string(len), "binary"), BasicJsonType()));
+ return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
+ exception_message(input_format_t::bson, concat("byte array length cannot be negative, is ", std::to_string(len)), "binary"), nullptr));
}
// All BSON binary values have a subtype
@@ -319,7 +322,9 @@ class binary_reader
{
std::array cr{{}};
static_cast((std::snprintf)(cr.data(), cr.size(), "%.2hhX", static_cast(element_type))); // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
- return sax->parse_error(element_type_parse_position, std::string(cr.data()), parse_error::create(114, element_type_parse_position, "Unsupported BSON record type 0x" + std::string(cr.data()), BasicJsonType()));
+ std::string cr_str{cr.data()};
+ return sax->parse_error(element_type_parse_position, cr_str,
+ parse_error::create(114, element_type_parse_position, concat("Unsupported BSON record type 0x", cr_str), nullptr));
}
}
}
@@ -719,7 +724,8 @@ class binary_reader
case cbor_tag_handler_t::error:
{
auto last_token = get_token_string();
- return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format_t::cbor, "invalid byte: 0x" + last_token, "value"), BasicJsonType()));
+ return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
+ exception_message(input_format_t::cbor, concat("invalid byte: 0x", last_token), "value"), nullptr));
}
case cbor_tag_handler_t::ignore:
@@ -876,7 +882,8 @@ class binary_reader
default: // anything else (0xFF is handled inside the other types)
{
auto last_token = get_token_string();
- return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format_t::cbor, "invalid byte: 0x" + last_token, "value"), BasicJsonType()));
+ return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
+ exception_message(input_format_t::cbor, concat("invalid byte: 0x", last_token), "value"), nullptr));
}
}
}
@@ -971,7 +978,8 @@ class binary_reader
default:
{
auto last_token = get_token_string();
- return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format_t::cbor, "expected length specification (0x60-0x7B) or indefinite string type (0x7F); last byte: 0x" + last_token, "string"), BasicJsonType()));
+ return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read,
+ exception_message(input_format_t::cbor, concat("expected length specification (0x60-0x7B) or indefinite string type (0x7F); last byte: 0x", last_token), "string"), nullptr));
}
}
}
@@ -1070,7 +1078,8 @@ class binary_reader
default:
{
auto last_token = get_token_string();
- return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format_t::cbor, "expected length specification (0x40-0x5B) or indefinite binary array type (0x5F); last byte: 0x" + last_token, "binary"), BasicJsonType()));
+ return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read,
+ exception_message(input_format_t::cbor, concat("expected length specification (0x40-0x5B) or indefinite binary array type (0x5F); last byte: 0x", last_token), "binary"), nullptr));
}
}
}
@@ -1540,7 +1549,8 @@ class binary_reader
default: // anything else
{
auto last_token = get_token_string();
- return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format_t::msgpack, "invalid byte: 0x" + last_token, "value"), BasicJsonType()));
+ return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
+ exception_message(input_format_t::msgpack, concat("invalid byte: 0x", last_token), "value"), nullptr));
}
}
}
@@ -1622,7 +1632,8 @@ class binary_reader
default:
{
auto last_token = get_token_string();
- return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format_t::msgpack, "expected length specification (0xA0-0xBF, 0xD9-0xDB); last byte: 0x" + last_token, "string"), BasicJsonType()));
+ return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read,
+ exception_message(input_format_t::msgpack, concat("expected length specification (0xA0-0xBF, 0xD9-0xDB); last byte: 0x", last_token), "string"), nullptr));
}
}
}
@@ -1872,7 +1883,8 @@ class binary_reader
default:
auto last_token = get_token_string();
- return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format_t::ubjson, "expected length type specification (U, i, I, l, L); last byte: 0x" + last_token, "string"), BasicJsonType()));
+ return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read,
+ exception_message(input_format_t::ubjson, concat("expected length type specification (U, i, I, l, L); last byte: 0x", last_token), "string"), nullptr));
}
}
@@ -1942,7 +1954,8 @@ class binary_reader
default:
{
auto last_token = get_token_string();
- return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format_t::ubjson, "expected length type specification (U, i, I, l, L) after '#'; last byte: 0x" + last_token, "size"), BasicJsonType()));
+ return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read,
+ exception_message(input_format_t::ubjson, concat("expected length type specification (U, i, I, l, L) after '#'; last byte: 0x", last_token), "size"), nullptr));
}
}
}
@@ -1980,7 +1993,8 @@ class binary_reader
return false;
}
auto last_token = get_token_string();
- return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format_t::ubjson, "expected '#' after type information; last byte: 0x" + last_token, "size"), BasicJsonType()));
+ return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
+ exception_message(input_format_t::ubjson, concat("expected '#' after type information; last byte: 0x", last_token), "size"), nullptr));
}
return get_ubjson_size_value(result.first);
@@ -2070,7 +2084,8 @@ class binary_reader
if (JSON_HEDLEY_UNLIKELY(current > 127))
{
auto last_token = get_token_string();
- return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format_t::ubjson, "byte after 'C' must be in range 0x00..0x7F; last byte: 0x" + last_token, "char"), BasicJsonType()));
+ return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read,
+ exception_message(input_format_t::ubjson, concat("byte after 'C' must be in range 0x00..0x7F; last byte: 0x", last_token), "char"), nullptr));
}
string_t s(1, static_cast(current));
return sax->string(s);
@@ -2091,7 +2106,8 @@ class binary_reader
default: // anything else
{
auto last_token = get_token_string();
- return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format_t::ubjson, "invalid byte: 0x" + last_token, "value"), BasicJsonType()));
+ return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
+ exception_message(input_format_t::ubjson, concat("invalid byte: 0x", last_token), "value"), nullptr));
}
}
}
@@ -2269,7 +2285,8 @@ class binary_reader
if (JSON_HEDLEY_UNLIKELY(result_remainder != token_type::end_of_input))
{
- return sax->parse_error(chars_read, number_string, parse_error::create(115, chars_read, exception_message(input_format_t::ubjson, "invalid number text: " + number_lexer.get_token_string(), "high-precision number"), BasicJsonType()));
+ return sax->parse_error(chars_read, number_string, parse_error::create(115, chars_read,
+ exception_message(input_format_t::ubjson, concat("invalid number text: ", number_lexer.get_token_string()), "high-precision number"), nullptr));
}
switch (result_number)
@@ -2295,7 +2312,8 @@ class binary_reader
case token_type::end_of_input:
case token_type::literal_or_value:
default:
- return sax->parse_error(chars_read, number_string, parse_error::create(115, chars_read, exception_message(input_format_t::ubjson, "invalid number text: " + number_lexer.get_token_string(), "high-precision number"), BasicJsonType()));
+ return sax->parse_error(chars_read, number_string, parse_error::create(115, chars_read,
+ exception_message(input_format_t::ubjson, concat("invalid number text: ", number_lexer.get_token_string()), "high-precision number"), nullptr));
}
}
@@ -2451,7 +2469,7 @@ class binary_reader
if (JSON_HEDLEY_UNLIKELY(current == std::char_traits::eof()))
{
return sax->parse_error(chars_read, "",
- parse_error::create(110, chars_read, exception_message(format, "unexpected end of input", context), BasicJsonType()));
+ parse_error::create(110, chars_read, exception_message(format, "unexpected end of input", context), nullptr));
}
return true;
}
@@ -2501,7 +2519,7 @@ class binary_reader
JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
}
- return error_msg + " " + context + ": " + detail;
+ return concat(error_msg, ' ', context, ": ", detail);
}
private:
diff --git a/include/nlohmann/detail/input/json_sax.hpp b/include/nlohmann/detail/input/json_sax.hpp
index fd9dab87a9..406008167f 100644
--- a/include/nlohmann/detail/input/json_sax.hpp
+++ b/include/nlohmann/detail/input/json_sax.hpp
@@ -7,6 +7,7 @@
#include
#include
+#include
namespace nlohmann
{
@@ -224,7 +225,7 @@ class json_sax_dom_parser
if (JSON_HEDLEY_UNLIKELY(len != static_cast(-1) && len > ref_stack.back()->max_size()))
{
- JSON_THROW(out_of_range::create(408, "excessive object size: " + std::to_string(len), *ref_stack.back()));
+ JSON_THROW(out_of_range::create(408, concat("excessive object size: ", std::to_string(len)), ref_stack.back()));
}
return true;
@@ -250,7 +251,7 @@ class json_sax_dom_parser
if (JSON_HEDLEY_UNLIKELY(len != static_cast(-1) && len > ref_stack.back()->max_size()))
{
- JSON_THROW(out_of_range::create(408, "excessive array size: " + std::to_string(len), *ref_stack.back()));
+ JSON_THROW(out_of_range::create(408, concat("excessive array size: ", std::to_string(len)), ref_stack.back()));
}
return true;
@@ -405,7 +406,7 @@ class json_sax_dom_callback_parser
// check object limit
if (ref_stack.back() && JSON_HEDLEY_UNLIKELY(len != static_cast(-1) && len > ref_stack.back()->max_size()))
{
- JSON_THROW(out_of_range::create(408, "excessive object size: " + std::to_string(len), *ref_stack.back()));
+ JSON_THROW(out_of_range::create(408, concat("excessive object size: ", std::to_string(len)), ref_stack.back()));
}
return true;
@@ -475,7 +476,7 @@ class json_sax_dom_callback_parser
// check array limit
if (ref_stack.back() && JSON_HEDLEY_UNLIKELY(len != static_cast(-1) && len > ref_stack.back()->max_size()))
{
- JSON_THROW(out_of_range::create(408, "excessive array size: " + std::to_string(len), *ref_stack.back()));
+ JSON_THROW(out_of_range::create(408, concat("excessive array size: ", std::to_string(len)), ref_stack.back()));
}
return true;
diff --git a/include/nlohmann/detail/input/parser.hpp b/include/nlohmann/detail/input/parser.hpp
index 024dd040f7..32b360969a 100644
--- a/include/nlohmann/detail/input/parser.hpp
+++ b/include/nlohmann/detail/input/parser.hpp
@@ -13,6 +13,7 @@
#include
#include
#include
+#include
#include
namespace nlohmann
@@ -95,7 +96,7 @@ class parser
sdp.parse_error(m_lexer.get_position(),
m_lexer.get_token_string(),
parse_error::create(101, m_lexer.get_position(),
- exception_message(token_type::end_of_input, "value"), BasicJsonType()));
+ exception_message(token_type::end_of_input, "value"), nullptr));
}
// in case of an error, return discarded value
@@ -122,7 +123,7 @@ class parser
{
sdp.parse_error(m_lexer.get_position(),
m_lexer.get_token_string(),
- parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_of_input, "value"), BasicJsonType()));
+ parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_of_input, "value"), nullptr));
}
// in case of an error, return discarded value
@@ -160,7 +161,7 @@ class parser
{
return sax->parse_error(m_lexer.get_position(),
m_lexer.get_token_string(),
- parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_of_input, "value"), BasicJsonType()));
+ parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_of_input, "value"), nullptr));
}
return result;
@@ -206,7 +207,7 @@ class parser
{
return sax->parse_error(m_lexer.get_position(),
m_lexer.get_token_string(),
- parse_error::create(101, m_lexer.get_position(), exception_message(token_type::value_string, "object key"), BasicJsonType()));
+ parse_error::create(101, m_lexer.get_position(), exception_message(token_type::value_string, "object key"), nullptr));
}
if (JSON_HEDLEY_UNLIKELY(!sax->key(m_lexer.get_string())))
{
@@ -218,7 +219,7 @@ class parser
{
return sax->parse_error(m_lexer.get_position(),
m_lexer.get_token_string(),
- parse_error::create(101, m_lexer.get_position(), exception_message(token_type::name_separator, "object separator"), BasicJsonType()));
+ parse_error::create(101, m_lexer.get_position(), exception_message(token_type::name_separator, "object separator"), nullptr));
}
// remember we are now inside an object
@@ -261,7 +262,7 @@ class parser
{
return sax->parse_error(m_lexer.get_position(),
m_lexer.get_token_string(),
- out_of_range::create(406, "number overflow parsing '" + m_lexer.get_token_string() + "'", BasicJsonType()));
+ out_of_range::create(406, concat("number overflow parsing '", m_lexer.get_token_string(), '\''), nullptr));
}
if (JSON_HEDLEY_UNLIKELY(!sax->number_float(res, m_lexer.get_string())))
@@ -331,7 +332,7 @@ class parser
// using "uninitialized" to avoid "expected" message
return sax->parse_error(m_lexer.get_position(),
m_lexer.get_token_string(),
- parse_error::create(101, m_lexer.get_position(), exception_message(token_type::uninitialized, "value"), BasicJsonType()));
+ parse_error::create(101, m_lexer.get_position(), exception_message(token_type::uninitialized, "value"), nullptr));
}
case token_type::uninitialized:
@@ -345,7 +346,7 @@ class parser
{
return sax->parse_error(m_lexer.get_position(),
m_lexer.get_token_string(),
- parse_error::create(101, m_lexer.get_position(), exception_message(token_type::literal_or_value, "value"), BasicJsonType()));
+ parse_error::create(101, m_lexer.get_position(), exception_message(token_type::literal_or_value, "value"), nullptr));
}
}
}
@@ -391,7 +392,7 @@ class parser
return sax->parse_error(m_lexer.get_position(),
m_lexer.get_token_string(),
- parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_array, "array"), BasicJsonType()));
+ parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_array, "array"), nullptr));
}
// states.back() is false -> object
@@ -404,7 +405,7 @@ class parser
{
return sax->parse_error(m_lexer.get_position(),
m_lexer.get_token_string(),
- parse_error::create(101, m_lexer.get_position(), exception_message(token_type::value_string, "object key"), BasicJsonType()));
+ parse_error::create(101, m_lexer.get_position(), exception_message(token_type::value_string, "object key"), nullptr));
}
if (JSON_HEDLEY_UNLIKELY(!sax->key(m_lexer.get_string())))
@@ -417,7 +418,7 @@ class parser
{
return sax->parse_error(m_lexer.get_position(),
m_lexer.get_token_string(),
- parse_error::create(101, m_lexer.get_position(), exception_message(token_type::name_separator, "object separator"), BasicJsonType()));
+ parse_error::create(101, m_lexer.get_position(), exception_message(token_type::name_separator, "object separator"), nullptr));
}
// parse values
@@ -445,7 +446,7 @@ class parser
return sax->parse_error(m_lexer.get_position(),
m_lexer.get_token_string(),
- parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_object, "object"), BasicJsonType()));
+ parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_object, "object"), nullptr));
}
}
@@ -461,24 +462,24 @@ class parser
if (!context.empty())
{
- error_msg += "while parsing " + context + " ";
+ error_msg += concat("while parsing ", context, ' ');
}
error_msg += "- ";
if (last_token == token_type::parse_error)
{
- error_msg += std::string(m_lexer.get_error_message()) + "; last read: '" +
- m_lexer.get_token_string() + "'";
+ error_msg += concat(m_lexer.get_error_message(), "; last read: '",
+ m_lexer.get_token_string(), '\'');
}
else
{
- error_msg += "unexpected " + std::string(lexer_t::token_type_name(last_token));
+ error_msg += concat("unexpected ", lexer_t::token_type_name(last_token));
}
if (expected != token_type::uninitialized)
{
- error_msg += "; expected " + std::string(lexer_t::token_type_name(expected));
+ error_msg += concat("; expected ", lexer_t::token_type_name(expected));
}
return error_msg;
diff --git a/include/nlohmann/detail/iterators/iter_impl.hpp b/include/nlohmann/detail/iterators/iter_impl.hpp
index d8060786ec..cdcdaff1f2 100644
--- a/include/nlohmann/detail/iterators/iter_impl.hpp
+++ b/include/nlohmann/detail/iterators/iter_impl.hpp
@@ -285,7 +285,7 @@ class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-speci
}
case value_t::null:
- JSON_THROW(invalid_iterator::create(214, "cannot get value", *m_object));
+ JSON_THROW(invalid_iterator::create(214, "cannot get value", m_object));
case value_t::string:
case value_t::boolean:
@@ -301,7 +301,7 @@ class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-speci
return *m_object;
}
- JSON_THROW(invalid_iterator::create(214, "cannot get value", *m_object));
+ JSON_THROW(invalid_iterator::create(214, "cannot get value", m_object));
}
}
}
@@ -343,7 +343,7 @@ class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-speci
return m_object;
}
- JSON_THROW(invalid_iterator::create(214, "cannot get value", *m_object));
+ JSON_THROW(invalid_iterator::create(214, "cannot get value", m_object));
}
}
}
@@ -460,7 +460,7 @@ class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-speci
// if objects are not the same, the comparison is undefined
if (JSON_HEDLEY_UNLIKELY(m_object != other.m_object))
{
- JSON_THROW(invalid_iterator::create(212, "cannot compare iterators of different containers", *m_object));
+ JSON_THROW(invalid_iterator::create(212, "cannot compare iterators of different containers", m_object));
}
JSON_ASSERT(m_object != nullptr);
@@ -505,7 +505,7 @@ class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-speci
// if objects are not the same, the comparison is undefined
if (JSON_HEDLEY_UNLIKELY(m_object != other.m_object))
{
- JSON_THROW(invalid_iterator::create(212, "cannot compare iterators of different containers", *m_object));
+ JSON_THROW(invalid_iterator::create(212, "cannot compare iterators of different containers", m_object));
}
JSON_ASSERT(m_object != nullptr);
@@ -513,7 +513,7 @@ class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-speci
switch (m_object->m_type)
{
case value_t::object:
- JSON_THROW(invalid_iterator::create(213, "cannot compare order of object iterators", *m_object));
+ JSON_THROW(invalid_iterator::create(213, "cannot compare order of object iterators", m_object));
case value_t::array:
return (m_it.array_iterator < other.m_it.array_iterator);
@@ -569,7 +569,7 @@ class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-speci
switch (m_object->m_type)
{
case value_t::object:
- JSON_THROW(invalid_iterator::create(209, "cannot use offsets with object iterators", *m_object));
+ JSON_THROW(invalid_iterator::create(209, "cannot use offsets with object iterators", m_object));
case value_t::array:
{
@@ -648,7 +648,7 @@ class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-speci
switch (m_object->m_type)
{
case value_t::object:
- JSON_THROW(invalid_iterator::create(209, "cannot use offsets with object iterators", *m_object));
+ JSON_THROW(invalid_iterator::create(209, "cannot use offsets with object iterators", m_object));
case value_t::array:
return m_it.array_iterator - other.m_it.array_iterator;
@@ -677,13 +677,13 @@ class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-speci
switch (m_object->m_type)
{
case value_t::object:
- JSON_THROW(invalid_iterator::create(208, "cannot use operator[] for object iterators", *m_object));
+ JSON_THROW(invalid_iterator::create(208, "cannot use operator[] for object iterators", m_object));
case value_t::array:
return *std::next(m_it.array_iterator, n);
case value_t::null:
- JSON_THROW(invalid_iterator::create(214, "cannot get value", *m_object));
+ JSON_THROW(invalid_iterator::create(214, "cannot get value", m_object));
case value_t::string:
case value_t::boolean:
@@ -699,7 +699,7 @@ class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-speci
return *m_object;
}
- JSON_THROW(invalid_iterator::create(214, "cannot get value", *m_object));
+ JSON_THROW(invalid_iterator::create(214, "cannot get value", m_object));
}
}
}
@@ -717,7 +717,7 @@ class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-speci
return m_it.object_iterator->first;
}
- JSON_THROW(invalid_iterator::create(207, "cannot use key() for non-object iterators", *m_object));
+ JSON_THROW(invalid_iterator::create(207, "cannot use key() for non-object iterators", m_object));
}
/*!
diff --git a/include/nlohmann/detail/json_pointer.hpp b/include/nlohmann/detail/json_pointer.hpp
index caed67c9e7..f94f3bdf9a 100644
--- a/include/nlohmann/detail/json_pointer.hpp
+++ b/include/nlohmann/detail/json_pointer.hpp
@@ -2,6 +2,8 @@
#include // all_of
#include // isdigit
+#include // errno, ERANGE
+#include // strtoull
#include // max
#include // accumulate
#include // string
@@ -10,6 +12,7 @@
#include
#include
+#include
#include
#include
@@ -18,35 +21,53 @@ namespace nlohmann
/// @brief JSON Pointer defines a string syntax for identifying a specific value within a JSON document
/// @sa https://json.nlohmann.me/api/json_pointer/
-template
+template
class json_pointer
{
// allow basic_json to access private members
NLOHMANN_BASIC_JSON_TPL_DECLARATION
friend class basic_json;
+ template
+ friend class json_pointer;
+
+ template
+ struct string_t_helper
+ {
+ using type = T;
+ };
+
+ NLOHMANN_BASIC_JSON_TPL_DECLARATION
+ struct string_t_helper
+ {
+ using type = StringType;
+ };
+
public:
+ // for backwards compatibility accept BasicJsonType
+ using string_t = typename string_t_helper::type;
+
/// @brief create JSON pointer
/// @sa https://json.nlohmann.me/api/json_pointer/json_pointer/
- explicit json_pointer(const std::string& s = "")
+ explicit json_pointer(const string_t& s = "")
: reference_tokens(split(s))
{}
/// @brief return a string representation of the JSON pointer
/// @sa https://json.nlohmann.me/api/json_pointer/to_string/
- std::string to_string() const
+ string_t to_string() const
{
return std::accumulate(reference_tokens.begin(), reference_tokens.end(),
- std::string{},
- [](const std::string & a, const std::string & b)
+ string_t{},
+ [](const string_t& a, const string_t& b)
{
- return a + "/" + detail::escape(b);
+ return detail::concat(a, '/', detail::escape(b));
});
}
/// @brief return a string representation of the JSON pointer
/// @sa https://json.nlohmann.me/api/json_pointer/operator_string/
- operator std::string() const
+ operator string_t() const
{
return to_string();
}
@@ -63,7 +84,7 @@ class json_pointer
/// @brief append an unescaped reference token at the end of this JSON pointer
/// @sa https://json.nlohmann.me/api/json_pointer/operator_slasheq/
- json_pointer& operator/=(std::string token)
+ json_pointer& operator/=(string_t token)
{
push_back(std::move(token));
return *this;
@@ -86,7 +107,7 @@ class json_pointer
/// @brief create a new JSON pointer by appending the unescaped token at the end of the JSON pointer
/// @sa https://json.nlohmann.me/api/json_pointer/operator_slash/
- friend json_pointer operator/(const json_pointer& lhs, std::string token) // NOLINT(performance-unnecessary-value-param)
+ friend json_pointer operator/(const json_pointer& lhs, string_t token) // NOLINT(performance-unnecessary-value-param)
{
return json_pointer(lhs) /= std::move(token);
}
@@ -118,7 +139,7 @@ class json_pointer
{
if (JSON_HEDLEY_UNLIKELY(empty()))
{
- JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent", BasicJsonType()));
+ JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent", nullptr));
}
reference_tokens.pop_back();
@@ -126,11 +147,11 @@ class json_pointer
/// @brief return last reference token
/// @sa https://json.nlohmann.me/api/json_pointer/back/
- const std::string& back() const
+ const string_t& back() const
{
if (JSON_HEDLEY_UNLIKELY(empty()))
{
- JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent", BasicJsonType()));
+ JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent", nullptr));
}
return reference_tokens.back();
@@ -138,14 +159,14 @@ class json_pointer
/// @brief append an unescaped token at the end of the reference pointer
/// @sa https://json.nlohmann.me/api/json_pointer/push_back/
- void push_back(const std::string& token)
+ void push_back(const string_t& token)
{
reference_tokens.push_back(token);
}
/// @brief append an unescaped token at the end of the reference pointer
/// @sa https://json.nlohmann.me/api/json_pointer/push_back/
- void push_back(std::string&& token)
+ void push_back(string_t&& token)
{
reference_tokens.push_back(std::move(token));
}
@@ -168,44 +189,39 @@ class json_pointer
@throw out_of_range.404 if string @a s could not be converted to an integer
@throw out_of_range.410 if an array index exceeds size_type
*/
- static typename BasicJsonType::size_type array_index(const std::string& s)
+ template
+ static typename BasicJsonType::size_type array_index(const string_t& s)
{
using size_type = typename BasicJsonType::size_type;
// error condition (cf. RFC 6901, Sect. 4)
if (JSON_HEDLEY_UNLIKELY(s.size() > 1 && s[0] == '0'))
{
- JSON_THROW(detail::parse_error::create(106, 0, "array index '" + s + "' must not begin with '0'", BasicJsonType()));
+ JSON_THROW(detail::parse_error::create(106, 0, detail::concat("array index '", s, "' must not begin with '0'"), nullptr));
}
// error condition (cf. RFC 6901, Sect. 4)
if (JSON_HEDLEY_UNLIKELY(s.size() > 1 && !(s[0] >= '1' && s[0] <= '9')))
{
- JSON_THROW(detail::parse_error::create(109, 0, "array index '" + s + "' is not a number", BasicJsonType()));
+ JSON_THROW(detail::parse_error::create(109, 0, detail::concat("array index '", s, "' is not a number"), nullptr));
}
- std::size_t processed_chars = 0;
- unsigned long long res = 0; // NOLINT(runtime/int)
- JSON_TRY
+ const char* p = s.c_str();
+ char* p_end = nullptr;
+ errno = 0; // strtoull doesn't reset errno
+ unsigned long long res = std::strtoull(p, &p_end, 10); // NOLINT(runtime/int)
+ if (p == p_end // invalid input or empty string
+ || errno == ERANGE // out of range
+ || JSON_HEDLEY_UNLIKELY(static_cast(p_end - p) != s.size())) // incomplete read
{
- res = std::stoull(s, &processed_chars);
- }
- JSON_CATCH(std::out_of_range&)
- {
- JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + s + "'", BasicJsonType()));
- }
-
- // check if the string was completely read
- if (JSON_HEDLEY_UNLIKELY(processed_chars != s.size()))
- {
- JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + s + "'", BasicJsonType()));
+ JSON_THROW(detail::out_of_range::create(404, detail::concat("unresolved reference token '", s, "'"), nullptr));
}
// only triggered on special platforms (like 32bit), see also
// https://github.com/nlohmann/json/pull/2203
if (res >= static_cast((std::numeric_limits::max)())) // NOLINT(runtime/int)
{
- JSON_THROW(detail::out_of_range::create(410, "array index " + s + " exceeds size_type", BasicJsonType())); // LCOV_EXCL_LINE
+ JSON_THROW(detail::out_of_range::create(410, detail::concat("array index ", s, " exceeds size_type"), nullptr)); // LCOV_EXCL_LINE
}
return static_cast(res);
@@ -216,7 +232,7 @@ class json_pointer
{
if (JSON_HEDLEY_UNLIKELY(empty()))
{
- JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent", BasicJsonType()));
+ JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent", nullptr));
}
json_pointer result = *this;
@@ -233,6 +249,7 @@ class json_pointer
@throw parse_error.109 if array index is not a number
@throw type_error.313 if value cannot be unflattened
*/
+ template
BasicJsonType& get_and_create(BasicJsonType& j) const
{
auto* result = &j;
@@ -268,7 +285,7 @@ class json_pointer
case detail::value_t::array:
{
// create an entry in the array
- result = &result->operator[](array_index(reference_token));
+ result = &result->operator[](array_index(reference_token));
break;
}
@@ -286,7 +303,7 @@ class json_pointer
case detail::value_t::binary:
case detail::value_t::discarded:
default:
- JSON_THROW(detail::type_error::create(313, "invalid value to unflatten", j));
+ JSON_THROW(detail::type_error::create(313, "invalid value to unflatten", &j));
}
}
@@ -312,6 +329,7 @@ class json_pointer
@throw parse_error.109 if an array index was not a number
@throw out_of_range.404 if the JSON pointer can not be resolved
*/
+ template
BasicJsonType& get_unchecked(BasicJsonType* ptr) const
{
for (const auto& reference_token : reference_tokens)
@@ -352,7 +370,7 @@ class json_pointer
else
{
// convert array index to number; unchecked access
- ptr = &ptr->operator[](array_index(reference_token));
+ ptr = &ptr->operator[](array_index(reference_token));
}
break;
}
@@ -366,7 +384,7 @@ class json_pointer
case detail::value_t::binary:
case detail::value_t::discarded:
default:
- JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + reference_token + "'", *ptr));
+ JSON_THROW(detail::out_of_range::create(404, detail::concat("unresolved reference token '", reference_token, "'"), ptr));
}
}
@@ -379,6 +397,7 @@ class json_pointer
@throw out_of_range.402 if the array index '-' is used
@throw out_of_range.404 if the JSON pointer can not be resolved
*/
+ template
BasicJsonType& get_checked(BasicJsonType* ptr) const
{
for (const auto& reference_token : reference_tokens)
@@ -397,13 +416,13 @@ class json_pointer
if (JSON_HEDLEY_UNLIKELY(reference_token == "-"))
{
// "-" always fails the range check
- JSON_THROW(detail::out_of_range::create(402,
- "array index '-' (" + std::to_string(ptr->m_value.array->size()) +
- ") is out of range", *ptr));
+ JSON_THROW(detail::out_of_range::create(402, detail::concat(
+ "array index '-' (", std::to_string(ptr->m_value.array->size()),
+ ") is out of range"), ptr));
}
// note: at performs range check
- ptr = &ptr->at(array_index(reference_token));
+ ptr = &ptr->at(array_index(reference_token));
break;
}
@@ -416,7 +435,7 @@ class json_pointer
case detail::value_t::binary:
case detail::value_t::discarded:
default:
- JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + reference_token + "'", *ptr));
+ JSON_THROW(detail::out_of_range::create(404, detail::concat("unresolved reference token '", reference_token, "'"), ptr));
}
}
@@ -436,6 +455,7 @@ class json_pointer
@throw out_of_range.402 if the array index '-' is used
@throw out_of_range.404 if the JSON pointer can not be resolved
*/
+ template
const BasicJsonType& get_unchecked(const BasicJsonType* ptr) const
{
for (const auto& reference_token : reference_tokens)
@@ -454,11 +474,11 @@ class json_pointer
if (JSON_HEDLEY_UNLIKELY(reference_token == "-"))
{
// "-" cannot be used for const access
- JSON_THROW(detail::out_of_range::create(402, "array index '-' (" + std::to_string(ptr->m_value.array->size()) + ") is out of range", *ptr));
+ JSON_THROW(detail::out_of_range::create(402, detail::concat("array index '-' (", std::to_string(ptr->m_value.array->size()), ") is out of range"), ptr));
}
// use unchecked array access
- ptr = &ptr->operator[](array_index(reference_token));
+ ptr = &ptr->operator[](array_index(reference_token));
break;
}
@@ -471,7 +491,7 @@ class json_pointer
case detail::value_t::binary:
case detail::value_t::discarded:
default:
- JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + reference_token + "'", *ptr));
+ JSON_THROW(detail::out_of_range::create(404, detail::concat("unresolved reference token '", reference_token, "'"), ptr));
}
}
@@ -484,6 +504,7 @@ class json_pointer
@throw out_of_range.402 if the array index '-' is used
@throw out_of_range.404 if the JSON pointer can not be resolved
*/
+ template
const BasicJsonType& get_checked(const BasicJsonType* ptr) const
{
for (const auto& reference_token : reference_tokens)
@@ -502,13 +523,13 @@ class json_pointer
if (JSON_HEDLEY_UNLIKELY(reference_token == "-"))
{
// "-" always fails the range check
- JSON_THROW(detail::out_of_range::create(402,
- "array index '-' (" + std::to_string(ptr->m_value.array->size()) +
- ") is out of range", *ptr));
+ JSON_THROW(detail::out_of_range::create(402, detail::concat(
+ "array index '-' (", std::to_string(ptr->m_value.array->size()),
+ ") is out of range"), ptr));
}
// note: at performs range check
- ptr = &ptr->at(array_index(reference_token));
+ ptr = &ptr->at(array_index(reference_token));
break;
}
@@ -521,7 +542,7 @@ class json_pointer
case detail::value_t::binary:
case detail::value_t::discarded:
default:
- JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + reference_token + "'", *ptr));
+ JSON_THROW(detail::out_of_range::create(404, detail::concat("unresolved reference token '", reference_token, "'"), ptr));
}
}
@@ -532,6 +553,7 @@ class json_pointer
@throw parse_error.106 if an array index begins with '0'
@throw parse_error.109 if an array index was not a number
*/
+ template
bool contains(const BasicJsonType* ptr) const
{
for (const auto& reference_token : reference_tokens)
@@ -579,7 +601,7 @@ class json_pointer
}
}
- const auto idx = array_index(reference_token);
+ const auto idx = array_index(reference_token);
if (idx >= ptr->size())
{
// index out of range
@@ -620,9 +642,9 @@ class json_pointer
@throw parse_error.107 if the pointer is not empty or begins with '/'
@throw parse_error.108 if character '~' is not followed by '0' or '1'
*/
- static std::vector split(const std::string& reference_string)
+ static std::vector split(const string_t& reference_string)
{
- std::vector result;
+ std::vector result;
// special case: empty reference string -> no reference tokens
if (reference_string.empty())
@@ -633,7 +655,7 @@ class json_pointer
// check if nonempty reference string begins with slash
if (JSON_HEDLEY_UNLIKELY(reference_string[0] != '/'))
{
- JSON_THROW(detail::parse_error::create(107, 1, "JSON pointer must be empty or begin with '/' - was: '" + reference_string + "'", BasicJsonType()));
+ JSON_THROW(detail::parse_error::create(107, 1, detail::concat("JSON pointer must be empty or begin with '/' - was: '", reference_string, "'"), nullptr));
}
// extract the reference tokens:
@@ -644,11 +666,11 @@ class json_pointer
std::size_t slash = reference_string.find_first_of('/', 1),
// set the beginning of the first reference token
start = 1;
- // we can stop if start == 0 (if slash == std::string::npos)
+ // we can stop if start == 0 (if slash == string_t::npos)
start != 0;
// set the beginning of the next reference token
- // (will eventually be 0 if slash == std::string::npos)
- start = (slash == std::string::npos) ? 0 : slash + 1,
+ // (will eventually be 0 if slash == string_t::npos)
+ start = (slash == string_t::npos) ? 0 : slash + 1,
// find next slash
slash = reference_string.find_first_of('/', start))
{
@@ -658,7 +680,7 @@ class json_pointer
// check reference tokens are properly escaped
for (std::size_t pos = reference_token.find_first_of('~');
- pos != std::string::npos;
+ pos != string_t::npos;
pos = reference_token.find_first_of('~', pos + 1))
{
JSON_ASSERT(reference_token[pos] == '~');
@@ -668,7 +690,7 @@ class json_pointer
(reference_token[pos + 1] != '0' &&
reference_token[pos + 1] != '1')))
{
- JSON_THROW(detail::parse_error::create(108, 0, "escape character '~' must be followed with '0' or '1'", BasicJsonType()));
+ JSON_THROW(detail::parse_error::create(108, 0, "escape character '~' must be followed with '0' or '1'", nullptr));
}
}
@@ -688,7 +710,8 @@ class json_pointer
@note Empty objects or arrays are flattened to `null`.
*/
- static void flatten(const std::string& reference_string,
+ template
+ static void flatten(const string_t& reference_string,
const BasicJsonType& value,
BasicJsonType& result)
{
@@ -706,7 +729,7 @@ class json_pointer
// iterate array and use index as reference string
for (std::size_t i = 0; i < value.m_value.array->size(); ++i)
{
- flatten(reference_string + "/" + std::to_string(i),
+ flatten(detail::concat(reference_string, '/', std::to_string(i)),
value.m_value.array->operator[](i), result);
}
}
@@ -725,7 +748,7 @@ class json_pointer
// iterate object and use keys as reference string
for (const auto& element : *value.m_value.object)
{
- flatten(reference_string + "/" + detail::escape(element.first), element.second, result);
+ flatten(detail::concat(reference_string, '/', detail::escape(element.first)), element.second, result);
}
}
break;
@@ -758,12 +781,13 @@ class json_pointer
@throw type_error.315 if object values are not primitive
@throw type_error.313 if value cannot be unflattened
*/
+ template
static BasicJsonType
unflatten(const BasicJsonType& value)
{
if (JSON_HEDLEY_UNLIKELY(!value.is_object()))
{
- JSON_THROW(detail::type_error::create(314, "only objects can be unflattened", value));
+ JSON_THROW(detail::type_error::create(314, "only objects can be unflattened", &value));
}
BasicJsonType result;
@@ -773,7 +797,7 @@ class json_pointer
{
if (JSON_HEDLEY_UNLIKELY(!element.second.is_primitive()))
{
- JSON_THROW(detail::type_error::create(315, "values in object must be primitive", element.second));
+ JSON_THROW(detail::type_error::create(315, "values in object must be primitive", &element.second));
}
// assign value to reference pointed to by JSON pointer; Note that if
@@ -786,6 +810,21 @@ class json_pointer
return result;
}
+ // can't use conversion operator because of ambiguity
+ json_pointer convert() const&
+ {
+ json_pointer result;
+ result.reference_tokens = reference_tokens;
+ return result;
+ }
+
+ json_pointer convert()&&
+ {
+ json_pointer result;
+ result.reference_tokens = std::move(reference_tokens);
+ return result;
+ }
+
/*!
@brief compares two JSON pointers for equality
@@ -797,11 +836,10 @@ class json_pointer
@exceptionsafety No-throw guarantee: this function never throws exceptions.
*/
- friend bool operator==(json_pointer const& lhs,
- json_pointer const& rhs) noexcept
- {
- return lhs.reference_tokens == rhs.reference_tokens;
- }
+ template
+ // NOLINTNEXTLINE(readability-redundant-declaration)
+ friend bool operator==(json_pointer const& lhs,
+ json_pointer const& rhs) noexcept;
/*!
@brief compares two JSON pointers for inequality
@@ -814,13 +852,27 @@ class json_pointer
@exceptionsafety No-throw guarantee: this function never throws exceptions.
*/
- friend bool operator!=(json_pointer const& lhs,
- json_pointer const& rhs) noexcept
- {
- return !(lhs == rhs);
- }
+ template
+ // NOLINTNEXTLINE(readability-redundant-declaration)
+ friend bool operator!=(json_pointer const& lhs,
+ json_pointer const& rhs) noexcept;
/// the reference tokens
- std::vector reference_tokens;
+ std::vector reference_tokens;
};
+
+// functions cannot be defined inside class due to ODR violations
+template
+inline bool operator==(json_pointer const& lhs,
+ json_pointer const& rhs) noexcept
+{
+ return lhs.reference_tokens == rhs.reference_tokens;
+}
+
+template
+inline bool operator!=(json_pointer const& lhs,
+ json_pointer const& rhs) noexcept
+{
+ return !(lhs == rhs);
+}
} // namespace nlohmann
diff --git a/include/nlohmann/detail/meta/type_traits.hpp b/include/nlohmann/detail/meta/type_traits.hpp
index 0a320e6e21..376c00a097 100644
--- a/include/nlohmann/detail/meta/type_traits.hpp
+++ b/include/nlohmann/detail/meta/type_traits.hpp
@@ -44,6 +44,21 @@ template struct is_basic_json : std::false_type {};
NLOHMANN_BASIC_JSON_TPL_DECLARATION
struct is_basic_json : std::true_type {};
+// used by exceptions create() member functions
+// true_type for pointer to possibly cv-qualified basic_json or std::nullptr_t
+// false_type otherwise
+template
+struct is_basic_json_context :
+ std::integral_constant < bool,
+ is_basic_json::type>::type>::value
+ || std::is_same::value >
+{};
+
+template struct is_json_pointer : std::false_type {};
+
+template
+struct is_json_pointer> : std::true_type {};
+
//////////////////////
// json_ref helpers //
//////////////////////
diff --git a/include/nlohmann/detail/output/binary_writer.hpp b/include/nlohmann/detail/output/binary_writer.hpp
index 598587141f..c018b8ccd7 100644
--- a/include/nlohmann/detail/output/binary_writer.hpp
+++ b/include/nlohmann/detail/output/binary_writer.hpp
@@ -12,6 +12,7 @@
#include
#include
#include
+#include
namespace nlohmann
{
@@ -67,7 +68,7 @@ class binary_writer
case value_t::discarded:
default:
{
- JSON_THROW(type_error::create(317, "to serialize to BSON, top-level type must be object, but is " + std::string(j.type_name()), j));
+ JSON_THROW(type_error::create(317, concat("to serialize to BSON, top-level type must be object, but is ", j.type_name()), &j));
}
}
}
@@ -937,7 +938,7 @@ class binary_writer
const auto it = name.find(static_cast(0));
if (JSON_HEDLEY_UNLIKELY(it != BasicJsonType::string_t::npos))
{
- JSON_THROW(out_of_range::create(409, "BSON key cannot contain code point U+0000 (at byte " + std::to_string(it) + ")", j));
+ JSON_THROW(out_of_range::create(409, concat("BSON key cannot contain code point U+0000 (at byte ", std::to_string(it), ")"), &j));
static_cast(j);
}
@@ -1062,7 +1063,7 @@ class binary_writer
}
else
{
- JSON_THROW(out_of_range::create(407, "integer number " + std::to_string(j.m_value.number_unsigned) + " cannot be represented by BSON as it does not fit int64", j));
+ JSON_THROW(out_of_range::create(407, concat("integer number ", std::to_string(j.m_value.number_unsigned), " cannot be represented by BSON as it does not fit int64"), &j));
}
}
diff --git a/include/nlohmann/detail/output/serializer.hpp b/include/nlohmann/detail/output/serializer.hpp
index e475ef959d..b6349ea8f9 100644
--- a/include/nlohmann/detail/output/serializer.hpp
+++ b/include/nlohmann/detail/output/serializer.hpp
@@ -19,6 +19,7 @@
#include
#include
#include
+#include
#include
namespace nlohmann
@@ -500,7 +501,7 @@ class serializer
{
case error_handler_t::strict:
{
- JSON_THROW(type_error::create(316, "invalid UTF-8 byte at index " + std::to_string(i) + ": 0x" + hex_bytes(byte | 0), BasicJsonType()));
+ JSON_THROW(type_error::create(316, concat("invalid UTF-8 byte at index ", std::to_string(i), ": 0x", hex_bytes(byte | 0)), nullptr));
}
case error_handler_t::ignore:
@@ -592,7 +593,7 @@ class serializer
{
case error_handler_t::strict:
{
- JSON_THROW(type_error::create(316, "incomplete UTF-8 string; last byte: 0x" + hex_bytes(static_cast(s.back() | 0)), BasicJsonType()));
+ JSON_THROW(type_error::create(316, concat("incomplete UTF-8 string; last byte: 0x", hex_bytes(static_cast(s.back() | 0))), nullptr));
}
case error_handler_t::ignore:
diff --git a/include/nlohmann/detail/string_concat.hpp b/include/nlohmann/detail/string_concat.hpp
new file mode 100644
index 0000000000..12f62289fe
--- /dev/null
+++ b/include/nlohmann/detail/string_concat.hpp
@@ -0,0 +1,139 @@
+#pragma once
+
+#include // strlen
+#include // string
+#include // forward
+
+#include
+#include
+
+namespace nlohmann
+{
+namespace detail
+{
+
+inline std::size_t concat_length()
+{
+ return 0;
+}
+
+template
+inline std::size_t concat_length(const char* cstr, Args&& ... rest);
+
+template
+inline std::size_t concat_length(const StringType& str, Args&& ... rest);
+
+template
+inline std::size_t concat_length(const char /*c*/, Args&& ... rest)
+{
+ return 1 + concat_length(std::forward(rest)...);
+}
+
+template
+inline std::size_t concat_length(const char* cstr, Args&& ... rest)
+{
+ // cppcheck-suppress ignoredReturnValue
+ return ::strlen(cstr) + concat_length(std::forward(rest)...);
+}
+
+template
+inline std::size_t concat_length(const StringType& str, Args&& ... rest)
+{
+ return str.size() + concat_length(std::forward(rest)...);
+}
+
+template
+inline void concat_into(OutStringType& /*out*/)
+{}
+
+template
+using string_can_append = decltype(std::declval().append(std::declval < Arg && > ()));
+
+template
+using detect_string_can_append = is_detected;
+
+template
+using string_can_append_op = decltype(std::declval() += std::declval < Arg && > ());
+
+template
+using detect_string_can_append_op = is_detected;
+
+template
+using string_can_append_iter = decltype(std::declval().append(std::declval().begin(), std::declval().end()));
+
+template
+using detect_string_can_append_iter = is_detected;
+
+template
+using string_can_append_data = decltype(std::declval().append(std::declval().data(), std::declval().size()));
+
+template
+using detect_string_can_append_data = is_detected;
+
+template < typename OutStringType, typename Arg, typename... Args,
+ enable_if_t < !detect_string_can_append::value
+ && detect_string_can_append_op::value, int > = 0 >
+inline void concat_into(OutStringType& out, Arg && arg, Args && ... rest);
+
+template < typename OutStringType, typename Arg, typename... Args,
+ enable_if_t < !detect_string_can_append::value
+ && !detect_string_can_append_op::value
+ && detect_string_can_append_iter::value, int > = 0 >
+inline void concat_into(OutStringType& out, const Arg& arg, Args && ... rest);
+
+template < typename OutStringType, typename Arg, typename... Args,
+ enable_if_t < !detect_string_can_append::value
+ && !detect_string_can_append_op::value
+ && !detect_string_can_append_iter::value
+ && detect_string_can_append_data::value, int > = 0 >
+inline void concat_into(OutStringType& out, const Arg& arg, Args && ... rest);
+
+template::value, int> = 0>
+inline void concat_into(OutStringType& out, Arg && arg, Args && ... rest)
+{
+ out.append(std::forward(arg));
+ concat_into(out, std::forward(rest)...);
+}
+
+template < typename OutStringType, typename Arg, typename... Args,
+ enable_if_t < !detect_string_can_append::value
+ && detect_string_can_append_op::value, int > >
+inline void concat_into(OutStringType& out, Arg&& arg, Args&& ... rest)
+{
+ out += std::forward(arg);
+ concat_into(out, std::forward(rest)...);
+}
+
+template < typename OutStringType, typename Arg, typename... Args,
+ enable_if_t < !detect_string_can_append::value
+ && !detect_string_can_append_op::value
+ && detect_string_can_append_iter::value, int > >
+inline void concat_into(OutStringType& out, const Arg& arg, Args&& ... rest)
+{
+ out.append(arg.begin(), arg.end());
+ concat_into(out, std::forward(rest)...);
+}
+
+template < typename OutStringType, typename Arg, typename... Args,
+ enable_if_t < !detect_string_can_append::value
+ && !detect_string_can_append_op::value
+ && !detect_string_can_append_iter::value
+ && detect_string_can_append_data::value, int > >
+inline void concat_into(OutStringType& out, const Arg& arg, Args&& ... rest)
+{
+ out.append(arg.data(), arg.size());
+ concat_into(out, std::forward(rest)...);
+}
+
+template
+inline OutStringType concat(Args && ... args)
+{
+ OutStringType str;
+ str.reserve(concat_length(std::forward(args)...));
+ concat_into(str, std::forward(args)...);
+ return str;
+}
+
+} // namespace detail
+} // namespace nlohmann
diff --git a/include/nlohmann/detail/string_escape.hpp b/include/nlohmann/detail/string_escape.hpp
index 84f7da52e0..8911239dfc 100644
--- a/include/nlohmann/detail/string_escape.hpp
+++ b/include/nlohmann/detail/string_escape.hpp
@@ -1,6 +1,5 @@
#pragma once
-#include
#include
namespace nlohmann
@@ -21,12 +20,13 @@ enforced with an assertion.**
@since version 2.0.0
*/
-inline void replace_substring(std::string& s, const std::string& f,
- const std::string& t)
+template
+inline void replace_substring(StringType& s, const StringType& f,
+ const StringType& t)
{
JSON_ASSERT(!f.empty());
for (auto pos = s.find(f); // find first occurrence of f
- pos != std::string::npos; // make sure f was found
+ pos != StringType::npos; // make sure f was found
s.replace(pos, f.size(), t), // replace with t, and
pos = s.find(f, pos + t.size())) // find next occurrence of f
{}
@@ -39,10 +39,11 @@ inline void replace_substring(std::string& s, const std::string& f,
*
* Note the order of escaping "~" to "~0" and "/" to "~1" is important.
*/
-inline std::string escape(std::string s)
+template
+inline StringType escape(StringType s)
{
- replace_substring(s, "~", "~0");
- replace_substring(s, "/", "~1");
+ replace_substring(s, StringType{"~"}, StringType{"~0"});
+ replace_substring(s, StringType{"/"}, StringType{"~1"});
return s;
}
@@ -53,10 +54,11 @@ inline std::string escape(std::string s)
*
* Note the order of escaping "~1" to "/" and "~0" to "~" is important.
*/
-static void unescape(std::string& s)
+template
+static void unescape(StringType& s)
{
- replace_substring(s, "~1", "/");
- replace_substring(s, "~0", "~");
+ replace_substring(s, StringType{"~1"}, StringType{"/"});
+ replace_substring(s, StringType{"~0"}, StringType{"~"});
}
} // namespace detail
diff --git a/include/nlohmann/json.hpp b/include/nlohmann/json.hpp
index b776708031..1a2da8d45e 100644
--- a/include/nlohmann/json.hpp
+++ b/include/nlohmann/json.hpp
@@ -83,6 +83,7 @@ SOFTWARE.
#include
#include
#include
+#include
#include
#include
#include
@@ -129,7 +130,11 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
{
private:
template friend struct detail::external_constructor;
- friend ::nlohmann::json_pointer;
+
+ template
+ friend class ::nlohmann::json_pointer;
+ // can be restored when json_pointer backwards compatibility is removed
+ // friend ::nlohmann::json_pointer;
template
friend class ::nlohmann::detail::parser;
@@ -188,7 +193,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
public:
using value_t = detail::value_t;
/// JSON Pointer, see @ref nlohmann::json_pointer
- using json_pointer = ::nlohmann::json_pointer;
+ using json_pointer = ::nlohmann::json_pointer;
template
using json_serializer = JSONSerializer;
/// how to treat decoding errors
@@ -280,9 +285,9 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
result["name"] = "JSON for Modern C++";
result["url"] = "https://github.com/nlohmann/json";
result["version"]["string"] =
- std::to_string(NLOHMANN_JSON_VERSION_MAJOR) + "." +
- std::to_string(NLOHMANN_JSON_VERSION_MINOR) + "." +
- std::to_string(NLOHMANN_JSON_VERSION_PATCH);
+ detail::concat(std::to_string(NLOHMANN_JSON_VERSION_MAJOR), '.',
+ std::to_string(NLOHMANN_JSON_VERSION_MINOR), '.',
+ std::to_string(NLOHMANN_JSON_VERSION_PATCH));
result["version"]["major"] = NLOHMANN_JSON_VERSION_MAJOR;
result["version"]["minor"] = NLOHMANN_JSON_VERSION_MINOR;
result["version"]["patch"] = NLOHMANN_JSON_VERSION_PATCH;
@@ -304,7 +309,12 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
#elif defined(__clang__)
result["compiler"] = {{"family", "clang"}, {"version", __clang_version__}};
#elif defined(__GNUC__) || defined(__GNUG__)
- result["compiler"] = {{"family", "gcc"}, {"version", std::to_string(__GNUC__) + "." + std::to_string(__GNUC_MINOR__) + "." + std::to_string(__GNUC_PATCHLEVEL__)}};
+ result["compiler"] = {{"family", "gcc"}, {"version", detail::concat(
+ std::to_string(__GNUC__), '.',
+ std::to_string(__GNUC_MINOR__), '.',
+ std::to_string(__GNUC_PATCHLEVEL__))
+ }
+ };
#elif defined(__HP_cc) || defined(__HP_aCC)
result["compiler"] = "hp"
#elif defined(__IBMCPP__)
@@ -532,7 +542,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
object = nullptr; // silence warning, see #821
if (JSON_HEDLEY_UNLIKELY(t == value_t::null))
{
- JSON_THROW(other_error::create(500, "961c151d2e87f2686a955a9be24d316f1362bf21 3.10.5", basic_json())); // LCOV_EXCL_LINE
+ JSON_THROW(other_error::create(500, "961c151d2e87f2686a955a9be24d316f1362bf21 3.10.5", nullptr)); // LCOV_EXCL_LINE
}
break;
}
@@ -930,7 +940,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
// if object is wanted but impossible, throw an exception
if (JSON_HEDLEY_UNLIKELY(manual_type == value_t::object && !is_an_object))
{
- JSON_THROW(type_error::create(301, "cannot create object from initializer list", basic_json()));
+ JSON_THROW(type_error::create(301, "cannot create object from initializer list", nullptr));
}
}
@@ -1042,7 +1052,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
// make sure iterator fits the current value
if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object))
{
- JSON_THROW(invalid_iterator::create(201, "iterators are not compatible", basic_json()));
+ JSON_THROW(invalid_iterator::create(201, "iterators are not compatible", nullptr));
}
// copy type from first iterator
@@ -1060,7 +1070,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
if (JSON_HEDLEY_UNLIKELY(!first.m_it.primitive_iterator.is_begin()
|| !last.m_it.primitive_iterator.is_end()))
{
- JSON_THROW(invalid_iterator::create(204, "iterators out of range", *first.m_object));
+ JSON_THROW(invalid_iterator::create(204, "iterators out of range", first.m_object));
}
break;
}
@@ -1129,7 +1139,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
case value_t::null:
case value_t::discarded:
default:
- JSON_THROW(invalid_iterator::create(206, "cannot construct with iterators from " + std::string(first.m_object->type_name()), *first.m_object));
+ JSON_THROW(invalid_iterator::create(206, detail::concat("cannot construct with iterators from ", first.m_object->type_name()), first.m_object));
}
set_parents();
@@ -1413,7 +1423,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
return m_value.boolean;
}
- JSON_THROW(type_error::create(302, "type must be boolean, but is " + std::string(type_name()), *this));
+ JSON_THROW(type_error::create(302, detail::concat("type must be boolean, but is ", type_name()), this));
}
/// get a pointer to the value (object)
@@ -1534,7 +1544,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
return *ptr;
}
- JSON_THROW(type_error::create(303, "incompatible ReferenceType for get_ref, actual type is " + std::string(obj.type_name()), obj));
+ JSON_THROW(type_error::create(303, detail::concat("incompatible ReferenceType for get_ref, actual type is ", obj.type_name()), &obj));
}
public:
@@ -1910,7 +1920,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
{
if (!is_binary())
{
- JSON_THROW(type_error::create(302, "type must be binary, but is " + std::string(type_name()), *this));
+ JSON_THROW(type_error::create(302, detail::concat("type must be binary, but is ", type_name()), this));
}
return *get_ptr();
@@ -1922,7 +1932,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
{
if (!is_binary())
{
- JSON_THROW(type_error::create(302, "type must be binary, but is " + std::string(type_name()), *this));
+ JSON_THROW(type_error::create(302, detail::concat("type must be binary, but is ", type_name()), this));
}
return *get_ptr();
@@ -1953,12 +1963,12 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
JSON_CATCH (std::out_of_range&)
{
// create better exception explanation
- JSON_THROW(out_of_range::create(401, "array index " + std::to_string(idx) + " is out of range", *this));
+ JSON_THROW(out_of_range::create(401, detail::concat("array index ", std::to_string(idx), " is out of range"), this));
}
}
else
{
- JSON_THROW(type_error::create(304, "cannot use at() with " + std::string(type_name()), *this));
+ JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this));
}
}
@@ -1976,12 +1986,12 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
JSON_CATCH (std::out_of_range&)
{
// create better exception explanation
- JSON_THROW(out_of_range::create(401, "array index " + std::to_string(idx) + " is out of range", *this));
+ JSON_THROW(out_of_range::create(401, detail::concat("array index ", std::to_string(idx), " is out of range"), this));
}
}
else
{
- JSON_THROW(type_error::create(304, "cannot use at() with " + std::string(type_name()), *this));
+ JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this));
}
}
@@ -1999,12 +2009,12 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
JSON_CATCH (std::out_of_range&)
{
// create better exception explanation
- JSON_THROW(out_of_range::create(403, "key '" + key + "' not found", *this));
+ JSON_THROW(out_of_range::create(403, detail::concat("key '", key, "' not found"), this));
}
}
else
{
- JSON_THROW(type_error::create(304, "cannot use at() with " + std::string(type_name()), *this));
+ JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this));
}
}
@@ -2022,12 +2032,12 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
JSON_CATCH (std::out_of_range&)
{
// create better exception explanation
- JSON_THROW(out_of_range::create(403, "key '" + key + "' not found", *this));
+ JSON_THROW(out_of_range::create(403, detail::concat("key '", key, "' not found"), this));
}
}
else
{
- JSON_THROW(type_error::create(304, "cannot use at() with " + std::string(type_name()), *this));
+ JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this));
}
}
@@ -2074,7 +2084,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
return m_value.array->operator[](idx);
}
- JSON_THROW(type_error::create(305, "cannot use operator[] with a numeric argument with " + std::string(type_name()), *this));
+ JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a numeric argument with ", type_name()), this));
}
/// @brief access specified array element
@@ -2087,7 +2097,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
return m_value.array->operator[](idx);
}
- JSON_THROW(type_error::create(305, "cannot use operator[] with a numeric argument with " + std::string(type_name()), *this));
+ JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a numeric argument with ", type_name()), this));
}
/// @brief access specified object element
@@ -2108,7 +2118,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
return set_parent(m_value.object->operator[](key));
}
- JSON_THROW(type_error::create(305, "cannot use operator[] with a string argument with " + std::string(type_name()), *this));
+ JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a string argument with ", type_name()), this));
}
/// @brief access specified object element
@@ -2122,7 +2132,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
return m_value.object->find(key)->second;
}
- JSON_THROW(type_error::create(305, "cannot use operator[] with a string argument with " + std::string(type_name()), *this));
+ JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a string argument with ", type_name()), this));
}
/// @brief access specified object element
@@ -2145,7 +2155,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
return set_parent(m_value.object->operator[](key));
}
- JSON_THROW(type_error::create(305, "cannot use operator[] with a string argument with " + std::string(type_name()), *this));
+ JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a string argument with ", type_name()), this));
}
/// @brief access specified object element
@@ -2161,7 +2171,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
return m_value.object->find(key)->second;
}
- JSON_THROW(type_error::create(305, "cannot use operator[] with a string argument with " + std::string(type_name()), *this));
+ JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a string argument with ", type_name()), this));
}
/// @brief access specified object element with default value
@@ -2185,7 +2195,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
return default_value;
}
- JSON_THROW(type_error::create(306, "cannot use value() with " + std::string(type_name()), *this));
+ JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
}
/// @brief access specified object element with default value
@@ -2216,7 +2226,15 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
}
}
- JSON_THROW(type_error::create(306, "cannot use value() with " + std::string(type_name()), *this));
+ JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
+ }
+
+ template::value, int>::type = 0>
+ JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer) // NOLINT(readability/alt_tokens)
+ ValueType value(const ::nlohmann::json_pointer& ptr, const ValueType& default_value) const
+ {
+ return value(ptr.convert(), default_value);
}
/// @brief access specified object element via JSON Pointer with default value
@@ -2228,6 +2246,14 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
return value(ptr, string_t(default_value));
}
+ template
+ JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer) // NOLINT(readability/alt_tokens)
+ JSON_HEDLEY_NON_NULL(3)
+ string_t value(const typename ::nlohmann::json_pointer& ptr, const char* default_value) const
+ {
+ return value(ptr.convert(), default_value);
+ }
+
/// @brief access the first element
/// @sa https://json.nlohmann.me/api/basic_json/front/
reference front()
@@ -2271,7 +2297,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
// make sure iterator fits the current value
if (JSON_HEDLEY_UNLIKELY(this != pos.m_object))
{
- JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", *this));
+ JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", this));
}
IteratorType result = end();
@@ -2287,7 +2313,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
{
if (JSON_HEDLEY_UNLIKELY(!pos.m_it.primitive_iterator.is_begin()))
{
- JSON_THROW(invalid_iterator::create(205, "iterator out of range", *this));
+ JSON_THROW(invalid_iterator::create(205, "iterator out of range", this));
}
if (is_string())
@@ -2325,7 +2351,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
case value_t::null:
case value_t::discarded:
default:
- JSON_THROW(type_error::create(307, "cannot use erase() with " + std::string(type_name()), *this));
+ JSON_THROW(type_error::create(307, detail::concat("cannot use erase() with ", type_name()), this));
}
return result;
@@ -2342,7 +2368,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
// make sure iterator fits the current value
if (JSON_HEDLEY_UNLIKELY(this != first.m_object || this != last.m_object))
{
- JSON_THROW(invalid_iterator::create(203, "iterators do not fit current value", *this));
+ JSON_THROW(invalid_iterator::create(203, "iterators do not fit current value", this));
}
IteratorType result = end();
@@ -2359,7 +2385,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
if (JSON_HEDLEY_LIKELY(!first.m_it.primitive_iterator.is_begin()
|| !last.m_it.primitive_iterator.is_end()))
{
- JSON_THROW(invalid_iterator::create(204, "iterators out of range", *this));
+ JSON_THROW(invalid_iterator::create(204, "iterators out of range", this));
}
if (is_string())
@@ -2399,7 +2425,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
case value_t::null:
case value_t::discarded:
default:
- JSON_THROW(type_error::create(307, "cannot use erase() with " + std::string(type_name()), *this));
+ JSON_THROW(type_error::create(307, detail::concat("cannot use erase() with ", type_name()), this));
}
return result;
@@ -2415,7 +2441,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
return m_value.object->erase(key);
}
- JSON_THROW(type_error::create(307, "cannot use erase() with " + std::string(type_name()), *this));
+ JSON_THROW(type_error::create(307, detail::concat("cannot use erase() with ", type_name()), this));
}
/// @brief remove element from a JSON array given an index
@@ -2427,14 +2453,14 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
{
if (JSON_HEDLEY_UNLIKELY(idx >= size()))
{
- JSON_THROW(out_of_range::create(401, "array index " + std::to_string(idx) + " is out of range", *this));
+ JSON_THROW(out_of_range::create(401, detail::concat("array index ", std::to_string(idx), " is out of range"), this));
}
m_value.array->erase(m_value.array->begin() + static_cast(idx));
}
else
{
- JSON_THROW(type_error::create(307, "cannot use erase() with " + std::string(type_name()), *this));
+ JSON_THROW(type_error::create(307, detail::concat("cannot use erase() with ", type_name()), this));
}
}
@@ -2490,7 +2516,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
/// @brief check the existence of an element in a JSON object
/// @sa https://json.nlohmann.me/api/basic_json/contains/
template < typename KeyT, typename std::enable_if <
- !std::is_same::type, json_pointer>::value, int >::type = 0 >
+ !detail::is_json_pointer::type>::value, int >::type = 0 >
bool contains(KeyT && key) const
{
return is_object() && m_value.object->find(std::forward(key)) != m_value.object->end();
@@ -2503,6 +2529,13 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
return ptr.contains(this);
}
+ template
+ JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer) // NOLINT(readability/alt_tokens)
+ bool contains(const typename ::nlohmann::json_pointer ptr) const
+ {
+ return ptr.contains(this);
+ }
+
/// @}
@@ -2842,7 +2875,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
// push_back only works for null objects or arrays
if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_array())))
{
- JSON_THROW(type_error::create(308, "cannot use push_back() with " + std::string(type_name()), *this));
+ JSON_THROW(type_error::create(308, detail::concat("cannot use push_back() with ", type_name()), this));
}
// transform null object into an array
@@ -2875,7 +2908,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
// push_back only works for null objects or arrays
if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_array())))
{
- JSON_THROW(type_error::create(308, "cannot use push_back() with " + std::string(type_name()), *this));
+ JSON_THROW(type_error::create(308, detail::concat("cannot use push_back() with ", type_name()), this));
}
// transform null object into an array
@@ -2907,7 +2940,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
// push_back only works for null objects or objects
if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_object())))
{
- JSON_THROW(type_error::create(308, "cannot use push_back() with " + std::string(type_name()), *this));
+ JSON_THROW(type_error::create(308, detail::concat("cannot use push_back() with ", type_name()), this));
}
// transform null object into an object
@@ -2963,7 +2996,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
// emplace_back only works for null objects or arrays
if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_array())))
{
- JSON_THROW(type_error::create(311, "cannot use emplace_back() with " + std::string(type_name()), *this));
+ JSON_THROW(type_error::create(311, detail::concat("cannot use emplace_back() with ", type_name()), this));
}
// transform null object into an array
@@ -2988,7 +3021,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
// emplace only works for null objects or arrays
if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_object())))
{
- JSON_THROW(type_error::create(311, "cannot use emplace() with " + std::string(type_name()), *this));
+ JSON_THROW(type_error::create(311, detail::concat("cannot use emplace() with ", type_name()), this));
}
// transform null object into an object
@@ -3042,14 +3075,14 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
// check if iterator pos fits to this JSON value
if (JSON_HEDLEY_UNLIKELY(pos.m_object != this))
{
- JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", *this));
+ JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", this));
}
// insert to array and return iterator
return insert_iterator(pos, val);
}
- JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name()), *this));
+ JSON_THROW(type_error::create(309, detail::concat("cannot use insert() with ", type_name()), this));
}
/// @brief inserts element into array
@@ -3069,14 +3102,14 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
// check if iterator pos fits to this JSON value
if (JSON_HEDLEY_UNLIKELY(pos.m_object != this))
{
- JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", *this));
+ JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", this));
}
// insert to array and return iterator
return insert_iterator(pos, cnt, val);
}
- JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name()), *this));
+ JSON_THROW(type_error::create(309, detail::concat("cannot use insert() with ", type_name()), this));
}
/// @brief inserts range of elements into array
@@ -3086,24 +3119,24 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
// insert only works for arrays
if (JSON_HEDLEY_UNLIKELY(!is_array()))
{
- JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name()), *this));
+ JSON_THROW(type_error::create(309, detail::concat("cannot use insert() with ", type_name()), this));
}
// check if iterator pos fits to this JSON value
if (JSON_HEDLEY_UNLIKELY(pos.m_object != this))
{
- JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", *this));
+ JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", this));
}
// check if range iterators belong to the same JSON object
if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object))
{
- JSON_THROW(invalid_iterator::create(210, "iterators do not fit", *this));
+ JSON_THROW(invalid_iterator::create(210, "iterators do not fit", this));
}
if (JSON_HEDLEY_UNLIKELY(first.m_object == this))
{
- JSON_THROW(invalid_iterator::create(211, "passed iterators may not belong to container", *this));
+ JSON_THROW(invalid_iterator::create(211, "passed iterators may not belong to container", this));
}
// insert to array and return iterator
@@ -3117,13 +3150,13 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
// insert only works for arrays
if (JSON_HEDLEY_UNLIKELY(!is_array()))
{
- JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name()), *this));
+ JSON_THROW(type_error::create(309, detail::concat("cannot use insert() with ", type_name()), this));
}
// check if iterator pos fits to this JSON value
if (JSON_HEDLEY_UNLIKELY(pos.m_object != this))
{
- JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", *this));
+ JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", this));
}
// insert to array and return iterator
@@ -3137,19 +3170,19 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
// insert only works for objects
if (JSON_HEDLEY_UNLIKELY(!is_object()))
{
- JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name()), *this));
+ JSON_THROW(type_error::create(309, detail::concat("cannot use insert() with ", type_name()), this));
}
// check if range iterators belong to the same JSON object
if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object))
{
- JSON_THROW(invalid_iterator::create(210, "iterators do not fit", *this));
+ JSON_THROW(invalid_iterator::create(210, "iterators do not fit", this));
}
// passed iterators must belong to objects
if (JSON_HEDLEY_UNLIKELY(!first.m_object->is_object()))
{
- JSON_THROW(invalid_iterator::create(202, "iterators first and last must point to objects", *this));
+ JSON_THROW(invalid_iterator::create(202, "iterators first and last must point to objects", this));
}
m_value.object->insert(first.m_it.object_iterator, last.m_it.object_iterator);
@@ -3176,19 +3209,19 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
if (JSON_HEDLEY_UNLIKELY(!is_object()))
{
- JSON_THROW(type_error::create(312, "cannot use update() with " + std::string(type_name()), *this));
+ JSON_THROW(type_error::create(312, detail::concat("cannot use update() with ", type_name()), this));
}
// check if range iterators belong to the same JSON object
if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object))
{
- JSON_THROW(invalid_iterator::create(210, "iterators do not fit", *this));
+ JSON_THROW(invalid_iterator::create(210, "iterators do not fit", this));
}
// passed iterators must belong to objects
if (JSON_HEDLEY_UNLIKELY(!first.m_object->is_object()))
{
- JSON_THROW(type_error::create(312, "cannot use update() with " + std::string(first.m_object->type_name()), *first.m_object));
+ JSON_THROW(type_error::create(312, detail::concat("cannot use update() with ", first.m_object->type_name()), first.m_object));
}
for (auto it = first; it != last; ++it)
@@ -3249,7 +3282,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
}
else
{
- JSON_THROW(type_error::create(310, "cannot use swap() with " + std::string(type_name()), *this));
+ JSON_THROW(type_error::create(310, detail::concat("cannot use swap() with ", type_name()), this));
}
}
@@ -3264,7 +3297,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
}
else
{
- JSON_THROW(type_error::create(310, "cannot use swap() with " + std::string(type_name()), *this));
+ JSON_THROW(type_error::create(310, detail::concat("cannot use swap() with ", type_name()), this));
}
}
@@ -3279,7 +3312,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
}
else
{
- JSON_THROW(type_error::create(310, "cannot use swap() with " + std::string(type_name()), *this));
+ JSON_THROW(type_error::create(310, detail::concat("cannot use swap() with ", type_name()), this));
}
}
@@ -3294,7 +3327,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
}
else
{
- JSON_THROW(type_error::create(310, "cannot use swap() with " + std::string(type_name()), *this));
+ JSON_THROW(type_error::create(310, detail::concat("cannot use swap() with ", type_name()), this));
}
}
@@ -3309,7 +3342,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
}
else
{
- JSON_THROW(type_error::create(310, "cannot use swap() with " + std::string(type_name()), *this));
+ JSON_THROW(type_error::create(310, detail::concat("cannot use swap() with ", type_name()), this));
}
}
@@ -4191,6 +4224,13 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
return ptr.get_unchecked(this);
}
+ template
+ JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer