object.hpp

来自「这是整套横扫千军3D版游戏的源码」· HPP 代码 · 共 1,163 行 · 第 1/2 页

HPP
1,163
字号

      template<class T>
      this_type& operator=(T const& value)
      {
          value_wrapper_traits<Next>::unwrap(m_interpreter, m_next);
          detail::stack_pop pop(m_interpreter, 1);

          lua_pushvalue(m_interpreter, m_key_index);
          detail::push(m_interpreter, value);
          lua_settable(m_interpreter, -3);
          return *this;
      }

      template<class T>
      index_proxy<this_type> operator[](T const& key)
      {
          return index_proxy<this_type>(*this, m_interpreter, key);
      }

      void push(lua_State* interpreter);

      lua_State* interpreter() const
      {
          return m_interpreter;
      }

  private:
      this_type& operator=(index_proxy<Next> const&);

      mutable lua_State* m_interpreter;
      int m_key_index;

      Next const& m_next;
  };

} // namespace adl

typedef detail::basic_iterator<detail::basic_access> iterator;
typedef detail::basic_iterator<detail::raw_access> raw_iterator;

#ifndef LUABIND_USE_VALUE_WRAPPER_TAG
template<class T>
struct value_wrapper_traits<adl::index_proxy<T> >
#else
template<>
struct value_wrapper_traits<adl::index_proxy_tag>
#endif
{
    typedef boost::mpl::true_ is_specialized;

    template<class Next>
    static lua_State* interpreter(adl::index_proxy<Next> const& proxy)
    {
        return proxy.interpreter();
    }

    template<class Next>
    static void unwrap(lua_State* interpreter, adl::index_proxy<Next> const& proxy)
    {
        const_cast<adl::index_proxy<Next>&>(proxy).push(interpreter);
    }
};

#ifndef LUABIND_USE_VALUE_WRAPPER_TAG
template<class AccessPolicy>
struct value_wrapper_traits<adl::iterator_proxy<AccessPolicy> >
#else
template<>
struct value_wrapper_traits<adl::iterator_proxy_tag>
#endif
{
    typedef boost::mpl::true_ is_specialized;

    template<class Proxy>
    static lua_State* interpreter(Proxy const& p)
    {
        return p.interpreter();
    }

    template<class Proxy>
    static void unwrap(lua_State* interpreter, Proxy const& p)
    {
        // TODO: Why const_cast?
        const_cast<Proxy&>(p).push(interpreter);
    }
};

namespace adl
{
  class object_init
  {
  protected:
      object_init()
      {}
      
      explicit object_init(from_stack const& stack_reference, boost::mpl::true_)
        : m_handle(stack_reference.interpreter, stack_reference.index)
      {
      }

      template<class ValueWrapper>
      explicit object_init(ValueWrapper const& value_wrapper, boost::mpl::false_)
      {
          lua_State* interpreter = value_wrapper_traits<ValueWrapper>::interpreter(
              value_wrapper
          );

          value_wrapper_traits<ValueWrapper>::unwrap(interpreter, value_wrapper);
          detail::stack_pop pop(interpreter, 1);

          handle(interpreter, -1).swap(m_handle);
      }

      handle m_handle;
  };

  // An object holds a reference to a Lua value residing
  // in the registry.
  class object : public object_interface<object>
  {
      struct safe_bool_type {};
  public:
      object()
      {}

      explicit object(handle const& other)
        : m_handle(other)
      {}

      explicit object(from_stack const& stack_reference)
        : m_handle(stack_reference.interpreter, stack_reference.index)
      {
      }

      template<class T>
      object(lua_State* interpreter, T const& value)
      {
          detail::push(interpreter, value);
          detail::stack_pop pop(interpreter, 1);
          handle(interpreter, -1).swap(m_handle);
      }

      template<class T, class Policies>
      object(lua_State* interpreter, T const& value, Policies const&)
      {
          detail::push(interpreter, value, Policies());
          detail::stack_pop pop(interpreter, 1);
          handle(interpreter, -1).swap(m_handle);
      }

      void push(lua_State* interpreter) const;
      lua_State* interpreter() const;
      bool is_valid() const;
      operator safe_bool_type*() const;

      template<class T>
      index_proxy<object> operator[](T const& key) const
      {
          return index_proxy<object>(
              *this, m_handle.interpreter(), key
          );
      }

      void swap(object& other)
      {
          m_handle.swap(other.m_handle);
      }

  private:
      handle m_handle;
  };

  inline void object::push(lua_State* interpreter) const
  {
      m_handle.push(interpreter);
  }

  inline lua_State* object::interpreter() const
  {
      return m_handle.interpreter();
  }

  inline bool object::is_valid() const
  {
      return m_handle.interpreter() != 0;
  }

  inline object::operator object::safe_bool_type*() const
  {
      return is_valid()?(safe_bool_type*)1:0;
  }

} // namespace adl

using adl::object;

template<>
struct value_wrapper_traits<object>
{
    typedef boost::mpl::true_ is_specialized;

    static lua_State* interpreter(object const& value)
    {
        return value.interpreter();
    }

    static void unwrap(lua_State* interpreter, object const& value)
    {
        value.push(interpreter);
    }

    static bool check(...)
    {
        return true;
    }
};

template<class Next>
inline void adl::index_proxy<Next>::push(lua_State* interpreter)
{
    assert(interpreter == m_interpreter);

    value_wrapper_traits<Next>::unwrap(m_interpreter, m_next);

    lua_pushvalue(m_interpreter, m_key_index);
    lua_gettable(m_interpreter, -2);
    lua_remove(m_interpreter, -2);
}

template<class Next>
inline adl::index_proxy<Next>::operator object()
{
    detail::stack_pop pop(m_interpreter, 1);
    push(m_interpreter);
    return object(from_stack(m_interpreter, -1));
}

template<class AccessPolicy>
adl::iterator_proxy<AccessPolicy>::operator object()
{
    lua_pushvalue(m_interpreter, m_key_index);
    AccessPolicy::get(m_interpreter, m_table_index);
    detail::stack_pop pop(m_interpreter, 1);
    return object(from_stack(m_interpreter, -1));
}

template<class AccessPolicy>
object detail::basic_iterator<AccessPolicy>::key() const
{
    return object(m_key);
}

namespace detail 
{

  template<
      class T
    , class ValueWrapper
    , class Policies
    , class ErrorPolicy
    , class ReturnType
  >
  ReturnType object_cast_aux(
      ValueWrapper const& value_wrapper
    , T*
    , Policies*
    , ErrorPolicy*
    , ReturnType*
  )
  {
      lua_State* interpreter = value_wrapper_traits<ValueWrapper>::interpreter(
          value_wrapper
      );

#ifndef LUABIND_NO_ERROR_CHECKING
      if (!interpreter) 
          return ErrorPolicy::handle_error(interpreter, LUABIND_TYPEID(void));
#endif

      value_wrapper_traits<ValueWrapper>::unwrap(interpreter, value_wrapper);

      detail::stack_pop pop(interpreter, 1);

      typedef typename detail::find_conversion_policy<
          0
        , Policies
      >::type converter_generator;

      typename mpl::apply_wrap2<converter_generator, T, lua_to_cpp>::type cv;

#ifndef LUABIND_NO_ERROR_CHECKING
      if (cv.match(interpreter, LUABIND_DECORATE_TYPE(T), -1) < 0)
      {
          return ErrorPolicy::handle_error(interpreter, LUABIND_TYPEID(T));
      }
#endif

      return cv.apply(interpreter, LUABIND_DECORATE_TYPE(T), -1);
  }

  template<class T>
  struct throw_error_policy
  {
      static T handle_error(lua_State* interpreter, LUABIND_TYPE_INFO type_info)
      {
#ifndef LUABIND_NO_EXCEPTIONS
          throw cast_failed(interpreter, type_info);
#else
          cast_failed_callback_fun e = get_cast_failed_callback();
          if (e) e(interpreter, type_info);

          assert(0 && "object_cast failed. If you want to handle this error use "
              "luabind::set_error_callback()");
          std::terminate();
#endif
      }
  };

  template<class T>
  struct nothrow_error_policy
  {
      static boost::optional<T> handle_error(lua_State*, LUABIND_TYPE_INFO)
      {
          return boost::optional<T>();
      }
  };

} // namespace detail

template<class T, class ValueWrapper>
T object_cast(ValueWrapper const& value_wrapper)
{
    return detail::object_cast_aux(
        value_wrapper
      , (T*)0
      , (detail::null_type*)0
      , (detail::throw_error_policy<T>*)0
      , (T*)0
    );
}

template<class T, class ValueWrapper, class Policies>
T object_cast(ValueWrapper const& value_wrapper, Policies const&)
{
    return detail::object_cast_aux(
        value_wrapper
      , (T*)0
      , (Policies*)0
      , (detail::throw_error_policy<T>*)0
      , (T*)0
    );
}

template<class T, class ValueWrapper>
boost::optional<T> object_cast_nothrow(ValueWrapper const& value_wrapper)
{
    return detail::object_cast_aux(
        value_wrapper
      , (T*)0
      , (detail::null_type*)0
      , (detail::nothrow_error_policy<T>*)0
      , (boost::optional<T>*)0
    );
}

template<class T, class ValueWrapper, class Policies>
boost::optional<T> object_cast_nothrow(ValueWrapper const& value_wrapper, Policies const&)
{
    return detail::object_cast_aux(
        value_wrapper
      , (T*)0
      , (Policies*)0
      , (detail::nothrow_error_policy<T>*)0
      , (boost::optional<T>*)0
    );
}

namespace detail
{

  template<int Index>
  struct push_args_from_tuple
  {
      template<class H, class T, class Policies>
      inline static void apply(lua_State* L, const boost::tuples::cons<H, T>& x, const Policies& p) 
      {
          convert_to_lua_p<Index>(L, *x.get_head(), p);
          push_args_from_tuple<Index+1>::apply(L, x.get_tail(), p);
      }

      template<class H, class T>
      inline static void apply(lua_State* L, const boost::tuples::cons<H, T>& x) 
      {
          convert_to_lua(L, *x.get_head());
          push_args_from_tuple<Index+1>::apply(L, x.get_tail());
      }

      template<class Policies>
      inline static void apply(lua_State*, const boost::tuples::null_type&, const Policies&) {};

      inline static void apply(lua_State*, const boost::tuples::null_type&) {};
  };

} // namespace detail

namespace adl
{

  template<class ValueWrapper, class Arguments>
  struct call_proxy
  {
      call_proxy(ValueWrapper& value_wrapper, Arguments arguments)
        : value_wrapper(&value_wrapper)
        , arguments(arguments)
      {}

      call_proxy(call_proxy const& other)
        : value_wrapper(other.value_wrapper)
        , arguments(other.arguments)
      {
          other.value_wrapper = 0;
      }

      ~call_proxy()
      {
          if (value_wrapper)
              call((detail::null_type*)0);
      }

      operator object()
      {
          return call((detail::null_type*)0);
      }

      template<class Policies>
      object operator[](Policies const&)
      {
          return call((Policies*)0);
      }

      template<class Policies>
      object call(Policies*)
      {
          lua_State* interpreter = value_wrapper_traits<ValueWrapper>::interpreter(
              *value_wrapper
          );

          value_wrapper_traits<ValueWrapper>::unwrap(
              interpreter
            , *value_wrapper
          );

          value_wrapper = 0;

          detail::push_args_from_tuple<1>::apply(interpreter, arguments, Policies());

          if (detail::pcall(interpreter, boost::tuples::length<Arguments>::value, 1))
          {
#ifndef LUABIND_NO_EXCEPTIONS
              throw luabind::error(interpreter);
#else
              error_callback_fun e = get_error_callback();
              if (e) e(interpreter);

              assert(0 && "the lua function threw an error and exceptions are disabled."
                  "if you want to handle this error use luabind::set_error_callback()");
              std::terminate();
#endif
          }

          detail::stack_pop pop(interpreter, 1);
          return object(from_stack(interpreter, -1));
      }

      mutable ValueWrapper* value_wrapper;
      Arguments arguments;
  };

  template<class Derived>
  call_proxy<Derived, boost::tuples::tuple<> >
  object_interface<Derived>::operator()()
  {
      return call_proxy<Derived, boost::tuples::tuple<> >(
          derived()
        , boost::tuples::tuple<>()
      );
  }

} // namespace adl

inline object newtable(lua_State* interpreter)
{
    lua_newtable(interpreter);
    detail::stack_pop pop(interpreter, 1);
    return object(from_stack(interpreter, -1));
}

inline object globals(lua_State* interpreter)
{
    lua_pushvalue(interpreter, LUA_GLOBALSINDEX);
    detail::stack_pop pop(interpreter, 1);
    return object(from_stack(interpreter, -1));
}

template<class ValueWrapper, class K>
inline object gettable(ValueWrapper const& table, K const& key)
{
    lua_State* interpreter = value_wrapper_traits<ValueWrapper>::interpreter(
        table
    );

    value_wrapper_traits<ValueWrapper>::unwrap(interpreter, table);
    detail::stack_pop pop(interpreter, 2);
    detail::push(interpreter, key);
    lua_gettable(interpreter, -2);
    return object(from_stack(interpreter, -1));
}

template<class ValueWrapper, class K, class T>
inline void settable(ValueWrapper const& table, K const& key, T const& value)
{
    lua_State* interpreter = value_wrapper_traits<ValueWrapper>::interpreter(
        table
    );

    // TODO: Exception safe?
    
    value_wrapper_traits<ValueWrapper>::unwrap(interpreter, table);
    detail::stack_pop pop(interpreter, 1);
    detail::push(interpreter, key);
    detail::push(interpreter, value);
    lua_settable(interpreter, -3);
}

template<class ValueWrapper, class K>
inline object rawget(ValueWrapper const& table, K const& key)
{
    lua_State* interpreter = value_wrapper_traits<ValueWrapper>::interpreter(
        table
    );

    value_wrapper_traits<ValueWrapper>::unwrap(interpreter, table);
    detail::stack_pop pop(interpreter, 2);
    detail::push(interpreter, key);
    lua_rawget(interpreter, -2);
    return object(from_stack(interpreter, -1));
}

template<class ValueWrapper, class K, class T>
inline void rawset(ValueWrapper const& table, K const& key, T const& value)
{
    lua_State* interpreter = value_wrapper_traits<ValueWrapper>::interpreter(
        table
    );

    // TODO: Exception safe?
    
    value_wrapper_traits<ValueWrapper>::unwrap(interpreter, table);
    detail::stack_pop pop(interpreter, 1);
    detail::push(interpreter, key);
    detail::push(interpreter, value);
    lua_rawset(interpreter, -3);
}

template<class ValueWrapper>
inline int type(ValueWrapper const& value)
{
    lua_State* interpreter = value_wrapper_traits<ValueWrapper>::interpreter(
        value
    );

    value_wrapper_traits<ValueWrapper>::unwrap(interpreter, value);
    detail::stack_pop pop(interpreter, 1);
    return lua_type(interpreter, -1);
}

} // namespace luabind

#endif // LUABIND_OBJECT_050419_HPP

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?