diff --git a/.travis.yml b/.travis.yml index 1e2d881..866ff72 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,14 +4,6 @@ dist: trusty matrix: include: - - os: linux - compiler: gcc - addons: - apt: - sources: ['ubuntu-toolchain-r-test'] - packages: ['g++-4.9', 'valgrind', 'python-pip', 'python-yaml'] - env: COMPILER=g++-4.9 - - os: linux compiler: gcc addons: diff --git a/Authors b/Authors index 00c1984..6cea566 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/CMakeLists.txt b/CMakeLists.txt index 9eec952..6880905 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -7,18 +7,13 @@ option (BUILD_TESTS "Build valijson Tests." TRUE) SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall ") if (BUILD_TESTS OR BUILD_EXAMPLES) SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -O0") -if(VALIJSON_CXX11_ADAPTERS STREQUAL "disabled") - message(STATUS "Building with C++11 support disabled") + +include(CheckCXXCompilerFlag) +CHECK_CXX_COMPILER_FLAG("-std=c++11" COMPILER_SUPPORTS_CXX11) +if(COMPILER_SUPPORTS_CXX11) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -DVALIJSON_BUILD_CXX11_ADAPTERS=1") else() - include(CheckCXXCompilerFlag) - CHECK_CXX_COMPILER_FLAG("-std=c++11" COMPILER_SUPPORTS_CXX11) - if(COMPILER_SUPPORTS_CXX11) - set(VALIJSON_CXX11_ADAPTERS_ARE_ENABLED 1) - message(STATUS "Building with C++11 support enabled") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -DVALIJSON_BUILD_CXX11_ADAPTERS=1") - else() - message(FATAL_ERROR "The compiler ${CMAKE_CXX_COMPILER} has no C++11 support. Please use a different C++ compiler.") - endif() + message(FATAL_ERROR "The compiler ${CMAKE_CXX_COMPILER} has no C++11 support. Please use a different C++ compiler.") endif() add_definitions(-DBOOST_ALL_DYN_LINK) @@ -26,7 +21,7 @@ set(Boost_USE_STATIC_LIBS OFF) set(Boost_USE_MULTITHREADED ON) set(Boost_USE_STATIC_RUNTIME OFF) -find_package(Boost 1.55.0 COMPONENTS regex REQUIRED) +find_package(Boost 1.54.0 REQUIRED) # jsoncpp library add_library(jsoncpp @@ -35,11 +30,23 @@ add_library(jsoncpp thirdparty/jsoncpp-0.9.4/src/lib_json/json_writer.cpp ) -if(VALIJSON_CXX11_ADAPTERS_ARE_ENABLED) - add_library(json11 - thirdparty/json11-2016-01-26/json11.cpp - ) -endif() +target_include_directories(jsoncpp SYSTEM PRIVATE + thirdparty/jsoncpp-0.9.4/include +) + +set_target_properties(jsoncpp PROPERTIES + ARCHIVE_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/thirdparty/jsoncpp-0.9.4) + +add_library(json11 + thirdparty/json11-2016-01-26/json11.cpp +) + +target_include_directories(json11 SYSTEM PRIVATE + thirdparty/json11-2016-01-26 +) + +set_target_properties(json11 PROPERTIES + ARCHIVE_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/thirdparty/json11-2016-01-26) # Build local gtest set(gtest_force_shared_crt ON) @@ -51,18 +58,14 @@ include_directories( ) include_directories(SYSTEM - ${Boost_INCLUDE_DIRS} thirdparty/gtest-1.7.0/include + thirdparty/json11-2016-01-26 thirdparty/jsoncpp-0.9.4/include thirdparty/rapidjson-1.0.2/include thirdparty/picojson-1.3.0 thirdparty/nlohmann-json-1.1.0 + ${Boost_INCLUDE_DIRS} ) -if(VALIJSON_CXX11_ADAPTERS_ARE_ENABLED) - include_directories(SYSTEM - thirdparty/json11-2016-01-26 - ) -endif() # Custom schema validation example add_executable(custom_schema @@ -78,22 +81,16 @@ set(TEST_SOURCES tests/test_adapter_comparison.cpp tests/test_fetch_document_callback.cpp tests/test_json_pointer.cpp + tests/test_json11_adapter.cpp tests/test_jsoncpp_adapter.cpp + tests/test_nlohmann_json_adapter.cpp tests/test_property_tree_adapter.cpp tests/test_rapidjson_adapter.cpp tests/test_picojson_adapter.cpp tests/test_validation_errors.cpp tests/test_validator.cpp tests/test_poly_constraint.cpp - ) - -if(VALIJSON_CXX11_ADAPTERS_ARE_ENABLED) - set(TEST_SOURCES - ${TEST_SOURCES} - tests/test_json11_adapter.cpp - tests/test_nlohmann_json_adapter.cpp - ) -endif() +) # Unit tests executable add_executable(test_suite ${TEST_SOURCES}) @@ -103,10 +100,7 @@ set_target_properties(test_suite PROPERTIES COMPILE_DEFINITIONS "PICOJSON_USE_INT64" ) -set(TEST_LIBS gtest gtest_main jsoncpp) -if(VALIJSON_CXX11_ADAPTERS_ARE_ENABLED) - set(TEST_LIBS ${TEST_LIBS} json11) -endif() +set(TEST_LIBS gtest gtest_main jsoncpp json11) target_link_libraries(test_suite ${TEST_LIBS} ${Boost_LIBRARIES}) target_link_libraries(custom_schema ${Boost_LIBRARIES}) diff --git a/README.md b/README.md index 1156e9b..7ddb29d 100644 --- a/README.md +++ b/README.md @@ -2,13 +2,13 @@ ## Overview ## -Valijson is a header-only [JSON Schema](http://json-schema.org/) Validation library for C++. +Valijson is a header-only [JSON Schema](http://json-schema.org/) Validation library for C++11. Valijson provides a simple validation API that allows you load JSON Schemas, and validate documents loaded by one of several supported parser libraries. ## Project Goals ## -The goal of this project is to support validation of all constraints available in JSON Schema v4, while being competitive with the performance of hand-written JSON validators. +The goal of this project is to support validation of all constraints available in JSON Schema v4, while being competitive with the performance of a hand-written schema validator. ## Usage ## @@ -104,9 +104,9 @@ Things get more interesting when you build a schema using custom code, as illust ## JSON References ## -The library includes support for local JSON References, as well as remote JSON References when the appropriate callback functions are provided. +The library includes support for local JSON References. Remote JSON References are supported only when the appropriate callback functions are provided. -Two callback functions are required. The first is expected to return a pointer to a newly fetched document. Valijson takes ownership of this pointer. The second callback function is used to release ownership of that pointer back to the application. Typically, this would immediately free the memory that was allocated for the document. +Valijson's JSON Reference implementation requires that two callback functions are required. The first is expected to return a pointer to a newly fetched document. Valijson takes ownership of this pointer. The second callback function is used to release ownership of that pointer back to the application. Typically, this would immediately free the memory that was allocated for the document. ## Test Suite ## @@ -160,11 +160,7 @@ Doxygen documentation can be built by running 'doxygen' from the project root di ## Dependencies ## -Required: - - - boost 1.54 - -Later versions of boost (up to 1.59) are also known to work correctly. +Valijson requires a compiler with robust C++11 support. ## Supported Parsers ## @@ -177,11 +173,17 @@ Valijson supports JSON documents loaded using JsonCpp, RapidJson, Boost Property - [rapidjson 1.0.2](https://github.com/miloyip/rapidjson/releases/tag/v1.0.2) - [PicoJSON 1.3.0](https://github.com/kazuho/picojson/archive/v1.3.0.tar.gz) -Version of JsonCpp going back to 0.5.0 should also work correctly, but versions from 1.0 onwards have not yet been tested. +Other versions of these libraries may work, but have not been tested. In particular, versions of JsonCpp going back to 0.5.0 should also work correctly, but versions from 1.0 onwards have not yet been tested. -Also note that when using PicoJSON, it may be necessary to include the `picojson.h` before other headers to ensure that the appropriate macros have been enabled. +## Test Suite Requirements ## -Other versions of these libraries may work, but have not been tested. +Supported versions of these libraries have been included in the 'thirdparty' directory so as to support Valijson's examples and test suite. + +The only exception to this is boost, which due to its sheer size must be installed to a location that CMake can find. + +## Known Issues ## + +Note that when using PicoJSON, it may be necessary to include the `picojson.h` before other headers to ensure that the appropriate macros have been enabled. ## License ## diff --git a/examples/custom_schema.cpp b/examples/custom_schema.cpp index 008e67a..0305871 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..8e74387 100644 --- a/include/valijson/adapters/basic_adapter.hpp +++ b/include/valijson/adapters/basic_adapter.hpp @@ -5,15 +5,48 @@ #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); + } + +private: + Value m_ref; +}; + /** * @brief Template class that implements the expected semantics of an Adapter. * @@ -215,8 +248,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 +266,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 +477,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 +511,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 +521,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 +550,7 @@ public: */ ArrayType getArray() const { - boost::optional arrayValue = value.getArrayOptional(); + opt::optional arrayValue = value.getArrayOptional(); if (arrayValue) { return *arrayValue; } @@ -630,7 +659,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..6c63b8b 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++; + + 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..d6b7a5a 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,8 +193,7 @@ public: template void applyToPropertyDependencies(const FunctorType &fn) const { - BOOST_FOREACH( const PropertyDependencies::value_type &v, - propertyDependencies ) { + for (const PropertyDependencies::value_type &v : propertyDependencies) { if (!fn(v.first, v.second)) { return; } @@ -207,8 +203,7 @@ public: template void applyToSchemaDependencies(const FunctorType &fn) const { - BOOST_FOREACH( const SchemaDependencies::value_type &v, - schemaDependencies ) { + for (const SchemaDependencies::value_type &v : schemaDependencies) { if (!fn(v.first, v.second)) { return; } @@ -254,7 +249,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 +261,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 +270,7 @@ public: virtual ~EnumConstraint() { - BOOST_FOREACH( const EnumValue *value, enumValues ) { + for (const EnumValue *value : enumValues) { delete value; } } @@ -295,7 +290,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 +340,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 +722,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 +865,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 +876,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 +932,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 +1019,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 +1030,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..fc126db 100644 --- a/include/valijson/internal/json_pointer.hpp +++ b/include/valijson/internal/json_pointer.hpp @@ -2,13 +2,19 @@ #ifndef __VALIJSON_INTERNAL_JSON_POINTER_HPP #define __VALIJSON_INTERNAL_JSON_POINTER_HPP +#include #include +#include #include #include -#include -#include -#include +#if __has_include() +# include +namespace opt = std; +#else +# include +namespace opt = std::experimental; +#endif #include @@ -16,6 +22,24 @@ 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 +102,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 +193,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(); @@ -180,18 +203,18 @@ inline AdapterType resolveJsonPointer( "out of bounds; actual token: " + referenceToken); } - if (index > static_cast(std::numeric_limits::max())) { + if (index > static_cast(std::numeric_limits::max())) { throw std::runtime_error("Array index out of bounds; hard " - "limit is " + boost::lexical_cast( - std::numeric_limits::max())); + "limit is " + std::to_string( + std::numeric_limits::max())); } - itr.advance(static_cast(index)); + itr.advance(static_cast(index)); // 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..999a662 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..11254a7 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/file_utils.hpp b/include/valijson/utils/file_utils.hpp index 4fd3c9d..2a9f724 100644 --- a/include/valijson/utils/file_utils.hpp +++ b/include/valijson/utils/file_utils.hpp @@ -3,6 +3,7 @@ #define __VALIJSON_FILE_UTILS_HPP #include +#include namespace valijson { namespace utils { diff --git a/include/valijson/utils/property_tree_utils.hpp b/include/valijson/utils/property_tree_utils.hpp index fdbe4cb..8b987e0 100644 --- a/include/valijson/utils/property_tree_utils.hpp +++ b/include/valijson/utils/property_tree_utils.hpp @@ -16,8 +16,6 @@ # include #endif -#include - #include namespace valijson { @@ -27,7 +25,7 @@ inline bool loadDocument(const std::string &path, boost::property_tree::ptree &d { try { boost::property_tree::read_json(path, document); - } catch (boost::property_tree::json_parser::json_parser_error &e) { + } catch (std::exception &e) { std::cerr << "Boost Property Tree JSON parser failed to parse the document:" << std::endl; std::cerr << e.what() << std::endl; return false; 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..ba9756d 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..9250a03 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..47a7d63 100644 --- a/tests/test_json_pointer.cpp +++ b/tests/test_json_pointer.cpp @@ -1,5 +1,4 @@ -#include -#include +#include #include @@ -36,43 +35,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 +79,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 +87,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 +95,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 +110,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 +127,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 +144,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 +161,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 +192,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 +220,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 +234,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 +248,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 +263,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..bd088df 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..075710e 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..398d1f9 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..eba84b2 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..bd583ea 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..7fe9bf2 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/travis.sh b/travis.sh index fe6a6e0..081fe1c 100755 --- a/travis.sh +++ b/travis.sh @@ -26,22 +26,10 @@ if [[ $CXX == 'clang++' ]]; then echo "Additional flags to pass to cmake: $CMAKE_FLAGS" fi -echo "Attempting to build and run test suite with C++11 support disabled..." -cmake $CMAKE_FLAGS -DVALIJSON_CXX11_ADAPTERS=disabled .. +echo "Attempting to build and run test suite with C++11 support enabled..." +cmake $CMAKE_FLAGS -DVALIJSON_CXX11_ADAPTERS=enabled .. VERBOSE=1 make ./test_suite - -echo "Checking if current compiler is GCC..." -if [[ $CXX == 'g++' ]]; then - echo "Not building test suite with C++11 support due to ancient version of GCC on Travis CI" -else - echo "Attempting to build and run test suite with C++11 support enabled..." - make clean - cmake $CMAKE_FLAGS -DVALIJSON_CXX11_ADAPTERS=enabled .. - VERBOSE=1 make - ./test_suite -fi - make clean popd > /dev/null 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;