diff --git a/include/d/psyc/common.d b/include/d/psyc/common.d index efb5a90..41ad6a5 100644 --- a/include/d/psyc/common.d +++ b/include/d/psyc/common.d @@ -1,20 +1,9 @@ -/** @file d/.d +/** @file d/psyc/common.d * * @brief Main PSYC interface providing crucial functionality. */ -/** @mainpage PSYC Core Library - * - * @section intro_sec Introduction - * - * This is the introduction. - * - * @section install_sec Installation - * - * @subsection step1 Step 1: Opening the box - * - * etc... - */ + module psyc.common; @@ -33,13 +22,13 @@ enum Bool */ enum Part { - PART_RESET = -1, - PART_ROUTING, - PART_LENGTH, - PART_CONTENT, - PART_METHOD, - PART_DATA, - PART_END, + RESET = -1, + ROUTING = 0, + LENGTH = 1, + CONTENT = 2, + METHOD = 3, + DATA = 4, + END = 5, } /** @@ -52,19 +41,19 @@ enum Part */ enum Type { - TYPE_UNKNOWN, - TYPE_AMOUNT, - TYPE_COLOR, - TYPE_DATE, - TYPE_DEGREE, - TYPE_ENTITY, - TYPE_FLAG, - TYPE_LANGUAGE, - TYPE_LIST, - TYPE_NICK, - TYPE_PAGE, - TYPE_UNIFORM, - TYPE_TIME, + UNKNOWN, + AMOUNT, + COLOR, + DATE, + DEGREE, + ENTITY, + FLAG, + LANGUAGE, + LIST, + NICK, + PAGE, + UNIFORM, + TIME, } /** @@ -77,32 +66,10 @@ enum ListType LIST_BINARY = 2, } -enum ModifierFlag -{ - MODIFIER_CHECK_LENGTH = 0, - MODIFIER_NEED_LENGTH = 1, - MODIFIER_NO_LENGTH = 2, - MODIFIER_ROUTING = 3, -} - -enum ListFlag -{ - LIST_CHECK_LENGTH = 0, - LIST_NEED_LENGTH = 1, - LIST_NO_LENGTH = 2, -} - -enum PacketFlag -{ - PACKET_CHECK_LENGTH = 0, - PACKET_NEED_LENGTH = 1, - PACKET_NO_LENGTH = 2, -} - struct String { size_t length; - char *ptr; + ubyte *ptr; } struct MatchVar @@ -111,98 +78,11 @@ struct MatchVar int value; } -/** -* Shortcut for creating a String. - * - * @param memory Pointer to the buffer. - * @param length Length of that buffer. - * - * @return An instance of the String struct. - */ -String newString (char *str, size_t strlen); - -/* intermediate struct for a PSYC variable modification */ -struct Modifier +int psyc_version() { - char oper; // not call it 'operator' as C++ may not like that.. - String name; - String value; - ModifierFlag flag; + return 1; } -struct Header -{ - size_t lines; - Modifier *modifiers; -} - -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; - String data; - size_t routingLength; ///< Length of routing part. - size_t contentLength; ///< Length of content part. - size_t length; ///< Total length of packet. - PacketFlag flag; -} - -int psyc_version(); - -/** Check if a modifier needs length */ -ModifierFlag checkModifierLength(Modifier *m); - -/** Get the total length of a modifier. */ -size_t getModifierLength(Modifier *m); - -/** Create new modifier */ -Modifier newModifier(char oper, String *name, String *value, - ModifierFlag flag); - -/** Create new modifier */ -Modifier newModifier2(char oper, - char *name, size_t namelen, - char *value, size_t valuelen, - ModifierFlag flag); - -/** Check if a list needs length */ -ListFlag checkListLength(List *list); - -/** Get the total length of a list. */ -ListFlag getListLength(List *list); - -/** Check if a packet needs length */ -PacketFlag checkPacketLength(Packet *p); - -/** Calculate and set the length of packet parts and total packet length */ -size_t setPacketLength(Packet *p); - -/** Create new list */ -List newList(String *elems, size_t num_elems, ListFlag flag); - -/** Create new packet */ -Packet newPacket(Header *routing, - Header *entity, - String *method, String *data, - PacketFlag flag); - -/** Create new packet */ -Packet newPacket2(Modifier *routing, size_t routinglen, - Modifier *entity, size_t entitylen, - char *method, size_t methodlen, - char *data, size_t datalen, - PacketFlag flag); - /// Routing vars in alphabetical order. extern (C) String routingVars[]; extern (C) MatchVar varTypes[]; @@ -221,40 +101,12 @@ Type getVarType(char *name, size_t len); * Checks if long keyword string inherits from short keyword string. */ int inherits(char *sho, size_t slen, - char *lon, size_t llen); + char *lon, size_t llen); /** * Checks if short keyword string matches long keyword string. */ int matches(char *sho, size_t slen, - char *lon, size_t llen); + char *lon, size_t llen); -/** - * Callback for text() that produces a value for a match. - * - * The application looks up a match such as _fruit from [_fruit] and - * if found writes its current value from its variable store into the - * outgoing buffer.. "Apple" for example. The template returns the - * number of bytes written. 0 is a legal return value. Should the - * callback return -1, text leaves the original template text as is. - */ -alias extern (C) int function (char *match, size_t mlen, char **buffer, size_t *blen) textCB; - -/** - * Fills out text templates by asking a callback for content. - * - * Copies the contents of the template into the buffer while looking - * for braceOpen and braceClose strings and calling the callback for - * each enclosed string between these braces. Should the callback - * return -1, the original template text is copied as is. - * - * By default PSYC's "[" and "]" are used but you can provide any other - * brace strings such as "${" and "}" or "". - * - * See also http://about..eu/text - */ -int text(char *_template, size_t tlen, - char **buffer, size_t *blen, - textCB lookupValue, - char *braceOpen, char *braceClose); diff --git a/include/d/psyc/parser.d b/include/d/psyc/parser.d index 465a641..244aa01 100644 --- a/include/d/psyc/parser.d +++ b/include/d/psyc/parser.d @@ -21,8 +21,8 @@ extern (C): enum ParseFlag { - PARSE_HEADER_ONLY = 1, - PARSE_BEGIN_AT_CONTENT = 2, + ROUTING_ONLY = 1, + START_AT_CONTENT = 2, } /** @@ -31,43 +31,66 @@ enum ParseFlag */ enum ParseRC { - PARSE_ERROR_END = -9, - PARSE_ERROR_BODY = -8, - PARSE_ERROR_METHOD = -7, - PARSE_ERROR_MOD_NL = -6, - PARSE_ERROR_MOD_LEN = -5, - PARSE_ERROR_MOD_TAB = -4, - PARSE_ERROR_MOD_NAME = -3, - PARSE_ERROR_LENGTH = -2, - PARSE_ERROR = -1, - PARSE_SUCCESS = 0, +/// Error, packet is not ending with a valid delimiter. + ERROR_END = -8, +/// Error, expected NL after the method. + ERROR_METHOD = -7, +/// Error, expected NL after a modifier. + ERROR_MOD_NL = -6, +/// Error, modifier length is not numeric. + ERROR_MOD_LEN = -5, +/// Error, expected TAB before modifier value. + ERROR_MOD_TAB = -4, +/// Error, modifier name is missing. + ERROR_MOD_NAME = -3, +/// Error, expected NL after the content length. + ERROR_LENGTH = -2, +/// Error in packet. + ERROR = -1, +// Success, used internally. + 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. - PARSE_INSUFFICIENT = 1, + INSUFFICIENT = 1, /// Routing modifier parsing done. /// Operator, name & value contains the respective parts. - PARSE_ROUTING = 2, -/// Entity modifier parsing done. -/// Operator, name & value contains the respective parts. - PARSE_ENTITY = 3, -/// Entity modifier parsing is incomplete. + ROUTING = 2, +/// Start of an incomplete entity modifier. /// Operator & name are complete, value is incomplete. - PARSE_ENTITY_INCOMPLETE = 4, -/// Body parsing done, name contains method, value contains body. - PARSE_BODY = 5, -/// Body parsing is incomplete, name contains method, value contains part of the body. - PARSE_BODY_INCOMPLETE = 6, -/// Content parsing done, value contains the whole content. -/// Used when PSYC_PARSE_ROUTING_ONLY is set. - PARSE_CONTENT = 5, -/// Content parsing is incomplete, value contains part of content. -/// Used when PSYC_PARSE_ROUTING_ONLY is set. - PARSE_CONTENT_INCOMPLETE = 6, -/// Reached end of packet, parsing done. - PARSE_COMPLETE = 7, -/// Binary value parsing incomplete, used internally. - PARSE_INCOMPLETE = 8, + ENTITY_START = 3, +/// Continuation of an incomplete entity modifier. + ENTITY_CONT = 4, +/// End of an incomplete entity modifier. + ENTITY_END = 5, +/// Entity modifier parsing done in one go. +/// Operator, name & value contains the respective parts. + ENTITY = 6, +/// Start of an incomplete body. +/// Name contains method, value contains part of the body. + BODY_START = 7, +/// Continuation of an incomplete body. + BODY_CONT = 8, +/// End of an incomplete body. + BODY_END = 9, +/// Body parsing done in one go, name contains method, value contains body. + BODY = 10, +/// Start of an incomplete content, value contains part of content. +/// Used when ROUTING_ONLY is set. + CONTENT_START = 7, +/// Continuation of an incomplete body. +/// Used when ROUTING_ONLY is set. + CONTENT_CONT = 8, +/// End of an incomplete body. +/// Used when ROUTING_ONLY is set. + CONTENT_END = 9, +/// Content parsing done in one go, value contains the whole content. +/// Used when ROUTING_ONLY is set. + CONTENT = 10, +// Binary value parsing complete, used internally. + COMPLETE = 11, +// Binary value parsing incomplete, used internally. + INCOMPLETE = 12, } /** @@ -76,17 +99,17 @@ enum ParseRC */ enum ParseListRC { - PARSE_LIST_ERROR_DELIM = -5, - PARSE_LIST_ERROR_LEN = -4, - PARSE_LIST_ERROR_TYPE = -3, - PARSE_LIST_ERROR_NAME = -2, - PARSE_LIST_ERROR= -1, + LIST_ERROR_DELIM = -5, + LIST_ERROR_LEN = -4, + LIST_ERROR_TYPE = -3, + LIST_ERROR_NAME = -2, + LIST_ERROR = -1, /// Completed parsing a list element. - PARSE_LIST_ELEM = 1, + LIST_ELEM = 1, /// Reached end of buffer. - PARSE_LIST_END = 2, + LIST_END = 2, /// Binary list is incomplete. - PARSE_LIST_INCOMPLETE = 3, + LIST_INCOMPLETE = 3, } /** @@ -106,6 +129,118 @@ struct ParseState Bool contentLengthFound; ///< is there a length given for this packet? size_t valueParsed; ///< number of bytes parsed from the value so far size_t valueLength; ///< expected length of the value + Bool valueLengthFound; ///< is there a length given for this modifier? + + /** + * Initiates the state struct. + */ + static ParseState opCall ( ) + { + ParseState inst; + return inst; + } + + /** + * Initializes the state struct with flags. + * + * @param flags Flags to be set for the parser, see ParseFlag. + */ + static ParseState opCall ( ubyte flags ) + { + ParseState inst; + inst.flags = flags; + + if (flags & ParseFlag.ROUTING_ONLY) + inst.part = Part.CONTENT; + + return inst; + } + + /** + * Sets a new buffer in the parser state struct with data to be parsed. + * + * @param buffer the buffer that should be parsed now + * @see String + */ + void setParseBuffer ( String buffer ) + { + this.buffer = buffer; + this.cursor = 0; + + if (this.flags & ParseFlag.START_AT_CONTENT) + { + this.contentLength = buffer.length; + this.contentLengthFound = Bool.TRUE; + } + } + + /** + * Sets a new buffer in the parser state struct with data to be parsed. + * + * @param buffer the buffer that should be parsed now + * @see String + */ + void setParseBuffer ( ubyte[] buffer ) + { + this.setParseBuffer(*(cast(String*) &buffer)); + } + + /** + * Sets a new buffer in the parser state struct with data to be parsed. + * + * @param buffer pointer to the buffer that should be parsed now + * @param 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; + } + + bool isContentLengthFound ( ) + { + return this.contentLengthFound == Bool.TRUE; + } + + size_t getValueLength ( ) + { + return this.valueLength; + } + + bool isValueLengthFound ( ) + { + return this.valueLengthFound == Bool.TRUE; + } + + size_t getCursor ( ) + { + return this.cursor; + } + + size_t getBufferLength ( ) + { + return this.buffer.length; + } + + size_t getRemainingLength ( ) + { + return this.buffer.length - this.cursor; + } + + ubyte* getRemainingBuffer ( ) + { + return this.buffer.ptr + this.cursor; + } + + void getRemainingBuffer ( ref ubyte[] buf ) + { + buf = this.buffer.ptr[cursor .. getRemainingLength()]; + } + } /** @@ -120,35 +255,37 @@ struct ParseListState size_t elemParsed; ///< number of bytes parsed from the elem so far size_t elemLength; ///< expected length of the elem + + /** + * Sets a new buffer with data to be parsed + * @param buffer the buffer to be parsed + */ + void setBuffer ( String buffer ) + { + this.buffer = buffer; + this.cursor = 0; + } + + /** + * Sets a new buffer with data to be parsed + * @param buffer the buffer to be parsed + */ + void setBuffer ( ubyte[] buffer ) + { + this.setBuffer(*(cast(String*) &buffer)); + } + + /** + * Sets a new buffer with data to be parsed + * @param buffer pointer to the buffer to be parsed + * @param length size of the buffer + */ + void setBuffer ( ubyte* buffer, size_t length ) + { + this.setBuffer(String(length, buffer)); + } } -/** - * Initiates the state struct. - * - * @param state Pointer to the state struct that should be initiated. - */ -void psyc_initParseState (ParseState* state); - -/** - * Initiates the state struct with flags. - * - * @param state Pointer to the state struct that should be initiated. - * @param flags Flags to be set for the parser, see ParseFlag. - */ -void psyc_initParseState2 (ParseState* state, ubyte flags); - -/** - * Initiates the list state struct. - * - * @param state Pointer to the list state struct that should be initiated. - */ -void psyc_initParseListState (ParseListState* state); - -void psyc_nextParseBuffer (ParseState* state, String newBuf); - -void psyc_nextParseListBuffer (ParseListState* state, String newBuf); - -size_t psyc_getContentLength (ParseState* s); /** * Parse PSYC packets.