src/ucx/buffer.c

changeset 61
47a5fc33590a
parent 60
9f25df78925e
child 62
3fff4c364ffc
equal deleted inserted replaced
60:9f25df78925e 61:47a5fc33590a
1 /*
2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3 *
4 * Copyright 2015 Olaf Wintermann. All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are met:
8 *
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 *
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 * POSSIBILITY OF SUCH DAMAGE.
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 }

mercurial