parser: fixes routing-only mode, set valueParsed & valueLength for data as well; render: added support for rendering raw content

This commit is contained in:
tg(x) 2011-05-06 00:13:37 +02:00
parent fea30e3688
commit fd5d886053
6 changed files with 116 additions and 46 deletions

View File

@ -39,12 +39,12 @@ typedef enum
typedef enum
{
PSYC_PART_RESET = -1,
PSYC_PART_ROUTING,
PSYC_PART_LENGTH,
PSYC_PART_CONTENT,
PSYC_PART_METHOD,
PSYC_PART_DATA,
PSYC_PART_END,
PSYC_PART_ROUTING = 0,
PSYC_PART_LENGTH = 1,
PSYC_PART_CONTENT = 2,
PSYC_PART_METHOD = 3,
PSYC_PART_DATA = 4,
PSYC_PART_END = 5,
} psycPart;
/**

View File

@ -56,6 +56,7 @@ typedef struct
psycHeader entity; ///< Entity header.
psycString method;
psycString data;
psycString content;
size_t routingLength; ///< Length of routing part.
size_t contentLength; ///< Length of content part.
size_t length; ///< Total length of packet.
@ -135,4 +136,11 @@ psycPacket psyc_newPacket2 (psycModifier *routing, size_t routinglen,
const char *data, size_t datalen,
psycPacketFlag flag);
psycPacket psyc_newPacketContent (psycHeader *routing, psycString *content,
psycPacketFlag flag);
psycPacket psyc_newPacketContent2 (psycModifier *routing, size_t routinglen,
const char *content, size_t contentlen,
psycPacketFlag flag);
#endif // PSYC_PACKET_H

View File

@ -4,7 +4,7 @@
*
* All parsing functions and the definitions they use are
* defined in this file.
*/
*/
/**
* @defgroup parser Parsing Functions

View File

@ -114,15 +114,20 @@ size_t psyc_setPacketLength(psycPacket *p)
for (i = 0; i < p->routing.lines; i++)
p->routingLength += psyc_getModifierLength(&(p->routing.modifiers[i]));
// add entity header length
for (i = 0; i < p->entity.lines; i++)
p->contentLength += psyc_getModifierLength(&(p->entity.modifiers[i]));
if (p->content.length)
p->contentLength = p->content.length;
else
{
// 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
// 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
}
// set total length: routing-header content |\n
p->length = p->routingLength + p->contentLength + 2;
@ -141,7 +146,7 @@ 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}, 0, 0, flag};
if (flag == PSYC_PACKET_CHECK_LENGTH) // find out if it needs a length
p.flag = psyc_checkPacketLength(&p);
@ -164,3 +169,27 @@ psycPacket psyc_newPacket2 (psycModifier *routing, size_t routinglen,
return psyc_newPacket(&r, &e, &m, &d, flag);
}
inline
psycPacket psyc_newPacketContent (psycHeader *routing, psycString *content,
psycPacketFlag flag)
{
psycPacket p = {*routing, {0,0}, {0,0}, {0,0}, *content, 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_newPacketContent2 (psycModifier *routing, size_t routinglen,
const char *content, size_t contentlen,
psycPacketFlag flag)
{
psycHeader r = {routinglen, routing};
psycString c = {contentlen, content};
return psyc_newPacketContent(&r, &c, flag);
}

View File

@ -222,6 +222,7 @@ psycParseRC psyc_parse (psycParseState *state, char *oper,
case PSYC_PART_RESET: // New packet starts here, reset state.
state->valueParsed = 0;
state->valueLength = 0;
state->valueLengthFound = 0;
state->routingLength = 0;
state->contentParsed = 0;
state->contentLength = 0;
@ -354,6 +355,10 @@ psycParseRC psyc_parse (psycParseState *state, char *oper,
if (state->buffer.ptr[state->cursor] != '\n')
return PSYC_PARSE_ERROR_METHOD;
state->valueLengthFound = 0;
state->valueParsed = 0;
state->valueLength = 0;
if (state->contentLengthFound)
{ // if length was found set start position to the beginning of data
state->cursor++;
@ -362,7 +367,9 @@ psycParseRC psyc_parse (psycParseState *state, char *oper,
state->part = PSYC_PART_DATA;
}
else // otherwise keep it at the beginning of method
{
ADVANCE_CURSOR_OR_RETURN(PSYC_PARSE_INSUFFICIENT);
}
// fall thru
}
@ -380,19 +387,21 @@ psycParseRC psyc_parse (psycParseState *state, char *oper,
if (state->contentLengthFound) // We know the length of the packet.
{
if (state->contentParsed < state->contentLength &&
psyc_parseBinaryValue(state, value, &(state->contentLength),
&(state->contentParsed)) == PSYC_PARSE_INCOMPLETE)
return PSYC_PARSE_BODY_INCOMPLETE;
if (!state->valueLengthFound) // start of data
{
state->valueLengthFound = 1;
state->valueLength = state->contentLength - state->contentParsed; // length of data
if (state->valueLength && !(state->flags & PSYC_PARSE_ROUTING_ONLY))
state->valueLength--; // \n at the end is not part of data
}
if (state->valueParsed < state->valueLength)
{
ret = psyc_parseBinaryValue(state, value, &(state->valueLength), &(state->valueParsed));
state->contentParsed += value->length;
if (value->length)
value->length--; // \n at the end is not part of the body
if (state->cursor >= state->buffer.length)
return PSYC_PARSE_BODY;
if (state->buffer.ptr[state->cursor] != '|')
return PSYC_PARSE_ERROR_BODY;
if (ret == PSYC_PARSE_INCOMPLETE)
return PSYC_PARSE_BODY_INCOMPLETE;
}
state->part = PSYC_PART_END;
return PSYC_PARSE_BODY;
@ -415,6 +424,9 @@ psycParseRC psyc_parse (psycParseState *state, char *oper,
if (state->buffer.ptr[state->cursor+nl] == '|' &&
state->buffer.ptr[state->cursor+1+nl] == '\n') // packet ends here
{
if (state->flags & PSYC_PARSE_ROUTING_ONLY)
value->length++;
state->contentParsed += state->cursor - pos;
state->cursor += nl;
state->part = PSYC_PART_END;
@ -428,6 +440,19 @@ psycParseRC psyc_parse (psycParseState *state, char *oper,
case PSYC_PART_END:
PSYC_PART_END:
if (state->contentLengthFound && state->valueLengthFound && state->valueLength &&
!(state->flags & PSYC_PARSE_ROUTING_ONLY))
{ // if data was not empty next is the \n at the end of data
state->valueLength = 0;
state->valueLengthFound = 0;
if (state->buffer.ptr[state->cursor] != '\n')
return PSYC_PARSE_ERROR_END;
state->contentParsed++;
state->cursor++;
}
// End of packet, at this point we have already passed a \n
// and the cursor should point to |
if (state->cursor+1 >= state->buffer.length) // incremented cursor inside length?

View File

@ -82,29 +82,37 @@ psycRenderRC psyc_render (psycPacket *packet, char *buffer, size_t buflen)
if (packet->flag == PSYC_PACKET_NEED_LENGTH)
cur += itoa(packet->contentLength, buffer + cur, 10);
if (packet->flag == PSYC_PACKET_NEED_LENGTH ||
if (packet->flag == PSYC_PACKET_NEED_LENGTH || packet->content.length ||
packet->entity.lines || packet->method.length || packet->data.length)
buffer[cur++] = '\n'; // start of content part if there's content or length
// render entity modifiers
for (i = 0; i < packet->entity.lines; i++)
cur += psyc_renderModifier(&packet->entity.modifiers[i], buffer + cur);
if (packet->method.length) // add method\n
if (packet->content.length) // render raw content if present
{
memcpy(buffer + cur, packet->method.ptr, packet->method.length);
cur += packet->method.length;
buffer[cur++] = '\n';
if (packet->data.length) // add data\n
{
memcpy(buffer + cur, packet->data.ptr, packet->data.length);
cur += packet->data.length;
buffer[cur++] = '\n';
}
memcpy(buffer + cur, packet->content.ptr, packet->content.length);
cur += packet->content.length;
}
else
{
// render entity modifiers
for (i = 0; i < packet->entity.lines; i++)
cur += psyc_renderModifier(&packet->entity.modifiers[i], buffer + cur);
if (packet->method.length) // add method\n
{
memcpy(buffer + cur, packet->method.ptr, packet->method.length);
cur += packet->method.length;
buffer[cur++] = '\n';
if (packet->data.length) // add data\n
{
memcpy(buffer + cur, packet->data.ptr, packet->data.length);
cur += packet->data.length;
buffer[cur++] = '\n';
}
}
else if (packet->data.length) // error, we have data but no modifier
return PSYC_RENDER_ERROR_METHOD_MISSING;
}
else if (packet->data.length) // error, we have data but no modifier
return PSYC_RENDER_ERROR_METHOD_MISSING;
// add packet delimiter
buffer[cur++] = C_GLYPH_PACKET_DELIMITER;