summaryrefslogtreecommitdiff
path: root/vendor/jsoncons-0.104.0/jsoncons_ext/jsonpointer/jsonpointer.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/jsoncons-0.104.0/jsoncons_ext/jsonpointer/jsonpointer.hpp')
-rw-r--r--vendor/jsoncons-0.104.0/jsoncons_ext/jsonpointer/jsonpointer.hpp810
1 files changed, 810 insertions, 0 deletions
diff --git a/vendor/jsoncons-0.104.0/jsoncons_ext/jsonpointer/jsonpointer.hpp b/vendor/jsoncons-0.104.0/jsoncons_ext/jsonpointer/jsonpointer.hpp
new file mode 100644
index 00000000..56b4efa2
--- /dev/null
+++ b/vendor/jsoncons-0.104.0/jsoncons_ext/jsonpointer/jsonpointer.hpp
@@ -0,0 +1,810 @@
+// Copyright 2017 Daniel Parker
+// Distributed under the Boost license, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+// See https://github.com/danielaparker/jsoncons for latest version
+
+#ifndef JSONCONS_JSONPOINTER_JSONPOINTER_HPP
+#define JSONCONS_JSONPOINTER_JSONPOINTER_HPP
+
+#include <string>
+#include <sstream>
+#include <vector>
+#include <istream>
+#include <cstdlib>
+#include <memory>
+#include <jsoncons/json.hpp>
+#include <jsoncons_ext/jsonpointer/jsonpointer_error_category.hpp>
+
+namespace jsoncons { namespace jsonpointer {
+
+class jsonpointer_error : public std::exception, public virtual json_exception
+{
+public:
+ jsonpointer_error(const std::error_code& ec)
+ : error_code_(ec)
+ {
+ }
+ jsonpointer_error(const jsonpointer_error& other) = default;
+
+ jsonpointer_error(jsonpointer_error&& other) = default;
+
+ const char* what() const JSONCONS_NOEXCEPT override
+ {
+ try
+ {
+ const_cast<std::string&>(buffer_) = error_code_.message();
+ return buffer_.c_str();
+ }
+ catch (...)
+ {
+ return "";
+ }
+ }
+
+ const std::error_code code() const
+ {
+ return error_code_;
+ }
+
+ jsonpointer_error& operator=(const jsonpointer_error& e) = default;
+ jsonpointer_error& operator=(jsonpointer_error&& e) = default;
+private:
+ std::string buffer_;
+ std::error_code error_code_;
+};
+
+namespace detail {
+
+enum class pointer_state
+{
+ start,
+ array_reference_token,
+ zero_array_reference_token,
+ nonzero_array_reference_token,
+ after_last_array_reference_token,
+ object_reference_token,
+ escaped
+};
+template <class Json,class JsonReference, class Enable = void>
+class json_wrapper
+{
+};
+
+template <class Json,class JsonReference>
+class json_wrapper<Json,JsonReference,typename std::enable_if<std::is_reference<decltype(std::declval<Json>().at(typename Json::string_view_type()))>::value>::type>
+{
+public:
+ using reference = JsonReference;
+ using pointer = typename std::conditional<std::is_const<typename std::remove_reference<JsonReference>::type>::value,typename Json::const_pointer,typename Json::pointer>::type;
+
+ json_wrapper(reference ref) JSONCONS_NOEXCEPT
+ : ptr_(std::addressof(ref))
+ {
+ }
+
+ json_wrapper(const json_wrapper&) JSONCONS_NOEXCEPT = default;
+
+ json_wrapper& operator=(const json_wrapper&) JSONCONS_NOEXCEPT = default;
+
+ reference get() const JSONCONS_NOEXCEPT
+ {
+ return *ptr_;
+ }
+private:
+ pointer ptr_;
+};
+
+template <class Json,class JsonReference>
+class json_wrapper<Json,JsonReference,typename std::enable_if<!std::is_reference<decltype(std::declval<Json>().at(typename Json::string_view_type()))>::value>::type>
+{
+public:
+ using value_type = typename Json::value_type;
+ using reference = JsonReference;
+ using pointer = typename std::conditional<std::is_const<typename std::remove_reference<JsonReference>::type>::value,typename Json::const_pointer,typename Json::pointer>::type;
+
+ json_wrapper(reference ref) JSONCONS_NOEXCEPT
+ : val_(ref)
+ {
+ }
+
+ json_wrapper(const json_wrapper& w) JSONCONS_NOEXCEPT
+ : val_(w.val_)
+ {
+ }
+
+ json_wrapper& operator=(const json_wrapper&) JSONCONS_NOEXCEPT = default;
+
+ value_type get() const JSONCONS_NOEXCEPT
+ {
+ return val_;
+ }
+private:
+ value_type val_;
+};
+
+template<class Json,class JsonReference>
+struct path_resolver
+{
+ typedef typename Json::string_type string_type;
+ typedef typename Json::string_view_type string_view_type;
+ using reference = JsonReference;
+ using pointer = typename std::conditional<std::is_const<typename std::remove_reference<JsonReference>::type>::value,typename Json::const_pointer,typename Json::pointer>::type;
+
+ jsonpointer_errc operator()(std::vector<json_wrapper<Json,JsonReference>>& current,
+ size_t index) const
+ {
+ if (index >= current.back().get().size())
+ {
+ return jsonpointer_errc::index_exceeds_array_size;
+ }
+ current.push_back(current.back().get().at(index));
+ return jsonpointer_errc();
+ }
+
+ jsonpointer_errc operator()(std::vector<json_wrapper<Json,JsonReference>>& current,
+ const string_view_type& name) const
+ {
+ if (!current.back().get().has_key(name))
+ {
+ return jsonpointer_errc::name_not_found;
+ }
+ current.push_back(current.back().get().at(name));
+ return jsonpointer_errc();
+ }
+};
+
+template<class Json, class JsonReference>
+struct path_setter
+{
+ typedef typename Json::string_type string_type;
+ typedef typename Json::string_view_type string_view_type;
+ using reference = JsonReference;
+ using pointer = typename std::conditional<std::is_const<typename std::remove_reference<JsonReference>::type>::value,typename Json::const_pointer,typename Json::pointer>::type;
+
+ jsonpointer_errc operator()(std::vector<json_wrapper<Json,JsonReference>>& current,
+ size_t index) const
+ {
+ if (index >= current.back().get().size())
+ {
+ return jsonpointer_errc::index_exceeds_array_size;
+ }
+ current.push_back(current.back().get().at(index));
+ return jsonpointer_errc();
+ }
+
+ jsonpointer_errc operator()(std::vector<json_wrapper<Json,JsonReference>>& current,
+ const string_view_type& name) const
+ {
+ jsonpointer_errc ec = jsonpointer_errc();
+ if (!current.back().get().has_key(name))
+ {
+ return jsonpointer_errc::name_not_found;
+ }
+ current.push_back(current.back().get().at(name));
+ return ec;
+ }
+};
+
+template<class Json,class JsonReference>
+class jsonpointer_evaluator : private parsing_context
+{
+ typedef typename Json::string_type string_type;
+ typedef typename string_type::value_type char_type;
+ typedef typename Json::string_view_type string_view_type;
+ using reference = JsonReference;
+ using pointer = typename std::conditional<std::is_const<typename std::remove_reference<JsonReference>::type>::value,typename Json::const_pointer,typename Json::pointer>::type;
+
+ jsonpointer::detail::pointer_state state_;
+ size_t line_;
+ size_t column_;
+ const char_type* begin_input_;
+ const char_type* end_input_;
+ const char_type* p_;
+ string_type buffer_;
+ size_t index_;
+ std::vector<json_wrapper<Json,JsonReference>> current_;
+public:
+ Json get_result()
+ {
+ return std::move(current_.back().get());
+ }
+
+ size_t line_number() const
+ {
+ return line_;
+ }
+
+ size_t column_number() const
+ {
+ return column_;
+ }
+
+ jsonpointer_errc get(reference root, const string_view_type& path)
+ {
+ path_resolver<Json,reference> op;
+ jsonpointer_errc ec = evaluate(root,op,path);
+ if (ec != jsonpointer_errc())
+ {
+ return ec;
+ }
+
+ switch (state_)
+ {
+ case pointer_state::start:
+ break;
+ case pointer_state::zero_array_reference_token:
+ case pointer_state::nonzero_array_reference_token:
+ ec = op(current_,index_);
+ break;
+ case pointer_state::object_reference_token:
+ ec = op(current_,buffer_);
+ break;
+ default:
+ return jsonpointer_errc::end_of_input;
+ }
+ return ec;
+ }
+
+ string_type normalized_path(reference root, const string_view_type& path)
+ {
+ jsonpointer_errc ec = evaluate(root,path_setter<Json,reference>(),path);
+ if (ec != jsonpointer_errc())
+ {
+ return string_type(path);
+ }
+ if (state_ == jsonpointer::detail::pointer_state::after_last_array_reference_token)
+ {
+ string_type p = string_type(path.substr(0,path.length()-1));
+ std::string s = std::to_string(current_.back().get().size());
+ for (auto c : s)
+ {
+ p.push_back(c);
+ }
+ return p;
+ }
+ else
+ {
+ return string_type(path);
+ }
+ }
+
+ jsonpointer_errc insert_or_assign(reference root, const string_view_type& path, const Json& value)
+ {
+ jsonpointer_errc ec = evaluate(root,path_setter<Json,reference>(),path);
+ if (ec != jsonpointer_errc())
+ {
+ return ec;
+ }
+
+ switch (state_)
+ {
+ case jsonpointer::detail::pointer_state::start:
+ break;
+ case jsonpointer::detail::pointer_state::zero_array_reference_token:
+ case jsonpointer::detail::pointer_state::nonzero_array_reference_token:
+ if (index_ > current_.back().get().size())
+ {
+ return jsonpointer_errc::index_exceeds_array_size;
+ }
+ if (index_ == current_.back().get().size())
+ {
+ current_.back().get().push_back(value);
+ }
+ else
+ {
+ current_.back().get().insert(current_.back().get().array_range().begin()+index_,value);
+ }
+ break;
+ case jsonpointer::detail::pointer_state::after_last_array_reference_token:
+ current_.back().get().push_back(value);
+ break;
+ case jsonpointer::detail::pointer_state::object_reference_token:
+ current_.back().get().insert_or_assign(buffer_,value);
+ break;
+ default:
+ return jsonpointer_errc::end_of_input;
+ }
+ return ec;
+ }
+
+ jsonpointer_errc insert(reference root, const string_view_type& path, const Json& value)
+ {
+ jsonpointer_errc ec = evaluate(root,path_setter<Json,reference>(),path);
+ if (ec != jsonpointer_errc())
+ {
+ return ec;
+ }
+
+ switch (state_)
+ {
+ case jsonpointer::detail::pointer_state::start:
+ break;
+ case jsonpointer::detail::pointer_state::zero_array_reference_token:
+ case jsonpointer::detail::pointer_state::nonzero_array_reference_token:
+ if (index_ > current_.back().get().size())
+ {
+ return jsonpointer_errc::index_exceeds_array_size;
+ }
+ if (index_ == current_.back().get().size())
+ {
+ current_.back().get().push_back(value);
+ }
+ else
+ {
+ current_.back().get().insert(current_.back().get().array_range().begin()+index_,value);
+ }
+ break;
+ case jsonpointer::detail::pointer_state::after_last_array_reference_token:
+ current_.back().get().push_back(value);
+ break;
+ case jsonpointer::detail::pointer_state::object_reference_token:
+ if (current_.back().get().has_key(buffer_))
+ {
+ ec = jsonpointer_errc::key_already_exists;
+ }
+ else
+ {
+ current_.back().get().insert_or_assign(buffer_,value);
+ }
+ break;
+ default:
+ return jsonpointer_errc::end_of_input;
+ }
+ return ec;
+ }
+
+ jsonpointer_errc remove(reference root, const string_view_type& path)
+ {
+ jsonpointer_errc ec = evaluate(root,path_resolver<Json,reference>(),path);
+ if (ec != jsonpointer_errc())
+ {
+ return ec;
+ }
+
+ switch (state_)
+ {
+ case jsonpointer::detail::pointer_state::start:
+ break;
+ case jsonpointer::detail::pointer_state::zero_array_reference_token:
+ case jsonpointer::detail::pointer_state::nonzero_array_reference_token:
+ if (index_ >= current_.back().get().size())
+ {
+ return jsonpointer_errc::index_exceeds_array_size;
+ }
+ current_.back().get().erase(current_.back().get().array_range().begin()+index_);
+ break;
+ case jsonpointer::detail::pointer_state::after_last_array_reference_token:
+ return jsonpointer_errc::index_exceeds_array_size;
+ case jsonpointer::detail::pointer_state::object_reference_token:
+ if (!current_.back().get().has_key(buffer_))
+ {
+ return jsonpointer_errc::name_not_found;
+ }
+ current_.back().get().erase(buffer_);
+ break;
+ default:
+ return jsonpointer_errc::end_of_input;
+ }
+ return ec;
+ }
+
+ jsonpointer_errc replace(reference root, const string_view_type& path, const Json& value)
+ {
+ jsonpointer_errc ec = evaluate(root,path_resolver<Json,reference>(),path);
+ if (ec != jsonpointer_errc())
+ {
+ return ec;
+ }
+
+ switch (state_)
+ {
+ case jsonpointer::detail::pointer_state::start:
+ break;
+ case jsonpointer::detail::pointer_state::zero_array_reference_token:
+ case jsonpointer::detail::pointer_state::nonzero_array_reference_token:
+ if (index_ >= current_.back().get().size())
+ {
+ return jsonpointer_errc::index_exceeds_array_size;
+ }
+ (current_.back().get())[index_] = value;
+ break;
+ case jsonpointer::detail::pointer_state::after_last_array_reference_token:
+ return jsonpointer_errc::index_exceeds_array_size;
+ case jsonpointer::detail::pointer_state::object_reference_token:
+ if (!current_.back().get().has_key(buffer_))
+ {
+ return jsonpointer_errc::name_not_found;
+ }
+ current_.back().get().insert_or_assign(buffer_,value);
+ break;
+ default:
+ return jsonpointer_errc::end_of_input;
+ }
+ return jsonpointer_errc();
+ }
+
+ template <class Op>
+ jsonpointer_errc evaluate(reference root, Op op, const string_view_type& path)
+ {
+ jsonpointer_errc ec = jsonpointer_errc();
+
+ line_ = 1;
+ column_ = 1;
+ state_ = jsonpointer::detail::pointer_state::start;
+ begin_input_ = path.data();
+ end_input_ = path.data() + path.length();
+ p_ = begin_input_;
+
+ index_ = 0;
+
+ current_.push_back(root);
+
+ while (p_ < end_input_)
+ {
+ switch (state_)
+ {
+ case jsonpointer::detail::pointer_state::start:
+ switch (*p_)
+ {
+ case '/':
+ if (current_.back().get().is_array())
+ {
+ state_ = jsonpointer::detail::pointer_state::array_reference_token;
+ index_ = 0;
+ }
+ else if (current_.back().get().is_object())
+ {
+ state_ = jsonpointer::detail::pointer_state::object_reference_token;
+ buffer_.clear();
+ }
+ else
+ {
+ return jsonpointer_errc::expected_object_or_array;
+ }
+ break;
+ default:
+ return jsonpointer_errc::expected_slash;
+ };
+ ++p_;
+ ++column_;
+ break;
+ case jsonpointer::detail::pointer_state::array_reference_token:
+ switch (*p_)
+ {
+ case '0':
+ index_ = 0;
+ state_ = jsonpointer::detail::pointer_state::zero_array_reference_token;
+ break;
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ index_ = (*p_ - '0');
+ state_ = jsonpointer::detail::pointer_state::nonzero_array_reference_token;
+ break;
+ case '-':
+ state_ = jsonpointer::detail::pointer_state::after_last_array_reference_token;
+ break;
+ default:
+ return jsonpointer_errc::expected_digit_or_dash;
+ };
+ ++p_;
+ ++column_;
+ break;
+ case jsonpointer::detail::pointer_state::zero_array_reference_token:
+ switch (*p_)
+ {
+ case '/':
+ ec = op(current_,index_);
+ if (ec != jsonpointer_errc())
+ {
+ return ec;
+ }
+ if (current_.back().get().is_array())
+ {
+ state_ = jsonpointer::detail::pointer_state::array_reference_token;
+ index_ = 0;
+ }
+ else if (current_.back().get().is_object())
+ {
+ state_ = jsonpointer::detail::pointer_state::object_reference_token;
+ buffer_.clear();
+ }
+ else
+ {
+ return jsonpointer_errc::expected_object_or_array;
+ }
+ break;
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ return jsonpointer_errc::unexpected_leading_zero;
+ case '-':
+ return jsonpointer_errc::index_exceeds_array_size;
+ default:
+ return jsonpointer_errc::expected_digit_or_dash;
+ };
+ ++p_;
+ ++column_;
+ break;
+ case jsonpointer::detail::pointer_state::after_last_array_reference_token:
+ switch (*p_)
+ {
+ case '/':
+ return jsonpointer_errc::index_exceeds_array_size;
+ default:
+ return jsonpointer_errc::expected_slash;
+ };
+ ++p_;
+ ++column_;
+ break;
+ case jsonpointer::detail::pointer_state::nonzero_array_reference_token:
+ switch (*p_)
+ {
+ case '/':
+ ec = op(current_,index_);
+ if (ec != jsonpointer_errc())
+ {
+ return ec;
+ }
+ if (current_.back().get().is_array())
+ {
+ state_ = jsonpointer::detail::pointer_state::array_reference_token;
+ index_ = 0;
+ }
+ else if (current_.back().get().is_object())
+ {
+ state_ = jsonpointer::detail::pointer_state::object_reference_token;
+ buffer_.clear();
+ }
+ else
+ {
+ return jsonpointer_errc::expected_object_or_array;
+ }
+ break;
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ index_ = index_ * 10 + (*p_ - '0');
+ break;
+ case '-':
+ return jsonpointer_errc::index_exceeds_array_size;
+ default:
+ return jsonpointer_errc::expected_digit_or_dash;
+ };
+ ++p_;
+ ++column_;
+ break;
+ case jsonpointer::detail::pointer_state::object_reference_token:
+ switch (*p_)
+ {
+ case '/':
+ ec = op(current_,buffer_);
+ if (ec != jsonpointer_errc())
+ {
+ return ec;
+ }
+ if (current_.back().get().is_array())
+ {
+ state_ = jsonpointer::detail::pointer_state::array_reference_token;
+ index_ = 0;
+ }
+ else if (current_.back().get().is_object())
+ {
+ state_ = jsonpointer::detail::pointer_state::object_reference_token;
+ buffer_.clear();
+ }
+ else
+ {
+ return jsonpointer_errc::expected_object_or_array;
+ }
+ break;
+ case '~':
+ state_ = jsonpointer::detail::pointer_state::escaped;
+ break;
+ default:
+ buffer_.push_back(*p_);
+ break;
+ };
+ ++p_;
+ ++column_;
+ break;
+ case jsonpointer::detail::pointer_state::escaped:
+ switch (*p_)
+ {
+ case '0':
+ buffer_.push_back('~');
+ state_ = jsonpointer::detail::pointer_state::object_reference_token;
+ break;
+ case '1':
+ buffer_.push_back('/');
+ state_ = jsonpointer::detail::pointer_state::object_reference_token;
+ break;
+ default:
+ return jsonpointer_errc::expected_0_or_1;
+ };
+ ++p_;
+ ++column_;
+ break;
+ }
+ }
+ return ec;
+ }
+
+private:
+
+ // parsing_context
+
+ size_t do_line_number() const override
+ {
+ return line_;
+ }
+
+ size_t do_column_number() const override
+ {
+ return column_;
+ }
+};
+
+}
+
+template<class Json>
+typename Json::string_type normalized_path(const Json& root, const typename Json::string_view_type& path)
+{
+ detail::jsonpointer_evaluator<Json,const Json&> evaluator;
+ return evaluator.normalized_path(root,path);
+}
+
+template<class Json>
+Json get(const Json& root, const typename Json::string_view_type& path)
+{
+ detail::jsonpointer_evaluator<Json,const Json&> evaluator;
+ jsonpointer_errc ec = evaluator.get(root,path);
+ if (ec != jsonpointer_errc())
+ {
+ JSONCONS_THROW(jsonpointer_error(ec));
+ }
+ return evaluator.get_result();
+}
+
+template<class Json>
+Json get(const Json& root, const typename Json::string_view_type& path, std::error_code& ec)
+{
+ detail::jsonpointer_evaluator<Json,const Json&> evaluator;
+ ec = evaluator.get(root,path);
+ return evaluator.get_result();
+}
+
+template<class Json>
+bool contains(const Json& root, const typename Json::string_view_type& path)
+{
+ detail::jsonpointer_evaluator<Json,const Json&> evaluator;
+ jsonpointer_errc ec = evaluator.get(root,path);
+ return ec == jsonpointer_errc() ? true : false;
+}
+
+template<class Json>
+void insert_or_assign(Json& root, const typename Json::string_view_type& path, const Json& value)
+{
+ detail::jsonpointer_evaluator<Json,Json&> evaluator;
+
+ jsonpointer_errc ec = evaluator.insert_or_assign(root,path,value);
+ if (ec != jsonpointer_errc())
+ {
+ JSONCONS_THROW(jsonpointer_error(ec));
+ }
+}
+
+template<class Json>
+void insert_or_assign(Json& root, const typename Json::string_view_type& path, const Json& value, std::error_code& ec)
+{
+ detail::jsonpointer_evaluator<Json,Json&> evaluator;
+
+ ec = evaluator.insert_or_assign(root,path,value);
+}
+
+template<class Json>
+void insert(Json& root, const typename Json::string_view_type& path, const Json& value)
+{
+ detail::jsonpointer_evaluator<Json,Json&> evaluator;
+
+ jsonpointer_errc ec = evaluator.insert(root,path,value);
+ if (ec != jsonpointer_errc())
+ {
+ JSONCONS_THROW(jsonpointer_error(ec));
+ }
+}
+
+template<class Json>
+void insert(Json& root, const typename Json::string_view_type& path, const Json& value, std::error_code& ec)
+{
+ detail::jsonpointer_evaluator<Json,Json&> evaluator;
+
+ ec = evaluator.insert(root,path,value);
+}
+
+template<class Json>
+void remove(Json& root, const typename Json::string_view_type& path)
+{
+ detail::jsonpointer_evaluator<Json,Json&> evaluator;
+
+ jsonpointer_errc ec = evaluator.remove(root,path);
+ if (ec != jsonpointer_errc())
+ {
+ JSONCONS_THROW(jsonpointer_error(ec));
+ }
+}
+
+template<class Json>
+void remove(Json& root, const typename Json::string_view_type& path, std::error_code& ec)
+{
+ detail::jsonpointer_evaluator<Json,Json&> evaluator;
+
+ ec = evaluator.remove(root,path);
+}
+
+template<class Json>
+void replace(Json& root, const typename Json::string_view_type& path, const Json& value)
+{
+ detail::jsonpointer_evaluator<Json,Json&> evaluator;
+
+ jsonpointer_errc ec = evaluator.replace(root,path,value);
+ if (ec != jsonpointer_errc())
+ {
+ JSONCONS_THROW(jsonpointer_error(ec));
+ }
+}
+
+template<class Json>
+void replace(Json& root, const typename Json::string_view_type& path, const Json& value, std::error_code& ec)
+{
+ detail::jsonpointer_evaluator<Json,Json&> evaluator;
+
+ ec = evaluator.replace(root,path,value);
+}
+
+template <class String>
+void escape(const String& s, std::basic_ostringstream<typename String::value_type>& os)
+{
+ for (auto c : s)
+ {
+ if (c == '~')
+ {
+ os.put('~');
+ os.put('0');
+ }
+ else if (c == '/')
+ {
+ os.put('~');
+ os.put('1');
+ }
+ else
+ {
+ os.put(c);
+ }
+ }
+}
+
+}}
+
+#endif