mirror of
git://git.psyc.eu/libpsyc
synced 2024-08-15 03:19:02 +00:00
dict syntax; index & update mod parser; psyc-mode for emacs
This commit is contained in:
parent
3ee2f0e392
commit
d3aa4508b9
31 changed files with 2063 additions and 691 deletions
4
.gitignore
vendored
4
.gitignore
vendored
|
@ -19,7 +19,9 @@ test/test_strlen
|
||||||
test/test_text
|
test/test_text
|
||||||
test/test_table
|
test/test_table
|
||||||
test/test_packet_id
|
test/test_packet_id
|
||||||
test/var_is_routing
|
test/test_index
|
||||||
|
test/test_update
|
||||||
|
test/var_routing
|
||||||
test/var_type
|
test/var_type
|
||||||
test/uniform_parse
|
test/uniform_parse
|
||||||
|
|
||||||
|
|
124
emacs/psyc.el
Normal file
124
emacs/psyc.el
Normal file
|
@ -0,0 +1,124 @@
|
||||||
|
(require 'font-lock)
|
||||||
|
|
||||||
|
(setq
|
||||||
|
psyc-op "\\([:!?=$@+-]\\)"
|
||||||
|
psyc-routing-op "^\\([:=]\\)"
|
||||||
|
psyc-state-op "^\\([?=]\\)$"
|
||||||
|
|
||||||
|
psyc-num "\\([0-9]+\\)"
|
||||||
|
psyc-kw "\\([a-z_][a-z0-9_]*\\)"
|
||||||
|
|
||||||
|
psyc-length "^[0-9]+$"
|
||||||
|
|
||||||
|
psyc-routing-var-names (regexp-opt '("_amount_fragments" "_context" "_counter"
|
||||||
|
"_fragment" "_source" "_source_relay"
|
||||||
|
"_target" "_target_relay"
|
||||||
|
"_tag" "_tag_relay") 'word)
|
||||||
|
psyc-routing-var (concat psyc-routing-op psyc-routing-var-names)
|
||||||
|
|
||||||
|
psyc-types (concat "\\([a-z][a-z0-9]+\\|"
|
||||||
|
(regexp-opt '("_dict" "_list" "_struct"
|
||||||
|
"_int" "_uint" "_num" "_unum" "_flag" "_amount"
|
||||||
|
"_date" "_time" "_uniform") nil)
|
||||||
|
"\\)")
|
||||||
|
|
||||||
|
psyc-mod-op (concat "^" psyc-op)
|
||||||
|
psyc-mod-name (concat psyc-mod-op psyc-kw) ;2
|
||||||
|
psyc-mod-type (concat psyc-mod-op psyc-types "\\b") ;2
|
||||||
|
psyc-mod-len (concat psyc-mod-op psyc-kw " " psyc-num) ;3
|
||||||
|
psyc-mod-delim (concat "\\(?: " psyc-num "\\)?[\t ]+")
|
||||||
|
psyc-mod (concat psyc-mod-op psyc-kw psyc-mod-delim) ;3
|
||||||
|
|
||||||
|
psyc-default-name (concat psyc-mod psyc-kw "[|{]") ;4
|
||||||
|
psyc-default-type (concat psyc-mod psyc-types "[_|{]") ;4
|
||||||
|
; psyc-default-name (concat "[\t ]" psyc-kw "[|{]")
|
||||||
|
; psyc-default-type (concat "[\t ]" psyc-types "[_|{]")
|
||||||
|
|
||||||
|
|
||||||
|
psyc-elem-delim "[|{}]"
|
||||||
|
psyc-elem-start "[|}]"
|
||||||
|
psyc-elem-op (concat psyc-elem-start "\\(=\\)")
|
||||||
|
psyc-elem-name (concat psyc-elem-start "=" psyc-kw)
|
||||||
|
psyc-elem-type (concat psyc-elem-start "=" psyc-types "\\b")
|
||||||
|
psyc-elem-name-delim (concat psyc-elem-name "\\(:\\)") ;2
|
||||||
|
psyc-elem-len (concat "\\(?:" psyc-elem-name-delim "\\)?" psyc-num) ;3
|
||||||
|
|
||||||
|
psyc-update-op (concat "^@" psyc-kw psyc-mod-delim ".+ " psyc-op) ;3
|
||||||
|
psyc-update-name (concat "^@" psyc-kw psyc-mod-delim ".+ "
|
||||||
|
psyc-op psyc-kw) ;4
|
||||||
|
psyc-update-type (concat "^@" psyc-kw psyc-mod-delim ".+ "
|
||||||
|
psyc-op psyc-types "\\b") ;4
|
||||||
|
psyc-update-len-delim (concat "^@" psyc-kw psyc-mod-delim ".+ "
|
||||||
|
psyc-op psyc-kw "?\\(:\\)") ;5
|
||||||
|
psyc-update-len (concat "^@" psyc-kw psyc-mod-delim ".+ "
|
||||||
|
psyc-op psyc-kw "?:" psyc-num) ;5
|
||||||
|
|
||||||
|
psyc-index-delim "\\(#\\)-?[0-9]+"
|
||||||
|
|
||||||
|
psyc-struct-delim "[\t0-9}]\\(\\.\\)"
|
||||||
|
psyc-struct-name (concat psyc-struct-delim psyc-kw) ;2
|
||||||
|
psyc-struct-type (concat psyc-struct-delim psyc-types "\\b") ;2
|
||||||
|
|
||||||
|
|
||||||
|
psyc-dict-key-len (concat "{" psyc-num)
|
||||||
|
psyc-dict-key (concat "{\\(?:" psyc-num " \\)?\\([^}]+\\)") ;2
|
||||||
|
|
||||||
|
psyc-method (concat "^_" psyc-kw)
|
||||||
|
;psyc-body "^[^_:!?=$@+-].*$"
|
||||||
|
|
||||||
|
psyc-tmpl-start (concat "\\(\\[\\)" psyc-kw ".+?\\]")
|
||||||
|
psyc-tmpl-end (concat "\\[" psyc-kw ".+?\\(\\]\\)")
|
||||||
|
|
||||||
|
psyc-packet-delim "^|$"
|
||||||
|
|
||||||
|
psyc-font-lock-keywords
|
||||||
|
`(
|
||||||
|
(,psyc-routing-var . (2 font-lock-keyword-face t))
|
||||||
|
(,psyc-length . (0 font-lock-constant-face))
|
||||||
|
(,psyc-state-op . (0 font-lock-preprocessor-face))
|
||||||
|
(,psyc-mod-op . (1 font-lock-preprocessor-face))
|
||||||
|
(,psyc-mod-name . (2 font-lock-variable-name-face))
|
||||||
|
(,psyc-mod-type . (2 font-lock-type-face t))
|
||||||
|
(,psyc-mod-len . (3 font-lock-constant-face))
|
||||||
|
|
||||||
|
(,psyc-default-name . (4 font-lock-variable-name-face))
|
||||||
|
(,psyc-default-type . (4 font-lock-type-face t))
|
||||||
|
|
||||||
|
(,psyc-dict-key-len . (1 font-lock-constant-face))
|
||||||
|
(,psyc-dict-key . (2 font-lock-string-face))
|
||||||
|
|
||||||
|
(,psyc-elem-op . (1 font-lock-preprocessor-face))
|
||||||
|
(,psyc-elem-name . (1 font-lock-variable-name-face))
|
||||||
|
(,psyc-elem-type . (1 font-lock-type-face t))
|
||||||
|
(,psyc-elem-name-delim . (2 font-lock-comment-face))
|
||||||
|
(,psyc-elem-len . (3 font-lock-constant-face))
|
||||||
|
(,psyc-elem-delim . (0 font-lock-keyword-face))
|
||||||
|
|
||||||
|
(,psyc-update-op . (3 font-lock-preprocessor-face))
|
||||||
|
(,psyc-update-name . (4 font-lock-variable-name-face))
|
||||||
|
(,psyc-update-type . (4 font-lock-type-face t))
|
||||||
|
(,psyc-update-len-delim . (5 font-lock-comment-face))
|
||||||
|
(,psyc-update-len . (5 font-lock-constant-face))
|
||||||
|
|
||||||
|
(,psyc-method . (0 font-lock-function-name-face))
|
||||||
|
;(,psyc-body . (0 font-lock-comment-face))
|
||||||
|
|
||||||
|
(,psyc-index-delim . (1 font-lock-comment-face))
|
||||||
|
(,psyc-struct-name . (1 font-lock-comment-face))
|
||||||
|
(,psyc-struct-name . (2 font-lock-variable-name-face))
|
||||||
|
(,psyc-struct-type . (2 font-lock-type-face t))
|
||||||
|
|
||||||
|
(,psyc-tmpl-start . (1 font-lock-keyword-face))
|
||||||
|
(,psyc-tmpl-end . (2 font-lock-keyword-face))
|
||||||
|
|
||||||
|
(,psyc-packet-delim . (0 font-lock-preprocessor-face))
|
||||||
|
))
|
||||||
|
|
||||||
|
(define-derived-mode psyc-mode fundamental-mode
|
||||||
|
"PSYC"
|
||||||
|
"Major mode for editing PSYC packets"
|
||||||
|
|
||||||
|
(setq font-lock-defaults '((psyc-font-lock-keywords)))
|
||||||
|
(setq show-trailing-whitespace t))
|
||||||
|
|
||||||
|
(provide 'psyc)
|
|
@ -24,7 +24,6 @@
|
||||||
#define PSYC_VERSION 1
|
#define PSYC_VERSION 1
|
||||||
#define PSYC_EPOCH 1440444041 // 2015-08-24 21:20:41 CET (Monday)
|
#define PSYC_EPOCH 1440444041 // 2015-08-24 21:20:41 CET (Monday)
|
||||||
|
|
||||||
#define PSYC_STRING(data, len) (PsycString) {len, data}
|
|
||||||
#define PSYC_C2STR(str) (PsycString) {sizeof(str)-1, str}
|
#define PSYC_C2STR(str) (PsycString) {sizeof(str)-1, str}
|
||||||
#define PSYC_C2STRI(str) {sizeof(str)-1, str}
|
#define PSYC_C2STRI(str) {sizeof(str)-1, str}
|
||||||
#define PSYC_C2ARG(str) str, sizeof(str)-1
|
#define PSYC_C2ARG(str) str, sizeof(str)-1
|
||||||
|
@ -50,53 +49,6 @@ typedef enum {
|
||||||
PSYC_ERROR = -1,
|
PSYC_ERROR = -1,
|
||||||
} PsycRC;
|
} PsycRC;
|
||||||
|
|
||||||
/// PSYC packet parts.
|
|
||||||
typedef enum {
|
|
||||||
PSYC_PART_RESET = -1,
|
|
||||||
PSYC_PART_ROUTING = 0,
|
|
||||||
PSYC_PART_LENGTH = 1,
|
|
||||||
PSYC_PART_CONTENT = 2,
|
|
||||||
PSYC_PART_METHOD = 3,
|
|
||||||
PSYC_PART_DATA = 4,
|
|
||||||
PSYC_PART_END = 5,
|
|
||||||
} PsycPart;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Different types that a variable can have.
|
|
||||||
*
|
|
||||||
* This enum lists PSYC variable types that
|
|
||||||
* this library is capable of checking for
|
|
||||||
* validity. Other variable types are treated
|
|
||||||
* as opaque data.
|
|
||||||
*/
|
|
||||||
typedef enum {
|
|
||||||
PSYC_TYPE_UNKNOWN,
|
|
||||||
PSYC_TYPE_AMOUNT,
|
|
||||||
PSYC_TYPE_COLOR,
|
|
||||||
PSYC_TYPE_COUNTER,
|
|
||||||
PSYC_TYPE_DEF,
|
|
||||||
PSYC_TYPE_DATE,
|
|
||||||
PSYC_TYPE_DEGREE,
|
|
||||||
PSYC_TYPE_ENTITY,
|
|
||||||
PSYC_TYPE_FLAG,
|
|
||||||
PSYC_TYPE_LANGUAGE,
|
|
||||||
PSYC_TYPE_LIST,
|
|
||||||
PSYC_TYPE_NICK,
|
|
||||||
PSYC_TYPE_PAGE,
|
|
||||||
PSYC_TYPE_TABLE,
|
|
||||||
PSYC_TYPE_TIME,
|
|
||||||
PSYC_TYPE_UNIFORM,
|
|
||||||
} PsycType;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* List types.
|
|
||||||
* Possible types are text and binary.
|
|
||||||
*/
|
|
||||||
typedef enum {
|
|
||||||
PSYC_LIST_TEXT = 1,
|
|
||||||
PSYC_LIST_BINARY = 2,
|
|
||||||
} PsycListType;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* String struct.
|
* String struct.
|
||||||
*
|
*
|
||||||
|
@ -109,14 +61,15 @@ typedef struct {
|
||||||
char *data;
|
char *data;
|
||||||
} PsycString;
|
} PsycString;
|
||||||
|
|
||||||
#include "psyc/syntax.h"
|
#define PSYC_STRING(data, len) (PsycString) {len, data}
|
||||||
|
|
||||||
#include "psyc/match.h"
|
#include "psyc/match.h"
|
||||||
#include "psyc/method.h"
|
#include "psyc/method.h"
|
||||||
#include "psyc/packet.h"
|
#include "psyc/packet.h"
|
||||||
|
#include "psyc/variable.h"
|
||||||
#include "psyc/parse.h"
|
#include "psyc/parse.h"
|
||||||
#include "psyc/render.h"
|
#include "psyc/render.h"
|
||||||
#include "psyc/text.h"
|
#include "psyc/text.h"
|
||||||
#include "psyc/uniform.h"
|
#include "psyc/uniform.h"
|
||||||
#include "psyc/variable.h"
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -4,7 +4,7 @@ prefix = /usr
|
||||||
includedir = ${prefix}/include
|
includedir = ${prefix}/include
|
||||||
|
|
||||||
INSTALL = install
|
INSTALL = install
|
||||||
HEADERS = match.h method.h packet.h parse.h render.h syntax.h text.h uniform.h variable.h
|
HEADERS = match.h method.h packet.h parse.h render.h text.h uniform.h variable.h
|
||||||
|
|
||||||
install: ${HEADERS}
|
install: ${HEADERS}
|
||||||
|
|
||||||
|
|
|
@ -1,12 +1,15 @@
|
||||||
|
#ifndef PSYC_MATCH_H
|
||||||
|
#define PSYC_MATCH_H
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
PsycString key;
|
PsycString key;
|
||||||
void *value;
|
void *value;
|
||||||
} PsycDict;
|
} PsycMap;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
PsycString key;
|
PsycString key;
|
||||||
intptr_t value;
|
intptr_t value;
|
||||||
} PsycDictInt;
|
} PsycMapInt;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks if long keyword string inherits from short keyword string.
|
* Checks if long keyword string inherits from short keyword string.
|
||||||
|
@ -21,10 +24,10 @@ int
|
||||||
psyc_matches (char *sho, size_t slen, char *lon, size_t llen);
|
psyc_matches (char *sho, size_t slen, char *lon, size_t llen);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Look up value associated with a key in a dictionary.
|
* Look up value associated with a key in a map.
|
||||||
*
|
*
|
||||||
* @param dict The dictionary to search, should be ordered alphabetically.
|
* @param map The dictionary to search, should be ordered alphabetically.
|
||||||
* @param size Size of dict.
|
* @param size Size of map.
|
||||||
* @param key Key to look for.
|
* @param key Key to look for.
|
||||||
* @param keylen Length of key.
|
* @param keylen Length of key.
|
||||||
* @param inherit If true, also look for anything inheriting from key,
|
* @param inherit If true, also look for anything inheriting from key,
|
||||||
|
@ -34,16 +37,18 @@ psyc_matches (char *sho, size_t slen, char *lon, size_t llen);
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void *
|
void *
|
||||||
psyc_dict_lookup (const PsycDict *dict, size_t size,
|
psyc_map_lookup (const PsycMap *map, size_t size,
|
||||||
const char *key, size_t keylen, PsycBool inherit);
|
const char *key, size_t keylen, PsycBool inherit);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Look up value associated with a key in a dictionary of integers.
|
* Look up value associated with a key in a map with integer values.
|
||||||
* @see psyc_dict_lookup
|
* @see psyc_map_lookup
|
||||||
*/
|
*/
|
||||||
static inline intptr_t
|
static inline intptr_t
|
||||||
psyc_dict_lookup_int (const PsycDictInt * dict, size_t size,
|
psyc_map_lookup_int (const PsycMapInt * map, size_t size,
|
||||||
const char *key, size_t keylen, PsycBool inherit)
|
const char *key, size_t keylen, PsycBool inherit)
|
||||||
{
|
{
|
||||||
return (intptr_t) psyc_dict_lookup((PsycDict *) dict, size, key, keylen, inherit);
|
return (intptr_t) psyc_map_lookup((PsycMap *) map, size, key, keylen, inherit);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
|
@ -18,9 +18,53 @@
|
||||||
|
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
|
||||||
#include "syntax.h"
|
|
||||||
#include "method.h"
|
#include "method.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Maximum allowed content size without length.
|
||||||
|
* Parser stops after reaching this limit.
|
||||||
|
*/
|
||||||
|
#define PSYC_CONTENT_SIZE_MAX 512
|
||||||
|
/**
|
||||||
|
* Content size after which a length is added when rendering.
|
||||||
|
*/
|
||||||
|
#ifndef PSYC_CONTENT_SIZE_THRESHOLD
|
||||||
|
# define PSYC_CONTENT_SIZE_THRESHOLD 9
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Maximum allowed modifier size without length.
|
||||||
|
* Parser stops after reaching this limit.
|
||||||
|
*/
|
||||||
|
#define PSYC_MODIFIER_SIZE_MAX 256
|
||||||
|
/**
|
||||||
|
* Modifier size after which a length is added when rendering.
|
||||||
|
*/
|
||||||
|
#ifndef PSYC_MODIFIER_SIZE_THRESHOLD
|
||||||
|
# define PSYC_MODIFIER_SIZE_THRESHOLD 9
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Maximum allowed element size without length.
|
||||||
|
* Parser stops after reaching this limit.
|
||||||
|
*/
|
||||||
|
#define PSYC_ELEM_SIZE_MAX 128
|
||||||
|
/**
|
||||||
|
* Element size after which a length is added when rendering.
|
||||||
|
*/
|
||||||
|
#ifndef PSYC_ELEM_SIZE_THRESHOLD
|
||||||
|
# define PSYC_ELEM_SIZE_THRESHOLD 9
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define PSYC_PACKET_DELIMITER_CHAR '|'
|
||||||
|
#define PSYC_PACKET_DELIMITER "\n|\n"
|
||||||
|
|
||||||
|
#define PSYC_LIST_ELEM_START '|'
|
||||||
|
#define PSYC_DICT_KEY_START '{'
|
||||||
|
#define PSYC_DICT_KEY_END '}'
|
||||||
|
#define PSYC_DICT_VALUE_START PSYC_DICT_KEY_END
|
||||||
|
#define PSYC_DICT_VALUE_END PSYC_DICT_KEY_START
|
||||||
|
|
||||||
/** Modifier flags. */
|
/** Modifier flags. */
|
||||||
typedef enum {
|
typedef enum {
|
||||||
/// Modifier needs to be checked if it needs length.
|
/// Modifier needs to be checked if it needs length.
|
||||||
|
@ -30,18 +74,18 @@ typedef enum {
|
||||||
/// Modifier doesn't need length.
|
/// Modifier doesn't need length.
|
||||||
PSYC_MODIFIER_NO_LENGTH = 2,
|
PSYC_MODIFIER_NO_LENGTH = 2,
|
||||||
/// Routing modifier, which implies that it doesn't need length.
|
/// Routing modifier, which implies that it doesn't need length.
|
||||||
PSYC_MODIFIER_ROUTING = 3,
|
PSYC_MODIFIER_ROUTING = 4,
|
||||||
} PsycModifierFlag;
|
} PsycModifierFlag;
|
||||||
|
|
||||||
/** List flags. */
|
/** List/dict element flags. */
|
||||||
typedef enum {
|
typedef enum {
|
||||||
/// List needs to be checked if it needs length.
|
/// Element needs to be checked if it needs length.
|
||||||
PSYC_LIST_CHECK_LENGTH = 0,
|
PSYC_ELEM_CHECK_LENGTH = 0,
|
||||||
/// List needs length.
|
/// Element needs length.
|
||||||
PSYC_LIST_NEED_LENGTH = 1,
|
PSYC_ELEM_NEED_LENGTH = 1,
|
||||||
/// List doesn't need length.
|
/// Element doesn't need length.
|
||||||
PSYC_LIST_NO_LENGTH = 2,
|
PSYC_ELEM_NO_LENGTH = 2,
|
||||||
} PsycListFlag;
|
} PsycElemFlag;
|
||||||
|
|
||||||
/** Packet flags. */
|
/** Packet flags. */
|
||||||
typedef enum {
|
typedef enum {
|
||||||
|
@ -77,35 +121,90 @@ typedef enum {
|
||||||
PSYC_PACKET_ID_ELEMS = 5,
|
PSYC_PACKET_ID_ELEMS = 5,
|
||||||
} PsycPacketId;
|
} PsycPacketId;
|
||||||
|
|
||||||
/** Structure for a modifier. */
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
char oper;
|
PsycString type;
|
||||||
|
PsycString value;
|
||||||
|
size_t length;
|
||||||
|
PsycElemFlag flag;
|
||||||
|
} PsycElem;
|
||||||
|
|
||||||
|
#define PSYC_ELEM(typ, typlen, val, vallen, flg) \
|
||||||
|
(PsycElem) { \
|
||||||
|
.type = PSYC_STRING(typ, typlen), \
|
||||||
|
.value = PSYC_STRING(val, vallen), \
|
||||||
|
.flag = flg, \
|
||||||
|
}
|
||||||
|
#define PSYC_ELEM_TV(typ, typlen, val, vallen) \
|
||||||
|
(PsycElem) { \
|
||||||
|
.type = PSYC_STRING(typ, typlen), \
|
||||||
|
.value = PSYC_STRING(val, vallen), \
|
||||||
|
}
|
||||||
|
#define PSYC_ELEM_VF(val, vallen, flg) \
|
||||||
|
(PsycElem) { \
|
||||||
|
.value = PSYC_STRING(val, vallen), \
|
||||||
|
.flag = flg, \
|
||||||
|
}
|
||||||
|
#define PSYC_ELEM_V(val, vallen) \
|
||||||
|
(PsycElem) { \
|
||||||
|
.value = PSYC_STRING(val, vallen), \
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Dict key */
|
||||||
|
typedef struct {
|
||||||
|
PsycString value;
|
||||||
|
size_t length;
|
||||||
|
PsycElemFlag flag;
|
||||||
|
} PsycDictKey;
|
||||||
|
|
||||||
|
#define PSYC_DICT_KEY(k, klen, flg) \
|
||||||
|
(PsycDictKey) { \
|
||||||
|
.value = PSYC_STRING(k, klen), \
|
||||||
|
.flag = flg, \
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Dict key/value */
|
||||||
|
typedef struct {
|
||||||
|
PsycElem value;
|
||||||
|
PsycDictKey key;
|
||||||
|
} PsycDictElem;
|
||||||
|
|
||||||
|
#define PSYC_DICT_ELEM(k, v) \
|
||||||
|
(PsycDictElem) { \
|
||||||
|
.key = k, \
|
||||||
|
.value = v, \
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Dictionary */
|
||||||
|
typedef struct {
|
||||||
|
PsycString type;
|
||||||
|
PsycDictElem *elems;
|
||||||
|
size_t num_elems;
|
||||||
|
size_t length;
|
||||||
|
} PsycDict;
|
||||||
|
|
||||||
|
/** List */
|
||||||
|
typedef struct {
|
||||||
|
PsycString type;
|
||||||
|
PsycElem *elems;
|
||||||
|
size_t num_elems;
|
||||||
|
size_t length;
|
||||||
|
} PsycList;
|
||||||
|
|
||||||
|
/** Modifier */
|
||||||
|
typedef struct {
|
||||||
PsycString name;
|
PsycString name;
|
||||||
PsycString value;
|
PsycString value;
|
||||||
PsycModifierFlag flag;
|
PsycModifierFlag flag;
|
||||||
|
char oper;
|
||||||
} PsycModifier;
|
} PsycModifier;
|
||||||
|
|
||||||
/** Structure for an entity or routing header. */
|
/** Entity or routing header */
|
||||||
typedef struct {
|
typedef struct {
|
||||||
size_t lines;
|
size_t lines;
|
||||||
PsycModifier *modifiers;
|
PsycModifier *modifiers;
|
||||||
} PsycHeader;
|
} PsycHeader;
|
||||||
|
|
||||||
/** Structure for a list. */
|
/** Intermediate struct for a PSYC packet. */
|
||||||
typedef struct {
|
|
||||||
size_t num_elems;
|
|
||||||
PsycString *elems;
|
|
||||||
size_t length;
|
|
||||||
PsycListFlag flag;
|
|
||||||
} PsycList;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
PsycList *list;
|
|
||||||
size_t width;
|
|
||||||
size_t length;
|
|
||||||
} PsycTable;
|
|
||||||
|
|
||||||
/** Intermediate struct for a PSYC packet */
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
PsycHeader routing; ///< Routing header.
|
PsycHeader routing; ///< Routing header.
|
||||||
PsycHeader entity; ///< Entity header.
|
PsycHeader entity; ///< Entity header.
|
||||||
|
@ -135,16 +234,12 @@ psyc_num_length (size_t n)
|
||||||
static inline PsycModifierFlag
|
static inline PsycModifierFlag
|
||||||
psyc_modifier_length_check (PsycModifier *m)
|
psyc_modifier_length_check (PsycModifier *m)
|
||||||
{
|
{
|
||||||
PsycModifierFlag flag;
|
if (m->value.length > 0
|
||||||
|
&& (m->value.length > PSYC_MODIFIER_SIZE_THRESHOLD
|
||||||
|
|| memchr(m->value.data, (int) '\n', m->value.length)))
|
||||||
|
return PSYC_MODIFIER_NEED_LENGTH;
|
||||||
|
|
||||||
if (m->value.length > PSYC_MODIFIER_SIZE_THRESHOLD)
|
return PSYC_MODIFIER_NO_LENGTH;
|
||||||
flag = PSYC_MODIFIER_NEED_LENGTH;
|
|
||||||
else if (memchr(m->value.data, (int) '\n', m->value.length))
|
|
||||||
flag = PSYC_MODIFIER_NEED_LENGTH;
|
|
||||||
else
|
|
||||||
flag = PSYC_MODIFIER_NO_LENGTH;
|
|
||||||
|
|
||||||
return flag;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Initialize modifier */
|
/** Initialize modifier */
|
||||||
|
@ -153,33 +248,61 @@ psyc_modifier_init (PsycModifier *m, PsycOperator oper,
|
||||||
char *name, size_t namelen,
|
char *name, size_t namelen,
|
||||||
char *value, size_t valuelen, PsycModifierFlag flag)
|
char *value, size_t valuelen, PsycModifierFlag flag)
|
||||||
{
|
{
|
||||||
*m = (PsycModifier) {oper, {namelen, name}, {valuelen, value}, flag};
|
*m = (PsycModifier) {
|
||||||
|
.oper = oper,
|
||||||
|
.name = {namelen, name},
|
||||||
|
.value = {valuelen, value},
|
||||||
|
.flag = flag
|
||||||
|
};
|
||||||
|
|
||||||
if (flag == PSYC_MODIFIER_CHECK_LENGTH) // find out if it needs a length
|
if (flag == PSYC_MODIFIER_CHECK_LENGTH) // find out if it needs a length
|
||||||
m->flag = psyc_modifier_length_check(m);
|
m->flag = psyc_modifier_length_check(m);
|
||||||
|
else if (flag & PSYC_MODIFIER_ROUTING)
|
||||||
|
m->flag |= PSYC_MODIFIER_NO_LENGTH;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \internal
|
* \internal
|
||||||
* Get the total length of a modifier when rendered.
|
* Check if a list/dict element needs length.
|
||||||
|
*/
|
||||||
|
PsycElemFlag
|
||||||
|
psyc_elem_length_check (PsycString *value, const char end);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \internal
|
||||||
|
* Get the rendered length of a list/dict element.
|
||||||
|
*/
|
||||||
|
size_t
|
||||||
|
psyc_elem_length (PsycElem *elem);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \internal
|
||||||
|
* Get the rendered length of a dict key.
|
||||||
|
*/
|
||||||
|
size_t
|
||||||
|
psyc_dict_key_length (PsycDictKey *elem);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \internal
|
||||||
|
* Get the rendered length of a list.
|
||||||
|
*/
|
||||||
|
size_t
|
||||||
|
psyc_list_length_set (PsycList *list);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \internal
|
||||||
|
* Get the rendered length of a dict.
|
||||||
|
*/
|
||||||
|
size_t
|
||||||
|
psyc_dict_length_set (PsycDict *dict);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \internal
|
||||||
|
* Get the rendered length of a modifier.
|
||||||
*/
|
*/
|
||||||
size_t
|
size_t
|
||||||
psyc_modifier_length (PsycModifier *m);
|
psyc_modifier_length (PsycModifier *m);
|
||||||
|
|
||||||
/**
|
|
||||||
* \internal
|
|
||||||
* Check if a list needs length.
|
|
||||||
*/
|
|
||||||
PsycListFlag
|
|
||||||
psyc_list_length_check (PsycList *list);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* \internal
|
|
||||||
* Get the total length of a list when rendered.
|
|
||||||
*/
|
|
||||||
PsycListFlag
|
|
||||||
psyc_list_length (PsycList *list);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \internal
|
* \internal
|
||||||
* Check if a packet needs length.
|
* Check if a packet needs length.
|
||||||
|
@ -195,12 +318,11 @@ psyc_packet_length_set (PsycPacket *p);
|
||||||
|
|
||||||
/** Initialize a list. */
|
/** Initialize a list. */
|
||||||
void
|
void
|
||||||
psyc_list_init (PsycList *list, PsycString *elems, size_t num_elems,
|
psyc_list_init (PsycList *list, PsycElem *elems, size_t num_elems);
|
||||||
PsycListFlag flag);
|
|
||||||
|
|
||||||
/** Initialize a table. */
|
/** Initialize a dict. */
|
||||||
void
|
void
|
||||||
psyc_table_init (PsycTable *table, size_t width, PsycList *list);
|
psyc_dict_init (PsycDict *dict, PsycDictElem *elems, size_t num_elems);
|
||||||
|
|
||||||
/** Initialize a packet. */
|
/** Initialize a packet. */
|
||||||
void
|
void
|
||||||
|
@ -218,10 +340,13 @@ psyc_packet_init_raw (PsycPacket *packet,
|
||||||
char *content, size_t contentlen,
|
char *content, size_t contentlen,
|
||||||
PsycPacketFlag flag);
|
PsycPacketFlag flag);
|
||||||
|
|
||||||
/** Get the total length of a packet ID when rendered. */
|
void
|
||||||
size_t
|
psyc_packet_id (PsycList *list, PsycElem *elems,
|
||||||
psyc_packet_id_length (size_t contextlen, size_t sourcelen, size_t targetelen,
|
char *context, size_t contextlen,
|
||||||
size_t counterlen, size_t fragmentlen);
|
char *source, size_t sourcelen,
|
||||||
|
char *target, size_t targetlen,
|
||||||
|
char *counter, size_t counterlen,
|
||||||
|
char *fragment, size_t fragmentlen);
|
||||||
|
|
||||||
/** @} */ // end of packet group
|
/** @} */ // end of packet group
|
||||||
|
|
||||||
|
|
|
@ -132,6 +132,10 @@ typedef enum {
|
||||||
* @see psyc_parse()
|
* @see psyc_parse()
|
||||||
*/
|
*/
|
||||||
typedef enum {
|
typedef enum {
|
||||||
|
/// Error, no length is set for a modifier which is longer than PSYC_MODIFIER_SIZE_THRESHOLD.
|
||||||
|
PSYC_PARSE_ERROR_MOD_NO_LEN = -10,
|
||||||
|
/// Error, no length is set for the content but it is longer than PSYC_CONTENT_SIZE_THRESHOLD.
|
||||||
|
PSYC_PARSE_ERROR_NO_LEN = -9,
|
||||||
/// Error, packet is not ending with a valid delimiter.
|
/// Error, packet is not ending with a valid delimiter.
|
||||||
PSYC_PARSE_ERROR_END = -8,
|
PSYC_PARSE_ERROR_END = -8,
|
||||||
/// Error, expected NL after the method.
|
/// Error, expected NL after the method.
|
||||||
|
@ -197,106 +201,286 @@ typedef enum {
|
||||||
PSYC_PARSE_COMPLETE = 13,
|
PSYC_PARSE_COMPLETE = 13,
|
||||||
} PsycParseRC;
|
} PsycParseRC;
|
||||||
|
|
||||||
|
/// PSYC packet parts.
|
||||||
|
typedef enum {
|
||||||
|
PSYC_PART_RESET = -1,
|
||||||
|
PSYC_PART_ROUTING = 0,
|
||||||
|
PSYC_PART_LENGTH = 1,
|
||||||
|
PSYC_PART_CONTENT = 2,
|
||||||
|
PSYC_PART_METHOD = 3,
|
||||||
|
PSYC_PART_DATA = 4,
|
||||||
|
PSYC_PART_END = 5,
|
||||||
|
} PsycPart;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The return value definitions for the list parsing function.
|
* The return value definitions for the list parsing function.
|
||||||
* @see psyc_parse_list()
|
* @see psyc_parse_list()
|
||||||
*/
|
*/
|
||||||
typedef enum {
|
typedef enum {
|
||||||
PSYC_PARSE_LIST_ERROR_DELIM = -4,
|
/// Error, no length is set for an element which is longer than PSYC_ELEM_SIZE_THRESHOLD.
|
||||||
PSYC_PARSE_LIST_ERROR_LEN = -3,
|
PSYC_PARSE_LIST_ERROR_ELEM_NO_LEN = -6,
|
||||||
|
PSYC_PARSE_LIST_ERROR_ELEM_LENGTH = -5,
|
||||||
|
PSYC_PARSE_LIST_ERROR_ELEM_TYPE = -4,
|
||||||
|
PSYC_PARSE_LIST_ERROR_ELEM_START = -3,
|
||||||
PSYC_PARSE_LIST_ERROR_TYPE = -2,
|
PSYC_PARSE_LIST_ERROR_TYPE = -2,
|
||||||
PSYC_PARSE_LIST_ERROR = -1,
|
PSYC_PARSE_LIST_ERROR = -1,
|
||||||
/// Completed parsing a list element.
|
|
||||||
PSYC_PARSE_LIST_ELEM = 1,
|
|
||||||
/// Reached end of buffer.
|
/// Reached end of buffer.
|
||||||
PSYC_PARSE_LIST_END = 2,
|
/// Buffer contains insufficient amount of data.
|
||||||
/// Binary list is incomplete.
|
/// Fill another buffer and concatenate it with the end of the current buffer,
|
||||||
PSYC_PARSE_LIST_INCOMPLETE = 3,
|
/// from the cursor position to the end.
|
||||||
|
PSYC_PARSE_LIST_INSUFFICIENT = 1,
|
||||||
|
/// Completed parsing the default type of the list.
|
||||||
|
PSYC_PARSE_LIST_TYPE = 2,
|
||||||
|
/// Start of an element is parsed but still not complete.
|
||||||
|
PSYC_PARSE_LIST_ELEM_START = 3,
|
||||||
|
/// Continuation of an incomplete element.
|
||||||
|
PSYC_PARSE_LIST_ELEM_CONT = 4,
|
||||||
|
/// Element parsing completed.
|
||||||
|
PSYC_PARSE_LIST_ELEM_END = 5,
|
||||||
|
/// Completed parsing a list element.
|
||||||
|
PSYC_PARSE_LIST_ELEM = 6,
|
||||||
|
/// Completed parsing the last element in the list.
|
||||||
|
PSYC_PARSE_LIST_ELEM_LAST = 7,
|
||||||
|
/// Reached end of buffer.
|
||||||
|
PSYC_PARSE_LIST_END = 8,
|
||||||
} PsycParseListRC;
|
} PsycParseListRC;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
PSYC_PARSE_TABLE_ERROR_BODY = -5,
|
PSYC_LIST_PART_START = 0,
|
||||||
PSYC_PARSE_TABLE_ERROR_DELIM = -4,
|
PSYC_LIST_PART_TYPE = 1,
|
||||||
PSYC_PARSE_TABLE_ERROR_HEAD = -3,
|
PSYC_LIST_PART_ELEM_START = 2,
|
||||||
PSYC_PARSE_TABLE_ERROR_WIDTH = -2,
|
PSYC_LIST_PART_ELEM_TYPE = 3,
|
||||||
PSYC_PARSE_TABLE_ERROR = -1,
|
PSYC_LIST_PART_ELEM_LENGTH = 4,
|
||||||
/// Completed parsing the width of the table.
|
PSYC_LIST_PART_ELEM = 5,
|
||||||
PSYC_PARSE_TABLE_WIDTH = 1,
|
} PsycListPart;
|
||||||
#ifdef PSYC_PARSE_TABLE_HEAD
|
|
||||||
/// Completed parsing the name of the key column.
|
|
||||||
PSYC_PARSE_TABLE_NAME_KEY = 2,
|
|
||||||
/// Completed parsing the name of a value column.
|
|
||||||
PSYC_PARSE_TABLE_NAME_VALUE = 3,
|
|
||||||
#endif
|
|
||||||
/// Completed parsing a key.
|
|
||||||
PSYC_PARSE_TABLE_KEY = 4,
|
|
||||||
/// Completed parsing a value.
|
|
||||||
PSYC_PARSE_TABLE_VALUE = 5,
|
|
||||||
/// Completed parsing a key and reached end of buffer.
|
|
||||||
PSYC_PARSE_TABLE_KEY_END = 6,
|
|
||||||
/// Completed parsing a value and reached end of buffer.
|
|
||||||
PSYC_PARSE_TABLE_VALUE_END = 7,
|
|
||||||
/// Binary table is incomplete.
|
|
||||||
PSYC_PARSE_TABLE_INCOMPLETE = 8,
|
|
||||||
} PsycParseTableRC;
|
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
PSYC_TABLE_PART_START = 0,
|
PSYC_PARSE_DICT_ERROR_VALUE = -9,
|
||||||
PSYC_TABLE_PART_WIDTH = 1,
|
PSYC_PARSE_DICT_ERROR_VALUE_LENGTH = -8,
|
||||||
#ifdef PSYC_PARSE_TABLE_HEAD
|
PSYC_PARSE_DICT_ERROR_VALUE_TYPE = -7,
|
||||||
PSYC_TABLE_PART_HEAD_START = 2,
|
PSYC_PARSE_DICT_ERROR_VALUE_START = -6,
|
||||||
PSYC_TABLE_PART_HEAD = 3,
|
PSYC_PARSE_DICT_ERROR_KEY = -5,
|
||||||
#endif
|
PSYC_PARSE_DICT_ERROR_KEY_LENGTH = -4,
|
||||||
PSYC_TABLE_PART_BODY_START = 4,
|
PSYC_PARSE_DICT_ERROR_KEY_START = -3,
|
||||||
PSYC_TABLE_PART_BODY = 5,
|
PSYC_PARSE_DICT_ERROR_TYPE = -2,
|
||||||
} PsycTablePart;
|
PSYC_PARSE_DICT_ERROR = -1,
|
||||||
|
/// Reached end of buffer.
|
||||||
|
/// 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.
|
||||||
|
PSYC_PARSE_DICT_INSUFFICIENT = 1,
|
||||||
|
/// Completed parsing the default type of the dict.
|
||||||
|
PSYC_PARSE_DICT_TYPE = 2,
|
||||||
|
/// Start of a key is parsed but still not complete.
|
||||||
|
PSYC_PARSE_DICT_KEY_START = 3,
|
||||||
|
/// Continuation of an incomplete key.
|
||||||
|
PSYC_PARSE_DICT_KEY_CONT = 4,
|
||||||
|
/// Last continuation of a key.
|
||||||
|
PSYC_PARSE_DICT_KEY_END = 5,
|
||||||
|
/// Completed parsing a key in one go.
|
||||||
|
PSYC_PARSE_DICT_KEY = 6,
|
||||||
|
/// Start of a value is parsed but still not complete.
|
||||||
|
PSYC_PARSE_DICT_VALUE_START = 7,
|
||||||
|
/// Continuation of an incomplete value.
|
||||||
|
PSYC_PARSE_DICT_VALUE_CONT = 8,
|
||||||
|
/// Last continuation of a value.
|
||||||
|
PSYC_PARSE_DICT_VALUE_END = 9,
|
||||||
|
/// Completed parsing a value.
|
||||||
|
PSYC_PARSE_DICT_VALUE = 10,
|
||||||
|
/// Completed parsing the last value.
|
||||||
|
PSYC_PARSE_DICT_VALUE_LAST = 11,
|
||||||
|
/// Reached end of buffer.
|
||||||
|
PSYC_PARSE_DICT_END = 12,
|
||||||
|
} PsycParseDictRC;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
PSYC_DICT_PART_START = 0,
|
||||||
|
PSYC_DICT_PART_TYPE = 1,
|
||||||
|
PSYC_DICT_PART_KEY_START = 2,
|
||||||
|
PSYC_DICT_PART_KEY_LENGTH = 3,
|
||||||
|
PSYC_DICT_PART_KEY = 4,
|
||||||
|
PSYC_DICT_PART_VALUE_START = 5,
|
||||||
|
PSYC_DICT_PART_VALUE_TYPE = 6,
|
||||||
|
PSYC_DICT_PART_VALUE_LENGTH = 7,
|
||||||
|
PSYC_DICT_PART_VALUE = 8,
|
||||||
|
} PsycDictPart;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
PSYC_PARSE_INDEX_ERROR_DICT = -6,
|
||||||
|
PSYC_PARSE_INDEX_ERROR_DICT_LENGTH = -5,
|
||||||
|
PSYC_PARSE_INDEX_ERROR_STRUCT = -4,
|
||||||
|
PSYC_PARSE_INDEX_ERROR_LIST = -3,
|
||||||
|
PSYC_PARSE_INDEX_ERROR_TYPE = -2,
|
||||||
|
PSYC_PARSE_INDEX_ERROR = -1,
|
||||||
|
/// Reached end of buffer.
|
||||||
|
/// 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.
|
||||||
|
PSYC_PARSE_INDEX_INSUFFICIENT = 1,
|
||||||
|
// Completed parsing a list index.
|
||||||
|
PSYC_PARSE_INDEX_LIST = 3,
|
||||||
|
// Completed parsing a list index at the end of the buffer.
|
||||||
|
PSYC_PARSE_INDEX_LIST_LAST = 4,
|
||||||
|
// Completed parsing a struct element name.
|
||||||
|
PSYC_PARSE_INDEX_STRUCT = 5,
|
||||||
|
// Completed parsing a struct element name at the end of the buffer.
|
||||||
|
PSYC_PARSE_INDEX_STRUCT_LAST = 6,
|
||||||
|
/// Start of a dict key is parsed but still not complete.
|
||||||
|
PSYC_PARSE_INDEX_DICT_START = 7,
|
||||||
|
/// Continuation of an incomplete dict key.
|
||||||
|
PSYC_PARSE_INDEX_DICT_CONT = 8,
|
||||||
|
/// Last continuation of a dict key.
|
||||||
|
PSYC_PARSE_INDEX_DICT_END = 9,
|
||||||
|
/// Completed parsing a dict key in one go.
|
||||||
|
PSYC_PARSE_INDEX_DICT = 10,
|
||||||
|
/// Reached end of buffer.
|
||||||
|
PSYC_PARSE_INDEX_END = 11,
|
||||||
|
} PsycParseIndexRC;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
PSYC_INDEX_PART_START = 0,
|
||||||
|
PSYC_INDEX_PART_TYPE = 1,
|
||||||
|
PSYC_INDEX_PART_LIST = 2,
|
||||||
|
PSYC_INDEX_PART_STRUCT = 3,
|
||||||
|
PSYC_INDEX_PART_DICT_LENGTH = 4,
|
||||||
|
PSYC_INDEX_PART_DICT = 5,
|
||||||
|
} PsycIndexPart;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
PSYC_PARSE_UPDATE_ERROR_VALUE = -24,
|
||||||
|
PSYC_PARSE_UPDATE_ERROR_LENGTH = -23,
|
||||||
|
PSYC_PARSE_UPDATE_ERROR_TYPE = -22,
|
||||||
|
PSYC_PARSE_UPDATE_ERROR_OPER = -21,
|
||||||
|
PSYC_PARSE_UPDATE_ERROR = -1,
|
||||||
|
/// Reached end of buffer.
|
||||||
|
/// 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.
|
||||||
|
PSYC_PARSE_UPDATE_INSUFFICIENT = 1,
|
||||||
|
|
||||||
|
// Completed parsing a list index.
|
||||||
|
PSYC_PARSE_UPDATE_INDEX_LIST = 3,
|
||||||
|
// Completed parsing a struct element name.
|
||||||
|
PSYC_PARSE_UPDATE_INDEX_STRUCT = 5,
|
||||||
|
/// Start of a dict key is parsed but still not complete.
|
||||||
|
PSYC_PARSE_UPDATE_INDEX_DICT_START = 7,
|
||||||
|
/// Continuation of an incomplete dict key.
|
||||||
|
PSYC_PARSE_UPDATE_INDEX_DICT_CONT = 8,
|
||||||
|
/// Last continuation of a dict key.
|
||||||
|
PSYC_PARSE_UPDATE_INDEX_DICT_END = 9,
|
||||||
|
/// Completed parsing a dict key in one go.
|
||||||
|
PSYC_PARSE_UPDATE_INDEX_DICT = 10,
|
||||||
|
|
||||||
|
/// Completed parsing the type.
|
||||||
|
PSYC_PARSE_UPDATE_TYPE = 21,
|
||||||
|
/// Completed parsing the type and reached end of buffer.
|
||||||
|
PSYC_PARSE_UPDATE_TYPE_END = 22,
|
||||||
|
/// Start of the value is parsed but still not complete.
|
||||||
|
PSYC_PARSE_UPDATE_VALUE_START = 23,
|
||||||
|
/// Continuation of incomplete value.
|
||||||
|
PSYC_PARSE_UPDATE_VALUE_CONT = 24,
|
||||||
|
/// Last continuation of the value.
|
||||||
|
PSYC_PARSE_UPDATE_VALUE_END = 25,
|
||||||
|
/// Completed parsing the value in one go.
|
||||||
|
PSYC_PARSE_UPDATE_VALUE = 26,
|
||||||
|
/// Reached end of buffer.
|
||||||
|
PSYC_PARSE_UPDATE_END = 27,
|
||||||
|
} PsycParseUpdateRC;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
PSYC_UPDATE_PART_START = 0,
|
||||||
|
|
||||||
|
PSYC_UPDATE_INDEX_PART_TYPE = 1,
|
||||||
|
PSYC_UPDATE_INDEX_PART_LIST = 2,
|
||||||
|
PSYC_UPDATE_INDEX_PART_STRUCT = 3,
|
||||||
|
PSYC_UPDATE_INDEX_PART_DICT_LENGTH = 4,
|
||||||
|
PSYC_UPDATE_INDEX_PART_DICT = 5,
|
||||||
|
|
||||||
|
PSYC_UPDATE_PART_TYPE = 12,
|
||||||
|
PSYC_UPDATE_PART_LENGTH = 13,
|
||||||
|
PSYC_UPDATE_PART_VALUE = 14,
|
||||||
|
} PsycUpdatePart;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Struct for keeping parser state.
|
* Struct for keeping parser state.
|
||||||
*/
|
*/
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
PsycString buffer; ///< Buffer with data to be parsed.
|
||||||
size_t cursor; ///< Current position in buffer.
|
size_t cursor; ///< Current position in buffer.
|
||||||
size_t startc; ///< Position where the parsing would be resumed.
|
size_t startc; ///< Position where the parsing would be resumed.
|
||||||
PsycString buffer; ///< Buffer with data to be parsed.
|
|
||||||
uint8_t flags; ///< Flags for the parser, see PsycParseFlag.
|
|
||||||
PsycPart part; ///< Part of the packet being parsed currently.
|
|
||||||
|
|
||||||
size_t routinglen; ///< Length of routing part parsed so far.
|
size_t routinglen; ///< Length of routing part parsed so far.
|
||||||
size_t content_parsed; ///< Number of bytes parsed from the content so far.
|
|
||||||
size_t contentlen; ///< Expected length of the content.
|
size_t contentlen; ///< Expected length of the content.
|
||||||
PsycBool contentlen_found; ///< Is there a length given for this packet?
|
size_t content_parsed; ///< Number of bytes parsed from the content so far.
|
||||||
size_t value_parsed; ///< Number of bytes parsed from the value so far.
|
|
||||||
size_t valuelen; ///< Expected length of the value.
|
size_t valuelen; ///< Expected length of the value.
|
||||||
PsycBool valuelen_found; ///< Is there a length given for this modifier?
|
size_t value_parsed; ///< Number of bytes parsed from the value so far.
|
||||||
|
|
||||||
|
PsycPart part; ///< Part of the packet being parsed currently.
|
||||||
|
uint8_t flags; ///< Flags for the parser, see PsycParseFlag.
|
||||||
|
uint8_t contentlen_found; ///< Is there a length given for this packet?
|
||||||
|
uint8_t valuelen_found; ///< Is there a length given for this modifier?
|
||||||
} PsycParseState;
|
} PsycParseState;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Struct for keeping list parser state.
|
* Struct for keeping list parser state.
|
||||||
*/
|
*/
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
PsycString buffer; ///< Buffer with data to be parsed.
|
||||||
size_t cursor; ///< Current position in buffer.
|
size_t cursor; ///< Current position in buffer.
|
||||||
size_t startc; ///< Line start position.
|
size_t startc; ///< Line start position.
|
||||||
PsycString buffer; ///< Buffer with data to be parsed.
|
|
||||||
PsycListType type; ///< List type.
|
|
||||||
char term; ///< Terminator character at the end.
|
|
||||||
uint8_t term_set; ///< Look for terminator.
|
|
||||||
|
|
||||||
size_t elem_parsed; ///< Number of bytes parsed from the elem so far.
|
PsycString type; ///< List type.
|
||||||
size_t elemlen; ///< Expected length of the elem.
|
size_t elemlen; ///< Expected length of the elem.
|
||||||
|
size_t elem_parsed; ///< Number of bytes parsed from the elem so far.
|
||||||
|
|
||||||
|
PsycListPart part; ///< Part of the list being parsed currently.
|
||||||
|
uint8_t elemlen_found; ///< Is there a length given for this element?
|
||||||
} PsycParseListState;
|
} PsycParseListState;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Struct for keeping table parser state.
|
* Struct for keeping dict parser state.
|
||||||
*/
|
*/
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
PsycString buffer; ///< Buffer with data to be parsed.
|
||||||
size_t cursor; ///< Current position in buffer.
|
size_t cursor; ///< Current position in buffer.
|
||||||
size_t startc; ///< Line start position.
|
size_t startc; ///< Line start position.
|
||||||
|
|
||||||
|
size_t elemlen; ///< Expected length of the key/value.
|
||||||
|
size_t elem_parsed; ///< Number of bytes parsed from the key/value so far.
|
||||||
|
|
||||||
|
PsycDictPart part; ///< Part of the dict being parsed currently.
|
||||||
|
uint8_t elemlen_found; ///< Is there a length given for this key/value?
|
||||||
|
} PsycParseDictState;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Struct for keeping index parser state.
|
||||||
|
*/
|
||||||
|
typedef struct {
|
||||||
PsycString buffer; ///< Buffer with data to be parsed.
|
PsycString buffer; ///< Buffer with data to be parsed.
|
||||||
PsycTablePart part; ///< Table type.
|
size_t cursor; ///< Current position in buffer.
|
||||||
size_t width; ///< Width of table.
|
size_t startc; ///< Position where the parsing would be resumed.
|
||||||
size_t elems; ///< Elems parsed so far in the table.
|
|
||||||
PsycParseListState list;
|
size_t elemlen; ///< Expected length of an element.
|
||||||
} PsycParseTableState;
|
size_t elem_parsed; ///< Number of bytes parsed from the elem so far.
|
||||||
|
|
||||||
|
PsycIndexPart part; ///< Part of the packet being parsed currently.
|
||||||
|
uint8_t elemlen_found; ///< Is there a length given for this element?
|
||||||
|
} PsycParseIndexState;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Struct for keeping update modifier parser state.
|
||||||
|
*/
|
||||||
|
typedef struct {
|
||||||
|
PsycString buffer; ///< Buffer with data to be parsed.
|
||||||
|
size_t cursor; ///< Current position in buffer.
|
||||||
|
size_t startc; ///< Position where the parsing would be resumed.
|
||||||
|
|
||||||
|
size_t elemlen; ///< Expected length of an element.
|
||||||
|
size_t elem_parsed; ///< Number of bytes parsed from the elem so far.
|
||||||
|
|
||||||
|
PsycUpdatePart part; ///< Part of the packet being parsed currently.
|
||||||
|
uint8_t elemlen_found; ///< Is there a length given for this element?
|
||||||
|
} PsycParseUpdateState;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initializes the state struct.
|
* Initializes the state struct.
|
||||||
|
@ -339,7 +523,7 @@ psyc_parse_buffer_set (PsycParseState *state, const char *buffer, size_t length)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initializes the list state.
|
* Initializes the list parser state.
|
||||||
*/
|
*/
|
||||||
static inline void
|
static inline void
|
||||||
psyc_parse_list_state_init (PsycParseListState *state)
|
psyc_parse_list_state_init (PsycParseListState *state)
|
||||||
|
@ -358,27 +542,60 @@ psyc_parse_list_buffer_set (PsycParseListState *state,
|
||||||
state->cursor = 0;
|
state->cursor = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes the dict parser state.
|
||||||
|
*/
|
||||||
static inline void
|
static inline void
|
||||||
psyc_parse_list_term_set (PsycParseListState *state, char term)
|
psyc_parse_dict_state_init (PsycParseDictState *state)
|
||||||
{
|
{
|
||||||
state->term = term;
|
memset(state, 0, sizeof(PsycParseDictState));
|
||||||
state->term_set = PSYC_TRUE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initializes the table state.
|
* Sets a new buffer in the dict parser state struct with data to be parsed.
|
||||||
*/
|
*/
|
||||||
static inline void
|
static inline void
|
||||||
psyc_parse_table_state_init (PsycParseTableState *state)
|
psyc_parse_dict_buffer_set (PsycParseDictState *state,
|
||||||
|
const char *buffer, size_t length)
|
||||||
{
|
{
|
||||||
memset(state, 0, sizeof(PsycParseTableState));
|
state->buffer = (PsycString) {length, (char*)buffer};
|
||||||
|
state->cursor = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets a new buffer in the list parser state struct with data to be parsed.
|
* Initializes the index parser state.
|
||||||
*/
|
*/
|
||||||
static inline void
|
static inline void
|
||||||
psyc_parse_table_buffer_set (PsycParseTableState *state,
|
psyc_parse_index_state_init (PsycParseIndexState *state)
|
||||||
|
{
|
||||||
|
memset(state, 0, sizeof(PsycParseIndexState));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets a new buffer in the index parser state struct with data to be parsed.
|
||||||
|
*/
|
||||||
|
static inline void
|
||||||
|
psyc_parse_index_buffer_set (PsycParseIndexState *state,
|
||||||
|
const char *buffer, size_t length)
|
||||||
|
{
|
||||||
|
state->buffer = (PsycString) {length, (char*)buffer};
|
||||||
|
state->cursor = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes the update modifier parser state.
|
||||||
|
*/
|
||||||
|
static inline void
|
||||||
|
psyc_parse_update_state_init (PsycParseUpdateState *state)
|
||||||
|
{
|
||||||
|
memset(state, 0, sizeof(PsycParseUpdateState));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets a new buffer in the update modifier parser state struct with data to be parsed.
|
||||||
|
*/
|
||||||
|
static inline void
|
||||||
|
psyc_parse_update_buffer_set (PsycParseUpdateState *state,
|
||||||
const char *buffer, size_t length)
|
const char *buffer, size_t length)
|
||||||
{
|
{
|
||||||
state->buffer = (PsycString) {length, (char*)buffer};
|
state->buffer = (PsycString) {length, (char*)buffer};
|
||||||
|
@ -471,10 +688,25 @@ psyc_parse (PsycParseState *state, char *oper,
|
||||||
static inline
|
static inline
|
||||||
#endif
|
#endif
|
||||||
PsycParseListRC
|
PsycParseListRC
|
||||||
psyc_parse_list (PsycParseListState *state, PsycString *elem);
|
psyc_parse_list (PsycParseListState *state, PsycString *type, PsycString *elem);
|
||||||
|
|
||||||
PsycParseTableRC
|
#ifdef __INLINE_PSYC_PARSE
|
||||||
psyc_parse_table (PsycParseTableState *state, PsycString *elem);
|
static inline
|
||||||
|
#endif
|
||||||
|
PsycParseDictRC
|
||||||
|
psyc_parse_dict (PsycParseDictState *state, PsycString *type, PsycString *elem);
|
||||||
|
|
||||||
|
#ifdef __INLINE_PSYC_PARSE
|
||||||
|
static inline
|
||||||
|
#endif
|
||||||
|
PsycParseIndexRC
|
||||||
|
psyc_parse_index (PsycParseIndexState *state, PsycString *idx);
|
||||||
|
|
||||||
|
#ifdef __INLINE_PSYC_PARSE
|
||||||
|
static inline
|
||||||
|
#endif
|
||||||
|
PsycParseUpdateRC
|
||||||
|
psyc_parse_update (PsycParseUpdateState *state, char *oper, PsycString *value);
|
||||||
|
|
||||||
static inline size_t
|
static inline size_t
|
||||||
psyc_parse_int (const char *value, size_t len, int64_t *n)
|
psyc_parse_int (const char *value, size_t len, int64_t *n)
|
||||||
|
@ -516,7 +748,7 @@ psyc_parse_uint (const char *value, size_t len, uint64_t *n)
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline size_t
|
static inline size_t
|
||||||
psyc_parse_index (const char *value, size_t len, int64_t *n)
|
psyc_parse_list_index (const char *value, size_t len, int64_t *n)
|
||||||
{
|
{
|
||||||
if (!value || len == 0 || value[0] != '#')
|
if (!value || len == 0 || value[0] != '#')
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -51,6 +51,12 @@ static inline
|
||||||
PsycRenderRC
|
PsycRenderRC
|
||||||
psyc_render (PsycPacket *packet, char *buffer, size_t buflen);
|
psyc_render (PsycPacket *packet, char *buffer, size_t buflen);
|
||||||
|
|
||||||
|
PsycRenderRC
|
||||||
|
psyc_render_elem (PsycElem *elem, char *buffer, size_t buflen);
|
||||||
|
|
||||||
|
PsycRenderRC
|
||||||
|
psyc_render_dict_key (PsycDictKey *elem, char *buffer, size_t buflen);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Render a PSYC list into a buffer.
|
* Render a PSYC list into a buffer.
|
||||||
*/
|
*/
|
||||||
|
@ -61,15 +67,7 @@ PsycRenderRC
|
||||||
psyc_render_list (PsycList *list, char *buffer, size_t buflen);
|
psyc_render_list (PsycList *list, char *buffer, size_t buflen);
|
||||||
|
|
||||||
PsycRenderRC
|
PsycRenderRC
|
||||||
psyc_render_table (PsycTable *table, char *buffer, size_t buflen);
|
psyc_render_dict (PsycDict *dict, char *buffer, size_t buflen);
|
||||||
|
|
||||||
PsycRenderRC
|
|
||||||
psyc_render_packet_id (char *context, size_t contextlen,
|
|
||||||
char *source, size_t sourcelen,
|
|
||||||
char *target, size_t targetlen,
|
|
||||||
char *counter, size_t counterlen,
|
|
||||||
char *fragment, size_t fragmentlen,
|
|
||||||
char *buffer, size_t buflen);
|
|
||||||
|
|
||||||
/** @} */ // end of render group
|
/** @} */ // end of render group
|
||||||
|
|
||||||
|
|
|
@ -1,21 +0,0 @@
|
||||||
#ifndef PSYC_SYNTAX_H
|
|
||||||
|
|
||||||
#ifndef PSYC_LIST_SIZE_LIMIT
|
|
||||||
# define PSYC_LIST_SIZE_LIMIT 404
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* beyond this a content length must be provided */
|
|
||||||
#ifndef PSYC_CONTENT_SIZE_THRESHOLD
|
|
||||||
# define PSYC_CONTENT_SIZE_THRESHOLD 444
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* beyond this a modifier value length must be provided */
|
|
||||||
#ifndef PSYC_MODIFIER_SIZE_THRESHOLD
|
|
||||||
# define PSYC_MODIFIER_SIZE_THRESHOLD 404
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define PSYC_PACKET_DELIMITER_CHAR '|'
|
|
||||||
#define PSYC_PACKET_DELIMITER "\n|\n"
|
|
||||||
|
|
||||||
#define PSYC_SYNTAX_H
|
|
||||||
#endif
|
|
|
@ -5,16 +5,17 @@
|
||||||
#ifndef PSYC_VARIABLE_H
|
#ifndef PSYC_VARIABLE_H
|
||||||
#define PSYC_VARIABLE_H
|
#define PSYC_VARIABLE_H
|
||||||
|
|
||||||
|
#include "match.h"
|
||||||
#include "packet.h"
|
#include "packet.h"
|
||||||
|
|
||||||
/// Routing variables in alphabetical order.
|
/// Routing variables in alphabetical order.
|
||||||
extern const PsycDictInt psyc_rvars[];
|
extern const PsycMapInt psyc_rvars[];
|
||||||
|
|
||||||
// Variable types in alphabetical order.
|
// Variable types in alphabetical order.
|
||||||
extern const PsycDictInt psyc_var_types[];
|
extern const PsycMapInt psyc_var_types[];
|
||||||
|
|
||||||
/// Method names in alphabetical order.
|
/// Method names in alphabetical order.
|
||||||
extern const PsycDictInt psyc_methods[];
|
extern const PsycMapInt psyc_methods[];
|
||||||
|
|
||||||
extern const size_t psyc_rvars_num;
|
extern const size_t psyc_rvars_num;
|
||||||
extern const size_t psyc_var_types_num;
|
extern const size_t psyc_var_types_num;
|
||||||
|
@ -37,14 +38,41 @@ typedef enum {
|
||||||
PSYC_RVARS_NUM,
|
PSYC_RVARS_NUM,
|
||||||
} PsycRoutingVar;
|
} PsycRoutingVar;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Variable types.
|
||||||
|
*
|
||||||
|
* This enum lists PSYC variable types that
|
||||||
|
* this library is capable of checking for
|
||||||
|
* validity. Other variable types are treated
|
||||||
|
* as opaque data.
|
||||||
|
*/
|
||||||
|
typedef enum {
|
||||||
|
PSYC_TYPE_UNKNOWN,
|
||||||
|
PSYC_TYPE_AMOUNT,
|
||||||
|
PSYC_TYPE_COLOR,
|
||||||
|
PSYC_TYPE_COUNTER,
|
||||||
|
PSYC_TYPE_DATE,
|
||||||
|
PSYC_TYPE_DEGREE,
|
||||||
|
PSYC_TYPE_DICT,
|
||||||
|
PSYC_TYPE_ENTITY,
|
||||||
|
PSYC_TYPE_FLAG,
|
||||||
|
PSYC_TYPE_LANGUAGE,
|
||||||
|
PSYC_TYPE_LIST,
|
||||||
|
PSYC_TYPE_NICK,
|
||||||
|
PSYC_TYPE_PAGE,
|
||||||
|
PSYC_TYPE_STRUCT,
|
||||||
|
PSYC_TYPE_TIME,
|
||||||
|
PSYC_TYPE_UNIFORM,
|
||||||
|
} PsycType;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Look up routing variable.
|
* Look up routing variable.
|
||||||
*/
|
*/
|
||||||
static inline PsycRoutingVar
|
static inline PsycRoutingVar
|
||||||
psyc_var_routing (const char *name, size_t len)
|
psyc_var_routing (const char *name, size_t len)
|
||||||
{
|
{
|
||||||
return (PsycRoutingVar) psyc_dict_lookup((PsycDict *)psyc_rvars,
|
return (PsycRoutingVar)
|
||||||
psyc_rvars_num, name, len, PSYC_NO);
|
psyc_map_lookup((PsycMap*)psyc_rvars, psyc_rvars_num, name, len, PSYC_NO);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -53,8 +81,9 @@ psyc_var_routing (const char *name, size_t len)
|
||||||
static inline PsycType
|
static inline PsycType
|
||||||
psyc_var_type (const char *name, size_t len)
|
psyc_var_type (const char *name, size_t len)
|
||||||
{
|
{
|
||||||
return (PsycType) psyc_dict_lookup((PsycDict *)psyc_var_types,
|
return (PsycType)
|
||||||
psyc_var_types_num, name, len, PSYC_YES);
|
psyc_map_lookup((PsycMap*)psyc_var_types, psyc_var_types_num,
|
||||||
|
name, len, PSYC_YES);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -4,8 +4,10 @@
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
# include <stdio.h>
|
# include <stdio.h>
|
||||||
# define PP(args) printf args;
|
# define PP(args) printf args;
|
||||||
|
# define ASSERT(cond) assert(cond)
|
||||||
#else
|
#else
|
||||||
# define PP(args)
|
# define PP(args)
|
||||||
|
# define ASSERT(cond)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef TEST
|
#ifdef TEST
|
||||||
|
|
20
src/match.c
20
src/match.c
|
@ -107,10 +107,10 @@ psyc_matches(char *sho, size_t slen, char *lon, size_t llen)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Look up value associated with a key in a dictionary.
|
* Look up value associated with a key in a map.
|
||||||
*/
|
*/
|
||||||
void *
|
void *
|
||||||
psyc_dict_lookup(const PsycDict * dict, size_t size,
|
psyc_map_lookup(const PsycMap * map, size_t size,
|
||||||
const char *key, size_t keylen, PsycBool inherit)
|
const char *key, size_t keylen, PsycBool inherit)
|
||||||
{
|
{
|
||||||
//size_t cursor = 1;
|
//size_t cursor = 1;
|
||||||
|
@ -122,25 +122,25 @@ psyc_dict_lookup(const PsycDict * dict, size_t size,
|
||||||
|
|
||||||
//for (c = 0, i = 0; c < keylen && i < size; c++) {
|
//for (c = 0, i = 0; c < keylen && i < size; c++) {
|
||||||
for (i = 0; i < size; i++) {
|
for (i = 0; i < size; i++) {
|
||||||
if (!(keylen == dict[i].key.length
|
if (!(keylen == map[i].key.length
|
||||||
|| (inherit && keylen > dict[i].key.length
|
|| (inherit && keylen > map[i].key.length
|
||||||
&& key[dict[i].key.length] == '_')))
|
&& key[map[i].key.length] == '_')))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
match = 1;
|
match = 1;
|
||||||
for (c = 0; c < keylen; c++) {
|
for (c = 0; c < keylen; c++) {
|
||||||
if (c < dict[i].key.length && dict[i].key.data[c] == key[c])
|
if (c < map[i].key.length && map[i].key.data[c] == key[c])
|
||||||
continue;
|
continue;
|
||||||
else if (c == dict[i].key.length && key[c] == '_')
|
else if (c == map[i].key.length && key[c] == '_')
|
||||||
return dict[i].value; // after the end of a matching prefix
|
return map[i].value; // after the end of a matching prefix
|
||||||
else if (dict[i].key.data[c] > key[c])
|
else if (map[i].key.data[c] > key[c])
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
match = 0;
|
match = 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (match)
|
if (match)
|
||||||
return dict[i].value;
|
return map[i].value;
|
||||||
}
|
}
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
157
src/packet.c
157
src/packet.c
|
@ -1,73 +1,99 @@
|
||||||
#include "lib.h"
|
#include "lib.h"
|
||||||
#include <psyc/syntax.h>
|
|
||||||
#include <psyc/packet.h>
|
#include <psyc/packet.h>
|
||||||
|
|
||||||
inline PsycListFlag
|
inline PsycElemFlag
|
||||||
psyc_list_length_check (PsycList *list)
|
psyc_elem_length_check (PsycString *value, const char end)
|
||||||
{
|
{
|
||||||
PsycListFlag flag = PSYC_LIST_NO_LENGTH;
|
if (value->length > PSYC_ELEM_SIZE_THRESHOLD
|
||||||
size_t i, length = 0;
|
|| memchr(value->data, (int)end, value->length))
|
||||||
|
return PSYC_ELEM_NEED_LENGTH;
|
||||||
|
|
||||||
for (i = 0; i < list->num_elems; i++) {
|
return PSYC_ELEM_NO_LENGTH;;
|
||||||
PsycString *elem = &list->elems[i];
|
|
||||||
length += 1 + elem->length; // |elem
|
|
||||||
if (length > PSYC_MODIFIER_SIZE_THRESHOLD ||
|
|
||||||
memchr(elem->data, (int) '|', elem->length) ||
|
|
||||||
memchr(elem->data, (int) '\n', elem->length)) {
|
|
||||||
flag = PSYC_LIST_NEED_LENGTH;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return flag;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline PsycListFlag
|
inline size_t
|
||||||
psyc_list_length (PsycList *list)
|
psyc_elem_length (PsycElem *elem)
|
||||||
{
|
{
|
||||||
size_t i, length = 0;
|
return
|
||||||
|
(elem->type.length ? 1 + elem->type.length : 0)
|
||||||
|
+ (elem->value.length && elem->flag != PSYC_ELEM_NO_LENGTH
|
||||||
|
? (elem->type.length ? 1 : 0) + psyc_num_length(elem->value.length) : 0)
|
||||||
|
+ (elem->value.length ? 1 + elem->value.length : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline size_t
|
||||||
|
psyc_dict_key_length (PsycDictKey *elem)
|
||||||
|
{
|
||||||
|
return
|
||||||
|
(elem->flag != PSYC_ELEM_NO_LENGTH
|
||||||
|
? psyc_num_length(elem->value.length) : 0)
|
||||||
|
+ (elem->value.length ? 1 + elem->value.length : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline size_t
|
||||||
|
psyc_list_length_set (PsycList *list)
|
||||||
|
{
|
||||||
|
size_t i;
|
||||||
|
PsycElem *elem;
|
||||||
|
|
||||||
|
list->length = list->type.length;
|
||||||
|
|
||||||
if (list->flag == PSYC_LIST_NEED_LENGTH) {
|
|
||||||
for (i = 0; i < list->num_elems; i++) {
|
for (i = 0; i < list->num_elems; i++) {
|
||||||
if (i > 0)
|
elem = &list->elems[i];
|
||||||
length++; // |
|
if (elem->flag == PSYC_ELEM_CHECK_LENGTH)
|
||||||
length += // length SP elem
|
elem->flag = psyc_elem_length_check(&elem->value, '|');
|
||||||
psyc_num_length(list->elems[i].length) + 1 + list->elems[i].length;
|
elem->length = psyc_elem_length(elem);
|
||||||
}
|
list->length += 1 + elem->length;
|
||||||
} else {
|
|
||||||
for (i = 0; i < list->num_elems; i++)
|
|
||||||
length += 1 + list->elems[i].length; // |elem
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return length;
|
return list->length;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline size_t
|
||||||
|
psyc_dict_length_set (PsycDict *dict)
|
||||||
|
{
|
||||||
|
size_t i;
|
||||||
|
PsycDictKey *key;
|
||||||
|
PsycElem *value;
|
||||||
|
|
||||||
|
dict->length = dict->type.length;
|
||||||
|
|
||||||
|
for (i = 0; i < dict->num_elems; i++) {
|
||||||
|
key = &dict->elems[i].key;
|
||||||
|
value = &dict->elems[i].value;
|
||||||
|
|
||||||
|
if (key->flag == PSYC_ELEM_CHECK_LENGTH)
|
||||||
|
key->flag = psyc_elem_length_check(&key->value, '}');
|
||||||
|
if (value->flag == PSYC_ELEM_CHECK_LENGTH)
|
||||||
|
value->flag = psyc_elem_length_check(&value->value, '{');
|
||||||
|
|
||||||
|
key->length = psyc_dict_key_length(key);
|
||||||
|
value->length = psyc_elem_length(value);
|
||||||
|
|
||||||
|
dict->length += 1 + key->length + 1 + value->length;
|
||||||
|
}
|
||||||
|
|
||||||
|
return dict->length;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
psyc_list_init (PsycList *list, PsycString *elems, size_t num_elems,
|
psyc_list_init (PsycList *list, PsycElem *elems, size_t num_elems)
|
||||||
PsycListFlag flag)
|
|
||||||
{
|
{
|
||||||
*list = (PsycList) {
|
*list = (PsycList) {
|
||||||
.num_elems = num_elems,
|
.num_elems = num_elems,
|
||||||
.elems = elems,
|
.elems = elems,
|
||||||
.length = 0,
|
|
||||||
.flag = flag,
|
|
||||||
};
|
};
|
||||||
|
psyc_list_length_set(list);
|
||||||
if (flag == PSYC_LIST_CHECK_LENGTH) // check if list elements need length
|
|
||||||
list->flag = psyc_list_length_check(list);
|
|
||||||
|
|
||||||
list->length = psyc_list_length(list);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
psyc_table_init (PsycTable *table, size_t width, PsycList *list)
|
psyc_dict_init (PsycDict *dict, PsycDictElem *elems, size_t num_elems)
|
||||||
{
|
{
|
||||||
*table = (PsycTable) {
|
*dict = (PsycDict) {
|
||||||
.width = width,
|
.num_elems = num_elems,
|
||||||
.list = list,
|
.elems = elems,
|
||||||
};
|
};
|
||||||
|
psyc_dict_length_set(dict);
|
||||||
table->length = (width > 0 ? psyc_num_length(width) + 2 : 0) + list->length;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline size_t
|
inline size_t
|
||||||
|
@ -77,7 +103,10 @@ psyc_modifier_length (PsycModifier *m)
|
||||||
if (m->name.length > 0)
|
if (m->name.length > 0)
|
||||||
length += m->name.length + 1 + m->value.length; // name\tvalue
|
length += m->name.length + 1 + m->value.length; // name\tvalue
|
||||||
|
|
||||||
if (m->flag == PSYC_MODIFIER_NEED_LENGTH) // add length of length if needed
|
// add length of length if needed
|
||||||
|
if (m->value.length
|
||||||
|
&& (m->flag & PSYC_MODIFIER_NEED_LENGTH
|
||||||
|
|| m->flag == PSYC_MODIFIER_CHECK_LENGTH))
|
||||||
length += psyc_num_length(m->value.length) + 1; // SP length
|
length += psyc_num_length(m->value.length) + 1; // SP length
|
||||||
|
|
||||||
return length;
|
return length;
|
||||||
|
@ -96,7 +125,8 @@ psyc_packet_length_check (PsycPacket *p)
|
||||||
// If any entity modifiers need length, it is possible they contain
|
// If any entity modifiers need length, it is possible they contain
|
||||||
// a packet terminator, thus the content should have a length as well.
|
// a packet terminator, thus the content should have a length as well.
|
||||||
for (i = 0; i < p->entity.lines; i++)
|
for (i = 0; i < p->entity.lines; i++)
|
||||||
if (p->entity.modifiers[i].flag == PSYC_MODIFIER_NEED_LENGTH)
|
if (p->entity.modifiers[i].flag & PSYC_MODIFIER_NEED_LENGTH
|
||||||
|
|| p->entity.modifiers[i].flag == PSYC_MODIFIER_CHECK_LENGTH)
|
||||||
return PSYC_PACKET_NEED_LENGTH;
|
return PSYC_PACKET_NEED_LENGTH;
|
||||||
|
|
||||||
if (memmem(p->data.data, p->data.length, PSYC_C2ARG(PSYC_PACKET_DELIMITER)))
|
if (memmem(p->data.data, p->data.length, PSYC_C2ARG(PSYC_PACKET_DELIMITER)))
|
||||||
|
@ -137,10 +167,11 @@ psyc_packet_length_set (PsycPacket *p)
|
||||||
// set total length: routing-header content |\n
|
// set total length: routing-header content |\n
|
||||||
p->length = p->routinglen + p->contentlen + 2;
|
p->length = p->routinglen + p->contentlen + 2;
|
||||||
|
|
||||||
if (p->contentlen > 0 || p->flag == PSYC_PACKET_NEED_LENGTH)
|
if (p->contentlen)
|
||||||
p->length++; // add \n at the start of the content part
|
p->length++; // add \n at the start of the content part
|
||||||
|
|
||||||
if (p->flag == PSYC_PACKET_NEED_LENGTH) // add length of length if needed
|
// add length of length if needed
|
||||||
|
if (p->contentlen && !(p->flag & PSYC_PACKET_NO_LENGTH))
|
||||||
p->length += psyc_num_length(p->contentlen);
|
p->length += psyc_num_length(p->contentlen);
|
||||||
|
|
||||||
return p->length;
|
return p->length;
|
||||||
|
@ -198,9 +229,29 @@ psyc_packet_init_raw (PsycPacket *p,
|
||||||
psyc_packet_length_set(p);
|
psyc_packet_length_set(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t
|
void
|
||||||
psyc_packet_id_length (size_t contextlen, size_t sourcelen, size_t targetlen,
|
psyc_packet_id (PsycList *list, PsycElem *elems,
|
||||||
size_t counterlen, size_t fragmentlen)
|
char *context, size_t contextlen,
|
||||||
|
char *source, size_t sourcelen,
|
||||||
|
char *target, size_t targetlen,
|
||||||
|
char *counter, size_t counterlen,
|
||||||
|
char *fragment, size_t fragmentlen)
|
||||||
{
|
{
|
||||||
return contextlen + sourcelen + targetlen + counterlen + fragmentlen + 5;
|
if (contextlen)
|
||||||
|
elems[PSYC_PACKET_ID_CONTEXT] =
|
||||||
|
PSYC_ELEM_VF(context, contextlen, PSYC_ELEM_NO_LENGTH);
|
||||||
|
if (sourcelen)
|
||||||
|
elems[PSYC_PACKET_ID_SOURCE] =
|
||||||
|
PSYC_ELEM_VF(source, sourcelen, PSYC_ELEM_NO_LENGTH);
|
||||||
|
if (targetlen)
|
||||||
|
elems[PSYC_PACKET_ID_TARGET] =
|
||||||
|
PSYC_ELEM_VF(target, targetlen, PSYC_ELEM_NO_LENGTH);
|
||||||
|
if (counterlen)
|
||||||
|
elems[PSYC_PACKET_ID_COUNTER] =
|
||||||
|
PSYC_ELEM_VF(counter, counterlen, PSYC_ELEM_NO_LENGTH);
|
||||||
|
if (fragmentlen)
|
||||||
|
elems[PSYC_PACKET_ID_FRAGMENT] =
|
||||||
|
PSYC_ELEM_VF(fragment, fragmentlen, PSYC_ELEM_NO_LENGTH);
|
||||||
|
|
||||||
|
psyc_list_init(list, elems, PSYC_PACKET_ID_ELEMS);
|
||||||
}
|
}
|
||||||
|
|
876
src/parse.c
876
src/parse.c
|
@ -15,33 +15,67 @@
|
||||||
return ret; \
|
return ret; \
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define ADVANCE_STARTC_OR_RETURN(ret) \
|
||||||
|
state->startc = state->cursor + 1; \
|
||||||
|
if (++(state->cursor) >= state->buffer.length) \
|
||||||
|
return ret; \
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
PARSE_ERROR = -1,
|
PARSE_ERROR = -1,
|
||||||
PARSE_SUCCESS = 0,
|
PARSE_SUCCESS = 0,
|
||||||
PARSE_INSUFFICIENT = 1,
|
PARSE_INSUFFICIENT = 1,
|
||||||
PARSE_COMPLETE = 100,
|
PARSE_INCOMPLETE = 2,
|
||||||
PARSE_INCOMPLETE = 101,
|
|
||||||
} ParseRC;
|
} ParseRC;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
PsycString buffer;
|
||||||
|
size_t cursor;
|
||||||
|
size_t startc;
|
||||||
|
} ParseState;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parse variable name or method name.
|
* Parse variable name or method name.
|
||||||
|
*
|
||||||
* It should contain one or more keyword characters.
|
* It should contain one or more keyword characters.
|
||||||
|
*
|
||||||
* @return PARSE_ERROR or PARSE_SUCCESS
|
* @return PARSE_ERROR or PARSE_SUCCESS
|
||||||
*/
|
*/
|
||||||
static inline ParseRC
|
static inline ParseRC
|
||||||
parse_keyword (PsycParseState *state, PsycString *name)
|
parse_keyword (ParseState *state, PsycString *name)
|
||||||
{
|
{
|
||||||
name->data = state->buffer.data + state->cursor;
|
name->data = state->buffer.data + state->cursor;
|
||||||
name->length = 0;
|
name->length = 0;
|
||||||
|
|
||||||
while (psyc_is_kw_char(state->buffer.data[state->cursor])) {
|
while (psyc_is_kw_char(state->buffer.data[state->cursor])) {
|
||||||
name->length++; // was a valid char, increase length
|
name->length++; // was a valid char, increase length
|
||||||
ADVANCE_CURSOR_OR_RETURN(PSYC_PARSE_INSUFFICIENT);
|
ADVANCE_CURSOR_OR_RETURN(PARSE_INSUFFICIENT);
|
||||||
}
|
}
|
||||||
|
|
||||||
return name->length > 0 ? PARSE_SUCCESS : PARSE_ERROR;
|
return name->length > 0 ? PARSE_SUCCESS : PARSE_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse length.
|
||||||
|
*
|
||||||
|
* @return PARSE_SUCCESS, PARSE_ERROR or PARSE_INSUFFICIENT
|
||||||
|
*/
|
||||||
|
static inline ParseRC
|
||||||
|
parse_length (ParseState *state, size_t *len)
|
||||||
|
{
|
||||||
|
ParseRC ret = PARSE_ERROR;
|
||||||
|
*len = 0;
|
||||||
|
|
||||||
|
if (psyc_is_numeric(state->buffer.data[state->cursor])) {
|
||||||
|
ret = PARSE_SUCCESS;
|
||||||
|
do {
|
||||||
|
*len = 10 * *len + state->buffer.data[state->cursor] - '0';
|
||||||
|
ADVANCE_CURSOR_OR_RETURN(PARSE_INSUFFICIENT);
|
||||||
|
} while (psyc_is_numeric(state->buffer.data[state->cursor]));
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parse binary data.
|
* Parse binary data.
|
||||||
*
|
*
|
||||||
|
@ -50,13 +84,12 @@ parse_keyword (PsycParseState *state, PsycString *name)
|
||||||
* @param length Expected length of the data.
|
* @param length Expected length of the data.
|
||||||
* @param parsed Number of bytes parsed so far.
|
* @param parsed Number of bytes parsed so far.
|
||||||
*
|
*
|
||||||
* @return PARSE_COMPLETE or PARSE_INCOMPLETE
|
* @return PARSE_SUCCESS or PARSE_INCOMPLETE
|
||||||
*/
|
*/
|
||||||
static inline ParseRC
|
static inline ParseRC
|
||||||
psyc_parse_binary_value (PsycParseState *state, PsycString *value,
|
parse_binary (ParseState *state, size_t length, PsycString *value, size_t *parsed)
|
||||||
size_t *length, size_t *parsed)
|
|
||||||
{
|
{
|
||||||
size_t remaining = *length - *parsed;
|
size_t remaining = length - *parsed;
|
||||||
value->data = state->buffer.data + state->cursor;
|
value->data = state->buffer.data + state->cursor;
|
||||||
|
|
||||||
if (state->cursor + remaining > state->buffer.length) {
|
if (state->cursor + remaining > state->buffer.length) {
|
||||||
|
@ -70,9 +103,32 @@ psyc_parse_binary_value (PsycParseState *state, PsycString *value,
|
||||||
value->length = remaining;
|
value->length = remaining;
|
||||||
state->cursor += remaining;
|
state->cursor += remaining;
|
||||||
*parsed += remaining;
|
*parsed += remaining;
|
||||||
assert(*parsed == *length);
|
ASSERT(*parsed == length);
|
||||||
|
|
||||||
return PARSE_COMPLETE;
|
return PARSE_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse data until a given character is found.
|
||||||
|
*
|
||||||
|
* @param state Parser state.
|
||||||
|
* @param value Start & length of parsed data is saved here.
|
||||||
|
* @param end Parse until this character is found.
|
||||||
|
* @param parsed Number of bytes parsed so far.
|
||||||
|
*
|
||||||
|
* @return PARSE_SUCCESS or PARSE_INSUFFICIENT
|
||||||
|
*/
|
||||||
|
static inline ParseRC
|
||||||
|
parse_until (ParseState *state, const char end, PsycString *value)
|
||||||
|
{
|
||||||
|
value->data = state->buffer.data + state->cursor;
|
||||||
|
|
||||||
|
while (state->buffer.data[state->cursor] != end) {
|
||||||
|
value->length++;
|
||||||
|
ADVANCE_CURSOR_OR_RETURN(PARSE_INSUFFICIENT);
|
||||||
|
}
|
||||||
|
|
||||||
|
return PARSE_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -86,7 +142,7 @@ psyc_parse_modifier (PsycParseState *state, char *oper,
|
||||||
*oper = *(state->buffer.data + state->cursor);
|
*oper = *(state->buffer.data + state->cursor);
|
||||||
ADVANCE_CURSOR_OR_RETURN(PSYC_PARSE_INSUFFICIENT);
|
ADVANCE_CURSOR_OR_RETURN(PSYC_PARSE_INSUFFICIENT);
|
||||||
|
|
||||||
ParseRC ret = parse_keyword(state, name);
|
ParseRC ret = parse_keyword((ParseState*)state, name);
|
||||||
if (ret == PARSE_ERROR)
|
if (ret == PARSE_ERROR)
|
||||||
return PSYC_PARSE_ERROR_MOD_NAME;
|
return PSYC_PARSE_ERROR_MOD_NAME;
|
||||||
else if (ret != PARSE_SUCCESS)
|
else if (ret != PARSE_SUCCESS)
|
||||||
|
@ -123,9 +179,7 @@ psyc_parse_modifier (PsycParseState *state, char *oper,
|
||||||
if (++(state->cursor) >= state->buffer.length)
|
if (++(state->cursor) >= state->buffer.length)
|
||||||
return length ? PARSE_INCOMPLETE : PARSE_SUCCESS; // if length=0 we're done
|
return length ? PARSE_INCOMPLETE : PARSE_SUCCESS; // if length=0 we're done
|
||||||
|
|
||||||
ret =
|
ret = parse_binary((ParseState*)state, state->valuelen, value, &state->value_parsed);
|
||||||
psyc_parse_binary_value(state, value, &(state->valuelen),
|
|
||||||
&(state->value_parsed));
|
|
||||||
if (ret == PARSE_INCOMPLETE)
|
if (ret == PARSE_INCOMPLETE)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
@ -244,8 +298,8 @@ psyc_parse (PsycParseState *state, char *oper,
|
||||||
case PSYC_PART_CONTENT:
|
case PSYC_PART_CONTENT:
|
||||||
// In case of an incomplete binary variable resume parsing it.
|
// In case of an incomplete binary variable resume parsing it.
|
||||||
if (state->value_parsed < state->valuelen) {
|
if (state->value_parsed < state->valuelen) {
|
||||||
ret = psyc_parse_binary_value(state, value, &(state->valuelen),
|
ret = parse_binary((ParseState*)state, state->valuelen, value,
|
||||||
&(state->value_parsed));
|
&state->value_parsed);
|
||||||
state->content_parsed += value->length;
|
state->content_parsed += value->length;
|
||||||
|
|
||||||
if (ret == PARSE_INCOMPLETE)
|
if (ret == PARSE_INCOMPLETE)
|
||||||
|
@ -303,7 +357,7 @@ psyc_parse (PsycParseState *state, char *oper,
|
||||||
|
|
||||||
case PSYC_PART_METHOD:
|
case PSYC_PART_METHOD:
|
||||||
pos = state->cursor;
|
pos = state->cursor;
|
||||||
ret = parse_keyword(state, name);
|
ret = parse_keyword((ParseState*)state, name);
|
||||||
|
|
||||||
if (ret == PARSE_INSUFFICIENT)
|
if (ret == PARSE_INSUFFICIENT)
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -345,8 +399,8 @@ psyc_parse (PsycParseState *state, char *oper,
|
||||||
state->valuelen--; // \n at the end is not part of data
|
state->valuelen--; // \n at the end is not part of data
|
||||||
}
|
}
|
||||||
if (state->value_parsed < state->valuelen) {
|
if (state->value_parsed < state->valuelen) {
|
||||||
ret = psyc_parse_binary_value(state, value, &(state->valuelen),
|
ret = parse_binary((ParseState*)state, state->valuelen, value,
|
||||||
&(state->value_parsed));
|
&state->value_parsed);
|
||||||
state->content_parsed += value->length;
|
state->content_parsed += value->length;
|
||||||
|
|
||||||
if (ret == PARSE_INCOMPLETE)
|
if (ret == PARSE_INCOMPLETE)
|
||||||
|
@ -422,191 +476,653 @@ psyc_parse (PsycParseState *state, char *oper,
|
||||||
return PSYC_PARSE_ERROR; // should not be reached
|
return PSYC_PARSE_ERROR; // should not be reached
|
||||||
}
|
}
|
||||||
|
|
||||||
/** List parser. */
|
/**
|
||||||
|
* Parse list.
|
||||||
|
*
|
||||||
|
* list = [ default-type ] *list-elem
|
||||||
|
* list-elem = "|" ( type [ SP list-value ] / [ length ] [ ":" type ] [ SP *OCTET ] )
|
||||||
|
* list-value = %x00-7B / %x7D-FF ; any byte except "|"
|
||||||
|
*/
|
||||||
#ifdef __INLINE_PSYC_PARSE
|
#ifdef __INLINE_PSYC_PARSE
|
||||||
static inline
|
static inline
|
||||||
#endif
|
#endif
|
||||||
PsycParseListRC
|
PsycParseListRC
|
||||||
psyc_parse_list (PsycParseListState *state, PsycString *elem)
|
psyc_parse_list (PsycParseListState *state, PsycString *type, PsycString *elem)
|
||||||
{
|
{
|
||||||
if (state->cursor >= state->buffer.length)
|
ParseRC ret;
|
||||||
return PSYC_PARSE_LIST_INCOMPLETE;
|
|
||||||
|
|
||||||
state->startc = state->cursor;
|
|
||||||
|
|
||||||
if (!state->type) { // If type is not set we're at the start.
|
|
||||||
// First character is either | for text lists, or a number for binary lists
|
|
||||||
if (state->buffer.data[state->cursor] == '|') {
|
|
||||||
state->type = PSYC_LIST_TEXT;
|
|
||||||
state->cursor++;
|
|
||||||
} else if (psyc_is_numeric(state->buffer.data[state->cursor]))
|
|
||||||
state->type = PSYC_LIST_BINARY;
|
|
||||||
else
|
|
||||||
return PSYC_PARSE_LIST_ERROR_TYPE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (state->type == PSYC_LIST_TEXT) {
|
|
||||||
elem->data = state->buffer.data + state->cursor;
|
|
||||||
elem->length = 0;
|
|
||||||
|
|
||||||
if (state->cursor >= state->buffer.length)
|
if (state->cursor >= state->buffer.length)
|
||||||
return PSYC_PARSE_LIST_END;
|
return PSYC_PARSE_LIST_END;
|
||||||
|
|
||||||
if (state->term_set) {
|
|
||||||
while (state->buffer.data[state->cursor] != '|') {
|
|
||||||
elem->length++;
|
|
||||||
if (state->buffer.data[state->cursor] == state->term)
|
|
||||||
return PSYC_PARSE_LIST_END;
|
|
||||||
if (++(state->cursor) >= state->buffer.length)
|
|
||||||
return PSYC_PARSE_LIST_END;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
while (state->buffer.data[state->cursor] != '|') {
|
|
||||||
elem->length++;
|
|
||||||
if (++(state->cursor) >= state->buffer.length)
|
|
||||||
return PSYC_PARSE_LIST_END;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
state->cursor++;
|
|
||||||
return PSYC_PARSE_LIST_ELEM;
|
|
||||||
} else { // binary list
|
|
||||||
if (!(state->elem_parsed < state->elemlen)) {
|
|
||||||
// Element starts with a number.
|
|
||||||
if (psyc_is_numeric(state->buffer.data[state->cursor])) {
|
|
||||||
do {
|
|
||||||
state->elemlen =
|
|
||||||
10 * state->elemlen +
|
|
||||||
state->buffer.data[state->cursor] - '0';
|
|
||||||
ADVANCE_CURSOR_OR_RETURN(PSYC_PARSE_LIST_INCOMPLETE);
|
|
||||||
} while (psyc_is_numeric(state->buffer.data[state->cursor]));
|
|
||||||
} else
|
|
||||||
return PSYC_PARSE_LIST_ERROR_LEN;
|
|
||||||
|
|
||||||
if (state->buffer.data[state->cursor] != ' ')
|
|
||||||
return PSYC_PARSE_LIST_ERROR_LEN;
|
|
||||||
|
|
||||||
state->cursor++;
|
|
||||||
elem->data = state->buffer.data + state->cursor;
|
|
||||||
elem->length = 0;
|
|
||||||
state->elem_parsed = 0;
|
|
||||||
}
|
|
||||||
// Start or resume parsing the binary data
|
|
||||||
if (state->elem_parsed < state->elemlen) {
|
|
||||||
if (PARSE_INCOMPLETE == psyc_parse_binary_value((PsycParseState*)state,
|
|
||||||
elem, &state->elemlen,
|
|
||||||
&state->elem_parsed))
|
|
||||||
return PSYC_PARSE_LIST_INCOMPLETE;
|
|
||||||
|
|
||||||
state->elemlen = 0;
|
|
||||||
|
|
||||||
if (state->cursor >= state->buffer.length)
|
|
||||||
return PSYC_PARSE_LIST_END;
|
|
||||||
|
|
||||||
if (state->buffer.data[state->cursor] != '|')
|
|
||||||
return PSYC_PARSE_LIST_ERROR_DELIM;
|
|
||||||
|
|
||||||
state->cursor++;
|
|
||||||
return PSYC_PARSE_LIST_ELEM;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return PSYC_PARSE_LIST_ERROR; // should not be reached
|
|
||||||
}
|
|
||||||
|
|
||||||
PsycParseTableRC
|
|
||||||
psyc_parse_table (PsycParseTableState *state, PsycString *elem)
|
|
||||||
{
|
|
||||||
if (state->cursor >= state->buffer.length)
|
|
||||||
return PSYC_PARSE_TABLE_INCOMPLETE;
|
|
||||||
|
|
||||||
state->startc = state->cursor;
|
state->startc = state->cursor;
|
||||||
|
|
||||||
switch (state->part) {
|
switch (state->part) {
|
||||||
case PSYC_TABLE_PART_START:
|
case PSYC_LIST_PART_START:
|
||||||
if (state->buffer.data[state->cursor] != '*') {
|
type->length = elem->length = 0;
|
||||||
state->part = PSYC_TABLE_PART_BODY_START;
|
type->data = elem->data = NULL;
|
||||||
goto PSYC_TABLE_PART_BODY_START;
|
|
||||||
} else {
|
state->part = PSYC_LIST_PART_TYPE;
|
||||||
state->part = PSYC_TABLE_PART_WIDTH;
|
// fall thru
|
||||||
ADVANCE_CURSOR_OR_RETURN(PSYC_PARSE_TABLE_INCOMPLETE);
|
|
||||||
|
case PSYC_LIST_PART_TYPE:
|
||||||
|
switch (parse_keyword((ParseState*)state, type)) {
|
||||||
|
case PARSE_SUCCESS: // end of keyword
|
||||||
|
state->part = PSYC_LIST_PART_ELEM_START;
|
||||||
|
return PSYC_PARSE_LIST_TYPE;
|
||||||
|
case PARSE_INSUFFICIENT: // end of buffer
|
||||||
|
return PSYC_PARSE_LIST_END;
|
||||||
|
case PARSE_ERROR: // no keyword
|
||||||
|
state->part = PSYC_LIST_PART_ELEM_START;
|
||||||
|
break;
|
||||||
|
default: // should not be reached
|
||||||
|
return PSYC_PARSE_LIST_ERROR;
|
||||||
}
|
}
|
||||||
// fall thru
|
// fall thru
|
||||||
|
|
||||||
case PSYC_TABLE_PART_WIDTH:
|
case PSYC_LIST_PART_ELEM_START:
|
||||||
if (psyc_is_numeric(state->buffer.data[state->cursor])) {
|
if (state->buffer.data[state->cursor] != '|')
|
||||||
do {
|
return PSYC_PARSE_LIST_ERROR_ELEM_START;
|
||||||
state->width =
|
|
||||||
10 * state->width + state->buffer.data[state->cursor] - '0';
|
type->length = elem->length = 0;
|
||||||
ADVANCE_CURSOR_OR_RETURN(PSYC_PARSE_TABLE_INCOMPLETE);
|
type->data = elem->data = NULL;
|
||||||
} while (psyc_is_numeric(state->buffer.data[state->cursor]));
|
|
||||||
} else
|
state->elem_parsed = 0;
|
||||||
return PSYC_PARSE_TABLE_ERROR_WIDTH;
|
state->elemlen_found = 0;
|
||||||
|
|
||||||
|
state->part = PSYC_LIST_PART_ELEM_LENGTH;
|
||||||
|
ADVANCE_STARTC_OR_RETURN(PSYC_PARSE_LIST_ELEM_LAST);
|
||||||
|
// fall thru
|
||||||
|
|
||||||
|
case PSYC_LIST_PART_ELEM_TYPE:
|
||||||
|
if (state->buffer.data[state->cursor] == '=') {
|
||||||
|
ADVANCE_CURSOR_OR_RETURN(PSYC_PARSE_INSUFFICIENT);
|
||||||
|
|
||||||
|
switch (parse_keyword((ParseState*)state, type)) {
|
||||||
|
case PARSE_SUCCESS:
|
||||||
|
switch (state->buffer.data[state->cursor]) {
|
||||||
|
case ':':
|
||||||
|
state->part = PSYC_LIST_PART_ELEM_LENGTH;
|
||||||
|
ADVANCE_STARTC_OR_RETURN(PSYC_PARSE_LIST_ELEM_LAST);
|
||||||
|
break;
|
||||||
|
case ' ':
|
||||||
|
state->part = PSYC_LIST_PART_ELEM;
|
||||||
|
ADVANCE_STARTC_OR_RETURN(PSYC_PARSE_LIST_ELEM_LAST);
|
||||||
|
goto PSYC_LIST_PART_ELEM;
|
||||||
|
case '|':
|
||||||
|
state->part = PSYC_LIST_PART_ELEM_START;
|
||||||
|
return PSYC_PARSE_LIST_ELEM;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return PSYC_PARSE_LIST_ERROR_ELEM_TYPE;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case PARSE_INSUFFICIENT: // end of buffer
|
||||||
|
return PSYC_PARSE_LIST_ELEM_LAST;
|
||||||
|
case PARSE_ERROR:
|
||||||
|
return PSYC_PARSE_LIST_ERROR_ELEM_TYPE;
|
||||||
|
default: // should not be reached
|
||||||
|
return PSYC_PARSE_LIST_ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// fall thru
|
||||||
|
|
||||||
|
case PSYC_LIST_PART_ELEM_LENGTH:
|
||||||
|
switch (parse_length((ParseState*)state, &state->elemlen)) {
|
||||||
|
case PARSE_SUCCESS: // length is complete
|
||||||
|
state->elemlen_found = 1;
|
||||||
|
state->elem_parsed = 0;
|
||||||
|
elem->length = state->elemlen;
|
||||||
|
elem->data = NULL;
|
||||||
|
break;
|
||||||
|
case PARSE_INSUFFICIENT: // length is incomplete
|
||||||
|
return PSYC_PARSE_LIST_INSUFFICIENT;
|
||||||
|
case PARSE_ERROR: // no length
|
||||||
|
break;
|
||||||
|
default: // should not be reached
|
||||||
|
return PSYC_PARSE_LIST_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
switch (state->buffer.data[state->cursor]) {
|
switch (state->buffer.data[state->cursor]) {
|
||||||
#ifdef PSYC_PARSE_TABLE_HEAD
|
|
||||||
case '|':
|
|
||||||
state->part = PSYC_TABLE_PART_HEAD_START;
|
|
||||||
break;
|
|
||||||
#endif
|
|
||||||
case ' ':
|
case ' ':
|
||||||
state->part = PSYC_TABLE_PART_BODY_START;
|
state->part = PSYC_LIST_PART_ELEM;
|
||||||
state->cursor++;
|
ADVANCE_STARTC_OR_RETURN(PSYC_PARSE_LIST_ELEM_LAST);
|
||||||
|
break;
|
||||||
|
case '|':
|
||||||
|
state->part = PSYC_LIST_PART_ELEM_START;
|
||||||
|
return PSYC_PARSE_LIST_ELEM;
|
||||||
|
default:
|
||||||
|
return PSYC_PARSE_LIST_ERROR_ELEM_LENGTH;
|
||||||
}
|
}
|
||||||
|
|
||||||
elem->length = state->width;
|
|
||||||
return PSYC_TABLE_PART_WIDTH;
|
|
||||||
#ifdef PSYC_PARSE_TABLE_HEAD
|
|
||||||
case PSYC_TABLE_PART_HEAD_START:
|
|
||||||
psyc_parse_list_buffer_set(&state->list, state->buffer.data + state->cursor,
|
|
||||||
state->buffer.length - state->cursor);
|
|
||||||
psyc_parse_list_term_set(&state->list, ' ');
|
|
||||||
state->part = PSYC_TABLE_PART_HEAD;
|
|
||||||
// fall thru
|
// fall thru
|
||||||
|
|
||||||
case PSYC_TABLE_PART_HEAD:
|
case PSYC_LIST_PART_ELEM:
|
||||||
switch (psyc_parse_list(&state->list, elem)) {
|
PSYC_LIST_PART_ELEM:
|
||||||
case PSYC_PARSE_LIST_ELEM:
|
if (state->elemlen_found) {
|
||||||
if (state->elems == 0) {
|
switch (parse_binary((ParseState*)state, state->elemlen, elem,
|
||||||
state->elems++;
|
&state->elem_parsed)) {
|
||||||
return PSYC_PARSE_TABLE_NAME_KEY;
|
case PARSE_SUCCESS:
|
||||||
} else if (state->elems < state->width) {
|
if (elem->length == state->elem_parsed)
|
||||||
state->elems++;
|
ret = PSYC_PARSE_LIST_ELEM;
|
||||||
return PSYC_PARSE_TABLE_NAME_VALUE;
|
else
|
||||||
} else // too many elements
|
ret = PSYC_PARSE_LIST_ELEM_END;
|
||||||
return PSYC_PARSE_TABLE_ERROR_HEAD;
|
break;
|
||||||
|
case PARSE_INCOMPLETE:
|
||||||
case PSYC_PARSE_LIST_END:
|
if (elem->length == state->elem_parsed)
|
||||||
if (state->elems != state->width)
|
ret = PSYC_PARSE_LIST_ELEM_START;
|
||||||
return PSYC_PARSE_TABLE_ERROR_HEAD;
|
else
|
||||||
|
ret = PSYC_PARSE_LIST_ELEM_CONT;
|
||||||
state->part = PSYC_TABLE_PART_BODY_START;
|
break;
|
||||||
state->cursor += state->list.cursor + 1;
|
default: // should not be reached
|
||||||
psyc_parse_list_state_init(&state->list);
|
return PSYC_PARSE_LIST_ERROR;
|
||||||
return state->elems++ == 0
|
|
||||||
? PSYC_PARSE_TABLE_NAME_KEY : PSYC_PARSE_TABLE_NAME_VALUE;
|
|
||||||
default:
|
|
||||||
return PSYC_PARSE_TABLE_ERROR_HEAD;
|
|
||||||
}
|
}
|
||||||
#endif
|
} else {
|
||||||
case PSYC_TABLE_PART_BODY_START:
|
switch (parse_until((ParseState*)state, '|', elem)) {
|
||||||
PSYC_TABLE_PART_BODY_START:
|
case PARSE_SUCCESS:
|
||||||
psyc_parse_list_buffer_set(&state->list, state->buffer.data + state->cursor,
|
ret = PSYC_PARSE_LIST_ELEM;
|
||||||
state->buffer.length - state->cursor);
|
break;
|
||||||
state->part = PSYC_TABLE_PART_BODY;
|
case PARSE_INSUFFICIENT:
|
||||||
// fall thru
|
return PSYC_PARSE_LIST_ELEM_LAST;
|
||||||
|
default: // should not be reached
|
||||||
case PSYC_TABLE_PART_BODY:
|
return PSYC_PARSE_LIST_ERROR;
|
||||||
switch (psyc_parse_list(&state->list, elem)) {
|
|
||||||
case PSYC_PARSE_LIST_ELEM:
|
|
||||||
return state->elems++ % (state->width + 1) == 0
|
|
||||||
? PSYC_PARSE_TABLE_KEY : PSYC_PARSE_TABLE_VALUE;
|
|
||||||
case PSYC_PARSE_LIST_END:
|
|
||||||
return state->elems++ % (state->width + 1) == 0
|
|
||||||
? PSYC_PARSE_TABLE_KEY_END : PSYC_PARSE_TABLE_VALUE_END;
|
|
||||||
default:
|
|
||||||
return PSYC_PARSE_TABLE_ERROR_BODY;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
state->part = PSYC_LIST_PART_ELEM_START;
|
||||||
|
state->startc = state->cursor;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
return PSYC_PARSE_LIST_ERROR; // should not be reached
|
return PSYC_PARSE_LIST_ERROR; // should not be reached
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse dictionary.
|
||||||
|
*
|
||||||
|
* dict = [ type ] *dict-item
|
||||||
|
* dict-item = "{" ( dict-key / length SP OCTET) "}"
|
||||||
|
* ( type [ SP dict-value ] / [ length ] [ ":" type ] [ SP *OCTET ] )
|
||||||
|
* dict-key = %x00-7C / %x7E-FF ; any byte except "{"
|
||||||
|
* dict-value = %x00-7A / %x7C-FF ; any byte except "}"
|
||||||
|
*/
|
||||||
|
PsycParseDictRC
|
||||||
|
psyc_parse_dict (PsycParseDictState *state, PsycString *type, PsycString *elem)
|
||||||
|
{
|
||||||
|
ParseRC ret;
|
||||||
|
|
||||||
|
if (state->cursor >= state->buffer.length)
|
||||||
|
return PSYC_PARSE_DICT_END;
|
||||||
|
|
||||||
|
state->startc = state->cursor;
|
||||||
|
|
||||||
|
switch (state->part) {
|
||||||
|
case PSYC_DICT_PART_START:
|
||||||
|
type->length = elem->length = 0;
|
||||||
|
type->data = elem->data = NULL;
|
||||||
|
|
||||||
|
state->part = PSYC_DICT_PART_TYPE;
|
||||||
|
// fall thru
|
||||||
|
|
||||||
|
case PSYC_DICT_PART_TYPE:
|
||||||
|
switch (parse_keyword((ParseState*)state, type)) {
|
||||||
|
case PARSE_SUCCESS: // end of keyword
|
||||||
|
state->part = PSYC_DICT_PART_KEY_START;
|
||||||
|
return PSYC_PARSE_DICT_TYPE;
|
||||||
|
case PARSE_INSUFFICIENT: // end of buffer
|
||||||
|
return PSYC_PARSE_DICT_END;
|
||||||
|
case PARSE_ERROR: // no keyword
|
||||||
|
state->part = PSYC_DICT_PART_KEY_START;
|
||||||
|
break;
|
||||||
|
default: // should not be reached
|
||||||
|
return PSYC_PARSE_DICT_ERROR;
|
||||||
|
}
|
||||||
|
// fall thru
|
||||||
|
|
||||||
|
case PSYC_DICT_PART_KEY_START:
|
||||||
|
if (state->buffer.data[state->cursor] != '{')
|
||||||
|
return PSYC_PARSE_DICT_ERROR_KEY_START;
|
||||||
|
|
||||||
|
type->length = elem->length = 0;
|
||||||
|
type->data = elem->data = NULL;
|
||||||
|
|
||||||
|
state->elem_parsed = 0;
|
||||||
|
state->elemlen_found = 0;
|
||||||
|
|
||||||
|
state->part = PSYC_DICT_PART_KEY_LENGTH;
|
||||||
|
ADVANCE_STARTC_OR_RETURN(PSYC_PARSE_DICT_INSUFFICIENT);
|
||||||
|
// fall thru
|
||||||
|
|
||||||
|
case PSYC_DICT_PART_KEY_LENGTH:
|
||||||
|
switch (parse_length((ParseState*)state, &state->elemlen)) {
|
||||||
|
case PARSE_SUCCESS: // length is complete
|
||||||
|
state->elemlen_found = 1;
|
||||||
|
state->elem_parsed = 0;
|
||||||
|
elem->length = state->elemlen;
|
||||||
|
elem->data = NULL;
|
||||||
|
|
||||||
|
if (state->buffer.data[state->cursor] != ' ')
|
||||||
|
return PSYC_PARSE_DICT_ERROR_KEY_LENGTH;
|
||||||
|
|
||||||
|
state->part = PSYC_DICT_PART_KEY;
|
||||||
|
ADVANCE_STARTC_OR_RETURN(PSYC_PARSE_INSUFFICIENT);
|
||||||
|
break;
|
||||||
|
case PARSE_INSUFFICIENT: // length is incomplete
|
||||||
|
return PSYC_PARSE_DICT_INSUFFICIENT;
|
||||||
|
case PARSE_ERROR: // no length
|
||||||
|
state->part = PSYC_DICT_PART_KEY;
|
||||||
|
break;
|
||||||
|
default: // should not be reached
|
||||||
|
return PSYC_PARSE_DICT_ERROR;
|
||||||
|
}
|
||||||
|
// fall thru
|
||||||
|
|
||||||
|
case PSYC_DICT_PART_KEY:
|
||||||
|
if (state->elemlen_found) {
|
||||||
|
switch (parse_binary((ParseState*)state, state->elemlen, elem,
|
||||||
|
&state->elem_parsed)) {
|
||||||
|
case PARSE_SUCCESS:
|
||||||
|
if (elem->length == state->elem_parsed)
|
||||||
|
ret = PSYC_PARSE_DICT_KEY;
|
||||||
|
else
|
||||||
|
ret = PSYC_PARSE_DICT_KEY_END;
|
||||||
|
break;
|
||||||
|
case PARSE_INCOMPLETE:
|
||||||
|
if (elem->length == state->elem_parsed)
|
||||||
|
ret = PSYC_PARSE_DICT_KEY_START;
|
||||||
|
else
|
||||||
|
ret = PSYC_PARSE_DICT_KEY_CONT;
|
||||||
|
break;
|
||||||
|
default: // should not be reached
|
||||||
|
return PSYC_PARSE_DICT_ERROR;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
switch (parse_until((ParseState*)state, '}', elem)) {
|
||||||
|
case PARSE_SUCCESS:
|
||||||
|
ret = PSYC_PARSE_DICT_KEY;
|
||||||
|
break;
|
||||||
|
case PARSE_INSUFFICIENT:
|
||||||
|
return PSYC_PARSE_DICT_INSUFFICIENT;
|
||||||
|
default: // should not be reached
|
||||||
|
return PSYC_PARSE_DICT_ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
state->part = PSYC_DICT_PART_VALUE_START;
|
||||||
|
state->startc = state->cursor;
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
case PSYC_DICT_PART_VALUE_START:
|
||||||
|
switch (state->buffer.data[state->cursor] != '}')
|
||||||
|
return PSYC_PARSE_DICT_ERROR_VALUE_START;
|
||||||
|
|
||||||
|
type->length = elem->length = 0;
|
||||||
|
type->data = elem->data = NULL;
|
||||||
|
|
||||||
|
state->elem_parsed = 0;
|
||||||
|
state->elemlen_found = 0;
|
||||||
|
|
||||||
|
state->part = PSYC_DICT_PART_VALUE_TYPE;
|
||||||
|
ADVANCE_STARTC_OR_RETURN(PSYC_PARSE_DICT_VALUE_LAST);
|
||||||
|
// fall thru
|
||||||
|
|
||||||
|
case PSYC_DICT_PART_VALUE_TYPE:
|
||||||
|
if (state->buffer.data[state->cursor] == '=') {
|
||||||
|
ADVANCE_CURSOR_OR_RETURN(PSYC_PARSE_INSUFFICIENT);
|
||||||
|
|
||||||
|
switch (parse_keyword((ParseState*)state, type)) {
|
||||||
|
case PARSE_SUCCESS:
|
||||||
|
switch (state->buffer.data[state->cursor]) {
|
||||||
|
case ':':
|
||||||
|
state->part = PSYC_DICT_PART_VALUE_LENGTH;
|
||||||
|
ADVANCE_STARTC_OR_RETURN(PSYC_PARSE_DICT_VALUE_LAST);
|
||||||
|
break;
|
||||||
|
case ' ':
|
||||||
|
state->part = PSYC_DICT_PART_VALUE;
|
||||||
|
ADVANCE_STARTC_OR_RETURN(PSYC_PARSE_DICT_VALUE_LAST);
|
||||||
|
goto PSYC_DICT_PART_VALUE;
|
||||||
|
case '{':
|
||||||
|
state->part = PSYC_DICT_PART_KEY_START;
|
||||||
|
return PSYC_PARSE_DICT_VALUE;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return PSYC_PARSE_DICT_ERROR_VALUE_TYPE;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case PARSE_INSUFFICIENT: // end of buffer
|
||||||
|
return PSYC_PARSE_DICT_VALUE_LAST;
|
||||||
|
case PARSE_ERROR:
|
||||||
|
return PSYC_PARSE_DICT_ERROR_VALUE_TYPE;
|
||||||
|
default: // should not be reached
|
||||||
|
return PSYC_PARSE_DICT_ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// fall thru
|
||||||
|
|
||||||
|
case PSYC_DICT_PART_VALUE_LENGTH:
|
||||||
|
switch (parse_length((ParseState*)state, &state->elemlen)) {
|
||||||
|
case PARSE_SUCCESS: // length is complete
|
||||||
|
state->elemlen_found = 1;
|
||||||
|
state->elem_parsed = 0;
|
||||||
|
elem->length = state->elemlen;
|
||||||
|
elem->data = NULL;
|
||||||
|
break;
|
||||||
|
case PARSE_INSUFFICIENT: // length is incomplete
|
||||||
|
return PSYC_PARSE_DICT_INSUFFICIENT;
|
||||||
|
case PARSE_ERROR: // no length
|
||||||
|
break;
|
||||||
|
default: // should not be reached
|
||||||
|
return PSYC_PARSE_DICT_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (state->buffer.data[state->cursor]) {
|
||||||
|
case ' ':
|
||||||
|
state->part = PSYC_DICT_PART_VALUE;
|
||||||
|
ADVANCE_STARTC_OR_RETURN(PSYC_PARSE_DICT_VALUE_LAST);
|
||||||
|
break;
|
||||||
|
case '{':
|
||||||
|
state->part = PSYC_DICT_PART_KEY_START;
|
||||||
|
return PSYC_PARSE_DICT_VALUE;
|
||||||
|
default:
|
||||||
|
return PSYC_PARSE_DICT_ERROR_VALUE_LENGTH;
|
||||||
|
}
|
||||||
|
// fall thru
|
||||||
|
|
||||||
|
case PSYC_DICT_PART_VALUE:
|
||||||
|
PSYC_DICT_PART_VALUE:
|
||||||
|
if (state->elemlen_found) {
|
||||||
|
switch (parse_binary((ParseState*)state, state->elemlen, elem,
|
||||||
|
&state->elem_parsed)) {
|
||||||
|
case PARSE_SUCCESS:
|
||||||
|
if (elem->length == state->elem_parsed)
|
||||||
|
ret = PSYC_PARSE_DICT_VALUE;
|
||||||
|
else
|
||||||
|
ret = PSYC_PARSE_DICT_VALUE_END;
|
||||||
|
break;
|
||||||
|
case PARSE_INCOMPLETE:
|
||||||
|
if (elem->length == state->elem_parsed)
|
||||||
|
ret = PSYC_PARSE_DICT_VALUE_START;
|
||||||
|
else
|
||||||
|
ret = PSYC_PARSE_DICT_VALUE_CONT;
|
||||||
|
break;
|
||||||
|
default: // should not be reached
|
||||||
|
return PSYC_PARSE_DICT_ERROR;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
switch (parse_until((ParseState*)state, '{', elem)) {
|
||||||
|
case PARSE_SUCCESS:
|
||||||
|
ret = PSYC_PARSE_DICT_VALUE;
|
||||||
|
break;
|
||||||
|
case PARSE_INSUFFICIENT:
|
||||||
|
return PSYC_PARSE_DICT_VALUE_LAST;
|
||||||
|
default: // should not be reached
|
||||||
|
return PSYC_PARSE_DICT_ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
state->part = PSYC_DICT_PART_KEY_START;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
return PSYC_PARSE_DICT_ERROR; // should not be reached
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef __INLINE_PSYC_PARSE
|
||||||
|
static inline
|
||||||
|
#endif
|
||||||
|
PsycParseIndexRC
|
||||||
|
psyc_parse_index (PsycParseIndexState *state, PsycString *idx)
|
||||||
|
{
|
||||||
|
ParseRC ret;
|
||||||
|
|
||||||
|
if (state->cursor >= state->buffer.length)
|
||||||
|
return PSYC_PARSE_INDEX_END;
|
||||||
|
|
||||||
|
state->startc = state->cursor;
|
||||||
|
|
||||||
|
switch (state->part) {
|
||||||
|
case PSYC_INDEX_PART_START:
|
||||||
|
case PSYC_INDEX_PART_TYPE:
|
||||||
|
idx->length = 0;
|
||||||
|
idx->data = NULL;
|
||||||
|
|
||||||
|
switch (state->buffer.data[state->cursor]) {
|
||||||
|
case '#':
|
||||||
|
state->part = PSYC_INDEX_PART_LIST;
|
||||||
|
ADVANCE_STARTC_OR_RETURN(PSYC_PARSE_INSUFFICIENT);
|
||||||
|
goto PSYC_INDEX_PART_LIST;
|
||||||
|
case '.':
|
||||||
|
state->part = PSYC_INDEX_PART_DICT;
|
||||||
|
ADVANCE_STARTC_OR_RETURN(PSYC_PARSE_INSUFFICIENT);
|
||||||
|
goto PSYC_INDEX_PART_STRUCT;
|
||||||
|
case '{':
|
||||||
|
state->part = PSYC_INDEX_PART_DICT;
|
||||||
|
ADVANCE_STARTC_OR_RETURN(PSYC_PARSE_INSUFFICIENT);
|
||||||
|
goto PSYC_INDEX_PART_DICT_LENGTH;
|
||||||
|
default:
|
||||||
|
return PSYC_PARSE_INDEX_ERROR_TYPE;
|
||||||
|
}
|
||||||
|
|
||||||
|
case PSYC_INDEX_PART_LIST:
|
||||||
|
PSYC_INDEX_PART_LIST:
|
||||||
|
switch (parse_length((ParseState*)state, &idx->length)) {
|
||||||
|
case PARSE_SUCCESS: // list index is complete
|
||||||
|
state->part = PSYC_INDEX_PART_TYPE;
|
||||||
|
return PSYC_PARSE_INDEX_LIST;
|
||||||
|
case PARSE_INSUFFICIENT: // list index at the end of buffer
|
||||||
|
return PSYC_PARSE_INDEX_LIST_LAST;
|
||||||
|
case PARSE_ERROR: // no index
|
||||||
|
return PSYC_PARSE_INDEX_ERROR_LIST;
|
||||||
|
default: // should not be reached
|
||||||
|
return PSYC_PARSE_INDEX_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
case PSYC_INDEX_PART_STRUCT:
|
||||||
|
PSYC_INDEX_PART_STRUCT:
|
||||||
|
switch (parse_keyword((ParseState*)state, idx)) {
|
||||||
|
case PARSE_SUCCESS: // end of keyword
|
||||||
|
state->part = PSYC_INDEX_PART_TYPE;
|
||||||
|
return PSYC_PARSE_INDEX_STRUCT;
|
||||||
|
case PARSE_INSUFFICIENT: // end of buffer
|
||||||
|
return PSYC_PARSE_INDEX_STRUCT_LAST;
|
||||||
|
case PARSE_ERROR: // no keyword
|
||||||
|
return PSYC_PARSE_INDEX_ERROR_STRUCT;
|
||||||
|
default: // should not be reached
|
||||||
|
return PSYC_PARSE_INDEX_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
case PSYC_INDEX_PART_DICT_LENGTH:
|
||||||
|
PSYC_INDEX_PART_DICT_LENGTH:
|
||||||
|
switch (parse_length((ParseState*)state, &state->elemlen)) {
|
||||||
|
case PARSE_SUCCESS: // length is complete
|
||||||
|
state->elemlen_found = 1;
|
||||||
|
state->elem_parsed = 0;
|
||||||
|
idx->length = state->elemlen;
|
||||||
|
idx->data = NULL;
|
||||||
|
|
||||||
|
if (state->buffer.data[state->cursor] != ' ')
|
||||||
|
return PSYC_PARSE_INDEX_ERROR_DICT_LENGTH;
|
||||||
|
|
||||||
|
state->part = PSYC_INDEX_PART_DICT;
|
||||||
|
ADVANCE_STARTC_OR_RETURN(PSYC_PARSE_INSUFFICIENT);
|
||||||
|
break;
|
||||||
|
case PARSE_INSUFFICIENT: // length is incomplete
|
||||||
|
return PSYC_PARSE_DICT_INSUFFICIENT;
|
||||||
|
case PARSE_ERROR: // no length
|
||||||
|
state->part = PSYC_INDEX_PART_DICT;
|
||||||
|
break;
|
||||||
|
default: // should not be reached
|
||||||
|
return PSYC_PARSE_INDEX_ERROR;
|
||||||
|
}
|
||||||
|
// fall thru
|
||||||
|
|
||||||
|
case PSYC_INDEX_PART_DICT:
|
||||||
|
if (state->elemlen_found) {
|
||||||
|
switch (parse_binary((ParseState*)state, state->elemlen, idx,
|
||||||
|
&state->elem_parsed)) {
|
||||||
|
case PARSE_SUCCESS:
|
||||||
|
if (idx->length == state->elem_parsed)
|
||||||
|
ret = PSYC_PARSE_INDEX_DICT;
|
||||||
|
else
|
||||||
|
ret = PSYC_PARSE_INDEX_DICT_END;
|
||||||
|
break;
|
||||||
|
case PARSE_INCOMPLETE:
|
||||||
|
if (idx->length == state->elem_parsed)
|
||||||
|
ret = PSYC_PARSE_INDEX_DICT_START;
|
||||||
|
else
|
||||||
|
ret = PSYC_PARSE_INDEX_DICT_CONT;
|
||||||
|
break;
|
||||||
|
default: // should not be reached
|
||||||
|
return PSYC_PARSE_INDEX_ERROR_DICT;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
switch (parse_until((ParseState*)state, '}', idx)) {
|
||||||
|
case PARSE_SUCCESS:
|
||||||
|
ret = PSYC_PARSE_INDEX_DICT;
|
||||||
|
break;
|
||||||
|
case PARSE_INSUFFICIENT:
|
||||||
|
return PSYC_PARSE_INDEX_INSUFFICIENT;
|
||||||
|
default: // should not be reached
|
||||||
|
return PSYC_PARSE_INDEX_ERROR_DICT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
state->part = PSYC_INDEX_PART_TYPE;
|
||||||
|
state->cursor++;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
return PSYC_PARSE_INDEX_ERROR; // should not be reached
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef __INLINE_PSYC_PARSE
|
||||||
|
static inline
|
||||||
|
#endif
|
||||||
|
PsycParseUpdateRC
|
||||||
|
psyc_parse_update (PsycParseUpdateState *state, char *oper, PsycString *value)
|
||||||
|
{
|
||||||
|
PsycParseIndexRC ret;
|
||||||
|
|
||||||
|
if (state->cursor >= state->buffer.length)
|
||||||
|
return PSYC_PARSE_UPDATE_END;
|
||||||
|
|
||||||
|
state->startc = state->cursor;
|
||||||
|
|
||||||
|
switch (state->part) {
|
||||||
|
case PSYC_UPDATE_PART_START:
|
||||||
|
value->length = 0;
|
||||||
|
value->data = NULL;
|
||||||
|
// fall thru
|
||||||
|
|
||||||
|
case PSYC_INDEX_PART_TYPE:
|
||||||
|
case PSYC_INDEX_PART_LIST:
|
||||||
|
case PSYC_INDEX_PART_STRUCT:
|
||||||
|
case PSYC_INDEX_PART_DICT_LENGTH:
|
||||||
|
case PSYC_INDEX_PART_DICT:
|
||||||
|
ret = psyc_parse_index((PsycParseIndexState*)state, value);
|
||||||
|
|
||||||
|
switch (ret) {
|
||||||
|
case PSYC_PARSE_INDEX_INSUFFICIENT:
|
||||||
|
case PSYC_PARSE_INDEX_LIST_LAST:
|
||||||
|
case PSYC_PARSE_INDEX_STRUCT_LAST:
|
||||||
|
case PSYC_PARSE_INDEX_END:
|
||||||
|
return PSYC_PARSE_UPDATE_INSUFFICIENT;
|
||||||
|
case PSYC_PARSE_INDEX_ERROR_TYPE:
|
||||||
|
if (state->buffer.data[state->cursor] != ' ')
|
||||||
|
return ret;
|
||||||
|
state->part = PSYC_PARSE_UPDATE_TYPE;
|
||||||
|
value->length = 0;
|
||||||
|
value->data = NULL;
|
||||||
|
ADVANCE_STARTC_OR_RETURN(PSYC_PARSE_UPDATE_INSUFFICIENT);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
case PSYC_UPDATE_PART_TYPE:
|
||||||
|
if (!psyc_is_oper(state->buffer.data[state->cursor]))
|
||||||
|
return PSYC_PARSE_UPDATE_ERROR_OPER;
|
||||||
|
|
||||||
|
*oper = state->buffer.data[state->cursor];
|
||||||
|
ADVANCE_CURSOR_OR_RETURN(PSYC_PARSE_UPDATE_END);
|
||||||
|
|
||||||
|
switch (parse_keyword((ParseState*)state, value)) {
|
||||||
|
case PARSE_SUCCESS: // end of keyword
|
||||||
|
case PARSE_ERROR: // no keyword
|
||||||
|
switch (state->buffer.data[state->cursor]) {
|
||||||
|
case ':':
|
||||||
|
state->part = PSYC_UPDATE_PART_LENGTH;
|
||||||
|
break;
|
||||||
|
case ' ':
|
||||||
|
state->part = PSYC_UPDATE_PART_VALUE;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return PSYC_PARSE_UPDATE_ERROR_TYPE;
|
||||||
|
}
|
||||||
|
|
||||||
|
state->cursor++;
|
||||||
|
return PSYC_PARSE_UPDATE_TYPE;
|
||||||
|
break;
|
||||||
|
case PARSE_INSUFFICIENT: // end of buffer
|
||||||
|
return PSYC_PARSE_UPDATE_TYPE_END;
|
||||||
|
default: // should not be reached
|
||||||
|
return PSYC_PARSE_UPDATE_ERROR;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PSYC_UPDATE_PART_LENGTH:
|
||||||
|
switch (parse_length((ParseState*)state, &state->elemlen)) {
|
||||||
|
case PARSE_SUCCESS: // length is complete
|
||||||
|
state->elemlen_found = 1;
|
||||||
|
state->elem_parsed = 0;
|
||||||
|
value->length = state->elemlen;
|
||||||
|
value->data = NULL;
|
||||||
|
|
||||||
|
if (state->buffer.data[state->cursor] != ' ')
|
||||||
|
return PSYC_PARSE_UPDATE_ERROR_LENGTH;
|
||||||
|
|
||||||
|
state->part = PSYC_UPDATE_PART_VALUE;
|
||||||
|
if (value->length == 0)
|
||||||
|
return PSYC_PARSE_UPDATE_END;
|
||||||
|
ADVANCE_STARTC_OR_RETURN(PSYC_PARSE_UPDATE_INSUFFICIENT);
|
||||||
|
break;
|
||||||
|
case PARSE_INSUFFICIENT: // length is incomplete
|
||||||
|
if (value->length == 0)
|
||||||
|
return PSYC_PARSE_UPDATE_END;
|
||||||
|
return PSYC_PARSE_UPDATE_INSUFFICIENT;
|
||||||
|
case PARSE_ERROR: // no length after :
|
||||||
|
return PSYC_PARSE_UPDATE_ERROR_LENGTH;
|
||||||
|
default: // should not be reached
|
||||||
|
return PSYC_PARSE_UPDATE_ERROR;
|
||||||
|
}
|
||||||
|
// fall thru
|
||||||
|
|
||||||
|
case PSYC_UPDATE_PART_VALUE:
|
||||||
|
if (state->elemlen_found) {
|
||||||
|
switch (parse_binary((ParseState*)state, state->elemlen, value,
|
||||||
|
&state->elem_parsed)) {
|
||||||
|
case PARSE_SUCCESS:
|
||||||
|
if (value->length == state->elem_parsed)
|
||||||
|
ret = PSYC_PARSE_UPDATE_VALUE;
|
||||||
|
else
|
||||||
|
ret = PSYC_PARSE_UPDATE_VALUE_END;
|
||||||
|
break;
|
||||||
|
case PARSE_INCOMPLETE:
|
||||||
|
if (value->length == state->elem_parsed)
|
||||||
|
ret = PSYC_PARSE_UPDATE_VALUE_START;
|
||||||
|
else
|
||||||
|
ret = PSYC_PARSE_UPDATE_VALUE_CONT;
|
||||||
|
break;
|
||||||
|
default: // should not be reached
|
||||||
|
return PSYC_PARSE_UPDATE_ERROR_VALUE;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
value->data = state->buffer.data + state->cursor;
|
||||||
|
value->length = state->buffer.length - state->cursor;
|
||||||
|
ret = PSYC_PARSE_UPDATE_VALUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
state->part = PSYC_INDEX_PART_TYPE;
|
||||||
|
state->cursor++;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
return PSYC_PARSE_INDEX_ERROR; // should not be reached
|
||||||
|
}
|
||||||
|
|
190
src/render.c
190
src/render.c
|
@ -3,7 +3,59 @@
|
||||||
#include "lib.h"
|
#include "lib.h"
|
||||||
#include <psyc/packet.h>
|
#include <psyc/packet.h>
|
||||||
#include <psyc/render.h>
|
#include <psyc/render.h>
|
||||||
#include <psyc/syntax.h>
|
|
||||||
|
inline PsycRenderRC
|
||||||
|
psyc_render_elem (PsycElem *elem, char *buffer, size_t buflen)
|
||||||
|
{
|
||||||
|
size_t cur = 0;
|
||||||
|
|
||||||
|
if (elem->length > buflen) // return error if element doesn't fit in buffer
|
||||||
|
return PSYC_RENDER_ERROR;
|
||||||
|
|
||||||
|
if (elem->type.length) {
|
||||||
|
buffer[cur++] = '=';
|
||||||
|
memcpy(buffer + cur, PSYC_S2ARG(elem->type));
|
||||||
|
cur += elem->type.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (elem->value.length && !(elem->flag & PSYC_ELEM_NO_LENGTH)) {
|
||||||
|
if (elem->type.length)
|
||||||
|
buffer[cur++] = ':';
|
||||||
|
cur += itoa(elem->value.length, buffer + cur, 10);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (elem->value.length) {
|
||||||
|
buffer[cur++] = ' ';
|
||||||
|
memcpy(buffer + cur, PSYC_S2ARG(elem->value));
|
||||||
|
cur += elem->value.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Actual length should be equal to pre-calculated length at this point.
|
||||||
|
ASSERT(cur == elem->length);
|
||||||
|
return PSYC_RENDER_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline PsycRenderRC
|
||||||
|
psyc_render_dict_key (PsycDictKey *elem, char *buffer, size_t buflen)
|
||||||
|
{
|
||||||
|
size_t cur = 0;
|
||||||
|
|
||||||
|
if (elem->length > buflen) // return error if element doesn't fit in buffer
|
||||||
|
return PSYC_RENDER_ERROR;
|
||||||
|
|
||||||
|
if (elem->value.length && !(elem->flag & PSYC_ELEM_NO_LENGTH))
|
||||||
|
cur += itoa(elem->value.length, buffer + cur, 10);
|
||||||
|
|
||||||
|
if (elem->value.length) {
|
||||||
|
buffer[cur++] = ' ';
|
||||||
|
memcpy(buffer + cur, PSYC_S2ARG(elem->value));
|
||||||
|
cur += elem->value.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Actual length should be equal to pre-calculated length at this point.
|
||||||
|
ASSERT(cur == elem->length);
|
||||||
|
return PSYC_RENDER_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef __INLINE_PSYC_RENDER
|
#ifdef __INLINE_PSYC_RENDER
|
||||||
static inline
|
static inline
|
||||||
|
@ -12,51 +64,55 @@ PsycRenderRC
|
||||||
psyc_render_list (PsycList *list, char *buffer, size_t buflen)
|
psyc_render_list (PsycList *list, char *buffer, size_t buflen)
|
||||||
{
|
{
|
||||||
size_t i, cur = 0;
|
size_t i, cur = 0;
|
||||||
PsycString *elem;
|
|
||||||
|
|
||||||
if (list->length > buflen) // return error if list doesn't fit in buffer
|
if (list->length > buflen) // return error if list doesn't fit in buffer
|
||||||
return PSYC_RENDER_ERROR;
|
return PSYC_RENDER_ERROR;
|
||||||
|
|
||||||
if (list->flag == PSYC_LIST_NEED_LENGTH) {
|
if (list->type.length) {
|
||||||
for (i = 0; i < list->num_elems; i++) {
|
memcpy(buffer + cur, PSYC_S2ARG(list->type));
|
||||||
elem = &list->elems[i];
|
cur += list->type.length;
|
||||||
if (i > 0)
|
}
|
||||||
buffer[cur++] = '|';
|
|
||||||
cur += itoa(elem->length, buffer + cur, 10);
|
for (i = 0; i < list->num_elems; i++) {
|
||||||
buffer[cur++] = ' ';
|
buffer[cur++] = '|';
|
||||||
memcpy(buffer + cur, elem->data, elem->length);
|
psyc_render_elem(&list->elems[i], buffer + cur, buflen - cur);
|
||||||
cur += elem->length;
|
cur += list->elems[i].length;
|
||||||
}
|
|
||||||
} else {
|
|
||||||
for (i = 0; i < list->num_elems; i++) {
|
|
||||||
elem = &list->elems[i];
|
|
||||||
buffer[cur++] = '|';
|
|
||||||
memcpy(buffer + cur, elem->data, elem->length);
|
|
||||||
cur += elem->length;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef DEBUG
|
|
||||||
// Actual length should be equal to pre-calculated length at this point.
|
// Actual length should be equal to pre-calculated length at this point.
|
||||||
assert(cur == list->length);
|
ASSERT(cur == list->length);
|
||||||
#endif
|
|
||||||
return PSYC_RENDER_SUCCESS;
|
return PSYC_RENDER_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef __INLINE_PSYC_RENDER
|
||||||
|
static inline
|
||||||
|
#endif
|
||||||
PsycRenderRC
|
PsycRenderRC
|
||||||
psyc_render_table (PsycTable *table, char *buffer, size_t buflen)
|
psyc_render_dict (PsycDict *dict, char *buffer, size_t buflen)
|
||||||
{
|
{
|
||||||
size_t cur = 0;
|
size_t i, cur = 0;
|
||||||
|
|
||||||
if (table->length > buflen) // return error if table doesn't fit in buffer
|
if (dict->length > buflen) // return error if dict doesn't fit in buffer
|
||||||
return PSYC_RENDER_ERROR;
|
return PSYC_RENDER_ERROR;
|
||||||
|
|
||||||
if (table->width > 0) {
|
if (dict->type.length) {
|
||||||
cur = sprintf(buffer, "*%ld", table->width);
|
memcpy(buffer + cur, PSYC_S2ARG(dict->type));
|
||||||
buffer[cur++] = ' ';
|
cur += dict->type.length;
|
||||||
}
|
}
|
||||||
|
|
||||||
return psyc_render_list(table->list, buffer + cur, buflen - cur);
|
for (i = 0; i < dict->num_elems; i++) {
|
||||||
|
buffer[cur++] = '{';
|
||||||
|
psyc_render_dict_key(&dict->elems[i].key, buffer + cur, buflen - cur);
|
||||||
|
cur += dict->elems[i].key.length;
|
||||||
|
|
||||||
|
buffer[cur++] = '}';
|
||||||
|
psyc_render_elem(&dict->elems[i].value, buffer + cur, buflen - cur);
|
||||||
|
cur += dict->elems[i].value.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Actual length should be equal to pre-calculated length at this point.
|
||||||
|
ASSERT(cur == dict->length);
|
||||||
|
return PSYC_RENDER_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline size_t
|
static inline size_t
|
||||||
|
@ -70,7 +126,9 @@ psyc_render_modifier (PsycModifier *mod, char *buffer)
|
||||||
if (cur == 1)
|
if (cur == 1)
|
||||||
return cur; // error, name can't be empty
|
return cur; // error, name can't be empty
|
||||||
|
|
||||||
if (mod->flag == PSYC_MODIFIER_NEED_LENGTH) {
|
if (mod->value.length
|
||||||
|
&& (mod->flag & PSYC_MODIFIER_NEED_LENGTH
|
||||||
|
|| mod->flag == PSYC_MODIFIER_CHECK_LENGTH)) {
|
||||||
buffer[cur++] = ' ';
|
buffer[cur++] = ' ';
|
||||||
cur += itoa(mod->value.length, buffer + cur, 10);
|
cur += itoa(mod->value.length, buffer + cur, 10);
|
||||||
}
|
}
|
||||||
|
@ -87,54 +145,52 @@ psyc_render_modifier (PsycModifier *mod, char *buffer)
|
||||||
static inline
|
static inline
|
||||||
#endif
|
#endif
|
||||||
PsycRenderRC
|
PsycRenderRC
|
||||||
psyc_render (PsycPacket *packet, char *buffer, size_t buflen)
|
psyc_render (PsycPacket *p, char *buffer, size_t buflen)
|
||||||
{
|
{
|
||||||
size_t i, cur = 0, len;
|
size_t i, cur = 0, len;
|
||||||
|
|
||||||
if (packet->length > buflen) // return error if packet doesn't fit in buffer
|
if (p->length > buflen) // return error if packet doesn't fit in buffer
|
||||||
return PSYC_RENDER_ERROR;
|
return PSYC_RENDER_ERROR;
|
||||||
|
|
||||||
// render routing modifiers
|
// render routing modifiers
|
||||||
for (i = 0; i < packet->routing.lines; i++) {
|
for (i = 0; i < p->routing.lines; i++) {
|
||||||
len = psyc_render_modifier(&packet->routing.modifiers[i], buffer + cur);
|
len = psyc_render_modifier(&p->routing.modifiers[i], buffer + cur);
|
||||||
cur += len;
|
cur += len;
|
||||||
if (len <= 1)
|
if (len <= 1)
|
||||||
return PSYC_RENDER_ERROR_MODIFIER_NAME_MISSING;
|
return PSYC_RENDER_ERROR_MODIFIER_NAME_MISSING;
|
||||||
}
|
}
|
||||||
|
|
||||||
// add length if needed
|
// add length if needed
|
||||||
if (packet->flag == PSYC_PACKET_NEED_LENGTH)
|
if (p->contentlen && !(p->flag & PSYC_PACKET_NO_LENGTH))
|
||||||
cur += itoa(packet->contentlen, buffer + cur, 10);
|
cur += itoa(p->contentlen, buffer + cur, 10);
|
||||||
|
|
||||||
if (packet->flag == PSYC_PACKET_NEED_LENGTH || packet->content.length
|
if (p->contentlen)
|
||||||
|| packet->stateop || packet->entity.lines
|
|
||||||
|| packet->method.length || packet->data.length)
|
|
||||||
buffer[cur++] = '\n'; // start of content part if there's content or length
|
buffer[cur++] = '\n'; // start of content part if there's content or length
|
||||||
|
|
||||||
if (packet->content.length) { // render raw content if present
|
if (p->content.length) { // render raw content if present
|
||||||
memcpy(buffer + cur, packet->content.data, packet->content.length);
|
memcpy(buffer + cur, p->content.data, p->content.length);
|
||||||
cur += packet->content.length;
|
cur += p->content.length;
|
||||||
} else {
|
} else {
|
||||||
if (packet->stateop) {
|
if (p->stateop) {
|
||||||
buffer[cur++] = packet->stateop;
|
buffer[cur++] = p->stateop;
|
||||||
buffer[cur++] = '\n';
|
buffer[cur++] = '\n';
|
||||||
}
|
}
|
||||||
// render entity modifiers
|
// render entity modifiers
|
||||||
for (i = 0; i < packet->entity.lines; i++)
|
for (i = 0; i < p->entity.lines; i++)
|
||||||
cur += psyc_render_modifier(&packet->entity.modifiers[i],
|
cur += psyc_render_modifier(&p->entity.modifiers[i],
|
||||||
buffer + cur);
|
buffer + cur);
|
||||||
|
|
||||||
if (packet->method.length) { // add method\n
|
if (p->method.length) { // add method\n
|
||||||
memcpy(buffer + cur, packet->method.data, packet->method.length);
|
memcpy(buffer + cur, p->method.data, p->method.length);
|
||||||
cur += packet->method.length;
|
cur += p->method.length;
|
||||||
buffer[cur++] = '\n';
|
buffer[cur++] = '\n';
|
||||||
|
|
||||||
if (packet->data.length) { // add data\n
|
if (p->data.length) { // add data\n
|
||||||
memcpy(buffer + cur, packet->data.data, packet->data.length);
|
memcpy(buffer + cur, p->data.data, p->data.length);
|
||||||
cur += packet->data.length;
|
cur += p->data.length;
|
||||||
buffer[cur++] = '\n';
|
buffer[cur++] = '\n';
|
||||||
}
|
}
|
||||||
} else if (packet->data.length) // error, we have data but no modifier
|
} else if (p->data.length) // error, we have data but no modifier
|
||||||
return PSYC_RENDER_ERROR_METHOD_MISSING;
|
return PSYC_RENDER_ERROR_METHOD_MISSING;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -143,32 +199,6 @@ psyc_render (PsycPacket *packet, char *buffer, size_t buflen)
|
||||||
buffer[cur++] = '\n';
|
buffer[cur++] = '\n';
|
||||||
|
|
||||||
// actual length should be equal to pre-calculated length at this point
|
// actual length should be equal to pre-calculated length at this point
|
||||||
assert(cur == packet->length);
|
ASSERT(cur == p->length);
|
||||||
return PSYC_RENDER_SUCCESS;
|
return PSYC_RENDER_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
PsycRenderRC
|
|
||||||
psyc_render_packet_id (char *context, size_t contextlen,
|
|
||||||
char *source, size_t sourcelen,
|
|
||||||
char *target, size_t targetlen,
|
|
||||||
char *counter, size_t counterlen,
|
|
||||||
char *fragment, size_t fragmentlen,
|
|
||||||
char *buffer, size_t buflen)
|
|
||||||
{
|
|
||||||
PsycList list;
|
|
||||||
PsycString elems[PSYC_PACKET_ID_ELEMS] = {};
|
|
||||||
|
|
||||||
if (contextlen)
|
|
||||||
elems[PSYC_PACKET_ID_CONTEXT] = PSYC_STRING(context, contextlen);
|
|
||||||
if (sourcelen)
|
|
||||||
elems[PSYC_PACKET_ID_SOURCE] = PSYC_STRING(source, sourcelen);
|
|
||||||
if (targetlen)
|
|
||||||
elems[PSYC_PACKET_ID_TARGET] = PSYC_STRING(target, targetlen);
|
|
||||||
if (counterlen)
|
|
||||||
elems[PSYC_PACKET_ID_COUNTER] = PSYC_STRING(counter, counterlen);
|
|
||||||
if (fragmentlen)
|
|
||||||
elems[PSYC_PACKET_ID_FRAGMENT] = PSYC_STRING(fragment, fragmentlen);
|
|
||||||
|
|
||||||
psyc_list_init(&list, elems, PSYC_PACKET_ID_ELEMS, PSYC_LIST_NO_LENGTH);
|
|
||||||
return psyc_render_list(&list, buffer, buflen);
|
|
||||||
}
|
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
#include <psyc/packet.h>
|
#include <psyc/packet.h>
|
||||||
|
|
||||||
/// Routing variables in alphabetical order.
|
/// Routing variables in alphabetical order.
|
||||||
const PsycDictInt psyc_rvars[] = {
|
const PsycMapInt psyc_rvars[] = {
|
||||||
{ PSYC_C2STRI("_amount_fragments"), PSYC_RVAR_AMOUNT_FRAGMENTS },
|
{ PSYC_C2STRI("_amount_fragments"), PSYC_RVAR_AMOUNT_FRAGMENTS },
|
||||||
{ PSYC_C2STRI("_context"), PSYC_RVAR_CONTEXT },
|
{ PSYC_C2STRI("_context"), PSYC_RVAR_CONTEXT },
|
||||||
{ PSYC_C2STRI("_counter"), PSYC_RVAR_COUNTER },
|
{ PSYC_C2STRI("_counter"), PSYC_RVAR_COUNTER },
|
||||||
|
@ -30,26 +30,26 @@ const PsycDictInt psyc_rvars[] = {
|
||||||
const size_t psyc_rvars_num = PSYC_NUM_ELEM(psyc_rvars);
|
const size_t psyc_rvars_num = PSYC_NUM_ELEM(psyc_rvars);
|
||||||
|
|
||||||
// Variable types in alphabetical order.
|
// Variable types in alphabetical order.
|
||||||
const PsycDictInt psyc_var_types[] = {
|
const PsycMapInt psyc_var_types[] = {
|
||||||
{ PSYC_C2STRI("_amount"), PSYC_TYPE_AMOUNT },
|
{ PSYC_C2STRI("_amount"), PSYC_TYPE_AMOUNT },
|
||||||
{ PSYC_C2STRI("_color"), PSYC_TYPE_COLOR },
|
{ PSYC_C2STRI("_color"), PSYC_TYPE_COLOR },
|
||||||
{ PSYC_C2STRI("_date"), PSYC_TYPE_DATE },
|
{ PSYC_C2STRI("_date"), PSYC_TYPE_DATE },
|
||||||
{ PSYC_C2STRI("_def"), PSYC_TYPE_DEF },
|
|
||||||
{ PSYC_C2STRI("_degree"), PSYC_TYPE_DEGREE },
|
{ PSYC_C2STRI("_degree"), PSYC_TYPE_DEGREE },
|
||||||
|
{ PSYC_C2STRI("_dict"), PSYC_TYPE_DICT },
|
||||||
{ PSYC_C2STRI("_entity"), PSYC_TYPE_ENTITY },
|
{ PSYC_C2STRI("_entity"), PSYC_TYPE_ENTITY },
|
||||||
{ PSYC_C2STRI("_flag"), PSYC_TYPE_FLAG },
|
{ PSYC_C2STRI("_flag"), PSYC_TYPE_FLAG },
|
||||||
{ PSYC_C2STRI("_language"), PSYC_TYPE_LANGUAGE },
|
{ PSYC_C2STRI("_language"), PSYC_TYPE_LANGUAGE },
|
||||||
{ PSYC_C2STRI("_list"), PSYC_TYPE_LIST },
|
{ PSYC_C2STRI("_list"), PSYC_TYPE_LIST },
|
||||||
{ PSYC_C2STRI("_nick"), PSYC_TYPE_NICK },
|
{ PSYC_C2STRI("_nick"), PSYC_TYPE_NICK },
|
||||||
{ PSYC_C2STRI("_page"), PSYC_TYPE_PAGE },
|
{ PSYC_C2STRI("_page"), PSYC_TYPE_PAGE },
|
||||||
{ PSYC_C2STRI("_table"), PSYC_TYPE_TABLE },
|
{ PSYC_C2STRI("_struct"), PSYC_TYPE_STRUCT },
|
||||||
{ PSYC_C2STRI("_time"), PSYC_TYPE_TIME },
|
{ PSYC_C2STRI("_time"), PSYC_TYPE_TIME },
|
||||||
{ PSYC_C2STRI("_uniform"), PSYC_TYPE_UNIFORM },
|
{ PSYC_C2STRI("_uniform"), PSYC_TYPE_UNIFORM },
|
||||||
};
|
};
|
||||||
const size_t psyc_var_types_num = PSYC_NUM_ELEM(psyc_var_types);
|
const size_t psyc_var_types_num = PSYC_NUM_ELEM(psyc_var_types);
|
||||||
|
|
||||||
/// Method names in alphabetical order.
|
/// Method names in alphabetical order.
|
||||||
const PsycDictInt psyc_methods[] = {
|
const PsycMapInt psyc_methods[] = {
|
||||||
{ PSYC_C2STRI("_data"), PSYC_MC_DATA },
|
{ PSYC_C2STRI("_data"), PSYC_MC_DATA },
|
||||||
{ PSYC_C2STRI("_echo_context_enter"), PSYC_MC_ECHO_CONTEXT_ENTER },
|
{ PSYC_C2STRI("_echo_context_enter"), PSYC_MC_ECHO_CONTEXT_ENTER },
|
||||||
{ PSYC_C2STRI("_echo_context_leave"), PSYC_MC_ECHO_CONTEXT_LEAVE },
|
{ PSYC_C2STRI("_echo_context_leave"), PSYC_MC_ECHO_CONTEXT_LEAVE },
|
||||||
|
@ -88,7 +88,7 @@ const size_t psyc_methods_num = PSYC_NUM_ELEM(psyc_methods);
|
||||||
PsycMethod
|
PsycMethod
|
||||||
psyc_method (char *method, size_t methodlen, PsycMethod *family, unsigned int *flag)
|
psyc_method (char *method, size_t methodlen, PsycMethod *family, unsigned int *flag)
|
||||||
{
|
{
|
||||||
int mc = psyc_dict_lookup_int(psyc_methods, psyc_methods_num,
|
int mc = psyc_map_lookup_int(psyc_methods, psyc_methods_num,
|
||||||
method, methodlen, PSYC_YES);
|
method, methodlen, PSYC_YES);
|
||||||
|
|
||||||
switch (mc) {
|
switch (mc) {
|
||||||
|
|
|
@ -3,7 +3,7 @@ DEBUG = 2
|
||||||
CFLAGS = -I../include -I../src -Wall -std=c99 ${OPT}
|
CFLAGS = -I../include -I../src -Wall -std=c99 ${OPT}
|
||||||
LDFLAGS = -L../lib
|
LDFLAGS = -L../lib
|
||||||
LOADLIBES = -lpsyc -lm
|
LOADLIBES = -lpsyc -lm
|
||||||
TARGETS = test_psyc test_psyc_speed test_parser test_match test_render test_text var_routing var_type uniform_parse test_list test_table test_packet_id method
|
TARGETS = test_psyc test_psyc_speed test_parser test_match test_render test_text var_routing var_type uniform_parse test_packet_id test_index test_update method
|
||||||
O = test.o
|
O = test.o
|
||||||
WRAPPER =
|
WRAPPER =
|
||||||
DIET = diet
|
DIET = diet
|
||||||
|
@ -47,10 +47,13 @@ test: ${TARGETS}
|
||||||
./test_text
|
./test_text
|
||||||
./var_routing
|
./var_routing
|
||||||
./var_type
|
./var_type
|
||||||
|
./method
|
||||||
./uniform_parse
|
./uniform_parse
|
||||||
./test_list
|
# ./test_list
|
||||||
./test_table
|
# ./test_table
|
||||||
./test_packet_id
|
./test_packet_id
|
||||||
|
./test_index
|
||||||
|
./test_update
|
||||||
x=0; for f in packets/[0-9]*; do echo ">> $$f"; ./test_psyc -f $$f | ${DIFF} -u $$f -; x=$$((x+$$?)); done; exit $$x
|
x=0; for f in packets/[0-9]*; do echo ">> $$f"; ./test_psyc -f $$f | ${DIFF} -u $$f -; x=$$((x+$$?)); done; exit $$x
|
||||||
x=0; for f in packets/[0-9]*; do echo ">> $$f"; ./test_psyc -rf $$f | ${DIFF} -u $$f -; x=$$((x+$$?)); done; exit $$x
|
x=0; for f in packets/[0-9]*; do echo ">> $$f"; ./test_psyc -rf $$f | ${DIFF} -u $$f -; x=$$((x+$$?)); done; exit $$x
|
||||||
|
|
||||||
|
|
|
@ -1,4 +0,0 @@
|
||||||
:_source psyc://foo.example.com/
|
|
||||||
:_target psyc://bar.example.com/
|
|
||||||
0
|
|
||||||
|
|
|
|
@ -1,7 +0,0 @@
|
||||||
:_source psyc://foo.example.com/
|
|
||||||
:_target psyc://bar.example.com/
|
|
||||||
|
|
||||||
:_foo 0
|
|
||||||
_message_private
|
|
||||||
OHAI
|
|
||||||
|
|
|
|
@ -1,18 +1,17 @@
|
||||||
=_source psyc://foo/~bar
|
=_context psyc://foo/~bar
|
||||||
:_target psyc://bar/~baz
|
|
||||||
=_list_foo |foo|bar|baz
|
|
||||||
:_tag sch1828hu3r2cm
|
|
||||||
|
|
||||||
=_foo bar baz
|
=_list_xxx |=_foo|=_bar|=_baz|4 abc
|
||||||
=_abc_def 11 ghi jkl
|
=_list_foo |=_foo|=_bar ||=_baz|
|
||||||
|
=_list_foo _test|3 foo|=_color:4 blue|=_nick bar
|
||||||
xq
|
=_list_bar 43 |3 foo|=_color:4 blue|=_nick bar|8
|
||||||
=_list_bar 36 3 foo|3 bar|7 foo
|
foo|bar
|
||||||
bar|11 foo
|
=_list_bar 43 |3 foo|=_color:4 blue|=_nick bar|9
|
||||||
bar
|
foo|bar
|
||||||
baz
|
=_list_a _type| elem1| elem2| elem3
|
||||||
:_foo_bar yay
|
=_list_b |=_type1 elem1|=_type2 elem2|=_type3 elem3
|
||||||
_message_foo_bar
|
=_list_members _uniform| psyc://example.net/~alice| psyc://example.org/~bob
|
||||||
ohai there!
|
=_list_topic |9 democracy|3 now
|
||||||
\o/
|
=_list_c | foo| bar|6 foobar|3 baz|=_int 234|=_time 1234
|
||||||
|
=_list_foo |=_int 234|=_time 1234|=_picture:3 \o/|7 \oXoXo/
|
||||||
|
_test_list
|
||||||
|
|
|
|
||||||
|
|
7
test/packets/02-list2
Normal file
7
test/packets/02-list2
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
:_source psyc://foo/~bar
|
||||||
|
:_target psyc://bar/~baz
|
||||||
|
|
||||||
|
=_list_foo _test|3 foo|=_color:4 blue|=_nick bar
|
||||||
|
=_list_bar |3 foo|=_color:4 blue|=_nick bar
|
||||||
|
_test
|
||||||
|
|
|
11
test/packets/03-dict
Normal file
11
test/packets/03-dict
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
=_context psyc://foo/~bar
|
||||||
|
|
||||||
|
=_dict _type{4 key1}6 value1{key2} value2{key3}6 value3{key4} value4
|
||||||
|
=_dict_example {4 key1}=_type1:6 value1{key2}=_type2 value2{key3}6 value3{key4} value4
|
||||||
|
=_struct_member |=_nick|=_picture
|
||||||
|
=_dict_owners {psyc://example.net/~alice}{psyc://example.org/~bob}
|
||||||
|
=_dict_members {psyc://example.net/~alice}=_struct_member | alice| \o/{psyc://example.org/~bob}=_struct_member | bob| \oXo/
|
||||||
|
=_dict_members {25 psyc://example.net/~alice}=_struct_member:12 | alice| \o/{psyc://example.org/~bob}=_struct_member | bob| \oXo/
|
||||||
|
=_dict_members _struct_member{25 psyc://example.net/~alice}12 | alice| \o/{psyc://example.org/~bob} | bob| \oXo/
|
||||||
|
_test_dict
|
||||||
|
|
|
|
@ -1,20 +0,0 @@
|
||||||
=_source psyc://foo/~bar
|
|
||||||
:_target psyc://bar/~baz
|
|
||||||
=_list_foo |foo|bar|baz
|
|
||||||
:_tag sch1828hu3r2cm
|
|
||||||
|
|
||||||
?_test ignored
|
|
||||||
=_foo bar baz
|
|
||||||
=_abc_def 11 ghi jkl
|
|
||||||
|
|
||||||
xq
|
|
||||||
=_list_bar 36 3 foo|3 bar|7 foo
|
|
||||||
bar|11 foo
|
|
||||||
b|r
|
|
||||||
baz
|
|
||||||
:_foo_bar yay
|
|
||||||
=_amount_x 10
|
|
||||||
_message_foo_bar
|
|
||||||
ohai there!
|
|
||||||
\o/
|
|
||||||
|
|
|
|
@ -1,4 +1,4 @@
|
||||||
:_list_understand_modules |_state|_fragments|_context
|
:_list_understand_modules | _state| _fragments| _context
|
||||||
|
|
||||||
_request_features
|
_request_features
|
||||||
|
|
|
|
||||||
|
|
87
test/test_index.c
Normal file
87
test/test_index.c
Normal file
|
@ -0,0 +1,87 @@
|
||||||
|
#include <psyc.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <lib.h>
|
||||||
|
|
||||||
|
uint8_t verbose;
|
||||||
|
|
||||||
|
int
|
||||||
|
test_index (const char *buf, size_t buflen)
|
||||||
|
{
|
||||||
|
char *res = malloc(buflen * 2);
|
||||||
|
size_t reslen = 0;
|
||||||
|
|
||||||
|
int ret, reti, len = 0;
|
||||||
|
PsycString idx;
|
||||||
|
PsycParseIndexState state;
|
||||||
|
psyc_parse_index_state_init(&state);
|
||||||
|
psyc_parse_index_buffer_set(&state, buf, buflen);
|
||||||
|
|
||||||
|
if (verbose)
|
||||||
|
printf(">> %.*s\n", (int)buflen, buf);
|
||||||
|
|
||||||
|
do {
|
||||||
|
ret = reti = psyc_parse_index(&state, &idx);
|
||||||
|
len = 0;
|
||||||
|
|
||||||
|
switch (ret) {
|
||||||
|
case PSYC_PARSE_INDEX_LIST_LAST:
|
||||||
|
ret = 0;
|
||||||
|
case PSYC_PARSE_INDEX_LIST:
|
||||||
|
len = sprintf(res + reslen, "#%ld", idx.length);
|
||||||
|
break;
|
||||||
|
case PSYC_PARSE_INDEX_STRUCT_LAST:
|
||||||
|
ret = 0;
|
||||||
|
case PSYC_PARSE_INDEX_STRUCT:
|
||||||
|
len = sprintf(res + reslen, ".%.*s", PSYC_S2ARGP(idx));
|
||||||
|
break;
|
||||||
|
case PSYC_PARSE_INDEX_DICT:
|
||||||
|
if (state.elemlen_found)
|
||||||
|
len = sprintf(res + reslen, "{%ld %.*s}",
|
||||||
|
idx.length, PSYC_S2ARGP(idx));
|
||||||
|
else
|
||||||
|
len = sprintf(res + reslen, "{%.*s}", PSYC_S2ARGP(idx));
|
||||||
|
break;
|
||||||
|
case PSYC_PARSE_INDEX_END:
|
||||||
|
ret = 0;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
ret = -1;
|
||||||
|
}
|
||||||
|
if (verbose)
|
||||||
|
printf("%2d: %.*s\n", reti, len, res + reslen);
|
||||||
|
reslen += len;
|
||||||
|
} while (ret > 0);
|
||||||
|
|
||||||
|
if (reslen != buflen || memcmp(res, buf, buflen) != 0) {
|
||||||
|
printf("ERROR: got\n\[%.*s] (%ld) instead of\n[%.*s] (%ld)\n",
|
||||||
|
(int)reslen, res, reslen, (int)buflen, buf, buflen);
|
||||||
|
ret = 1;
|
||||||
|
} else
|
||||||
|
ret = 0;
|
||||||
|
|
||||||
|
free(res);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
main (int argc, char **argv)
|
||||||
|
{
|
||||||
|
verbose = argc > 1;
|
||||||
|
|
||||||
|
if (test_index(PSYC_C2ARG("#1{foo}._bar")) != 0)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
if (test_index(PSYC_C2ARG("{3 foo}._bar#0")) != 0)
|
||||||
|
return 2;
|
||||||
|
|
||||||
|
if (test_index(PSYC_C2ARG("{foo}#2._bar")) != 0)
|
||||||
|
return 3;
|
||||||
|
|
||||||
|
if (test_index(PSYC_C2ARG("._bar#1{3 foo}")) != 0)
|
||||||
|
return 4;
|
||||||
|
|
||||||
|
printf("test_index passed all tests.\n");
|
||||||
|
return 0; // passed all tests
|
||||||
|
}
|
|
@ -17,21 +17,25 @@ main (int argc, char **argv)
|
||||||
|
|
||||||
PsycParseListState listState;
|
PsycParseListState listState;
|
||||||
PsycList list_text, list_bin;
|
PsycList list_text, list_bin;
|
||||||
PsycString elems_text[NELEMS], elems_bin[NELEMS], elem;
|
PsycElem elems_text[NELEMS], elems_bin[NELEMS];
|
||||||
|
PsycString type, value;
|
||||||
char buf_text[NELEMS * 200], buf_bin[NELEMS * 200], *elems[NELEMS], **elems2 = NULL;
|
char buf_text[NELEMS * 200], buf_bin[NELEMS * 200], *elems[NELEMS], **elems2 = NULL;
|
||||||
|
|
||||||
struct timeval start, end;
|
struct timeval start, end;
|
||||||
|
|
||||||
for (i=0; i<NELEMS; i++)
|
char *text = "1234567890abcdefghijklmnopqrstuvwxyz-._ "
|
||||||
elems_text[i] = PSYC_C2STR("1234567890abcdefghijklmnopqrstuvwxyz-._ "
|
|
||||||
"1234567890abcdefghijklmnopqrstuvwxyz-._ "
|
"1234567890abcdefghijklmnopqrstuvwxyz-._ "
|
||||||
"1234567890abcdefghijklmnopqrstuvwxyz-._ "
|
"1234567890abcdefghijklmnopqrstuvwxyz-._ "
|
||||||
"1234567890");
|
"1234567890";
|
||||||
|
char *bin = "1234567890|abcdefghijklmnopqrstuvwxyz|_\n"
|
||||||
|
"1234567890|abcdefghijklmnopqrstuvwxyz|_\n"
|
||||||
|
"1234567890|abcdefghijklmnopqrstuvwxyz|_\n"
|
||||||
|
"1234567890";
|
||||||
|
|
||||||
for (i=0; i<NELEMS; i++)
|
for (i=0; i<NELEMS; i++)
|
||||||
elems_bin[i] = PSYC_C2STR("1234567890|abcdefghijklmnopqrstuvwxyz|_\n"
|
elems_text[i] = PSYC_ELEM_V(text, strlen(text));
|
||||||
"1234567890|abcdefghijklmnopqrstuvwxyz|_\n"
|
for (i=0; i<NELEMS; i++)
|
||||||
"1234567890|abcdefghijklmnopqrstuvwxyz|_\n"
|
elems_bin[i] = PSYC_ELEM_V(bin, strlen(bin));
|
||||||
"1234567890");
|
|
||||||
|
|
||||||
psyc_list_init(&list_text, elems_text, PSYC_NUM_ELEM(elems_text),
|
psyc_list_init(&list_text, elems_text, PSYC_NUM_ELEM(elems_text),
|
||||||
PSYC_LIST_NO_LENGTH);
|
PSYC_LIST_NO_LENGTH);
|
||||||
|
@ -54,13 +58,14 @@ main (int argc, char **argv)
|
||||||
psyc_parse_list_buffer_set(&listState, buf_text, list_text.length);
|
psyc_parse_list_buffer_set(&listState, buf_text, list_text.length);
|
||||||
i = 0;
|
i = 0;
|
||||||
do {
|
do {
|
||||||
ret = psyc_parse_list(&listState, &elem);
|
ret = psyc_parse_list(&listState, &type, &value);
|
||||||
switch (ret) {
|
switch (ret) {
|
||||||
case PSYC_PARSE_LIST_END:
|
case PSYC_PARSE_LIST_END:
|
||||||
ret = 0;
|
ret = 0;
|
||||||
case PSYC_PARSE_LIST_ELEM:
|
case PSYC_PARSE_LIST_ELEM:
|
||||||
if (verbose)
|
if (verbose)
|
||||||
printf("|%d: %.*s... (%ld)\n", i, 10, elem.data, elem.length);
|
printf("|%ld:%.*s %.*s...\n", value.length,
|
||||||
|
(int)type.length, type.data, 10, value.data);
|
||||||
//elems[i] = malloc(elem.length);
|
//elems[i] = malloc(elem.length);
|
||||||
//memcpy(&elems[i++], elem.data, elem.length);
|
//memcpy(&elems[i++], elem.data, elem.length);
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -5,6 +5,8 @@
|
||||||
#include <psyc/packet.h>
|
#include <psyc/packet.h>
|
||||||
#include <psyc/render.h>
|
#include <psyc/render.h>
|
||||||
|
|
||||||
|
uint8_t verbose;
|
||||||
|
|
||||||
int
|
int
|
||||||
packet_id (char *context, size_t contextlen,
|
packet_id (char *context, size_t contextlen,
|
||||||
char *source, size_t sourcelen,
|
char *source, size_t sourcelen,
|
||||||
|
@ -13,16 +15,22 @@ packet_id (char *context, size_t contextlen,
|
||||||
char *fragment, size_t fragmentlen,
|
char *fragment, size_t fragmentlen,
|
||||||
char *result, size_t resultlen)
|
char *result, size_t resultlen)
|
||||||
{
|
{
|
||||||
size_t idlen = psyc_packet_id_length(contextlen, sourcelen, targetlen,
|
PsycList list;
|
||||||
counterlen, fragmentlen);
|
PsycElem elems[PSYC_PACKET_ID_ELEMS];
|
||||||
|
memset(&list, 0, sizeof(PsycList));
|
||||||
|
memset(elems, 0, sizeof(PsycElem) * PSYC_PACKET_ID_ELEMS);
|
||||||
|
|
||||||
|
psyc_packet_id(&list, elems, context, contextlen,
|
||||||
|
source, sourcelen, target, targetlen,
|
||||||
|
counter, counterlen, fragment, fragmentlen);
|
||||||
|
|
||||||
|
size_t idlen = list.length;
|
||||||
char *id = malloc(idlen);
|
char *id = malloc(idlen);
|
||||||
psyc_render_packet_id(context, contextlen,
|
|
||||||
source, sourcelen,
|
psyc_render_list(&list, id, idlen);
|
||||||
target, targetlen,
|
|
||||||
counter, counterlen,
|
if (verbose)
|
||||||
fragment, fragmentlen,
|
printf("[%.*s]\n", (int)idlen, id);
|
||||||
id, idlen);
|
|
||||||
printf("%.*s\n", (int)idlen, id);
|
|
||||||
int ret = idlen == resultlen && memcmp(result, id, idlen) == 0;
|
int ret = idlen == resultlen && memcmp(result, id, idlen) == 0;
|
||||||
free(id);
|
free(id);
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -31,13 +39,16 @@ packet_id (char *context, size_t contextlen,
|
||||||
int
|
int
|
||||||
main (int argc, char **argv)
|
main (int argc, char **argv)
|
||||||
{
|
{
|
||||||
|
verbose = argc > 1;
|
||||||
|
|
||||||
if (!packet_id(PSYC_C2ARG(""),
|
if (!packet_id(PSYC_C2ARG(""),
|
||||||
PSYC_C2ARG("psyc://example.net/~alice"),
|
PSYC_C2ARG("psyc://example.net/~alice"),
|
||||||
PSYC_C2ARG("psyc://example.net/~bob"),
|
PSYC_C2ARG("psyc://example.net/~bob"),
|
||||||
PSYC_C2ARG("1337"),
|
PSYC_C2ARG("1337"),
|
||||||
PSYC_C2ARG("42"),
|
PSYC_C2ARG("42"),
|
||||||
PSYC_C2ARG("||psyc://example.net/~alice|psyc://example.net/~bob"
|
PSYC_C2ARG("|| psyc://example.net/~alice"
|
||||||
"|1337|42")))
|
"| psyc://example.net/~bob"
|
||||||
|
"| 1337| 42")))
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
if (!packet_id(PSYC_C2ARG("psyc://example.net/@bar"),
|
if (!packet_id(PSYC_C2ARG("psyc://example.net/@bar"),
|
||||||
|
@ -45,8 +56,9 @@ main (int argc, char **argv)
|
||||||
PSYC_C2ARG(""),
|
PSYC_C2ARG(""),
|
||||||
PSYC_C2ARG("1337"),
|
PSYC_C2ARG("1337"),
|
||||||
PSYC_C2ARG("42"),
|
PSYC_C2ARG("42"),
|
||||||
PSYC_C2ARG("|psyc://example.net/@bar|psyc://example.net/~alice|"
|
PSYC_C2ARG("| psyc://example.net/@bar"
|
||||||
"|1337|42")))
|
"| psyc://example.net/~alice|"
|
||||||
|
"| 1337| 42")))
|
||||||
return 2;
|
return 2;
|
||||||
|
|
||||||
if (!packet_id(PSYC_C2ARG("psyc://example.net/@bar"),
|
if (!packet_id(PSYC_C2ARG("psyc://example.net/@bar"),
|
||||||
|
@ -54,8 +66,9 @@ main (int argc, char **argv)
|
||||||
PSYC_C2ARG("psyc://example.net/~alice"),
|
PSYC_C2ARG("psyc://example.net/~alice"),
|
||||||
PSYC_C2ARG("1337"),
|
PSYC_C2ARG("1337"),
|
||||||
PSYC_C2ARG("42"),
|
PSYC_C2ARG("42"),
|
||||||
PSYC_C2ARG("|psyc://example.net/@bar||psyc://example.net/~alice"
|
PSYC_C2ARG("| psyc://example.net/@bar|"
|
||||||
"|1337|42")))
|
"| psyc://example.net/~alice"
|
||||||
|
"| 1337| 42")))
|
||||||
return 3;
|
return 3;
|
||||||
|
|
||||||
if (!packet_id(PSYC_C2ARG("psyc://example.net/@bar"),
|
if (!packet_id(PSYC_C2ARG("psyc://example.net/@bar"),
|
||||||
|
@ -63,7 +76,7 @@ main (int argc, char **argv)
|
||||||
PSYC_C2ARG(""),
|
PSYC_C2ARG(""),
|
||||||
PSYC_C2ARG(""),
|
PSYC_C2ARG(""),
|
||||||
PSYC_C2ARG(""),
|
PSYC_C2ARG(""),
|
||||||
PSYC_C2ARG("|psyc://example.net/@bar||||")))
|
PSYC_C2ARG("| psyc://example.net/@bar||||")))
|
||||||
return 4;
|
return 4;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -12,7 +12,7 @@ main (int argc, char **argv)
|
||||||
uint8_t verbose = argc > 2 && memchr(argv[2], (int)'v', strlen(argv[2]));
|
uint8_t verbose = argc > 2 && memchr(argv[2], (int)'v', strlen(argv[2]));
|
||||||
int idx, ret;
|
int idx, ret;
|
||||||
char buffer[2048], oper;
|
char buffer[2048], oper;
|
||||||
PsycString name, value, elem;
|
PsycString name, value, type;
|
||||||
PsycParseState state;
|
PsycParseState state;
|
||||||
PsycParseListState listState;
|
PsycParseListState listState;
|
||||||
|
|
||||||
|
@ -62,12 +62,13 @@ main (int argc, char **argv)
|
||||||
psyc_parse_list_state_init(&listState);
|
psyc_parse_list_state_init(&listState);
|
||||||
psyc_parse_list_buffer_set(&listState, PSYC_S2ARG(value));
|
psyc_parse_list_buffer_set(&listState, PSYC_S2ARG(value));
|
||||||
|
|
||||||
while ((ret = psyc_parse_list(&listState, &elem))) {
|
while ((ret = psyc_parse_list(&listState, &type, &value))) {
|
||||||
switch (ret) {
|
switch (ret) {
|
||||||
case PSYC_PARSE_LIST_END:
|
case PSYC_PARSE_LIST_END:
|
||||||
case PSYC_PARSE_LIST_ELEM:
|
case PSYC_PARSE_LIST_ELEM:
|
||||||
if (verbose)
|
if (verbose)
|
||||||
printf("|%.*s\n", (int)elem.length, elem.data);
|
printf("|%.*s %.*s\n", (int)type.length, type.data,
|
||||||
|
(int)value.length, value.data);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
printf("Error while parsing list: %i\n", ret);
|
printf("Error while parsing list: %i\n", ret);
|
||||||
|
|
126
test/test_psyc.c
126
test/test_psyc.c
|
@ -8,9 +8,6 @@
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
|
|
||||||
#include <psyc.h>
|
#include <psyc.h>
|
||||||
#include <psyc/parse.h>
|
|
||||||
#include <psyc/render.h>
|
|
||||||
#include <psyc/syntax.h>
|
|
||||||
|
|
||||||
#include "test.c"
|
#include "test.c"
|
||||||
|
|
||||||
|
@ -71,10 +68,11 @@ test_input (int i, char *recvbuf, size_t nbytes)
|
||||||
PsycPacket *packet = &packets[i];
|
PsycPacket *packet = &packets[i];
|
||||||
|
|
||||||
char oper;
|
char oper;
|
||||||
PsycString name, value, elem;
|
PsycString name, value, type;
|
||||||
PsycString *pname = NULL, *pvalue = NULL;
|
PsycString *pname = NULL, *pvalue = NULL;
|
||||||
PsycModifier *mod = NULL;
|
PsycModifier *mod = NULL;
|
||||||
PsycParseListState listState;
|
PsycParseListState lstate;
|
||||||
|
PsycParseDictState dstate;
|
||||||
size_t len;
|
size_t len;
|
||||||
|
|
||||||
// Set buffer with data for the parser.
|
// Set buffer with data for the parser.
|
||||||
|
@ -283,37 +281,131 @@ test_input (int i, char *recvbuf, size_t nbytes)
|
||||||
oper = 0;
|
oper = 0;
|
||||||
name.length = 0;
|
name.length = 0;
|
||||||
value.length = 0;
|
value.length = 0;
|
||||||
|
type.length = 0;
|
||||||
|
|
||||||
if (psyc_var_is_list(PSYC_S2ARG(*pname))) {
|
switch (psyc_var_type(PSYC_S2ARG(*pname))) {
|
||||||
|
case PSYC_TYPE_LIST:
|
||||||
if (verbose >= 2)
|
if (verbose >= 2)
|
||||||
printf("## LIST START\n");
|
printf("## LIST START\n");
|
||||||
|
|
||||||
psyc_parse_list_state_init(&listState);
|
psyc_parse_list_state_init(&lstate);
|
||||||
psyc_parse_list_buffer_set(&listState, PSYC_S2ARG(*pvalue));
|
psyc_parse_list_buffer_set(&lstate, PSYC_S2ARG(*pvalue));
|
||||||
|
|
||||||
do {
|
do {
|
||||||
retl = psyc_parse_list(&listState, &elem);
|
retl = psyc_parse_list(&lstate, &type, &value);
|
||||||
switch (retl) {
|
switch (retl) {
|
||||||
case PSYC_PARSE_LIST_END:
|
case PSYC_PARSE_LIST_TYPE:
|
||||||
|
if (verbose >= 2)
|
||||||
|
printf("## LIST TYPE: %.*s\n", (int)type.length, type.data);
|
||||||
|
break;
|
||||||
|
case PSYC_PARSE_LIST_ELEM_START:
|
||||||
|
case PSYC_PARSE_LIST_ELEM_LAST:
|
||||||
retl = 0;
|
retl = 0;
|
||||||
case PSYC_PARSE_LIST_ELEM:
|
case PSYC_PARSE_LIST_ELEM:
|
||||||
if (verbose >= 2) {
|
if (verbose >= 2) {
|
||||||
printf("|%.*s\n", (int)elem.length, elem.data);
|
printf("|%.*s [%.*s]", (int)type.length, type.data,
|
||||||
if (ret == PSYC_PARSE_LIST_END)
|
(int)value.length, value.data);
|
||||||
printf("## LIST END");
|
if (retl == PSYC_PARSE_LIST_ELEM_START)
|
||||||
|
printf(" ...");
|
||||||
|
printf("\n");
|
||||||
|
if (ret == PSYC_PARSE_LIST_ELEM_LAST)
|
||||||
|
printf("## LAST ELEM\n");
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case PSYC_PARSE_LIST_ELEM_CONT:
|
||||||
|
retl = 0;
|
||||||
|
case PSYC_PARSE_LIST_ELEM_END:
|
||||||
|
if (verbose >= 2) {
|
||||||
|
printf("... [%.*s]", (int)value.length, value.data);
|
||||||
|
if (retl == PSYC_PARSE_LIST_ELEM_CONT)
|
||||||
|
printf(" ...");
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case PSYC_PARSE_LIST_END:
|
||||||
|
retl = 0;
|
||||||
|
if (verbose >= 2)
|
||||||
|
printf("## LIST END\n");
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
printf("# Error while parsing list: %i\n", retl);
|
printf("# Error while parsing list: %i\n", retl);
|
||||||
ret = retl = -1;
|
ret = retl = -1;
|
||||||
}
|
}
|
||||||
|
} while (retl > 0);
|
||||||
|
break;
|
||||||
|
case PSYC_TYPE_DICT:
|
||||||
|
if (verbose >= 2)
|
||||||
|
printf("## DICT START\n");
|
||||||
|
|
||||||
|
psyc_parse_dict_state_init(&dstate);
|
||||||
|
psyc_parse_dict_buffer_set(&dstate, PSYC_S2ARG(*pvalue));
|
||||||
|
|
||||||
|
do {
|
||||||
|
retl = psyc_parse_dict(&dstate, &type, &value);
|
||||||
|
switch (retl) {
|
||||||
|
case PSYC_PARSE_DICT_TYPE:
|
||||||
|
if (verbose >= 2)
|
||||||
|
printf("## DICT TYPE: %.*s\n", (int)type.length, type.data);
|
||||||
|
break;
|
||||||
|
case PSYC_PARSE_DICT_KEY_START:
|
||||||
|
retl = 0;
|
||||||
|
case PSYC_PARSE_DICT_KEY:
|
||||||
|
if (verbose >= 2) {
|
||||||
|
printf("{[%.*s]", (int)value.length, value.data);
|
||||||
|
if (retl == PSYC_PARSE_DICT_KEY_START)
|
||||||
|
printf(" ...");
|
||||||
|
printf("\n");
|
||||||
}
|
}
|
||||||
while (retl > 0);
|
break;
|
||||||
|
case PSYC_PARSE_DICT_KEY_CONT:
|
||||||
|
retl = 0;
|
||||||
|
case PSYC_PARSE_DICT_KEY_END:
|
||||||
|
if (verbose >= 2) {
|
||||||
|
printf("... [%.*s]", (int)value.length, value.data);
|
||||||
|
if (retl == PSYC_PARSE_DICT_KEY_CONT)
|
||||||
|
printf(" ...");
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case PSYC_PARSE_DICT_VALUE_START:
|
||||||
|
case PSYC_PARSE_DICT_VALUE_LAST:
|
||||||
|
retl = 0;
|
||||||
|
case PSYC_PARSE_DICT_VALUE:
|
||||||
|
if (verbose >= 2) {
|
||||||
|
printf("}%.*s [%.*s]", (int)type.length, type.data,
|
||||||
|
(int)value.length, value.data);
|
||||||
|
if (retl == PSYC_PARSE_DICT_VALUE_START)
|
||||||
|
printf(" ...");
|
||||||
|
printf("\n");
|
||||||
|
if (ret == PSYC_PARSE_DICT_VALUE_LAST)
|
||||||
|
printf("## LAST VALUE\n");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case PSYC_PARSE_DICT_VALUE_CONT:
|
||||||
|
retl = 0;
|
||||||
|
case PSYC_PARSE_DICT_VALUE_END:
|
||||||
|
if (verbose >= 2) {
|
||||||
|
printf("... [%.*s]", (int)value.length, value.data);
|
||||||
|
if (retl == PSYC_PARSE_DICT_VALUE_CONT)
|
||||||
|
printf(" ...");
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case PSYC_PARSE_DICT_END:
|
||||||
|
retl = 0;
|
||||||
|
printf("## DICT END\n");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
printf("# Error while parsing dict: %i\n", retl);
|
||||||
|
ret = retl = -1;
|
||||||
|
}
|
||||||
|
} while (retl > 0);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
} while (ret > 0);
|
||||||
while (ret > 0);
|
|
||||||
|
|
||||||
if (progress)
|
if (progress)
|
||||||
r = write(1, " ", 1);
|
r = write(1, " ", 1);
|
||||||
|
|
|
@ -1,14 +1,13 @@
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
#include <lib.h>
|
#include <lib.h>
|
||||||
#include <psyc/render.h>
|
#include <psyc.h>
|
||||||
#include <psyc/syntax.h>
|
|
||||||
|
|
||||||
#define myUNI "psyc://10.100.1000/~ludwig"
|
#define myUNI "psyc://10.100.1000/~ludwig"
|
||||||
|
|
||||||
/* example renderer generating a presence packet */
|
/* example renderer generating a presence packet */
|
||||||
int
|
int
|
||||||
testPresence (char *avail, int availlen,
|
test_presence (char *avail, int availlen,
|
||||||
char *desc, int desclen,
|
char *desc, int desclen,
|
||||||
char *rendered, uint8_t verbose)
|
char *rendered, uint8_t verbose)
|
||||||
{
|
{
|
||||||
|
@ -42,7 +41,7 @@ testPresence (char *avail, int availlen,
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
testList (const char *rendered, uint8_t verbose)
|
test_list (const char *rendered, uint8_t verbose)
|
||||||
{
|
{
|
||||||
PsycModifier routing[2];
|
PsycModifier routing[2];
|
||||||
psyc_modifier_init(&routing[0], PSYC_OPERATOR_SET,
|
psyc_modifier_init(&routing[0], PSYC_OPERATOR_SET,
|
||||||
|
@ -52,23 +51,21 @@ testList (const char *rendered, uint8_t verbose)
|
||||||
PSYC_C2ARG("_context"),
|
PSYC_C2ARG("_context"),
|
||||||
PSYC_C2ARG(myUNI), PSYC_MODIFIER_ROUTING);
|
PSYC_C2ARG(myUNI), PSYC_MODIFIER_ROUTING);
|
||||||
|
|
||||||
PsycString elems_text[] = {
|
PsycElem elems_text[] = {
|
||||||
PSYC_C2STR("foo"),
|
PSYC_ELEM_V("foo", 3),
|
||||||
PSYC_C2STR("bar"),
|
PSYC_ELEM_V("bar", 3),
|
||||||
PSYC_C2STR("baz"),
|
PSYC_ELEM_V("baz", 3),
|
||||||
};
|
};
|
||||||
|
|
||||||
PsycString elems_bin[] = {
|
PsycElem elems_bin[] = {
|
||||||
PSYC_C2STR("foo"),
|
PSYC_ELEM_V("foo", 3),
|
||||||
PSYC_C2STR("b|r"),
|
PSYC_ELEM_V("b|r", 3),
|
||||||
PSYC_C2STR("baz\nqux"),
|
PSYC_ELEM_V("baz\nqux", 7),
|
||||||
};
|
};
|
||||||
|
|
||||||
PsycList list_text, list_bin;
|
PsycList list_text, list_bin;
|
||||||
psyc_list_init(&list_text, elems_text,
|
psyc_list_init(&list_text, elems_text, PSYC_NUM_ELEM(elems_text));
|
||||||
PSYC_NUM_ELEM(elems_text), PSYC_LIST_CHECK_LENGTH);
|
psyc_list_init(&list_bin, elems_bin, PSYC_NUM_ELEM(elems_bin));
|
||||||
psyc_list_init(&list_bin, elems_bin,
|
|
||||||
PSYC_NUM_ELEM(elems_bin), PSYC_LIST_CHECK_LENGTH);
|
|
||||||
|
|
||||||
char buf_text[32], buf_bin[32];
|
char buf_text[32], buf_bin[32];
|
||||||
psyc_render_list(&list_text, buf_text, sizeof(buf_text));
|
psyc_render_list(&list_text, buf_text, sizeof(buf_text));
|
||||||
|
@ -77,10 +74,12 @@ testList (const char *rendered, uint8_t verbose)
|
||||||
PsycModifier entity[2];
|
PsycModifier entity[2];
|
||||||
psyc_modifier_init(&entity[0], PSYC_OPERATOR_SET,
|
psyc_modifier_init(&entity[0], PSYC_OPERATOR_SET,
|
||||||
PSYC_C2ARG("_list_text"),
|
PSYC_C2ARG("_list_text"),
|
||||||
buf_text, list_text.length, list_text.flag);
|
buf_text, list_text.length,
|
||||||
|
PSYC_MODIFIER_CHECK_LENGTH);
|
||||||
psyc_modifier_init(&entity[1], PSYC_OPERATOR_SET,
|
psyc_modifier_init(&entity[1], PSYC_OPERATOR_SET,
|
||||||
PSYC_C2ARG("_list_binary"),
|
PSYC_C2ARG("_list_binary"),
|
||||||
buf_bin, list_bin.length, list_bin.flag);
|
buf_bin, list_bin.length,
|
||||||
|
PSYC_MODIFIER_CHECK_LENGTH);
|
||||||
|
|
||||||
PsycPacket packet;
|
PsycPacket packet;
|
||||||
psyc_packet_init(&packet, routing, PSYC_NUM_ELEM(routing),
|
psyc_packet_init(&packet, routing, PSYC_NUM_ELEM(routing),
|
||||||
|
@ -102,21 +101,21 @@ main (int argc, char **argv)
|
||||||
{
|
{
|
||||||
uint8_t verbose = argc > 1;
|
uint8_t verbose = argc > 1;
|
||||||
|
|
||||||
if (testPresence(PSYC_C2ARG("_here"), PSYC_C2ARG("I'm omnipresent right now"), "\
|
if (test_presence(PSYC_C2ARG("_here"), PSYC_C2ARG("I'm omnipresent right now"), "\
|
||||||
:_context\t" myUNI "\n\
|
:_context\t" myUNI "\n\
|
||||||
\n\
|
97\n\
|
||||||
=_degree_availability\t_here\n\
|
=_degree_availability\t_here\n\
|
||||||
=_description_presence\tI'm omnipresent right now\n\
|
=_description_presence 25\tI'm omnipresent right now\n\
|
||||||
_notice_presence\n\
|
_notice_presence\n\
|
||||||
|\n", verbose))
|
|\n", verbose))
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
if (testList("\
|
if (test_list("\
|
||||||
:_source psyc://10.100.1000/~ludwig\n\
|
:_source psyc://10.100.1000/~ludwig\n\
|
||||||
:_context psyc://10.100.1000/~ludwig\n\
|
:_context psyc://10.100.1000/~ludwig\n\
|
||||||
85\n\
|
90\n\
|
||||||
:_list_text |foo|bar|baz\n\
|
:_list_text 15 | foo| bar| baz\n\
|
||||||
:_list_binary 21 3 foo|3 b|r|7 baz\n\
|
:_list_binary 20 | foo|3 b|r| baz\n\
|
||||||
qux\n\
|
qux\n\
|
||||||
_test_list\n\
|
_test_list\n\
|
||||||
list test\n\
|
list test\n\
|
||||||
|
|
140
test/test_update.c
Normal file
140
test/test_update.c
Normal file
|
@ -0,0 +1,140 @@
|
||||||
|
#include <psyc.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <lib.h>
|
||||||
|
|
||||||
|
uint8_t verbose;
|
||||||
|
|
||||||
|
int
|
||||||
|
test_update (const char *buf, size_t buflen,
|
||||||
|
const char *r_idx, size_t r_idxlen, char r_oper,
|
||||||
|
const char *r_typ, size_t r_typlen,
|
||||||
|
const char *r_val, size_t r_vallen)
|
||||||
|
{
|
||||||
|
char *idx = malloc(r_idxlen * 2);
|
||||||
|
char *typ = NULL, *val = NULL;
|
||||||
|
size_t idxlen = 0, typlen = 0, vallen = 0;
|
||||||
|
|
||||||
|
int ret, reti, len = 0;
|
||||||
|
char oper;
|
||||||
|
PsycString value;
|
||||||
|
PsycParseUpdateState state;
|
||||||
|
psyc_parse_update_state_init(&state);
|
||||||
|
psyc_parse_update_buffer_set(&state, buf, buflen);
|
||||||
|
|
||||||
|
if (verbose)
|
||||||
|
printf(">> %.*s\n", (int)buflen, buf);
|
||||||
|
|
||||||
|
do {
|
||||||
|
ret = reti = psyc_parse_update(&state, &oper, &value);
|
||||||
|
len = 0;
|
||||||
|
|
||||||
|
switch (ret) {
|
||||||
|
case PSYC_PARSE_INDEX_LIST:
|
||||||
|
len = sprintf(idx + idxlen, "#%ld", value.length);
|
||||||
|
break;
|
||||||
|
case PSYC_PARSE_INDEX_STRUCT:
|
||||||
|
len = sprintf(idx + idxlen, ".%.*s", PSYC_S2ARGP(value));
|
||||||
|
break;
|
||||||
|
case PSYC_PARSE_INDEX_DICT:
|
||||||
|
if (state.elemlen_found)
|
||||||
|
len = sprintf(idx + idxlen, "{%ld %.*s}",
|
||||||
|
value.length, PSYC_S2ARGP(value));
|
||||||
|
else
|
||||||
|
len = sprintf(idx + idxlen, "{%.*s}", PSYC_S2ARGP(value));
|
||||||
|
break;
|
||||||
|
case PSYC_PARSE_UPDATE_TYPE_END:
|
||||||
|
ret = 0;
|
||||||
|
case PSYC_PARSE_UPDATE_TYPE:
|
||||||
|
typ = value.data;
|
||||||
|
typlen = value.length;
|
||||||
|
if (verbose)
|
||||||
|
printf("%c[%.*s]\n", oper, PSYC_S2ARGP(value));
|
||||||
|
break;
|
||||||
|
case PSYC_PARSE_UPDATE_VALUE:
|
||||||
|
val = value.data;
|
||||||
|
vallen = value.length;
|
||||||
|
ret = 0;
|
||||||
|
if (verbose)
|
||||||
|
printf("[%.*s]\n", PSYC_S2ARGP(value));
|
||||||
|
break;
|
||||||
|
case PSYC_PARSE_UPDATE_END:
|
||||||
|
ret = 0;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
ret = -1;
|
||||||
|
}
|
||||||
|
if (verbose && len)
|
||||||
|
printf("%2d: %.*s\n", reti, len, idx + idxlen);
|
||||||
|
idxlen += len;
|
||||||
|
} while (ret > 0);
|
||||||
|
|
||||||
|
if (ret == 0) {
|
||||||
|
if (idxlen != r_idxlen || oper != r_oper
|
||||||
|
|| typlen != r_typlen || vallen != r_vallen
|
||||||
|
|| memcmp(r_idx, idx, idxlen) != 0
|
||||||
|
|| memcmp(r_typ, typ, typlen) != 0
|
||||||
|
|| memcmp(r_val, val, vallen) != 0) {
|
||||||
|
printf("ERROR: got\n\[%.*s] %c[%.*s]:[%ld] [%.*s] instead of\n[%.*s]\n",
|
||||||
|
(int)idxlen, idx, oper, (int)typlen, typ, vallen, (int)vallen, val,
|
||||||
|
(int)buflen, buf);
|
||||||
|
ret = 1;
|
||||||
|
} else
|
||||||
|
ret = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
free(idx);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
main (int argc, char **argv)
|
||||||
|
{
|
||||||
|
verbose = argc > 1;
|
||||||
|
|
||||||
|
if (test_update(PSYC_C2ARG("#1{foo}._bar =_foo:3 bar"),
|
||||||
|
PSYC_C2ARG("#1{foo}._bar"), '=',
|
||||||
|
PSYC_C2ARG("_foo"),
|
||||||
|
PSYC_C2ARG("bar")) != 0)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
if (test_update(PSYC_C2ARG("{3 foo}._bar#0 +:3 baz"),
|
||||||
|
PSYC_C2ARG("{3 foo}._bar#0"), '+',
|
||||||
|
PSYC_C2ARG(""),
|
||||||
|
PSYC_C2ARG("baz")) != 0)
|
||||||
|
return 2;
|
||||||
|
|
||||||
|
if (test_update(PSYC_C2ARG("{foo}#2._bar - 1337"),
|
||||||
|
PSYC_C2ARG("{foo}#2._bar"), '-',
|
||||||
|
PSYC_C2ARG(""),
|
||||||
|
PSYC_C2ARG("1337")) != 0)
|
||||||
|
return 3;
|
||||||
|
|
||||||
|
if (test_update(PSYC_C2ARG("._bar#1{3 foo} ="),
|
||||||
|
PSYC_C2ARG("._bar#1{3 foo}"), '=',
|
||||||
|
PSYC_C2ARG(""),
|
||||||
|
PSYC_C2ARG("")) != 0)
|
||||||
|
return 4;
|
||||||
|
|
||||||
|
if (test_update(PSYC_C2ARG("#1{3 foo}._bar =_list"),
|
||||||
|
PSYC_C2ARG("#1{3 foo}._bar"), '=',
|
||||||
|
PSYC_C2ARG("_list"),
|
||||||
|
PSYC_C2ARG("")) != 0)
|
||||||
|
return 5;
|
||||||
|
|
||||||
|
if (test_update(PSYC_C2ARG("#1{3 foo}._bar =_list "),
|
||||||
|
PSYC_C2ARG("#1{3 foo}._bar"), '=',
|
||||||
|
PSYC_C2ARG("_list"),
|
||||||
|
PSYC_C2ARG("")) != 0)
|
||||||
|
return 6;
|
||||||
|
|
||||||
|
if (test_update(PSYC_C2ARG("#1{3 foo}._bar =_list"),
|
||||||
|
PSYC_C2ARG("#1{3 foo}._bar"), '=',
|
||||||
|
PSYC_C2ARG("_list"),
|
||||||
|
PSYC_C2ARG("")) != 0)
|
||||||
|
return 7;
|
||||||
|
|
||||||
|
printf("test_update passed all tests.\n");
|
||||||
|
return 0; // passed all tests
|
||||||
|
}
|
Loading…
Reference in a new issue