summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGeorge Sedov <radist.morse@gmail.com>2015-11-27 13:56:54 +0300
committerVictor Toso <me@victortoso.com>2016-01-30 11:09:03 +0100
commit2bfcff90d589d4335105a6423616c7de61cf4c71 (patch)
treec1d19bd91df060f6f95ab9c321aff9421e76c62b
parent66abb77948744d09722c503c029b4c458beb19d0 (diff)
lua-factory: change grl.get_options() into the static table
It's part of the work aimed at removing the OperationSpec from the global scope. grl_l_operation_get_keys was replced by push_operation_requested_keys grl_l_operation_get_options was split and replaced by push_operation_type_filter push_operation_range_filters push_operation_filters grl_lua_library_push_grl_options https://bugzilla.gnome.org/show_bug.cgi?id=753141 Acked-by: Victor Toso <me@victortoso.com>
-rw-r--r--src/lua-factory/grl-lua-common.h5
-rw-r--r--src/lua-factory/grl-lua-factory.c27
-rw-r--r--src/lua-factory/grl-lua-library.c527
3 files changed, 340 insertions, 219 deletions
diff --git a/src/lua-factory/grl-lua-common.h b/src/lua-factory/grl-lua-common.h
index 9c6f901..79f8fd3 100644
--- a/src/lua-factory/grl-lua-common.h
+++ b/src/lua-factory/grl-lua-common.h
@@ -68,14 +68,11 @@ typedef enum {
typedef struct _OperationSpec {
GrlSource *source;
guint operation_id;
- GrlOperationOptions *options;
- GList *keys;
LuaOperationType op_type;
union {
GrlSourceResultCb result;
GrlSourceResolveCb resolve;
} cb;
- char *string;
GrlMedia *media;
gpointer user_data;
guint error_code;
@@ -93,4 +90,6 @@ OperationSpec * grl_lua_library_get_current_operation (lua_State *L);
void grl_lua_library_save_goa_data (lua_State *L, gpointer goa_object);
gpointer grl_lua_library_load_goa_data (lua_State *L);
+void grl_lua_library_push_grl_options (lua_State *L, guint operation_id, GrlOperationOptions *options, GList *keys);
+
#endif /* _GRL_LUA_LIBRARY_COMMON_H_ */
diff --git a/src/lua-factory/grl-lua-factory.c b/src/lua-factory/grl-lua-factory.c
index 1f93d75..8954671 100644
--- a/src/lua-factory/grl-lua-factory.c
+++ b/src/lua-factory/grl-lua-factory.c
@@ -1495,10 +1495,7 @@ grl_lua_factory_source_search (GrlSource *source,
os->operation_id = ss->operation_id;
os->cb.result = ss->callback;
os->user_data = ss->user_data;
- os->string = g_strdup (text);
os->error_code = GRL_CORE_ERROR_SEARCH_FAILED;
- os->keys = g_list_copy (ss->keys);
- os->options = grl_operation_options_copy (ss->options);
os->op_type = LUA_SEARCH;
grl_lua_library_save_operation_data (L, os);
@@ -1506,7 +1503,9 @@ grl_lua_factory_source_search (GrlSource *source,
lua_getglobal (L, LUA_SOURCE_OPERATION[LUA_SEARCH]);
lua_pushstring (L, text);
- if (lua_pcall (L, 1, 0, 0)) {
+ grl_lua_library_push_grl_options (L, ss->operation_id, ss->options, ss->keys);
+
+ if (lua_pcall (L, 2, 0, 0)) {
GRL_WARNING ("%s '%s'", "calling search function fail:",
lua_tolstring (L, -1, NULL));
lua_pop (L, 1);
@@ -1534,10 +1533,7 @@ grl_lua_factory_source_browse (GrlSource *source,
os->media = bs->container;
os->cb.result = bs->callback;
os->user_data = bs->user_data;
- os->string = g_strdup (media_id);
os->error_code = GRL_CORE_ERROR_BROWSE_FAILED;
- os->keys = g_list_copy (bs->keys);
- os->options = grl_operation_options_copy (bs->options);
os->op_type = LUA_BROWSE;
grl_lua_library_save_operation_data (L, os);
@@ -1545,7 +1541,9 @@ grl_lua_factory_source_browse (GrlSource *source,
lua_getglobal (L, LUA_SOURCE_OPERATION[LUA_BROWSE]);
lua_pushstring (L, media_id);
- if (lua_pcall (L, 1, 0, 0)) {
+ grl_lua_library_push_grl_options (L, bs->operation_id, bs->options, bs->keys);
+
+ if (lua_pcall (L, 2, 0, 0)) {
GRL_WARNING ("%s '%s'", "calling browse function fail:",
lua_tolstring (L, -1, NULL));
lua_pop (L, 1);
@@ -1572,10 +1570,7 @@ grl_lua_factory_source_query (GrlSource *source,
os->operation_id = qs->operation_id;
os->cb.result = qs->callback;
os->user_data = qs->user_data;
- os->string = g_strdup (query);
os->error_code = GRL_CORE_ERROR_QUERY_FAILED;
- os->keys = g_list_copy (qs->keys);
- os->options = grl_operation_options_copy (qs->options);
os->op_type = LUA_QUERY;
grl_lua_library_save_operation_data (L, os);
@@ -1583,7 +1578,9 @@ grl_lua_factory_source_query (GrlSource *source,
lua_getglobal (L, LUA_SOURCE_OPERATION[LUA_QUERY]);
lua_pushstring (L, query);
- if (lua_pcall (L, 1, 0, 0)) {
+ grl_lua_library_push_grl_options (L, qs->operation_id, qs->options, qs->keys);
+
+ if (lua_pcall (L, 2, 0, 0)) {
GRL_WARNING ("%s '%s'", "calling query function fail:",
lua_tolstring (L, -1, NULL));
lua_pop (L, 1);
@@ -1611,15 +1608,15 @@ grl_lua_factory_source_resolve (GrlSource *source,
os->media = rs->media;
os->user_data = rs->user_data;
os->error_code = GRL_CORE_ERROR_RESOLVE_FAILED;
- os->keys = g_list_copy (rs->keys);
- os->options = grl_operation_options_copy (rs->options);
os->op_type = LUA_RESOLVE;
grl_lua_library_save_operation_data (L, os);
grl_lua_library_set_current_operation (L, os->operation_id);
lua_getglobal (L, LUA_SOURCE_OPERATION[LUA_RESOLVE]);
- if (lua_pcall (L, 0, 0, 0)) {
+ grl_lua_library_push_grl_options (L, rs->operation_id, rs->options, rs->keys);
+
+ if (lua_pcall (L, 1, 0, 0)) {
GRL_WARNING ("%s '%s'", "calling resolve function fail:",
lua_tolstring (L, -1, NULL));
lua_pop (L, 1);
diff --git a/src/lua-factory/grl-lua-library.c b/src/lua-factory/grl-lua-library.c
index ec53faf..84ec452 100644
--- a/src/lua-factory/grl-lua-library.c
+++ b/src/lua-factory/grl-lua-library.c
@@ -722,202 +722,6 @@ net_wc_new_with_options(lua_State *L,
/* ================== Lua-Library methods ================================== */
-/**
-* grl.get_options
-*
-* @option: (string) Name of the option you want (e.g. count, flags).
-* @key: (string) Name of the key when option request it.
-* @return: The option or nil if none;
-*/
-static gint
-grl_l_operation_get_options (lua_State *L)
-{
- OperationSpec *os;
- const gchar *option;
-
- luaL_argcheck (L, lua_isstring (L, 1), 1, "expecting option (string)");
-
- os = grl_lua_library_get_current_operation (L);
- g_return_val_if_fail (os != NULL, 0);
- option = lua_tostring (L, 1);
-
- if (g_strcmp0 (option, "type") == 0) {
- const char *type;
- switch (os->op_type) {
- case LUA_SEARCH:
- type = "search";
- break;
- case LUA_BROWSE:
- type = "browse";
- break;
- case LUA_QUERY:
- type = "query";
- break;
- case LUA_RESOLVE:
- type = "resolve";
- break;
- default:
- g_assert_not_reached ();
- }
-
- lua_pushstring (L, type);
- return 1;
- }
-
- if (g_strcmp0 (option, "count") == 0) {
- gint count = grl_operation_options_get_count (os->options);
-
- lua_pushinteger (L, count);
- return 1;
- }
-
- if (g_strcmp0 (option, "skip") == 0) {
- guint skip = grl_operation_options_get_skip (os->options);
-
- lua_pushinteger (L, skip);
- return 1;
- }
-
- if (g_strcmp0 (option, "flags") == 0) {
- GrlResolutionFlags flags = grl_operation_options_get_resolution_flags (os->options);
-
- lua_pushinteger (L, (gint) flags);
- return 1;
- }
-
- if (g_strcmp0 (option, "key-filter") == 0) {
- GrlKeyID key;
- GValue *value = NULL;
- const gchar *key_name = NULL;
- GrlRegistry *registry = grl_registry_get_default ();
-
- luaL_argcheck (L, lua_isstring (L, 2), 2, "expecting key name");
- key_name = lua_tostring (L, 2);
-
- key = grl_registry_lookup_metadata_key (registry, key_name);
- value = grl_operation_options_get_key_filter (os->options, key);
- switch (grl_registry_lookup_metadata_key_type (registry, key)) {
- case G_TYPE_INT:
- (value) ? (void) lua_pushinteger (L, g_value_get_int (value)) : lua_pushnil (L);
- break;
-
- case G_TYPE_FLOAT:
- (value) ? (void) lua_pushnumber (L, g_value_get_float (value)) : lua_pushnil (L);
- break;
-
- case G_TYPE_STRING:
- (value) ? (void) lua_pushstring (L, g_value_get_string (value)) : lua_pushnil (L);
- break;
-
- case G_TYPE_BOOLEAN:
- (value) ? (void) lua_pushboolean (L, g_value_get_boolean (value)) : lua_pushnil (L);
- break;
-
- default:
- GRL_DEBUG ("'%s' is being ignored as G_TYPE is not being handled.",
- key_name);
- }
- return 1;
- }
-
- if (g_strcmp0 (option, "range-filter") == 0) {
- GValue *min = NULL;
- GValue *max = NULL;
- GrlKeyID key;
- const gchar *key_name = NULL;
- GrlRegistry *registry = grl_registry_get_default ();
-
- luaL_argcheck (L, lua_isstring (L, 2), 2, "expecting key name");
- key_name = lua_tostring (L, 2);
-
- key = grl_registry_lookup_metadata_key (registry, key_name);
- if (key != GRL_METADATA_KEY_INVALID) {
- grl_operation_options_get_key_range_filter (os->options, key, &min, &max);
- switch (grl_registry_lookup_metadata_key_type (registry, key)) {
- case G_TYPE_INT:
- (min) ? (void) lua_pushinteger (L, g_value_get_int (min)) : lua_pushnil (L);
- (max) ? (void) lua_pushinteger (L, g_value_get_int (max)) : lua_pushnil (L);
- break;
-
- case G_TYPE_FLOAT:
- (min) ? (void) lua_pushnumber (L, g_value_get_float (min)) : lua_pushnil (L);
- (max) ? (void) lua_pushnumber (L, g_value_get_float (max)) : lua_pushnil (L);
- break;
-
- case G_TYPE_STRING:
- (min) ? (void) lua_pushstring (L, g_value_get_string (min)) : lua_pushnil (L);
- (max) ? (void) lua_pushstring (L, g_value_get_string (max)) : lua_pushnil (L);
- break;
-
- default:
- GRL_DEBUG ("'%s' is being ignored as G_TYPE is not being handled.",
- key_name);
- }
- }
- return 2;
- }
-
- if (g_strcmp0 (option, "operation-id") == 0) {
- lua_pushinteger (L, (gint) os->operation_id);
- return 1;
- }
-
- if (g_strcmp0 (option, "media-id") == 0 &&
- os->op_type == LUA_BROWSE) {
- lua_pushstring (L, os->string);
- return 1;
- }
-
- if (g_strcmp0 (option, "query") == 0 &&
- os->op_type == LUA_QUERY) {
- lua_pushstring (L, os->string);
- return 1;
- }
-
- if (g_strcmp0 (option, "search") == 0 &&
- os->op_type == LUA_SEARCH) {
- lua_pushstring (L, os->string);
- return 1;
- }
-
- luaL_error (L, "'%s' is not available nor implemented.", option);
- return 0;
-}
-
-/**
-* grl.get_media_keys
-*
-* @return: array of all requested keys from application (may be empty);
-*/
-static gint
-grl_l_operation_get_keys (lua_State *L)
-{
- OperationSpec *os;
- GrlRegistry *registry;
- GList *it;
- gint i = 0;
-
- os = grl_lua_library_get_current_operation (L);
- g_return_val_if_fail (os != NULL, 0);
-
- registry = grl_registry_get_default ();
- lua_newtable (L);
- for (it = os->keys; it; it = g_list_next (it)) {
- GrlKeyID key_id;
- const gchar *key_name;
-
- key_id = GRLPOINTER_TO_KEYID (it->data);
- key_name = grl_registry_lookup_metadata_key_name (registry, key_id);
- if (key_id != GRL_METADATA_KEY_INVALID) {
- lua_pushinteger (L, i + 1);
- lua_pushstring (L, key_name);
- lua_settable (L, -3);
- i++;
- }
- }
- return 1;
-}
-
static gboolean
push_grl_media_key (lua_State *L,
GrlMedia *media,
@@ -1182,12 +986,9 @@ grl_l_callback (lua_State *L)
/* Free Operation Spec */
if (count == 0) {
- g_list_free (os->keys);
- g_object_unref (os->options);
os->callback_done = TRUE;
grl_lua_library_remove_operation_data (L, os->operation_id);
grl_lua_library_set_current_operation (L, 0);
- g_free (os->string);
g_slice_free (OperationSpec, os);
}
@@ -1528,8 +1329,6 @@ gint
luaopen_grilo (lua_State *L)
{
static const luaL_Reg library_fn[] = {
- {"get_options", &grl_l_operation_get_options},
- {"get_requested_keys", &grl_l_operation_get_keys},
{"get_media_keys", &grl_l_media_get_keys},
{"callback", &grl_l_callback},
{"fetch", &grl_l_fetch},
@@ -1772,3 +1571,329 @@ grl_lua_library_load_goa_data (lua_State *L)
return NULL;
#endif /* GOA_ENABLED */
}
+
+/**
+ * push_operation_requested_keys
+ *
+ * Pushes the table representing the list of requested
+ * keys for the current operation on top of the lua stack.
+ *
+ * @L: LuaState where the data is stored.
+ * @keys: The requested keys of the current operation.
+ * @return: Nothing.
+ */
+static void
+push_operation_requested_keys (lua_State *L,
+ GList *keys)
+{
+ GrlRegistry *registry = grl_registry_get_default ();
+ GList *it;
+ gint i = 1;
+
+ lua_newtable (L);
+ for (it = keys; it != NULL; it = it->next) {
+ GrlKeyID key_id;
+ const gchar *key_name;
+
+ key_id = GRLPOINTER_TO_KEYID (it->data);
+ if (key_id == GRL_METADATA_KEY_INVALID)
+ continue;
+
+ key_name = grl_registry_lookup_metadata_key_name (registry, key_id);
+ lua_pushinteger (L, i);
+ lua_pushstring (L, key_name);
+ lua_settable (L, -3);
+ i++;
+ }
+}
+
+/**
+ * push_operation_type_filter
+ *
+ * Pushes the type filter table into the filters table. The
+ * filters table should already be on top of the lua stack.
+ *
+ * @L: LuaState where the data is stored.
+ * @options: The GrlOperationOptions from which to retrieve filter.
+ * @return: Nothing.
+ */
+static void
+push_operation_type_filter (lua_State *L,
+ GrlOperationOptions *options)
+{
+ GrlTypeFilter type_filter;
+
+ g_assert (lua_istable (L, -1));
+
+ type_filter = grl_operation_options_get_type_filter (options);
+
+ lua_pushstring (L, "types");
+ lua_newtable (L);
+
+ lua_pushstring (L, "audio");
+ lua_pushboolean (L, (type_filter & GRL_TYPE_FILTER_AUDIO));
+ lua_settable (L, -3);
+ lua_pushstring (L, "video");
+ lua_pushboolean (L, (type_filter & GRL_TYPE_FILTER_VIDEO));
+ lua_settable (L, -3);
+ lua_pushstring (L, "image");
+ lua_pushboolean (L, (type_filter & GRL_TYPE_FILTER_IMAGE));
+ lua_settable (L, -3);
+ lua_settable (L, -3);
+}
+
+/**
+ * push_operation_range_filters
+ *
+ * Pushes the elements of the filters table representing
+ * the range filters into the table. The filters table should
+ * already be on top of the lua stack.
+ *
+ * @L: LuaState where the data is stored.
+ * @options: The GrlOperationOptions from which to retrieve filters.
+ * @return: Nothing.
+ */
+static void
+push_operation_range_filters (lua_State *L,
+ GrlOperationOptions *options)
+{
+ GrlRegistry *registry;
+ GList *range_filters;
+ GList *it;
+
+ g_assert (lua_istable (L, -1));
+
+ registry = grl_registry_get_default ();
+ range_filters = grl_operation_options_get_key_range_filter_list (options);
+
+ for (it = range_filters; it != NULL; it = it->next) {
+ GrlKeyID key_id;
+ gchar *key_name;
+ gchar *ptr;
+ GValue *min = NULL;
+ GValue *max = NULL;
+ gboolean success = TRUE;
+
+ key_id = GRLPOINTER_TO_KEYID (it->data);
+ if (key_id == GRL_METADATA_KEY_INVALID)
+ continue;
+
+ grl_operation_options_get_key_range_filter (options, key_id, &min, &max);
+ key_name = g_strdup (grl_registry_lookup_metadata_key_name (registry, key_id));
+
+ /* Replace '-' to '_': as a convenience for the developer */
+ while ((ptr = strstr (key_name, "-")) != NULL) {
+ *ptr = '_';
+ }
+
+ lua_pushstring (L, key_name);
+ g_free (key_name);
+ lua_newtable (L);
+
+ switch (grl_registry_lookup_metadata_key_type (registry, key_id)) {
+ case G_TYPE_INT:
+ lua_pushstring (L, "min");
+ (min) ? (void) lua_pushinteger (L, g_value_get_int (min)) : lua_pushnil (L);
+ lua_settable (L, -3);
+ lua_pushstring (L, "max");
+ (max) ? (void) lua_pushinteger (L, g_value_get_int (max)) : lua_pushnil (L);
+ lua_settable (L, -3);
+ break;
+
+ case G_TYPE_FLOAT:
+ lua_pushstring (L, "min");
+ (min) ? (void) lua_pushnumber (L, g_value_get_float (min)) : lua_pushnil (L);
+ lua_settable (L, -3);
+ lua_pushstring (L, "max");
+ (max) ? (void) lua_pushnumber (L, g_value_get_float (max)) : lua_pushnil (L);
+ lua_settable (L, -3);
+ break;
+
+ case G_TYPE_STRING:
+ lua_pushstring (L, "min");
+ (min) ? (void) lua_pushstring (L, g_value_get_string (min)) : lua_pushnil (L);
+ lua_settable (L, -3);
+ lua_pushstring (L, "max");
+ (max) ? (void) lua_pushstring (L, g_value_get_string (max)) : lua_pushnil (L);
+ lua_settable (L, -3);
+ break;
+
+ case G_TYPE_INT64:
+ lua_pushstring (L, "min");
+ (min) ? (void) lua_pushinteger (L, g_value_get_int64 (min)) : lua_pushnil (L);
+ lua_settable (L, -3);
+ lua_pushstring (L, "max");
+ (max) ? (void) lua_pushinteger (L, g_value_get_int64 (max)) : lua_pushnil (L);
+ lua_settable (L, -3);
+ break;
+
+ default:
+ if (grl_registry_lookup_metadata_key_type (registry, key_id) == G_TYPE_DATE_TIME) {
+ /* since the value would be used for comparison, and since os.time()
+ * returns unix time in lua, it'd be a good idea to pass g_date_time
+ * as unix time here */
+ GDateTime *date;
+ lua_pushstring (L, "min");
+ if (min) {
+ date = g_value_get_boxed (min);
+ lua_pushinteger (L, g_date_time_to_unix (date));
+ } else {
+ lua_pushnil (L);
+ }
+ lua_settable (L, -3);
+ lua_pushstring (L, "max");
+ if (max) {
+ date = g_value_get_boxed (max);
+ lua_pushinteger (L, g_date_time_to_unix (date));
+ } else {
+ lua_pushnil (L);
+ }
+ lua_settable (L, -3);
+ } else {
+ GRL_DEBUG ("Key %s has unhandled G_TYPE. Lua source will miss this data",
+ grl_registry_lookup_metadata_key_name (registry, key_id));
+
+ success = FALSE;
+ }
+ }
+
+ if (success) {
+ lua_settable (L, -3);
+ } else {
+ lua_pop (L, 2);
+ }
+ }
+ g_list_free (range_filters);
+}
+
+/**
+ * push_operation_filters
+ *
+ * Pushes the elements of the filters table representing
+ * the non-range filters into the table. The filters table
+ * should already be on top of the lua stack.
+ *
+ * @L: LuaState where the data is stored.
+ * @options: The GrlOperationOptions from which to retrieve filters.
+ * @return: Nothing.
+ */
+static void
+push_operation_filters (lua_State *L,
+ GrlOperationOptions *options)
+{
+ GrlRegistry *registry;
+ GList *filters;
+ GList *it;
+
+ g_assert (lua_istable (L, -1));
+
+ registry = grl_registry_get_default ();
+ filters = grl_operation_options_get_key_filter_list (options);
+
+ for (it = filters; it != NULL; it = it->next) {
+ GrlKeyID key_id;
+ gchar *key_name;
+ gchar *ptr;
+ GValue *value = NULL;
+ gboolean success = TRUE;
+
+ key_id = GRLPOINTER_TO_KEYID (it->data);
+ if (key_id == GRL_METADATA_KEY_INVALID)
+ continue;
+
+ value = grl_operation_options_get_key_filter (options, key_id);
+ key_name = g_strdup (grl_registry_lookup_metadata_key_name (registry, key_id));
+
+ /* Replace '-' to '_': as a convenience for the developers */
+ while ((ptr = strstr (key_name, "-")) != NULL) {
+ *ptr = '_';
+ }
+
+ lua_pushstring (L, key_name);
+ g_free (key_name);
+
+ /* Keep all the filters in tables */
+ lua_newtable (L);
+ lua_pushstring (L, "value");
+
+ switch (grl_registry_lookup_metadata_key_type (registry, key_id)) {
+ case G_TYPE_INT:
+ (value) ? (void) lua_pushinteger (L, g_value_get_int (value)) : lua_pushnil (L);
+ break;
+
+ case G_TYPE_FLOAT:
+ (value) ? (void) lua_pushnumber (L, g_value_get_float (value)) : lua_pushnil (L);
+ break;
+
+ case G_TYPE_STRING:
+ (value) ? (void) lua_pushstring (L, g_value_get_string (value)) : lua_pushnil (L);
+ break;
+
+ case G_TYPE_BOOLEAN:
+ (value) ? (void) lua_pushboolean (L, g_value_get_boolean (value)) : lua_pushnil (L);
+ break;
+
+ case G_TYPE_INT64:
+ (value) ? (void) lua_pushinteger (L, g_value_get_int64 (value)) : lua_pushnil (L);
+ break;
+
+ default:
+ GRL_DEBUG ("'%s' is being ignored as G_TYPE is not being handled.",
+ grl_registry_lookup_metadata_key_name (registry, key_id));
+ success = FALSE;
+ }
+ if (success) {
+ lua_settable (L, -3);
+ lua_settable (L, -3);
+ } else {
+ lua_pop (L, 3);
+ }
+ }
+ g_list_free (filters);
+}
+
+/**
+ * grl_lua_library_push_grl_options
+ *
+ * Pushes the table representing the various options of the operation
+ * on top of the lua stack.
+ *
+ * @L: LuaState where the data is stored.
+ * @opearation_id: id of the current operation
+ * @option: The options of the current operation.
+ * @key: The requested keys of the current operation.
+ * @return: Nothing.
+ */
+void
+grl_lua_library_push_grl_options (lua_State *L,
+ guint operation_id,
+ GrlOperationOptions *options,
+ GList *keys)
+{
+ lua_newtable (L);
+
+ lua_pushstring (L, "count");
+ lua_pushinteger (L, grl_operation_options_get_count (options));
+ lua_settable (L, -3);
+
+ lua_pushstring (L, "skip");
+ lua_pushinteger (L, grl_operation_options_get_skip (options));
+ lua_settable (L, -3);
+
+ lua_pushstring (L, "operation_id");
+ lua_pushinteger (L, (gint) operation_id);
+ lua_settable (L, -3);
+
+ lua_pushstring (L, "requested_keys");
+ push_operation_requested_keys(L, keys);
+ lua_settable (L, -3);
+
+ lua_pushstring (L, "filters");
+ lua_newtable (L);
+
+ push_operation_type_filter (L, options);
+ push_operation_range_filters (L, options);
+ push_operation_filters (L, options);
+
+ lua_settable (L, -3);
+}