1
0
Fork 0
mirror of git://git.psyc.eu/libpsyc synced 2024-08-15 03:19:02 +00:00

list rendering

This commit is contained in:
Gabor Adam Toth 2011-04-26 17:23:06 +02:00
parent 7e29ca4e5a
commit 7a225b79c5
5 changed files with 198 additions and 39 deletions

View file

@ -87,6 +87,13 @@ typedef enum
PSYC_MODIFIER_ROUTING = 3, PSYC_MODIFIER_ROUTING = 3,
} psycModifierFlag; } psycModifierFlag;
typedef enum
{
PSYC_LIST_CHECK_LENGTH = 0,
PSYC_LIST_NEED_LENGTH = 1,
PSYC_LIST_NO_LENGTH = 2,
} psycListFlag;
typedef enum typedef enum
{ {
PSYC_PACKET_CHECK_LENGTH = 0, PSYC_PACKET_CHECK_LENGTH = 0,
@ -126,13 +133,21 @@ typedef struct
{ {
size_t lines; size_t lines;
psycModifier *modifiers; psycModifier *modifiers;
} psycModifierArray; } psycHeader;
typedef struct
{
size_t num_elems;
psycString *elems;
size_t length;
psycListFlag flag;
} psycList;
/* intermediate struct for a PSYC packet */ /* intermediate struct for a PSYC packet */
typedef struct typedef struct
{ {
psycModifierArray routing; ///< Routing header. psycHeader routing; ///< Routing header.
psycModifierArray entity; ///< Entitiy header. psycHeader entity; ///< Entitiy header.
psycString method; psycString method;
psycString data; psycString data;
size_t routingLength; ///< Length of routing part. size_t routingLength; ///< Length of routing part.
@ -151,8 +166,10 @@ inline psycModifier psyc_newModifier2(char oper,
const char *value, size_t valuelen, const char *value, size_t valuelen,
psycModifierFlag flag); psycModifierFlag flag);
inline psycPacket psyc_newPacket(psycModifierArray *routing, inline psycList psyc_newList(psycString *elems, size_t num_elems, psycListFlag flag);
psycModifierArray *entity,
inline psycPacket psyc_newPacket(psycHeader *routing,
psycHeader *entity,
psycString *method, psycString *data, psycString *method, psycString *data,
psycPacketFlag flag); psycPacketFlag flag);

View file

@ -31,6 +31,11 @@ typedef enum
*/ */
psycRenderRC psyc_render(psycPacket *packet, char *buffer, size_t buflen); psycRenderRC psyc_render(psycPacket *packet, char *buffer, size_t buflen);
/**
* Render a PSYC list into a buffer.
*/
inline psycRenderRC psyc_renderList(psycList *list, char *buffer, size_t buflen);
/* /*
typedef enum typedef enum
{ {

View file

@ -10,7 +10,7 @@ inline psycString psyc_newString(const char *str, size_t strlen)
} }
inline psycModifier psyc_newModifier(char oper, psycString *name, psycString *value, inline psycModifier psyc_newModifier(char oper, psycString *name, psycString *value,
psycModifierFlag flag) psycModifierFlag flag)
{ {
psycModifier m = {oper, *name, *value, flag}; psycModifier m = {oper, *name, *value, flag};
@ -28,9 +28,9 @@ inline psycModifier psyc_newModifier(char oper, psycString *name, psycString *va
} }
inline psycModifier psyc_newModifier2(char oper, inline psycModifier psyc_newModifier2(char oper,
const char *name, size_t namelen, const char *name, size_t namelen,
const char *value, size_t valuelen, const char *value, size_t valuelen,
psycModifierFlag flag) psycModifierFlag flag)
{ {
psycString n = {namelen, name}; psycString n = {namelen, name};
psycString v = {valuelen, value}; psycString v = {valuelen, value};
@ -50,10 +50,46 @@ inline size_t psyc_getModifierLength(psycModifier *m)
return length; return length;
} }
inline psycPacket psyc_newPacket(psycModifierArray *routing, inline psycList psyc_newList(psycString *elems, size_t num_elems, psycListFlag flag)
psycModifierArray *entity, {
psycString *method, psycString *data, psycList list = {num_elems, elems, 0, flag};
psycPacketFlag flag) size_t i;
if (flag == PSYC_LIST_CHECK_LENGTH) // check if list elements need length
{
for (i = 0; i < num_elems; i++)
{
if (memchr(elems[i].ptr, (int)'|', elems[i].length) ||
memchr(elems[i].ptr, (int)'\n', elems[i].length))
{
list.flag = PSYC_LIST_NEED_LENGTH;
break;
}
}
}
if (list.flag == PSYC_LIST_NEED_LENGTH)
{
for (i = 0; i < num_elems; i++)
{
if (i > 0)
list.length++; // |
list.length += log10((double)elems[i].length) + 2 + elems[i].length; // length SP elem
}
}
else
{
for (i = 0; i < num_elems; i++)
list.length += 1 + elems[i].length; // |elem
}
return list;
}
inline psycPacket psyc_newPacket(psycHeader *routing,
psycHeader *entity,
psycString *method, psycString *data,
psycPacketFlag flag)
{ {
psycPacket p = {*routing, *entity, *method, *data, 0, 0, flag}; psycPacket p = {*routing, *entity, *method, *data, 0, 0, flag};
size_t i; size_t i;
@ -93,13 +129,13 @@ inline psycPacket psyc_newPacket(psycModifierArray *routing,
} }
inline psycPacket psyc_newPacket2(psycModifier *routing, size_t routinglen, inline psycPacket psyc_newPacket2(psycModifier *routing, size_t routinglen,
psycModifier *entity, size_t entitylen, psycModifier *entity, size_t entitylen,
const char *method, size_t methodlen, const char *method, size_t methodlen,
const char *data, size_t datalen, const char *data, size_t datalen,
psycPacketFlag flag) psycPacketFlag flag)
{ {
psycModifierArray r = {routinglen, routing}; psycHeader r = {routinglen, routing};
psycModifierArray e = {entitylen, entity}; psycHeader e = {entitylen, entity};
psycString m = {methodlen, method}; psycString m = {methodlen, method};
psycString d = {datalen, data}; psycString d = {datalen, data};

View file

@ -2,23 +2,58 @@
#include "psyc/render.h" #include "psyc/render.h"
#include "psyc/syntax.h" #include "psyc/syntax.h"
inline size_t psyc_renderModifier(psycModifier *m, char *buffer) inline psycRenderRC psyc_renderList(psycList *list, char *buffer, size_t buflen)
{
size_t i, cur = 0;
psycString *elem;
if (list->length > buflen)
return PSYC_RENDER_ERROR; // return error if list doesn't fit in buffer
if (list->flag == PSYC_LIST_NEED_LENGTH)
{
for (i = 0; i < list->num_elems; i++)
{
elem = &list->elems[i];
if (i > 0)
buffer[cur++] = '|';
cur += itoa(elem->length, buffer + cur, 10);
buffer[cur++] = ' ';
memcpy(buffer + cur, elem->ptr, elem->length);
cur += elem->length;
}
}
else
{
for (i = 0; i < list->num_elems; i++)
{
elem = &list->elems[i];
buffer[cur++] = '|';
memcpy(buffer + cur, elem->ptr, elem->length);
cur += elem->length;
}
}
return PSYC_RENDER_SUCCESS;
}
inline size_t psyc_renderModifier(psycModifier *mod, char *buffer)
{ {
size_t cur = 0; size_t cur = 0;
buffer[cur++] = m->oper; buffer[cur++] = mod->oper;
memcpy(buffer + cur, m->name.ptr, m->name.length); memcpy(buffer + cur, mod->name.ptr, mod->name.length);
cur += m->name.length; cur += mod->name.length;
if (m->flag == PSYC_MODIFIER_NEED_LENGTH) if (mod->flag == PSYC_MODIFIER_NEED_LENGTH)
{ {
buffer[cur++] = ' '; buffer[cur++] = ' ';
//cur += sprintf(buffer + cur, "%ld", m->value.length); //cur += sprintf(buffer + cur, "%ld", mod->value.length);
cur += itoa(m->value.length, buffer + cur, 10); cur += itoa(mod->value.length, buffer + cur, 10);
} }
buffer[cur++] = '\t'; buffer[cur++] = '\t';
memcpy(buffer + cur, m->value.ptr, m->value.length); memcpy(buffer + cur, mod->value.ptr, mod->value.length);
cur += m->value.length; cur += mod->value.length;
buffer[cur++] = '\n'; buffer[cur++] = '\n';
return cur; return cur;

View file

@ -7,11 +7,9 @@
#define myUNI "psyc://10.100.1000/~ludwig" #define myUNI "psyc://10.100.1000/~ludwig"
/* example renderer generating a presence packet */ /* example renderer generating a presence packet */
int testPresence(const char *avail, int availlen, const char *desc, int desclen, const char *rendered) int testPresence(const char *avail, int availlen, const char *desc, int desclen, const char *rendered, uint8_t verbose)
{ {
psycModifier routing[] = { psycModifier routing[] = {
// psyc_newModifier2(C_GLYPH_OPERATOR_SET, PSYC_C2ARG("_source"), PSYC_C2ARG(myUNI),
// PSYC_MODIFIER_ROUTING),
psyc_newModifier2(C_GLYPH_OPERATOR_SET, PSYC_C2ARG("_context"), PSYC_C2ARG(myUNI), psyc_newModifier2(C_GLYPH_OPERATOR_SET, PSYC_C2ARG("_context"), PSYC_C2ARG(myUNI),
PSYC_MODIFIER_ROUTING), PSYC_MODIFIER_ROUTING),
}; };
@ -19,9 +17,9 @@ int testPresence(const char *avail, int availlen, const char *desc, int desclen,
psycModifier entity[] = { psycModifier entity[] = {
// presence is to be assigned permanently in distributed state // presence is to be assigned permanently in distributed state
psyc_newModifier2(C_GLYPH_OPERATOR_ASSIGN, PSYC_C2ARG("_degree_availability"), psyc_newModifier2(C_GLYPH_OPERATOR_ASSIGN, PSYC_C2ARG("_degree_availability"),
avail, availlen, PSYC_PACKET_CHECK_LENGTH), avail, availlen, PSYC_MODIFIER_CHECK_LENGTH),
psyc_newModifier2(C_GLYPH_OPERATOR_ASSIGN, PSYC_C2ARG("_description_presence"), psyc_newModifier2(C_GLYPH_OPERATOR_ASSIGN, PSYC_C2ARG("_description_presence"),
desc, desclen, PSYC_PACKET_CHECK_LENGTH), desc, desclen, PSYC_MODIFIER_CHECK_LENGTH),
}; };
psycPacket packet = psyc_newPacket2(routing, PSYC_NUM_ELEM(routing), psycPacket packet = psyc_newPacket2(routing, PSYC_NUM_ELEM(routing),
@ -33,18 +31,86 @@ int testPresence(const char *avail, int availlen, const char *desc, int desclen,
char buffer[512]; char buffer[512];
psyc_render(&packet, buffer, sizeof(buffer)); psyc_render(&packet, buffer, sizeof(buffer));
// write(0, buffer, packet.length); if (verbose)
write(0, buffer, packet.length);
return strncmp(rendered, buffer, packet.length); return strncmp(rendered, buffer, packet.length);
} }
int main() { int testList(const char *rendered, uint8_t verbose)
int rc = testPresence(PSYC_C2ARG("_here"), PSYC_C2ARG("I'm omnipresent right now"), "\ {
psycModifier routing[] = {
psyc_newModifier2(C_GLYPH_OPERATOR_SET, PSYC_C2ARG("_source"), PSYC_C2ARG(myUNI),
PSYC_MODIFIER_ROUTING),
psyc_newModifier2(C_GLYPH_OPERATOR_SET, PSYC_C2ARG("_context"), PSYC_C2ARG(myUNI),
PSYC_MODIFIER_ROUTING),
};
psycString elems_text[] = {
PSYC_C2STR("foo"),
PSYC_C2STR("bar"),
PSYC_C2STR("baz"),
};
psycString elems_bin[] = {
PSYC_C2STR("foo"),
PSYC_C2STR("b|r"),
PSYC_C2STR("baz\nqux"),
};
psycList list_text, list_bin;
list_text = psyc_newList(elems_text, PSYC_NUM_ELEM(elems_text), PSYC_LIST_CHECK_LENGTH);
list_bin = psyc_newList(elems_bin, PSYC_NUM_ELEM(elems_bin), PSYC_LIST_CHECK_LENGTH);
char buf_text[32], buf_bin[32];
psyc_renderList(&list_text, buf_text, sizeof(buf_text));
psyc_renderList(&list_bin, buf_bin, sizeof(buf_bin));
psycModifier entity[] = {
// presence is to be assigned permanently in distributed state
psyc_newModifier2(C_GLYPH_OPERATOR_SET, PSYC_C2ARG("_list_text"),
buf_text, list_text.length, list_text.flag),
psyc_newModifier2(C_GLYPH_OPERATOR_SET, PSYC_C2ARG("_list_binary"),
buf_bin, list_bin.length, list_text.flag),
};
psycPacket packet = psyc_newPacket2(routing, PSYC_NUM_ELEM(routing),
entity, PSYC_NUM_ELEM(entity),
PSYC_C2ARG("_test_list"),
PSYC_C2ARG("list test"),
PSYC_PACKET_CHECK_LENGTH);
char buffer[512];
psyc_render(&packet, buffer, sizeof(buffer));
if (verbose)
write(0, buffer, packet.length);
return strncmp(rendered, buffer, packet.length);
}
int main(int argc, char* argv[]) {
uint8_t verbose = argc > 1;
if (testPresence(PSYC_C2ARG("_here"), PSYC_C2ARG("I'm omnipresent right now"), "\
:_context\t" myUNI "\n\ :_context\t" myUNI "\n\
\n\ \n\
=_degree_availability\t_here\n\ =_degree_availability\t_here\n\
=_description_presence\tI'm omnipresent right now\n\ =_description_presence\tI'm omnipresent right now\n\
_notice_presence\n\ _notice_presence\n\
|\n"); |\n", verbose))
unless (rc) puts("psyc_render passed the test."); return -1;
return rc;
if (testList("\
:_source psyc://10.100.1000/~ludwig\n\
:_context psyc://10.100.1000/~ludwig\n\
\n\
:_list_text |foo|bar|baz\n\
:_list_binary 21 3 foo|3 b|r|7 baz\n\
qux\n\
_test_list\n\
list test\n\
|\n", verbose))
return -2;
puts("psyc_render passed all tests.");
return 0;
} }