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