Skip to content

Commit cacdb9c

Browse files
authored
Merge pull request #127 from moteus/null
Allow use null value.
2 parents 532719c + 886f696 commit cacdb9c

File tree

10 files changed

+259
-17
lines changed

10 files changed

+259
-17
lines changed

src/l52util.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,3 +156,11 @@ int64_t lutil_optint64(lua_State *L, int idx, int64_t v){
156156
void lutil_pushnvalues(lua_State *L, int n){
157157
for(;n;--n) lua_pushvalue(L, -n);
158158
}
159+
160+
int lutil_is_null(lua_State *L, int i){
161+
return lua_islightuserdata(L, i) && 0 == lua_touserdata(L, i);
162+
}
163+
164+
void lutil_push_null(lua_State *L){
165+
lua_pushlightuserdata(L, (void*)0);
166+
}

src/l52util.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,4 +88,8 @@ int64_t lutil_optint64(lua_State *L, int idx, int64_t v);
8888

8989
void lutil_pushnvalues(lua_State *L, int n);
9090

91+
int lutil_is_null(lua_State *L, int i);
92+
93+
void lutil_push_null(lua_State *L);
94+
9195
#endif

src/lceasy.c

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -344,16 +344,22 @@ static int lcurl_opt_set_off_(lua_State *L, int opt){
344344

345345
static int lcurl_opt_set_string_(lua_State *L, int opt, int store){
346346
lcurl_easy_t *p = lcurl_geteasy(L);
347-
CURLcode code;
347+
CURLcode code; const char *value;
348348

349-
luaL_argcheck(L, lua_type(L, 2) == LUA_TSTRING, 2, "string expected");
349+
luaL_argcheck(L, lua_type(L, 2) == LUA_TSTRING || lutil_is_null(L, 2), 2, "string expected");
350350

351-
code = curl_easy_setopt(p->curl, opt, lua_tostring(L, 2));
351+
value = lua_tostring(L, 2);
352+
code = curl_easy_setopt(p->curl, opt, value);
352353
if(code != CURLE_OK){
353354
return lcurl_fail_ex(L, p->err_mode, LCURL_ERROR_EASY, code);
354355
}
355356

356-
if(store)lcurl_storage_preserve_iv(L, p->storage, opt, 2);
357+
if(store){
358+
if(value)
359+
lcurl_storage_preserve_iv(L, p->storage, opt, 2);
360+
else
361+
lcurl_storage_remove_i(L, p->storage, opt);
362+
}
357363

358364
lua_settop(L, 1);
359365
return 1;
@@ -365,7 +371,7 @@ static int lcurl_opt_set_slist_(lua_State *L, int opt, int list_no){
365371
CURLcode code;
366372
int ref = p->lists[list_no];
367373

368-
luaL_argcheck(L, list || lua_istable(L, 2), 2, "array expected");
374+
luaL_argcheck(L, list || lua_istable(L, 2) || lutil_is_null(L, 2), 2, "array expected");
369375

370376
if(ref != LUA_NOREF){
371377
struct curl_slist *tmp = lcurl_storage_remove_slist(L, p->storage, ref);

src/lcmime.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,7 @@ int lcurl_mime_set_lua(lua_State *L, lcurl_mime_t *p, lua_State *v){
135135

136136
#define IS_NILORSTR(L, i) (lua_type(L, i) == LUA_TSTRING) || (lua_type(L, i) == LUA_TNIL)
137137
#define IS_TABLE(L, i) lua_type(L, i) == LUA_TTABLE
138-
#define IS_FALSE(L, i) (lua_type(L, i) == LUA_TBOOLEAN) && (!lua_toboolean(L, i))
138+
#define IS_FALSE(L, i) ((lua_type(L, i) == LUA_TBOOLEAN) && (!lua_toboolean(L, i))) || lutil_is_null(L,i)
139139
#define IS_OPTSTR(L, i) (IS_FALSE(L, i)) || (IS_NILORSTR(L, i))
140140

141141
static int lutil_isarray(lua_State *L, int i){
@@ -512,13 +512,13 @@ static int lcurl_mime_part_headers(lua_State *L){
512512
}
513513
else{
514514
list = lcurl_util_to_slist(L, 2);
515-
luaL_argcheck(L, list, 2, "array or nil expected");
515+
luaL_argcheck(L, list || IS_TABLE(L, 2), 2, "array or null expected");
516516
}
517517

518518
ret = curl_mime_headers(p->part, list, 1);
519519

520520
if(ret != CURLE_OK){
521-
curl_slist_free_all(list);
521+
if(list) curl_slist_free_all(list);
522522
return lcurl_fail_ex(L, p->err_mode, LCURL_ERROR_EASY, ret);
523523
}
524524

src/lcmulti.c

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -424,16 +424,22 @@ static int lcurl_opt_set_string_array_(lua_State *L, int opt){
424424
lcurl_multi_t *p = lcurl_getmulti(L);
425425
CURLMcode code;
426426
int n;
427-
luaL_argcheck(L, lua_type(L, 2) == LUA_TTABLE, 2, "array expected");
428-
n = lua_rawlen(L, 2);
427+
428+
if (lutil_is_null(L, 2)) {
429+
n = 0;
430+
}
431+
else {
432+
luaL_argcheck(L, lua_type(L, 2) == LUA_TTABLE, 2, "array expected");
433+
n = lua_rawlen(L, 2);
434+
}
435+
429436
if(n == 0){
430-
char *val[] = {NULL};
431-
code = curl_multi_setopt(p->curl, opt, val);
437+
code = curl_multi_setopt(p->curl, opt, 0);
432438
}
433439
else{
434440
int i;
435-
char const* *val = malloc(sizeof(char*) * (n + 1));
436-
if(!*val){
441+
char const**val = malloc(sizeof(char*) * (n + 1));
442+
if(!val){
437443
return lcurl_fail_ex(L, p->err_mode, LCURL_ERROR_MULTI, CURLM_OUT_OF_MEMORY);
438444
}
439445
for(i = 1; i <= n; ++i){

src/lcoptshare.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,14 @@ OPT_ENTRY(unshare, UNSHARE, LNG, 0 )
1414
FLG_ENTRY( LOCK_DATA_COOKIE )
1515
FLG_ENTRY( LOCK_DATA_DNS )
1616
FLG_ENTRY( LOCK_DATA_SSL_SESSION )
17+
FLG_ENTRY( LOCK_DATA_CONNECT )
1718

1819
#ifdef OPT_ENTRY_IS_NULL
1920
# undef OPT_ENTRY
21+
# undef OPT_ENTRY_IS_NULL
2022
#endif
2123

2224
#ifdef FLG_ENTRY_IS_NULL
2325
# undef FLG_ENTRY
26+
# undef FLG_ENTRY_IS_NULL
2427
#endif

src/lcurl.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -270,6 +270,9 @@ static int luaopen_lcurl_(lua_State *L, const struct luaL_Reg *func){
270270

271271
lcurl_util_set_const(L, lcurl_flags);
272272

273+
lutil_push_null(L);
274+
lua_setfield(L, -2, "null");
275+
273276
return 1;
274277
}
275278

src/lcutils.c

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -171,8 +171,6 @@ int lcurl_set_callback(lua_State *L, lcurl_callback_t *c, int i, const char *met
171171
luaL_argcheck(L, !lua_isnoneornil(L, i), i, "no function present");
172172
luaL_argcheck(L, (top < (i + 2)), i + 2, "no arguments expected");
173173

174-
// if(top > (i + 1)) lua_settop(L, i + 1); // this for force ignore other arguments
175-
176174
assert((top == i)||(top == (i + 1)));
177175

178176
if(c->ud_ref != LUA_NOREF){
@@ -185,6 +183,19 @@ int lcurl_set_callback(lua_State *L, lcurl_callback_t *c, int i, const char *met
185183
c->cb_ref = LUA_NOREF;
186184
}
187185

186+
if(lutil_is_null(L, i)){
187+
if(top == (i + 1)){
188+
// Do we can just ignore this?
189+
luaL_argcheck(L,
190+
lua_isnoneornil(L, i + 1) || lutil_is_null(L, i + 1)
191+
,i + 1, "no context allowed when set callback to null"
192+
);
193+
}
194+
lua_pop(L, top - i + 1);
195+
196+
return 1;
197+
}
198+
188199
if(lua_gettop(L) == (i + 1)){// function + context
189200
c->ud_ref = luaL_ref(L, LCURL_LUA_REGISTRY);
190201
c->cb_ref = luaL_ref(L, LCURL_LUA_REGISTRY);

test/test_easy.lua

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@ local POST_URL = "http://127.0.0.1:7090/post"
3535
local weak_ptr, gc_collect, is_curl_ge, read_file, stream, Stream, dump_request =
3636
utils.import('weak_ptr', 'gc_collect', 'is_curl_ge', 'read_file', 'stream', 'Stream', 'dump_request')
3737

38+
local null = curl.null
39+
3840
local ENABLE = true
3941

4042
local _ENV = TEST_CASE'curl error' if ENABLE then
@@ -151,9 +153,16 @@ function test_reset_write_callback()
151153
assert_equal(c, c:setopt_writefunction(f))
152154
assert_equal(c, c:setopt_writefunction(f.write, f))
153155
assert_equal(c, c:setopt_writefunction(print))
156+
assert_equal(c, c:setopt_writefunction(print, null))
157+
assert_equal(c, c:setopt_writefunction(null))
158+
assert_equal(c, c:setopt_writefunction(null, nil))
159+
assert_equal(c, c:setopt_writefunction(null, null))
154160
assert_error(function()c:setopt_writefunction()end)
155161
assert_error(function()c:setopt_writefunction(nil)end)
156162
assert_error(function()c:setopt_writefunction(nil, f)end)
163+
assert_error(function()c:setopt_writefunction(null, {})end)
164+
assert_error(function()c:setopt_writefunction(print, {}, nil)end)
165+
assert_error(function()c:setopt_writefunction(print, {}, null)end)
157166
end
158167

159168
function test_write_pass_01()
@@ -208,6 +217,38 @@ function test_write_coro()
208217
assert_equal(co2, called)
209218
end
210219

220+
function test_write_pass_null_context()
221+
c = assert(curl.easy{
222+
url = GET_URL;
223+
})
224+
225+
local context
226+
assert_equal(c, c:setopt_writefunction(function(ctx)
227+
context = ctx
228+
return true
229+
end, null))
230+
231+
assert_equal(c, c:perform())
232+
assert_equal(null, context)
233+
end
234+
235+
function test_write_pass_nil_context()
236+
c = assert(curl.easy{
237+
url = GET_URL;
238+
})
239+
240+
local context, called
241+
assert_equal(c, c:setopt_writefunction(function(ctx)
242+
context = ctx
243+
called = true
244+
return true
245+
end, nil))
246+
247+
assert_equal(c, c:perform())
248+
assert_true(called)
249+
assert_nil(context)
250+
end
251+
211252
end
212253

213254
local _ENV = TEST_CASE'progress_callback' if ENABLE then
@@ -379,9 +420,14 @@ function test_reset_header_callback()
379420
assert_equal(c, c:setopt_headerfunction(f))
380421
assert_equal(c, c:setopt_headerfunction(f.header, f))
381422
assert_equal(c, c:setopt_headerfunction(print))
423+
assert_equal(c, c:setopt_headerfunction(null))
424+
assert_equal(c, c:setopt_headerfunction(null, nil))
425+
assert_equal(c, c:setopt_headerfunction(null, null))
382426
assert_error(function()c:setopt_headerfunction()end)
383427
assert_error(function()c:setopt_headerfunction(nil)end)
384428
assert_error(function()c:setopt_headerfunction(nil, f)end)
429+
assert_error(function()c:setopt_headerfunction(null, {})end)
430+
assert_error(function()c:setopt_headerfunction(print, {}, nil)end)
385431
end
386432

387433
function test_header_pass_01()
@@ -1060,4 +1106,62 @@ end
10601106

10611107
end
10621108

1109+
local _ENV = TEST_CASE'set_null' if ENABLE then
1110+
1111+
local c, m
1112+
1113+
function teardown()
1114+
if c then c:close() end
1115+
if m then m:close() end
1116+
m, c = nil
1117+
end
1118+
1119+
function test_string()
1120+
c = curl.easy()
1121+
c:setopt_accept_encoding('gzip')
1122+
local body, headers = assert_string(dump_request(c))
1123+
assert_match("Accept%-Encoding:%s*gzip", headers)
1124+
1125+
c:setopt_accept_encoding(null)
1126+
body, headers = assert_string(dump_request(c))
1127+
assert_not_match("Accept%-Encoding:%s*gzip", headers)
1128+
end
1129+
1130+
function test_string_via_table()
1131+
c = curl.easy()
1132+
c:setopt_accept_encoding('gzip')
1133+
local body, headers = assert_string(dump_request(c))
1134+
assert_match("Accept%-Encoding:%s*gzip", headers)
1135+
1136+
c:setopt{ accept_encoding = null }
1137+
body, headers = assert_string(dump_request(c))
1138+
assert_not_match("Accept%-Encoding:%s*gzip", headers)
1139+
end
1140+
1141+
function test_slist()
1142+
c = curl.easy()
1143+
c:setopt_httpheader({'X-Custom: value'})
1144+
c:setopt_httpheader(null)
1145+
local body, headers = assert_string(dump_request(c))
1146+
assert_not_match("X%-Custom:%s*value\r\n", headers)
1147+
end
1148+
1149+
function test_slist_via_table()
1150+
c = curl.easy()
1151+
c:setopt_httpheader({'X-Custom: value'})
1152+
c:setopt{httpheader = null}
1153+
local body, headers = assert_string(dump_request(c))
1154+
assert_not_match("X%-Custom:%s*value\r\n", headers)
1155+
end
1156+
1157+
function test_multi_set_array()
1158+
m = curl.multi()
1159+
m:setopt_pipelining_site_bl{
1160+
'127.0.0.1'
1161+
}
1162+
assert_equal(m, m:setopt_pipelining_site_bl(null))
1163+
end
1164+
1165+
end
1166+
10631167
RUN()

0 commit comments

Comments
 (0)