From ec76ea765e751549af3201eac68e987566ac5e7f Mon Sep 17 00:00:00 2001 From: Gabor Adam Toth Date: Fri, 22 Apr 2011 17:09:32 +0200 Subject: [PATCH] isRoutingVar, rendering, some renames --- .gitignore | 1 + include/psyc.h | 24 ++++++-- include/psyc/debug.h | 4 ++ include/psyc/lib.h | 4 ++ include/psyc/parser.h | 73 +++++++++++-------------- include/psyc/render.h | 52 +++++++++++++----- src/Makefile | 8 +-- src/parser.c | 124 +++++++++++++++++++++--------------------- src/render.c | 83 +++++++++++++++++----------- src/variable.c | 73 +++++++++++++++++++++++++ test/Makefile | 2 +- test/isRoutingVar.c | 26 +++++++++ test/testParser.c | 24 ++++---- 13 files changed, 326 insertions(+), 172 deletions(-) create mode 100644 src/variable.c create mode 100644 test/isRoutingVar.c diff --git a/.gitignore b/.gitignore index 6804378..e802e07 100644 --- a/.gitignore +++ b/.gitignore @@ -5,6 +5,7 @@ src/match test/testMatch test/testParser test/testRender +test/isRoutingVar .config ~$* diff --git a/include/psyc.h b/include/psyc.h index 16ad97d..20fb553 100644 --- a/include/psyc.h +++ b/include/psyc.h @@ -36,7 +36,7 @@ typedef enum typedef enum { PSYC_PART_RESET = -1, - PSYC_PART_HEADER = 0, + PSYC_PART_ROUTING, PSYC_PART_LENGTH, PSYC_PART_CONTENT, PSYC_PART_METHOD, @@ -54,6 +54,7 @@ typedef enum */ typedef enum { + PSYC_TYPE_UNKNOWN, PSYC_TYPE_AMOUNT, PSYC_TYPE_COLOR, PSYC_TYPE_DATE, @@ -78,15 +79,26 @@ typedef enum PSYC_LIST_BINARY = 2, } PSYC_ListType; -/** - * Get the type of variable name. - */ -PSYC_Type PSYC_getVarType(char* name, size_t len); +typedef struct +{ + size_t length; + const char* ptr; +} PSYC_Array; + +/// Routing vars in alphabetical order. +extern const PSYC_Array PSYC_routingVars[]; +/// Number of routing vars. +extern const size_t PSYC_routingVarsNum; /** * Get the type of variable name. */ -PSYC_Bool PSYC_isRoutingVar(char* name, size_t len); +PSYC_Bool PSYC_isRoutingVar(const char* name, size_t len); + +/** + * Get the type of variable name. + */ +PSYC_Type PSYC_getVarType(char* name, size_t len); /** * Checks if long keyword string inherits from short keyword string. diff --git a/include/psyc/debug.h b/include/psyc/debug.h index 0fcdb05..6ddec4c 100644 --- a/include/psyc/debug.h +++ b/include/psyc/debug.h @@ -1,3 +1,6 @@ +#ifndef DEBUG_H +# define DEBUG_H + #ifdef DEBUG # include # define PP(args) printf args; @@ -93,3 +96,4 @@ # define ASSERT(NAME,CONDITION,VALUE) #endif +#endif // DEBUG_H diff --git a/include/psyc/lib.h b/include/psyc/lib.h index e6c8c6d..8378468 100644 --- a/include/psyc/lib.h +++ b/include/psyc/lib.h @@ -1,5 +1,8 @@ /* this is needed to compile the library, not to use it */ +#ifndef PSYC_LIB_H +# define PSYC_LIB_H + #include "../psyc.h" #include "./debug.h" @@ -12,3 +15,4 @@ void *memmem(const void *haystack, size_t haystacklen, const void *needle, size_t needlelen); #endif +#endif // PSYC_LIB_H diff --git a/include/psyc/parser.h b/include/psyc/parser.h index b669ca5..b4b0d89 100644 --- a/include/psyc/parser.h +++ b/include/psyc/parser.h @@ -21,7 +21,7 @@ typedef enum { - PSYC_HEADER_ONLY = 1, + PSYC_PARSE_HEADER_ONLY = 1, } PSYC_ParseFlag; /** @@ -30,35 +30,35 @@ typedef enum */ typedef enum { - 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_PARSE_ERROR_END = -7, + PSYC_PARSE_ERROR_METHOD = -6, + PSYC_PARSE_ERROR_VAR_LEN = -5, + PSYC_PARSE_ERROR_VAR_TAB = -4, + PSYC_PARSE_ERROR_VAR_NAME = -3, + PSYC_PARSE_ERROR_LENGTH = -2, + PSYC_PARSE_ERROR = -1, + PSYC_PARSE_SUCCESS = 0, /// Buffer contains insufficient amount of data. /// Fill another buffer and concatenate it with the end of the current buffer, /// from the cursor position to the end. - PSYC_INSUFFICIENT = 1, + PSYC_PARSE_INSUFFICIENT = 1, /// Routing variable parsing done. /// Modifier, name & value contains the respective parts. - PSYC_ROUTING = 2, + PSYC_PARSE_ROUTING = 2, /// Entity variable parsing done. /// Modifier, name & value contains the respective parts. - PSYC_ENTITY = 3, + PSYC_PARSE_ENTITY = 3, /// Entity variable parsing is incomplete. /// Modifier & name are complete, value is incomplete. - PSYC_ENTITY_INCOMPLETE = 4, + PSYC_PARSE_ENTITY_INCOMPLETE = 4, /// Body parsing done, name contains method, value contains body. - PSYC_BODY = 5, + PSYC_PARSE_BODY = 5, /// Body parsing is incomplete, name contains method, value contains part of the body. - PSYC_BODY_INCOMPLETE = 6, + PSYC_PARSE_BODY_INCOMPLETE = 6, /// Reached end of packet, parsing done. - PSYC_COMPLETE = 7, + PSYC_PARSE_COMPLETE = 7, /// Binary value parsing incomplete, used internally. - PSYC_INCOMPLETE = 8, + PSYC_PARSE_INCOMPLETE = 8, } PSYC_ParseRC; /** @@ -67,25 +67,19 @@ typedef enum */ typedef enum { - PSYC_ERROR_LIST_DELIM = -5, - PSYC_ERROR_LIST_LEN = -4, - PSYC_ERROR_LIST_TYPE = -3, - PSYC_ERROR_LIST_NAME = -2, - PSYC_ERROR_LIST= -1, + PSYC_PARSE_LIST_ERROR_DELIM = -5, + PSYC_PARSE_LIST_ERROR_LEN = -4, + PSYC_PARSE_LIST_ERROR_TYPE = -3, + PSYC_PARSE_LIST_ERROR_NAME = -2, + PSYC_PARSE_LIST_ERROR= -1, /// Completed parsing a list element. - PSYC_LIST_ELEM = 1, + PSYC_PARSE_LIST_ELEM = 1, /// Reached end of buffer. - PSYC_LIST_END = 2, + PSYC_PARSE_LIST_END = 2, /// Binary list is incomplete. - PSYC_LIST_INCOMPLETE = 3, + PSYC_PARSE_LIST_INCOMPLETE = 3, } PSYC_ParseListRC; -typedef struct -{ - size_t length; - const uint8_t* ptr; // just an unsigned char for opaque data -} PSYC_Array; // to be renamed or solved differently.. - /** * Struct for keeping parser state. */ @@ -118,7 +112,6 @@ typedef struct size_t elemLength; ///< expected length of the elem } PSYC_ParseListState; -#ifndef PSYC_COMPILE_LIBRARY /** * Shortcut for creating an array. * @@ -127,7 +120,7 @@ typedef struct * * @return An instance of the PSYC_Array struct. */ -inline PSYC_Array PSYC_createArray (uint8_t* const memory, size_t length) +inline PSYC_Array PSYC_createArray (const char* memory, size_t length) { PSYC_Array arr = {length, memory}; return arr; @@ -139,7 +132,7 @@ inline PSYC_Array PSYC_createArray (uint8_t* const memory, size_t length) * @param state Pointer to the state struct that should be initiated. * @param flags Flags to be set for the parser, see PSYC_ParseFlag. */ -inline void PSYC_initState2 (PSYC_ParseState* state, uint8_t flags) +inline void PSYC_initParseState2 (PSYC_ParseState* state, uint8_t flags) { memset(state, 0, sizeof(PSYC_ParseState)); state->flags = flags; @@ -150,7 +143,7 @@ inline void PSYC_initState2 (PSYC_ParseState* state, uint8_t flags) * * @param state Pointer to the state struct that should be initiated. */ -inline void PSYC_initState (PSYC_ParseState* state) +inline void PSYC_initParseState (PSYC_ParseState* state) { memset(state, 0, sizeof(PSYC_ParseState)); } @@ -160,18 +153,18 @@ inline void PSYC_initState (PSYC_ParseState* state) * * @param state Pointer to the list state struct that should be initiated. */ -inline void PSYC_initListState (PSYC_ParseListState* state) +inline void PSYC_initParseListState (PSYC_ParseListState* state) { memset(state, 0, sizeof(PSYC_ParseListState)); } -inline void PSYC_nextBuffer (PSYC_ParseState* state, PSYC_Array newBuf) +inline void PSYC_nextParseBuffer (PSYC_ParseState* state, PSYC_Array newBuf) { state->buffer = newBuf; state->cursor = 0; } -inline void PSYC_nextListBuffer (PSYC_ParseListState* state, PSYC_Array newBuf) +inline void PSYC_nextParseListBuffer (PSYC_ParseListState* state, PSYC_Array newBuf) { state->buffer = newBuf; state->cursor = 0; @@ -182,8 +175,6 @@ inline size_t PSYC_getContentLength (PSYC_ParseState* s) return s->contentLength; } -#endif - /** * Parse PSYC packets. * @@ -197,7 +188,7 @@ inline size_t PSYC_getContentLength (PSYC_ParseState* s) * @param value A pointer to a PSYC_Array. It will point to the * value/body the variable/method and its length will be set accordingly */ -PSYC_ParseRC PSYC_parse(PSYC_ParseState* state, uint8_t* modifier, PSYC_Array* name, PSYC_Array* value); +PSYC_ParseRC PSYC_parse(PSYC_ParseState* state, char* modifier, PSYC_Array* name, PSYC_Array* value); /** * List value parser. diff --git a/include/psyc/render.h b/include/psyc/render.h index c236aa4..3170924 100644 --- a/include/psyc/render.h +++ b/include/psyc/render.h @@ -1,18 +1,33 @@ +#ifndef PSYC_RENDER_H +# define PSYC_RENDER_H + #include "syntax.h" +#define PSYC_FLAG_UNDEFINED 0 +#define PSYC_FLAG_NOT_BINARY 1 +#define PSYC_FLAG_YES_BINARY 2 +#define PSYC_FLAG_CHECK_BINARY 3 + +typedef enum +{ + PSYC_RENDER_CHECK_BINARY = 0, + PSYC_RENDER_BINARY = 1, + PSYC_RENDER_NOT_BINARY = 2, + PSYC_RENDER_ROUTING = 3, +} PSYC_RenderFlag; + +typedef enum +{ + PSYC_RENDER_ERROR_ROUTING = -2, + PSYC_RENDER_ERROR = -1, + PSYC_RENDER_SUCCESS = 0, +} PSYC_RenderRC; + /** * Struct for keeping render state. */ -typedef enum { - PSYC_FINE = 0, - PSYC_NEED_LENGTH = 1 -} PSYC_RenderFlag; - -typedef enum { - PSYC_FLAG_ROUTING = 1 -} PSYC_RenderHeaderFlag; - -typedef struct { +typedef struct +{ PSYC_RenderFlag flag; ///< flags for the renderer PSYC_Part part; ///< part of the packet being rendered size_t cursor; ///< current position in buffer @@ -22,14 +37,23 @@ typedef struct { char buffer[]; ///< OMG a C99 feature! variable size buffer! } PSYC_RenderState; -int PSYC_renderHeader(PSYC_RenderState* render, +/** + * Initiates the state struct. + * + * @param state Pointer to the state struct that should be initiated. + */ +inline void PSYC_initRenderState (PSYC_RenderState* state) +{ + memset(state, 0, sizeof(PSYC_RenderState)); +} + +int PSYC_renderVar(PSYC_RenderState* render, const char* name, size_t nlength, const char* value, size_t vlength, - PSYC_RenderHeaderFlag flags, char modifier); + PSYC_RenderFlag flags, char modifier); int PSYC_renderBody(PSYC_RenderState* render, const char* method, size_t mlength, const char* data, size_t dlength); -int PSYC_doneRender(PSYC_RenderState* render, - uint8_t** buf, size_t* written); +#endif // PSYC_RENDER_H diff --git a/src/Makefile b/src/Makefile index 5251245..4a3b661 100644 --- a/src/Makefile +++ b/src/Makefile @@ -1,9 +1,9 @@ -CFLAGS=-I../../include -DDEBUG=2 -DPSYC_COMPILE_LIBRARY -g -O0 -Wall -CC=cc -I../include +CFLAGS=-I../include -DDEBUG=2 -DPSYC_COMPILE_LIBRARY -g -O0 -Wall +CC=cc # CC=clang -S=parser.c match.c render.c memmem.c -O=parser.o match.o render.o memmem.o +S=parser.c match.c render.c memmem.c variable.c +O=parser.o match.o render.o memmem.o variable.o default: @/bin/echo -e "Usage:\n\tmake diet - compile with diet libc\n\tmake lib - compile with normal gnu libc" diff --git a/src/parser.c b/src/parser.c index 264b0d7..6d18511 100644 --- a/src/parser.c +++ b/src/parser.c @@ -66,7 +66,7 @@ inline char isKwChar(uint8_t c) /** * Parse variable name or method name. * It should contain one or more keyword characters. - * @return PSYC_ERROR or PSYC_SUCCESS + * @return PSYC_PARSE_ERROR or PSYC_PARSE_SUCCESS */ inline PSYC_ParseRC PSYC_parseName(PSYC_ParseState* state, PSYC_Array* name) { @@ -76,10 +76,10 @@ inline PSYC_ParseRC PSYC_parseName(PSYC_ParseState* state, PSYC_Array* name) while (isKwChar(state->buffer.ptr[state->cursor])) { name->length++; // was a valid char, increase length - ADVANCE_CURSOR_OR_RETURN(PSYC_INSUFFICIENT); + ADVANCE_CURSOR_OR_RETURN(PSYC_PARSE_INSUFFICIENT); } - return name->length > 0 ? PSYC_SUCCESS : PSYC_ERROR; + return name->length > 0 ? PSYC_PARSE_SUCCESS : PSYC_PARSE_ERROR; } /** @@ -90,7 +90,7 @@ inline PSYC_ParseRC PSYC_parseName(PSYC_ParseState* state, PSYC_Array* name) * @param length Expected length of the data. * @param parsed Number of bytes parsed so far. * - * @return PSYC_COMPLETE or PSYC_INCOMPLETE + * @return PSYC_PARSE_COMPLETE or PSYC_PARSE_INCOMPLETE */ inline PSYC_ParseRC PSYC_parseBinaryValue(PSYC_ParseState* state, PSYC_Array* value, size_t* length, size_t* parsed) { @@ -101,27 +101,27 @@ inline PSYC_ParseRC PSYC_parseBinaryValue(PSYC_ParseState* state, PSYC_Array* va { value->length = state->buffer.length - state->cursor; *parsed += value->length; - return PSYC_INCOMPLETE; + return PSYC_PARSE_INCOMPLETE; } value->length += remaining; state->cursor += remaining; *parsed += value->length; - return PSYC_COMPLETE; + return PSYC_PARSE_COMPLETE; } /** * Parse simple or binary variable. - * @return PSYC_ERROR or PSYC_SUCCESS + * @return PSYC_PARSE_ERROR or PSYC_PARSE_SUCCESS */ -inline PSYC_ParseRC PSYC_parseVar(PSYC_ParseState* state, uint8_t* modifier, PSYC_Array* name, PSYC_Array* value) +inline PSYC_ParseRC PSYC_parseVar(PSYC_ParseState* state, char* modifier, PSYC_Array* name, PSYC_Array* value) { *modifier = *(state->buffer.ptr + state->cursor); - ADVANCE_CURSOR_OR_RETURN(PSYC_INSUFFICIENT); + ADVANCE_CURSOR_OR_RETURN(PSYC_PARSE_INSUFFICIENT); - if (PSYC_parseName(state, name) != PSYC_SUCCESS) - return PSYC_ERROR_VAR_NAME; + if (PSYC_parseName(state, name) != PSYC_PARSE_SUCCESS) + return PSYC_PARSE_ERROR_VAR_NAME; value->length = 0; state->valueLength = 0; @@ -131,55 +131,55 @@ inline PSYC_ParseRC PSYC_parseVar(PSYC_ParseState* state, uint8_t* modifier, PSY // 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(PSYC_INSUFFICIENT); + ADVANCE_CURSOR_OR_RETURN(PSYC_PARSE_INSUFFICIENT); if (isNumeric(state->buffer.ptr[state->cursor])) { do { state->valueLength = 10 * state->valueLength + state->buffer.ptr[state->cursor] - '0'; - ADVANCE_CURSOR_OR_RETURN(PSYC_INSUFFICIENT); + ADVANCE_CURSOR_OR_RETURN(PSYC_PARSE_INSUFFICIENT); } while (isNumeric(state->buffer.ptr[state->cursor])); } else - return PSYC_ERROR_VAR_LEN; + return PSYC_PARSE_ERROR_VAR_LEN; // After the length a TAB follows. if (state->buffer.ptr[state->cursor] != '\t') - return PSYC_ERROR_VAR_TAB; + return PSYC_PARSE_ERROR_VAR_TAB; if (state->buffer.length <= ++(state->cursor)) // Incremented cursor inside length? - return PSYC_ENTITY_INCOMPLETE; + return PSYC_PARSE_ENTITY_INCOMPLETE; - if (PSYC_parseBinaryValue(state, value, &(state->valueLength), &(state->valueParsed)) == PSYC_INCOMPLETE) - return PSYC_ENTITY_INCOMPLETE; + if (PSYC_parseBinaryValue(state, value, &(state->valueLength), &(state->valueParsed)) == PSYC_PARSE_INCOMPLETE) + return PSYC_PARSE_ENTITY_INCOMPLETE; state->cursor++; - return PSYC_SUCCESS; + return PSYC_PARSE_SUCCESS; } else if (state->buffer.ptr[state->cursor] == '\t') // simple arg { - ADVANCE_CURSOR_OR_RETURN(PSYC_INSUFFICIENT); + ADVANCE_CURSOR_OR_RETURN(PSYC_PARSE_INSUFFICIENT); value->ptr = state->buffer.ptr + state->cursor; while (state->buffer.ptr[state->cursor] != '\n') { value->length++; - ADVANCE_CURSOR_OR_RETURN(PSYC_INSUFFICIENT); + ADVANCE_CURSOR_OR_RETURN(PSYC_PARSE_INSUFFICIENT); } state->cursor++; - return PSYC_SUCCESS; + return PSYC_PARSE_SUCCESS; } else - return PSYC_ERROR_VAR_TAB; + return PSYC_PARSE_ERROR_VAR_TAB; } /** * Parse PSYC packets. * Generalized line-based parser. */ -PSYC_ParseRC PSYC_parse(PSYC_ParseState* state, uint8_t* modifier, PSYC_Array* name, PSYC_Array* value) +PSYC_ParseRC PSYC_parse(PSYC_ParseState* state, char* modifier, PSYC_Array* name, PSYC_Array* value) { int ret; // a return value size_t pos; // a cursor position @@ -190,7 +190,7 @@ PSYC_ParseRC PSYC_parse(PSYC_ParseState* state, uint8_t* modifier, PSYC_Array* n // First we test if we can access the first char. if (state->cursor >= state->buffer.length) // cursor is not inside the length - return PSYC_INSUFFICIENT; + return PSYC_PARSE_INSUFFICIENT; switch (state->part) { @@ -200,17 +200,17 @@ PSYC_ParseRC PSYC_parse(PSYC_ParseState* state, uint8_t* modifier, PSYC_Array* n state->contentParsed = 0; state->contentLength = 0; state->contentLengthFound = 0; - state->part = PSYC_PART_HEADER; + state->part = PSYC_PART_ROUTING; // fall thru - case PSYC_PART_HEADER: + case PSYC_PART_ROUTING: // 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; + return ret == PSYC_PARSE_SUCCESS ? PSYC_PARSE_ROUTING : ret; } else // not a glyph { @@ -227,7 +227,7 @@ PSYC_ParseRC PSYC_parse(PSYC_ParseState* state, uint8_t* modifier, PSYC_Array* n do { state->contentLength = 10 * state->contentLength + state->buffer.ptr[state->cursor] - '0'; - ADVANCE_CURSOR_OR_RETURN(PSYC_INSUFFICIENT); + ADVANCE_CURSOR_OR_RETURN(PSYC_PARSE_INSUFFICIENT); } while (isNumeric(state->buffer.ptr[state->cursor])); } @@ -236,7 +236,7 @@ PSYC_ParseRC PSYC_parse(PSYC_ParseState* state, uint8_t* modifier, PSYC_Array* n { // 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) + if (state->flags & PSYC_PARSE_HEADER_ONLY && state->contentLengthFound) state->part = PSYC_PART_DATA; else state->part = PSYC_PART_CONTENT; @@ -245,13 +245,13 @@ PSYC_ParseRC PSYC_parse(PSYC_ParseState* state, uint8_t* modifier, PSYC_Array* n { // If we have a length then it should've been followed by a \n if (state->contentLengthFound) - return PSYC_ERROR_LENGTH; + return PSYC_PARSE_ERROR_LENGTH; state->part = PSYC_PART_END; goto PSYC_PART_END; } - ADVANCE_CURSOR_OR_RETURN(PSYC_INSUFFICIENT); + ADVANCE_CURSOR_OR_RETURN(PSYC_PARSE_INSUFFICIENT); state->startc = state->cursor; // fall thru @@ -260,7 +260,7 @@ PSYC_ParseRC PSYC_parse(PSYC_ParseState* state, uint8_t* modifier, PSYC_Array* n 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; + return ret == PSYC_PARSE_COMPLETE ? PSYC_PARSE_ENTITY : PSYC_PARSE_ENTITY_INCOMPLETE; } // Each line of the header starts with a glyph, @@ -273,7 +273,7 @@ PSYC_ParseRC PSYC_parse(PSYC_ParseState* state, uint8_t* modifier, PSYC_Array* n pos = state->cursor; ret = PSYC_parseVar(state, modifier, name, value); state->contentParsed += state->cursor - pos; - return ret == PSYC_SUCCESS ? PSYC_ENTITY : ret; + return ret == PSYC_PARSE_SUCCESS ? PSYC_PARSE_ENTITY : ret; } else { @@ -284,17 +284,17 @@ PSYC_ParseRC PSYC_parse(PSYC_ParseState* state, uint8_t* modifier, PSYC_Array* n case PSYC_PART_METHOD: pos = state->cursor; - if (PSYC_parseName(state, name) == PSYC_SUCCESS) + if (PSYC_parseName(state, name) == PSYC_PARSE_SUCCESS) { // the method ends with a \n then the data follows if (state->buffer.ptr[state->cursor] != '\n') - return PSYC_ERROR_METHOD; + return PSYC_PARSE_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; + return PSYC_PARSE_INSUFFICIENT; // fall thru } else // No method, which means the packet should end now. @@ -310,12 +310,12 @@ PSYC_ParseRC PSYC_parse(PSYC_ParseState* state, uint8_t* modifier, PSYC_Array* n 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; + if (PSYC_parseBinaryValue(state, value, &(state->contentLength), &(state->contentParsed)) == PSYC_PARSE_INCOMPLETE) + return PSYC_PARSE_BODY_INCOMPLETE; state->cursor++; state->part = PSYC_PART_END; - return PSYC_BODY; + return PSYC_PARSE_BODY; } else // Search for the terminator. { @@ -326,7 +326,7 @@ PSYC_ParseRC PSYC_parse(PSYC_ParseState* state, uint8_t* modifier, PSYC_Array* n if (state->cursor+2 >= state->buffer.length) // incremented cursor inside length? { state->cursor = state->startc; - return PSYC_INSUFFICIENT; + return PSYC_PARSE_INSUFFICIENT; } if (state->buffer.ptr[state->cursor+1] == '|' && @@ -334,11 +334,11 @@ PSYC_ParseRC PSYC_parse(PSYC_ParseState* state, uint8_t* modifier, PSYC_Array* n { state->cursor++; state->part = PSYC_PART_END; - return PSYC_BODY; + return PSYC_PARSE_BODY; } } value->length++; - ADVANCE_CURSOR_OR_RETURN(PSYC_INSUFFICIENT); + ADVANCE_CURSOR_OR_RETURN(PSYC_PARSE_INSUFFICIENT); } } @@ -347,22 +347,22 @@ PSYC_ParseRC PSYC_parse(PSYC_ParseState* state, uint8_t* modifier, PSYC_Array* n // 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 PSYC_PARSE_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; + return PSYC_PARSE_COMPLETE; } else // packet should've ended here, return error { state->part = PSYC_PART_RESET; - return PSYC_ERROR_END; + return PSYC_PARSE_ERROR_END; } } - return PSYC_ERROR; // should not be reached + return PSYC_PARSE_ERROR; // should not be reached } /** @@ -372,7 +372,7 @@ PSYC_ParseRC PSYC_parse(PSYC_ParseState* state, uint8_t* modifier, PSYC_Array* n PSYC_ParseListRC PSYC_parseList(PSYC_ParseListState* state, PSYC_Array *name, PSYC_Array* value, PSYC_Array* elem) { if (state->cursor >= state->buffer.length) - return PSYC_LIST_INCOMPLETE; + return PSYC_PARSE_LIST_INCOMPLETE; state->startc = state->cursor; @@ -380,7 +380,7 @@ PSYC_ParseListRC PSYC_parseList(PSYC_ParseListState* state, PSYC_Array *name, PS { if (name->length < 5 || memcmp(name->ptr, "_list", 5) != 0 || (name->length > 5 && name->ptr[5] != '_')) // name should be _list or should start with _list_ - return PSYC_ERROR_LIST_NAME; + return PSYC_PARSE_LIST_ERROR_NAME; // First character is either | for text lists, or a number for binary lists if (state->buffer.ptr[state->cursor] == '|') @@ -391,7 +391,7 @@ PSYC_ParseListRC PSYC_parseList(PSYC_ParseListState* state, PSYC_Array *name, PS else if (isNumeric(state->buffer.ptr[state->cursor])) state->type = PSYC_LIST_BINARY; else - return PSYC_ERROR_LIST_TYPE; + return PSYC_PARSE_LIST_ERROR_TYPE; } if (state->type == PSYC_LIST_TEXT) @@ -400,16 +400,16 @@ PSYC_ParseListRC PSYC_parseList(PSYC_ParseListState* state, PSYC_Array *name, PS elem->length = 0; if (state->cursor >= state->buffer.length) - return PSYC_LIST_END; + return PSYC_PARSE_LIST_END; while (state->buffer.ptr[state->cursor] != '|') { elem->length++; if (++(state->cursor) >= state->buffer.length) - return PSYC_LIST_END; + return PSYC_PARSE_LIST_END; } state->cursor++; - return PSYC_LIST_ELEM; + return PSYC_PARSE_LIST_ELEM; } else // binary list { @@ -421,15 +421,15 @@ PSYC_ParseListRC PSYC_parseList(PSYC_ParseListState* state, PSYC_Array *name, PS do { state->elemLength = 10 * state->elemLength + state->buffer.ptr[state->cursor] - '0'; - ADVANCE_CURSOR_OR_RETURN(PSYC_LIST_INCOMPLETE); + ADVANCE_CURSOR_OR_RETURN(PSYC_PARSE_LIST_INCOMPLETE); } while (isNumeric(state->buffer.ptr[state->cursor])); } else - return PSYC_ERROR_LIST_LEN; + return PSYC_PARSE_LIST_ERROR_LEN; if (state->buffer.ptr[state->cursor] != ' ') - return PSYC_ERROR_LIST_LEN; + return PSYC_PARSE_LIST_ERROR_LEN; state->cursor++; elem->ptr = state->buffer.ptr + state->cursor; @@ -440,21 +440,21 @@ PSYC_ParseListRC PSYC_parseList(PSYC_ParseListState* state, PSYC_Array *name, PS // Start or resume parsing the binary data if (state->elemParsed < state->elemLength) { - if (PSYC_parseBinaryValue((PSYC_ParseState*)state, elem, &(state->elemLength), &(state->elemParsed)) == PSYC_INCOMPLETE) - return PSYC_LIST_INCOMPLETE; + if (PSYC_parseBinaryValue((PSYC_ParseState*)state, elem, &(state->elemLength), &(state->elemParsed)) == PSYC_PARSE_INCOMPLETE) + return PSYC_PARSE_LIST_INCOMPLETE; state->elemLength = 0; if (state->cursor >= state->buffer.length) - return PSYC_LIST_END; + return PSYC_PARSE_LIST_END; if (state->buffer.ptr[state->cursor] != '|') - return PSYC_ERROR_LIST_DELIM; + return PSYC_PARSE_LIST_ERROR_DELIM; state->cursor++; - return PSYC_LIST_ELEM; + return PSYC_PARSE_LIST_ELEM; } } - return PSYC_ERROR_LIST; // should not be reached + return PSYC_PARSE_LIST_ERROR; // should not be reached } diff --git a/src/render.c b/src/render.c index bf5e039..69a2771 100644 --- a/src/render.c +++ b/src/render.c @@ -1,51 +1,70 @@ #include "psyc/lib.h" #include "psyc/render.h" -int PSYC_renderHeader(PSYC_RenderState* r, - const char* name, size_t nlength, - const char* value, size_t vlength, - const PSYC_RenderHeaderFlag flags, - char modifier) { +PSYC_RenderRC PSYC_renderVar(PSYC_RenderState* state, + const char* name, size_t nlength, + const char* value, size_t vlength, + const PSYC_RenderFlag flags, char modifier) +{ + size_t startc = state->cursor; + unless (nlength) nlength = strlen(name); // vlength 0 means an empty variable.. no cheating there unless (modifier) modifier = C_GLYPH_MODIFIER_SET; - r->buffer[r->cursor++] = modifier; - strncpy(&r->buffer[r->cursor], name, nlength); - r->cursor += nlength; - if (vlength) { - r->buffer[r->cursor++] = '\t'; - strncpy(&r->buffer[r->cursor], value, vlength); - r->cursor += vlength; + state->buffer[state->cursor++] = modifier; + strncpy(&state->buffer[state->cursor], name, nlength); + state->cursor += nlength; + + if (vlength) + { + state->buffer[state->cursor++] = '\t'; + strncpy(&state->buffer[state->cursor], value, vlength); + state->cursor += vlength; } - if (flags == PSYC_FLAG_ROUTING) { - if (r->spot != 0) { - P1(("Too late to add a routing variable!\n")) - return -1; + //if (flags == PSYC_RENDER_ROUTING) + if (PSYC_isRoutingVar(name, nlength)) + { // no more routing headers allowed after content started + if (state->part != PSYC_PART_ROUTING) + { + P1(("Too late to add a routing variable!\n")); + return PSYC_RENDER_ERROR_ROUTING; } - } else if (r->spot == 0) { + } + else if (state->part == PSYC_PART_ROUTING) + { // first entity header, set part to content + state->part = PSYC_PART_CONTENT; // add "\n000000000" to buffer // and make spot point to the first 0 } - return 0; + + // update content length if we're in the content part + if (state->part == PSYC_PART_CONTENT) + state->contentLength += state->cursor - startc; + + return PSYC_RENDER_SUCCESS; } -int PSYC_renderBody(PSYC_RenderState* render, +/* render PSYC packets */ +PSYC_RenderRC PSYC_renderBody(PSYC_RenderState* state, const char* method, size_t mlength, - const char* data, size_t dlength) { - - // find out if this packet needs a prepended length - if (dlength == 1 && data[0] == C_GLYPH_PACKET_DELIMITER) - render->flag = PSYC_NEED_LENGTH; - else if (dlength > 404) - render->flag = PSYC_NEED_LENGTH; - else if (memmem(data, dlength, PSYC_PACKET_DELIMITER, - sizeof(PSYC_PACKET_DELIMITER))) - render->flag = PSYC_NEED_LENGTH; - else - render->flag = PSYC_FINE; + const char* data, size_t dlength) +{ + if (state->flag == PSYC_RENDER_CHECK_BINARY) + { + // find out if this packet needs a prepended length + if (dlength == 1 && data[0] == C_GLYPH_PACKET_DELIMITER) + state->flag = PSYC_RENDER_BINARY; + else if (dlength > 404) + state->flag = PSYC_RENDER_BINARY; + else if (memmem(data, dlength, PSYC_PACKET_DELIMITER, sizeof(PSYC_PACKET_DELIMITER))) + state->flag = PSYC_RENDER_BINARY; + else + state->flag = PSYC_RENDER_NOT_BINARY; + } // TBD - return 0; + + return PSYC_RENDER_SUCCESS; } diff --git a/src/variable.c b/src/variable.c new file mode 100644 index 0000000..abd786a --- /dev/null +++ b/src/variable.c @@ -0,0 +1,73 @@ +#include +#include + +const PSYC_Array PSYC_routingVars[] = +{ + {17, "_amount_fragments"}, + { 8, "_context"}, + { 6, "_count"}, + { 8, "_counter"}, // the name for this is supposed to be _count, not _counter + { 9, "_fragment"}, + { 7, "_length"}, + { 7, "_source"}, + {22, "_source_identification"}, + {13, "_source_relay"}, + {19, "_source_relay_relay"}, // until you have a better idea.. is this really in use? + { 4, "_tag"}, + {10, "_tag_relay"}, + {10, "_tag_reply"}, // should be obsolete, but.. TODO + { 7, "_target"}, + {15, "_target_forward"}, + {13, "_target_relay"}, + {19, "_understand_modules"}, + {14, "_using_modules"}, +}; + +const size_t PSYC_routingVarsNum = sizeof(PSYC_routingVars) / sizeof(*PSYC_routingVars); + +/** + * Get the type of variable name. + */ +PSYC_Bool PSYC_isRoutingVar(const char* name, size_t len) +{ + size_t cursor = 1; + int8_t matching[PSYC_routingVarsNum]; // indexes of matching vars + memset(&matching, -1, sizeof(matching)); + uint8_t i, m = 0; + + if (len < 2 || name[0] != '_') + return PSYC_FALSE; + + // first find the vars with matching length + for (i=0; i= 0) + { + for (i = m = 0; i < PSYC_routingVarsNum; i++) + { + if (matching[i] < 0) + break; + if (PSYC_routingVars[matching[i]].ptr[cursor] == name[cursor]) + matching[m++] = matching[i]; // found a match, update matching indexes + else if (PSYC_routingVars[matching[i]].ptr[cursor] > name[cursor]) + break; // passed the possible matches in alphabetical order + } + + if (m < PSYC_routingVarsNum) + matching[m] = -1; // mark the end of matching indexes + + cursor++; + } + + return matching[0] >= 0 ? PSYC_TRUE : PSYC_FALSE; +} + +/** + * Get the type of variable name. + */ +PSYC_Type PSYC_getVarType(char* name, size_t len) +{ + return PSYC_TYPE_UNKNOWN; +} diff --git a/test/Makefile b/test/Makefile index fd61356..2cd792c 100644 --- a/test/Makefile +++ b/test/Makefile @@ -1,7 +1,7 @@ CFLAGS=-I../include -DDEBUG -g -O0 -Wall LDFLAGS=-L../src LOADLIBES=-lpsyc -TARGETS=testParser testMatch testRender +TARGETS=testParser testMatch testRender isRoutingVar all: $(TARGETS) diff --git a/test/isRoutingVar.c b/test/isRoutingVar.c new file mode 100644 index 0000000..e744b95 --- /dev/null +++ b/test/isRoutingVar.c @@ -0,0 +1,26 @@ +#include +#include +#include +#include + +int main(int argc, char** argv) +{ + char* vars[] = + { + "_source", + "_source_relay", + "_source_foo", + "_sourcherry", + "_foo", + "bar", + "_", + }; + + int i; + for (i = 0; i < sizeof(vars) / sizeof(*vars); i++) + { + printf("%s: %d\n", vars[i], PSYC_isRoutingVar(vars[i], strlen(vars[i]))); + } + + return 0; +} diff --git a/test/testParser.c b/test/testParser.c index c743462..6815441 100644 --- a/test/testParser.c +++ b/test/testParser.c @@ -21,18 +21,18 @@ int main(int argc, char** argv) write(1, buffer, index); write(1, ">> PARSE\n", 9); - PSYC_initState(&state); - PSYC_nextBuffer(&state, PSYC_createArray(buffer, index)); + PSYC_initParseState(&state); + PSYC_nextParseBuffer(&state, PSYC_createArray(buffer, index)); // try parsing that now while ((ret = PSYC_parse(&state, &modifier, &name, &value))) { switch (ret) { - case PSYC_ROUTING: - case PSYC_ENTITY: + case PSYC_PARSE_ROUTING: + case PSYC_PARSE_ENTITY: write(1, &modifier, 1); - case PSYC_BODY: + case PSYC_PARSE_BODY: // printf("the string is '%.*s'\n", name); write(1, name.ptr, name.length); write(1, " = ", 3); @@ -41,14 +41,14 @@ int main(int argc, char** argv) if (memcmp(name.ptr, "_list", 5) == 0) { write(1, ">>> LIST START\n", 15); - PSYC_initListState(&listState); - PSYC_nextListBuffer(&listState, value); + PSYC_initParseListState(&listState); + PSYC_nextParseListBuffer(&listState, value); while ((ret = PSYC_parseList(&listState, &name, &value, &elem))) { switch (ret) { - case PSYC_LIST_END: - case PSYC_LIST_ELEM: + case PSYC_PARSE_LIST_END: + case PSYC_PARSE_LIST_ELEM: write(1, "|", 1); write(1, elem.ptr, elem.length); write(1, "\n", 1); @@ -58,7 +58,7 @@ int main(int argc, char** argv) return 1; } - if (ret == PSYC_LIST_END) + if (ret == PSYC_PARSE_LIST_END) { write(1, ">>> LIST END\n", 13); break; @@ -66,10 +66,10 @@ int main(int argc, char** argv) } } break; - case PSYC_COMPLETE: + case PSYC_PARSE_COMPLETE: printf("Done parsing.\n"); continue; - case PSYC_INSUFFICIENT: + case PSYC_PARSE_INSUFFICIENT: printf("Insufficient data.\n"); return 0; default: