From e2143674ae20fbadbea004bd54d6f5dc32b83803 Mon Sep 17 00:00:00 2001 From: Thiago de Arruda Date: Sun, 31 Aug 2014 10:46:28 -0300 Subject: deps: Update to the experimental msgpack v5 branch Using msgpack v5 will let nvim be more compatible with msgpack libraries for other platforms. This also replaces "raw" references by "bin" which is the new name for msgpack binary data type --- scripts/msgpack-gen.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'scripts') diff --git a/scripts/msgpack-gen.lua b/scripts/msgpack-gen.lua index 8940cc72f6..43459743e2 100644 --- a/scripts/msgpack-gen.lua +++ b/scripts/msgpack-gen.lua @@ -277,9 +277,9 @@ Object msgpack_rpc_dispatch(uint64_t channel_id, msgpack_object method = req->via.array.ptr[2]; uint64_t method_id = method.via.u64; - if (method.type == MSGPACK_OBJECT_RAW) { + if (method.type == MSGPACK_OBJECT_BIN) { char method_name[]]..(max_fname_len + 1)..[[]; - xstrlcpy(method_name, method.via.raw.ptr, min(method.via.raw.size, ]] ..(max_fname_len)..[[) + 1); + xstrlcpy(method_name, method.via.bin.ptr, min(method.via.bin.size, ]] ..(max_fname_len)..[[) + 1); method_id = map_get(cstr_t, uint64_t)(rpc_method_ids, method_name); if (!method_id) { method_id = UINT64_MAX; -- cgit From c39ae3e4d475c868f8ba76116735501ea97dfae1 Mon Sep 17 00:00:00 2001 From: Thiago de Arruda Date: Wed, 3 Sep 2014 11:46:35 -0300 Subject: map/msgpack-rpc: Declare/define maps rpc method handlers The new map type uses `String` instances as keys to avoid unnecessary copying to zero-terminated buffers. --- scripts/msgpack-gen.lua | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'scripts') diff --git a/scripts/msgpack-gen.lua b/scripts/msgpack-gen.lua index 43459743e2..7967aad232 100644 --- a/scripts/msgpack-gen.lua +++ b/scripts/msgpack-gen.lua @@ -93,6 +93,7 @@ output:write([[ #include "nvim/map.h" #include "nvim/log.h" +#include "nvim/vim.h" #include "nvim/os/msgpack_rpc.h" #include "nvim/os/msgpack_rpc_helpers.h" #include "nvim/api/private/helpers.h" @@ -268,8 +269,6 @@ end output:write('\n}\n\n') output:write([[ -#define min(X, Y) (X < Y ? X : Y) - Object msgpack_rpc_dispatch(uint64_t channel_id, msgpack_object *req, Error *error) -- cgit From 74aff19691aeea83fa23265719668467db2b049c Mon Sep 17 00:00:00 2001 From: Thiago de Arruda Date: Wed, 3 Sep 2014 14:26:16 -0300 Subject: msgpack-rpc: Refactor initializer and dispatcher Use Map(String, rpc_method_handler_fn) for storing/retrieving rpc method handlers in msgpack_rpc_init and msgpack_rpc_dispatch. Also refactor serialization/validation functions in the msgpack_rpc.c/msgpack_rpc_helpers.c modules to accept the new STR and BIN types. --- scripts/msgpack-gen.lua | 46 +++++++++++++++++++++++++--------------------- 1 file changed, 25 insertions(+), 21 deletions(-) (limited to 'scripts') diff --git a/scripts/msgpack-gen.lua b/scripts/msgpack-gen.lua index 7967aad232..f868a67568 100644 --- a/scripts/msgpack-gen.lua +++ b/scripts/msgpack-gen.lua @@ -245,22 +245,24 @@ output:write('\n};\n\n') -- Generate a function that initializes method names with handler functions output:write([[ -static Map(cstr_t, uint64_t) *rpc_method_ids = NULL; +static Map(String, rpc_method_handler_fn) *methods = NULL; void msgpack_rpc_init(void) { - rpc_method_ids = map_new(cstr_t, uint64_t)(); + methods = map_new(String, rpc_method_handler_fn)(); ]]) --- Msgpack strings must be copied to a 0-terminated temporary buffer before --- searching in the map, so we keep track of the maximum method name length in --- order to create the smallest possible buffer for xstrlcpy +-- Keep track of the maximum method name length in order to avoid walking +-- strings longer than that when searching for a method handler local max_fname_len = 0 for i = 1, #api.functions do local fn = api.functions[i] - output:write(' map_put(cstr_t, uint64_t)(rpc_method_ids, "' - ..fn.name..'", '..i..');\n') + output:write(' map_put(String, rpc_method_handler_fn)(methods, '.. + '(String) {.data = "'..fn.name..'", '.. + '.size = sizeof("'..fn.name..'") - 1}, handle_'.. + fn.name..');\n') + if #fn.name > max_fname_len then max_fname_len = #fn.name end @@ -275,22 +277,24 @@ Object msgpack_rpc_dispatch(uint64_t channel_id, { msgpack_object method = req->via.array.ptr[2]; uint64_t method_id = method.via.u64; + rpc_method_handler_fn handler = NULL; - if (method.type == MSGPACK_OBJECT_BIN) { - char method_name[]]..(max_fname_len + 1)..[[]; - xstrlcpy(method_name, method.via.bin.ptr, min(method.via.bin.size, ]] ..(max_fname_len)..[[) + 1); - method_id = map_get(cstr_t, uint64_t)(rpc_method_ids, method_name); - if (!method_id) { - method_id = UINT64_MAX; - } + if (method.type == MSGPACK_OBJECT_BIN || method.type == MSGPACK_OBJECT_STR) { +]]) +output:write(' handler = map_get(String, rpc_method_handler_fn)') +output:write('(methods, (String){.data=(char *)method.via.bin.ptr,') +output:write('.size=min(method.via.bin.size, '..max_fname_len..')});\n') +output:write([[ + } else if (method_id <= ]]..#api.functions..[[) { + handler = rpc_method_handlers[method_id]; } + + if (!handler) { + handler = handle_missing_method; + } + + return handler(channel_id, req, error); +} ]]) -output:write('\n // method_id=0 is specially handled') -output:write('\n assert(method_id > 0);') -output:write('\n'); -output:write('\n rpc_method_handler_fn handler = (method_id <= '..#api.functions..') ?') -output:write('\n rpc_method_handlers[method_id] : handle_missing_method;') -output:write('\n return handler(channel_id, req, error);') -output:write('\n}\n') output:close() -- cgit From 19bc29ee834516ff76944741b25fe158d2282b15 Mon Sep 17 00:00:00 2001 From: Thiago de Arruda Date: Wed, 3 Sep 2014 14:55:55 -0300 Subject: msgpack-rpc: Move handle_missing_method to msgpack_rpc.c Since that function is not automatically generated, it's best to place it in a normal C module --- scripts/msgpack-gen.lua | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) (limited to 'scripts') diff --git a/scripts/msgpack-gen.lua b/scripts/msgpack-gen.lua index f868a67568..946cff1d11 100644 --- a/scripts/msgpack-gen.lua +++ b/scripts/msgpack-gen.lua @@ -220,18 +220,6 @@ for i = 1, #api.functions do end end -output:write([[ -static Object handle_missing_method(uint64_t channel_id, - msgpack_object *req, - Error *error) -{ - snprintf(error->msg, sizeof(error->msg), "Invalid function id"); - error->set = true; - return NIL; -} - -]]) - -- Generate the table of handler functions indexed by method id output:write([[ static const rpc_method_handler_fn rpc_method_handlers[] = { @@ -290,7 +278,7 @@ output:write([[ } if (!handler) { - handler = handle_missing_method; + handler = msgpack_rpc_handle_missing_method; } return handler(channel_id, req, error); -- cgit From cd70b9c0152f79887ed548e6cf8992ae2121fedb Mon Sep 17 00:00:00 2001 From: Thiago de Arruda Date: Wed, 3 Sep 2014 16:22:05 -0300 Subject: msgpack-rpc: Refactor API metadata discovery method A new method is now exposed via msgpack-rpc: "get_api_metadata". This method has the same job as the old method '0', it returns an object with API metadata for use by generators. There's one difference in the return value though: instead of returning a string containing another serialized msgpack document, the metadata object is returned directly(a separate deserialization step by clients is not required). --- scripts/msgpack-gen.lua | 15 +++++++++++++++ 1 file changed, 15 insertions(+) (limited to 'scripts') diff --git a/scripts/msgpack-gen.lua b/scripts/msgpack-gen.lua index 946cff1d11..1516271973 100644 --- a/scripts/msgpack-gen.lua +++ b/scripts/msgpack-gen.lua @@ -123,6 +123,7 @@ end output:write([[ }; const unsigned int msgpack_metadata_size = sizeof(msgpack_metadata); +msgpack_unpacked msgpack_unpacked_metadata; ]]) @@ -237,6 +238,14 @@ static Map(String, rpc_method_handler_fn) *methods = NULL; void msgpack_rpc_init(void) { + msgpack_unpacked_init(&msgpack_unpacked_metadata); + if (msgpack_unpack_next(&msgpack_unpacked_metadata, + (const char *)msgpack_metadata, + msgpack_metadata_size, + NULL) != MSGPACK_UNPACK_SUCCESS) { + abort(); + } + methods = map_new(String, rpc_method_handler_fn)(); ]]) @@ -256,6 +265,12 @@ for i = 1, #api.functions do end end +local metadata_fn = 'get_api_metadata' +output:write(' map_put(String, rpc_method_handler_fn)(methods, '.. + '(String) {.data = "'..metadata_fn..'", '.. + '.size = sizeof("'..metadata_fn..'") - 1}, msgpack_rpc_handle_'.. + metadata_fn..');\n') + output:write('\n}\n\n') output:write([[ -- cgit From d5e3cede28858dfe079b782cfea4bce6ebc268c0 Mon Sep 17 00:00:00 2001 From: Thiago de Arruda Date: Wed, 3 Sep 2014 17:19:55 -0300 Subject: msgpack-rpc: Remove support for integer ids in methods There's no need to have integer and string ids, and since we now fully support msgpack-RPC, support for integer ids was removed. --- scripts/msgpack-gen.lua | 19 +------------------ 1 file changed, 1 insertion(+), 18 deletions(-) (limited to 'scripts') diff --git a/scripts/msgpack-gen.lua b/scripts/msgpack-gen.lua index 1516271973..36fe07896b 100644 --- a/scripts/msgpack-gen.lua +++ b/scripts/msgpack-gen.lua @@ -60,8 +60,7 @@ for i = 1, #arg - 1 do local tmp = grammar:match(input:read('*all')) for i = 1, #tmp do api.functions[#api.functions + 1] = tmp[i] - local fn_id = #api.functions - local fn = api.functions[fn_id] + local fn = tmp[i] if #fn.parameters ~= 0 and fn.parameters[1][2] == 'channel_id' then -- this function should receive the channel id fn.receives_channel_id = true @@ -75,8 +74,6 @@ for i = 1, #arg - 1 do -- for specifying errors fn.parameters[#fn.parameters] = nil end - -- assign a unique integer id for each api function - fn.id = fn_id end input:close() end @@ -221,17 +218,6 @@ for i = 1, #api.functions do end end --- Generate the table of handler functions indexed by method id -output:write([[ -static const rpc_method_handler_fn rpc_method_handlers[] = { - [0] = (rpc_method_handler_fn)NULL]]) - -for i = 1, #api.functions do - local fn = api.functions[i] - output:write(',\n ['..i..'] = handle_'..fn.name..'') -end -output:write('\n};\n\n') - -- Generate a function that initializes method names with handler functions output:write([[ static Map(String, rpc_method_handler_fn) *methods = NULL; @@ -279,7 +265,6 @@ Object msgpack_rpc_dispatch(uint64_t channel_id, Error *error) { msgpack_object method = req->via.array.ptr[2]; - uint64_t method_id = method.via.u64; rpc_method_handler_fn handler = NULL; if (method.type == MSGPACK_OBJECT_BIN || method.type == MSGPACK_OBJECT_STR) { @@ -288,8 +273,6 @@ output:write(' handler = map_get(String, rpc_method_handler_fn)') output:write('(methods, (String){.data=(char *)method.via.bin.ptr,') output:write('.size=min(method.via.bin.size, '..max_fname_len..')});\n') output:write([[ - } else if (method_id <= ]]..#api.functions..[[) { - handler = rpc_method_handlers[method_id]; } if (!handler) { -- cgit From 2f566c83d9eee4a8097c9a18eb58dcef6adf894e Mon Sep 17 00:00:00 2001 From: Thiago de Arruda Date: Sun, 7 Sep 2014 20:40:07 -0300 Subject: api/msgpack-rpc: Parse type information from api/private/defs.h Enhance msgpack-gen.lua to extract custom api type codes from the ObjectType enum in api/private/defs.h. The type information is made available from the api metadata and clients can use to correctly serialize/deserialize these types using msgpack EXT type. --- scripts/msgpack-gen.lua | 25 ++++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) (limited to 'scripts') diff --git a/scripts/msgpack-gen.lua b/scripts/msgpack-gen.lua index 36fe07896b..7da52432d6 100644 --- a/scripts/msgpack-gen.lua +++ b/scripts/msgpack-gen.lua @@ -38,9 +38,28 @@ assert(#arg >= 1) -- api metadata api = { functions = {}, - -- Helpers for object-oriented languages - classes = {'Buffer', 'Window', 'Tabpage'} + types = {} } + +-- Extract type codes from api/private/defs.h. The codes are values between +-- comment markers in the ObjectType enum +local typedefs_header = arg[1] +local input = io.open(typedefs_header, 'rb') +local reading_types = false +while true do + local line = input:read('*l'):gsub("^%s*(.-)%s*$", "%1") + if reading_types then + if line == '// end custom types' then + break + end + local type_name = line:gsub("^kObjectType(.-),$", "%1") + api.types[#api.types + 1] = type_name + else + reading_types = line == '// start custom types' + end +end +input:close() + -- names of all headers relative to the source root(for inclusion in the -- generated file) headers = {} @@ -48,7 +67,7 @@ headers = {} outputf = arg[#arg] -- read each input file, parse and append to the api metadata -for i = 1, #arg - 1 do +for i = 2, #arg - 1 do local full_path = arg[i] local parts = {} for part in string.gmatch(full_path, '[^/]+') do -- cgit From cac24cb06ddcad0cfb3a9379c3bdd0e8706602f9 Mon Sep 17 00:00:00 2001 From: Thiago de Arruda Date: Tue, 9 Sep 2014 09:36:14 -0300 Subject: api/msgpack-rpc: Refactor msgpack_rpc_helpers.{c,h} - Move helpers that are specific to API types to api/private/helpers.{c,h} - Include headers with generated declarations - Delete unused macros --- scripts/msgpack-gen.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'scripts') diff --git a/scripts/msgpack-gen.lua b/scripts/msgpack-gen.lua index 7da52432d6..5ef61267f2 100644 --- a/scripts/msgpack-gen.lua +++ b/scripts/msgpack-gen.lua @@ -158,7 +158,7 @@ for i = 1, #api.functions do for j = 1, #fn.parameters do local param = fn.parameters[j] local converted = 'arg_'..j - output:write('\n '..param[1]..' '..converted..' msgpack_rpc_init_'..string.lower(param[1])..';') + output:write('\n '..param[1]..' '..converted..' api_init_'..string.lower(param[1])..';') end output:write('\n') output:write('\n if (req->via.array.ptr[3].via.array.size != '..#fn.parameters..') {') @@ -228,7 +228,7 @@ for i = 1, #api.functions do for j = 1, #fn.parameters do local param = fn.parameters[j] - output:write('\n msgpack_rpc_free_'..string.lower(param[1])..'(arg_'..j..');') + output:write('\n api_free_'..string.lower(param[1])..'(arg_'..j..');') end if fn.return_type ~= 'void' then output:write('\n return ret;\n}\n\n'); -- cgit From cd2e46c0785d40b9ea15f6d722a3fad54c007b9b Mon Sep 17 00:00:00 2001 From: Thiago de Arruda Date: Thu, 11 Sep 2014 21:56:52 -0300 Subject: api/msgpack-rpc: Refactor metadata object construction Instead of building all metadata from msgpack-gen.lua, we now merge the generated part with manual information(such as types and features). The metadata is accessible through the api method `vim_get_api_info`. This was done to simplify the generator while also increasing flexibility(by being able to add more metadata) --- scripts/msgpack-gen.lua | 78 +++++++++++++++++-------------------------------- 1 file changed, 26 insertions(+), 52 deletions(-) (limited to 'scripts') diff --git a/scripts/msgpack-gen.lua b/scripts/msgpack-gen.lua index 5ef61267f2..8fbf64ebc0 100644 --- a/scripts/msgpack-gen.lua +++ b/scripts/msgpack-gen.lua @@ -35,30 +35,7 @@ grammar = Ct((c_proto + c_comment + c_preproc + ws) ^ 1) -- we need at least 2 arguments since the last one is the output file assert(#arg >= 1) --- api metadata -api = { - functions = {}, - types = {} -} - --- Extract type codes from api/private/defs.h. The codes are values between --- comment markers in the ObjectType enum -local typedefs_header = arg[1] -local input = io.open(typedefs_header, 'rb') -local reading_types = false -while true do - local line = input:read('*l'):gsub("^%s*(.-)%s*$", "%1") - if reading_types then - if line == '// end custom types' then - break - end - local type_name = line:gsub("^kObjectType(.-),$", "%1") - api.types[#api.types + 1] = type_name - else - reading_types = line == '// start custom types' - end -end -input:close() +functions = {} -- names of all headers relative to the source root(for inclusion in the -- generated file) @@ -67,7 +44,7 @@ headers = {} outputf = arg[#arg] -- read each input file, parse and append to the api metadata -for i = 2, #arg - 1 do +for i = 1, #arg - 1 do local full_path = arg[i] local parts = {} for part in string.gmatch(full_path, '[^/]+') do @@ -78,7 +55,7 @@ for i = 2, #arg - 1 do local input = io.open(full_path, 'rb') local tmp = grammar:match(input:read('*all')) for i = 1, #tmp do - api.functions[#api.functions + 1] = tmp[i] + functions[#functions + 1] = tmp[i] local fn = tmp[i] if #fn.parameters ~= 0 and fn.parameters[1][2] == 'channel_id' then -- this function should receive the channel id @@ -124,12 +101,12 @@ end output:write([[ -const uint8_t msgpack_metadata[] = { +static const uint8_t msgpack_metadata[] = { ]]) -- serialize the API metadata using msgpack and embed into the resulting -- binary for easy querying by clients -packed = msgpack.pack(api) +packed = msgpack.pack(functions) for i = 1, #packed do output:write(string.byte(packed, i)..', ') if i % 10 == 0 then @@ -138,17 +115,28 @@ for i = 1, #packed do end output:write([[ }; -const unsigned int msgpack_metadata_size = sizeof(msgpack_metadata); -msgpack_unpacked msgpack_unpacked_metadata; + +void msgpack_rpc_init_function_metadata(Dictionary *metadata) +{ + msgpack_unpacked unpacked; + msgpack_unpacked_init(&unpacked); + assert(msgpack_unpack_next(&unpacked, + (const char *)msgpack_metadata, + sizeof(msgpack_metadata), + NULL) == MSGPACK_UNPACK_SUCCESS); + Object functions; + msgpack_rpc_to_object(&unpacked.data, &functions); + msgpack_unpacked_destroy(&unpacked); + PUT(*metadata, "functions", functions); +} ]]) --- start the handler functions. First handler (method_id=0) is reserved for --- querying the metadata, usually it is the first function called by clients. --- Visit each function metadata to build the handler function with code --- generated for validating arguments and calling to the real API. -for i = 1, #api.functions do - local fn = api.functions[i] +-- start the handler functions. Visit each function metadata to build the +-- handler function with code generated for validating arguments and calling to +-- the real API. +for i = 1, #functions do + local fn = functions[i] local args = {} output:write('static Object handle_'..fn.name..'(uint64_t channel_id, msgpack_object *req, Error *error)') @@ -243,14 +231,6 @@ static Map(String, rpc_method_handler_fn) *methods = NULL; void msgpack_rpc_init(void) { - msgpack_unpacked_init(&msgpack_unpacked_metadata); - if (msgpack_unpack_next(&msgpack_unpacked_metadata, - (const char *)msgpack_metadata, - msgpack_metadata_size, - NULL) != MSGPACK_UNPACK_SUCCESS) { - abort(); - } - methods = map_new(String, rpc_method_handler_fn)(); ]]) @@ -258,8 +238,8 @@ void msgpack_rpc_init(void) -- Keep track of the maximum method name length in order to avoid walking -- strings longer than that when searching for a method handler local max_fname_len = 0 -for i = 1, #api.functions do - local fn = api.functions[i] +for i = 1, #functions do + local fn = functions[i] output:write(' map_put(String, rpc_method_handler_fn)(methods, '.. '(String) {.data = "'..fn.name..'", '.. '.size = sizeof("'..fn.name..'") - 1}, handle_'.. @@ -270,12 +250,6 @@ for i = 1, #api.functions do end end -local metadata_fn = 'get_api_metadata' -output:write(' map_put(String, rpc_method_handler_fn)(methods, '.. - '(String) {.data = "'..metadata_fn..'", '.. - '.size = sizeof("'..metadata_fn..'") - 1}, msgpack_rpc_handle_'.. - metadata_fn..');\n') - output:write('\n}\n\n') output:write([[ -- cgit From 545acf2024ea2653ae6937d570a37aa0340caa5e Mon Sep 17 00:00:00 2001 From: Thiago de Arruda Date: Fri, 12 Sep 2014 11:24:01 -0300 Subject: api metadata: Allow typed container information in api functions Adapt gendeclarations.lua/msgpack-gen.lua to allow the `ArrayOf(...)` and `DictionaryOf(...)` types in function headers. These are simple macros that expand to Array and Dictionary respectively, but the information is kept in the metadata object, which is useful for building clients in statically typed languages. --- scripts/gendeclarations.lua | 15 +++++++++++---- scripts/msgpack-gen.lua | 28 +++++++++++++++++++++++----- 2 files changed, 34 insertions(+), 9 deletions(-) (limited to 'scripts') diff --git a/scripts/gendeclarations.lua b/scripts/gendeclarations.lua index 76711cc214..bc55b48a0a 100755 --- a/scripts/gendeclarations.lua +++ b/scripts/gendeclarations.lua @@ -59,9 +59,16 @@ local right_word = concat( raw_word, neg_look_ahead(aw) ) -local word = concat( - neg_look_behind(aw), - right_word +local word = branch( + concat( + branch(lit('ArrayOf('), lit('DictionaryOf(')), -- typed container macro + one_or_more(any_character - lit(')')), + lit(')') + ), + concat( + neg_look_behind(aw), + right_word + ) ) local spaces = any_amount(branch( s, @@ -204,7 +211,7 @@ while init ~= nil do declaration = declaration:gsub('\n', ' ') declaration = declaration:gsub('%s+', ' ') declaration = declaration:gsub(' ?%( ?', '(') - declaration = declaration:gsub(' ?%) ?', ')') + -- declaration = declaration:gsub(' ?%) ?', ')') declaration = declaration:gsub(' ?, ?', ', ') declaration = declaration:gsub(' ?(%*+) ?', ' %1') declaration = declaration:gsub(' ?(FUNC_ATTR_)', ' %1') diff --git a/scripts/msgpack-gen.lua b/scripts/msgpack-gen.lua index 8fbf64ebc0..68faa18c31 100644 --- a/scripts/msgpack-gen.lua +++ b/scripts/msgpack-gen.lua @@ -16,7 +16,12 @@ ws = S(' \t') + nl fill = ws ^ 0 c_comment = P('//') * (not_nl ^ 0) c_preproc = P('#') * (not_nl ^ 0) -c_id = letter * (alpha ^ 0) +typed_container = + (P('ArrayOf(') + P('DictionaryOf(')) * ((any - P(')')) ^ 1) * P(')') +c_id = ( + typed_container + + (letter * (alpha ^ 0)) +) c_void = P('void') c_param_type = ( ((P('Error') * fill * P('*') * fill) * Cc('error')) + @@ -90,6 +95,7 @@ output:write([[ #include "nvim/os/msgpack_rpc.h" #include "nvim/os/msgpack_rpc_helpers.h" #include "nvim/api/private/helpers.h" +#include "nvim/api/private/defs.h" ]]) for i = 1, #headers do @@ -132,6 +138,18 @@ void msgpack_rpc_init_function_metadata(Dictionary *metadata) ]]) +local function real_type(type) + local rv = type + if typed_container:match(rv) then + if rv:match('Array') then + rv = 'Array' + else + rv = 'Dictionary' + end + end + return rv +end + -- start the handler functions. Visit each function metadata to build the -- handler function with code generated for validating arguments and calling to -- the real API. @@ -146,7 +164,7 @@ for i = 1, #functions do for j = 1, #fn.parameters do local param = fn.parameters[j] local converted = 'arg_'..j - output:write('\n '..param[1]..' '..converted..' api_init_'..string.lower(param[1])..';') + output:write('\n '..param[1]..' '..converted..' api_init_'..string.lower(real_type(param[1]))..';') end output:write('\n') output:write('\n if (req->via.array.ptr[3].via.array.size != '..#fn.parameters..') {') @@ -161,7 +179,7 @@ for i = 1, #functions do param = fn.parameters[j] arg = '(req->via.array.ptr[3].via.array.ptr + '..(j - 1)..')' converted = 'arg_'..j - convert_arg = 'msgpack_rpc_to_'..string.lower(param[1]) + convert_arg = 'msgpack_rpc_to_'..real_type(param[1]):lower() output:write('\n if (!'..convert_arg..'('..arg..', &'..converted..')) {') output:write('\n snprintf(error->msg, sizeof(error->msg), "Wrong type for argument '..j..', expecting '..param[1]..'");') output:write('\n error->set = true;') @@ -208,7 +226,7 @@ for i = 1, #functions do end if fn.return_type ~= 'void' then - output:write('\n Object ret = '..string.upper(fn.return_type)..'_OBJ(rv);') + output:write('\n Object ret = '..string.upper(real_type(fn.return_type))..'_OBJ(rv);') end -- Now generate the cleanup label for freeing memory allocated for the -- arguments @@ -216,7 +234,7 @@ for i = 1, #functions do for j = 1, #fn.parameters do local param = fn.parameters[j] - output:write('\n api_free_'..string.lower(param[1])..'(arg_'..j..');') + output:write('\n api_free_'..string.lower(real_type(param[1]))..'(arg_'..j..');') end if fn.return_type ~= 'void' then output:write('\n return ret;\n}\n\n'); -- cgit