Merge branch 'order_3pl' into process_pipes

This commit is contained in:
2025-08-13 11:26:56 +03:00
37 changed files with 36 additions and 20 deletions

View File

@@ -1,55 +0,0 @@
// https://github.com/vinniefalco/LuaBridge
//
// Copyright 2018, Dmitry Tarakanov
// SPDX-License-Identifier: MIT
#pragma once
#include <LuaBridge/detail/Stack.h>
#include <list>
namespace luabridge {
template <class T>
struct Stack <std::list <T> >
{
static void push (lua_State* L, std::list <T> const& list)
{
lua_createtable (L, static_cast <int> (list.size ()), 0);
typename std::list <T>::const_iterator item = list.begin ();
for (std::size_t i = 1; i <= list.size (); ++i)
{
lua_pushinteger (L, static_cast <lua_Integer> (i));
Stack <T>::push (L, *item);
lua_settable (L, -3);
++item;
}
}
static std::list <T> get (lua_State* L, int index)
{
if (!lua_istable (L, index))
{
luaL_error (L, "#%d argument must be a table", index);
}
std::list <T> list;
int const absindex = lua_absindex (L, index);
lua_pushnil (L);
while (lua_next (L, absindex) != 0)
{
list.push_back (Stack <T>::get (L, -1));
lua_pop (L, 1);
}
return list;
}
static bool isInstance (lua_State* L, int index)
{
return lua_istable (L, index);
}
};
} // namespace luabridge

View File

@@ -1,59 +0,0 @@
//------------------------------------------------------------------------------
/*
https://github.com/vinniefalco/LuaBridge
Copyright 2019, Dmitry Tarakanov
Copyright 2012, Vinnie Falco <vinnie.falco@gmail.com>
Copyright 2007, Nathan Reed
License: The MIT License (http://www.opensource.org/licenses/mit-license.php)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
//==============================================================================
#pragma once
// All #include dependencies are listed here
// instead of in the individual header files.
//
#define LUABRIDGE_MAJOR_VERSION 2
#define LUABRIDGE_MINOR_VERSION 3
#define LUABRIDGE_VERSION 203
#ifndef LUA_VERSION_NUM
#error "Lua headers must be included prior to LuaBridge ones"
#endif
#include <LuaBridge/detail/LuaHelpers.h>
#include <LuaBridge/detail/TypeTraits.h>
#include <LuaBridge/detail/TypeList.h>
#include <LuaBridge/detail/FuncTraits.h>
#include <LuaBridge/detail/Constructor.h>
#include <LuaBridge/detail/ClassInfo.h>
#include <LuaBridge/detail/LuaException.h>
#include <LuaBridge/detail/LuaRef.h>
#include <LuaBridge/detail/Iterator.h>
#include <LuaBridge/detail/Userdata.h>
#include <LuaBridge/detail/CFunctions.h>
#include <LuaBridge/detail/Security.h>
#include <LuaBridge/detail/Stack.h>
#include <LuaBridge/detail/Namespace.h>

View File

@@ -1,56 +0,0 @@
// https://github.com/vinniefalco/LuaBridge
//
// Copyright 2018, Dmitry Tarakanov
// SPDX-License-Identifier: MIT
#pragma once
#include <LuaBridge/detail/Stack.h>
#include <LuaBridge/detail/dump.h>
#include <map>
namespace luabridge {
template <class K, class V>
struct Stack <std::map <K, V> >
{
typedef std::map <K, V> Map;
static void push (lua_State* L, const Map& map)
{
lua_createtable (L, 0, static_cast <int> (map.size ()));
typedef typename Map::const_iterator ConstIter;
for (ConstIter i = map.begin (); i != map.end (); ++i)
{
Stack <K>::push (L, i->first);
Stack <V>::push (L, i->second);
lua_settable (L, -3);
}
}
static Map get (lua_State* L, int index)
{
if (!lua_istable (L, index))
{
luaL_error (L, "#%d argument must be a table", index);
}
Map map;
int const absindex = lua_absindex (L, index);
lua_pushnil (L);
while (lua_next (L, absindex) != 0)
{
map.emplace (Stack <K>::get (L, -2), Stack <V>::get (L, -1));
lua_pop (L, 1);
}
return map;
}
static bool isInstance (lua_State* L, int index)
{
return lua_istable (L, index);
}
};
} // namespace luabridge

View File

@@ -1,356 +0,0 @@
//==============================================================================
/*
https://github.com/vinniefalco/LuaBridge
Copyright 2012, Vinnie Falco <vinnie.falco@gmail.com>
Copyright 2004-11 by Raw Material Software Ltd.
This is a derivative work used by permission from part of
JUCE, available at http://www.rawaterialsoftware.com
License: The MIT License (http://www.opensource.org/licenses/mit-license.php)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
This file incorporates work covered by the following copyright and
permission notice:
This file is part of the JUCE library - "Jules' Utility Class Extensions"
Copyright 2004-11 by Raw Material Software Ltd.
*/
//==============================================================================
#pragma once
//#define LUABRIDGE_COMPILER_SUPPORTS_MOVE_SEMANTICS 1
#include <LuaBridge/detail/TypeTraits.h>
#include <cassert>
namespace luabridge {
//==============================================================================
/**
Adds reference-counting to an object.
To add reference-counting to a class, derive it from this class, and
use the RefCountedObjectPtr class to point to it.
e.g. @code
class MyClass : public RefCountedObjectType
{
void foo();
// This is a neat way of declaring a typedef for a pointer class,
// rather than typing out the full templated name each time..
typedef RefCountedObjectPtr<MyClass> Ptr;
};
MyClass::Ptr p = new MyClass();
MyClass::Ptr p2 = p;
p = 0;
p2->foo();
@endcode
Once a new RefCountedObjectType has been assigned to a pointer, be
careful not to delete the object manually.
*/
template <class CounterType>
class RefCountedObjectType
{
public:
//==============================================================================
/** Increments the object's reference count.
This is done automatically by the smart pointer, but is public just
in case it's needed for nefarious purposes.
*/
inline void incReferenceCount() const
{
++refCount;
}
/** Decreases the object's reference count.
If the count gets to zero, the object will be deleted.
*/
inline void decReferenceCount() const
{
assert (getReferenceCount() > 0);
if (--refCount == 0)
delete this;
}
/** Returns the object's current reference count. */
inline int getReferenceCount() const
{
return static_cast <int> (refCount);
}
protected:
//==============================================================================
/** Creates the reference-counted object (with an initial ref count of zero). */
RefCountedObjectType() : refCount ()
{
}
/** Destructor. */
virtual ~RefCountedObjectType()
{
// it's dangerous to delete an object that's still referenced by something else!
assert (getReferenceCount() == 0);
}
private:
//==============================================================================
CounterType mutable refCount;
};
//==============================================================================
/** Non thread-safe reference counted object.
This creates a RefCountedObjectType that uses a non-atomic integer
as the counter.
*/
typedef RefCountedObjectType <int> RefCountedObject;
//==============================================================================
/**
A smart-pointer class which points to a reference-counted object.
The template parameter specifies the class of the object you want to point
to - the easiest way to make a class reference-countable is to simply make
it inherit from RefCountedObjectType, but if you need to, you could roll
your own reference-countable class by implementing a pair of methods called
incReferenceCount() and decReferenceCount().
When using this class, you'll probably want to create a typedef to
abbreviate the full templated name - e.g.
@code
typedef RefCountedObjectPtr <MyClass> MyClassPtr;
@endcode
*/
template <class ReferenceCountedObjectClass>
class RefCountedObjectPtr
{
public:
/** The class being referenced by this pointer. */
typedef ReferenceCountedObjectClass ReferencedType;
//==============================================================================
/** Creates a pointer to a null object. */
inline RefCountedObjectPtr() : referencedObject (0)
{
}
/** Creates a pointer to an object.
This will increment the object's reference-count if it is non-null.
*/
inline RefCountedObjectPtr (ReferenceCountedObjectClass* const refCountedObject)
: referencedObject (refCountedObject)
{
if (refCountedObject != 0)
refCountedObject->incReferenceCount();
}
/** Copies another pointer.
This will increment the object's reference-count (if it is non-null).
*/
inline RefCountedObjectPtr (const RefCountedObjectPtr& other)
: referencedObject (other.referencedObject)
{
if (referencedObject != 0)
referencedObject->incReferenceCount();
}
#if LUABRIDGE_COMPILER_SUPPORTS_MOVE_SEMANTICS
/** Takes-over the object from another pointer. */
inline RefCountedObjectPtr (RefCountedObjectPtr&& other)
: referencedObject (other.referencedObject)
{
other.referencedObject = 0;
}
#endif
/** Copies another pointer.
This will increment the object's reference-count (if it is non-null).
*/
template <class DerivedClass>
inline RefCountedObjectPtr (const RefCountedObjectPtr<DerivedClass>& other)
: referencedObject (static_cast <ReferenceCountedObjectClass*> (other.getObject()))
{
if (referencedObject != 0)
referencedObject->incReferenceCount();
}
/** Changes this pointer to point at a different object.
The reference count of the old object is decremented, and it might be
deleted if it hits zero. The new object's count is incremented.
*/
RefCountedObjectPtr& operator= (const RefCountedObjectPtr& other)
{
return operator= (other.referencedObject);
}
/** Changes this pointer to point at a different object.
The reference count of the old object is decremented, and it might be
deleted if it hits zero. The new object's count is incremented.
*/
template <class DerivedClass>
RefCountedObjectPtr& operator= (const RefCountedObjectPtr<DerivedClass>& other)
{
return operator= (static_cast <ReferenceCountedObjectClass*> (other.getObject()));
}
#if LUABRIDGE_COMPILER_SUPPORTS_MOVE_SEMANTICS
/** Takes-over the object from another pointer. */
RefCountedObjectPtr& operator= (RefCountedObjectPtr&& other)
{
std::swap (referencedObject, other.referencedObject);
return *this;
}
#endif
/** Changes this pointer to point at a different object.
The reference count of the old object is decremented, and it might be
deleted if it hits zero. The new object's count is incremented.
*/
RefCountedObjectPtr& operator= (ReferenceCountedObjectClass* const newObject)
{
if (referencedObject != newObject)
{
if (newObject != 0)
newObject->incReferenceCount();
ReferenceCountedObjectClass* const oldObject = referencedObject;
referencedObject = newObject;
if (oldObject != 0)
oldObject->decReferenceCount();
}
return *this;
}
/** Destructor.
This will decrement the object's reference-count, and may delete it if it
gets to zero.
*/
inline ~RefCountedObjectPtr()
{
if (referencedObject != 0)
referencedObject->decReferenceCount();
}
/** Returns the object that this pointer references.
The pointer returned may be zero, of course.
*/
inline operator ReferenceCountedObjectClass*() const
{
return referencedObject;
}
// the -> operator is called on the referenced object
inline ReferenceCountedObjectClass* operator->() const
{
return referencedObject;
}
/** Returns the object that this pointer references.
The pointer returned may be zero, of course.
*/
inline ReferenceCountedObjectClass* getObject() const
{
return referencedObject;
}
private:
//==============================================================================
ReferenceCountedObjectClass* referencedObject;
};
/** Compares two ReferenceCountedObjectPointers. */
template <class ReferenceCountedObjectClass>
bool operator== (const RefCountedObjectPtr<ReferenceCountedObjectClass>& object1, ReferenceCountedObjectClass* const object2)
{
return object1.getObject() == object2;
}
/** Compares two ReferenceCountedObjectPointers. */
template <class ReferenceCountedObjectClass>
bool operator== (const RefCountedObjectPtr<ReferenceCountedObjectClass>& object1, const RefCountedObjectPtr<ReferenceCountedObjectClass>& object2)
{
return object1.getObject() == object2.getObject();
}
/** Compares two ReferenceCountedObjectPointers. */
template <class ReferenceCountedObjectClass>
bool operator== (ReferenceCountedObjectClass* object1, RefCountedObjectPtr<ReferenceCountedObjectClass>& object2)
{
return object1 == object2.getObject();
}
/** Compares two ReferenceCountedObjectPointers. */
template <class ReferenceCountedObjectClass>
bool operator!= (const RefCountedObjectPtr<ReferenceCountedObjectClass>& object1, const ReferenceCountedObjectClass* object2)
{
return object1.getObject() != object2;
}
/** Compares two ReferenceCountedObjectPointers. */
template <class ReferenceCountedObjectClass>
bool operator!= (const RefCountedObjectPtr<ReferenceCountedObjectClass>& object1, RefCountedObjectPtr<ReferenceCountedObjectClass>& object2)
{
return object1.getObject() != object2.getObject();
}
/** Compares two ReferenceCountedObjectPointers. */
template <class ReferenceCountedObjectClass>
bool operator!= (ReferenceCountedObjectClass* object1, RefCountedObjectPtr<ReferenceCountedObjectClass>& object2)
{
return object1 != object2.getObject();
}
//==============================================================================
template <class T>
struct ContainerTraits <RefCountedObjectPtr <T> >
{
typedef T Type;
static T* get (RefCountedObjectPtr <T> const& c)
{
return c.getObject ();
}
};
//==============================================================================
} // namespace luabridge

View File

@@ -1,244 +0,0 @@
//==============================================================================
/*
https://github.com/vinniefalco/LuaBridge
Copyright 2019, Dmitry Tarakanov
Copyright 2012, Vinnie Falco <vinnie.falco@gmail.com>
Copyright 2007, Nathan Reed
License: The MIT License (http://www.opensource.org/licenses/mit-license.php)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
//==============================================================================
#pragma once
#include <unordered_map>
#include "RefCountedObject.h"
namespace luabridge {
//==============================================================================
/**
Support for our RefCountedPtr.
*/
struct RefCountedPtrBase
{
// Declaration of container for the refcounts
typedef std::unordered_map <const void *, int> RefCountsType;
protected:
RefCountsType& getRefCounts () const
{
static RefCountsType refcounts;
return refcounts ;
}
};
//==============================================================================
/**
A reference counted smart pointer.
The api is compatible with boost::RefCountedPtr and std::RefCountedPtr, in the
sense that it implements a strict subset of the functionality.
This implementation uses a hash table to look up the reference count
associated with a particular pointer.
@tparam T The class type.
@todo Decompose RefCountedPtr using a policy. At a minimum, the underlying
reference count should be policy based (to support atomic operations)
and the delete behavior should be policy based (to support custom
disposal methods).
@todo Provide an intrusive version of RefCountedPtr.
*/
template <class T>
class RefCountedPtr : private RefCountedPtrBase
{
public:
template <typename Other>
struct rebind
{
typedef RefCountedPtr <Other> other;
};
/** Construct as nullptr or from existing pointer to T.
@param p The optional, existing pointer to assign from.
*/
RefCountedPtr (T* p = 0) : m_p (p)
{
++getRefCounts () [m_p];
}
/** Construct from another RefCountedPtr.
@param rhs The RefCountedPtr to assign from.
*/
RefCountedPtr (RefCountedPtr <T> const& rhs) : m_p (rhs.get())
{
++getRefCounts () [m_p];
}
/** Construct from a RefCountedPtr of a different type.
@invariant A pointer to U must be convertible to a pointer to T.
@param rhs The RefCountedPtr to assign from.
@tparam U The other object type.
*/
template <typename U>
RefCountedPtr (RefCountedPtr <U> const& rhs) : m_p (static_cast <T*> (rhs.get()))
{
++getRefCounts () [m_p];
}
/** Release the object.
If there are no more references then the object is deleted.
*/
~RefCountedPtr ()
{
reset();
}
/** Assign from another RefCountedPtr.
@param rhs The RefCountedPtr to assign from.
@return A reference to the RefCountedPtr.
*/
RefCountedPtr <T>& operator= (RefCountedPtr <T> const& rhs)
{
if (m_p != rhs.m_p)
{
reset ();
m_p = rhs.m_p;
++getRefCounts () [m_p];
}
return *this;
}
/** Assign from another RefCountedPtr of a different type.
@note A pointer to U must be convertible to a pointer to T.
@tparam U The other object type.
@param rhs The other RefCountedPtr to assign from.
@return A reference to the RefCountedPtr.
*/
template <typename U>
RefCountedPtr <T>& operator= (RefCountedPtr <U> const& rhs)
{
reset ();
m_p = static_cast <T*> (rhs.get());
++getRefCounts () [m_p];
return *this;
}
/** Retrieve the raw pointer.
@return A pointer to the object.
*/
T* get () const
{
return m_p;
}
/** Retrieve the raw pointer.
@return A pointer to the object.
*/
T* operator* () const
{
return m_p;
}
/** Retrieve the raw pointer.
@return A pointer to the object.
*/
T* operator-> () const
{
return m_p;
}
/** Determine the number of references.
@note This is not thread-safe.
@return The number of active references.
*/
long use_count () const
{
return getRefCounts () [m_p];
}
/** Release the pointer.
The reference count is decremented. If the reference count reaches
zero, the object is deleted.
*/
void reset ()
{
if (m_p != 0)
{
if (--getRefCounts () [m_p] <= 0)
delete m_p;
m_p = 0;
}
}
private:
T* m_p;
};
template <class T>
bool operator== (const RefCountedPtr <T>& lhs, const RefCountedPtr <T>& rhs)
{
return lhs.get () == rhs.get ();
}
template <class T>
bool operator!= (const RefCountedPtr <T>& lhs, const RefCountedPtr <T>& rhs)
{
return lhs.get() != rhs.get();
}
//==============================================================================
// forward declaration
template <class T>
struct ContainerTraits;
template <class T>
struct ContainerTraits <RefCountedPtr <T> >
{
typedef T Type;
static T* get (RefCountedPtr <T> const& c)
{
return c.get ();
}
};
} // namespace luabridge

View File

@@ -1,55 +0,0 @@
// https://github.com/vinniefalco/LuaBridge
//
// Copyright 2019, Dmitry Tarakanov
// SPDX-License-Identifier: MIT
#pragma once
#include <LuaBridge/detail/Stack.h>
#include <unordered_map>
namespace luabridge {
template <class K, class V>
struct Stack <std::unordered_map <K, V>>
{
typedef std::unordered_map <K, V> Map;
static void push (lua_State* L, const Map& map)
{
lua_createtable (L, 0, static_cast <int> (map.size ()));
typedef typename Map::const_iterator ConstIter;
for (ConstIter i = map.begin (); i != map.end (); ++i)
{
Stack <K>::push (L, i->first);
Stack <V>::push (L, i->second);
lua_settable (L, -3);
}
}
static Map get (lua_State* L, int index)
{
if (!lua_istable (L, index))
{
luaL_error (L, "#%d argument must be a table", index);
}
Map map;
int const absindex = lua_absindex (L, index);
lua_pushnil (L);
while (lua_next (L, absindex) != 0)
{
map.emplace (Stack <K>::get (L, -2), Stack <V>::get (L, -1));
lua_pop (L, 1);
}
return map;
}
static bool isInstance (lua_State* L, int index)
{
return lua_istable (L, index);
}
};
} // namespace luabridge

View File

@@ -1,54 +0,0 @@
// https://github.com/vinniefalco/LuaBridge
//
// Copyright 2018, Dmitry Tarakanov
// SPDX-License-Identifier: MIT
#pragma once
#include <LuaBridge/detail/Stack.h>
#include <vector>
namespace luabridge {
template <class T>
struct Stack <std::vector <T> >
{
static void push (lua_State* L, std::vector <T> const& vector)
{
lua_createtable (L, static_cast <int> (vector.size ()), 0);
for (std::size_t i = 0; i < vector.size (); ++i)
{
lua_pushinteger (L, static_cast <lua_Integer> (i + 1));
Stack <T>::push (L, vector [i]);
lua_settable (L, -3);
}
}
static std::vector <T> get (lua_State* L, int index)
{
if (!lua_istable (L, index))
{
luaL_error (L, "#%d argument must be a table", index);
}
std::vector <T> vector;
vector.reserve (static_cast <std::size_t> (get_length (L, index)));
int const absindex = lua_absindex (L, index);
lua_pushnil (L);
while (lua_next (L, absindex) != 0)
{
vector.push_back (Stack <T>::get (L, -1));
lua_pop (L, 1);
}
return vector;
}
static bool isInstance (lua_State* L, int index)
{
return lua_istable (L, index);
}
};
} // namespace luabridge

View File

@@ -1,495 +0,0 @@
//------------------------------------------------------------------------------
/*
https://github.com/vinniefalco/LuaBridge
Copyright 2019, Dmitry Tarakanov
Copyright 2012, Vinnie Falco <vinnie.falco@gmail.com>
License: The MIT License (http://www.opensource.org/licenses/mit-license.php)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
//==============================================================================
#pragma once
#include <LuaBridge/detail/Config.h>
#include <LuaBridge/detail/FuncTraits.h>
#include <string>
namespace luabridge {
// We use a structure so we can define everything in the header.
//
struct CFunc
{
static void addGetter (lua_State* L, const char* name, int tableIndex)
{
assert (lua_istable (L, tableIndex));
assert (lua_iscfunction (L, -1)); // Stack: getter
lua_rawgetp (L, tableIndex, getPropgetKey ()); // Stack: getter, propget table (pg)
lua_pushvalue (L, -2); // Stack: getter, pg, getter
rawsetfield (L, -2, name); // Stack: getter, pg
lua_pop (L, 2); // Stack: -
}
static void addSetter (lua_State* L, const char* name, int tableIndex)
{
assert (lua_istable (L, tableIndex));
assert (lua_iscfunction (L, -1)); // Stack: setter
lua_rawgetp (L, tableIndex, getPropsetKey ()); // Stack: setter, propset table (ps)
lua_pushvalue (L, -2); // Stack: setter, ps, setter
rawsetfield (L, -2, name); // Stack: setter, ps
lua_pop (L, 2); // Stack: -
}
//----------------------------------------------------------------------------
/**
__index metamethod for a namespace or class static and non-static members.
Retrieves functions from metatables and properties from propget tables.
Looks through the class hierarchy if inheritance is present.
*/
static int indexMetaMethod (lua_State* L)
{
assert (lua_istable (L, 1) || lua_isuserdata (L, 1)); // Stack (further not shown): table | userdata, name
lua_getmetatable (L, 1); // Stack: class/const table (mt)
assert (lua_istable (L, -1));
for (;;)
{
lua_pushvalue (L, 2); // Stack: mt, field name
lua_rawget (L, -2); // Stack: mt, field | nil
if (lua_iscfunction (L, -1)) // Stack: mt, field
{
lua_remove (L, -2); // Stack: field
return 1;
}
assert (lua_isnil (L, -1)); // Stack: mt, nil
lua_pop (L, 1); // Stack: mt
lua_rawgetp (L, -1, getPropgetKey ()); // Stack: mt, propget table (pg)
assert (lua_istable (L, -1));
lua_pushvalue (L, 2); // Stack: mt, pg, field name
lua_rawget (L, -2); // Stack: mt, pg, getter | nil
lua_remove (L, -2); // Stack: mt, getter | nil
if (lua_iscfunction (L, -1)) // Stack: mt, getter
{
lua_remove (L, -2); // Stack: getter
lua_pushvalue (L, 1); // Stack: getter, table | userdata
lua_call (L, 1, 1); // Stack: value
return 1;
}
assert (lua_isnil (L, -1)); // Stack: mt, nil
lua_pop (L, 1); // Stack: mt
// It may mean that the field may be in const table and it's constness violation.
// Don't check that, just return nil
// Repeat the lookup in the parent metafield,
// or return nil if the field doesn't exist.
lua_rawgetp (L, -1, getParentKey ()); // Stack: mt, parent mt | nil
if (lua_isnil (L, -1)) // Stack: mt, nil
{
lua_remove (L, -2); // Stack: nil
return 1;
}
// Removethe metatable and repeat the search in the parent one.
assert (lua_istable (L, -1)); // Stack: mt, parent mt
lua_remove (L, -2); // Stack: parent mt
}
// no return
}
//----------------------------------------------------------------------------
/**
__newindex metamethod for namespace or class static members.
Retrieves properties from propset tables.
*/
static int newindexStaticMetaMethod (lua_State* L)
{
return newindexMetaMethod (L, false);
}
//----------------------------------------------------------------------------
/**
__newindex metamethod for non-static members.
Retrieves properties from propset tables.
*/
static int newindexObjectMetaMethod (lua_State* L)
{
return newindexMetaMethod (L, true);
}
static int newindexMetaMethod (lua_State* L, bool pushSelf)
{
assert (lua_istable (L, 1) || lua_isuserdata (L, 1)); // Stack (further not shown): table | userdata, name, new value
lua_getmetatable (L, 1); // Stack: metatable (mt)
assert (lua_istable (L, -1));
for (;;)
{
lua_rawgetp (L, -1, getPropsetKey ()); // Stack: mt, propset table (ps) | nil
if (lua_isnil (L, -1)) // Stack: mt, nil
{
lua_pop (L, 2); // Stack: -
return luaL_error (L, "No member named '%s'", lua_tostring (L, 2));
}
assert (lua_istable (L, -1));
lua_pushvalue (L, 2); // Stack: mt, ps, field name
lua_rawget (L, -2); // Stack: mt, ps, setter | nil
lua_remove (L, -2); // Stack: mt, setter | nil
if (lua_iscfunction (L, -1)) // Stack: mt, setter
{
lua_remove (L, -2); // Stack: setter
if (pushSelf)
{
lua_pushvalue (L, 1); // Stack: setter, table | userdata
}
lua_pushvalue (L, 3); // Stack: setter, table | userdata, new value
lua_call (L, pushSelf ? 2 : 1, 0); // Stack: -
return 0;
}
assert (lua_isnil (L, -1)); // Stack: mt, nil
lua_pop (L, 1); // Stack: mt
lua_rawgetp (L, -1, getParentKey ()); // Stack: mt, parent mt | nil
if (lua_isnil (L, -1)) // Stack: mt, nil
{
lua_pop (L, 1); // Stack: -
return luaL_error (L, "No writable member '%s'", lua_tostring (L, 2));
}
assert (lua_istable (L, -1)); // Stack: mt, parent mt
lua_remove (L, -2); // Stack: parent mt
// Repeat the search in the parent
}
// no return
}
//----------------------------------------------------------------------------
/**
lua_CFunction to report an error writing to a read-only value.
The name of the variable is in the first upvalue.
*/
static int readOnlyError (lua_State* L)
{
std::string s;
s = s + "'" + lua_tostring (L, lua_upvalueindex (1)) + "' is read-only";
return luaL_error (L, s.c_str ());
}
//----------------------------------------------------------------------------
/**
lua_CFunction to get a variable.
This is used for global variables or class static data members.
The pointer to the data is in the first upvalue.
*/
template <class T>
static int getVariable (lua_State* L)
{
assert (lua_islightuserdata (L, lua_upvalueindex (1)));
T const* ptr = static_cast <T const*> (lua_touserdata (L, lua_upvalueindex (1)));
assert (ptr != 0);
Stack <T>::push (L, *ptr);
return 1;
}
//----------------------------------------------------------------------------
/**
lua_CFunction to set a variable.
This is used for global variables or class static data members.
The pointer to the data is in the first upvalue.
*/
template <class T>
static int setVariable (lua_State* L)
{
assert (lua_islightuserdata (L, lua_upvalueindex (1)));
T* ptr = static_cast <T*> (lua_touserdata (L, lua_upvalueindex (1)));
assert (ptr != 0);
*ptr = Stack <T>::get (L, 1);
return 0;
}
//----------------------------------------------------------------------------
/**
lua_CFunction to call a function with a return value.
This is used for global functions, global properties, class static methods,
and class static properties.
The function pointer (lightuserdata) in the first upvalue.
*/
template <class FnPtr>
struct Call
{
typedef typename FuncTraits <FnPtr>::Params Params;
typedef typename FuncTraits <FnPtr>::ReturnType ReturnType;
static int f (lua_State* L)
{
assert (lua_islightuserdata (L, lua_upvalueindex (1)));
FnPtr fnptr = reinterpret_cast <FnPtr> (lua_touserdata (L, lua_upvalueindex (1)));
assert (fnptr != 0);
return Invoke <ReturnType, Params, 1>::run (L, fnptr);
}
};
//----------------------------------------------------------------------------
/**
lua_CFunction to call a class member function with a return value.
The member function pointer is in the first upvalue.
The class userdata object is at the top of the Lua stack.
*/
template <class MemFnPtr>
struct CallMember
{
typedef typename FuncTraits <MemFnPtr>::ClassType T;
typedef typename FuncTraits <MemFnPtr>::Params Params;
typedef typename FuncTraits <MemFnPtr>::ReturnType ReturnType;
static int f (lua_State* L)
{
assert (isfulluserdata (L, lua_upvalueindex (1)));
T* const t = Userdata::get <T> (L, 1, false);
MemFnPtr const& fnptr = *static_cast <MemFnPtr const*> (lua_touserdata (L, lua_upvalueindex (1)));
assert (fnptr != 0);
return Invoke <ReturnType, Params, 2>::run (L, t, fnptr);
}
};
template <class MemFnPtr>
struct CallConstMember
{
typedef typename FuncTraits <MemFnPtr>::ClassType T;
typedef typename FuncTraits <MemFnPtr>::Params Params;
typedef typename FuncTraits <MemFnPtr>::ReturnType ReturnType;
static int f (lua_State* L)
{
assert (isfulluserdata (L, lua_upvalueindex (1)));
T const* const t = Userdata::get <T> (L, 1, true);
MemFnPtr const& fnptr = *static_cast <MemFnPtr const*> (lua_touserdata (L, lua_upvalueindex (1)));
assert (fnptr != 0);
return Invoke <ReturnType, Params, 2>::run (L, t, fnptr);
}
};
//--------------------------------------------------------------------------
/**
lua_CFunction to call a class member lua_CFunction.
The member function pointer is in the first upvalue.
The object userdata ('this') value is at top ot the Lua stack.
*/
template <class T>
struct CallMemberCFunction
{
static int f (lua_State* L)
{
assert (isfulluserdata (L, lua_upvalueindex (1)));
typedef int (T::*MFP) (lua_State* L);
T* const t = Userdata::get <T> (L, 1, false);
MFP const& fnptr = *static_cast <MFP const*> (lua_touserdata (L, lua_upvalueindex (1)));
assert (fnptr != 0);
return (t->*fnptr) (L);
}
};
template <class T>
struct CallConstMemberCFunction
{
static int f (lua_State* L)
{
assert (isfulluserdata (L, lua_upvalueindex (1)));
typedef int (T::*MFP) (lua_State* L);
T const* const t = Userdata::get <T> (L, 1, true);
MFP const& fnptr = *static_cast <MFP const*> (lua_touserdata (L, lua_upvalueindex (1)));
assert (fnptr != 0);
return (t->*fnptr) (L);
}
};
#ifdef LUABRIDGE_CXX11
//--------------------------------------------------------------------------
/**
lua_CFunction to call on a object.
The proxy function pointer (lightuserdata) is in the first upvalue.
The class userdata object is at the top of the Lua stack.
*/
template <class FnPtr>
struct CallProxyFunction
{
using Params = typename FuncTraits <FnPtr>::Params;
using ReturnType = typename FuncTraits <FnPtr>::ReturnType;
static int f (lua_State* L)
{
assert (lua_islightuserdata (L, lua_upvalueindex (1)));
auto fnptr = reinterpret_cast <FnPtr> (lua_touserdata (L, lua_upvalueindex (1)));
assert (fnptr != 0);
return Invoke <ReturnType, Params, 1>::run (L, fnptr);
}
};
template <class Functor>
struct CallProxyFunctor
{
using Params = typename FuncTraits <Functor>::Params;
using ReturnType = typename FuncTraits <Functor>::ReturnType;
static int f (lua_State* L)
{
assert (isfulluserdata (L, lua_upvalueindex (1)));
Functor& fn = *static_cast <Functor*> (lua_touserdata (L, lua_upvalueindex (1)));
return Invoke <ReturnType, Params, 1>::run (L, fn);
}
};
#endif
//--------------------------------------------------------------------------
// SFINAE Helpers
template <class MemFnPtr, bool isConst>
struct CallMemberFunctionHelper
{
static void add (lua_State* L, char const* name, MemFnPtr mf)
{
new (lua_newuserdata (L, sizeof (MemFnPtr))) MemFnPtr (mf);
lua_pushcclosure (L, &CallConstMember <MemFnPtr>::f, 1);
lua_pushvalue (L, -1);
rawsetfield (L, -5, name); // const table
rawsetfield (L, -3, name); // class table
}
};
template <class MemFnPtr>
struct CallMemberFunctionHelper <MemFnPtr, false>
{
static void add (lua_State* L, char const* name, MemFnPtr mf)
{
new (lua_newuserdata (L, sizeof (MemFnPtr))) MemFnPtr (mf);
lua_pushcclosure (L, &CallMember <MemFnPtr>::f, 1);
rawsetfield (L, -3, name); // class table
}
};
//--------------------------------------------------------------------------
/**
__gc metamethod for a class.
*/
template <class C>
static int gcMetaMethod (lua_State* L)
{
Userdata* const ud = Userdata::getExact <C> (L, 1);
ud->~Userdata ();
return 0;
}
/**
__gc metamethod for an arbitrary class.
*/
template <class T>
static int gcMetaMethodAny (lua_State* L)
{
assert (isfulluserdata (L, 1));
T* t = static_cast <T*> (lua_touserdata (L, 1));
t->~T ();
return 0;
}
//--------------------------------------------------------------------------
/**
lua_CFunction to get a class data member.
The pointer-to-member is in the first upvalue.
The class userdata object is at the top of the Lua stack.
*/
template <class C, typename T>
static int getProperty (lua_State* L)
{
C* const c = Userdata::get <C> (L, 1, true);
T C::** mp = static_cast <T C::**> (lua_touserdata (L, lua_upvalueindex (1)));
try
{
Stack <T&>::push (L, c->**mp);
}
catch (const std::exception& e)
{
luaL_error (L, e.what ());
}
return 1;
}
//--------------------------------------------------------------------------
/**
lua_CFunction to set a class data member.
The pointer-to-member is in the first upvalue.
The class userdata object is at the top of the Lua stack.
*/
template <class C, typename T>
static int setProperty (lua_State* L)
{
C* const c = Userdata::get <C> (L, 1, false);
T C::** mp = static_cast <T C::**> (lua_touserdata (L, lua_upvalueindex (1)));
try
{
c->**mp = Stack <T>::get (L, 2);
}
catch (const std::exception& e)
{
luaL_error (L, e.what ());
}
return 0;
}
};
} // namespace luabridge

View File

@@ -1,169 +0,0 @@
//------------------------------------------------------------------------------
/*
https://github.com/vinniefalco/LuaBridge
Copyright 2012, Vinnie Falco <vinnie.falco@gmail.com>
License: The MIT License (http://www.opensource.org/licenses/mit-license.php)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
//==============================================================================
#pragma once
namespace luabridge {
/**
* A unique key for a type name in a metatable.
*/
inline const void* getTypeKey ()
{
#ifdef _NDEBUG
static char value;
return &value;
#else
return reinterpret_cast <void*> (0x71);
#endif
}
/**
* The key of a const table in another metatable.
*/
inline const void* getConstKey ()
{
#ifdef _NDEBUG
static char value;
return &value;
#else
return reinterpret_cast <void*> (0xc07);
#endif
}
/**
* The key of a class table in another metatable.
*/
inline const void* getClassKey ()
{
#ifdef _NDEBUG
static char value;
return &value;
#else
return reinterpret_cast <void*> (0xc1a);
#endif
}
/**
* The key of a propget table in another metatable.
*/
inline const void* getPropgetKey ()
{
#ifdef _NDEBUG
static char value;
return &value;
#else
return reinterpret_cast <void*> (0x6e7);
#endif
}
/**
* The key of a propset table in another metatable.
*/
inline const void* getPropsetKey ()
{
#ifdef _NDEBUG
static char value;
return &value;
#else
return reinterpret_cast <void*> (0x5e7);
#endif
}
/**
* The key of a static table in another metatable.
*/
inline const void* getStaticKey ()
{
#ifdef _NDEBUG
static char value;
return &value;
#else
return reinterpret_cast <void*> (0x57a);
#endif
}
/**
* The key of a parent table in another metatable.
*/
inline const void* getParentKey ()
{
#ifdef _NDEBUG
static char value;
return &value;
#else
return reinterpret_cast <void*> (0xdad);
#endif
}
/** Unique Lua registry keys for a class.
Each registered class inserts three keys into the registry, whose
values are the corresponding static, class, and const metatables. This
allows a quick and reliable lookup for a metatable from a template type.
*/
template <class T>
class ClassInfo
{
public:
/** Get the key for the static table.
The static table holds the static data members, static properties, and
static member functions for a class.
*/
static void const* getStaticKey ()
{
static char value;
return &value;
}
/** Get the key for the class table.
The class table holds the data members, properties, and member functions
of a class. Read-only data and properties, and const member functions are
also placed here (to save a lookup in the const table).
*/
static void const* getClassKey ()
{
static char value;
return &value;
}
/** Get the key for the const table.
The const table holds read-only data members and properties, and const
member functions of a class.
*/
static void const* getConstKey ()
{
static char value;
return &value;
}
};
} // namespace luabridge

View File

@@ -1,10 +0,0 @@
// https://github.com/vinniefalco/LuaBridge
//
// Copyright 2019, Dmitry Tarakanov
// SPDX-License-Identifier: MIT
#pragma once
#if !defined (LUABRIDGE_NO_CXX11) && (__cplusplus >= 201103L || (defined (_MSC_VER) && _MSC_VER >= 1900))
#define LUABRIDGE_CXX11
#endif

View File

@@ -1,205 +0,0 @@
//------------------------------------------------------------------------------
/*
https://github.com/vinniefalco/LuaBridge
Copyright 2012, Vinnie Falco <vinnie.falco@gmail.com>
Copyright 2007, Nathan Reed
License: The MIT License (http://www.opensource.org/licenses/mit-license.php)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
//==============================================================================
#pragma once
namespace luabridge {
/*
* Constructor generators. These templates allow you to call operator new and
* pass the contents of a type/value list to the Constructor. Like the
* function pointer containers, these are only defined up to 8 parameters.
*/
/** Constructor generators.
These templates call operator new with the contents of a type/value
list passed to the Constructor with up to 8 parameters. Two versions
of call() are provided. One performs a regular new, the other performs
a placement new.
*/
template <class T, typename List>
struct Constructor {};
template <class T>
struct Constructor <T, None>
{
static T* call (TypeListValues <None> const&)
{
return new T;
}
static T* call (void* mem, TypeListValues <None> const&)
{
return new (mem) T;
}
};
template <class T, class P1>
struct Constructor <T, TypeList <P1> >
{
static T* call (const TypeListValues<TypeList <P1> > &tvl)
{
return new T(tvl.hd);
}
static T* call (void* mem, const TypeListValues<TypeList <P1> > &tvl)
{
return new (mem) T(tvl.hd);
}
};
template <class T, class P1, class P2>
struct Constructor <T, TypeList <P1, TypeList <P2> > >
{
static T* call (const TypeListValues<TypeList <P1, TypeList <P2> > > &tvl)
{
return new T(tvl.hd, tvl.tl.hd);
}
static T* call (void* mem, const TypeListValues<TypeList <P1, TypeList <P2> > > &tvl)
{
return new (mem) T(tvl.hd, tvl.tl.hd);
}
};
template <class T, class P1, class P2, class P3>
struct Constructor <T, TypeList <P1, TypeList <P2, TypeList <P3> > > >
{
static T* call (const TypeListValues<TypeList <P1, TypeList <P2,
TypeList <P3> > > > &tvl)
{
return new T(tvl.hd, tvl.tl.hd, tvl.tl.tl.hd);
}
static T* call (void* mem, const TypeListValues<TypeList <P1, TypeList <P2,
TypeList <P3> > > > &tvl)
{
return new (mem) T(tvl.hd, tvl.tl.hd, tvl.tl.tl.hd);
}
};
template <class T, class P1, class P2, class P3, class P4>
struct Constructor <T, TypeList <P1, TypeList <P2, TypeList <P3,
TypeList <P4> > > > >
{
static T* call (const TypeListValues<TypeList <P1, TypeList <P2,
TypeList <P3, TypeList <P4> > > > > &tvl)
{
return new T(tvl.hd, tvl.tl.hd, tvl.tl.tl.hd, tvl.tl.tl.tl.hd);
}
static T* call (void* mem, const TypeListValues<TypeList <P1, TypeList <P2,
TypeList <P3, TypeList <P4> > > > > &tvl)
{
return new (mem) T(tvl.hd, tvl.tl.hd, tvl.tl.tl.hd, tvl.tl.tl.tl.hd);
}
};
template <class T, class P1, class P2, class P3, class P4,
class P5>
struct Constructor <T, TypeList <P1, TypeList <P2, TypeList <P3,
TypeList <P4, TypeList <P5> > > > > >
{
static T* call (const TypeListValues<TypeList <P1, TypeList <P2,
TypeList <P3, TypeList <P4, TypeList <P5> > > > > > &tvl)
{
return new T(tvl.hd, tvl.tl.hd, tvl.tl.tl.hd, tvl.tl.tl.tl.hd,
tvl.tl.tl.tl.tl.hd);
}
static T* call (void* mem, const TypeListValues<TypeList <P1, TypeList <P2,
TypeList <P3, TypeList <P4, TypeList <P5> > > > > > &tvl)
{
return new (mem) T(tvl.hd, tvl.tl.hd, tvl.tl.tl.hd, tvl.tl.tl.tl.hd,
tvl.tl.tl.tl.tl.hd);
}
};
template <class T, class P1, class P2, class P3, class P4,
class P5, class P6>
struct Constructor <T, TypeList <P1, TypeList <P2, TypeList <P3,
TypeList <P4, TypeList <P5, TypeList <P6> > > > > > >
{
static T* call (const TypeListValues<TypeList <P1, TypeList <P2,
TypeList <P3, TypeList <P4, TypeList <P5, TypeList <P6> > > > > > > &tvl)
{
return new T(tvl.hd, tvl.tl.hd, tvl.tl.tl.hd, tvl.tl.tl.tl.hd,
tvl.tl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.tl.hd);
}
static T* call (void* mem, const TypeListValues<TypeList <P1, TypeList <P2,
TypeList <P3, TypeList <P4, TypeList <P5, TypeList <P6> > > > > > > &tvl)
{
return new (mem) T(tvl.hd, tvl.tl.hd, tvl.tl.tl.hd, tvl.tl.tl.tl.hd,
tvl.tl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.tl.hd);
}
};
template <class T, class P1, class P2, class P3, class P4,
class P5, class P6, class P7>
struct Constructor <T, TypeList <P1, TypeList <P2, TypeList <P3,
TypeList <P4, TypeList <P5, TypeList <P6, TypeList <P7> > > > > > > >
{
static T* call (const TypeListValues<TypeList <P1, TypeList <P2,
TypeList <P3, TypeList <P4, TypeList <P5, TypeList <P6,
TypeList <P7> > > > > > > > &tvl)
{
return new T(tvl.hd, tvl.tl.hd, tvl.tl.tl.hd, tvl.tl.tl.tl.hd,
tvl.tl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.tl.hd,
tvl.tl.tl.tl.tl.tl.tl.hd);
}
static T* call (void* mem, const TypeListValues<TypeList <P1, TypeList <P2,
TypeList <P3, TypeList <P4, TypeList <P5, TypeList <P6,
TypeList <P7> > > > > > > > &tvl)
{
return new (mem) T(tvl.hd, tvl.tl.hd, tvl.tl.tl.hd, tvl.tl.tl.tl.hd,
tvl.tl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.tl.hd,
tvl.tl.tl.tl.tl.tl.tl.hd);
}
};
template <class T, class P1, class P2, class P3, class P4,
class P5, class P6, class P7, class P8>
struct Constructor <T, TypeList <P1, TypeList <P2, TypeList <P3,
TypeList <P4, TypeList <P5, TypeList <P6, TypeList <P7,
TypeList <P8> > > > > > > > >
{
static T* call (const TypeListValues<TypeList <P1, TypeList <P2,
TypeList <P3, TypeList <P4, TypeList <P5, TypeList <P6,
TypeList <P7, TypeList <P8> > > > > > > > > &tvl)
{
return new T(tvl.hd, tvl.tl.hd, tvl.tl.tl.hd, tvl.tl.tl.tl.hd,
tvl.tl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.tl.hd,
tvl.tl.tl.tl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.tl.tl.tl.hd);
}
static T* call (void* mem, const TypeListValues<TypeList <P1, TypeList <P2,
TypeList <P3, TypeList <P4, TypeList <P5, TypeList <P6,
TypeList <P7, TypeList <P8> > > > > > > > > &tvl)
{
return new (mem) T(tvl.hd, tvl.tl.hd, tvl.tl.tl.hd, tvl.tl.tl.tl.hd,
tvl.tl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.tl.hd,
tvl.tl.tl.tl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.tl.tl.tl.hd);
}
};
} // namespace luabridge

View File

@@ -1,942 +0,0 @@
//------------------------------------------------------------------------------
/*
https://github.com/vinniefalco/LuaBridge
Copyright 2020, Dmitry Tarakanov
Copyright 2012, Vinnie Falco <vinnie.falco@gmail.com>
License: The MIT License (http://www.opensource.org/licenses/mit-license.php)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
//==============================================================================
#pragma once
#include <LuaBridge/detail/Config.h>
#ifdef LUABRIDGE_CXX11
#include <functional>
#endif
namespace luabridge {
/**
Since the throw specification is part of a function signature, the FuncTraits
family of templates needs to be specialized for both types. The
LUABRIDGE_THROWSPEC macro controls whether we use the 'throw ()' form, or
'noexcept' (if C++11 is available) to distinguish the functions.
*/
#if defined (__APPLE_CPP__) || defined (__APPLE_CC__) || defined (__clang__) || defined (__GNUC__) || \
(defined (_MSC_VER) && (_MSC_VER >= 1700))
// Do not define LUABRIDGE_THROWSPEC since the Xcode and gcc compilers do not
// distinguish the throw specification in the function signature.
#define LUABRIDGE_THROWSPEC
#else
// Visual Studio 10 and earlier pay too much mind to useless throw () spec.
//
# define LUABRIDGE_THROWSPEC throw ()
#endif
//==============================================================================
/**
* Traits class for unrolling the type list values into function arguments.
*/
template <class ReturnType, size_t NUM_PARAMS>
struct Caller;
template <class ReturnType>
struct Caller <ReturnType, 0>
{
template <class Fn, class Params>
static ReturnType f (Fn& fn, TypeListValues <Params>& params)
{
return fn ();
}
template <class T, class MemFn, class Params>
static ReturnType f (T* obj, MemFn& fn, TypeListValues <Params>&)
{
return (obj->*fn) ();
}
};
template <class ReturnType>
struct Caller <ReturnType, 1>
{
template <class Fn, class Params>
static ReturnType f (Fn& fn, TypeListValues <Params>& tvl)
{
return fn (tvl.hd);
}
template <class T, class MemFn, class Params>
static ReturnType f (T* obj, MemFn& fn, TypeListValues <Params>& tvl)
{
return (obj->*fn) (tvl.hd);
}
};
template <class ReturnType>
struct Caller <ReturnType, 2>
{
template <class Fn, class Params>
static ReturnType f (Fn& fn, TypeListValues <Params>& tvl)
{
return fn (tvl.hd, tvl.tl.hd);
}
template <class T, class MemFn, class Params>
static ReturnType f (T* obj, MemFn& fn, TypeListValues <Params>& tvl)
{
return (obj->*fn) (tvl.hd, tvl.tl.hd);
}
};
template <class ReturnType>
struct Caller <ReturnType, 3>
{
template <class Fn, class Params>
static ReturnType f (Fn& fn, TypeListValues <Params>& tvl)
{
return fn (tvl.hd, tvl.tl.hd, tvl.tl.tl.hd);
}
template <class T, class MemFn, class Params>
static ReturnType f (T* obj, MemFn& fn, TypeListValues <Params>& tvl)
{
return (obj->*fn) (tvl.hd, tvl.tl.hd, tvl.tl.tl.hd);
}
};
template <class ReturnType>
struct Caller <ReturnType, 4>
{
template <class Fn, class Params>
static ReturnType f (Fn& fn, TypeListValues <Params>& tvl)
{
return fn (tvl.hd, tvl.tl.hd, tvl.tl.tl.hd, tvl.tl.tl.tl.hd);
}
template <class T, class MemFn, class Params>
static ReturnType f (T* obj, MemFn& fn, TypeListValues <Params>& tvl)
{
return (obj->*fn) (tvl.hd, tvl.tl.hd, tvl.tl.tl.hd, tvl.tl.tl.tl.hd);
}
};
template <class ReturnType>
struct Caller <ReturnType, 5>
{
template <class Fn, class Params>
static ReturnType f (Fn& fn, TypeListValues <Params>& tvl)
{
return fn (tvl.hd, tvl.tl.hd, tvl.tl.tl.hd, tvl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.hd);
}
template <class T, class MemFn, class Params>
static ReturnType f (T* obj, MemFn& fn, TypeListValues <Params>& tvl)
{
return (obj->*fn) (tvl.hd, tvl.tl.hd, tvl.tl.tl.hd, tvl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.hd);
}
};
template <class ReturnType>
struct Caller <ReturnType, 6>
{
template <class Fn, class Params>
static ReturnType f (Fn& fn, TypeListValues <Params>& tvl)
{
return fn (tvl.hd, tvl.tl.hd, tvl.tl.tl.hd, tvl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.hd,
tvl.tl.tl.tl.tl.tl.hd);
}
template <class T, class MemFn, class Params>
static ReturnType f (T* obj, MemFn& fn, TypeListValues <Params>& tvl)
{
return (obj->*fn) (tvl.hd, tvl.tl.hd, tvl.tl.tl.hd, tvl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.hd,
tvl.tl.tl.tl.tl.tl.hd);
}
};
template <class ReturnType>
struct Caller <ReturnType, 7>
{
template <class Fn, class Params>
static ReturnType f (Fn& fn, TypeListValues <Params>& tvl)
{
return fn (tvl.hd, tvl.tl.hd, tvl.tl.tl.hd, tvl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.hd,
tvl.tl.tl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.tl.tl.hd);
}
template <class T, class MemFn, class Params>
static ReturnType f (T* obj, MemFn& fn, TypeListValues <Params>& tvl)
{
return (obj->*fn) (tvl.hd, tvl.tl.hd, tvl.tl.tl.hd, tvl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.hd,
tvl.tl.tl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.tl.tl.hd);
}
};
template <class ReturnType>
struct Caller <ReturnType, 8>
{
template <class Fn, class Params>
static ReturnType f (Fn& fn, TypeListValues <Params>& tvl)
{
return fn (tvl.hd, tvl.tl.hd, tvl.tl.tl.hd, tvl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.hd,
tvl.tl.tl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.tl.tl.tl.hd);
}
template <class T, class MemFn, class Params>
static ReturnType f (T* obj, MemFn& fn, TypeListValues <Params>& tvl)
{
return (obj->*fn) (tvl.hd, tvl.tl.hd, tvl.tl.tl.hd, tvl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.hd,
tvl.tl.tl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.tl.tl.tl.hd);
}
};
template <class ReturnType>
struct Caller <ReturnType, 9>
{
template <class Fn, class Params>
static ReturnType f (Fn& fn, TypeListValues <Params>& tvl)
{
return fn (tvl.hd, tvl.tl.hd, tvl.tl.tl.hd, tvl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.hd,
tvl.tl.tl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.tl.tl.tl.hd,
tvl.tl.tl.tl.tl.tl.tl.tl.tl.hd);
}
template <class T, class MemFn, class Params>
static ReturnType f (T* obj, MemFn& fn, TypeListValues <Params>& tvl)
{
return (obj->*fn) (tvl.hd, tvl.tl.hd, tvl.tl.tl.hd, tvl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.hd,
tvl.tl.tl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.tl.tl.tl.hd,
tvl.tl.tl.tl.tl.tl.tl.tl.tl.hd);
}
};
template <class ReturnType, class Fn, class Params>
ReturnType doCall (Fn& fn, TypeListValues <Params>& tvl)
{
return Caller <ReturnType, TypeListSize <Params>::value>::f (fn, tvl);
}
template <class ReturnType, class T, class MemFn, class Params>
static ReturnType doCall(T* obj, MemFn& fn, TypeListValues <Params>& tvl)
{
return Caller <ReturnType, TypeListSize <Params>::value>::f (obj, fn, tvl);
}
//==============================================================================
/**
Traits for function pointers.
There are three types of functions: global, non-const member, and const
member. These templates determine the type of function, which class type it
belongs to if it is a class member, the const-ness if it is a member
function, and the type information for the return value and argument list.
Expansions are provided for functions with up to 8 parameters. This can be
manually extended, or expanded to an arbitrary amount using C++11 features.
*/
template <class MemFn, class D = MemFn>
struct FuncTraits
{
};
#ifndef LUABRIDGE_CXX11
/* Ordinary function pointers. */
template <class R, class D>
struct FuncTraits <R (*) () LUABRIDGE_THROWSPEC, D>
{
static bool const isMemberFunction = false;
typedef D DeclType;
typedef R ReturnType;
typedef None Params;
static R call (D fp, TypeListValues <Params>& tvl)
{
return doCall <R> (fp, tvl);
}
};
template <class R, class P1, class D>
struct FuncTraits <R (*) (P1) LUABRIDGE_THROWSPEC, D>
{
static bool const isMemberFunction = false;
typedef D DeclType;
typedef R ReturnType;
typedef TypeList <P1> Params;
static R call (D fp, TypeListValues <Params>& tvl)
{
return doCall <R> (fp, tvl);
}
};
template <class R, class P1, class P2, class D>
struct FuncTraits <R (*) (P1, P2) LUABRIDGE_THROWSPEC, D>
{
static bool const isMemberFunction = false;
typedef D DeclType;
typedef R ReturnType;
typedef TypeList <P1, TypeList <P2> > Params;
static R call (D fp, TypeListValues <Params>& tvl)
{
return doCall <R> (fp, tvl);
}
};
template <class R, class P1, class P2, class P3, class D>
struct FuncTraits <R (*) (P1, P2, P3) LUABRIDGE_THROWSPEC, D>
{
static bool const isMemberFunction = false;
typedef D DeclType;
typedef R ReturnType;
typedef TypeList <P1, TypeList <P2, TypeList <P3> > > Params;
static R call (D fp, TypeListValues <Params>& tvl)
{
return doCall <R> (fp, tvl);
}
};
template <class R, class P1, class P2, class P3, class P4, class D>
struct FuncTraits <R (*) (P1, P2, P3, P4) LUABRIDGE_THROWSPEC, D>
{
static bool const isMemberFunction = false;
typedef D DeclType;
typedef R ReturnType;
typedef TypeList <P1, TypeList <P2, TypeList <P3, TypeList <P4> > > > Params;
static R call (D fp, TypeListValues <Params>& tvl)
{
return doCall <R> (fp, tvl);
}
};
template <class R, class P1, class P2, class P3, class P4, class P5, class D>
struct FuncTraits <R (*) (P1, P2, P3, P4, P5) LUABRIDGE_THROWSPEC, D>
{
static bool const isMemberFunction = false;
typedef D DeclType;
typedef R ReturnType;
typedef TypeList <P1, TypeList <P2, TypeList <P3, TypeList <P4, TypeList <P5> > > > > Params;
static R call (D fp, TypeListValues <Params>& tvl)
{
return doCall <R> (fp, tvl);
}
};
template <class R, class P1, class P2, class P3, class P4, class P5, class P6, class D>
struct FuncTraits <R (*) (P1, P2, P3, P4, P5, P6) LUABRIDGE_THROWSPEC, D>
{
static bool const isMemberFunction = false;
typedef D DeclType;
typedef R ReturnType;
typedef TypeList <P1, TypeList <P2, TypeList <P3, TypeList <P4, TypeList <P5, TypeList <P6> > > > > > Params;
static R call (D fp, TypeListValues <Params>& tvl)
{
return doCall <R> (fp, tvl);
}
};
template <class R, class P1, class P2, class P3, class P4, class P5, class P6, class P7, class D>
struct FuncTraits <R (*) (P1, P2, P3, P4, P5, P6, P7) LUABRIDGE_THROWSPEC, D>
{
static bool const isMemberFunction = false;
typedef D DeclType;
typedef R ReturnType;
typedef TypeList <P1, TypeList <P2, TypeList <P3, TypeList <P4, TypeList <P5, TypeList <P6, TypeList <P7> > > > > > > Params;
static R call (D fp, TypeListValues <Params>& tvl)
{
return doCall <R> (fp, tvl);
}
};
template <class R, class P1, class P2, class P3, class P4, class P5, class P6, class P7, class P8, class D>
struct FuncTraits <R (*) (P1, P2, P3, P4, P5, P6, P7, P8) LUABRIDGE_THROWSPEC, D>
{
static bool const isMemberFunction = false;
typedef D DeclType;
typedef R ReturnType;
typedef TypeList <P1, TypeList <P2, TypeList <P3, TypeList <P4, TypeList <P5, TypeList <P6, TypeList <P7, TypeList <P8> > > > > > > > Params;
static R call (D fp, TypeListValues <Params>& tvl)
{
return doCall <R> (fp, tvl);
}
};
/* Windows: WINAPI (a.k.a. __stdcall) function pointers. */
#ifdef _M_IX86 // Windows 32bit only
template <class R, class D>
struct FuncTraits <R (__stdcall *) (), D>
{
static bool const isMemberFunction = false;
typedef D DeclType;
typedef R ReturnType;
typedef None Params;
static R call (D fp, TypeListValues <Params>& tvl)
{
return doCall <R> (fp, tvl);
}
};
template <class R, class P1, class D>
struct FuncTraits <R (__stdcall *) (P1), D>
{
static bool const isMemberFunction = false;
typedef D DeclType;
typedef R ReturnType;
typedef TypeList <P1> Params;
static R call (D fp, TypeListValues <Params>& tvl)
{
return doCall <R> (fp, tvl);
}
};
template <class R, class P1, class P2, class D>
struct FuncTraits <R (__stdcall *) (P1, P2), D>
{
static bool const isMemberFunction = false;
typedef D DeclType;
typedef R ReturnType;
typedef TypeList <P1, TypeList <P2> > Params;
static R call (D fp, TypeListValues <Params>& tvl)
{
return doCall <R> (fp, tvl);
}
};
template <class R, class P1, class P2, class P3, class D>
struct FuncTraits <R (__stdcall *) (P1, P2, P3), D>
{
static bool const isMemberFunction = false;
typedef D DeclType;
typedef R ReturnType;
typedef TypeList <P1, TypeList <P2, TypeList <P3> > > Params;
static R call (D fp, TypeListValues <Params>& tvl)
{
return doCall <R> (fp, tvl);
}
};
template <class R, class P1, class P2, class P3, class P4, class D>
struct FuncTraits <R (__stdcall *) (P1, P2, P3, P4), D>
{
static bool const isMemberFunction = false;
typedef D DeclType;
typedef R ReturnType;
typedef TypeList <P1, TypeList <P2, TypeList <P3, TypeList <P4> > > > Params;
static R call (D fp, TypeListValues <Params>& tvl)
{
return doCall <R> (fp, tvl);
}
};
template <class R, class P1, class P2, class P3, class P4, class P5, class D>
struct FuncTraits <R (__stdcall *) (P1, P2, P3, P4, P5), D>
{
static bool const isMemberFunction = false;
typedef D DeclType;
typedef R ReturnType;
typedef TypeList <P1, TypeList <P2, TypeList <P3, TypeList <P4, TypeList <P5> > > > > Params;
static R call (D fp, TypeListValues <Params>& tvl)
{
return doCall <R> (fp, tvl);
}
};
template <class R, class P1, class P2, class P3, class P4, class P5, class P6, class D>
struct FuncTraits <R (__stdcall *) (P1, P2, P3, P4, P5, P6), D>
{
static bool const isMemberFunction = false;
typedef D DeclType;
typedef R ReturnType;
typedef TypeList <P1, TypeList <P2, TypeList <P3, TypeList <P4, TypeList <P5, TypeList <P6> > > > > > Params;
static R call (D fp, TypeListValues <Params>& tvl)
{
return doCall <R> (fp, tvl);
}
};
template <class R, class P1, class P2, class P3, class P4, class P5, class P6, class P7, class D>
struct FuncTraits <R (__stdcall *) (P1, P2, P3, P4, P5, P6, P7), D>
{
static bool const isMemberFunction = false;
typedef D DeclType;
typedef R ReturnType;
typedef TypeList <P1, TypeList <P2, TypeList <P3, TypeList <P4, TypeList <P5, TypeList <P6, TypeList <P7> > > > > > > Params;
static R call (D fp, TypeListValues <Params>& tvl)
{
return doCall <R> (fp, tvl);
}
};
template <class R, class P1, class P2, class P3, class P4, class P5, class P6, class P7, class P8, class D>
struct FuncTraits <R (__stdcall *) (P1, P2, P3, P4, P5, P6, P7, P8), D>
{
static bool const isMemberFunction = false;
typedef D DeclType;
typedef R ReturnType;
typedef TypeList <P1, TypeList <P2, TypeList <P3, TypeList <P4, TypeList <P5, TypeList <P6, TypeList <P7, TypeList <P8> > > > > > > > Params;
static R call (D fp, TypeListValues <Params>& tvl)
{
return doCall <R> (fp, tvl);
}
};
#endif // _M_IX86
/* Non-const member function pointers. */
template <class T, class R, class D>
struct FuncTraits <R (T::*) () LUABRIDGE_THROWSPEC, D>
{
static bool const isMemberFunction = true;
static bool const isConstMemberFunction = false;
typedef D DeclType;
typedef T ClassType;
typedef R ReturnType;
typedef None Params;
static R call (T* obj, D fp, TypeListValues <Params>& tvl)
{
return doCall <R> (obj, fp, tvl);
}
};
template <class T, class R, class P1, class D>
struct FuncTraits <R (T::*) (P1) LUABRIDGE_THROWSPEC, D>
{
static bool const isMemberFunction = true;
static bool const isConstMemberFunction = false;
typedef D DeclType;
typedef T ClassType;
typedef R ReturnType;
typedef TypeList <P1> Params;
static R call (T* obj, D fp, TypeListValues <Params>& tvl)
{
return doCall <R> (obj, fp, tvl);
}
};
template <class T, class R, class P1, class P2, class D>
struct FuncTraits <R (T::*) (P1, P2) LUABRIDGE_THROWSPEC, D>
{
static bool const isMemberFunction = true;
static bool const isConstMemberFunction = false;
typedef D DeclType;
typedef T ClassType;
typedef R ReturnType;
typedef TypeList <P1, TypeList <P2> > Params;
static R call (T* obj, D fp, TypeListValues <Params>& tvl)
{
return doCall <R> (obj, fp, tvl);
}
};
template <class T, class R, class P1, class P2, class P3, class D>
struct FuncTraits <R (T::*) (P1, P2, P3) LUABRIDGE_THROWSPEC, D>
{
static bool const isMemberFunction = true;
static bool const isConstMemberFunction = false;
typedef D DeclType;
typedef T ClassType;
typedef R ReturnType;
typedef TypeList <P1, TypeList <P2, TypeList <P3> > > Params;
static R call (T* obj, D fp, TypeListValues <Params>& tvl)
{
return doCall <R> (obj, fp, tvl);
}
};
template <class T, class R, class P1, class P2, class P3, class P4, class D>
struct FuncTraits <R (T::*) (P1, P2, P3, P4) LUABRIDGE_THROWSPEC, D>
{
static bool const isMemberFunction = true;
static bool const isConstMemberFunction = false;
typedef D DeclType;
typedef T ClassType;
typedef R ReturnType;
typedef TypeList <P1, TypeList <P2, TypeList <P3, TypeList <P4> > > > Params;
static R call (T* obj, D fp, TypeListValues <Params>& tvl)
{
return doCall <R> (obj, fp, tvl);
}
};
template <class T, class R, class P1, class P2, class P3, class P4, class P5, class D>
struct FuncTraits <R (T::*) (P1, P2, P3, P4, P5) LUABRIDGE_THROWSPEC, D>
{
static bool const isMemberFunction = true;
static bool const isConstMemberFunction = false;
typedef D DeclType;
typedef T ClassType;
typedef R ReturnType;
typedef TypeList <P1, TypeList <P2, TypeList <P3, TypeList <P4, TypeList <P5> > > > > Params;
static R call (T* obj, D fp, TypeListValues <Params>& tvl)
{
return doCall <R> (obj, fp, tvl);
}
};
template <class T, class R, class P1, class P2, class P3, class P4, class P5, class P6, class D>
struct FuncTraits <R (T::*) (P1, P2, P3, P4, P5, P6) LUABRIDGE_THROWSPEC, D>
{
static bool const isMemberFunction = true;
static bool const isConstMemberFunction = false;
typedef D DeclType;
typedef T ClassType;
typedef R ReturnType;
typedef TypeList <P1, TypeList <P2, TypeList <P3, TypeList <P4, TypeList <P5, TypeList <P6> > > > > > Params;
static R call (T* obj, D fp, TypeListValues <Params>& tvl)
{
return doCall <R> (obj, fp, tvl);
}
};
template <class T, class R, class P1, class P2, class P3, class P4, class P5, class P6, class P7, class D>
struct FuncTraits <R (T::*) (P1, P2, P3, P4, P5, P6, P7) LUABRIDGE_THROWSPEC, D>
{
static bool const isMemberFunction = true;
static bool const isConstMemberFunction = false;
typedef D DeclType;
typedef T ClassType;
typedef R ReturnType;
typedef TypeList <P1, TypeList <P2, TypeList <P3, TypeList <P4, TypeList <P5, TypeList <P6, TypeList <P7> > > > > > > Params;
static R call (T* obj, D fp, TypeListValues <Params>& tvl)
{
return doCall <R> (obj, fp, tvl);
}
};
template <class T, class R, class P1, class P2, class P3, class P4, class P5, class P6, class P7, class P8, class D>
struct FuncTraits <R (T::*) (P1, P2, P3, P4, P5, P6, P7, P8) LUABRIDGE_THROWSPEC, D>
{
static bool const isMemberFunction = true;
static bool const isConstMemberFunction = false;
typedef D DeclType;
typedef T ClassType;
typedef R ReturnType;
typedef TypeList <P1, TypeList <P2, TypeList <P3, TypeList <P4, TypeList <P5, TypeList <P6, TypeList <P7, TypeList <P8> > > > > > > > Params;
static R call (T* obj, D fp, TypeListValues <Params>& tvl)
{
return doCall <R> (obj, fp, tvl);
}
};
/* Const member function pointers. */
template <class T, class R, class D>
struct FuncTraits <R (T::*) () const LUABRIDGE_THROWSPEC, D>
{
static bool const isMemberFunction = true;
static bool const isConstMemberFunction = true;
typedef D DeclType;
typedef T ClassType;
typedef R ReturnType;
typedef None Params;
static R call (T const* obj, D fp, TypeListValues <Params>& tvl)
{
return doCall <R> (obj, fp, tvl);
}
};
template <class T, class R, class P1, class D>
struct FuncTraits <R (T::*) (P1) const LUABRIDGE_THROWSPEC, D>
{
static bool const isMemberFunction = true;
static bool const isConstMemberFunction = true;
typedef D DeclType;
typedef T ClassType;
typedef R ReturnType;
typedef TypeList <P1> Params;
static R call (T const* obj, D fp, TypeListValues <Params>& tvl)
{
return doCall <R> (obj, fp, tvl);
}
};
template <class T, class R, class P1, class P2, class D>
struct FuncTraits <R (T::*) (P1, P2) const LUABRIDGE_THROWSPEC, D>
{
static bool const isMemberFunction = true;
static bool const isConstMemberFunction = true;
typedef D DeclType;
typedef T ClassType;
typedef R ReturnType;
typedef TypeList <P1, TypeList <P2> > Params;
static R call (T const* obj, R (T::*fp) (P1, P2) const, TypeListValues <Params>& tvl)
{
return doCall <R> (obj, fp, tvl);
}
};
template <class T, class R, class P1, class P2, class P3, class D>
struct FuncTraits <R (T::*) (P1, P2, P3) const LUABRIDGE_THROWSPEC, D>
{
static bool const isMemberFunction = true;
static bool const isConstMemberFunction = true;
typedef D DeclType;
typedef T ClassType;
typedef R ReturnType;
typedef TypeList <P1, TypeList <P2, TypeList <P3> > > Params;
static R call (T const* obj, D fp, TypeListValues <Params>& tvl)
{
return doCall <R> (obj, fp, tvl);
}
};
template <class T, class R, class P1, class P2, class P3, class P4, class D>
struct FuncTraits <R (T::*) (P1, P2, P3, P4) const LUABRIDGE_THROWSPEC, D>
{
static bool const isMemberFunction = true;
static bool const isConstMemberFunction = true;
typedef D DeclType;
typedef T ClassType;
typedef R ReturnType;
typedef TypeList <P1, TypeList <P2, TypeList <P3, TypeList <P4> > > > Params;
static R call (T const* obj, D fp, TypeListValues <Params>& tvl)
{
return doCall <R> (obj, fp, tvl);
}
};
template <class T, class R, class P1, class P2, class P3, class P4, class P5, class D>
struct FuncTraits <R (T::*) (P1, P2, P3, P4, P5) const LUABRIDGE_THROWSPEC, D>
{
static bool const isMemberFunction = true;
static bool const isConstMemberFunction = true;
typedef D DeclType;
typedef T ClassType;
typedef R ReturnType;
typedef TypeList <P1, TypeList <P2, TypeList <P3, TypeList <P4, TypeList <P5> > > > > Params;
static R call (T const* obj, D fp, TypeListValues <Params>& tvl)
{
return doCall <R> (obj, fp, tvl);
}
};
template <class T, class R, class P1, class P2, class P3, class P4, class P5, class P6, class D>
struct FuncTraits <R (T::*) (P1, P2, P3, P4, P5, P6) const LUABRIDGE_THROWSPEC, D>
{
static bool const isMemberFunction = true;
static bool const isConstMemberFunction = true;
typedef D DeclType;
typedef T ClassType;
typedef R ReturnType;
typedef TypeList <P1, TypeList <P2, TypeList <P3, TypeList <P4, TypeList <P5, TypeList <P6> > > > > > Params;
static R call (T const* obj, D fp, TypeListValues <Params>& tvl)
{
return doCall <R> (obj, fp, tvl);
}
};
template <class T, class R, class P1, class P2, class P3, class P4, class P5, class P6, class P7, class D>
struct FuncTraits <R (T::*) (P1, P2, P3, P4, P5, P6, P7) const LUABRIDGE_THROWSPEC, D>
{
static bool const isMemberFunction = true;
static bool const isConstMemberFunction = true;
typedef D DeclType;
typedef T ClassType;
typedef R ReturnType;
typedef TypeList <P1, TypeList <P2, TypeList <P3, TypeList <P4, TypeList <P5, TypeList <P6, TypeList <P7> > > > > > > Params;
static R call (T const* obj, D fp, TypeListValues <Params>& tvl)
{
return doCall <R> (obj, fp, tvl);
}
};
template <class T, class R, class P1, class P2, class P3, class P4, class P5, class P6, class P7, class P8, class D>
struct FuncTraits <R (T::*) (P1, P2, P3, P4, P5, P6, P7, P8) const LUABRIDGE_THROWSPEC, D>
{
static bool const isMemberFunction = true;
static bool const isConstMemberFunction = true;
typedef D DeclType;
typedef T ClassType;
typedef R ReturnType;
typedef TypeList <P1, TypeList <P2, TypeList <P3, TypeList <P4, TypeList <P5, TypeList <P6, TypeList <P7, TypeList <P8> > > > > > > > Params;
static R call (T const* obj, D fp, TypeListValues <Params>& tvl)
{
return doCall <R> (obj, fp, tvl);
}
};
#else // ifndef LUABRIDGE_CXX11
/* Ordinary function pointers. */
template <class R, class... ParamList>
struct FuncTraits <R (*) (ParamList...)>
{
static bool const isMemberFunction = false;
using DeclType = R (*) (ParamList...);
using ReturnType = R;
using Params = typename MakeTypeList <ParamList...>::Result;
static R call (const DeclType& fp, TypeListValues <Params>& tvl)
{
return doCall <R> (fp, tvl);
}
};
/* Windows: WINAPI (a.k.a. __stdcall) function pointers. */
#ifdef _M_IX86 // Windows 32bit only
template <class R, class... ParamList>
struct FuncTraits <R (__stdcall *) (ParamList...)>
{
static bool const isMemberFunction = false;
using DeclType = R (__stdcall *) (ParamList...);
using ReturnType = R;
using Params = typename MakeTypeList <ParamList...>::Result;
static R call (const DeclType& fp, TypeListValues <Params>& tvl)
{
return doCall <R> (fp, tvl);
}
};
#endif // _M_IX86
/* Non-const member function pointers. */
template <class T, class R, class... ParamList>
struct FuncTraits <R (T::*) (ParamList...)>
{
static bool const isMemberFunction = true;
static bool const isConstMemberFunction = false;
using DeclType = R (T::*) (ParamList...);
using ClassType = T;
using ReturnType = R;
using Params = typename MakeTypeList <ParamList...>::Result;
static R call (ClassType* obj, const DeclType& fp, TypeListValues <Params>& tvl)
{
return doCall <R> (obj, fp, tvl);
}
};
/* Const member function pointers. */
template <class T, class R, class... ParamList>
struct FuncTraits <R (T::*) (ParamList...) const>
{
static bool const isMemberFunction = true;
static bool const isConstMemberFunction = true;
using DeclType = R (T::*) (ParamList...) const;
using ClassType = T;
using ReturnType = R;
using Params = typename MakeTypeList <ParamList...>::Result;
static R call (const ClassType* obj, const DeclType& fp, TypeListValues <Params>& tvl)
{
return doCall <R> (obj, fp, tvl);
}
};
/* std::function */
template <class R, class... ParamList>
struct FuncTraits <std::function <R (ParamList...)>>
{
static bool const isMemberFunction = false;
static bool const isConstMemberFunction = false;
using DeclType = std::function <R (ParamList...)>;
using ReturnType = R;
using Params = typename MakeTypeList <ParamList...>::Result;
static ReturnType call (DeclType& fn, TypeListValues <Params>& tvl)
{
return doCall <ReturnType> (fn, tvl);
}
};
#endif // ifndef LUABRIDGE_CXX11
template <class ReturnType, class Params, int startParam>
struct Invoke
{
template <class Fn>
static int run (lua_State* L, Fn& fn)
{
try
{
ArgList <Params, startParam> args (L);
Stack <ReturnType>::push (L, FuncTraits <Fn>::call (fn, args));
return 1;
}
catch (const std::exception& e)
{
return luaL_error (L, e.what ());
}
}
template <class T, class MemFn>
static int run (lua_State* L, T* object, const MemFn& fn)
{
try
{
ArgList <Params, startParam> args (L);
Stack <ReturnType>::push (L, FuncTraits <MemFn>::call (object, fn, args));
return 1;
}
catch (const std::exception& e)
{
return luaL_error (L, e.what ());
}
}
};
template <class Params, int startParam>
struct Invoke <void, Params, startParam>
{
template <class Fn>
static int run (lua_State* L, Fn& fn)
{
try
{
ArgList <Params, startParam> args (L);
FuncTraits <Fn>::call (fn, args);
return 0;
}
catch (const std::exception& e)
{
return luaL_error (L, e.what ());
}
}
template <class T, class MemFn>
static int run (lua_State* L, T* object, const MemFn& fn)
{
try
{
ArgList <Params, startParam> args (L);
FuncTraits <MemFn>::call (object, fn, args);
return 0;
}
catch (const std::exception& e)
{
return luaL_error (L, e.what ());
}
}
};
} // namespace luabridge

View File

@@ -1,154 +0,0 @@
//------------------------------------------------------------------------------
/*
https://github.com/vinniefalco/LuaBridge
Copyright 2018, Dmitry Tarakanov
Copyright 2012, Vinnie Falco <vinnie.falco@gmail.com>
License: The MIT License (http://www.opensource.org/licenses/mit-license.php)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
//==============================================================================
#pragma once
#include <LuaBridge/detail/LuaRef.h>
#include <utility>
namespace luabridge {
/** Allows table iteration.
*/
class Iterator
{
lua_State* m_L;
LuaRef m_table;
LuaRef m_key;
LuaRef m_value;
void next ()
{
m_table.push ();
m_key.push ();
if (lua_next (m_L, -2))
{
m_value.pop ();
m_key.pop ();
}
else
{
m_key = Nil ();
m_value = Nil ();
}
lua_pop (m_L, 1);
}
public:
explicit Iterator (const LuaRef& table, bool isEnd = false)
: m_L (table.state ())
, m_table (table)
, m_key (table.state ()) // m_key is nil
, m_value (table.state ()) // m_value is nil
{
if (!isEnd)
{
next (); // get the first (key, value) pair from table
}
}
lua_State* state () const
{
return m_L;
}
std::pair <LuaRef, LuaRef> operator* () const
{
return std::make_pair (m_key, m_value);
}
LuaRef operator-> () const
{
return m_value;
}
bool operator!= (const Iterator& rhs) const
{
assert (m_L == rhs.m_L);
return !m_table.rawequal (rhs.m_table) || !m_key.rawequal (rhs.m_key);
}
Iterator& operator++ ()
{
if (isNil ())
{
// if the iterator reaches the end, do nothing
return *this;
}
else
{
next ();
return *this;
}
}
bool isNil () const
{
return m_key.isNil ();
}
LuaRef key () const
{
return m_key;
}
LuaRef value () const
{
return m_value;
}
private:
// Don't use postfix increment, it is less efficient
Iterator operator++ (int);
};
class Range
{
Iterator m_begin;
Iterator m_end;
public:
Range (const Iterator& begin, const Iterator& end)
: m_begin (begin)
, m_end (end)
{
}
const Iterator& begin () const { return m_begin; }
const Iterator& end () const { return m_end; }
};
inline Range pairs (const LuaRef& table)
{
return Range (Iterator (table, false), Iterator (table, true));
}
} // namespace luabridge

View File

@@ -1,144 +0,0 @@
//------------------------------------------------------------------------------
/*
https://github.com/vinniefalco/LuaBridge
Copyright 2012, Vinnie Falco <vinnie.falco@gmail.com>
Copyright 2008, Nigel Atkinson <suprapilot+LuaCode@gmail.com>
License: The MIT License (http://www.opensource.org/licenses/mit-license.php)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
//==============================================================================
#pragma once
#include <exception>
#include <string>
namespace luabridge {
class LuaException : public std::exception
{
private:
lua_State* m_L;
std::string m_what;
public:
//----------------------------------------------------------------------------
/**
Construct a LuaException after a lua_pcall().
*/
LuaException (lua_State* L, int /*code*/)
: m_L (L)
{
whatFromStack ();
}
//----------------------------------------------------------------------------
LuaException (lua_State *L,
char const*,
char const*,
long)
: m_L (L)
{
whatFromStack ();
}
//----------------------------------------------------------------------------
~LuaException() throw ()
{
}
//----------------------------------------------------------------------------
char const* what() const throw ()
{
return m_what.c_str();
}
//============================================================================
/**
Throw an exception.
This centralizes all the exceptions thrown, so that we can set
breakpoints before the stack is unwound, or otherwise customize the
behavior.
*/
template <class Exception>
static void Throw (Exception e)
{
throw e;
}
//----------------------------------------------------------------------------
/**
Wrapper for lua_pcall that throws.
*/
static void pcall (lua_State* L, int nargs = 0, int nresults = 0, int msgh = 0)
{
int code = lua_pcall (L, nargs, nresults, msgh);
if (code != LUABRIDGE_LUA_OK)
Throw (LuaException (L, code));
}
//----------------------------------------------------------------------------
/**
Initializes error handling. Subsequent Lua errors are translated to C++ exceptions.
*/
static void enableExceptions (lua_State* L)
{
lua_atpanic (L, throwAtPanic);
}
protected:
void whatFromStack ()
{
if (lua_gettop (m_L) > 0)
{
char const* s = lua_tostring (m_L, -1);
m_what = s ? s : "";
}
else
{
// stack is empty
m_what = "missing error";
}
}
private:
static int throwAtPanic (lua_State* L)
{
throw LuaException (L, -1);
}
};
//----------------------------------------------------------------------------
/**
Initializes error handling. Subsequent Lua errors are translated to C++ exceptions.
*/
static void enableExceptions (lua_State* L)
{
LuaException::enableExceptions (L);
}
} // namespace luabridge

View File

@@ -1,151 +0,0 @@
//------------------------------------------------------------------------------
/*
https://github.com/vinniefalco/LuaBridge
Copyright 2012, Vinnie Falco <vinnie.falco@gmail.com>
Copyright 2007, Nathan Reed
License: The MIT License (http://www.opensource.org/licenses/mit-license.php)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
//==============================================================================
#pragma once
#include <cassert>
namespace luabridge {
// These are for Lua versions prior to 5.2.0.
//
#if LUA_VERSION_NUM < 502
inline int lua_absindex (lua_State* L, int idx)
{
if (idx > LUA_REGISTRYINDEX && idx < 0)
return lua_gettop (L) + idx + 1;
else
return idx;
}
inline void lua_rawgetp (lua_State* L, int idx, void const* p)
{
idx = lua_absindex (L, idx);
lua_pushlightuserdata (L, const_cast <void*> (p));
lua_rawget (L,idx);
}
inline void lua_rawsetp (lua_State* L, int idx, void const* p)
{
idx = lua_absindex (L, idx);
lua_pushlightuserdata (L, const_cast <void*> (p));
// put key behind value
lua_insert (L, -2);
lua_rawset (L, idx);
}
#define LUA_OPEQ 1
#define LUA_OPLT 2
#define LUA_OPLE 3
inline int lua_compare (lua_State* L, int idx1, int idx2, int op)
{
switch (op)
{
case LUA_OPEQ:
return lua_equal (L, idx1, idx2);
break;
case LUA_OPLT:
return lua_lessthan (L, idx1, idx2);
break;
case LUA_OPLE:
return lua_equal (L, idx1, idx2) || lua_lessthan (L, idx1, idx2);
break;
default:
return 0;
};
}
inline int get_length (lua_State* L, int idx)
{
return int (lua_objlen (L, idx));
}
#else
inline int get_length (lua_State* L, int idx)
{
lua_len (L, idx);
int len = int (luaL_checknumber (L, -1));
lua_pop (L, 1);
return len;
}
#endif
#ifndef LUA_OK
# define LUABRIDGE_LUA_OK 0
#else
# define LUABRIDGE_LUA_OK LUA_OK
#endif
/** Get a table value, bypassing metamethods.
*/
inline void rawgetfield (lua_State* L, int index, char const* key)
{
assert (lua_istable (L, index));
index = lua_absindex (L, index);
lua_pushstring (L, key);
lua_rawget (L, index);
}
/** Set a table value, bypassing metamethods.
*/
inline void rawsetfield (lua_State* L, int index, char const* key)
{
assert (lua_istable (L, index));
index = lua_absindex (L, index);
lua_pushstring (L, key);
lua_insert (L, -2);
lua_rawset (L, index);
}
/** Returns true if the value is a full userdata (not light).
*/
inline bool isfulluserdata (lua_State* L, int index)
{
return lua_isuserdata (L, index) && !lua_islightuserdata (L, index);
}
/** Test lua_State objects for global equality.
This can determine if two different lua_State objects really point
to the same global state, such as when using coroutines.
@note This is used for assertions.
*/
inline bool equalstates (lua_State* L1, lua_State* L2)
{
return lua_topointer (L1, LUA_REGISTRYINDEX) ==
lua_topointer (L2, LUA_REGISTRYINDEX);
}
} // namespace luabridge

View File

@@ -1,1051 +0,0 @@
//------------------------------------------------------------------------------
/*
https://github.com/vinniefalco/LuaBridge
Copyright 2018, Dmitry Tarakanov
Copyright 2012, Vinnie Falco <vinnie.falco@gmail.com>
Copyright 2008, Nigel Atkinson <suprapilot+LuaCode@gmail.com>
License: The MIT License (http://www.opensource.org/licenses/mit-license.php)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
//==============================================================================
#pragma once
#include <LuaBridge/detail/LuaException.h>
#include <LuaBridge/detail/Stack.h>
#include <iostream>
#include <string>
#include <vector>
#include <map>
namespace luabridge {
//------------------------------------------------------------------------------
/**
Type tag for representing LUA_TNIL.
Construct one of these using `Nil ()` to represent a Lua nil. This is faster
than creating a reference in the registry to nil. Example:
LuaRef t (LuaRef::createTable (L));
...
t ["k"] = Nil (); // assign nil
*/
struct Nil
{
};
//------------------------------------------------------------------------------
/**
Stack specialization for Nil.
*/
template <>
struct Stack <Nil>
{
static void push (lua_State* L, Nil)
{
lua_pushnil (L);
}
static bool isInstance (lua_State* L, int index)
{
return lua_type (L, index) == LUA_TTABLE;
}
};
/**
* Base class for LuaRef and table value proxy classes.
*/
template <class Impl, class LuaRef>
class LuaRefBase
{
protected:
//----------------------------------------------------------------------------
/**
Pop the Lua stack.
Pops the specified number of stack items on destruction. We use this
when returning objects, to avoid an explicit temporary variable, since
the destructor executes after the return statement. For example:
template <class U>
U cast (lua_State* L)
{
StackPop p (L, 1);
...
return U (); // dtor called after this line
}
@note The `StackPop` object must always be a named local variable.
*/
class StackPop
{
public:
/** Create a StackPop object.
@param count The number of stack entries to pop on destruction.
*/
StackPop (lua_State* L, int count)
: m_L (L)
, m_count (count)
{
}
~StackPop ()
{
lua_pop (m_L, m_count);
}
private:
lua_State* m_L;
int m_count;
};
friend struct Stack <LuaRef>;
//----------------------------------------------------------------------------
/**
Type tag for stack construction.
*/
struct FromStack { };
LuaRefBase (lua_State* L)
: m_L (L)
{
}
//----------------------------------------------------------------------------
/**
Create a reference to this ref.
This is used internally.
*/
int createRef () const
{
impl ().push ();
return luaL_ref (m_L, LUA_REGISTRYINDEX);
}
public:
//----------------------------------------------------------------------------
/**
converts to a string using luas tostring function
*/
std::string tostring () const
{
lua_getglobal (m_L, "tostring");
impl ().push ();
lua_call (m_L, 1, 1);
const char* str = lua_tostring (m_L, -1);
lua_pop (m_L, 1);
return str;
}
//----------------------------------------------------------------------------
/**
Print a text description of the value to a stream.
This is used for diagnostics.
*/
void print (std::ostream& os) const
{
switch (type ())
{
case LUA_TNIL:
os << "nil";
break;
case LUA_TNUMBER:
os << cast <lua_Number> ();
break;
case LUA_TBOOLEAN:
os << (cast <bool> () ? "true" : "false");
break;
case LUA_TSTRING:
os << '"' << cast <std::string> () << '"';
break;
case LUA_TTABLE:
os << "table: " << tostring ();
break;
case LUA_TFUNCTION:
os << "function: " << tostring ();
break;
case LUA_TUSERDATA:
os << "userdata: " << tostring ();
break;
case LUA_TTHREAD:
os << "thread: " << tostring ();
break;
case LUA_TLIGHTUSERDATA:
os << "lightuserdata: " << tostring ();
break;
default:
os << "unknown";
break;
}
}
//------------------------------------------------------------------------------
/**
Write a LuaRef to a stream.
This allows LuaRef and table proxies to work with streams.
*/
friend std::ostream& operator<< (std::ostream& os, LuaRefBase const& ref)
{
ref.print (os);
return os;
}
//============================================================================
//
// This group of member functions is mirrored in Proxy
//
/** Retrieve the lua_State associated with the reference.
*/
lua_State* state () const
{
return m_L;
}
//----------------------------------------------------------------------------
/**
Place the object onto the Lua stack.
*/
void push (lua_State* L) const
{
assert (equalstates (L, m_L));
(void) L;
impl ().push ();
}
//----------------------------------------------------------------------------
/**
Pop the top of Lua stack and assign the ref to m_ref
*/
void pop (lua_State* L)
{
assert (equalstates (L, m_L));
(void) L;
impl ().pop ();
}
//----------------------------------------------------------------------------
/**
Determine the object type.
The return values are the same as for `lua_type`.
*/
/** @{ */
int type () const
{
impl ().push ();
StackPop p (m_L, 1);
return lua_type (m_L, -1);
}
// should never happen
// bool isNone () const { return m_ref == LUA_NOREF; }
bool isNil () const { return type () == LUA_TNIL; }
bool isBool () const { return type () == LUA_TBOOLEAN; }
bool isNumber () const { return type () == LUA_TNUMBER; }
bool isString () const { return type () == LUA_TSTRING; }
bool isTable () const { return type () == LUA_TTABLE; }
bool isFunction () const { return type () == LUA_TFUNCTION; }
bool isUserdata () const { return type () == LUA_TUSERDATA; }
bool isThread () const { return type () == LUA_TTHREAD; }
bool isLightUserdata () const { return type () == LUA_TLIGHTUSERDATA; }
/** @} */
//----------------------------------------------------------------------------
/**
Perform an explicit conversion.
*/
template <class T>
T cast () const
{
StackPop p (m_L, 1);
impl ().push ();
return Stack <T>::get (m_L, -1);
}
//----------------------------------------------------------------------------
/**
Type check
*/
template <class T>
bool isInstance () const
{
StackPop p (m_L, 1);
impl ().push ();
return Stack <T>::isInstance (m_L, -1);
}
//----------------------------------------------------------------------------
/**
Universal implicit conversion operator.
NOTE: Visual Studio 2010 and 2012 have a bug where this function
is not used. See:
http://social.msdn.microsoft.com/Forums/en-US/vcgeneral/thread/e30b2664-a92d-445c-9db2-e8e0fbde2014
https://connect.microsoft.com/VisualStudio/feedback/details/771509/correct-code-doesnt-compile
// This code snippet fails to compile in vs2010,vs2012
struct S {
template <class T> operator T () const { return T (); }
};
int main () {
S () || false;
return 0;
}
*/
template <class T>
operator T () const
{
return cast <T> ();
}
//----------------------------------------------------------------------------
/**
Universal comparison operators.
*/
/** @{ */
template <class T>
bool operator== (T rhs) const
{
StackPop p (m_L, 2);
impl ().push ();
Stack <T>::push (m_L, rhs);
return lua_compare (m_L, -2, -1, LUA_OPEQ) == 1;
}
template <class T>
bool operator< (T rhs) const
{
StackPop p (m_L, 2);
impl ().push ();;
Stack <T>::push (m_L, rhs);
int lhsType = lua_type (m_L, -2);
int rhsType = lua_type (m_L, -1);
if (lhsType != rhsType)
{
return lhsType < rhsType;
}
return lua_compare (m_L, -2, -1, LUA_OPLT) == 1;
}
template <class T>
bool operator<= (T rhs) const
{
StackPop p (m_L, 2);
impl ().push ();;
Stack <T>::push (m_L, rhs);
int lhsType = lua_type (m_L, -2);
int rhsType = lua_type (m_L, -1);
if (lhsType != rhsType)
{
return lhsType <= rhsType;
}
return lua_compare (m_L, -2, -1, LUA_OPLE) == 1;
}
template <class T>
bool operator> (T rhs) const
{
StackPop p (m_L, 2);
impl ().push ();;
Stack <T>::push (m_L, rhs);
int lhsType = lua_type (m_L, -2);
int rhsType = lua_type (m_L, -1);
if (lhsType != rhsType)
{
return lhsType > rhsType;
}
return lua_compare (m_L, -1, -2, LUA_OPLT) == 1;
}
template <class T>
bool operator>= (T rhs) const
{
StackPop p (m_L, 2);
impl ().push ();;
Stack <T>::push (m_L, rhs);
int lhsType = lua_type (m_L, -2);
int rhsType = lua_type (m_L, -1);
if (lhsType != rhsType)
{
return lhsType >= rhsType;
}
return lua_compare (m_L, -1, -2, LUA_OPLE) == 1;
}
template <class T>
bool rawequal (T rhs) const
{
StackPop p (m_L, 2);
impl ().push ();;
Stack <T>::push (m_L, rhs);
return lua_rawequal (m_L, -1, -2) == 1;
}
/** @} */
//----------------------------------------------------------------------------
/**
Append a value to the table.
If the table is a sequence this will add another element to it.
*/
template <class T>
void append (T v) const
{
impl ().push ();;
Stack <T>::push (m_L, v);
luaL_ref (m_L, -2);
lua_pop (m_L, 1);
}
//----------------------------------------------------------------------------
/**
Call the length operator.
This is identical to applying the Lua # operator.
*/
int length () const
{
StackPop p (m_L, 1);
impl ().push ();;
return get_length (m_L, -1);
}
//----------------------------------------------------------------------------
/**
Call Lua code.
These overloads allow Lua code to be called with up to 8 parameters.
The return value is provided as a LuaRef (which may be LUA_REFNIL).
If an error occurs, a LuaException is thrown.
*/
/** @{ */
LuaRef operator() () const
{
impl ().push ();;
LuaException::pcall (m_L, 0, 1);
return LuaRef::fromStack (m_L);
}
template <class P1>
LuaRef operator() (P1 p1) const
{
impl ().push ();;
Stack <P1>::push (m_L, p1);
LuaException::pcall (m_L, 1, 1);
return LuaRef::fromStack (m_L);
}
template <class P1, class P2>
LuaRef operator() (P1 p1, P2 p2) const
{
impl ().push ();;
Stack <P1>::push (m_L, p1);
Stack <P2>::push (m_L, p2);
LuaException::pcall (m_L, 2, 1);
return LuaRef::fromStack (m_L);
}
template <class P1, class P2, class P3>
LuaRef operator() (P1 p1, P2 p2, P3 p3) const
{
impl ().push ();;
Stack <P1>::push (m_L, p1);
Stack <P2>::push (m_L, p2);
Stack <P3>::push (m_L, p3);
LuaException::pcall (m_L, 3, 1);
return LuaRef::fromStack (m_L);
}
template <class P1, class P2, class P3, class P4>
LuaRef operator() (P1 p1, P2 p2, P3 p3, P4 p4) const
{
impl ().push ();;
Stack <P1>::push (m_L, p1);
Stack <P2>::push (m_L, p2);
Stack <P3>::push (m_L, p3);
Stack <P4>::push (m_L, p4);
LuaException::pcall (m_L, 4, 1);
return LuaRef::fromStack (m_L);
}
template <class P1, class P2, class P3, class P4, class P5>
LuaRef operator() (P1 p1, P2 p2, P3 p3, P4 p4, P5 p5) const
{
impl ().push ();;
Stack <P1>::push (m_L, p1);
Stack <P2>::push (m_L, p2);
Stack <P3>::push (m_L, p3);
Stack <P4>::push (m_L, p4);
Stack <P5>::push (m_L, p5);
LuaException::pcall (m_L, 5, 1);
return LuaRef::fromStack (m_L);
}
template <class P1, class P2, class P3, class P4, class P5, class P6>
LuaRef operator() (P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6) const
{
impl ().push ();;
Stack <P1>::push (m_L, p1);
Stack <P2>::push (m_L, p2);
Stack <P3>::push (m_L, p3);
Stack <P4>::push (m_L, p4);
Stack <P5>::push (m_L, p5);
Stack <P6>::push (m_L, p6);
LuaException::pcall (m_L, 6, 1);
return LuaRef::fromStack (m_L);
}
template <class P1, class P2, class P3, class P4, class P5, class P6, class P7>
LuaRef operator() (P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7) const
{
impl ().push ();;
Stack <P1>::push (m_L, p1);
Stack <P2>::push (m_L, p2);
Stack <P3>::push (m_L, p3);
Stack <P4>::push (m_L, p4);
Stack <P5>::push (m_L, p5);
Stack <P6>::push (m_L, p6);
Stack <P7>::push (m_L, p7);
LuaException::pcall (m_L, 7, 1);
return LuaRef::fromStack (m_L);
}
template <class P1, class P2, class P3, class P4, class P5, class P6, class P7, class P8>
LuaRef operator() (P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7, P8 p8) const
{
impl ().push ();
Stack <P1>::push (m_L, p1);
Stack <P2>::push (m_L, p2);
Stack <P3>::push (m_L, p3);
Stack <P4>::push (m_L, p4);
Stack <P5>::push (m_L, p5);
Stack <P6>::push (m_L, p6);
Stack <P7>::push (m_L, p7);
Stack <P8>::push (m_L, p8);
LuaException::pcall (m_L, 8, 1);
return LuaRef::fromStack (m_L);
}
/** @} */
//============================================================================
protected:
lua_State* m_L;
private:
const Impl& impl () const
{
return static_cast <const Impl&> (*this);
}
Impl& impl ()
{
return static_cast <Impl&> (*this);
}
};
//------------------------------------------------------------------------------
/**
Lightweight reference to a Lua object.
The reference is maintained for the lifetime of the C++ object.
*/
class LuaRef : public LuaRefBase <LuaRef, LuaRef>
{
//----------------------------------------------------------------------------
/**
A proxy for representing table values.
*/
class Proxy : public LuaRefBase <Proxy, LuaRef>
{
friend class LuaRef;
public:
//--------------------------------------------------------------------------
/**
Construct a Proxy from a table value.
The table is in the registry, and the key is at the top of the stack.
The key is popped off the stack.
*/
Proxy (lua_State* L, int tableRef)
: LuaRefBase (L)
, m_tableRef (LUA_NOREF)
, m_keyRef (luaL_ref (L, LUA_REGISTRYINDEX))
{
lua_rawgeti (m_L, LUA_REGISTRYINDEX, tableRef);
m_tableRef = luaL_ref (L, LUA_REGISTRYINDEX);
}
//--------------------------------------------------------------------------
/**
Create a Proxy via copy constructor.
It is best to avoid code paths that invoke this, because it creates
an extra temporary Lua reference. Typically this is done by passing
the Proxy parameter as a `const` reference.
*/
Proxy (Proxy const& other)
: LuaRefBase (other.m_L)
, m_tableRef (LUA_NOREF)
, m_keyRef (LUA_NOREF)
{
lua_rawgeti (m_L, LUA_REGISTRYINDEX, other.m_tableRef);
m_tableRef = luaL_ref (m_L, LUA_REGISTRYINDEX);
lua_rawgeti (m_L, LUA_REGISTRYINDEX, other.m_keyRef);
m_keyRef = luaL_ref (m_L, LUA_REGISTRYINDEX);
}
//--------------------------------------------------------------------------
/**
Destroy the proxy.
This does not destroy the table value.
*/
~Proxy ()
{
luaL_unref (m_L, LUA_REGISTRYINDEX, m_keyRef);
luaL_unref (m_L, LUA_REGISTRYINDEX, m_tableRef);
}
//--------------------------------------------------------------------------
/**
Assign a new value to this table key.
This may invoke metamethods.
*/
template <class T>
Proxy& operator= (T v)
{
StackPop p (m_L, 1);
lua_rawgeti (m_L, LUA_REGISTRYINDEX, m_tableRef);
lua_rawgeti (m_L, LUA_REGISTRYINDEX, m_keyRef);
Stack <T>::push (m_L, v);
lua_settable (m_L, -3);
return *this;
}
//--------------------------------------------------------------------------
/**
Assign a new value to this table key.
The assignment is raw, no metamethods are invoked.
*/
template <class T>
Proxy& rawset (T v)
{
StackPop p (m_L, 1);
lua_rawgeti (m_L, LUA_REGISTRYINDEX, m_tableRef);
lua_rawgeti (m_L, LUA_REGISTRYINDEX, m_keyRef);
Stack <T>::push (m_L, v);
lua_rawset (m_L, -3);
return *this;
}
//--------------------------------------------------------------------------
/**
Push the value onto the Lua stack.
*/
using LuaRefBase::push;
void push () const
{
lua_rawgeti (m_L, LUA_REGISTRYINDEX, m_tableRef);
lua_rawgeti (m_L, LUA_REGISTRYINDEX, m_keyRef);
lua_gettable (m_L, -2);
lua_remove (m_L, -2); // remove the table
}
//--------------------------------------------------------------------------
/**
Access a table value using a key.
This invokes metamethods.
*/
template <class T>
Proxy operator[] (T key) const
{
return LuaRef (*this) [key];
}
//--------------------------------------------------------------------------
/**
Access a table value using a key.
The operation is raw, metamethods are not invoked. The result is
passed by value and may not be modified.
*/
template <class T>
LuaRef rawget (T key) const
{
return LuaRef (*this).rawget (key);
}
private:
int m_tableRef;
int m_keyRef;
};
friend struct Stack <Proxy>;
friend struct Stack <Proxy&>;
//----------------------------------------------------------------------------
/**
Create a reference to an object at the top of the Lua stack and pop it.
This constructor is private and not invoked directly.
Instead, use the `fromStack` function.
@note The object is popped.
*/
LuaRef (lua_State* L, FromStack)
: LuaRefBase (L)
, m_ref (luaL_ref (m_L, LUA_REGISTRYINDEX))
{
}
//----------------------------------------------------------------------------
/**
Create a reference to an object on the Lua stack.
This constructor is private and not invoked directly.
Instead, use the `fromStack` function.
@note The object is not popped.
*/
LuaRef (lua_State* L, int index, FromStack)
: LuaRefBase (L)
, m_ref (LUA_NOREF)
{
lua_pushvalue (m_L, index);
m_ref = luaL_ref (m_L, LUA_REGISTRYINDEX);
}
public:
//----------------------------------------------------------------------------
/**
Create a nil reference.
The LuaRef may be assigned later.
*/
LuaRef (lua_State* L)
: LuaRefBase (L)
, m_ref (LUA_NOREF)
{
}
//----------------------------------------------------------------------------
/**
Create a reference to a value.
*/
template <class T>
LuaRef (lua_State* L, T v)
: LuaRefBase (L)
, m_ref (LUA_NOREF)
{
Stack <T>::push (m_L, v);
m_ref = luaL_ref (m_L, LUA_REGISTRYINDEX);
}
//----------------------------------------------------------------------------
/**
Create a reference to a table value.
*/
LuaRef (Proxy const& v)
: LuaRefBase (v.state ())
, m_ref (v.createRef ())
{
}
//----------------------------------------------------------------------------
/**
Create a new reference to an existing reference.
*/
LuaRef (LuaRef const& other)
: LuaRefBase (other.m_L)
, m_ref (other.createRef ())
{
}
//----------------------------------------------------------------------------
/**
Destroy a reference.
The corresponding Lua registry reference will be released.
@note If the state refers to a thread, it is the responsibility of the
caller to ensure that the thread still exists when the LuaRef
is destroyed.
*/
~LuaRef ()
{
luaL_unref (m_L, LUA_REGISTRYINDEX, m_ref);
}
//----------------------------------------------------------------------------
/**
Return a LuaRef from a top stack item.
The stack item is not popped.
*/
static LuaRef fromStack (lua_State* L)
{
return LuaRef (L, FromStack ());
}
//----------------------------------------------------------------------------
/**
Return a LuaRef from a stack item.
The stack item is not popped.
*/
static LuaRef fromStack (lua_State* L, int index)
{
lua_pushvalue (L, index);
return LuaRef (L, FromStack ());
}
//----------------------------------------------------------------------------
/**
Create a new empty table and return a reference to it.
It is also possible to use the free function `newTable`.
@see ::luabridge::newTable
*/
static LuaRef newTable (lua_State* L)
{
lua_newtable (L);
return LuaRef (L, FromStack ());
}
//----------------------------------------------------------------------------
/**
Return a reference to a named global.
It is also possible to use the free function `getGlobal`.
@see ::luabridge::getGlobal
*/
static LuaRef getGlobal (lua_State *L, char const* name)
{
lua_getglobal (L, name);
return LuaRef (L, FromStack ());
}
//----------------------------------------------------------------------------
/**
Assign another LuaRef to this LuaRef.
*/
LuaRef& operator= (LuaRef const& rhs)
{
LuaRef ref (rhs);
swap (ref);
return *this;
}
//----------------------------------------------------------------------------
/**
Assign Proxy to this LuaRef.
*/
LuaRef& operator= (LuaRef::Proxy const& rhs)
{
LuaRef ref (rhs);
swap (ref);
return *this;
}
//----------------------------------------------------------------------------
/**
Assign nil to this LuaRef.
*/
LuaRef& operator= (Nil const&)
{
LuaRef ref (m_L);
swap (ref);
return *this;
}
//----------------------------------------------------------------------------
/**
Assign a different value to this LuaRef.
*/
template <class T>
LuaRef& operator= (T rhs)
{
LuaRef ref (m_L, rhs);
swap (ref);
return *this;
}
//----------------------------------------------------------------------------
/**
Place the object onto the Lua stack.
*/
using LuaRefBase::push;
void push () const
{
lua_rawgeti (m_L, LUA_REGISTRYINDEX, m_ref);
}
//----------------------------------------------------------------------------
/**
Pop the top of Lua stack and assign the ref to m_ref
*/
void pop ()
{
luaL_unref (m_L, LUA_REGISTRYINDEX, m_ref);
m_ref = luaL_ref (m_L, LUA_REGISTRYINDEX);
}
//----------------------------------------------------------------------------
/**
Access a table value using a key.
This invokes metamethods.
*/
template <class T>
Proxy operator[] (T key) const
{
Stack <T>::push (m_L, key);
return Proxy (m_L, m_ref);
}
//--------------------------------------------------------------------------
/**
Access a table value using a key.
The operation is raw, metamethods are not invoked. The result is
passed by value and may not be modified.
*/
template <class T>
LuaRef rawget (T key) const
{
StackPop (m_L, 1);
push (m_L);
Stack <T>::push (m_L, key);
lua_rawget (m_L, -2);
return LuaRef (m_L, FromStack ());
}
private:
void swap (LuaRef& other)
{
std::swap (m_L, other.m_L);
std::swap (m_ref, other.m_ref);
}
int m_ref;
};
//------------------------------------------------------------------------------
/**
* Stack specialization for `LuaRef`.
*/
template <>
struct Stack <LuaRef>
{
// The value is const& to prevent a copy construction.
//
static void push (lua_State* L, LuaRef const& v)
{
v.push (L);
}
static LuaRef get (lua_State* L, int index)
{
return LuaRef::fromStack (L, index);
}
};
//------------------------------------------------------------------------------
/**
* Stack specialization for `Proxy`.
*/
template <>
struct Stack <LuaRef::Proxy>
{
// The value is const& to prevent a copy construction.
//
static void push (lua_State* L, LuaRef::Proxy const& v)
{
v.push (L);
}
};
//------------------------------------------------------------------------------
/**
Create a reference to a new, empty table.
This is a syntactic abbreviation for LuaRef::newTable ().
*/
inline LuaRef newTable (lua_State* L)
{
return LuaRef::newTable (L);
}
//------------------------------------------------------------------------------
/**
Create a reference to a value in the global table.
This is a syntactic abbreviation for LuaRef::getGlobal ().
*/
inline LuaRef getGlobal (lua_State *L, char const* name)
{
return LuaRef::getGlobal (L, name);
}
//------------------------------------------------------------------------------
// more C++-like cast syntax
//
template <class T>
T LuaRef_cast (LuaRef const& lr)
{
return lr.cast <T> ();
}
} // namespace luabridge

View File

@@ -1,1252 +0,0 @@
//------------------------------------------------------------------------------
/*
https://github.com/vinniefalco/LuaBridge
Copyright 2019, Dmitry Tarakanov
Copyright 2012, Vinnie Falco <vinnie.falco@gmail.com>
Copyright 2007, Nathan Reed
License: The MIT License (http://www.opensource.org/licenses/mit-license.php)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
//==============================================================================
#pragma once
#include <LuaBridge/detail/Config.h>
#include <LuaBridge/detail/ClassInfo.h>
#include <LuaBridge/detail/LuaException.h>
#include <LuaBridge/detail/Security.h>
#include <LuaBridge/detail/TypeTraits.h>
#include <stdexcept>
#include <string>
namespace luabridge {
namespace detail {
/**
* Base for class and namespace registration.
* Maintains Lua stack in the proper state.
* Once beginNamespace, beginClass or deriveClass is called the parent
* object upon its destruction may no longer clear the Lua stack.
* Then endNamespace or endClass is called, a new parent is created
* and the child transfers the responsibility for clearing stack to it.
* So there can be maximum one "active" registrar object.
*/
class Registrar
{
protected:
lua_State* const L;
int mutable m_stackSize;
Registrar (lua_State* L)
: L (L)
, m_stackSize (0)
{
}
Registrar (const Registrar& rhs)
: L (rhs.L)
, m_stackSize (rhs.m_stackSize)
{
rhs.m_stackSize = 0;
}
#ifndef _MSC_VER
// MS compiler thinks it's the 2nd copy ctor
Registrar(Registrar& rhs)
: L (rhs.L)
, m_stackSize (rhs.m_stackSize)
{
rhs.m_stackSize = 0;
}
#endif // ifndef _MSC_VER
Registrar& operator= (const Registrar& rhs)
{
Registrar tmp (rhs);
std::swap (m_stackSize, tmp.m_stackSize);
return *this;
}
~Registrar ()
{
if (m_stackSize > 0)
{
assert (m_stackSize <= lua_gettop (L));
lua_pop (L, m_stackSize);
}
}
void assertIsActive () const
{
if (m_stackSize == 0)
{
throw std::logic_error ("Unable to continue registration");
}
}
};
} // namespace detail
/** Provides C++ to Lua registration capabilities.
This class is not instantiated directly, call `getGlobalNamespace` to start
the registration process.
*/
class Namespace : public detail::Registrar
{
//============================================================================
/**
Error reporting.
VF: This function looks handy, why aren't we using it?
*/
#if 0
static int luaError (lua_State* L, std::string message)
{
assert (lua_isstring (L, lua_upvalueindex (1)));
std::string s;
// Get information on the caller's caller to format the message,
// so the error appears to originate from the Lua source.
lua_Debug ar;
int result = lua_getstack (L, 2, &ar);
if (result != 0)
{
lua_getinfo (L, "Sl", &ar);
s = ar.short_src;
if (ar.currentline != -1)
{
// poor mans int to string to avoid <strstrream>.
lua_pushnumber (L, ar.currentline);
s = s + ":" + lua_tostring (L, -1) + ": ";
lua_pop (L, 1);
}
}
s = s + message;
return luaL_error (L, s.c_str ());
}
#endif
/**
Factored base to reduce template instantiations.
*/
class ClassBase : public detail::Registrar
{
public:
explicit ClassBase (Namespace& parent)
: Registrar (parent)
{
}
using Registrar::operator=;
protected:
//--------------------------------------------------------------------------
/**
Create the const table.
*/
void createConstTable (const char* name, bool trueConst = true)
{
std::string type_name = std::string (trueConst ? "const " : "") + name;
// Stack: namespace table (ns)
lua_newtable (L); // Stack: ns, const table (co)
lua_pushvalue (L, -1); // Stack: ns, co, co
lua_setmetatable (L, -2); // co.__metatable = co. Stack: ns, co
lua_pushstring (L, type_name.c_str ());
lua_rawsetp (L, -2, getTypeKey ()); // co [typeKey] = name. Stack: ns, co
lua_pushcfunction (L, &CFunc::indexMetaMethod);
rawsetfield (L, -2, "__index");
lua_pushcfunction (L, &CFunc::newindexObjectMetaMethod);
rawsetfield (L, -2, "__newindex");
lua_newtable (L);
lua_rawsetp (L, -2, getPropgetKey ());
if (Security::hideMetatables ())
{
lua_pushnil (L);
rawsetfield (L, -2, "__metatable");
}
}
//--------------------------------------------------------------------------
/**
Create the class table.
The Lua stack should have the const table on top.
*/
void createClassTable (char const* name)
{
// Stack: namespace table (ns), const table (co)
// Class table is the same as const table except the propset table
createConstTable (name, false); // Stack: ns, co, cl
lua_newtable (L); // Stack: ns, co, cl, propset table (ps)
lua_rawsetp (L, -2, getPropsetKey ()); // cl [propsetKey] = ps. Stack: ns, co, cl
lua_pushvalue (L, -2); // Stack: ns, co, cl, co
lua_rawsetp(L, -2, getConstKey ()); // cl [constKey] = co. Stack: ns, co, cl
lua_pushvalue (L, -1); // Stack: ns, co, cl, cl
lua_rawsetp (L, -3, getClassKey ()); // co [classKey] = cl. Stack: ns, co, cl
}
//--------------------------------------------------------------------------
/**
Create the static table.
*/
void createStaticTable (char const* name)
{
// Stack: namespace table (ns), const table (co), class table (cl)
lua_newtable (L); // Stack: ns, co, cl, visible static table (vst)
lua_newtable (L); // Stack: ns, co, cl, st, static metatable (st)
lua_pushvalue (L, -1); // Stack: ns, co, cl, vst, st, st
lua_setmetatable (L, -3); // st.__metatable = mt. Stack: ns, co, cl, vst, st
lua_insert (L, -2); // Stack: ns, co, cl, st, vst
rawsetfield (L, -5, name); // ns [name] = vst. Stack: ns, co, cl, st
#if 0
lua_pushlightuserdata (L, this);
lua_pushcclosure (L, &tostringMetaMethod, 1);
rawsetfield (L, -2, "__tostring");
#endif
lua_pushcfunction (L, &CFunc::indexMetaMethod);
rawsetfield (L, -2, "__index");
lua_pushcfunction (L, &CFunc::newindexStaticMetaMethod);
rawsetfield (L, -2, "__newindex");
lua_newtable (L); // Stack: ns, co, cl, st, proget table (pg)
lua_rawsetp (L, -2, getPropgetKey ()); // st [propgetKey] = pg. Stack: ns, co, cl, st
lua_newtable (L); // Stack: ns, co, cl, st, propset table (ps)
lua_rawsetp (L, -2, getPropsetKey ()); // st [propsetKey] = pg. Stack: ns, co, cl, st
lua_pushvalue (L, -2); // Stack: ns, co, cl, st, cl
lua_rawsetp(L, -2, getClassKey()); // st [classKey] = cl. Stack: ns, co, cl, st
if (Security::hideMetatables ())
{
lua_pushnil (L);
rawsetfield (L, -2, "__metatable");
}
}
//==========================================================================
/**
lua_CFunction to construct a class object wrapped in a container.
*/
template <class Params, class C>
static int ctorContainerProxy (lua_State* L)
{
typedef typename ContainerTraits <C>::Type T;
ArgList <Params, 2> args (L);
T* const p = Constructor <T, Params>::call (args);
UserdataSharedHelper <C, false>::push (L, p);
return 1;
}
//--------------------------------------------------------------------------
/**
lua_CFunction to construct a class object in-place in the userdata.
*/
template <class Params, class T>
static int ctorPlacementProxy (lua_State* L)
{
ArgList <Params, 2> args (L);
UserdataValue <T>* value = UserdataValue <T>::place (L);
Constructor <T, Params>::call (value->getObject (), args);
value->commit ();
return 1;
}
void assertStackState () const
{
// Stack: const table (co), class table (cl), static table (st)
assert (lua_istable (L, -3));
assert (lua_istable (L, -2));
assert (lua_istable (L, -1));
}
};
//============================================================================
//
// Class
//
//============================================================================
/**
Provides a class registration in a lua_State.
After construction the Lua stack holds these objects:
-1 static table
-2 class table
-3 const table
-4 enclosing namespace table
*/
template <class T>
class Class : public ClassBase
{
public:
//==========================================================================
/**
Register a new class or add to an existing class registration.
*/
Class (char const* name, Namespace& parent)
: ClassBase (parent)
{
assert (lua_istable (L, -1)); // Stack: namespace table (ns)
rawgetfield (L, -1, name); // Stack: ns, static table (st) | nil
if (lua_isnil (L, -1)) // Stack: ns, nil
{
lua_pop (L, 1); // Stack: ns
createConstTable (name); // Stack: ns, const table (co)
lua_pushcfunction (L, &CFunc::gcMetaMethod <T>); // Stack: ns, co, function
rawsetfield (L, -2, "__gc"); // co ["__gc"] = function. Stack: ns, co
++m_stackSize;
createClassTable (name); // Stack: ns, co, class table (cl)
lua_pushcfunction (L, &CFunc::gcMetaMethod <T>); // Stack: ns, co, cl, function
rawsetfield (L, -2, "__gc"); // cl ["__gc"] = function. Stack: ns, co, cl
++m_stackSize;
createStaticTable (name); // Stack: ns, co, cl, st
++m_stackSize;
// Map T back to its tables.
lua_pushvalue (L, -1); // Stack: ns, co, cl, st, st
lua_rawsetp (L, LUA_REGISTRYINDEX, ClassInfo <T>::getStaticKey ()); // Stack: ns, co, cl, st
lua_pushvalue (L, -2); // Stack: ns, co, cl, st, cl
lua_rawsetp (L, LUA_REGISTRYINDEX, ClassInfo <T>::getClassKey ()); // Stack: ns, co, cl, st
lua_pushvalue (L, -3); // Stack: ns, co, cl, st, co
lua_rawsetp (L, LUA_REGISTRYINDEX, ClassInfo <T>::getConstKey ()); // Stack: ns, co, cl, st
}
else
{
assert (lua_istable (L, -1)); // Stack: ns, st
++m_stackSize;
// Map T back from its stored tables
lua_rawgetp (L, LUA_REGISTRYINDEX, ClassInfo <T>::getConstKey ()); // Stack: ns, st, co
lua_insert (L, -2); // Stack: ns, co, st
++m_stackSize;
lua_rawgetp (L, LUA_REGISTRYINDEX, ClassInfo <T>::getClassKey ()); // Stack: ns, co, st, cl
lua_insert (L, -2); // Stack: ns, co, cl, st
++m_stackSize;
}
}
//==========================================================================
/**
Derive a new class.
*/
Class (char const* name, Namespace& parent, void const* const staticKey)
: ClassBase (parent)
{
assert (lua_istable (L, -1)); // Stack: namespace table (ns)
createConstTable (name); // Stack: ns, const table (co)
lua_pushcfunction (L, &CFunc::gcMetaMethod <T>); // Stack: ns, co, function
rawsetfield (L, -2, "__gc"); // co ["__gc"] = function. Stack: ns, co
++m_stackSize;
createClassTable (name); // Stack: ns, co, class table (cl)
lua_pushcfunction (L, &CFunc::gcMetaMethod <T>); // Stack: ns, co, cl, function
rawsetfield (L, -2, "__gc"); // cl ["__gc"] = function. Stack: ns, co, cl
++m_stackSize;
createStaticTable (name); // Stack: ns, co, cl, st
++m_stackSize;
lua_rawgetp (L, LUA_REGISTRYINDEX, staticKey); // Stack: ns, co, cl, st, parent st (pst) | nil
if (lua_isnil (L, -1)) // Stack: ns, co, cl, st, nil
{
++m_stackSize;
throw std::runtime_error ("Base class is not registered");
}
assert (lua_istable (L, -1)); // Stack: ns, co, cl, st, pst
lua_rawgetp (L, -1, getClassKey ()); // Stack: ns, co, cl, st, pst, parent cl (pcl)
assert (lua_istable (L, -1));
lua_rawgetp (L, -1, getConstKey ()); // Stack: ns, co, cl, st, pst, pcl, parent co (pco)
assert (lua_istable (L, -1));
lua_rawsetp (L, -6, getParentKey ()); // co [parentKey] = pco. Stack: ns, co, cl, st, pst, pcl
lua_rawsetp (L, -4, getParentKey ()); // cl [parentKey] = pcl. Stack: ns, co, cl, st, pst
lua_rawsetp (L, -2, getParentKey ()); // st [parentKey] = pst. Stack: ns, co, cl, st
lua_pushvalue (L, -1); // Stack: ns, co, cl, st, st
lua_rawsetp (L, LUA_REGISTRYINDEX, ClassInfo <T>::getStaticKey ()); // Stack: ns, co, cl, st
lua_pushvalue (L, -2); // Stack: ns, co, cl, st, cl
lua_rawsetp (L, LUA_REGISTRYINDEX, ClassInfo <T>::getClassKey ()); // Stack: ns, co, cl, st
lua_pushvalue (L, -3); // Stack: ns, co, cl, st, co
lua_rawsetp (L, LUA_REGISTRYINDEX, ClassInfo <T>::getConstKey ()); // Stack: ns, co, cl, st
}
//--------------------------------------------------------------------------
/**
Continue registration in the enclosing namespace.
*/
Namespace endClass ()
{
assert (m_stackSize > 3);
m_stackSize -= 3;
lua_pop (L, 3);
return Namespace (*this);
}
//--------------------------------------------------------------------------
/**
Add or replace a static data member.
*/
template <class U>
Class <T>& addStaticProperty (char const* name, U* pu, bool isWritable = true)
{
return addStaticData (name, pu, isWritable);
}
//--------------------------------------------------------------------------
/**
Add or replace a static data member.
*/
template <class U>
Class <T>& addStaticData (char const* name, U* pu, bool isWritable = true)
{
assertStackState (); // Stack: const table (co), class table (cl), static table (st)
lua_pushlightuserdata (L, pu); // Stack: co, cl, st, pointer
lua_pushcclosure (L, &CFunc::getVariable <U>, 1); // Stack: co, cl, st, getter
CFunc::addGetter (L, name, -2); // Stack: co, cl, st
if (isWritable)
{
lua_pushlightuserdata (L, pu); // Stack: co, cl, st, ps, pointer
lua_pushcclosure (L, &CFunc::setVariable <U>, 1); // Stack: co, cl, st, ps, setter
}
else
{
lua_pushstring (L, name); // Stack: co, cl, st, name
lua_pushcclosure (L, &CFunc::readOnlyError, 1); // Stack: co, cl, st, error_fn
}
CFunc::addSetter (L, name, -2); // Stack: co, cl, st
return *this;
}
//--------------------------------------------------------------------------
/**
Add or replace a static property member.
If the set function is null, the property is read-only.
*/
template <class U>
Class <T>& addStaticProperty (char const* name, U (*get) (), void (*set) (U) = 0)
{
assertStackState (); // Stack: const table (co), class table (cl), static table (st)
lua_pushlightuserdata (L, reinterpret_cast <void*> (get)); // Stack: co, cl, st, function ptr
lua_pushcclosure (L, &CFunc::Call <U (*) ()>::f, 1); // Stack: co, cl, st, getter
CFunc::addGetter (L, name, -2); // Stack: co, cl, st
if (set != 0)
{
lua_pushlightuserdata (L, reinterpret_cast <void*> (set)); // Stack: co, cl, st, function ptr
lua_pushcclosure (L, &CFunc::Call <void (*) (U)>::f, 1); // Stack: co, cl, st, setter
}
else
{
lua_pushstring (L, name); // Stack: co, cl, st, ps, name
lua_pushcclosure (L, &CFunc::readOnlyError, 1); // Stack: co, cl, st, error_fn
}
CFunc::addSetter (L, name, -2); // Stack: co, cl, st
return *this;
}
//--------------------------------------------------------------------------
/**
Add or replace a static member function.
*/
template <class FP>
Class <T>& addStaticFunction (char const* name, FP const fp)
{
assertStackState (); // Stack: const table (co), class table (cl), static table (st)
lua_pushlightuserdata (L, reinterpret_cast <void*> (fp)); // Stack: co, cl, st, function ptr
lua_pushcclosure (L, &CFunc::Call <FP>::f, 1); // co, cl, st, function
rawsetfield (L, -2, name); // co, cl, st
return *this;
}
//--------------------------------------------------------------------------
/**
Add or replace a lua_CFunction.
*/
Class <T>& addStaticFunction (char const* name, int (*const fp) (lua_State*))
{
return addStaticCFunction (name, fp);
}
//--------------------------------------------------------------------------
/**
Add or replace a lua_CFunction.
*/
Class <T>& addStaticCFunction (char const* name, int (*const fp) (lua_State*))
{
assertStackState (); // Stack: const table (co), class table (cl), static table (st)
lua_pushcfunction (L, fp); // co, cl, st, function
rawsetfield (L, -2, name); // co, cl, st
return *this;
}
//--------------------------------------------------------------------------
/**
Add or replace a data member.
*/
template <class U>
Class <T>& addProperty (char const* name, U T::* mp, bool isWritable = true)
{
return addData (name, mp, isWritable);
}
//--------------------------------------------------------------------------
/**
Add or replace a data member.
*/
template <class U>
Class <T>& addData (char const* name, U T::* mp, bool isWritable = true)
{
assertStackState (); // Stack: const table (co), class table (cl), static table (st)
typedef const U T::*mp_t;
new (lua_newuserdata (L, sizeof (mp_t))) mp_t (mp); // Stack: co, cl, st, field ptr
lua_pushcclosure (L, &CFunc::getProperty <T, U>, 1); // Stack: co, cl, st, getter
lua_pushvalue (L, -1); // Stack: co, cl, st, getter, getter
CFunc::addGetter (L, name, -5); // Stack: co, cl, st, getter
CFunc::addGetter (L, name, -3); // Stack: co, cl, st
if (isWritable)
{
new (lua_newuserdata (L, sizeof (mp_t))) mp_t (mp); // Stack: co, cl, st, field ptr
lua_pushcclosure (L, &CFunc::setProperty <T, U>, 1); // Stack: co, cl, st, setter
CFunc::addSetter (L, name, -3); // Stack: co, cl, st
}
return *this;
}
//--------------------------------------------------------------------------
/**
Add or replace a property member.
*/
template <class TG, class TS = TG>
Class <T>& addProperty (char const* name, TG (T::* get) () const, void (T::* set) (TS) = 0)
{
assertStackState (); // Stack: const table (co), class table (cl), static table (st)
typedef TG (T::*get_t) () const;
new (lua_newuserdata (L, sizeof (get_t))) get_t (get); // Stack: co, cl, st, funcion ptr
lua_pushcclosure (L, &CFunc::CallConstMember <get_t>::f, 1); // Stack: co, cl, st, getter
lua_pushvalue (L, -1); // Stack: co, cl, st, getter, getter
CFunc::addGetter (L, name, -5); // Stack: co, cl, st, getter
CFunc::addGetter (L, name, -3); // Stack: co, cl, st
if (set != 0)
{
typedef void (T::* set_t) (TS);
new (lua_newuserdata (L, sizeof (set_t))) set_t (set); // Stack: co, cl, st, function ptr
lua_pushcclosure (L, &CFunc::CallMember <set_t>::f, 1); // Stack: co, cl, st, setter
CFunc::addSetter (L, name, -3); // Stack: co, cl, st
}
return *this;
}
//--------------------------------------------------------------------------
/**
Add or replace a property member.
*/
template <class TG, class TS = TG>
Class <T>& addProperty (char const* name, TG (T::* get) (lua_State*) const, void (T::* set) (TS, lua_State*) = 0)
{
assertStackState (); // Stack: const table (co), class table (cl), static table (st)
typedef TG (T::*get_t) (lua_State*) const;
new (lua_newuserdata (L, sizeof (get_t))) get_t (get); // Stack: co, cl, st, funcion ptr
lua_pushcclosure (L, &CFunc::CallConstMember <get_t>::f, 1); // Stack: co, cl, st, getter
lua_pushvalue (L, -1); // Stack: co, cl, st, getter, getter
CFunc::addGetter (L, name, -5); // Stack: co, cl, st, getter
CFunc::addGetter (L, name, -3); // Stack: co, cl, st
if (set != 0)
{
typedef void (T::* set_t) (TS, lua_State*);
new (lua_newuserdata (L, sizeof (set_t))) set_t (set); // Stack: co, cl, st, function ptr
lua_pushcclosure (L, &CFunc::CallMember <set_t>::f, 1); // Stack: co, cl, st, setter
CFunc::addSetter (L, name, -3); // Stack: co, cl, st
}
return *this;
}
//--------------------------------------------------------------------------
/**
Add or replace a property member, by proxy.
When a class is closed for modification and does not provide (or cannot
provide) the function signatures necessary to implement get or set for
a property, this will allow non-member functions act as proxies.
Both the get and the set functions require a T const* and T* in the first
argument respectively.
*/
template <class TG, class TS = TG>
Class <T>& addProperty (char const* name, TG (*get) (T const*), void (*set) (T*, TS) = 0)
{
assertStackState (); // Stack: const table (co), class table (cl), static table (st)
lua_pushlightuserdata (L, reinterpret_cast <void*> (get)); // Stack: co, cl, st, function ptr
lua_pushcclosure (L, &CFunc::Call <TG (*) (const T*)>::f, 1); // Stack: co, cl, st, getter
lua_pushvalue (L, -1); // Stack: co, cl, st,, getter, getter
CFunc::addGetter (L, name, -5); // Stack: co, cl, st, getter
CFunc::addGetter (L, name, -3); // Stack: co, cl, st
if (set != 0)
{
lua_pushlightuserdata (L, reinterpret_cast <void*> (set)); // Stack: co, cl, st, function ptr
lua_pushcclosure (L, &CFunc::Call <void (*) (T*, TS)>::f, 1); // Stack: co, cl, st, setter
CFunc::addSetter (L, name, -3); // Stack: co, cl, st
}
return *this;
}
//--------------------------------------------------------------------------
/**
Add or replace a property member, by proxy C-function.
When a class is closed for modification and does not provide (or cannot
provide) the function signatures necessary to implement get or set for
a property, this will allow non-member functions act as proxies.
The object userdata ('this') value is at the index 1.
The new value for set function is at the index 2.
*/
Class <T>& addProperty (char const* name, int (*get) (lua_State*), int (*set) (lua_State*) = 0)
{
assertStackState (); // Stack: const table (co), class table (cl), static table (st)
lua_pushcfunction (L, get);
lua_pushvalue (L, -1); // Stack: co, cl, st,, getter, getter
CFunc::addGetter (L, name, -5); // Stack: co, cl, st,, getter
CFunc::addGetter (L, name, -3); // Stack: co, cl, st,
if (set != 0)
{
lua_pushcfunction (L, set);
CFunc::addSetter (L, name, -3); // Stack: co, cl, st,
}
return *this;
}
#ifdef LUABRIDGE_CXX11
template <class TG, class TS = TG>
Class <T>& addProperty (char const* name,
std::function <TG (const T*)> get,
std::function <void (T*, TS)> set = nullptr)
{
using GetType = decltype (get);
new (lua_newuserdata (L, sizeof (get))) GetType (std::move (get)); // Stack: co, cl, st, function userdata (ud)
lua_newtable (L); // Stack: co, cl, st, ud, ud metatable (mt)
lua_pushcfunction (L, &CFunc::gcMetaMethodAny <GetType>); // Stack: co, cl, st, ud, mt, gc function
rawsetfield (L, -2, "__gc"); // Stack: co, cl, st, ud, mt
lua_setmetatable (L, -2); // Stack: co, cl, st, ud
lua_pushcclosure (L, &CFunc::CallProxyFunctor <GetType>::f, 1); // Stack: co, cl, st, getter
lua_pushvalue (L, -1); // Stack: co, cl, st, getter, getter
CFunc::addGetter (L, name, -4); // Stack: co, cl, st, getter
CFunc::addGetter (L, name, -4); // Stack: co, cl, st
if (set != nullptr)
{
using SetType = decltype (set);
new (lua_newuserdata (L, sizeof (set))) SetType (std::move (set)); // Stack: co, cl, st, function userdata (ud)
lua_newtable (L); // Stack: co, cl, st, ud, ud metatable (mt)
lua_pushcfunction (L, &CFunc::gcMetaMethodAny <SetType>); // Stack: co, cl, st, ud, mt, gc function
rawsetfield (L, -2, "__gc"); // Stack: co, cl, st, ud, mt
lua_setmetatable (L, -2); // Stack: co, cl, st, ud
lua_pushcclosure (L, &CFunc::CallProxyFunctor <SetType>::f, 1); // Stack: co, cl, st, setter
CFunc::addSetter (L, name, -3); // Stack: co, cl, st
}
return *this;
}
#endif // LUABRIDGE_CXX11
#ifndef LUABRIDGE_CXX11
//--------------------------------------------------------------------------
/**
Add or replace a member function.
*/
template <class MemFn>
Class <T>& addFunction (char const* name, MemFn mf)
{
assertStackState (); // Stack: const table (co), class table (cl), static table (st)
static const std::string GC = "__gc";
if (name == GC)
{
throw std::logic_error (GC + " metamethod registration is forbidden");
}
CFunc::CallMemberFunctionHelper <MemFn, FuncTraits <MemFn>::isConstMemberFunction>::add (L, name, mf);
return *this;
}
#else // ifndef LUABRIDGE_CXX11
//--------------------------------------------------------------------------
/**
Add or replace a member function by std::function.
*/
template <class ReturnType, class... Params>
Class <T>& addFunction (char const* name, std::function <ReturnType (T*, Params...)> function)
{
assertStackState (); // Stack: const table (co), class table (cl), static table (st)
using FnType = decltype (function);
new (lua_newuserdata (L, sizeof (function))) FnType (std::move (function)); // Stack: co, cl, st, function userdata (ud)
lua_newtable (L); // Stack: co, cl, st, ud, ud metatable (mt)
lua_pushcfunction (L, &CFunc::gcMetaMethodAny <FnType>); // Stack: co, cl, st, ud, mt, gc function
rawsetfield (L, -2, "__gc"); // Stack: co, cl, st, ud, mt
lua_setmetatable (L, -2); // Stack: co, cl, st, ud
lua_pushcclosure (L, &CFunc::CallProxyFunctor <FnType>::f, 1); // Stack: co, cl, st, function
rawsetfield (L, -3, name); // Stack: co, cl, st
return *this;
}
//--------------------------------------------------------------------------
/**
Add or replace a const member function by std::function.
*/
template <class ReturnType, class... Params>
Class <T>& addFunction (char const* name, std::function <ReturnType (const T*, Params...)> function)
{
assertStackState (); // Stack: const table (co), class table (cl), static table (st)
using FnType = decltype (function);
new (lua_newuserdata (L, sizeof (function))) FnType (std::move (function)); // Stack: co, cl, st, function userdata (ud)
lua_newtable (L); // Stack: co, cl, st, ud, ud metatable (mt)
lua_pushcfunction (L, &CFunc::gcMetaMethodAny <FnType>); // Stack: co, cl, st, ud, mt, gc function
rawsetfield (L, -2, "__gc"); // Stack: co, cl, st, ud, mt
lua_setmetatable (L, -2); // Stack: co, cl, st, ud
lua_pushcclosure (L, &CFunc::CallProxyFunctor <FnType>::f, 1); // Stack: co, cl, st, function
lua_pushvalue (L, -1); // Stack: co, cl, st, function, function
rawsetfield (L, -4, name); // Stack: co, cl, st, function
rawsetfield (L, -4, name); // Stack: co, cl, st
return *this;
}
//--------------------------------------------------------------------------
/**
Add or replace a member function.
*/
template <class ReturnType, class... Params>
Class <T>& addFunction (char const* name, ReturnType (T::* mf) (Params...))
{
using MemFn = ReturnType (T::*) (Params...);
assertStackState (); // Stack: const table (co), class table (cl), static table (st)
static const std::string GC = "__gc";
if (name == GC)
{
throw std::logic_error (GC + " metamethod registration is forbidden");
}
CFunc::CallMemberFunctionHelper <MemFn, false>::add (L, name, mf);
return *this;
}
template <class ReturnType, class... Params>
Class <T>& addFunction (char const* name, ReturnType (T::* mf) (Params...) const)
{
using MemFn = ReturnType (T::*) (Params...) const;
assertStackState (); // Stack: const table (co), class table (cl), static table (st)
static const std::string GC = "__gc";
if (name == GC)
{
throw std::logic_error (GC + " metamethod registration is forbidden");
}
CFunc::CallMemberFunctionHelper <MemFn, true>::add (L, name, mf);
return *this;
}
//--------------------------------------------------------------------------
/**
Add or replace a proxy function.
*/
template <class ReturnType, class... Params>
Class <T>& addFunction (char const* name, ReturnType (*proxyFn) (T* object, Params...))
{
assertStackState (); // Stack: const table (co), class table (cl), static table (st)
static const std::string GC = "__gc";
if (name == GC)
{
throw std::logic_error (GC + " metamethod registration is forbidden");
}
using FnType = decltype (proxyFn);
lua_pushlightuserdata (L, reinterpret_cast <void*> (proxyFn)); // Stack: co, cl, st, function ptr
lua_pushcclosure (L, &CFunc::CallProxyFunction <FnType>::f, 1); // Stack: co, cl, st, function
rawsetfield (L, -3, name); // Stack: co, cl, st
return *this;
}
template <class ReturnType, class... Params>
Class <T>& addFunction (char const* name, ReturnType (*proxyFn) (const T* object, Params...))
{
assertStackState (); // Stack: const table (co), class table (cl), static table (st)
static const std::string GC = "__gc";
if (name == GC)
{
throw std::logic_error (GC + " metamethod registration is forbidden");
}
using FnType = decltype (proxyFn);
lua_pushlightuserdata (L, reinterpret_cast <void*> (proxyFn)); // Stack: co, cl, st, function ptr
lua_pushcclosure (L, &CFunc::CallProxyFunction <FnType>::f, 1); // Stack: co, cl, st, function
lua_pushvalue (L, -1); // Stack: co, cl, st, function, function
rawsetfield (L, -4, name); // Stack: co, cl, st, function
rawsetfield (L, -4, name); // Stack: co, cl, st
return *this;
}
#endif
//--------------------------------------------------------------------------
/**
Add or replace a member lua_CFunction.
*/
Class <T>& addFunction (char const* name, int (T::*mfp) (lua_State*))
{
return addCFunction (name, mfp);
}
//--------------------------------------------------------------------------
/**
Add or replace a member lua_CFunction.
*/
Class <T>& addCFunction (char const* name, int (T::*mfp) (lua_State*))
{
assertStackState (); // Stack: const table (co), class table (cl), static table (st)
typedef int (T::*MFP) (lua_State*);
new (lua_newuserdata (L, sizeof (mfp))) MFP (mfp); // Stack: co, cl, st, function ptr
lua_pushcclosure (L, &CFunc::CallMemberCFunction <T>::f, 1); // Stack: co, cl, st, function
rawsetfield (L, -3, name); // Stack: co, cl, st
return *this;
}
//--------------------------------------------------------------------------
/**
Add or replace a const member lua_CFunction.
*/
Class <T>& addFunction (char const* name, int (T::*mfp) (lua_State*) const)
{
return addCFunction (name, mfp);
}
//--------------------------------------------------------------------------
/**
Add or replace a const member lua_CFunction.
*/
Class <T>& addCFunction (char const* name, int (T::*mfp) (lua_State*) const)
{
assertStackState (); // Stack: const table (co), class table (cl), static table (st)
typedef int (T::*MFP) (lua_State*) const;
new (lua_newuserdata (L, sizeof (mfp))) MFP (mfp);
lua_pushcclosure (L, &CFunc::CallConstMemberCFunction <T>::f, 1);
lua_pushvalue (L, -1); // Stack: co, cl, st, function, function
rawsetfield (L, -4, name); // Stack: co, cl, st, function
rawsetfield (L, -4, name); // Stack: co, cl, st
return *this;
}
//--------------------------------------------------------------------------
/**
Add or replace a primary Constructor.
The primary Constructor is invoked when calling the class type table
like a function.
The template parameter should be a function pointer type that matches
the desired Constructor (since you can't take the address of a Constructor
and pass it as an argument).
*/
template <class MemFn, class C>
Class <T>& addConstructor ()
{
assertStackState (); // Stack: const table (co), class table (cl), static table (st)
lua_pushcclosure (L, &ctorContainerProxy <typename FuncTraits <MemFn>::Params, C>, 0);
rawsetfield (L, -2, "__call");
return *this;
}
template <class MemFn>
Class <T>& addConstructor ()
{
assertStackState (); // Stack: const table (co), class table (cl), static table (st)
lua_pushcclosure (L, &ctorPlacementProxy <typename FuncTraits <MemFn>::Params, T>, 0);
rawsetfield (L, -2, "__call");
return *this;
}
};
private:
//----------------------------------------------------------------------------
/**
Open the global namespace for registrations.
*/
explicit Namespace (lua_State* L)
: Registrar (L)
{
lua_getglobal (L, "_G");
++m_stackSize;
}
//----------------------------------------------------------------------------
/**
Open a namespace for registrations.
The namespace is created if it doesn't already exist.
The parent namespace is at the top of the Lua stack.
*/
Namespace (char const* name, Namespace& parent)
: Registrar (parent)
{
assert (lua_istable (L, -1)); // Stack: parent namespace (pns)
rawgetfield (L, -1, name); // Stack: pns, namespace (ns) | nil
if (lua_isnil (L, -1)) // Stack: pns, nil
{
lua_pop (L, 1); // Stack: pns
lua_newtable (L); // Stack: pns, ns
lua_pushvalue (L, -1); // Stack: pns, ns, ns
// na.__metatable = ns
lua_setmetatable (L, -2); // Stack: pns, ns
// ns.__index = indexMetaMethod
lua_pushcfunction (L, &CFunc::indexMetaMethod);
rawsetfield (L, -2, "__index"); // Stack: pns, ns
// ns.__newindex = newindexMetaMethod
lua_pushcfunction (L, &CFunc::newindexStaticMetaMethod);
rawsetfield (L, -2, "__newindex"); // Stack: pns, ns
lua_newtable (L); // Stack: pns, ns, propget table (pg)
lua_rawsetp (L, -2, getPropgetKey ()); // ns [propgetKey] = pg. Stack: pns, ns
lua_newtable (L); // Stack: pns, ns, propset table (ps)
lua_rawsetp (L, -2, getPropsetKey ()); // ns [propsetKey] = ps. Stack: pns, ns
// pns [name] = ns
lua_pushvalue (L, -1); // Stack: pns, ns, ns
rawsetfield (L, -3, name); // Stack: pns, ns
#if 0
lua_pushcfunction (L, &tostringMetaMethod);
rawsetfield (L, -2, "__tostring");
#endif
}
++m_stackSize;
}
//----------------------------------------------------------------------------
/**
Close the class and continue the namespace registrations.
*/
explicit Namespace (ClassBase& child)
: Registrar (child)
{
}
using Registrar::operator=;
public:
//----------------------------------------------------------------------------
/**
Open the global namespace.
*/
static Namespace getGlobalNamespace (lua_State* L)
{
enableExceptions (L);
return Namespace (L);
}
//----------------------------------------------------------------------------
/**
Open a new or existing namespace for registrations.
*/
Namespace beginNamespace (char const* name)
{
assertIsActive ();
return Namespace (name, *this);
}
//----------------------------------------------------------------------------
/**
Continue namespace registration in the parent.
Do not use this on the global namespace.
*/
Namespace endNamespace ()
{
if (m_stackSize == 1)
{
throw std::logic_error ("endNamespace () called on global namespace");
}
assert (m_stackSize > 1);
--m_stackSize;
lua_pop (L, 1);
return Namespace (*this);
}
//----------------------------------------------------------------------------
/**
Add or replace a variable.
*/
template <class T>
Namespace& addProperty (char const* name, T* pt, bool isWritable = true)
{
return addVariable (name, pt, isWritable);
}
//----------------------------------------------------------------------------
/**
Add or replace a variable.
*/
template <class T>
Namespace& addVariable (char const* name, T* pt, bool isWritable = true)
{
if (m_stackSize == 1)
{
throw std::logic_error ("addProperty () called on global namespace");
}
assert (lua_istable (L, -1)); // Stack: namespace table (ns)
lua_pushlightuserdata (L, pt); // Stack: ns, pointer
lua_pushcclosure (L, &CFunc::getVariable <T>, 1); // Stack: ns, getter
CFunc::addGetter (L, name, -2); // Stack: ns
if (isWritable)
{
lua_pushlightuserdata (L, pt); // Stack: ns, pointer
lua_pushcclosure (L, &CFunc::setVariable <T>, 1); // Stack: ns, setter
}
else
{
lua_pushstring (L, name); // Stack: ns, ps, name
lua_pushcclosure (L, &CFunc::readOnlyError, 1); // Stack: ns, error_fn
}
CFunc::addSetter (L, name, -2); // Stack: ns
return *this;
}
//----------------------------------------------------------------------------
/**
Add or replace a property.
If the set function is omitted or null, the property is read-only.
*/
template <class TG, class TS = TG>
Namespace& addProperty (char const* name, TG (*get) (), void (*set) (TS) = 0)
{
if (m_stackSize == 1)
{
throw std::logic_error ("addProperty () called on global namespace");
}
assert (lua_istable (L, -1)); // Stack: namespace table (ns)
lua_pushlightuserdata (L, reinterpret_cast <void*> (get)); // Stack: ns, function ptr
lua_pushcclosure (L, &CFunc::Call <TG (*) ()>::f, 1); // Stack: ns, getter
CFunc::addGetter (L, name, -2);
if (set != 0)
{
lua_pushlightuserdata(L, reinterpret_cast <void*> (set)); // Stack: ns, function ptr
lua_pushcclosure (L, &CFunc::Call <void (*) (TS)>::f, 1);
}
else
{
lua_pushstring (L, name);
lua_pushcclosure (L, &CFunc::readOnlyError, 1);
}
CFunc::addSetter (L, name, -2);
return *this;
}
//----------------------------------------------------------------------------
/**
Add or replace a property.
If the set function is omitted or null, the property is read-only.
*/
Namespace& addProperty (char const* name, int (*get) (lua_State*), int (*set) (lua_State*) = 0)
{
if (m_stackSize == 1)
{
throw std::logic_error ("addProperty () called on global namespace");
}
assert (lua_istable (L, -1)); // Stack: namespace table (ns)
lua_pushcfunction (L, get); // Stack: ns, getter
CFunc::addGetter (L, name, -2); // Stack: ns
if (set != 0)
{
lua_pushcfunction(L, set); // Stack: ns, setter
CFunc::addSetter(L, name, -2); // Stack: ns
}
else
{
lua_pushstring(L, name); // Stack: ns, name
lua_pushcclosure(L, &CFunc::readOnlyError, 1); // Stack: ns, name, readOnlyError
CFunc::addSetter(L, name, -2); // Stack: ns
}
return *this;
}
//----------------------------------------------------------------------------
/**
Add or replace a free function.
*/
template <class FP>
Namespace& addFunction (char const* name, FP const fp)
{
assert (lua_istable (L, -1)); // Stack: namespace table (ns)
lua_pushlightuserdata (L, reinterpret_cast <void*> (fp)); // Stack: ns, function ptr
lua_pushcclosure (L, &CFunc::Call <FP>::f, 1); // Stack: ns, function
rawsetfield (L, -2, name); // Stack: ns
return *this;
}
//----------------------------------------------------------------------------
/**
Add or replace a lua_CFunction.
*/
Namespace& addFunction (char const* name, int (*const fp) (lua_State*))
{
return addCFunction (name, fp);
}
//----------------------------------------------------------------------------
/**
Add or replace a lua_CFunction.
*/
Namespace& addCFunction (char const* name, int (*const fp) (lua_State*))
{
assert (lua_istable (L, -1)); // Stack: namespace table (ns)
lua_pushcfunction (L, fp); // Stack: ns, function
rawsetfield (L, -2, name); // Stack: ns
return *this;
}
//----------------------------------------------------------------------------
/**
Open a new or existing class for registrations.
*/
template <class T>
Class <T> beginClass (char const* name)
{
assertIsActive ();
return Class <T> (name, *this);
}
//----------------------------------------------------------------------------
/**
Derive a new class for registrations.
To continue registrations for the class later, use beginClass ().
Do not call deriveClass () again.
*/
template <class Derived, class Base>
Class <Derived> deriveClass (char const* name)
{
assertIsActive ();
return Class <Derived> (name, *this, ClassInfo <Base>::getStaticKey ());
}
};
//------------------------------------------------------------------------------
/**
Retrieve the global namespace.
It is recommended to put your namespace inside the global namespace, and
then add your classes and functions to it, rather than adding many classes
and functions directly to the global namespace.
*/
inline Namespace getGlobalNamespace (lua_State* L)
{
return Namespace::getGlobalNamespace (L);
}
} // namespace luabridge

View File

@@ -1,62 +0,0 @@
#pragma once
namespace luabridge {
//------------------------------------------------------------------------------
/**
security options.
*/
class Security
{
public:
static bool hideMetatables()
{
return getSettings().hideMetatables;
}
static void setHideMetatables(bool shouldHide)
{
getSettings().hideMetatables = shouldHide;
}
private:
struct Settings
{
Settings() : hideMetatables(true)
{
}
bool hideMetatables;
};
static Settings& getSettings()
{
static Settings settings;
return settings;
}
};
//------------------------------------------------------------------------------
/**
Set a global value in the lua_State.
@note This works on any type specialized by `Stack`, including `LuaRef` and
its table proxies.
*/
template <class T>
inline void setGlobal(lua_State* L, T t, char const* name)
{
push(L, t);
lua_setglobal(L, name);
}
//------------------------------------------------------------------------------
/**
Change whether or not metatables are hidden (on by default).
*/
inline void setHideMetatables(bool shouldHide)
{
Security::setHideMetatables(shouldHide);
}
} // namespace luabridge

View File

@@ -1,622 +0,0 @@
//------------------------------------------------------------------------------
/*
https://github.com/vinniefalco/LuaBridge
Copyright 2019, Dmitry Tarakanov
Copyright 2012, Vinnie Falco <vinnie.falco@gmail.com>
Copyright 2007, Nathan Reed
License: The MIT License (http://www.opensource.org/licenses/mit-license.php)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
//==============================================================================
#pragma once
#include <LuaBridge/detail/LuaHelpers.h>
#include <LuaBridge/detail/Userdata.h>
#include <string>
namespace luabridge {
template <class T>
struct Stack;
template <>
struct Stack <void>
{
static void push (lua_State* L)
{
}
};
//------------------------------------------------------------------------------
/**
Receive the lua_State* as an argument.
*/
template <>
struct Stack <lua_State*>
{
static lua_State* get (lua_State* L, int)
{
return L;
}
};
//------------------------------------------------------------------------------
/**
Push a lua_CFunction.
*/
template <>
struct Stack <lua_CFunction>
{
static void push (lua_State* L, lua_CFunction f)
{
lua_pushcfunction (L, f);
}
static lua_CFunction get (lua_State* L, int index)
{
return lua_tocfunction (L, index);
}
static bool isInstance (lua_State* L, int index)
{
return lua_iscfunction (L, index);
}
};
//------------------------------------------------------------------------------
/**
Stack specialization for `int`.
*/
template <>
struct Stack <int>
{
static void push (lua_State* L, int value)
{
lua_pushinteger (L, static_cast <lua_Integer> (value));
}
static int get (lua_State* L, int index)
{
return static_cast <int> (luaL_checkinteger (L, index));
}
static bool isInstance (lua_State* L, int index)
{
return lua_type (L, index) == LUA_TNUMBER;
}
};
//------------------------------------------------------------------------------
/**
Stack specialization for `unsigned int`.
*/
template <>
struct Stack <unsigned int>
{
static void push (lua_State* L, unsigned int value)
{
lua_pushinteger (L, static_cast <lua_Integer> (value));
}
static unsigned int get (lua_State* L, int index)
{
return static_cast <unsigned int> (luaL_checkinteger (L, index));
}
static bool isInstance (lua_State* L, int index)
{
return lua_type (L, index) == LUA_TNUMBER;
}
};
//------------------------------------------------------------------------------
/**
Stack specialization for `unsigned char`.
*/
template <>
struct Stack <unsigned char>
{
static void push (lua_State* L, unsigned char value)
{
lua_pushinteger (L, static_cast <lua_Integer> (value));
}
static unsigned char get (lua_State* L, int index)
{
return static_cast <unsigned char> (luaL_checkinteger (L, index));
}
static bool isInstance (lua_State* L, int index)
{
return lua_type (L, index) == LUA_TNUMBER;
}
};
//------------------------------------------------------------------------------
/**
Stack specialization for `short`.
*/
template <>
struct Stack <short>
{
static void push (lua_State* L, short value)
{
lua_pushinteger (L, static_cast <lua_Integer> (value));
}
static short get (lua_State* L, int index)
{
return static_cast <short> (luaL_checkinteger (L, index));
}
static bool isInstance (lua_State* L, int index)
{
return lua_type (L, index) == LUA_TNUMBER;
}
};
//------------------------------------------------------------------------------
/**
Stack specialization for `unsigned short`.
*/
template <>
struct Stack <unsigned short>
{
static void push (lua_State* L, unsigned short value)
{
lua_pushinteger (L, static_cast <lua_Integer> (value));
}
static unsigned short get (lua_State* L, int index)
{
return static_cast <unsigned short> (luaL_checkinteger (L, index));
}
static bool isInstance (lua_State* L, int index)
{
return lua_type (L, index) == LUA_TNUMBER;
}
};
//------------------------------------------------------------------------------
/**
Stack specialization for `long`.
*/
template <>
struct Stack <long>
{
static void push (lua_State* L, long value)
{
lua_pushinteger (L, static_cast <lua_Integer> (value));
}
static long get (lua_State* L, int index)
{
return static_cast <long> (luaL_checkinteger (L, index));
}
static bool isInstance (lua_State* L, int index)
{
return lua_type (L, index) == LUA_TNUMBER;
}
};
//------------------------------------------------------------------------------
/**
Stack specialization for `unsigned long`.
*/
template <>
struct Stack <unsigned long>
{
static void push (lua_State* L, unsigned long value)
{
lua_pushinteger (L, static_cast <lua_Integer> (value));
}
static unsigned long get (lua_State* L, int index)
{
return static_cast <unsigned long> (luaL_checkinteger (L, index));
}
static bool isInstance (lua_State* L, int index)
{
return lua_type (L, index) == LUA_TNUMBER;
}
};
//------------------------------------------------------------------------------
/**
* Stack specialization for `long long`.
*/
template <>
struct Stack <long long>
{
static void push (lua_State* L, long long value)
{
lua_pushinteger (L, static_cast <lua_Integer> (value));
}
static long long get (lua_State* L, int index)
{
return static_cast <long long> (luaL_checkinteger (L, index));
}
static bool isInstance (lua_State* L, int index)
{
return lua_type (L, index) == LUA_TNUMBER;
}
};
//------------------------------------------------------------------------------
/**
* Stack specialization for `unsigned long long`.
*/
template <>
struct Stack <unsigned long long>
{
static void push (lua_State* L, unsigned long long value)
{
lua_pushinteger (L, static_cast <lua_Integer> (value));
}
static unsigned long long get (lua_State* L, int index)
{
return static_cast <unsigned long long> (luaL_checkinteger (L, index));
}
static bool isInstance (lua_State* L, int index)
{
return lua_type (L, index) == LUA_TNUMBER;
}
};
//------------------------------------------------------------------------------
/**
Stack specialization for `float`.
*/
template <>
struct Stack <float>
{
static void push (lua_State* L, float value)
{
lua_pushnumber (L, static_cast <lua_Number> (value));
}
static float get (lua_State* L, int index)
{
return static_cast <float> (luaL_checknumber (L, index));
}
static bool isInstance (lua_State* L, int index)
{
return lua_type (L, index) == LUA_TNUMBER;
}
};
//------------------------------------------------------------------------------
/**
Stack specialization for `double`.
*/
template <>
struct Stack <double>
{
static void push (lua_State* L, double value)
{
lua_pushnumber (L, static_cast <lua_Number> (value));
}
static double get (lua_State* L, int index)
{
return static_cast <double> (luaL_checknumber (L, index));
}
static bool isInstance (lua_State* L, int index)
{
return lua_type (L, index) == LUA_TNUMBER;
}
};
//------------------------------------------------------------------------------
/**
Stack specialization for `bool`.
*/
template <>
struct Stack <bool>
{
static void push (lua_State* L, bool value)
{
lua_pushboolean (L, value ? 1 : 0);
}
static bool get (lua_State* L, int index)
{
return lua_toboolean (L, index) ? true : false;
}
static bool isInstance (lua_State* L, int index)
{
return lua_isboolean (L, index);
}
};
//------------------------------------------------------------------------------
/**
Stack specialization for `char`.
*/
template <>
struct Stack <char>
{
static void push (lua_State* L, char value)
{
lua_pushlstring (L, &value, 1);
}
static char get (lua_State* L, int index)
{
return luaL_checkstring (L, index) [0];
}
static bool isInstance (lua_State* L, int index)
{
return lua_type (L, index) == LUA_TSTRING;
}
};
//------------------------------------------------------------------------------
/**
Stack specialization for `const char*`.
*/
template <>
struct Stack <char const*>
{
static void push (lua_State* L, char const* str)
{
if (str != 0)
lua_pushstring (L, str);
else
lua_pushnil (L);
}
static char const* get (lua_State* L, int index)
{
return lua_isnil (L, index) ? 0 : luaL_checkstring (L, index);
}
static bool isInstance (lua_State* L, int index)
{
return lua_isnil (L, index) || lua_type (L, index) == LUA_TSTRING;
}
};
//------------------------------------------------------------------------------
/**
Stack specialization for `std::string`.
*/
template <>
struct Stack <std::string>
{
static void push (lua_State* L, std::string const& str)
{
lua_pushlstring (L, str.data (), str.size ());
}
static std::string get (lua_State* L, int index)
{
size_t len;
if (lua_type (L, index) == LUA_TSTRING)
{
const char* str = lua_tolstring (L, index, &len);
return std::string (str, len);
}
// Lua reference manual:
// If the value is a number, then lua_tolstring also changes the actual value in the stack to a string.
// (This change confuses lua_next when lua_tolstring is applied to keys during a table traversal.)
lua_pushvalue (L, index);
const char* str = lua_tolstring(L, -1, &len);
std::string string (str, len);
lua_pop (L, 1); // Pop the temporary string
return string;
}
static bool isInstance (lua_State* L, int index)
{
return lua_type (L, index) == LUA_TSTRING;
}
};
template <class T>
struct StackOpSelector <T&, false>
{
typedef T ReturnType;
static void push (lua_State* L, T& value)
{
Stack <T>::push (L, value);
}
static ReturnType get (lua_State* L, int index)
{
return Stack <T>::get (L, index);
}
static bool isInstance (lua_State* L, int index)
{
return Stack <T>::isInstance (L, index);
}
};
template <class T>
struct StackOpSelector <const T&, false>
{
typedef T ReturnType;
static void push (lua_State* L, const T& value)
{
Stack <T>::push (L, value);
}
static ReturnType get (lua_State* L, int index)
{
return Stack <T>::get (L, index);
}
static bool isInstance (lua_State* L, int index)
{
return Stack <T>::isInstance (L, index);
}
};
template <class T>
struct StackOpSelector <T*, false>
{
typedef T ReturnType;
static void push (lua_State* L, T* value)
{
Stack <T>::push (L, *value);
}
static ReturnType get (lua_State* L, int index)
{
return Stack <T>::get (L, index);
}
static bool isInstance (lua_State* L, int index)
{
return Stack <T>::isInstance (L, index);
}
};
template <class T>
struct StackOpSelector <const T*, false>
{
typedef T ReturnType;
static void push (lua_State* L, const T* value)
{
Stack <T>::push (L, *value);
}
static ReturnType get (lua_State* L, int index)
{
return Stack <T>::get (L, index);
}
static bool isInstance (lua_State* L, int index)
{
return Stack <T>::isInstance (L, index);
}
};
template <class T>
struct Stack <T&>
{
typedef StackOpSelector <T&, IsUserdata <T>::value> Helper;
typedef typename Helper::ReturnType ReturnType;
static void push (lua_State* L, T& value)
{
Helper::push (L, value);
}
static ReturnType get (lua_State* L, int index)
{
return Helper::get (L, index);
}
};
template <class T>
struct Stack <const T&>
{
typedef StackOpSelector <const T&, IsUserdata <T>::value> Helper;
typedef typename Helper::ReturnType ReturnType;
static void push (lua_State* L, const T& value)
{
Helper::push (L, value);
}
static ReturnType get (lua_State* L, int index)
{
return Helper::get (L, index);
}
};
template <class T>
struct Stack <T*>
{
typedef StackOpSelector <T*, IsUserdata <T>::value> Helper;
typedef typename Helper::ReturnType ReturnType;
static void push (lua_State* L, T* value)
{
Helper::push (L, value);
}
static ReturnType get (lua_State* L, int index)
{
return Helper::get (L, index);
}
};
template <class T>
struct Stack <const T*>
{
typedef StackOpSelector <const T*, IsUserdata <T>::value> Helper;
typedef typename Helper::ReturnType ReturnType;
static void push (lua_State* L, const T* value)
{
Helper::push (L, value);
}
static ReturnType get (lua_State* L, int index)
{
return Helper::get (L, index);
}
};
//------------------------------------------------------------------------------
/**
* Push an object onto the Lua stack.
*/
template <class T>
inline void push (lua_State* L, T t)
{
Stack <T>::push (L, t);
}
//------------------------------------------------------------------------------
/**
* Check whether an object on the Lua stack is of type T.
*/
template <class T>
inline bool isInstance (lua_State* L, int index)
{
return Stack <T>::isInstance (L, index);
}
} // namespace luabridge

View File

@@ -1,218 +0,0 @@
//------------------------------------------------------------------------------
/*
https://github.com/vinniefalco/LuaBridge
Copyright 2012, Vinnie Falco <vinnie.falco@gmail.com>
Copyright 2007, Nathan Reed
License: The MIT License (http://www.opensource.org/licenses/mit-license.php)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
This file incorporates work covered by the following copyright and
permission notice:
The Loki Library
Copyright (c) 2001 by Andrei Alexandrescu
This code accompanies the book:
Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design
Patterns Applied". Copyright (c) 2001. Addison-Wesley.
Permission to use, copy, modify, distribute and sell this software for any
purpose is hereby granted without fee, provided that the above copyright
notice appear in all copies and that both that copyright notice and this
permission notice appear in supporting documentation.
The author or Addison-Welsey Longman make no representations about the
suitability of this software for any purpose. It is provided "as is"
without express or implied warranty.
*/
//==============================================================================
#pragma once
#include <LuaBridge/detail/Config.h>
#include <LuaBridge/detail/Stack.h>
#include <string>
#include <typeinfo>
namespace luabridge {
/**
None type means void parameters or return value.
*/
typedef void None;
template <typename Head, typename Tail = None>
struct TypeList
{
typedef Tail TailType;
};
template <class List>
struct TypeListSize
{
static const size_t value = TypeListSize <typename List::TailType>::value + 1;
};
template <>
struct TypeListSize <None>
{
static const size_t value = 0;
};
#ifdef LUABRIDGE_CXX11
template <class... Params>
struct MakeTypeList;
template <class Param, class... Params>
struct MakeTypeList <Param, Params...>
{
using Result = TypeList <Param, typename MakeTypeList <Params...>::Result>;
};
template <>
struct MakeTypeList <>
{
using Result = None;
};
#endif
/**
A TypeList with actual values.
*/
template <typename List>
struct TypeListValues
{
static std::string const tostring (bool)
{
return "";
}
};
/**
TypeListValues recursive template definition.
*/
template <typename Head, typename Tail>
struct TypeListValues <TypeList <Head, Tail> >
{
Head hd;
TypeListValues <Tail> tl;
TypeListValues (Head hd_, TypeListValues <Tail> const& tl_)
: hd (hd_), tl (tl_)
{
}
static std::string tostring (bool comma = false)
{
std::string s;
if (comma)
s = ", ";
s = s + typeid (Head).name ();
return s + TypeListValues <Tail>::tostring (true);
}
};
// Specializations of type/value list for head types that are references and
// const-references. We need to handle these specially since we can't count
// on the referenced object hanging around for the lifetime of the list.
template <typename Head, typename Tail>
struct TypeListValues <TypeList <Head&, Tail> >
{
Head hd;
TypeListValues <Tail> tl;
TypeListValues (Head& hd_, TypeListValues <Tail> const& tl_)
: hd (hd_), tl (tl_)
{
}
static std::string const tostring (bool comma = false)
{
std::string s;
if (comma)
s = ", ";
s = s + typeid (Head).name () + "&";
return s + TypeListValues <Tail>::tostring (true);
}
};
template <typename Head, typename Tail>
struct TypeListValues <TypeList <Head const&, Tail> >
{
Head hd;
TypeListValues <Tail> tl;
TypeListValues (Head const& hd_, const TypeListValues <Tail>& tl_)
: hd (hd_), tl (tl_)
{
}
static std::string const tostring (bool comma = false)
{
std::string s;
if (comma)
s = ", ";
s = s + typeid (Head).name () + " const&";
return s + TypeListValues <Tail>::tostring (true);
}
};
//==============================================================================
/**
Subclass of a TypeListValues constructable from the Lua stack.
*/
template <typename List, int Start = 1>
struct ArgList
{
};
template <int Start>
struct ArgList <None, Start> : public TypeListValues <None>
{
ArgList (lua_State*)
{
}
};
template <typename Head, typename Tail, int Start>
struct ArgList <TypeList <Head, Tail>, Start>
: public TypeListValues <TypeList <Head, Tail> >
{
ArgList (lua_State* L)
: TypeListValues <TypeList <Head, Tail> > (Stack <Head>::get (L, Start),
ArgList <Tail, Start + 1> (L))
{
}
};
} // namespace luabridge

View File

@@ -1,135 +0,0 @@
//------------------------------------------------------------------------------
/*
https://github.com/vinniefalco/LuaBridge
Copyright 2019, Dmitry Tarakanov
Copyright 2012, Vinnie Falco <vinnie.falco@gmail.com>
License: The MIT License (http://www.opensource.org/licenses/mit-license.php)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
//==============================================================================
#pragma once
#include <string>
namespace luabridge {
//------------------------------------------------------------------------------
/**
Container traits.
Unspecialized ContainerTraits has the isNotContainer typedef for SFINAE.
All user defined containers must supply an appropriate specialization for
ContinerTraits (without the typedef isNotContainer). The containers that
come with LuaBridge also come with the appropriate ContainerTraits
specialization. See the corresponding declaration for details.
A specialization of ContainerTraits for some generic type ContainerType
looks like this:
template <class T>
struct ContainerTraits <ContainerType <T> >
{
typedef typename T Type;
static T* get (ContainerType <T> const& c)
{
return c.get (); // Implementation-dependent on ContainerType
}
};
*/
template <class T>
struct ContainerTraits
{
typedef bool isNotContainer;
typedef T Type;
};
//------------------------------------------------------------------------------
/**
Type traits.
Specializations return information about a type.
*/
struct TypeTraits
{
/** Determine if type T is a container.
To be considered a container, there must be a specialization of
ContainerTraits with the required fields.
*/
template <typename T>
class isContainer
{
private:
typedef char yes[1]; // sizeof (yes) == 1
typedef char no [2]; // sizeof (no) == 2
template <typename C>
static no& test (typename C::isNotContainer*);
template <typename>
static yes& test (...);
public:
static const bool value = sizeof (test <ContainerTraits <T> >(0)) == sizeof (yes);
};
/** Determine if T is const qualified.
*/
/** @{ */
template <class T>
struct isConst
{
static bool const value = false;
};
template <class T>
struct isConst <T const>
{
static bool const value = true;
};
/** @} */
/** Remove the const qualifier from T.
*/
/** @{ */
template <class T>
struct removeConst
{
typedef T Type;
};
template <class T>
struct removeConst <T const>
{
typedef T Type;
};
/**@}*/
};
template <class T>
struct Stack;
} // namespace luabridge

View File

@@ -1,829 +0,0 @@
//------------------------------------------------------------------------------
/*
https://github.com/vinniefalco/LuaBridge
Copyright 2019, Dmitry Tarakanov
Copyright 2012, Vinnie Falco <vinnie.falco@gmail.com>
License: The MIT License (http://www.opensource.org/licenses/mit-license.php)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
//==============================================================================
#pragma once
#include <LuaBridge/detail/ClassInfo.h>
#include <cassert>
#include <stdexcept>
namespace luabridge {
//==============================================================================
/**
Return the identity pointer for our lightuserdata tokens.
Because of Lua's dynamic typing and our improvised system of imposing C++
class structure, there is the possibility that executing scripts may
knowingly or unknowingly cause invalid data to get passed to the C functions
created by LuaBridge. In particular, our security model addresses the
following:
1. Scripts cannot create a userdata (ignoring the debug lib).
2. Scripts cannot create a lightuserdata (ignoring the debug lib).
3. Scripts cannot set the metatable on a userdata.
*/
/**
Interface to a class pointer retrievable from a userdata.
*/
class Userdata
{
protected:
void* m_p; // subclasses must set this
Userdata() : m_p (0)
{
}
//--------------------------------------------------------------------------
/**
Get an untyped pointer to the contained class.
*/
void* getPointer ()
{
return m_p;
}
private:
//--------------------------------------------------------------------------
/**
Validate and retrieve a Userdata on the stack.
The Userdata must exactly match the corresponding class table or
const table, or else a Lua error is raised. This is used for the
__gc metamethod.
*/
static Userdata* getExactClass (lua_State* L, int index, void const* /*classKey*/)
{
return static_cast <Userdata*> (lua_touserdata (L, lua_absindex (L, index)));
}
//--------------------------------------------------------------------------
/**
Validate and retrieve a Userdata on the stack.
The Userdata must be derived from or the same as the given base class,
identified by the key. If canBeConst is false, generates an error if
the resulting Userdata represents to a const object. We do the type check
first so that the error message is informative.
*/
static Userdata* getClass (lua_State* L,
int index,
void const* registryConstKey,
void const* registryClassKey,
bool canBeConst)
{
index = lua_absindex (L, index);
lua_getmetatable (L, index); // Stack: object metatable (ot) | nil
if (!lua_istable (L, -1))
{
lua_rawgetp (L, LUA_REGISTRYINDEX, registryClassKey); // Stack: registry metatable (rt) | nil
return throwBadArg (L, index);
}
lua_rawgetp (L, -1, getConstKey ()); // Stack: ot | nil, const table (co) | nil
assert (lua_istable (L, -1) || lua_isnil (L, -1));
// If const table is NOT present, object is const. Use non-const registry table
// if object cannot be const, so constness validation is done automatically.
// E.g. nonConstFn (constObj)
// -> canBeConst = false, isConst = true
// -> 'Class' registry table, 'const Class' object table
// -> 'expected Class, got const Class'
bool isConst = lua_isnil (L, -1); // Stack: ot | nil, nil, rt
if (isConst && canBeConst)
{
lua_rawgetp (L, LUA_REGISTRYINDEX, registryConstKey); // Stack: ot, nil, rt
}
else
{
lua_rawgetp (L, LUA_REGISTRYINDEX, registryClassKey); // Stack: ot, co, rt
}
lua_insert (L, -3); // Stack: rt, ot, co | nil
lua_pop (L, 1); // Stack: rt, ot
for (;;)
{
if (lua_rawequal (L, -1, -2)) // Stack: rt, ot
{
lua_pop (L, 2); // Stack: -
return static_cast <Userdata*> (lua_touserdata (L, index));
}
// Replace current metatable with it's base class.
lua_rawgetp (L, -1, getParentKey ()); // Stack: rt, ot, parent ot (pot) | nil
if (lua_isnil (L, -1)) // Stack: rt, ot, nil
{
// Drop the object metatable because it may be some parent metatable
lua_pop (L, 2); // Stack: rt
return throwBadArg (L, index);
}
lua_remove (L, -2); // Stack: rt, pot
}
// no return
}
static bool isInstance (lua_State* L, int index, void const* registryClassKey)
{
index = lua_absindex (L, index);
int result = lua_getmetatable (L, index); // Stack: object metatable (ot) | nothing
if (result == 0)
{
return false; // Nothing was pushed on the stack
}
if (!lua_istable (L, -1))
{
lua_pop (L, 1); // Stack: -
return false;
}
lua_rawgetp (L, LUA_REGISTRYINDEX, registryClassKey); // Stack: ot, rt
lua_insert (L, -2); // Stack: rt, ot
for (;;)
{
if (lua_rawequal (L, -1, -2)) // Stack: rt, ot
{
lua_pop (L, 2); // Stack: -
return true;
}
// Replace current metatable with it's base class.
lua_rawgetp (L, -1, getParentKey ()); // Stack: rt, ot, parent ot (pot) | nil
if (lua_isnil (L, -1)) // Stack: rt, ot, nil
{
lua_pop (L, 3); // Stack: -
return false;
}
lua_remove (L, -2); // Stack: rt, pot
}
}
static Userdata* throwBadArg (lua_State* L, int index)
{
assert (lua_istable (L, -1) || lua_isnil (L, -1)); // Stack: rt | nil
const char* expected = 0;
if (lua_isnil (L, -1)) // Stack: nil
{
expected = "unregistered class";
}
else
{
lua_rawgetp (L, -1, getTypeKey ()); // Stack: rt, registry type
expected = lua_tostring (L, -1);
}
const char* got = 0;
if (lua_isuserdata (L, index))
{
lua_getmetatable (L, index); // Stack: ..., ot | nil
if (lua_istable (L, -1)) // Stack: ..., ot
{
lua_rawgetp (L, -1, getTypeKey ()); // Stack: ..., ot, object type | nil
if (lua_isstring (L, -1))
{
got = lua_tostring (L, -1);
}
}
}
if (!got)
{
got = lua_typename (L, lua_type (L, index));
}
luaL_argerror (L, index, lua_pushfstring (L, "%s expected, got %s", expected, got));
return 0;
}
public:
virtual ~Userdata () { }
//--------------------------------------------------------------------------
/**
Returns the Userdata* if the class on the Lua stack matches.
If the class does not match, a Lua error is raised.
*/
template <class T>
static Userdata* getExact (lua_State* L, int index)
{
return getExactClass (L, index, ClassInfo <T>::getClassKey ());
}
//--------------------------------------------------------------------------
/**
Get a pointer to the class from the Lua stack.
If the object is not the class or a subclass, or it violates the
const-ness, a Lua error is raised.
*/
template <class T>
static T* get (lua_State* L, int index, bool canBeConst)
{
if (lua_isnil (L, index))
return 0;
return static_cast <T*> (getClass (
L, index, ClassInfo <T>::getConstKey (),
ClassInfo <T>::getClassKey (),
canBeConst)->getPointer ());
}
template <class T>
static bool isInstance (lua_State* L, int index)
{
return isInstance (L, index, ClassInfo <T>::getClassKey ());
}
};
//----------------------------------------------------------------------------
/**
Wraps a class object stored in a Lua userdata.
The lifetime of the object is managed by Lua. The object is constructed
inside the userdata using placement new.
*/
template <class T>
class UserdataValue : public Userdata
{
private:
UserdataValue <T> (UserdataValue <T> const&);
UserdataValue <T> operator= (UserdataValue <T> const&);
char m_storage [sizeof (T)];
private:
/**
Used for placement construction.
*/
UserdataValue ()
{
m_p = 0;
}
~UserdataValue ()
{
if (getPointer () != 0)
{
getObject ()->~T ();
}
}
public:
/**
Push a T via placement new.
The caller is responsible for calling placement new using the
returned uninitialized storage.
*/
static UserdataValue <T>* place (lua_State* const L)
{
UserdataValue <T>* const ud = new (
lua_newuserdata (L, sizeof (UserdataValue <T>))) UserdataValue <T> ();
lua_rawgetp (L, LUA_REGISTRYINDEX, ClassInfo <T>::getClassKey ());
if (!lua_istable (L, -1))
{
throw std::logic_error ("The class is not registered in LuaBridge");
}
lua_setmetatable (L, -2);
return ud;
}
/**
Push T via copy construction from U.
*/
template <class U>
static inline void push (lua_State* const L, U const& u)
{
UserdataValue <T>* ud = place (L);
new (ud->getObject ()) U (u);
ud->commit ();
}
/**
Confirm object construction.
*/
void commit ()
{
m_p = getObject ();
}
T* getObject ()
{
// If this fails to compile it means you forgot to provide
// a Container specialization for your container!
//
return reinterpret_cast <T*> (&m_storage [0]);
}
};
//----------------------------------------------------------------------------
/**
Wraps a pointer to a class object inside a Lua userdata.
The lifetime of the object is managed by C++.
*/
class UserdataPtr : public Userdata
{
private:
UserdataPtr (UserdataPtr const&);
UserdataPtr operator= (UserdataPtr const&);
private:
/** Push a pointer to object using metatable key.
*/
static void push (lua_State* L, const void* p, void const* const key)
{
new (lua_newuserdata (L, sizeof (UserdataPtr))) UserdataPtr (const_cast <void*> (p));
lua_rawgetp (L, LUA_REGISTRYINDEX, key);
if (!lua_istable (L, -1))
{
throw std::logic_error ("The class is not registered in LuaBridge");
}
lua_setmetatable (L, -2);
}
explicit UserdataPtr (void* const p)
{
m_p = p;
// Can't construct with a null pointer!
//
assert (m_p != 0);
}
public:
/** Push non-const pointer to object.
*/
template <class T>
static void push (lua_State* const L, T* const p)
{
if (p)
push (L, p, ClassInfo <T>::getClassKey ());
else
lua_pushnil (L);
}
/** Push const pointer to object.
*/
template <class T>
static void push (lua_State* const L, T const* const p)
{
if (p)
push (L, p, ClassInfo <T>::getConstKey ());
else
lua_pushnil (L);
}
};
//============================================================================
/**
Wraps a container that references a class object.
The template argument C is the container type, ContainerTraits must be
specialized on C or else a compile error will result.
*/
template <class C>
class UserdataShared : public Userdata
{
private:
UserdataShared (UserdataShared <C> const&);
UserdataShared <C>& operator= (UserdataShared <C> const&);
typedef typename TypeTraits::removeConst <
typename ContainerTraits <C>::Type>::Type T;
C m_c;
private:
~UserdataShared ()
{
}
public:
/**
Construct from a container to the class or a derived class.
*/
template <class U>
explicit UserdataShared (U const& u) : m_c (u)
{
m_p = const_cast <void*> (reinterpret_cast <void const*> (
(ContainerTraits <C>::get (m_c))));
}
/**
Construct from a pointer to the class or a derived class.
*/
template <class U>
explicit UserdataShared (U* u) : m_c (u)
{
m_p = const_cast <void*> (reinterpret_cast <void const*> (
(ContainerTraits <C>::get (m_c))));
}
};
//----------------------------------------------------------------------------
//
// SFINAE helpers.
//
// non-const objects
template <class C, bool makeObjectConst>
struct UserdataSharedHelper
{
typedef typename TypeTraits::removeConst <
typename ContainerTraits <C>::Type>::Type T;
static void push (lua_State* L, C const& c)
{
if (ContainerTraits <C>::get (c) != 0)
{
new (lua_newuserdata (L, sizeof (UserdataShared <C>))) UserdataShared <C> (c);
lua_rawgetp (L, LUA_REGISTRYINDEX, ClassInfo <T>::getClassKey ());
// If this goes off it means the class T is unregistered!
assert (lua_istable (L, -1));
lua_setmetatable (L, -2);
}
else
{
lua_pushnil (L);
}
}
static void push (lua_State* L, T* const t)
{
if (t)
{
new (lua_newuserdata (L, sizeof (UserdataShared <C>))) UserdataShared <C> (t);
lua_rawgetp (L, LUA_REGISTRYINDEX, ClassInfo <T>::getClassKey ());
// If this goes off it means the class T is unregistered!
assert (lua_istable (L, -1));
lua_setmetatable (L, -2);
}
else
{
lua_pushnil (L);
}
}
};
// const objects
template <class C>
struct UserdataSharedHelper <C, true>
{
typedef typename TypeTraits::removeConst <
typename ContainerTraits <C>::Type>::Type T;
static void push (lua_State* L, C const& c)
{
if (ContainerTraits <C>::get (c) != 0)
{
new (lua_newuserdata (L, sizeof (UserdataShared <C>))) UserdataShared <C> (c);
lua_rawgetp (L, LUA_REGISTRYINDEX, ClassInfo <T>::getConstKey ());
// If this goes off it means the class T is unregistered!
assert (lua_istable (L, -1));
lua_setmetatable (L, -2);
}
else
{
lua_pushnil (L);
}
}
static void push (lua_State* L, T* const t)
{
if (t)
{
new (lua_newuserdata (L, sizeof (UserdataShared <C>))) UserdataShared <C> (t);
lua_rawgetp (L, LUA_REGISTRYINDEX, ClassInfo <T>::getConstKey ());
// If this goes off it means the class T is unregistered!
assert (lua_istable (L, -1));
lua_setmetatable (L, -2);
}
else
{
lua_pushnil (L);
}
}
};
/**
Pass by container.
The container controls the object lifetime. Typically this will be a
lifetime shared by C++ and Lua using a reference count. Because of type
erasure, containers like std::shared_ptr will not work. Containers must
either be of the intrusive variety, or in the style of the RefCountedPtr
type provided by LuaBridge (that uses a global hash table).
*/
template <class C, bool byContainer>
struct StackHelper
{
static void push (lua_State* L, C const& c)
{
UserdataSharedHelper <C,
TypeTraits::isConst <typename ContainerTraits <C>::Type>::value>::push (L, c);
}
typedef typename TypeTraits::removeConst <
typename ContainerTraits <C>::Type>::Type T;
static C get (lua_State* L, int index)
{
return Userdata::get <T> (L, index, true);
}
};
/**
Pass by value.
Lifetime is managed by Lua. A C++ function which accesses a pointer or
reference to an object outside the activation record in which it was
retrieved may result in undefined behavior if Lua garbage collected it.
*/
template <class T>
struct StackHelper <T, false>
{
static inline void push (lua_State* L, T const& t)
{
UserdataValue <T>::push (L, t);
}
static inline T const& get (lua_State* L, int index)
{
return *Userdata::get <T> (L, index, true);
}
};
//------------------------------------------------------------------------------
/**
Lua stack conversions for pointers and references to class objects.
Lifetime is managed by C++. Lua code which remembers a reference to the
value may result in undefined behavior if C++ destroys the object. The
handling of the const and volatile qualifiers happens in UserdataPtr.
*/
template <class C, bool byContainer>
struct RefStackHelper
{
typedef C return_type;
static inline void push (lua_State* L, C const& t)
{
UserdataSharedHelper <C,
TypeTraits::isConst <typename ContainerTraits <C>::Type>::value>::push (L, t);
}
typedef typename TypeTraits::removeConst <
typename ContainerTraits <C>::Type>::Type T;
static return_type get (lua_State* L, int index)
{
return Userdata::get <T> (L, index, true);
}
};
template <class T>
struct RefStackHelper <T, false>
{
typedef T& return_type;
static void push (lua_State* L, T const& t)
{
UserdataPtr::push (L, &t);
}
static return_type get (lua_State* L, int index)
{
T* t = Userdata::get <T> (L, index, true);
if (!t)
luaL_error (L, "nil passed to reference");
return *t;
}
};
/**
* Voider class template. Used to force a comiler to instantiate
* an otherwise probably unused template parameter type T.
* See the C++20 std::void_t <> for details.
*/
template <class T>
struct Void
{
typedef void Type;
};
/**
* Trait class that selects whether to return a user registered
* class object by value or by reference.
*/
template <class T, class Enabler = void>
struct UserdataGetter
{
typedef T* ReturnType;
static ReturnType get (lua_State* L, int index)
{
return Userdata::get <T> (L, index, false);
}
};
template <class T>
struct UserdataGetter <T, typename Void <T (*) ()>::Type>
{
typedef T ReturnType;
static ReturnType get (lua_State* L, int index)
{
return StackHelper <T, TypeTraits::isContainer <T>::value>::get (L, index);
}
};
//==============================================================================
/**
Lua stack conversions for class objects passed by value.
*/
template <class T>
struct Stack
{
typedef void IsUserdata;
typedef UserdataGetter <T> Getter;
typedef typename Getter::ReturnType ReturnType;
static void push (lua_State* L, T const& value)
{
StackHelper <T, TypeTraits::isContainer <T>::value>::push (L, value);
}
static ReturnType get (lua_State* L, int index)
{
return Getter::get (L, index);
}
static bool isInstance (lua_State* L, int index)
{
return Userdata::isInstance <T> (L, index);
}
};
/**
* Trait class indicating whether the parameter type must be
* a user registered class. The trait checks the existence of
* member type Stack <T>::IsUserdata specialization for detection.
*/
template <class T, class Enable = void>
struct IsUserdata
{
static const bool value = false;
};
template <class T>
struct IsUserdata <T, typename Void <typename Stack <T>::IsUserdata>::Type>
{
static const bool value = true;
};
/**
* Trait class that selects a specific push/get implemenation.
*/
template <class T, bool isUserdata>
struct StackOpSelector;
// pointer
template <class T>
struct StackOpSelector <T*, true>
{
typedef T* ReturnType;
static void push (lua_State* L, T* value)
{
UserdataPtr::push (L, value);
}
static T* get (lua_State* L, int index)
{
return Userdata::get <T> (L, index, false);
}
static bool isInstance (lua_State* L, int index)
{
return Userdata::isInstance <T> (L, index);
}
};
// pointer to const
template <class T>
struct StackOpSelector <const T*, true>
{
typedef const T* ReturnType;
static void push (lua_State* L, const T* value)
{
UserdataPtr::push (L, value);
}
static const T* get (lua_State* L, int index)
{
return Userdata::get <T> (L, index, true);
}
static bool isInstance (lua_State* L, int index)
{
return Userdata::isInstance <T> (L, index);
}
};
// reference
template <class T>
struct StackOpSelector <T&, true>
{
typedef RefStackHelper <T, TypeTraits::isContainer <T>::value> Helper;
typedef typename Helper::return_type ReturnType;
static void push (lua_State* L, T& value)
{
UserdataPtr::push (L, &value);
}
static ReturnType get (lua_State* L, int index)
{
return Helper::get (L, index);
}
static bool isInstance (lua_State* L, int index)
{
return Userdata::isInstance <T> (L, index);
}
};
// reference to const
template <class T>
struct StackOpSelector <const T&, true>
{
typedef RefStackHelper <T, TypeTraits::isContainer <T>::value> Helper;
typedef typename Helper::return_type ReturnType;
static void push (lua_State* L, const T& value)
{
Helper::push (L, value);
}
static ReturnType get (lua_State* L, int index)
{
return Helper::get (L, index);
}
static bool isInstance (lua_State* L, int index)
{
return Userdata::isInstance <T> (L, index);
}
};
} // namespace luabridge

View File

@@ -1,143 +0,0 @@
//==============================================================================
/*
https://github.com/vinniefalco/LuaBridge
Copyright 2019, Dmitry Tarakanov
Copyright 2012, Vinnie Falco <vinnie.falco@gmail.com>
Copyright 2007, Nathan Reed
License: The MIT License (http://www.opensource.org/licenses/mit-license.php)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
//==============================================================================
#pragma once
#include "LuaBridge/detail/ClassInfo.h"
#include <iostream>
#include <string>
namespace luabridge {
namespace debug {
inline void putIndent (std::ostream& stream, unsigned level)
{
for (unsigned i = 0; i < level; ++i)
{
stream << " ";
}
}
inline void dumpTable (lua_State* L, int index, std::ostream& stream, unsigned level);
inline void dumpValue (lua_State* L, int index, std::ostream& stream, unsigned level = 0)
{
const int type = lua_type (L, index);
switch (type)
{
case LUA_TNIL:
stream << "nil";
break;
case LUA_TBOOLEAN:
stream << (lua_toboolean (L, index) ? "true" : "false");
break;
case LUA_TNUMBER:
stream << lua_tonumber (L, index);
break;
case LUA_TSTRING:
stream << '"' << lua_tostring (L, index) << '"';
break;
case LUA_TFUNCTION:
if (lua_iscfunction (L, index))
{
stream << "cfunction@" << lua_topointer (L, index);
}
else
{
stream << "function@" << lua_topointer (L, index);
}
break;
case LUA_TTHREAD:
stream << "thread@" << lua_tothread (L, index);
break;
case LUA_TLIGHTUSERDATA:
stream << "lightuserdata@" << lua_touserdata (L, index);
break;
case LUA_TTABLE:
dumpTable (L, index, stream, level);
break;
case LUA_TUSERDATA:
stream << "userdata@" << lua_touserdata (L, index);
break;
default:
stream << lua_typename (L, type);;
break;
}
}
inline void dumpTable (lua_State* L, int index, std::ostream& stream, unsigned level)
{
stream << "table@" << lua_topointer (L, index);
if (level > 0)
{
return;
}
index = lua_absindex (L, index);
stream << " {";
lua_pushnil (L); // Initial key
while (lua_next (L, index))
{
stream << "\n";
putIndent (stream, level + 1);
dumpValue (L, -2, stream, level + 1); // Key
stream << ": ";
dumpValue (L, -1, stream, level + 1); // Value
lua_pop (L, 1); // Value
}
putIndent (stream, level);
stream << "\n}";
}
inline void dumpState (lua_State *L, std::ostream& stream = std::cerr)
{
int top = lua_gettop (L);
for (int i = 1; i <= top; ++i)
{
stream << "stack #" << i << ": ";
dumpValue (L, i, stream, 0);
stream << "\n";
}
}
} // namespace debug
} // namespace luabridge

View File

@@ -1,160 +0,0 @@
/*
BLAKE2 reference source code package - reference C implementations
Copyright 2012, Samuel Neves <sneves@dei.uc.pt>. You may use this under the
terms of the CC0, the OpenSSL Licence, or the Apache Public License 2.0, at
your option. The terms of these licenses can be found at:
- CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0
- OpenSSL license : https://www.openssl.org/source/license.html
- Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0
More information about the BLAKE2 hash function can be found at
https://blake2.net.
*/
#ifndef BLAKE2_IMPL_H
#define BLAKE2_IMPL_H
#include <stdint.h>
#include <string.h>
#if !defined(__cplusplus) && (!defined(__STDC_VERSION__) || __STDC_VERSION__ < 199901L)
#if defined(_MSC_VER)
#define BLAKE2_INLINE __inline
#elif defined(__GNUC__)
#define BLAKE2_INLINE __inline__
#else
#define BLAKE2_INLINE
#endif
#else
#define BLAKE2_INLINE inline
#endif
static BLAKE2_INLINE uint32_t load32( const void *src )
{
#if defined(NATIVE_LITTLE_ENDIAN)
uint32_t w;
memcpy(&w, src, sizeof w);
return w;
#else
const uint8_t *p = ( const uint8_t * )src;
return (( uint32_t )( p[0] ) << 0) |
(( uint32_t )( p[1] ) << 8) |
(( uint32_t )( p[2] ) << 16) |
(( uint32_t )( p[3] ) << 24) ;
#endif
}
static BLAKE2_INLINE uint64_t load64( const void *src )
{
#if defined(NATIVE_LITTLE_ENDIAN)
uint64_t w;
memcpy(&w, src, sizeof w);
return w;
#else
const uint8_t *p = ( const uint8_t * )src;
return (( uint64_t )( p[0] ) << 0) |
(( uint64_t )( p[1] ) << 8) |
(( uint64_t )( p[2] ) << 16) |
(( uint64_t )( p[3] ) << 24) |
(( uint64_t )( p[4] ) << 32) |
(( uint64_t )( p[5] ) << 40) |
(( uint64_t )( p[6] ) << 48) |
(( uint64_t )( p[7] ) << 56) ;
#endif
}
static BLAKE2_INLINE uint16_t load16( const void *src )
{
#if defined(NATIVE_LITTLE_ENDIAN)
uint16_t w;
memcpy(&w, src, sizeof w);
return w;
#else
const uint8_t *p = ( const uint8_t * )src;
return ( uint16_t )((( uint32_t )( p[0] ) << 0) |
(( uint32_t )( p[1] ) << 8));
#endif
}
static BLAKE2_INLINE void store16( void *dst, uint16_t w )
{
#if defined(NATIVE_LITTLE_ENDIAN)
memcpy(dst, &w, sizeof w);
#else
uint8_t *p = ( uint8_t * )dst;
*p++ = ( uint8_t )w; w >>= 8;
*p++ = ( uint8_t )w;
#endif
}
static BLAKE2_INLINE void store32( void *dst, uint32_t w )
{
#if defined(NATIVE_LITTLE_ENDIAN)
memcpy(dst, &w, sizeof w);
#else
uint8_t *p = ( uint8_t * )dst;
p[0] = (uint8_t)(w >> 0);
p[1] = (uint8_t)(w >> 8);
p[2] = (uint8_t)(w >> 16);
p[3] = (uint8_t)(w >> 24);
#endif
}
static BLAKE2_INLINE void store64( void *dst, uint64_t w )
{
#if defined(NATIVE_LITTLE_ENDIAN)
memcpy(dst, &w, sizeof w);
#else
uint8_t *p = ( uint8_t * )dst;
p[0] = (uint8_t)(w >> 0);
p[1] = (uint8_t)(w >> 8);
p[2] = (uint8_t)(w >> 16);
p[3] = (uint8_t)(w >> 24);
p[4] = (uint8_t)(w >> 32);
p[5] = (uint8_t)(w >> 40);
p[6] = (uint8_t)(w >> 48);
p[7] = (uint8_t)(w >> 56);
#endif
}
static BLAKE2_INLINE uint64_t load48( const void *src )
{
const uint8_t *p = ( const uint8_t * )src;
return (( uint64_t )( p[0] ) << 0) |
(( uint64_t )( p[1] ) << 8) |
(( uint64_t )( p[2] ) << 16) |
(( uint64_t )( p[3] ) << 24) |
(( uint64_t )( p[4] ) << 32) |
(( uint64_t )( p[5] ) << 40) ;
}
static BLAKE2_INLINE void store48( void *dst, uint64_t w )
{
uint8_t *p = ( uint8_t * )dst;
p[0] = (uint8_t)(w >> 0);
p[1] = (uint8_t)(w >> 8);
p[2] = (uint8_t)(w >> 16);
p[3] = (uint8_t)(w >> 24);
p[4] = (uint8_t)(w >> 32);
p[5] = (uint8_t)(w >> 40);
}
static BLAKE2_INLINE uint32_t rotr32( const uint32_t w, const unsigned c )
{
return ( w >> c ) | ( w << ( 32 - c ) );
}
static BLAKE2_INLINE uint64_t rotr64( const uint64_t w, const unsigned c )
{
return ( w >> c ) | ( w << ( 64 - c ) );
}
/* prevents compiler optimizing out memset() */
static BLAKE2_INLINE void secure_zero_memory(void *v, size_t n)
{
static void *(*const volatile memset_v)(void *, int, size_t) = &memset;
memset_v(v, 0, n);
}
#endif

View File

@@ -1,195 +0,0 @@
/*
BLAKE2 reference source code package - reference C implementations
Copyright 2012, Samuel Neves <sneves@dei.uc.pt>. You may use this under the
terms of the CC0, the OpenSSL Licence, or the Apache Public License 2.0, at
your option. The terms of these licenses can be found at:
- CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0
- OpenSSL license : https://www.openssl.org/source/license.html
- Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0
More information about the BLAKE2 hash function can be found at
https://blake2.net.
*/
#ifndef BLAKE2_H
#define BLAKE2_H
#include <stddef.h>
#include <stdint.h>
#if defined(_MSC_VER)
#define BLAKE2_PACKED(x) __pragma(pack(push, 1)) x __pragma(pack(pop))
#else
#define BLAKE2_PACKED(x) x __attribute__((packed))
#endif
#if defined(__cplusplus)
extern "C" {
#endif
enum blake2s_constant
{
BLAKE2S_BLOCKBYTES = 64,
BLAKE2S_OUTBYTES = 32,
BLAKE2S_KEYBYTES = 32,
BLAKE2S_SALTBYTES = 8,
BLAKE2S_PERSONALBYTES = 8
};
enum blake2b_constant
{
BLAKE2B_BLOCKBYTES = 128,
BLAKE2B_OUTBYTES = 64,
BLAKE2B_KEYBYTES = 64,
BLAKE2B_SALTBYTES = 16,
BLAKE2B_PERSONALBYTES = 16
};
typedef struct blake2s_state__
{
uint32_t h[8];
uint32_t t[2];
uint32_t f[2];
uint8_t buf[BLAKE2S_BLOCKBYTES];
size_t buflen;
size_t outlen;
uint8_t last_node;
} blake2s_state;
typedef struct blake2b_state__
{
uint64_t h[8];
uint64_t t[2];
uint64_t f[2];
uint8_t buf[BLAKE2B_BLOCKBYTES];
size_t buflen;
size_t outlen;
uint8_t last_node;
} blake2b_state;
typedef struct blake2sp_state__
{
blake2s_state S[8][1];
blake2s_state R[1];
uint8_t buf[8 * BLAKE2S_BLOCKBYTES];
size_t buflen;
size_t outlen;
} blake2sp_state;
typedef struct blake2bp_state__
{
blake2b_state S[4][1];
blake2b_state R[1];
uint8_t buf[4 * BLAKE2B_BLOCKBYTES];
size_t buflen;
size_t outlen;
} blake2bp_state;
BLAKE2_PACKED(struct blake2s_param__
{
uint8_t digest_length; /* 1 */
uint8_t key_length; /* 2 */
uint8_t fanout; /* 3 */
uint8_t depth; /* 4 */
uint32_t leaf_length; /* 8 */
uint32_t node_offset; /* 12 */
uint16_t xof_length; /* 14 */
uint8_t node_depth; /* 15 */
uint8_t inner_length; /* 16 */
/* uint8_t reserved[0]; */
uint8_t salt[BLAKE2S_SALTBYTES]; /* 24 */
uint8_t personal[BLAKE2S_PERSONALBYTES]; /* 32 */
});
typedef struct blake2s_param__ blake2s_param;
BLAKE2_PACKED(struct blake2b_param__
{
uint8_t digest_length; /* 1 */
uint8_t key_length; /* 2 */
uint8_t fanout; /* 3 */
uint8_t depth; /* 4 */
uint32_t leaf_length; /* 8 */
uint32_t node_offset; /* 12 */
uint32_t xof_length; /* 16 */
uint8_t node_depth; /* 17 */
uint8_t inner_length; /* 18 */
uint8_t reserved[14]; /* 32 */
uint8_t salt[BLAKE2B_SALTBYTES]; /* 48 */
uint8_t personal[BLAKE2B_PERSONALBYTES]; /* 64 */
});
typedef struct blake2b_param__ blake2b_param;
typedef struct blake2xs_state__
{
blake2s_state S[1];
blake2s_param P[1];
} blake2xs_state;
typedef struct blake2xb_state__
{
blake2b_state S[1];
blake2b_param P[1];
} blake2xb_state;
/* Padded structs result in a compile-time error */
enum {
BLAKE2_DUMMY_1 = 1/(int)(sizeof(blake2s_param) == BLAKE2S_OUTBYTES),
BLAKE2_DUMMY_2 = 1/(int)(sizeof(blake2b_param) == BLAKE2B_OUTBYTES)
};
/* Streaming API */
int blake2s_init( blake2s_state *S, size_t outlen );
int blake2s_init_key( blake2s_state *S, size_t outlen, const void *key, size_t keylen );
int blake2s_init_param( blake2s_state *S, const blake2s_param *P );
int blake2s_update( blake2s_state *S, const void *in, size_t inlen );
int blake2s_final( blake2s_state *S, void *out, size_t outlen );
int blake2b_init( blake2b_state *S, size_t outlen );
int blake2b_init_key( blake2b_state *S, size_t outlen, const void *key, size_t keylen );
int blake2b_init_param( blake2b_state *S, const blake2b_param *P );
int blake2b_update( blake2b_state *S, const void *in, size_t inlen );
int blake2b_final( blake2b_state *S, void *out, size_t outlen );
int blake2sp_init( blake2sp_state *S, size_t outlen );
int blake2sp_init_key( blake2sp_state *S, size_t outlen, const void *key, size_t keylen );
int blake2sp_update( blake2sp_state *S, const void *in, size_t inlen );
int blake2sp_final( blake2sp_state *S, void *out, size_t outlen );
int blake2bp_init( blake2bp_state *S, size_t outlen );
int blake2bp_init_key( blake2bp_state *S, size_t outlen, const void *key, size_t keylen );
int blake2bp_update( blake2bp_state *S, const void *in, size_t inlen );
int blake2bp_final( blake2bp_state *S, void *out, size_t outlen );
/* Variable output length API */
int blake2xs_init( blake2xs_state *S, const size_t outlen );
int blake2xs_init_key( blake2xs_state *S, const size_t outlen, const void *key, size_t keylen );
int blake2xs_update( blake2xs_state *S, const void *in, size_t inlen );
int blake2xs_final(blake2xs_state *S, void *out, size_t outlen);
int blake2xb_init( blake2xb_state *S, const size_t outlen );
int blake2xb_init_key( blake2xb_state *S, const size_t outlen, const void *key, size_t keylen );
int blake2xb_update( blake2xb_state *S, const void *in, size_t inlen );
int blake2xb_final(blake2xb_state *S, void *out, size_t outlen);
/* Simple API */
int blake2s( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen );
int blake2b( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen );
int blake2sp( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen );
int blake2bp( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen );
int blake2xs( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen );
int blake2xb( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen );
/* This is simply an alias for blake2b */
int blake2( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen );
#if defined(__cplusplus)
}
#endif
#endif

View File

@@ -1,379 +0,0 @@
/*
BLAKE2 reference source code package - reference C implementations
Copyright 2012, Samuel Neves <sneves@dei.uc.pt>. You may use this under the
terms of the CC0, the OpenSSL Licence, or the Apache Public License 2.0, at
your option. The terms of these licenses can be found at:
- CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0
- OpenSSL license : https://www.openssl.org/source/license.html
- Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0
More information about the BLAKE2 hash function can be found at
https://blake2.net.
*/
#include <stdint.h>
#include <string.h>
#include <stdio.h>
#include "blake2.h"
#include "blake2-impl.h"
static const uint64_t blake2b_IV[8] =
{
0x6a09e667f3bcc908ULL, 0xbb67ae8584caa73bULL,
0x3c6ef372fe94f82bULL, 0xa54ff53a5f1d36f1ULL,
0x510e527fade682d1ULL, 0x9b05688c2b3e6c1fULL,
0x1f83d9abfb41bd6bULL, 0x5be0cd19137e2179ULL
};
static const uint8_t blake2b_sigma[12][16] =
{
{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 } ,
{ 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 } ,
{ 11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4 } ,
{ 7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8 } ,
{ 9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13 } ,
{ 2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9 } ,
{ 12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11 } ,
{ 13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10 } ,
{ 6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5 } ,
{ 10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13 , 0 } ,
{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 } ,
{ 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 }
};
static void blake2b_set_lastnode( blake2b_state *S )
{
S->f[1] = (uint64_t)-1;
}
/* Some helper functions, not necessarily useful */
static int blake2b_is_lastblock( const blake2b_state *S )
{
return S->f[0] != 0;
}
static void blake2b_set_lastblock( blake2b_state *S )
{
if( S->last_node ) blake2b_set_lastnode( S );
S->f[0] = (uint64_t)-1;
}
static void blake2b_increment_counter( blake2b_state *S, const uint64_t inc )
{
S->t[0] += inc;
S->t[1] += ( S->t[0] < inc );
}
static void blake2b_init0( blake2b_state *S )
{
size_t i;
memset( S, 0, sizeof( blake2b_state ) );
for( i = 0; i < 8; ++i ) S->h[i] = blake2b_IV[i];
}
/* init xors IV with input parameter block */
int blake2b_init_param( blake2b_state *S, const blake2b_param *P )
{
const uint8_t *p = ( const uint8_t * )( P );
size_t i;
blake2b_init0( S );
/* IV XOR ParamBlock */
for( i = 0; i < 8; ++i )
S->h[i] ^= load64( p + sizeof( S->h[i] ) * i );
S->outlen = P->digest_length;
return 0;
}
int blake2b_init( blake2b_state *S, size_t outlen )
{
blake2b_param P[1];
if ( ( !outlen ) || ( outlen > BLAKE2B_OUTBYTES ) ) return -1;
P->digest_length = (uint8_t)outlen;
P->key_length = 0;
P->fanout = 1;
P->depth = 1;
store32( &P->leaf_length, 0 );
store32( &P->node_offset, 0 );
store32( &P->xof_length, 0 );
P->node_depth = 0;
P->inner_length = 0;
memset( P->reserved, 0, sizeof( P->reserved ) );
memset( P->salt, 0, sizeof( P->salt ) );
memset( P->personal, 0, sizeof( P->personal ) );
return blake2b_init_param( S, P );
}
int blake2b_init_key( blake2b_state *S, size_t outlen, const void *key, size_t keylen )
{
blake2b_param P[1];
if ( ( !outlen ) || ( outlen > BLAKE2B_OUTBYTES ) ) return -1;
if ( !key || !keylen || keylen > BLAKE2B_KEYBYTES ) return -1;
P->digest_length = (uint8_t)outlen;
P->key_length = (uint8_t)keylen;
P->fanout = 1;
P->depth = 1;
store32( &P->leaf_length, 0 );
store32( &P->node_offset, 0 );
store32( &P->xof_length, 0 );
P->node_depth = 0;
P->inner_length = 0;
memset( P->reserved, 0, sizeof( P->reserved ) );
memset( P->salt, 0, sizeof( P->salt ) );
memset( P->personal, 0, sizeof( P->personal ) );
if( blake2b_init_param( S, P ) < 0 ) return -1;
{
uint8_t block[BLAKE2B_BLOCKBYTES];
memset( block, 0, BLAKE2B_BLOCKBYTES );
memcpy( block, key, keylen );
blake2b_update( S, block, BLAKE2B_BLOCKBYTES );
secure_zero_memory( block, BLAKE2B_BLOCKBYTES ); /* Burn the key from stack */
}
return 0;
}
#define G(r,i,a,b,c,d) \
do { \
a = a + b + m[blake2b_sigma[r][2*i+0]]; \
d = rotr64(d ^ a, 32); \
c = c + d; \
b = rotr64(b ^ c, 24); \
a = a + b + m[blake2b_sigma[r][2*i+1]]; \
d = rotr64(d ^ a, 16); \
c = c + d; \
b = rotr64(b ^ c, 63); \
} while(0)
#define ROUND(r) \
do { \
G(r,0,v[ 0],v[ 4],v[ 8],v[12]); \
G(r,1,v[ 1],v[ 5],v[ 9],v[13]); \
G(r,2,v[ 2],v[ 6],v[10],v[14]); \
G(r,3,v[ 3],v[ 7],v[11],v[15]); \
G(r,4,v[ 0],v[ 5],v[10],v[15]); \
G(r,5,v[ 1],v[ 6],v[11],v[12]); \
G(r,6,v[ 2],v[ 7],v[ 8],v[13]); \
G(r,7,v[ 3],v[ 4],v[ 9],v[14]); \
} while(0)
static void blake2b_compress( blake2b_state *S, const uint8_t block[BLAKE2B_BLOCKBYTES] )
{
uint64_t m[16];
uint64_t v[16];
size_t i;
for( i = 0; i < 16; ++i ) {
m[i] = load64( block + i * sizeof( m[i] ) );
}
for( i = 0; i < 8; ++i ) {
v[i] = S->h[i];
}
v[ 8] = blake2b_IV[0];
v[ 9] = blake2b_IV[1];
v[10] = blake2b_IV[2];
v[11] = blake2b_IV[3];
v[12] = blake2b_IV[4] ^ S->t[0];
v[13] = blake2b_IV[5] ^ S->t[1];
v[14] = blake2b_IV[6] ^ S->f[0];
v[15] = blake2b_IV[7] ^ S->f[1];
ROUND( 0 );
ROUND( 1 );
ROUND( 2 );
ROUND( 3 );
ROUND( 4 );
ROUND( 5 );
ROUND( 6 );
ROUND( 7 );
ROUND( 8 );
ROUND( 9 );
ROUND( 10 );
ROUND( 11 );
for( i = 0; i < 8; ++i ) {
S->h[i] = S->h[i] ^ v[i] ^ v[i + 8];
}
}
#undef G
#undef ROUND
int blake2b_update( blake2b_state *S, const void *pin, size_t inlen )
{
const unsigned char * in = (const unsigned char *)pin;
if( inlen > 0 )
{
size_t left = S->buflen;
size_t fill = BLAKE2B_BLOCKBYTES - left;
if( inlen > fill )
{
S->buflen = 0;
memcpy( S->buf + left, in, fill ); /* Fill buffer */
blake2b_increment_counter( S, BLAKE2B_BLOCKBYTES );
blake2b_compress( S, S->buf ); /* Compress */
in += fill; inlen -= fill;
while(inlen > BLAKE2B_BLOCKBYTES) {
blake2b_increment_counter(S, BLAKE2B_BLOCKBYTES);
blake2b_compress( S, in );
in += BLAKE2B_BLOCKBYTES;
inlen -= BLAKE2B_BLOCKBYTES;
}
}
memcpy( S->buf + S->buflen, in, inlen );
S->buflen += inlen;
}
return 0;
}
int blake2b_final( blake2b_state *S, void *out, size_t outlen )
{
uint8_t buffer[BLAKE2B_OUTBYTES] = {0};
size_t i;
if( out == NULL || outlen < S->outlen )
return -1;
if( blake2b_is_lastblock( S ) )
return -1;
blake2b_increment_counter( S, S->buflen );
blake2b_set_lastblock( S );
memset( S->buf + S->buflen, 0, BLAKE2B_BLOCKBYTES - S->buflen ); /* Padding */
blake2b_compress( S, S->buf );
for( i = 0; i < 8; ++i ) /* Output full hash to temp buffer */
store64( buffer + sizeof( S->h[i] ) * i, S->h[i] );
memcpy( out, buffer, S->outlen );
secure_zero_memory(buffer, sizeof(buffer));
return 0;
}
/* inlen, at least, should be uint64_t. Others can be size_t. */
int blake2b( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen )
{
blake2b_state S[1];
/* Verify parameters */
if ( NULL == in && inlen > 0 ) return -1;
if ( NULL == out ) return -1;
if( NULL == key && keylen > 0 ) return -1;
if( !outlen || outlen > BLAKE2B_OUTBYTES ) return -1;
if( keylen > BLAKE2B_KEYBYTES ) return -1;
if( keylen > 0 )
{
if( blake2b_init_key( S, outlen, key, keylen ) < 0 ) return -1;
}
else
{
if( blake2b_init( S, outlen ) < 0 ) return -1;
}
blake2b_update( S, ( const uint8_t * )in, inlen );
blake2b_final( S, out, outlen );
return 0;
}
int blake2( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen ) {
return blake2b(out, outlen, in, inlen, key, keylen);
}
#if defined(SUPERCOP)
int crypto_hash( unsigned char *out, unsigned char *in, unsigned long long inlen )
{
return blake2b( out, BLAKE2B_OUTBYTES, in, inlen, NULL, 0 );
}
#endif
#if defined(BLAKE2B_SELFTEST)
#include <string.h>
#include "blake2-kat.h"
int main( void )
{
uint8_t key[BLAKE2B_KEYBYTES];
uint8_t buf[BLAKE2_KAT_LENGTH];
size_t i, step;
for( i = 0; i < BLAKE2B_KEYBYTES; ++i )
key[i] = ( uint8_t )i;
for( i = 0; i < BLAKE2_KAT_LENGTH; ++i )
buf[i] = ( uint8_t )i;
/* Test simple API */
for( i = 0; i < BLAKE2_KAT_LENGTH; ++i )
{
uint8_t hash[BLAKE2B_OUTBYTES];
blake2b( hash, BLAKE2B_OUTBYTES, buf, i, key, BLAKE2B_KEYBYTES );
if( 0 != memcmp( hash, blake2b_keyed_kat[i], BLAKE2B_OUTBYTES ) )
{
goto fail;
}
}
/* Test streaming API */
for(step = 1; step < BLAKE2B_BLOCKBYTES; ++step) {
for (i = 0; i < BLAKE2_KAT_LENGTH; ++i) {
uint8_t hash[BLAKE2B_OUTBYTES];
blake2b_state S;
uint8_t * p = buf;
size_t mlen = i;
int err = 0;
if( (err = blake2b_init_key(&S, BLAKE2B_OUTBYTES, key, BLAKE2B_KEYBYTES)) < 0 ) {
goto fail;
}
while (mlen >= step) {
if ( (err = blake2b_update(&S, p, step)) < 0 ) {
goto fail;
}
mlen -= step;
p += step;
}
if ( (err = blake2b_update(&S, p, mlen)) < 0) {
goto fail;
}
if ( (err = blake2b_final(&S, hash, BLAKE2B_OUTBYTES)) < 0) {
goto fail;
}
if (0 != memcmp(hash, blake2b_keyed_kat[i], BLAKE2B_OUTBYTES)) {
goto fail;
}
}
}
puts( "ok" );
return 0;
fail:
puts("error");
return -1;
}
#endif

View File

@@ -1,359 +0,0 @@
/*
BLAKE2 reference source code package - reference C implementations
Copyright 2012, Samuel Neves <sneves@dei.uc.pt>. You may use this under the
terms of the CC0, the OpenSSL Licence, or the Apache Public License 2.0, at
your option. The terms of these licenses can be found at:
- CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0
- OpenSSL license : https://www.openssl.org/source/license.html
- Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0
More information about the BLAKE2 hash function can be found at
https://blake2.net.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#if defined(_OPENMP)
#include <omp.h>
#endif
#include "blake2.h"
#include "blake2-impl.h"
#define PARALLELISM_DEGREE 4
/*
blake2b_init_param defaults to setting the expecting output length
from the digest_length parameter block field.
In some cases, however, we do not want this, as the output length
of these instances is given by inner_length instead.
*/
static int blake2bp_init_leaf_param( blake2b_state *S, const blake2b_param *P )
{
int err = blake2b_init_param(S, P);
S->outlen = P->inner_length;
return err;
}
static int blake2bp_init_leaf( blake2b_state *S, size_t outlen, size_t keylen, uint64_t offset )
{
blake2b_param P[1];
P->digest_length = (uint8_t)outlen;
P->key_length = (uint8_t)keylen;
P->fanout = PARALLELISM_DEGREE;
P->depth = 2;
store32( &P->leaf_length, 0 );
store32( &P->node_offset, offset );
store32( &P->xof_length, 0 );
P->node_depth = 0;
P->inner_length = BLAKE2B_OUTBYTES;
memset( P->reserved, 0, sizeof( P->reserved ) );
memset( P->salt, 0, sizeof( P->salt ) );
memset( P->personal, 0, sizeof( P->personal ) );
return blake2bp_init_leaf_param( S, P );
}
static int blake2bp_init_root( blake2b_state *S, size_t outlen, size_t keylen )
{
blake2b_param P[1];
P->digest_length = (uint8_t)outlen;
P->key_length = (uint8_t)keylen;
P->fanout = PARALLELISM_DEGREE;
P->depth = 2;
store32( &P->leaf_length, 0 );
store32( &P->node_offset, 0 );
store32( &P->xof_length, 0 );
P->node_depth = 1;
P->inner_length = BLAKE2B_OUTBYTES;
memset( P->reserved, 0, sizeof( P->reserved ) );
memset( P->salt, 0, sizeof( P->salt ) );
memset( P->personal, 0, sizeof( P->personal ) );
return blake2b_init_param( S, P );
}
int blake2bp_init( blake2bp_state *S, size_t outlen )
{
size_t i;
if( !outlen || outlen > BLAKE2B_OUTBYTES ) return -1;
memset( S->buf, 0, sizeof( S->buf ) );
S->buflen = 0;
S->outlen = outlen;
if( blake2bp_init_root( S->R, outlen, 0 ) < 0 )
return -1;
for( i = 0; i < PARALLELISM_DEGREE; ++i )
if( blake2bp_init_leaf( S->S[i], outlen, 0, i ) < 0 ) return -1;
S->R->last_node = 1;
S->S[PARALLELISM_DEGREE - 1]->last_node = 1;
return 0;
}
int blake2bp_init_key( blake2bp_state *S, size_t outlen, const void *key, size_t keylen )
{
size_t i;
if( !outlen || outlen > BLAKE2B_OUTBYTES ) return -1;
if( !key || !keylen || keylen > BLAKE2B_KEYBYTES ) return -1;
memset( S->buf, 0, sizeof( S->buf ) );
S->buflen = 0;
S->outlen = outlen;
if( blake2bp_init_root( S->R, outlen, keylen ) < 0 )
return -1;
for( i = 0; i < PARALLELISM_DEGREE; ++i )
if( blake2bp_init_leaf( S->S[i], outlen, keylen, i ) < 0 ) return -1;
S->R->last_node = 1;
S->S[PARALLELISM_DEGREE - 1]->last_node = 1;
{
uint8_t block[BLAKE2B_BLOCKBYTES];
memset( block, 0, BLAKE2B_BLOCKBYTES );
memcpy( block, key, keylen );
for( i = 0; i < PARALLELISM_DEGREE; ++i )
blake2b_update( S->S[i], block, BLAKE2B_BLOCKBYTES );
secure_zero_memory( block, BLAKE2B_BLOCKBYTES ); /* Burn the key from stack */
}
return 0;
}
int blake2bp_update( blake2bp_state *S, const void *pin, size_t inlen )
{
const unsigned char * in = (const unsigned char *)pin;
size_t left = S->buflen;
size_t fill = sizeof( S->buf ) - left;
size_t i;
if( left && inlen >= fill )
{
memcpy( S->buf + left, in, fill );
for( i = 0; i < PARALLELISM_DEGREE; ++i )
blake2b_update( S->S[i], S->buf + i * BLAKE2B_BLOCKBYTES, BLAKE2B_BLOCKBYTES );
in += fill;
inlen -= fill;
left = 0;
}
#if defined(_OPENMP)
#pragma omp parallel shared(S), num_threads(PARALLELISM_DEGREE)
#else
for( i = 0; i < PARALLELISM_DEGREE; ++i )
#endif
{
#if defined(_OPENMP)
size_t i = omp_get_thread_num();
#endif
size_t inlen__ = inlen;
const unsigned char *in__ = ( const unsigned char * )in;
in__ += i * BLAKE2B_BLOCKBYTES;
while( inlen__ >= PARALLELISM_DEGREE * BLAKE2B_BLOCKBYTES )
{
blake2b_update( S->S[i], in__, BLAKE2B_BLOCKBYTES );
in__ += PARALLELISM_DEGREE * BLAKE2B_BLOCKBYTES;
inlen__ -= PARALLELISM_DEGREE * BLAKE2B_BLOCKBYTES;
}
}
in += inlen - inlen % ( PARALLELISM_DEGREE * BLAKE2B_BLOCKBYTES );
inlen %= PARALLELISM_DEGREE * BLAKE2B_BLOCKBYTES;
if( inlen > 0 )
memcpy( S->buf + left, in, inlen );
S->buflen = left + inlen;
return 0;
}
int blake2bp_final( blake2bp_state *S, void *out, size_t outlen )
{
uint8_t hash[PARALLELISM_DEGREE][BLAKE2B_OUTBYTES];
size_t i;
if(out == NULL || outlen < S->outlen) {
return -1;
}
for( i = 0; i < PARALLELISM_DEGREE; ++i )
{
if( S->buflen > i * BLAKE2B_BLOCKBYTES )
{
size_t left = S->buflen - i * BLAKE2B_BLOCKBYTES;
if( left > BLAKE2B_BLOCKBYTES ) left = BLAKE2B_BLOCKBYTES;
blake2b_update( S->S[i], S->buf + i * BLAKE2B_BLOCKBYTES, left );
}
blake2b_final( S->S[i], hash[i], BLAKE2B_OUTBYTES );
}
for( i = 0; i < PARALLELISM_DEGREE; ++i )
blake2b_update( S->R, hash[i], BLAKE2B_OUTBYTES );
return blake2b_final( S->R, out, S->outlen );
}
int blake2bp( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen )
{
uint8_t hash[PARALLELISM_DEGREE][BLAKE2B_OUTBYTES];
blake2b_state S[PARALLELISM_DEGREE][1];
blake2b_state FS[1];
size_t i;
/* Verify parameters */
if ( NULL == in && inlen > 0 ) return -1;
if ( NULL == out ) return -1;
if( NULL == key && keylen > 0 ) return -1;
if( !outlen || outlen > BLAKE2B_OUTBYTES ) return -1;
if( keylen > BLAKE2B_KEYBYTES ) return -1;
for( i = 0; i < PARALLELISM_DEGREE; ++i )
if( blake2bp_init_leaf( S[i], outlen, keylen, i ) < 0 ) return -1;
S[PARALLELISM_DEGREE - 1]->last_node = 1; /* mark last node */
if( keylen > 0 )
{
uint8_t block[BLAKE2B_BLOCKBYTES];
memset( block, 0, BLAKE2B_BLOCKBYTES );
memcpy( block, key, keylen );
for( i = 0; i < PARALLELISM_DEGREE; ++i )
blake2b_update( S[i], block, BLAKE2B_BLOCKBYTES );
secure_zero_memory( block, BLAKE2B_BLOCKBYTES ); /* Burn the key from stack */
}
#if defined(_OPENMP)
#pragma omp parallel shared(S,hash), num_threads(PARALLELISM_DEGREE)
#else
for( i = 0; i < PARALLELISM_DEGREE; ++i )
#endif
{
#if defined(_OPENMP)
size_t i = omp_get_thread_num();
#endif
size_t inlen__ = inlen;
const unsigned char *in__ = ( const unsigned char * )in;
in__ += i * BLAKE2B_BLOCKBYTES;
while( inlen__ >= PARALLELISM_DEGREE * BLAKE2B_BLOCKBYTES )
{
blake2b_update( S[i], in__, BLAKE2B_BLOCKBYTES );
in__ += PARALLELISM_DEGREE * BLAKE2B_BLOCKBYTES;
inlen__ -= PARALLELISM_DEGREE * BLAKE2B_BLOCKBYTES;
}
if( inlen__ > i * BLAKE2B_BLOCKBYTES )
{
const size_t left = inlen__ - i * BLAKE2B_BLOCKBYTES;
const size_t len = left <= BLAKE2B_BLOCKBYTES ? left : BLAKE2B_BLOCKBYTES;
blake2b_update( S[i], in__, len );
}
blake2b_final( S[i], hash[i], BLAKE2B_OUTBYTES );
}
if( blake2bp_init_root( FS, outlen, keylen ) < 0 )
return -1;
FS->last_node = 1; /* Mark as last node */
for( i = 0; i < PARALLELISM_DEGREE; ++i )
blake2b_update( FS, hash[i], BLAKE2B_OUTBYTES );
return blake2b_final( FS, out, outlen );;
}
#if defined(BLAKE2BP_SELFTEST)
#include <string.h>
#include "blake2-kat.h"
int main( void )
{
uint8_t key[BLAKE2B_KEYBYTES];
uint8_t buf[BLAKE2_KAT_LENGTH];
size_t i, step;
for( i = 0; i < BLAKE2B_KEYBYTES; ++i )
key[i] = ( uint8_t )i;
for( i = 0; i < BLAKE2_KAT_LENGTH; ++i )
buf[i] = ( uint8_t )i;
/* Test simple API */
for( i = 0; i < BLAKE2_KAT_LENGTH; ++i )
{
uint8_t hash[BLAKE2B_OUTBYTES];
blake2bp( hash, BLAKE2B_OUTBYTES, buf, i, key, BLAKE2B_KEYBYTES );
if( 0 != memcmp( hash, blake2bp_keyed_kat[i], BLAKE2B_OUTBYTES ) )
{
goto fail;
}
}
/* Test streaming API */
for(step = 1; step < BLAKE2B_BLOCKBYTES; ++step) {
for (i = 0; i < BLAKE2_KAT_LENGTH; ++i) {
uint8_t hash[BLAKE2B_OUTBYTES];
blake2bp_state S;
uint8_t * p = buf;
size_t mlen = i;
int err = 0;
if( (err = blake2bp_init_key(&S, BLAKE2B_OUTBYTES, key, BLAKE2B_KEYBYTES)) < 0 ) {
goto fail;
}
while (mlen >= step) {
if ( (err = blake2bp_update(&S, p, step)) < 0 ) {
goto fail;
}
mlen -= step;
p += step;
}
if ( (err = blake2bp_update(&S, p, mlen)) < 0) {
goto fail;
}
if ( (err = blake2bp_final(&S, hash, BLAKE2B_OUTBYTES)) < 0) {
goto fail;
}
if (0 != memcmp(hash, blake2bp_keyed_kat[i], BLAKE2B_OUTBYTES)) {
goto fail;
}
}
}
puts( "ok" );
return 0;
fail:
puts("error");
return -1;
}
#endif

View File

@@ -1,367 +0,0 @@
/*
BLAKE2 reference source code package - reference C implementations
Copyright 2012, Samuel Neves <sneves@dei.uc.pt>. You may use this under the
terms of the CC0, the OpenSSL Licence, or the Apache Public License 2.0, at
your option. The terms of these licenses can be found at:
- CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0
- OpenSSL license : https://www.openssl.org/source/license.html
- Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0
More information about the BLAKE2 hash function can be found at
https://blake2.net.
*/
#include <stdint.h>
#include <string.h>
#include <stdio.h>
#include "blake2.h"
#include "blake2-impl.h"
static const uint32_t blake2s_IV[8] =
{
0x6A09E667UL, 0xBB67AE85UL, 0x3C6EF372UL, 0xA54FF53AUL,
0x510E527FUL, 0x9B05688CUL, 0x1F83D9ABUL, 0x5BE0CD19UL
};
static const uint8_t blake2s_sigma[10][16] =
{
{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 } ,
{ 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 } ,
{ 11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4 } ,
{ 7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8 } ,
{ 9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13 } ,
{ 2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9 } ,
{ 12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11 } ,
{ 13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10 } ,
{ 6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5 } ,
{ 10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13 , 0 } ,
};
static void blake2s_set_lastnode( blake2s_state *S )
{
S->f[1] = (uint32_t)-1;
}
/* Some helper functions, not necessarily useful */
static int blake2s_is_lastblock( const blake2s_state *S )
{
return S->f[0] != 0;
}
static void blake2s_set_lastblock( blake2s_state *S )
{
if( S->last_node ) blake2s_set_lastnode( S );
S->f[0] = (uint32_t)-1;
}
static void blake2s_increment_counter( blake2s_state *S, const uint32_t inc )
{
S->t[0] += inc;
S->t[1] += ( S->t[0] < inc );
}
static void blake2s_init0( blake2s_state *S )
{
size_t i;
memset( S, 0, sizeof( blake2s_state ) );
for( i = 0; i < 8; ++i ) S->h[i] = blake2s_IV[i];
}
/* init2 xors IV with input parameter block */
int blake2s_init_param( blake2s_state *S, const blake2s_param *P )
{
const unsigned char *p = ( const unsigned char * )( P );
size_t i;
blake2s_init0( S );
/* IV XOR ParamBlock */
for( i = 0; i < 8; ++i )
S->h[i] ^= load32( &p[i * 4] );
S->outlen = P->digest_length;
return 0;
}
/* Sequential blake2s initialization */
int blake2s_init( blake2s_state *S, size_t outlen )
{
blake2s_param P[1];
/* Move interval verification here? */
if ( ( !outlen ) || ( outlen > BLAKE2S_OUTBYTES ) ) return -1;
P->digest_length = (uint8_t)outlen;
P->key_length = 0;
P->fanout = 1;
P->depth = 1;
store32( &P->leaf_length, 0 );
store32( &P->node_offset, 0 );
store16( &P->xof_length, 0 );
P->node_depth = 0;
P->inner_length = 0;
/* memset(P->reserved, 0, sizeof(P->reserved) ); */
memset( P->salt, 0, sizeof( P->salt ) );
memset( P->personal, 0, sizeof( P->personal ) );
return blake2s_init_param( S, P );
}
int blake2s_init_key( blake2s_state *S, size_t outlen, const void *key, size_t keylen )
{
blake2s_param P[1];
if ( ( !outlen ) || ( outlen > BLAKE2S_OUTBYTES ) ) return -1;
if ( !key || !keylen || keylen > BLAKE2S_KEYBYTES ) return -1;
P->digest_length = (uint8_t)outlen;
P->key_length = (uint8_t)keylen;
P->fanout = 1;
P->depth = 1;
store32( &P->leaf_length, 0 );
store32( &P->node_offset, 0 );
store16( &P->xof_length, 0 );
P->node_depth = 0;
P->inner_length = 0;
/* memset(P->reserved, 0, sizeof(P->reserved) ); */
memset( P->salt, 0, sizeof( P->salt ) );
memset( P->personal, 0, sizeof( P->personal ) );
if( blake2s_init_param( S, P ) < 0 ) return -1;
{
uint8_t block[BLAKE2S_BLOCKBYTES];
memset( block, 0, BLAKE2S_BLOCKBYTES );
memcpy( block, key, keylen );
blake2s_update( S, block, BLAKE2S_BLOCKBYTES );
secure_zero_memory( block, BLAKE2S_BLOCKBYTES ); /* Burn the key from stack */
}
return 0;
}
#define G(r,i,a,b,c,d) \
do { \
a = a + b + m[blake2s_sigma[r][2*i+0]]; \
d = rotr32(d ^ a, 16); \
c = c + d; \
b = rotr32(b ^ c, 12); \
a = a + b + m[blake2s_sigma[r][2*i+1]]; \
d = rotr32(d ^ a, 8); \
c = c + d; \
b = rotr32(b ^ c, 7); \
} while(0)
#define ROUND(r) \
do { \
G(r,0,v[ 0],v[ 4],v[ 8],v[12]); \
G(r,1,v[ 1],v[ 5],v[ 9],v[13]); \
G(r,2,v[ 2],v[ 6],v[10],v[14]); \
G(r,3,v[ 3],v[ 7],v[11],v[15]); \
G(r,4,v[ 0],v[ 5],v[10],v[15]); \
G(r,5,v[ 1],v[ 6],v[11],v[12]); \
G(r,6,v[ 2],v[ 7],v[ 8],v[13]); \
G(r,7,v[ 3],v[ 4],v[ 9],v[14]); \
} while(0)
static void blake2s_compress( blake2s_state *S, const uint8_t in[BLAKE2S_BLOCKBYTES] )
{
uint32_t m[16];
uint32_t v[16];
size_t i;
for( i = 0; i < 16; ++i ) {
m[i] = load32( in + i * sizeof( m[i] ) );
}
for( i = 0; i < 8; ++i ) {
v[i] = S->h[i];
}
v[ 8] = blake2s_IV[0];
v[ 9] = blake2s_IV[1];
v[10] = blake2s_IV[2];
v[11] = blake2s_IV[3];
v[12] = S->t[0] ^ blake2s_IV[4];
v[13] = S->t[1] ^ blake2s_IV[5];
v[14] = S->f[0] ^ blake2s_IV[6];
v[15] = S->f[1] ^ blake2s_IV[7];
ROUND( 0 );
ROUND( 1 );
ROUND( 2 );
ROUND( 3 );
ROUND( 4 );
ROUND( 5 );
ROUND( 6 );
ROUND( 7 );
ROUND( 8 );
ROUND( 9 );
for( i = 0; i < 8; ++i ) {
S->h[i] = S->h[i] ^ v[i] ^ v[i + 8];
}
}
#undef G
#undef ROUND
int blake2s_update( blake2s_state *S, const void *pin, size_t inlen )
{
const unsigned char * in = (const unsigned char *)pin;
if( inlen > 0 )
{
size_t left = S->buflen;
size_t fill = BLAKE2S_BLOCKBYTES - left;
if( inlen > fill )
{
S->buflen = 0;
memcpy( S->buf + left, in, fill ); /* Fill buffer */
blake2s_increment_counter( S, BLAKE2S_BLOCKBYTES );
blake2s_compress( S, S->buf ); /* Compress */
in += fill; inlen -= fill;
while(inlen > BLAKE2S_BLOCKBYTES) {
blake2s_increment_counter(S, BLAKE2S_BLOCKBYTES);
blake2s_compress( S, in );
in += BLAKE2S_BLOCKBYTES;
inlen -= BLAKE2S_BLOCKBYTES;
}
}
memcpy( S->buf + S->buflen, in, inlen );
S->buflen += inlen;
}
return 0;
}
int blake2s_final( blake2s_state *S, void *out, size_t outlen )
{
uint8_t buffer[BLAKE2S_OUTBYTES] = {0};
size_t i;
if( out == NULL || outlen < S->outlen )
return -1;
if( blake2s_is_lastblock( S ) )
return -1;
blake2s_increment_counter( S, ( uint32_t )S->buflen );
blake2s_set_lastblock( S );
memset( S->buf + S->buflen, 0, BLAKE2S_BLOCKBYTES - S->buflen ); /* Padding */
blake2s_compress( S, S->buf );
for( i = 0; i < 8; ++i ) /* Output full hash to temp buffer */
store32( buffer + sizeof( S->h[i] ) * i, S->h[i] );
memcpy( out, buffer, outlen );
secure_zero_memory(buffer, sizeof(buffer));
return 0;
}
int blake2s( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen )
{
blake2s_state S[1];
/* Verify parameters */
if ( NULL == in && inlen > 0 ) return -1;
if ( NULL == out ) return -1;
if ( NULL == key && keylen > 0) return -1;
if( !outlen || outlen > BLAKE2S_OUTBYTES ) return -1;
if( keylen > BLAKE2S_KEYBYTES ) return -1;
if( keylen > 0 )
{
if( blake2s_init_key( S, outlen, key, keylen ) < 0 ) return -1;
}
else
{
if( blake2s_init( S, outlen ) < 0 ) return -1;
}
blake2s_update( S, ( const uint8_t * )in, inlen );
blake2s_final( S, out, outlen );
return 0;
}
#if defined(SUPERCOP)
int crypto_hash( unsigned char *out, unsigned char *in, unsigned long long inlen )
{
return blake2s( out, BLAKE2S_OUTBYTES, in, inlen, NULL, 0 );
}
#endif
#if defined(BLAKE2S_SELFTEST)
#include <string.h>
#include "blake2-kat.h"
int main( void )
{
uint8_t key[BLAKE2S_KEYBYTES];
uint8_t buf[BLAKE2_KAT_LENGTH];
size_t i, step;
for( i = 0; i < BLAKE2S_KEYBYTES; ++i )
key[i] = ( uint8_t )i;
for( i = 0; i < BLAKE2_KAT_LENGTH; ++i )
buf[i] = ( uint8_t )i;
/* Test simple API */
for( i = 0; i < BLAKE2_KAT_LENGTH; ++i )
{
uint8_t hash[BLAKE2S_OUTBYTES];
blake2s( hash, BLAKE2S_OUTBYTES, buf, i, key, BLAKE2S_KEYBYTES );
if( 0 != memcmp( hash, blake2s_keyed_kat[i], BLAKE2S_OUTBYTES ) )
{
goto fail;
}
}
/* Test streaming API */
for(step = 1; step < BLAKE2S_BLOCKBYTES; ++step) {
for (i = 0; i < BLAKE2_KAT_LENGTH; ++i) {
uint8_t hash[BLAKE2S_OUTBYTES];
blake2s_state S;
uint8_t * p = buf;
size_t mlen = i;
int err = 0;
if( (err = blake2s_init_key(&S, BLAKE2S_OUTBYTES, key, BLAKE2S_KEYBYTES)) < 0 ) {
goto fail;
}
while (mlen >= step) {
if ( (err = blake2s_update(&S, p, step)) < 0 ) {
goto fail;
}
mlen -= step;
p += step;
}
if ( (err = blake2s_update(&S, p, mlen)) < 0) {
goto fail;
}
if ( (err = blake2s_final(&S, hash, BLAKE2S_OUTBYTES)) < 0) {
goto fail;
}
if (0 != memcmp(hash, blake2s_keyed_kat[i], BLAKE2S_OUTBYTES)) {
goto fail;
}
}
}
puts( "ok" );
return 0;
fail:
puts("error");
return -1;
}
#endif

View File

@@ -1,359 +0,0 @@
/*
BLAKE2 reference source code package - reference C implementations
Copyright 2012, Samuel Neves <sneves@dei.uc.pt>. You may use this under the
terms of the CC0, the OpenSSL Licence, or the Apache Public License 2.0, at
your option. The terms of these licenses can be found at:
- CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0
- OpenSSL license : https://www.openssl.org/source/license.html
- Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0
More information about the BLAKE2 hash function can be found at
https://blake2.net.
*/
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#if defined(_OPENMP)
#include <omp.h>
#endif
#include "blake2.h"
#include "blake2-impl.h"
#define PARALLELISM_DEGREE 8
/*
blake2sp_init_param defaults to setting the expecting output length
from the digest_length parameter block field.
In some cases, however, we do not want this, as the output length
of these instances is given by inner_length instead.
*/
static int blake2sp_init_leaf_param( blake2s_state *S, const blake2s_param *P )
{
int err = blake2s_init_param(S, P);
S->outlen = P->inner_length;
return err;
}
static int blake2sp_init_leaf( blake2s_state *S, size_t outlen, size_t keylen, uint64_t offset )
{
blake2s_param P[1];
P->digest_length = (uint8_t)outlen;
P->key_length = (uint8_t)keylen;
P->fanout = PARALLELISM_DEGREE;
P->depth = 2;
store32( &P->leaf_length, 0 );
store32( &P->node_offset, offset );
store16( &P->xof_length, 0 );
P->node_depth = 0;
P->inner_length = BLAKE2S_OUTBYTES;
memset( P->salt, 0, sizeof( P->salt ) );
memset( P->personal, 0, sizeof( P->personal ) );
return blake2sp_init_leaf_param( S, P );
}
static int blake2sp_init_root( blake2s_state *S, size_t outlen, size_t keylen )
{
blake2s_param P[1];
P->digest_length = (uint8_t)outlen;
P->key_length = (uint8_t)keylen;
P->fanout = PARALLELISM_DEGREE;
P->depth = 2;
store32( &P->leaf_length, 0 );
store32( &P->node_offset, 0 );
store16( &P->xof_length, 0 );
P->node_depth = 1;
P->inner_length = BLAKE2S_OUTBYTES;
memset( P->salt, 0, sizeof( P->salt ) );
memset( P->personal, 0, sizeof( P->personal ) );
return blake2s_init_param( S, P );
}
int blake2sp_init( blake2sp_state *S, size_t outlen )
{
size_t i;
if( !outlen || outlen > BLAKE2S_OUTBYTES ) return -1;
memset( S->buf, 0, sizeof( S->buf ) );
S->buflen = 0;
S->outlen = outlen;
if( blake2sp_init_root( S->R, outlen, 0 ) < 0 )
return -1;
for( i = 0; i < PARALLELISM_DEGREE; ++i )
if( blake2sp_init_leaf( S->S[i], outlen, 0, i ) < 0 ) return -1;
S->R->last_node = 1;
S->S[PARALLELISM_DEGREE - 1]->last_node = 1;
return 0;
}
int blake2sp_init_key( blake2sp_state *S, size_t outlen, const void *key, size_t keylen )
{
size_t i;
if( !outlen || outlen > BLAKE2S_OUTBYTES ) return -1;
if( !key || !keylen || keylen > BLAKE2S_KEYBYTES ) return -1;
memset( S->buf, 0, sizeof( S->buf ) );
S->buflen = 0;
S->outlen = outlen;
if( blake2sp_init_root( S->R, outlen, keylen ) < 0 )
return -1;
for( i = 0; i < PARALLELISM_DEGREE; ++i )
if( blake2sp_init_leaf( S->S[i], outlen, keylen, i ) < 0 ) return -1;
S->R->last_node = 1;
S->S[PARALLELISM_DEGREE - 1]->last_node = 1;
{
uint8_t block[BLAKE2S_BLOCKBYTES];
memset( block, 0, BLAKE2S_BLOCKBYTES );
memcpy( block, key, keylen );
for( i = 0; i < PARALLELISM_DEGREE; ++i )
blake2s_update( S->S[i], block, BLAKE2S_BLOCKBYTES );
secure_zero_memory( block, BLAKE2S_BLOCKBYTES ); /* Burn the key from stack */
}
return 0;
}
int blake2sp_update( blake2sp_state *S, const void *pin, size_t inlen )
{
const unsigned char * in = (const unsigned char *)pin;
size_t left = S->buflen;
size_t fill = sizeof( S->buf ) - left;
size_t i;
if( left && inlen >= fill )
{
memcpy( S->buf + left, in, fill );
for( i = 0; i < PARALLELISM_DEGREE; ++i )
blake2s_update( S->S[i], S->buf + i * BLAKE2S_BLOCKBYTES, BLAKE2S_BLOCKBYTES );
in += fill;
inlen -= fill;
left = 0;
}
#if defined(_OPENMP)
#pragma omp parallel shared(S), num_threads(PARALLELISM_DEGREE)
#else
for( i = 0; i < PARALLELISM_DEGREE; ++i )
#endif
{
#if defined(_OPENMP)
size_t i = omp_get_thread_num();
#endif
size_t inlen__ = inlen;
const unsigned char *in__ = ( const unsigned char * )in;
in__ += i * BLAKE2S_BLOCKBYTES;
while( inlen__ >= PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES )
{
blake2s_update( S->S[i], in__, BLAKE2S_BLOCKBYTES );
in__ += PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES;
inlen__ -= PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES;
}
}
in += inlen - inlen % ( PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES );
inlen %= PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES;
if( inlen > 0 )
memcpy( S->buf + left, in, inlen );
S->buflen = left + inlen;
return 0;
}
int blake2sp_final( blake2sp_state *S, void *out, size_t outlen )
{
uint8_t hash[PARALLELISM_DEGREE][BLAKE2S_OUTBYTES];
size_t i;
if(out == NULL || outlen < S->outlen) {
return -1;
}
for( i = 0; i < PARALLELISM_DEGREE; ++i )
{
if( S->buflen > i * BLAKE2S_BLOCKBYTES )
{
size_t left = S->buflen - i * BLAKE2S_BLOCKBYTES;
if( left > BLAKE2S_BLOCKBYTES ) left = BLAKE2S_BLOCKBYTES;
blake2s_update( S->S[i], S->buf + i * BLAKE2S_BLOCKBYTES, left );
}
blake2s_final( S->S[i], hash[i], BLAKE2S_OUTBYTES );
}
for( i = 0; i < PARALLELISM_DEGREE; ++i )
blake2s_update( S->R, hash[i], BLAKE2S_OUTBYTES );
return blake2s_final( S->R, out, S->outlen );
}
int blake2sp( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen )
{
uint8_t hash[PARALLELISM_DEGREE][BLAKE2S_OUTBYTES];
blake2s_state S[PARALLELISM_DEGREE][1];
blake2s_state FS[1];
size_t i;
/* Verify parameters */
if ( NULL == in && inlen > 0 ) return -1;
if ( NULL == out ) return -1;
if ( NULL == key && keylen > 0) return -1;
if( !outlen || outlen > BLAKE2S_OUTBYTES ) return -1;
if( keylen > BLAKE2S_KEYBYTES ) return -1;
for( i = 0; i < PARALLELISM_DEGREE; ++i )
if( blake2sp_init_leaf( S[i], outlen, keylen, i ) < 0 ) return -1;
S[PARALLELISM_DEGREE - 1]->last_node = 1; /* mark last node */
if( keylen > 0 )
{
uint8_t block[BLAKE2S_BLOCKBYTES];
memset( block, 0, BLAKE2S_BLOCKBYTES );
memcpy( block, key, keylen );
for( i = 0; i < PARALLELISM_DEGREE; ++i )
blake2s_update( S[i], block, BLAKE2S_BLOCKBYTES );
secure_zero_memory( block, BLAKE2S_BLOCKBYTES ); /* Burn the key from stack */
}
#if defined(_OPENMP)
#pragma omp parallel shared(S,hash), num_threads(PARALLELISM_DEGREE)
#else
for( i = 0; i < PARALLELISM_DEGREE; ++i )
#endif
{
#if defined(_OPENMP)
size_t i = omp_get_thread_num();
#endif
size_t inlen__ = inlen;
const unsigned char *in__ = ( const unsigned char * )in;
in__ += i * BLAKE2S_BLOCKBYTES;
while( inlen__ >= PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES )
{
blake2s_update( S[i], in__, BLAKE2S_BLOCKBYTES );
in__ += PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES;
inlen__ -= PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES;
}
if( inlen__ > i * BLAKE2S_BLOCKBYTES )
{
const size_t left = inlen__ - i * BLAKE2S_BLOCKBYTES;
const size_t len = left <= BLAKE2S_BLOCKBYTES ? left : BLAKE2S_BLOCKBYTES;
blake2s_update( S[i], in__, len );
}
blake2s_final( S[i], hash[i], BLAKE2S_OUTBYTES );
}
if( blake2sp_init_root( FS, outlen, keylen ) < 0 )
return -1;
FS->last_node = 1;
for( i = 0; i < PARALLELISM_DEGREE; ++i )
blake2s_update( FS, hash[i], BLAKE2S_OUTBYTES );
return blake2s_final( FS, out, outlen );
}
#if defined(BLAKE2SP_SELFTEST)
#include <string.h>
#include "blake2-kat.h"
int main( void )
{
uint8_t key[BLAKE2S_KEYBYTES];
uint8_t buf[BLAKE2_KAT_LENGTH];
size_t i, step;
for( i = 0; i < BLAKE2S_KEYBYTES; ++i )
key[i] = ( uint8_t )i;
for( i = 0; i < BLAKE2_KAT_LENGTH; ++i )
buf[i] = ( uint8_t )i;
/* Test simple API */
for( i = 0; i < BLAKE2_KAT_LENGTH; ++i )
{
uint8_t hash[BLAKE2S_OUTBYTES];
blake2sp( hash, BLAKE2S_OUTBYTES, buf, i, key, BLAKE2S_KEYBYTES );
if( 0 != memcmp( hash, blake2sp_keyed_kat[i], BLAKE2S_OUTBYTES ) )
{
goto fail;
}
}
/* Test streaming API */
for(step = 1; step < BLAKE2S_BLOCKBYTES; ++step) {
for (i = 0; i < BLAKE2_KAT_LENGTH; ++i) {
uint8_t hash[BLAKE2S_OUTBYTES];
blake2sp_state S;
uint8_t * p = buf;
size_t mlen = i;
int err = 0;
if( (err = blake2sp_init_key(&S, BLAKE2S_OUTBYTES, key, BLAKE2S_KEYBYTES)) < 0 ) {
goto fail;
}
while (mlen >= step) {
if ( (err = blake2sp_update(&S, p, step)) < 0 ) {
goto fail;
}
mlen -= step;
p += step;
}
if ( (err = blake2sp_update(&S, p, mlen)) < 0) {
goto fail;
}
if ( (err = blake2sp_final(&S, hash, BLAKE2S_OUTBYTES)) < 0) {
goto fail;
}
if (0 != memcmp(hash, blake2sp_keyed_kat[i], BLAKE2S_OUTBYTES)) {
goto fail;
}
}
}
puts( "ok" );
return 0;
fail:
puts("error");
return -1;
}
#endif

View File

@@ -1,241 +0,0 @@
/*
BLAKE2 reference source code package - reference C implementations
Copyright 2016, JP Aumasson <jeanphilippe.aumasson@gmail.com>.
Copyright 2016, Samuel Neves <sneves@dei.uc.pt>.
You may use this under the terms of the CC0, the OpenSSL Licence, or
the Apache Public License 2.0, at your option. The terms of these
licenses can be found at:
- CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0
- OpenSSL license : https://www.openssl.org/source/license.html
- Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0
More information about the BLAKE2 hash function can be found at
https://blake2.net.
*/
#include <stdint.h>
#include <string.h>
#include <stdio.h>
#include "blake2.h"
#include "blake2-impl.h"
int blake2xb_init( blake2xb_state *S, const size_t outlen ) {
return blake2xb_init_key(S, outlen, NULL, 0);
}
int blake2xb_init_key( blake2xb_state *S, const size_t outlen, const void *key, size_t keylen)
{
if ( outlen == 0 || outlen > 0xFFFFFFFFUL ) {
return -1;
}
if (NULL != key && keylen > BLAKE2B_KEYBYTES) {
return -1;
}
if (NULL == key && keylen > 0) {
return -1;
}
/* Initialize parameter block */
S->P->digest_length = BLAKE2B_OUTBYTES;
S->P->key_length = keylen;
S->P->fanout = 1;
S->P->depth = 1;
store32( &S->P->leaf_length, 0 );
store32( &S->P->node_offset, 0 );
store32( &S->P->xof_length, outlen );
S->P->node_depth = 0;
S->P->inner_length = 0;
memset( S->P->reserved, 0, sizeof( S->P->reserved ) );
memset( S->P->salt, 0, sizeof( S->P->salt ) );
memset( S->P->personal, 0, sizeof( S->P->personal ) );
if( blake2b_init_param( S->S, S->P ) < 0 ) {
return -1;
}
if (keylen > 0) {
uint8_t block[BLAKE2B_BLOCKBYTES];
memset(block, 0, BLAKE2B_BLOCKBYTES);
memcpy(block, key, keylen);
blake2b_update(S->S, block, BLAKE2B_BLOCKBYTES);
secure_zero_memory(block, BLAKE2B_BLOCKBYTES);
}
return 0;
}
int blake2xb_update( blake2xb_state *S, const void *in, size_t inlen ) {
return blake2b_update( S->S, in, inlen );
}
int blake2xb_final( blake2xb_state *S, void *out, size_t outlen) {
blake2b_state C[1];
blake2b_param P[1];
uint32_t xof_length = load32(&S->P->xof_length);
uint8_t root[BLAKE2B_BLOCKBYTES];
size_t i;
if (NULL == out) {
return -1;
}
/* outlen must match the output size defined in xof_length, */
/* unless it was -1, in which case anything goes except 0. */
if(xof_length == 0xFFFFFFFFUL) {
if(outlen == 0) {
return -1;
}
} else {
if(outlen != xof_length) {
return -1;
}
}
/* Finalize the root hash */
if (blake2b_final(S->S, root, BLAKE2B_OUTBYTES) < 0) {
return -1;
}
/* Set common block structure values */
/* Copy values from parent instance, and only change the ones below */
memcpy(P, S->P, sizeof(blake2b_param));
P->key_length = 0;
P->fanout = 0;
P->depth = 0;
store32(&P->leaf_length, BLAKE2B_OUTBYTES);
P->inner_length = BLAKE2B_OUTBYTES;
P->node_depth = 0;
for (i = 0; outlen > 0; ++i) {
const size_t block_size = (outlen < BLAKE2B_OUTBYTES) ? outlen : BLAKE2B_OUTBYTES;
/* Initialize state */
P->digest_length = block_size;
store32(&P->node_offset, i);
blake2b_init_param(C, P);
/* Process key if needed */
blake2b_update(C, root, BLAKE2B_OUTBYTES);
if (blake2b_final(C, (uint8_t *)out + i * BLAKE2B_OUTBYTES, block_size) < 0 ) {
return -1;
}
outlen -= block_size;
}
secure_zero_memory(root, sizeof(root));
secure_zero_memory(P, sizeof(P));
secure_zero_memory(C, sizeof(C));
/* Put blake2xb in an invalid state? cf. blake2s_is_lastblock */
return 0;
}
int blake2xb(void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen)
{
blake2xb_state S[1];
/* Verify parameters */
if (NULL == in && inlen > 0)
return -1;
if (NULL == out)
return -1;
if (NULL == key && keylen > 0)
return -1;
if (keylen > BLAKE2B_KEYBYTES)
return -1;
if (outlen == 0)
return -1;
/* Initialize the root block structure */
if (blake2xb_init_key(S, outlen, key, keylen) < 0) {
return -1;
}
/* Absorb the input message */
blake2xb_update(S, in, inlen);
/* Compute the root node of the tree and the final hash using the counter construction */
return blake2xb_final(S, out, outlen);
}
#if defined(BLAKE2XB_SELFTEST)
#include <string.h>
#include "blake2-kat.h"
int main( void )
{
uint8_t key[BLAKE2B_KEYBYTES];
uint8_t buf[BLAKE2_KAT_LENGTH];
size_t i, step, outlen;
for( i = 0; i < BLAKE2B_KEYBYTES; ++i ) {
key[i] = ( uint8_t )i;
}
for( i = 0; i < BLAKE2_KAT_LENGTH; ++i ) {
buf[i] = ( uint8_t )i;
}
/* Testing length of outputs rather than inputs */
/* (Test of input lengths mostly covered by blake2b tests) */
/* Test simple API */
for( outlen = 1; outlen <= BLAKE2_KAT_LENGTH; ++outlen )
{
uint8_t hash[BLAKE2_KAT_LENGTH] = {0};
if( blake2xb( hash, outlen, buf, BLAKE2_KAT_LENGTH, key, BLAKE2B_KEYBYTES ) < 0 ) {
goto fail;
}
if( 0 != memcmp( hash, blake2xb_keyed_kat[outlen-1], outlen ) )
{
goto fail;
}
}
/* Test streaming API */
for(step = 1; step < BLAKE2B_BLOCKBYTES; ++step) {
for (outlen = 1; outlen <= BLAKE2_KAT_LENGTH; ++outlen) {
uint8_t hash[BLAKE2_KAT_LENGTH];
blake2xb_state S;
uint8_t * p = buf;
size_t mlen = BLAKE2_KAT_LENGTH;
int err = 0;
if( (err = blake2xb_init_key(&S, outlen, key, BLAKE2B_KEYBYTES)) < 0 ) {
goto fail;
}
while (mlen >= step) {
if ( (err = blake2xb_update(&S, p, step)) < 0 ) {
goto fail;
}
mlen -= step;
p += step;
}
if ( (err = blake2xb_update(&S, p, mlen)) < 0) {
goto fail;
}
if ( (err = blake2xb_final(&S, hash, outlen)) < 0) {
goto fail;
}
if (0 != memcmp(hash, blake2xb_keyed_kat[outlen-1], outlen)) {
goto fail;
}
}
}
puts( "ok" );
return 0;
fail:
puts("error");
return -1;
}
#endif

View File

@@ -1,239 +0,0 @@
/*
BLAKE2 reference source code package - reference C implementations
Copyright 2016, JP Aumasson <jeanphilippe.aumasson@gmail.com>.
Copyright 2016, Samuel Neves <sneves@dei.uc.pt>.
You may use this under the terms of the CC0, the OpenSSL Licence, or
the Apache Public License 2.0, at your option. The terms of these
licenses can be found at:
- CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0
- OpenSSL license : https://www.openssl.org/source/license.html
- Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0
More information about the BLAKE2 hash function can be found at
https://blake2.net.
*/
#include <stdint.h>
#include <string.h>
#include <stdio.h>
#include "blake2.h"
#include "blake2-impl.h"
int blake2xs_init( blake2xs_state *S, const size_t outlen ) {
return blake2xs_init_key(S, outlen, NULL, 0);
}
int blake2xs_init_key( blake2xs_state *S, const size_t outlen, const void *key, size_t keylen )
{
if ( outlen == 0 || outlen > 0xFFFFUL ) {
return -1;
}
if (NULL != key && keylen > BLAKE2S_KEYBYTES) {
return -1;
}
if (NULL == key && keylen > 0) {
return -1;
}
/* Initialize parameter block */
S->P->digest_length = BLAKE2S_OUTBYTES;
S->P->key_length = keylen;
S->P->fanout = 1;
S->P->depth = 1;
store32( &S->P->leaf_length, 0 );
store32( &S->P->node_offset, 0 );
store16( &S->P->xof_length, outlen );
S->P->node_depth = 0;
S->P->inner_length = 0;
memset( S->P->salt, 0, sizeof( S->P->salt ) );
memset( S->P->personal, 0, sizeof( S->P->personal ) );
if( blake2s_init_param( S->S, S->P ) < 0 ) {
return -1;
}
if (keylen > 0) {
uint8_t block[BLAKE2S_BLOCKBYTES];
memset(block, 0, BLAKE2S_BLOCKBYTES);
memcpy(block, key, keylen);
blake2s_update(S->S, block, BLAKE2S_BLOCKBYTES);
secure_zero_memory(block, BLAKE2S_BLOCKBYTES);
}
return 0;
}
int blake2xs_update( blake2xs_state *S, const void *in, size_t inlen ) {
return blake2s_update( S->S, in, inlen );
}
int blake2xs_final(blake2xs_state *S, void *out, size_t outlen) {
blake2s_state C[1];
blake2s_param P[1];
uint16_t xof_length = load16(&S->P->xof_length);
uint8_t root[BLAKE2S_BLOCKBYTES];
size_t i;
if (NULL == out) {
return -1;
}
/* outlen must match the output size defined in xof_length, */
/* unless it was -1, in which case anything goes except 0. */
if(xof_length == 0xFFFFUL) {
if(outlen == 0) {
return -1;
}
} else {
if(outlen != xof_length) {
return -1;
}
}
/* Finalize the root hash */
if (blake2s_final(S->S, root, BLAKE2S_OUTBYTES) < 0) {
return -1;
}
/* Set common block structure values */
/* Copy values from parent instance, and only change the ones below */
memcpy(P, S->P, sizeof(blake2s_param));
P->key_length = 0;
P->fanout = 0;
P->depth = 0;
store32(&P->leaf_length, BLAKE2S_OUTBYTES);
P->inner_length = BLAKE2S_OUTBYTES;
P->node_depth = 0;
for (i = 0; outlen > 0; ++i) {
const size_t block_size = (outlen < BLAKE2S_OUTBYTES) ? outlen : BLAKE2S_OUTBYTES;
/* Initialize state */
P->digest_length = block_size;
store32(&P->node_offset, i);
blake2s_init_param(C, P);
/* Process key if needed */
blake2s_update(C, root, BLAKE2S_OUTBYTES);
if (blake2s_final(C, (uint8_t *)out + i * BLAKE2S_OUTBYTES, block_size) < 0) {
return -1;
}
outlen -= block_size;
}
secure_zero_memory(root, sizeof(root));
secure_zero_memory(P, sizeof(P));
secure_zero_memory(C, sizeof(C));
/* Put blake2xs in an invalid state? cf. blake2s_is_lastblock */
return 0;
}
int blake2xs(void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen)
{
blake2xs_state S[1];
/* Verify parameters */
if (NULL == in && inlen > 0)
return -1;
if (NULL == out)
return -1;
if (NULL == key && keylen > 0)
return -1;
if (keylen > BLAKE2S_KEYBYTES)
return -1;
if (outlen == 0)
return -1;
/* Initialize the root block structure */
if (blake2xs_init_key(S, outlen, key, keylen) < 0) {
return -1;
}
/* Absorb the input message */
blake2xs_update(S, in, inlen);
/* Compute the root node of the tree and the final hash using the counter construction */
return blake2xs_final(S, out, outlen);
}
#if defined(BLAKE2XS_SELFTEST)
#include <string.h>
#include "blake2-kat.h"
int main( void )
{
uint8_t key[BLAKE2S_KEYBYTES];
uint8_t buf[BLAKE2_KAT_LENGTH];
size_t i, step, outlen;
for( i = 0; i < BLAKE2S_KEYBYTES; ++i ) {
key[i] = ( uint8_t )i;
}
for( i = 0; i < BLAKE2_KAT_LENGTH; ++i ) {
buf[i] = ( uint8_t )i;
}
/* Testing length of outputs rather than inputs */
/* (Test of input lengths mostly covered by blake2s tests) */
/* Test simple API */
for( outlen = 1; outlen <= BLAKE2_KAT_LENGTH; ++outlen )
{
uint8_t hash[BLAKE2_KAT_LENGTH] = {0};
if( blake2xs( hash, outlen, buf, BLAKE2_KAT_LENGTH, key, BLAKE2S_KEYBYTES ) < 0 ) {
goto fail;
}
if( 0 != memcmp( hash, blake2xs_keyed_kat[outlen-1], outlen ) )
{
goto fail;
}
}
/* Test streaming API */
for(step = 1; step < BLAKE2S_BLOCKBYTES; ++step) {
for (outlen = 1; outlen <= BLAKE2_KAT_LENGTH; ++outlen) {
uint8_t hash[BLAKE2_KAT_LENGTH];
blake2xs_state S;
uint8_t * p = buf;
size_t mlen = BLAKE2_KAT_LENGTH;
int err = 0;
if( (err = blake2xs_init_key(&S, outlen, key, BLAKE2S_KEYBYTES)) < 0 ) {
goto fail;
}
while (mlen >= step) {
if ( (err = blake2xs_update(&S, p, step)) < 0 ) {
goto fail;
}
mlen -= step;
p += step;
}
if ( (err = blake2xs_update(&S, p, mlen)) < 0) {
goto fail;
}
if ( (err = blake2xs_final(&S, hash, outlen)) < 0) {
goto fail;
}
if (0 != memcmp(hash, blake2xs_keyed_kat[outlen-1], outlen)) {
goto fail;
}
}
}
puts( "ok" );
return 0;
fail:
puts("error");
return -1;
}
#endif

View File

@@ -176,14 +176,16 @@ bool PIFile::openTemporary(PIIODevice::DeviceMode mode) {
PIString tp;
#ifdef WINDOWS
tp = PIDir::temporary().path() + PIDir::separator + "file" + PIString::fromNumber(randomi());
#else
char * rc = tmpnam(0);
if (!rc) return false;
tp = rc;
#endif
while (isExists(tp)) {
tp += PIString::fromNumber(randomi() % 10);
}
#else
char template_rc[] = "/tmp/pifile_tmp_XXXXXX";
int fd = mkstemp(template_rc);
if (fd == -1) return false;
::close(fd);
tp = template_rc;
#endif
return open(tp, mode);
}