aboutsummaryrefslogtreecommitdiffstats
path: root/lib/src
diff options
context:
space:
mode:
Diffstat (limited to 'lib/src')
-rw-r--r--lib/src/CMakeLists.txt3
-rw-r--r--lib/src/common.c73
-rw-r--r--lib/src/ops.c4
-rw-r--r--lib/src/protocol/ah.c4
-rw-r--r--lib/src/protocol/icmp.c4
-rw-r--r--lib/src/protocol/ipv4.c25
-rw-r--r--lib/src/protocol/ipv6.c25
-rw-r--r--lib/src/protocol/new.c5
-rw-r--r--lib/src/protocol/tcp.c29
-rw-r--r--lib/src/protocol/udp.c29
-rw-r--r--lib/src/util/log.c13
-rw-r--r--lib/src/util/pool.c174
-rw-r--r--lib/src/util/ring.c49
-rw-r--r--lib/src/util/vector.c101
14 files changed, 490 insertions, 48 deletions
diff --git a/lib/src/CMakeLists.txt b/lib/src/CMakeLists.txt
index ef74127cc..8e81aa442 100644
--- a/lib/src/CMakeLists.txt
+++ b/lib/src/CMakeLists.txt
@@ -33,6 +33,9 @@ list(APPEND LIBHICN_SOURCE_FILES
protocol/new.c
util/ip_address.c
util/log.c
+ util/pool.c
+ util/ring.c
+ util/vector.c
)
if (WIN32)
diff --git a/lib/src/common.c b/lib/src/common.c
index c4cb8bc3e..362034942 100644
--- a/lib/src/common.c
+++ b/lib/src/common.c
@@ -54,61 +54,44 @@ get_addr_family (const char *ip_address)
/* hashes */
-u32
-cumulative_hash32 (const void *data, size_t len, u32 lastValue)
+// FNV-1a 32-bit http://www.isthe.com/chongo/tech/comp/fnv/
+typedef u_int32_t Fnv32_t;
+#define FNV_32_PRIME ((Fnv32_t) 0x01000193)
+#define FNV1_32_INIT ((Fnv32_t) 0x811c9dc5)
+#define FNV1_32A_INIT FNV1_32_INIT
+
+Fnv32_t
+cumulative_hash32 (const void *buf, size_t len, Fnv32_t hval)
{
- // Standard FNV 32-bit prime: see
- // http://www.isthe.com/chongo/tech/comp/fnv/#FNV-param
- const u32 fnv1a_prime = 0x01000193;
- u32 hash = lastValue;
- size_t i;
-
- const char *chardata = data;
+ unsigned char *bp = (unsigned char *) buf; /* start of buffer */
+ unsigned char *be = bp + len; /* beyond end of buffer */
- for (i = 0; i < len; i++)
+ /*
+ * FNV-1a hash each octet in the buffer
+ */
+ while (bp < be)
{
- hash = hash ^ chardata[i];
- hash = hash * fnv1a_prime;
- }
- return hash;
-}
+ /* xor the bottom with the current octet */
+ hval ^= (Fnv32_t) *bp++;
-u32
-hash32 (const void *data, size_t len)
-{
- // Standard FNV 32-bit offset: see
- // http://www.isthe.com/chongo/tech/comp/fnv/#FNV-param
- const u32 fnv1a_offset = 0x811C9DC5;
- return cumulative_hash32 (data, len, fnv1a_offset);
-}
-
-u64
-cumulative_hash64 (const void *data, size_t len, u64 lastValue)
-{
- // Standard FNV 64-bit prime: see
- // http://www.isthe.com/chongo/tech/comp/fnv/#FNV-param
- const u64 fnv1a_prime = 0x00000100000001B3ULL;
- u64 hash = lastValue;
- const char *chardata = data;
- size_t i;
-
- for (i = 0; i < len; i++)
- {
- hash = hash ^ chardata[i];
- hash = hash * fnv1a_prime;
+ /* multiply by the 32 bit FNV magic prime mod 2^32 */
+#if defined(NO_FNV_GCC_OPTIMIZATION)
+ hval *= FNV_32_PRIME;
+#else
+ hval +=
+ (hval << 1) + (hval << 4) + (hval << 7) + (hval << 8) + (hval << 24);
+#endif
}
- return hash;
+ /* return our new hash value */
+ return hval;
}
-u64
-hash64 (const void *data, size_t len)
+u32
+hash32 (const void *data, size_t len)
{
- // Standard FNV 64-bit offset: see
- // http://www.isthe.com/chongo/tech/comp/fnv/#FNV-param
- const u64 fnv1a_offset = 0xCBF29CE484222325ULL;
- return cumulative_hash64 (data, len, fnv1a_offset);
+ return cumulative_hash32 (data, len, FNV1_32A_INIT);
}
void
diff --git a/lib/src/ops.c b/lib/src/ops.c
index 80ffcf3c5..20362d69d 100644
--- a/lib/src/ops.c
+++ b/lib/src/ops.c
@@ -57,6 +57,10 @@ DECLARE_update_data_pathlabel (none, NONE);
DECLARE_reset_data_for_hash (none, NONE);
DECLARE_get_lifetime (none, NONE);
DECLARE_set_lifetime (none, NONE);
+DECLARE_get_source_port (none, NONE);
+DECLARE_get_dest_port (none, NONE);
+DECLARE_set_source_port (none, NONE);
+DECLARE_set_dest_port (none, NONE);
DECLARE_update_checksums (none, NONE);
DECLARE_verify_checksums (none, NONE);
DECLARE_rewrite_interest (none, NONE);
diff --git a/lib/src/protocol/ah.c b/lib/src/protocol/ah.c
index b3d24161d..c9ed40179 100644
--- a/lib/src/protocol/ah.c
+++ b/lib/src/protocol/ah.c
@@ -45,6 +45,10 @@ DECLARE_set_data_pathlabel (ah, UNEXPECTED);
DECLARE_update_data_pathlabel (ah, UNEXPECTED);
DECLARE_get_lifetime (ah, UNEXPECTED);
DECLARE_set_lifetime (ah, UNEXPECTED);
+DECLARE_get_source_port (ah, UNEXPECTED);
+DECLARE_get_dest_port (ah, UNEXPECTED);
+DECLARE_set_source_port (ah, UNEXPECTED);
+DECLARE_set_dest_port (ah, UNEXPECTED);
DECLARE_get_payload_length (ah, UNEXPECTED);
DECLARE_set_payload_length (ah, UNEXPECTED);
DECLARE_get_payload_type (ah, UNEXPECTED);
diff --git a/lib/src/protocol/icmp.c b/lib/src/protocol/icmp.c
index 0452e4fbb..1fc6c7d2f 100644
--- a/lib/src/protocol/icmp.c
+++ b/lib/src/protocol/icmp.c
@@ -38,6 +38,10 @@ DECLARE_set_data_pathlabel (icmp, UNEXPECTED);
DECLARE_update_data_pathlabel (icmp, UNEXPECTED);
DECLARE_get_lifetime (icmp, UNEXPECTED);
DECLARE_set_lifetime (icmp, UNEXPECTED);
+DECLARE_get_source_port (icmp, UNEXPECTED);
+DECLARE_get_dest_port (icmp, UNEXPECTED);
+DECLARE_set_source_port (icmp, UNEXPECTED);
+DECLARE_set_dest_port (icmp, UNEXPECTED);
DECLARE_get_length (icmp, UNEXPECTED);
DECLARE_get_payload_length (icmp, UNEXPECTED);
DECLARE_set_payload_length (icmp, UNEXPECTED);
diff --git a/lib/src/protocol/ipv4.c b/lib/src/protocol/ipv4.c
index 5d445f018..840fbe34b 100644
--- a/lib/src/protocol/ipv4.c
+++ b/lib/src/protocol/ipv4.c
@@ -228,6 +228,31 @@ ipv4_set_lifetime (hicn_type_t type, hicn_protocol_t *h,
}
int
+ipv4_get_source_port (hicn_type_t type, const hicn_protocol_t *h,
+ u16 *source_port)
+{
+ return CHILD_OPS (get_source_port, type, h, source_port);
+}
+
+int
+ipv4_get_dest_port (hicn_type_t type, const hicn_protocol_t *h, u16 *dest_port)
+{
+ return CHILD_OPS (get_dest_port, type, h, dest_port);
+}
+
+int
+ipv4_set_source_port (hicn_type_t type, hicn_protocol_t *h, u16 source_port)
+{
+ return CHILD_OPS (set_source_port, type, h, source_port);
+}
+
+int
+ipv4_set_dest_port (hicn_type_t type, hicn_protocol_t *h, u16 dest_port)
+{
+ return CHILD_OPS (set_dest_port, type, h, dest_port);
+}
+
+int
ipv4_update_checksums (hicn_type_t type, hicn_protocol_t *h, u16 partial_csum,
size_t payload_length)
{
diff --git a/lib/src/protocol/ipv6.c b/lib/src/protocol/ipv6.c
index b3a107a13..b3c543249 100644
--- a/lib/src/protocol/ipv6.c
+++ b/lib/src/protocol/ipv6.c
@@ -212,6 +212,31 @@ ipv6_set_lifetime (hicn_type_t type, hicn_protocol_t *h,
}
int
+ipv6_get_source_port (hicn_type_t type, const hicn_protocol_t *h,
+ u16 *source_port)
+{
+ return CHILD_OPS (get_source_port, type, h, source_port);
+}
+
+int
+ipv6_get_dest_port (hicn_type_t type, const hicn_protocol_t *h, u16 *dest_port)
+{
+ return CHILD_OPS (get_dest_port, type, h, dest_port);
+}
+
+int
+ipv6_set_source_port (hicn_type_t type, hicn_protocol_t *h, u16 source_port)
+{
+ return CHILD_OPS (set_source_port, type, h, source_port);
+}
+
+int
+ipv6_set_dest_port (hicn_type_t type, hicn_protocol_t *h, u16 dest_port)
+{
+ return CHILD_OPS (set_dest_port, type, h, dest_port);
+}
+
+int
ipv6_update_checksums (hicn_type_t type, hicn_protocol_t *h, u16 partial_csum,
size_t payload_length)
{
diff --git a/lib/src/protocol/new.c b/lib/src/protocol/new.c
index 8c79963ad..07c1d0d76 100644
--- a/lib/src/protocol/new.c
+++ b/lib/src/protocol/new.c
@@ -22,6 +22,11 @@
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-function"
+DECLARE_get_source_port (new, UNEXPECTED);
+DECLARE_get_dest_port (new, UNEXPECTED);
+DECLARE_set_source_port (new, UNEXPECTED);
+DECLARE_set_dest_port (new, UNEXPECTED);
+
static int
is_interest (u8 flags)
{
diff --git a/lib/src/protocol/tcp.c b/lib/src/protocol/tcp.c
index 8097cfd12..82fc461ea 100644
--- a/lib/src/protocol/tcp.c
+++ b/lib/src/protocol/tcp.c
@@ -251,6 +251,35 @@ tcp_set_lifetime (hicn_type_t type, hicn_protocol_t *h,
}
int
+tcp_get_source_port (hicn_type_t type, const hicn_protocol_t *h,
+ u16 *source_port)
+{
+ *source_port = ntohs (h->tcp.sport);
+ return HICN_LIB_ERROR_NONE;
+}
+
+int
+tcp_get_dest_port (hicn_type_t type, const hicn_protocol_t *h, u16 *dest_port)
+{
+ *dest_port = ntohs (h->tcp.dport);
+ return HICN_LIB_ERROR_NONE;
+}
+
+int
+tcp_set_source_port (hicn_type_t type, hicn_protocol_t *h, u16 source_port)
+{
+ h->tcp.sport = htons (source_port);
+ return HICN_LIB_ERROR_NONE;
+}
+
+int
+tcp_set_dest_port (hicn_type_t type, hicn_protocol_t *h, u16 dest_port)
+{
+ h->tcp.dport = htons (dest_port);
+ return HICN_LIB_ERROR_NONE;
+}
+
+int
tcp_update_checksums (hicn_type_t type, hicn_protocol_t *h, u16 partial_csum,
size_t payload_length)
{
diff --git a/lib/src/protocol/udp.c b/lib/src/protocol/udp.c
index ee46b8e9d..7a14b09c2 100644
--- a/lib/src/protocol/udp.c
+++ b/lib/src/protocol/udp.c
@@ -143,6 +143,35 @@ udp_set_lifetime (hicn_type_t type, hicn_protocol_t *h,
}
int
+udp_get_source_port (hicn_type_t type, const hicn_protocol_t *h,
+ u16 *source_port)
+{
+ *source_port = ntohs (h->udp.src_port);
+ return HICN_LIB_ERROR_NONE;
+}
+
+int
+udp_get_dest_port (hicn_type_t type, const hicn_protocol_t *h, u16 *dest_port)
+{
+ *dest_port = ntohs (h->udp.dst_port);
+ return HICN_LIB_ERROR_NONE;
+}
+
+int
+udp_set_source_port (hicn_type_t type, hicn_protocol_t *h, u16 source_port)
+{
+ h->udp.src_port = htons (source_port);
+ return HICN_LIB_ERROR_NONE;
+}
+
+int
+udp_set_dest_port (hicn_type_t type, hicn_protocol_t *h, u16 dest_port)
+{
+ h->udp.dst_port = htons (dest_port);
+ return HICN_LIB_ERROR_NONE;
+}
+
+int
udp_update_checksums (hicn_type_t type, hicn_protocol_t *h, u16 partial_csum,
size_t payload_length)
{
diff --git a/lib/src/util/log.c b/lib/src/util/log.c
index 975762603..91a87e848 100644
--- a/lib/src/util/log.c
+++ b/lib/src/util/log.c
@@ -30,6 +30,10 @@ log_conf_t log_conf = DEFAULT_LOG_CONF;
#define FMT_DATETIME_LEN 20
#define snprintf_nowarn(...) (snprintf (__VA_ARGS__) < 0 ? abort () : (void) 0)
+#define COLOR_RED "\033[31m"
+#define COLOR_YELLOW "\033[33m"
+#define COLOR_RESET "\033[0m"
+
static char ts[FMT_DATETIME_LEN];
static char *
@@ -104,7 +108,7 @@ _log_va (int level, const char *fmt, va_list ap)
}
else
{
- __android_log_vprint (ANDROID_LOG_INFO, "HICN FACEMGR", fmt, ap);
+ __android_log_vprint (prio, "HICN FACEMGR", fmt, ap);
}
#else
@@ -112,6 +116,7 @@ _log_va (int level, const char *fmt, va_list ap)
if (level > log_conf.log_level)
return;
+ char *color = COLOR_RESET;
switch (level)
{
case LOG_FATAL:
@@ -119,9 +124,11 @@ _log_va (int level, const char *fmt, va_list ap)
break;
case LOG_ERROR:
prefix = "ERROR: ";
+ color = COLOR_RED;
break;
case LOG_WARN:
prefix = "WARNING: ";
+ color = COLOR_YELLOW;
break;
case LOG_INFO:
prefix = "";
@@ -137,9 +144,9 @@ _log_va (int level, const char *fmt, va_list ap)
break;
}
FILE *f = log_conf.log_file ? log_conf.log_file : stdout;
- fprintf (f, "%s %s", timestamp (), prefix);
+ fprintf (f, "%s%s %s", color, timestamp (), prefix);
vfprintf (f, fmt, ap);
- fprintf (f, "\n");
+ fprintf (f, "%s\n", COLOR_RESET);
#ifdef DEBUG
fflush (f);
#endif
diff --git a/lib/src/util/pool.c b/lib/src/util/pool.c
new file mode 100644
index 000000000..c6be92ce8
--- /dev/null
+++ b/lib/src/util/pool.c
@@ -0,0 +1,174 @@
+/*
+ * Copyright (c) 2021 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * \file pool.c
+ * \brief Implementation of fixed-size pool allocator.
+ *
+ * NOTE:
+ * - Ideally, we should have a single realloc per resize, that would encompass
+ * both the free indices vector and bitmap, by nesting data structures.
+ * Because of the added complexity, and by lack of evidence of the need for
+ * this, we currently rely on a simpler implementation.
+ */
+
+#include <assert.h>
+#include <stdlib.h> // calloc
+
+#include <hicn/util/pool.h>
+
+#include <stdio.h> // XXX
+
+void
+_pool_init (void **pool_ptr, size_t elt_size, size_t init_size,
+ size_t max_size)
+{
+ assert (pool_ptr);
+ assert (elt_size);
+
+ init_size = next_pow2 (init_size);
+
+ if (max_size && init_size > max_size)
+ goto ERR_MAX_SIZE;
+
+ /* The initial pool size is rounded to the next power of two */
+ size_t alloc_size = next_pow2 (init_size);
+
+ pool_hdr_t *ph = calloc (POOL_HDRLEN + alloc_size * elt_size, 1);
+ if (!ph)
+ goto ERR_MALLOC;
+
+ ph->elt_size = elt_size;
+ ph->alloc_size = alloc_size;
+ ph->max_size = max_size;
+
+ /* Free indices */
+ off_t *free_indices;
+ vector_init (free_indices, init_size, max_size);
+ for (unsigned i = 0; i < init_size; i++)
+ free_indices[i] = (init_size - 1) - i;
+ vector_len (free_indices) = init_size;
+ ph->free_indices = free_indices;
+
+ /* Free bitmap */
+ bitmap_t *fb = ph->free_bitmap;
+ bitmap_init (fb, init_size, max_size);
+ bitmap_set_to (fb, init_size);
+ ph->free_bitmap = fb;
+
+ *pool_ptr = (uint8_t *) ph + POOL_HDRLEN;
+
+ return;
+
+ERR_MALLOC:
+ERR_MAX_SIZE:
+ *pool_ptr = NULL;
+ return;
+}
+
+void
+_pool_free (void **pool_ptr)
+{
+ pool_hdr_t *ph = pool_hdr (*pool_ptr);
+ vector_free (ph->free_indices);
+ bitmap_free (ph->free_bitmap);
+
+ free (pool_hdr (*pool_ptr));
+ *pool_ptr = NULL;
+}
+
+bool
+_pool_validate_id (void **pool_ptr, off_t id)
+{
+ pool_hdr_t *ph = pool_hdr (*pool_ptr);
+ size_t pool_size = pool_get_alloc_size (*pool_ptr);
+ if (id >= pool_size || !bitmap_is_unset (ph->free_bitmap, id))
+ return false;
+
+ return true;
+}
+
+void
+_pool_resize (void **pool_ptr, size_t elt_size)
+{
+ pool_hdr_t *ph = pool_hdr (*pool_ptr);
+ size_t old_size = ph->alloc_size;
+ size_t new_size = old_size * 2;
+
+ WARN ("pool_resize to %lu", new_size);
+
+ if (ph->max_size && new_size > ph->max_size)
+ goto ERR_MAX_SIZE;
+
+ /* Double pool storage */
+ ph = realloc (ph, POOL_HDRLEN + new_size * elt_size);
+ if (!ph)
+ goto ERR_REALLOC;
+ ph->elt_size = elt_size;
+ ph->alloc_size = new_size;
+
+ /*
+ * After resize, the pool will have new free indices, ranging from
+ * old_size to (new_size - 1)
+ */
+ vector_ensure_pos (ph->free_indices, old_size);
+ for (unsigned i = 0; i < old_size; i++)
+ ph->free_indices[i] = new_size - 1 - i;
+ vector_len (ph->free_indices) = old_size;
+
+ /* We also need to update the bitmap */
+ bitmap_ensure_pos (&(ph->free_bitmap), new_size - 1);
+ bitmap_set_range (ph->free_bitmap, old_size, new_size - 1);
+
+ /* Reassign pool pointer */
+ *pool_ptr = (uint8_t *) ph + POOL_HDRLEN;
+
+ return;
+
+ERR_REALLOC:
+ERR_MAX_SIZE:
+ *pool_ptr = NULL;
+ return;
+}
+
+off_t
+_pool_get (void **pool_ptr, void **elt, size_t elt_size)
+{
+ pool_hdr_t *ph = pool_hdr (*pool_ptr);
+ uint64_t l = vector_len (ph->free_indices);
+ if (l == 0)
+ {
+ _pool_resize (pool_ptr, elt_size);
+ ph = pool_hdr (*pool_ptr);
+ l = vector_len (ph->free_indices);
+ }
+ off_t free_id = ph->free_indices[l - 1];
+ vector_len (ph->free_indices)--;
+ bitmap_unset (ph->free_bitmap, free_id);
+ *elt = *pool_ptr + free_id * elt_size;
+ return free_id;
+}
+
+void
+_pool_put (void **pool_ptr, void **elt, size_t elt_size)
+{
+ pool_hdr_t *ph = pool_hdr (*pool_ptr);
+ uint64_t l = vector_len (ph->free_indices);
+ vector_ensure_pos (ph->free_indices, l);
+ off_t freed_id = (*elt - *pool_ptr) / elt_size;
+ ph->free_indices[l] = freed_id;
+ vector_len (ph->free_indices)++;
+ bitmap_set (ph->free_bitmap, freed_id);
+}
diff --git a/lib/src/util/ring.c b/lib/src/util/ring.c
new file mode 100644
index 000000000..2c722a842
--- /dev/null
+++ b/lib/src/util/ring.c
@@ -0,0 +1,49 @@
+
+/*
+ * Copyright (c) 2021 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * \file ring.c
+ * \brief Implementation of ring buffer.
+ */
+
+#include <stdlib.h>
+
+#include <hicn/util/ring.h>
+
+void
+_ring_init (void **ring_ptr, size_t elt_size, size_t max_size)
+{
+ assert (ring_ptr);
+ assert (elt_size > 0);
+ // we use a static array, not a vector (for now)
+ assert (max_size != 0);
+
+ ring_hdr_t *rh = malloc (RING_HDRLEN + max_size * elt_size);
+
+ rh->roff = 0;
+ rh->woff = 0;
+ rh->size = 0;
+ rh->max_size = max_size;
+
+ *ring_ptr = (uint8_t *) rh + RING_HDRLEN;
+}
+
+void
+_ring_free (void **ring_ptr)
+{
+ free (ring_hdr (*ring_ptr));
+ *ring_ptr = NULL;
+}
diff --git a/lib/src/util/vector.c b/lib/src/util/vector.c
new file mode 100644
index 000000000..1f5cd0269
--- /dev/null
+++ b/lib/src/util/vector.c
@@ -0,0 +1,101 @@
+/*
+ * Copyright (c) 2021 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * \file vector.c
+ * \brief Implementation of resizeable static array
+ */
+
+#include <assert.h>
+#include <stddef.h> // size_t
+#include <stdlib.h> // calloc
+#include <stdio.h>
+
+#include <hicn/util/vector.h>
+
+#define DEFAULT_VECTOR_SIZE 64
+
+int
+_vector_init (void **vector_ptr, size_t elt_size, size_t init_size,
+ size_t max_size)
+{
+ assert (vector_ptr);
+ assert (max_size == 0 || init_size < max_size);
+
+ if (init_size == 0)
+ init_size = DEFAULT_VECTOR_SIZE;
+
+ *vector_ptr = NULL;
+ int rc = _vector_resize (vector_ptr, elt_size, init_size);
+ if (rc < 0)
+ return -1;
+
+ vector_hdr_t *vh = vector_hdr (*vector_ptr);
+ vh->cur_size = 0;
+ vh->max_size = max_size;
+
+ return 0;
+}
+
+void
+_vector_free (void **vector_ptr)
+{
+ free (vector_hdr (*vector_ptr));
+ *vector_ptr = NULL;
+}
+
+int
+_vector_resize (void **vector_ptr, size_t elt_size, off_t pos)
+{
+ vector_hdr_t *vh;
+ size_t old_size;
+
+ if (*vector_ptr)
+ {
+ vh = vector_hdr (*vector_ptr);
+ old_size = vh->alloc_size;
+ }
+ else
+ {
+ vh = NULL;
+ old_size = 0;
+ }
+
+ /* Round the allocated size to the next power of 2 of the requested position
+ */
+ size_t new_size = next_pow2 (pos);
+
+ /* Don't grow the vector back */
+ if (new_size < old_size)
+ return 0;
+
+ /* Don't exceed maximum size (for init, check is done beforehand) */
+ if (vh && vh->max_size && new_size > vh->max_size)
+ return -1;
+
+ vh = realloc (vh, VECTOR_HDRLEN + new_size * elt_size);
+ if (!vh)
+ return -1;
+ vh->alloc_size = new_size;
+
+ /* Zero out the newly allocated memory (except headers) */
+ memset ((uint8_t *) vh + VECTOR_HDRLEN + old_size * elt_size, 0,
+ (new_size - old_size) * elt_size);
+
+ /* Reassign vector pointer */
+ *vector_ptr = (uint8_t *) vh + VECTOR_HDRLEN;
+
+ return 0;
+}