diff options
author | Niels Provos <provos@gmail.com> | 2008-02-28 02:47:43 +0000 |
---|---|---|
committer | Niels Provos <provos@gmail.com> | 2008-02-28 02:47:43 +0000 |
commit | 5c70ea4c9d8720525405063658ccd3e24b6966b1 (patch) | |
tree | c207babc0f0e9122a5dbc5d250ae60d853c0bbef /event_tagging.c | |
parent | eb9b958089bcf59ad712c747e294da95c6baf20c (diff) | |
download | libevent-5c70ea4c9d8720525405063658ccd3e24b6966b1.tar.gz |
improved code for evbuffer; avoids memcpy
svn:r674
Diffstat (limited to 'event_tagging.c')
-rw-r--r-- | event_tagging.c | 149 |
1 files changed, 87 insertions, 62 deletions
diff --git a/event_tagging.c b/event_tagging.c index eec4bf8a..4f12ac78 100644 --- a/event_tagging.c +++ b/event_tagging.c @@ -87,11 +87,10 @@ evtag_init(void) * integers. This function is byte-order independent. */ -void -encode_int(struct evbuffer *evbuf, ev_uint32_t number) +static inline int +encode_int_internal(ev_uint8_t *data, ev_uint32_t number) { int off = 1, nibbles = 0; - ev_uint8_t data[5]; memset(data, 0, sizeof(data)); while (number) { @@ -110,7 +109,15 @@ encode_int(struct evbuffer *evbuf, ev_uint32_t number) /* Off - 1 is the number of encoded nibbles */ data[0] = (data[0] & 0x0f) | ((nibbles & 0x0f) << 4); - evbuffer_add(evbuf, data, (off + 1) / 2); + return ((off + 1) / 2); +} + +void +encode_int(struct evbuffer *evbuf, ev_uint32_t number) +{ + ev_uint8_t data[5]; + int len = encode_int_internal(data, number); + evbuffer_add(evbuf, data, len); } /* @@ -145,10 +152,17 @@ static int decode_tag_internal(ev_uint32_t *ptag, struct evbuffer *evbuf, int dodrain) { ev_uint32_t number = 0; - ev_uint8_t *data = EVBUFFER_DATA(evbuf); int len = EVBUFFER_LENGTH(evbuf); + ev_uint8_t *data; int count = 0, shift = 0, done = 0; + /* + * the encoding of a number is at most one byte more than its + * storage size. however, it may also be much smaller. + */ + data = evbuffer_pullup( + evbuf, len < sizeof(number) + 1 ? len : sizeof(number) + 1); + while (count++ < len) { ev_uint8_t lower = *data++; number |= (lower & 0x7f) << shift; @@ -193,16 +207,25 @@ evtag_marshal(struct evbuffer *evbuf, ev_uint32_t tag, evbuffer_add(evbuf, (void *)data, len); } +void +evtag_marshal_buffer(struct evbuffer *evbuf, ev_uint32_t tag, + struct evbuffer *data) +{ + evtag_encode_tag(evbuf, tag); + encode_int(evbuf, EVBUFFER_LENGTH(data)); + evbuffer_add_buffer(evbuf, data); +} + /* Marshaling for integers */ void evtag_marshal_int(struct evbuffer *evbuf, ev_uint32_t tag, ev_uint32_t integer) { - evbuffer_drain(_buf, EVBUFFER_LENGTH(_buf)); - encode_int(_buf, integer); + ev_uint8_t data[5]; + int len = encode_int_internal(data, integer); evtag_encode_tag(evbuf, tag); - encode_int(evbuf, EVBUFFER_LENGTH(_buf)); - evbuffer_add_buffer(evbuf, _buf); + encode_int(evbuf, len); + evbuffer_add(evbuf, data, len); } void @@ -214,31 +237,33 @@ evtag_marshal_string(struct evbuffer *buf, ev_uint32_t tag, const char *string) void evtag_marshal_timeval(struct evbuffer *evbuf, ev_uint32_t tag, struct timeval *tv) { - evbuffer_drain(_buf, EVBUFFER_LENGTH(_buf)); - - encode_int(_buf, tv->tv_sec); - encode_int(_buf, tv->tv_usec); - - evtag_marshal(evbuf, tag, EVBUFFER_DATA(_buf), - EVBUFFER_LENGTH(_buf)); + ev_uint8_t data[10]; + int len = encode_int_internal(data, tv->tv_sec); + len += encode_int_internal(data + len, tv->tv_usec); + evtag_marshal(evbuf, tag, data, len); } static int -decode_int_internal(ev_uint32_t *pnumber, struct evbuffer *evbuf, int dodrain) +decode_int_internal(ev_uint32_t *pnumber, struct evbuffer *evbuf, int offset) { ev_uint32_t number = 0; - ev_uint8_t *data = EVBUFFER_DATA(evbuf); - int len = EVBUFFER_LENGTH(evbuf); + ev_uint8_t *data; + int len = EVBUFFER_LENGTH(evbuf) - offset; int nibbles = 0; - if (!len) + 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) @@ -248,9 +273,6 @@ decode_int_internal(ev_uint32_t *pnumber, struct evbuffer *evbuf, int dodrain) nibbles--; } - if (dodrain) - evbuffer_drain(evbuf, len); - *pnumber = number; return (len); @@ -259,7 +281,11 @@ decode_int_internal(ev_uint32_t *pnumber, struct evbuffer *evbuf, int dodrain) int evtag_decode_int(ev_uint32_t *pnumber, struct evbuffer *evbuf) { - return (decode_int_internal(pnumber, evbuf, 1) == -1 ? -1 : 0); + int res = decode_int_internal(pnumber, evbuf, 0); + if (res != -1) + evbuffer_drain(evbuf, res); + + return (res == -1 ? -1 : 0); } int @@ -271,18 +297,13 @@ evtag_peek(struct evbuffer *evbuf, ev_uint32_t *ptag) int evtag_peek_length(struct evbuffer *evbuf, ev_uint32_t *plength) { - struct evbuffer tmp; int res, len; len = decode_tag_internal(NULL, evbuf, 0 /* dodrain */); if (len == -1) return (-1); - tmp = *evbuf; - tmp.buffer += len; - tmp.off -= len; - - res = decode_int_internal(plength, &tmp, 0); + res = decode_int_internal(plength, evbuf, len); if (res == -1) return (-1); @@ -294,32 +315,43 @@ evtag_peek_length(struct evbuffer *evbuf, ev_uint32_t *plength) int evtag_payload_length(struct evbuffer *evbuf, ev_uint32_t *plength) { - struct evbuffer tmp; int res, len; len = decode_tag_internal(NULL, evbuf, 0 /* dodrain */); if (len == -1) return (-1); - tmp = *evbuf; - tmp.buffer += len; - tmp.off -= len; - - res = decode_int_internal(plength, &tmp, 0); + res = decode_int_internal(plength, evbuf, len); if (res == -1) return (-1); return (0); } +/* just unmarshals the header and returns the length of the remaining data */ + int -evtag_consume(struct evbuffer *evbuf) +evtag_unmarshal_header(struct evbuffer *evbuf, ev_uint32_t *ptag) { ev_uint32_t len; - if (decode_tag_internal(NULL, evbuf, 1 /* dodrain */) == -1) + + if (decode_tag_internal(ptag, evbuf, 1 /* dodrain */) == -1) return (-1); if (evtag_decode_int(&len, evbuf) == -1) return (-1); + + if (EVBUFFER_LENGTH(evbuf) < len) + return (-1); + + return (len); +} + +int +evtag_consume(struct evbuffer *evbuf) +{ + int len; + if ((len = evtag_unmarshal_header(evbuf, NULL)) == -1) + return (-1); evbuffer_drain(evbuf, len); return (0); @@ -330,19 +362,12 @@ evtag_consume(struct evbuffer *evbuf) int evtag_unmarshal(struct evbuffer *src, ev_uint32_t *ptag, struct evbuffer *dst) { - ev_uint32_t len; - ev_uint32_t integer; + int len; - if (decode_tag_internal(ptag, src, 1 /* dodrain */) == -1) + if ((len = evtag_unmarshal_header(src, ptag)) == -1) return (-1); - if (evtag_decode_int(&integer, src) == -1) - return (-1); - len = integer; - if (EVBUFFER_LENGTH(src) < len) - return (-1); - - if (evbuffer_add(dst, EVBUFFER_DATA(src), len) == -1) + if (evbuffer_add(dst, evbuffer_pullup(src, len), len) == -1) return (-1); evbuffer_drain(src, len); @@ -372,7 +397,7 @@ evtag_unmarshal_int(struct evbuffer *evbuf, ev_uint32_t need_tag, return (-1); evbuffer_drain(_buf, EVBUFFER_LENGTH(_buf)); - if (evbuffer_add(_buf, EVBUFFER_DATA(evbuf), len) == -1) + if (evbuffer_add(_buf, evbuffer_pullup(evbuf, len), len) == -1) return (-1); evbuffer_drain(evbuf, len); @@ -387,18 +412,17 @@ evtag_unmarshal_fixed(struct evbuffer *src, ev_uint32_t need_tag, void *data, size_t len) { ev_uint32_t tag; - - /* Initialize this event buffer so that we can read into it */ - evbuffer_drain(_buf, EVBUFFER_LENGTH(_buf)); + int tag_len; /* Now unmarshal a tag and check that it matches the tag we want */ - if (evtag_unmarshal(src, &tag, _buf) == -1 || tag != need_tag) + if ((tag_len = evtag_unmarshal_header(src, &tag)) == -1 || + tag != need_tag) return (-1); - if (EVBUFFER_LENGTH(_buf) != len) + if (tag_len != len) return (-1); - - memcpy(data, EVBUFFER_DATA(_buf), len); + + evbuffer_remove(src, data, len); return (0); } @@ -407,16 +431,17 @@ evtag_unmarshal_string(struct evbuffer *evbuf, ev_uint32_t need_tag, char **pstring) { ev_uint32_t tag; + int tag_len; - evbuffer_drain(_buf, EVBUFFER_LENGTH(_buf)); - - if (evtag_unmarshal(evbuf, &tag, _buf) == -1 || tag != need_tag) + if ((tag_len = evtag_unmarshal_header(evbuf, &tag)) == -1 || + tag != need_tag) return (-1); - *pstring = event_calloc(EVBUFFER_LENGTH(_buf) + 1, 1); + *pstring = event_malloc(tag_len + 1); if (*pstring == NULL) - event_err(1, "%s: calloc", __func__); - evbuffer_remove(_buf, *pstring, EVBUFFER_LENGTH(_buf)); + event_err(1, "%s: malloc", __func__); + evbuffer_remove(evbuf, *pstring, tag_len); + (*pstring)[tag_len] = '\0'; return (0); } |