isbear@23:
isbear@66: /* Copyright 2009-2016 Myhailo Danylenko
isbear@23:
isbear@23: This file is part of lua-lm.
isbear@23:
isbear@23: lua-lm is free software: you can redistribute it and/or modify
isbear@23: it under the terms of the GNU General Public License as published by
isbear@23: the Free Software Foundation, either version 2 of the License, or
isbear@23: (at your option) any later version.
isbear@23:
isbear@23: This program is distributed in the hope that it will be useful,
isbear@23: but WITHOUT ANY WARRANTY; without even the implied warranty of
isbear@23: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
isbear@23: GNU General Public License for more details.
isbear@23:
isbear@23: You should have received a copy of the GNU General Public License
isbear@23: along with this program. If not, see . */
isbear@0:
isbear@0: #include
isbear@0: #include
isbear@0: #include
isbear@0:
isbear@6: #include "config.h"
isbear@0: #include "lm_types.h"
isbear@0:
isbear@0: /// lm.message_node
isbear@0: /// Object, representing xml node of the message.
isbear@0: /// Cannot be created directly, only as a part of message tree.
isbear@0:
isbear@0: /// lm.message_node.bless
isbear@0: /// Blesses given pointer to lm message node object.
isbear@0: /// A: lightuserdata (C lm message node object)
isbear@0: /// R: lm message node object
isbear@11: static int bless_lua_lm_node (lua_State *L)
isbear@0: {
isbear@0: luaL_argcheck (L, lua_islightuserdata (L, 1), 1, "loudmouth message node lightuserdata expected");
isbear@11: bless_lm_node (L, lua_touserdata (L, 1));
isbear@0: return 1;
isbear@0: }
isbear@0:
isbear@0: /// message_node:name
isbear@0: /// Gets a name of message node.
isbear@0: /// R: string
isbear@11: int name_lm_node (lua_State *L)
isbear@0: {
isbear@7: LmMessageNode *node = luaL_checkLmMessageNode (L, 1);
isbear@7: lua_pushstring (L, node->name);
isbear@0: return 1;
isbear@0: }
isbear@0:
isbear@0: /// message_node:next
isbear@0: /// Gets next message node.
isbear@0: /// R: lm message node object or nil
isbear@11: int next_lm_node (lua_State *L)
isbear@0: {
isbear@7: LmMessageNode *node = luaL_checkLmMessageNode (L, 1);
isbear@7: LmMessageNode *next = node->next;
isbear@7: if (next)
isbear@11: bless_lm_node (L, next);
isbear@0: else
isbear@0: lua_pushnil (L);
isbear@0: return 1;
isbear@0: }
isbear@0:
isbear@0: /// message_node:prev
isbear@0: /// Gets previous message node.
isbear@0: /// R: lm message node object or nil
isbear@11: int prev_lm_node (lua_State *L)
isbear@0: {
isbear@7: LmMessageNode *node = luaL_checkLmMessageNode (L, 1);
isbear@7: LmMessageNode *prev = node->prev;
isbear@7: if (prev)
isbear@11: bless_lm_node (L, prev);
isbear@0: else
isbear@0: lua_pushnil (L);
isbear@0: return 1;
isbear@0: }
isbear@0:
isbear@0: /// message_node:parent
isbear@0: /// Gets parent message node.
isbear@0: /// R: lm message node object or nil
isbear@11: int parent_lm_node (lua_State *L)
isbear@0: {
isbear@7: LmMessageNode *node = luaL_checkLmMessageNode (L, 1);
isbear@7: LmMessageNode *parent = node->parent;
isbear@7: if (parent)
isbear@11: bless_lm_node (L, parent);
isbear@0: else
isbear@0: lua_pushnil (L);
isbear@0: return 1;
isbear@0: }
isbear@0:
isbear@0: /// message_node:value
isbear@0: /// Gets or sets a value of message node.
isbear@0: /// A: string (optional value)
isbear@6: /// R: string (if called without arguments) or lm message node object
isbear@11: int value_lm_node (lua_State *L)
isbear@0: {
isbear@7: LmMessageNode *node = luaL_checkLmMessageNode (L, 1);
isbear@0: if (lua_gettop (L) > 1) { // Set
isbear@0: const char *value = luaL_checkstring (L, 2);
isbear@7: lm_message_node_set_value (node, value);
isbear@6: lua_pop (L, 1);
isbear@6: } else // Get
isbear@7: lua_pushstring (L, lm_message_node_get_value (node));
isbear@6: return 1;
isbear@0: }
isbear@0:
isbear@0: /// message_node:child
isbear@0: /// Gets or creates child node object with given name.
isbear@14: /// If name is omitted, first child node is returned.
isbear@14: /// A: string (name, optional), string (optional value)
isbear@0: /// R: lm message node object or nil
isbear@11: int child_lm_node (lua_State *L)
isbear@0: {
isbear@7: LmMessageNode *node = luaL_checkLmMessageNode (L, 1);
isbear@0: LmMessageNode *child;
isbear@14: int top = lua_gettop (L);
isbear@14: if (top > 1) {
isbear@14: const char *name = luaL_checkstring (L, 2);
isbear@0:
isbear@14: if (top > 2) // Add
isbear@14: child = lm_message_node_add_child (node, name,
isbear@14: luaL_checkstring (L, 3));
isbear@14: else // Get
isbear@14: child = lm_message_node_get_child (node, name);
isbear@14: } else
isbear@14: child = node->children;
isbear@14:
isbear@14: if (child)
isbear@14: bless_lm_node (L, child);
isbear@14: // XXX lm_message_node_unref (child); // may be necessary on _get/_add'ed nodes
isbear@14: else
isbear@14: lua_pushnil (L);
isbear@0: return 1;
isbear@0: }
isbear@0:
isbear@39: static int children_iterator_lm_node (lua_State *L)
isbear@39: {
isbear@39: const char *name = lua_tostring (L, lua_upvalueindex (1));
isbear@39: LmMessageNode *node;
isbear@39: if (lua_type (L, 2) == LUA_TUSERDATA) {
isbear@39: node = luaL_checkLmMessageNode (L, 2);
isbear@39: node = node -> next;
isbear@39: } else {
isbear@39: node = luaL_checkLmMessageNode (L, 1);
isbear@39: node = node -> children;
isbear@39: }
isbear@39:
isbear@39: if (name)
isbear@39: while (node && g_strcmp0 (node -> name, name))
isbear@39: node = node -> next;
isbear@39:
isbear@39: if (node)
isbear@39: bless_lm_node (L, node);
isbear@39: // XXX lm_message_node_unref (child); // may be necessary on _get/_add'ed nodes
isbear@39: else
isbear@39: lua_pushnil (L);
isbear@39:
isbear@39: return 1;
isbear@39: }
isbear@39:
isbear@39: /// message_node:children
isbear@39: /// Returns iterator over child nodes of given node. Optionally filters childs by name.
isbear@39: /// A: string (name, optional)
isbear@39: /// R: iterator function, lm message node object, nil
isbear@39: int children_lm_node (lua_State *L)
isbear@39: {
isbear@39: if (lua_type (L, 2) != LUA_TSTRING)
isbear@39: lua_pushnil (L);
isbear@39:
isbear@39: lua_pushcclosure (L, children_iterator_lm_node, 1);
isbear@39: lua_pushvalue (L, 1);
isbear@39: lua_pushnil (L);
isbear@39:
isbear@39: return 3;
isbear@39: }
isbear@39:
isbear@0: /// message_node:find_child
isbear@0: /// Searches for node with a given name over all node subtree.
isbear@0: /// A: string (name)
isbear@0: /// R: lm message node object or nil
isbear@11: int find_child_lm_node (lua_State *L)
isbear@0: {
isbear@39: LmMessageNode *node = luaL_checkLmMessageNode (L, 1);
isbear@39: const char *name = luaL_checkstring (L, 2);
isbear@0: LmMessageNode *child;
isbear@0:
isbear@7: child = lm_message_node_get_child (node, name);
isbear@0: if (!child)
isbear@0: lua_pushnil (L);
isbear@0: else {
isbear@11: bless_lm_node (L, child);
isbear@0: // XXX lm_message_node_unref (child);
isbear@0: }
isbear@0: return 1;
isbear@0: }
isbear@0:
isbear@0: /// message_node:raw
isbear@0: /// Gets or sets raw mode flag for node.
isbear@0: /// When set, value of node will not be escaped.
isbear@0: /// A: boolean (optional)
isbear@6: /// V: boolean (if called with no apguments) or lm message node object
isbear@11: int raw_lm_node (lua_State *L)
isbear@0: {
isbear@7: LmMessageNode *node = luaL_checkLmMessageNode (L, 1);
isbear@0: if (lua_gettop (L) > 1) { // Set
isbear@0: luaL_checktype (L, 2, LUA_TBOOLEAN);
isbear@7: lm_message_node_set_raw_mode (node, lua_toboolean (L, 2));
isbear@6: lua_pop (L, 1);
isbear@6: } else // Get
isbear@7: lua_pushboolean (L, lm_message_node_get_raw_mode (node));
isbear@6: return 1;
isbear@0: }
isbear@0:
isbear@0: /// message_node:attribute
isbear@0: /// Gets or sets value of node attribute with a given name.
isbear@0: /// A: string (name), string (optional value)
isbear@6: /// R: string (when called with one aprgument) or lm message node object
isbear@11: int attribute_lm_node (lua_State *L)
isbear@0: {
isbear@7: LmMessageNode *node = luaL_checkLmMessageNode (L, 1);
isbear@39: const char *name = luaL_checkstring (L, 2);
isbear@0: if (lua_gettop (L) > 2) { // Set
isbear@7: lm_message_node_set_attribute (node, name, luaL_checkstring (L, 3));
isbear@6: lua_pop (L, 2);
isbear@6: } else // Get
isbear@7: lua_pushstring (L, lm_message_node_get_attribute (node, name));
isbear@6: return 1;
isbear@0: }
isbear@0:
isbear@66: /// message_node:attributes
isbear@66: /// Returns a table with message node attributes.
isbear@66: /// R: table
isbear@66: int attributes_lm_node (lua_State *L)
isbear@66: {
isbear@66: lua_newtable (L);
isbear@66: #ifdef HAVE_LM_MESSAGE_NODE_ATTRIBUTE
isbear@66: LmMessageNode *node = luaL_checkLmMessageNode (L, 1);
isbear@66: LmMessageNodeAttribute *attribute;
isbear@66: for (attribute = node -> attributes; attribute; attribute = attribute -> next) {
isbear@66: lua_pushstring (L, attribute -> value);
isbear@66: lua_setfield (L, -2, attribute -> name);
isbear@66: }
isbear@66: #endif
isbear@66: return 1;
isbear@66: }
isbear@66:
isbear@0: /// message_node:xml
isbear@0: /// Returns node representation in xml.
isbear@0: /// R: string
isbear@11: int xml_lm_node (lua_State *L)
isbear@0: {
isbear@7: LmMessageNode *node = luaL_checkLmMessageNode (L, 1);
isbear@7: lua_pushstring (L, lm_message_node_to_string (node));
isbear@0: return 1;
isbear@0: }
isbear@0:
isbear@8: /// message_node:path
isbear@8: /// Returns node with specified path to it.
isbear@8: /// If any element in a path cannot be found, it returns nil.
isbear@8: /// A: string (node name), ...
isbear@8: /// R: lm message node object or nil
isbear@11: int path_lm_node (lua_State *L)
isbear@8: {
isbear@8: LmMessageNode *node = luaL_checkLmMessageNode (L, 1);
isbear@8: int i = 1;
isbear@8: while (i++ < lua_gettop (L)) {
isbear@8: node = lm_message_node_get_child (node, luaL_checkstring (L, i));
isbear@8: if (node == NULL) {
isbear@8: lua_pushnil (L);
isbear@8: return 1;
isbear@8: }
isbear@8: }
isbear@11: bless_lm_node (L, node);
isbear@8: // XXX lm_message_node_unref (child);
isbear@8: return 1;
isbear@8: }
isbear@8:
isbear@0: /// message_node:pointer
isbear@0: /// Returns pointer to underlying C structure.
isbear@0: /// R: lightuserdata
isbear@11: static int pointer_lm_node (lua_State *L)
isbear@0: {
isbear@11: llm_node_t *object = luaL_checklm_node (L, 1);
isbear@11: lua_pushlightuserdata (L, object->node);
isbear@0: return 1;
isbear@0: }
isbear@0:
isbear@11: static int gc_lm_node (lua_State *L)
isbear@0: {
isbear@11: llm_node_t *object = luaL_checklm_node (L, 1);
isbear@38: D ("Message node %p gc called", object);
isbear@11: lm_message_node_unref (object->node);
isbear@0: return 0;
isbear@0: }
isbear@0:
isbear@11: static const luaL_Reg reg_f_lm_node[] = {
isbear@11: { "bless", bless_lua_lm_node },
isbear@12: { NULL, NULL },
isbear@0: };
isbear@0:
isbear@11: static const luaL_Reg reg_m_lm_node[] = {
isbear@11: { "name", name_lm_node },
isbear@11: { "next", next_lm_node },
isbear@11: { "prev", prev_lm_node },
isbear@11: { "parent", parent_lm_node },
isbear@11: { "value", value_lm_node },
isbear@11: { "child", child_lm_node },
isbear@39: { "children", children_lm_node },
isbear@11: { "find_child", find_child_lm_node },
isbear@11: { "attribute", attribute_lm_node },
isbear@11: { "raw", raw_lm_node },
isbear@11: { "xml", xml_lm_node },
isbear@11: { "path", path_lm_node },
isbear@11: { "pointer", pointer_lm_node },
isbear@11: { "__gc", gc_lm_node },
isbear@12: { NULL, NULL },
isbear@0: };
isbear@0:
isbear@0: int luaopen_lm_message_node (lua_State *L)
isbear@0: {
isbear@0: luaL_newmetatable (L, "loudmouth.message_node");
isbear@19: lua_pushvalue (L, -1);
isbear@19: lua_setfield (L, -2, "__index");
isbear@54: luaL_setfuncs (L, reg_m_lm_node, 0);
isbear@0: lua_pop (L, 1);
isbear@16: lua_newtable (L); // XXX we can specify here exact amount of fields
isbear@54: luaL_setfuncs (L, reg_f_lm_node, 0);
isbear@0: return 1;
isbear@0: }
isbear@0: