aboutsummaryrefslogtreecommitdiff
path: root/src/nvim/lib
diff options
context:
space:
mode:
authorZyX <kp-pav@yandex.ru>2016-05-01 06:27:11 +0300
committerZyX <kp-pav@yandex.ru>2016-05-30 23:34:28 +0300
commitd9137b1a3aca67072aac7c020658278a9334640a (patch)
treeb13b5474459c8e854b85f9ea914ead69b550dbf0 /src/nvim/lib
parent139c1bb48b3754533e1766f2e80b0f0af42172e2 (diff)
downloadrneovim-d9137b1a3aca67072aac7c020658278a9334640a.tar.gz
rneovim-d9137b1a3aca67072aac7c020658278a9334640a.tar.bz2
rneovim-d9137b1a3aca67072aac7c020658278a9334640a.zip
kvec,typval_encode: Add new vector: the one with preallocated array
Diffstat (limited to 'src/nvim/lib')
-rw-r--r--src/nvim/lib/kvec.h94
1 files changed, 94 insertions, 0 deletions
diff --git a/src/nvim/lib/kvec.h b/src/nvim/lib/kvec.h
index dcc69f7b26..36c91c86b2 100644
--- a/src/nvim/lib/kvec.h
+++ b/src/nvim/lib/kvec.h
@@ -38,6 +38,7 @@
#define NVIM_LIB_KVEC_H
#include <stdlib.h>
+#include <string.h>
#include "nvim/memory.h"
@@ -96,4 +97,97 @@
: 0)), \
(v).items[(i)])
+/// Type of a vector with a few first members allocated on stack
+///
+/// Is compatible with #kv_A, #kv_pop, #kv_size, #kv_max, #kv_last.
+/// Is not compatible with #kv_resize, #kv_resize_full, #kv_copy, #kv_push,
+/// #kv_pushp, #kv_a, #kv_destroy.
+///
+/// @param[in] type Type of vector elements.
+/// @param[in] init_size Number of the elements in the initial array.
+#define kvec_withinit_t(type, INIT_SIZE) \
+ struct { \
+ size_t size; \
+ size_t capacity; \
+ type *items; \
+ type init_array[INIT_SIZE]; \
+ }
+
+/// Initialize vector with preallocated array
+///
+/// @param[out] v Vector to initialize.
+#define kvi_init(v) \
+ ((v).capacity = ARRAY_SIZE((v).init_array), \
+ (v).size = 0, \
+ (v).items = (v).init_array)
+
+/// Move data to a new destination and free source
+static inline void *_memcpy_free(void *const restrict dest,
+ void *const restrict src,
+ const size_t size)
+ FUNC_ATTR_NONNULL_ALL FUNC_ATTR_NONNULL_RET FUNC_ATTR_ALWAYS_INLINE
+{
+ memcpy(dest, src, size);
+ xfree(src);
+ return dest;
+}
+
+/// Resize vector with preallocated array
+///
+/// @param[out] v Vector to resize.
+/// @param[in] s New size.
+#define kvi_resize(v, s) \
+ ((v).capacity = ((s) > ARRAY_SIZE((v).init_array) \
+ ? (s) \
+ : ARRAY_SIZE((v).init_array)), \
+ (v).items = ((v).capacity == ARRAY_SIZE((v).init_array) \
+ ? ((v).items == (v).init_array \
+ ? (v).items \
+ : _memcpy_free((v).init_array, (v).items, \
+ (v).size * sizeof((v).items[0]))) \
+ : ((v).items == (v).init_array \
+ ? memcpy(xmalloc((v).capacity * sizeof((v).items[0])), \
+ (v).items, \
+ (v).size * sizeof((v).items[0])) \
+ : xrealloc((v).items, \
+ (v).capacity * sizeof((v).items[0])))))
+
+/// Resize vector with preallocated array when it is full
+///
+/// @param[out] v Vector to resize.
+#define kvi_resize_full(v) \
+ /* ARRAY_SIZE((v).init_array) is the minimal capacity of this vector. */ \
+ /* Thus when vector is full capacity may not be zero and it is safe */ \
+ /* not to bother with checking whether (v).capacity is 0. But now */ \
+ /* capacity is not guaranteed to have size that is a power of 2. */ \
+ kvi_resize(v, ((v).capacity == ARRAY_SIZE((v).init_array) \
+ ? ((v).capacity++, kv_roundup32((v).capacity)) \
+ : (v).capacity << 1))
+
+/// Get location where to store new element to a vector with preallocated array
+///
+/// @param[in,out] v Vector to push to.
+///
+/// @return Pointer to the place where new value should be stored.
+#define kvi_pushp(v) \
+ ((((v).size == (v).capacity) ? (kvi_resize_full(v), 0) : 0), \
+ ((v).items + ((v).size++)))
+
+/// Push value to a vector with preallocated array
+///
+/// @param[out] v Vector to push to.
+/// @param[in] x Value to push.
+#define kvi_push(v, x) \
+ (*kvi_pushp(v) = (x))
+
+/// Free array of elements of a vector with preallocated array if needed
+///
+/// @param[out] v Vector to free.
+#define kvi_destroy(v) \
+ do { \
+ if ((v).items != (v).init_array) { \
+ xfree((v).items); \
+ } \
+ } while (0)
+
#endif // NVIM_LIB_KVEC_H