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 #include "buffer.h"
30 #include <stdarg.h>
31 #include <stdlib.h>
32 #include <string.h>
33
34 UcxBuffer *ucx_buffer_new(
void *space,
size_t capacity,
int flags) {
35 UcxBuffer *buffer = (UcxBuffer*) malloc(
sizeof(UcxBuffer));
36 if (buffer) {
37 buffer->flags = flags;
38 if (!space) {
39 buffer->space = (
char*)malloc(capacity);
40 if (!buffer->space) {
41 free(buffer);
42 return NULL;
43 }
44 memset(buffer->space,
0, capacity);
45 buffer->flags |=
UCX_BUFFER_AUTOFREE;
46 }
else {
47 buffer->space = (
char*)space;
48 }
49 buffer->capacity = capacity;
50 buffer->size =
0;
51
52 buffer->pos =
0;
53 }
54
55 return buffer;
56 }
57
58 void ucx_buffer_free(UcxBuffer *buffer) {
59 if ((buffer->flags &
UCX_BUFFER_AUTOFREE) ==
UCX_BUFFER_AUTOFREE) {
60 free(buffer->space);
61 }
62 free(buffer);
63 }
64
65 UcxBuffer* ucx_buffer_extract(
66 UcxBuffer *src,
size_t start,
size_t length,
int flags) {
67
68 if (src->size ==
0 || length ==
0 || start+length > src->capacity) {
69 return NULL;
70 }
71
72 UcxBuffer *dst = (UcxBuffer*) malloc(
sizeof(UcxBuffer));
73 if (dst) {
74 dst->space = (
char*)malloc(length);
75 if (!dst->space) {
76 free(dst);
77 return NULL;
78 }
79 dst->capacity = length;
80 dst->size = length;
81 dst->flags = flags |
UCX_BUFFER_AUTOFREE;
82 dst->pos =
0;
83 memcpy(dst->space, src->space+start, length);
84 }
85 return dst;
86 }
87
88 int ucx_buffer_seek(UcxBuffer *buffer,
off_t offset,
int whence) {
89 size_t npos;
90 switch (whence) {
91 case SEEK_CUR:
92 npos = buffer->pos;
93 break;
94 case SEEK_END:
95 npos = buffer->size;
96 break;
97 case SEEK_SET:
98 npos =
0;
99 break;
100 default:
101 return -
1;
102 }
103
104 size_t opos = npos;
105 npos += offset;
106
107 if ((offset >
0 && npos < opos) || (offset <
0 && npos > opos)) {
108 return -
1;
109 }
110
111 if (npos >= buffer->size) {
112 return -
1;
113 }
else {
114 buffer->pos = npos;
115 return 0;
116 }
117
118 }
119
120 int ucx_buffer_eof(UcxBuffer *buffer) {
121 return buffer->pos >= buffer->size;
122 }
123
124 int ucx_buffer_extend(UcxBuffer *buffer,
size_t len) {
125 size_t newcap = buffer->capacity;
126
127 if (buffer->capacity + len < buffer->capacity) {
128 return -
1;
129 }
130
131 while (buffer->capacity + len > newcap) {
132 newcap <<=
1;
133 if (newcap < buffer->capacity) {
134 return -
1;
135 }
136 }
137
138 char *newspace = (
char*)realloc(buffer->space, newcap);
139 if (newspace) {
140 memset(newspace+buffer->size,
0, newcap-buffer->size);
141 buffer->space = newspace;
142 buffer->capacity = newcap;
143 }
else {
144 return -
1;
145 }
146
147 return 0;
148 }
149
150 size_t ucx_buffer_write(
const void *ptr,
size_t size,
size_t nitems,
151 UcxBuffer *buffer) {
152 size_t len = size * nitems;
153 size_t required = buffer->pos + len;
154 if (buffer->pos > required) {
155 return 0;
156 }
157
158 if (required > buffer->capacity) {
159 if ((buffer->flags &
UCX_BUFFER_AUTOEXTEND) ==
UCX_BUFFER_AUTOEXTEND) {
160 if (ucx_buffer_extend(buffer, required - buffer->capacity)) {
161 return 0;
162 }
163 }
else {
164 len = buffer->capacity - buffer->pos;
165 if (size >
1) {
166 len -= len%size;
167 }
168 }
169 }
170
171 if (len ==
0) {
172 return len;
173 }
174
175 memcpy(buffer->space + buffer->pos, ptr, len);
176 buffer->pos += len;
177 if(buffer->pos > buffer->size) {
178 buffer->size = buffer->pos;
179 }
180
181 return len / size;
182 }
183
184 size_t ucx_buffer_read(
void *ptr,
size_t size,
size_t nitems,
185 UcxBuffer *buffer) {
186 size_t len = size * nitems;
187 if (buffer->pos + len > buffer->size) {
188 len = buffer->size - buffer->pos;
189 if (size >
1) len -= len%size;
190 }
191
192 if (len <=
0) {
193 return len;
194 }
195
196 memcpy(ptr, buffer->space + buffer->pos, len);
197 buffer->pos += len;
198
199 return len / size;
200 }
201
202 int ucx_buffer_putc(UcxBuffer *buffer,
int c) {
203 if(buffer->pos >= buffer->capacity) {
204 if ((buffer->flags &
UCX_BUFFER_AUTOEXTEND) ==
UCX_BUFFER_AUTOEXTEND) {
205 if(ucx_buffer_extend(buffer,
1)) {
206 return EOF;
207 }
208 }
else {
209 return EOF;
210 }
211 }
212
213 c &= 0xFF;
214 buffer->space[buffer->pos] = (
char) c;
215 buffer->pos++;
216 if(buffer->pos > buffer->size) {
217 buffer->size = buffer->pos;
218 }
219 return c;
220 }
221
222 int ucx_buffer_getc(UcxBuffer *buffer) {
223 if (ucx_buffer_eof(buffer)) {
224 return EOF;
225 }
else {
226 int c = buffer->space[buffer->pos];
227 buffer->pos++;
228 return c;
229 }
230 }
231
232 size_t ucx_buffer_puts(UcxBuffer *buffer,
char *str) {
233 return ucx_buffer_write((
const void*)str,
1, strlen(str), buffer);
234 }
235