4
* See copyright notice in luabins.h
7
#include <string.h> /* memcpy() */
9
#include "luaheaders.h"
12
#include "savebuffer.h"
15
#define SPAM(a) printf a
17
#define SPAM(a) (void)0
20
/* Minimum allocation size */
21
#define LUABINS_SAVEMINALLOC (256)
23
/* TODO: Test this with custom allocator! */
26
luabins_SaveBuffer * sb,
31
sb->alloc_fn = alloc_fn;
32
sb->alloc_ud = alloc_ud;
41
* Ensures that there is at least delta size available in buffer.
42
* New size is aligned by blockSize increments
43
* Returns non-zero if resize failed.
44
* If you pre-sized the buffer, subsequent writes up to the new size
45
* are guaranteed to not fail.
47
int lbsSB_grow(luabins_SaveBuffer * sb, size_t delta)
49
size_t needed_size = sb->end + delta;
51
if (needed_size > sb->buf_size)
55
* Discussion on possible values:
56
* http://stackoverflow.com/questions/2269063/buffer-growth-strategy
59
/* TODO: Handle size_t overflow? */
63
size_t add_size = sb->buf_size / 2;
64
if (add_size < LUABINS_SAVEMINALLOC)
66
add_size = LUABINS_SAVEMINALLOC;
69
new_size = sb->buf_size + add_size;
73
"trying %lu + %lu = %lu (needed %lu)\n",
81
while (new_size < needed_size)
83
SPAM(("...+%lu not enough, growing more\n", add_size));
84
/* Grow exponentially as needed */
85
add_size += new_size / 2;
90
"growing from %lu to %lu (needed %lu)\n",
96
sb->buffer = (unsigned char *)sb->alloc_fn(
102
if (sb->buffer == NULL)
104
/* TODO: We probably should free the buffer here */
107
return LUABINS_ETOOLONG;
110
sb->buf_size = new_size;
113
return LUABINS_ESUCCESS;
117
* Returns non-zero if write failed.
118
* Allocates buffer as needed.
121
luabins_SaveBuffer * sb,
122
const unsigned char * bytes,
126
int result = lbsSB_grow(sb, length);
127
if (result != LUABINS_ESUCCESS)
132
memcpy(&sb->buffer[sb->end], bytes, length);
135
return LUABINS_ESUCCESS;
139
* Returns non-zero if write failed.
140
* Allocates buffer as needed.
141
* Convenience function.
144
luabins_SaveBuffer * sb,
145
const unsigned char byte
148
/* TODO: Shouldn't this be a macro? */
149
int result = lbsSB_grow(sb, 1);
150
if (result != LUABINS_ESUCCESS)
155
sb->buffer[sb->end] = byte;
158
return LUABINS_ESUCCESS;
162
* If offset is greater than total length, data is appended to the end.
163
* Returns non-zero if write failed.
164
* Allocates buffer as needed.
167
luabins_SaveBuffer * sb,
169
const unsigned char * bytes,
173
if (offset > sb->end)
178
if (offset + length > sb->end)
180
int result = lbsSB_grow(sb, length);
181
if (result != LUABINS_ESUCCESS)
186
sb->end = offset + length;
189
memcpy(&sb->buffer[offset], bytes, length);
191
return LUABINS_ESUCCESS;
195
* If offset is greater than total length, data is appended to the end.
196
* Returns non-zero if write failed.
197
* Allocates buffer as needed.
198
* Convenience function.
200
int lbsSB_overwritechar(
201
luabins_SaveBuffer * sb,
206
if (offset > sb->end)
211
if (offset + 1 > sb->end)
213
int result = lbsSB_grow(sb, 1);
214
if (result != LUABINS_ESUCCESS)
219
sb->end = offset + 1;
222
sb->buffer[offset] = byte;
224
return LUABINS_ESUCCESS;
228
* Returns a pointer to the internal buffer with data.
229
* Note that buffer is NOT zero-terminated.
230
* Buffer is valid until next operation with the given sb.
232
const unsigned char * lbsSB_buffer(luabins_SaveBuffer * sb, size_t * length)
241
void lbsSB_destroy(luabins_SaveBuffer * sb)
243
if (sb->buffer != NULL)
245
/* Ignoring errors */
246
SPAM(("dealloc size %lu\n", sb->buf_size));
247
sb->alloc_fn(sb->alloc_ud, sb->buffer, sb->buf_size, 0UL);