From 28f64c22a9ca3abb905addd97ae31796b8df5f9f Mon Sep 17 00:00:00 2001 From: Florian Weber Date: Sun, 26 Apr 2015 14:19:56 +0200 Subject: [PATCH 1/5] simplify operator< --- src/json.hpp | 67 ++++++++++++++++------------------------------- src/json.hpp.re2c | 67 ++++++++++++++++------------------------------- 2 files changed, 46 insertions(+), 88 deletions(-) diff --git a/src/json.hpp b/src/json.hpp index e91ed371..4eb073b1 100644 --- a/src/json.hpp +++ b/src/json.hpp @@ -1951,77 +1951,56 @@ class basic_json /// comparison: less than friend bool operator<(const_reference lhs, const_reference rhs) noexcept { - switch (lhs.type()) + const auto lhs_type = lhs.type(); + const auto rhs_type = rhs.type(); + if (lhs_type == rhs_type) { - case (value_t::array): + switch (lhs_type) { - if (rhs.type() == value_t::array) + case (value_t::array): { - return *lhs.m_value.array < *rhs.m_value.array; + return *lhs.m_value_array < *rhs.m_value.array; } - break; - } - case (value_t::object): - { - if (rhs.type() == value_t::object) + case (value_t::onject): { return *lhs.m_value.object < *rhs.m_value.object; } - break; - } - case (value_t::null): - { - if (rhs.type() == value_t::null) + case (value_t::null): { return false; } - break; - } - case (value_t::string): - { - if (rhs.type() == value_t::string) + case (value_t::string): { return *lhs.m_value.string < *rhs.m_value.string; } - break; - } - case (value_t::boolean): - { - if (rhs.type() == value_t::boolean) + case (value_t::boolean): { return lhs.m_value.boolean < rhs.m_value.boolean; } - break; - } - case (value_t::number_integer): - { - if (rhs.type() == value_t::number_integer) + case (value_t::number_integer): { return lhs.m_value.number_integer < rhs.m_value.number_integer; } - if (rhs.type() == value_t::number_float) - { - return lhs.m_value.number_integer < static_cast(rhs.m_value.number_float); - } - break; - } - case (value_t::number_float): - { - if (rhs.type() == value_t::number_integer) - { - return lhs.m_value.number_float < static_cast(rhs.m_value.number_integer); - } - if (rhs.type() == value_t::number_float) + case (value_t::number_float): { return lhs.m_value.number_float < rhs.m_value.number_float; } - break; } } + else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_float) + { + return lhs.m_value.number_integer < + static_cast(rhs.m_value.number_float); + } + else if (lhs_type == value_t::number_float and rhs_type == value_t::number_integer) + { + return lhs.m_value.number_float < + static_cast(rhs.m_value.number_integer); + } // We only reach this line if we cannot compare values. In that case, // we compare types. - return lhs.type() < rhs.type(); + return lhs_type < rhs_type; } /// comparison: less than or equal diff --git a/src/json.hpp.re2c b/src/json.hpp.re2c index bd4ab7a5..a66f109d 100644 --- a/src/json.hpp.re2c +++ b/src/json.hpp.re2c @@ -1951,77 +1951,56 @@ class basic_json /// comparison: less than friend bool operator<(const_reference lhs, const_reference rhs) noexcept { - switch (lhs.type()) + const auto lhs_type = lhs.type(); + const auto rhs_type = rhs.type(); + if (lhs_type == rhs_type) { - case (value_t::array): + switch (lhs_type) { - if (rhs.type() == value_t::array) + case (value_t::array): { - return *lhs.m_value.array < *rhs.m_value.array; + return *lhs.m_value_array < *rhs.m_value.array; } - break; - } - case (value_t::object): - { - if (rhs.type() == value_t::object) + case (value_t::onject): { return *lhs.m_value.object < *rhs.m_value.object; } - break; - } - case (value_t::null): - { - if (rhs.type() == value_t::null) + case (value_t::null): { return false; } - break; - } - case (value_t::string): - { - if (rhs.type() == value_t::string) + case (value_t::string): { return *lhs.m_value.string < *rhs.m_value.string; } - break; - } - case (value_t::boolean): - { - if (rhs.type() == value_t::boolean) + case (value_t::boolean): { return lhs.m_value.boolean < rhs.m_value.boolean; } - break; - } - case (value_t::number_integer): - { - if (rhs.type() == value_t::number_integer) + case (value_t::number_integer): { return lhs.m_value.number_integer < rhs.m_value.number_integer; } - if (rhs.type() == value_t::number_float) - { - return lhs.m_value.number_integer < static_cast(rhs.m_value.number_float); - } - break; - } - case (value_t::number_float): - { - if (rhs.type() == value_t::number_integer) - { - return lhs.m_value.number_float < static_cast(rhs.m_value.number_integer); - } - if (rhs.type() == value_t::number_float) + case (value_t::number_float): { return lhs.m_value.number_float < rhs.m_value.number_float; } - break; } } + else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_float) + { + return lhs.m_value.number_integer < + static_cast(rhs.m_value.number_float); + } + else if (lhs_type == value_t::number_float and rhs_type == value_t::number_integer) + { + return lhs.m_value.number_float < + static_cast(rhs.m_value.number_integer); + } // We only reach this line if we cannot compare values. In that case, // we compare types. - return lhs.type() < rhs.type(); + return lhs_type < rhs_type; } /// comparison: less than or equal From 306695dd258c3bbf5c0a00bc2b29ae7ac5e88181 Mon Sep 17 00:00:00 2001 From: Florian Weber Date: Sun, 26 Apr 2015 14:31:31 +0200 Subject: [PATCH 2/5] fix typos and improve operator== --- src/json.hpp | 68 ++++++++++++++++------------------------------- src/json.hpp.re2c | 68 ++++++++++++++++------------------------------- 2 files changed, 46 insertions(+), 90 deletions(-) diff --git a/src/json.hpp b/src/json.hpp index 4eb073b1..67bfcea6 100644 --- a/src/json.hpp +++ b/src/json.hpp @@ -1868,74 +1868,52 @@ class basic_json */ friend bool operator==(const_reference lhs, const_reference rhs) noexcept { - switch (lhs.type()) + const auto lhs_type = lhs.type(); + const auto rhs_type = rhs.type(); + if (lhs_type == rhs_type) { - case (value_t::array): + switch (lhs_type) { - if (rhs.type() == value_t::array) + case (value_t::array): { return *lhs.m_value.array == *rhs.m_value.array; } - break; - } - case (value_t::object): - { - if (rhs.type() == value_t::object) + case (value_t::object): { return *lhs.m_value.object == *rhs.m_value.object; } - break; - } - case (value_t::null): - { - if (rhs.type() == value_t::null) + case (value_t::null): { return true; } - break; - } - case (value_t::string): - { - if (rhs.type() == value_t::string) + case (value_t::string): { return *lhs.m_value.string == *rhs.m_value.string; } - break; - } - case (value_t::boolean): - { - if (rhs.type() == value_t::boolean) + case (value_t::boolean): { return lhs.m_value.boolean == rhs.m_value.boolean; } - break; - } - case (value_t::number_integer): - { - if (rhs.type() == value_t::number_integer) + case (value_t::number_integer): { return lhs.m_value.number_integer == rhs.m_value.number_integer; } - if (rhs.type() == value_t::number_float) - { - return lhs.m_value.number_integer == static_cast(rhs.m_value.number_float); - } - break; - } - case (value_t::number_float): - { - if (rhs.type() == value_t::number_integer) - { - return approx(lhs.m_value.number_float, static_cast(rhs.m_value.number_integer)); - } - if (rhs.type() == value_t::number_float) + case (value_t::number_float): { return approx(lhs.m_value.number_float, rhs.m_value.number_float); } - break; } } - + else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_float) + { + return lhs.m_value.number_integer == + static_cast(rhs.m_value.number_float); + } + else if (lhs_type == value_t::number_float and rhs_type == value_t::number_integer) + { + return approx(lhs.m_value.number_float, + static_cast(rhs.m_value.number_integer)); + } return false; } @@ -1959,9 +1937,9 @@ class basic_json { case (value_t::array): { - return *lhs.m_value_array < *rhs.m_value.array; + return *lhs.m_value.array < *rhs.m_value.array; } - case (value_t::onject): + case (value_t::object): { return *lhs.m_value.object < *rhs.m_value.object; } diff --git a/src/json.hpp.re2c b/src/json.hpp.re2c index a66f109d..16139cae 100644 --- a/src/json.hpp.re2c +++ b/src/json.hpp.re2c @@ -1868,74 +1868,52 @@ class basic_json */ friend bool operator==(const_reference lhs, const_reference rhs) noexcept { - switch (lhs.type()) + const auto lhs_type = lhs.type(); + const auto rhs_type = rhs.type(); + if (lhs_type == rhs_type) { - case (value_t::array): + switch (lhs_type) { - if (rhs.type() == value_t::array) + case (value_t::array): { return *lhs.m_value.array == *rhs.m_value.array; } - break; - } - case (value_t::object): - { - if (rhs.type() == value_t::object) + case (value_t::object): { return *lhs.m_value.object == *rhs.m_value.object; } - break; - } - case (value_t::null): - { - if (rhs.type() == value_t::null) + case (value_t::null): { return true; } - break; - } - case (value_t::string): - { - if (rhs.type() == value_t::string) + case (value_t::string): { return *lhs.m_value.string == *rhs.m_value.string; } - break; - } - case (value_t::boolean): - { - if (rhs.type() == value_t::boolean) + case (value_t::boolean): { return lhs.m_value.boolean == rhs.m_value.boolean; } - break; - } - case (value_t::number_integer): - { - if (rhs.type() == value_t::number_integer) + case (value_t::number_integer): { return lhs.m_value.number_integer == rhs.m_value.number_integer; } - if (rhs.type() == value_t::number_float) - { - return lhs.m_value.number_integer == static_cast(rhs.m_value.number_float); - } - break; - } - case (value_t::number_float): - { - if (rhs.type() == value_t::number_integer) - { - return approx(lhs.m_value.number_float, static_cast(rhs.m_value.number_integer)); - } - if (rhs.type() == value_t::number_float) + case (value_t::number_float): { return approx(lhs.m_value.number_float, rhs.m_value.number_float); } - break; } } - + else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_float) + { + return lhs.m_value.number_integer == + static_cast(rhs.m_value.number_float); + } + else if (lhs_type == value_t::number_float and rhs_type == value_t::number_integer) + { + return approx(lhs.m_value.number_float, + static_cast(rhs.m_value.number_integer)); + } return false; } @@ -1959,9 +1937,9 @@ class basic_json { case (value_t::array): { - return *lhs.m_value_array < *rhs.m_value.array; + return *lhs.m_value.array < *rhs.m_value.array; } - case (value_t::onject): + case (value_t::object): { return *lhs.m_value.object < *rhs.m_value.object; } From d2771eb1bb98827f992a7c7d3c05da484e67b6dc Mon Sep 17 00:00:00 2001 From: Florian Weber Date: Sun, 26 Apr 2015 14:39:39 +0200 Subject: [PATCH 3/5] Fix comparission between integers and floats MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Until now it depended on the parameter-order whether integers and floats were compared as integers or floats. Appart from being not logical, this might even have meant that the provided “order” was in fact not that. (not sure here, but I like to be carefull) --- src/json.hpp | 8 ++++---- src/json.hpp.re2c | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/json.hpp b/src/json.hpp index 67bfcea6..8a4ad12d 100644 --- a/src/json.hpp +++ b/src/json.hpp @@ -1906,8 +1906,8 @@ class basic_json } else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_float) { - return lhs.m_value.number_integer == - static_cast(rhs.m_value.number_float); + return approx(static_cast(lhs.m_value.number_integer), + rhs.m_value.number_float); } else if (lhs_type == value_t::number_float and rhs_type == value_t::number_integer) { @@ -1967,8 +1967,8 @@ class basic_json } else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_float) { - return lhs.m_value.number_integer < - static_cast(rhs.m_value.number_float); + return static_cast(lhs.m_value.number_integer) < + rhs.m_value.number_float; } else if (lhs_type == value_t::number_float and rhs_type == value_t::number_integer) { diff --git a/src/json.hpp.re2c b/src/json.hpp.re2c index 16139cae..1d41b39c 100644 --- a/src/json.hpp.re2c +++ b/src/json.hpp.re2c @@ -1906,8 +1906,8 @@ class basic_json } else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_float) { - return lhs.m_value.number_integer == - static_cast(rhs.m_value.number_float); + return approx(static_cast(lhs.m_value.number_integer), + rhs.m_value.number_float); } else if (lhs_type == value_t::number_float and rhs_type == value_t::number_integer) { @@ -1967,8 +1967,8 @@ class basic_json } else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_float) { - return lhs.m_value.number_integer < - static_cast(rhs.m_value.number_float); + return static_cast(lhs.m_value.number_integer) < + rhs.m_value.number_float; } else if (lhs_type == value_t::number_float and rhs_type == value_t::number_integer) { From f5e95522aae45f1f105247d7f2a5b9310879a4bd Mon Sep 17 00:00:00 2001 From: Florian Weber Date: Sun, 26 Apr 2015 14:44:56 +0200 Subject: [PATCH 4/5] remove braces around single-return-statement switch-cases --- src/json.hpp | 28 ---------------------------- src/json.hpp.re2c | 28 ---------------------------- 2 files changed, 56 deletions(-) diff --git a/src/json.hpp b/src/json.hpp index 8a4ad12d..cf5befe7 100644 --- a/src/json.hpp +++ b/src/json.hpp @@ -1875,33 +1875,19 @@ class basic_json switch (lhs_type) { case (value_t::array): - { return *lhs.m_value.array == *rhs.m_value.array; - } case (value_t::object): - { return *lhs.m_value.object == *rhs.m_value.object; - } case (value_t::null): - { return true; - } case (value_t::string): - { return *lhs.m_value.string == *rhs.m_value.string; - } case (value_t::boolean): - { return lhs.m_value.boolean == rhs.m_value.boolean; - } case (value_t::number_integer): - { return lhs.m_value.number_integer == rhs.m_value.number_integer; - } case (value_t::number_float): - { return approx(lhs.m_value.number_float, rhs.m_value.number_float); - } } } else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_float) @@ -1936,33 +1922,19 @@ class basic_json switch (lhs_type) { case (value_t::array): - { return *lhs.m_value.array < *rhs.m_value.array; - } case (value_t::object): - { return *lhs.m_value.object < *rhs.m_value.object; - } case (value_t::null): - { return false; - } case (value_t::string): - { return *lhs.m_value.string < *rhs.m_value.string; - } case (value_t::boolean): - { return lhs.m_value.boolean < rhs.m_value.boolean; - } case (value_t::number_integer): - { return lhs.m_value.number_integer < rhs.m_value.number_integer; - } case (value_t::number_float): - { return lhs.m_value.number_float < rhs.m_value.number_float; - } } } else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_float) diff --git a/src/json.hpp.re2c b/src/json.hpp.re2c index 1d41b39c..ae91d735 100644 --- a/src/json.hpp.re2c +++ b/src/json.hpp.re2c @@ -1875,33 +1875,19 @@ class basic_json switch (lhs_type) { case (value_t::array): - { return *lhs.m_value.array == *rhs.m_value.array; - } case (value_t::object): - { return *lhs.m_value.object == *rhs.m_value.object; - } case (value_t::null): - { return true; - } case (value_t::string): - { return *lhs.m_value.string == *rhs.m_value.string; - } case (value_t::boolean): - { return lhs.m_value.boolean == rhs.m_value.boolean; - } case (value_t::number_integer): - { return lhs.m_value.number_integer == rhs.m_value.number_integer; - } case (value_t::number_float): - { return approx(lhs.m_value.number_float, rhs.m_value.number_float); - } } } else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_float) @@ -1936,33 +1922,19 @@ class basic_json switch (lhs_type) { case (value_t::array): - { return *lhs.m_value.array < *rhs.m_value.array; - } case (value_t::object): - { return *lhs.m_value.object < *rhs.m_value.object; - } case (value_t::null): - { return false; - } case (value_t::string): - { return *lhs.m_value.string < *rhs.m_value.string; - } case (value_t::boolean): - { return lhs.m_value.boolean < rhs.m_value.boolean; - } case (value_t::number_integer): - { return lhs.m_value.number_integer < rhs.m_value.number_integer; - } case (value_t::number_float): - { return lhs.m_value.number_float < rhs.m_value.number_float; - } } } else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_float) From 4fbff7d1402142a74e578450fb6afb0c8524f417 Mon Sep 17 00:00:00 2001 From: Florian Weber Date: Sun, 26 Apr 2015 14:55:06 +0200 Subject: [PATCH 5/5] simplify value_t::operator< by using a lookup-table --- src/json.hpp | 80 +++++++---------------------------------------- src/json.hpp.re2c | 80 +++++++---------------------------------------- 2 files changed, 22 insertions(+), 138 deletions(-) diff --git a/src/json.hpp b/src/json.hpp index cf5befe7..b294e8e1 100644 --- a/src/json.hpp +++ b/src/json.hpp @@ -11,6 +11,7 @@ #define NLOHMANN_JSON_HPP #include +#include #include #include #include @@ -202,76 +203,17 @@ class basic_json */ friend bool operator<(const value_t lhs, const value_t rhs) { - // no type is smaller than itself - if (lhs == rhs) - { - return false; - } - - switch (lhs) - { - case (value_t::null): - { - // nulls are smaller than all other types - return true; + std::array order = {{ + 0, // null + 3, // object + 4, // array + 5, // string + 1, // boolean + 2, // integer + 2 // float } - - case (value_t::boolean): - { - // only nulls are smaller than booleans - return (rhs != value_t::null); - } - - case (value_t::number_float): - case (value_t::number_integer): - { - switch (rhs) - { - // numbers are smaller than objects, arrays, and string - case (value_t::object): - case (value_t::array): - case (value_t::string): - { - return true; - } - - default: - { - return false; - } - } - } - - case (value_t::object): - { - switch (rhs) - { - // objects are smaller than arrays and string - case (value_t::array): - case (value_t::string): - { - return true; - } - - default: - { - return false; - } - } - } - - case (value_t::array): - { - // arrays are smaller than strings - return (rhs == value_t::string); - } - - default: - { - // a string is not smaller than any other types - return false; - } - } + }; + return order[static_cast(lhs)] < order[static_cast(rhs)]; } diff --git a/src/json.hpp.re2c b/src/json.hpp.re2c index ae91d735..b50eb2a9 100644 --- a/src/json.hpp.re2c +++ b/src/json.hpp.re2c @@ -11,6 +11,7 @@ #define NLOHMANN_JSON_HPP #include +#include #include #include #include @@ -202,76 +203,17 @@ class basic_json */ friend bool operator<(const value_t lhs, const value_t rhs) { - // no type is smaller than itself - if (lhs == rhs) - { - return false; - } - - switch (lhs) - { - case (value_t::null): - { - // nulls are smaller than all other types - return true; + std::array order = {{ + 0, // null + 3, // object + 4, // array + 5, // string + 1, // boolean + 2, // integer + 2 // float } - - case (value_t::boolean): - { - // only nulls are smaller than booleans - return (rhs != value_t::null); - } - - case (value_t::number_float): - case (value_t::number_integer): - { - switch (rhs) - { - // numbers are smaller than objects, arrays, and string - case (value_t::object): - case (value_t::array): - case (value_t::string): - { - return true; - } - - default: - { - return false; - } - } - } - - case (value_t::object): - { - switch (rhs) - { - // objects are smaller than arrays and string - case (value_t::array): - case (value_t::string): - { - return true; - } - - default: - { - return false; - } - } - } - - case (value_t::array): - { - // arrays are smaller than strings - return (rhs == value_t::string); - } - - default: - { - // a string is not smaller than any other types - return false; - } - } + }; + return order[static_cast(lhs)] < order[static_cast(rhs)]; }