Browse Source

refactor: Array and Object iterators were in the wrong header files, swap them

Sam Jaffe 3 months ago
parent
commit
d40526278d
2 changed files with 51 additions and 20 deletions
  1. 19 11
      include/jvalidate/detail/array_iterator.h
  2. 32 9
      include/jvalidate/detail/object_iterator.h

+ 19 - 11
include/jvalidate/detail/array_iterator.h

@@ -1,37 +1,45 @@
 #pragma once
 
 #include <iterator>
-#include <string>
 
 #include <jvalidate/detail/deref_proxy.h>
 
 namespace jvalidate::adapter::detail {
-
-template <typename It, typename Adapter> class JsonObjectIterator : public It {
+/**
+ * @brief An iterator for binding JSON values of type Array - which are
+ * congruent to a vector<JSON>.
+ *
+ * @tparam It The underlying iterator type being operated on
+ * @tparam Adapter The owning adapter type, must fulfill the following
+ * contracts:
+ *    - is constructible from the value_type of It
+ * Additionally, Adapter is expected to conform to the jvalidate::Adapter
+ * concept.
+ */
+template <typename It, typename Adapter> class JsonArrayIterator : public It {
 public:
-  using value_type = std::pair<std::string, Adapter>;
-  using reference = std::pair<std::string, Adapter>;
+  using value_type = Adapter;
+  using reference = Adapter;
   using pointer = ::jvalidate::detail::DerefProxy<reference>;
   using difference_type = std::ptrdiff_t;
   using iterator_category = std::forward_iterator_tag;
 
-  JsonObjectIterator() = default;
-  JsonObjectIterator(It it) : It(it) {}
+  JsonArrayIterator() = default; // Sentinel for handling null objects
+  JsonArrayIterator(It it) : It(it) {}
 
-  reference operator*() const { return {Adapter::key(*this), Adapter(It::operator->())}; }
+  reference operator*() const { return Adapter(It::operator*()); }
 
   pointer operator->() const { return {operator*()}; }
 
-  JsonObjectIterator operator++(int) {
+  JsonArrayIterator operator++(int) {
     auto tmp = *this;
     ++*this;
     return tmp;
   }
 
-  JsonObjectIterator & operator++() {
+  JsonArrayIterator & operator++() {
     It::operator++();
     return *this;
   }
 };
-
 }

+ 32 - 9
include/jvalidate/detail/object_iterator.h

@@ -1,33 +1,56 @@
 #pragma once
 
 #include <iterator>
+#include <string>
 
 #include <jvalidate/detail/deref_proxy.h>
 
 namespace jvalidate::adapter::detail {
-
-template <typename It, typename Adapter> class JsonArrayIterator : public It {
+/**
+ * @brief An iterator for binding JSON values of type Object - which are
+ * congruent to a map<string, JSON>.
+ *
+ * Conventionally - many JSON libraries use the same iterator object to
+ * represent both Array iteration and Object iteration, either by returning
+ * the Array index as a string-key, or by providing a special method e.g.
+ * `key()` which accesses the Object key, while dereferencing the iterator
+ * always returns the pointed-to JSON, regardless of Array/Object-ness.
+ *
+ * @tparam It The underlying iterator type being operated on
+ * @tparam Adapter The owning adapter type, must fulfill the following
+ * contracts:
+ *    - is constructible from the value_type of It
+ *    - has a static method key() which extracts the Object key from an It
+ * Additionally, Adapter is expected to conform to the jvalidate::Adapter
+ * concept.
+ */
+template <typename It, typename Adapter> class JsonObjectIterator : public It {
 public:
-  using value_type = Adapter;
-  using reference = Adapter;
+  using value_type = std::pair<std::string, Adapter>;
+  // Cannot return key by reference - because we don't know for certain
+  // that the key-extraction function on It will return a string by reference
+  // (such as if they do not store a default empty key).
+  using reference = std::pair<std::string, Adapter>;
   using pointer = ::jvalidate::detail::DerefProxy<reference>;
   using difference_type = std::ptrdiff_t;
   using iterator_category = std::forward_iterator_tag;
 
-  JsonArrayIterator() = default;
-  JsonArrayIterator(It it) : It(it) {}
+  JsonObjectIterator() = default; // Sentinel for handling null objects
+  JsonObjectIterator(It it) : It(it) {}
 
-  reference operator*() const { return {It::operator*()}; }
+  reference operator*() const {
+    return { Adapter::key(*this), Adapter(It::operator->()) };
+  }
 
   pointer operator->() const { return {operator*()}; }
 
-  JsonArrayIterator operator++(int) {
+  JsonObjectIterator operator++(int) {
     auto tmp = *this;
     ++*this;
     return tmp;
   }
 
-  JsonArrayIterator & operator++() {
+  JsonObjectIterator & operator++() {
     It::operator++();
     return *this;
   }