diff --git a/d/include/psyc/common.d b/d/include/psyc/common.d index 8a39604..ecaba77 100644 --- a/d/include/psyc/common.d +++ b/d/include/psyc/common.d @@ -11,11 +11,15 @@ const EPOCH = 1440444041; // 2015-08-24 21:20:41 CET (Monday) extern (C): -enum Bool +/+enum Bool { FALSE = 0, TRUE = 1, -} +}+/ + +alias bool Bool; +static const FALSE = false; +static const TRUE = true; /** * PSYC packet parts. @@ -73,7 +77,7 @@ struct String ubyte *ptr; }+/ -alias char[] String; +alias ubyte[] String; struct MatchVar { @@ -93,9 +97,12 @@ extern (C) MatchVar varTypes[]; /** * Get the type of variable name. */ -Bool psyc_isRoutingVar(char *name, size_t len); +Bool psyc_isRoutingVar (char[]* name); -alias psyc_isRoutingVar isRoutingVar; +bool isRoutingVar (char[] name) +{ + return psyc_isRoutingVar(&name); +} /** * Get the type of variable name. diff --git a/d/include/psyc/packet.d b/d/include/psyc/packet.d index 9817ad3..3846b3f 100644 --- a/d/include/psyc/packet.d +++ b/d/include/psyc/packet.d @@ -6,8 +6,9 @@ module psyc.packet; import psyc.common; import psyc.syntax; +import psyc.render; - +import tango.stdc.string : memchr; extern (C): /** Modifier flags. */ @@ -49,11 +50,17 @@ enum PacketFlag struct Modifier { char operator; - String name; + char[] name; String value; ModifierFlag flag; - static Modifier opCall ( char op, char[] nam, char[] val ) + static Modifier opCall ( char op, char[] nam, char[] val, + ModifierFlag flg = ModifierFlag.CHECK_LENGTH ) + { + return opCall(op, nam, cast(ubyte[])val, flg); + } + static Modifier opCall ( char op, char[] nam, ubyte[] val, + ModifierFlag flg = ModifierFlag.CHECK_LENGTH ) { Modifier v; @@ -62,11 +69,18 @@ struct Modifier operator = op; name = nam; value = val; + flag = (flg == ModifierFlag.CHECK_LENGTH) ? + checkLength(val) : flg; } return v; } + char[] valuestr ( ) + { + return cast(char[]) value; + } + bool opEquals ( ref Modifier n ) { return operator == n.operator && @@ -79,17 +93,29 @@ struct Modifier auto v = M(operator, name.dup, value.dup); return v; } + + size_t length ( ) + { + return psyc_getModifierLength (this); + } + + private ModifierFlag checkLength ( ubyte[] value ) + { + ModifierFlag flag; + + if (value.length > PSYC_MODIFIER_SIZE_THRESHOLD) + flag = ModifierFlag.NEED_LENGTH; + else if (memchr(value.ptr, cast(int)'\n', value.length)) + flag = ModifierFlag.NEED_LENGTH; + else + flag = ModifierFlag.NO_LENGTH; + + return flag; + } }; alias Modifier M; -/** Structure for an entity or routing header. */ -struct Header -{ - size_t lines; - Modifier *modifiers; -} ; - /** Structure for a list. */ struct List { @@ -102,66 +128,68 @@ struct List /** intermediate struct for a PSYC packet */ struct Packet { - Header routing; ///< Routing header. - Header entity; ///< Entity header. + Modifier[] routing; ///< Routing header. + Modifier[] 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. + size_t _length; ///< Total length of packet. PacketFlag flag; ///< Packet flag. -} ; + + static Packet opCall (Modifier[] routing, Modifier[] entity, + char[] method, ubyte[] data, + PacketFlag flag = PacketFlag.CHECK_LENGTH) + { + return psyc_newPacket (&routing, &entity, cast(ubyte[]*)&method, &data, flag); + } + + static Packet opCall (Modifier[] routing, ubyte[] content, + PacketFlag flag = PacketFlag.CHECK_LENGTH) + { + return psyc_newRawPacket (&routing, &content, flag); + } + + size_t length ( ) + { + psyc_setPacketLength(this); + return this._length; + } + + ubyte[] render ( ubyte[] buffer ) + { + psyc_setPacketLength(this); + + with (RenderRC) + switch (psyc_render(this, buffer.ptr, buffer.length)) + { + case ERROR_METHOD_MISSING: + throw new Exception("Method missing"); + break; + + case ERROR_MODIFIER_NAME_MISSING: + throw new Exception("Modifier name missing"); + break; + + case ERROR: + throw new Exception("Buffer to small"); + break; + + case SUCCESS: + return buffer[0 .. this._length]; + + default: + throw new Exception("Unknown Return Code"); + } + } +}; + /** * \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); +private size_t psyc_getModifierLength (Modifier *m); /** * \internal @@ -184,26 +212,29 @@ PacketFlag psyc_checkPacketLength (Packet *p); /** * Calculate and set the rendered length of packet parts and total packet length. */ -size_t psyc_setPacketLength (Packet *p); +private 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); +private Packet psyc_newPacket (Modifier[]* routing, + Modifier[]* 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); + 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, +Packet psyc_newRawPacket (Modifier[] *routing, ubyte[] *content, PacketFlag flag); /** Create new packet with raw content. */ diff --git a/d/include/psyc/parse.d b/d/include/psyc/parse.d index dcc1015..ac5be77 100644 --- a/d/include/psyc/parse.d +++ b/d/include/psyc/parse.d @@ -141,6 +141,24 @@ struct ParseState return inst; } + /** + * Parse PSYC packets. + * + * Generalized line-based packet parser. + * + * Params: + * oper = A reference to a character. In case of a variable, it will + * be set to the operator of that variable + * name = A reference to a String. It will point to the name of + * the variable or method and its length will be set accordingly + * value = A reference to a String. It will point to the + * value/body the variable/method and its length will be set accordingly + */ + ParseRC parse ( ref char oper, ref char[] name, ref ubyte[] value ) + { + return psyc_parse(this, &oper, cast(String*) &name, cast(String*) &value); + } + /** * Parse PSYC packets. * @@ -175,7 +193,7 @@ struct ParseState if (this.flags & ParseFlag.START_AT_CONTENT) { this.contentLength = buffer.length; - this.contentLengthFound = Bool.TRUE; + this.contentLengthFound = TRUE; } } @@ -187,23 +205,11 @@ struct ParseState * * See_Also: String */ - void setParseBuffer ( ubyte[] buffer ) + void setParseBuffer ( char[] buffer ) { this.setParseBuffer(*(cast(String*) &buffer)); } - /** - * Sets a new buffer in the parser state struct with data to be parsed. - * - * Params: - * buffer = pointer to the buffer that should be parsed now - * length = length of the buffer - */ - void setParseBuffer ( ubyte* buffer, size_t length ) - { - this.setParseBuffer(String(length, cast(ubyte*)buffer)); - } - size_t getContentLength ( ) { return this.contentLength; @@ -211,7 +217,7 @@ struct ParseState bool isContentLengthFound ( ) { - return this.contentLengthFound == Bool.TRUE; + return this.contentLengthFound == TRUE; } size_t getValueLength ( ) @@ -221,7 +227,7 @@ struct ParseState bool isValueLengthFound ( ) { - return this.valueLengthFound == Bool.TRUE; + return this.valueLengthFound == true; } size_t getCursor ( ) @@ -241,13 +247,13 @@ struct ParseState ubyte* getRemainingBuffer ( ) { - return this.buffer.ptr + this.cursor; + return cast(ubyte*)this.buffer.ptr + this.cursor; } void getRemainingBuffer ( ref ubyte[] buf ) { - buf = this.buffer.ptr[cursor .. cursor + getRemainingLength()]; + buf = cast(ubyte[])this.buffer.ptr[cursor .. cursor + getRemainingLength()]; } } @@ -283,22 +289,10 @@ struct ParseListState * Params: * buffer = the buffer to be parsed */ - void setBuffer ( ubyte[] buffer ) + void setBuffer ( char[] buffer ) { this.setBuffer(*(cast(String*) &buffer)); } - - /** - * Sets a new buffer with data to be parsed - * - * Params: - * buffer = pointer to the buffer to be parsed - * length = size of the buffer - */ - void setBuffer ( ubyte* buffer, size_t length ) - { - this.setBuffer(String(length, buffer)); - } } private: diff --git a/d/include/psyc/render.d b/d/include/psyc/render.d index c02a188..c9e248a 100644 --- a/d/include/psyc/render.d +++ b/d/include/psyc/render.d @@ -51,10 +51,10 @@ enum RenderListRC * @see psyc_newRawPacket2 * @see psyc_setPacketLength */ -RenderRC psyc_render (Packet *packet, char *buffer, size_t buflen); +RenderRC psyc_render (Packet *packet, ubyte *buffer, size_t buflen); /** * Render a PSYC list into a buffer. */ -RenderListRC psyc_renderList (List *list, char *buffer, size_t buflen); +RenderListRC psyc_renderList (List *list, ubyte *buffer, size_t buflen); diff --git a/d/include/psyc/syntax.d b/d/include/psyc/syntax.d index a5fcfe3..2962f57 100644 --- a/d/include/psyc/syntax.d +++ b/d/include/psyc/syntax.d @@ -3,7 +3,7 @@ module psyc.syntax; const PSYC_LIST_SIZE_LIMIT = 404; /* beyond this a content length must be provided */ -const = PSYC_CONTENT_SIZE_THRESHOLD = 444; +const PSYC_CONTENT_SIZE_THRESHOLD = 444; /* beyond this a modifier value length must be provided */ const PSYC_MODIFIER_SIZE_THRESHOLD = 404;