Skip to content

Commit

Permalink
Lua: Use standard pairs/ipairs implementation, use 1-based array inde…
Browse files Browse the repository at this point in the history
…xing (#137)

* Use standard pairs/ipairs implementation

* Remove some warning

* Fixes lua5.2 compile

* Remove exception handle

* Change Lua's array object from base-0 to base-1

* GetContext ignores illegal index access.
  • Loading branch information
actboy168 authored Oct 23, 2020
1 parent e3b74a4 commit 551ea37
Show file tree
Hide file tree
Showing 17 changed files with 239 additions and 371 deletions.
6 changes: 3 additions & 3 deletions Source/Core/Core.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -285,9 +285,9 @@ Context* GetContext(int index)
{
ContextMap::iterator i = contexts.begin();
int count = 0;

if (index >= GetNumContexts())
index = GetNumContexts() - 1;
if (index < 0 || index >= GetNumContexts())
return nullptr;

while (count < index)
{
Expand Down
106 changes: 47 additions & 59 deletions Source/Lua/ContextDocumentsProxy.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,6 @@ template<> void ExtraInit<ContextDocumentsProxy>(lua_State* L, int metatable_ind
lua_setfield(L,metatable_index,"__index");
lua_pushcfunction(L,ContextDocumentsProxy__pairs);
lua_setfield(L,metatable_index,"__pairs");
lua_pushcfunction(L,ContextDocumentsProxy__ipairs);
lua_setfield(L,metatable_index,"__ipairs");
}

int ContextDocumentsProxy__index(lua_State* L)
Expand All @@ -53,7 +51,7 @@ int ContextDocumentsProxy__index(lua_State* L)
if(type == LUA_TSTRING)
ret = proxy->owner->GetDocument(luaL_checkstring(L,2));
else
ret = proxy->owner->GetDocument((int)luaL_checkinteger(L,2));
ret = proxy->owner->GetDocument((int)luaL_checkinteger(L,2)-1);
LuaType<Document>::push(L,ret,false);
return 1;
}
Expand All @@ -62,75 +60,65 @@ int ContextDocumentsProxy__index(lua_State* L)

}

//[1] is the object, [2] is the last used key, [3] is the userdata
int ContextDocumentsProxy__pairs(lua_State* L)
struct ContextDocumentsProxyPairs
{
Document* doc = nullptr;
ContextDocumentsProxy* obj = LuaType<ContextDocumentsProxy>::check(L,1);
RMLUI_CHECK_OBJ(obj);
int* pindex = (int*)lua_touserdata(L,3);
if((*pindex) == -1)
*pindex = 0;

int num_docs = obj->owner->GetNumDocuments();
//because there can be missing indexes, make sure to continue until there
//is actually a document at the index
while((*pindex) < num_docs)
{
doc = obj->owner->GetDocument((*pindex)++);
if(doc != nullptr)
break;
}

//If we found a document
if(doc != nullptr)
static int next(lua_State* L)
{
ContextDocumentsProxy* obj = LuaType<ContextDocumentsProxy>::check(L,1);
ContextDocumentsProxyPairs* self = static_cast<ContextDocumentsProxyPairs*>(lua_touserdata(L, lua_upvalueindex(1)));
Document* doc = nullptr;
int num_docs = obj->owner->GetNumDocuments();
//because there can be missing indexes, make sure to continue until there
//is actually a document at the index
while (self->m_cur < num_docs)
{
doc = obj->owner->GetDocument(self->m_cur++);
if (doc != nullptr)
break;
}
if (doc == nullptr)
{
return 0;
}
lua_pushstring(L,doc->GetId().c_str());
LuaType<Document>::push(L,doc);
return 2;
}
else //if we were at the end and didn't find a document
static int destroy(lua_State* L)
{
lua_pushnil(L);
lua_pushnil(L);
static_cast<ContextDocumentsProxyPairs*>(lua_touserdata(L, 1))->~ContextDocumentsProxyPairs();
return 0;
}
return 2;
}

//same as __pairs, but putting an integer key instead of a string key
int ContextDocumentsProxy__ipairs(lua_State* L)
{
Document* doc = nullptr;
ContextDocumentsProxy* obj = LuaType<ContextDocumentsProxy>::check(L,1);
RMLUI_CHECK_OBJ(obj);
int* pindex = (int*)lua_touserdata(L,3);
if((*pindex) == -1)
*pindex = 0;

int num_docs = obj->owner->GetNumDocuments();
//because there can be missing indexes, make sure to continue until there
//is actually a document at the index
while((*pindex) < num_docs)
static int constructor(lua_State* L)
{
doc = obj->owner->GetDocument((*pindex)++);
if(doc != nullptr)
break;
void* storage = lua_newuserdata(L, sizeof(ContextDocumentsProxyPairs));
if (luaL_newmetatable(L, "RmlUi::Lua::ContextDocumentsProxyPairs"))
{
static luaL_Reg mt[] =
{
{"__gc", destroy},
{NULL, NULL},
};
luaL_setfuncs(L, mt, 0);
}
lua_setmetatable(L, -2);
lua_pushcclosure(L, next, 1);
new (storage) ContextDocumentsProxyPairs();
return 1;
}
ContextDocumentsProxyPairs()
: m_cur(0)
{ }
int m_cur;
};

//we found a document
if(doc != nullptr)
{
lua_pushinteger(L,(*pindex)-1);
LuaType<Document>::push(L,doc);
}
else //we got to the end and didn't find another document
{
lua_pushnil(L);
lua_pushnil(L);
}
int ContextDocumentsProxy__pairs(lua_State* L)
{
ContextDocumentsProxyPairs::constructor(L);
lua_pushvalue(L, 1);
return 2;
}


RegType<ContextDocumentsProxy> ContextDocumentsProxyMethods[] =
{
{ nullptr, nullptr },
Expand Down
1 change: 0 additions & 1 deletion Source/Lua/ContextDocumentsProxy.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,6 @@ struct ContextDocumentsProxy { Context* owner; };
template<> void ExtraInit<ContextDocumentsProxy>(lua_State* L, int metatable_index);
int ContextDocumentsProxy__index(lua_State* L);
int ContextDocumentsProxy__pairs(lua_State* L);
int ContextDocumentsProxy__ipairs(lua_State* L);

extern RegType<ContextDocumentsProxy> ContextDocumentsProxyMethods[];
extern luaL_Reg ContextDocumentsProxyGetters[];
Expand Down
34 changes: 2 additions & 32 deletions Source/Lua/ElementAttributesProxy.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
#include "ElementAttributesProxy.h"
#include <RmlUi/Lua/Utilities.h>
#include <RmlUi/Core/Variant.h>
#include "Pairs.h"

namespace Rml {
namespace Lua {
Expand All @@ -38,8 +39,6 @@ template<> void ExtraInit<ElementAttributesProxy>(lua_State* L, int metatable_in
lua_setfield(L,metatable_index,"__index");
lua_pushcfunction(L,ElementAttributesProxy__pairs);
lua_setfield(L,metatable_index,"__pairs");
lua_pushcfunction(L,ElementAttributesProxy__ipairs);
lua_setfield(L,metatable_index,"__ipairs");
}

int ElementAttributesProxy__index(lua_State* L)
Expand All @@ -59,40 +58,11 @@ int ElementAttributesProxy__index(lua_State* L)
return LuaType<ElementAttributesProxy>::index(L);
}

//[1] is the object, [2] is the key that was used previously, [3] is the userdata
int ElementAttributesProxy__pairs(lua_State* L)
{
ElementAttributesProxy* obj = LuaType<ElementAttributesProxy>::check(L,1);
RMLUI_CHECK_OBJ(obj);
int& pindex = *(int*)lua_touserdata(L,3);
if ((pindex) == -1)
pindex = 0;
const ElementAttributes& attributes = obj->owner->GetAttributes();

if(pindex >= 0 && pindex < (int)attributes.size())
{
auto it = attributes.begin();
for (int i = 0; i < pindex; ++i)
++it;
const String& key = it->first;
const Variant* value = &it->second;
lua_pushstring(L,key.c_str());
PushVariant(L,value);
}
else
{
lua_pushnil(L);
lua_pushnil(L);
}
return 2;
}

//Doesn't index by integer, so don't return anything
int ElementAttributesProxy__ipairs(lua_State* L)
{
lua_pushnil(L);
lua_pushnil(L);
return 2;
return MakePairs(L, obj->owner->GetAttributes());
}

RegType<ElementAttributesProxy> ElementAttributesProxyMethods[] =
Expand Down
1 change: 0 additions & 1 deletion Source/Lua/ElementAttributesProxy.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,6 @@ struct ElementAttributesProxy { Element* owner; };
template<> void ExtraInit<ElementAttributesProxy>(lua_State* L, int metatable_index);
int ElementAttributesProxy__index(lua_State* L);
int ElementAttributesProxy__pairs(lua_State* L);
int ElementAttributesProxy__ipairs(lua_State* L);

extern RegType<ElementAttributesProxy> ElementAttributesProxyMethods[];
extern luaL_Reg ElementAttributesProxyGetters[];
Expand Down
32 changes: 3 additions & 29 deletions Source/Lua/ElementChildNodesProxy.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@

#include "ElementChildNodesProxy.h"
#include "Element.h"
#include "Pairs.h"

namespace Rml {
namespace Lua {
Expand All @@ -38,8 +39,6 @@ template<> void ExtraInit<ElementChildNodesProxy>(lua_State* L, int metatable_in
lua_setfield(L,metatable_index,"__index");
lua_pushcfunction(L,ElementChildNodesProxy__pairs);
lua_setfield(L,metatable_index,"__pairs");
lua_pushcfunction(L,ElementChildNodesProxy__ipairs);
lua_setfield(L,metatable_index,"__ipairs");
}

int ElementChildNodesProxy__index(lua_State* L)
Expand All @@ -51,7 +50,7 @@ int ElementChildNodesProxy__index(lua_State* L)
ElementChildNodesProxy* obj = LuaType<ElementChildNodesProxy>::check(L,1);
RMLUI_CHECK_OBJ(obj);
int key = (int)luaL_checkinteger(L,2);
Element* child = obj->owner->GetChild(key);
Element* child = obj->owner->GetChild(key-1);
LuaType<Element>::push(L,child,false);
return 1;
}
Expand All @@ -61,32 +60,7 @@ int ElementChildNodesProxy__index(lua_State* L)

int ElementChildNodesProxy__pairs(lua_State* L)
{
//because it is only indexed by integer, just go through ipairs
return ElementChildNodesProxy__ipairs(L);
}


//[1] is the object, [2] is the key that was just used, [3] is the userdata
int ElementChildNodesProxy__ipairs(lua_State* L)
{
ElementChildNodesProxy* obj = LuaType<ElementChildNodesProxy>::check(L,1);
RMLUI_CHECK_OBJ(obj);
int* pindex = (int*)lua_touserdata(L,3);
if((*pindex) == -1) //initial value
(*pindex) = 0;
int num_children = obj->owner->GetNumChildren();
if((*pindex) < num_children)
{
lua_pushinteger(L,*pindex); //key
LuaType<Element>::push(L,obj->owner->GetChild(*pindex)); //value
(*pindex) += 1;
}
else
{
lua_pushnil(L);
lua_pushnil(L);
}
return 2;
return MakeIntPairs(L);
}

RegType<ElementChildNodesProxy> ElementChildNodesProxyMethods[] =
Expand Down
1 change: 0 additions & 1 deletion Source/Lua/ElementChildNodesProxy.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,6 @@ struct ElementChildNodesProxy { Element* owner; };
template<> void ExtraInit<ElementChildNodesProxy>(lua_State* L, int metatable_index);
int ElementChildNodesProxy__index(lua_State* L);
int ElementChildNodesProxy__pairs(lua_State* L);
int ElementChildNodesProxy__ipairs(lua_State* L);

extern RegType<ElementChildNodesProxy> ElementChildNodesProxyMethods[];
extern luaL_Reg ElementChildNodesProxyGetters[];
Expand Down
77 changes: 43 additions & 34 deletions Source/Lua/ElementStyleProxy.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,9 +46,6 @@ template<> void ExtraInit<ElementStyleProxy>(lua_State* L, int metatable_index)

lua_pushcfunction(L,ElementStyleProxy__pairs);
lua_setfield(L,metatable_index,"__pairs");

lua_pushcfunction(L,ElementStyleProxy__ipairs);
lua_setfield(L,metatable_index,"__ipairs");
}

int ElementStyleProxy__index(lua_State* L)
Expand Down Expand Up @@ -101,46 +98,58 @@ int ElementStyleProxy__newindex(lua_State* L)

}

//[1] is the object, [2] is the last used key, [3] is the userdata
int ElementStyleProxy__pairs(lua_State* L)
struct ElementStyleProxyPairs
{
ElementStyleProxy* obj = LuaType<ElementStyleProxy>::check(L,1);
RMLUI_CHECK_OBJ(obj);
int* pindex = (int*)lua_touserdata(L,3);
if ((*pindex) == -1)
*pindex = 0;

int i = 0;
auto it = obj->owner->IterateLocalProperties();
while (i < (*pindex) && !it.AtEnd())
{
++it;
++i;
}

if(!it.AtEnd())
static int next(lua_State* L)
{
const String& key = it.GetName();
const Property& property = it.GetProperty();
ElementStyleProxyPairs* self = static_cast<ElementStyleProxyPairs*>(lua_touserdata(L, lua_upvalueindex(1)));
if (self->m_view.AtEnd())
{
return 0;
}
const String& key = self->m_view.GetName();
const Property& property = self->m_view.GetProperty();
String val;
property.definition->GetValue(val, property);
lua_pushstring(L,key.c_str());
lua_pushstring(L,val.c_str());
lua_pushlstring(L, key.c_str(), key.size());
lua_pushlstring(L, val.c_str(), val.size());
++self->m_view;
return 2;
}
else
static int destroy(lua_State* L)
{
lua_pushnil(L);
lua_pushnil(L);
static_cast<ElementStyleProxyPairs*>(lua_touserdata(L, 1))->~ElementStyleProxyPairs();
return 0;
}
return 2;
}
static int constructor(lua_State* L, ElementStyleProxy* obj)
{
void* storage = lua_newuserdata(L, sizeof(ElementStyleProxyPairs));
if (luaL_newmetatable(L, "RmlUi::Lua::ElementStyleProxyPairs"))
{
static luaL_Reg mt[] =
{
{"__gc", destroy},
{NULL, NULL},
};
luaL_setfuncs(L, mt, 0);
}
lua_setmetatable(L, -2);
lua_pushcclosure(L, next, 1);
new (storage) ElementStyleProxyPairs(obj);
return 1;
}
ElementStyleProxyPairs(ElementStyleProxy* obj)
: m_view(obj->owner->IterateLocalProperties())
{ }
PropertiesIteratorView m_view;
};

//only indexed by string
int ElementStyleProxy__ipairs(lua_State* L)
int ElementStyleProxy__pairs(lua_State* L)
{
lua_pushnil(L);
lua_pushnil(L);
return 2;
ElementStyleProxy* obj = LuaType<ElementStyleProxy>::check(L,1);
RMLUI_CHECK_OBJ(obj);
ElementStyleProxyPairs::constructor(L, obj);
return 1;
}

RegType<ElementStyleProxy> ElementStyleProxyMethods[] =
Expand Down
Loading

0 comments on commit 551ea37

Please sign in to comment.