Comparison

util-src/ringbuffer.c @ 10901:5e33926f4b43

util.ringbuffer: Add :sub() and :byte() methods equivalent to the string methods
author Matthew Wild <mwild1@gmail.com>
date Thu, 04 Jun 2020 15:19:20 +0100
parent 10899:8048255ae61e
child 10921:6eb5d2bb11af
comparison
equal deleted inserted replaced
10900:9e6d979dd603 10901:5e33926f4b43
1 1
2 #include <stdlib.h> 2 #include <stdlib.h>
3 #include <unistd.h> 3 #include <unistd.h>
4 #include <string.h> 4 #include <string.h>
5 #include <stdio.h>
6 5
7 #include <lua.h> 6 #include <lua.h>
8 #include <lauxlib.h> 7 #include <lauxlib.h>
9 8
10 typedef struct { 9 typedef struct {
13 size_t alen; /* allocated size */ 12 size_t alen; /* allocated size */
14 size_t blen; /* current content size */ 13 size_t blen; /* current content size */
15 char buffer[]; 14 char buffer[];
16 } ringbuffer; 15 } ringbuffer;
17 16
17 /* Translate absolute idx to a wrapped index within the buffer,
18 based on current read position */
19 static int wrap_pos(const ringbuffer *b, const long idx, long *pos) {
20 if(idx > (long)b->blen) {
21 return 0;
22 }
23 if(idx + (long)b->rpos > (long)b->alen) {
24 *pos = idx - (b->alen - b->rpos);
25 } else {
26 *pos = b->rpos + idx;
27 }
28 return 1;
29 }
30
31 static int calc_splice_positions(const ringbuffer *b, long start, long end, long *out_start, long *out_end) {
32 if(start < 0) {
33 start = 1 + start + b->blen;
34 }
35 if(start <= 0) {
36 start = 1;
37 }
38
39 if(end < 0) {
40 end = 1 + end + b->blen;
41 }
42
43 if(end > (long)b->blen) {
44 end = b->blen;
45 }
46 if(start < 1) {
47 start = 1;
48 }
49
50 if(start > end) {
51 return 0;
52 }
53
54 start = start - 1;
55
56 if(!wrap_pos(b, start, out_start)) {
57 return 0;
58 }
59 if(!wrap_pos(b, end, out_end)) {
60 return 0;
61 }
62
63 return 1;
64 }
65
18 static void writechar(ringbuffer *b, char c) { 66 static void writechar(ringbuffer *b, char c) {
19 b->blen++; 67 b->blen++;
20 b->buffer[(b->wpos++) % b->alen] = c; 68 b->buffer[(b->wpos++) % b->alen] = c;
21 } 69 }
22 70
174 222
175 static int rb_tostring(lua_State *L) { 223 static int rb_tostring(lua_State *L) {
176 ringbuffer *b = luaL_checkudata(L, 1, "ringbuffer_mt"); 224 ringbuffer *b = luaL_checkudata(L, 1, "ringbuffer_mt");
177 lua_pushfstring(L, "ringbuffer: %p %d/%d", b, b->blen, b->alen); 225 lua_pushfstring(L, "ringbuffer: %p %d/%d", b, b->blen, b->alen);
178 return 1; 226 return 1;
227 }
228
229 static int rb_sub(lua_State *L) {
230 ringbuffer *b = luaL_checkudata(L, 1, "ringbuffer_mt");
231
232 long start = luaL_checkinteger(L, 2);
233 long end = luaL_optinteger(L, 3, -1);
234
235 long wrapped_start, wrapped_end;
236 if(!calc_splice_positions(b, start, end, &wrapped_start, &wrapped_end)) {
237 lua_pushstring(L, "");
238 } else if(wrapped_end <= wrapped_start) {
239 lua_pushlstring(L, &b->buffer[wrapped_start], b->alen - wrapped_start);
240 lua_pushlstring(L, b->buffer, wrapped_end);
241 lua_concat(L, 2);
242 } else {
243 lua_pushlstring(L, &b->buffer[wrapped_start], (wrapped_end - wrapped_start));
244 }
245
246 return 1;
247 }
248
249 static int rb_byte(lua_State *L) {
250 ringbuffer *b = luaL_checkudata(L, 1, "ringbuffer_mt");
251
252 long start = luaL_optinteger(L, 2, 1);
253 long end = luaL_optinteger(L, 3, start);
254
255 long i;
256
257 long wrapped_start, wrapped_end;
258 if(calc_splice_positions(b, start, end, &wrapped_start, &wrapped_end)) {
259 if(wrapped_end <= wrapped_start) {
260 for(i = wrapped_start; i < (long)b->alen; i++) {
261 lua_pushinteger(L, b->buffer[i]);
262 }
263 for(i = 0; i < wrapped_end; i++) {
264 lua_pushinteger(L, b->buffer[i]);
265 }
266 return wrapped_end + (b->alen - wrapped_start);
267 } else {
268 for(i = wrapped_start; i < wrapped_end; i++) {
269 lua_pushinteger(L, b->buffer[i]);
270 }
271 return wrapped_end - wrapped_start;
272 }
273 }
274
275 return 0;
179 } 276 }
180 277
181 static int rb_length(lua_State *L) { 278 static int rb_length(lua_State *L) {
182 ringbuffer *b = luaL_checkudata(L, 1, "ringbuffer_mt"); 279 ringbuffer *b = luaL_checkudata(L, 1, "ringbuffer_mt");
183 lua_pushinteger(L, b->blen); 280 lua_pushinteger(L, b->blen);
237 lua_setfield(L, -2, "write"); 334 lua_setfield(L, -2, "write");
238 lua_pushcfunction(L, rb_size); 335 lua_pushcfunction(L, rb_size);
239 lua_setfield(L, -2, "size"); 336 lua_setfield(L, -2, "size");
240 lua_pushcfunction(L, rb_length); 337 lua_pushcfunction(L, rb_length);
241 lua_setfield(L, -2, "length"); 338 lua_setfield(L, -2, "length");
339 lua_pushcfunction(L, rb_sub);
340 lua_setfield(L, -2, "sub");
341 lua_pushcfunction(L, rb_byte);
342 lua_setfield(L, -2, "byte");
242 lua_pushcfunction(L, rb_free); 343 lua_pushcfunction(L, rb_free);
243 lua_setfield(L, -2, "free"); 344 lua_setfield(L, -2, "free");
244 } 345 }
245 lua_setfield(L, -2, "__index"); 346 lua_setfield(L, -2, "__index");
246 } 347 }