1 /* A really basic expanding/appendable string type */
2
3 #include <stdlib.h>
4 #include <sys/time.h>
5 #include <sys/stat.h>
6 #include <time.h>
7 #include <assert.h>
8 #include <stdio.h>
9 #include <limits.h>
10 #include <string.h>
11 #include <getopt.h>
12 #include <errno.h>
13 #include "cstring.h"
14
15 #define INITIAL_SIZE 1024
16 #define INCREMENT 1024
17 #define CHECKER_WORD 0xbcd6712a
18
19 struct cstring_header
20 {
21 size_t checker;
22 size_t allocated;
23 size_t used;
24 char the_string[];
25 };
26
27 cstring_t cstring_alloc(void)
28 {
29 char *cstring = malloc(INITIAL_SIZE);
30 if (cstring) {
31 struct cstring_header *h = (struct cstring_header *)cstring;
32 h->checker = CHECKER_WORD;
33 h->allocated = INITIAL_SIZE;
34 h->used = 0;
35 h->the_string[0] = '\0';
36 return cstring;
37 } else {
38 return NULL;
39 }
40 }
41
42 char *cstring_to_chars(cstring_t cstring)
43 {
44 struct cstring_header *h = (struct cstring_header *)cstring;
45
|
(1) Event cond_false: |
Condition "!h", taking false branch. |
46 if (!h) {
47 return NULL;
|
(2) Event if_end: |
End of if statement. |
48 }
49
|
(3) Event cond_true: |
Condition "h->checker == 3168170282U", taking true branch. |
|
(4) Event if_fallthrough: |
Falling through to end of if statement. |
|
(5) Event if_end: |
End of if statement. |
50 assert(h->checker == CHECKER_WORD);
|
(6) Event alloc_fn: |
Storage is returned from allocation function "strdup". |
|
(7) Event return_alloc_fn: |
Directly returning storage allocated by "strdup". |
51 return strdup(h->the_string);
52 }
53
54 size_t cstring_len(cstring_t cstring)
55 {
56 struct cstring_header *h = (struct cstring_header *)cstring;
57
58 if (!h) {
59 return 0;
60 }
61
62 assert(h->checker == CHECKER_WORD);
63 return h->used;
64 }
65
66
67 cstring_t cstring_append_chars(cstring_t cstring, const char *newstring)
68 {
69 struct cstring_header *h = (struct cstring_header *)cstring;
70 size_t newlen;
71
72 if (!h) {
73 return NULL;
74 }
75
76 assert(h->checker == CHECKER_WORD);
77 if (!newstring) {
78 return NULL;
79 }
80
81 newlen = h->used + strlen(newstring)+1 + sizeof(struct cstring_header);
82 if (newlen > h->allocated) {
83 size_t new_allocsize = (newlen + 2048) & 0xFFFFFC00;
84 char *tmp = realloc(cstring, new_allocsize);
85 if (!tmp) {
86 return cstring;
87 }
88
89 cstring = tmp;
90 h = (struct cstring_header *)cstring;
91 h->allocated = new_allocsize;
92 }
93 strncat(h->the_string, newstring, h->allocated - h->used -1);
94 h->used += strlen(newstring);
95 return cstring;
96 }
97
98 cstring_t cstring_append_cstring(cstring_t cstring, cstring_t newstring)
99 {
100 /* Just check the newstring - cstring_append_chars() will check the target */
101 struct cstring_header *h = (struct cstring_header *)newstring;
102
103 if (!h) {
104 return NULL;
105 }
106
107 assert(h->checker == CHECKER_WORD);
108 return cstring_append_chars(cstring, h->the_string);
109 }
110
111 cstring_t cstring_from_chars(const char* chars)
112 {
113 cstring_t new_string = cstring_alloc();
114 if (!new_string) {
115 return NULL;
116 }
117 return cstring_append_chars(new_string, chars);
118 }
119
120 void cstring_free(cstring_t cstring)
121 {
122 struct cstring_header *h = (struct cstring_header *)cstring;
123
124 if (!h) {
125 return;
126 }
127 assert(h->checker == CHECKER_WORD);
128 free(cstring);
129 }
130
131
132