forked from sixtyeight/kassomat-payout
-
Notifications
You must be signed in to change notification settings - Fork 2
/
StringBuffer.c
112 lines (93 loc) · 3.06 KB
/
StringBuffer.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
/*
* Taken from: https://sites.google.com/site/rickcreamer/Home/cc/c-implementation-of-stringbuffer-functionality
*/
#include <stdlib.h>
#include <stdio.h>
#include <malloc.h>
#include <string.h>
#include "StringBuffer.h"
/* Constant determining initial pointer list length - is small so we can test growPtrList() */
#define STR_BUF_INIT_SIZE 4
/* Function declarations */
void append(SB *sb, char *s);
char *toString(SB *sb);
void dispose(SB **sb);
void error(char *msg);
void growPtrList(SB *sb);
void *getMem(int nBytes);
void init(SB *sb);
/* Quasi-public functions exposed as function pointers in StringBuffer structure */
/* Factory-like StringBuffer instantiator */
SB * getStringBuffer() {
SB *sb = (SB *) getMem(sizeof(SB));
init(sb);
return sb;
}
/* Append a string to the StringBuffer */
void append(SB *sb, char *s) {
if (!s)
error("Null pointer passed for argument 's' in SB.append()!"); /* Abort */
if (sb->count == sb->capacity)
growPtrList(sb);
char *copy_of_s=NULL;
asprintf(©_of_s, "%s", s);
sb->ptrList[sb->count++] = copy_of_s;
}
/* Catenate all strings and return result */
char *toString(SB *sb) {
if (!sb || !sb->count)
return ""; /* TODO: Decide if error message or other action is preferable */
int len = 0;
for (size_t i = 0; i < sb->count; ++i)
len += strlen(sb->ptrList[i]);
size_t nBytes = (len + 1) * sizeof(char); /* 1 is for '\0' null terminator */
char *ret = (char *) getMem(nBytes);
for (size_t i = 0; i < sb->count; ++i)
strcat(ret, sb->ptrList[i]);
return ret;
}
/* Delete this StringBuffer object and free all memory */
/* Argument 'freeStrings' controls whether the individual append()ed strings will be freed */
/* Note: The argument 'sb' is the ADDRESS of the POINTER to a StringBuffer structure */
void dispose(SB **sb) {
if (!sb || !*sb || !(*sb)->ptrList)
return; /* TODO: Decide if should abort here or take other action */
// free all the strings allocated in append
for (size_t i = 0; i < (*sb)->count; ++i)
free((*sb)->ptrList[i]);
free((*sb)->ptrList);
free(*sb);
*sb = 0; /* Set value of pointer to zero */
}
/* Begin of quasi-private functions */
/* Print simple error message to stderr and call exit() */
void error(char *msg) {
fprintf( stderr, "%s\n", (msg) ? msg : "");
exit(1);
}
/* Double length of the array of pointers when append() needs to go past current limit */
void growPtrList(SB *sb) {
size_t nBytes = 2 * sb->capacity * sizeof(char *);
char **pTemp = (char **) getMem(nBytes);
memcpy((void *) pTemp, (void *) sb->ptrList, sb->capacity * sizeof(char *));
sb->capacity *= 2;
free(sb->ptrList);
sb->ptrList = pTemp;
}
/* Wrapper around malloc() - allocate memory and initialize to all zeros */
void *getMem(int nBytes) {
void *ret = malloc(nBytes);
if (!ret)
error("Memory allocation failed!");
memset(ret, 0, nBytes);
return ret;
}
/* Initialize a new StringBuffer structure */
void init(SB *sb) {
sb->count = 0;
sb->capacity = STR_BUF_INIT_SIZE;
sb->ptrList = (char **) getMem( STR_BUF_INIT_SIZE * sizeof(char *));
sb->append = append;
sb->toString = toString;
sb->dispose = dispose;
}