diff options
author | Niels Provos <provos@gmail.com> | 2008-06-21 02:21:25 +0000 |
---|---|---|
committer | Niels Provos <provos@gmail.com> | 2008-06-21 02:21:25 +0000 |
commit | 99a1063e735f70443268b50d14f042c87cb9b99a (patch) | |
tree | 2789eb33ecbbb259c280e9c290f183b31ba40d72 /event_tagging.c | |
parent | 4c56ba1cede32ba30624208e8e84672531e644e3 (diff) | |
download | libevent-99a1063e735f70443268b50d14f042c87cb9b99a.tar.gz |
support 64-bit integers in rpc structs
svn:r856
Diffstat (limited to 'event_tagging.c')
-rw-r--r-- | event_tagging.c | 167 |
1 files changed, 117 insertions, 50 deletions
diff --git a/event_tagging.c b/event_tagging.c index 62fc4b22..4a39ea2c 100644 --- a/event_tagging.c +++ b/event_tagging.c @@ -87,29 +87,39 @@ evtag_init(void) * @return the number of bytes written into data. */ +#define ENCODE_INT_INTERNAL(data, number) do { \ + int off = 1, nibbles = 0; \ + \ + memset(data, 0, sizeof(number)+1); \ + while (number) { \ + if (off & 0x1) \ + data[off/2] = (data[off/2] & 0xf0) | (number & 0x0f); \ + else \ + data[off/2] = (data[off/2] & 0x0f) | \ + ((number & 0x0f) << 4); \ + number >>= 4; \ + off++; \ + } \ + \ + if (off > 2) \ + nibbles = off - 2; \ + \ + /* Off - 1 is the number of encoded nibbles */ \ + data[0] = (data[0] & 0x0f) | ((nibbles & 0x0f) << 4); \ + \ + return ((off + 1) / 2); \ +} while (0) + static inline int encode_int_internal(ev_uint8_t *data, ev_uint32_t number) { - int off = 1, nibbles = 0; - - memset(data, 0, sizeof(ev_uint32_t)+1); - while (number) { - if (off & 0x1) - data[off/2] = (data[off/2] & 0xf0) | (number & 0x0f); - else - data[off/2] = (data[off/2] & 0x0f) | - ((number & 0x0f) << 4); - number >>= 4; - off++; - } - - if (off > 2) - nibbles = off - 2; - - /* Off - 1 is the number of encoded nibbles */ - data[0] = (data[0] & 0x0f) | ((nibbles & 0x0f) << 4); + ENCODE_INT_INTERNAL(data, number); +} - return ((off + 1) / 2); +static inline int +encode_int64_internal(ev_uint8_t *data, ev_uint64_t number) +{ + ENCODE_INT_INTERNAL(data, number); } void @@ -120,6 +130,14 @@ encode_int(struct evbuffer *evbuf, ev_uint32_t number) evbuffer_add(evbuf, data, len); } +void +encode_int64(struct evbuffer *evbuf, ev_uint64_t number) +{ + ev_uint8_t data[9]; + int len = encode_int64_internal(data, number); + evbuffer_add(evbuf, data, len); +} + /* * Support variable length encoding of tags; we use the high bit in each * octet as a continuation signal. @@ -229,6 +247,18 @@ evtag_marshal_int(struct evbuffer *evbuf, ev_uint32_t tag, ev_uint32_t integer) } void +evtag_marshal_int64(struct evbuffer *evbuf, ev_uint32_t tag, + ev_uint64_t integer) +{ + ev_uint8_t data[9]; + int len = encode_int64_internal(data, integer); + + evtag_encode_tag(evbuf, tag); + encode_int(evbuf, len); + evbuffer_add(evbuf, data, len); +} + +void evtag_marshal_string(struct evbuffer *buf, ev_uint32_t tag, const char *string) { evtag_marshal(buf, tag, string, strlen(string)); @@ -243,6 +273,39 @@ evtag_marshal_timeval(struct evbuffer *evbuf, ev_uint32_t tag, struct timeval *t evtag_marshal(evbuf, tag, data, len); } +#define DECODE_INT_INTERNAL(number, maxnibbles, pnumber, evbuf, offset) \ +do { \ + ev_uint8_t *data; \ + int len = EVBUFFER_LENGTH(evbuf) - offset; \ + int nibbles = 0; \ + \ + if (len <= 0) \ + return (-1); \ + \ + /* XXX(niels): faster? */ \ + data = evbuffer_pullup(evbuf, offset + 1) + offset; \ + \ + nibbles = ((data[0] & 0xf0) >> 4) + 1; \ + if (nibbles > maxnibbles || (nibbles >> 1) + 1 > len) \ + return (-1); \ + len = (nibbles >> 1) + 1; \ + \ + data = evbuffer_pullup(evbuf, offset + len) + offset; \ + \ + while (nibbles > 0) { \ + number <<= 4; \ + if (nibbles & 0x1) \ + number |= data[nibbles >> 1] & 0x0f; \ + else \ + number |= (data[nibbles >> 1] & 0xf0) >> 4; \ + nibbles--; \ + } \ + \ + *pnumber = number; \ + \ + return (len); \ +} while (0) + /* Internal: decode an integer from an evbuffer, without draining it. * Only integers up to 32-bits are supported. * @@ -251,39 +314,19 @@ evtag_marshal_timeval(struct evbuffer *evbuf, ev_uint32_t tag, struct timeval *t * @param pnumber a pointer to receive the integer. * @return The length of the number as encoded, or -1 on error. */ + static int decode_int_internal(ev_uint32_t *pnumber, struct evbuffer *evbuf, int offset) { ev_uint32_t number = 0; - ev_uint8_t *data; - int len = EVBUFFER_LENGTH(evbuf) - offset; - int nibbles = 0; - - if (len <= 0) - return (-1); - - /* XXX(niels): faster? */ - data = evbuffer_pullup(evbuf, offset + 1) + offset; - - nibbles = ((data[0] & 0xf0) >> 4) + 1; - if (nibbles > 8 || (nibbles >> 1) + 1 > len) - return (-1); - len = (nibbles >> 1) + 1; - - data = evbuffer_pullup(evbuf, offset + len) + offset; - - while (nibbles > 0) { - number <<= 4; - if (nibbles & 0x1) - number |= data[nibbles >> 1] & 0x0f; - else - number |= (data[nibbles >> 1] & 0xf0) >> 4; - nibbles--; - } - - *pnumber = number; + DECODE_INT_INTERNAL(number, 8, pnumber, evbuf, offset); +} - return (len); +static int +decode_int64_internal(ev_uint64_t *pnumber, struct evbuffer *evbuf, int offset) +{ + ev_uint64_t number = 0; + DECODE_INT_INTERNAL(number, 16, pnumber, evbuf, offset); } int @@ -391,16 +434,14 @@ evtag_unmarshal_int(struct evbuffer *evbuf, ev_uint32_t need_tag, { ev_uint32_t tag; ev_uint32_t len; - ev_uint32_t integer; int result; if (decode_tag_internal(&tag, evbuf, 1 /* dodrain */) == -1) return (-1); if (need_tag != tag) return (-1); - if (evtag_decode_int(&integer, evbuf) == -1) + if (evtag_decode_int(&len, evbuf) == -1) return (-1); - len = integer; if (EVBUFFER_LENGTH(evbuf) < len) return (-1); @@ -413,6 +454,32 @@ evtag_unmarshal_int(struct evbuffer *evbuf, ev_uint32_t need_tag, return result; } +int +evtag_unmarshal_int64(struct evbuffer *evbuf, ev_uint32_t need_tag, + ev_uint64_t *pinteger) +{ + ev_uint32_t tag; + ev_uint32_t len; + int result; + + if (decode_tag_internal(&tag, evbuf, 1 /* dodrain */) == -1) + return (-1); + if (need_tag != tag) + return (-1); + if (evtag_decode_int(&len, evbuf) == -1) + return (-1); + + if (EVBUFFER_LENGTH(evbuf) < len) + return (-1); + + result = decode_int64_internal(pinteger, evbuf, 0); + evbuffer_drain(evbuf, len); + if (result < 0 || result > len) /* XXX Should this be != rather than > ?*/ + return (-1); + else + return result; +} + /* Unmarshal a fixed length tag */ int |