CVector  4.1.0
A C++ style vector library in strict ANSI C (C89)
cvector_str.c
Go to the documentation of this file.
1 #include "cvector_str.h"
2 
3 
4 
5 #if defined(CVEC_MALLOC) && defined(CVEC_FREE) && defined(CVEC_REALLOC)
6 /* ok */
7 #elif !defined(CVEC_MALLOC) && !defined(CVEC_FREE) && !defined(CVEC_REALLOC)
8 /* ok */
9 #else
10 #error "Must define all or none of CVEC_MALLOC, CVEC_FREE, and CVEC_REALLOC."
11 #endif
12 
13 #ifndef CVEC_MALLOC
14 #define CVEC_MALLOC(sz) malloc(sz)
15 #define CVEC_REALLOC(p, sz) realloc(p, sz)
16 #define CVEC_FREE(p) free(p)
17 #endif
18 
19 #ifndef CVEC_MEMMOVE
20 #include <string.h>
21 #define CVEC_MEMMOVE(dst, src, sz) memmove(dst, src, sz)
22 #endif
23 
24 #ifndef CVEC_ASSERT
25 #include <assert.h>
26 #define CVEC_ASSERT(x) assert(x)
27 #endif
28 
30 
31 #define CVEC_STR_ALLOCATOR(x) ((x+1) * 2)
32 
33 #if CVEC_STRDUP == cvec_strdup
35 char* cvec_strdup(const char* str)
36 {
37  cvec_sz len;
38  char* temp;
39  if (!str)
40  return NULL;
41 
42  len = strlen(str);
43  temp = (char*)CVEC_MALLOC(len+1);
44  if (!temp) {
45  CVEC_ASSERT(temp != NULL);
46  return NULL;
47  }
48  temp[len] = 0;
49 
50  return (char*)CVEC_MEMMOVE(temp, str, len); /* CVEC_MEMMOVE returns to */
51 }
52 #endif
53 
65 {
66  cvector_str* vec;
67  if (!(vec = (cvector_str*)CVEC_MALLOC(sizeof(cvector_str)))) {
68  CVEC_ASSERT(vec != NULL);
69  return NULL;
70  }
71 
72  vec->size = size;
73  vec->capacity = (capacity > vec->size || (vec->size && capacity == vec->size)) ? capacity : vec->size + CVEC_STR_START_SZ;
74 
75  if (!(vec->a = (char**)CVEC_MALLOC(vec->capacity * sizeof(char*)))) {
76  CVEC_ASSERT(vec->a != NULL);
77  CVEC_FREE(vec);
78  return NULL;
79  }
80  /* clearing to 0 here because if the user gave a non-zero initial size, popping/
81  * erasing will crash unless they're NULL. Really the user should never do that.
82  * They should use cvec_init or otherwise immediately assign to the size elements they
83  * started with. */
84  memset(vec->a, 0, vec->capacity*sizeof(char*));
85 
86  return vec;
87 }
88 
92 {
93  cvector_str* vec;
94  cvec_sz i;
95 
96  if (!(vec = (cvector_str*)CVEC_MALLOC(sizeof(cvector_str)))) {
97  CVEC_ASSERT(vec != NULL);
98  return NULL;
99  }
100 
101  vec->capacity = num + CVEC_STR_START_SZ;
102  vec->size = num;
103  if (!(vec->a = (char**)CVEC_MALLOC(vec->capacity*sizeof(char*)))) {
104  CVEC_ASSERT(vec->a != NULL);
105  CVEC_FREE(vec);
106  return NULL;
107  }
108 
109  for(i=0; i<num; i++) {
110  vec->a[i] = CVEC_STRDUP(vals[i]);
111  }
112 
113  return vec;
114 }
115 
120 int cvec_str(cvector_str* vec, cvec_sz size, cvec_sz capacity)
121 {
122  vec->size = size;
123  vec->capacity = (capacity > vec->size || (vec->size && capacity == vec->size)) ? capacity : vec->size + CVEC_STR_START_SZ;
124 
125  if (!(vec->a = (char**)CVEC_MALLOC(vec->capacity * sizeof(char*)))) {
126  CVEC_ASSERT(vec->a != NULL);
127  vec->size = vec->capacity = 0;
128  return 0;
129  }
130  /* clearing to 0 here because if the user gave a non-zero initial size, popping/
131  * erasing will crash unless they're NULL */
132  memset(vec->a, 0, vec->capacity*sizeof(char*));
133 
134  return 1;
135 }
136 
140 int cvec_init_str(cvector_str* vec, char** vals, cvec_sz num)
141 {
142  cvec_sz i;
143 
144  vec->capacity = num + CVEC_STR_START_SZ;
145  vec->size = num;
146  if (!(vec->a = (char**)CVEC_MALLOC(vec->capacity*sizeof(char*)))) {
147  CVEC_ASSERT(vec->a != NULL);
148  vec->size = vec->capacity = 0;
149  return 0;
150  }
151 
152  for(i=0; i<num; i++) {
153  vec->a[i] = CVEC_STRDUP(vals[i]);
154  }
155 
156  return 1;
157 }
158 
169 int cvec_copyc_str(void* dest, void* src)
170 {
171  cvector_str* vec1 = (cvector_str*)dest;
172  cvector_str* vec2 = (cvector_str*)src;
173 
174  vec1->a = NULL;
175  vec1->size = 0;
176  vec1->capacity = 0;
177 
178  return cvec_copy_str(vec1, vec2);
179 }
180 
191 {
192  int i;
193  char** tmp = NULL;
194  if (!(tmp = (char**)CVEC_REALLOC(dest->a, src->capacity*sizeof(char*)))) {
195  CVEC_ASSERT(tmp != NULL);
196  return 0;
197  }
198  dest->a = tmp;
199 
200  for (i=0; i<src->size; ++i) {
201  dest->a[i] = CVEC_STRDUP(src->a[i]);
202  }
203  dest->size = src->size;
204  dest->capacity = src->capacity;
205  return 1;
206 }
207 
212 int cvec_push_str(cvector_str* vec, char* a)
213 {
214  char** tmp;
215  cvec_sz tmp_sz;
216  if (vec->capacity == vec->size) {
217  tmp_sz = CVEC_STR_ALLOCATOR(vec->capacity);
218  if (!(tmp = (char**)CVEC_REALLOC(vec->a, sizeof(char*)*tmp_sz))) {
219  CVEC_ASSERT(tmp != NULL);
220  return 0;
221  }
222  vec->a = tmp;
223  vec->capacity = tmp_sz;
224  }
225 
226  vec->a[vec->size++] = CVEC_STRDUP(a);
227  return 1;
228 }
229 
231 int cvec_pushm_str(cvector_str* vec, char* a)
232 {
233  char** tmp;
234  cvec_sz tmp_sz;
235  if (vec->capacity == vec->size) {
236  tmp_sz = CVEC_STR_ALLOCATOR(vec->capacity);
237  if (!(tmp = (char**)CVEC_REALLOC(vec->a, sizeof(char*)*tmp_sz))) {
238  CVEC_ASSERT(tmp != NULL);
239  return 0;
240  }
241  vec->a = tmp;
242  vec->capacity = tmp_sz;
243  }
244 
245  vec->a[vec->size++] = a;
246  return 1;
247 }
248 
253 void cvec_pop_str(cvector_str* vec, char* ret)
254 {
255  vec->size--;
256  if (ret)
257  strcpy(ret, vec->a[vec->size]);
258  CVEC_FREE(vec->a[vec->size]);
259 }
260 
263 {
264  return &vec->a[vec->size-1];
265 }
266 
271 {
272  char** tmp;
273  cvec_sz tmp_sz;
274  if (vec->capacity < vec->size + num) {
275  tmp_sz = vec->capacity + num + CVEC_STR_START_SZ;
276  if (!(tmp = (char**)CVEC_REALLOC(vec->a, sizeof(char*)*tmp_sz))) {
277  CVEC_ASSERT(tmp != NULL);
278  return 0;
279  }
280  vec->a = tmp;
281  vec->capacity = tmp_sz;
282  }
283 
284  memset(&vec->a[vec->size], 0, num*sizeof(char*));
285  vec->size += num;
286  return 1;
287 }
288 
293 int cvec_insert_str(cvector_str* vec, cvec_sz i, char* a)
294 {
295  char** tmp;
296  cvec_sz tmp_sz;
297  if (vec->capacity == vec->size) {
298  tmp_sz = CVEC_STR_ALLOCATOR(vec->capacity);
299  if (!(tmp = (char**)CVEC_REALLOC(vec->a, sizeof(char*)*tmp_sz))) {
300  CVEC_ASSERT(tmp != NULL);
301  return 0;
302  }
303  vec->a = tmp;
304  vec->capacity = tmp_sz;
305  }
306 
307  CVEC_MEMMOVE(&vec->a[i+1], &vec->a[i], (vec->size-i)*sizeof(char*));
308  vec->a[i] = CVEC_STRDUP(a);
309  vec->size++;
310  return 1;
311 }
312 
316 int cvec_insertm_str(cvector_str* vec, cvec_sz i, char* a)
317 {
318  char** tmp;
319  cvec_sz tmp_sz;
320  if (vec->capacity == vec->size) {
321  tmp_sz = CVEC_STR_ALLOCATOR(vec->capacity);
322  if (!(tmp = (char**)CVEC_REALLOC(vec->a, sizeof(char*)*tmp_sz))) {
323  CVEC_ASSERT(tmp != NULL);
324  return 0;
325  }
326  vec->a = tmp;
327  vec->capacity = tmp_sz;
328  }
329 
330  CVEC_MEMMOVE(&vec->a[i+1], &vec->a[i], (vec->size-i)*sizeof(char*));
331  vec->a[i] = a;
332  vec->size++;
333  return 1;
334 }
335 
342 {
343  char** tmp;
344  cvec_sz tmp_sz, j;
345  if (vec->capacity < vec->size + num) {
346  tmp_sz = vec->capacity + num + CVEC_STR_START_SZ;
347  if (!(tmp = (char**)CVEC_REALLOC(vec->a, sizeof(char*)*tmp_sz))) {
348  CVEC_ASSERT(tmp != NULL);
349  return 0;
350  }
351  vec->a = tmp;
352  vec->capacity = tmp_sz;
353  }
354 
355  CVEC_MEMMOVE(&vec->a[i+num], &vec->a[i], (vec->size-i)*sizeof(char*));
356  for (j=0; j<num; ++j) {
357  vec->a[j+i] = CVEC_STRDUP(a[j]);
358  }
359 
360  vec->size += num;
361  return 1;
362 }
363 
368 {
369  char** tmp;
370  cvec_sz tmp_sz;
371  if (vec->capacity < vec->size + num) {
372  tmp_sz = vec->capacity + num + CVEC_STR_START_SZ;
373  if (!(tmp = (char**)CVEC_REALLOC(vec->a, sizeof(char*)*tmp_sz))) {
374  CVEC_ASSERT(tmp != NULL);
375  return 0;
376  }
377  vec->a = tmp;
378  vec->capacity = tmp_sz;
379  }
380 
381  CVEC_MEMMOVE(&vec->a[i+num], &vec->a[i], (vec->size-i)*sizeof(char*));
382 
383  CVEC_MEMMOVE(&vec->a[i], a, num*sizeof(char*));
384  vec->size += num;
385  return 1;
386 }
387 
392 void cvec_replace_str(cvector_str* vec, cvec_sz i, char* a, char* ret)
393 {
394  if (ret)
395  strcpy(ret, vec->a[i]);
396  CVEC_FREE(vec->a[i]);
397  vec->a[i] = CVEC_STRDUP(a);
398 }
399 
406 {
407  cvec_sz i;
408  cvec_sz d = end - start + 1;
409  for (i=start; i<=end; i++) {
410  CVEC_FREE(vec->a[i]);
411  }
412 
413  CVEC_MEMMOVE(&vec->a[start], &vec->a[end+1], (vec->size-1-end)*sizeof(char*));
414  vec->size -= d;
415 }
416 
419 {
420  cvec_sz d = end - start + 1;
421  CVEC_MEMMOVE(&vec->a[start], &vec->a[end+1], (vec->size-1-end)*sizeof(char*));
422  vec->size -= d;
423 }
424 
427 {
428  char** tmp;
429  if (vec->capacity < size) {
430  if (!(tmp = (char**)CVEC_REALLOC(vec->a, sizeof(char*)*(size+CVEC_STR_START_SZ)))) {
431  CVEC_ASSERT(tmp != NULL);
432  return 0;
433  }
434  vec->a = tmp;
435  vec->capacity = size + CVEC_STR_START_SZ;
436  }
437  return 1;
438 }
439 
445 {
446  cvec_sz i;
447  char** tmp;
448  if (size < vec->size) {
449  for(i=vec->size-1; i>size-1; i--) {
450  CVEC_FREE(vec->a[i]);
451  }
452 
453  vec->size = size;
454  }
455 
456  if (!(tmp = (char**)CVEC_REALLOC(vec->a, sizeof(char*)*size))) {
457  CVEC_ASSERT(tmp != NULL);
458  return 0;
459  }
460  vec->a = tmp;
461  vec->capacity = size;
462  return 1;
463 }
464 
466 void cvec_set_val_sz_str(cvector_str* vec, char* val)
467 {
468  cvec_sz i;
469  for(i=0; i<vec->size; i++) {
470  CVEC_FREE(vec->a[i]);
471 
472  /* not worth checking to me see commit msg aa0c5cf */
473  vec->a[i] = CVEC_STRDUP(val);
474  }
475 }
476 
481 void cvec_set_val_cap_str(cvector_str* vec, char* val)
482 {
483  cvec_sz i;
484  for (i=0; i<vec->capacity; i++) {
485  if (i<vec->size) {
486  CVEC_FREE(vec->a[i]);
487  }
488 
489  vec->a[i] = CVEC_STRDUP(val);
490  }
491  vec->size = vec->capacity;
492 }
493 
496 {
497  int i;
498  for (i=0; i<vec->size; i++) {
499  CVEC_FREE(vec->a[i]);
500  }
501 
502  vec->size = 0;
503 }
504 
507 void cvec_free_str_heap(void* vec)
508 {
509  cvec_sz i;
510  cvector_str* tmp = (cvector_str*)vec;
511  if (!tmp) return;
512  for (i=0; i<tmp->size; i++) {
513  CVEC_FREE(tmp->a[i]);
514  }
515 
516  CVEC_FREE(tmp->a);
517  CVEC_FREE(tmp);
518 }
519 
521 void cvec_free_str(void* vec)
522 {
523  cvec_sz i;
524  cvector_str* tmp = (cvector_str*)vec;
525  for (i=0; i<tmp->size; i++) {
526  CVEC_FREE(tmp->a[i]);
527  }
528 
529  CVEC_FREE(tmp->a);
530  tmp->size = 0;
531  tmp->capacity = 0;
532 }
CVEC_SIZE_T cvec_sz
Definition: cvector.h:88
#define CVEC_STRDUP
Definition: cvector.h:195
int cvec_init_str(cvector_str *vec, char **vals, cvec_sz num)
Same as cvec_init_str_heap() except the vector passed in was declared on the stack so it isn't alloca...
Definition: cvector_str.c:140
void cvec_clear_str(cvector_str *vec)
Clears the contents of vector (frees all strings) and sets size to 0.
Definition: cvector_str.c:495
#define CVEC_FREE(p)
Definition: cvector_str.c:16
char * cvec_strdup(const char *str)
Useful utility function since strdup isn't in standard C.
Definition: cvector_str.c:35
int cvec_copy_str(cvector_str *dest, cvector_str *src)
Makes dest a copy of src.
Definition: cvector_str.c:190
int cvec_set_cap_str(cvector_str *vec, cvec_sz size)
Set capacity to size.
Definition: cvector_str.c:444
#define CVEC_REALLOC(p, sz)
Definition: cvector_str.c:15
int cvec_extend_str(cvector_str *vec, cvec_sz num)
Increase the size of the array num items.
Definition: cvector_str.c:270
void cvec_set_val_cap_str(cvector_str *vec, char *val)
Fills entire allocated array (capacity) with val.
Definition: cvector_str.c:481
int cvec_copyc_str(void *dest, void *src)
Makes dest a copy of src.
Definition: cvector_str.c:169
#define CVEC_MEMMOVE(dst, src, sz)
Definition: cvector_str.c:21
#define CVEC_MALLOC(sz)
Definition: cvector_str.c:14
void cvec_set_val_sz_str(cvector_str *vec, char *val)
Sets all size elements to val.
Definition: cvector_str.c:466
int cvec_insert_array_str(cvector_str *vec, cvec_sz i, char **a, cvec_sz num)
Insert the first num elements of array a at index i.
Definition: cvector_str.c:341
#define CVEC_ASSERT(x)
Definition: cvector_str.c:26
int cvec_insertm_str(cvector_str *vec, cvec_sz i, char *a)
Same as insert except no CVEC_STRDUP.
Definition: cvector_str.c:316
void cvec_erase_str(cvector_str *vec, cvec_sz start, cvec_sz end)
Erases strings from start to end inclusive.
Definition: cvector_str.c:405
void cvec_free_str(void *vec)
Frees the internal array and sets size and capacity to 0.
Definition: cvector_str.c:521
char ** cvec_back_str(cvector_str *vec)
Return pointer to last element.
Definition: cvector_str.c:262
int cvec_push_str(cvector_str *vec, char *a)
Append a to end of vector (size increased 1).
Definition: cvector_str.c:212
int cvec_insert_arraym_str(cvector_str *vec, cvec_sz i, char **a, cvec_sz num)
Same as insert_array except no CVEC_STRDUP.
Definition: cvector_str.c:367
int cvec_pushm_str(cvector_str *vec, char *a)
same as push but without calling CVEC_STRDUP(a), m suffix is for "move"
Definition: cvector_str.c:231
void cvec_replace_str(cvector_str *vec, cvec_sz i, char *a, char *ret)
Replace string at i with a.
Definition: cvector_str.c:392
void cvec_pop_str(cvector_str *vec, char *ret)
Remove the last element (size decreased 1).
Definition: cvector_str.c:253
void cvec_free_str_heap(void *vec)
Frees contents (individual strings and array) and frees vector so don't use after calling this.
Definition: cvector_str.c:507
#define CVEC_STR_ALLOCATOR(x)
Definition: cvector_str.c:31
int cvec_reserve_str(cvector_str *vec, cvec_sz size)
Makes sure the vector capacity is >= size (parameter not member).
Definition: cvector_str.c:426
int cvec_insert_str(cvector_str *vec, cvec_sz i, char *a)
Insert a at index i (0 based).
Definition: cvector_str.c:293
cvector_str * cvec_str_heap(cvec_sz size, cvec_sz capacity)
Create a new cvector_str on the heap.
Definition: cvector_str.c:64
void cvec_remove_str(cvector_str *vec, cvec_sz start, cvec_sz end)
Same as erase except it does not call CVEC_FREE.
Definition: cvector_str.c:418
int cvec_str(cvector_str *vec, cvec_sz size, cvec_sz capacity)
Same as cvec_str_heap() except the vector passed in was declared on the stack so it isn't allocated i...
Definition: cvector_str.c:120
cvector_str * cvec_init_str_heap(char **vals, cvec_sz num)
Create (on the heap) and initialize cvector_str with num elements of vals.
Definition: cvector_str.c:91
cvec_sz CVEC_STR_START_SZ
Definition: cvector_str.c:29
Data structure for string vector.
Definition: cvector.h:186
cvec_sz capacity
Allocated size of array; always >= size.
Definition: cvector.h:189
cvec_sz size
Current size (amount you use when manipulating array directly).
Definition: cvector.h:188
char ** a
Array.
Definition: cvector.h:187