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   	{
CID (unavailable; MK=2ec5f3903ac70354ac0975b58774f745) (#1 of 1): Wrong size argument (SIZEOF_MISMATCH):
(1) Event suspicious_sizeof: Passing argument "1024UL" to function "malloc" that returns a pointer of type "struct cstring_header *" is suspicious because a multiple of "sizeof (struct cstring_header) /*24*/" is expected.
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   	
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   	
71   		if (!h) {
72   			return NULL;
73   		}
74   	
75   		assert(h->checker == CHECKER_WORD);
76   		if (!newstring) {
77   			return NULL;
78   		}
79   	
80   		newlen = h->used + strlen(newstring)+1 + sizeof(struct cstring_header);
81   		if (newlen > h->allocated) {
82   			size_t new_allocsize = (newlen + 2048) & 0xFFFFFC00;
83   			char *tmp = realloc(cstring, new_allocsize);
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