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