Fix for issue #82 - Nested loops (#84)

* Fix for issue #82 - Nested loops

I made the following changes in renderer.hpp
- Removed the member LoopLevel::it - it was not being used and was
causing issues.
- Added LoopLevel::loop_type with a matching enum class to mark the loop
as looping on either a Map or an Array. This was to replace the hard to
understand test for key_name.empty().
- Modified update_loop_data to get the correct data for map type loops
when copying in outer loop control data.
- Modified update_loop_data to only copy in the outer loop data during
StartLoop, it does not need to be done at EndLoop and can be expensive
since it can copy a large part of the json tree.

All the tests pass and the test cases from the issue also now work. Both
GCC and Clang will compile and run the tests with no issue. No issue is
seen with address_sanitizer in either compiler.

* Remove forgotten debugging code.
diff --git a/include/inja/renderer.hpp b/include/inja/renderer.hpp
index 042c362..f87a6b7 100644
--- a/include/inja/renderer.hpp
+++ b/include/inja/renderer.hpp
@@ -106,18 +106,22 @@
     }
   }
 
-  void update_loop_data()  {
+  void update_loop_data(bool link = true)  {
     LoopLevel& level = m_loop_stack.back();
 
-    if (m_loop_stack.size() > 1) {
+    if (link && (m_loop_stack.size() > 1)) {
       for (int i = m_loop_stack.size() - 2; i >= 0; i--) {
         auto& level_it = m_loop_stack.at(i);
 
-        level.data[static_cast<std::string>(level_it.value_name)] = level_it.values.at(level_it.index);
+        if (level_it.loop_type == LoopLevel::Type::Array) {
+          level.data[static_cast<std::string>(level_it.value_name)] = level_it.values.at(level_it.index);
+        } else {
+          level.data[static_cast<std::string>(level_it.value_name)] = *level_it.map_it->second;
+        }
       }
     }
 
-    if (level.key_name.empty()) {
+    if (level.loop_type == LoopLevel::Type::Array) {
       level.data[static_cast<std::string>(level.value_name)] = level.values.at(level.index); // *level.it;
       auto& loopData = level.data["loop"];
       loopData["index"] = level.index;
@@ -135,7 +139,11 @@
 
   std::vector<json> m_stack;
 
+
   struct LoopLevel {
+    enum class Type { Map, Array };
+
+    Type loop_type;
     nonstd::string_view key_name;       // variable name for keys
     nonstd::string_view value_name;     // variable name for values
     json data;                      // data with loop info added
@@ -143,7 +151,6 @@
     json values;                    // values to iterate over
 
     // loop over list
-    json::iterator it;              // iterator over values
     size_t index;                   // current list index
     size_t size;                    // length of list
 
@@ -152,6 +159,7 @@
     using MapValues = std::vector<KeyValue>;
     MapValues map_values;            // values to iterate over
     MapValues::iterator map_it;      // iterator over values
+
   };
 
   std::vector<LoopLevel> m_loop_stack;
@@ -165,6 +173,7 @@
   Renderer(const TemplateStorage& included_templates, const FunctionStorage& callbacks): m_included_templates(included_templates), m_callbacks(callbacks) {
     m_stack.reserve(16);
     m_tmp_args.reserve(4);
+    m_loop_stack.reserve(16);
   }
 
   void render_to(std::ostream& os, const Template& tmpl, const json& data) {
@@ -474,7 +483,7 @@
           LoopLevel& level = m_loop_stack.back();
           level.value_name = bc.str;
           level.values = std::move(m_stack.back());
-          level.data = data;
+          level.data = (*m_data);
           m_stack.pop_back();
 
           if (bc.value.is_string()) {
@@ -483,6 +492,7 @@
               m_loop_stack.pop_back();
               inja_throw("render_error", "for key, value requires object");
             }
+            level.loop_type = LoopLevel::Type::Map;
             level.key_name = bc.value.get_ref<const std::string&>();
 
             // sort by key
@@ -498,7 +508,7 @@
             }
 
             // list iterator
-            level.it = level.values.begin();
+            level.loop_type = LoopLevel::Type::Array;
             level.index = 0;
             level.size = level.values.size();
           }
@@ -522,10 +532,8 @@
           LoopLevel& level = m_loop_stack.back();
 
           bool done;
-          if (level.key_name.empty()) {
-            level.it += 1;
+          if (level.loop_type == LoopLevel::Type::Array) {
             level.index += 1;
-            // done = (level.it == level.values.end());
             done = (level.index == level.values.size());
           } else {
             level.map_it += 1;
@@ -543,7 +551,7 @@
             break;
           }
 
-          update_loop_data();
+          update_loop_data(false);
 
           // jump back to start of loop
           i = bc.args - 1;  // -1 due to ++i in loop
diff --git a/single_include/inja/inja.hpp b/single_include/inja/inja.hpp
index c6edbb4..0fa6b41 100644
--- a/single_include/inja/inja.hpp
+++ b/single_include/inja/inja.hpp
@@ -2710,18 +2710,22 @@
     }
   }
 
-  void update_loop_data()  {
+  void update_loop_data(bool link = true)  {
     LoopLevel& level = m_loop_stack.back();
 
-    if (m_loop_stack.size() > 1) {
+    if (link && (m_loop_stack.size() > 1)) {
       for (int i = m_loop_stack.size() - 2; i >= 0; i--) {
         auto& level_it = m_loop_stack.at(i);
 
-        level.data[static_cast<std::string>(level_it.value_name)] = level_it.values.at(level_it.index);
+        if (level_it.loop_type == LoopLevel::Type::Array) {
+          level.data[static_cast<std::string>(level_it.value_name)] = level_it.values.at(level_it.index);
+        } else {
+          level.data[static_cast<std::string>(level_it.value_name)] = *level_it.map_it->second;
+        }
       }
     }
 
-    if (level.key_name.empty()) {
+    if (level.loop_type == LoopLevel::Type::Array) {
       level.data[static_cast<std::string>(level.value_name)] = level.values.at(level.index); // *level.it;
       auto& loopData = level.data["loop"];
       loopData["index"] = level.index;
@@ -2739,7 +2743,11 @@
 
   std::vector<json> m_stack;
 
+
   struct LoopLevel {
+    enum class Type { Map, Array };
+
+    Type loop_type;
     nonstd::string_view key_name;       // variable name for keys
     nonstd::string_view value_name;     // variable name for values
     json data;                      // data with loop info added
@@ -2747,7 +2755,6 @@
     json values;                    // values to iterate over
 
     // loop over list
-    json::iterator it;              // iterator over values
     size_t index;                   // current list index
     size_t size;                    // length of list
 
@@ -2756,6 +2763,7 @@
     using MapValues = std::vector<KeyValue>;
     MapValues map_values;            // values to iterate over
     MapValues::iterator map_it;      // iterator over values
+
   };
 
   std::vector<LoopLevel> m_loop_stack;
@@ -2769,6 +2777,7 @@
   Renderer(const TemplateStorage& included_templates, const FunctionStorage& callbacks): m_included_templates(included_templates), m_callbacks(callbacks) {
     m_stack.reserve(16);
     m_tmp_args.reserve(4);
+    m_loop_stack.reserve(16);
   }
 
   void render_to(std::ostream& os, const Template& tmpl, const json& data) {
@@ -3078,7 +3087,7 @@
           LoopLevel& level = m_loop_stack.back();
           level.value_name = bc.str;
           level.values = std::move(m_stack.back());
-          level.data = data;
+          level.data = (*m_data);
           m_stack.pop_back();
 
           if (bc.value.is_string()) {
@@ -3087,6 +3096,7 @@
               m_loop_stack.pop_back();
               inja_throw("render_error", "for key, value requires object");
             }
+            level.loop_type = LoopLevel::Type::Map;
             level.key_name = bc.value.get_ref<const std::string&>();
 
             // sort by key
@@ -3102,7 +3112,7 @@
             }
 
             // list iterator
-            level.it = level.values.begin();
+            level.loop_type = LoopLevel::Type::Array;
             level.index = 0;
             level.size = level.values.size();
           }
@@ -3126,10 +3136,8 @@
           LoopLevel& level = m_loop_stack.back();
 
           bool done;
-          if (level.key_name.empty()) {
-            level.it += 1;
+          if (level.loop_type == LoopLevel::Type::Array) {
             level.index += 1;
-            // done = (level.it == level.values.end());
             done = (level.index == level.values.size());
           } else {
             level.map_it += 1;
@@ -3147,7 +3155,7 @@
             break;
           }
 
-          update_loop_data();
+          update_loop_data(false);
 
           // jump back to start of loop
           i = bc.args - 1;  // -1 due to ++i in loop