ucx/buffer.c

changeset 0
1f419bd32da1
child 124
80609f9675f1
equal deleted inserted replaced
-1:000000000000 0:1f419bd32da1
1 /*
2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3 *
4 * Copyright 2013 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 size, int flags) {
35 UcxBuffer *buffer = (UcxBuffer*) malloc(sizeof(UcxBuffer));
36 if (buffer) {
37 buffer->flags = flags;
38 if (!space) {
39 buffer->space = (char*)malloc(size);
40 if (!buffer->space) {
41 free(buffer);
42 return NULL;
43 }
44 memset(buffer->space, 0, size);
45 buffer->flags |= UCX_BUFFER_AUTOFREE;
46 } else {
47 buffer->space = (char*)space;
48 }
49 buffer->capacity = size;
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 if(src->size == 0) {
68 return NULL;
69 }
70 if (length == 0) {
71 length = src->size - start;
72 }
73 if (start+length > src->size) {
74 return NULL;
75 }
76
77 UcxBuffer *dst = (UcxBuffer*) malloc(sizeof(UcxBuffer));
78 if (dst) {
79 dst->space = (char*)malloc(length);
80 if (!dst->space) {
81 free(dst);
82 return NULL;
83 }
84 dst->capacity = length;
85 dst->size = length;
86 dst->flags = flags | UCX_BUFFER_AUTOFREE;
87 dst->pos = 0;
88 memcpy(dst->space, src->space+start, length);
89 }
90 return dst;
91 }
92
93 int ucx_buffer_seek(UcxBuffer *buffer, off_t offset, int whence) {
94 size_t npos;
95 switch (whence) {
96 case SEEK_CUR:
97 npos = buffer->pos;
98 break;
99 case SEEK_END:
100 npos = buffer->size;
101 break;
102 default:
103 npos = 0;
104 }
105
106 npos += offset;
107
108 if (npos > buffer->size) {
109 return -1;
110 } else {
111 buffer->pos = npos;
112 return 0;
113 }
114
115 }
116
117 int ucx_buffer_eof(UcxBuffer *buffer) {
118 return buffer->pos >= buffer->size;
119 }
120
121 int ucx_buffer_extend(UcxBuffer *buffer, size_t len) {
122 size_t newcap = buffer->capacity;
123 while (buffer->pos + len > newcap) newcap <<= 1;
124
125 char *newspace = (char*)realloc(buffer->space, newcap);
126 if (newspace) {
127 memset(newspace+buffer->size, 0, newcap-buffer->size);
128 buffer->space = newspace;
129 buffer->capacity = newcap;
130 } else {
131 return -1;
132 }
133
134 return 0;
135 }
136
137 size_t ucx_buffer_write(const void *ptr, size_t size, size_t nitems,
138 UcxBuffer *buffer) {
139 size_t len = size * nitems;
140 if (buffer->pos + len > buffer->capacity) {
141 if ((buffer->flags & UCX_BUFFER_AUTOEXTEND) == UCX_BUFFER_AUTOEXTEND) {
142 if(ucx_buffer_extend(buffer, len)) {
143 return -1;
144 }
145 } else {
146 len = buffer->capacity - buffer->pos;
147 if (size > 1) len -= len%size;
148 }
149 }
150
151 if (len <= 0) {
152 return len;
153 }
154
155 memcpy(buffer->space + buffer->pos, ptr, len);
156 buffer->pos += len;
157 if(buffer->pos > buffer->size) {
158 buffer->size = buffer->pos;
159 }
160
161 return len / size;
162 }
163
164 size_t ucx_buffer_read(void *ptr, size_t size, size_t nitems,
165 UcxBuffer *buffer) {
166 size_t len = size * nitems;
167 if (buffer->pos + len > buffer->size) {
168 len = buffer->size - buffer->pos;
169 if (size > 1) len -= len%size;
170 }
171
172 if (len <= 0) {
173 return len;
174 }
175
176 memcpy(ptr, buffer->space + buffer->pos, len);
177 buffer->pos += len;
178
179 return len / size;
180 }
181
182 int ucx_buffer_putc(UcxBuffer *buffer, int c) {
183 if(buffer->pos >= buffer->capacity) {
184 if ((buffer->flags & UCX_BUFFER_AUTOEXTEND) == UCX_BUFFER_AUTOEXTEND) {
185 if(ucx_buffer_extend(buffer, 1)) {
186 return EOF;
187 }
188 } else {
189 return EOF;
190 }
191 }
192
193 c &= 0xFF;
194 buffer->space[buffer->pos] = (char) c;
195 buffer->pos++;
196 if(buffer->pos > buffer->size) {
197 buffer->size = buffer->pos;
198 }
199 return c;
200 }
201
202 int ucx_buffer_getc(UcxBuffer *buffer) {
203 if (ucx_buffer_eof(buffer)) {
204 return EOF;
205 } else {
206 int c = buffer->space[buffer->pos];
207 buffer->pos++;
208 return c;
209 }
210 }
211
212 size_t ucx_buffer_puts(UcxBuffer *buffer, char *str) {
213 return ucx_buffer_write((const void*)str, 1, strlen(str), buffer);
214 }

mercurial