/* Luwra * Minimal-overhead Lua wrapper for C++ * * Copyright (C) 2015, Ole Krüger */ #ifndef LUWRA_STACK_H_ #define LUWRA_STACK_H_ #include "common.hpp" #include "types.hpp" #include #include #include #include LUWRA_NS_BEGIN namespace internal { template struct Layout { static_assert( sizeof(T) == -1, "Parameter to Layout is not a valid signature" ); }; template struct Layout { using ReturnType = R; template static inline R direct(State*, int, F&& hook, A&&... args) { return hook( std::forward(args)... ); } }; template struct Layout { using ReturnType = R; template static inline R direct(State* state, int n, F&& hook, A&&... args) { return hook( std::forward(args)..., Value::read(state, n) ); } }; template struct Layout { using ReturnType = R; template static inline R direct(State* state, int n, F&& hook, A&&... args) { return Layout::direct( state, n + 1, std::forward(hook), std::forward(args)..., Value::read(state, n) ); } }; } /** * Retrieve values from the stack and invoke a `Callable` with them. * * \tparam S Signature in the form of `R(A...)` where `A` is a sequence of types, which shall be * retrieved from the stack, and `R` the return type of `hook` * \tparam F An instance of `Callable` which accepts parameters `X..., A...` and returns `R` * (this parameter should be inferable and can be omitted) * \tparam X Extra argument types * * \param state Lua state instance * \param pos Index of the first value * \param hook Callable value * \param args Extra arguments which shall be be passed to `hook` before the stack values * * \returns Result of calling `hook` */ template static inline typename internal::Layout::ReturnType direct(State* state, int pos, F&& hook, X&&... args) { return internal::Layout::direct( state, pos, std::forward(hook), std::forward(args)... ); } /** * Same as `direct(state, 1, hook)`. */ template static inline typename internal::Layout::ReturnType direct(State* state, F&& hook, A&&... args) { return internal::Layout::direct( state, 1, std::forward(hook), std::forward(args)... ); } /** * Synonym for [direct](@ref direct) with a function pointer which lets you omit all template parameters. * The stack layout will be inferred using the signature of the given function pointer. */ template static inline R apply(State* state, int pos, R (* fun)(A...)) { return direct(state, pos, fun); } /** * Same as `apply(state, 1, fun)`. */ template static inline R apply(State* state, R (* fun)(A...)) { return apply(state, 1, fun); } /** * Synonym for [direct](@ref direct) with a function object which lets you omit all template parameters. * The stack layout will be inferred using the template parameter to your `std::function` object. */ template static inline R apply(State* state, int pos, const std::function& fun) { return internal::Layout::direct(state, pos, fun); } /** * Same as `apply(state, 1, fun)`. */ template static inline R apply(State* state, const std::function& fun) { return apply(state, 1, fun); } namespace internal { template struct LayoutMapper { static_assert( sizeof(T) == -1, "Parameter to LayoutMapper is not a valid signature" ); }; template struct LayoutMapper { template static inline size_t map(State* state, int n, F&& hook, X&&... args) { direct( state, n, std::forward(hook), std::forward(args)... ); return 0; } }; template struct LayoutMapper { template static inline size_t map(State* state, int n, F&& hook, X&&... args) { return push( state, direct( state, n, std::forward(hook), std::forward(args)... ) ); } }; } /** * Similiar to [direct](@ref direct) but pushes the result of the given `Callable` onto the stack. * \returns Number of values pushed */ template static inline size_t map(State* state, int pos, F&& hook, A&&... args) { return internal::LayoutMapper::map( state, pos, std::forward(hook), std::forward(args)... ); } /** * Same as `map(state, 1, hook)`. */ template static inline size_t map(State* state, F&& hook, A&&... args) { return internal::LayoutMapper::map( state, 1, std::forward(hook), std::forward(args)... ); } LUWRA_NS_END #endif