From 807de404635e397e3a401de2bc6160809bbbb57f Mon Sep 17 00:00:00 2001
From: Niels <niels.lohmann@gmail.com>
Date: Fri, 23 Jan 2015 18:27:58 +0100
Subject: [PATCH] implemented missing operator[]

---
 header_only/json.h | 23 ++++++++++++++++++-----
 src/json.cc        | 12 ++++++++++--
 src/json.h         | 11 ++++++++---
 test/json_unit.cc  | 18 ++++++++++++++++++
 4 files changed, 54 insertions(+), 10 deletions(-)

diff --git a/header_only/json.h b/header_only/json.h
index ca774a85..5943cd13 100644
--- a/header_only/json.h
+++ b/header_only/json.h
@@ -192,11 +192,14 @@ class json
     @brief create an array object
     @param v  any type of container whose elements can be use to construct
               JSON objects (e.g., std::vector, std::set, std::array)
+    @note For some reason, we need to explicitly forbid JSON iterator types.
     */
     template <class V, typename
               std::enable_if<
-                  not std::is_same<V, json::const_iterator>::value and
                   not std::is_same<V, json::iterator>::value and
+                  not std::is_same<V, json::const_iterator>::value and
+                  not std::is_same<V, json::reverse_iterator>::value and
+                  not std::is_same<V, json::const_reverse_iterator>::value and
                   std::is_constructible<json, typename V::value_type>::value, int>::type
               = 0>
     json(const V& v) : json(array_t(v.begin(), v.end()))
@@ -325,9 +328,9 @@ class json
     void push_back(list_init_t);
 
     /// operator to set an element in an array
-    json& operator[](const int);
+    reference operator[](const int);
     /// operator to get an element in an array
-    const json& operator[](const int) const;
+    const_reference operator[](const int) const;
     /// operator to get an element in an array
     reference at(const int);
     /// operator to get an element in an array
@@ -339,6 +342,8 @@ class json
     reference operator[](const char*);
     /// operator to get an element in an object
     const_reference operator[](const std::string&) const;
+    /// operator to get an element in an object
+    const_reference operator[](const char*) const;
     /// operator to set an element in an object
     reference at(const std::string&);
     /// operator to set an element in an object
@@ -1546,6 +1551,14 @@ json::reference json::operator[](const char* key)
     return (*value_.object)[key];
 }
 
+/*!
+@copydoc json::operator[](const char* key)
+*/
+json::const_reference json::operator[](const std::string& key) const
+{
+    return operator[](key.c_str());
+}
+
 /*!
 This operator realizes read-only access to object elements given a string
 key.
@@ -1557,7 +1570,7 @@ key.
 @exception std::domain_error if object is not an object
 @exception std::out_of_range if key is not found in object
 */
-json::const_reference json::operator[](const std::string& key) const
+json::const_reference json::operator[](const char* key) const
 {
     // this [] operator only works for objects
     if (type_ != value_t::object)
@@ -1572,7 +1585,7 @@ json::const_reference json::operator[](const std::string& key) const
     // make sure the key exists in the object
     if (it == value_.object->end())
     {
-        throw std::out_of_range("key " + key + " not found");
+        throw std::out_of_range("key " + std::string(key) + " not found");
     }
 
     // return element from array at given key
diff --git a/src/json.cc b/src/json.cc
index 5da3cf3a..bec3fff6 100644
--- a/src/json.cc
+++ b/src/json.cc
@@ -981,6 +981,14 @@ json::reference json::operator[](const char* key)
     return (*value_.object)[key];
 }
 
+/*!
+@copydoc json::operator[](const char* key)
+*/
+json::const_reference json::operator[](const std::string& key) const
+{
+    return operator[](key.c_str());
+}
+
 /*!
 This operator realizes read-only access to object elements given a string
 key.
@@ -992,7 +1000,7 @@ key.
 @exception std::domain_error if object is not an object
 @exception std::out_of_range if key is not found in object
 */
-json::const_reference json::operator[](const std::string& key) const
+json::const_reference json::operator[](const char* key) const
 {
     // this [] operator only works for objects
     if (type_ != value_t::object)
@@ -1007,7 +1015,7 @@ json::const_reference json::operator[](const std::string& key) const
     // make sure the key exists in the object
     if (it == value_.object->end())
     {
-        throw std::out_of_range("key " + key + " not found");
+        throw std::out_of_range("key " + std::string(key) + " not found");
     }
 
     // return element from array at given key
diff --git a/src/json.h b/src/json.h
index 72db5fed..f6acc761 100644
--- a/src/json.h
+++ b/src/json.h
@@ -192,11 +192,14 @@ class json
     @brief create an array object
     @param v  any type of container whose elements can be use to construct
               JSON objects (e.g., std::vector, std::set, std::array)
+    @note For some reason, we need to explicitly forbid JSON iterator types.
     */
     template <class V, typename
               std::enable_if<
-                  not std::is_same<V, json::const_iterator>::value and
                   not std::is_same<V, json::iterator>::value and
+                  not std::is_same<V, json::const_iterator>::value and
+                  not std::is_same<V, json::reverse_iterator>::value and
+                  not std::is_same<V, json::const_reverse_iterator>::value and
                   std::is_constructible<json, typename V::value_type>::value, int>::type
               = 0>
     json(const V& v) : json(array_t(v.begin(), v.end()))
@@ -325,9 +328,9 @@ class json
     void push_back(list_init_t);
 
     /// operator to set an element in an array
-    json& operator[](const int);
+    reference operator[](const int);
     /// operator to get an element in an array
-    const json& operator[](const int) const;
+    const_reference operator[](const int) const;
     /// operator to get an element in an array
     reference at(const int);
     /// operator to get an element in an array
@@ -339,6 +342,8 @@ class json
     reference operator[](const char*);
     /// operator to get an element in an object
     const_reference operator[](const std::string&) const;
+    /// operator to get an element in an object
+    const_reference operator[](const char*) const;
     /// operator to set an element in an object
     reference at(const std::string&);
     /// operator to set an element in an object
diff --git a/test/json_unit.cc b/test/json_unit.cc
index fd2d18a8..977eb53d 100644
--- a/test/json_unit.cc
+++ b/test/json_unit.cc
@@ -504,6 +504,18 @@ TEST_CASE("object")
             bool v4 = j[std::string("k4")];
             CHECK(v4 == true);
         }
+        {
+            const std::string v0 = k["k0"];
+            CHECK(v0 == "v0");
+            auto v1 = k["k1"];
+            CHECK(v1 == nullptr);
+            int v2 = k["k2"];
+            CHECK(v2 == 42);
+            double v3 = k["k3"];
+            CHECK(v3 == 3.141);
+            bool v4 = k["k4"];
+            CHECK(v4 == true);
+        }
         {
             const std::string v0 = k[std::string("k0")];
             CHECK(v0 == "v0");
@@ -925,6 +937,12 @@ TEST_CASE("null")
 
         CHECK(n1 == json());
         CHECK(n2 == json());
+
+        json::reverse_iterator ri = n1.rbegin();
+        ri--;
+
+        json::const_reverse_iterator rci = n1.crbegin();
+        rci--;
     }
 }