libpsyc/include/psyc/packet.h

354 lines
8.0 KiB
C
Raw Normal View History

#ifndef PSYC_PACKET_H
2011-11-11 21:18:24 +00:00
#define PSYC_PACKET_H
2011-05-09 12:37:57 +00:00
/**
* @file psyc/packet.h
* @brief Interface for PSYC packet data structures.
*
* Packet data structures and functions for creating them are defined here.
*/
/**
* @defgroup packet Packet data structures
*
* This module contains definitions of packet data structures and functions for
* creating them.
* @{
*/
2011-10-31 19:04:16 +00:00
#include <math.h>
2011-11-30 12:51:50 +00:00
#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
2011-05-09 14:32:39 +00:00
/** Modifier flags. */
2011-11-11 21:18:24 +00:00
typedef enum {
/// Modifier needs to be checked if it needs length.
PSYC_MODIFIER_CHECK_LENGTH = 0,
/// Modifier needs length.
PSYC_MODIFIER_NEED_LENGTH = 1,
/// Modifier doesn't need length.
PSYC_MODIFIER_NO_LENGTH = 2,
/// Routing modifier, which implies that it doesn't need length.
PSYC_MODIFIER_ROUTING = 4,
2011-10-31 19:26:47 +00:00
} PsycModifierFlag;
/** List/dict element flags. */
2011-11-11 21:18:24 +00:00
typedef enum {
/// Element needs to be checked if it needs length.
PSYC_ELEM_CHECK_LENGTH = 0,
/// Element needs length.
PSYC_ELEM_NEED_LENGTH = 1,
/// Element doesn't need length.
PSYC_ELEM_NO_LENGTH = 2,
} PsycElemFlag;
2011-05-09 14:32:39 +00:00
/** Packet flags. */
2011-11-11 21:18:24 +00:00
typedef enum {
/// Packet needs to be checked if it needs content length.
PSYC_PACKET_CHECK_LENGTH = 0,
/// Packet needs content length.
PSYC_PACKET_NEED_LENGTH = 1,
/// Packet doesn't need content length.
PSYC_PACKET_NO_LENGTH = 2,
2011-10-31 19:26:47 +00:00
} PsycPacketFlag;
2011-11-11 21:18:24 +00:00
typedef enum {
PSYC_OPERATOR_SET = ':',
PSYC_OPERATOR_ASSIGN = '=',
PSYC_OPERATOR_AUGMENT = '+',
PSYC_OPERATOR_DIMINISH = '-',
PSYC_OPERATOR_UPDATE = '@',
2011-11-11 21:18:24 +00:00
PSYC_OPERATOR_QUERY = '?',
2011-11-09 18:01:05 +00:00
} PsycOperator;
2011-11-11 21:18:24 +00:00
typedef enum {
PSYC_STATE_NOOP = 0,
PSYC_STATE_RESET = '=',
PSYC_STATE_RESYNC = '?',
} PsycStateOp;
2011-12-28 22:45:16 +00:00
typedef enum {
PSYC_PACKET_ID_CONTEXT = 0,
PSYC_PACKET_ID_SOURCE = 1,
PSYC_PACKET_ID_TARGET = 2,
PSYC_PACKET_ID_COUNTER = 3,
PSYC_PACKET_ID_FRAGMENT = 4,
PSYC_PACKET_ID_ELEMS = 5,
} PsycPacketId;
2011-11-11 21:18:24 +00:00
typedef struct {
PsycString type;
2011-11-11 21:18:24 +00:00
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 */
2011-11-11 21:18:24 +00:00
typedef struct {
PsycElem value;
PsycDictKey key;
} PsycDictElem;
#define PSYC_DICT_ELEM(k, v) \
(PsycDictElem) { \
.key = k, \
.value = v, \
}
/** Dictionary */
2011-11-11 21:18:24 +00:00
typedef struct {
PsycString type;
PsycDictElem *elems;
2011-11-11 21:18:24 +00:00
size_t num_elems;
size_t length;
} PsycDict;
/** List */
2011-11-26 14:03:10 +00:00
typedef struct {
PsycString type;
PsycElem *elems;
size_t num_elems;
2011-11-26 14:03:10 +00:00
size_t length;
} PsycList;
/** Modifier */
typedef struct {
PsycString name;
PsycString value;
PsycModifierFlag flag;
char oper;
} PsycModifier;
/** Entity or routing header */
typedef struct {
size_t lines;
PsycModifier *modifiers;
} PsycHeader;
2011-11-26 14:03:10 +00:00
/** Intermediate struct for a PSYC packet. */
2011-11-11 21:18:24 +00:00
typedef struct {
PsycHeader routing; ///< Routing header.
PsycHeader entity; ///< Entity header.
PsycString method; ///< Contains the method.
PsycString data; ///< Contains the data.
PsycString content; ///< Contains the whole content.
size_t routinglen; ///< Length of routing part.
size_t contentlen; ///< Length of content part.
2011-11-11 21:18:24 +00:00
size_t length; ///< Total length of packet.
PsycStateOp stateop; ///< State operation. @see PsycStateOp
2011-11-11 21:18:24 +00:00
PsycPacketFlag flag; ///< Packet flag.
2011-10-31 19:26:47 +00:00
} PsycPacket;
2011-10-31 19:04:16 +00:00
/**
* Return the number of digits a number has in its base 10 representation.
*/
2011-11-11 21:18:24 +00:00
static inline size_t
psyc_num_length (size_t n)
2011-10-31 19:04:16 +00:00
{
2011-11-11 21:18:24 +00:00
return n < 10 ? 1 : log10(n) + 1;
2011-10-31 19:04:16 +00:00
}
2011-05-28 18:24:36 +00:00
/**
* \internal
* Check if a modifier needs length.
*/
2011-11-11 21:18:24 +00:00
static inline PsycModifierFlag
psyc_modifier_length_check (PsycModifier *m)
{
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;
return PSYC_MODIFIER_NO_LENGTH;
}
2011-11-03 13:27:01 +00:00
/** Initialize modifier */
2011-11-11 21:18:24 +00:00
static inline void
2011-12-01 13:12:41 +00:00
psyc_modifier_init (PsycModifier *m, PsycOperator oper,
2011-11-11 21:18:24 +00:00
char *name, size_t namelen,
char *value, size_t valuelen, PsycModifierFlag flag)
2011-11-01 21:24:35 +00:00
{
*m = (PsycModifier) {
.oper = oper,
.name = {namelen, name},
.value = {valuelen, value},
.flag = flag
};
2011-11-11 21:18:24 +00:00
if (flag == PSYC_MODIFIER_CHECK_LENGTH) // find out if it needs a length
m->flag = psyc_modifier_length_check(m);
else if (flag & PSYC_MODIFIER_ROUTING)
m->flag |= PSYC_MODIFIER_NO_LENGTH;
}
2011-05-28 18:29:19 +00:00
/**
* \internal
* 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.
2011-05-28 18:29:19 +00:00
*/
2011-11-11 21:18:24 +00:00
size_t
psyc_elem_length (PsycElem *elem);
2011-05-28 18:24:36 +00:00
/**
* \internal
* Get the rendered length of a dict key.
2011-05-28 18:24:36 +00:00
*/
size_t
psyc_dict_key_length (PsycDictKey *elem);
2011-05-28 18:29:19 +00:00
/**
* \internal
* Get the rendered length of a list.
2011-05-28 18:29:19 +00:00
*/
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
psyc_modifier_length (PsycModifier *m);
2011-05-28 18:24:36 +00:00
/**
* \internal
* Check if a packet needs length.
*/
2011-11-11 21:18:24 +00:00
PsycPacketFlag
psyc_packet_length_check (PsycPacket *p);
2011-05-28 18:29:19 +00:00
/**
* Calculate and set the rendered length of packet parts and total packet length.
*/
2011-11-11 21:18:24 +00:00
size_t
psyc_packet_length_set (PsycPacket *p);
2011-11-26 14:03:10 +00:00
/** Initialize a list. */
2011-11-11 21:18:24 +00:00
void
psyc_list_init (PsycList *list, PsycElem *elems, size_t num_elems);
2011-11-03 13:27:01 +00:00
/** Initialize a dict. */
2011-11-26 14:03:10 +00:00
void
psyc_dict_init (PsycDict *dict, PsycDictElem *elems, size_t num_elems);
2011-11-26 14:03:10 +00:00
/** Initialize a packet. */
2011-11-11 21:18:24 +00:00
void
psyc_packet_init (PsycPacket *packet,
PsycModifier *routing, size_t routinglen,
PsycModifier *entity, size_t entitylen,
char *method, size_t methodlen,
char *data, size_t datalen,
char stateop, PsycPacketFlag flag);
2011-11-03 13:27:01 +00:00
/** Initialize packet with raw content. */
2011-11-11 21:18:24 +00:00
void
psyc_packet_init_raw (PsycPacket *packet,
PsycModifier *routing, size_t routinglen,
char *content, size_t contentlen,
PsycPacketFlag flag);
void
psyc_packet_id (PsycList *list, PsycElem *elems,
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);
2011-12-28 22:45:16 +00:00
2011-05-09 12:37:57 +00:00
/** @} */ // end of packet group
2011-05-09 07:02:15 +00:00
#endif