diff --git a/Doxyfile b/Doxyfile index a05f707..38a7fa8 100644 --- a/Doxyfile +++ b/Doxyfile @@ -338,7 +338,7 @@ EXTRACT_PRIVATE = NO # If the EXTRACT_STATIC tag is set to YES all static members of a file # will be included in the documentation. -EXTRACT_STATIC = NO +EXTRACT_STATIC = YES # If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) # defined locally in source files will be included in the documentation. diff --git a/bench/benchmark.org b/bench/benchmark.org index 805f3fb..f67d5e1 100644 --- a/bench/benchmark.org +++ b/bench/benchmark.org @@ -138,8 +138,7 @@ Parsing time of 1 000 000 packets, in milliseconds. A simple strlen() scan of the respective message is provided for comparison. These tests were performed on a 2.53 GHz Intel(R) Core(TM)2 Duo P9500 CPU. -| input: | PSYC | | JSON | | | XML | | -| parser: | strlen | libpsyc | json-c | json-glib | libxml sax | libxml | rapidxml | +| | strlen | libpsyc | json-c | json-glib | libxml sax | libxml | rapidxml | |-----------------+--------+---------+--------+-----------+------------+--------+----------| | user profile | 55 | 608 | 4715 | 16503 | 7350 | 12377 | 2477 | | psyc-unfriendly | 70 | 286 | 2892 | 12567 | 5538 | 8659 | 1896 | @@ -151,21 +150,20 @@ These tests were performed on a 2.53 GHz Intel(R) Core(TM)2 Duo P9500 CPU. Pure syntax comparisons above, protocol performance comparisons below: -| input: | | PSYC | | JSON | | | XMPP | | -| parser: | strlen | libpsyc | compact | json-c | json-glib | libxml sax | libxml | rapidxml | -|----------+--------+---------+---------+--------+-----------+------------+--------+----------| -| presence | 30 | 236 | 122 | 2463 | 10016 | 4997 | 7557 | 1719 | -| chat msg | 40 | 295 | 258 | 2147 | 9526 | 5911 | 8999 | 1850 | -| activity | 42 | 353 | 279 | 4666 | 16327 | 13357 | 28858 | 4356 | -|----------+--------+---------+---------+--------+-----------+------------+--------+----------| -| / | < | | > | < | > | < | | > | +| | strlen | libpsyc | libpsyc compact | json-c | json-glib | libxml sax | libxml | rapidxml | +|----------+--------+---------+-----------------+--------+-----------+------------+--------+----------| +| presence | 30 | 236 | 122 | 2463 | 10016 | 4997 | 7557 | 1719 | +| chat msg | 40 | 295 | 258 | 2147 | 9526 | 5911 | 8999 | 1850 | +| activity | 42 | 353 | 279 | 4666 | 16327 | 13357 | 28858 | 4356 | +|----------+--------+---------+-----------------+--------+-----------+------------+--------+----------| +| / | < | | > | < | > | < | | > | +| | | | | | | | | | Parsing large amounts of binary data. For JSON & XML base64 encoding was used. Note that the results below include only the parsing time, base64 decoding was not performed. -| input: | PSYC | | JSON | | | XML | | -| parser: | strlen | libpsyc | json-c | json-glib | libxml sax | libxml | rapidxml | +| | strlen | libpsyc | json-c | json-glib | libxml sax | libxml | rapidxml | |---------+----------+---------+-----------+------------+------------+-----------+----------| | 7K | 978 | 77 | 18609 | 98000 | 11445 | 19299 | 8701 | | 70K | 9613 | 77 | 187540 | 1003900 | 96209 | 167738 | 74296 | diff --git a/d/include/psyc/packet.d b/d/include/psyc/packet.d new file mode 100644 index 0000000..b9584cb --- /dev/null +++ b/d/include/psyc/packet.d @@ -0,0 +1,182 @@ + /* + * Packet data structures and functions for creating them are defined here. + */ + +module psyc.packet; + +import psyc.common; +import psyc.syntax; + + +/** Modifier flags. */ +enum ModifierFlag +{ + /// Modifier needs to be checked if it needs length. + CHECK_LENGTH = 0, + /// Modifier needs length. + NEED_LENGTH = 1, + /// Modifier doesn't need length. + NO_LENGTH = 2, + /// Routing modifier, which implies that it doesn't need length. + ROUTING = 3, +}; + +/** List flags. */ +enum ListFlag +{ + /// List needs to be checked if it needs length. + CHECK_LENGTH = 0, + /// List needs length. + NEED_LENGTH = 1, + /// List doesn't need length. + NO_LENGTH = 2, +} ; + +/** Packet flags. */ +enum PacketFlag +{ + /// Packet needs to be checked if it needs content length. + CHECK_LENGTH = 0, + /// Packet needs content length. + NEED_LENGTH = 1, + /// Packet doesn't need content length. + NO_LENGTH = 2, +} ; + +/** Structure for a modifier. */ +struct Modifier +{ + char oper; + String name; + String value; + ModifierFlag flag; +} ; + +/** Structure for an entity or routing header. */ +struct Header +{ + size_t lines; + Modifier *modifiers; +} ; + +/** Structure for a list. */ +struct List +{ + size_t num_elems; + String *elems; + size_t length; + ListFlag flag; +} ; + +/** intermediate struct for a PSYC packet */ +struct Packet +{ + Header routing; ///< Routing header. + Header entity; ///< Entity header. + String method; ///< Contains the method. + String data; ///< Contains the data. + String 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. + PacketFlag flag; ///< Packet flag. +} ; + +/** + * \internal + * Check if a modifier needs length. + */ + +ModifierFlag psyc_checkModifierLength (Modifier *m) +{ + ModifierFlag flag; + + if (m->value.length > PSYC_MODIFIER_SIZE_THRESHOLD) + flag = ModifierFlag.NEED_LENGTH; + else if (memchr(m->value.ptr, (int)'\n', m->value.length)) + flag = ModifierFlag.NEED_LENGTH; + else + flag = ModifierFlag.NO_LENGTH; + + return flag; +} + +/** Create new modifier. */ + +Modifier psyc_newModifier (char oper, String *name, String *value, + ModifierFlag flag) +{ + Modifier m = {oper, *name, *value, flag}; + + if (flag == ModifierFlag.CHECK_LENGTH) // find out if it needs a length + m.flag = psyc_checkModifierLength(&m); + + return m; +} + +/** Create new modifier */ +Modifier psyc_newModifier2 (char oper, + char *name, size_t namelen, + char *value, size_t valuelen, + ModifierFlag flag) +{ + String n = {namelen, name}; + String v = {valuelen, value}; + + return psyc_newModifier(oper, &n, &v, flag); +} + +/** + * \internal + * Get the total length of a modifier when rendered. + */ +size_t psyc_getModifierLength (Modifier *m); + +/** + * \internal + * Check if a list needs length. + */ +ListFlag psyc_checkListLength (List *list); + +/** + * \internal + * Get the total length of a list when rendered. + */ +ListFlag psyc_getListLength (List *list); + +/** + * \internal + * Check if a packet needs length. + */ +PacketFlag psyc_checkPacketLength (Packet *p); + +/** + * Calculate and set the rendered length of packet parts and total packet length. + */ +size_t psyc_setPacketLength (Packet *p); + +/** Create new list. */ +List psyc_newList (String *elems, size_t num_elems, ListFlag flag); + +/** Create new packet. */ +Packet psyc_newPacket (Header *routing, + Header *entity, + String *method, String *data, + PacketFlag flag); + +/** Create new packet. */ +Packet psyc_newPacket2 (Modifier *routing, size_t routinglen, + Modifier *entity, size_t entitylen, + char *method, size_t methodlen, + char *data, size_t datalen, + PacketFlag flag); + +/** Create new packet with raw content. */ +Packet psyc_newRawPacket (Header *routing, String *content, + PacketFlag flag); + +/** Create new packet with raw content. */ +Packet psyc_newRawPacket2 (Modifier *routing, size_t routinglen, + char *content, size_t contentlen, + PacketFlag flag); + diff --git a/d/include/psyc/parse.d b/d/include/psyc/parse.d index adb9acd..dcc1015 100644 --- a/d/include/psyc/parse.d +++ b/d/include/psyc/parse.d @@ -159,25 +159,6 @@ struct ParseState return psyc_parse(this, &oper, cast(String*) &name, cast(String*) &value); } - /** - * Change parse flags in state - * - * Params: - * state = Pointer to the state struct that should be initialized. - * flags = Flags to be set for the parser, see psycParseFlag. - * - * See_Also: psyc_initParseState psycParseFlag - */ - void setParseFlags (ParseFlag flags) - { - this.flags = flags; - - if (flags & ParseFlag.START_AT_CONTENT) - this.part = Part.CONTENT; - else - this.part = Part.ROUTING; - } - /** * Sets a new buffer in the parser state struct with data to be parsed. * @@ -265,6 +246,7 @@ struct ParseState void getRemainingBuffer ( ref ubyte[] buf ) { + buf = this.buffer.ptr[cursor .. cursor + getRemainingLength()]; } diff --git a/d/include/psyc/render.d b/d/include/psyc/render.d new file mode 100644 index 0000000..f12bbbe --- /dev/null +++ b/d/include/psyc/render.d @@ -0,0 +1,57 @@ +module psyc.render; + +import psyc.packet; + + /* + * All rendering functions and the definitions they use are defined here. + */ + +/** + * Return codes for psyc_render. + */ +enum RenderRC +{ + /// Error, method is missing, but data is present. + ERROR_METHOD_MISSING = -3, + /// Error, a modifier name is missing. + ERROR_MODIFIER_NAME_MISSING = -2, + /// Error, buffer is too small to render the packet. + ERROR = -1, + /// Packet is rendered successfully in the buffer. + SUCCESS = 0, +} ; + +/** + * Return codes for psyc_renderList. + */ +enum RenderListRC +{ + /// Error, buffer is too small to render the list. + ERROR = -1, + /// List is rendered successfully in the buffer. + SUCCESS = 0, +}; + +/** + * Render a PSYC packet into a buffer. + * + * The packet structure should contain the packet parts, either routing, entity, + * method & data, or routing & content when rendering raw content. + * It should also contain the contentLength & total length of the packet, + * you can use psyc_setPacketLength() for calculating & setting these values. + * This function renders packet->length bytes to the buffer, + * if buflen is less than that an error is returned. + * + * @see psyc_newPacket + * @see psyc_newPacket2 + * @see psyc_newRawPacket + * @see psyc_newRawPacket2 + * @see psyc_setPacketLength + */ +RenderRC psyc_render (Packet *packet, char *buffer, size_t buflen); + +/** + * Render a PSYC list into a buffer. + */ +RenderListRC psyc_renderList (List *list, char *buffer, size_t buflen); + diff --git a/d/include/psyc/syntax.d b/d/include/psyc/syntax.d new file mode 100644 index 0000000..a5fcfe3 --- /dev/null +++ b/d/include/psyc/syntax.d @@ -0,0 +1,36 @@ +module psyc.syntax; + +const PSYC_LIST_SIZE_LIMIT = 404; + +/* beyond this a content length must be provided */ +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 = "?"; + +/* might move into routing.h or something */ +const PSYC_ROUTING = 1; +const PSYC_ROUTING_MERGE = 2; +const PSYC_ROUTING_RENDER = 4; diff --git a/include/psyc.h b/include/psyc.h index 6146665..769ea8b 100644 --- a/include/psyc.h +++ b/include/psyc.h @@ -88,9 +88,9 @@ typedef enum typedef struct { /// Length of the data pointed to by ptr - size_t length; + size_t length; /// pointer to the data - const char *ptr; + const char *ptr; } psycString; typedef struct diff --git a/include/psyc/packet.h b/include/psyc/packet.h index 94d16f3..5407ba2 100644 --- a/include/psyc/packet.h +++ b/include/psyc/packet.h @@ -92,7 +92,10 @@ typedef struct psycPacketFlag flag; ///< Packet flag. } psycPacket; -/** Check if a modifier needs length. */ +/** + * \internal + * Check if a modifier needs length. + */ static inline psycModifierFlag psyc_checkModifierLength (psycModifier *m) { @@ -134,19 +137,33 @@ psycModifier psyc_newModifier2 (char oper, return psyc_newModifier(oper, &n, &v, flag); } -/** Get the total length of a modifier when rendered. */ +/** + * \internal + * Get the total length of a modifier when rendered. + */ size_t psyc_getModifierLength (psycModifier *m); -/** Check if a list needs length. */ +/** + * \internal + * Check if a list needs length. + */ psycListFlag psyc_checkListLength (psycList *list); -/** Get the total length of a list when rendered. */ +/** + * \internal + * Get the total length of a list when rendered. + */ psycListFlag psyc_getListLength (psycList *list); -/** Check if a packet needs length. */ +/** + * \internal + * Check if a packet needs length. + */ psycPacketFlag psyc_checkPacketLength (psycPacket *p); -/** Calculate and set the rendered length of packet parts and total packet length. */ +/** + * Calculate and set the rendered length of packet parts and total packet length. + */ size_t psyc_setPacketLength (psycPacket *p); /** Create new list. */ diff --git a/include/psyc/parse.h b/include/psyc/parse.h index 1b6ef6a..08eacc4 100644 --- a/include/psyc/parse.h +++ b/include/psyc/parse.h @@ -40,9 +40,7 @@ * char* raw_data; // points to our (possibly incomplete) packet * size_t raw_len; // how many bytes of data * - * psyc_setParseBuffer(&state, // our initialized state from before - * raw_data, - * raw_len); + * psyc_setParseBuffer(&state, raw_data, raw_len); // state is our initialized state from before * @endcode * * Now the the variables that will save the output of the parser need to be @@ -179,10 +177,10 @@ typedef enum /// Start of an incomplete content, value contains part of content. /// Used when PSYC_PARSE_ROUTING_ONLY is set. PSYC_PARSE_CONTENT_START = 7, - /// Continuation of an incomplete body. + /// Continuation of an incomplete content. /// Used when PSYC_PARSE_ROUTING_ONLY is set. PSYC_PARSE_CONTENT_CONT = 8, - /// End of an incomplete body. + /// End of an incomplete content. /// Used when PSYC_PARSE_ROUTING_ONLY is set. PSYC_PARSE_CONTENT_END = 9, /// Content parsing done in one go, value contains the whole content. @@ -274,27 +272,6 @@ void psyc_initParseState2 (psycParseState *state, uint8_t flags) state->part = PSYC_PART_CONTENT; } -/** - * Change parse flags in state - * - * @param state Pointer to the state struct that should be initialized. - * @param flags Flags to be set for the parser, see psycParseFlag. - * @see psyc_initParseState - * @see psycParseFlag - */ -static inline -void psyc_setParseFlags (psycParseState *state, uint8_t flags) -{ - state->flags = flags; - - if (flags & PSYC_PARSE_START_AT_CONTENT) - state->part = PSYC_PART_CONTENT; - else - state->part = 0; -} - - - /** * Sets a new buffer in the parser state struct with data to be parsed. * @@ -330,7 +307,7 @@ void psyc_setParseBuffer (psycParseState *state, psycString buffer) * @see psycString */ static inline -void psyc_setParseBuffer2 (psycParseState *state, char *buffer, size_t length) +void psyc_setParseBuffer2 (psycParseState *state, const char *buffer, size_t length) { psycString buf = {length, buffer}; psyc_setParseBuffer(state, buf); @@ -358,7 +335,7 @@ void psyc_setParseListBuffer (psycParseListState *state, psycString buffer) } static inline -void psyc_setParseListBuffer2 (psycParseListState *state, char *buffer, size_t length) +void psyc_setParseListBuffer2 (psycParseListState *state, const char *buffer, size_t length) { psycString buf = {length, buffer}; psyc_setParseListBuffer(state, buf); diff --git a/include/psyc/text.h b/include/psyc/text.h index 5b964b3..a94dd3b 100644 --- a/include/psyc/text.h +++ b/include/psyc/text.h @@ -26,7 +26,7 @@ typedef enum /// Text template parsing & rendering complete. PSYC_TEXT_COMPLETE = 0, /// Text template parsing & rendering is incomplete, because the buffer was too small. - /// Another call is required to this function with a new buffer. + /// Another call is required to this function after setting a new buffer. PSYC_TEXT_INCOMPLETE = 1, } psycTextRC; @@ -48,8 +48,8 @@ typedef struct { size_t cursor; ///< current position in the template size_t written; ///< number of bytes written to buffer - psycString template; ///< template to parse - psycString buffer; ///< buffer for writing to + psycString tmpl; ///< input buffer with text template to parse + psycString buffer; ///< output buffer for rendered text psycString open; psycString close; } psycTextState; @@ -70,32 +70,32 @@ typedef psycTextValueRC (*psycTextCB)(const char *name, size_t len, psycString * * Initializes the PSYC text state struct. * * @param state Pointer to the PSYC text state struct that should be initialized. - * @param template Text template to be parsed. - * @param tlen Length of template. - * @param buffer Buffer where the rendered text is going to be written. - * @param blen Length of buffer. + * @param tmpl Input buffer with text template to be parsed. + * @param tmplen Length of input buffer. + * @param buffer Output buffer where the rendered text is going to be written. + * @param buflen Length of output buffer. */ static inline void psyc_initTextState (psycTextState *state, - char *template, size_t tlen, - char *buffer, size_t blen) + const char *tmpl, size_t tmplen, + char *buffer, size_t buflen) { - state->cursor = 0; - state->written = 0; - state->template = (psycString) {tlen, template}; - state->buffer = (psycString) {blen, buffer}; - state->open = (psycString) {1, "["}; - state->close = (psycString) {1, "]"}; + state->cursor = 0; + state->written = 0; + state->tmpl = (psycString) {tmplen, tmpl}; + state->buffer = (psycString) {buflen, buffer}; + state->open = (psycString) {1, "["}; + state->close = (psycString) {1, "]"}; } /** - * Initializes the PSYC text state struct with custom open & closing braces. + * Initializes the PSYC text state struct with custom opening & closing braces. * * @param state Pointer to the PSYC text state struct that should be initialized. - * @param template Text template to be parsed. - * @param tlen Length of template. - * @param buffer Buffer where the rendered text is going to be written. - * @param blen Length of buffer. + * @param tmpl Input buffer with text template to be parsed. + * @param tmplen Length of input buffer. + * @param buffer Output buffer where the rendered text is going to be written. + * @param buflen Length of output buffer. * @param open Opening brace. * @param openlen Length of opening brace. * @param close Closing brace. @@ -103,19 +103,21 @@ void psyc_initTextState (psycTextState *state, */ static inline void psyc_initTextState2 (psycTextState *state, - char *template, size_t tlen, - char *buffer, size_t blen, - char *open, size_t openlen, - char *close, size_t closelen) + const char *tmpl, size_t tmplen, + char *buffer, size_t buflen, + const char *open, size_t openlen, + const char *close, size_t closelen) { - state->template = (psycString) {tlen, template}; - state->buffer = (psycString) {blen, buffer}; - state->open = (psycString) {openlen, open}; - state->close = (psycString) {closelen, close}; + state->cursor = 0; + state->written = 0; + state->tmpl = (psycString) {tmplen, tmpl}; + state->buffer = (psycString) {buflen, buffer}; + state->open = (psycString) {openlen, open}; + state->close = (psycString) {closelen, close}; } /** - * Sets a new buffer in the PSYC text state struct. + * Sets a new output buffer in the PSYC text state struct. */ static inline void psyc_setTextBuffer (psycTextState *state, psycString buffer) @@ -149,10 +151,10 @@ size_t psyc_getTextBytesWritten (psycTextState *state) * string between these braces. Should the callback return * PSYC_TEXT_VALUE_NOT_FOUND, the original template text is copied as is. * - * Before calling this function psyc_initTextState or psyc_initTextState should - * be called to initialze the state struct. By default PSYC's "[" and "]" are - * used but you can provide any other brace strings such as "${" and "}" or - * "". + * Before calling this function psyc_initTextState should be called to initialize + * the state struct. By default PSYC's "[" and "]" are used but you can provide + * any other brace strings such as "${" and "}" or "" if you use + * the psyc_initTextState2 variant. * * @see http://about.psyc.eu/psyctext **/ diff --git a/src/Makefile b/src/Makefile index 3ef9d67..822ccfa 100644 --- a/src/Makefile +++ b/src/Makefile @@ -1,12 +1,15 @@ OPT = -O2 DEBUG = 2 -CFLAGS = -I../include -Wall -std=c99 ${OPT} +CFLAGS = -I../include -Wall -std=c99 -fPIC ${OPT} DIET = diet S = packet.c parse.c match.c render.c memmem.c itoa.c variable.c text.c O = packet.o parse.o match.o render.o memmem.o itoa.o variable.o text.o P = match itoa +A = ../lib/libpsyc.a +SO = ../lib/libpsyc.so + all: CC := ${WRAPPER} ${CC} all: lib @@ -18,9 +21,15 @@ diet: WRAPPER = ${DIET} diet: CC := ${WRAPPER} ${CC} diet: lib -lib: $O +lib: $O $A ${SO} + +${SO}: @mkdir -p ../lib - ${WRAPPER} ${AR} rcs ../lib/libpsyc.a $O + ${CC} ${CFLAGS} -shared -lm -o $@ $O + +$A: + @mkdir -p ../lib + ${WRAPPER} ${AR} rcs $@ $O match: match.c ${CC} -o $@ -DDEBUG=4 -DCMDTOOL -DTEST $< diff --git a/src/text.c b/src/text.c index 70a437b..c4a5fea 100644 --- a/src/text.c +++ b/src/text.c @@ -3,29 +3,29 @@ psycTextRC psyc_text (psycTextState *state, psycTextCB getValue) { - const char *start = state->template.ptr, *end; // start & end of variable name - const char *prev = state->template.ptr + state->cursor; + const char *start = state->tmpl.ptr, *end; // start & end of variable name + const char *prev = state->tmpl.ptr + state->cursor; psycString value; int ret; size_t len; uint8_t no_subst = (state->cursor == 0); // whether we can return NO_SUBST - while (state->cursor < state->template.length) + while (state->cursor < state->tmpl.length) { - start = memmem(state->template.ptr + state->cursor, - state->template.length - state->cursor, + start = memmem(state->tmpl.ptr + state->cursor, + state->tmpl.length - state->cursor, state->open.ptr, state->open.length); if (!start) break; - state->cursor = (start - state->template.ptr) + state->open.length; - if (state->cursor >= state->template.length) + state->cursor = (start - state->tmpl.ptr) + state->open.length; + if (state->cursor >= state->tmpl.length) break; // [ at the end - end = memmem(state->template.ptr + state->cursor, - state->template.length - state->cursor, + end = memmem(state->tmpl.ptr + state->cursor, + state->tmpl.length - state->cursor, state->close.ptr, state->close.length); - state->cursor = (end - state->template.ptr) + state->close.length; + state->cursor = (end - state->tmpl.ptr) + state->close.length; if (!end) break; // ] not found @@ -40,12 +40,12 @@ psycTextRC psyc_text (psycTextState *state, psycTextCB getValue) if (ret < 0) continue; // value not found, no substitution - // first copy the part in the template from the previous subst. to the current one + // first copy the part in the input from the previous subst. to the current one // if there's enough buffer space for that len = start - prev; if (state->written + len > state->buffer.length) { - state->cursor = prev - state->template.ptr; + state->cursor = prev - state->tmpl.ptr; return PSYC_TEXT_INCOMPLETE; } @@ -55,7 +55,7 @@ psycTextRC psyc_text (psycTextState *state, psycTextCB getValue) // now substitute the value if there's enough buffer space if (state->written + value.length > state->buffer.length) { - state->cursor = start - state->template.ptr; + state->cursor = start - state->tmpl.ptr; return PSYC_TEXT_INCOMPLETE; } @@ -63,7 +63,7 @@ psycTextRC psyc_text (psycTextState *state, psycTextCB getValue) state->written += value.length; // mark the start of the next chunk of text in the template - prev = state->template.ptr + state->cursor; + prev = state->tmpl.ptr + state->cursor; no_subst = 0; } @@ -71,7 +71,7 @@ psycTextRC psyc_text (psycTextState *state, psycTextCB getValue) return PSYC_TEXT_NO_SUBST; // copy the rest of the template after the last var - len = state->template.length - (prev - state->template.ptr); + len = state->tmpl.length - (prev - state->tmpl.ptr); if (state->written + len > state->buffer.length) return PSYC_TEXT_INCOMPLETE; diff --git a/test/packets/00-body-only b/test/packets/00-body-only new file mode 100644 index 0000000..116d391 --- /dev/null +++ b/test/packets/00-body-only @@ -0,0 +1,4 @@ + +_message_private +OHAI +| diff --git a/test/packets/00-empty b/test/packets/00-empty new file mode 100644 index 0000000..948cf94 --- /dev/null +++ b/test/packets/00-empty @@ -0,0 +1 @@ +| diff --git a/test/packets/00-length-body-only b/test/packets/00-length-body-only new file mode 100644 index 0000000..22e96eb --- /dev/null +++ b/test/packets/00-length-body-only @@ -0,0 +1,4 @@ +22 +_message_private +OHAI +| diff --git a/test/packets/00-length-no-entity b/test/packets/00-length-no-entity new file mode 100644 index 0000000..27785b5 --- /dev/null +++ b/test/packets/00-length-no-entity @@ -0,0 +1,6 @@ +:_source psyc://foo.example.com/ +:_target psyc://bar.example.com/ +22 +_message_private +OHAI +| diff --git a/test/packets/00-method-only-1 b/test/packets/00-method-only-1 new file mode 100644 index 0000000..0da4d2f --- /dev/null +++ b/test/packets/00-method-only-1 @@ -0,0 +1,3 @@ + +_ +| diff --git a/test/testPsyc.c b/test/testPsyc.c index 087beaf..43e969e 100644 --- a/test/testPsyc.c +++ b/test/testPsyc.c @@ -80,6 +80,8 @@ int test_input (int i, char *recvbuf, size_t nbytes) { value.length = 0; do { + if (verbose >= 3) + printf("\n# buffer = [%.*s]\n# part = %d\n", (int)parsers[i].buffer.length, parsers[i].buffer.ptr, parsers[i].part); // Parse the next part of the packet (a routing/entity modifier or the body) ret = exit_code = psyc_parse(&parsers[i], &oper, &name, &value); if (verbose >= 2) @@ -188,6 +190,8 @@ int test_input (int i, char *recvbuf, size_t nbytes) { contbytes = psyc_getParseRemainingLength(&parsers[i]); if (contbytes > 0) { // copy end of parsebuf before start of recvbuf + if (verbose >= 3) + printf("# remaining = [%.*s]\n", (int)contbytes, psyc_getParseRemainingBuffer(&parsers[i])); assert(contbytes <= CONT_BUF_SIZE); // make sure it's still in the buffer memmove(recvbuf - contbytes, psyc_getParseRemainingBuffer(&parsers[i]), contbytes); }