+ implemented member and non-member swap

This commit is contained in:
Niels 2015-01-19 19:51:07 +01:00
parent 7724d34741
commit a144800774
4 changed files with 154 additions and 4 deletions

View file

@ -34,7 +34,6 @@ due to alignment.
@bug Numbers are currently handled too generously. There are several formats @bug Numbers are currently handled too generously. There are several formats
that are forbidden by the standard, but are accepted by the parser. that are forbidden by the standard, but are accepted by the parser.
@todo Implement json::swap()
@todo Implement json::insert(), json::emplace(), json::emplace_back, json::erase @todo Implement json::insert(), json::emplace(), json::emplace_back, json::erase
@todo Implement json::reverse_iterator, json::const_reverse_iterator, @todo Implement json::reverse_iterator, json::const_reverse_iterator,
json::rbegin(), json::rend(), json::crbegin(), json::crend()? json::rbegin(), json::rend(), json::crbegin(), json::crend()?
@ -178,6 +177,7 @@ class json
operator std::string() const; operator std::string() const;
/// implicit conversion to integer (only for numbers) /// implicit conversion to integer (only for numbers)
operator int() const; operator int() const;
operator long() const;
/// implicit conversion to double (only for numbers) /// implicit conversion to double (only for numbers)
operator double() const; operator double() const;
/// implicit conversion to Boolean (only for Booleans) /// implicit conversion to Boolean (only for Booleans)
@ -289,6 +289,9 @@ class json
/// removes all elements from compounds and resets values to default /// removes all elements from compounds and resets values to default
void clear() noexcept; void clear() noexcept;
/// swaps content with other object
void swap(json&) noexcept;
/// return the type of the object /// return the type of the object
value_type type() const noexcept; value_type type() const noexcept;
@ -418,7 +421,7 @@ class json
/// read the next character, stripping whitespace /// read the next character, stripping whitespace
bool next(); bool next();
/// raise an exception with an error message /// raise an exception with an error message
inline void error(const std::string&) const __attribute__((noreturn)); [[noreturn]] inline void error(const std::string&) const;
/// parse a quoted string /// parse a quoted string
inline std::string parseString(); inline std::string parseString();
/// transforms a unicode codepoint to it's UTF-8 presentation /// transforms a unicode codepoint to it's UTF-8 presentation
@ -450,6 +453,19 @@ class json
/// user-defined literal operator to create JSON objects from strings /// user-defined literal operator to create JSON objects from strings
nlohmann::json operator "" _json(const char*, std::size_t); nlohmann::json operator "" _json(const char*, std::size_t);
// specialization of std::swap
namespace std
{
template <>
/// swaps the values of two JSON objects
inline void swap(nlohmann::json& j1,
nlohmann::json& j2) noexcept(is_nothrow_move_constructible<nlohmann::json>::value and
is_nothrow_move_assignable<nlohmann::json>::value)
{
j1.swap(j2);
}
}
/*! /*!
@file @file
@copyright The code is licensed under the MIT License @copyright The code is licensed under the MIT License
@ -1720,6 +1736,12 @@ void json::clear() noexcept
} }
} }
void json::swap(json& o) noexcept
{
std::swap(type_, o.type_);
std::swap(value_, o.value_);
}
json::value_type json::type() const noexcept json::value_type json::type() const noexcept
{ {
return type_; return type_;

View file

@ -1268,6 +1268,12 @@ void json::clear() noexcept
} }
} }
void json::swap(json& o) noexcept
{
std::swap(type_, o.type_);
std::swap(value_, o.value_);
}
json::value_type json::type() const noexcept json::value_type json::type() const noexcept
{ {
return type_; return type_;

View file

@ -34,7 +34,6 @@ due to alignment.
@bug Numbers are currently handled too generously. There are several formats @bug Numbers are currently handled too generously. There are several formats
that are forbidden by the standard, but are accepted by the parser. that are forbidden by the standard, but are accepted by the parser.
@todo Implement json::swap()
@todo Implement json::insert(), json::emplace(), json::emplace_back, json::erase @todo Implement json::insert(), json::emplace(), json::emplace_back, json::erase
@todo Implement json::reverse_iterator, json::const_reverse_iterator, @todo Implement json::reverse_iterator, json::const_reverse_iterator,
json::rbegin(), json::rend(), json::crbegin(), json::crend()? json::rbegin(), json::rend(), json::crbegin(), json::crend()?
@ -289,6 +288,9 @@ class json
/// removes all elements from compounds and resets values to default /// removes all elements from compounds and resets values to default
void clear() noexcept; void clear() noexcept;
/// swaps content with other object
void swap(json&) noexcept;
/// return the type of the object /// return the type of the object
value_type type() const noexcept; value_type type() const noexcept;
@ -418,7 +420,7 @@ class json
/// read the next character, stripping whitespace /// read the next character, stripping whitespace
bool next(); bool next();
/// raise an exception with an error message /// raise an exception with an error message
inline void error(const std::string&) const __attribute__((noreturn)); [[noreturn]] inline void error(const std::string&) const;
/// parse a quoted string /// parse a quoted string
inline std::string parseString(); inline std::string parseString();
/// transforms a unicode codepoint to it's UTF-8 presentation /// transforms a unicode codepoint to it's UTF-8 presentation
@ -450,3 +452,16 @@ class json
/// user-defined literal operator to create JSON objects from strings /// user-defined literal operator to create JSON objects from strings
nlohmann::json operator "" _json(const char*, std::size_t); nlohmann::json operator "" _json(const char*, std::size_t);
// specialization of std::swap
namespace std
{
template <>
/// swaps the values of two JSON objects
inline void swap(nlohmann::json& j1,
nlohmann::json& j2) noexcept(is_nothrow_move_constructible<nlohmann::json>::value and
is_nothrow_move_assignable<nlohmann::json>::value)
{
j1.swap(j2);
}
}

View file

@ -311,6 +311,17 @@ TEST_CASE("array")
json::const_iterator i4(i1); json::const_iterator i4(i1);
json::const_iterator i5(i2); json::const_iterator i5(i2);
} }
SECTION("Container operations")
{
json a1 = {1, 2, 3, 4};
json a2 = {"one", "two", "three"};
a1.swap(a2);
CHECK(a1 == json({"one", "two", "three"}));
CHECK(a2 == json({1, 2, 3, 4}));
}
} }
TEST_CASE("object") TEST_CASE("object")
@ -714,6 +725,22 @@ TEST_CASE("object")
json::const_iterator i4(i1); json::const_iterator i4(i1);
json::const_iterator i5(i2); json::const_iterator i5(i2);
} }
SECTION("Container operations")
{
json o1 = { {"one", "eins"}, {"two", "zwei"} };
json o2 = { {"one", 1}, {"two", 2} };
o1.swap(o2);
CHECK(o1 == json({ {"one", 1}, {"two", 2} }));
CHECK(o2 == json({ {"one", "eins"}, {"two", "zwei"} }));
std::swap(o1, o2);
CHECK(o1 == json({ {"one", "eins"}, {"two", "zwei"} }));
CHECK(o2 == json({ {"one", 1}, {"two", 2} }));
}
} }
TEST_CASE("null") TEST_CASE("null")
@ -777,6 +804,22 @@ TEST_CASE("null")
j1.clear(); j1.clear();
CHECK(j1 == json(nullptr)); CHECK(j1 == json(nullptr));
} }
SECTION("Container operations")
{
json n1;
json n2;
n1.swap(n2);
CHECK(n1 == json());
CHECK(n2 == json());
std::swap(n1, n2);
CHECK(n1 == json());
CHECK(n2 == json());
}
} }
TEST_CASE("string") TEST_CASE("string")
@ -871,6 +914,22 @@ TEST_CASE("string")
CHECK(json("\f").dump(0) == "\"\\f\""); CHECK(json("\f").dump(0) == "\"\\f\"");
CHECK(json("\r").dump(0) == "\"\\r\""); CHECK(json("\r").dump(0) == "\"\\r\"");
} }
SECTION("Container operations")
{
json s1 = "foo";
json s2 = "bar";
s1.swap(s2);
CHECK(s1 == json("bar"));
CHECK(s2 == json("foo"));
std::swap(s1, s2);
CHECK(s1 == json("foo"));
CHECK(s2 == json("bar"));
}
} }
TEST_CASE("boolean") TEST_CASE("boolean")
@ -950,6 +1009,22 @@ TEST_CASE("boolean")
j1.clear(); j1.clear();
CHECK(j1.get<bool>() == false); CHECK(j1.get<bool>() == false);
} }
SECTION("Container operations")
{
json b1 = true;
json b2 = false;
b1.swap(b2);
CHECK(b1 == json(false));
CHECK(b2 == json(true));
std::swap(b1, b2);
CHECK(b1 == json(true));
CHECK(b2 == json(false));
}
} }
TEST_CASE("number (int)") TEST_CASE("number (int)")
@ -1036,6 +1111,22 @@ TEST_CASE("number (int)")
CHECK(j2.find("foo") == j2.end()); CHECK(j2.find("foo") == j2.end());
CHECK(j2.find(std::string("foo")) == j2.end()); CHECK(j2.find(std::string("foo")) == j2.end());
} }
SECTION("Container operations")
{
json n1 = 23;
json n2 = 42;
n1.swap(n2);
CHECK(n1 == json(42));
CHECK(n2 == json(23));
std::swap(n1, n2);
CHECK(n1 == json(23));
CHECK(n2 == json(42));
}
} }
TEST_CASE("number (float)") TEST_CASE("number (float)")
@ -1115,6 +1206,22 @@ TEST_CASE("number (float)")
j1.clear(); j1.clear();
CHECK(j1.get<double>() == 0.0); CHECK(j1.get<double>() == 0.0);
} }
SECTION("Container operations")
{
json n1 = 23.42;
json n2 = 42.23;
n1.swap(n2);
CHECK(n1 == json(42.23));
CHECK(n2 == json(23.42));
std::swap(n1, n2);
CHECK(n1 == json(23.42));
CHECK(n2 == json(42.23));
}
} }
TEST_CASE("Iterators") TEST_CASE("Iterators")