mirror of
git://git.psyc.eu/libpsyc
synced 2024-08-15 03:19:02 +00:00
list rendering
This commit is contained in:
parent
1a0b28003d
commit
a252040c62
5 changed files with 198 additions and 39 deletions
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
{
|
{
|
||||||
|
|
64
src/packet.c
64
src/packet.c
|
@ -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};
|
||||||
|
|
||||||
|
|
53
src/render.c
53
src/render.c
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue