# HG changeset patch # User Myhailo Danylenko # Date 1238932551 -10800 # Node ID ab4470465a0cde043915fc118aacc53d3ea99a67 # Parent 09b375e9ce32eb0ec1e4f183c56b1a1f46b8b25a Create message in C * Pre-formatted text in docgen * Replace lua_pushconststring with lua_pushliteral * Create message in C * Add forgotten name node method to message * Default message type and subtype diff -r 09b375e9ce32 -r ab4470465a0c docgen.pl --- a/docgen.pl Fri Mar 27 09:43:41 2009 +0200 +++ b/docgen.pl Sun Apr 05 14:55:51 2009 +0300 @@ -78,6 +78,8 @@ s/^A: /Arguments: /; s/^R: /Return values: /; s/^V: /Values: /; + s/^\[ /
/;
+			s/^\]/<\/pre>/;
 			if ( $list ) {
 				if ( /^\* / ) {
 					s/^\* /<\/li>
  • /; diff -r 09b375e9ce32 -r ab4470465a0c lm.c --- a/lm.c Fri Mar 27 09:43:41 2009 +0200 +++ b/lm.c Sun Apr 05 14:55:51 2009 +0300 @@ -21,33 +21,33 @@ int luaopen_loudmouth (lua_State *L) { - lua_pushconststring (L, LLM_OBJREGISTRY); // 1 registry key + lua_pushliteral (L, LLM_OBJREGISTRY); // 1 registry key lua_newtable (L); // 2 registry value (table) lua_createtable (L, 0, 1); // 3 metatable - lua_pushconststring (L, "__mode"); // 4 metatable key - lua_pushconststring (L, "v"); // 5 metatable value + lua_pushliteral (L, "__mode"); // 4 metatable key + lua_pushliteral (L, "v"); // 5 metatable value lua_settable (L, -3); // 3 metatable lua_setmetatable (L, -2); // 2 registry value lua_rawset (L, LUA_REGISTRYINDEX); // 0 lua_createtable (L, 6, 0); - lua_pushconststring (L, "message_node"); + lua_pushliteral (L, "message_node"); luaopen_lm_message_node (L); lua_settable (L, -3); - lua_pushconststring (L, "message"); + lua_pushliteral (L, "message"); luaopen_lm_message (L); lua_settable (L, -3); - lua_pushconststring (L, "message_handler"); + lua_pushliteral (L, "message_handler"); luaopen_lm_message_handler (L); lua_settable (L, -3); - lua_pushconststring (L, "proxy"); + lua_pushliteral (L, "proxy"); luaopen_lm_proxy (L); lua_settable (L, -3); - lua_pushconststring (L, "ssl"); + lua_pushliteral (L, "ssl"); luaopen_lm_ssl (L); lua_settable (L, -3); - lua_pushconststring (L, "connection"); + lua_pushliteral (L, "connection"); luaopen_lm_connection (L); lua_settable (L, -3); diff -r 09b375e9ce32 -r ab4470465a0c lm.lua --- a/lm.lua Fri Mar 27 09:43:41 2009 +0200 +++ b/lm.lua Sun Apr 05 14:55:51 2009 +0300 @@ -153,6 +153,7 @@ end end +--[=[ -- recursively fills a node, see lm.message.create function lm.message_node.fill ( n, a ) for name, value in pairs ( a ) do @@ -171,7 +172,6 @@ end end end - --[[ -- recursively fills a message lm.message.create { mtype = 'iq-result', to = 'foo@bar.xyz', @@ -225,6 +225,7 @@ lm.message_node.fill ( m, a ) return m end +--]=] -- TODO: multiple nodes with same name function lm.message_node.parse ( node, r ) diff -r 09b375e9ce32 -r ab4470465a0c lm_message.c --- a/lm_message.c Fri Mar 27 09:43:41 2009 +0200 +++ b/lm_message.c Sun Apr 05 14:55:51 2009 +0300 @@ -2,6 +2,7 @@ #include #include #include +#include #include "config.h" #include "util.h" @@ -12,7 +13,7 @@ /// Module, representing individual message. /// Message have a type and optionally a sub type. /// Message have a set common methods with message node, -/// these are next, prev, children, parent, value, child, +/// these are name, next, prev, children, parent, value, child, /// find_child, attribute, raw, xml and path. They just save /// you typing :node() each time and save memory for /// one node object. @@ -40,7 +41,7 @@ { "stream:features", LM_MESSAGE_TYPE_STREAM_FEATURES }, { "stream_error", LM_MESSAGE_TYPE_STREAM_ERROR }, { "stream_features", LM_MESSAGE_TYPE_STREAM_FEATURES }, - { NULL, 0 }, + { NULL, LM_MESSAGE_TYPE_MESSAGE }, }; /// message sub type @@ -64,7 +65,7 @@ { "result", LM_MESSAGE_SUB_TYPE_RESULT }, { "error", LM_MESSAGE_SUB_TYPE_ERROR }, { "not_set", LM_MESSAGE_SUB_TYPE_NOT_SET }, - { NULL, 0 }, + { NULL, LM_MESSAGE_SUB_TYPE_NOT_SET }, }; /// lm.message.new @@ -91,6 +92,111 @@ return 1; } +/// message table +/// Table describes xml structure of the message, the only exception is mtype key of root table. +/// mtype is a string of form "-", eg "iq-set". +/// Best way to learn how this table is organized, is just to look at next example: +/// [ lm.message.create { mtype = 'iq-result', to = 'foo@bar.xyz', +/// command = { xmlns = 'http://jabber.org/protocol/commands', node = 'http://jabber.org/protocol/rc#set-status', status = 'executing', sessionid = 'set-status:aaa3', +/// x = { xmlns = 'jabber:x:data', type = 'form', +/// title = { "Change Status" }, +/// instructions = { "Choose the status and status message" }, +/// field = {{ type = 'hidden', var = 'FORM_TYPE', +/// value = { "http://jabber.org/protocol/rc" }, +/// },{ type = 'list-single', label = 'Status', var = 'status', +/// required = { }, +/// value = { "online" }, +/// option = {{ label = 'Chat', +/// value = { "chat" }, +/// },{ label = 'Online', +/// value = { "online" }, +/// },{ label = 'Away', +/// value = { "away" }, +/// },{ label = 'Extended Away', +/// value = { "xa" }, +/// },{ label = 'Do Not Disturb', +/// value = { "dnd" }, +/// },{ label = 'Invisible', +/// value = { "invisible" }, +/// },{ label = 'Offline', +/// value = { "offline" }, +/// }}, +/// },{ type = 'text-single', label = 'Priority', var = 'status-priority', +/// value = { "5" }, +/// },{ type = 'text-multi', label = 'Message', var = 'status-message' }}, +/// }, +/// }, +/// } +/// ] +static void fill_lm_node (lua_State *L, LmMessageNode *node, int index) +{ + int top = lua_gettop (L); // 0 + for (lua_pushnil (L); lua_next (L, index) != 0; lua_pop (L, lua_gettop (L) - top - 1)) // 2 value + if (lua_type (L, top + 2) == LUA_TTABLE) { + const char *name = lua_tostring (L, top + 1); + lua_pushinteger (L, 1); // 3 1 + lua_gettable (L, top + 2); // 3 value[1] + if (lua_type (L, top + 3) == LUA_TTABLE) { + int i = 1; + do { + fill_lm_node (L, lm_message_node_add_child (node, name, NULL), top + 3); + lua_pop (L, 1); // 2 value + lua_pushinteger (L, ++i); // 3 i + lua_gettable (L, top + 2); // 3 value[i] + } while (lua_type (L, top + 3) == LUA_TTABLE); + } else + fill_lm_node (L, lm_message_node_add_child (node, name, NULL), top + 2); + } else if (lua_type (L, top + 1) == LUA_TNUMBER && lua_tointeger (L, top + 1) == 1) + lm_message_node_set_value (node, lua_tostring (L, top + 2)); + else + lm_message_node_set_attribute (node, lua_tostring (L, top + 1), lua_tostring (L, top + 2)); +} + +/// lm.message.create +/// Creates new message object and fills it from message table. +/// Note, that table fields are not checked for their types, so, on wrong input results may be undefined. +/// A: message table +/// R: lm message object +static int create_lm_message (lua_State *L) +{ + const char *mtype; + const char *st; + const char *to = NULL; + LmMessage *message; + luaL_checktype (L, 1, LUA_TTABLE); + + lua_getfield (L, 1, "mtype"); + mtype = lua_tostring (L, -1); + st = strchr (mtype, '-'); + + lua_getfield (L, 1, "to"); + if (lua_type (L, -1) == LUA_TSTRING) + to = lua_tostring (L, -1); + + if (st) { + LmMessageType mt; + lua_pushlstring (L, mtype, st - mtype); + mt = luaL_checkenum (L, -1, type_lm_message); + lua_pop (L, 1); + message = lm_message_new_with_sub_type (to, mt, string2enum (st + 1, sub_type_lm_message)); + } else + message = lm_message_new (to, luaL_checkenum (L, -2, type_lm_message)); + + lua_pop (L, 2); + lua_pushnil (L); + lua_setfield (L, 1, "mtype"); + lua_pushnil (L); + lua_setfield (L, 1, "to"); + + fill_lm_node (L, lm_message_get_node (message), 1); + + bless_lm_message (L, message); + lm_message_unref (message); + D ("Message %X created", (int) message); + + return 1; +} + /// lm.message.bless /// Blesses given pointer to lm message object. /// A: lightuserdata (C lm message object) @@ -144,15 +250,17 @@ } static const luaL_Reg reg_f_lm_message[] = { - { "new", new_lm_message }, - { "bless", bless_lua_lm_message }, - { NULL, NULL }, + { "new", new_lm_message }, + { "create", create_lm_message }, + { "bless", bless_lua_lm_message }, + { NULL, NULL }, }; static const luaL_Reg reg_m_lm_message[] = { { "node", node_lm_message }, { "type", kind_lm_message }, // These methods are common for message and message node + { "name", name_lm_node }, { "next", next_lm_node }, { "prev", prev_lm_node }, { "children", children_lm_node }, diff -r 09b375e9ce32 -r ab4470465a0c lm_types.h --- a/lm_types.h Fri Mar 27 09:43:41 2009 +0200 +++ b/lm_types.h Sun Apr 05 14:55:51 2009 +0300 @@ -6,7 +6,7 @@ #include #ifndef LLM_OBJREGISTRY -#define LLM_OBJREGISTRY ( "llm.obj_registry" ) +#define LLM_OBJREGISTRY "llm.obj_registry" #endif typedef struct { diff -r 09b375e9ce32 -r ab4470465a0c util.h --- a/util.h Fri Mar 27 09:43:41 2009 +0200 +++ b/util.h Sun Apr 05 14:55:51 2009 +0300 @@ -9,8 +9,6 @@ #define enum_value_t int #endif -#define lua_pushconststring(L, STRING) { lua_pushlstring (L, STRING, sizeof(STRING)-1); } - // Array of string2eunm_t's must be ended with pair { NULL, fallback_value } typedef struct { const char *string;