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

parser fixes & refactoring; added more tests

This commit is contained in:
tg(x) 2011-04-19 09:21:00 +02:00
parent 344f327e19
commit a0ab246127
21 changed files with 479 additions and 406 deletions

View file

@ -9,15 +9,35 @@ enum PSYC_Flags
enum PSYC_ReturnCodes enum PSYC_ReturnCodes
{ {
PSYC_ERROR_EXPECTED_TAB = -8, PSYC_ERROR_END = -7,
PSYC_ERROR_METHOD = -6,
PSYC_ERROR_VAR_LEN = -5,
PSYC_ERROR_VAR_TAB = -4,
PSYC_ERROR_VAR_NAME = -3,
PSYC_ERROR_LENGTH = -2,
PSYC_ERROR = -1,
PSYC_SUCCESS = 0,
PSYC_BODY = 1, PSYC_BODY = 1,
PSYC_BODY_INCOMPLETE, PSYC_BODY_INCOMPLETE = 2,
PSYC_INSUFFICIENT, PSYC_INSUFFICIENT = 3,
PSYC_ROUTING, PSYC_ROUTING = 4,
PSYC_ENTITY, PSYC_ENTITY = 5,
PSYC_ENTITY_INCOMPLETE, PSYC_ENTITY_INCOMPLETE = 6,
PSYC_HEADER_COMPLETE, PSYC_HEADER_COMPLETE = 7,
PSYC_COMPLETE, PSYC_COMPLETE = 8,
PSYC_INCOMPLETE = 9,
};
enum PSYC_Parts
{
PSYC_PART_RESET = -1,
PSYC_PART_HEADER = 0,
PSYC_PART_LENGTH,
PSYC_PART_HEADER_END,
PSYC_PART_CONTENT,
PSYC_PART_METHOD,
PSYC_PART_DATA,
PSYC_PART_END,
}; };
@ -30,14 +50,17 @@ typedef struct
typedef struct typedef struct
{ {
unsigned int cursor; // current position in buffer unsigned int cursor; /** current position in buffer */
unsigned int startc; /** line start position */
PSYC_Array buffer; PSYC_Array buffer;
uint8_t flags; uint8_t flags;
char part; /** part of the packet being parsed currently, see PSYC_Parts */
unsigned int contentParsed; // unsigned int contentParsed; /** number of bytes parsed from the content so far */
char inContent; unsigned int contentLength; /** expected length of the content */
unsigned int valueRemaining; char contentLengthFound; /** is there a length given for this packet? */
unsigned int contentLength; unsigned int valueParsed; /** number of bytes parsef from the value so far */
unsigned int valueLength; /** expected length of the value */
} PSYC_State; } PSYC_State;
#ifndef PSYC_COMPILE_LIBRARY #ifndef PSYC_COMPILE_LIBRARY
@ -83,12 +106,6 @@ inline unsigned int PSYC_getContentLength (PSYC_State* s)
return s->contentLength; return s->contentLength;
} }
inline unsigned int PSYC_getValueRemaining (PSYC_State* s)
{
return s->valueRemaining;
}
#endif #endif
int PSYC_parse(PSYC_State* state, int PSYC_parse(PSYC_State* state, uint8_t* modifier, PSYC_Array* name, PSYC_Array* value);
uint8_t* modifier, PSYC_Array* name, PSYC_Array* value);

View file

@ -1,3 +1,4 @@
CFLAGS=-I../../include -DDEBUG -DPSYC_COMPILE_LIBRARY -g -O0 -Wall
CC=cc -I../include CC=cc -I../include
# CC=clang # CC=clang
@ -8,11 +9,11 @@ default:
@/bin/echo -e "Usage:\n\tmake diet - compile with diet libc\n\tmake lib - compile with normal gnu libc" @/bin/echo -e "Usage:\n\tmake diet - compile with diet libc\n\tmake lib - compile with normal gnu libc"
diet: diet:
diet ${CC} -static -c -Os $S -DDEBUG -DPSYC_COMPILE_LIBRARY diet ${CC} -static -c -Os $S ${CFLAGS}
diet ar rcs libpsyc.a $O diet ar rcs libpsyc.a $O
lib: $S lib: $S
${CC} -static -c -g -O0 $S -lc -DDEBUG -DPSYC_COMPILE_LIBRARY ${CC} -static -c -g -O0 $S -lc ${CFLAGS}
ar rcs libpsyc.a $O ar rcs libpsyc.a $O
match: match.c match: match.c

View file

@ -7,6 +7,13 @@
#include <psyc/parser.h> #include <psyc/parser.h>
#define ADVANCE_CURSOR_OR_RETURN() \
if (++(state->cursor) >= state->buffer.length) \
{ \
state->cursor = state->startc; \
return PSYC_INSUFFICIENT; \
}
/** @brief isGlyph /** @brief isGlyph
* *
* @todo: document this function * @todo: document this function
@ -16,9 +23,10 @@ inline char isGlyph(uint8_t g)
switch(g) switch(g)
{ {
case ':': case ':':
case '-':
case '+':
case '=': case '=':
case '?':
case '+':
case '-':
return 1; return 1;
default: default:
return 0; return 0;
@ -26,411 +34,319 @@ inline char isGlyph(uint8_t g)
} }
inline char isNumeric(uint8_t c) inline char isNumeric(uint8_t c)
{ {
return c >= '0' && c <= '9' ; return c >= '0' && c <= '9';
} }
inline char isAlphaNumeric(uint8_t c) inline char isAlphaNumeric(uint8_t c)
{ {
return return
(( c >= 'a' && c <= 'z' )|| (c >= 'a' && c <= 'z') ||
( c >= 'A' && c <= 'Z' )|| (c >= 'A' && c <= 'Z') ||
isNumeric(c)) isNumeric(c);
;
} }
inline char isKwChar(uint8_t c)
/** @brief generalized linebased parser */
inline int PSYC_parse(
PSYC_State* state,
uint8_t* modifier, PSYC_Array* name, PSYC_Array* value)
{ {
start: return c == '_' || isAlphaNumeric(c);
}
if (state->valueRemaining != 0) /**
goto binaryArg; * @brief Parse variable name or method name.
* @details It should contain one or more keyword characters.
/* first we test if we can access the first char */ * @return PSYC_ERROR or PSYC_SUCCESS
if(state->buffer.length<=state->cursor) // cursor is not inside the length
return PSYC_INSUFFICIENT; // return insufficient data.
// in case we return insufficent, we rewind to the start.
unsigned int startc=state->cursor;
/******************************************
* * * * * * * Inspect Header * * * * * * *
*******************************************/
/* each line of the header starts with a glyph.
* iE :_name, -_name +_name etc, so just test if
* the first char is a glyph. */
if(0==state->inContent)
{
if(!isGlyph(state->buffer.ptr[state->cursor])) // is the first char not a glyph?
{ // parse length of content here
if(isNumeric(state->buffer.ptr[state->cursor]))
{
if(state->buffer.length<=++(state->cursor)) // incremented cursor inside length?
{
state->cursor=startc; // set to start value
return PSYC_INSUFFICIENT; // return insufficient
}
while(isNumeric(state->buffer.ptr[state->cursor]));
{
state->contentLength = 10 * state->contentLength + state->buffer.ptr[state->cursor] - '0';
if(state->buffer.length<=++(state->cursor)) // incremented cursor inside length?
{
state->cursor=startc; // set to start value
return PSYC_INSUFFICIENT; // return insufficient
}
}
}
// header ends with a NL
if (state->buffer.ptr[state->cursor] != '\n')
{
return -10;
}
if (state->buffer.length<=++(state->cursor)) // incremented cursor inside length?
{
state->cursor=startc; // set to start value
return PSYC_INSUFFICIENT; // return insufficient
}
// the only other possibility now is that the packet
// is complete(empty packet) or that the method started.
if (isAlphaNumeric(state->buffer.ptr[state->cursor]))
{
state->inContent = 1;
if (state->flags & PSYC_HEADER_ONLY)
return PSYC_HEADER_COMPLETE; // return header finished
else
goto start;
}
if (state->buffer.ptr[state->cursor] == '|')
{
if (state->buffer.length<=++(state->cursor)) // incremented cursor inside length?
{
state->cursor=startc; // set to start value
return PSYC_INSUFFICIENT; // return insufficient
}
if (state->buffer.ptr[state->cursor]=='\n')
{
++(state->cursor);
state->inContent = 0;
return PSYC_COMPLETE; // return packet finished
}
}
return -6; // report error
}
else // it is a glyph, so a variable name starts here
{
/***************************************************
* * * * * * * Routing Variable Start * * * * * * *
**************************************************/
*modifier = *(state->buffer.ptr+state->cursor);
if (state->buffer.length <= ++(state->cursor))
{
state->cursor = startc; // rewind to start of line
return PSYC_INSUFFICIENT; // return insufficient
}
name->ptr = state->buffer.ptr + state->cursor;
name->length = 1;
}
} // endif inContent=0
char method=0;
/* each line of the header starts with a glyph.
* iE :_name, -_name +_name etc, so just test if
* the first char is a glyph. */
/* in the body, the same applies, only that the
* method does not start with a glyph.*/
if(1==state->inContent)
{
if(!isGlyph(state->buffer.ptr[state->cursor]))
{
if(!isAlphaNumeric(state->buffer.ptr[state->cursor]) && state->buffer.ptr[state->cursor] != '_')
{
// the body rule is optional, which means
// that now also just |\n can follow.
if(state->buffer.ptr[state->cursor] == '|')
{
if(state->buffer.length<=++(state->cursor)) // incremented cursor inside length?
{
state->cursor=startc; // set to start value
return PSYC_INSUFFICIENT; // return insufficient
}
if(state->buffer.ptr[state->cursor]=='\n')
{
++(state->cursor);
state->inContent = 0;
return PSYC_COMPLETE; // return packet finished
}
}
return -5; // report error
}
else
{
name->ptr = state->buffer.ptr+state->cursor;
name->length=1;
method=1;
}
}
else
{
*modifier = *(state->buffer.ptr+state->cursor);
if (state->buffer.length <= ++(state->cursor))
{
state->cursor = startc; // rewind
return PSYC_INSUFFICIENT; // return insufficient
}
name->ptr = state->buffer.ptr+state->cursor;
name->length=1;
}
}
/* validate the incremented cursor */
if(state->buffer.length <= ++(state->cursor))
{
state->cursor=startc;
return PSYC_INSUFFICIENT;
}
/* what follows is the name. At least one char.
* allowed is alphanumeric and _ */
// first char must exist.
if(!isAlphaNumeric(state->buffer.ptr[state->cursor]) // is it not alphanum
&& state->buffer.ptr[state->cursor] != '_') // AND not '_'. must be invalid then
return -1; // return parser error.
name->length+=1;
/* now checking how long the name of the variable is. */
unsigned int i=0;
while(1)
{
if(state->buffer.length<= ++(state->cursor)) // incremented cursor inside length?
{
state->cursor=startc; // set to start value
return PSYC_INSUFFICIENT; // return insufficient
}
// same as bevore
if(!isAlphaNumeric(state->buffer.ptr[state->cursor]) &&
state->buffer.ptr[state->cursor] != '_')
break; // not valid? then stop the loop right here
++(name->length); // was a valid char, increase length
}
/* we now parsed the variable name successfully
* after the name either a \n or a \t follows.
*
* for the method, the data starts after an \n
* so checking for \n too here
* We dont check if cursor inside length, because
* the last loop iteration did that already.
*/ */
if(state->buffer.ptr[state->cursor] == '\t' || state->buffer.ptr[state->cursor] == '\n') // && method==1)) inline int PSYC_parseName(PSYC_State* state, PSYC_Array* name)
{
name->ptr = state->buffer.ptr + state->cursor;
name->length = 0;
while (isKwChar(state->buffer.ptr[state->cursor]))
{ {
/* after the \t the data follows, which is name->length++; // was a valid char, increase length
* anything but \n. data can be of length 0 ADVANCE_CURSOR_OR_RETURN();
*
* for the method: after the \n data follows,
* which is anything but \n|\n
*
* but data is optional, so we first check
* here if data follows at all.
*
* arg-data=value. we set value here so it
* points to a valid range and so we point
* to the first potential arg-data byte.
* If there is no arg-data, we still have
* the length attribute on 0. */
if((method == 0 && state->buffer.ptr[state->cursor] == '\n') /* emptyvar */ ||
(method == 1 && state->cursor+2 < state->buffer.length &&
state->buffer.ptr[state->cursor+1] == '|' &&
state->buffer.ptr[state->cursor+2] == '\n') /*no data */ )
{
value->ptr=state->buffer.ptr+state->cursor;
value->length=0;
} }
else
return name->length > 0 ? PSYC_SUCCESS : PSYC_ERROR;
}
/**
* @brief Parse binary data into value.
* @details length is the expected length of the data, parsed is the number of bytes parsed so far
* @return PSYC_COMPLETE or PSYC_INCOMPLETE
*/
inline int PSYC_parseBinaryValue(PSYC_State* state, PSYC_Array* value, unsigned int* length, unsigned int* parsed)
{
unsigned int remaining = *length - *parsed;
value->ptr = state->buffer.ptr + state->cursor;
if (state->cursor + remaining > state->buffer.length) // is the length larger than this buffer?
{ {
value->ptr=state->buffer.ptr+state->cursor+1;
if (0 != state->contentLength) // we know the length of the packet
{
// is the packet in the buffer?
if (value->ptr + state->contentLength + 3 > state->buffer.ptr + state->buffer.length)
{ // no
value->length = state->buffer.length - state->cursor; value->length = state->buffer.length - state->cursor;
//*expectedBytes = state->contentLength - value->length; *parsed += value->length;
} state->cursor = 0;
else // yes, the packet is complete in the buffer. return PSYC_INCOMPLETE;
{
value->length= state->buffer.length - state->cursor -3;
//*expectedBytes = 0;
}
}
else // else search for the terminator
{
value->length=0;
while (1)
{
if(state->buffer.length<=++(state->cursor)) // incremented cursor inside length?
{
state->cursor=startc; // set to start value
return PSYC_INSUFFICIENT ; // return insufficient
} }
if(0 == method && state->buffer.ptr[state->cursor] == '\n') value->length += remaining;
break; state->cursor += remaining;
*parsed += value->length;
if(1 == method && state->buffer.ptr[state->cursor] == '\n')
{
if(state->buffer.length<=(state->cursor)+2) // incremented cursor inside length?
{
state->cursor=startc; // set to start value
return PSYC_INSUFFICIENT; // return insufficient
}
if(state->buffer.ptr[state->cursor+1] == '|')
if(state->buffer.ptr[state->cursor+2] == '\n')
{
/* packet finishes here */
state->cursor+=3;
state->inContent = 0;
return PSYC_COMPLETE; return PSYC_COMPLETE;
} }
} /**
++(value->length); * @brief Parse simple or binary variable
} * @return PSYC_ERROR or PSYC_SUCCESS
} */
} inline int PSYC_parseVar(PSYC_State* state, uint8_t* modifier, PSYC_Array* name, PSYC_Array* value)
} {
else if(state->inContent == 1 && method==0 && state->buffer.ptr[state->cursor] == ' ') // oi, its a binary var! *modifier = *(state->buffer.ptr + state->cursor);
{ // after SP the length follows. ADVANCE_CURSOR_OR_RETURN();
if(state->buffer.length<=++(state->cursor)) // incremented cursor inside length?
{
state->cursor=startc; // set to start value
return PSYC_INSUFFICIENT; // return insufficient
}
while(isNumeric(state->buffer.ptr[state->cursor])) if (PSYC_parseName(state, name) != PSYC_SUCCESS)
{ return PSYC_ERROR_VAR_NAME;
value->length = 10 * value->length + state->buffer.ptr[state->cursor] - '0';
if(state->buffer.length<=++(state->cursor)) // incremented cursor inside length?
{
state->cursor=startc; // set to start value
return PSYC_INSUFFICIENT; // return insufficient
}
}
// after the length a TAB follows
if (state->buffer.ptr[state->cursor] != '\t')
return PSYC_ERROR_EXPECTED_TAB;
binaryArg:
if(state->buffer.length<=++(state->cursor)) // incremented cursor inside length?
{
state->valueRemaining = value->length - state->cursor;
state->cursor=0;
value->length = 0; value->length = 0;
value->ptr = state->buffer.ptr;
/* Parse the value.
* If we're in the content part check if it's a binary var */
if (state->part == PSYC_PART_CONTENT && state->buffer.ptr[state->cursor] == ' ') // binary arg
{ // after SP the length follows.
ADVANCE_CURSOR_OR_RETURN();
state->valueLength = 0;
state->valueParsed = 0;
if (isNumeric(state->buffer.ptr[state->cursor]))
{
do
{
state->valueLength = 10 * state->valueLength + state->buffer.ptr[state->cursor] - '0';
ADVANCE_CURSOR_OR_RETURN();
}
while (isNumeric(state->buffer.ptr[state->cursor]));
}
else
return PSYC_ERROR_VAR_LEN;
// after the length a TAB follows
if (state->buffer.ptr[state->cursor] != '\t')
return PSYC_ERROR_VAR_TAB;
if (state->buffer.length <= ++(state->cursor)) // incremented cursor inside length?
{
state->cursor = 0;
return PSYC_ENTITY_INCOMPLETE; return PSYC_ENTITY_INCOMPLETE;
} }
// is the length still in this buffer? if (PSYC_parseBinaryValue(state, value, &(state->valueLength), &(state->valueParsed)) == PSYC_INCOMPLETE)
if(state->buffer.length <= state->cursor+value->length+1 )
{
state->valueRemaining = value->length - state->cursor;
state->cursor=0;
value->ptr = state->buffer.ptr + state->cursor;
value->length = state->buffer.length - state->cursor;
return PSYC_ENTITY_INCOMPLETE; return PSYC_ENTITY_INCOMPLETE;
}
state->cursor++;
return PSYC_SUCCESS;
}
else if (state->buffer.ptr[state->cursor] == '\t') // simple arg
{
ADVANCE_CURSOR_OR_RETURN();
value->ptr = state->buffer.ptr + state->cursor; value->ptr = state->buffer.ptr + state->cursor;
state->cursor += value->length;
state->valueRemaining = 0; while (state->buffer.ptr[state->cursor] != '\n')
{
value->length++;
ADVANCE_CURSOR_OR_RETURN();
}
state->cursor++;
return PSYC_SUCCESS;
} }
else else
return -8; return PSYC_ERROR_VAR_TAB;
/* if there was a \t, then we parsed up until the
* \n char from the simple-arg rule ( \t arg-data \n )
*
* Now, if there would be no \t, we still would be at
* the point where a \n must follow.
*
* So, just checking \n here will cover both cases of
* the alternative ( simple-arg / \n ) from rule
* routing-modifier
*
* again, the loop has already validated the cursors
* position*/
if(state->buffer.ptr[state->cursor] != '\n')
return -2; // return parser error.
/* if a \n follows now, the an body is attached.
* if not, a |\n must follow */
if(state->buffer.length<=++(state->cursor)) // incremented cursor inside length?
{
state->cursor=startc; // set to start value
return PSYC_INSUFFICIENT; // return insufficient
}
if(0 == state->inContent && state->buffer.ptr[state->cursor] == '\n')
{
state->cursor+=1;
state->inContent = 1;
return PSYC_ROUTING; // return header finished
}
if(state->buffer.ptr[state->cursor] != '|') // no pipe, then only line complete, not the packet.
{
if (state->inContent == 0)
return PSYC_ROUTING;
else
return PSYC_ENTITY;
}
if(state->buffer.length<=++(state->cursor)) // incremented cursor inside length?
{
state->cursor=startc; // set to start value
return PSYC_INSUFFICIENT; // return insufficient
}
if(state->buffer.ptr[state->cursor] != '\n')
return -4;
state->cursor+=1;
state->inContent = 0;
return PSYC_COMPLETE; // packet is complete
} }
/** @brief generalized line-based parser */
int PSYC_parse(PSYC_State* state, uint8_t* modifier, PSYC_Array* name, PSYC_Array* value)
{
int ret; /* a return value */
unsigned int pos; /* a cursor position */
/* start position of the current line in the buffer
* in case we return insufficent, we rewind to this position */
state->startc = state->cursor;
/* first we test if we can access the first char */
if (state->buffer.length <= state->cursor) // cursor is not inside the length
return PSYC_INSUFFICIENT; // return insufficient data.
switch (state->part)
{
case PSYC_PART_RESET: // new packet starts here, reset state
state->valueParsed = 0;
state->valueLength = 0;
state->contentParsed = 0;
state->contentLength = 0;
state->contentLengthFound = 0;
state->part = PSYC_PART_HEADER;
// fall thru
case PSYC_PART_HEADER:
/* Each line of the header starts with a glyph,
* i.e. :_name, -_name +_name etc,
* so just test if the first char is a glyph.
*/
if (isGlyph(state->buffer.ptr[state->cursor])) // is the first char a glyph?
{ // it is a glyph, so a variable starts here
ret = PSYC_parseVar(state, modifier, name, value);
return ret == PSYC_SUCCESS ? PSYC_ROUTING : ret;
}
else // not a glyph
{
state->part = PSYC_PART_LENGTH;
// fall thru
}
case PSYC_PART_LENGTH:
/* End of header, content starts with an optional length then a NL */
if (isNumeric(state->buffer.ptr[state->cursor]))
{
state->contentLengthFound = 1;
state->contentLength = 0;
do
{
state->contentLength = 10 * state->contentLength + state->buffer.ptr[state->cursor] - '0';
ADVANCE_CURSOR_OR_RETURN();
}
while (isNumeric(state->buffer.ptr[state->cursor]));
}
if (state->buffer.ptr[state->cursor] == '\n') /* start of content */
{
/* If we need to parse the header only and we know the content length, then skip content parsing. */
if (state->flags & PSYC_HEADER_ONLY && state->contentLengthFound)
state->part = PSYC_PART_DATA;
else
state->part = PSYC_PART_CONTENT;
}
else /* not start of content, this must be the end */
{
/* if we have a length then it should've been followed by a \n */
if (state->contentLengthFound)
return PSYC_ERROR_LENGTH;
state->part = PSYC_PART_END;
goto PSYC_PART_END;
}
ADVANCE_CURSOR_OR_RETURN();
state->startc = state->cursor;
// fall thru
case PSYC_PART_CONTENT:
/* In case of an incomplete binary variable resume parsing it. */
if (state->valueParsed < state->valueLength) {
ret = PSYC_parseBinaryValue(state, value, &(state->valueLength), &(state->valueParsed));
state->contentParsed += value->length;
return ret == PSYC_COMPLETE ? PSYC_ENTITY : PSYC_ENTITY_INCOMPLETE;
}
/* Each line of the header starts with a glyph,
* i.e. :_name, -_name +_name etc.
* So just test if the first char is a glyph.
* In the body, the same applies, only that the
* method does not start with a glyph.
*/
if (isGlyph(state->buffer.ptr[state->cursor]))
{
pos = state->cursor;
ret = PSYC_parseVar(state, modifier, name, value);
state->contentParsed += state->cursor - pos;
return ret == PSYC_SUCCESS ? PSYC_ENTITY : ret;
}
else
{
state->part = PSYC_PART_METHOD;
state->startc = state->cursor;
// fall thru
}
case PSYC_PART_METHOD:
pos = state->cursor;
if (PSYC_parseName(state, name) == PSYC_SUCCESS)
{ /* the method ends with a \n then the data follows */
if (state->buffer.ptr[state->cursor] != '\n')
return PSYC_ERROR_METHOD;
state->cursor++;
state->startc = state->cursor;
state->contentParsed += state->cursor - pos;
state->part = PSYC_PART_DATA;
if (state->cursor >= state->buffer.length)
return PSYC_INSUFFICIENT;
// fall thru
}
else /* no method, which means the packet should end now */
{
state->part = PSYC_PART_END;
state->startc = state->cursor;
goto PSYC_PART_END;
}
case PSYC_PART_DATA:
value->ptr = state->buffer.ptr + state->cursor;
value->length = 0;
if (state->contentLengthFound) // we know the length of the packet
{
if (PSYC_parseBinaryValue(state, value, &(state->contentLength), &(state->contentParsed)) == PSYC_INCOMPLETE)
return PSYC_BODY_INCOMPLETE;
state->cursor++;
state->part = PSYC_PART_END;
return PSYC_BODY;
}
else // search for the terminator
{
while (1)
{
if (state->buffer.ptr[state->cursor] == '\n')
{
if (state->cursor+2 >= state->buffer.length) // incremented cursor inside length?
{
state->cursor = state->startc; // set to start value
return PSYC_INSUFFICIENT; // return insufficient
}
if (state->buffer.ptr[state->cursor+1] == '|' &&
state->buffer.ptr[state->cursor+2] == '\n') /* packet ends here */
{
state->cursor++;
state->part = PSYC_PART_END;
return PSYC_BODY;
}
}
value->length++;
ADVANCE_CURSOR_OR_RETURN();
}
}
case PSYC_PART_END:
PSYC_PART_END:
/* 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?
return PSYC_INSUFFICIENT; // return insufficient
if (state->buffer.ptr[state->cursor] == '|' &&
state->buffer.ptr[state->cursor+1] == '\n') /* packet ends here */
{
state->cursor += 2;
state->part = PSYC_PART_RESET;
return PSYC_COMPLETE;
}
else /* packet should've ended here, return error */
{
state->part = PSYC_PART_RESET;
return PSYC_ERROR_END;
}
}
return PSYC_ERROR; // should not be reached
}

View file

@ -1,16 +1,12 @@
CFLAGS=-I../../include -DDEBUG -g -O0 CFLAGS=-I../../include -DDEBUG -g -O0 -Wall
LDFLAGS=-L.. LDFLAGS=-L..
LOADLIBES=-lpsyc LOADLIBES=-lpsyc
TARGETS=testParser testMatch TARGETS=testParser testMatch
all: $(TARGETS) all: $(TARGETS)
# special case because not in the same directory
testParser:
${CC} ${CFLAGS} ${LDFLAGS} parser/testParser.c ${LOADLIBES} -o testParser
test: test:
for f in parser/*txt; do echo -e "\n>> $$f"; ./testParser $$f; done for f in packets/*; do echo -e "\n>> $$f"; ./testParser $$f; done
clean: clean:
rm $(TARGETS) rm -f $(TARGETS)

View file

@ -4,4 +4,3 @@
_request_some_things _request_some_things
content! content!
| |

View file

@ -0,0 +1,3 @@
:_source psyc://test.psyc.eu/
:_target psyc://test.psyc.eu/
|

14
src/tests/packets/test-1 Normal file
View file

@ -0,0 +1,14 @@
|
:_source psyc://foo/~bar
:_target psyc://bar/~baz
:_tag sch1828hu3r2cm
:_foo bar baz
:_abc_def 11 foo bar
baz
:_foo_bar yay
_message_foo_bar
ohai there!
\o/
|
|

View file

@ -0,0 +1,14 @@
|
:_source psyc://foo/~bar
:_target psyc://bar/~baz
:_tag sch1828hu3r2cm
85
:_foo bar baz
:_abc_def 11 foo bar
baz
:_foo_bar yay
_message_foo_bar
ohai there!
\o/
|
|

View file

@ -0,0 +1,14 @@
|
:_source psyc://foo/~bar
:_target psyc://bar/~baz
:_tag sch1828hu3r2cm
80
:_foo bar baz
:_abc_def 11 foo bar
baz
:_foo_bar yay
_message_foo_bar
ohai there!
\o/
|
|

View file

@ -0,0 +1,14 @@
|
:_source psyc://foo/~bar
:_target psyc://bar/~baz
:_tag sch1828hu3r2cm
:_foo bar baz
:_abc_def 15 fóö bär
báz
:_foo_bar yay
_message_foo_bar
ohai there!
\o/
|
|

View file

@ -0,0 +1,25 @@
|
=_source psyc://foo/~bar
:_target psyc://bar/~baz
=_list_foo foo|bar|baz
:_tag sch1828hu3r2cm
=_foo bar baz
=_abc_def 11 ghi jkl
xq
=_list_bar 36 3 foo|3 bar|7 foo
bar|11 foo
bar
baz
:_foo_bar yay
_message_foo_bar
ohai there!
\o/
|
:_target psyc://foo.bar/~baz
:_test 123
_message_test
ohai!
|

View file

@ -0,0 +1,34 @@
|
=_source psyc://foo/~bar
:_target psyc://bar/~baz
=_list_foo foo|bar|baz
:_tag sch1828hu3r2cm
?_test ignored
=_foo bar baz
=_abc_def 11 ghi jkl
xq
=_list_bar 36 3 foo|3 bar|7 foo
bar|11 foo
b|r
baz
:_foo_bar yay
=_amount_x 10
_message_foo_bar
ohai there!
\o/
|
:_target psyc://foo.bar/~baz
:_test 123
_message_test
ohai!
|
:_target psyc://foo.bar/~baz
+_list_foo yay
-_amount_x 2
_notice_test
test!
|

View file

@ -0,0 +1,5 @@
|
:_list_understand_modules _state|_fragments|_context
_request_features
|

View file

@ -0,0 +1,4 @@
:_list_understand_modules _state|_fragments|_context
_request_features
|

View file

@ -0,0 +1,9 @@
|
:_source psyc://test.psyc.eu/~foo
:_target psyc://test.psyc.eu/~bar
:_tag f00b4rb4z
:_foo bar
_message_private
OHAI
|

View file

@ -0,0 +1,9 @@
|
:_source psyc://test.psyc.eu/~foo
:_target psyc://test2.psyc.eu/~bar
:_tag f00b4rb4z
:_foo bar
_message_private
OHAI
|

View file

@ -1,6 +0,0 @@
parser:
$(DIETLIB) cc -L../.. -I../../../include -DDEBUG -lpsyc testParser.c -lpsyc -o testParser
diet:
DIETLIB=/opt/diet/bin/diet make parser

View file

@ -13,12 +13,15 @@ int main(int argc, char** argv)
return -1; return -1;
index = read(file,(void*)buffer,sizeof(buffer)); index = read(file,(void*)buffer,sizeof(buffer));
write(1, ">> INPUT:\n", 10);
write(1, buffer, index);
write(1, ">> PARSE:\n", 10);
PSYC_State state; PSYC_State state;
PSYC_initState(&state); PSYC_initState(&state);
unsigned int cursor=0,tmp=0; //unsigned int cursor=0,tmp=0;
unsigned long expectedBytes=0; //unsigned long expectedBytes=0;
uint8_t modifier; uint8_t modifier;
int ret; int ret;
PSYC_Array name, value; PSYC_Array name, value;
@ -26,27 +29,29 @@ int main(int argc, char** argv)
PSYC_nextBuffer(&state, PSYC_createArray(buffer, index)); PSYC_nextBuffer(&state, PSYC_createArray(buffer, index));
// try parsing that now // try parsing that now
while(ret=PSYC_parse(&state, &name, &value, &modifier)) while((ret=PSYC_parse(&state, &modifier, &name, &value)))
{ {
switch (ret) switch (ret)
{ {
case PSYC_ROUTING: case PSYC_ROUTING:
case PSYC_ENTITY: case PSYC_ENTITY:
write(0,&modifier,1); write(1, &modifier, 1);
case PSYC_METHOD: case PSYC_BODY:
write(0,name.ptr, name.length); write(1, name.ptr, name.length);
write(0," = ", 3); write(1, " = ", 3);
write(0,value.ptr, value.length); write(1, value.ptr, value.length);
write(0,"\n", 1); write(1, "\n", 1);
break; break;
case PSYC_COMPLETE: case PSYC_COMPLETE:
write(0, "Done parsing.\n", 15); printf("Done parsing.\n");
continue; continue;
case PSYC_INSUFFICIENT:
printf("Insufficient data.\n");
return 0;
default: default:
printf("Error while parsing: %i\n", ret); printf("Error while parsing: %i\n", ret);
return; return 1;
} }
} }
return 0; return 0;