11 size_t rpos
; /* read position */
12 size_t wpos
; /* write position */
13 size_t alen
; /* allocated size */
14 size_t blen
; /* current content size */
18 char readchar(ringbuffer
*b
) {
20 return b
->buffer
[(b
->rpos
++) % b
->alen
];
23 void writechar(ringbuffer
*b
, char c
) {
25 b
->buffer
[(b
->wpos
++) % b
->alen
] = c
;
28 /* make sure position counters stay within the allocation */
29 void modpos(ringbuffer
*b
) {
30 b
->rpos
= b
->rpos
% b
->alen
;
31 b
->wpos
= b
->wpos
% b
->alen
;
34 int find(ringbuffer
*b
, const char *s
, size_t l
) {
38 if(b
->rpos
== b
->wpos
) { /* empty */
42 /* look for a matching first byte */
43 for(i
= 0; i
<= b
->blen
- l
; i
++) {
44 if(b
->buffer
[(b
->rpos
+ i
) % b
->alen
] == *s
) {
47 /* check if the following byte also match */
48 for(j
= 1; j
< l
; j
++)
49 if(b
->buffer
[(b
->rpos
+ i
+ j
) % b
->alen
] != s
[j
]) {
64 * Find first position of a substring in buffer
65 * (buffer, string) -> number
67 int rb_find(lua_State
*L
) {
69 ringbuffer
*b
= luaL_checkudata(L
, 1, "ringbuffer_mt");
70 const char *s
= luaL_checklstring(L
, 2, &l
);
74 lua_pushinteger(L
, m
);
82 * Move read position forward without returning the data
83 * (buffer, number) -> boolean
85 int rb_discard(lua_State
*L
) {
86 ringbuffer
*b
= luaL_checkudata(L
, 1, "ringbuffer_mt");
87 size_t r
= luaL_checkinteger(L
, 2);
90 lua_pushboolean(L
, 0);
98 lua_pushboolean(L
, 1);
103 * Read bytes from buffer
104 * (buffer, number, boolean?) -> string
106 int rb_read(lua_State
*L
) {
107 ringbuffer
*b
= luaL_checkudata(L
, 1, "ringbuffer_mt");
108 size_t r
= luaL_checkinteger(L
, 2);
109 int peek
= lua_toboolean(L
, 3);
116 if((b
->rpos
+ r
) > b
->alen
) {
117 /* Substring wraps around to the beginning of the buffer */
118 lua_pushlstring(L
, &b
->buffer
[b
->rpos
], b
->alen
- b
->rpos
);
119 lua_pushlstring(L
, b
->buffer
, r
- (b
->alen
- b
->rpos
));
122 lua_pushlstring(L
, &b
->buffer
[b
->rpos
], r
);
135 * Read buffer until first occurrence of a substring
136 * (buffer, string) -> string
138 int rb_readuntil(lua_State
*L
) {
140 ringbuffer
*b
= luaL_checkudata(L
, 1, "ringbuffer_mt");
141 const char *s
= luaL_checklstring(L
, 2, &l
);
146 lua_pushinteger(L
, m
);
154 * Write bytes into the buffer
155 * (buffer, string) -> integer
157 int rb_write(lua_State
*L
) {
159 ringbuffer
*b
= luaL_checkudata(L
, 1, "ringbuffer_mt");
160 const char *s
= luaL_checklstring(L
, 2, &l
);
162 /* Does `l` bytes fit? */
163 if((l
+ b
->blen
) > b
->alen
) {
175 lua_pushinteger(L
, w
);
180 int rb_tostring(lua_State
*L
) {
181 ringbuffer
*b
= luaL_checkudata(L
, 1, "ringbuffer_mt");
182 lua_pushfstring(L
, "ringbuffer: %p %d/%d", b
, b
->blen
, b
->alen
);
186 int rb_length(lua_State
*L
) {
187 ringbuffer
*b
= luaL_checkudata(L
, 1, "ringbuffer_mt");
188 lua_pushinteger(L
, b
->blen
);
192 int rb_size(lua_State
*L
) {
193 ringbuffer
*b
= luaL_checkudata(L
, 1, "ringbuffer_mt");
194 lua_pushinteger(L
, b
->alen
);
198 int rb_free(lua_State
*L
) {
199 ringbuffer
*b
= luaL_checkudata(L
, 1, "ringbuffer_mt");
200 lua_pushinteger(L
, b
->alen
- b
->blen
);
204 int rb_new(lua_State
*L
) {
205 size_t size
= luaL_optinteger(L
, 1, sysconf(_SC_PAGESIZE
));
206 ringbuffer
*b
= lua_newuserdata(L
, sizeof(ringbuffer
) + size
);
213 luaL_getmetatable(L
, "ringbuffer_mt");
214 lua_setmetatable(L
, -2);
219 int luaopen_util_ringbuffer(lua_State
*L
) {
220 #if (LUA_VERSION_NUM > 501)
221 luaL_checkversion(L
);
224 if(luaL_newmetatable(L
, "ringbuffer_mt")) {
225 lua_pushcfunction(L
, rb_tostring
);
226 lua_setfield(L
, -2, "__tostring");
227 lua_pushcfunction(L
, rb_length
);
228 lua_setfield(L
, -2, "__len");
230 lua_createtable(L
, 0, 7); /* __index */
232 lua_pushcfunction(L
, rb_find
);
233 lua_setfield(L
, -2, "find");
234 lua_pushcfunction(L
, rb_discard
);
235 lua_setfield(L
, -2, "discard");
236 lua_pushcfunction(L
, rb_read
);
237 lua_setfield(L
, -2, "read");
238 lua_pushcfunction(L
, rb_readuntil
);
239 lua_setfield(L
, -2, "readuntil");
240 lua_pushcfunction(L
, rb_write
);
241 lua_setfield(L
, -2, "write");
242 lua_pushcfunction(L
, rb_size
);
243 lua_setfield(L
, -2, "size");
244 lua_pushcfunction(L
, rb_length
);
245 lua_setfield(L
, -2, "length");
246 lua_pushcfunction(L
, rb_free
);
247 lua_setfield(L
, -2, "free");
249 lua_setfield(L
, -2, "__index");
252 lua_createtable(L
, 0, 1);
253 lua_pushcfunction(L
, rb_new
);
254 lua_setfield(L
, -2, "new");