diff options
-rw-r--r-- | plugins/MirLua/Modules/m_enumerable/m_enumerable.vcxproj | 33 | ||||
-rw-r--r-- | plugins/MirLua/Modules/m_enumerable/src/main.cpp | 440 | ||||
-rw-r--r-- | plugins/MirLua/Modules/m_enumerable/src/stdafx.cxx | 1 | ||||
-rw-r--r-- | plugins/MirLua/Modules/m_enumerable/src/stdafx.h | 12 |
4 files changed, 486 insertions, 0 deletions
diff --git a/plugins/MirLua/Modules/m_enumerable/m_enumerable.vcxproj b/plugins/MirLua/Modules/m_enumerable/m_enumerable.vcxproj new file mode 100644 index 0000000000..a8e4c9307c --- /dev/null +++ b/plugins/MirLua/Modules/m_enumerable/m_enumerable.vcxproj @@ -0,0 +1,33 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <ItemGroup Label="ProjectConfigurations"> + <ProjectConfiguration Include="Debug|Win32"> + <Configuration>Debug</Configuration> + <Platform>Win32</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Debug|x64"> + <Configuration>Debug</Configuration> + <Platform>x64</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Release|Win32"> + <Configuration>Release</Configuration> + <Platform>Win32</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Release|x64"> + <Configuration>Release</Configuration> + <Platform>x64</Platform> + </ProjectConfiguration> + </ItemGroup> + <PropertyGroup Label="Globals"> + <ProjectName>m_enumerable</ProjectName> + <ProjectGuid>{82BC22BE-EFA7-4A61-B817-8B1D81080AA4}</ProjectGuid> + </PropertyGroup> + <ImportGroup Label="PropertySheets"> + <Import Project="$(ProjectDir)..\module.props" /> + </ImportGroup> + <ItemDefinitionGroup> + <ClCompile> + <ExceptionHandling>Sync</ExceptionHandling> + </ClCompile> + </ItemDefinitionGroup> +</Project> diff --git a/plugins/MirLua/Modules/m_enumerable/src/main.cpp b/plugins/MirLua/Modules/m_enumerable/src/main.cpp new file mode 100644 index 0000000000..709377f589 --- /dev/null +++ b/plugins/MirLua/Modules/m_enumerable/src/main.cpp @@ -0,0 +1,440 @@ +#include "stdafx.h" + +#define MT_ENUMERABLE "ENUMERABLE" + +/***********************************************/ + +static int lua_WhereIterator(lua_State *L) +{ + int enumeratorRef = lua_tointeger(L, lua_upvalueindex(1)); + int whereRef = lua_tointeger(L, lua_upvalueindex(2)); + + int top = lua_gettop(L); + while (true) + { + lua_rawgeti(L, LUA_REGISTRYINDEX, enumeratorRef); + lua_call(L, 0, LUA_MULTRET); + int nres = lua_gettop(L) - top; + if (lua_isnoneornil(L, top + 1)) + { + lua_pop(L, nres); + break; + } + + lua_rawgeti(L, LUA_REGISTRYINDEX, whereRef); + for (int i = top; i < top + nres; i++) + lua_pushvalue(L, i + 1); + lua_call(L, nres, 1); + if (lua_toboolean(L, -1)) + { + lua_pop(L, 1); + return nres; + } + lua_pop(L, nres + 1); + } + + lua_pushnil(L); + + return 1; +} + +static int lua_Where(lua_State *L) +{ + int enumeratorRef = *(int*)luaL_checkudata(L, 1, MT_ENUMERABLE); + luaL_checktype(L, 2, LUA_TFUNCTION); + + lua_pushinteger(L, enumeratorRef); + lua_pushvalue(L, 2); + lua_pushinteger(L, luaL_ref(L, LUA_REGISTRYINDEX)); + lua_pushcclosure(L, lua_WhereIterator, 2); + enumeratorRef = luaL_ref(L, LUA_REGISTRYINDEX); + int *udata = (int*)lua_newuserdata(L, sizeof(int)); + *udata = enumeratorRef; + luaL_setmetatable(L, MT_ENUMERABLE); + + return 1; +} + +static int lua_SelectIterator(lua_State *L) +{ + int enumeratorRef = lua_tointeger(L, lua_upvalueindex(1)); + int selectRef = lua_tointeger(L, lua_upvalueindex(2)); + + int top = lua_gettop(L); + lua_rawgeti(L, LUA_REGISTRYINDEX, enumeratorRef); + lua_call(L, 0, LUA_MULTRET); + int nres = lua_gettop(L) - top; + if (lua_isnoneornil(L, top + 1)) + { + lua_pop(L, nres); + return 0; + } + + lua_rawgeti(L, LUA_REGISTRYINDEX, selectRef); + lua_insert(L, top + 1); + lua_call(L, nres, LUA_MULTRET); + nres = lua_gettop(L) - top; + + return nres; +} + +static int lua_Select(lua_State *L) +{ + int enumeratorRef = *(int*)luaL_checkudata(L, 1, MT_ENUMERABLE); + luaL_checktype(L, 2, LUA_TFUNCTION); + + lua_pushinteger(L, enumeratorRef); + lua_pushvalue(L, 2); + lua_pushinteger(L, luaL_ref(L, LUA_REGISTRYINDEX)); + lua_pushcclosure(L, lua_SelectIterator, 2); + enumeratorRef = luaL_ref(L, LUA_REGISTRYINDEX); + int *udata = (int*)lua_newuserdata(L, sizeof(int)); + *udata = enumeratorRef; + luaL_setmetatable(L, MT_ENUMERABLE); + + return 1; +} + +static int lua_Any(lua_State *L) +{ + int enumeratorRef = *(int*)luaL_checkudata(L, 1, MT_ENUMERABLE); + bool hasFunc = lua_gettop(L) >= 2; + if(hasFunc) + luaL_checktype(L, 2, LUA_TFUNCTION); + + int top = lua_gettop(L); + while (true) + { + lua_rawgeti(L, LUA_REGISTRYINDEX, enumeratorRef); + lua_call(L, 0, LUA_MULTRET); + int nres = lua_gettop(L) - top; + if (lua_isnoneornil(L, top + 1)) + { + lua_pop(L, nres); + break; + } + + if (hasFunc) + { + lua_pushvalue(L, 2); + lua_insert(L, top + 1); + lua_call(L, nres, 1); + nres = lua_gettop(L) - top; + if (lua_toboolean(L, -1)) + { + lua_pop(L, nres); + lua_pushboolean(L, 1); + return 1; + } + lua_pop(L, nres); + continue; + } + + lua_pop(L, nres); + lua_pushboolean(L, 1); + + return 1; + } + + lua_pushboolean(L, 0); + + return 1; +} + +static int lua_First(lua_State *L) +{ + int enumeratorRef = *(int*)luaL_checkudata(L, 1, MT_ENUMERABLE); + bool hasFunc = lua_gettop(L) >= 2; + if (hasFunc) + luaL_checktype(L, 2, LUA_TFUNCTION); + + int top = lua_gettop(L); + while (true) + { + lua_rawgeti(L, LUA_REGISTRYINDEX, enumeratorRef); + lua_call(L, 0, LUA_MULTRET); + int nres = lua_gettop(L) - top; + if (lua_isnoneornil(L, top + 1)) + { + lua_pop(L, nres); + break; + } + + if (hasFunc) + { + lua_pushvalue(L, 2); + for (int i = top; i < top + nres; i++) + lua_pushvalue(L, i + 1); + lua_call(L, nres, 1); + if (lua_toboolean(L, -1)) + { + lua_pop(L, 1); + return nres; + } + lua_pop(L, nres + 1); + continue; + } + + return nres; + } + + lua_pushnil(L); + + return 1; +} + +static int lua_Last(lua_State *L) +{ + int enumeratorRef = *(int*)luaL_checkudata(L, 1, MT_ENUMERABLE); + bool hasFunc = lua_gettop(L) >= 2; + if (hasFunc) + luaL_checktype(L, 2, LUA_TFUNCTION); + + int top = lua_gettop(L); + lua_pushnil(L); + int nres = lua_gettop(L) - top; + while (true) + { + lua_rawgeti(L, LUA_REGISTRYINDEX, enumeratorRef); + lua_call(L, 0, LUA_MULTRET); + int newres = lua_gettop(L) - top - nres; + if (lua_isnoneornil(L, top + nres + 1)) + { + lua_pop(L, newres); + break; + } + + if (hasFunc) + { + lua_pushvalue(L, 2); + for (int i = top + nres; i < top + nres + newres; i++) + lua_pushvalue(L, i + 1); + lua_call(L, newres, 1); + if (!lua_toboolean(L, -1)) + { + lua_pop(L, newres + 1); + continue; + } + lua_pop(L, 1); + } + + for (int i = 0; i < nres; i++) + lua_remove(L, top + 1); + nres = newres; + } + + return nres; +} + +static int lua_Count(lua_State *L) +{ + int enumeratorRef = *(int*)luaL_checkudata(L, 1, MT_ENUMERABLE); + + int count = 0; + while (true) + { + lua_rawgeti(L, LUA_REGISTRYINDEX, enumeratorRef); + lua_call(L, 0, 1); + if (lua_isnoneornil(L, -1)) + { + lua_pop(L, 1); + break; + } + + lua_pop(L, 1); + count++; + } + + lua_pushinteger(L, count); + + return 1; +} + +static int lua_ToArray(lua_State *L) +{ + int enumeratorRef = *(int*)luaL_checkudata(L, 1, MT_ENUMERABLE); + + lua_newtable(L); + for (int i = 1;; i++) + { + int top = lua_gettop(L); + lua_rawgeti(L, LUA_REGISTRYINDEX, enumeratorRef); + lua_call(L, 0, LUA_MULTRET); + int nres = lua_gettop(L) - top; + if (lua_isnoneornil(L, top + 1)) + { + lua_pop(L, nres); + break; + } + lua_rawseti(L, -nres - 1, i); + lua_pop(L, nres - 1); + } + + return 1; +} + +static int lua_ToTable(lua_State *L) +{ + int enumeratorRef = *(int*)luaL_checkudata(L, 1, MT_ENUMERABLE); + luaL_checktype(L, 2, LUA_TFUNCTION); + bool hasValueSelectorFunc = lua_gettop(L) >= 3; + if (hasValueSelectorFunc) + luaL_checktype(L, 3, LUA_TFUNCTION); + + lua_newtable(L); + int top = lua_gettop(L); + while (true) + { + lua_rawgeti(L, LUA_REGISTRYINDEX, enumeratorRef); + lua_call(L, 0, LUA_MULTRET); + int nres = lua_gettop(L) - top; + if (lua_isnoneornil(L, top + 1)) + { + lua_pop(L, nres); + break; + } + + lua_pushvalue(L, 2); + for (int i = top; i < top + nres; i++) + lua_pushvalue(L, i + 1); + lua_call(L, nres, 1); + + if (hasValueSelectorFunc) + { + lua_pushvalue(L, 3); + for (int i = top; i < top + nres; i++) + lua_pushvalue(L, i + 1); + lua_call(L, nres, 1); + } + else + lua_pushvalue(L, top + 1); + + lua_rawset(L, top); + lua_pop(L, nres); + } + + return 1; +} + +/***********************************************/ + +static int lua__call(lua_State *L) +{ + int *enumeratorRef = (int*)luaL_checkudata(L, 1, MT_ENUMERABLE); + + int top = lua_gettop(L); + lua_rawgeti(L, LUA_REGISTRYINDEX, *enumeratorRef); + lua_call(L, 0, LUA_MULTRET); + int nres = lua_gettop(L) - top; + + return nres; +} + +static int lua__pairs(lua_State *L) +{ + int *enumeratorRef = (int*)luaL_checkudata(L, 1, MT_ENUMERABLE); + + lua_rawgeti(L, LUA_REGISTRYINDEX, *enumeratorRef); + + return 1; +} + +static int lua__gc(lua_State *L) +{ + int *enumeratorRef = (int*)luaL_checkudata(L, 1, MT_ENUMERABLE); + luaL_unref(L, LUA_REGISTRYINDEX, *enumeratorRef); + + return 0; +} + +/***********************************************/ + +static int lua_tableIterator(lua_State *L) +{ + lua_pushvalue(L, lua_upvalueindex(1)); + if (lua_next(L, lua_upvalueindex(2))) + { + lua_pushvalue(L, -2); + lua_replace(L, lua_upvalueindex(1)); + return 2; + } + + lua_pushnil(L); + + return 1; +} + +static int lua__new(lua_State *L) +{ + switch (lua_type(L, 1)) + { + case LUA_TTABLE: + lua_pushnil(L); + lua_pushvalue(L, 1); + lua_pushcclosure(L, lua_tableIterator, 2); + break; + case LUA_TFUNCTION: + lua_pushvalue(L, -1); + break; + default: + luaL_argerror(L, 1, luaL_typename(L, 1)); + } + + int enumeratorRef = luaL_ref(L, LUA_REGISTRYINDEX); + + int *udata = (int*)lua_newuserdata(L, sizeof(int)); + *udata = enumeratorRef; + luaL_setmetatable(L, MT_ENUMERABLE); + + return 1; +} + +/***********************************************/ + +static luaL_Reg enumerableApi[] = +{ + { "Where", lua_Where }, + { "Select", lua_Select }, + + { "Any", lua_Any }, + { "First", lua_First }, + { "Last", lua_Last }, + { "Count", lua_Count }, + + { "ToArray", lua_ToArray }, + { "ToTable", lua_ToTable }, + + { NULL, NULL } +}; + +static luaL_Reg enumerableMeta[] = +{ + { "__call", lua__call }, + { "__pairs", lua__pairs }, + { "__gc", lua__gc }, + + { NULL, NULL } +}; + +static luaL_Reg methods[] = +{ + { "new", lua__new }, + + { NULL, NULL } +}; + +/***********************************************/ + +extern "C" LUAMOD_API int luaopen_m_enumerable(lua_State *L) +{ + luaL_newlib(L, methods); + + luaL_newmetatable(L, MT_ENUMERABLE); + luaL_setfuncs(L, enumerableMeta, 0); + lua_pushvalue(L, -1); + lua_setfield(L, -2, "__index"); + luaL_setfuncs(L, enumerableApi, 0); + lua_pop(L, 1); + + return 1; +} diff --git a/plugins/MirLua/Modules/m_enumerable/src/stdafx.cxx b/plugins/MirLua/Modules/m_enumerable/src/stdafx.cxx new file mode 100644 index 0000000000..fd4f341c7b --- /dev/null +++ b/plugins/MirLua/Modules/m_enumerable/src/stdafx.cxx @@ -0,0 +1 @@ +#include "stdafx.h" diff --git a/plugins/MirLua/Modules/m_enumerable/src/stdafx.h b/plugins/MirLua/Modules/m_enumerable/src/stdafx.h new file mode 100644 index 0000000000..5b8469c7fb --- /dev/null +++ b/plugins/MirLua/Modules/m_enumerable/src/stdafx.h @@ -0,0 +1,12 @@ +#ifndef _COMMON_H_ +#define _COMMON_H_ + +#include <windows.h> +#include <time.h> + +#include <lua.hpp> + +#include <m_core.h> +#include <m_utils.h> + +#endif //_COMMON_H_
\ No newline at end of file |