mirror of
git://git.psyc.eu/libpsyc
synced 2024-08-15 03:19:02 +00:00
Merge commit 'origin'
This commit is contained in:
commit
f55f105ff9
18 changed files with 401 additions and 119 deletions
2
Doxyfile
2
Doxyfile
|
@ -338,7 +338,7 @@ EXTRACT_PRIVATE = NO
|
||||||
# If the EXTRACT_STATIC tag is set to YES all static members of a file
|
# If the EXTRACT_STATIC tag is set to YES all static members of a file
|
||||||
# will be included in the documentation.
|
# 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)
|
# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs)
|
||||||
# defined locally in source files will be included in the documentation.
|
# defined locally in source files will be included in the documentation.
|
||||||
|
|
|
@ -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.
|
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.
|
These tests were performed on a 2.53 GHz Intel(R) Core(TM)2 Duo P9500 CPU.
|
||||||
|
|
||||||
| input: | PSYC | | JSON | | | XML | |
|
| | strlen | libpsyc | json-c | json-glib | libxml sax | libxml | rapidxml |
|
||||||
| parser: | strlen | libpsyc | json-c | json-glib | libxml sax | libxml | rapidxml |
|
|
||||||
|-----------------+--------+---------+--------+-----------+------------+--------+----------|
|
|-----------------+--------+---------+--------+-----------+------------+--------+----------|
|
||||||
| user profile | 55 | 608 | 4715 | 16503 | 7350 | 12377 | 2477 |
|
| user profile | 55 | 608 | 4715 | 16503 | 7350 | 12377 | 2477 |
|
||||||
| psyc-unfriendly | 70 | 286 | 2892 | 12567 | 5538 | 8659 | 1896 |
|
| 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:
|
Pure syntax comparisons above, protocol performance comparisons below:
|
||||||
|
|
||||||
| input: | | PSYC | | JSON | | | XMPP | |
|
| | strlen | libpsyc | libpsyc compact | json-c | json-glib | libxml sax | libxml | rapidxml |
|
||||||
| parser: | strlen | libpsyc | compact | json-c | json-glib | libxml sax | libxml | rapidxml |
|
|----------+--------+---------+-----------------+--------+-----------+------------+--------+----------|
|
||||||
|----------+--------+---------+---------+--------+-----------+------------+--------+----------|
|
| presence | 30 | 236 | 122 | 2463 | 10016 | 4997 | 7557 | 1719 |
|
||||||
| presence | 30 | 236 | 122 | 2463 | 10016 | 4997 | 7557 | 1719 |
|
| chat msg | 40 | 295 | 258 | 2147 | 9526 | 5911 | 8999 | 1850 |
|
||||||
| chat msg | 40 | 295 | 258 | 2147 | 9526 | 5911 | 8999 | 1850 |
|
| activity | 42 | 353 | 279 | 4666 | 16327 | 13357 | 28858 | 4356 |
|
||||||
| activity | 42 | 353 | 279 | 4666 | 16327 | 13357 | 28858 | 4356 |
|
|----------+--------+---------+-----------------+--------+-----------+------------+--------+----------|
|
||||||
|----------+--------+---------+---------+--------+-----------+------------+--------+----------|
|
| / | < | | > | < | > | < | | > |
|
||||||
| / | < | | > | < | > | < | | > |
|
| | | | <c> | | | | | |
|
||||||
|
|
||||||
Parsing large amounts of binary data. For JSON & XML base64 encoding was used.
|
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
|
Note that the results below include only the parsing time, base64 decoding was
|
||||||
not performed.
|
not performed.
|
||||||
|
|
||||||
| input: | PSYC | | JSON | | | XML | |
|
| | strlen | libpsyc | json-c | json-glib | libxml sax | libxml | rapidxml |
|
||||||
| parser: | strlen | libpsyc | json-c | json-glib | libxml sax | libxml | rapidxml |
|
|
||||||
|---------+----------+---------+-----------+------------+------------+-----------+----------|
|
|---------+----------+---------+-----------+------------+------------+-----------+----------|
|
||||||
| 7K | 978 | 77 | 18609 | 98000 | 11445 | 19299 | 8701 |
|
| 7K | 978 | 77 | 18609 | 98000 | 11445 | 19299 | 8701 |
|
||||||
| 70K | 9613 | 77 | 187540 | 1003900 | 96209 | 167738 | 74296 |
|
| 70K | 9613 | 77 | 187540 | 1003900 | 96209 | 167738 | 74296 |
|
||||||
|
|
182
d/include/psyc/packet.d
Normal file
182
d/include/psyc/packet.d
Normal file
|
@ -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);
|
||||||
|
|
|
@ -159,25 +159,6 @@ struct ParseState
|
||||||
return psyc_parse(this, &oper, cast(String*) &name, cast(String*) &value);
|
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.
|
* 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 )
|
void getRemainingBuffer ( ref ubyte[] buf )
|
||||||
{
|
{
|
||||||
|
|
||||||
buf = this.buffer.ptr[cursor .. cursor + getRemainingLength()];
|
buf = this.buffer.ptr[cursor .. cursor + getRemainingLength()];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
57
d/include/psyc/render.d
Normal file
57
d/include/psyc/render.d
Normal file
|
@ -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);
|
||||||
|
|
36
d/include/psyc/syntax.d
Normal file
36
d/include/psyc/syntax.d
Normal file
|
@ -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;
|
|
@ -88,9 +88,9 @@ typedef enum
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
/// Length of the data pointed to by ptr
|
/// Length of the data pointed to by ptr
|
||||||
size_t length;
|
size_t length;
|
||||||
/// pointer to the data
|
/// pointer to the data
|
||||||
const char *ptr;
|
const char *ptr;
|
||||||
} psycString;
|
} psycString;
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
|
|
|
@ -92,7 +92,10 @@ typedef struct
|
||||||
psycPacketFlag flag; ///< Packet flag.
|
psycPacketFlag flag; ///< Packet flag.
|
||||||
} psycPacket;
|
} psycPacket;
|
||||||
|
|
||||||
/** Check if a modifier needs length. */
|
/**
|
||||||
|
* \internal
|
||||||
|
* Check if a modifier needs length.
|
||||||
|
*/
|
||||||
static inline
|
static inline
|
||||||
psycModifierFlag psyc_checkModifierLength (psycModifier *m)
|
psycModifierFlag psyc_checkModifierLength (psycModifier *m)
|
||||||
{
|
{
|
||||||
|
@ -134,19 +137,33 @@ psycModifier psyc_newModifier2 (char oper,
|
||||||
return psyc_newModifier(oper, &n, &v, flag);
|
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);
|
size_t psyc_getModifierLength (psycModifier *m);
|
||||||
|
|
||||||
/** Check if a list needs length. */
|
/**
|
||||||
|
* \internal
|
||||||
|
* Check if a list needs length.
|
||||||
|
*/
|
||||||
psycListFlag psyc_checkListLength (psycList *list);
|
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);
|
psycListFlag psyc_getListLength (psycList *list);
|
||||||
|
|
||||||
/** Check if a packet needs length. */
|
/**
|
||||||
|
* \internal
|
||||||
|
* Check if a packet needs length.
|
||||||
|
*/
|
||||||
psycPacketFlag psyc_checkPacketLength (psycPacket *p);
|
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);
|
size_t psyc_setPacketLength (psycPacket *p);
|
||||||
|
|
||||||
/** Create new list. */
|
/** Create new list. */
|
||||||
|
|
|
@ -40,9 +40,7 @@
|
||||||
* char* raw_data; // points to our (possibly incomplete) packet
|
* char* raw_data; // points to our (possibly incomplete) packet
|
||||||
* size_t raw_len; // how many bytes of data
|
* size_t raw_len; // how many bytes of data
|
||||||
*
|
*
|
||||||
* psyc_setParseBuffer(&state, // our initialized state from before
|
* psyc_setParseBuffer(&state, raw_data, raw_len); // state is our initialized state from before
|
||||||
* raw_data,
|
|
||||||
* raw_len);
|
|
||||||
* @endcode
|
* @endcode
|
||||||
*
|
*
|
||||||
* Now the the variables that will save the output of the parser need to be
|
* 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.
|
/// Start of an incomplete content, value contains part of content.
|
||||||
/// Used when PSYC_PARSE_ROUTING_ONLY is set.
|
/// Used when PSYC_PARSE_ROUTING_ONLY is set.
|
||||||
PSYC_PARSE_CONTENT_START = 7,
|
PSYC_PARSE_CONTENT_START = 7,
|
||||||
/// Continuation of an incomplete body.
|
/// Continuation of an incomplete content.
|
||||||
/// Used when PSYC_PARSE_ROUTING_ONLY is set.
|
/// Used when PSYC_PARSE_ROUTING_ONLY is set.
|
||||||
PSYC_PARSE_CONTENT_CONT = 8,
|
PSYC_PARSE_CONTENT_CONT = 8,
|
||||||
/// End of an incomplete body.
|
/// End of an incomplete content.
|
||||||
/// Used when PSYC_PARSE_ROUTING_ONLY is set.
|
/// Used when PSYC_PARSE_ROUTING_ONLY is set.
|
||||||
PSYC_PARSE_CONTENT_END = 9,
|
PSYC_PARSE_CONTENT_END = 9,
|
||||||
/// Content parsing done in one go, value contains the whole content.
|
/// 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;
|
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.
|
* 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
|
* @see psycString
|
||||||
*/
|
*/
|
||||||
static inline
|
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};
|
psycString buf = {length, buffer};
|
||||||
psyc_setParseBuffer(state, buf);
|
psyc_setParseBuffer(state, buf);
|
||||||
|
@ -358,7 +335,7 @@ void psyc_setParseListBuffer (psycParseListState *state, psycString buffer)
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline
|
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};
|
psycString buf = {length, buffer};
|
||||||
psyc_setParseListBuffer(state, buf);
|
psyc_setParseListBuffer(state, buf);
|
||||||
|
|
|
@ -26,7 +26,7 @@ typedef enum
|
||||||
/// Text template parsing & rendering complete.
|
/// Text template parsing & rendering complete.
|
||||||
PSYC_TEXT_COMPLETE = 0,
|
PSYC_TEXT_COMPLETE = 0,
|
||||||
/// Text template parsing & rendering is incomplete, because the buffer was too small.
|
/// 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,
|
PSYC_TEXT_INCOMPLETE = 1,
|
||||||
} psycTextRC;
|
} psycTextRC;
|
||||||
|
|
||||||
|
@ -48,8 +48,8 @@ typedef struct
|
||||||
{
|
{
|
||||||
size_t cursor; ///< current position in the template
|
size_t cursor; ///< current position in the template
|
||||||
size_t written; ///< number of bytes written to buffer
|
size_t written; ///< number of bytes written to buffer
|
||||||
psycString template; ///< template to parse
|
psycString tmpl; ///< input buffer with text template to parse
|
||||||
psycString buffer; ///< buffer for writing to
|
psycString buffer; ///< output buffer for rendered text
|
||||||
psycString open;
|
psycString open;
|
||||||
psycString close;
|
psycString close;
|
||||||
} psycTextState;
|
} psycTextState;
|
||||||
|
@ -70,32 +70,32 @@ typedef psycTextValueRC (*psycTextCB)(const char *name, size_t len, psycString *
|
||||||
* Initializes the PSYC text state struct.
|
* Initializes the PSYC text state struct.
|
||||||
*
|
*
|
||||||
* @param state Pointer to the PSYC text state struct that should be initialized.
|
* @param state Pointer to the PSYC text state struct that should be initialized.
|
||||||
* @param template Text template to be parsed.
|
* @param tmpl Input buffer with text template to be parsed.
|
||||||
* @param tlen Length of template.
|
* @param tmplen Length of input buffer.
|
||||||
* @param buffer Buffer where the rendered text is going to be written.
|
* @param buffer Output buffer where the rendered text is going to be written.
|
||||||
* @param blen Length of buffer.
|
* @param buflen Length of output buffer.
|
||||||
*/
|
*/
|
||||||
static inline
|
static inline
|
||||||
void psyc_initTextState (psycTextState *state,
|
void psyc_initTextState (psycTextState *state,
|
||||||
char *template, size_t tlen,
|
const char *tmpl, size_t tmplen,
|
||||||
char *buffer, size_t blen)
|
char *buffer, size_t buflen)
|
||||||
{
|
{
|
||||||
state->cursor = 0;
|
state->cursor = 0;
|
||||||
state->written = 0;
|
state->written = 0;
|
||||||
state->template = (psycString) {tlen, template};
|
state->tmpl = (psycString) {tmplen, tmpl};
|
||||||
state->buffer = (psycString) {blen, buffer};
|
state->buffer = (psycString) {buflen, buffer};
|
||||||
state->open = (psycString) {1, "["};
|
state->open = (psycString) {1, "["};
|
||||||
state->close = (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 state Pointer to the PSYC text state struct that should be initialized.
|
||||||
* @param template Text template to be parsed.
|
* @param tmpl Input buffer with text template to be parsed.
|
||||||
* @param tlen Length of template.
|
* @param tmplen Length of input buffer.
|
||||||
* @param buffer Buffer where the rendered text is going to be written.
|
* @param buffer Output buffer where the rendered text is going to be written.
|
||||||
* @param blen Length of buffer.
|
* @param buflen Length of output buffer.
|
||||||
* @param open Opening brace.
|
* @param open Opening brace.
|
||||||
* @param openlen Length of opening brace.
|
* @param openlen Length of opening brace.
|
||||||
* @param close Closing brace.
|
* @param close Closing brace.
|
||||||
|
@ -103,19 +103,21 @@ void psyc_initTextState (psycTextState *state,
|
||||||
*/
|
*/
|
||||||
static inline
|
static inline
|
||||||
void psyc_initTextState2 (psycTextState *state,
|
void psyc_initTextState2 (psycTextState *state,
|
||||||
char *template, size_t tlen,
|
const char *tmpl, size_t tmplen,
|
||||||
char *buffer, size_t blen,
|
char *buffer, size_t buflen,
|
||||||
char *open, size_t openlen,
|
const char *open, size_t openlen,
|
||||||
char *close, size_t closelen)
|
const char *close, size_t closelen)
|
||||||
{
|
{
|
||||||
state->template = (psycString) {tlen, template};
|
state->cursor = 0;
|
||||||
state->buffer = (psycString) {blen, buffer};
|
state->written = 0;
|
||||||
state->open = (psycString) {openlen, open};
|
state->tmpl = (psycString) {tmplen, tmpl};
|
||||||
state->close = (psycString) {closelen, close};
|
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
|
static inline
|
||||||
void psyc_setTextBuffer (psycTextState *state, psycString buffer)
|
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
|
* string between these braces. Should the callback return
|
||||||
* PSYC_TEXT_VALUE_NOT_FOUND, the original template text is copied as is.
|
* PSYC_TEXT_VALUE_NOT_FOUND, the original template text is copied as is.
|
||||||
*
|
*
|
||||||
* Before calling this function psyc_initTextState or psyc_initTextState should
|
* Before calling this function psyc_initTextState should be called to initialize
|
||||||
* be called to initialze the state struct. By default PSYC's "[" and "]" are
|
* the state struct. By default PSYC's "[" and "]" are used but you can provide
|
||||||
* used but you can provide any other brace strings such as "${" and "}" or
|
* any other brace strings such as "${" and "}" or "<!--" and "-->" if you use
|
||||||
* "<!--" and "-->".
|
* the psyc_initTextState2 variant.
|
||||||
*
|
*
|
||||||
* @see http://about.psyc.eu/psyctext
|
* @see http://about.psyc.eu/psyctext
|
||||||
**/
|
**/
|
||||||
|
|
15
src/Makefile
15
src/Makefile
|
@ -1,12 +1,15 @@
|
||||||
OPT = -O2
|
OPT = -O2
|
||||||
DEBUG = 2
|
DEBUG = 2
|
||||||
CFLAGS = -I../include -Wall -std=c99 ${OPT}
|
CFLAGS = -I../include -Wall -std=c99 -fPIC ${OPT}
|
||||||
DIET = diet
|
DIET = diet
|
||||||
|
|
||||||
S = packet.c parse.c match.c render.c memmem.c itoa.c variable.c text.c
|
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
|
O = packet.o parse.o match.o render.o memmem.o itoa.o variable.o text.o
|
||||||
P = match itoa
|
P = match itoa
|
||||||
|
|
||||||
|
A = ../lib/libpsyc.a
|
||||||
|
SO = ../lib/libpsyc.so
|
||||||
|
|
||||||
all: CC := ${WRAPPER} ${CC}
|
all: CC := ${WRAPPER} ${CC}
|
||||||
all: lib
|
all: lib
|
||||||
|
|
||||||
|
@ -18,9 +21,15 @@ diet: WRAPPER = ${DIET}
|
||||||
diet: CC := ${WRAPPER} ${CC}
|
diet: CC := ${WRAPPER} ${CC}
|
||||||
diet: lib
|
diet: lib
|
||||||
|
|
||||||
lib: $O
|
lib: $O $A ${SO}
|
||||||
|
|
||||||
|
${SO}:
|
||||||
@mkdir -p ../lib
|
@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
|
match: match.c
|
||||||
${CC} -o $@ -DDEBUG=4 -DCMDTOOL -DTEST $<
|
${CC} -o $@ -DDEBUG=4 -DCMDTOOL -DTEST $<
|
||||||
|
|
30
src/text.c
30
src/text.c
|
@ -3,29 +3,29 @@
|
||||||
|
|
||||||
psycTextRC psyc_text (psycTextState *state, psycTextCB getValue)
|
psycTextRC psyc_text (psycTextState *state, psycTextCB getValue)
|
||||||
{
|
{
|
||||||
const char *start = state->template.ptr, *end; // start & end of variable name
|
const char *start = state->tmpl.ptr, *end; // start & end of variable name
|
||||||
const char *prev = state->template.ptr + state->cursor;
|
const char *prev = state->tmpl.ptr + state->cursor;
|
||||||
psycString value;
|
psycString value;
|
||||||
int ret;
|
int ret;
|
||||||
size_t len;
|
size_t len;
|
||||||
uint8_t no_subst = (state->cursor == 0); // whether we can return NO_SUBST
|
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,
|
start = memmem(state->tmpl.ptr + state->cursor,
|
||||||
state->template.length - state->cursor,
|
state->tmpl.length - state->cursor,
|
||||||
state->open.ptr, state->open.length);
|
state->open.ptr, state->open.length);
|
||||||
if (!start)
|
if (!start)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
state->cursor = (start - state->template.ptr) + state->open.length;
|
state->cursor = (start - state->tmpl.ptr) + state->open.length;
|
||||||
if (state->cursor >= state->template.length)
|
if (state->cursor >= state->tmpl.length)
|
||||||
break; // [ at the end
|
break; // [ at the end
|
||||||
|
|
||||||
end = memmem(state->template.ptr + state->cursor,
|
end = memmem(state->tmpl.ptr + state->cursor,
|
||||||
state->template.length - state->cursor,
|
state->tmpl.length - state->cursor,
|
||||||
state->close.ptr, state->close.length);
|
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)
|
if (!end)
|
||||||
break; // ] not found
|
break; // ] not found
|
||||||
|
@ -40,12 +40,12 @@ psycTextRC psyc_text (psycTextState *state, psycTextCB getValue)
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
continue; // value not found, no substitution
|
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
|
// if there's enough buffer space for that
|
||||||
len = start - prev;
|
len = start - prev;
|
||||||
if (state->written + len > state->buffer.length)
|
if (state->written + len > state->buffer.length)
|
||||||
{
|
{
|
||||||
state->cursor = prev - state->template.ptr;
|
state->cursor = prev - state->tmpl.ptr;
|
||||||
return PSYC_TEXT_INCOMPLETE;
|
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
|
// now substitute the value if there's enough buffer space
|
||||||
if (state->written + value.length > state->buffer.length)
|
if (state->written + value.length > state->buffer.length)
|
||||||
{
|
{
|
||||||
state->cursor = start - state->template.ptr;
|
state->cursor = start - state->tmpl.ptr;
|
||||||
return PSYC_TEXT_INCOMPLETE;
|
return PSYC_TEXT_INCOMPLETE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -63,7 +63,7 @@ psycTextRC psyc_text (psycTextState *state, psycTextCB getValue)
|
||||||
state->written += value.length;
|
state->written += value.length;
|
||||||
|
|
||||||
// mark the start of the next chunk of text in the template
|
// 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;
|
no_subst = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -71,7 +71,7 @@ psycTextRC psyc_text (psycTextState *state, psycTextCB getValue)
|
||||||
return PSYC_TEXT_NO_SUBST;
|
return PSYC_TEXT_NO_SUBST;
|
||||||
|
|
||||||
// copy the rest of the template after the last var
|
// 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)
|
if (state->written + len > state->buffer.length)
|
||||||
return PSYC_TEXT_INCOMPLETE;
|
return PSYC_TEXT_INCOMPLETE;
|
||||||
|
|
||||||
|
|
4
test/packets/00-body-only
Normal file
4
test/packets/00-body-only
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
|
||||||
|
_message_private
|
||||||
|
OHAI
|
||||||
|
|
|
1
test/packets/00-empty
Normal file
1
test/packets/00-empty
Normal file
|
@ -0,0 +1 @@
|
||||||
|
|
|
4
test/packets/00-length-body-only
Normal file
4
test/packets/00-length-body-only
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
22
|
||||||
|
_message_private
|
||||||
|
OHAI
|
||||||
|
|
|
6
test/packets/00-length-no-entity
Normal file
6
test/packets/00-length-no-entity
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
:_source psyc://foo.example.com/
|
||||||
|
:_target psyc://bar.example.com/
|
||||||
|
22
|
||||||
|
_message_private
|
||||||
|
OHAI
|
||||||
|
|
|
3
test/packets/00-method-only-1
Normal file
3
test/packets/00-method-only-1
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
|
||||||
|
_
|
||||||
|
|
|
|
@ -80,6 +80,8 @@ int test_input (int i, char *recvbuf, size_t nbytes) {
|
||||||
value.length = 0;
|
value.length = 0;
|
||||||
|
|
||||||
do {
|
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)
|
// Parse the next part of the packet (a routing/entity modifier or the body)
|
||||||
ret = exit_code = psyc_parse(&parsers[i], &oper, &name, &value);
|
ret = exit_code = psyc_parse(&parsers[i], &oper, &name, &value);
|
||||||
if (verbose >= 2)
|
if (verbose >= 2)
|
||||||
|
@ -188,6 +190,8 @@ int test_input (int i, char *recvbuf, size_t nbytes) {
|
||||||
contbytes = psyc_getParseRemainingLength(&parsers[i]);
|
contbytes = psyc_getParseRemainingLength(&parsers[i]);
|
||||||
|
|
||||||
if (contbytes > 0) { // copy end of parsebuf before start of recvbuf
|
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
|
assert(contbytes <= CONT_BUF_SIZE); // make sure it's still in the buffer
|
||||||
memmove(recvbuf - contbytes, psyc_getParseRemainingBuffer(&parsers[i]), contbytes);
|
memmove(recvbuf - contbytes, psyc_getParseRemainingBuffer(&parsers[i]), contbytes);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue