implemented issue #57: erase with iterators
This commit is contained in:
		
							parent
							
								
									d7d0509161
								
							
						
					
					
						commit
						6dceab583c
					
				
					 3 changed files with 707 additions and 50 deletions
				
			
		
							
								
								
									
										146
									
								
								src/json.hpp
									
										
									
									
									
								
							
							
						
						
									
										146
									
								
								src/json.hpp
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -7,26 +7,6 @@
 | 
			
		|||
@see https://github.com/nlohmann/json
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
/*!
 | 
			
		||||
@defgroup container Container
 | 
			
		||||
@brief C++ Container concept
 | 
			
		||||
 | 
			
		||||
A Container is an object used to store other objects and taking care of the
 | 
			
		||||
management of the memory used by the objects it contains.
 | 
			
		||||
 | 
			
		||||
@see http://en.cppreference.com/w/cpp/concept/Container
 | 
			
		||||
 | 
			
		||||
@defgroup reversiblecontainer Reversible Container
 | 
			
		||||
@brief C++ Reversible Container concept
 | 
			
		||||
@ingroup container
 | 
			
		||||
 | 
			
		||||
A ReversibleContainer is a Container that has iterators that meet the
 | 
			
		||||
requirements of either BidirectionalIterator or RandomAccessIterator. Such
 | 
			
		||||
iterators allow a ReversibleContainer to be iterated over in reverse.
 | 
			
		||||
 | 
			
		||||
@see http://en.cppreference.com/w/cpp/concept/ReversibleContainer
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
#ifndef _NLOHMANN_JSON
 | 
			
		||||
#define _NLOHMANN_JSON
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -871,15 +851,12 @@ class basic_json
 | 
			
		|||
            case (value_t::array):
 | 
			
		||||
            {
 | 
			
		||||
                T to_vector;
 | 
			
		||||
                //to_vector.reserve(m_value.array->size());
 | 
			
		||||
                std::transform(m_value.array->begin(), m_value.array->end(),
 | 
			
		||||
                               std::inserter(to_vector, to_vector.end()), [](basic_json i)
 | 
			
		||||
                {
 | 
			
		||||
                    return i.get<typename T::value_type>();
 | 
			
		||||
                });
 | 
			
		||||
                return to_vector;
 | 
			
		||||
 | 
			
		||||
                //   return T(m_value.array->begin(), m_value.array->end());
 | 
			
		||||
            }
 | 
			
		||||
            default:
 | 
			
		||||
            {
 | 
			
		||||
| 
						 | 
				
			
			@ -1187,6 +1164,129 @@ class basic_json
 | 
			
		|||
        return m_value.object->operator[](key);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// remove element given an iterator
 | 
			
		||||
    template <class T, typename
 | 
			
		||||
              std::enable_if<
 | 
			
		||||
                  std::is_same<T, basic_json::iterator>::value or
 | 
			
		||||
                  std::is_same<T, basic_json::const_iterator>::value
 | 
			
		||||
                  , int>::type
 | 
			
		||||
              = 0>
 | 
			
		||||
    inline T erase(T pos)
 | 
			
		||||
    {
 | 
			
		||||
        // make sure iterator fits the current value
 | 
			
		||||
        if (this != pos.m_object or m_type != pos.m_object->m_type)
 | 
			
		||||
        {
 | 
			
		||||
            throw std::runtime_error("iterator does not fit current value");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        T result = end();
 | 
			
		||||
 | 
			
		||||
        switch (m_type)
 | 
			
		||||
        {
 | 
			
		||||
            case value_t::number_integer:
 | 
			
		||||
            case value_t::number_float:
 | 
			
		||||
            case value_t::boolean:
 | 
			
		||||
            case value_t::string:
 | 
			
		||||
            {
 | 
			
		||||
                if (pos.m_it.generic_iterator != 0)
 | 
			
		||||
                {
 | 
			
		||||
                    throw std::out_of_range("iterator out of range");
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                if (m_type == value_t::string)
 | 
			
		||||
                {
 | 
			
		||||
                    delete m_value.string;
 | 
			
		||||
                    m_value.string = nullptr;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                m_type = value_t::null;
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            case value_t::object:
 | 
			
		||||
            {
 | 
			
		||||
                result.m_it.object_iterator = m_value.object->erase(pos.m_it.object_iterator);
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            case value_t::array:
 | 
			
		||||
            {
 | 
			
		||||
                result.m_it.array_iterator = m_value.array->erase(pos.m_it.array_iterator);
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            default:
 | 
			
		||||
            {
 | 
			
		||||
                throw std::runtime_error("cannot use erase with " + type_name());
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return result;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// remove elements given an iterator range
 | 
			
		||||
    template <class T, typename
 | 
			
		||||
              std::enable_if<
 | 
			
		||||
                  std::is_same<T, basic_json::iterator>::value or
 | 
			
		||||
                  std::is_same<T, basic_json::const_iterator>::value
 | 
			
		||||
                  , int>::type
 | 
			
		||||
              = 0>
 | 
			
		||||
    inline T erase(T first, T last)
 | 
			
		||||
    {
 | 
			
		||||
        // make sure iterator fits the current value
 | 
			
		||||
        if (this != first.m_object or this != last.m_object or
 | 
			
		||||
                m_type != first.m_object->m_type or m_type != last.m_object->m_type)
 | 
			
		||||
        {
 | 
			
		||||
            throw std::runtime_error("iterators do not fit current value");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        T result = end();
 | 
			
		||||
 | 
			
		||||
        switch (m_type)
 | 
			
		||||
        {
 | 
			
		||||
            case value_t::number_integer:
 | 
			
		||||
            case value_t::number_float:
 | 
			
		||||
            case value_t::boolean:
 | 
			
		||||
            case value_t::string:
 | 
			
		||||
            {
 | 
			
		||||
                if (first.m_it.generic_iterator != 0 or last.m_it.generic_iterator != 1)
 | 
			
		||||
                {
 | 
			
		||||
                    throw std::out_of_range("iterators out of range");
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                if (m_type == value_t::string)
 | 
			
		||||
                {
 | 
			
		||||
                    delete m_value.string;
 | 
			
		||||
                    m_value.string = nullptr;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                m_type = value_t::null;
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            case value_t::object:
 | 
			
		||||
            {
 | 
			
		||||
                result.m_it.object_iterator = m_value.object->erase(first.m_it.object_iterator,
 | 
			
		||||
                                              last.m_it.object_iterator);
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            case value_t::array:
 | 
			
		||||
            {
 | 
			
		||||
                result.m_it.array_iterator = m_value.array->erase(first.m_it.array_iterator,
 | 
			
		||||
                                             last.m_it.array_iterator);
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            default:
 | 
			
		||||
            {
 | 
			
		||||
                throw std::runtime_error("cannot use erase with " + type_name());
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return result;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// remove element from an object given a key
 | 
			
		||||
    inline size_type erase(const typename object_t::key_type& key)
 | 
			
		||||
    {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -7,26 +7,6 @@
 | 
			
		|||
@see https://github.com/nlohmann/json
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
/*!
 | 
			
		||||
@defgroup container Container
 | 
			
		||||
@brief C++ Container concept
 | 
			
		||||
 | 
			
		||||
A Container is an object used to store other objects and taking care of the
 | 
			
		||||
management of the memory used by the objects it contains.
 | 
			
		||||
 | 
			
		||||
@see http://en.cppreference.com/w/cpp/concept/Container
 | 
			
		||||
 | 
			
		||||
@defgroup reversiblecontainer Reversible Container
 | 
			
		||||
@brief C++ Reversible Container concept
 | 
			
		||||
@ingroup container
 | 
			
		||||
 | 
			
		||||
A ReversibleContainer is a Container that has iterators that meet the
 | 
			
		||||
requirements of either BidirectionalIterator or RandomAccessIterator. Such
 | 
			
		||||
iterators allow a ReversibleContainer to be iterated over in reverse.
 | 
			
		||||
 | 
			
		||||
@see http://en.cppreference.com/w/cpp/concept/ReversibleContainer
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
#ifndef _NLOHMANN_JSON
 | 
			
		||||
#define _NLOHMANN_JSON
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -871,15 +851,12 @@ class basic_json
 | 
			
		|||
            case (value_t::array):
 | 
			
		||||
            {
 | 
			
		||||
                T to_vector;
 | 
			
		||||
                //to_vector.reserve(m_value.array->size());
 | 
			
		||||
                std::transform(m_value.array->begin(), m_value.array->end(),
 | 
			
		||||
                               std::inserter(to_vector, to_vector.end()), [](basic_json i)
 | 
			
		||||
                {
 | 
			
		||||
                    return i.get<typename T::value_type>();
 | 
			
		||||
                });
 | 
			
		||||
                return to_vector;
 | 
			
		||||
 | 
			
		||||
                //   return T(m_value.array->begin(), m_value.array->end());
 | 
			
		||||
            }
 | 
			
		||||
            default:
 | 
			
		||||
            {
 | 
			
		||||
| 
						 | 
				
			
			@ -1187,6 +1164,129 @@ class basic_json
 | 
			
		|||
        return m_value.object->operator[](key);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// remove element given an iterator
 | 
			
		||||
    template <class T, typename
 | 
			
		||||
              std::enable_if<
 | 
			
		||||
                  std::is_same<T, basic_json::iterator>::value or
 | 
			
		||||
                  std::is_same<T, basic_json::const_iterator>::value
 | 
			
		||||
                  , int>::type
 | 
			
		||||
              = 0>
 | 
			
		||||
    inline T erase(T pos)
 | 
			
		||||
    {
 | 
			
		||||
        // make sure iterator fits the current value
 | 
			
		||||
        if (this != pos.m_object or m_type != pos.m_object->m_type)
 | 
			
		||||
        {
 | 
			
		||||
            throw std::runtime_error("iterator does not fit current value");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        T result = end();
 | 
			
		||||
 | 
			
		||||
        switch (m_type)
 | 
			
		||||
        {
 | 
			
		||||
            case value_t::number_integer:
 | 
			
		||||
            case value_t::number_float:
 | 
			
		||||
            case value_t::boolean:
 | 
			
		||||
            case value_t::string:
 | 
			
		||||
            {
 | 
			
		||||
                if (pos.m_it.generic_iterator != 0)
 | 
			
		||||
                {
 | 
			
		||||
                    throw std::out_of_range("iterator out of range");
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                if (m_type == value_t::string)
 | 
			
		||||
                {
 | 
			
		||||
                    delete m_value.string;
 | 
			
		||||
                    m_value.string = nullptr;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                m_type = value_t::null;
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            case value_t::object:
 | 
			
		||||
            {
 | 
			
		||||
                result.m_it.object_iterator = m_value.object->erase(pos.m_it.object_iterator);
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            case value_t::array:
 | 
			
		||||
            {
 | 
			
		||||
                result.m_it.array_iterator = m_value.array->erase(pos.m_it.array_iterator);
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            default:
 | 
			
		||||
            {
 | 
			
		||||
                throw std::runtime_error("cannot use erase with " + type_name());
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return result;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// remove elements given an iterator range
 | 
			
		||||
    template <class T, typename
 | 
			
		||||
              std::enable_if<
 | 
			
		||||
                  std::is_same<T, basic_json::iterator>::value or
 | 
			
		||||
                  std::is_same<T, basic_json::const_iterator>::value
 | 
			
		||||
                  , int>::type
 | 
			
		||||
              = 0>
 | 
			
		||||
    inline T erase(T first, T last)
 | 
			
		||||
    {
 | 
			
		||||
        // make sure iterator fits the current value
 | 
			
		||||
        if (this != first.m_object or this != last.m_object or
 | 
			
		||||
                m_type != first.m_object->m_type or m_type != last.m_object->m_type)
 | 
			
		||||
        {
 | 
			
		||||
            throw std::runtime_error("iterators do not fit current value");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        T result = end();
 | 
			
		||||
 | 
			
		||||
        switch (m_type)
 | 
			
		||||
        {
 | 
			
		||||
            case value_t::number_integer:
 | 
			
		||||
            case value_t::number_float:
 | 
			
		||||
            case value_t::boolean:
 | 
			
		||||
            case value_t::string:
 | 
			
		||||
            {
 | 
			
		||||
                if (first.m_it.generic_iterator != 0 or last.m_it.generic_iterator != 1)
 | 
			
		||||
                {
 | 
			
		||||
                    throw std::out_of_range("iterators out of range");
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                if (m_type == value_t::string)
 | 
			
		||||
                {
 | 
			
		||||
                    delete m_value.string;
 | 
			
		||||
                    m_value.string = nullptr;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                m_type = value_t::null;
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            case value_t::object:
 | 
			
		||||
            {
 | 
			
		||||
                result.m_it.object_iterator = m_value.object->erase(first.m_it.object_iterator,
 | 
			
		||||
                                              last.m_it.object_iterator);
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            case value_t::array:
 | 
			
		||||
            {
 | 
			
		||||
                result.m_it.array_iterator = m_value.array->erase(first.m_it.array_iterator,
 | 
			
		||||
                                             last.m_it.array_iterator);
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            default:
 | 
			
		||||
            {
 | 
			
		||||
                throw std::runtime_error("cannot use erase with " + type_name());
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return result;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// remove element from an object given a key
 | 
			
		||||
    inline size_type erase(const typename object_t::key_type& key)
 | 
			
		||||
    {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										465
									
								
								test/unit.cpp
									
										
									
									
									
								
							
							
						
						
									
										465
									
								
								test/unit.cpp
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -2294,7 +2294,7 @@ TEST_CASE("element access")
 | 
			
		|||
 | 
			
		||||
        SECTION("remove specified element")
 | 
			
		||||
        {
 | 
			
		||||
            SECTION("remove element")
 | 
			
		||||
            SECTION("remove element by index")
 | 
			
		||||
            {
 | 
			
		||||
                {
 | 
			
		||||
                    json jarray = {1, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}};
 | 
			
		||||
| 
						 | 
				
			
			@ -2337,7 +2337,112 @@ TEST_CASE("element access")
 | 
			
		|||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            SECTION("access on non-object type")
 | 
			
		||||
            SECTION("remove element by iterator")
 | 
			
		||||
            {
 | 
			
		||||
                SECTION("erase(begin())")
 | 
			
		||||
                {
 | 
			
		||||
                    {
 | 
			
		||||
                        json jarray = {1, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}};
 | 
			
		||||
                        json::iterator it2 = jarray.erase(jarray.begin());
 | 
			
		||||
                        CHECK(jarray == json({true, nullptr, "string", 42.23, json::object(), {1, 2, 3}}));
 | 
			
		||||
                        CHECK(*it2 == json(true));
 | 
			
		||||
                    }
 | 
			
		||||
                    {
 | 
			
		||||
                        json jarray = {1, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}};
 | 
			
		||||
                        json::const_iterator it2 = jarray.erase(jarray.cbegin());
 | 
			
		||||
                        CHECK(jarray == json({true, nullptr, "string", 42.23, json::object(), {1, 2, 3}}));
 | 
			
		||||
                        CHECK(*it2 == json(true));
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                SECTION("erase(begin(), end())")
 | 
			
		||||
                {
 | 
			
		||||
                    {
 | 
			
		||||
                        json jarray = {1, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}};
 | 
			
		||||
                        json::iterator it2 = jarray.erase(jarray.begin(), jarray.end());
 | 
			
		||||
                        CHECK(jarray == json::array());
 | 
			
		||||
                        CHECK(it2 == jarray.end());
 | 
			
		||||
                    }
 | 
			
		||||
                    {
 | 
			
		||||
                        json jarray = {1, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}};
 | 
			
		||||
                        json::const_iterator it2 = jarray.erase(jarray.cbegin(), jarray.cend());
 | 
			
		||||
                        CHECK(jarray == json::array());
 | 
			
		||||
                        CHECK(it2 == jarray.cend());
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                SECTION("erase(begin(), begin())")
 | 
			
		||||
                {
 | 
			
		||||
                    {
 | 
			
		||||
                        json jarray = {1, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}};
 | 
			
		||||
                        json::iterator it2 = jarray.erase(jarray.begin(), jarray.begin());
 | 
			
		||||
                        CHECK(jarray == json({1, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}}));
 | 
			
		||||
                        CHECK(*it2 == json(1));
 | 
			
		||||
                    }
 | 
			
		||||
                    {
 | 
			
		||||
                        json jarray = {1, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}};
 | 
			
		||||
                        json::const_iterator it2 = jarray.erase(jarray.cbegin(), jarray.cbegin());
 | 
			
		||||
                        CHECK(jarray == json({1, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}}));
 | 
			
		||||
                        CHECK(*it2 == json(1));
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                SECTION("erase at offset")
 | 
			
		||||
                {
 | 
			
		||||
                    {
 | 
			
		||||
                        json jarray = {1, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}};
 | 
			
		||||
                        json::iterator it = jarray.begin() + 3;
 | 
			
		||||
                        json::iterator it2 = jarray.erase(it);
 | 
			
		||||
                        CHECK(jarray == json({1, true, nullptr, 42.23, json::object(), {1, 2, 3}}));
 | 
			
		||||
                        CHECK(*it2 == json(42.23));
 | 
			
		||||
                    }
 | 
			
		||||
                    {
 | 
			
		||||
                        json jarray = {1, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}};
 | 
			
		||||
                        json::const_iterator it = jarray.cbegin() + 3;
 | 
			
		||||
                        json::const_iterator it2 = jarray.erase(it);
 | 
			
		||||
                        CHECK(jarray == json({1, true, nullptr, 42.23, json::object(), {1, 2, 3}}));
 | 
			
		||||
                        CHECK(*it2 == json(42.23));
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                SECTION("erase subrange")
 | 
			
		||||
                {
 | 
			
		||||
                    {
 | 
			
		||||
                        json jarray = {1, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}};
 | 
			
		||||
                        json::iterator it2 = jarray.erase(jarray.begin() + 2, jarray.begin() + 5);
 | 
			
		||||
                        CHECK(jarray == json({1, true, json::object(), {1, 2, 3}}));
 | 
			
		||||
                        CHECK(*it2 == json::object());
 | 
			
		||||
                    }
 | 
			
		||||
                    {
 | 
			
		||||
                        json jarray = {1, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}};
 | 
			
		||||
                        json::const_iterator it2 = jarray.erase(jarray.cbegin() + 2, jarray.cbegin() + 5);
 | 
			
		||||
                        CHECK(jarray == json({1, true, json::object(), {1, 2, 3}}));
 | 
			
		||||
                        CHECK(*it2 == json::object());
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                SECTION("different arrays")
 | 
			
		||||
                {
 | 
			
		||||
                    {
 | 
			
		||||
                        json jarray = {1, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}};
 | 
			
		||||
                        json jarray2 = {"foo", "bar"};
 | 
			
		||||
                        CHECK_THROWS_AS(jarray.erase(jarray2.begin()), std::runtime_error);
 | 
			
		||||
                        CHECK_THROWS_AS(jarray.erase(jarray.begin(), jarray2.end()), std::runtime_error);
 | 
			
		||||
                        CHECK_THROWS_AS(jarray.erase(jarray2.begin(), jarray.end()), std::runtime_error);
 | 
			
		||||
                        CHECK_THROWS_AS(jarray.erase(jarray2.begin(), jarray2.end()), std::runtime_error);
 | 
			
		||||
                    }
 | 
			
		||||
                    {
 | 
			
		||||
                        json jarray = {1, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}};
 | 
			
		||||
                        json jarray2 = {"foo", "bar"};
 | 
			
		||||
                        CHECK_THROWS_AS(jarray.erase(jarray2.cbegin()), std::runtime_error);
 | 
			
		||||
                        CHECK_THROWS_AS(jarray.erase(jarray.cbegin(), jarray2.cend()), std::runtime_error);
 | 
			
		||||
                        CHECK_THROWS_AS(jarray.erase(jarray2.cbegin(), jarray.cend()), std::runtime_error);
 | 
			
		||||
                        CHECK_THROWS_AS(jarray.erase(jarray2.cbegin(), jarray2.cend()), std::runtime_error);
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            SECTION("remove element by index in non-array type")
 | 
			
		||||
            {
 | 
			
		||||
                SECTION("null")
 | 
			
		||||
                {
 | 
			
		||||
| 
						 | 
				
			
			@ -2569,7 +2674,7 @@ TEST_CASE("element access")
 | 
			
		|||
 | 
			
		||||
        SECTION("remove specified element")
 | 
			
		||||
        {
 | 
			
		||||
            SECTION("remove element")
 | 
			
		||||
            SECTION("remove element by key")
 | 
			
		||||
            {
 | 
			
		||||
                CHECK(j.find("integer") != j.end());
 | 
			
		||||
                CHECK(j.erase("integer") == 1);
 | 
			
		||||
| 
						 | 
				
			
			@ -2607,7 +2712,112 @@ TEST_CASE("element access")
 | 
			
		|||
                CHECK(j.erase("array") == 0);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            SECTION("access on non-object type")
 | 
			
		||||
            SECTION("remove element by iterator")
 | 
			
		||||
            {
 | 
			
		||||
                SECTION("erase(begin())")
 | 
			
		||||
                {
 | 
			
		||||
                    {
 | 
			
		||||
                        json jobject = {{"a", "a"}, {"b", 1}, {"c", 17}};
 | 
			
		||||
                        json::iterator it2 = jobject.erase(jobject.begin());
 | 
			
		||||
                        CHECK(jobject == json({{"b", 1}, {"c", 17}}));
 | 
			
		||||
                        CHECK(*it2 == json(1));
 | 
			
		||||
                    }
 | 
			
		||||
                    {
 | 
			
		||||
                        json jobject = {{"a", "a"}, {"b", 1}, {"c", 17}};
 | 
			
		||||
                        json::const_iterator it2 = jobject.erase(jobject.cbegin());
 | 
			
		||||
                        CHECK(jobject == json({{"b", 1}, {"c", 17}}));
 | 
			
		||||
                        CHECK(*it2 == json(1));
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                SECTION("erase(begin(), end())")
 | 
			
		||||
                {
 | 
			
		||||
                    {
 | 
			
		||||
                        json jobject = {{"a", "a"}, {"b", 1}, {"c", 17}};
 | 
			
		||||
                        json::iterator it2 = jobject.erase(jobject.begin(), jobject.end());
 | 
			
		||||
                        CHECK(jobject == json::object());
 | 
			
		||||
                        CHECK(it2 == jobject.end());
 | 
			
		||||
                    }
 | 
			
		||||
                    {
 | 
			
		||||
                        json jobject = {{"a", "a"}, {"b", 1}, {"c", 17}};
 | 
			
		||||
                        json::const_iterator it2 = jobject.erase(jobject.cbegin(), jobject.cend());
 | 
			
		||||
                        CHECK(jobject == json::object());
 | 
			
		||||
                        CHECK(it2 == jobject.cend());
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                SECTION("erase(begin(), begin())")
 | 
			
		||||
                {
 | 
			
		||||
                    {
 | 
			
		||||
                        json jobject = {{"a", "a"}, {"b", 1}, {"c", 17}};
 | 
			
		||||
                        json::iterator it2 = jobject.erase(jobject.begin(), jobject.begin());
 | 
			
		||||
                        CHECK(jobject == json({{"a", "a"}, {"b", 1}, {"c", 17}}));
 | 
			
		||||
                        CHECK(*it2 == json("a"));
 | 
			
		||||
                    }
 | 
			
		||||
                    {
 | 
			
		||||
                        json jobject = {{"a", "a"}, {"b", 1}, {"c", 17}};
 | 
			
		||||
                        json::const_iterator it2 = jobject.erase(jobject.cbegin(), jobject.cbegin());
 | 
			
		||||
                        CHECK(jobject == json({{"a", "a"}, {"b", 1}, {"c", 17}}));
 | 
			
		||||
                        CHECK(*it2 == json("a"));
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                SECTION("erase at offset")
 | 
			
		||||
                {
 | 
			
		||||
                    {
 | 
			
		||||
                        json jobject = {{"a", "a"}, {"b", 1}, {"c", 17}};
 | 
			
		||||
                        json::iterator it = jobject.find("b");
 | 
			
		||||
                        json::iterator it2 = jobject.erase(it);
 | 
			
		||||
                        CHECK(jobject == json({{"a", "a"}, {"c", 17}}));
 | 
			
		||||
                        CHECK(*it2 == json(17));
 | 
			
		||||
                    }
 | 
			
		||||
                    {
 | 
			
		||||
                        json jobject = {{"a", "a"}, {"b", 1}, {"c", 17}};
 | 
			
		||||
                        json::const_iterator it = jobject.find("b");
 | 
			
		||||
                        json::const_iterator it2 = jobject.erase(it);
 | 
			
		||||
                        CHECK(jobject == json({{"a", "a"}, {"c", 17}}));
 | 
			
		||||
                        CHECK(*it2 == json(17));
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                SECTION("erase subrange")
 | 
			
		||||
                {
 | 
			
		||||
                    {
 | 
			
		||||
                        json jobject = {{"a", "a"}, {"b", 1}, {"c", 17}, {"d", false}, {"e", true}};
 | 
			
		||||
                        json::iterator it2 = jobject.erase(jobject.find("b"), jobject.find("e"));
 | 
			
		||||
                        CHECK(jobject == json({{"a", "a"}, {"e", true}}));
 | 
			
		||||
                        CHECK(*it2 == json(true));
 | 
			
		||||
                    }
 | 
			
		||||
                    {
 | 
			
		||||
                        json jobject = {{"a", "a"}, {"b", 1}, {"c", 17}, {"d", false}, {"e", true}};
 | 
			
		||||
                        json::const_iterator it2 = jobject.erase(jobject.find("b"), jobject.find("e"));
 | 
			
		||||
                        CHECK(jobject == json({{"a", "a"}, {"e", true}}));
 | 
			
		||||
                        CHECK(*it2 == json(true));
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                SECTION("different arrays")
 | 
			
		||||
                {
 | 
			
		||||
                    {
 | 
			
		||||
                        json jobject = {{"a", "a"}, {"b", 1}, {"c", 17}, {"d", false}, {"e", true}};
 | 
			
		||||
                        json jobject2 = {{"a", "a"}, {"b", 1}, {"c", 17}};
 | 
			
		||||
                        CHECK_THROWS_AS(jobject.erase(jobject2.begin()), std::runtime_error);
 | 
			
		||||
                        CHECK_THROWS_AS(jobject.erase(jobject.begin(), jobject2.end()), std::runtime_error);
 | 
			
		||||
                        CHECK_THROWS_AS(jobject.erase(jobject2.begin(), jobject.end()), std::runtime_error);
 | 
			
		||||
                        CHECK_THROWS_AS(jobject.erase(jobject2.begin(), jobject2.end()), std::runtime_error);
 | 
			
		||||
                    }
 | 
			
		||||
                    {
 | 
			
		||||
                        json jobject = {{"a", "a"}, {"b", 1}, {"c", 17}, {"d", false}, {"e", true}};
 | 
			
		||||
                        json jobject2 = {{"a", "a"}, {"b", 1}, {"c", 17}};
 | 
			
		||||
                        CHECK_THROWS_AS(jobject.erase(jobject2.cbegin()), std::runtime_error);
 | 
			
		||||
                        CHECK_THROWS_AS(jobject.erase(jobject.cbegin(), jobject2.cend()), std::runtime_error);
 | 
			
		||||
                        CHECK_THROWS_AS(jobject.erase(jobject2.cbegin(), jobject.cend()), std::runtime_error);
 | 
			
		||||
                        CHECK_THROWS_AS(jobject.erase(jobject2.cbegin(), jobject2.cend()), std::runtime_error);
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            SECTION("remove element by key in non-object type")
 | 
			
		||||
            {
 | 
			
		||||
                SECTION("null")
 | 
			
		||||
                {
 | 
			
		||||
| 
						 | 
				
			
			@ -2807,6 +3017,253 @@ TEST_CASE("element access")
 | 
			
		|||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    SECTION("other values")
 | 
			
		||||
    {
 | 
			
		||||
        SECTION("erase with one valid iterator")
 | 
			
		||||
        {
 | 
			
		||||
            SECTION("string")
 | 
			
		||||
            {
 | 
			
		||||
                {
 | 
			
		||||
                    json j = "foo";
 | 
			
		||||
                    json::iterator it = j.erase(j.begin());
 | 
			
		||||
                    CHECK(j.type() == json::value_t::null);
 | 
			
		||||
                    CHECK(it == j.end());
 | 
			
		||||
                }
 | 
			
		||||
                {
 | 
			
		||||
                    json j = "bar";
 | 
			
		||||
                    json::const_iterator it = j.erase(j.cbegin());
 | 
			
		||||
                    CHECK(j.type() == json::value_t::null);
 | 
			
		||||
                    CHECK(it == j.end());
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            SECTION("number (boolean)")
 | 
			
		||||
            {
 | 
			
		||||
                {
 | 
			
		||||
                    json j = false;
 | 
			
		||||
                    json::iterator it = j.erase(j.begin());
 | 
			
		||||
                    CHECK(j.type() == json::value_t::null);
 | 
			
		||||
                    CHECK(it == j.end());
 | 
			
		||||
                }
 | 
			
		||||
                {
 | 
			
		||||
                    json j = true;
 | 
			
		||||
                    json::const_iterator it = j.erase(j.cbegin());
 | 
			
		||||
                    CHECK(j.type() == json::value_t::null);
 | 
			
		||||
                    CHECK(it == j.end());
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            SECTION("number (integer)")
 | 
			
		||||
            {
 | 
			
		||||
                {
 | 
			
		||||
                    json j = 17;
 | 
			
		||||
                    json::iterator it = j.erase(j.begin());
 | 
			
		||||
                    CHECK(j.type() == json::value_t::null);
 | 
			
		||||
                    CHECK(it == j.end());
 | 
			
		||||
                }
 | 
			
		||||
                {
 | 
			
		||||
                    json j = 17;
 | 
			
		||||
                    json::const_iterator it = j.erase(j.cbegin());
 | 
			
		||||
                    CHECK(j.type() == json::value_t::null);
 | 
			
		||||
                    CHECK(it == j.end());
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            SECTION("number (floating point)")
 | 
			
		||||
            {
 | 
			
		||||
                {
 | 
			
		||||
                    json j = 23.42;
 | 
			
		||||
                    json::iterator it = j.erase(j.begin());
 | 
			
		||||
                    CHECK(j.type() == json::value_t::null);
 | 
			
		||||
                    CHECK(it == j.end());
 | 
			
		||||
                }
 | 
			
		||||
                {
 | 
			
		||||
                    json j = 23.42;
 | 
			
		||||
                    json::const_iterator it = j.erase(j.cbegin());
 | 
			
		||||
                    CHECK(j.type() == json::value_t::null);
 | 
			
		||||
                    CHECK(it == j.end());
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        SECTION("erase with one invalid iterator")
 | 
			
		||||
        {
 | 
			
		||||
            SECTION("string")
 | 
			
		||||
            {
 | 
			
		||||
                {
 | 
			
		||||
                    json j = "foo";
 | 
			
		||||
                    CHECK_THROWS_AS(j.erase(j.end()), std::out_of_range);
 | 
			
		||||
                }
 | 
			
		||||
                {
 | 
			
		||||
                    json j = "bar";
 | 
			
		||||
                    CHECK_THROWS_AS(j.erase(j.cend()), std::out_of_range);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            SECTION("number (boolean)")
 | 
			
		||||
            {
 | 
			
		||||
                {
 | 
			
		||||
                    json j = false;
 | 
			
		||||
                    CHECK_THROWS_AS(j.erase(j.end()), std::out_of_range);
 | 
			
		||||
                }
 | 
			
		||||
                {
 | 
			
		||||
                    json j = true;
 | 
			
		||||
                    CHECK_THROWS_AS(j.erase(j.cend()), std::out_of_range);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            SECTION("number (integer)")
 | 
			
		||||
            {
 | 
			
		||||
                {
 | 
			
		||||
                    json j = 17;
 | 
			
		||||
                    CHECK_THROWS_AS(j.erase(j.end()), std::out_of_range);
 | 
			
		||||
                }
 | 
			
		||||
                {
 | 
			
		||||
                    json j = 17;
 | 
			
		||||
                    CHECK_THROWS_AS(j.erase(j.cend()), std::out_of_range);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            SECTION("number (floating point)")
 | 
			
		||||
            {
 | 
			
		||||
                {
 | 
			
		||||
                    json j = 23.42;
 | 
			
		||||
                    CHECK_THROWS_AS(j.erase(j.end()), std::out_of_range);
 | 
			
		||||
                }
 | 
			
		||||
                {
 | 
			
		||||
                    json j = 23.42;
 | 
			
		||||
                    CHECK_THROWS_AS(j.erase(j.cend()), std::out_of_range);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        SECTION("erase with two valid iterators")
 | 
			
		||||
        {
 | 
			
		||||
            SECTION("string")
 | 
			
		||||
            {
 | 
			
		||||
                {
 | 
			
		||||
                    json j = "foo";
 | 
			
		||||
                    json::iterator it = j.erase(j.begin(), j.end());
 | 
			
		||||
                    CHECK(j.type() == json::value_t::null);
 | 
			
		||||
                    CHECK(it == j.end());
 | 
			
		||||
                }
 | 
			
		||||
                {
 | 
			
		||||
                    json j = "bar";
 | 
			
		||||
                    json::const_iterator it = j.erase(j.cbegin(), j.cend());
 | 
			
		||||
                    CHECK(j.type() == json::value_t::null);
 | 
			
		||||
                    CHECK(it == j.end());
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            SECTION("number (boolean)")
 | 
			
		||||
            {
 | 
			
		||||
                {
 | 
			
		||||
                    json j = false;
 | 
			
		||||
                    json::iterator it = j.erase(j.begin(), j.end());
 | 
			
		||||
                    CHECK(j.type() == json::value_t::null);
 | 
			
		||||
                    CHECK(it == j.end());
 | 
			
		||||
                }
 | 
			
		||||
                {
 | 
			
		||||
                    json j = true;
 | 
			
		||||
                    json::const_iterator it = j.erase(j.cbegin(), j.cend());
 | 
			
		||||
                    CHECK(j.type() == json::value_t::null);
 | 
			
		||||
                    CHECK(it == j.end());
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            SECTION("number (integer)")
 | 
			
		||||
            {
 | 
			
		||||
                {
 | 
			
		||||
                    json j = 17;
 | 
			
		||||
                    json::iterator it = j.erase(j.begin(), j.end());
 | 
			
		||||
                    CHECK(j.type() == json::value_t::null);
 | 
			
		||||
                    CHECK(it == j.end());
 | 
			
		||||
                }
 | 
			
		||||
                {
 | 
			
		||||
                    json j = 17;
 | 
			
		||||
                    json::const_iterator it = j.erase(j.cbegin(), j.cend());
 | 
			
		||||
                    CHECK(j.type() == json::value_t::null);
 | 
			
		||||
                    CHECK(it == j.end());
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            SECTION("number (floating point)")
 | 
			
		||||
            {
 | 
			
		||||
                {
 | 
			
		||||
                    json j = 23.42;
 | 
			
		||||
                    json::iterator it = j.erase(j.begin(), j.end());
 | 
			
		||||
                    CHECK(j.type() == json::value_t::null);
 | 
			
		||||
                    CHECK(it == j.end());
 | 
			
		||||
                }
 | 
			
		||||
                {
 | 
			
		||||
                    json j = 23.42;
 | 
			
		||||
                    json::const_iterator it = j.erase(j.cbegin(), j.cend());
 | 
			
		||||
                    CHECK(j.type() == json::value_t::null);
 | 
			
		||||
                    CHECK(it == j.end());
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        SECTION("erase with two invalid iterators")
 | 
			
		||||
        {
 | 
			
		||||
            SECTION("string")
 | 
			
		||||
            {
 | 
			
		||||
                {
 | 
			
		||||
                    json j = "foo";
 | 
			
		||||
                    CHECK_THROWS_AS(j.erase(j.end(), j.end()), std::out_of_range);
 | 
			
		||||
                    CHECK_THROWS_AS(j.erase(j.begin(), j.begin()), std::out_of_range);
 | 
			
		||||
                }
 | 
			
		||||
                {
 | 
			
		||||
                    json j = "bar";
 | 
			
		||||
                    CHECK_THROWS_AS(j.erase(j.cend(), j.cend()), std::out_of_range);
 | 
			
		||||
                    CHECK_THROWS_AS(j.erase(j.cbegin(), j.cbegin()), std::out_of_range);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            SECTION("number (boolean)")
 | 
			
		||||
            {
 | 
			
		||||
                {
 | 
			
		||||
                    json j = false;
 | 
			
		||||
                    CHECK_THROWS_AS(j.erase(j.end(), j.end()), std::out_of_range);
 | 
			
		||||
                    CHECK_THROWS_AS(j.erase(j.begin(), j.begin()), std::out_of_range);
 | 
			
		||||
                }
 | 
			
		||||
                {
 | 
			
		||||
                    json j = true;
 | 
			
		||||
                    CHECK_THROWS_AS(j.erase(j.cend(), j.cend()), std::out_of_range);
 | 
			
		||||
                    CHECK_THROWS_AS(j.erase(j.cbegin(), j.cbegin()), std::out_of_range);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            SECTION("number (integer)")
 | 
			
		||||
            {
 | 
			
		||||
                {
 | 
			
		||||
                    json j = 17;
 | 
			
		||||
                    CHECK_THROWS_AS(j.erase(j.end(), j.end()), std::out_of_range);
 | 
			
		||||
                    CHECK_THROWS_AS(j.erase(j.begin(), j.begin()), std::out_of_range);
 | 
			
		||||
                }
 | 
			
		||||
                {
 | 
			
		||||
                    json j = 17;
 | 
			
		||||
                    CHECK_THROWS_AS(j.erase(j.cend(), j.cend()), std::out_of_range);
 | 
			
		||||
                    CHECK_THROWS_AS(j.erase(j.cbegin(), j.cbegin()), std::out_of_range);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            SECTION("number (floating point)")
 | 
			
		||||
            {
 | 
			
		||||
                {
 | 
			
		||||
                    json j = 23.42;
 | 
			
		||||
                    CHECK_THROWS_AS(j.erase(j.end(), j.end()), std::out_of_range);
 | 
			
		||||
                    CHECK_THROWS_AS(j.erase(j.begin(), j.begin()), std::out_of_range);
 | 
			
		||||
                }
 | 
			
		||||
                {
 | 
			
		||||
                    json j = 23.42;
 | 
			
		||||
                    CHECK_THROWS_AS(j.erase(j.cend(), j.cend()), std::out_of_range);
 | 
			
		||||
                    CHECK_THROWS_AS(j.erase(j.cbegin(), j.cbegin()), std::out_of_range);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST_CASE("iterators")
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue