From b6854612a4ced5ae4ae9e5b61250b78357034eba Mon Sep 17 00:00:00 2001 From: Lars Immisch Date: Mon, 1 Aug 2016 22:09:31 +0200 Subject: [PATCH] This patch drops boost as a dependency from the valijson core. It is based on https://github.com/tristanpenman/valijson/pull/28, but squashed and rebased for simplicity. See the original https://github.com/tristanpenman/valijson/pull/28 for history. --- Authors | 3 + examples/custom_schema.cpp | 4 +- include/compat/optional.hpp | 1042 +++++++++++++++++ include/valijson/adapters/adapter.hpp | 6 +- include/valijson/adapters/basic_adapter.hpp | 57 +- include/valijson/adapters/json11_adapter.hpp | 100 +- include/valijson/adapters/jsoncpp_adapter.hpp | 102 +- .../adapters/nlohmann_json_adapter.hpp | 100 +- .../valijson/adapters/picojson_adapter.hpp | 103 +- .../adapters/property_tree_adapter.hpp | 121 +- .../valijson/adapters/rapidjson_adapter.hpp | 110 +- .../constraints/concrete_constraints.hpp | 35 +- include/valijson/internal/json_pointer.hpp | 40 +- include/valijson/internal/json_reference.hpp | 16 +- include/valijson/schema_parser.hpp | 107 +- include/valijson/subschema.hpp | 30 +- include/valijson/utils/utf8_utils.hpp | 2 +- include/valijson/validation_visitor.hpp | 79 +- include/valijson/validator.hpp | 3 - tests/test_adapter_comparison.cpp | 3 - tests/test_fetch_document_callback.cpp | 1 - tests/test_json11_adapter.cpp | 11 +- tests/test_json_pointer.cpp | 40 +- tests/test_jsoncpp_adapter.cpp | 10 +- tests/test_nlohmann_json_adapter.cpp | 11 +- tests/test_picojson_adapter.cpp | 11 +- tests/test_property_tree_adapter.cpp | 14 +- tests/test_rapidjson_adapter.cpp | 13 +- tests/test_validation_errors.cpp | 3 - tests/test_validator.cpp | 7 +- xcode/valijson.xcodeproj/project.pbxproj | 10 + 31 files changed, 1743 insertions(+), 451 deletions(-) create mode 100644 include/compat/optional.hpp diff --git a/Authors b/Authors index 00c1984..77af5d0 100644 --- a/Authors +++ b/Authors @@ -18,3 +18,6 @@ Michael Smith, michael.smith@puppetlabs.com Richard Clamp, richardc@unixbeard.net Boost-related fixes + +Lars Immisch, lars@ibp.de + noboost branch diff --git a/examples/custom_schema.cpp b/examples/custom_schema.cpp index 008e67a..aa7f6be 100644 --- a/examples/custom_schema.cpp +++ b/examples/custom_schema.cpp @@ -210,7 +210,7 @@ int main(int argc, char *argv[]) while (results.popError(error)) { cerr << "Error #" << errorNum << std::endl; cerr << " "; - BOOST_FOREACH( const std::string contextElement, error.context ) { + for( const std::string contextElement : error.context ) { cerr << contextElement << " "; } cerr << endl; @@ -221,4 +221,4 @@ int main(int argc, char *argv[]) } return 0; -} \ No newline at end of file +} diff --git a/include/compat/optional.hpp b/include/compat/optional.hpp new file mode 100644 index 0000000..3ba123f --- /dev/null +++ b/include/compat/optional.hpp @@ -0,0 +1,1042 @@ +// Copyright (C) 2011 - 2012 Andrzej Krzemienski. +// +// Use, modification, and distribution is subject to the Boost Software +// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +// The idea and interface is based on Boost.Optional library +// authored by Fernando Luis Cacciola Carballal + +# ifndef ___OPTIONAL_HPP___ +# define ___OPTIONAL_HPP___ + +# include +# include +# include +# include +# include +# include +# include + +# define TR2_OPTIONAL_REQUIRES(...) typename enable_if<__VA_ARGS__::value, bool>::type = false + +# if defined __GNUC__ // NOTE: GNUC is also defined for Clang +# if (__GNUC__ == 4) && (__GNUC_MINOR__ >= 8) +# define TR2_OPTIONAL_GCC_4_8_AND_HIGHER___ +# elif (__GNUC__ > 4) +# define TR2_OPTIONAL_GCC_4_8_AND_HIGHER___ +# endif +# +# if (__GNUC__ == 4) && (__GNUC_MINOR__ >= 7) +# define TR2_OPTIONAL_GCC_4_7_AND_HIGHER___ +# elif (__GNUC__ > 4) +# define TR2_OPTIONAL_GCC_4_7_AND_HIGHER___ +# endif +# +# if (__GNUC__ == 4) && (__GNUC_MINOR__ == 8) && (__GNUC_PATCHLEVEL__ >= 1) +# define TR2_OPTIONAL_GCC_4_8_1_AND_HIGHER___ +# elif (__GNUC__ == 4) && (__GNUC_MINOR__ >= 9) +# define TR2_OPTIONAL_GCC_4_8_1_AND_HIGHER___ +# elif (__GNUC__ > 4) +# define TR2_OPTIONAL_GCC_4_8_1_AND_HIGHER___ +# endif +# endif +# +# if defined __clang_major__ +# if (__clang_major__ == 3 && __clang_minor__ >= 5) +# define TR2_OPTIONAL_CLANG_3_5_AND_HIGHTER_ +# elif (__clang_major__ > 3) +# define TR2_OPTIONAL_CLANG_3_5_AND_HIGHTER_ +# endif +# if defined TR2_OPTIONAL_CLANG_3_5_AND_HIGHTER_ +# define TR2_OPTIONAL_CLANG_3_4_2_AND_HIGHER_ +# elif (__clang_major__ == 3 && __clang_minor__ == 4 && __clang_patchlevel__ >= 2) +# define TR2_OPTIONAL_CLANG_3_4_2_AND_HIGHER_ +# endif +# endif +# +# if defined _MSC_VER +# if (_MSC_VER >= 1900) +# define TR2_OPTIONAL_MSVC_2015_AND_HIGHER___ +# endif +# endif + +# if defined __clang__ +# if (__clang_major__ > 2) || (__clang_major__ == 2) && (__clang_minor__ >= 9) +# define OPTIONAL_HAS_THIS_RVALUE_REFS 1 +# else +# define OPTIONAL_HAS_THIS_RVALUE_REFS 0 +# endif +# elif defined TR2_OPTIONAL_GCC_4_8_1_AND_HIGHER___ +# define OPTIONAL_HAS_THIS_RVALUE_REFS 1 +# elif defined TR2_OPTIONAL_MSVC_2015_AND_HIGHER___ +# define OPTIONAL_HAS_THIS_RVALUE_REFS 1 +# else +# define OPTIONAL_HAS_THIS_RVALUE_REFS 0 +# endif + + +# if defined TR2_OPTIONAL_GCC_4_8_1_AND_HIGHER___ +# define OPTIONAL_HAS_CONSTEXPR_INIT_LIST 1 +# define OPTIONAL_CONSTEXPR_INIT_LIST constexpr +# else +# define OPTIONAL_HAS_CONSTEXPR_INIT_LIST 0 +# define OPTIONAL_CONSTEXPR_INIT_LIST +# endif + +# if defined TR2_OPTIONAL_CLANG_3_5_AND_HIGHTER_ && (defined __cplusplus) && (__cplusplus != 201103L) +# define OPTIONAL_HAS_MOVE_ACCESSORS 1 +# else +# define OPTIONAL_HAS_MOVE_ACCESSORS 0 +# endif + +# // In C++11 constexpr implies const, so we need to make non-const members also non-constexpr +# if (defined __cplusplus) && (__cplusplus == 201103L) +# define OPTIONAL_MUTABLE_CONSTEXPR +# else +# define OPTIONAL_MUTABLE_CONSTEXPR constexpr +# endif + +namespace std{ + + namespace experimental{ + + // BEGIN workaround for missing is_trivially_destructible +# if defined TR2_OPTIONAL_GCC_4_8_AND_HIGHER___ + // leave it: it is already there +# elif defined TR2_OPTIONAL_CLANG_3_4_2_AND_HIGHER_ + // leave it: it is already there +# elif defined TR2_OPTIONAL_MSVC_2015_AND_HIGHER___ + // leave it: it is already there +# elif defined TR2_OPTIONAL_DISABLE_EMULATION_OF_TYPE_TRAITS + // leave it: the user doesn't want it +# else + template + using is_trivially_destructible = std::has_trivial_destructor; +# endif + // END workaround for missing is_trivially_destructible + +# if (defined TR2_OPTIONAL_GCC_4_7_AND_HIGHER___) + // leave it; our metafunctions are already defined. +# elif defined TR2_OPTIONAL_CLANG_3_4_2_AND_HIGHER_ + // leave it; our metafunctions are already defined. +# elif defined TR2_OPTIONAL_MSVC_2015_AND_HIGHER___ + // leave it: it is already there +# elif defined TR2_OPTIONAL_DISABLE_EMULATION_OF_TYPE_TRAITS + // leave it: the user doesn't want it +# else + + + // workaround for missing traits in GCC and CLANG + template + struct is_nothrow_move_constructible + { + constexpr static bool value = std::is_nothrow_constructible::value; + }; + + + template + struct is_assignable + { + template + constexpr static bool has_assign(...) { return false; } + + template () = std::declval(), true)) > + // the comma operator is necessary for the cases where operator= returns void + constexpr static bool has_assign(bool) { return true; } + + constexpr static bool value = has_assign(true); + }; + + + template + struct is_nothrow_move_assignable + { + template + struct has_nothrow_move_assign { + constexpr static bool value = false; + }; + + template + struct has_nothrow_move_assign { + constexpr static bool value = noexcept( std::declval() = std::declval() ); + }; + + constexpr static bool value = has_nothrow_move_assign::value>::value; + }; + // end workaround + + +# endif + + + + // 20.5.4, optional for object types + template class optional; + + // 20.5.5, optional for lvalue reference types + template class optional; + + + // workaround: std utility functions aren't constexpr yet + template inline constexpr T&& constexpr_forward(typename std::remove_reference::type& t) noexcept + { + return static_cast(t); + } + + template inline constexpr T&& constexpr_forward(typename std::remove_reference::type&& t) noexcept + { + static_assert(!std::is_lvalue_reference::value, "!!"); + return static_cast(t); + } + + template inline constexpr typename std::remove_reference::type&& constexpr_move(T&& t) noexcept + { + return static_cast::type&&>(t); + } + + +#if defined NDEBUG +# define TR2_OPTIONAL_ASSERTED_EXPRESSION(CHECK, EXPR) (EXPR) +#else +# define TR2_OPTIONAL_ASSERTED_EXPRESSION(CHECK, EXPR) ((CHECK) ? (EXPR) : ([]{assert(!#CHECK);}(), (EXPR))) +#endif + + + namespace detail_ + { + + // static_addressof: a constexpr version of addressof + template + struct has_overloaded_addressof + { + template + constexpr static bool has_overload(...) { return false; } + + template ().operator&()) > + constexpr static bool has_overload(bool) { return true; } + + constexpr static bool value = has_overload(true); + }; + + template )> + constexpr T* static_addressof(T& ref) + { + return &ref; + } + + template )> + T* static_addressof(T& ref) + { + return std::addressof(ref); + } + + + // the call to convert(b) has return type A and converts b to type A iff b decltype(b) is implicitly convertible to A + template + constexpr U convert(U v) { return v; } + + } // namespace detail + + + constexpr struct trivial_init_t{} trivial_init{}; + + + // 20.5.6, In-place construction + constexpr struct in_place_t{} in_place{}; + + + // 20.5.7, Disengaged state indicator + struct nullopt_t + { + struct init{}; + constexpr explicit nullopt_t(init){} + }; + constexpr nullopt_t nullopt{nullopt_t::init()}; + + + // 20.5.8, class bad_optional_access + class bad_optional_access : public logic_error { + public: + explicit bad_optional_access(const string& what_arg) : logic_error{what_arg} {} + explicit bad_optional_access(const char* what_arg) : logic_error{what_arg} {} + }; + + + template + union storage_t + { + unsigned char dummy_; + T value_; + + constexpr storage_t( trivial_init_t ) noexcept : dummy_() {}; + + template + constexpr storage_t( Args&&... args ) : value_(constexpr_forward(args)...) {} + + ~storage_t(){} + }; + + + template + union constexpr_storage_t + { + unsigned char dummy_; + T value_; + + constexpr constexpr_storage_t( trivial_init_t ) noexcept : dummy_() {}; + + template + constexpr constexpr_storage_t( Args&&... args ) : value_(constexpr_forward(args)...) {} + + ~constexpr_storage_t() = default; + }; + + + template + struct optional_base + { + bool init_; + storage_t storage_; + + constexpr optional_base() noexcept : init_(false), storage_(trivial_init) {}; + + explicit constexpr optional_base(const T& v) : init_(true), storage_(v) {} + + explicit constexpr optional_base(T&& v) : init_(true), storage_(constexpr_move(v)) {} + + template explicit optional_base(in_place_t, Args&&... args) + : init_(true), storage_(constexpr_forward(args)...) {} + + template >)> + explicit optional_base(in_place_t, std::initializer_list il, Args&&... args) + : init_(true), storage_(il, std::forward(args)...) {} + + ~optional_base() { if (init_) storage_.value_.T::~T(); } + }; + + + template + struct constexpr_optional_base + { + bool init_; + constexpr_storage_t storage_; + + constexpr constexpr_optional_base() noexcept : init_(false), storage_(trivial_init) {}; + + explicit constexpr constexpr_optional_base(const T& v) : init_(true), storage_(v) {} + + explicit constexpr constexpr_optional_base(T&& v) : init_(true), storage_(constexpr_move(v)) {} + + template explicit constexpr constexpr_optional_base(in_place_t, Args&&... args) + : init_(true), storage_(constexpr_forward(args)...) {} + + template >)> + OPTIONAL_CONSTEXPR_INIT_LIST explicit constexpr_optional_base(in_place_t, std::initializer_list il, Args&&... args) + : init_(true), storage_(il, std::forward(args)...) {} + + ~constexpr_optional_base() = default; + }; + + template + using OptionalBase = typename std::conditional< + is_trivially_destructible::value, + constexpr_optional_base::type>, + optional_base::type> + >::type; + + + + template + class optional : private OptionalBase + { + static_assert( !std::is_same::type, nullopt_t>::value, "bad T" ); + static_assert( !std::is_same::type, in_place_t>::value, "bad T" ); + + + constexpr bool initialized() const noexcept { return OptionalBase::init_; } + typename std::remove_const::type* dataptr() { return std::addressof(OptionalBase::storage_.value_); } + constexpr const T* dataptr() const { return detail_::static_addressof(OptionalBase::storage_.value_); } + +# if OPTIONAL_HAS_THIS_RVALUE_REFS == 1 + constexpr const T& contained_val() const& { return OptionalBase::storage_.value_; } +# if OPTIONAL_HAS_MOVE_ACCESSORS == 1 + OPTIONAL_MUTABLE_CONSTEXPR T&& contained_val() && { return std::move(OptionalBase::storage_.value_); } + OPTIONAL_MUTABLE_CONSTEXPR T& contained_val() & { return OptionalBase::storage_.value_; } +# else + T& contained_val() & { return OptionalBase::storage_.value_; } + T&& contained_val() && { return std::move(OptionalBase::storage_.value_); } +# endif +# else + constexpr const T& contained_val() const { return OptionalBase::storage_.value_; } + T& contained_val() { return OptionalBase::storage_.value_; } +# endif + + void clear() noexcept { + if (initialized()) dataptr()->T::~T(); + OptionalBase::init_ = false; + } + + template + void initialize(Args&&... args) noexcept(noexcept(T(std::forward(args)...))) + { + assert(!OptionalBase::init_); + ::new (static_cast(dataptr())) T(std::forward(args)...); + OptionalBase::init_ = true; + } + + template + void initialize(std::initializer_list il, Args&&... args) noexcept(noexcept(T(il, std::forward(args)...))) + { + assert(!OptionalBase::init_); + ::new (static_cast(dataptr())) T(il, std::forward(args)...); + OptionalBase::init_ = true; + } + + public: + typedef T value_type; + + // 20.5.5.1, constructors + constexpr optional() noexcept : OptionalBase() {}; + constexpr optional(nullopt_t) noexcept : OptionalBase() {}; + + optional(const optional& rhs) + : OptionalBase() + { + if (rhs.initialized()) { + ::new (static_cast(dataptr())) T(*rhs); + OptionalBase::init_ = true; + } + } + + optional(optional&& rhs) noexcept(is_nothrow_move_constructible::value) + : OptionalBase() + { + if (rhs.initialized()) { + ::new (static_cast(dataptr())) T(std::move(*rhs)); + OptionalBase::init_ = true; + } + } + + constexpr optional(const T& v) : OptionalBase(v) {} + + constexpr optional(T&& v) : OptionalBase(constexpr_move(v)) {} + + template + explicit constexpr optional(in_place_t, Args&&... args) + : OptionalBase(in_place_t{}, constexpr_forward(args)...) {} + + template >)> + OPTIONAL_CONSTEXPR_INIT_LIST explicit optional(in_place_t, std::initializer_list il, Args&&... args) + : OptionalBase(in_place_t{}, il, constexpr_forward(args)...) {} + + // 20.5.4.2, Destructor + ~optional() = default; + + // 20.5.4.3, assignment + optional& operator=(nullopt_t) noexcept + { + clear(); + return *this; + } + + optional& operator=(const optional& rhs) + { + if (initialized() == true && rhs.initialized() == false) clear(); + else if (initialized() == false && rhs.initialized() == true) initialize(*rhs); + else if (initialized() == true && rhs.initialized() == true) contained_val() = *rhs; + return *this; + } + + optional& operator=(optional&& rhs) + noexcept(is_nothrow_move_assignable::value && is_nothrow_move_constructible::value) + { + if (initialized() == true && rhs.initialized() == false) clear(); + else if (initialized() == false && rhs.initialized() == true) initialize(std::move(*rhs)); + else if (initialized() == true && rhs.initialized() == true) contained_val() = std::move(*rhs); + return *this; + } + + template + auto operator=(U&& v) + -> typename enable_if + < + is_same::type, T>::value, + optional& + >::type + { + if (initialized()) { contained_val() = std::forward(v); } + else { initialize(std::forward(v)); } + return *this; + } + + + template + void emplace(Args&&... args) + { + clear(); + initialize(std::forward(args)...); + } + + template + void emplace(initializer_list il, Args&&... args) + { + clear(); + initialize(il, std::forward(args)...); + } + + // 20.5.4.4, Swap + void swap(optional& rhs) noexcept(is_nothrow_move_constructible::value && noexcept(swap(declval(), declval()))) + { + if (initialized() == true && rhs.initialized() == false) { rhs.initialize(std::move(**this)); clear(); } + else if (initialized() == false && rhs.initialized() == true) { initialize(std::move(*rhs)); rhs.clear(); } + else if (initialized() == true && rhs.initialized() == true) { using std::swap; swap(**this, *rhs); } + } + + // 20.5.4.5, Observers + + explicit constexpr operator bool() const noexcept { return initialized(); } + + constexpr T const* operator ->() const { + return TR2_OPTIONAL_ASSERTED_EXPRESSION(initialized(), dataptr()); + } + +# if OPTIONAL_HAS_MOVE_ACCESSORS == 1 + + OPTIONAL_MUTABLE_CONSTEXPR T* operator ->() { + assert (initialized()); + return dataptr(); + } + + constexpr T const& operator *() const& { + return TR2_OPTIONAL_ASSERTED_EXPRESSION(initialized(), contained_val()); + } + + OPTIONAL_MUTABLE_CONSTEXPR T& operator *() & { + assert (initialized()); + return contained_val(); + } + + OPTIONAL_MUTABLE_CONSTEXPR T&& operator *() && { + assert (initialized()); + return constexpr_move(contained_val()); + } + + constexpr T const& value() const& { + return initialized() ? contained_val() : (throw bad_optional_access("bad optional access"), contained_val()); + } + + OPTIONAL_MUTABLE_CONSTEXPR T& value() & { + return initialized() ? contained_val() : (throw bad_optional_access("bad optional access"), contained_val()); + } + + OPTIONAL_MUTABLE_CONSTEXPR T&& value() && { + if (!initialized()) throw bad_optional_access("bad optional access"); + return std::move(contained_val()); + } + +# else + + T* operator ->() { + assert (initialized()); + return dataptr(); + } + + constexpr T const& operator *() const { + return TR2_OPTIONAL_ASSERTED_EXPRESSION(initialized(), contained_val()); + } + + T& operator *() { + assert (initialized()); + return contained_val(); + } + + constexpr T const& value() const { + return initialized() ? contained_val() : (throw bad_optional_access("bad optional access"), contained_val()); + } + + T& value() { + return initialized() ? contained_val() : (throw bad_optional_access("bad optional access"), contained_val()); + } + +# endif + +# if OPTIONAL_HAS_THIS_RVALUE_REFS == 1 + + template + constexpr T value_or(V&& v) const& + { + return *this ? **this : detail_::convert(constexpr_forward(v)); + } + +# if OPTIONAL_HAS_MOVE_ACCESSORS == 1 + + template + OPTIONAL_MUTABLE_CONSTEXPR T value_or(V&& v) && + { + return *this ? constexpr_move(const_cast&>(*this).contained_val()) : detail_::convert(constexpr_forward(v)); + } + +# else + + template + T value_or(V&& v) && + { + return *this ? constexpr_move(const_cast&>(*this).contained_val()) : detail_::convert(constexpr_forward(v)); + } + +# endif + +# else + + template + constexpr T value_or(V&& v) const + { + return *this ? **this : detail_::convert(constexpr_forward(v)); + } + +# endif + + }; + + + template + class optional + { + static_assert( !std::is_same::value, "bad T" ); + static_assert( !std::is_same::value, "bad T" ); + T* ref; + + public: + + // 20.5.5.1, construction/destruction + constexpr optional() noexcept : ref(nullptr) {} + + constexpr optional(nullopt_t) noexcept : ref(nullptr) {} + + constexpr optional(T& v) noexcept : ref(detail_::static_addressof(v)) {} + + optional(T&&) = delete; + + constexpr optional(const optional& rhs) noexcept : ref(rhs.ref) {} + + explicit constexpr optional(in_place_t, T& v) noexcept : ref(detail_::static_addressof(v)) {} + + explicit optional(in_place_t, T&&) = delete; + + ~optional() = default; + + // 20.5.5.2, mutation + optional& operator=(nullopt_t) noexcept { + ref = nullptr; + return *this; + } + + // optional& operator=(const optional& rhs) noexcept { + // ref = rhs.ref; + // return *this; + // } + + // optional& operator=(optional&& rhs) noexcept { + // ref = rhs.ref; + // return *this; + // } + + template + auto operator=(U&& rhs) noexcept + -> typename enable_if + < + is_same::type, optional>::value, + optional& + >::type + { + ref = rhs.ref; + return *this; + } + + template + auto operator=(U&& rhs) noexcept + -> typename enable_if + < + !is_same::type, optional>::value, + optional& + >::type + = delete; + + void emplace(T& v) noexcept { + ref = detail_::static_addressof(v); + } + + void emplace(T&&) = delete; + + + void swap(optional& rhs) noexcept + { + std::swap(ref, rhs.ref); + } + + // 20.5.5.3, observers + constexpr T* operator->() const { + return TR2_OPTIONAL_ASSERTED_EXPRESSION(ref, ref); + } + + constexpr T& operator*() const { + return TR2_OPTIONAL_ASSERTED_EXPRESSION(ref, *ref); + } + + constexpr T& value() const { + return ref ? *ref : (throw bad_optional_access("bad optional access"), *ref); + } + + explicit constexpr operator bool() const noexcept { + return ref != nullptr; + } + + template + constexpr typename decay::type value_or(V&& v) const + { + return *this ? **this : detail_::convert::type>(constexpr_forward(v)); + } + }; + + + template + class optional + { + static_assert( sizeof(T) == 0, "optional rvalue references disallowed" ); + }; + + + // 20.5.8, Relational operators + template constexpr bool operator==(const optional& x, const optional& y) + { + return bool(x) != bool(y) ? false : bool(x) == false ? true : *x == *y; + } + + template constexpr bool operator!=(const optional& x, const optional& y) + { + return !(x == y); + } + + template constexpr bool operator<(const optional& x, const optional& y) + { + return (!y) ? false : (!x) ? true : *x < *y; + } + + template constexpr bool operator>(const optional& x, const optional& y) + { + return (y < x); + } + + template constexpr bool operator<=(const optional& x, const optional& y) + { + return !(y < x); + } + + template constexpr bool operator>=(const optional& x, const optional& y) + { + return !(x < y); + } + + + // 20.5.9, Comparison with nullopt + template constexpr bool operator==(const optional& x, nullopt_t) noexcept + { + return (!x); + } + + template constexpr bool operator==(nullopt_t, const optional& x) noexcept + { + return (!x); + } + + template constexpr bool operator!=(const optional& x, nullopt_t) noexcept + { + return bool(x); + } + + template constexpr bool operator!=(nullopt_t, const optional& x) noexcept + { + return bool(x); + } + + template constexpr bool operator<(const optional&, nullopt_t) noexcept + { + return false; + } + + template constexpr bool operator<(nullopt_t, const optional& x) noexcept + { + return bool(x); + } + + template constexpr bool operator<=(const optional& x, nullopt_t) noexcept + { + return (!x); + } + + template constexpr bool operator<=(nullopt_t, const optional&) noexcept + { + return true; + } + + template constexpr bool operator>(const optional& x, nullopt_t) noexcept + { + return bool(x); + } + + template constexpr bool operator>(nullopt_t, const optional&) noexcept + { + return false; + } + + template constexpr bool operator>=(const optional&, nullopt_t) noexcept + { + return true; + } + + template constexpr bool operator>=(nullopt_t, const optional& x) noexcept + { + return (!x); + } + + + + // 20.5.10, Comparison with T + template constexpr bool operator==(const optional& x, const T& v) + { + return bool(x) ? *x == v : false; + } + + template constexpr bool operator==(const T& v, const optional& x) + { + return bool(x) ? v == *x : false; + } + + template constexpr bool operator!=(const optional& x, const T& v) + { + return bool(x) ? *x != v : true; + } + + template constexpr bool operator!=(const T& v, const optional& x) + { + return bool(x) ? v != *x : true; + } + + template constexpr bool operator<(const optional& x, const T& v) + { + return bool(x) ? *x < v : true; + } + + template constexpr bool operator>(const T& v, const optional& x) + { + return bool(x) ? v > *x : true; + } + + template constexpr bool operator>(const optional& x, const T& v) + { + return bool(x) ? *x > v : false; + } + + template constexpr bool operator<(const T& v, const optional& x) + { + return bool(x) ? v < *x : false; + } + + template constexpr bool operator>=(const optional& x, const T& v) + { + return bool(x) ? *x >= v : false; + } + + template constexpr bool operator<=(const T& v, const optional& x) + { + return bool(x) ? v <= *x : false; + } + + template constexpr bool operator<=(const optional& x, const T& v) + { + return bool(x) ? *x <= v : true; + } + + template constexpr bool operator>=(const T& v, const optional& x) + { + return bool(x) ? v >= *x : true; + } + + + // Comparison of optional with T + template constexpr bool operator==(const optional& x, const T& v) + { + return bool(x) ? *x == v : false; + } + + template constexpr bool operator==(const T& v, const optional& x) + { + return bool(x) ? v == *x : false; + } + + template constexpr bool operator!=(const optional& x, const T& v) + { + return bool(x) ? *x != v : true; + } + + template constexpr bool operator!=(const T& v, const optional& x) + { + return bool(x) ? v != *x : true; + } + + template constexpr bool operator<(const optional& x, const T& v) + { + return bool(x) ? *x < v : true; + } + + template constexpr bool operator>(const T& v, const optional& x) + { + return bool(x) ? v > *x : true; + } + + template constexpr bool operator>(const optional& x, const T& v) + { + return bool(x) ? *x > v : false; + } + + template constexpr bool operator<(const T& v, const optional& x) + { + return bool(x) ? v < *x : false; + } + + template constexpr bool operator>=(const optional& x, const T& v) + { + return bool(x) ? *x >= v : false; + } + + template constexpr bool operator<=(const T& v, const optional& x) + { + return bool(x) ? v <= *x : false; + } + + template constexpr bool operator<=(const optional& x, const T& v) + { + return bool(x) ? *x <= v : true; + } + + template constexpr bool operator>=(const T& v, const optional& x) + { + return bool(x) ? v >= *x : true; + } + + // Comparison of optional with T + template constexpr bool operator==(const optional& x, const T& v) + { + return bool(x) ? *x == v : false; + } + + template constexpr bool operator==(const T& v, const optional& x) + { + return bool(x) ? v == *x : false; + } + + template constexpr bool operator!=(const optional& x, const T& v) + { + return bool(x) ? *x != v : true; + } + + template constexpr bool operator!=(const T& v, const optional& x) + { + return bool(x) ? v != *x : true; + } + + template constexpr bool operator<(const optional& x, const T& v) + { + return bool(x) ? *x < v : true; + } + + template constexpr bool operator>(const T& v, const optional& x) + { + return bool(x) ? v > *x : true; + } + + template constexpr bool operator>(const optional& x, const T& v) + { + return bool(x) ? *x > v : false; + } + + template constexpr bool operator<(const T& v, const optional& x) + { + return bool(x) ? v < *x : false; + } + + template constexpr bool operator>=(const optional& x, const T& v) + { + return bool(x) ? *x >= v : false; + } + + template constexpr bool operator<=(const T& v, const optional& x) + { + return bool(x) ? v <= *x : false; + } + + template constexpr bool operator<=(const optional& x, const T& v) + { + return bool(x) ? *x <= v : true; + } + + template constexpr bool operator>=(const T& v, const optional& x) + { + return bool(x) ? v >= *x : true; + } + + + // 20.5.12, Specialized algorithms + template + void swap(optional& x, optional& y) noexcept(noexcept(x.swap(y))) + { + x.swap(y); + } + + + template + constexpr optional::type> make_optional(T&& v) + { + return optional::type>(constexpr_forward(v)); + } + + template + constexpr optional make_optional(reference_wrapper v) + { + return optional(v.get()); + } + + + } // namespace experimental +} // namespace std + +namespace std +{ + template + struct hash> + { + typedef typename hash::result_type result_type; + typedef std::experimental::optional argument_type; + + constexpr result_type operator()(argument_type const& arg) const { + return arg ? std::hash{}(*arg) : result_type{}; + } + }; + + template + struct hash> + { + typedef typename hash::result_type result_type; + typedef std::experimental::optional argument_type; + + constexpr result_type operator()(argument_type const& arg) const { + return arg ? std::hash{}(*arg) : result_type{}; + } + }; +} + +# undef TR2_OPTIONAL_REQUIRES +# undef TR2_OPTIONAL_ASSERTED_EXPRESSION + +# endif //___OPTIONAL_HPP___ diff --git a/include/valijson/adapters/adapter.hpp b/include/valijson/adapters/adapter.hpp index d39c9ee..fba50dd 100644 --- a/include/valijson/adapters/adapter.hpp +++ b/include/valijson/adapters/adapter.hpp @@ -2,7 +2,7 @@ #ifndef __VALIJSON_ADAPTERS_ADAPTER_HPP #define __VALIJSON_ADAPTERS_ADAPTER_HPP -#include +#include namespace valijson { namespace adapters { @@ -26,11 +26,11 @@ class Adapter public: /// Typedef for callback function supplied to applyToArray. - typedef boost::function + typedef std::function ArrayValueCallback; /// Typedef for callback function supplied to applyToObject. - typedef boost::function + typedef std::function ObjectMemberCallback; /** diff --git a/include/valijson/adapters/basic_adapter.hpp b/include/valijson/adapters/basic_adapter.hpp index a98499c..b807beb 100644 --- a/include/valijson/adapters/basic_adapter.hpp +++ b/include/valijson/adapters/basic_adapter.hpp @@ -5,15 +5,38 @@ #include #include -#include -#include -#include +// This should be removed once C++17 is widely available +#if __has_include() +# include +namespace opt = std; +#else +# include +namespace opt = std::experimental; +#endif #include namespace valijson { namespace adapters { +/** + * @brief A helper for the array and object member iterators. + * + * See http://www.stlsoft.org/doc-1.9/group__group____pattern____dereference__proxy.html + * for motivation + * + * @tparam Value Name of the value type + */ +template +struct DerefProxy +{ + explicit DerefProxy(const Value& x) : m_ref(x) {} + Value* operator->() { return std::addressof(m_ref); } + operator Value*() { return std::addressof(m_ref); } + + Value m_ref; +}; + /** * @brief Template class that implements the expected semantics of an Adapter. * @@ -215,8 +238,8 @@ public: // effort of constructing an ArrayType instance if the value is // definitely an array. if (value.isArray()) { - const boost::optional array = value.getArrayOptional(); - BOOST_FOREACH( const AdapterType element, *array ) { + const opt::optional array = value.getArrayOptional(); + for( const AdapterType element : *array ) { if (!fn(element)) { return false; } @@ -233,8 +256,8 @@ public: } if (value.isObject()) { - const boost::optional object = value.getObjectOptional(); - BOOST_FOREACH( const ObjectMemberType member, *object ) { + const opt::optional object = value.getObjectOptional(); + for( const ObjectMemberType member : *object ) { if (!fn(member.first, AdapterType(member.second))) { return false; } @@ -444,18 +467,14 @@ public: } else if (value.isInteger()) { int64_t integerValue; if (value.getInteger(integerValue)) { - try { - result = boost::lexical_cast(integerValue); - return true; - } catch (boost::bad_lexical_cast &) { } + result = std::to_string(integerValue); + return true; } } else if (value.isDouble()) { double doubleValue; if (value.getDouble(doubleValue)) { - try { - result = boost::lexical_cast(doubleValue); - return true; - } catch (boost::bad_lexical_cast &) { } + result = std::to_string(doubleValue); + return true; } } @@ -482,7 +501,7 @@ public: other.asString() == asString(); } else if (isArray()) { if (other.isArray() && getArraySize() == other.getArraySize()) { - const boost::optional array = value.getArrayOptional(); + const opt::optional array = value.getArrayOptional(); if (array) { ArrayComparisonFunctor fn(*array, strict); return other.applyToArray(fn); @@ -492,7 +511,7 @@ public: } } else if (isObject()) { if (other.isObject() && other.getObjectSize() == getObjectSize()) { - const boost::optional object = value.getObjectOptional(); + const opt::optional object = value.getObjectOptional(); if (object) { ObjectComparisonFunctor fn(*object, strict); return other.applyToObject(fn); @@ -521,7 +540,7 @@ public: */ ArrayType getArray() const { - boost::optional arrayValue = value.getArrayOptional(); + opt::optional arrayValue = value.getArrayOptional(); if (arrayValue) { return *arrayValue; } @@ -630,7 +649,7 @@ public: */ ObjectType getObject() const { - boost::optional objectValue = value.getObjectOptional(); + opt::optional objectValue = value.getObjectOptional(); if (objectValue) { return *objectValue; } diff --git a/include/valijson/adapters/json11_adapter.hpp b/include/valijson/adapters/json11_adapter.hpp index c22f23e..8e8508b 100644 --- a/include/valijson/adapters/json11_adapter.hpp +++ b/include/valijson/adapters/json11_adapter.hpp @@ -29,8 +29,6 @@ #include #include -#include -#include #include #include @@ -289,18 +287,18 @@ public: * @brief Optionally return a Json11Array instance. * * If the referenced Json11 value is an array, this function will return - * a boost::optional containing a Json11Array instance referencing the + * a std::optional containing a Json11Array instance referencing the * array. * - * Otherwise it will return boost::none. + * Otherwise it will return an empty optional. */ - boost::optional getArrayOptional() const + opt::optional getArrayOptional() const { if (value.is_array()) { - return boost::make_optional(Json11Array(value)); + return opt::make_optional(Json11Array(value)); } - return boost::none; + return opt::optional(); } /** @@ -357,18 +355,18 @@ public: * @brief Optionally return a Json11Object instance. * * If the referenced Json11 value is an object, this function will return a - * boost::optional containing a Json11Object instance referencing the + * std::optional containing a Json11Object instance referencing the * object. * - * Otherwise it will return boost::none. + * Otherwise it will return an empty optional. */ - boost::optional getObjectOptional() const + opt::optional getObjectOptional() const { if (value.is_object()) { - return boost::make_optional(Json11Object(value)); + return opt::make_optional(Json11Object(value)); } - return boost::none; + return opt::optional(); } /** @@ -498,11 +496,9 @@ public: * @see Json11Array */ class Json11ArrayValueIterator: - public boost::iterator_facade< - Json11ArrayValueIterator, // name of derived type - Json11Adapter, // value type - boost::bidirectional_traversal_tag, // bi-directional iterator - Json11Adapter> // type returned when dereferenced + public std::iterator< + std::bidirectional_iterator_tag, // bi-directional iterator + Json11Adapter> // value type { public: @@ -518,11 +514,16 @@ public: /// Returns a Json11Adapter that contains the value of the current /// element. - Json11Adapter dereference() const + Json11Adapter operator*() const { return Json11Adapter(*itr); } + DerefProxy operator->() const + { + return DerefProxy(**this); + } + /** * @brief Compare this iterator against another iterator. * @@ -534,19 +535,35 @@ public: * * @returns true if the iterators are equal, false otherwise. */ - bool equal(const Json11ArrayValueIterator &other) const + bool operator==(const Json11ArrayValueIterator &other) const { return itr == other.itr; } - void increment() + bool operator!=(const Json11ArrayValueIterator &other) const { - itr++; + return !(itr == other.itr); } - void decrement() + const Json11ArrayValueIterator& operator++() + { + itr++; + + return *this; + } + + Json11ArrayValueIterator operator++(int) + { + Json11ArrayValueIterator iterator_pre(itr); + ++(*this); + return iterator_pre; + } + + const Json11ArrayValueIterator& operator--() { itr--; + + return *this; } void advance(std::ptrdiff_t n) @@ -570,11 +587,9 @@ private: * @see Json11ObjectMember */ class Json11ObjectMemberIterator: - public boost::iterator_facade< - Json11ObjectMemberIterator, // name of derived type - Json11ObjectMember, // value type - boost::bidirectional_traversal_tag, // bi-directional iterator - Json11ObjectMember> // type returned when dereferenced + public std::iterator< + std::bidirectional_iterator_tag, // bi-directional iterator + Json11ObjectMember> // value type { public: @@ -591,11 +606,16 @@ public: * @brief Returns a Json11ObjectMember that contains the key and value * belonging to the object member identified by the iterator. */ - Json11ObjectMember dereference() const + Json11ObjectMember operator*() const { return Json11ObjectMember(itr->first, itr->second); } + DerefProxy operator->() const + { + return DerefProxy(**this); + } + /** * @brief Compare this iterator with another iterator. * @@ -607,19 +627,35 @@ public: * * @returns true if the underlying iterators are equal, false otherwise */ - bool equal(const Json11ObjectMemberIterator &other) const + bool operator==(const Json11ObjectMemberIterator &other) const { return itr == other.itr; } - void increment() + bool operator!=(const Json11ObjectMemberIterator &other) const { - itr++; + return !(itr == other.itr); } - void decrement() + const Json11ObjectMemberIterator& operator++() + { + itr++; + + return *this; + } + + Json11ObjectMemberIterator operator++(int) + { + Json11ObjectMemberIterator iterator_pre(itr); + ++(*this); + return iterator_pre; + } + + const Json11ObjectMemberIterator& operator--() { itr--; + + return *this; } private: diff --git a/include/valijson/adapters/jsoncpp_adapter.hpp b/include/valijson/adapters/jsoncpp_adapter.hpp index e3cf43c..377fdb7 100644 --- a/include/valijson/adapters/jsoncpp_adapter.hpp +++ b/include/valijson/adapters/jsoncpp_adapter.hpp @@ -29,8 +29,7 @@ #include #include -#include -#include +#include #include @@ -284,18 +283,18 @@ public: * @brief Optionally return a JsonCppArray instance. * * If the referenced JsonCpp value is an array, this function will return a - * boost::optional containing a JsonCppArray instance referencing the + * std::optional containing a JsonCppArray instance referencing the * array. * - * Otherwise it will return boost::none. + * Otherwise it will return an empty optional. */ - boost::optional getArrayOptional() const + opt::optional getArrayOptional() const { if (value.isArray()) { - return boost::make_optional(JsonCppArray(value)); + return opt::make_optional(JsonCppArray(value)); } - return boost::none; + return opt::optional(); } /** @@ -353,18 +352,18 @@ public: * @brief Optionally return a JsonCppObject instance. * * If the referenced JsonCpp value is an object, this function will return a - * boost::optional containing a JsonCppObject instance referencing the + * std::optional containing a JsonCppObject instance referencing the * object. * - * Otherwise it will return boost::none. + * Otherwise it will return an empty optional. */ - boost::optional getObjectOptional() const + opt::optional getObjectOptional() const { if (value.isObject()) { - return boost::make_optional(JsonCppObject(value)); + return opt::make_optional(JsonCppObject(value)); } - return boost::none; + return opt::optional(); } /** @@ -493,12 +492,11 @@ public: * @see JsonCppArray */ class JsonCppArrayValueIterator: - public boost::iterator_facade< - JsonCppArrayValueIterator, // name of derived type - JsonCppAdapter, // value type - boost::bidirectional_traversal_tag, // bi-directional iterator - JsonCppAdapter> // type returned when dereferenced + public std::iterator< + std::bidirectional_iterator_tag, // bi-directional iterator + JsonCppAdapter> // value type { + public: /** @@ -511,11 +509,16 @@ public: : itr(itr) { } /// Returns a JsonCppAdapter that contains the value of the current element. - JsonCppAdapter dereference() const + JsonCppAdapter operator*() const { return JsonCppAdapter(*itr); } + DerefProxy operator->() const + { + return DerefProxy(**this); + } + /** * @brief Compare this iterator against another iterator. * @@ -527,19 +530,35 @@ public: * * @returns true if the iterators are equal, false otherwise. */ - bool equal(const JsonCppArrayValueIterator &rhs) const + bool operator==(const JsonCppArrayValueIterator &rhs) const { return itr == rhs.itr; } - void increment() + bool operator!=(const JsonCppArrayValueIterator &rhs) const { - itr++; + return !(itr == rhs.itr); } - void decrement() + JsonCppArrayValueIterator& operator++() + { + itr++; + + return *this; + } + + JsonCppArrayValueIterator operator++(int) + { + JsonCppArrayValueIterator iterator_pre(itr); + ++(*this); + return iterator_pre; + } + + JsonCppArrayValueIterator& operator--() { itr--; + + return *this; } void advance(std::ptrdiff_t n) @@ -571,11 +590,9 @@ private: * @see JsonCppObjectMember */ class JsonCppObjectMemberIterator: - public boost::iterator_facade< - JsonCppObjectMemberIterator, // name of derived type - JsonCppObjectMember, // value type - boost::bidirectional_traversal_tag, // bi-directional iterator - JsonCppObjectMember> // type returned when dereferenced + public std::iterator< + std::bidirectional_iterator_tag, // bi-directional iterator + JsonCppObjectMember> // value type { public: @@ -591,11 +608,16 @@ public: * @brief Returns a JsonCppObjectMember that contains the key and value * belonging to the object member identified by the iterator. */ - JsonCppObjectMember dereference() const + JsonCppObjectMember operator*() const { return JsonCppObjectMember(itr.key().asString(), *itr); } + DerefProxy operator->() const + { + return DerefProxy(**this); + } + /** * @brief Compare this iterator with another iterator. * @@ -607,19 +629,35 @@ public: * * @returns true if the underlying iterators are equal, false otherwise */ - bool equal(const JsonCppObjectMemberIterator &rhs) const + bool operator==(const JsonCppObjectMemberIterator &rhs) const { return itr == rhs.itr; } - void increment() + bool operator!=(const JsonCppObjectMemberIterator &rhs) const { - itr++; + return !(itr == rhs.itr); } - void decrement() + const JsonCppObjectMemberIterator& operator++() + { + itr++; + + return *this; + } + + JsonCppObjectMemberIterator operator++(int) + { + JsonCppObjectMemberIterator iterator_pre(itr); + ++(*this); + return iterator_pre; + } + + JsonCppObjectMemberIterator operator--() { itr--; + + return *this; } private: diff --git a/include/valijson/adapters/nlohmann_json_adapter.hpp b/include/valijson/adapters/nlohmann_json_adapter.hpp index ee7d723..6d86aa6 100644 --- a/include/valijson/adapters/nlohmann_json_adapter.hpp +++ b/include/valijson/adapters/nlohmann_json_adapter.hpp @@ -29,8 +29,6 @@ #include #include -#include -#include #include #include @@ -291,18 +289,18 @@ public: * @brief Optionally return a NlohmannJsonArray instance. * * If the referenced NlohmannJson value is an array, this function will return - * a boost::optional containing a NlohmannJsonArray instance referencing the + * a std::optional containing a NlohmannJsonArray instance referencing the * array. * - * Otherwise it will return boost::none. + * Otherwise it will return an empty optional. */ - boost::optional getArrayOptional() const + opt::optional getArrayOptional() const { if (value.is_array()) { - return boost::make_optional(NlohmannJsonArray(value)); + return opt::make_optional(NlohmannJsonArray(value)); } - return boost::none; + return opt::optional(); } /** @@ -359,18 +357,18 @@ public: * @brief Optionally return a NlohmannJsonObject instance. * * If the referenced NlohmannJson value is an object, this function will return a - * boost::optional containing a NlohmannJsonObject instance referencing the + * std::optional containing a NlohmannJsonObject instance referencing the * object. * - * Otherwise it will return boost::none. + * Otherwise it will return an empty optional. */ - boost::optional getObjectOptional() const + opt::optional getObjectOptional() const { if (value.is_object()) { - return boost::make_optional(NlohmannJsonObject(value)); + return opt::make_optional(NlohmannJsonObject(value)); } - return boost::none; + return opt::optional(); } /** @@ -498,11 +496,9 @@ public: * @see NlohmannJsonArray */ class NlohmannJsonArrayValueIterator: - public boost::iterator_facade< - NlohmannJsonArrayValueIterator, // name of derived type - NlohmannJsonAdapter, // value type - boost::bidirectional_traversal_tag, // bi-directional iterator - NlohmannJsonAdapter> // type returned when dereferenced + public std::iterator< + std::bidirectional_iterator_tag, // bi-directional iterator + NlohmannJsonAdapter> // value type { public: @@ -517,11 +513,16 @@ public: /// Returns a NlohmannJsonAdapter that contains the value of the current /// element. - NlohmannJsonAdapter dereference() const + NlohmannJsonAdapter operator*() const { return NlohmannJsonAdapter(*itr); } + DerefProxy operator->() const + { + return DerefProxy(**this); + } + /** * @brief Compare this iterator against another iterator. * @@ -533,19 +534,35 @@ public: * * @returns true if the iterators are equal, false otherwise. */ - bool equal(const NlohmannJsonArrayValueIterator &other) const + bool operator==(const NlohmannJsonArrayValueIterator &other) const { return itr == other.itr; } - void increment() + bool operator!=(const NlohmannJsonArrayValueIterator &other) const { - itr++; + return !(itr == other.itr); } - void decrement() + const NlohmannJsonArrayValueIterator& operator++() + { + itr++; + + return *this; + } + + NlohmannJsonArrayValueIterator operator++(int) + { + NlohmannJsonArrayValueIterator iterator_pre(itr); + ++(*this); + return iterator_pre; + } + + const NlohmannJsonArrayValueIterator& operator--() { itr--; + + return *this; } void advance(std::ptrdiff_t n) @@ -569,11 +586,9 @@ private: * @see NlohmannJsonObjectMember */ class NlohmannJsonObjectMemberIterator: - public boost::iterator_facade< - NlohmannJsonObjectMemberIterator, // name of derived type - NlohmannJsonObjectMember, // value type - boost::bidirectional_traversal_tag, // bi-directional iterator - NlohmannJsonObjectMember> // type returned when dereferenced + public std::iterator< + std::bidirectional_iterator_tag, // bi-directional iterator + NlohmannJsonObjectMember> // value type { public: @@ -589,11 +604,16 @@ public: * @brief Returns a NlohmannJsonObjectMember that contains the key and value * belonging to the object member identified by the iterator. */ - NlohmannJsonObjectMember dereference() const + NlohmannJsonObjectMember operator*() const { return NlohmannJsonObjectMember(itr.key(), itr.value()); } + DerefProxy operator->() const + { + return DerefProxy(**this); + } + /** * @brief Compare this iterator with another iterator. * @@ -605,19 +625,35 @@ public: * * @returns true if the underlying iterators are equal, false otherwise */ - bool equal(const NlohmannJsonObjectMemberIterator &other) const + bool operator==(const NlohmannJsonObjectMemberIterator &other) const { return itr == other.itr; } - void increment() + bool operator!=(const NlohmannJsonObjectMemberIterator &other) const { - itr++; + return !(itr == other.itr); } - void decrement() + const NlohmannJsonObjectMemberIterator& operator++() + { + itr++; + + return *this; + } + + NlohmannJsonObjectMemberIterator operator++(int) + { + NlohmannJsonObjectMemberIterator iterator_pre(itr); + ++(*this); + return iterator_pre; + } + + const NlohmannJsonObjectMemberIterator& operator--() { itr--; + + return *this; } private: diff --git a/include/valijson/adapters/picojson_adapter.hpp b/include/valijson/adapters/picojson_adapter.hpp index 1d495ed..4d2b0d0 100644 --- a/include/valijson/adapters/picojson_adapter.hpp +++ b/include/valijson/adapters/picojson_adapter.hpp @@ -28,9 +28,6 @@ #define __VALIJSON_ADAPTERS_PICOJSON_ADAPTER_HPP #include -#include -#include -#include #include @@ -293,18 +290,18 @@ public: * @brief Optionally return a PicoJsonArray instance. * * If the referenced PicoJson value is an array, this function will return - * a boost::optional containing a PicoJsonArray instance referencing the + * a std::optional containing a PicoJsonArray instance referencing the * array. * - * Otherwise it will return boost::none. + * Otherwise it will return an empty optional. */ - boost::optional getArrayOptional() const + opt::optional getArrayOptional() const { if (value.is()) { - return boost::make_optional(PicoJsonArray(value)); + return opt::make_optional(PicoJsonArray(value)); } - return boost::none; + return opt::optional(); } /** @@ -363,18 +360,18 @@ public: * @brief Optionally return a PicoJsonObject instance. * * If the referenced PicoJson value is an object, this function will return a - * boost::optional containing a PicoJsonObject instance referencing the + * std::optional containing a PicoJsonObject instance referencing the * object. * - * Otherwise it will return boost::none. + * Otherwise it will return an empty optional. */ - boost::optional getObjectOptional() const + opt::optional getObjectOptional() const { if (value.is()) { - return boost::make_optional(PicoJsonObject(value)); + return opt::make_optional(PicoJsonObject(value)); } - return boost::none; + return opt::optional(); } /** @@ -503,16 +500,14 @@ public: * * This class provides a JSON array iterator that dereferences as an instance of * PicoJsonAdapter representing a value stored in the array. It has been - * implemented using the boost iterator_facade template. + * implemented using the std::iterator template. * * @see PicoJsonArray */ class PicoJsonArrayValueIterator: - public boost::iterator_facade< - PicoJsonArrayValueIterator, // name of derived type - PicoJsonAdapter, // value type - boost::bidirectional_traversal_tag, // bi-directional iterator - PicoJsonAdapter> // type returned when dereferenced + public std::iterator< + std::bidirectional_iterator_tag, // bi-directional iterator + PicoJsonAdapter> // value type { public: @@ -528,11 +523,16 @@ public: /// Returns a PicoJsonAdapter that contains the value of the current /// element. - PicoJsonAdapter dereference() const + PicoJsonAdapter operator*() const { return PicoJsonAdapter(*itr); } + DerefProxy operator->() const + { + return DerefProxy(**this); + } + /** * @brief Compare this iterator against another iterator. * @@ -544,19 +544,35 @@ public: * * @returns true if the iterators are equal, false otherwise. */ - bool equal(const PicoJsonArrayValueIterator &other) const + bool operator==(const PicoJsonArrayValueIterator &other) const { return itr == other.itr; } - void increment() + bool operator!=(const PicoJsonArrayValueIterator &other) const { - itr++; + return !(itr == other.itr); } - void decrement() + const PicoJsonArrayValueIterator& operator++() + { + itr++; + + return *this; + } + + PicoJsonArrayValueIterator operator++(int) + { + PicoJsonArrayValueIterator iterator_pre(itr); + ++(*this); + return iterator_pre; + } + + const PicoJsonArrayValueIterator& operator--() { itr--; + + return *this; } void advance(std::ptrdiff_t n) @@ -580,11 +596,9 @@ private: * @see PicoJsonObjectMember */ class PicoJsonObjectMemberIterator: - public boost::iterator_facade< - PicoJsonObjectMemberIterator, // name of derived type - PicoJsonObjectMember, // value type - boost::bidirectional_traversal_tag, // bi-directional iterator - PicoJsonObjectMember> // type returned when dereferenced + public std::iterator< + std::bidirectional_iterator_tag, // bi-directional iterator + PicoJsonObjectMember> // value type { public: @@ -601,11 +615,16 @@ public: * @brief Returns a PicoJsonObjectMember that contains the key and value * belonging to the object member identified by the iterator. */ - PicoJsonObjectMember dereference() const + PicoJsonObjectMember operator*() const { return PicoJsonObjectMember(itr->first, itr->second); } + DerefProxy operator->() const + { + return DerefProxy(**this); + } + /** * @brief Compare this iterator with another iterator. * @@ -617,19 +636,35 @@ public: * * @returns true if the underlying iterators are equal, false otherwise */ - bool equal(const PicoJsonObjectMemberIterator &other) const + bool operator==(const PicoJsonObjectMemberIterator &other) const { return itr == other.itr; } - void increment() + bool operator!=(const PicoJsonObjectMemberIterator &other) const { - itr++; + return !(itr == other.itr); } - void decrement() + const PicoJsonObjectMemberIterator& operator++() + { + itr++; + + return *this; + } + + PicoJsonObjectMemberIterator operator++(int) + { + PicoJsonObjectMemberIterator iterator_pre(itr); + ++(*this); + return iterator_pre; + } + + const PicoJsonObjectMemberIterator& operator--(int) { itr--; + + return *this; } private: diff --git a/include/valijson/adapters/property_tree_adapter.hpp b/include/valijson/adapters/property_tree_adapter.hpp index 2957d1c..239691f 100644 --- a/include/valijson/adapters/property_tree_adapter.hpp +++ b/include/valijson/adapters/property_tree_adapter.hpp @@ -28,8 +28,7 @@ #define __VALIJSON_ADAPTERS_PROPERTY_TREE_ADAPTER_HPP #include -#include -#include + #include #include @@ -281,7 +280,7 @@ public: { if (tree.data().empty()) { // No string content if (tree.size() == 0) { // No children - array = tree; // Treat as empty array + array.emplace(tree); // Treat as empty array } else { bool isArray = true; boost::property_tree::ptree::const_iterator itr; @@ -293,9 +292,9 @@ public: } if (isArray) { - array = tree; + array.emplace(tree); } else { - object = tree; + object.emplace(tree); } } } else { @@ -325,18 +324,18 @@ public: * @brief Return an instance of PropertyTreeArrayAdapter. * * If the referenced property tree value is an array, this function will - * return a boost::optional containing a PropertyTreeArray instance + * return a std::optional containing a PropertyTreeArray instance * referencing the array. * - * Otherwise it will return boost::none. + * Otherwise it will return an empty optional. */ - boost::optional getArrayOptional() const + opt::optional getArrayOptional() const { if (array) { - return boost::make_optional(PropertyTreeArray(*array)); + return opt::make_optional(PropertyTreeArray(*array)); } - return boost::none; + return opt::optional(); } /** @@ -379,18 +378,18 @@ public: * @brief Optionally return a PropertyTreeObject instance. * * If the referenced property tree is an object, this function will return a - * boost::optional containing a PropertyTreeObject instance referencing the + * std::optional containing a PropertyTreeObject instance referencing the * object. * - * Otherwise it will return boost::none. + * Otherwise it will return an empty optional. */ - boost::optional getObjectOptional() const + opt::optional getObjectOptional() const { if (object) { - return boost::make_optional(PropertyTreeObject(*object)); + return opt::make_optional(PropertyTreeObject(*object)); } - return boost::none; + return opt::optional(); } /** @@ -431,7 +430,7 @@ public: bool isArray() const { - return array != boost::none; + return static_cast(array); } bool isBool() const @@ -461,12 +460,12 @@ public: bool isObject() const { - return object != boost::none; + return static_cast(object); } bool isString() const { - return value != boost::none; + return static_cast(value); } private: @@ -478,13 +477,13 @@ private: } /// Reference used if the value is known to be an array - boost::optional array; + opt::optional array; /// Reference used if the value is known to be an object - boost::optional object; + opt::optional object; /// Reference used if the value is known to be a POD type - boost::optional value; + opt::optional value; }; /** @@ -525,11 +524,9 @@ public: * @see PropertyTreeArray */ class PropertyTreeArrayValueIterator: - public boost::iterator_facade< - PropertyTreeArrayValueIterator, // name of derived type - PropertyTreeAdapter, // value type - boost::bidirectional_traversal_tag, // bi-directional iterator - PropertyTreeAdapter> // type returned when dereferenced + public std::iterator< + std::bidirectional_iterator_tag, // bi-directional iterator + PropertyTreeAdapter> // value type { public: @@ -545,11 +542,16 @@ public: /// Returns a PropertyTreeAdapter that contains the value of the current /// element. - PropertyTreeAdapter dereference() const + PropertyTreeAdapter operator*() const { return PropertyTreeAdapter(itr->second); } + DerefProxy operator->() const + { + return DerefProxy(**this); + } + /** * @brief Compare this iterator against another iterator. * @@ -561,19 +563,35 @@ public: * * @returns true if the iterators are equal, false otherwise. */ - bool equal(const PropertyTreeArrayValueIterator &rhs) const + bool operator==(const PropertyTreeArrayValueIterator &rhs) const { return itr == rhs.itr; } - void increment() + bool operator!=(const PropertyTreeArrayValueIterator &rhs) const { - itr++; + return !(itr == rhs.itr); } - void decrement() + const PropertyTreeArrayValueIterator& operator++() + { + itr++; + + return *this; + } + + PropertyTreeArrayValueIterator operator++(int) + { + PropertyTreeArrayValueIterator iterator_pre(itr); + ++(*this); + return iterator_pre; + } + + const PropertyTreeArrayValueIterator& operator--() { itr--; + + return *this; } void advance(std::ptrdiff_t n) @@ -605,11 +623,9 @@ private: * @see PropertyTreeObjectMember */ class PropertyTreeObjectMemberIterator: - public boost::iterator_facade< - PropertyTreeObjectMemberIterator, // name of derived type - PropertyTreeObjectMember, // value type - boost::bidirectional_traversal_tag, // bi-directional iterator - PropertyTreeObjectMember> // type returned when dereferenced + public std::iterator< + std::bidirectional_iterator_tag, // bi-directional iterator + PropertyTreeObjectMember> // value type { public: @@ -626,11 +642,16 @@ public: * @brief Returns a PropertyTreeObjectMember that contains the key and * value belonging to the object member identified by the iterator. */ - PropertyTreeObjectMember dereference() const + PropertyTreeObjectMember operator*() const { return PropertyTreeObjectMember(itr->first, itr->second); } + DerefProxy operator->() const + { + return DerefProxy(**this); + } + /** * @brief Compare this iterator with another iterator. * @@ -642,19 +663,35 @@ public: * * @returns true if the underlying iterators are equal, false otherwise */ - bool equal(const PropertyTreeObjectMemberIterator &rhs) const + bool operator==(const PropertyTreeObjectMemberIterator &rhs) const { return itr == rhs.itr; } - void increment() + bool operator!=(const PropertyTreeObjectMemberIterator &rhs) const { - itr++; + return !(itr == rhs.itr); } - void decrement() + const PropertyTreeObjectMemberIterator& operator++() { - itr--; + itr++; + + return *this; + } + + PropertyTreeObjectMemberIterator operator++(int) + { + PropertyTreeObjectMemberIterator iterator_pre(itr); + ++(*this); + return iterator_pre; + } + + const PropertyTreeObjectMemberIterator& operator--() + { + itr++; + + return *this; } private: diff --git a/include/valijson/adapters/rapidjson_adapter.hpp b/include/valijson/adapters/rapidjson_adapter.hpp index c0f83bf..aed7bdf 100644 --- a/include/valijson/adapters/rapidjson_adapter.hpp +++ b/include/valijson/adapters/rapidjson_adapter.hpp @@ -43,9 +43,7 @@ #define __VALIJSON_ADAPTERS_RAPIDJSON_ADAPTER_HPP #include -#include -#include -#include +#include #include @@ -403,18 +401,18 @@ public: * @brief Optionally return a GenericRapidJsonArray instance. * * If the referenced RapidJson value is an array, this function will return - * a boost::optional containing a GenericRapidJsonArray instance referencing + * a std::optional containing a GenericRapidJsonArray instance referencing * the array. * - * Otherwise it will return boost::none. + * Otherwise it will return an empty optional. */ - boost::optional > getArrayOptional() const + opt::optional > getArrayOptional() const { if (value.IsArray()) { - return boost::make_optional(GenericRapidJsonArray(value)); + return opt::make_optional(GenericRapidJsonArray(value)); } - return boost::none; + return opt::optional >(); } /** @@ -481,18 +479,18 @@ public: * @brief Optionally return a GenericRapidJsonObject instance. * * If the referenced RapidJson value is an object, this function will return - * a boost::optional containing a GenericRapidJsonObject instance + * a std::optional containing a GenericRapidJsonObject instance * referencing the object. * - * Otherwise it will return boost::none. + * Otherwise it will return an empty optional. */ - boost::optional > getObjectOptional() const + opt::optional > getObjectOptional() const { if (value.IsObject()) { - return boost::make_optional(GenericRapidJsonObject(value)); + return opt::make_optional(GenericRapidJsonObject(value)); } - return boost::none; + return opt::optional >(); } /** @@ -626,17 +624,15 @@ public: * * This class provides a JSON array iterator that dereferences as an instance of * RapidJsonAdapter representing a value stored in the array. It has been - * implemented using the boost iterator_facade template. + * implemented using the std::iterator template. * * @see RapidJsonArray */ template class GenericRapidJsonArrayValueIterator: - public boost::iterator_facade< - GenericRapidJsonArrayValueIterator, // name of derived type - GenericRapidJsonAdapter, // value type - boost::bidirectional_traversal_tag, // bi-directional iterator - GenericRapidJsonAdapter > // type returned when dereferenced + public std::iterator< + std::bidirectional_iterator_tag, // bi-directional iterator + GenericRapidJsonAdapter > // value type { public: @@ -652,11 +648,17 @@ public: /// Returns a GenericRapidJsonAdapter that contains the value of the current /// element. - GenericRapidJsonAdapter dereference() const + GenericRapidJsonAdapter operator*() const { return GenericRapidJsonAdapter(*itr); } + /// Returns a proxy for the value of the current element + DerefProxy > operator->() const + { + return DerefProxy >(**this); + } + /** * @brief Compare this iterator against another iterator. * @@ -668,19 +670,34 @@ public: * * @returns true if the iterators are equal, false otherwise. */ - bool equal(const GenericRapidJsonArrayValueIterator &other) const + bool operator==(const GenericRapidJsonArrayValueIterator &other) const { return itr == other.itr; } - void increment() + bool operator!=(const GenericRapidJsonArrayValueIterator& other) const { - itr++; + return !(itr == other.itr); } - void decrement() + GenericRapidJsonArrayValueIterator& operator++() + { + itr++; + + return *this; + } + + GenericRapidJsonArrayValueIterator operator++(int) { + GenericRapidJsonArrayValueIterator iterator_pre(itr); + ++(*this); + return iterator_pre; + } + + GenericRapidJsonArrayValueIterator& operator--() { itr--; + + return *this; } void advance(std::ptrdiff_t n) @@ -688,7 +705,7 @@ public: itr += n; } - std::ptrdiff_t difference(const GenericRapidJsonArrayValueIterator &other) + std::ptrdiff_t difference(const GenericRapidJsonArrayValueIterator &other) { return std::distance(itr, other.itr); } @@ -703,18 +720,16 @@ private: * * This class provides a JSON object iterator that dereferences as an instance * of GenericRapidJsonObjectMember representing one of the members of the - * object. It has been implemented using the boost iterator_facade template. + * object. It has been implemented using the std::iterator template. * * @see GenericRapidJsonObject * @see GenericRapidJsonObjectMember */ template class GenericRapidJsonObjectMemberIterator: - public boost::iterator_facade< - GenericRapidJsonObjectMemberIterator, // name of derived type - GenericRapidJsonObjectMember, // value type - boost::bidirectional_traversal_tag, // bi-directional iterator - GenericRapidJsonObjectMember > // type returned when dereferenced + public std::iterator< + std::bidirectional_iterator_tag, // bi-directional iterator + GenericRapidJsonObjectMember > // value type { public: @@ -727,17 +742,24 @@ public: const typename ValueType::ConstMemberIterator &itr) : itr(itr) { } + /** * @brief Returns a GenericRapidJsonObjectMember that contains the key and * value belonging to the object member identified by the iterator. */ - GenericRapidJsonObjectMember dereference() const + GenericRapidJsonObjectMember operator*() const { return GenericRapidJsonObjectMember( std::string(itr->name.GetString(), itr->name.GetStringLength()), itr->value); } + /// Returns a proxy for the value of the current element + DerefProxy > operator->() const + { + return DerefProxy >(**this); + } + /** * @brief Compare this iterator with another iterator. * @@ -749,19 +771,35 @@ public: * * @returns true if the underlying iterators are equal, false otherwise */ - bool equal(const GenericRapidJsonObjectMemberIterator &other) const + bool operator==(const GenericRapidJsonObjectMemberIterator &other) const { return itr == other.itr; } - void increment() + bool operator!=(const GenericRapidJsonObjectMemberIterator &other) const { - itr++; + return !(itr == other.itr); } - void decrement() + GenericRapidJsonObjectMemberIterator& operator++() + { + itr++; + + return *this; + } + + GenericRapidJsonObjectMemberIterator operator++(int) + { + GenericRapidJsonObjectMemberIterator iterator_pre(itr); + ++(*this); + return iterator_pre; + } + + GenericRapidJsonObjectMemberIterator& operator--() { itr--; + + return *this; } std::ptrdiff_t difference(const GenericRapidJsonObjectMemberIterator &other) diff --git a/include/valijson/constraints/concrete_constraints.hpp b/include/valijson/constraints/concrete_constraints.hpp index e5dbe64..7ada085 100644 --- a/include/valijson/constraints/concrete_constraints.hpp +++ b/include/valijson/constraints/concrete_constraints.hpp @@ -16,9 +16,6 @@ #ifndef __VALIJSON_CONSTRAINTS_CONCRETE_CONSTRAINTS_HPP #define __VALIJSON_CONSTRAINTS_CONCRETE_CONSTRAINTS_HPP -#include -#include - #include #include #include @@ -60,7 +57,7 @@ public: void applyToSubschemas(const FunctorType &fn) const { unsigned int index = 0; - BOOST_FOREACH( const Subschema *subschema, subschemas ) { + for( const Subschema *subschema : subschemas ) { if (!fn(index, subschema)) { return; } @@ -103,7 +100,7 @@ public: void applyToSubschemas(const FunctorType &fn) const { unsigned int index = 0; - BOOST_FOREACH( const Subschema *subschema, subschemas ) { + for( const Subschema *subschema : subschemas ) { if (!fn(index, subschema)) { return; } @@ -170,7 +167,7 @@ public: } typedef typename ContainerType::value_type ValueType; - BOOST_FOREACH( const ValueType &dependencyName, dependencyNames ) { + for( const ValueType &dependencyName : dependencyNames ) { itr->second.insert(String(dependencyName.c_str(), allocator)); } @@ -196,7 +193,7 @@ public: template void applyToPropertyDependencies(const FunctorType &fn) const { - BOOST_FOREACH( const PropertyDependencies::value_type &v, + for( const PropertyDependencies::value_type &v : propertyDependencies ) { if (!fn(v.first, v.second)) { return; @@ -207,7 +204,7 @@ public: template void applyToSchemaDependencies(const FunctorType &fn) const { - BOOST_FOREACH( const SchemaDependencies::value_type &v, + for( const SchemaDependencies::value_type &v : schemaDependencies ) { if (!fn(v.first, v.second)) { return; @@ -254,7 +251,7 @@ public: { try { // Clone individual enum values - BOOST_FOREACH( const EnumValue *otherValue, other.enumValues ) { + for( const EnumValue *otherValue : other.enumValues ) { const EnumValue *value = otherValue->clone(); try { enumValues.push_back(value); @@ -266,7 +263,7 @@ public: } catch (...) { // Delete values already added to constraint - BOOST_FOREACH( const EnumValue *value, enumValues ) { + for( const EnumValue *value : enumValues ) { delete value; } throw; @@ -275,7 +272,7 @@ public: virtual ~EnumConstraint() { - BOOST_FOREACH( const EnumValue *value, enumValues ) { + for( const EnumValue *value : enumValues ) { delete value; } } @@ -295,7 +292,7 @@ public: template void applyToValues(const FunctorType &fn) const { - BOOST_FOREACH( const EnumValue *value, enumValues ) { + for( const EnumValue *value : enumValues ) { if (!fn(*value)) { return; } @@ -345,7 +342,7 @@ public: void applyToItemSubschemas(const FunctorType &fn) const { unsigned int index = 0; - BOOST_FOREACH( const Subschema *subschema, itemSubschemas ) { + for( const Subschema *subschema : itemSubschemas ) { if (!fn(index, subschema)) { return; } @@ -727,7 +724,7 @@ public: void applyToSubschemas(const FunctorType &fn) const { unsigned int index = 0; - BOOST_FOREACH( const Subschema *subschema, subschemas ) { + for( const Subschema *subschema : subschemas ) { if (!fn(index, subschema)) { return; } @@ -870,7 +867,7 @@ public: void applyToPatternProperties(const FunctorType &fn) const { typedef typename PropertySchemaMap::value_type ValueType; - BOOST_FOREACH( const ValueType &value, patternProperties ) { + for( const ValueType &value : patternProperties ) { if (!fn(value.first, value.second)) { return; } @@ -881,7 +878,7 @@ public: void applyToProperties(const FunctorType &fn) const { typedef typename PropertySchemaMap::value_type ValueType; - BOOST_FOREACH( const ValueType &value, properties ) { + for( const ValueType &value : properties ) { if (!fn(value.first, value.second)) { return; } @@ -937,7 +934,7 @@ public: template void applyToRequiredProperties(const FunctorType &fn) const { - BOOST_FOREACH( const String &propertyName, requiredProperties ) { + for( const String &propertyName : requiredProperties ) { if (!fn(propertyName)) { return; } @@ -1024,7 +1021,7 @@ public: template void applyToNamedTypes(const FunctorType &fn) const { - BOOST_FOREACH( const JsonType namedType, namedTypes ) { + for( const JsonType namedType : namedTypes ) { if (!fn(namedType)) { return; } @@ -1035,7 +1032,7 @@ public: void applyToSchemaTypes(const FunctorType &fn) const { unsigned int index = 0; - BOOST_FOREACH( const Subschema *subschema, schemaTypes ) { + for( const Subschema *subschema : schemaTypes ) { if (!fn(index, subschema)) { return; } diff --git a/include/valijson/internal/json_pointer.hpp b/include/valijson/internal/json_pointer.hpp index 650d062..77f1c2d 100644 --- a/include/valijson/internal/json_pointer.hpp +++ b/include/valijson/internal/json_pointer.hpp @@ -6,9 +6,13 @@ #include #include -#include -#include -#include +#if __has_include() +# include +namespace opt = std; +#else +# include +namespace opt = std::experimental; +#endif #include @@ -16,6 +20,25 @@ namespace valijson { namespace internal { namespace json_pointer { +/** + * @brief Replace all occurrences of `search` with `replace`. Modifies `subject` in place + * + * @param subject string to operate on + * @param search string to search + * @param replace replacement string + */ + +inline void replace_all_inplace(std::string& subject, const char* search, + const char* replace) +{ + size_t pos = 0; + + while((pos = subject.find(search, pos)) != std::string::npos) { + subject.replace(pos, strlen(search), replace); + pos += strlen(replace); + } +} + /** * @brief Return the char value corresponding to a 2-digit hexadecimal string * @@ -78,8 +101,8 @@ inline std::string extractReferenceToken(std::string::const_iterator begin, std::string token(begin, end); // Replace JSON Pointer-specific escaped character sequences - boost::replace_all(token, "~1", "/"); - boost::replace_all(token, "~0", "~"); + replace_all_inplace(token, "~1", "/"); + replace_all_inplace(token, "~0", "~"); // Replace %-encoded character sequences with their actual characters for (size_t n = token.find('%'); n != std::string::npos; @@ -169,8 +192,7 @@ inline AdapterType resolveJsonPointer( try { // Fragment must be non-negative integer - const uint64_t index = boost::lexical_cast( - referenceToken); + const uint64_t index = std::stoul(referenceToken); typedef typename AdapterType::Array Array; typename Array::const_iterator itr = node.asArray().begin(); @@ -182,7 +204,7 @@ inline AdapterType resolveJsonPointer( if (index > static_cast(std::numeric_limits::max())) { throw std::runtime_error("Array index out of bounds; hard " - "limit is " + boost::lexical_cast( + "limit is " + std::to_string( std::numeric_limits::max())); } @@ -191,7 +213,7 @@ inline AdapterType resolveJsonPointer( // Recursively process the remaining tokens return resolveJsonPointer(*itr, jsonPointer, jsonPointerNext); - } catch (boost::bad_lexical_cast &) { + } catch (std::invalid_argument &) { throw std::runtime_error("Expected reference token to contain a " "non-negative integer to identify an element in the " "current array; actual token: " + referenceToken); diff --git a/include/valijson/internal/json_reference.hpp b/include/valijson/internal/json_reference.hpp index d06538a..bd8e87c 100644 --- a/include/valijson/internal/json_reference.hpp +++ b/include/valijson/internal/json_reference.hpp @@ -5,7 +5,13 @@ #include #include -#include +#if __has_include() +# include +namespace opt = std; +#else +# include +namespace opt = std::experimental; +#endif namespace valijson { namespace internal { @@ -19,14 +25,14 @@ namespace json_reference { * * @return Optional string containing URI */ - inline boost::optional getJsonReferenceUri( + inline opt::optional getJsonReferenceUri( const std::string &jsonRef) { const size_t ptrPos = jsonRef.find("#"); if (ptrPos == 0) { // The JSON Reference does not contain a URI, but might contain a // JSON Pointer that refers to the current document - return boost::none; + return opt::optional(); } else if (ptrPos != std::string::npos) { // The JSON Reference contains a URI and possibly a JSON Pointer return jsonRef.substr(0, ptrPos); @@ -43,7 +49,7 @@ namespace json_reference { * * @return Optional string containing JSON Pointer */ - inline boost::optional getJsonReferencePointer( + inline opt::optional getJsonReferencePointer( const std::string &jsonRef) { // Attempt to extract JSON Pointer if '#' character is present. Note @@ -54,7 +60,7 @@ namespace json_reference { return jsonRef.substr(ptrPos + 1); } - return boost::none; + return opt::optional(); } diff --git a/include/valijson/schema_parser.hpp b/include/valijson/schema_parser.hpp index 8970d12..68e8c9e 100644 --- a/include/valijson/schema_parser.hpp +++ b/include/valijson/schema_parser.hpp @@ -7,11 +7,6 @@ #include #include -#include -#include -#include -#include - #include #include #include @@ -135,7 +130,8 @@ public: typename DocumentCache::Type docCache; SchemaCache schemaCache; try { - resolveThenPopulateSchema(schema, node, node, schema, boost::none, "", + resolveThenPopulateSchema(schema, node, node, schema, + opt::optional(), "", fetchDoc, NULL, NULL, docCache, schemaCache); } catch (...) { freeDocumentCache(docCache, freeDoc); @@ -178,7 +174,7 @@ private: { typedef typename DocumentCache::Type DocCacheType; - BOOST_FOREACH( const typename DocCacheType::value_type &v, docCache ) { + for( const typename DocCacheType::value_type &v : docCache ) { freeDoc(v.second); } } @@ -207,9 +203,9 @@ private: * document URI should be used to replace the path, query and fragment * portions of URI provided by the resolution scope. */ - static boost::optional findAbsoluteDocumentUri( - const boost::optional resolutionScope, - const boost::optional documentUri) + static opt::optional findAbsoluteDocumentUri( + const opt::optional resolutionScope, + const opt::optional documentUri) { if (resolutionScope) { if (documentUri) { @@ -225,7 +221,7 @@ private: } else if (documentUri && internal::uri::isUriAbsolute(*documentUri)) { return *documentUri; } else { - return boost::none; + return opt::optional(); } } @@ -262,7 +258,7 @@ private: /** * Sanitise an optional JSON Pointer, trimming trailing slashes */ - std::string sanitiseJsonPointer(const boost::optional input) + std::string sanitiseJsonPointer(const opt::optional input) { if (input) { // Trim trailing slash(es) @@ -318,7 +314,7 @@ private: const std::vector &keysToCreate, const Subschema *schema) { - BOOST_FOREACH( const std::string &keyToCreate, keysToCreate ) { + for( const std::string &keyToCreate : keysToCreate ) { const SchemaCache::value_type value(keyToCreate, schema); if (!schemaCache.insert(value).second) { throw std::logic_error( @@ -363,7 +359,7 @@ private: Schema &rootSchema, const AdapterType &rootNode, const AdapterType &node, - const boost::optional currentScope, + const opt::optional currentScope, const std::string &nodePath, const typename FunctionPtrs::FetchDoc fetchDoc, const Subschema *parentSubschema, @@ -408,7 +404,7 @@ private: // Returns a document URI if the reference points somewhere // other than the current document - const boost::optional documentUri = + const opt::optional documentUri = internal::json_reference::getJsonReferenceUri(jsonRef); // Extract JSON Pointer from JSON Reference, with any trailing @@ -421,7 +417,7 @@ private: // scope. An absolute document URI will take precedence when // present, otherwise we need to resolve the URI relative to // the current resolution scope - const boost::optional actualDocumentUri = + const opt::optional actualDocumentUri = findAbsoluteDocumentUri(currentScope, documentUri); // Construct a key to search the schema cache for an existing schema @@ -536,7 +532,7 @@ private: Schema &rootSchema, const AdapterType &rootNode, const AdapterType &node, - const boost::optional currentScope, + const opt::optional currentScope, const std::string &nodePath, const typename FunctionPtrs::FetchDoc fetchDoc, const Subschema *parentSubschema, @@ -583,7 +579,7 @@ private: const AdapterType &rootNode, const AdapterType &node, const Subschema &subschema, - const boost::optional currentScope, + const opt::optional currentScope, const std::string &nodePath, const typename FunctionPtrs::FetchDoc fetchDoc, const Subschema *parentSubschema, @@ -591,7 +587,7 @@ private: typename DocumentCache::Type &docCache, SchemaCache &schemaCache) { - BOOST_STATIC_ASSERT_MSG((boost::is_convertible::value), "SchemaParser::populateSchema must be invoked with an " "appropriate Adapter implementation"); @@ -600,7 +596,7 @@ private: typename AdapterType::Object::const_iterator itr(object.end()); // Check for 'id' attribute and update current scope - boost::optional updatedScope; + opt::optional updatedScope; if ((itr = object.find("id")) != object.end() && itr->second.maybeString()) { const std::string id = itr->second.asString(); @@ -841,7 +837,7 @@ private: if ((itr = object.find("required")) != object.end()) { if (version == kDraft3) { if (parentSubschema && ownName) { - boost::optional + opt::optional constraint = makeRequiredConstraintForSelf( itr->second, *ownName); if (constraint) { @@ -877,7 +873,7 @@ private: } if ((itr = object.find("uniqueItems")) != object.end()) { - boost::optional constraint = + opt::optional constraint = makeUniqueItemsConstraint(itr->second); if (constraint) { rootSchema.addConstraintToSubschema(*constraint, &subschema); @@ -933,7 +929,7 @@ private: const AdapterType &rootNode, const AdapterType &node, const Subschema &subschema, - const boost::optional currentScope, + const opt::optional currentScope, const std::string &nodePath, const typename FunctionPtrs::FetchDoc fetchDoc, const Subschema *parentSchema, @@ -951,7 +947,7 @@ private: // Returns a document URI if the reference points somewhere // other than the current document - const boost::optional documentUri = + const opt::optional documentUri = internal::json_reference::getJsonReferenceUri(jsonRef); // Extract JSON Pointer from JSON Reference @@ -989,7 +985,7 @@ private: // TODO: Need to detect degenerate circular references resolveThenPopulateSchema(rootSchema, newRootNode, - referencedAdapter, subschema, boost::none, + referencedAdapter, subschema, opt::optional(), actualJsonPointer, fetchDoc, parentSchema, ownName, docCache, schemaCache); @@ -1000,7 +996,8 @@ private: // TODO: Need to detect degenerate circular references resolveThenPopulateSchema(rootSchema, rootNode, referencedAdapter, - subschema, boost::none, actualJsonPointer, fetchDoc, + subschema, opt::optional(), + actualJsonPointer, fetchDoc, parentSchema, ownName, docCache, schemaCache); } } @@ -1028,7 +1025,7 @@ private: Schema &rootSchema, const AdapterType &rootNode, const AdapterType &node, - const boost::optional currentScope, + const opt::optional currentScope, const std::string &nodePath, const typename FunctionPtrs::FetchDoc fetchDoc, typename DocumentCache::Type &docCache, @@ -1042,10 +1039,10 @@ private: constraints::AllOfConstraint constraint; int index = 0; - BOOST_FOREACH ( const AdapterType schemaNode, node.asArray() ) { + for ( const AdapterType schemaNode : node.asArray() ) { if (schemaNode.maybeObject()) { const std::string childPath = nodePath + "/" + - boost::lexical_cast(index); + std::to_string(index); const Subschema *subschema = makeOrReuseSchema( rootSchema, rootNode, schemaNode, currentScope, childPath, fetchDoc, NULL, NULL, docCache, schemaCache); @@ -1084,7 +1081,7 @@ private: Schema &rootSchema, const AdapterType &rootNode, const AdapterType &node, - const boost::optional currentScope, + const opt::optional currentScope, const std::string &nodePath, const typename FunctionPtrs::FetchDoc fetchDoc, typename DocumentCache::Type &docCache, @@ -1098,10 +1095,10 @@ private: constraints::AnyOfConstraint constraint; int index = 0; - BOOST_FOREACH ( const AdapterType schemaNode, node.asArray() ) { + for ( const AdapterType schemaNode : node.asArray() ) { if (schemaNode.maybeObject()) { const std::string childPath = nodePath + "/" + - boost::lexical_cast(index); + std::to_string(index); const Subschema *subschema = makeOrReuseSchema( rootSchema, rootNode, schemaNode, currentScope, childPath, fetchDoc, NULL, NULL, docCache, schemaCache); @@ -1158,7 +1155,7 @@ private: Schema &rootSchema, const AdapterType &rootNode, const AdapterType &node, - const boost::optional currentScope, + const opt::optional currentScope, const std::string &nodePath, const typename FunctionPtrs::FetchDoc fetchDoc, typename DocumentCache::Type &docCache, @@ -1171,7 +1168,7 @@ private: constraints::DependenciesConstraint dependenciesConstraint; // Process each of the dependency mappings defined by the object - BOOST_FOREACH ( const typename AdapterType::ObjectMember member, node.asObject() ) { + for ( const typename AdapterType::ObjectMember member : node.asObject() ) { // First, we attempt to parse the value of the dependency mapping // as an array of strings. If the Adapter type does not support @@ -1183,7 +1180,7 @@ private: if (member.second.maybeArray()) { // Parse an array of dependency names std::vector dependentPropertyNames; - BOOST_FOREACH( const AdapterType dependencyName, member.second.asArray() ) { + for( const AdapterType dependencyName : member.second.asArray() ) { if (dependencyName.maybeString()) { dependentPropertyNames.push_back(dependencyName.getString()); } else { @@ -1240,7 +1237,7 @@ private: { // Make a copy of each value in the enum array constraints::EnumConstraint constraint; - BOOST_FOREACH( const AdapterType value, node.getArray() ) { + for( const AdapterType value : node.getArray() ) { constraint.addValue(value); } @@ -1286,7 +1283,7 @@ private: const AdapterType &rootNode, const AdapterType *items, const AdapterType *additionalItems, - const boost::optional currentScope, + const opt::optional currentScope, const std::string &itemsPath, const std::string &additionalItemsPath, const typename FunctionPtrs::FetchDoc fetchDoc, @@ -1338,9 +1335,9 @@ private: // validate the values at the corresponding indexes in a target // array. int index = 0; - BOOST_FOREACH( const AdapterType v, items->getArray() ) { + for( const AdapterType v : items->getArray() ) { const std::string childPath = itemsPath + "/" + - boost::lexical_cast(index); + std::to_string(index); const Subschema *subschema = makeOrReuseSchema( rootSchema, rootNode, v, currentScope, childPath, fetchDoc, NULL, NULL, docCache, schemaCache); @@ -1391,7 +1388,7 @@ private: Schema &rootSchema, const AdapterType &rootNode, const AdapterType &items, - const boost::optional currentScope, + const opt::optional currentScope, const std::string &itemsPath, const typename FunctionPtrs::FetchDoc fetchDoc, typename DocumentCache::Type &docCache, @@ -1726,7 +1723,7 @@ private: Schema &rootSchema, const AdapterType &rootNode, const AdapterType &node, - const boost::optional currentScope, + const opt::optional currentScope, const std::string &nodePath, const typename FunctionPtrs::FetchDoc fetchDoc, typename DocumentCache::Type &docCache, @@ -1766,7 +1763,7 @@ private: Schema &rootSchema, const AdapterType &rootNode, const AdapterType &node, - const boost::optional currentScope, + const opt::optional currentScope, const std::string &nodePath, const typename FunctionPtrs::FetchDoc fetchDoc, typename DocumentCache::Type &docCache, @@ -1775,9 +1772,9 @@ private: constraints::OneOfConstraint constraint; int index = 0; - BOOST_FOREACH ( const AdapterType schemaNode, node.getArray() ) { + for ( const AdapterType schemaNode : node.getArray() ) { const std::string childPath = nodePath + "/" + - boost::lexical_cast(index); + std::to_string(index); const Subschema *subschema = makeOrReuseSchema( rootSchema, rootNode, schemaNode, currentScope, childPath, fetchDoc, NULL, NULL, docCache, schemaCache); @@ -1849,7 +1846,7 @@ private: const AdapterType *properties, const AdapterType *patternProperties, const AdapterType *additionalProperties, - const boost::optional currentScope, + const opt::optional currentScope, const std::string &propertiesPath, const std::string &patternPropertiesPath, const std::string &additionalPropertiesPath, @@ -1864,7 +1861,7 @@ private: // Create subschemas for 'properties' constraint if (properties) { - BOOST_FOREACH( const Member m, properties->getObject() ) { + for( const Member m : properties->getObject() ) { const std::string &property = m.first; const std::string childPath = propertiesPath + "/" + property; const Subschema *subschema = makeOrReuseSchema( @@ -1877,7 +1874,7 @@ private: // Create subschemas for 'patternProperties' constraint if (patternProperties) { - BOOST_FOREACH( const Member m, patternProperties->getObject() ) { + for( const Member m : patternProperties->getObject() ) { const std::string &pattern = m.first; const std::string childPath = patternPropertiesPath + "/" + pattern; @@ -1942,7 +1939,7 @@ private: * caller */ template - boost::optional + opt::optional makeRequiredConstraintForSelf(const AdapterType &node, const std::string &name) { @@ -1956,7 +1953,7 @@ private: return constraint; } - return boost::none; + return opt::optional(); } /** @@ -1976,7 +1973,7 @@ private: { constraints::RequiredConstraint constraint; - BOOST_FOREACH( const AdapterType v, node.getArray() ) { + for( const AdapterType v : node.getArray() ) { if (!v.isString()) { throw std::runtime_error("Expected required property name to " "be a string value"); @@ -2010,7 +2007,7 @@ private: Schema &rootSchema, const AdapterType &rootNode, const AdapterType &node, - const boost::optional currentScope, + const opt::optional currentScope, const std::string &nodePath, const typename FunctionPtrs::FetchDoc fetchDoc, typename DocumentCache::Type &docCache, @@ -2033,7 +2030,7 @@ private: } else if (node.isArray()) { int index = 0; - BOOST_FOREACH( const AdapterType v, node.getArray() ) { + for( const AdapterType v : node.getArray() ) { if (v.isString()) { const TypeConstraint::JsonType type = TypeConstraint::jsonTypeFromString(v.getString()); @@ -2048,7 +2045,7 @@ private: } else if (v.isObject() && version == kDraft3) { const std::string childPath = nodePath + "/" + - boost::lexical_cast(index); + std::to_string(index); const Subschema *subschema = makeOrReuseSchema( rootSchema, rootNode, v, currentScope, childPath, fetchDoc, NULL, NULL, docCache, schemaCache); @@ -2083,7 +2080,7 @@ private: * the caller, or NULL if the boolean value is false. */ template - boost::optional + opt::optional makeUniqueItemsConstraint(const AdapterType &node) { if (node.isBool() || node.maybeBool()) { @@ -2093,7 +2090,7 @@ private: if (node.asBool()) { return constraints::UniqueItemsConstraint(); } else { - return boost::none; + return opt::optional(); } } diff --git a/include/valijson/subschema.hpp b/include/valijson/subschema.hpp index 7d88f03..f80dadf 100644 --- a/include/valijson/subschema.hpp +++ b/include/valijson/subschema.hpp @@ -4,11 +4,17 @@ #include -#include -#include -#include #include +// This should be removed once C++17 is widely available +#if __has_include() +# include +namespace opt = std; +#else +# include +namespace opt = std::experimental; +#endif + #include namespace valijson { @@ -37,7 +43,7 @@ public: /// Typedef for a function that can be applied to each of the Constraint /// instances owned by a Schema. - typedef boost::function ApplyFunction; + typedef std::function ApplyFunction; /** * @brief Construct a new Subschema object @@ -115,7 +121,7 @@ public: bool apply(ApplyFunction &applyFunction) const { bool allTrue = true; - BOOST_FOREACH( const Constraint *constraint, constraints ) { + for( const Constraint *constraint : constraints ) { allTrue = allTrue && applyFunction(*constraint); } @@ -134,7 +140,7 @@ public: */ bool applyStrict(ApplyFunction &applyFunction) const { - BOOST_FOREACH( const Constraint *constraint, constraints ) { + for( const Constraint *constraint : constraints ) { if (!applyFunction(*constraint)) { return false; } @@ -198,7 +204,7 @@ public: */ bool hasDescription() const { - return description != boost::none; + return static_cast(description); } /** @@ -208,7 +214,7 @@ public: */ bool hasId() const { - return id != boost::none; + return static_cast(id); } /** @@ -218,7 +224,7 @@ public: */ bool hasTitle() const { - return title != boost::none; + return static_cast(title); } /** @@ -274,13 +280,13 @@ private: std::vector constraints; /// Schema description (optional) - boost::optional description; + opt::optional description; /// Id to apply when resolving the schema URI - boost::optional id; + opt::optional id; /// Title string associated with the schema (optional) - boost::optional title; + opt::optional title; }; } // namespace valijson diff --git a/include/valijson/utils/utf8_utils.hpp b/include/valijson/utils/utf8_utils.hpp index bea356f..4c3bc48 100644 --- a/include/valijson/utils/utf8_utils.hpp +++ b/include/valijson/utils/utf8_utils.hpp @@ -50,7 +50,7 @@ inline uint64_t u8_strlen(const char *s) if (i == maxLength) { throw std::runtime_error( "String exceeded maximum size of " + - boost::lexical_cast(maxLength) + " bytes."); + std::to_string(maxLength) + " bytes."); } count++; } diff --git a/include/valijson/validation_visitor.hpp b/include/valijson/validation_visitor.hpp index 085774f..b8e1b61 100644 --- a/include/valijson/validation_visitor.hpp +++ b/include/valijson/validation_visitor.hpp @@ -3,10 +3,8 @@ #define __VALIJSON_VALIDATION_VISITOR_HPP #include - -#include -#include -#include +#include +#include #include #include @@ -70,7 +68,7 @@ public: // Wrap the validationCallback() function below so that it will be // passed a reference to a constraint (_1), and a reference to the // visitor (*this). - Subschema::ApplyFunction fn(boost::bind(validationCallback, _1, *this)); + Subschema::ApplyFunction fn(std::bind(validationCallback, std::placeholders::_1, *this)); // Perform validation against each constraint defined in the schema if (results == NULL) { @@ -308,7 +306,7 @@ public: // Update context for current array item std::vector newContext = context; newContext.push_back("[" + - boost::lexical_cast(index) + "]"); + std::to_string(index) + "]"); ValidationVisitor validator(*itr, newContext, strictTypes, results); @@ -317,7 +315,7 @@ public: if (results) { results->pushError(context, "Failed to validate item #" + - boost::lexical_cast(index) + + std::to_string(index) + " against additional items schema."); validated = false; } else { @@ -330,7 +328,7 @@ public: } else if (results) { results->pushError(context, "Cannot validate item #" + - boost::lexical_cast(numValidated) + " or " + std::to_string(numValidated) + " or " "greater using 'items' constraint or 'additionalItems' " "constraint."); validated = false; @@ -363,7 +361,7 @@ public: if (target.asDouble() >= maximum) { if (results) { results->pushError(context, "Expected number less than " + - boost::lexical_cast(maximum)); + std::to_string(maximum)); } return false; @@ -373,7 +371,7 @@ public: if (results) { results->pushError(context, "Expected number less than or equal to " + - boost::lexical_cast(maximum)); + std::to_string(maximum)); } return false; @@ -402,7 +400,7 @@ public: if (results) { results->pushError(context, "Array should contain no more than " + - boost::lexical_cast(maxItems) + " elements."); + std::to_string(maxItems) + " elements."); } return false; @@ -431,7 +429,7 @@ public: if (results) { results->pushError(context, "String should be no more than " + - boost::lexical_cast(maxLength) + + std::to_string(maxLength) + " characters in length."); } @@ -459,7 +457,7 @@ public: if (results) { results->pushError(context, "Object should have no more than " + - boost::lexical_cast(maxProperties) + + std::to_string(maxProperties) + " properties."); } @@ -487,7 +485,7 @@ public: if (results) { results->pushError(context, "Expected number greater than " + - boost::lexical_cast(minimum)); + std::to_string(minimum)); } return false; @@ -496,7 +494,7 @@ public: if (results) { results->pushError(context, "Expected number greater than or equal to " + - boost::lexical_cast(minimum)); + std::to_string(minimum)); } return false; @@ -525,7 +523,7 @@ public: if (results) { results->pushError(context, "Array should contain no fewer than " + - boost::lexical_cast(minItems) + " elements."); + std::to_string(minItems) + " elements."); } return false; @@ -554,7 +552,7 @@ public: if (results) { results->pushError(context, "String should be no fewer than " + - boost::lexical_cast(minLength) + + std::to_string(minLength) + " characters in length."); } @@ -582,7 +580,7 @@ public: if (results) { results->pushError(context, "Object should have no fewer than " + - boost::lexical_cast(minProperties) + + std::to_string(minProperties) + " properties."); } @@ -606,7 +604,7 @@ public: if (results) { results->pushError(context, "Value could not be converted " "to a number to check if it is a multiple of " + - boost::lexical_cast(divisor)); + std::to_string(divisor)); } return false; } @@ -616,7 +614,7 @@ public: if (results) { results->pushError(context, "Value could not be converted " "to a number to check if it is a multiple of " + - boost::lexical_cast(divisor)); + std::to_string(divisor)); } return false; } @@ -634,7 +632,7 @@ public: if (fabs(r) > std::numeric_limits::epsilon()) { if (results) { results->pushError(context, "Value should be a multiple of " + - boost::lexical_cast(divisor)); + std::to_string(divisor)); } return false; } @@ -683,7 +681,7 @@ public: if (i % divisor != 0) { if (results) { results->pushError(context, "Value should be a multiple of " + - boost::lexical_cast(divisor)); + std::to_string(divisor)); } return false; } @@ -777,11 +775,10 @@ public: return true; } - const boost::regex patternRegex( - constraint.getPattern(), - boost::regex::perl); + const std::regex patternRegex( + constraint.getPattern()); - if (!boost::regex_search(target.asString(), patternRegex)) { + if (!std::regex_search(target.asString(), patternRegex)) { if (results) { results->pushError(context, "Failed to match regex specified by 'pattern' " @@ -878,7 +875,7 @@ public: return validated; } - BOOST_FOREACH( const typename AdapterType::ObjectMember m, object ) { + for( const typename AdapterType::ObjectMember m : object ) { if (propertiesMatched.find(m.first) == propertiesMatched.end()) { // Update context std::vector newContext = context; @@ -959,11 +956,11 @@ public: bool validated = true; unsigned int index = 0; - BOOST_FOREACH( const AdapterType &item, target.getArray() ) { + for( const AdapterType &item : target.getArray() ) { // Update context for current array item std::vector newContext = context; newContext.push_back("[" + - boost::lexical_cast(index) + "]"); + std::to_string(index) + "]"); // Create a validator for the current array item ValidationVisitor validationVisitor(item, @@ -974,7 +971,7 @@ public: if (results) { results->pushError(context, "Failed to validate item #" + - boost::lexical_cast(index) + + std::to_string(index) + " in array."); validated = false; } else { @@ -1062,8 +1059,8 @@ public: if (outerItr->equalTo(*innerItr, true)) { if (results) { results->pushError(context, "Elements at indexes #" + - boost::lexical_cast(outerIndex) + " and #" + - boost::lexical_cast(innerIndex) + " violate uniqueness constraint."); + std::to_string(outerIndex) + " and #" + + std::to_string(innerIndex) + " violate uniqueness constraint."); validated = false; } else { return false; @@ -1202,7 +1199,7 @@ private: } typedef typename ContainerType::value_type ValueType; - BOOST_FOREACH( const ValueType &dependencyName, dependencyNames ) { + for( const ValueType &dependencyName : dependencyNames ) { const std::string dependencyNameKey(dependencyName.c_str()); if (object.find(dependencyNameKey) == object.end()) { if (validated) { @@ -1260,7 +1257,7 @@ private: // Update context std::vector newContext = context; newContext.push_back( - "[" + boost::lexical_cast(index) + "]"); + "[" + std::to_string(index) + "]"); // Find array item typename AdapterType::Array::const_iterator itr = arr.begin(); @@ -1283,7 +1280,7 @@ private: if (results) { results->pushError(newContext, "Failed to validate item #" + - boost::lexical_cast(index) + + std::to_string(index) + " against corresponding item schema."); } @@ -1405,17 +1402,17 @@ private: const std::string patternPropertyStr(patternProperty.c_str()); // It would be nice to store pre-allocated regex objects in the - // PropertiesConstraint, but boost::regex does not currently support - // custom allocators. This isn't an issue here, because Valijson's + // PropertiesConstraint. does std::regex currently support + // custom allocators? Anyway, this isn't an issue here, because Valijson's // JSON Scheme validator does not yet support custom allocators. - const boost::regex r(patternPropertyStr, boost::regex::perl); + const std::regex r(patternPropertyStr); bool matchFound = false; // Recursively validate all matching properties typedef const typename AdapterType::ObjectMember ObjectMember; - BOOST_FOREACH( const ObjectMember m, object ) { - if (boost::regex_search(m.first, r)) { + for( const ObjectMember m : object ) { + if (std::regex_search(m.first, r)) { matchFound = true; if (propertiesMatched) { propertiesMatched->insert(m.first); @@ -1647,7 +1644,7 @@ private: if (results) { results->pushError(context, "Failed to validate against child schema #" + - boost::lexical_cast(index) + "."); + std::to_string(index) + "."); } return continueOnFailure; diff --git a/include/valijson/validator.hpp b/include/valijson/validator.hpp index 8921ec4..4e4a586 100644 --- a/include/valijson/validator.hpp +++ b/include/valijson/validator.hpp @@ -2,9 +2,6 @@ #ifndef __VALIJSON_VALIDATOR_HPP #define __VALIJSON_VALIDATOR_HPP -#include -#include - #include #include diff --git a/tests/test_adapter_comparison.cpp b/tests/test_adapter_comparison.cpp index f609db4..57195d1 100644 --- a/tests/test_adapter_comparison.cpp +++ b/tests/test_adapter_comparison.cpp @@ -1,8 +1,5 @@ #include -#include -#include - #include #include diff --git a/tests/test_fetch_document_callback.cpp b/tests/test_fetch_document_callback.cpp index 56e25b6..b8fd47b 100644 --- a/tests/test_fetch_document_callback.cpp +++ b/tests/test_fetch_document_callback.cpp @@ -1,4 +1,3 @@ -#include #include diff --git a/tests/test_json11_adapter.cpp b/tests/test_json11_adapter.cpp index f54cdea..dfc5464 100644 --- a/tests/test_json11_adapter.cpp +++ b/tests/test_json11_adapter.cpp @@ -1,8 +1,5 @@ #ifdef VALIJSON_BUILD_CXX11_ADAPTERS -#include -#include - #include #include @@ -38,7 +35,7 @@ TEST_F(TestJson11Adapter, BasicArrayIteration) // Ensure that the elements are returned in the order they were inserted unsigned int expectedValue = 0; - BOOST_FOREACH( const valijson::adapters::Json11Adapter value, adapter.getArray() ) { + for( const valijson::adapters::Json11Adapter value : adapter.getArray() ) { ASSERT_TRUE( value.isNumber() ); EXPECT_EQ( double(expectedValue), value.getDouble() ); expectedValue++; @@ -56,7 +53,7 @@ TEST_F(TestJson11Adapter, BasicObjectIteration) // strings their corresponding numeric values json11::Json::object object; for (unsigned int i = 0; i < numElements; i++) { - std::string name(boost::lexical_cast(i)); + std::string name(std::to_string(i)); object[name] = json11::Json(static_cast(i)); } json11::Json document(object); @@ -75,9 +72,9 @@ TEST_F(TestJson11Adapter, BasicObjectIteration) // Ensure that the members are returned in the order they were inserted unsigned int expectedValue = 0; - BOOST_FOREACH( const valijson::adapters::Json11Adapter::ObjectMember member, adapter.getObject() ) { + for( const valijson::adapters::Json11Adapter::ObjectMember member : adapter.getObject() ) { ASSERT_TRUE( member.second.isNumber() ); - EXPECT_EQ( boost::lexical_cast(expectedValue), member.first ); + EXPECT_EQ( std::to_string(expectedValue), member.first ); EXPECT_EQ( double(expectedValue), member.second.getDouble() ); expectedValue++; } diff --git a/tests/test_json_pointer.cpp b/tests/test_json_pointer.cpp index e01f2f6..c7f5079 100644 --- a/tests/test_json_pointer.cpp +++ b/tests/test_json_pointer.cpp @@ -1,5 +1,3 @@ -#include -#include #include @@ -36,43 +34,43 @@ struct JsonPointerTestCase rapidjson::Value *expectedValue; }; -std::vector > +std::vector > testCasesForSingleLevelObjectPointers( RapidJsonCrtAllocator &allocator) { - typedef boost::shared_ptr TestCase; + typedef std::shared_ptr TestCase; std::vector testCases; - TestCase testCase = boost::make_shared( + TestCase testCase = std::make_shared( "Resolving '#' should cause an exception to be thrown"); testCase->value.SetNull(); testCase->jsonPointer = "#"; testCase->expectedValue = NULL; testCases.push_back(testCase); - testCase = boost::make_shared( + testCase = std::make_shared( "Resolving an empty string should return the root node"); testCase->value.SetNull(); testCase->jsonPointer = ""; testCase->expectedValue = &testCase->value; testCases.push_back(testCase); - testCase = boost::make_shared( + testCase = std::make_shared( "Resolving '/' should return the root node"); testCase->value.SetNull(); testCase->jsonPointer = "/"; testCase->expectedValue = &testCase->value; testCases.push_back(testCase); - testCase = boost::make_shared( + testCase = std::make_shared( "Resolving '//' should return the root node"); testCase->value.SetNull(); testCase->jsonPointer = "//"; testCase->expectedValue = &testCase->value; testCases.push_back(testCase); - testCase = boost::make_shared( + testCase = std::make_shared( "Resolve '/test' in object containing one member named 'test'"); testCase->value.SetObject(); testCase->value.AddMember("test", "test", allocator); @@ -80,7 +78,7 @@ std::vector > testCase->expectedValue = &testCase->value.FindMember("test")->value; testCases.push_back(testCase); - testCase = boost::make_shared( + testCase = std::make_shared( "Resolve '/test/' in object containing one member named 'test'"); testCase->value.SetObject(); testCase->value.AddMember("test", "test", allocator); @@ -88,7 +86,7 @@ std::vector > testCase->expectedValue = &testCase->value.FindMember("test")->value; testCases.push_back(testCase); - testCase = boost::make_shared( + testCase = std::make_shared( "Resolve '//test//' in object containing one member named 'test'"); testCase->value.SetObject(); testCase->value.AddMember("test", "test", allocator); @@ -96,7 +94,7 @@ std::vector > testCase->expectedValue = &testCase->value.FindMember("test")->value; testCases.push_back(testCase); - testCase = boost::make_shared( + testCase = std::make_shared( "Resolve '/missing' in object containing one member name 'test'"); testCase->value.SetObject(); testCase->value.AddMember("test", "test", allocator); @@ -111,7 +109,7 @@ std::vector > testArray.PushBack("test1", allocator); testArray.PushBack("test2", allocator); - testCase = boost::make_shared( + testCase = std::make_shared( "Resolve '/test/0' in object containing one member containing " "an array with 3 elements"); testCase->value.SetObject(); @@ -128,7 +126,7 @@ std::vector > testArray.PushBack("test1", allocator); testArray.PushBack("test2", allocator); - testCase = boost::make_shared( + testCase = std::make_shared( "Resolve '/test/1' in object containing one member containing " "an array with 3 elements"); testCase->value.SetObject(); @@ -145,7 +143,7 @@ std::vector > testArray.PushBack("test1", allocator); testArray.PushBack("test2", allocator); - testCase = boost::make_shared( + testCase = std::make_shared( "Resolve '/test/2' in object containing one member containing " "an array with 3 elements"); testCase->value.SetObject(); @@ -162,7 +160,7 @@ std::vector > testArray.PushBack("test1", allocator); testArray.PushBack("test2", allocator); - testCase = boost::make_shared( + testCase = std::make_shared( "Resolving '/test/3' in object containing one member containing " "an array with 3 elements should throw an exception"); testCase->value.SetObject(); @@ -193,7 +191,7 @@ std::vector > testArray.PushBack("test1", allocator); testArray.PushBack("test2", allocator); - testCase = boost::make_shared( + testCase = std::make_shared( "Resolving '/test/-' in object containing one member containing " "an array with 3 elements should throw an exception"); testCase->value.SetNull(); @@ -221,7 +219,7 @@ std::vector > rapidjson::Value value; value.SetDouble(10.); - testCase = boost::make_shared( + testCase = std::make_shared( "Resolving '/hello~1world' in object containing one member named " "'hello/world' should return the associated value"); testCase->value.SetObject(); @@ -235,7 +233,7 @@ std::vector > rapidjson::Value value; value.SetDouble(10.); - testCase = boost::make_shared( + testCase = std::make_shared( "Resolving '/hello~0world' in object containing one member named " "'hello~world' should return the associated value"); testCase->value.SetObject(); @@ -249,7 +247,7 @@ std::vector > rapidjson::Value value; value.SetDouble(10.); - testCase = boost::make_shared( + testCase = std::make_shared( "Resolving '/hello~01world' in object containing one member named " "'hello~1world' should return the associated value"); testCase->value.SetObject(); @@ -264,7 +262,7 @@ std::vector > TEST_F(TestJsonPointer, JsonPointerTestCases) { - typedef std::vector > TestCases; + typedef std::vector > TestCases; // Ensure memory used for test cases is freed when test function completes rapidjson::MemoryPoolAllocator allocator; diff --git a/tests/test_jsoncpp_adapter.cpp b/tests/test_jsoncpp_adapter.cpp index 3df4316..5784347 100644 --- a/tests/test_jsoncpp_adapter.cpp +++ b/tests/test_jsoncpp_adapter.cpp @@ -1,5 +1,3 @@ -#include -#include #include @@ -34,7 +32,7 @@ TEST_F(TestJsonCppAdapter, BasicArrayIteration) // Ensure that the elements are returned in the order they were inserted unsigned int expectedValue = 0; - BOOST_FOREACH( const valijson::adapters::JsonCppAdapter value, adapter.getArray() ) { + for( const valijson::adapters::JsonCppAdapter value : adapter.getArray() ) { ASSERT_TRUE( value.isNumber() ); EXPECT_EQ( double(expectedValue), value.getNumber() ); expectedValue++; @@ -52,7 +50,7 @@ TEST_F(TestJsonCppAdapter, BasicObjectIteration) // strings their corresponding numeric values Json::Value document(Json::objectValue); for (unsigned int i = 0; i < numElements; i++) { - std::string name(boost::lexical_cast(i)); + std::string name(std::to_string(i)); document[name] = Json::Value(double(i)); } @@ -70,9 +68,9 @@ TEST_F(TestJsonCppAdapter, BasicObjectIteration) // Ensure that the members are returned in the order they were inserted unsigned int expectedValue = 0; - BOOST_FOREACH( const valijson::adapters::JsonCppAdapter::ObjectMember member, adapter.getObject() ) { + for( const valijson::adapters::JsonCppAdapter::ObjectMember member : adapter.getObject() ) { ASSERT_TRUE( member.second.isNumber() ); - EXPECT_EQ( boost::lexical_cast(expectedValue), member.first ); + EXPECT_EQ( std::to_string(expectedValue), member.first ); EXPECT_EQ( double(expectedValue), member.second.getDouble() ); expectedValue++; } diff --git a/tests/test_nlohmann_json_adapter.cpp b/tests/test_nlohmann_json_adapter.cpp index 37fd44a..f736042 100644 --- a/tests/test_nlohmann_json_adapter.cpp +++ b/tests/test_nlohmann_json_adapter.cpp @@ -1,8 +1,5 @@ #ifdef VALIJSON_BUILD_CXX11_ADAPTERS -#include -#include - #include #include @@ -37,7 +34,7 @@ TEST_F(TestNlohmannJsonAdapter, BasicArrayIteration) // Ensure that the elements are returned in the order they were inserted unsigned int expectedValue = 0; - BOOST_FOREACH( const valijson::adapters::NlohmannJsonAdapter value, adapter.getArray() ) { + for( const valijson::adapters::NlohmannJsonAdapter value : adapter.getArray() ) { ASSERT_TRUE( value.isNumber() ); EXPECT_EQ( double(expectedValue), value.getDouble() ); expectedValue++; @@ -55,7 +52,7 @@ TEST_F(TestNlohmannJsonAdapter, BasicObjectIteration) // strings their corresponding numeric values nlohmann::json document; for (uint32_t i = 0; i < numElements; i++) { - document[boost::lexical_cast(i)] = static_cast(i); + document[std::to_string(i)] = static_cast(i); } // Ensure that wrapping the document preserves the object and does not @@ -72,9 +69,9 @@ TEST_F(TestNlohmannJsonAdapter, BasicObjectIteration) // Ensure that the members are returned in the order they were inserted unsigned int expectedValue = 0; - BOOST_FOREACH( const valijson::adapters::NlohmannJsonAdapter::ObjectMember member, adapter.getObject() ) { + for( const valijson::adapters::NlohmannJsonAdapter::ObjectMember member : adapter.getObject() ) { ASSERT_TRUE( member.second.isNumber() ); - EXPECT_EQ( boost::lexical_cast(expectedValue), member.first ); + EXPECT_EQ( std::to_string(expectedValue), member.first ); EXPECT_EQ( double(expectedValue), member.second.getDouble() ); expectedValue++; } diff --git a/tests/test_picojson_adapter.cpp b/tests/test_picojson_adapter.cpp index dea47e8..15fde4b 100644 --- a/tests/test_picojson_adapter.cpp +++ b/tests/test_picojson_adapter.cpp @@ -1,5 +1,4 @@ -#include -#include +#include #include @@ -36,7 +35,7 @@ TEST_F(TestPicoJsonAdapter, BasicArrayIteration) // Ensure that the elements are returned in the order they were inserted unsigned int expectedValue = 0; - BOOST_FOREACH( const valijson::adapters::PicoJsonAdapter value, adapter.getArray() ) { + for( const valijson::adapters::PicoJsonAdapter value : adapter.getArray() ) { ASSERT_TRUE( value.isNumber() ); EXPECT_EQ( double(expectedValue), value.getDouble() ); expectedValue++; @@ -54,7 +53,7 @@ TEST_F(TestPicoJsonAdapter, BasicObjectIteration) // strings their corresponding numeric values picojson::object object; for (unsigned int i = 0; i < numElements; i++) { - std::string name(boost::lexical_cast(i)); + std::string name(std::to_string(i)); object[name] = picojson::value(static_cast(i)); } picojson::value document(object); @@ -73,9 +72,9 @@ TEST_F(TestPicoJsonAdapter, BasicObjectIteration) // Ensure that the members are returned in the order they were inserted unsigned int expectedValue = 0; - BOOST_FOREACH( const valijson::adapters::PicoJsonAdapter::ObjectMember member, adapter.getObject() ) { + for( const valijson::adapters::PicoJsonAdapter::ObjectMember member : adapter.getObject() ) { ASSERT_TRUE( member.second.isNumber() ); - EXPECT_EQ( boost::lexical_cast(expectedValue), member.first ); + EXPECT_EQ( std::to_string(expectedValue), member.first ); EXPECT_EQ( double(expectedValue), member.second.getDouble() ); expectedValue++; } diff --git a/tests/test_property_tree_adapter.cpp b/tests/test_property_tree_adapter.cpp index 94e45b0..fc6c3b1 100644 --- a/tests/test_property_tree_adapter.cpp +++ b/tests/test_property_tree_adapter.cpp @@ -1,5 +1,3 @@ -#include -#include #include @@ -19,7 +17,7 @@ TEST_F(TestPropertyTreeAdapter, BasicArrayIteration) boost::property_tree::ptree document; for (unsigned int i = 0; i < numElements; i++) { document.push_back(std::make_pair(std::string(), - boost::property_tree::ptree(boost::lexical_cast(i)))); + boost::property_tree::ptree(std::to_string(i)))); } // Ensure that wrapping the document preserves the array and does not allow @@ -36,7 +34,7 @@ TEST_F(TestPropertyTreeAdapter, BasicArrayIteration) // Ensure that the elements are returned in the order they were inserted unsigned int expectedValue = 0; - BOOST_FOREACH( const valijson::adapters::PropertyTreeAdapter value, adapter.getArray() ) { + for( const valijson::adapters::PropertyTreeAdapter value : adapter.getArray() ) { ASSERT_TRUE( value.isString() ); ASSERT_FALSE( value.isNumber() ); ASSERT_TRUE( value.maybeDouble() ); @@ -56,9 +54,9 @@ TEST_F(TestPropertyTreeAdapter, BasicObjectIteration) // strings their corresponding numeric values boost::property_tree::ptree document; for (unsigned int i = 0; i < numElements; i++) { - std::string name(boost::lexical_cast(i)); + std::string name(std::to_string(i)); document.push_back(std::make_pair(name, boost::property_tree::ptree( - boost::lexical_cast(double(i))))); + std::to_string(double(i))))); } // Ensure that wrapping the document preserves the object and does not @@ -75,11 +73,11 @@ TEST_F(TestPropertyTreeAdapter, BasicObjectIteration) // Ensure that the members are returned in the order they were inserted unsigned int expectedValue = 0; - BOOST_FOREACH( const valijson::adapters::PropertyTreeAdapter::ObjectMember member, adapter.getObject() ) { + for( const valijson::adapters::PropertyTreeAdapter::ObjectMember member : adapter.getObject() ) { ASSERT_TRUE( member.second.isString() ); ASSERT_FALSE( member.second.isNumber() ); ASSERT_TRUE( member.second.maybeDouble() ); - EXPECT_EQ( boost::lexical_cast(expectedValue), member.first ); + EXPECT_EQ( std::to_string(expectedValue), member.first ); EXPECT_EQ( double(expectedValue), member.second.asDouble() ); expectedValue++; } diff --git a/tests/test_rapidjson_adapter.cpp b/tests/test_rapidjson_adapter.cpp index 2471317..a04f0cc 100644 --- a/tests/test_rapidjson_adapter.cpp +++ b/tests/test_rapidjson_adapter.cpp @@ -1,5 +1,4 @@ -#include -#include +#include #include @@ -38,7 +37,7 @@ void testBasicArrayIteration() // Ensure that the elements are returned in the order they were inserted unsigned int expectedValue = 0; - BOOST_FOREACH( const valijson::adapters::RapidJsonAdapter value, adapter.getArray() ) { + for( const valijson::adapters::RapidJsonAdapter value : adapter.getArray() ) { ASSERT_TRUE( value.isNumber() ); EXPECT_EQ( double(expectedValue), value.getDouble() ); expectedValue++; @@ -59,7 +58,7 @@ void testBasicObjectIteration() document.SetObject(); for (unsigned int i = 0; i < numElements; i++) { rapidjson::Value name, value; - name.SetString(boost::lexical_cast(i).c_str(), document.GetAllocator()); + name.SetString(std::to_string(i).c_str(), document.GetAllocator()); value.SetDouble(i); document.AddMember(name, value, document.GetAllocator()); } @@ -78,9 +77,9 @@ void testBasicObjectIteration() // Ensure that the members are returned in the order they were inserted unsigned int expectedValue = 0; - BOOST_FOREACH( const valijson::adapters::RapidJsonAdapter::ObjectMember member, adapter.getObject() ) { + for( const valijson::adapters::RapidJsonAdapter::ObjectMember member : adapter.getObject() ) { ASSERT_TRUE( member.second.isNumber() ); - EXPECT_EQ( boost::lexical_cast(expectedValue), member.first ); + EXPECT_EQ( std::to_string(expectedValue), member.first ); EXPECT_EQ( double(expectedValue), member.second.getDouble() ); expectedValue++; } @@ -107,4 +106,4 @@ TEST_F(TestRapidJsonAdapter, BasicObjectIteration) // Test using value type based on CrtAllocator testBasicObjectIteration, rapidjson::CrtAllocator> >(); -} \ No newline at end of file +} diff --git a/tests/test_validation_errors.cpp b/tests/test_validation_errors.cpp index 93e0630..2c173c6 100644 --- a/tests/test_validation_errors.cpp +++ b/tests/test_validation_errors.cpp @@ -1,8 +1,5 @@ #include -#include -#include - #include #include diff --git a/tests/test_validator.cpp b/tests/test_validator.cpp index 6b9f8ce..4fde7ef 100644 --- a/tests/test_validator.cpp +++ b/tests/test_validator.cpp @@ -2,9 +2,6 @@ #include -#include -#include - #include #include @@ -99,7 +96,7 @@ protected: ASSERT_TRUE( testCases.isArray() ); // Process each test case in the file - BOOST_FOREACH( const AdapterType testCase, testCases.getArray() ) { + for( const AdapterType testCase : testCases.getArray() ) { currentTestCase.clear(); currentTest.clear(); @@ -127,7 +124,7 @@ protected: itr = object.find("tests"); ASSERT_NE( object.end(), itr ); ASSERT_TRUE( itr->second.isArray() ); - BOOST_FOREACH( const AdapterType test, itr->second.getArray() ) { + for( const AdapterType test : itr->second.getArray() ) { const bool strict = itr->second.hasStrictTypes(); diff --git a/xcode/valijson.xcodeproj/project.pbxproj b/xcode/valijson.xcodeproj/project.pbxproj index 6409d99..fc26713 100644 --- a/xcode/valijson.xcodeproj/project.pbxproj +++ b/xcode/valijson.xcodeproj/project.pbxproj @@ -52,6 +52,7 @@ /* End PBXContainerItemProxy section */ /* Begin PBXFileReference section */ + 462CB4C31D50940F003DC976 /* optional.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = optional.hpp; path = compat/optional.hpp; sourceTree = ""; }; 6A309D2D1C28C1FD00EF761C /* subschema.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = subschema.hpp; sourceTree = ""; }; 6A34698C1BD109A900C97DA2 /* json_reference.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; name = json_reference.hpp; path = internal/json_reference.hpp; sourceTree = ""; }; 6A356B0D1C1CFD020007EB8B /* uri.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; name = uri.hpp; path = internal/uri.hpp; sourceTree = ""; }; @@ -335,6 +336,14 @@ /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ + 462CB4C41D50941E003DC976 /* compat */ = { + isa = PBXGroup; + children = ( + 462CB4C31D50940F003DC976 /* optional.hpp */, + ); + name = compat; + sourceTree = ""; + }; 6A477F8717D6EEF20013571C /* Frameworks */ = { isa = PBXGroup; children = ( @@ -846,6 +855,7 @@ 6AC78BDC17C5FC5F00674114 /* include */ = { isa = PBXGroup; children = ( + 462CB4C41D50941E003DC976 /* compat */, 6AC78BDD17C5FC6A00674114 /* valijson */, ); name = include;