9 changed files with 295 additions and 10 deletions
@ -0,0 +1,17 @@
|
||||
|
||||
#include "base.h" |
||||
|
||||
static server_option* find_option(server *srv, const char *key) { |
||||
return (server_option*) g_hash_table_lookup(srv->options, key); |
||||
} |
||||
|
||||
gboolean parse_option(server *srv, const char *key, option *opt, option_mark *mark) { |
||||
server_option *sopt; |
||||
|
||||
if (!srv || !key || !mark) return FALSE; |
||||
|
||||
sopt = find_option(srv, key); |
||||
if (!sopt) return FALSE; |
||||
|
||||
return FALSE; |
||||
} |
@ -0,0 +1,66 @@
|
||||
|
||||
#include "options.h" |
||||
|
||||
option* option_new_bool(gboolean val) { |
||||
option *opt = g_slice_new0(option); |
||||
opt->value.opt_bool = val; |
||||
return opt; |
||||
} |
||||
|
||||
option* option_new_int(gint val) { |
||||
option *opt = g_slice_new0(option); |
||||
opt->value.opt_int = val; |
||||
return opt; |
||||
} |
||||
|
||||
option* option_new_string(GString *val) { |
||||
option *opt = g_slice_new0(option); |
||||
opt->value.opt_string = val; |
||||
return opt; |
||||
} |
||||
|
||||
option* option_new_list() { |
||||
option *opt = g_slice_new0(option); |
||||
opt->value.opt_list = g_array_new(FALSE, TRUE, sizeof(option*)); |
||||
return opt; |
||||
} |
||||
|
||||
void _option_hash_free_key(gpointer data) { |
||||
g_string_free((GString*) data, TRUE); |
||||
} |
||||
|
||||
void _option_hash_free_value(gpointer data) { |
||||
option_free((option*) data); |
||||
} |
||||
|
||||
option* option_new_hash() { |
||||
option *opt = g_slice_new0(option); |
||||
opt->value.opt_hash = g_hash_table_new_full( |
||||
(GHashFunc) g_string_hash, (GEqualFunc) g_string_equal, |
||||
_option_hash_free_key, _option_hash_free_value); |
||||
return opt; |
||||
} |
||||
|
||||
|
||||
void option_free(option* opt) { |
||||
if (!opt) return; |
||||
|
||||
switch (opt->type) { |
||||
case OPTION_NONE: |
||||
case OPTION_BOOLEAN: |
||||
case OPTION_INT: |
||||
/* Nothing to free */ |
||||
break; |
||||
case OPTION_STRING: |
||||
g_string_free(opt->value.opt_string, TRUE); |
||||
break; |
||||
case OPTION_LIST: |
||||
/* TODO */ |
||||
break; |
||||
case OPTION_HASH: |
||||
/* TODO */ |
||||
break; |
||||
} |
||||
opt->type = OPTION_NONE; |
||||
g_slice_free(option, opt); |
||||
} |
@ -0,0 +1,138 @@
|
||||
|
||||
#include "options_lua.h" |
||||
#include "log.h" |
||||
|
||||
/* replace a negative stack index with a positive one,
|
||||
* so that you don't need to care about push/pop |
||||
*/ |
||||
static int lua_fixindex(lua_State *L, int ndx) { |
||||
int top; |
||||
if (ndx < 0 && ndx >= -(top = lua_gettop(L))) |
||||
ndx = top + ndx + 1; |
||||
return ndx; |
||||
} |
||||
|
||||
static option* option_from_lua_table(lua_State *L, int ndx) { |
||||
option *opt = NULL, *sub_option; |
||||
GArray *list = NULL; |
||||
GHashTable *hash = NULL; |
||||
int ikey; |
||||
GString *skey; |
||||
|
||||
ndx = lua_fixindex(L, ndx); |
||||
lua_pushnil(L); |
||||
while (lua_next(L, ndx) != 0) { |
||||
switch (lua_type(L, -2)) { |
||||
case LUA_TNUMBER: |
||||
if (hash) goto mixerror; |
||||
if (!list) { |
||||
opt = option_new_list(); |
||||
list = opt->value.opt_list; |
||||
} |
||||
ikey = lua_tointeger(L, -2); |
||||
if (ikey < 0) { |
||||
ERROR("Invalid key < 0: %i - skipping entry", ikey); |
||||
lua_pop(L, 1); |
||||
continue; |
||||
} |
||||
sub_option = option_from_lua(L); |
||||
if (!sub_option) continue; |
||||
if ((size_t) ikey >= list->len) { |
||||
g_array_set_size(list, ikey + 1); |
||||
} |
||||
g_array_index(list, option*, ikey) = sub_option; |
||||
break; |
||||
|
||||
case LUA_TSTRING: |
||||
if (list) goto mixerror; |
||||
if (!hash) { |
||||
opt = option_new_hash(); |
||||
hash = opt->value.opt_hash; |
||||
} |
||||
skey = lua_togstring(L, -2); |
||||
if (g_hash_table_lookup(hash, skey)) { |
||||
ERROR("Key already exists in hash: '%s' - skipping entry", skey->str); |
||||
lua_pop(L, 1); |
||||
continue; |
||||
} |
||||
sub_option = option_from_lua(L); |
||||
if (!sub_option) { |
||||
g_string_free(skey, TRUE); |
||||
continue; |
||||
} |
||||
g_hash_table_insert(hash, skey, sub_option); |
||||
break; |
||||
|
||||
default: |
||||
ERROR("Unexpted key type in table: %s (%i) - skipping entry", lua_typename(L, -1), lua_type(L, -1)); |
||||
lua_pop(L, 1); |
||||
break; |
||||
} |
||||
} |
||||
|
||||
return opt; |
||||
|
||||
mixerror: |
||||
ERROR("%s", "Cannot mix list with hash; skipping remaining part of table"); |
||||
lua_pop(L, 2); |
||||
return opt; |
||||
} |
||||
|
||||
|
||||
option* option_from_lua(lua_State *L) { |
||||
option *opt; |
||||
|
||||
switch (lua_type(L, -1)) { |
||||
case LUA_TNIL: |
||||
lua_pop(L, 1); |
||||
return NULL; |
||||
|
||||
case LUA_TBOOLEAN: |
||||
opt = option_new_bool(lua_toboolean(L, -1)); |
||||
lua_pop(L, 1); |
||||
return opt; |
||||
|
||||
case LUA_TNUMBER: |
||||
opt = option_new_int(lua_tointeger(L, -1)); |
||||
lua_pop(L, 1); |
||||
return opt; |
||||
|
||||
case LUA_TSTRING: |
||||
opt = option_new_string(lua_togstring(L, -1)); |
||||
lua_pop(L, 1); |
||||
return opt; |
||||
|
||||
case LUA_TTABLE: |
||||
opt = option_from_lua_table(L, -1); |
||||
lua_pop(L, 1); |
||||
return opt; |
||||
|
||||
case LUA_TLIGHTUSERDATA: |
||||
case LUA_TFUNCTION: |
||||
case LUA_TUSERDATA: |
||||
case LUA_TTHREAD: |
||||
case LUA_TNONE: |
||||
default: |
||||
ERROR("Unexpected lua type: %s (%i)", lua_typename(L, -1), lua_type(L, -1)); |
||||
lua_pop(L, 1); |
||||
return NULL; |
||||
} |
||||
} |
||||
|
||||
GString* lua_togstring(lua_State *L, int ndx) { |
||||
const char *buf; |
||||
size_t len = 0; |
||||
GString *str = NULL; |
||||
|
||||
if (lua_type(L, ndx) == LUA_TSTRING) { |
||||
buf = lua_tolstring(L, ndx, &len); |
||||
if (buf) str = g_string_new_len(buf, len); |
||||
} else { |
||||
lua_pushvalue(L, ndx); |
||||
buf = lua_tolstring(L, -1, &len); |
||||
if (buf) str = g_string_new_len(buf, len); |
||||
lua_pop(L, 1); |
||||
} |
||||
|
||||
return str; |
||||
} |
@ -0,0 +1,16 @@
|
||||
#ifndef _LIGHTTPD_OPTIONS_LUA_H_ |
||||
#define _LIGHTTPD_OPTIONS_LUA_H_ |
||||
|
||||
#include "options.h" |
||||
|
||||
#include <lua.h> |
||||
|
||||
/* converts the top of the stack into an option
|
||||
* and pops the value |
||||
* returns NULL if it couldn't convert the value (still pops it) |
||||
*/ |
||||
LI_API option* option_from_lua(lua_State *L); |
||||
|
||||
LI_API GString* lua_togstring(lua_State *L, int ndx); |
||||
|
||||
#endif |
Loading…
Reference in new issue