From 90eb0a91e0caffdf9b33939760880a92ec132aba Mon Sep 17 00:00:00 2001 From: Niels Lohmann Date: Sat, 26 May 2018 13:26:40 +0200 Subject: [PATCH 1/2] :zap: keys are now returned as const reference #1098 --- .../nlohmann/detail/iterators/iter_impl.hpp | 2 +- .../detail/iterators/iteration_proxy.hpp | 18 +++++++++++++---- single_include/nlohmann/json.hpp | 20 ++++++++++++++----- 3 files changed, 30 insertions(+), 10 deletions(-) diff --git a/include/nlohmann/detail/iterators/iter_impl.hpp b/include/nlohmann/detail/iterators/iter_impl.hpp index 52ede17b..08108a22 100644 --- a/include/nlohmann/detail/iterators/iter_impl.hpp +++ b/include/nlohmann/detail/iterators/iter_impl.hpp @@ -583,7 +583,7 @@ class iter_impl @brief return the key of an object iterator @pre The iterator is initialized; i.e. `m_object != nullptr`. */ - typename object_t::key_type key() const + const typename object_t::key_type& key() const { assert(m_object != nullptr); diff --git a/include/nlohmann/detail/iterators/iteration_proxy.hpp b/include/nlohmann/detail/iterators/iteration_proxy.hpp index 7547d038..39c35a2e 100644 --- a/include/nlohmann/detail/iterators/iteration_proxy.hpp +++ b/include/nlohmann/detail/iterators/iteration_proxy.hpp @@ -21,6 +21,10 @@ template class iteration_proxy IteratorType anchor; /// an index for arrays (used to create key names) std::size_t array_index = 0; + /// a string representation of the array index + std::string array_index_str = "0"; + /// an empty string (to return a reference for primitive values) + const std::string empty_str = ""; public: explicit iteration_proxy_internal(IteratorType it) noexcept : anchor(it) {} @@ -35,7 +39,13 @@ template class iteration_proxy iteration_proxy_internal& operator++() { ++anchor; - ++array_index; + + assert(anchor.m_object != nullptr); + if (anchor.m_object->is_array()) + { + // update array index and string representation + array_index_str = std::to_string(++array_index); + } return *this; } @@ -47,7 +57,7 @@ template class iteration_proxy } /// return key of the iterator - std::string key() const + const std::string& key() const { assert(anchor.m_object != nullptr); @@ -55,7 +65,7 @@ template class iteration_proxy { // use integer array index as key case value_t::array: - return std::to_string(array_index); + return array_index_str; // use key from the object case value_t::object: @@ -63,7 +73,7 @@ template class iteration_proxy // use an empty key for all primitive types default: - return ""; + return empty_str; } } diff --git a/single_include/nlohmann/json.hpp b/single_include/nlohmann/json.hpp index 8c9942bb..0b2e055c 100644 --- a/single_include/nlohmann/json.hpp +++ b/single_include/nlohmann/json.hpp @@ -4636,7 +4636,7 @@ class iter_impl @brief return the key of an object iterator @pre The iterator is initialized; i.e. `m_object != nullptr`. */ - typename object_t::key_type key() const + const typename object_t::key_type& key() const { assert(m_object != nullptr); @@ -4691,6 +4691,10 @@ template class iteration_proxy IteratorType anchor; /// an index for arrays (used to create key names) std::size_t array_index = 0; + /// a string representation of the array index + std::string array_index_str = "0"; + /// an empty string (to return a reference for primitive values) + const std::string empty_str = ""; public: explicit iteration_proxy_internal(IteratorType it) noexcept : anchor(it) {} @@ -4705,7 +4709,13 @@ template class iteration_proxy iteration_proxy_internal& operator++() { ++anchor; - ++array_index; + + assert(anchor.m_object != nullptr); + if (anchor.m_object->is_array()) + { + // update array index and string representation + array_index_str = std::to_string(++array_index); + } return *this; } @@ -4717,7 +4727,7 @@ template class iteration_proxy } /// return key of the iterator - std::string key() const + const std::string& key() const { assert(anchor.m_object != nullptr); @@ -4725,7 +4735,7 @@ template class iteration_proxy { // use integer array index as key case value_t::array: - return std::to_string(array_index); + return array_index_str; // use key from the object case value_t::object: @@ -4733,7 +4743,7 @@ template class iteration_proxy // use an empty key for all primitive types default: - return ""; + return empty_str; } } From 481ace65c49dc198ab3255f71d43b5bb50fd9af1 Mon Sep 17 00:00:00 2001 From: Niels Lohmann Date: Sun, 27 May 2018 12:04:22 +0200 Subject: [PATCH 2/2] :hammer: only calculate array index string when needed #1098 --- .../detail/iterators/iteration_proxy.hpp | 19 +++++++++++-------- single_include/nlohmann/json.hpp | 19 +++++++++++-------- 2 files changed, 22 insertions(+), 16 deletions(-) diff --git a/include/nlohmann/detail/iterators/iteration_proxy.hpp b/include/nlohmann/detail/iterators/iteration_proxy.hpp index 39c35a2e..047e1855 100644 --- a/include/nlohmann/detail/iterators/iteration_proxy.hpp +++ b/include/nlohmann/detail/iterators/iteration_proxy.hpp @@ -21,8 +21,10 @@ template class iteration_proxy IteratorType anchor; /// an index for arrays (used to create key names) std::size_t array_index = 0; + /// last stringified array index + mutable std::size_t array_index_last = 0; /// a string representation of the array index - std::string array_index_str = "0"; + mutable std::string array_index_str = "0"; /// an empty string (to return a reference for primitive values) const std::string empty_str = ""; @@ -39,13 +41,7 @@ template class iteration_proxy iteration_proxy_internal& operator++() { ++anchor; - - assert(anchor.m_object != nullptr); - if (anchor.m_object->is_array()) - { - // update array index and string representation - array_index_str = std::to_string(++array_index); - } + ++array_index; return *this; } @@ -65,7 +61,14 @@ template class iteration_proxy { // use integer array index as key case value_t::array: + { + if (array_index != array_index_last) + { + array_index_str = std::to_string(array_index); + array_index_last = array_index; + } return array_index_str; + } // use key from the object case value_t::object: diff --git a/single_include/nlohmann/json.hpp b/single_include/nlohmann/json.hpp index 0b2e055c..24d2269a 100644 --- a/single_include/nlohmann/json.hpp +++ b/single_include/nlohmann/json.hpp @@ -4691,8 +4691,10 @@ template class iteration_proxy IteratorType anchor; /// an index for arrays (used to create key names) std::size_t array_index = 0; + /// last stringified array index + mutable std::size_t array_index_last = 0; /// a string representation of the array index - std::string array_index_str = "0"; + mutable std::string array_index_str = "0"; /// an empty string (to return a reference for primitive values) const std::string empty_str = ""; @@ -4709,13 +4711,7 @@ template class iteration_proxy iteration_proxy_internal& operator++() { ++anchor; - - assert(anchor.m_object != nullptr); - if (anchor.m_object->is_array()) - { - // update array index and string representation - array_index_str = std::to_string(++array_index); - } + ++array_index; return *this; } @@ -4735,7 +4731,14 @@ template class iteration_proxy { // use integer array index as key case value_t::array: + { + if (array_index != array_index_last) + { + array_index_str = std::to_string(array_index); + array_index_last = array_index; + } return array_index_str; + } // use key from the object case value_t::object: