diff options
Diffstat (limited to 'src/ot_iovec.c')
| -rw-r--r-- | src/ot_iovec.c | 87 |
1 files changed, 87 insertions, 0 deletions
diff --git a/src/ot_iovec.c b/src/ot_iovec.c new file mode 100644 index 0000000..328f160 --- /dev/null +++ b/src/ot_iovec.c | |||
| @@ -0,0 +1,87 @@ | |||
| 1 | /* This software was written by Dirk Engling <erdgeist@erdgeist.org> | ||
| 2 | It is considered beerware. Prost. Skol. Cheers or whatever. */ | ||
| 3 | |||
| 4 | /* System */ | ||
| 5 | #include <stdlib.h> | ||
| 6 | #include <sys/uio.h> | ||
| 7 | |||
| 8 | /* Opentracker */ | ||
| 9 | #include "ot_iovec.h" | ||
| 10 | |||
| 11 | void *iovec_new_chunk(size_t *iovec_entries, struct iovec **iovector, size_t new_alloc) { | ||
| 12 | void *new_data; | ||
| 13 | size_t new_entries = 1 + *iovec_entries; | ||
| 14 | struct iovec *new_vec = realloc(*iovector, new_entries * sizeof(struct iovec)); | ||
| 15 | |||
| 16 | if (!new_vec) | ||
| 17 | return NULL; | ||
| 18 | |||
| 19 | *iovector = new_vec; | ||
| 20 | |||
| 21 | /* Only allocate after we have a place to store the pointer */ | ||
| 22 | new_data = malloc(new_alloc); | ||
| 23 | if (!new_data) | ||
| 24 | return NULL; | ||
| 25 | |||
| 26 | new_vec[new_entries - 1].iov_base = new_data; | ||
| 27 | new_vec[new_entries - 1].iov_len = new_alloc; | ||
| 28 | |||
| 29 | ++*iovec_entries; | ||
| 30 | return new_data; | ||
| 31 | } | ||
| 32 | |||
| 33 | void *iovec_append(size_t *iovec_entries, struct iovec **iovector, struct iovec *append_iovector) { | ||
| 34 | size_t new_entries = *iovec_entries + 1; | ||
| 35 | struct iovec *new_vec = realloc(*iovector, new_entries * sizeof(struct iovec)); | ||
| 36 | if (!new_vec) | ||
| 37 | return NULL; | ||
| 38 | |||
| 39 | /* Take over data from appended iovec */ | ||
| 40 | new_vec[*iovec_entries].iov_base = append_iovector->iov_base; | ||
| 41 | new_vec[*iovec_entries].iov_len = append_iovector->iov_len; | ||
| 42 | |||
| 43 | append_iovector->iov_base = NULL; | ||
| 44 | append_iovector->iov_len = 0; | ||
| 45 | |||
| 46 | *iovector = new_vec; | ||
| 47 | *iovec_entries = new_entries; | ||
| 48 | |||
| 49 | return new_vec; | ||
| 50 | } | ||
| 51 | |||
| 52 | void iovec_free(size_t *iovec_entries, struct iovec **iovector) { | ||
| 53 | size_t i; | ||
| 54 | for (i = 0; i < *iovec_entries; ++i) | ||
| 55 | free(((*iovector)[i]).iov_base); | ||
| 56 | free(*iovector); | ||
| 57 | *iovector = NULL; | ||
| 58 | *iovec_entries = 0; | ||
| 59 | } | ||
| 60 | |||
| 61 | void iovec_trim_last(size_t *iovec_entries, struct iovec **iovector, void *last_ptr) { | ||
| 62 | if (*iovec_entries) { | ||
| 63 | char *base = (char *)((*iovector)[*iovec_entries - 1]).iov_base; | ||
| 64 | size_t new_alloc = ((char *)last_ptr) - base; | ||
| 65 | |||
| 66 | ((*iovector)[*iovec_entries - 1]).iov_base = realloc(base, new_alloc); | ||
| 67 | ((*iovector)[*iovec_entries - 1]).iov_len = new_alloc; | ||
| 68 | } | ||
| 69 | } | ||
| 70 | |||
| 71 | void *iovec_next_chunk(size_t *iovec_entries, struct iovec **iovector, void *last_ptr, size_t new_alloc) { | ||
| 72 | void *new_data; | ||
| 73 | |||
| 74 | iovec_trim_last(iovec_entries, iovector, last_ptr); | ||
| 75 | |||
| 76 | if (!(new_data = iovec_new_chunk(iovec_entries, iovector, new_alloc))) | ||
| 77 | iovec_free(iovec_entries, iovector); | ||
| 78 | |||
| 79 | return new_data; | ||
| 80 | } | ||
| 81 | |||
| 82 | size_t iovec_length(const size_t *iovec_entries, const struct iovec **iovector) { | ||
| 83 | size_t i, length = 0; | ||
| 84 | for (i = 0; i < *iovec_entries; ++i) | ||
| 85 | length += ((*iovector)[i]).iov_len; | ||
| 86 | return length; | ||
| 87 | } | ||
