?login_element?

Subversion Repositories NedoOS

Rev

Blame | Last modification | View Log | Download

  1. // https://github.com/vinniefalco/LuaBridge
  2. // Copyright 2018, Dmitry Tarakanov
  3. // Copyright 2012, Vinnie Falco <vinnie.falco@gmail.com>
  4. // SPDX-License-Identifier: MIT
  5.  
  6. #pragma once
  7.  
  8. #include <LuaBridge/detail/LuaRef.h>
  9.  
  10. #include <utility>
  11.  
  12. namespace luabridge {
  13.  
  14. /** Allows table iteration.
  15.  */
  16. class Iterator
  17. {
  18.     lua_State* m_L;
  19.     LuaRef m_table;
  20.     LuaRef m_key;
  21.     LuaRef m_value;
  22.  
  23.     void next()
  24.     {
  25.         m_table.push();
  26.         m_key.push();
  27.         if (lua_next(m_L, -2))
  28.         {
  29.             m_value.pop();
  30.             m_key.pop();
  31.         }
  32.         else
  33.         {
  34.             m_key = Nil();
  35.             m_value = Nil();
  36.         }
  37.         lua_pop(m_L, 1);
  38.     }
  39.  
  40. public:
  41.     explicit Iterator(const LuaRef& table, bool isEnd = false)
  42.         : m_L(table.state())
  43.         , m_table(table)
  44.         , m_key(table.state()) // m_key is nil
  45.         , m_value(table.state()) // m_value is nil
  46.     {
  47.         if (!isEnd)
  48.         {
  49.             next(); // get the first (key, value) pair from table
  50.         }
  51.     }
  52.  
  53.     /// Return an associated Lua state.
  54.     ///
  55.     /// @returns A Lua state.
  56.     ///
  57.     lua_State* state() const { return m_L; }
  58.  
  59.     /// Dereference the iterator.
  60.     ///
  61.     /// @returns A key-value pair for a current table entry.
  62.     ///
  63.     std::pair<LuaRef, LuaRef> operator*() const { return std::make_pair(m_key, m_value); }
  64.  
  65.     /// Return the value referred by the iterator.
  66.     ///
  67.     /// @returns A value for the current table entry.
  68.     ///
  69.     LuaRef operator->() const { return m_value; }
  70.  
  71.     /// Compare two iterators.
  72.     ///
  73.     /// @param rhs Another iterator.
  74.     /// @returns True if iterators point to the same entry of the same table,
  75.     ///         false otherwise.
  76.     ///
  77.     bool operator!=(const Iterator& rhs) const
  78.     {
  79.         assert(m_L == rhs.m_L);
  80.         return !m_table.rawequal(rhs.m_table) || !m_key.rawequal(rhs.m_key);
  81.     }
  82.  
  83.     /// Move the iterator to the next table entry.
  84.     ///
  85.     /// @returns This iterator.
  86.     ///
  87.     Iterator& operator++()
  88.     {
  89.         if (isNil())
  90.         {
  91.             // if the iterator reaches the end, do nothing
  92.             return *this;
  93.         }
  94.         else
  95.         {
  96.             next();
  97.             return *this;
  98.         }
  99.     }
  100.  
  101.     /// Check if the iterator points after the last table entry.
  102.     ///
  103.     /// @returns True if there are no more table entries to iterate,
  104.     ///         false otherwise.
  105.     ///
  106.     bool isNil() const { return m_key.isNil(); }
  107.  
  108.     /// Return the key for the current table entry.
  109.     ///
  110.     /// @returns A reference to the entry key.
  111.     ///
  112.     LuaRef key() const { return m_key; }
  113.  
  114.     /// Return the key for the current table entry.
  115.     ///
  116.     /// @returns A reference to the entry value.
  117.     ///
  118.     LuaRef value() const { return m_value; }
  119.  
  120. private:
  121.     // Don't use postfix increment, it is less efficient
  122.     Iterator operator++(int);
  123. };
  124.  
  125. namespace detail {
  126.  
  127. class Range
  128. {
  129.     Iterator m_begin;
  130.     Iterator m_end;
  131.  
  132. public:
  133.     Range(const Iterator& begin, const Iterator& end) : m_begin(begin), m_end(end) {}
  134.  
  135.     const Iterator& begin() const { return m_begin; }
  136.     const Iterator& end() const { return m_end; }
  137. };
  138.  
  139. } // namespace detail
  140.  
  141. /// Return a range for the Lua table reference.
  142. ///
  143. /// @returns A range suitable for range-based for statement.
  144. ///
  145. inline detail::Range pairs(const LuaRef& table)
  146. {
  147.     return detail::Range(Iterator(table, false), Iterator(table, true));
  148. }
  149.  
  150. } // namespace luabridge
  151.