From: Vladislav Shpilevoy <v.shpilevoy@tarantool.org> To: tarantool-patches@freelists.org Cc: vdavydov.dev@gmail.com Subject: [PATCH v2 02/10] yaml: introduce yaml.encode_tagged Date: Fri, 20 Apr 2018 16:24:27 +0300 [thread overview] Message-ID: <7c30b9483a38bd36425d7e0c87b4d15e8893446e.1524228894.git.v.shpilevoy@tarantool.org> (raw) In-Reply-To: <cover.1524228894.git.v.shpilevoy@tarantool.org> In-Reply-To: <cover.1524228894.git.v.shpilevoy@tarantool.org> Encode_tagged allows to define one global YAML tag for a document. Tagged YAML documents are going to be used for console text pushes to distinguish actual box.session.push() from console.print(). The first will have tag !push, and the second - !print. --- test/app-tap/yaml.test.lua | 23 ++++++++++++++- third_party/lua-yaml/lyaml.cc | 69 +++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 88 insertions(+), 4 deletions(-) diff --git a/test/app-tap/yaml.test.lua b/test/app-tap/yaml.test.lua index def278570..b81402cc0 100755 --- a/test/app-tap/yaml.test.lua +++ b/test/app-tap/yaml.test.lua @@ -69,9 +69,29 @@ local function test_output(test, s) "--- |-\n Tutorial -- Header\n ====\n\n Text\n...\n", "tutorial string"); end +local function test_tagged(test, s) + test:plan(7) + local must_be_err = 'Usage: encode_tagged({prefix = <string>, handle = <string>}, object)' + local prefix = 'tag:tarantool.io/push,2018' + local ok, err = pcall(s.encode_tagged) + test:is(err, must_be_err, "encode_tagged usage") + ok, err = pcall(s.encode_tagged, {}, 100) + test:is(err, must_be_err, "encode_tagged usage") + ok, err = pcall(s.encode_tagged, {handle = true, prefix = 100}, 200) + test:is(err, must_be_err, "encode_tagged usage") + local ret + ret, err = s.encode_tagged({handle = '!push', prefix = prefix}, 300) + test:is(ret, nil, 'non-usage and non-oom errors do not raise') + test:is(err, "tag handle must end with '!'", "encode_tagged usage") + ret = s.encode_tagged({handle = '!push!', prefix = prefix}, 300) + test:is(ret, "%TAG !push! "..prefix.."\n--- 300\n...\n", "encode_tagged usage") + ret = s.encode_tagged({handle = '!print!', prefix = prefix}, {a = 100, b = 200}) + test:is(ret, "%TAG !print! tag:tarantool.io/push,2018\n---\na: 100\nb: 200\n...\n", 'encode_tagged usage') +end + tap.test("yaml", function(test) local serializer = require('yaml') - test:plan(10) + test:plan(11) test:test("unsigned", common.test_unsigned, serializer) test:test("signed", common.test_signed, serializer) test:test("double", common.test_double, serializer) @@ -82,4 +102,5 @@ tap.test("yaml", function(test) test:test("ucdata", common.test_ucdata, serializer) test:test("compact", test_compact, serializer) test:test("output", test_output, serializer) + test:test("tagged", test_tagged, serializer) end) diff --git a/third_party/lua-yaml/lyaml.cc b/third_party/lua-yaml/lyaml.cc index 430f4be2c..8329f84e9 100644 --- a/third_party/lua-yaml/lyaml.cc +++ b/third_party/lua-yaml/lyaml.cc @@ -78,6 +78,8 @@ struct lua_yaml_dumper { unsigned int anchor_number; yaml_emitter_t emitter; char error; + yaml_tag_directive_t begin_tag; + yaml_tag_directive_t *end_tag; lua_State *outputL; luaL_Buffer yamlbuf; @@ -571,7 +573,8 @@ static int dump_node(struct lua_yaml_dumper *dumper) static void dump_document(struct lua_yaml_dumper *dumper) { yaml_event_t ev; - if (!yaml_document_start_event_initialize(&ev, NULL, NULL, NULL, 0) || + if (!yaml_document_start_event_initialize(&ev, NULL, &dumper->begin_tag, + dumper->end_tag, 0) || !yaml_emitter_emit(&dumper->emitter, &ev)) return; @@ -618,13 +621,38 @@ static void find_references(struct lua_yaml_dumper *dumper) { } } -static int l_dump(lua_State *L) { +/** + * Encode a Lua object or objects into YAML documents onto Lua + * stack. + * @param L Lua stack to get arguments and push result. + * @param serializer Lua YAML serializer. + * @param tag_handle NULL, or a global tag handle. Handle becomes + * a synonym for prefix. + * @param tag_prefix NULL, or a global tag prefix, to which @a + * handle is expanded. + * @retval nil, error Error. + * @retval not nil Lua string with dumped object. + */ +static int +lua_yaml_encode_impl(lua_State *L, struct luaL_serializer *serializer, + const char *tag_handle, const char *tag_prefix) +{ struct lua_yaml_dumper dumper; int i, argcount = lua_gettop(L); yaml_event_t ev; dumper.L = L; - dumper.cfg = luaL_checkserializer(L); + dumper.begin_tag.handle = (yaml_char_t *) tag_handle; + dumper.begin_tag.prefix = (yaml_char_t *) tag_prefix; + /* + * If a tag is specified, then tag list is not empty and + * consists of a single tag. + */ + if (tag_handle != NULL && tag_prefix != NULL) + dumper.end_tag = &dumper.begin_tag + 1; + else + dumper.end_tag = &dumper.begin_tag; + dumper.cfg = serializer; dumper.error = 0; /* create thread to use for YAML buffer */ dumper.outputL = lua_newthread(L); @@ -684,11 +712,46 @@ error: } } +static int l_dump(lua_State *L) { + return lua_yaml_encode_impl(L, luaL_checkserializer(L), NULL, NULL); +} + +/** + * Dump a Lua object into YAML string with a global TAG specified. + * @param options First argument on a stack, consists of two + * options: tag prefix and tag handle. + * @param object Lua object to dump under the global tag. + * @retval Lua string with dumped object. + */ +static int l_dump_tagged(lua_State *L) +{ + struct luaL_serializer *serializer = luaL_checkserializer(L); + int argcount = lua_gettop(L); + if (argcount != 2 || !lua_istable(L, 1)) { +usage_error: + return luaL_error(L, "Usage: encode_tagged({prefix = <string>, "\ + "handle = <string>}, object)"); + } + lua_getfield(L, 1, "prefix"); + if (! lua_isstring(L, -1)) + goto usage_error; + const char *prefix = lua_tostring(L, -1); + lua_getfield(L, 1, "handle"); + if (! lua_isstring(L, -1)) + goto usage_error; + const char *handle = lua_tostring(L, -1); + lua_pop(L, 2); + lua_replace(L, 1); + lua_settop(L, 1); + return lua_yaml_encode_impl(L, serializer, handle, prefix); +} + static int l_new(lua_State *L); static const luaL_Reg yamllib[] = { { "encode", l_dump }, + { "encode_tagged", l_dump_tagged }, { "decode", l_load }, { "new", l_new }, { NULL, NULL} -- 2.15.1 (Apple Git-101)
next prev parent reply other threads:[~2018-04-20 13:24 UTC|newest] Thread overview: 34+ messages / expand[flat|nested] mbox.gz Atom feed top 2018-04-20 13:24 [PATCH v2 00/10] session: introduce box.session.push Vladislav Shpilevoy 2018-04-20 13:24 ` [PATCH v2 01/10] yaml: don't throw OOM on any error in yaml encoding Vladislav Shpilevoy 2018-05-10 18:10 ` [tarantool-patches] " Konstantin Osipov 2018-04-20 13:24 ` [tarantool-patches] [PATCH v2 10/10] session: introduce binary box.session.push Vladislav Shpilevoy 2018-05-10 19:50 ` Konstantin Osipov 2018-05-24 20:50 ` [tarantool-patches] " Vladislav Shpilevoy 2018-04-20 13:24 ` Vladislav Shpilevoy [this message] 2018-05-10 18:22 ` [tarantool-patches] [PATCH v2 02/10] yaml: introduce yaml.encode_tagged Konstantin Osipov 2018-05-24 20:50 ` [tarantool-patches] " Vladislav Shpilevoy 2018-05-30 19:15 ` Konstantin Osipov 2018-05-30 20:49 ` Vladislav Shpilevoy 2018-05-31 10:46 ` Konstantin Osipov 2018-04-20 13:24 ` [PATCH v2 03/10] yaml: introduce yaml.decode_tag Vladislav Shpilevoy 2018-05-10 18:41 ` [tarantool-patches] " Konstantin Osipov 2018-05-24 20:50 ` [tarantool-patches] " Vladislav Shpilevoy 2018-05-31 10:54 ` Konstantin Osipov 2018-05-31 11:36 ` Konstantin Osipov 2018-04-20 13:24 ` [PATCH v2 04/10] console: use Lua C API to do formatting for console Vladislav Shpilevoy 2018-05-10 18:46 ` [tarantool-patches] " Konstantin Osipov 2018-05-24 20:50 ` [tarantool-patches] " Vladislav Shpilevoy 2018-04-20 13:24 ` [PATCH v2 05/10] session: move salt into iproto connection Vladislav Shpilevoy 2018-05-10 18:47 ` [tarantool-patches] " Konstantin Osipov 2018-04-20 13:24 ` [PATCH v2 06/10] session: introduce session vtab and meta Vladislav Shpilevoy 2018-05-10 19:20 ` [tarantool-patches] " Konstantin Osipov 2018-05-24 20:50 ` [tarantool-patches] " Vladislav Shpilevoy 2018-04-20 13:24 ` [PATCH v2 07/10] port: rename dump() into dump_msgpack() Vladislav Shpilevoy 2018-05-10 19:21 ` [tarantool-patches] " Konstantin Osipov 2018-04-20 13:24 ` [PATCH v2 08/10] session: introduce text box.session.push Vladislav Shpilevoy 2018-05-10 19:27 ` [tarantool-patches] " Konstantin Osipov 2018-05-24 20:50 ` [tarantool-patches] " Vladislav Shpilevoy 2018-04-20 13:24 ` [PATCH v2 09/10] session: enable box.session.push in local console Vladislav Shpilevoy 2018-05-10 19:28 ` [tarantool-patches] " Konstantin Osipov 2018-05-24 20:50 ` [tarantool-patches] [PATCH 1/1] netbox: introduce iterable future objects Vladislav Shpilevoy 2018-06-04 22:17 ` [tarantool-patches] " Vladislav Shpilevoy
Reply instructions: You may reply publicly to this message via plain-text email using any one of the following methods: * Save the following mbox file, import it into your mail client, and reply-to-all from there: mbox Avoid top-posting and favor interleaved quoting: https://en.wikipedia.org/wiki/Posting_style#Interleaved_style * Reply using the --to, --cc, and --in-reply-to switches of git-send-email(1): git send-email \ --in-reply-to=7c30b9483a38bd36425d7e0c87b4d15e8893446e.1524228894.git.v.shpilevoy@tarantool.org \ --to=v.shpilevoy@tarantool.org \ --cc=tarantool-patches@freelists.org \ --cc=vdavydov.dev@gmail.com \ --subject='Re: [PATCH v2 02/10] yaml: introduce yaml.encode_tagged' \ /path/to/YOUR_REPLY https://kernel.org/pub/software/scm/git/docs/git-send-email.html * If your mail client supports setting the In-Reply-To header via mailto: links, try the mailto: link
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox