diff options
author | Philipp Janda <siffiejoe@gmx.net> | 2015-01-21 14:34:11 +0100 |
---|---|---|
committer | Philipp Janda <siffiejoe@gmx.net> | 2015-01-21 14:34:11 +0100 |
commit | c57750c925553f627701f2c4897ee6bd6488c7c1 (patch) | |
tree | 465e24fcc87ab8a49baf3e4dec380871275cd486 | |
parent | 866cb79f65c844b3fcfa99d2caa4bf19930dbc6d (diff) | |
download | lua-compat-5.3-c57750c925553f627701f2c4897ee6bd6488c7c1.tar.gz lua-compat-5.3-c57750c925553f627701f2c4897ee6bd6488c7c1.tar.bz2 lua-compat-5.3-c57750c925553f627701f2c4897ee6bd6488c7c1.zip |
backport Lua 5.2/5.3 buffer API for Lua 5.1
-rw-r--r-- | README.md | 4 | ||||
-rw-r--r-- | c-api/compat-5.3.c | 57 | ||||
-rw-r--r-- | c-api/compat-5.3.h | 55 | ||||
-rwxr-xr-x | tests/test.lua | 3 | ||||
-rw-r--r-- | tests/testmod.c | 15 |
5 files changed, 127 insertions, 7 deletions
@@ -129,6 +129,7 @@ For Lua 5.1 additionally: | |||
129 | * `luaL_fileresult` | 129 | * `luaL_fileresult` |
130 | * `luaL_checkversion` (with empty body, only to avoid compile errors) | 130 | * `luaL_checkversion` (with empty body, only to avoid compile errors) |
131 | * `luaL_tolstring` | 131 | * `luaL_tolstring` |
132 | * `luaL_buffinitsize`, `luaL_prepbuffsize`, and `luaL_pushresultsize` | ||
132 | * `lua_pushunsigned`, `lua_tounsignedx`, `lua_tounsigned`, | 133 | * `lua_pushunsigned`, `lua_tounsignedx`, `lua_tounsigned`, |
133 | `luaL_checkunsigned`, `luaL_optunsigned`, if | 134 | `luaL_checkunsigned`, `luaL_optunsigned`, if |
134 | `LUA_COMPAT_APIINTCASTS` is defined. | 135 | `LUA_COMPAT_APIINTCASTS` is defined. |
@@ -149,12 +150,9 @@ For Lua 5.1 additionally: | |||
149 | * `lua_upvaluejoin` (5.1) | 150 | * `lua_upvaluejoin` (5.1) |
150 | * `lua_version` (5.1) | 151 | * `lua_version` (5.1) |
151 | * `lua_yieldk` (5.1) | 152 | * `lua_yieldk` (5.1) |
152 | * `luaL_buffinitsize` (5.1) | ||
153 | * `luaL_execresult` (5.1) | 153 | * `luaL_execresult` (5.1) |
154 | * `luaL_loadbufferx` (5.1) | 154 | * `luaL_loadbufferx` (5.1) |
155 | * `luaL_loadfilex` (5.1) | 155 | * `luaL_loadfilex` (5.1) |
156 | * `luaL_prepbuffsize` (5.1) | ||
157 | * `luaL_pushresultsize` (5.1) | ||
158 | 156 | ||
159 | ## See also | 157 | ## See also |
160 | 158 | ||
diff --git a/c-api/compat-5.3.c b/c-api/compat-5.3.c index a539aed..8db5189 100644 --- a/c-api/compat-5.3.c +++ b/c-api/compat-5.3.c | |||
@@ -391,6 +391,63 @@ COMPAT53_API int luaL_fileresult (lua_State *L, int stat, const char *fname) { | |||
391 | #endif /* not COMPAT53_IS_LUAJIT */ | 391 | #endif /* not COMPAT53_IS_LUAJIT */ |
392 | 392 | ||
393 | 393 | ||
394 | COMPAT53_API void luaL_buffinit (lua_State *L, luaL_Buffer_53 *B) { | ||
395 | /* make it crash if used via pointer to a 5.1-style luaL_Buffer */ | ||
396 | B->b.p = NULL; | ||
397 | B->b.L = NULL; | ||
398 | B->b.lvl = 0; | ||
399 | /* reuse the buffer from the 5.1-style luaL_Buffer though! */ | ||
400 | B->ptr = B->b.buffer; | ||
401 | B->capacity = LUAL_BUFFERSIZE; | ||
402 | B->nelems = 0; | ||
403 | B->L2 = L; | ||
404 | } | ||
405 | |||
406 | |||
407 | COMPAT53_API char *luaL_prepbuffsize (luaL_Buffer_53 *B, size_t s) { | ||
408 | if (B->capacity - B->nelems < s) { /* needs to grow */ | ||
409 | char* newptr = NULL; | ||
410 | size_t newcap = B->capacity * 2; | ||
411 | if (newcap - B->nelems < s) | ||
412 | newcap = B->nelems + s; | ||
413 | if (newcap < B->capacity) /* overflow */ | ||
414 | luaL_error(B->L2, "buffer too large"); | ||
415 | newptr = lua_newuserdata(B->L2, newcap); | ||
416 | memcpy(newptr, B->ptr, B->nelems); | ||
417 | if (B->ptr != B->b.buffer) | ||
418 | lua_replace(B->L2, -2); /* remove old buffer */ | ||
419 | B->ptr = newptr; | ||
420 | B->capacity = newcap; | ||
421 | } | ||
422 | return B->ptr+B->nelems; | ||
423 | } | ||
424 | |||
425 | |||
426 | COMPAT53_API void luaL_addlstring (luaL_Buffer_53 *B, const char *s, size_t l) { | ||
427 | memcpy(luaL_prepbuffsize(B, l), s, l); | ||
428 | luaL_addsize(B, l); | ||
429 | } | ||
430 | |||
431 | |||
432 | COMPAT53_API void luaL_addvalue (luaL_Buffer_53 *B) { | ||
433 | size_t len = 0; | ||
434 | const char *s = lua_tolstring(B->L2, -1, &len); | ||
435 | if (!s) | ||
436 | luaL_error(B->L2, "cannot convert value to string"); | ||
437 | if (B->ptr != B->b.buffer) | ||
438 | lua_insert(B->L2, -2); /* userdata buffer must be at stack top */ | ||
439 | luaL_addlstring(B, s, len); | ||
440 | lua_remove(B->L2, B->ptr != B->b.buffer ? -2 : -1); | ||
441 | } | ||
442 | |||
443 | |||
444 | void luaL_pushresult (luaL_Buffer_53 *B) { | ||
445 | lua_pushlstring(B->L2, B->ptr, B->nelems); | ||
446 | if (B->ptr != B->b.buffer) | ||
447 | lua_replace(B->L2, -2); /* remove userdata buffer */ | ||
448 | } | ||
449 | |||
450 | |||
394 | #endif /* Lua 5.1 */ | 451 | #endif /* Lua 5.1 */ |
395 | 452 | ||
396 | 453 | ||
diff --git a/c-api/compat-5.3.h b/c-api/compat-5.3.h index 8f38719..51bf7eb 100644 --- a/c-api/compat-5.3.h +++ b/c-api/compat-5.3.h | |||
@@ -3,6 +3,7 @@ | |||
3 | 3 | ||
4 | #include <stddef.h> | 4 | #include <stddef.h> |
5 | #include <limits.h> | 5 | #include <limits.h> |
6 | #include <string.h> | ||
6 | #include <lua.h> | 7 | #include <lua.h> |
7 | #include <lauxlib.h> | 8 | #include <lauxlib.h> |
8 | #include <lualib.h> | 9 | #include <lualib.h> |
@@ -45,12 +46,9 @@ | |||
45 | * lua_upvaluejoin | 46 | * lua_upvaluejoin |
46 | * lua_version | 47 | * lua_version |
47 | * lua_yieldk | 48 | * lua_yieldk |
48 | * luaL_buffinitsize | ||
49 | * luaL_execresult | 49 | * luaL_execresult |
50 | * luaL_loadbufferx | 50 | * luaL_loadbufferx |
51 | * luaL_loadfilex | 51 | * luaL_loadfilex |
52 | * luaL_prepbuffsize | ||
53 | * luaL_pushresultsize | ||
54 | */ | 52 | */ |
55 | 53 | ||
56 | /* PUC-Rio Lua uses lconfig_h as include guard for luaconf.h, | 54 | /* PUC-Rio Lua uses lconfig_h as include guard for luaconf.h, |
@@ -80,6 +78,15 @@ typedef struct luaL_Stream { | |||
80 | 78 | ||
81 | typedef size_t lua_Unsigned; | 79 | typedef size_t lua_Unsigned; |
82 | 80 | ||
81 | typedef struct luaL_Buffer_53 { | ||
82 | luaL_Buffer b; /* make incorrect code crash! */ | ||
83 | char *ptr; | ||
84 | size_t nelems; | ||
85 | size_t capacity; | ||
86 | lua_State *L2; | ||
87 | } luaL_Buffer_53; | ||
88 | #define luaL_Buffer luaL_Buffer_53 | ||
89 | |||
83 | #define lua_absindex COMPAT53_CONCAT(COMPAT53_PREFIX, _absindex) | 90 | #define lua_absindex COMPAT53_CONCAT(COMPAT53_PREFIX, _absindex) |
84 | COMPAT53_API int lua_absindex (lua_State *L, int i); | 91 | COMPAT53_API int lua_absindex (lua_State *L, int i); |
85 | 92 | ||
@@ -156,6 +163,46 @@ COMPAT53_API int luaL_fileresult (lua_State *L, int stat, const char *fname); | |||
156 | #define lua_pcallk(L, na, nr, err, ctx, cont) \ | 163 | #define lua_pcallk(L, na, nr, err, ctx, cont) \ |
157 | ((void)(ctx), (void)(cont), lua_pcall(L, na, nr, err)) | 164 | ((void)(ctx), (void)(cont), lua_pcall(L, na, nr, err)) |
158 | 165 | ||
166 | #define luaL_buffinit COMPAT53_CONCAT(COMPAT53_PREFIX, _buffinit_53) | ||
167 | COMPAT53_API void luaL_buffinit (lua_State *L, luaL_Buffer_53 *B); | ||
168 | |||
169 | #define luaL_prepbuffsize COMPAT53_CONCAT(COMPAT53_PREFIX, _prepbufsize_53) | ||
170 | COMPAT53_API char *luaL_prepbuffsize (luaL_Buffer_53 *B, size_t s); | ||
171 | |||
172 | #define luaL_addlstring COMPAT53_CONCAT(COMPAT53_PREFIX, _addlstring_53) | ||
173 | COMPAT53_API void luaL_addlstring (luaL_Buffer_53 *B, const char *s, size_t l); | ||
174 | |||
175 | #define luaL_addvalue COMPAT53_CONCAT(COMPAT53_PREFIX, _addvalue_53) | ||
176 | COMPAT53_API void luaL_addvalue (luaL_Buffer_53 *B); | ||
177 | |||
178 | #define luaL_pushresult COMPAT53_CONCAT(COMPAT53_PREFIX, _pushresult_53) | ||
179 | COMPAT53_API void luaL_pushresult (luaL_Buffer_53 *B); | ||
180 | |||
181 | #undef luaL_buffinitsize | ||
182 | #define luaL_buffinitsize(L, B, s) \ | ||
183 | (luaL_buffinit(L, B), luaL_prepbuffsize(B, s)) | ||
184 | |||
185 | #undef luaL_prepbuffer | ||
186 | #define luaL_prepbuffer(B) \ | ||
187 | luaL_prepbuffsize(B, LUAL_BUFFERSIZE) | ||
188 | |||
189 | #undef luaL_addchar | ||
190 | #define luaL_addchar(B, c) \ | ||
191 | ((void)((B)->nelems < (B)->capacity || luaL_prepbuffsize(B, 1)), \ | ||
192 | ((B)->ptr[(B)->nelems++] = (c))) | ||
193 | |||
194 | #undef luaL_addsize | ||
195 | #define luaL_addsize(B, s) \ | ||
196 | ((B)->nelems += (s)) | ||
197 | |||
198 | #undef luaL_addstring | ||
199 | #define luaL_addstring(B, s) \ | ||
200 | luaL_addlstring(B, s, strlen(s)) | ||
201 | |||
202 | #undef luaL_pushresultsize | ||
203 | #define luaL_pushresultsize(B, s) \ | ||
204 | (luaL_addsize(B, s), luaL_pushresult(B)) | ||
205 | |||
159 | #if defined(LUA_COMPAT_APIINTCASTS) | 206 | #if defined(LUA_COMPAT_APIINTCASTS) |
160 | #define lua_pushunsigned(L, n) \ | 207 | #define lua_pushunsigned(L, n) \ |
161 | lua_pushinteger(L, (lua_Integer)(n)) | 208 | lua_pushinteger(L, (lua_Integer)(n)) |
@@ -216,7 +263,7 @@ COMPAT53_API size_t lua_stringtonumber (lua_State *L, const char *s); | |||
216 | #define luaL_getmetafield(L, o, e) \ | 263 | #define luaL_getmetafield(L, o, e) \ |
217 | (luaL_getmetafield(L, o, e) ? lua_type(L, -1) : LUA_TNIL) | 264 | (luaL_getmetafield(L, o, e) ? lua_type(L, -1) : LUA_TNIL) |
218 | 265 | ||
219 | #define luaL_requiref COMPAT53_CONCAT(COMPAT53_PREFIX, L_requiref_) | 266 | #define luaL_requiref COMPAT53_CONCAT(COMPAT53_PREFIX, L_requiref_53) |
220 | COMPAT53_API void luaL_requiref (lua_State *L, const char *modname, | 267 | COMPAT53_API void luaL_requiref (lua_State *L, const char *modname, |
221 | lua_CFunction openf, int glb ); | 268 | lua_CFunction openf, int glb ); |
222 | 269 | ||
diff --git a/tests/test.lua b/tests/test.lua index 98259fe..83e174e 100755 --- a/tests/test.lua +++ b/tests/test.lua | |||
@@ -679,5 +679,8 @@ local t = setmetatable({}, { | |||
679 | __tostring = function(v) return nil end | 679 | __tostring = function(v) return nil end |
680 | }) | 680 | }) |
681 | print(pcall(mod.tolstring, t)) | 681 | print(pcall(mod.tolstring, t)) |
682 | |||
683 | ___'' | ||
684 | print(mod.buffer()) | ||
682 | ___'' | 685 | ___'' |
683 | 686 | ||
diff --git a/tests/testmod.c b/tests/testmod.c index 2c6242b..f89b10a 100644 --- a/tests/testmod.c +++ b/tests/testmod.c | |||
@@ -242,6 +242,20 @@ static int test_tolstring (lua_State *L) { | |||
242 | return 2; | 242 | return 2; |
243 | } | 243 | } |
244 | 244 | ||
245 | static int test_buffer (lua_State *L) { | ||
246 | luaL_Buffer b; | ||
247 | char *p = luaL_buffinitsize(L, &b, LUAL_BUFFERSIZE+1); | ||
248 | p[0] = 'a'; | ||
249 | p[1] = 'b'; | ||
250 | luaL_addsize(&b, 2); | ||
251 | luaL_addstring(&b, "c"); | ||
252 | lua_pushliteral(L, "d"); | ||
253 | luaL_addvalue(&b); | ||
254 | luaL_addchar(&b, 'e'); | ||
255 | luaL_pushresult(&b); | ||
256 | return 1; | ||
257 | } | ||
258 | |||
245 | 259 | ||
246 | static const luaL_Reg funcs[] = { | 260 | static const luaL_Reg funcs[] = { |
247 | { "isinteger", test_isinteger }, | 261 | { "isinteger", test_isinteger }, |
@@ -262,6 +276,7 @@ static const luaL_Reg funcs[] = { | |||
262 | { "uservalue", test_uservalue }, | 276 | { "uservalue", test_uservalue }, |
263 | { "globals", test_globals }, | 277 | { "globals", test_globals }, |
264 | { "tolstring", test_tolstring }, | 278 | { "tolstring", test_tolstring }, |
279 | { "buffer", test_buffer }, | ||
265 | { NULL, NULL } | 280 | { NULL, NULL } |
266 | }; | 281 | }; |
267 | 282 | ||