-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy pathstring_buffer.c
143 lines (120 loc) · 2.97 KB
/
string_buffer.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
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
/**
* MIT License (MIT)
*
* Copyright (c) 2015 Zhiyuan Wang
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdarg.h>
#include "string_buffer.h"
static
int expand_buffer(StringBuffer *self, size_t min)
{
char *new_buf = NULL;
size_t new_capacity = 0;
min = min + 1 - (self->capacity - self->length);
if (min <= 0) return 0;
new_capacity = self->capacity + (min / STEP_LENGTH + 1) * STEP_LENGTH;
new_buf = realloc(self->buf, new_capacity);
if (new_buf != NULL) {
self->buf = new_buf;
memset(self->buf + self->capacity, 0, new_capacity - self->capacity);
self->capacity = new_capacity;
return 0;
} else {
return -1;
}
}
StringBuffer *string_buffer_new()
{
StringBuffer *self = NULL;
self = calloc(1, sizeof(*self));
if (self != NULL) {
self->buf = calloc(1, STEP_LENGTH);
if (self->buf != NULL) {
self->capacity = STEP_LENGTH;
} else {
free(self);
self = NULL;
}
}
return self;
}
void string_buffer_delete(StringBuffer *self)
{
if (self) {
if (self->buf) {
free(self->buf);
}
free(self);
}
}
size_t string_buffer_length(StringBuffer *self)
{
return self ? self->length : 0;
}
size_t string_buffer_capacity(StringBuffer *self)
{
return self ? (self->capacity - 1) : 0;
}
char *string_buffer_get_string(StringBuffer *self)
{
return self ? self->buf : NULL;
}
void string_buffer_clear(StringBuffer *self)
{
if (self != NULL) {
memset(self->buf, 0, self->length);
self->length = 0;
}
}
int string_buffer_append(StringBuffer *self, const char *str)
{
return string_buffer_append_n(self, str, strlen(str));
}
int string_buffer_append_n(StringBuffer *self, const char *str, size_t n)
{
if (self == NULL) return -1;
EXPAND_BUFFER(self, n);
memcpy(self->buf + self->length, str, n);
self->length += n;
self->buf[self->length] = '\0';
return n;
}
int string_buffer_appendf(StringBuffer *self, const char *format, ...)
{
size_t n = 0;
int ret = 0;
va_list args;
if (self == NULL) return -1;
while (1) {
n = self->capacity - self->length;
va_start(args, format);
ret = vsnprintf(self->buf + self->length, n, format, args);
va_end(args);
if (ret >= 0 && ret < n) {
self->length += ret;
return ret;
} else if (ret < 0) {
// error
return ret;
} else {
// no enough space in buffer
if (expand_buffer(self, ret - n)) {
// expand failed
return -1;
}
}
}
return ret;
}
int string_buffer_append_set(StringBuffer *self, int value, size_t num)
{
if (self == NULL) return -1;
EXPAND_BUFFER(self, num);
memset(self->buf + self->length, value, num);
self->length += num;
self->buf[self->length] = '\0';
return num;
}