lm_message_node.c
author Myhailo Danylenko <isbear@ukrpost.net>
Sun, 01 Feb 2009 21:28:57 +0200
changeset 0 84fdfb0344c9
child 6 90073cbb535d
permissions -rw-r--r--
Initial commit * It works * Still need to debug objects collection


#include <lua.h>
#include <lauxlib.h>
#include <loudmouth/loudmouth.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 llm_message_node_bless_lua (lua_State *L)
{
	luaL_argcheck (L, lua_islightuserdata (L, 1), 1, "loudmouth message node lightuserdata expected");
	llm_message_node_bless (L, lua_touserdata (L, 1));
	lua_remove (L, -2);
	return 1;
}

/// message_node:name
/// Gets a name of message node.
/// R: string
static int llm_message_node_name (lua_State *L)
{
	llm_message_node_t *object = luaL_checklm_message_node (L, 1);
	lua_pushstring (L, object->message_node->name);
	lua_remove (L, -2);
	return 1;
}

/// message_node:next
/// Gets next message node.
/// R: lm message node object or nil
static int llm_message_node_next (lua_State *L)
{
	llm_message_node_t *object = luaL_checklm_message_node (L, 1);
	LmMessageNode *node = object->message_node->next;
	if (node)
		llm_message_node_bless (L, node);
	else
		lua_pushnil (L);
	lua_remove (L, -2);
	return 1;
}

/// message_node:prev
/// Gets previous message node.
/// R: lm message node object or nil
static int llm_message_node_prev (lua_State *L)
{
	llm_message_node_t *object = luaL_checklm_message_node (L, 1);
	LmMessageNode *node = object->message_node->prev;
	if (node)
		llm_message_node_bless (L, node);
	else
		lua_pushnil (L);
	lua_remove (L, -2);
	return 1;
}

/// message_node:children
/// Gets first child node (raw access used).
/// R: lm message node object or nil
static int llm_message_node_children (lua_State *L)
{
	llm_message_node_t *object = luaL_checklm_message_node (L, 1);
	LmMessageNode *node = object->message_node->children;
	if (node)
		llm_message_node_bless (L, node);
	else
		lua_pushnil (L);
	lua_remove (L, -2);
	return 1;
}

/// message_node:parent
/// Gets parent message node.
/// R: lm message node object or nil
static int llm_message_node_parent (lua_State *L)
{
	llm_message_node_t *object = luaL_checklm_message_node (L, 1);
	LmMessageNode *node = object->message_node->parent;
	if (node)
		llm_message_node_bless (L, node);
	else
		lua_pushnil (L);
	lua_remove (L, -2);
	return 1;
}

/// message_node:value
/// Gets or sets a value of message node.
/// A: string (optional value)
/// R: string (if called without arguments)
static int llm_message_node_value (lua_State *L)
{
	llm_message_node_t *object = luaL_checklm_message_node (L, 1);
	if (lua_gettop (L) > 1) { // Set
		const char *value = luaL_checkstring (L, 2);
		lm_message_node_set_value (object->message_node, value);
		lua_pop (L, 2);
		return 0;
	} else { // Get
		lua_pushstring (L, lm_message_node_get_value (object->message_node));
		lua_remove (L, -2);
		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
static int llm_message_node_child (lua_State *L)
{
	llm_message_node_t *object = luaL_checklm_message_node (L, 1);
	const char *name = luaL_checkstring (L, 2);
	LmMessageNode *child;

	if (lua_gettop (L) > 2) { // Add
		child = lm_message_node_add_child (object->message_node, name,
						   luaL_checkstring (L, 3));
		lua_pop (L, 1);
	} else { // Get
		child = lm_message_node_get_child (object->message_node, name);
		if (!child) {
			lua_pushnil (L);
			return 1;
		}
	}
	llm_message_node_bless (L, child);
	// XXX lm_message_node_unref (child);
	lua_remove (L, -2);
	lua_remove (L, -2);
	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
static int llm_message_node_find_child (lua_State *L)
{
	llm_message_node_t *object = luaL_checklm_message_node (L, 1);
	const char *name = luaL_checkstring (L, 2);
	LmMessageNode *child;

	child = lm_message_node_get_child (object->message_node, name);
	if (!child)
		lua_pushnil (L);
	else {
		llm_message_node_bless (L, child);
		// XXX lm_message_node_unref (child);
	}
	lua_remove (L, -2);
	lua_remove (L, -2);
	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)
static int llm_message_node_raw (lua_State *L)
{
	llm_message_node_t *object = luaL_checklm_message_node (L, 1);
	if (lua_gettop (L) > 1) { // Set
		luaL_checktype (L, 2, LUA_TBOOLEAN);
		lm_message_node_set_raw_mode (object->message_node, lua_toboolean (L, 2));
		lua_pop (L, 2);
		return 0;
	} else { // Get
		lua_pushboolean (L, lm_message_node_get_raw_mode (object->message_node));
		lua_remove (L, -2);
		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)
static int llm_message_node_attribute (lua_State *L)
{
	llm_message_node_t *object = luaL_checklm_message_node (L, 1);
	const char *name = luaL_checkstring (L, 2);
	if (lua_gettop (L) > 2) { // Set
		lm_message_node_set_attribute (object->message_node, name, luaL_checkstring (L, 3));
		lua_pop (L, 3);
		return 0;
	} else { // Get
		lua_pushstring (L, lm_message_node_get_attribute (object->message_node, name));
		lua_remove (L, -2);
		lua_remove (L, -2);
		return 1;
	}
}

/// message_node:xml
/// Returns node representation in xml.
/// R: string
static int llm_message_node_xml (lua_State *L)
{
	llm_message_node_t *object = luaL_checklm_message_node (L, 1);
	lua_pushstring (L, lm_message_node_to_string (object->message_node));
	lua_remove (L, -2);
	return 1;
}

/// message_node:pointer
/// Returns pointer to underlying C structure.
/// R: lightuserdata
static int llm_message_node_pointer (lua_State *L)
{
	llm_message_node_t *object = luaL_checklm_message_node (L, 1);
	lua_pushlightuserdata (L, object->message_node);
	lua_remove (L, -2);
	return 1;
}

static int llm_message_node_gc (lua_State *L)
{
	llm_message_node_t *object = luaL_checklm_message_node (L, 1);
	lm_message_node_unref (object->message_node);
	lua_pop (L, 1);
	return 0;
}

static const luaL_Reg llm_message_node_reg_f[] = {
	{ "bless", llm_message_node_bless_lua },
	{ NULL,    NULL                       },
};

static const luaL_Reg llm_message_node_reg_m[] = {
	{ "name",       llm_message_node_name       },
	{ "next",       llm_message_node_next       },
	{ "prev",       llm_message_node_prev       },
	{ "children",   llm_message_node_children   },
	{ "parent",     llm_message_node_parent     },
	{ "value",      llm_message_node_value      },
	{ "child",      llm_message_node_child      },
	{ "find_child", llm_message_node_find_child },
	{ "attribute",  llm_message_node_attribute  },
	{ "raw",        llm_message_node_raw        },
	{ "xml",        llm_message_node_xml        },
	{ "pointer",    llm_message_node_pointer    },
	{ "__gc",       llm_message_node_gc         },
	{ 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, llm_message_node_reg_m);
	lua_pop (L, 1);
	luaL_register (L, "lm.message_node", llm_message_node_reg_f);
	return 1;
}