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 struct cstring_header *cstring = malloc(INITIAL_SIZE);
30
31 if (cstring == NULL)
32 return NULL;
33
34 cstring->checker = CHECKER_WORD;
35 cstring->allocated = INITIAL_SIZE;
36 cstring->used = 0;
37 cstring->the_string[0] = '\0';
38 return cstring;
39 }
40
|
(1) Event noescape: |
"cstring_to_chars(cstring_t)" does not free or save its parameter "cstring". |
41 char *cstring_to_chars(cstring_t cstring)
42 {
43 struct cstring_header *h = (struct cstring_header *)cstring;
44
45 if (!h) {
46 return NULL;
47 }
48
49 assert(h->checker == CHECKER_WORD);
50 return strdup(h->the_string);
51 }
52
53 size_t cstring_len(cstring_t cstring)
54 {
55 struct cstring_header *h = (struct cstring_header *)cstring;
56
57 if (!h) {
58 return 0;
59 }
60
61 assert(h->checker == CHECKER_WORD);
62 return h->used;
63 }
64
65
66 cstring_t cstring_append_chars(cstring_t cstring, const char *newstring)
67 {
68 struct cstring_header *h = (struct cstring_header *)cstring;
69 size_t newlen;
70
|
(1) Event path: |
Condition "!h", taking false branch. |
71 if (!h) {
72 return NULL;
73 }
74
|
(2) Event path: |
Condition "h->checker == 3168170282U", taking true branch. |
|
(3) Event path: |
Falling through to end of if statement. |
75 assert(h->checker == CHECKER_WORD);
|
(4) Event path: |
Condition "!newstring", taking false branch. |
76 if (!newstring) {
77 return NULL;
78 }
79
80 newlen = h->used + strlen(newstring)+1 + sizeof(struct cstring_header);
|
(5) Event path: |
Condition "newlen > h->allocated", taking true branch. |
81 if (newlen > h->allocated) {
82 size_t new_allocsize = (newlen + 2048) & 0xFFFFFC00;
|
(6) Event alloc_fn: |
Storage is returned from allocation function "realloc". |
|
(7) Event assign: |
Assigning: "tmp" = "realloc(cstring, new_allocsize)". |
| Also see events: |
[assign][assign][noescape][return_alloc] |
83 char *tmp = realloc(cstring, new_allocsize);
|
(8) Event path: |
Condition "!tmp", taking false branch. |
84 if (!tmp) {
85 return cstring;
86 }
87
88 cstring = tmp;
89 h = (struct cstring_header *)cstring;
90 h->allocated = new_allocsize;
91 }
92 strncat(h->the_string, newstring, h->allocated - h->used -1);
93 h->used += strlen(newstring);
94 return cstring;
95 }
96
97 cstring_t cstring_append_cstring(cstring_t cstring, cstring_t newstring)
98 {
99 /* Just check the newstring - cstring_append_chars() will check the target */
100 struct cstring_header *h = (struct cstring_header *)newstring;
101
102 if (!h) {
103 return NULL;
104 }
105
106 assert(h->checker == CHECKER_WORD);
107 return cstring_append_chars(cstring, h->the_string);
108 }
109
110 cstring_t cstring_from_chars(const char* chars)
111 {
112 cstring_t new_string = cstring_alloc();
113 if (!new_string) {
114 return NULL;
115 }
116 return cstring_append_chars(new_string, chars);
117 }
118
119 void cstring_free(cstring_t cstring)
120 {
121 struct cstring_header *h = (struct cstring_header *)cstring;
122
123 if (!h) {
124 return;
125 }
126 assert(h->checker == CHECKER_WORD);
127 free(cstring);
128 }
129
130
131