diff options
author | Nick Mathewson <nickm@torproject.org> | 2011-07-18 15:36:20 -0400 |
---|---|---|
committer | Nick Mathewson <nickm@torproject.org> | 2011-07-18 15:36:20 -0400 |
commit | 34a52534bb43b30e19267968807a540ba33abe3b (patch) | |
tree | add85f5570fa7d6a8cf597c1e497f6880977e917 /src/or/buffers.c | |
parent | 1e441df2d0d06aa66eaf2c0e00a42d7fe9c39c87 (diff) | |
download | tor-34a52534bb43b30e19267968807a540ba33abe3b.tar.gz tor-34a52534bb43b30e19267968807a540ba33abe3b.zip |
Add a generic_buffer_t to use the best buffer type we have on hand
Also add a quick function to copy all the data in a buffer. (This
one could be done much better, but let's see if it matters.)
Diffstat (limited to 'src/or/buffers.c')
-rw-r--r-- | src/or/buffers.c | 70 |
1 files changed, 70 insertions, 0 deletions
diff --git a/src/or/buffers.c b/src/or/buffers.c index 256b507729..63132db204 100644 --- a/src/or/buffers.c +++ b/src/or/buffers.c @@ -557,6 +557,39 @@ buf_free(buf_t *buf) tor_free(buf); } +/** Return a new copy of <b>in_chunk</b> */ +static chunk_t * +chunk_copy(const chunk_t *in_chunk) +{ + chunk_t *newch = tor_memdup(in_chunk, CHUNK_ALLOC_SIZE(in_chunk->memlen)); + newch->next = NULL; + if (in_chunk->data) { + off_t offset = in_chunk->data - in_chunk->mem; + newch->data = newch->mem + offset; + } + return newch; +} + +/** Return a new copy of <b>buf</b> */ +buf_t * +buf_copy(const buf_t *buf) +{ + chunk_t *ch; + buf_t *out = buf_new(); + out->default_chunk_size = buf->default_chunk_size; + for (ch = buf->head; ch; ch = ch->next) { + chunk_t *newch = chunk_copy(ch); + if (out->tail) { + out->tail->next = newch; + out->tail = newch; + } else { + out->head = out->tail = newch; + } + } + out->datalen = buf->datalen; + return out; +} + /** Append a new chunk with enough capacity to hold <b>capacity</b> bytes to * the tail of <b>buf</b>. If <b>capped</b>, don't allocate a chunk bigger * than MAX_CHUNK_ALLOC. */ @@ -2374,6 +2407,43 @@ write_to_evbuffer_zlib(struct evbuffer *buf, tor_zlib_state_t *state, } #endif +/** Set *<b>output</b> to contain a copy of the data in *<b>input</b> */ +int +generic_buffer_set_to_copy(generic_buffer_t **output, + const generic_buffer_t *input) +{ +#ifdef USE_BUFFEREVENTS + struct evbuffer_ptr ptr; + size_t remaining = evbuffer_get_length(input); + if (*output) { + evbuffer_drain(*output, evbuffer_get_length(*output)); + } else { + if (!(*output = evbuffer_new())) + return -1; + } + evbuffer_ptr_set((struct evbuffer*)input, &ptr, 0, EVBUFFER_PTR_SET); + while (remaining) { + struct evbuffer_iovec v[4]; + int n_used, i; + n_used = evbuffer_peek((struct evbuffer*)input, -1, &ptr, v, 4); + if (n_used < 0) + return -1; + for (i=0;i<n_used;++i) { + evbuffer_add(*output, v[i].iov_base, v[i].iov_len); + tor_assert(v[i].iov_len <= remaining); + remaining -= v[i].iov_len; + evbuffer_ptr_set((struct evbuffer*)input, + &ptr, v[i].iov_len, EVBUFFER_PTR_ADD); + } + } +#else + if (*output) + buf_free(*output); + *output = buf_copy(input); +#endif + return 0; +} + /** Log an error and exit if <b>buf</b> is corrupted. */ void |