libpsyc/src/packet.c

183 lines
4.9 KiB
C
Raw Normal View History

#include <psyc/lib.h>
#include <psyc/syntax.h>
#include <math.h>
inline psycString psyc_newString(const char *str, size_t strlen)
{
psycString s = {strlen, str};
return s;
}
inline psycModifierFlag psyc_checkModifierLength(psycModifier *m)
{
psycModifierFlag flag;
if (m->value.length > PSYC_MODIFIER_SIZE_THRESHOLD)
flag = PSYC_MODIFIER_NEED_LENGTH;
else if (memchr(m->value.ptr, (int)'\n', m->value.length))
flag = PSYC_MODIFIER_NEED_LENGTH;
else
flag = PSYC_MODIFIER_NO_LENGTH;
return flag;
}
inline size_t psyc_getModifierLength(psycModifier *m)
{
size_t length = 1 + // oper
m->name.length + 1 + // name\t
m->value.length + 1; // value\n
if (m->flag == PSYC_MODIFIER_NEED_LENGTH) // add length of length if needed
length += log10((double)m->value.length) + 2; // SP length
return length;
}
inline psycModifier psyc_newModifier(char oper, psycString *name, psycString *value,
2011-04-26 15:23:06 +00:00
psycModifierFlag flag)
{
psycModifier m = {oper, *name, *value, flag};
if (flag == PSYC_MODIFIER_CHECK_LENGTH) // find out if it needs a length
m.flag = psyc_checkModifierLength(&m);
return m;
}
inline psycModifier psyc_newModifier2(char oper,
2011-04-26 15:23:06 +00:00
const char *name, size_t namelen,
const char *value, size_t valuelen,
psycModifierFlag flag)
{
psycString n = {namelen, name};
psycString v = {valuelen, value};
return psyc_newModifier(oper, &n, &v, flag);
}
inline psycListFlag psyc_checkListLength(psycList *list)
2011-04-26 15:23:06 +00:00
{
psycListFlag flag = PSYC_LIST_NO_LENGTH;
size_t i, length = 0;
2011-04-26 15:23:06 +00:00
for (i = 0; i < list->num_elems; i++)
2011-04-26 15:23:06 +00:00
{
psycString *elem = &list->elems[i];
length += 1 + elem->length; // |elem
if (length > PSYC_MODIFIER_SIZE_THRESHOLD ||
memchr(elem->ptr, (int)'|', elem->length) ||
memchr(elem->ptr, (int)'\n', elem->length))
2011-04-26 15:23:06 +00:00
{
flag = PSYC_LIST_NEED_LENGTH;
break;
2011-04-26 15:23:06 +00:00
}
}
return flag;
}
inline psycListFlag psyc_getListLength(psycList *list)
{
size_t i, length = 0;
if (list->flag == PSYC_LIST_NEED_LENGTH)
2011-04-26 15:23:06 +00:00
{
for (i = 0; i < list->num_elems; i++)
2011-04-26 15:23:06 +00:00
{
if (i > 0)
length++; // |
length += log10((double)list->elems[i].length) + 2 + list->elems[i].length; // length SP elem
2011-04-26 15:23:06 +00:00
}
}
else
{
for (i = 0; i < list->num_elems; i++)
length += 1 + list->elems[i].length; // |elem
2011-04-26 15:23:06 +00:00
}
return length;
}
inline psycList psyc_newList(psycString *elems, size_t num_elems, psycListFlag flag)
{
psycList list = {num_elems, elems, 0, flag};
if (flag == PSYC_LIST_CHECK_LENGTH) // check if list elements need length
list.flag = psyc_checkListLength(&list);
list.length = psyc_getListLength(&list);
2011-04-26 15:23:06 +00:00
return list;
}
inline psycPacketFlag psyc_checkPacketLength(psycPacket *p)
{
psycPacketFlag flag;
if (p->data.length == 1 && p->data.ptr[0] == C_GLYPH_PACKET_DELIMITER)
flag = PSYC_PACKET_NEED_LENGTH;
else if (p->data.length > PSYC_CONTENT_SIZE_THRESHOLD)
flag = PSYC_PACKET_NEED_LENGTH;
else if (memmem(p->data.ptr, p->data.length, PSYC_C2ARG(PSYC_PACKET_DELIMITER)))
flag = PSYC_PACKET_NEED_LENGTH;
else
flag = PSYC_PACKET_NO_LENGTH;
return flag;
}
inline size_t psyc_setPacketLength(psycPacket *p)
{
size_t i;
2011-04-25 19:57:03 +00:00
// add routing header length
for (i = 0; i < p->routing.lines; i++)
p->routingLength += psyc_getModifierLength(&(p->routing.modifiers[i]));
2011-04-25 19:57:03 +00:00
// add entity header length
for (i = 0; i < p->entity.lines; i++)
p->contentLength += psyc_getModifierLength(&(p->entity.modifiers[i]));
// add length of method, data & delimiter
if (p->method.length)
p->contentLength += p->method.length + 1; // method\n
if (p->data.length)
p->contentLength += p->data.length + 1; // data\n
2011-04-25 19:57:03 +00:00
// set total length: routing-header \n content |\n
p->length = p->routingLength + 1 + p->contentLength + sizeof(PSYC_PACKET_DELIMITER) - 2;
if (p->flag == PSYC_PACKET_NEED_LENGTH) // add length of length if needed
p->length += log10((double)p->data.length) + 1;
return p->length;
}
inline psycPacket psyc_newPacket(psycHeader *routing,
psycHeader *entity,
psycString *method, psycString *data,
psycPacketFlag flag)
{
psycPacket p = {*routing, *entity, *method, *data, 0, 0, flag};
if (flag == PSYC_PACKET_CHECK_LENGTH) // find out if it needs a length
p.flag = psyc_checkPacketLength(&p);
psyc_setPacketLength(&p);
return p;
}
inline psycPacket psyc_newPacket2(psycModifier *routing, size_t routinglen,
2011-04-26 15:23:06 +00:00
psycModifier *entity, size_t entitylen,
const char *method, size_t methodlen,
const char *data, size_t datalen,
psycPacketFlag flag)
{
2011-04-26 15:23:06 +00:00
psycHeader r = {routinglen, routing};
psycHeader e = {entitylen, entity};
psycString m = {methodlen, method};
psycString d = {datalen, data};
return psyc_newPacket(&r, &e, &m, &d, flag);
}