From 0fd2f830882402979a83010e89650e7245960d39 Mon Sep 17 00:00:00 2001 From: Josh Haberman Date: Tue, 21 Jan 2014 18:38:49 -0800 Subject: Sync to internal Google development. --- bindings/lua/LICENSE | 32 -- bindings/lua/lunit/console.lua | 156 ------ bindings/lua/lunit/lunit.lua | 725 ------------------------- bindings/lua/table.c | 168 ------ bindings/lua/test.lua | 263 --------- bindings/lua/upb.c | 1162 ---------------------------------------- bindings/lua/upb.h | 45 -- 7 files changed, 2551 deletions(-) delete mode 100644 bindings/lua/LICENSE delete mode 100644 bindings/lua/lunit/console.lua delete mode 100644 bindings/lua/lunit/lunit.lua delete mode 100644 bindings/lua/table.c delete mode 100644 bindings/lua/test.lua delete mode 100644 bindings/lua/upb.c delete mode 100644 bindings/lua/upb.h (limited to 'bindings/lua') diff --git a/bindings/lua/LICENSE b/bindings/lua/LICENSE deleted file mode 100644 index fb720fe..0000000 --- a/bindings/lua/LICENSE +++ /dev/null @@ -1,32 +0,0 @@ - -Lunit License -------------- - -Lunit is written by Michael Roth and is licensed -under the terms of the MIT license reproduced below. - -======================================================================== - -Copyright (c) 2004-2010 Michael Roth - -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. - -======================================================================== - diff --git a/bindings/lua/lunit/console.lua b/bindings/lua/lunit/console.lua deleted file mode 100644 index 0ff22a4..0000000 --- a/bindings/lua/lunit/console.lua +++ /dev/null @@ -1,156 +0,0 @@ - ---[[-------------------------------------------------------------------------- - - This file is part of lunit 0.5. - - For Details about lunit look at: http://www.mroth.net/lunit/ - - Author: Michael Roth - - Copyright (c) 2006-2008 Michael Roth - - 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. - ---]]-------------------------------------------------------------------------- - - - ---[[ - - begin() - run(testcasename, testname) - err(fullname, message, traceback) - fail(fullname, where, message, usermessage) - pass(testcasename, testname) - done() - - Fullname: - testcase.testname - testcase.testname:setupname - testcase.testname:teardownname - ---]] - - -lunit = require "lunit" - -local lunit_console - -if _VERSION >= 'Lua 5.2' then - - lunit_console = setmetatable({},{__index = _ENV}) - _ENV = lunit_console - -else - - module( "lunit-console", package.seeall ) - lunit_console = _M - -end - - - -local function printformat(format, ...) - io.write( string.format(format, ...) ) -end - - -local columns_printed = 0 - -local function writestatus(char) - if columns_printed == 0 then - io.write(" ") - end - if columns_printed == 60 then - io.write("\n ") - columns_printed = 0 - end - io.write(char) - io.flush() - columns_printed = columns_printed + 1 -end - - -local msgs = {} - - -function begin() - local total_tc = 0 - local total_tests = 0 - - msgs = {} -- e - - for tcname in lunit.testcases() do - total_tc = total_tc + 1 - for testname, test in lunit.tests(tcname) do - total_tests = total_tests + 1 - end - end - - printformat("Loaded testsuite with %d tests in %d testcases.\n\n", total_tests, total_tc) -end - - -function run(testcasename, testname) - -- NOP -end - - -function err(fullname, message, traceback) - writestatus("E") - msgs[#msgs+1] = "Error! ("..fullname.."):\n"..message.."\n\t"..table.concat(traceback, "\n\t") .. "\n" -end - - -function fail(fullname, where, message, usermessage) - writestatus("F") - local text = "Failure ("..fullname.."):\n".. - where..": "..message.."\n" - - if usermessage then - text = text .. where..": "..usermessage.."\n" - end - - msgs[#msgs+1] = text -end - - -function pass(testcasename, testname) - writestatus(".") -end - - - -function done() - printformat("\n\n%d Assertions checked.\n", lunit.stats.assertions ) - print() - - for i, msg in ipairs(msgs) do - printformat( "%3d) %s\n", i, msg ) - end - - printformat("Testsuite finished (%d passed, %d failed, %d errors).\n", - lunit.stats.passed, lunit.stats.failed, lunit.stats.errors ) -end - - -return lunit_console - - diff --git a/bindings/lua/lunit/lunit.lua b/bindings/lua/lunit/lunit.lua deleted file mode 100644 index 80f43c1..0000000 --- a/bindings/lua/lunit/lunit.lua +++ /dev/null @@ -1,725 +0,0 @@ ---[[-------------------------------------------------------------------------- - - This file is part of lunit 0.5. - - For Details about lunit look at: http://www.mroth.net/lunit/ - - Author: Michael Roth - - Copyright (c) 2004, 2006-2010 Michael Roth - - 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. - ---]]-------------------------------------------------------------------------- - - -local orig_assert = assert - -local pairs = pairs -local ipairs = ipairs -local next = next -local type = type -local error = error -local tostring = tostring -local setmetatable = setmetatable -local pcall = pcall -local xpcall = xpcall -local require = require -local loadfile = loadfile - -local string_sub = string.sub -local string_gsub = string.gsub -local string_format = string.format -local string_lower = string.lower -local string_find = string.find - -local table_concat = table.concat - -local debug_getinfo = debug.getinfo - -local _G = _G - -local lunit - -if _VERSION >= 'Lua 5.2' then - - lunit = {} - _ENV = lunit - -else - - module("lunit") - lunit = _M - -end - - -local __failure__ = {} -- Type tag for failed assertions - -local typenames = { "nil", "boolean", "number", "string", "table", "function", "thread", "userdata" } - - -local traceback_hide -- Traceback function which hides lunit internals -local mypcall -- Protected call to a function with own traceback -do - local _tb_hide = setmetatable( {}, {__mode="k"} ) - - function traceback_hide(func) - _tb_hide[func] = true - end - - local function my_traceback(errobj) - if is_table(errobj) and errobj.type == __failure__ then - local info = debug_getinfo(5, "Sl") -- FIXME: Hardcoded integers are bad... - errobj.where = string_format( "%s:%d", info.short_src, info.currentline) - else - errobj = { msg = tostring(errobj) } - errobj.tb = {} - local i = 2 - while true do - local info = debug_getinfo(i, "Snlf") - if not is_table(info) then - break - end - if not _tb_hide[info.func] then - local line = {} -- Ripped from ldblib.c... - line[#line+1] = string_format("%s:", info.short_src) - if info.currentline > 0 then - line[#line+1] = string_format("%d:", info.currentline) - end - if info.namewhat ~= "" then - line[#line+1] = string_format(" in function '%s'", info.name) - else - if info.what == "main" then - line[#line+1] = " in main chunk" - elseif info.what == "C" or info.what == "tail" then - line[#line+1] = " ?" - else - line[#line+1] = string_format(" in function <%s:%d>", info.short_src, info.linedefined) - end - end - errobj.tb[#errobj.tb+1] = table_concat(line) - end - i = i + 1 - end - end - return errobj - end - - function mypcall(func) - orig_assert( is_function(func) ) - local ok, errobj = xpcall(func, my_traceback) - if not ok then - return errobj - end - end - traceback_hide(mypcall) -end - - --- Type check functions - -for _, typename in ipairs(typenames) do - lunit["is_"..typename] = function(x) - return type(x) == typename - end -end - -local is_nil = is_nil -local is_boolean = is_boolean -local is_number = is_number -local is_string = is_string -local is_table = is_table -local is_function = is_function -local is_thread = is_thread -local is_userdata = is_userdata - - -local function failure(name, usermsg, defaultmsg, ...) - local errobj = { - type = __failure__, - name = name, - msg = string_format(defaultmsg,...), - usermsg = usermsg - } - error(errobj, 0) -end -traceback_hide( failure ) - - -local function format_arg(arg) - local argtype = type(arg) - if argtype == "string" then - return "'"..arg.."'" - elseif argtype == "number" or argtype == "boolean" or argtype == "nil" then - return tostring(arg) - else - return "["..tostring(arg).."]" - end -end - - -local function selected(map, name) - if not map then - return true - end - - local m = {} - for k,v in pairs(map) do - m[k] = lunitpat2luapat(v) - end - return in_patternmap(m, name) -end - - -function fail(msg) - stats.assertions = stats.assertions + 1 - failure( "fail", msg, "failure" ) -end -traceback_hide( fail ) - - -function assert(assertion, msg) - stats.assertions = stats.assertions + 1 - if not assertion then - failure( "assert", msg, "assertion failed" ) - end - return assertion -end -traceback_hide( assert ) - - -function assert_true(actual, msg) - stats.assertions = stats.assertions + 1 - if actual ~= true then - failure( "assert_true", msg, "true expected but was %s", format_arg(actual) ) - end - return actual -end -traceback_hide( assert_true ) - - -function assert_false(actual, msg) - stats.assertions = stats.assertions + 1 - if actual ~= false then - failure( "assert_false", msg, "false expected but was %s", format_arg(actual) ) - end - return actual -end -traceback_hide( assert_false ) - - -function assert_equal(expected, actual, msg) - stats.assertions = stats.assertions + 1 - if expected ~= actual then - failure( "assert_equal", msg, "expected %s but was %s", format_arg(expected), format_arg(actual) ) - end - return actual -end -traceback_hide( assert_equal ) - - -function assert_not_equal(unexpected, actual, msg) - stats.assertions = stats.assertions + 1 - if unexpected == actual then - failure( "assert_not_equal", msg, "%s not expected but was one", format_arg(unexpected) ) - end - return actual -end -traceback_hide( assert_not_equal ) - - -function assert_match(pattern, actual, msg) - stats.assertions = stats.assertions + 1 - if type(pattern) ~= "string" then - failure( "assert_match", msg, "expected a string as pattern but was %s", format_arg(pattern) ) - end - if type(actual) ~= "string" then - failure( "assert_match", msg, "expected a string to match pattern '%s' but was a %s", pattern, format_arg(actual) ) - end - if not string_find(actual, pattern) then - failure( "assert_match", msg, "expected '%s' to match pattern '%s' but doesn't", actual, pattern ) - end - return actual -end -traceback_hide( assert_match ) - - -function assert_not_match(pattern, actual, msg) - stats.assertions = stats.assertions + 1 - if type(pattern) ~= "string" then - failure( "assert_not_match", msg, "expected a string as pattern but was %s", format_arg(pattern) ) - end - if type(actual) ~= "string" then - failure( "assert_not_match", msg, "expected a string to not match pattern '%s' but was %s", pattern, format_arg(actual) ) - end - if string_find(actual, pattern) then - failure( "assert_not_match", msg, "expected '%s' to not match pattern '%s' but it does", actual, pattern ) - end - return actual -end -traceback_hide( assert_not_match ) - - -function assert_error(msg, func) - stats.assertions = stats.assertions + 1 - if func == nil then - func, msg = msg, nil - end - if type(func) ~= "function" then - failure( "assert_error", msg, "expected a function as last argument but was %s", format_arg(func) ) - end - local ok, errmsg = pcall(func) - if ok then - failure( "assert_error", msg, "error expected but no error occurred" ) - end -end -traceback_hide( assert_error ) - - -function assert_error_match(msg, pattern, func) - stats.assertions = stats.assertions + 1 - if func == nil then - msg, pattern, func = nil, msg, pattern - end - if type(pattern) ~= "string" then - failure( "assert_error_match", msg, "expected the pattern as a string but was %s", format_arg(pattern) ) - end - if type(func) ~= "function" then - failure( "assert_error_match", msg, "expected a function as last argument but was %s", format_arg(func) ) - end - local ok, errmsg = pcall(func) - if ok then - failure( "assert_error_match", msg, "error expected but no error occurred" ) - end - if type(errmsg) ~= "string" then - failure( "assert_error_match", msg, "error as string expected but was %s", format_arg(errmsg) ) - end - if not string_find(errmsg, pattern) then - failure( "assert_error_match", msg, "expected error '%s' to match pattern '%s' but doesn't", errmsg, pattern ) - end -end -traceback_hide( assert_error_match ) - - -function assert_pass(msg, func) - stats.assertions = stats.assertions + 1 - if func == nil then - func, msg = msg, nil - end - if type(func) ~= "function" then - failure( "assert_pass", msg, "expected a function as last argument but was %s", format_arg(func) ) - end - local ok, errmsg = pcall(func) - if not ok then - failure( "assert_pass", msg, "no error expected but error was: '%s'", errmsg ) - end -end -traceback_hide( assert_pass ) - - --- lunit.assert_typename functions - -for _, typename in ipairs(typenames) do - local assert_typename = "assert_"..typename - lunit[assert_typename] = function(actual, msg) - stats.assertions = stats.assertions + 1 - if type(actual) ~= typename then - failure( assert_typename, msg, "%s expected but was %s", typename, format_arg(actual) ) - end - return actual - end - traceback_hide( lunit[assert_typename] ) -end - - --- lunit.assert_not_typename functions - -for _, typename in ipairs(typenames) do - local assert_not_typename = "assert_not_"..typename - lunit[assert_not_typename] = function(actual, msg) - stats.assertions = stats.assertions + 1 - if type(actual) == typename then - failure( assert_not_typename, msg, typename.." not expected but was one" ) - end - end - traceback_hide( lunit[assert_not_typename] ) -end - - -function lunit.clearstats() - stats = { - assertions = 0; - passed = 0; - failed = 0; - errors = 0; - } -end - - -local report, reporterrobj -do - local testrunner - - function lunit.setrunner(newrunner) - if not ( is_table(newrunner) or is_nil(newrunner) ) then - return error("lunit.setrunner: Invalid argument", 0) - end - local oldrunner = testrunner - testrunner = newrunner - return oldrunner - end - - function lunit.loadrunner(name) - if not is_string(name) then - return error("lunit.loadrunner: Invalid argument", 0) - end - local ok, runner = pcall( require, name ) - if not ok then - return error("lunit.loadrunner: Can't load test runner: "..runner, 0) - end - return setrunner(runner) - end - - function lunit.getrunner() - return testrunner - end - - function report(event, ...) - local f = testrunner and testrunner[event] - if is_function(f) then - pcall(f, ...) - end - end - - function reporterrobj(context, tcname, testname, errobj) - local fullname = tcname .. "." .. testname - if context == "setup" then - fullname = fullname .. ":" .. setupname(tcname, testname) - elseif context == "teardown" then - fullname = fullname .. ":" .. teardownname(tcname, testname) - end - if errobj.type == __failure__ then - stats.failed = stats.failed + 1 - report("fail", fullname, errobj.where, errobj.msg, errobj.usermsg) - else - stats.errors = stats.errors + 1 - report("err", fullname, errobj.msg, errobj.tb) - end - end -end - - - -local function key_iter(t, k) - return (next(t,k)) -end - - -local testcase -do - -- Array with all registered testcases - local _testcases = {} - - -- Marks a module as a testcase. - -- Applied over a module from module("xyz", lunit.testcase). - function lunit.testcase(m) - orig_assert( is_table(m) ) - --orig_assert( m._M == m ) - orig_assert( is_string(m._NAME) ) - --orig_assert( is_string(m._PACKAGE) ) - - -- Register the module as a testcase - _testcases[m._NAME] = m - - -- Import lunit, fail, assert* and is_* function to the module/testcase - m.lunit = lunit - m.fail = lunit.fail - for funcname, func in pairs(lunit) do - if "assert" == string_sub(funcname, 1, 6) or "is_" == string_sub(funcname, 1, 3) then - m[funcname] = func - end - end - end - - function lunit.module(name,seeall) - local m = {} - if seeall == "seeall" then - setmetatable(m, { __index = _G }) - end - m._NAME = name - lunit.testcase(m) - return m - end - - -- Iterator (testcasename) over all Testcases - function lunit.testcases() - -- Make a copy of testcases to prevent confusing the iterator when - -- new testcase are defined - local _testcases2 = {} - for k,v in pairs(_testcases) do - _testcases2[k] = true - end - return key_iter, _testcases2, nil - end - - function testcase(tcname) - return _testcases[tcname] - end -end - - -do - -- Finds a function in a testcase case insensitive - local function findfuncname(tcname, name) - for key, value in pairs(testcase(tcname)) do - if is_string(key) and is_function(value) and string_lower(key) == name then - return key - end - end - end - - function lunit.setupname(tcname) - return findfuncname(tcname, "setup") - end - - function lunit.teardownname(tcname) - return findfuncname(tcname, "teardown") - end - - -- Iterator over all test names in a testcase. - -- Have to collect the names first in case one of the test - -- functions creates a new global and throws off the iteration. - function lunit.tests(tcname) - local testnames = {} - for key, value in pairs(testcase(tcname)) do - if is_string(key) and is_function(value) then - local lfn = string_lower(key) - if string_sub(lfn, 1, 4) == "test" or string_sub(lfn, -4) == "test" then - testnames[key] = true - end - end - end - return key_iter, testnames, nil - end -end - - - - -function lunit.runtest(tcname, testname) - orig_assert( is_string(tcname) ) - orig_assert( is_string(testname) ) - - if (not getrunner()) then - loadrunner("console") - end - - local function callit(context, func) - if func then - local err = mypcall(func) - if err then - reporterrobj(context, tcname, testname, err) - return false - end - end - return true - end - traceback_hide(callit) - - report("run", tcname, testname) - - local tc = testcase(tcname) - local setup = tc[setupname(tcname)] - local test = tc[testname] - local teardown = tc[teardownname(tcname)] - - local setup_ok = callit( "setup", setup ) - local test_ok = setup_ok and callit( "test", test ) - local teardown_ok = setup_ok and callit( "teardown", teardown ) - - if setup_ok and test_ok and teardown_ok then - stats.passed = stats.passed + 1 - report("pass", tcname, testname) - end -end -traceback_hide(runtest) - - - -function lunit.run(testpatterns) - clearstats() - report("begin") - for testcasename in lunit.testcases() do - -- Run tests in the testcases - for testname in lunit.tests(testcasename) do - if selected(testpatterns, testname) then - runtest(testcasename, testname) - end - end - end - report("done") - return stats -end -traceback_hide(run) - - -function lunit.loadonly() - clearstats() - report("begin") - report("done") - return stats -end - - - - - - - - - -local lunitpat2luapat -do - local conv = { - ["^"] = "%^", - ["$"] = "%$", - ["("] = "%(", - [")"] = "%)", - ["%"] = "%%", - ["."] = "%.", - ["["] = "%[", - ["]"] = "%]", - ["+"] = "%+", - ["-"] = "%-", - ["?"] = ".", - ["*"] = ".*" - } - function lunitpat2luapat(str) - --return "^" .. string.gsub(str, "%W", conv) .. "$" - -- Above was very annoying, if I want to run all the tests having to do with - -- RSS, I want to be able to do "-t rss" not "-t \*rss\*". - return string_gsub(str, "%W", conv) - end -end - - - -local function in_patternmap(map, name) - if map[name] == true then - return true - else - for _, pat in ipairs(map) do - if string_find(name, pat) then - return true - end - end - end - return false -end - - - - - - - - --- Called from 'lunit' shell script. - -function main(argv) - argv = argv or {} - - -- FIXME: Error handling and error messages aren't nice. - - local function checkarg(optname, arg) - if not is_string(arg) then - return error("lunit.main: option "..optname..": argument missing.", 0) - end - end - - local function loadtestcase(filename) - if not is_string(filename) then - return error("lunit.main: invalid argument") - end - local chunk, err = loadfile(filename) - if err then - return error(err) - else - chunk() - end - end - - local testpatterns = nil - local doloadonly = false - - local i = 0 - while i < #argv do - i = i + 1 - local arg = argv[i] - if arg == "--loadonly" then - doloadonly = true - elseif arg == "--runner" or arg == "-r" then - local optname = arg; i = i + 1; arg = argv[i] - checkarg(optname, arg) - loadrunner(arg) - elseif arg == "--test" or arg == "-t" then - local optname = arg; i = i + 1; arg = argv[i] - checkarg(optname, arg) - testpatterns = testpatterns or {} - testpatterns[#testpatterns+1] = arg - elseif arg == "--help" or arg == "-h" then - print[[ -lunit 0.5 -Copyright (c) 2004-2009 Michael Roth -This program comes WITHOUT WARRANTY OF ANY KIND. - -Usage: lua test [OPTIONS] [--] scripts - -Options: - - -r, --runner RUNNER Testrunner to use, defaults to 'lunit-console'. - -t, --test PATTERN Which tests to run, may contain * or ? wildcards. - --loadonly Only load the tests. - -h, --help Print this help screen. - -Please report bugs to . -]] - return - elseif arg == "--" then - while i < #argv do - i = i + 1; arg = argv[i] - loadtestcase(arg) - end - else - loadtestcase(arg) - end - end - - if doloadonly then - return loadonly() - else - return run(testpatterns) - end -end - -clearstats() - -return lunit diff --git a/bindings/lua/table.c b/bindings/lua/table.c deleted file mode 100644 index 4e6aae2..0000000 --- a/bindings/lua/table.c +++ /dev/null @@ -1,168 +0,0 @@ -/* - * upb - a minimalist implementation of protocol buffers. - * - * Copyright (c) 2012 Google Inc. See LICENSE for details. - * Author: Josh Haberman - * - * Lua extension that provides access to upb_table. This is an internal-only - * interface and exists for the sole purpose of writing a C code generator in - * Lua that can dump a upb_table as static C initializers. This lets us use - * Lua for convenient string manipulation while saving us from re-implementing - * the upb_table hash function and hash table layout / collision strategy in - * Lua. - * - * Since this is used only as part of the toolchain (and not part of the - * runtime) we do not hold this module to the same stringent requirements as - * the main Lua modules (for example that misbehaving Lua programs cannot - * crash the interpreter). - */ - -#include -#include -#include -#include -#include "lauxlib.h" -#include "bindings/lua/upb.h" -#include "upb/def.h" - -static void lupbtable_setnum(lua_State *L, int tab, const char *key, - lua_Number val) { - lua_pushnumber(L, val); - lua_setfield(L, tab - 1, key); -} - -static void lupbtable_pushval(lua_State *L, _upb_value val, upb_ctype_t ctype) { - switch (ctype) { - case UPB_CTYPE_INT32: - lua_pushnumber(L, val.int32); - break; - case UPB_CTYPE_PTR: - lupb_def_pushwrapper(L, val.ptr, NULL); - break; - case UPB_CTYPE_CSTR: - lua_pushstring(L, val.cstr); - break; - default: - luaL_error(L, "Unexpected type: %d", ctype); - } -} - -// Sets a few fields common to both hash table entries and arrays. -static void lupbtable_setmetafields(lua_State *L, int ctype, const void *ptr) { - // We tack this onto every entry so we know it even if the entries - // don't stay with the table. - lua_pushnumber(L, ctype); - lua_setfield(L, -2, "valtype"); - - // Set this to facilitate linking. - lua_pushlightuserdata(L, (void*)ptr); - lua_setfield(L, -2, "ptr"); -} - -static void lupbtable_pushent(lua_State *L, const upb_tabent *e, - bool inttab, int ctype) { - lua_newtable(L); - if (!upb_tabent_isempty(e)) { - if (inttab) { - lua_pushnumber(L, e->key.num); - } else { - lua_pushstring(L, e->key.str); - } - lua_setfield(L, -2, "key"); - lupbtable_pushval(L, e->val, ctype); - lua_setfield(L, -2, "value"); - } - lua_pushlightuserdata(L, (void*)e->next); - lua_setfield(L, -2, "next"); - lupbtable_setmetafields(L, ctype, e); -} - -// Dumps the shared part of upb_table into a Lua table. -static void lupbtable_pushtable(lua_State *L, const upb_table *t, bool inttab) { - lua_newtable(L); - lupbtable_setnum(L, -1, "count", t->count); - lupbtable_setnum(L, -1, "mask", t->mask); - lupbtable_setnum(L, -1, "ctype", t->ctype); - lupbtable_setnum(L, -1, "size_lg2", t->size_lg2); - - lua_newtable(L); - for (int i = 0; i < upb_table_size(t); i++) { - lupbtable_pushent(L, &t->entries[i], inttab, t->ctype); - lua_rawseti(L, -2, i + 1); - } - lua_setfield(L, -2, "entries"); -} - -// Dumps a upb_inttable to a Lua table. -static void lupbtable_pushinttable(lua_State *L, const upb_inttable *t) { - lupbtable_pushtable(L, &t->t, true); - lupbtable_setnum(L, -1, "array_size", t->array_size); - lupbtable_setnum(L, -1, "array_count", t->array_count); - - lua_newtable(L); - for (int i = 0; i < t->array_size; i++) { - lua_newtable(L); - if (upb_arrhas(t->array[i])) { - lupbtable_pushval(L, t->array[i], t->t.ctype); - lua_setfield(L, -2, "val"); - } - lupbtable_setmetafields(L, t->t.ctype, &t->array[i]); - lua_rawseti(L, -2, i + 1); - } - lua_setfield(L, -2, "array"); -} - -static void lupbtable_pushstrtable(lua_State *L, const upb_strtable *t) { - lupbtable_pushtable(L, &t->t, false); -} - -static int lupbtable_msgdef_itof(lua_State *L) { - const upb_msgdef *m = lupb_msgdef_check(L, 1); - lupbtable_pushinttable(L, &m->itof); - return 1; -} - -static int lupbtable_msgdef_ntof(lua_State *L) { - const upb_msgdef *m = lupb_msgdef_check(L, 1); - lupbtable_pushstrtable(L, &m->ntof); - return 1; -} - -static int lupbtable_enumdef_iton(lua_State *L) { - const upb_enumdef *e = lupb_enumdef_check(L, 1); - lupbtable_pushinttable(L, &e->iton); - return 1; -} - -static int lupbtable_enumdef_ntoi(lua_State *L) { - const upb_enumdef *e = lupb_enumdef_check(L, 1); - lupbtable_pushstrtable(L, &e->ntoi); - return 1; -} - -static void lupbtable_setfieldi(lua_State *L, const char *field, int i) { - lua_pushnumber(L, i); - lua_setfield(L, -2, field); -} - -static const struct luaL_Reg lupbtable_toplevel_m[] = { - {"msgdef_itof", lupbtable_msgdef_itof}, - {"msgdef_ntof", lupbtable_msgdef_ntof}, - {"enumdef_iton", lupbtable_enumdef_iton}, - {"enumdef_ntoi", lupbtable_enumdef_ntoi}, - {NULL, NULL} -}; - -int luaopen_upbtable(lua_State *L) { - lupb_newlib(L, "upb.table", lupbtable_toplevel_m); - - // We define these here because they are not public. - lupbtable_setfieldi(L, "CTYPE_PTR", UPB_CTYPE_PTR); - lupbtable_setfieldi(L, "CTYPE_CSTR", UPB_CTYPE_CSTR); - lupbtable_setfieldi(L, "CTYPE_INT32", UPB_CTYPE_INT32); - - lua_pushlightuserdata(L, NULL); - lua_setfield(L, -2, "NULL"); - - return 1; // Return a single Lua value, the package table created above. -} diff --git a/bindings/lua/test.lua b/bindings/lua/test.lua deleted file mode 100644 index b19da53..0000000 --- a/bindings/lua/test.lua +++ /dev/null @@ -1,263 +0,0 @@ - -local upb = require "upb" -local lunit = require "lunit" - -if _VERSION >= 'Lua 5.2' then - _ENV = lunit.module("testupb", "seeall") -else - module("testupb", lunit.testcase, package.seeall) -end - -function test_fielddef() - local f = upb.FieldDef() - assert_false(f:is_frozen()) - assert_nil(f:number()) - assert_nil(f:name()) - assert_nil(f:type()) - assert_equal(upb.LABEL_OPTIONAL, f:label()) - - f:set_name("foo_field") - f:set_number(3) - f:set_label(upb.LABEL_REPEATED) - f:set_type(upb.TYPE_FLOAT) - - assert_equal("foo_field", f:name()) - assert_equal(3, f:number()) - assert_equal(upb.LABEL_REPEATED, f:label()) - assert_equal(upb.TYPE_FLOAT, f:type()) - - local f2 = upb.FieldDef{ - name = "foo", number = 5, type = upb.TYPE_DOUBLE, label = upb.LABEL_REQUIRED - } - - assert_equal("foo", f2:name()) - assert_equal(5, f2:number()) - assert_equal(upb.TYPE_DOUBLE, f2:type()) - assert_equal(upb.LABEL_REQUIRED, f2:label()) -end - -function test_enumdef() - local e = upb.EnumDef() - assert_equal(0, #e) - assert_nil(e:value(5)) - assert_nil(e:value("NONEXISTENT_NAME")) - - for name, value in e:values() do - fail() - end - - e:add("VAL1", 1) - e:add("VAL2", 2) - - local values = {} - for name, value in e:values() do - values[name] = value - end - - assert_equal(1, values["VAL1"]) - assert_equal(2, values["VAL2"]) - - local e2 = upb.EnumDef{ - values = { - {"FOO", 1}, - {"BAR", 77}, - } - } - - assert_equal(1, e2:value("FOO")) - assert_equal(77, e2:value("BAR")) - assert_equal("FOO", e2:value(1)) - assert_equal("BAR", e2:value(77)) -end - -function test_empty_msgdef() - local md = upb.MessageDef() - assert_nil(md:full_name()) -- Def without name is anonymous. - assert_false(md:is_frozen()) - assert_equal(0, #md) - assert_nil(md:field("nonexistent_field")) - assert_nil(md:field(3)) - for field in md:fields() do - fail() - end - - upb.freeze(md) - assert_true(md:is_frozen()) - assert_equal(0, #md) - assert_nil(md:field("nonexistent_field")) - assert_nil(md:field(3)) - for field in md:fields() do - fail() - end -end - -function test_msgdef_constructor() - local f1 = upb.FieldDef{name = "field1", number = 7, type = upb.TYPE_INT32} - local f2 = upb.FieldDef{name = "field2", number = 8, type = upb.TYPE_INT32} - local md = upb.MessageDef{ - full_name = "TestMessage", - fields = {f1, f2} - } - assert_equal("TestMessage", md:full_name()) - assert_false(md:is_frozen()) - assert_equal(2, #md) - assert_equal(f1, md:field("field1")) - assert_equal(f2, md:field("field2")) - assert_equal(f1, md:field(7)) - assert_equal(f2, md:field(8)) - local count = 0 - local found = {} - for field in md:fields() do - count = count + 1 - found[field] = true - end - assert_equal(2, count) - assert_true(found[f1]) - assert_true(found[f2]) - - upb.freeze(md) -end - -function test_msgdef_setters() - local md = upb.MessageDef() - md:set_full_name("Message1") - assert_equal("Message1", md:full_name()) - local f = upb.FieldDef{name = "field1", number = 3, type = upb.TYPE_DOUBLE} - md:add{f} - assert_equal(1, #md) - assert_equal(f, md:field("field1")) -end - -function test_msgdef_errors() - assert_error(function() upb.MessageDef{bad_initializer_key = 5} end) - local md = upb.MessageDef() - assert_error(function() - -- Duplicate field number. - upb.MessageDef{ - fields = { - upb.FieldDef{name = "field1", number = 1, type = upb.TYPE_INT32}, - upb.FieldDef{name = "field2", number = 1, type = upb.TYPE_INT32} - } - } - end) - assert_error(function() - -- Duplicate field name. - upb.MessageDef{ - fields = { - upb.FieldDef{name = "field1", number = 1, type = upb.TYPE_INT32}, - upb.FieldDef{name = "field1", number = 2, type = upb.TYPE_INT32} - } - } - end) - - -- attempt to set a name with embedded NULLs. - assert_error_match("names cannot have embedded NULLs", function() - md:set_full_name("abc\0def") - end) - - upb.freeze(md) - -- Attempt to mutate frozen MessageDef. - -- TODO(haberman): better error message and test for message. - assert_error(function() - md:add{upb.FieldDef{name = "field1", number = 1, type = upb.TYPE_INT32}} - end) - assert_error(function() - md:set_full_name("abc") - end) - - -- Attempt to freeze a msgdef without freezing its subdef. - assert_error_match("is not frozen or being frozen", function() - m1 = upb.MessageDef() - upb.freeze( - upb.MessageDef{ - fields = { - upb.FieldDef{name = "f1", number = 1, type = upb.TYPE_MESSAGE, - subdef = m1} - } - } - ) - end) -end - -function test_symtab() - local empty = upb.SymbolTable() - assert_equal(0, #empty:getdefs(upb.DEF_ANY)) - - local symtab = upb.SymbolTable{ - upb.MessageDef{full_name = "TestMessage"}, - upb.MessageDef{full_name = "ContainingMessage", fields = { - upb.FieldDef{name = "field1", number = 1, type = upb.TYPE_INT32}, - upb.FieldDef{name = "field2", number = 2, type = upb.TYPE_MESSAGE, - subdef_name = ".TestMessage"} - } - } - } - - local msgdef1 = symtab:lookup("TestMessage") - local msgdef2 = symtab:lookup("ContainingMessage") - assert_not_nil(msgdef1) - assert_not_nil(msgdef2) - assert_equal(msgdef1, msgdef2:field("field2"):subdef()) - assert_true(msgdef1:is_frozen()) - assert_true(msgdef2:is_frozen()) - - symtab:add{ - upb.MessageDef{full_name = "ContainingMessage2", fields = { - upb.FieldDef{name = "field5", number = 5, type = upb.TYPE_MESSAGE, - subdef = msgdef2} - } - } - } - - local msgdef3 = symtab:lookup("ContainingMessage2") - assert_not_nil(msgdef3) - assert_equal(msgdef3:field("field5"):subdef(), msgdef2) -end - --- Lua 5.1 and 5.2 have slightly different semantics for how a finalizer --- can be defined in Lua. -if _VERSION >= 'Lua 5.2' then - function defer(fn) - setmetatable({}, { __gc = fn }) - end -else - function defer(fn) - getmetatable(newproxy(true)).__gc = fn - end -end - -function test_finalizer() - -- Tests that we correctly handle a call into an already-finalized object. - -- Collectible objects are finalized in the opposite order of creation. - do - local t = {} - defer(function() - assert_error_match("called into dead def", function() - -- Generic def call. - t[1]:full_name() - end) - assert_error_match("called into dead msgdef", function() - -- Specific msgdef call. - t[1]:add() - end) - assert_error_match("called into dead enumdef", function() - t[2]:values() - end) - assert_error_match("called into dead fielddef", function() - t[3]:number() - end) - assert_error_match("called into dead symtab", - function() t[4]:lookup() - end) - end) - t = { - upb.MessageDef(), - upb.EnumDef(), - upb.FieldDef(), - upb.SymbolTable(), - } - end - collectgarbage() -end - -lunit.main() diff --git a/bindings/lua/upb.c b/bindings/lua/upb.c deleted file mode 100644 index 9eb46f3..0000000 --- a/bindings/lua/upb.c +++ /dev/null @@ -1,1162 +0,0 @@ -/* - * upb - a minimalist implementation of protocol buffers. - * - * Copyright (c) 2009 Google Inc. See LICENSE for details. - * Author: Josh Haberman - * - * A Lua extension for upb. Exposes only the core library - * (sub-libraries are exposed in other extensions). - */ - -#include -#include -#include -#include -#include "lauxlib.h" -#include "bindings/lua/upb.h" -#include "upb/handlers.h" -#include "upb/pb/glue.h" - -// Lua metatable types. -#define LUPB_MSGDEF "lupb.msgdef" -#define LUPB_ENUMDEF "lupb.enumdef" -#define LUPB_FIELDDEF "lupb.fielddef" -#define LUPB_SYMTAB "lupb.symtab" - -// Other table constants. -#define LUPB_OBJCACHE "lupb.objcache" - -#if LUA_VERSION_NUM == 501 - -// Taken from Lua 5.2's source. -void *luaL_testudata(lua_State *L, int ud, const char *tname) { - void *p = lua_touserdata(L, ud); - if (p != NULL) { /* value is a userdata? */ - if (lua_getmetatable(L, ud)) { /* does it have a metatable? */ - luaL_getmetatable(L, tname); /* get correct metatable */ - if (!lua_rawequal(L, -1, -2)) /* not the same? */ - p = NULL; /* value is a userdata with wrong metatable */ - lua_pop(L, 2); /* remove both metatables */ - return p; - } - } - return NULL; /* value is not a userdata with a metatable */ -} - -#elif LUA_VERSION_NUM == 502 - -int luaL_typerror(lua_State *L, int narg, const char *tname) { - const char *msg = lua_pushfstring(L, "%s expected, got %s", - tname, luaL_typename(L, narg)); - return luaL_argerror(L, narg, msg); -} - -#else -#error Only Lua 5.1 and 5.2 are supported -#endif - -static const char *chkname(lua_State *L, int narg) { - size_t len; - const char *name = luaL_checklstring(L, narg, &len); - if (strlen(name) != len) - luaL_error(L, "names cannot have embedded NULLs"); - return name; -} - -static bool streql(const char *a, const char *b) { return strcmp(a, b) == 0; } - -static uint32_t chkint32(lua_State *L, int narg, const char *name) { - lua_Number n = lua_tonumber(L, narg); - if (n > INT32_MAX || n < INT32_MIN || rint(n) != n) - luaL_error(L, "Invalid %s", name); - return n; -} - -// Sets a fielddef default from the given Lua value. -static void lupb_setdefault(lua_State *L, int narg, upb_fielddef *f) { - if (upb_fielddef_type(f) == UPB_TYPE_BOOL) { - if (!lua_isboolean(L, narg)) - luaL_error(L, "Must explicitly pass true or false for boolean fields"); - upb_fielddef_setdefaultbool(f, lua_toboolean(L, narg)); - } else { - // Numeric type. - lua_Number num = luaL_checknumber(L, narg); - switch (upb_fielddef_type(f)) { - case UPB_TYPE_INT32: - case UPB_TYPE_ENUM: - if (num > INT32_MAX || num < INT32_MIN || num != rint(num)) - luaL_error(L, "Cannot convert %f to 32-bit integer", num); - upb_fielddef_setdefaultint32(f, num); - break; - case UPB_TYPE_INT64: - if (num > INT64_MAX || num < INT64_MIN || num != rint(num)) - luaL_error(L, "Cannot convert %f to 64-bit integer", num); - upb_fielddef_setdefaultint64(f, num); - break; - case UPB_TYPE_UINT32: - if (num > UINT32_MAX || num < 0 || num != rint(num)) - luaL_error(L, "Cannot convert %f to unsigned 32-bit integer", num); - upb_fielddef_setdefaultuint32(f, num); - break; - case UPB_TYPE_UINT64: - if (num > UINT64_MAX || num < 0 || num != rint(num)) - luaL_error(L, "Cannot convert %f to unsigned 64-bit integer", num); - upb_fielddef_setdefaultuint64(f, num); - break; - case UPB_TYPE_DOUBLE: - if (num > DBL_MAX || num < -DBL_MAX) { - // This could happen if lua_Number was long double. - luaL_error(L, "Cannot convert %f to double", num); - } - upb_fielddef_setdefaultdouble(f, num); - break; - case UPB_TYPE_FLOAT: - if (num > FLT_MAX || num < -FLT_MAX) - luaL_error(L, "Cannot convert %f to float", num); - upb_fielddef_setdefaultfloat(f, num); - break; - default: luaL_error(L, "invalid type"); - } - } -} - -void lupb_checkstatus(lua_State *L, upb_status *s) { - if (!upb_ok(s)) { - lua_pushstring(L, upb_status_errmsg(s)); - lua_error(L); - } -} - -#define CHK(pred) do { \ - upb_status status = UPB_STATUS_INIT; \ - pred; \ - lupb_checkstatus(L, &status); \ - } while (0) - - -/* refcounted *****************************************************************/ - -// All upb objects that use upb_refcounted share a common Lua userdata -// representation and a common scheme for caching Lua wrapper object. They do -// however have different metatables. Objects are cached in a weak table -// indexed by the C pointer of the object they are caching. - -typedef union { - const upb_refcounted *refcounted; - const upb_def *def; - upb_symtab *symtab; -} lupb_refcounted; - -static bool lupb_refcounted_pushwrapper(lua_State *L, const upb_refcounted *obj, - const char *type, const void *owner) { - if (obj == NULL) { - lua_pushnil(L); - return false; - } - - // Lookup our cache in the registry (we don't put our objects in the registry - // directly because we need our cache to be a weak table). - lupb_refcounted *ud = NULL; - lua_getfield(L, LUA_REGISTRYINDEX, LUPB_OBJCACHE); - assert(!lua_isnil(L, -1)); // Should have been created by luaopen_upb. - lua_pushlightuserdata(L, (void*)obj); - lua_rawget(L, -2); - // Stack: objcache, cached value. - bool create = lua_isnil(L, -1) || - // A corner case: it is possible for the value to be GC'd - // already, in which case we should evict this entry and create - // a new one. - ((lupb_refcounted*)lua_touserdata(L, -1))->refcounted == NULL; - if (create) { - // Remove bad cached value and push new value. - lua_pop(L, 1); - - // We take advantage of the fact that all of our objects are currently a - // single pointer, and thus have the same layout. - // TODO: this probably violates aliasing. - ud = lua_newuserdata(L, sizeof(lupb_refcounted)); - ud->refcounted = obj; - upb_refcounted_donateref(obj, owner, ud); - - luaL_getmetatable(L, type); - assert(!lua_isnil(L, -1)); // Should have been created by luaopen_upb. - lua_setmetatable(L, -2); - - // Set it in the cache. - lua_pushlightuserdata(L, (void*)obj); - lua_pushvalue(L, -2); - lua_rawset(L, -4); - } else { - // Existing wrapper obj already has a ref. - ud = lua_touserdata(L, -1); - upb_refcounted_checkref(obj, ud); - if (owner) - upb_refcounted_unref(obj, owner); - } - lua_insert(L, -2); - lua_pop(L, 1); - return create; -} - -static void lupb_refcounted_pushnewrapper(lua_State *L, upb_refcounted *obj, - const char *type, const void *owner) { - bool created = lupb_refcounted_pushwrapper(L, obj, type, owner); - UPB_ASSERT_VAR(created, created == true); -} - - -/* lupb_def *******************************************************************/ - -static const upb_def *lupb_def_check(lua_State *L, int narg) { - lupb_refcounted *r = luaL_testudata(L, narg, LUPB_MSGDEF); - if (!r) r = luaL_testudata(L, narg, LUPB_ENUMDEF); - if (!r) r = luaL_testudata(L, narg, LUPB_FIELDDEF); - if (!r) luaL_typerror(L, narg, "upb def"); - if (!r->refcounted) luaL_error(L, "called into dead def"); - return r->def; -} - -static upb_def *lupb_def_checkmutable(lua_State *L, int narg) { - const upb_def *def = lupb_def_check(L, narg); - if (upb_def_isfrozen(def)) - luaL_typerror(L, narg, "not allowed on frozen value"); - return (upb_def*)def; -} - -bool lupb_def_pushwrapper(lua_State *L, const upb_def *def, const void *owner) { - if (def == NULL) { - lua_pushnil(L); - return false; - } - - const char *type = NULL; - switch (def->type) { - case UPB_DEF_MSG: type = LUPB_MSGDEF; break; - case UPB_DEF_ENUM: type = LUPB_ENUMDEF; break; - case UPB_DEF_FIELD: type = LUPB_FIELDDEF; break; - default: luaL_error(L, "unknown deftype %d", def->type); - } - return lupb_refcounted_pushwrapper(L, UPB_UPCAST(def), type, owner); -} - -void lupb_def_pushnewrapper(lua_State *L, const upb_def *def, - const void *owner) { - bool created = lupb_def_pushwrapper(L, def, owner); - UPB_ASSERT_VAR(created, created == true); -} - -static int lupb_def_type(lua_State *L) { - const upb_def *def = lupb_def_check(L, 1); - lua_pushnumber(L, upb_def_type(def)); - return 1; -} - -static int lupb_def_isfrozen(lua_State *L) { - const upb_def *def = lupb_def_check(L, 1); - lua_pushboolean(L, upb_def_isfrozen(def)); - return 1; -} - -static int lupb_def_fullname(lua_State *L) { - const upb_def *def = lupb_def_check(L, 1); - lua_pushstring(L, upb_def_fullname(def)); - return 1; -} - -static int lupb_def_setfullname(lua_State *L) { - CHK(upb_def_setfullname(lupb_def_checkmutable(L, 1), chkname(L, 2), &status)); - return 0; -} - -#define LUPB_COMMON_DEF_METHODS \ - {"def_type", lupb_def_type}, \ - {"full_name", lupb_def_fullname}, \ - {"is_frozen", lupb_def_isfrozen}, \ - {"set_full_name", lupb_def_setfullname}, \ - - -/* lupb_fielddef **************************************************************/ - -static const upb_fielddef *lupb_fielddef_check(lua_State *L, int narg) { - lupb_refcounted *r = luaL_checkudata(L, narg, LUPB_FIELDDEF); - if (!r) luaL_typerror(L, narg, "upb fielddef"); - if (!r->refcounted) luaL_error(L, "called into dead fielddef"); - return upb_downcast_fielddef(r->def); -} - -static upb_fielddef *lupb_fielddef_checkmutable(lua_State *L, int narg) { - const upb_fielddef *f = lupb_fielddef_check(L, narg); - if (upb_fielddef_isfrozen(f)) - luaL_typerror(L, narg, "not allowed on frozen value"); - return (upb_fielddef*)f; -} - -// Setter functions; these are called by both the constructor and the individual -// setter API calls like field:set_type(). - -static void lupb_fielddef_dosetdefault(lua_State *L, upb_fielddef *f, - int narg) { - int type = lua_type(L, narg); - upb_fieldtype_t upbtype = upb_fielddef_type(f); - if (type == LUA_TSTRING) { - if (!upb_fielddef_isstring(f) && upbtype != UPB_TYPE_ENUM) - luaL_argerror(L, narg, "field does not expect a string default"); - size_t len; - const char *str = lua_tolstring(L, narg, &len); - CHK(upb_fielddef_setdefaultstr(f, str, len, &status)); - } else { - lupb_setdefault(L, narg, f); - } -} - -static void lupb_fielddef_dosetlabel(lua_State *L, upb_fielddef *f, int narg) { - int label = luaL_checkint(L, narg); - if (!upb_fielddef_checklabel(label)) - luaL_argerror(L, narg, "invalid field label"); - upb_fielddef_setlabel(f, label); -} - -static void lupb_fielddef_dosetname(lua_State *L, upb_fielddef *f, int narg) { - CHK(upb_fielddef_setname(f, chkname(L, narg), &status)); -} - -static void lupb_fielddef_dosetnumber(lua_State *L, upb_fielddef *f, int narg) { - CHK(upb_fielddef_setnumber(f, luaL_checkint(L, narg), &status)); -} - -static void lupb_fielddef_dosetsubdef(lua_State *L, upb_fielddef *f, int narg) { - const upb_def *def = NULL; - if (!lua_isnil(L, narg)) - def = lupb_def_check(L, narg); - CHK(upb_fielddef_setsubdef(f, def, &status)); -} - -static void lupb_fielddef_dosetsubdefname(lua_State *L, upb_fielddef *f, - int narg) { - const char *name = NULL; - if (!lua_isnil(L, narg)) - name = chkname(L, narg); - CHK(upb_fielddef_setsubdefname(f, name, &status)); -} - -static void lupb_fielddef_dosettype(lua_State *L, upb_fielddef *f, int narg) { - int type = luaL_checkint(L, narg); - if (!upb_fielddef_checktype(type)) - luaL_argerror(L, narg, "invalid field type"); - upb_fielddef_settype(f, type); -} - -static void lupb_fielddef_dosetintfmt(lua_State *L, upb_fielddef *f, int narg) { - int32_t intfmt = luaL_checknumber(L, narg); - if (!upb_fielddef_checkintfmt(intfmt)) - luaL_argerror(L, narg, "invalid intfmt"); - upb_fielddef_setintfmt(f, intfmt); -} - -static void lupb_fielddef_dosettagdelim(lua_State *L, upb_fielddef *f, - int narg) { - if (!lua_isboolean(L, narg)) - luaL_argerror(L, narg, "tagdelim value must be boolean"); - int32_t tagdelim = luaL_checknumber(L, narg); - if (!upb_fielddef_settagdelim(f, tagdelim)) - luaL_argerror(L, narg, "invalid field tagdelim"); -} - -// Setter API calls. These use the setter functions above. - -static int lupb_fielddef_setdefault(lua_State *L) { - upb_fielddef *f = lupb_fielddef_checkmutable(L, 1); - lupb_fielddef_dosetdefault(L, f, 2); - return 0; -} - -static int lupb_fielddef_setlabel(lua_State *L) { - upb_fielddef *f = lupb_fielddef_checkmutable(L, 1); - lupb_fielddef_dosetlabel(L, f, 2); - return 0; -} - -static int lupb_fielddef_setname(lua_State *L) { - upb_fielddef *f = lupb_fielddef_checkmutable(L, 1); - lupb_fielddef_dosetname(L, f, 2); - return 0; -} - -static int lupb_fielddef_setnumber(lua_State *L) { - upb_fielddef *f = lupb_fielddef_checkmutable(L, 1); - lupb_fielddef_dosetnumber(L, f, 2); - return 0; -} - -static int lupb_fielddef_setsubdef(lua_State *L) { - upb_fielddef *f = lupb_fielddef_checkmutable(L, 1); - lupb_fielddef_dosetsubdef(L, f, 2); - return 0; -} - -static int lupb_fielddef_setsubdefname(lua_State *L) { - upb_fielddef *f = lupb_fielddef_checkmutable(L, 1); - lupb_fielddef_dosetsubdefname(L, f, 2); - return 0; -} - -static int lupb_fielddef_settype(lua_State *L) { - upb_fielddef *f = lupb_fielddef_checkmutable(L, 1); - lupb_fielddef_dosettype(L, f, 2); - return 0; -} - -static int lupb_fielddef_setintfmt(lua_State *L) { - upb_fielddef *f = lupb_fielddef_checkmutable(L, 1); - lupb_fielddef_dosetintfmt(L, f, 2); - return 0; -} - -static int lupb_fielddef_settagdelim(lua_State *L) { - upb_fielddef *f = lupb_fielddef_checkmutable(L, 1); - lupb_fielddef_dosettagdelim(L, f, 2); - return 0; -} - -// Constructor and other methods. - -static int lupb_fielddef_new(lua_State *L) { - upb_fielddef *f = upb_fielddef_new(&f); - int narg = lua_gettop(L); - - lupb_def_pushnewrapper(L, UPB_UPCAST(f), &f); - - if (narg == 0) return 1; - - // User can specify initialization values like so: - // upb.FieldDef{label=upb.LABEL_REQUIRED, name="my_field", number=5, - // type=upb.TYPE_INT32, default_value=12, type_name="Foo"} - luaL_checktype(L, 1, LUA_TTABLE); - for (lua_pushnil(L); lua_next(L, 1); lua_pop(L, 1)) { - luaL_checktype(L, -2, LUA_TSTRING); - const char *key = lua_tostring(L, -2); - int v = -1; - if (streql(key, "name")) lupb_fielddef_dosetname(L, f, v); - else if (streql(key, "number")) lupb_fielddef_dosetnumber(L, f, v); - else if (streql(key, "type")) lupb_fielddef_dosettype(L, f, v); - else if (streql(key, "label")) lupb_fielddef_dosetlabel(L, f, v); - else if (streql(key, "default_value")) ; // Defer to second pass. - else if (streql(key, "subdef")) ; // Defer to second pass. - else if (streql(key, "subdef_name")) ; // Defer to second pass. - else luaL_error(L, "Cannot set fielddef member '%s'", key); - } - - // Have to do these in a second pass because these depend on the type, so we - // have to make sure the type is set if the user specified one. - for (lua_pushnil(L); lua_next(L, 1); lua_pop(L, 1)) { - const char *key = lua_tostring(L, -2); - int v = -1; - if (streql(key, "default_value")) lupb_fielddef_dosetdefault(L, f, v); - else if (streql(key, "subdef")) lupb_fielddef_dosetsubdef(L, f, v); - else if (streql(key, "subdef_name")) lupb_fielddef_dosetsubdefname(L, f, v); - } - - return 1; -} - -static int lupb_fielddef_default(lua_State *L) { - const upb_fielddef *f = lupb_fielddef_check(L, 1); - switch (upb_fielddef_type(f)) { - case UPB_TYPE_INT32: - int32: - lua_pushnumber(L, upb_fielddef_defaultint32(f)); break; - case UPB_TYPE_INT64: - lua_pushnumber(L, upb_fielddef_defaultint64(f)); break; - case UPB_TYPE_UINT32: - lua_pushnumber(L, upb_fielddef_defaultuint32(f)); break; - case UPB_TYPE_UINT64: - lua_pushnumber(L, upb_fielddef_defaultuint64(f)); break; - case UPB_TYPE_DOUBLE: - lua_pushnumber(L, upb_fielddef_defaultdouble(f)); break; - case UPB_TYPE_FLOAT: - lua_pushnumber(L, upb_fielddef_defaultfloat(f)); break; - case UPB_TYPE_BOOL: - lua_pushboolean(L, upb_fielddef_defaultbool(f)); break; - case UPB_TYPE_ENUM: - if (!upb_fielddef_default_is_symbolic(f)) - goto int32; - // Fallthrough. - case UPB_TYPE_STRING: - case UPB_TYPE_BYTES: { - size_t len; - const char *data = upb_fielddef_defaultstr(f, &len); - lua_pushlstring(L, data, len); - break; - } - case UPB_TYPE_MESSAGE: - return luaL_error(L, "Message fields do not have explicit defaults."); - } - return 1; -} - -static int lupb_fielddef_getsel(lua_State *L) { - const upb_fielddef *f = lupb_fielddef_check(L, 1); - upb_selector_t sel; - if (upb_handlers_getselector(f, luaL_checknumber(L, 2), &sel)) { - lua_pushnumber(L, sel); - return 1; - } else { - return 0; - } -} - -static int lupb_fielddef_label(lua_State *L) { - const upb_fielddef *f = lupb_fielddef_check(L, 1); - lua_pushnumber(L, upb_fielddef_label(f)); - return 1; -} - -static int lupb_fielddef_name(lua_State *L) { - const upb_fielddef *f = lupb_fielddef_check(L, 1); - lua_pushstring(L, upb_fielddef_name(f)); - return 1; -} - -static int lupb_fielddef_number(lua_State *L) { - const upb_fielddef *f = lupb_fielddef_check(L, 1); - int32_t num = upb_fielddef_number(f); - if (num) - lua_pushnumber(L, num); - else - lua_pushnil(L); - return 1; -} - -static int lupb_fielddef_selectorbase(lua_State *L) { - const upb_fielddef *f = lupb_fielddef_check(L, 1); - if (!upb_fielddef_isfrozen(f)) - luaL_error(L, "_selectorbase is only defined for frozen fielddefs"); - lua_pushnumber(L, f->selector_base); - return 1; -} - -static int lupb_fielddef_hassubdef(lua_State *L) { - const upb_fielddef *f = lupb_fielddef_check(L, 1); - lua_pushboolean(L, upb_fielddef_hassubdef(f)); - return 1; -} - -static int lupb_fielddef_containingtype(lua_State *L) { - const upb_fielddef *f = lupb_fielddef_check(L, 1); - lupb_def_pushwrapper(L, UPB_UPCAST(upb_fielddef_containingtype(f)), NULL); - return 1; -} - -static int lupb_fielddef_subdef(lua_State *L) { - const upb_fielddef *f = lupb_fielddef_check(L, 1); - if (!upb_fielddef_hassubdef(f)) - luaL_error(L, "Tried to get subdef of non-message field"); - const upb_def *def = upb_fielddef_subdef(f); - lupb_def_pushwrapper(L, def, NULL); - return 1; -} - -static int lupb_fielddef_subdefname(lua_State *L) { - upb_fielddef *f = lupb_fielddef_checkmutable(L, 1); - if (!upb_fielddef_hassubdef(f)) - luaL_error(L, "Tried to get subdef name of non-message field"); - lua_pushstring(L, upb_fielddef_subdefname(f)); - return 1; -} - -static int lupb_fielddef_type(lua_State *L) { - const upb_fielddef *f = lupb_fielddef_check(L, 1); - if (upb_fielddef_typeisset(f)) - lua_pushnumber(L, upb_fielddef_type(f)); - else - lua_pushnil(L); - return 1; -} - -static int lupb_fielddef_index(lua_State *L) { - const upb_fielddef *f = lupb_fielddef_check(L, 1); - lua_pushnumber(L, upb_fielddef_index(f)); - return 1; -} - -static int lupb_fielddef_intfmt(lua_State *L) { - const upb_fielddef *f = lupb_fielddef_check(L, 1); - lua_pushnumber(L, upb_fielddef_intfmt(f)); - return 1; -} - -static int lupb_fielddef_istagdelim(lua_State *L) { - const upb_fielddef *f = lupb_fielddef_check(L, 1); - lua_pushboolean(L, upb_fielddef_istagdelim(f)); - return 1; -} - -static int lupb_fielddef_gc(lua_State *L) { - lupb_refcounted *r = luaL_checkudata(L, 1, LUPB_FIELDDEF); - upb_def_unref(r->def, r); - r->refcounted = NULL; - return 0; -} - -static const struct luaL_Reg lupb_fielddef_m[] = { - LUPB_COMMON_DEF_METHODS - - {"containing_type", lupb_fielddef_containingtype}, - {"default", lupb_fielddef_default}, - {"getsel", lupb_fielddef_getsel}, - {"has_subdef", lupb_fielddef_hassubdef}, - {"index", lupb_fielddef_index}, - {"intfmt", lupb_fielddef_intfmt}, - {"istagdelim", lupb_fielddef_istagdelim}, - {"label", lupb_fielddef_label}, - {"name", lupb_fielddef_name}, - {"number", lupb_fielddef_number}, - {"subdef", lupb_fielddef_subdef}, - {"subdef_name", lupb_fielddef_subdefname}, - {"type", lupb_fielddef_type}, - - {"set_default", lupb_fielddef_setdefault}, - {"set_label", lupb_fielddef_setlabel}, - {"set_name", lupb_fielddef_setname}, - {"set_number", lupb_fielddef_setnumber}, - {"set_subdef", lupb_fielddef_setsubdef}, - {"set_subdef_name", lupb_fielddef_setsubdefname}, - {"set_type", lupb_fielddef_settype}, - {"set_intfmt", lupb_fielddef_setintfmt}, - {"set_tagdelim", lupb_fielddef_settagdelim}, - - // Internal-only. - {"_selector_base", lupb_fielddef_selectorbase}, - - {NULL, NULL} -}; - -static const struct luaL_Reg lupb_fielddef_mm[] = { - {"__gc", lupb_fielddef_gc}, - {NULL, NULL} -}; - - -/* lupb_msgdef ****************************************************************/ - -const upb_msgdef *lupb_msgdef_check(lua_State *L, int narg) { - lupb_refcounted *r = luaL_checkudata(L, narg, LUPB_MSGDEF); - if (!r) luaL_typerror(L, narg, LUPB_MSGDEF); - if (!r->refcounted) luaL_error(L, "called into dead msgdef"); - return upb_downcast_msgdef(r->def); -} - -static upb_msgdef *lupb_msgdef_checkmutable(lua_State *L, int narg) { - const upb_msgdef *m = lupb_msgdef_check(L, narg); - if (upb_msgdef_isfrozen(m)) - luaL_typerror(L, narg, "not allowed on frozen value"); - return (upb_msgdef*)m; -} - -static int lupb_msgdef_gc(lua_State *L) { - lupb_refcounted *r = luaL_checkudata(L, 1, LUPB_MSGDEF); - upb_def_unref(r->def, r); - r->refcounted = NULL; - return 0; -} - -static int lupb_msgdef_new(lua_State *L) { - int narg = lua_gettop(L); - upb_msgdef *md = upb_msgdef_new(&md); - lupb_def_pushnewrapper(L, UPB_UPCAST(md), &md); - - if (narg == 0) return 1; - - // User can specify initialization values like so: - // upb.MessageDef{full_name="MyMessage", extstart=8000, fields={...}} - luaL_checktype(L, 1, LUA_TTABLE); - for (lua_pushnil(L); lua_next(L, 1); lua_pop(L, 1)) { - luaL_checktype(L, -2, LUA_TSTRING); - const char *key = lua_tostring(L, -2); - - if (streql(key, "full_name")) { // full_name="MyMessage" - CHK(upb_def_setfullname(UPB_UPCAST(md), chkname(L, -1), &status)); - } else if (streql(key, "fields")) { // fields={...} - // Iterate over the list of fields. - luaL_checktype(L, -1, LUA_TTABLE); - for (lua_pushnil(L); lua_next(L, -2); lua_pop(L, 1)) { - upb_fielddef *f = lupb_fielddef_checkmutable(L, -1); - CHK(upb_msgdef_addfield(md, f, NULL, &status)); - } - } else { - // TODO: extrange= - luaL_error(L, "Unknown initializer key '%s'", key); - } - } - return 1; -} - -static int lupb_msgdef_add(lua_State *L) { - upb_msgdef *m = lupb_msgdef_checkmutable(L, 1); - luaL_checktype(L, 2, LUA_TTABLE); - int n = lua_rawlen(L, 2); - // TODO: add upb interface that lets us avoid this malloc/free. - upb_fielddef **fields = malloc(n * sizeof(upb_fielddef*)); - for (int i = 0; i < n; i++) { - lua_rawgeti(L, -1, i + 1); - fields[i] = lupb_fielddef_checkmutable(L, -1); - lua_pop(L, 1); - } - - upb_status status = UPB_STATUS_INIT; - upb_msgdef_addfields(m, fields, n, NULL, &status); - free(fields); - lupb_checkstatus(L, &status); - return 0; -} - -static int lupb_msgdef_len(lua_State *L) { - const upb_msgdef *m = lupb_msgdef_check(L, 1); - lua_pushinteger(L, upb_msgdef_numfields(m)); - return 1; -} - -static int lupb_msgdef_selectorcount(lua_State *L) { - const upb_msgdef *m = lupb_msgdef_check(L, 1); - lua_pushinteger(L, m->selector_count); - return 1; -} - -static int lupb_msgdef_submsgfieldcount(lua_State *L) { - const upb_msgdef *m = lupb_msgdef_check(L, 1); - lua_pushinteger(L, m->submsg_field_count); - return 1; -} - -static int lupb_msgdef_field(lua_State *L) { - const upb_msgdef *m = lupb_msgdef_check(L, 1); - int type = lua_type(L, 2); - const upb_fielddef *f; - if (type == LUA_TNUMBER) { - f = upb_msgdef_itof(m, lua_tointeger(L, 2)); - } else if (type == LUA_TSTRING) { - f = upb_msgdef_ntof(m, lua_tostring(L, 2)); - } else { - const char *msg = lua_pushfstring(L, "number or string expected, got %s", - luaL_typename(L, 2)); - return luaL_argerror(L, 2, msg); - } - - lupb_def_pushwrapper(L, UPB_UPCAST(f), NULL); - return 1; -} - -static int lupb_msgiter_next(lua_State *L) { - upb_msg_iter *i = lua_touserdata(L, lua_upvalueindex(1)); - if (upb_msg_done(i)) return 0; - lupb_def_pushwrapper(L, UPB_UPCAST(upb_msg_iter_field(i)), NULL); - upb_msg_next(i); - return 1; -} - -static int lupb_msgdef_fields(lua_State *L) { - const upb_msgdef *m = lupb_msgdef_check(L, 1); - upb_msg_iter *i = lua_newuserdata(L, sizeof(upb_msg_iter)); - upb_msg_begin(i, m); - lua_pushcclosure(L, &lupb_msgiter_next, 1); - return 1; -} - -static const struct luaL_Reg lupb_msgdef_mm[] = { - {"__gc", lupb_msgdef_gc}, - {"__len", lupb_msgdef_len}, - {NULL, NULL} -}; - -static const struct luaL_Reg lupb_msgdef_m[] = { - LUPB_COMMON_DEF_METHODS - {"add", lupb_msgdef_add}, - {"field", lupb_msgdef_field}, - {"fields", lupb_msgdef_fields}, - - // Internal-only. - {"_selector_count", lupb_msgdef_selectorcount}, - {"_submsg_field_count", lupb_msgdef_submsgfieldcount}, - - {NULL, NULL} -}; - - -/* lupb_enumdef ***************************************************************/ - -const upb_enumdef *lupb_enumdef_check(lua_State *L, int narg) { - lupb_refcounted *r = luaL_checkudata(L, narg, LUPB_ENUMDEF); - if (!r) luaL_typerror(L, narg, LUPB_ENUMDEF); - if (!r->refcounted) luaL_error(L, "called into dead enumdef"); - return upb_downcast_enumdef(r->def); -} - -static upb_enumdef *lupb_enumdef_checkmutable(lua_State *L, int narg) { - const upb_enumdef *f = lupb_enumdef_check(L, narg); - if (upb_enumdef_isfrozen(f)) - luaL_typerror(L, narg, "not allowed on frozen value"); - return (upb_enumdef*)f; -} - -static int lupb_enumdef_gc(lua_State *L) { - lupb_refcounted *r = luaL_checkudata(L, 1, LUPB_ENUMDEF); - upb_def_unref(r->def, r); - r->refcounted = NULL; - return 0; -} - -static int lupb_enumdef_new(lua_State *L) { - int narg = lua_gettop(L); - upb_enumdef *e = upb_enumdef_new(&e); - lupb_def_pushnewrapper(L, UPB_UPCAST(e), &e); - - if (narg == 0) return 1; - - // User can specify initialization values like so: - // upb.EnumDef{full_name="MyEnum", - // values={ - // {"FOO_VALUE_1", 1}, - // {"FOO_VALUE_2", 2} - // } - // } - luaL_checktype(L, 1, LUA_TTABLE); - for (lua_pushnil(L); lua_next(L, 1); lua_pop(L, 1)) { - luaL_checktype(L, -2, LUA_TSTRING); - const char *key = lua_tostring(L, -2); - if (streql(key, "values")) { - for (lua_pushnil(L); lua_next(L, -2); lua_pop(L, 1)) { - lua_rawgeti(L, -1, 1); - luaL_checktype(L, -1, LUA_TSTRING); - const char *name = lua_tostring(L, -1); - lua_rawgeti(L, -2, 2); - CHK(upb_enumdef_addval(e, name, chkint32(L, -1, "value"), &status)); - lua_pop(L, 2); // The key/val we got from lua_rawgeti() - } - } else if (streql(key, "full_name")) { - CHK(upb_def_setfullname(UPB_UPCAST(e), chkname(L, -1), &status)); - } else { - luaL_error(L, "Unknown initializer key '%s'", key); - } - } - return 1; -} - -static int lupb_enumdef_add(lua_State *L) { - upb_enumdef *e = lupb_enumdef_checkmutable(L, 1); - CHK(upb_enumdef_addval(e, chkname(L, 2), chkint32(L, 3, "value"), &status)); - return 0; -} - -static int lupb_enumdef_len(lua_State *L) { - const upb_enumdef *e = lupb_enumdef_check(L, 1); - lua_pushinteger(L, upb_enumdef_numvals(e)); - return 1; -} - -static int lupb_enumdef_value(lua_State *L) { - const upb_enumdef *e = lupb_enumdef_check(L, 1); - int type = lua_type(L, 2); - if (type == LUA_TNUMBER) { - // Pushes "nil" for a NULL pointer. - lua_pushstring(L, upb_enumdef_iton(e, chkint32(L, 2, "value"))); - } else if (type == LUA_TSTRING) { - int32_t num; - if (upb_enumdef_ntoi(e, lua_tostring(L, 2), &num)) { - lua_pushnumber(L, num); - } else { - lua_pushnil(L); - } - } else { - const char *msg = lua_pushfstring(L, "number or string expected, got %s", - luaL_typename(L, 2)); - return luaL_argerror(L, 2, msg); - } - return 1; -} - -static int lupb_enumiter_next(lua_State *L) { - upb_enum_iter *i = lua_touserdata(L, lua_upvalueindex(1)); - if (upb_enum_done(i)) return 0; - lua_pushstring(L, upb_enum_iter_name(i)); - lua_pushnumber(L, upb_enum_iter_number(i)); - upb_enum_next(i); - return 2; -} - -static int lupb_enumdef_values(lua_State *L) { - const upb_enumdef *e = lupb_enumdef_check(L, 1); - upb_enum_iter *i = lua_newuserdata(L, sizeof(upb_enum_iter)); - upb_enum_begin(i, e); - lua_pushcclosure(L, &lupb_enumiter_next, 1); - return 1; -} - -static const struct luaL_Reg lupb_enumdef_mm[] = { - {"__gc", lupb_enumdef_gc}, - {"__len", lupb_enumdef_len}, - {NULL, NULL} -}; - -static const struct luaL_Reg lupb_enumdef_m[] = { - LUPB_COMMON_DEF_METHODS - {"add", lupb_enumdef_add}, - {"value", lupb_enumdef_value}, - {"values", lupb_enumdef_values}, - {NULL, NULL} -}; - - -/* lupb_symtab ****************************************************************/ - -// Inherits a ref on the symtab. -// Checks that narg is a proper lupb_symtab object. If it is, leaves its -// metatable on the stack for cache lookups/updates. -upb_symtab *lupb_symtab_check(lua_State *L, int narg) { - lupb_refcounted *r = luaL_checkudata(L, narg, LUPB_SYMTAB); - if (!r) luaL_typerror(L, narg, LUPB_SYMTAB); - if (!r->refcounted) luaL_error(L, "called into dead symtab"); - return r->symtab; -} - -// narg is a lua table containing a list of defs to add. -void lupb_symtab_doadd(lua_State *L, upb_symtab *s, int narg) { - luaL_checktype(L, narg, LUA_TTABLE); - // Iterate over table twice. First iteration to count entries and - // check constraints. - int n = 0; - for (lua_pushnil(L); lua_next(L, narg); lua_pop(L, 1)) { - lupb_def_check(L, -1); - ++n; - } - - // Second iteration to build deflist and layout. - upb_def **defs = malloc(n * sizeof(*defs)); - n = 0; - for (lua_pushnil(L); lua_next(L, narg); lua_pop(L, 1)) { - upb_def *def = lupb_def_checkmutable(L, -1); - defs[n++] = def; - } - - upb_status status = UPB_STATUS_INIT; - upb_symtab_add(s, defs, n, NULL, &status); - free(defs); - lupb_checkstatus(L, &status); -} - -static int lupb_symtab_new(lua_State *L) { - int narg = lua_gettop(L); - upb_symtab *s = upb_symtab_new(&s); - lupb_refcounted_pushnewrapper(L, UPB_UPCAST(s), LUPB_SYMTAB, &s); - if (narg > 0) lupb_symtab_doadd(L, s, 1); - return 1; -} - -static int lupb_symtab_add(lua_State *L) { - lupb_symtab_doadd(L, lupb_symtab_check(L, 1), 2); - return 0; -} - -static int lupb_symtab_gc(lua_State *L) { - lupb_refcounted *r = luaL_checkudata(L, 1, LUPB_SYMTAB); - upb_symtab_unref(r->symtab, r); - r->refcounted = NULL; - return 0; -} - -static int lupb_symtab_lookup(lua_State *L) { - upb_symtab *s = lupb_symtab_check(L, 1); - for (int i = 2; i <= lua_gettop(L); i++) { - const upb_def *def = - upb_symtab_lookup(s, luaL_checkstring(L, i), &def); - lupb_def_pushwrapper(L, def, &def); - lua_replace(L, i); - } - return lua_gettop(L) - 1; -} - -static int lupb_symtab_getdefs(lua_State *L) { - upb_symtab *s = lupb_symtab_check(L, 1); - upb_deftype_t type = luaL_checkint(L, 2); - int count; - const upb_def **defs = upb_symtab_getdefs(s, type, &defs, &count); - - // Create the table in which we will return the defs. - lua_createtable(L, count, 0); - for (int i = 0; i < count; i++) { - const upb_def *def = defs[i]; - lupb_def_pushwrapper(L, def, &defs); - lua_rawseti(L, -2, i + 1); - } - free(defs); - return 1; -} - -// This is a *temporary* API that will be removed once pending refactorings are -// complete (it does not belong here in core because it depends on both -// the descriptor.proto schema and the protobuf binary format. -static int lupb_symtab_load_descriptor(lua_State *L) { - size_t len; - upb_symtab *s = lupb_symtab_check(L, 1); - const char *str = luaL_checklstring(L, 2, &len); - CHK(upb_load_descriptor_into_symtab(s, str, len, &status)); - return 0; -} - -static const struct luaL_Reg lupb_symtab_m[] = { - {"add", lupb_symtab_add}, - {"getdefs", lupb_symtab_getdefs}, - {"lookup", lupb_symtab_lookup}, - {"load_descriptor", lupb_symtab_load_descriptor}, - {NULL, NULL} -}; - -static const struct luaL_Reg lupb_symtab_mm[] = { - {"__gc", lupb_symtab_gc}, - {NULL, NULL} -}; - - -/* lupb toplevel **************************************************************/ - -static int lupb_def_freeze(lua_State *L) { - int n = lua_gettop(L); - upb_def **defs = malloc(n * sizeof(upb_def*)); - for (int i = 0; i < n; i++) { - // Could allow an array of defs here also. - defs[i] = lupb_def_checkmutable(L, i + 1); - } - upb_status s = UPB_STATUS_INIT; - upb_def_freeze(defs, n, &s); - free(defs); - lupb_checkstatus(L, &s); - return 0; -} - -static const struct luaL_Reg lupb_toplevel_m[] = { - {"EnumDef", lupb_enumdef_new}, - {"FieldDef", lupb_fielddef_new}, - {"MessageDef", lupb_msgdef_new}, - {"SymbolTable", lupb_symtab_new}, - {"freeze", lupb_def_freeze}, - - {NULL, NULL} -}; - -// Register the given type with the given methods and metamethods. -static void lupb_register_type(lua_State *L, const char *name, - const luaL_Reg *m, const luaL_Reg *mm) { - luaL_newmetatable(L, name); - lupb_setfuncs(L, mm); // Register all mm in the metatable. - lua_createtable(L, 0, 0); - // Methods go in the mt's __index method. This implies that you can't - // implement __index. - lupb_setfuncs(L, m); - lua_setfield(L, -2, "__index"); - lua_pop(L, 1); // The mt. -} - -static void lupb_setfieldi(lua_State *L, const char *field, int i) { - lua_pushnumber(L, i); - lua_setfield(L, -2, field); -} - -int luaopen_upb(lua_State *L) { - lupb_register_type(L, LUPB_MSGDEF, lupb_msgdef_m, lupb_msgdef_mm); - lupb_register_type(L, LUPB_ENUMDEF, lupb_enumdef_m, lupb_enumdef_mm); - lupb_register_type(L, LUPB_FIELDDEF, lupb_fielddef_m, lupb_fielddef_mm); - lupb_register_type(L, LUPB_SYMTAB, lupb_symtab_m, lupb_symtab_mm); - - // Create our object cache. - lua_newtable(L); - lua_createtable(L, 0, 1); // Cache metatable. - lua_pushstring(L, "v"); // Values are weak. - lua_setfield(L, -2, "__mode"); - lua_setmetatable(L, -2); - lua_setfield(L, LUA_REGISTRYINDEX, LUPB_OBJCACHE); - - lupb_newlib(L, "upb", lupb_toplevel_m); - - // Define a couple functions as Lua source (kept here instead of a separate - // Lua file so that upb.so is self-contained) - const char *lua_source = - "return function(upb)\n" - " upb.build_defs = function(defs)\n" - " local symtab = upb.SymbolTable(defs)\n" - " return symtab:getdefs(upb.DEF_ANY)\n" - " end\n" - "end"; - - if (luaL_dostring(L, lua_source) != 0) - lua_error(L); - - // Call the chunk that will define the extra functions on upb, passing our - // package dictionary as the argument. - lua_pushvalue(L, -2); - lua_call(L, 1, 0); - - // Register constants. - lupb_setfieldi(L, "LABEL_OPTIONAL", UPB_LABEL_OPTIONAL); - lupb_setfieldi(L, "LABEL_REQUIRED", UPB_LABEL_REQUIRED); - lupb_setfieldi(L, "LABEL_REPEATED", UPB_LABEL_REPEATED); - - lupb_setfieldi(L, "TYPE_DOUBLE", UPB_TYPE_DOUBLE); - lupb_setfieldi(L, "TYPE_FLOAT", UPB_TYPE_FLOAT); - lupb_setfieldi(L, "TYPE_INT64", UPB_TYPE_INT64); - lupb_setfieldi(L, "TYPE_UINT64", UPB_TYPE_UINT64); - lupb_setfieldi(L, "TYPE_INT32", UPB_TYPE_INT32); - lupb_setfieldi(L, "TYPE_BOOL", UPB_TYPE_BOOL); - lupb_setfieldi(L, "TYPE_STRING", UPB_TYPE_STRING); - lupb_setfieldi(L, "TYPE_MESSAGE", UPB_TYPE_MESSAGE); - lupb_setfieldi(L, "TYPE_BYTES", UPB_TYPE_BYTES); - lupb_setfieldi(L, "TYPE_UINT32", UPB_TYPE_UINT32); - lupb_setfieldi(L, "TYPE_ENUM", UPB_TYPE_ENUM); - - lupb_setfieldi(L, "INTFMT_VARIABLE", UPB_INTFMT_VARIABLE); - lupb_setfieldi(L, "INTFMT_FIXED", UPB_INTFMT_FIXED); - lupb_setfieldi(L, "INTFMT_ZIGZAG", UPB_INTFMT_ZIGZAG); - - lupb_setfieldi(L, "DESCRIPTOR_TYPE_DOUBLE", UPB_DESCRIPTOR_TYPE_DOUBLE); - lupb_setfieldi(L, "DESCRIPTOR_TYPE_FLOAT", UPB_DESCRIPTOR_TYPE_FLOAT); - lupb_setfieldi(L, "DESCRIPTOR_TYPE_INT64", UPB_DESCRIPTOR_TYPE_INT64); - lupb_setfieldi(L, "DESCRIPTOR_TYPE_UINT64", UPB_DESCRIPTOR_TYPE_UINT64); - lupb_setfieldi(L, "DESCRIPTOR_TYPE_INT32", UPB_DESCRIPTOR_TYPE_INT32); - lupb_setfieldi(L, "DESCRIPTOR_TYPE_FIXED64", UPB_DESCRIPTOR_TYPE_FIXED64); - lupb_setfieldi(L, "DESCRIPTOR_TYPE_FIXED32", UPB_DESCRIPTOR_TYPE_FIXED32); - lupb_setfieldi(L, "DESCRIPTOR_TYPE_BOOL", UPB_DESCRIPTOR_TYPE_BOOL); - lupb_setfieldi(L, "DESCRIPTOR_TYPE_STRING", UPB_DESCRIPTOR_TYPE_STRING); - lupb_setfieldi(L, "DESCRIPTOR_TYPE_GROUP", UPB_DESCRIPTOR_TYPE_GROUP); - lupb_setfieldi(L, "DESCRIPTOR_TYPE_MESSAGE", UPB_DESCRIPTOR_TYPE_MESSAGE); - lupb_setfieldi(L, "DESCRIPTOR_TYPE_BYTES", UPB_DESCRIPTOR_TYPE_BYTES); - lupb_setfieldi(L, "DESCRIPTOR_TYPE_UINT32", UPB_DESCRIPTOR_TYPE_UINT32); - lupb_setfieldi(L, "DESCRIPTOR_TYPE_ENUM", UPB_DESCRIPTOR_TYPE_ENUM); - lupb_setfieldi(L, "DESCRIPTOR_TYPE_SFIXED32", UPB_DESCRIPTOR_TYPE_SFIXED32); - lupb_setfieldi(L, "DESCRIPTOR_TYPE_SFIXED64", UPB_DESCRIPTOR_TYPE_SFIXED64); - lupb_setfieldi(L, "DESCRIPTOR_TYPE_SINT32", UPB_DESCRIPTOR_TYPE_SINT32); - lupb_setfieldi(L, "DESCRIPTOR_TYPE_SINT64", UPB_DESCRIPTOR_TYPE_SINT64); - - lupb_setfieldi(L, "DEF_MSG", UPB_DEF_MSG); - lupb_setfieldi(L, "DEF_FIELD", UPB_DEF_FIELD); - lupb_setfieldi(L, "DEF_ENUM", UPB_DEF_ENUM); - lupb_setfieldi(L, "DEF_SERVICE", UPB_DEF_SERVICE); - lupb_setfieldi(L, "DEF_ANY", UPB_DEF_ANY); - - lupb_setfieldi(L, "HANDLER_INT32", UPB_HANDLER_INT32); - lupb_setfieldi(L, "HANDLER_INT64", UPB_HANDLER_INT64); - lupb_setfieldi(L, "HANDLER_UINT32", UPB_HANDLER_UINT32); - lupb_setfieldi(L, "HANDLER_UINT64", UPB_HANDLER_UINT64); - lupb_setfieldi(L, "HANDLER_FLOAT", UPB_HANDLER_FLOAT); - lupb_setfieldi(L, "HANDLER_DOUBLE", UPB_HANDLER_DOUBLE); - lupb_setfieldi(L, "HANDLER_BOOL", UPB_HANDLER_BOOL); - lupb_setfieldi(L, "HANDLER_STARTSTR", UPB_HANDLER_STARTSTR); - lupb_setfieldi(L, "HANDLER_STRING", UPB_HANDLER_STRING); - lupb_setfieldi(L, "HANDLER_ENDSTR", UPB_HANDLER_ENDSTR); - lupb_setfieldi(L, "HANDLER_STARTSUBMSG", UPB_HANDLER_STARTSUBMSG); - lupb_setfieldi(L, "HANDLER_ENDSUBMSG", UPB_HANDLER_ENDSUBMSG); - lupb_setfieldi(L, "HANDLER_STARTSEQ", UPB_HANDLER_STARTSEQ); - lupb_setfieldi(L, "HANDLER_ENDSEQ", UPB_HANDLER_ENDSEQ); - - return 1; // Return package table. -} - -// Alternate names so that the library can be loaded as upb5_1 etc. -int LUPB_OPENFUNC(upb)(lua_State *L) { return luaopen_upb(L); } diff --git a/bindings/lua/upb.h b/bindings/lua/upb.h deleted file mode 100644 index e6b4f2f..0000000 --- a/bindings/lua/upb.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - * upb - a minimalist implementation of protocol buffers. - * - * Copyright (c) 2012 Google Inc. See LICENSE for details. - * Author: Josh Haberman - * - * Shared definitions for upb Lua modules. - */ - -#ifndef UPB_LUA_UPB_H_ -#define UPB_LUA_UPB_H_ - -#include "upb/def.h" - -// Lua 5.1/5.2 compatibility code. -#if LUA_VERSION_NUM == 501 - -#define lua_rawlen lua_objlen -#define lupb_newlib(L, name, l) luaL_register(L, name, l) -#define lupb_setfuncs(L, l) luaL_register(L, NULL, l) -#define LUPB_OPENFUNC(mod) luaopen_ ## mod ## upb5_1 - -void *luaL_testudata(lua_State *L, int ud, const char *tname); - -#elif LUA_VERSION_NUM == 502 - -// Lua 5.2 modules are not expected to set a global variable, so "name" is -// unused. -#define lupb_newlib(L, name, l) luaL_newlib(L, l) -#define lupb_setfuncs(L, l) luaL_setfuncs(L, l, 0) -int luaL_typerror(lua_State *L, int narg, const char *tname); -#define LUPB_OPENFUNC(mod) luaopen_ ## mod ## upb5_2 - -#else -#error Only Lua 5.1 and 5.2 are supported -#endif - -const upb_msgdef *lupb_msgdef_check(lua_State *L, int narg); -const upb_enumdef *lupb_enumdef_check(lua_State *L, int narg); -const char *lupb_checkname(lua_State *L, int narg); -bool lupb_def_pushwrapper(lua_State *L, const upb_def *def, const void *owner); -void lupb_def_pushnewrapper(lua_State *L, const upb_def *def, - const void *owner); - -#endif // UPB_LUA_UPB_H_ -- cgit v1.2.3