1 /* |
1 /* |
2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. |
2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. |
3 * |
3 * |
4 * Copyright 2013 Olaf Wintermann. All rights reserved. |
4 * Copyright 2015 Olaf Wintermann. All rights reserved. |
5 * |
5 * |
6 * Redistribution and use in source and binary forms, with or without |
6 * Redistribution and use in source and binary forms, with or without |
7 * modification, are permitted provided that the following conditions are met: |
7 * modification, are permitted provided that the following conditions are met: |
8 * |
8 * |
9 * 1. Redistributions of source code must retain the above copyright |
9 * 1. Redistributions of source code must retain the above copyright |
29 #include "buffer.h" |
29 #include "buffer.h" |
30 #include <stdarg.h> |
30 #include <stdarg.h> |
31 #include <stdlib.h> |
31 #include <stdlib.h> |
32 #include <string.h> |
32 #include <string.h> |
33 |
33 |
34 UcxBuffer *ucx_buffer_new(void *space, size_t size, int flags) { |
34 UcxBuffer *ucx_buffer_new(void *space, size_t capacity, int flags) { |
35 UcxBuffer *buffer = (UcxBuffer*) malloc(sizeof(UcxBuffer)); |
35 UcxBuffer *buffer = (UcxBuffer*) malloc(sizeof(UcxBuffer)); |
36 if (buffer) { |
36 if (buffer) { |
37 buffer->flags = flags; |
37 buffer->flags = flags; |
38 if (!space) { |
38 if (!space) { |
39 buffer->space = (char*)malloc(size); |
39 buffer->space = (char*)malloc(capacity); |
40 if (!buffer->space) { |
40 if (!buffer->space) { |
41 free(buffer); |
41 free(buffer); |
42 return NULL; |
42 return NULL; |
43 } |
43 } |
44 memset(buffer->space, 0, size); |
44 memset(buffer->space, 0, capacity); |
45 buffer->flags |= UCX_BUFFER_AUTOFREE; |
45 buffer->flags |= UCX_BUFFER_AUTOFREE; |
46 } else { |
46 } else { |
47 buffer->space = (char*)space; |
47 buffer->space = (char*)space; |
48 } |
48 } |
49 buffer->capacity = size; |
49 buffer->capacity = capacity; |
50 buffer->size = 0; |
50 buffer->size = 0; |
51 |
51 |
52 buffer->pos = 0; |
52 buffer->pos = 0; |
53 } |
53 } |
54 |
54 |
62 free(buffer); |
62 free(buffer); |
63 } |
63 } |
64 |
64 |
65 UcxBuffer* ucx_buffer_extract( |
65 UcxBuffer* ucx_buffer_extract( |
66 UcxBuffer *src, size_t start, size_t length, int flags) { |
66 UcxBuffer *src, size_t start, size_t length, int flags) { |
67 if(src->size == 0) { |
67 |
68 return NULL; |
68 if (src->size == 0 || length == 0 || start+length > src->capacity) { |
69 } |
|
70 if (length == 0) { |
|
71 length = src->size - start; |
|
72 } |
|
73 if (start+length > src->size) { |
|
74 return NULL; |
69 return NULL; |
75 } |
70 } |
76 |
71 |
77 UcxBuffer *dst = (UcxBuffer*) malloc(sizeof(UcxBuffer)); |
72 UcxBuffer *dst = (UcxBuffer*) malloc(sizeof(UcxBuffer)); |
78 if (dst) { |
73 if (dst) { |
118 return buffer->pos >= buffer->size; |
121 return buffer->pos >= buffer->size; |
119 } |
122 } |
120 |
123 |
121 int ucx_buffer_extend(UcxBuffer *buffer, size_t len) { |
124 int ucx_buffer_extend(UcxBuffer *buffer, size_t len) { |
122 size_t newcap = buffer->capacity; |
125 size_t newcap = buffer->capacity; |
123 while (buffer->pos + len > newcap) newcap <<= 1; |
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 } |
124 |
137 |
125 char *newspace = (char*)realloc(buffer->space, newcap); |
138 char *newspace = (char*)realloc(buffer->space, newcap); |
126 if (newspace) { |
139 if (newspace) { |
127 memset(newspace+buffer->size, 0, newcap-buffer->size); |
140 memset(newspace+buffer->size, 0, newcap-buffer->size); |
128 buffer->space = newspace; |
141 buffer->space = newspace; |
135 } |
148 } |
136 |
149 |
137 size_t ucx_buffer_write(const void *ptr, size_t size, size_t nitems, |
150 size_t ucx_buffer_write(const void *ptr, size_t size, size_t nitems, |
138 UcxBuffer *buffer) { |
151 UcxBuffer *buffer) { |
139 size_t len = size * nitems; |
152 size_t len = size * nitems; |
140 if (buffer->pos + len > buffer->capacity) { |
153 size_t required = buffer->pos + len; |
|
154 if (buffer->pos > required) { |
|
155 return 0; |
|
156 } |
|
157 |
|
158 if (required > buffer->capacity) { |
141 if ((buffer->flags & UCX_BUFFER_AUTOEXTEND) == UCX_BUFFER_AUTOEXTEND) { |
159 if ((buffer->flags & UCX_BUFFER_AUTOEXTEND) == UCX_BUFFER_AUTOEXTEND) { |
142 if(ucx_buffer_extend(buffer, len)) { |
160 if (ucx_buffer_extend(buffer, required - buffer->capacity)) { |
143 return -1; |
161 return 0; |
144 } |
162 } |
145 } else { |
163 } else { |
146 len = buffer->capacity - buffer->pos; |
164 len = buffer->capacity - buffer->pos; |
147 if (size > 1) len -= len%size; |
165 if (size > 1) { |
148 } |
166 len -= len%size; |
149 } |
167 } |
150 |
168 } |
151 if (len <= 0) { |
169 } |
|
170 |
|
171 if (len == 0) { |
152 return len; |
172 return len; |
153 } |
173 } |
154 |
174 |
155 memcpy(buffer->space + buffer->pos, ptr, len); |
175 memcpy(buffer->space + buffer->pos, ptr, len); |
156 buffer->pos += len; |
176 buffer->pos += len; |