src/utils_array.c: Fix a segfault in "array_prepend".
[collection4.git] / src / utils_array.c
1 #include <stdlib.h>
2 #include <stdio.h>
3 #include <stdarg.h>
4 #include <string.h>
5 #include <errno.h>
6
7 #include "utils_array.h"
8
9 struct str_array_s
10 {
11   char **ptr;
12   size_t size;
13 };
14
15 static int sort_callback (const void *v0, const void *v1) /* {{{ */
16 {
17   const char *c0 = v0;
18   const char *c1 = v1;
19
20   return (strcmp (c0, c1));
21 } /* }}} int sort_callback */
22
23 str_array_t *array_create (void) /* {{{ */
24 {
25   str_array_t *a;
26
27   a = malloc (sizeof (*a));
28   if (a == NULL)
29     return (NULL);
30
31   memset (a, 0, sizeof (*a));
32   a->ptr = NULL;
33   a->size = 0;
34
35   return (a);
36 } /* }}} str_array_t *array_create */
37
38 void array_destroy (str_array_t *a) /* {{{ */
39 {
40   if (a == NULL)
41     return;
42
43   free (a->ptr);
44   a->ptr = NULL;
45   a->size = 0;
46
47   free (a);
48 } /* }}} void array_destroy */
49
50 int array_append (str_array_t *a, const char *entry) /* {{{ */
51 {
52   char **ptr;
53
54   if ((entry == NULL) || (a == NULL))
55     return (EINVAL);
56
57   ptr = realloc (a->ptr, sizeof (*a->ptr) * (a->size + 1));
58   if (ptr == NULL)
59     return (ENOMEM);
60   a->ptr = ptr;
61   ptr = a->ptr + a->size;
62
63   *ptr = strdup (entry);
64   if (*ptr == NULL)
65     return (ENOMEM);
66
67   a->size++;
68   return (0);
69 } /* }}} int array_append */
70
71 int array_append_format (str_array_t *a, const char *format, ...) /* {{{ */
72 {
73   char buffer[1024];
74   va_list ap;
75   int status;
76
77   va_start (ap, format);
78   status = vsnprintf (buffer, sizeof (buffer), format, ap);
79   va_end(ap);
80
81   if ((status < 0) || (((size_t) status) >= sizeof (buffer)))
82     return (ENOMEM);
83
84   return (array_append (a, buffer));
85 } /* }}} int array_append_format */
86
87 int array_prepend (str_array_t *a, const char *entry) /* {{{ */
88 {
89   char **ptr;
90   char *cpy;
91
92   if ((entry == NULL) || (a == NULL))
93     return (EINVAL);
94
95   cpy = strdup (entry);
96   if (cpy == NULL)
97     return (ENOMEM);
98
99   ptr = realloc (a->ptr, sizeof (*a->ptr) * (a->size + 1));
100   if (ptr == NULL)
101   {
102     free (cpy);
103     return (ENOMEM);
104   }
105   a->ptr = ptr;
106
107   memmove (a->ptr + 1, a->ptr, sizeof (*a->ptr) * a->size);
108   a->ptr[0] = cpy;
109   a->size++;
110
111   return (0);
112 } /* }}} int array_prepend */
113
114 int array_prepend_format (str_array_t *a, const char *format, ...) /* {{{ */
115 {
116   char buffer[1024];
117   va_list ap;
118   int status;
119
120   va_start (ap, format);
121   status = vsnprintf (buffer, sizeof (buffer), format, ap);
122   va_end(ap);
123
124   if ((status < 0) || (((size_t) status) >= sizeof (buffer)))
125     return (ENOMEM);
126
127   return (array_prepend (a, buffer));
128 } /* }}} int array_prepend_format */
129
130 int array_sort (str_array_t *a) /* {{{ */
131 {
132   if (a == NULL)
133     return (EINVAL);
134
135   qsort (a->ptr, a->size, sizeof (*a->ptr), sort_callback);
136
137   return (0);
138 } /* }}} int array_sort */
139
140 int array_argc (str_array_t *a) /* {{{ */
141 {
142   if (a == NULL)
143     return (-1);
144
145   return ((int) a->size);
146 } /* }}} int array_argc */
147
148 char **array_argv (str_array_t *a) /* {{{ */
149 {
150   if ((a == NULL) || (a->size == 0))
151     return (NULL);
152
153   return (a->ptr);
154 } /* }}} char **array_argv */
155
156 /* vim: set sw=2 sts=2 et fdm=marker : */