aboutsummaryrefslogtreecommitdiff
path: root/src/garray.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/garray.c')
-rw-r--r--src/garray.c144
1 files changed, 144 insertions, 0 deletions
diff --git a/src/garray.c b/src/garray.c
new file mode 100644
index 0000000000..ebd6748e78
--- /dev/null
+++ b/src/garray.c
@@ -0,0 +1,144 @@
+/*
+ * Functions for handling growing arrays.
+ */
+
+#include "vim.h"
+#include "ascii.h"
+#include "misc2.h"
+#include "garray.h"
+//#include "globals.h"
+#include "memline.h"
+
+/*
+ * Clear an allocated growing array.
+ */
+void ga_clear(garray_T *gap)
+{
+ vim_free(gap->ga_data);
+ ga_init(gap);
+}
+
+/*
+ * Clear a growing array that contains a list of strings.
+ */
+void ga_clear_strings(garray_T *gap)
+{
+ int i;
+
+ for (i = 0; i < gap->ga_len; ++i)
+ vim_free(((char_u **)(gap->ga_data))[i]);
+ ga_clear(gap);
+}
+
+/*
+ * Initialize a growing array. Don't forget to set ga_itemsize and
+ * ga_growsize! Or use ga_init2().
+ */
+void ga_init(garray_T *gap)
+{
+ gap->ga_data = NULL;
+ gap->ga_maxlen = 0;
+ gap->ga_len = 0;
+}
+
+void ga_init2(garray_T *gap, int itemsize, int growsize)
+{
+ ga_init(gap);
+ gap->ga_itemsize = itemsize;
+ gap->ga_growsize = growsize;
+}
+
+/*
+ * Make room in growing array "gap" for at least "n" items.
+ * Return FAIL for failure, OK otherwise.
+ */
+int ga_grow(garray_T *gap, int n)
+{
+ size_t old_len;
+ size_t new_len;
+ char_u *pp;
+
+ if (gap->ga_maxlen - gap->ga_len < n) {
+ if (n < gap->ga_growsize)
+ n = gap->ga_growsize;
+ new_len = gap->ga_itemsize * (gap->ga_len + n);
+ pp = (gap->ga_data == NULL)
+ ? alloc((unsigned)new_len) : vim_realloc(gap->ga_data, new_len);
+ if (pp == NULL)
+ return FAIL;
+ old_len = gap->ga_itemsize * gap->ga_maxlen;
+ vim_memset(pp + old_len, 0, new_len - old_len);
+ gap->ga_maxlen = gap->ga_len + n;
+ gap->ga_data = pp;
+ }
+ return OK;
+}
+
+/*
+ * For a growing array that contains a list of strings: concatenate all the
+ * strings with a separating comma.
+ * Returns NULL when out of memory.
+ */
+char_u *ga_concat_strings(garray_T *gap)
+{
+ int i;
+ int len = 0;
+ char_u *s;
+
+ for (i = 0; i < gap->ga_len; ++i)
+ len += (int)STRLEN(((char_u **)(gap->ga_data))[i]) + 1;
+
+ s = alloc(len + 1);
+ if (s != NULL) {
+ *s = NUL;
+ for (i = 0; i < gap->ga_len; ++i) {
+ if (*s != NUL)
+ STRCAT(s, ",");
+ STRCAT(s, ((char_u **)(gap->ga_data))[i]);
+ }
+ }
+ return s;
+}
+
+/*
+ * Concatenate a string to a growarray which contains characters.
+ * Note: Does NOT copy the NUL at the end!
+ */
+void ga_concat(garray_T *gap, char_u *s)
+{
+ int len = (int)STRLEN(s);
+
+ if (ga_grow(gap, len) == OK) {
+ mch_memmove((char *)gap->ga_data + gap->ga_len, s, (size_t)len);
+ gap->ga_len += len;
+ }
+}
+
+/*
+ * Append one byte to a growarray which contains bytes.
+ */
+void ga_append(garray_T *gap, int c)
+{
+ if (ga_grow(gap, 1) == OK) {
+ *((char *)gap->ga_data + gap->ga_len) = c;
+ ++gap->ga_len;
+ }
+}
+
+#if (defined(UNIX) && !defined(USE_SYSTEM)) || defined(WIN3264)
+/*
+ * Append the text in "gap" below the cursor line and clear "gap".
+ */
+void append_ga_line(garray_T *gap)
+{
+ /* Remove trailing CR. */
+ if (gap->ga_len > 0
+ && !curbuf->b_p_bin
+ && ((char_u *)gap->ga_data)[gap->ga_len - 1] == CAR)
+ --gap->ga_len;
+ ga_append(gap, NUL);
+ ml_append(curwin->w_cursor.lnum++, gap->ga_data, 0, FALSE);
+ gap->ga_len = 0;
+}
+#endif
+