diff --git a/d/include/psyc/syntax.d b/d/include/psyc/syntax.d index 2962f57..2a55864 100644 --- a/d/include/psyc/syntax.d +++ b/d/include/psyc/syntax.d @@ -8,27 +8,8 @@ const PSYC_CONTENT_SIZE_THRESHOLD = 444; /* beyond this a modifier value length must be provided */ const PSYC_MODIFIER_SIZE_THRESHOLD = 404; -const C_GLYPH_PACKET_DELIMITER = '|'; -const S_GLYPH_PACKET_DELIMITER = "|"; -const PSYC_PACKET_DELIMITER = "\n|\n"; - -const C_GLYPH_SEPARATOR_KEYWORD = '_'; -const S_GLYPH_SEPARATOR_KEYWORD = "_"; - -const C_GLYPH_OPERATOR_SET = ':'; -const S_GLYPH_OPERATOR_SET = ":"; - -const C_GLYPH_OPERATOR_ASSIGN = '='; -const S_GLYPH_OPERATOR_ASSIGN = "="; - -const C_GLYPH_OPERATOR_AUGMENT = '+'; -const S_GLYPH_OPERATOR_AUGMENT = "+"; - -const C_GLYPH_OPERATOR_DIMINISH = '-'; -const S_GLYPH_OPERATOR_DIMINISH = "-"; - -const C_GLYPH_OPERATOR_QUERY = '?'; -const S_GLYPH_OPERATOR_QUERY = "?"; +const PSYC_PACKET_DELIMITER_CHAR = '|'; +const PSYC_PACKET_DELIMITER = "\n|\n"; /* might move into routing.h or something */ const PSYC_ROUTING = 1; diff --git a/include/psyc/packet.h b/include/psyc/packet.h index 0a9d41b..e0d5383 100644 --- a/include/psyc/packet.h +++ b/include/psyc/packet.h @@ -63,6 +63,13 @@ typedef enum PSYC_OPERATOR_QUERY = '?', } PsycOperator; +typedef enum +{ + PSYC_STATE_NOOP = 0, + PSYC_STATE_RESET = '=', + PSYC_STATE_SYNC = '?', +} PsycStateOp; + /** Structure for a modifier. */ typedef struct { @@ -91,15 +98,16 @@ typedef struct /** Intermediate struct for a PSYC packet */ typedef struct { - PsycHeader routing; ///< Routing header. - PsycHeader entity; ///< Entity header. - PsycString method; ///< Contains the method. - PsycString data; ///< Contains the data. - PsycString content; ///< Contains the whole content. + PsycHeader routing; ///< Routing header. + PsycHeader entity; ///< Entity header. + char stateop; ///< State operation. @see PsycStateOp + PsycString method; ///< Contains the method. + PsycString data; ///< Contains the data. + PsycString content; ///< Contains the whole content. size_t routingLength; ///< Length of routing part. size_t contentLength; ///< Length of content part. - size_t length; ///< Total length of packet. - PsycPacketFlag flag; ///< Packet flag. + size_t length; ///< Total length of packet. + PsycPacketFlag flag; ///< Packet flag. } PsycPacket; /** @@ -182,7 +190,7 @@ void psyc_packet_init (PsycPacket *packet, PsycModifier *entity, size_t entitylen, char *method, size_t methodlen, char *data, size_t datalen, - PsycPacketFlag flag); + char stateop, PsycPacketFlag flag); /** Initialize packet with raw content. */ void psyc_packet_init_raw (PsycPacket *packet, diff --git a/include/psyc/parse.h b/include/psyc/parse.h index 2f8b31d..b290c5f 100644 --- a/include/psyc/parse.h +++ b/include/psyc/parse.h @@ -152,42 +152,46 @@ typedef enum { /// Routing modifier parsing done. /// Operator, name & value contains the respective parts. PSYC_PARSE_ROUTING = 2, + /// State sync operation. + PSYC_PARSE_STATE_SYNC = 3, + /// State reset operation. + PSYC_PARSE_STATE_RESET = 4, /// Start of an incomplete entity modifier. /// Operator & name are complete, value is incomplete. - PSYC_PARSE_ENTITY_START = 3, + PSYC_PARSE_ENTITY_START = 5, /// Continuation of an incomplete entity modifier. - PSYC_PARSE_ENTITY_CONT = 4, + PSYC_PARSE_ENTITY_CONT = 6, /// End of an incomplete entity modifier. - PSYC_PARSE_ENTITY_END = 5, + PSYC_PARSE_ENTITY_END = 7, /// Entity modifier parsing done in one go. /// Operator, name & value contains the respective parts. - PSYC_PARSE_ENTITY = 6, + PSYC_PARSE_ENTITY = 8, /// Start of an incomplete body. /// Name contains method, value contains part of the body. /// Used when packet length is given - PSYC_PARSE_BODY_START = 7, + PSYC_PARSE_BODY_START = 9, /// Continuation of an incomplete body. /// Used when packet length is given - PSYC_PARSE_BODY_CONT = 8, + PSYC_PARSE_BODY_CONT = 10, /// End of an incomplete body. /// Used when packet length is given - PSYC_PARSE_BODY_END = 9, + PSYC_PARSE_BODY_END = 11, /// Body parsing done in one go, name contains method, value contains body. - PSYC_PARSE_BODY = 10, + PSYC_PARSE_BODY = 12, /// Start of an incomplete content, value contains part of content. /// Used when PSYC_PARSE_ROUTING_ONLY is set. - PSYC_PARSE_CONTENT_START = 7, + PSYC_PARSE_CONTENT_START = 9, /// Continuation of an incomplete content. /// Used when PSYC_PARSE_ROUTING_ONLY is set. - PSYC_PARSE_CONTENT_CONT = 8, + PSYC_PARSE_CONTENT_CONT = 10, /// End of an incomplete content. /// Used when PSYC_PARSE_ROUTING_ONLY is set. - PSYC_PARSE_CONTENT_END = 9, + PSYC_PARSE_CONTENT_END = 11, /// Content parsing done in one go, value contains the whole content. /// Used when PSYC_PARSE_ROUTING_ONLY is set. - PSYC_PARSE_CONTENT = 10, + PSYC_PARSE_CONTENT = 12, /// Finished parsing packet. - PSYC_PARSE_COMPLETE = 11, + PSYC_PARSE_COMPLETE = 13, } PsycParseRC; /** diff --git a/include/psyc/syntax.h b/include/psyc/syntax.h index 105d59e..d46e0c0 100644 --- a/include/psyc/syntax.h +++ b/include/psyc/syntax.h @@ -14,32 +14,8 @@ # define PSYC_MODIFIER_SIZE_THRESHOLD 404 #endif -#define C_GLYPH_PACKET_DELIMITER '|' -#define S_GLYPH_PACKET_DELIMITER "|" -#define PSYC_PACKET_DELIMITER "\n|\n" - -#define C_GLYPH_SEPARATOR_KEYWORD '_' -#define S_GLYPH_SEPARATOR_KEYWORD "_" - -#define C_GLYPH_OPERATOR_SET ':' -#define S_GLYPH_OPERATOR_SET ":" - -#define C_GLYPH_OPERATOR_ASSIGN '=' -#define S_GLYPH_OPERATOR_ASSIGN "=" - -#define C_GLYPH_OPERATOR_AUGMENT '+' -#define S_GLYPH_OPERATOR_AUGMENT "+" - -#define C_GLYPH_OPERATOR_DIMINISH '-' -#define S_GLYPH_OPERATOR_DIMINISH "-" - -#define C_GLYPH_OPERATOR_QUERY '?' -#define S_GLYPH_OPERATOR_QUERY "?" - -/* might move into routing.h or something */ -#define PSYC_ROUTING 1 -#define PSYC_ROUTING_MERGE 2 -#define PSYC_ROUTING_RENDER 4 +#define PSYC_PACKET_DELIMITER_CHAR '|' +#define PSYC_PACKET_DELIMITER "\n|\n" #define PSYC_SYNTAX_H #endif diff --git a/src/packet.c b/src/packet.c index 8b305b6..e8594fd 100644 --- a/src/packet.c +++ b/src/packet.c @@ -76,7 +76,7 @@ size_t psyc_modifier_length (PsycModifier *m) inline PsycPacketFlag psyc_packet_length_check (PsycPacket *p) { - if (p->data.length == 1 && p->data.data[0] == C_GLYPH_PACKET_DELIMITER) + if (p->data.length == 1 && p->data.data[0] == PSYC_PACKET_DELIMITER_CHAR) return PSYC_PACKET_NEED_LENGTH; if (p->data.length > PSYC_CONTENT_SIZE_THRESHOLD) @@ -110,6 +110,10 @@ size_t psyc_packet_length_set (PsycPacket *p) p->contentLength = p->content.length; else { + // add state operation + if (p->stateop != PSYC_STATE_NOOP) + p->contentLength += 2; // op\n + // add entity header length for (i = 0; i < p->entity.lines; i++) p->contentLength += psyc_modifier_length(&(p->entity.modifiers[i])); @@ -139,9 +143,9 @@ void psyc_packet_init (PsycPacket *p, PsycModifier *entity, size_t entitylen, char *method, size_t methodlen, char *data, size_t datalen, - PsycPacketFlag flag) + char stateop, PsycPacketFlag flag) { - *p = (PsycPacket) {{routinglen, routing}, {entitylen, entity}, + *p = (PsycPacket) {{routinglen, routing}, {entitylen, entity}, stateop, {methodlen, method}, {datalen, data}, {0,0}, 0, 0, flag}; if (flag == PSYC_PACKET_CHECK_LENGTH) // find out if it needs length @@ -156,7 +160,7 @@ void psyc_packet_init_raw (PsycPacket *p, char *content, size_t contentlen, PsycPacketFlag flag) { - *p = (PsycPacket) {{routinglen, routing}, {0,0}, {0,0}, {0,0}, + *p = (PsycPacket) {{routinglen, routing}, {0,0}, 0, {0,0}, {0,0}, {contentlen, content}, 0, 0, flag}; if (flag == PSYC_PACKET_CHECK_LENGTH) // find out if it needs length diff --git a/src/parse.c b/src/parse.c index 9dca3c2..51246c6 100644 --- a/src/parse.c +++ b/src/parse.c @@ -88,10 +88,6 @@ ParseRC psyc_parse_modifier (PsycParseState *state, char *oper, *oper = *(state->buffer.data + state->cursor); ADVANCE_CURSOR_OR_RETURN(PSYC_PARSE_INSUFFICIENT); - if (state->part == PSYC_PART_CONTENT && state->buffer.data[state->cursor] == '\n' && - (*oper == PSYC_OPERATOR_ASSIGN || *oper == PSYC_OPERATOR_QUERY)) - return PARSE_SUCCESS; // only oper is present, used for state sync/reset - ParseRC ret = psyc_parse_keyword(state, name); if (ret == PARSE_ERROR) return PSYC_PARSE_ERROR_MOD_NAME; @@ -287,6 +283,24 @@ PsycParseRC psyc_parse (PsycParseState *state, char *oper, // method does not start with a glyph. if (psyc_is_glyph(state->buffer.data[state->cursor])) { + ADVANCE_CURSOR_OR_RETURN(PSYC_PARSE_INSUFFICIENT); + if (state->contentParsed == 0 && state->buffer.data[state->cursor] == '\n') + { + *oper = *(state->buffer.data + state->cursor - 1); + switch (*oper) + { + case PSYC_STATE_SYNC: + state->contentParsed += 2; + return PSYC_PARSE_STATE_SYNC; + case PSYC_STATE_RESET: + state->contentParsed += 2; + return PSYC_PARSE_STATE_RESET; + default: + return PSYC_PARSE_ERROR_MOD_NAME; + } + } + state->cursor--; + ret = psyc_parse_modifier(state, oper, name, value); state->contentParsed += state->cursor - pos; diff --git a/src/render.c b/src/render.c index bd26745..887f82e 100644 --- a/src/render.c +++ b/src/render.c @@ -1,4 +1,5 @@ #include "lib.h" +#include #include #include @@ -46,25 +47,24 @@ static inline size_t psyc_render_modifier (PsycModifier *mod, char *buffer) { size_t cur = 0; + buffer[cur++] = mod->oper; + memcpy(buffer + cur, mod->name.data, mod->name.length); + cur += mod->name.length; + if (cur == 1) + return cur; // error, name can't be empty - if (mod->name.length > 0) + if (mod->flag == PSYC_MODIFIER_NEED_LENGTH) { - memcpy(buffer + cur, mod->name.data, mod->name.length); - cur += mod->name.length; - - if (mod->flag == PSYC_MODIFIER_NEED_LENGTH) - { - buffer[cur++] = ' '; - cur += itoa(mod->value.length, buffer + cur, 10); - } - - buffer[cur++] = '\t'; - memcpy(buffer + cur, mod->value.data, mod->value.length); - cur += mod->value.length; + buffer[cur++] = ' '; + cur += itoa(mod->value.length, buffer + cur, 10); } + buffer[cur++] = '\t'; + memcpy(buffer + cur, mod->value.data, mod->value.length); + cur += mod->value.length; buffer[cur++] = '\n'; + return cur; } @@ -92,7 +92,8 @@ PsycRenderRC psyc_render (PsycPacket *packet, char *buffer, size_t buflen) cur += itoa(packet->contentLength, buffer + cur, 10); if (packet->flag == PSYC_PACKET_NEED_LENGTH || packet->content.length || - packet->entity.lines || packet->method.length || packet->data.length) + packet->stateop || packet->entity.lines || + packet->method.length || packet->data.length) buffer[cur++] = '\n'; // start of content part if there's content or length if (packet->content.length) // render raw content if present @@ -102,6 +103,11 @@ PsycRenderRC psyc_render (PsycPacket *packet, char *buffer, size_t buflen) } else { + if (packet->stateop) { + buffer[cur++] = packet->stateop; + buffer[cur++] = '\n'; + } + // render entity modifiers for (i = 0; i < packet->entity.lines; i++) cur += psyc_render_modifier(&packet->entity.modifiers[i], buffer + cur); @@ -124,7 +130,7 @@ PsycRenderRC psyc_render (PsycPacket *packet, char *buffer, size_t buflen) } // add packet delimiter - buffer[cur++] = C_GLYPH_PACKET_DELIMITER; + buffer[cur++] = PSYC_PACKET_DELIMITER_CHAR; buffer[cur++] = '\n'; // actual length should be equal to pre-calculated length at this point diff --git a/test/test_psyc.c b/test/test_psyc.c index c9961b6..ad052ee 100644 --- a/test/test_psyc.c +++ b/test/test_psyc.c @@ -98,6 +98,11 @@ int test_input (int i, char *recvbuf, size_t nbytes) { packet->routing.lines++; break; + case PSYC_PARSE_STATE_SYNC: + case PSYC_PARSE_STATE_RESET: + packet->stateop = oper; + break; + case PSYC_PARSE_ENTITY_START: case PSYC_PARSE_ENTITY_CONT: case PSYC_PARSE_ENTITY_END: diff --git a/test/test_render.c b/test/test_render.c index 8e55ec0..58f6036 100644 --- a/test/test_render.c +++ b/test/test_render.c @@ -30,6 +30,7 @@ int testPresence (const char *avail, int availlen, entity, PSYC_NUM_ELEM(entity), PSYC_C2ARG("_notice_presence"), NULL, 0, + PSYC_STATE_NOOP, PSYC_PACKET_CHECK_LENGTH); char buffer[512]; @@ -82,6 +83,7 @@ int testList (const char *rendered, uint8_t verbose) entity, PSYC_NUM_ELEM(entity), PSYC_C2ARG("_test_list"), PSYC_C2ARG("list test"), + PSYC_STATE_NOOP, PSYC_PACKET_CHECK_LENGTH); char buffer[512];