#include <lua.h>
#include <lauxlib.h>
#include <loudmouth/loudmouth.h>
#include "config.h"
#include "lm_types.h"
/// lm.message_node
/// Object, representing xml node of the message.
/// Cannot be created directly, only as a part of message tree.
/// lm.message_node.bless
/// Blesses given pointer to lm message node object.
/// A: lightuserdata (C lm message node object)
/// R: lm message node object
static int bless_lua_lm_node (lua_State *L)
{
luaL_argcheck (L, lua_islightuserdata (L, 1), 1, "loudmouth message node lightuserdata expected");
bless_lm_node (L, lua_touserdata (L, 1));
return 1;
}
/// message_node:name
/// Gets a name of message node.
/// R: string
int name_lm_node (lua_State *L)
{
LmMessageNode *node = luaL_checkLmMessageNode (L, 1);
lua_pushstring (L, node->name);
return 1;
}
/// message_node:next
/// Gets next message node.
/// R: lm message node object or nil
int next_lm_node (lua_State *L)
{
LmMessageNode *node = luaL_checkLmMessageNode (L, 1);
LmMessageNode *next = node->next;
if (next)
bless_lm_node (L, next);
else
lua_pushnil (L);
return 1;
}
/// message_node:prev
/// Gets previous message node.
/// R: lm message node object or nil
int prev_lm_node (lua_State *L)
{
LmMessageNode *node = luaL_checkLmMessageNode (L, 1);
LmMessageNode *prev = node->prev;
if (prev)
bless_lm_node (L, prev);
else
lua_pushnil (L);
return 1;
}
/// message_node:children
/// Gets first child node (raw access used).
/// R: lm message node object or nil
int children_lm_node (lua_State *L)
{
LmMessageNode *node = luaL_checkLmMessageNode (L, 1);
LmMessageNode *child = node->children;
if (child)
bless_lm_node (L, child);
else
lua_pushnil (L);
return 1;
}
/// message_node:parent
/// Gets parent message node.
/// R: lm message node object or nil
int parent_lm_node (lua_State *L)
{
LmMessageNode *node = luaL_checkLmMessageNode (L, 1);
LmMessageNode *parent = node->parent;
if (parent)
bless_lm_node (L, parent);
else
lua_pushnil (L);
return 1;
}
/// message_node:value
/// Gets or sets a value of message node.
/// A: string (optional value)
/// R: string (if called without arguments) or lm message node object
int value_lm_node (lua_State *L)
{
LmMessageNode *node = luaL_checkLmMessageNode (L, 1);
if (lua_gettop (L) > 1) { // Set
const char *value = luaL_checkstring (L, 2);
lm_message_node_set_value (node, value);
lua_pop (L, 1);
} else // Get
lua_pushstring (L, lm_message_node_get_value (node));
return 1;
}
/// message_node:child
/// Gets or creates child node object with given name.
/// A: string (name), string (optional value)
/// R: lm message node object or nil
int child_lm_node (lua_State *L)
{
LmMessageNode *node = luaL_checkLmMessageNode (L, 1);
const char *name = luaL_checkstring (L, 2);
LmMessageNode *child;
if (lua_gettop (L) > 2) // Add
child = lm_message_node_add_child (node, name,
luaL_checkstring (L, 3));
else { // Get
child = lm_message_node_get_child (node, name);
if (!child) {
lua_pushnil (L);
return 1;
}
}
bless_lm_node (L, child);
// XXX lm_message_node_unref (child);
return 1;
}
/// message_node:find_child
/// Searches for node with a given name over all node subtree.
/// A: string (name)
/// R: lm message node object or nil
int find_child_lm_node (lua_State *L)
{
LmMessageNode *node = luaL_checkLmMessageNode (L, 1);
const char *name = luaL_checkstring (L, 2);
LmMessageNode *child;
child = lm_message_node_get_child (node, name);
if (!child)
lua_pushnil (L);
else {
bless_lm_node (L, child);
// XXX lm_message_node_unref (child);
}
return 1;
}
/// message_node:raw
/// Gets or sets raw mode flag for node.
/// When set, value of node will not be escaped.
/// A: boolean (optional)
/// V: boolean (if called with no apguments) or lm message node object
int raw_lm_node (lua_State *L)
{
LmMessageNode *node = luaL_checkLmMessageNode (L, 1);
if (lua_gettop (L) > 1) { // Set
luaL_checktype (L, 2, LUA_TBOOLEAN);
lm_message_node_set_raw_mode (node, lua_toboolean (L, 2));
lua_pop (L, 1);
} else // Get
lua_pushboolean (L, lm_message_node_get_raw_mode (node));
return 1;
}
/// message_node:attribute
/// Gets or sets value of node attribute with a given name.
/// A: string (name), string (optional value)
/// R: string (when called with one aprgument) or lm message node object
int attribute_lm_node (lua_State *L)
{
LmMessageNode *node = luaL_checkLmMessageNode (L, 1);
const char *name = luaL_checkstring (L, 2);
if (lua_gettop (L) > 2) { // Set
lm_message_node_set_attribute (node, name, luaL_checkstring (L, 3));
lua_pop (L, 2);
} else // Get
lua_pushstring (L, lm_message_node_get_attribute (node, name));
return 1;
}
/// message_node:xml
/// Returns node representation in xml.
/// R: string
int xml_lm_node (lua_State *L)
{
LmMessageNode *node = luaL_checkLmMessageNode (L, 1);
lua_pushstring (L, lm_message_node_to_string (node));
return 1;
}
/// message_node:path
/// Returns node with specified path to it.
/// If any element in a path cannot be found, it returns nil.
/// A: string (node name), ...
/// R: lm message node object or nil
int path_lm_node (lua_State *L)
{
LmMessageNode *node = luaL_checkLmMessageNode (L, 1);
int i = 1;
while (i++ < lua_gettop (L)) {
node = lm_message_node_get_child (node, luaL_checkstring (L, i));
if (node == NULL) {
lua_pushnil (L);
return 1;
}
}
bless_lm_node (L, node);
// XXX lm_message_node_unref (child);
return 1;
}
/// message_node:pointer
/// Returns pointer to underlying C structure.
/// R: lightuserdata
static int pointer_lm_node (lua_State *L)
{
llm_node_t *object = luaL_checklm_node (L, 1);
lua_pushlightuserdata (L, object->node);
return 1;
}
static int gc_lm_node (lua_State *L)
{
llm_node_t *object = luaL_checklm_node (L, 1);
D ("Message node %X gc called", (int) object);
lm_message_node_unref (object->node);
return 0;
}
static const luaL_Reg reg_f_lm_node[] = {
{ "bless", bless_lua_lm_node },
{ NULL, NULL },
};
static const luaL_Reg reg_m_lm_node[] = {
{ "name", name_lm_node },
{ "next", next_lm_node },
{ "prev", prev_lm_node },
{ "children", children_lm_node },
{ "parent", parent_lm_node },
{ "value", value_lm_node },
{ "child", child_lm_node },
{ "find_child", find_child_lm_node },
{ "attribute", attribute_lm_node },
{ "raw", raw_lm_node },
{ "xml", xml_lm_node },
{ "path", path_lm_node },
{ "pointer", pointer_lm_node },
{ "__gc", gc_lm_node },
{ NULL, NULL },
};
int luaopen_lm_message_node (lua_State *L)
{
luaL_newmetatable (L, "loudmouth.message_node");
lua_pushstring (L, "__index");
lua_pushvalue (L, -2);
lua_settable (L, -3);
luaL_register (L, NULL, reg_m_lm_node);
lua_pop (L, 1);
luaL_register (L, "lm.message_node", reg_f_lm_node);
return 1;
}