/* a key-value structure for each message tag. */
struct MsgTag {
- const char *key;
- const char *value;
+ const char *key; /* the key of the tag (must be set) */
+ const char *value; /* the value of the tag or NULL */
+ unsigned int capmask; /* the capability mask this tag belongs to (used only when sending) */
};
struct MsgBuf {
- size_t n_tags;
- struct MsgTag tags[MAXPARA];
+ size_t n_tags; /* the number of tags in the MsgBuf */
+ struct MsgTag tags[MAXPARA]; /* the tags themselves, upto MAXPARA tags available */
- const char *origin;
- const char *cmd;
+ const char *origin; /* the origin of the message (or NULL) */
+ const char *target; /* the target of the message (either NULL, or custom defined) */
+ const char *cmd; /* the cmd/verb of the message (either NULL, or para[0]) */
- size_t parselen;
- size_t n_para;
- const char *para[MAXPARA];
+ size_t n_para; /* the number of parameters (always at least 1 if a full message) */
+ const char *para[MAXPARA]; /* parameters vector (starting with cmd as para[0]) */
+};
+
+struct MsgBuf_str_data {
+ const struct MsgBuf *msgbuf;
+ unsigned int caps;
+};
+
+#define MSGBUF_CACHE_SIZE 32
+
+struct MsgBuf_cache_entry {
+ unsigned int caps;
+ buf_head_t linebuf;
+ struct MsgBuf_cache_entry *next;
+};
+
+struct MsgBuf_cache {
+ const struct MsgBuf *msgbuf;
+ char message[DATALEN + 1];
+ unsigned int overall_capmask;
+
+ /* Fixed maximum size linked list, new entries are allocated at the end
+ * of the array but are accessed through the "next" pointers.
+ *
+ * This does not use rb dlink to avoid unnecessary individual allocations.
+ */
+ struct MsgBuf_cache_entry entry[MSGBUF_CACHE_SIZE];
+ struct MsgBuf_cache_entry *head; /* LRU cache head */
};
/*
* cmd may not be NULL.
* returns 0 on success, 1 on error.
*/
-int msgbuf_unparse(char *buf, struct MsgBuf *msgbuf);
+int msgbuf_unparse(char *buf, size_t buflen, const struct MsgBuf *msgbuf, unsigned int capmask);
/*
* unparse a MsgBuf header plus payload into a buffer.
* cmd may not be NULL.
* returns 0 on success, 1 on error.
*/
-int msgbuf_unparse_fmt(char *buf, struct MsgBuf *head, const char *fmt, ...) AFP(3, 4);
-int msgbuf_vunparse_fmt(char *buf, struct MsgBuf *head, const char *fmt, va_list va);
+int msgbuf_unparse_fmt(char *buf, size_t buflen, const struct MsgBuf *head, unsigned int capmask, const char *fmt, ...) AFP(5, 6);
+int msgbuf_vunparse_fmt(char *buf, size_t buflen, const struct MsgBuf *head, unsigned int capmask, const char *fmt, va_list va);
-static inline void
-msgbuf_init(struct MsgBuf *msgbuf)
-{
- msgbuf->n_tags = msgbuf->n_para = msgbuf->parselen = 0;
- msgbuf->origin = NULL;
- msgbuf->cmd = NULL;
-}
+int msgbuf_unparse_linebuf_tags(char *buf, size_t buflen, void *data);
+int msgbuf_unparse_prefix(char *buf, size_t *buflen, const struct MsgBuf *msgbuf, unsigned int capmask);
+
+void msgbuf_cache_init(struct MsgBuf_cache *cache, const struct MsgBuf *msgbuf, const rb_strf_t *message);
+void msgbuf_cache_initf(struct MsgBuf_cache *cache, const struct MsgBuf *msgbuf, const rb_strf_t *message, const char *format, ...) AFP(4, 5);
+buf_head_t *msgbuf_cache_get(struct MsgBuf_cache *cache, unsigned int caps);
+void msgbuf_cache_free(struct MsgBuf_cache *cache);
static inline void
-msgbuf_append_tag(struct MsgBuf *msgbuf, const char *key, const char *value)
+msgbuf_init(struct MsgBuf *msgbuf)
{
- msgbuf->tags[msgbuf->n_tags].key = key;
- msgbuf->tags[msgbuf->n_tags].value = value;
- msgbuf->n_tags++;
+ memset(msgbuf, 0, sizeof(*msgbuf));
}
static inline void
-msgbuf_append_para(struct MsgBuf *msgbuf, const char *para)
+msgbuf_append_tag(struct MsgBuf *msgbuf, const char *key, const char *value, unsigned int capmask)
{
- msgbuf->para[msgbuf->n_para] = para;
- msgbuf->n_para++;
+ if (msgbuf->n_tags < MAXPARA) {
+ msgbuf->tags[msgbuf->n_tags].key = key;
+ msgbuf->tags[msgbuf->n_tags].value = value;
+ msgbuf->tags[msgbuf->n_tags].capmask = capmask;
+ msgbuf->n_tags++;
+ }
}
#endif