Browse Source

[common] refactor liValue to share most of the code

* removing unused "range" value type in angel
personal/stbuehler/wip
Stefan Bühler 8 years ago
parent
commit
db58828e0b
  1. 2
      include/lighttpd/angel_base.h
  2. 58
      include/lighttpd/angel_value.h
  3. 2
      include/lighttpd/base.h
  4. 2
      include/lighttpd/options.h
  5. 15
      include/lighttpd/typedefs.h
  6. 50
      include/lighttpd/value.h
  7. 1
      src/CMakeLists.txt
  8. 14
      src/angel/angel_config_parser.rl
  9. 2
      src/angel/angel_plugin.c
  10. 207
      src/angel/angel_value.c
  11. 1
      src/common/Makefile.am
  12. 342
      src/common/value.c
  13. 4
      src/main/config_lua.c
  14. 5
      src/main/config_parser.rl
  15. 61
      src/main/plugin_core.c
  16. 325
      src/main/value.c
  17. 17
      src/main/value_lua.c
  18. 2
      src/modules/mod_accesslog.c

2
include/lighttpd/angel_base.h

@ -11,7 +11,7 @@
#include <lighttpd/angel_typedefs.h>
#include <lighttpd/angel_value.h>
#include <lighttpd/value.h>
#include <lighttpd/angel_data.h>
#include <lighttpd/angel_connection.h>
#include <lighttpd/angel_log.h>

58
include/lighttpd/angel_value.h

@ -1,58 +0,0 @@
#ifndef _LIGHTTPD_ANGEL_VALUE_H_
#define _LIGHTTPD_ANGEL_VALUE_H_
#ifndef _LIGHTTPD_ANGEL_BASE_H_
#error Please include <lighttpd/angel_base.h> instead of this file
#endif
typedef struct liValue liValue;
typedef struct liValueRange liValueRange;
typedef enum {
LI_VALUE_NONE,
/* primitive types */
LI_VALUE_BOOLEAN,
LI_VALUE_NUMBER,
LI_VALUE_STRING,
LI_VALUE_RANGE,
/* container */
LI_VALUE_LIST,
LI_VALUE_HASH
} liValueType;
struct liValueRange {
guint64 from, to;
};
struct liValue {
liValueType type;
union {
gboolean boolean;
gint64 number;
GString *string;
liValueRange range;
/* array of (liValue*) */
GPtrArray *list;
/* hash GString => value */
GHashTable *hash;
} data;
};
LI_API liValue* li_value_new_none(void);
LI_API liValue* li_value_new_bool(gboolean val);
LI_API liValue* li_value_new_number(gint64 val);
LI_API liValue* li_value_new_string(GString *val);
LI_API liValue* li_value_new_range(liValueRange val);
LI_API liValue* li_value_new_list(void);
LI_API liValue* li_value_new_hash(void);
LI_API liValue* li_value_copy(liValue* val);
LI_API void li_value_free(liValue* val);
LI_API const char* li_value_type_string(liValueType type);
LI_API GString *li_value_to_string(liValue *val);
#endif

2
include/lighttpd/base.h

@ -24,6 +24,7 @@
#include <lighttpd/radix.h>
#include <lighttpd/fetch.h>
#include <lighttpd/value.h>
#include <lighttpd/base_lua.h>
#include <lighttpd/log.h>
#include <lighttpd/server.h>
@ -32,7 +33,6 @@
#include <lighttpd/condition.h>
#include <lighttpd/ip_parsers.h>
#include <lighttpd/options.h>
#include <lighttpd/value.h>
#include <lighttpd/actions.h>
#include <lighttpd/plugin.h>
#include <lighttpd/http_headers.h>

2
include/lighttpd/options.h

@ -18,7 +18,7 @@ struct liOptionPtrValue {
/* some common pointer types */
GString *string;
GArray *list;
GPtrArray *list;
GHashTable *hash;
liAction *action;
liCondition *cond;

15
include/lighttpd/typedefs.h

@ -249,21 +249,6 @@ typedef enum {
typedef struct liThrottleState liThrottleState;
typedef struct liThrottlePool liThrottlePool;
/* value.h */
typedef struct liValue liValue;
typedef enum {
LI_VALUE_NONE,
LI_VALUE_BOOLEAN,
LI_VALUE_NUMBER,
LI_VALUE_STRING,
LI_VALUE_LIST,
LI_VALUE_HASH,
LI_VALUE_ACTION, /**< shouldn't be used for options, but may be needed for constructing actions */
LI_VALUE_CONDITION /**< shouldn't be used for options, but may be needed for constructing actions */
} liValueType;
/* virtualrequest.h */
typedef struct liConCallbacks liConCallbacks;

50
include/lighttpd/value.h

@ -1,10 +1,31 @@
#ifndef _LIGHTTPD_VALUE_H_
#define _LIGHTTPD_VALUE_H_
#ifndef _LIGHTTPD_BASE_H_
#error Please include <lighttpd/base.h> instead of this file
#if !(defined _LIGHTTPD_BASE_H_ || defined _LIGHTTPD_ANGEL_BASE_H_)
# ifdef _LIGHTTPD_COMMON_VALUE_C_
# include <lighttpd/settings.h>
# else
# error Please include <lighttpd/base.h> or <lighttpd/angel_base.h> instead of this file
# endif
#endif
/* common code for values in angel and worker; struct liValue must always be of same size! */
typedef struct liValue liValue;
typedef enum
{ LI_VALUE_NONE
, LI_VALUE_BOOLEAN
, LI_VALUE_NUMBER
, LI_VALUE_STRING
, LI_VALUE_LIST
, LI_VALUE_HASH
#ifdef _LIGHTTPD_BASE_H_
, LI_VALUE_ACTION /**< shouldn't be used for options, but may be needed for constructing actions */
, LI_VALUE_CONDITION /**< shouldn't be used for options, but may be needed for constructing actions */
#endif
} liValueType;
struct liValue {
liValueType type;
union {
@ -12,16 +33,16 @@ struct liValue {
gint64 number;
GString *string;
/* array of (liValue*) */
GArray *list;
GPtrArray *list;
/* hash GString => value */
GHashTable *hash;
struct {
liServer *srv; /* needed for destruction */
liAction *action;
struct liServer *srv; /* needed for destruction */
struct liAction *action;
} val_action;
struct {
liServer *srv; /* needed for destruction */
liCondition *cond;
struct liServer *srv; /* needed for destruction */
struct liCondition *cond;
} val_cond;
} data;
};
@ -32,8 +53,10 @@ LI_API liValue* li_value_new_number(gint64 val);
LI_API liValue* li_value_new_string(GString *val);
LI_API liValue* li_value_new_list(void);
LI_API liValue* li_value_new_hash(void);
#ifdef _LIGHTTPD_BASE_H_
LI_API liValue* li_value_new_action(liServer *srv, liAction *a);
LI_API liValue* li_value_new_condition(liServer *srv, liCondition *c);
#endif
LI_API GHashTable *li_value_new_hashtable(void); /* returns a GString -> liValue table with free funcs */
LI_API void li_value_list_append(liValue *list, liValue *item); /* list MUST be of type LIST */
@ -42,27 +65,34 @@ LI_API void li_value_list_append(liValue *list, liValue *item); /* list MUST be
LI_API void li_value_wrap_in_list(liValue *val);
LI_API liValue* li_value_copy(liValue* val);
LI_API liValue* li_common_value_copy_(liValue* val); /* internal function */
LI_API void li_value_clear(liValue *val); /* frees content, sets value to LI_VALUE_NONE */
LI_API void li_common_value_clear_(liValue *val); /* internal function */
LI_API void li_value_free(liValue* val);
LI_API void li_value_move(liValue *dest, liValue *src);
LI_API const char* li_valuetype_string(liValueType type);
LI_API const char* li_common_valuetype_string_(liValueType type); /* internal function */
INLINE const char* li_value_type_string(liValue *val);
LI_API GString *li_value_to_string(liValue *val);
LI_API GString *li_common_value_to_string_(liValue *val); /* internal function */
LI_API void li_value_list_free(GArray *vallist);
LI_API void li_value_list_free(GPtrArray *vallist);
/* extracts the pointer of a; set val->type to none (so a free on the value doesn't free the previous content)
* returns NULL (and doesn't modify val->type) if the type doesn't match
* there is no need to extract scalar values - just copy them
*/
LI_API gpointer li_value_extract_ptr(liValue *val);
LI_API gpointer li_common_value_extract_ptr_(liValue *val); /* internal function */
LI_API GString* li_value_extract_string(liValue *val);
LI_API GArray* li_value_extract_list(liValue *val);
LI_API GPtrArray* li_value_extract_list(liValue *val);
LI_API GHashTable* li_value_extract_hash(liValue *val);
#ifdef _LIGHTTPD_BASE_H_
LI_API liAction* li_value_extract_action(liValue *val);
LI_API liCondition* li_value_extract_condition(liValue *val);
#endif
/* move the value content to a new value, set the old type to none */
LI_API liValue* li_value_extract(liValue *val);
@ -121,7 +151,7 @@ INLINE guint li_value_list_len(liValue *val) {
INLINE liValue* li_value_list_at(liValue* val, guint ndx) {
if (NULL == val || LI_VALUE_LIST != val->type || ndx >= val->data.list->len) return NULL;
return g_array_index(val->data.list, liValue*, ndx);
return g_ptr_array_index(val->data.list, ndx);
}
INLINE liValueType li_value_list_type_at(liValue *val, guint ndx) {

1
src/CMakeLists.txt

@ -197,6 +197,7 @@ SET(COMMON_SRC
sys_socket.c
tasklet.c
utils.c
value.c
waitqueue.c
)

14
src/angel/angel_config_parser.rl

@ -210,18 +210,6 @@ static gchar *format_char(pcontext *ctx, gchar c) {
ctx->curvalue = li_value_new_number(ctx->number);
}
action value_range {
liValueRange vr = { ctx->number2, ctx->number };
ctx->curvalue = li_value_new_range(vr);
if (ctx->number2 > ctx->number) {
GString *tmp = li_value_to_string(ctx->curvalue);
UPDATE_COLUMN();
PARSE_ERROR_FMT("range broken: %s (from > to)", tmp->str);
g_string_free(tmp, TRUE);
ctx->cs = angel_config_parser_error; fbreak;
}
}
action value_string {
ctx->curvalue = li_value_new_string(ctx->token);
ctx->token = g_string_sized_new(0);
@ -347,7 +335,7 @@ static gchar *format_char(pcontext *ctx, gchar c) {
number = (('-'@{ctx->negate = TRUE;})? (digit digit**) $number_digit) >{ ctx->number = 0; ctx->negate = FALSE; };
value_bool = ('true'i | 'enabled'i) %value_true | ('false'i | 'disabled'i) %value_false;
value_number = number noise** ('-'@{ ctx->number2 = ctx->number; } (noise*) $err(error_expected_number) number %value_range | '' %value_number);
value_number = number %value_number;
value_string = string @value_string;
value_list = '(' @value_list_start;
value_hash = '[' @value_hash_start;

2
src/angel/angel_plugin.c

@ -250,7 +250,7 @@ void li_plugins_handle_item(liServer *srv, GString *itemname, liValue *hash) {
if (pi->type != LI_VALUE_NONE && optlist[i] && optlist[i]->type != pi->type) {
/* TODO: convert from string if possible */
ERROR(srv, "Invalid value type of option '%s' in item '%s', got '%s' but expected '%s'",
pi->name, itemname->str, li_value_type_string(optlist[i]->type), li_value_type_string(pi->type));
pi->name, itemname->str, li_value_type_string(optlist[i]), li_valuetype_string(pi->type));
valid = FALSE;
}
}

207
src/angel/angel_value.c

@ -1,210 +1,21 @@
#include <lighttpd/angel_base.h>
liValue* li_value_new_none(void) {
liValue *v = g_slice_new0(liValue);
v->type = LI_VALUE_NONE;
return v;
}
liValue* li_value_new_bool(gboolean val) {
liValue *v = g_slice_new0(liValue);
v->data.boolean = val;
v->type = LI_VALUE_BOOLEAN;
return v;
}
liValue* li_value_new_number(gint64 val) {
liValue *v = g_slice_new0(liValue);
v->data.number = val;
v->type = LI_VALUE_NUMBER;
return v;
}
liValue* li_value_new_string(GString *val) {
liValue *v = g_slice_new0(liValue);
v->data.string = val;
v->type = LI_VALUE_STRING;
return v;
}
liValue* li_value_new_range(liValueRange val) {
liValue *v = g_slice_new0(liValue);
v->data.range = val;
v->type = LI_VALUE_RANGE;
return v;
}
liValue* li_value_new_list(void) {
liValue *v = g_slice_new0(liValue);
v->data.list = g_ptr_array_new();
v->type = LI_VALUE_LIST;
return v;
}
static void _value_hash_free_key(gpointer data) {
g_string_free((GString*) data, TRUE);
}
static void _value_hash_free_value(gpointer data) {
li_value_free((liValue*) data);
}
liValue* li_value_new_hash(void) {
liValue *v = g_slice_new0(liValue);
v->data.hash = g_hash_table_new_full(
(GHashFunc) g_string_hash, (GEqualFunc) g_string_equal,
_value_hash_free_key, _value_hash_free_value);
v->type = LI_VALUE_HASH;
return v;
}
liValue* li_value_copy(liValue* val) {
liValue *n;
switch (val->type) {
case LI_VALUE_NONE: n = li_value_new_bool(FALSE); n->type = LI_VALUE_NONE; return n; /* hack */
case LI_VALUE_BOOLEAN: return li_value_new_bool(val->data.boolean);
case LI_VALUE_NUMBER: return li_value_new_number(val->data.number);
case LI_VALUE_STRING: return li_value_new_string(g_string_new_len(GSTR_LEN(val->data.string)));
case LI_VALUE_RANGE: return li_value_new_range(val->data.range);
/* list: we have to copy every value in the list! */
case LI_VALUE_LIST:
n = li_value_new_list();
g_ptr_array_set_size(n->data.list, val->data.list->len);
for (guint i = 0; i < val->data.list->len; i++) {
g_ptr_array_index(n->data.list, i) = li_value_copy(g_ptr_array_index(val->data.list, i));
}
return n;
/* hash: iterate over hashtable, clone each value */
case LI_VALUE_HASH:
n = li_value_new_hash();
{
GHashTableIter iter;
gpointer k, v;
g_hash_table_iter_init(&iter, val->data.hash);
while (g_hash_table_iter_next(&iter, &k, &v))
g_hash_table_insert(n->data.hash, g_string_new_len(GSTR_LEN((GString*)k)), li_value_copy((liValue*)v));
}
return n;
}
return NULL;
return li_common_value_copy_(val);
}
static void li_value_list_free(GPtrArray *vallist) {
if (!vallist) return;
for (gsize i = 0; i < vallist->len; i++) {
li_value_free(g_ptr_array_index(vallist, i));
}
g_ptr_array_free(vallist, TRUE);
void li_value_clear(liValue *val) {
li_common_value_clear_(val);
}
void li_value_free(liValue* val) {
if (!val) return;
switch (val->type) {
case LI_VALUE_NONE:
case LI_VALUE_BOOLEAN:
case LI_VALUE_NUMBER:
/* Nothing to free */
break;
case LI_VALUE_STRING:
g_string_free(val->data.string, TRUE);
break;
case LI_VALUE_RANGE:
break;
case LI_VALUE_LIST:
li_value_list_free(val->data.list);
break;
case LI_VALUE_HASH:
g_hash_table_destroy(val->data.hash);
break;
}
val->type = LI_VALUE_NONE;
g_slice_free(liValue, val);
}
const char* li_value_type_string(liValueType type) {
switch(type) {
case LI_VALUE_NONE:
return "none";
case LI_VALUE_BOOLEAN:
return "boolean";
case LI_VALUE_NUMBER:
return "number";
case LI_VALUE_STRING:
return "string";
case LI_VALUE_RANGE:
return "range";
case LI_VALUE_LIST:
return "list";
case LI_VALUE_HASH:
return "hash";
}
return "<unknown>";
const char* li_valuetype_string(liValueType type) {
return li_common_valuetype_string_(type);
}
GString *li_value_to_string(liValue *val) {
GString *str = NULL;
switch (val->type) {
case LI_VALUE_NONE:
return NULL;
case LI_VALUE_BOOLEAN:
str = g_string_new(val->data.boolean ? "true" : "false");
break;
case LI_VALUE_NUMBER:
str = g_string_sized_new(0);
g_string_printf(str, "%" G_GINT64_FORMAT, val->data.number);
break;
case LI_VALUE_STRING:
str = g_string_new_len(CONST_STR_LEN("\""));
g_string_append_len(str, GSTR_LEN(val->data.string));
g_string_append_c(str, '"');
break;
case LI_VALUE_RANGE:
str = g_string_sized_new(0);
g_string_printf(str, "%" G_GINT64_FORMAT "-%" G_GINT64_FORMAT, val->data.range.from, val->data.range.to);
break;
case LI_VALUE_LIST:
str = g_string_new_len(CONST_STR_LEN("("));
if (val->data.list->len) {
GString *tmp = li_value_to_string(g_ptr_array_index(val->data.list, 0));
g_string_append(str, tmp->str);
g_string_free(tmp, TRUE);
for (guint i = 1; i < val->data.list->len; i++) {
tmp = li_value_to_string(g_ptr_array_index(val->data.list, i));
g_string_append_len(str, CONST_STR_LEN(", "));
g_string_append(str, tmp->str);
g_string_free(tmp, TRUE);
}
}
g_string_append_c(str, ')');
break;
case LI_VALUE_HASH:
{
GHashTableIter iter;
gpointer k, v;
GString *tmp;
guint i = 0;
str = g_string_new_len(CONST_STR_LEN("["));
g_hash_table_iter_init(&iter, val->data.hash);
while (g_hash_table_iter_next(&iter, &k, &v)) {
if (i)
g_string_append_len(str, CONST_STR_LEN(", "));
tmp = li_value_to_string((liValue*)v);
g_string_append_len(str, GSTR_LEN((GString*)k));
g_string_append_len(str, CONST_STR_LEN(": "));
g_string_append_len(str, GSTR_LEN(tmp));
g_string_free(tmp, TRUE);
i++;
}
g_string_append_c(str, ']');
break;
}
}
return li_common_value_to_string_(val);
}
return str;
gpointer li_value_extract_ptr(liValue *val) {
return li_common_value_extract_ptr_(val);
}

1
src/common/Makefile.am

@ -19,6 +19,7 @@ common_src= \
sys_socket.c \
tasklet.c \
utils.c \
value.c \
waitqueue.c
parsers=ip_parsers.c

342
src/common/value.c

@ -0,0 +1,342 @@
#define _LIGHTTPD_COMMON_VALUE_C_
#include <lighttpd/value.h>
liValue* li_value_new_none(void) {
liValue *v = g_slice_new0(liValue);
v->type = LI_VALUE_NONE;
return v;
}
liValue* li_value_new_bool(gboolean val) {
liValue *v = g_slice_new0(liValue);
v->data.boolean = val;
v->type = LI_VALUE_BOOLEAN;
return v;
}
liValue* li_value_new_number(gint64 val) {
liValue *v = g_slice_new0(liValue);
v->data.number = val;
v->type = LI_VALUE_NUMBER;
return v;
}
liValue* li_value_new_string(GString *val) {
liValue *v = g_slice_new0(liValue);
v->data.string = val;
v->type = LI_VALUE_STRING;
return v;
}
liValue* li_value_new_list(void) {
liValue *v = g_slice_new0(liValue);
v->data.list = g_ptr_array_new();
v->type = LI_VALUE_LIST;
return v;
}
static void _value_hash_free_key(gpointer data) {
g_string_free((GString*) data, TRUE);
}
static void _value_hash_free_value(gpointer data) {
li_value_free((liValue*) data);
}
liValue* li_value_new_hash(void) {
liValue *v = g_slice_new0(liValue);
v->data.hash = li_value_new_hashtable();
v->type = LI_VALUE_HASH;
return v;
}
GHashTable *li_value_new_hashtable(void) {
return g_hash_table_new_full(
(GHashFunc) g_string_hash, (GEqualFunc) g_string_equal,
_value_hash_free_key, _value_hash_free_value);
}
void li_value_list_append(liValue *list, liValue *item) {
assert(LI_VALUE_LIST == list->type);
g_ptr_array_add(list->data.list, item);
}
void li_value_wrap_in_list(liValue *val) {
liValue *item;
assert(NULL != val);
item = li_value_extract(val);
val->type = LI_VALUE_LIST;
val->data.list = g_ptr_array_new();
g_ptr_array_add(val->data.list, item);
}
liValue* li_common_value_copy_(liValue* val) {
liValue *n;
if (NULL == val) return NULL;
switch (val->type) {
case LI_VALUE_NONE: return li_value_new_none();
case LI_VALUE_BOOLEAN: return li_value_new_bool(val->data.boolean);
case LI_VALUE_NUMBER: return li_value_new_number(val->data.number);
case LI_VALUE_STRING: return li_value_new_string(g_string_new_len(GSTR_LEN(val->data.string)));
/* list: we have to copy every value in the list! */
case LI_VALUE_LIST:
n = li_value_new_list();
g_ptr_array_set_size(n->data.list, val->data.list->len);
for (guint i = 0; i < val->data.list->len; i++) {
g_ptr_array_index(n->data.list, i) = li_value_copy(g_ptr_array_index(val->data.list, i));
}
return n;
/* hash: iterate over hashtable, clone each value */
case LI_VALUE_HASH:
n = li_value_new_hash();
{
GHashTableIter iter;
gpointer k, v;
g_hash_table_iter_init(&iter, val->data.hash);
while (g_hash_table_iter_next(&iter, &k, &v))
g_hash_table_insert(n->data.hash, g_string_new_len(GSTR_LEN((GString*)k)), li_value_copy((liValue*)v));
}
return n;
}
return NULL;
}
static void _li_value_clear(liValue *val) {
memset(val, 0, sizeof(*val));
val->type = LI_VALUE_NONE;
}
void li_common_value_clear_(liValue *val) {
if (NULL == val) return;
switch (val->type) {
case LI_VALUE_NONE:
case LI_VALUE_BOOLEAN:
case LI_VALUE_NUMBER:
/* Nothing to free */
break;
case LI_VALUE_STRING:
g_string_free(val->data.string, TRUE);
break;
case LI_VALUE_LIST:
li_value_list_free(val->data.list);
break;
case LI_VALUE_HASH:
g_hash_table_destroy(val->data.hash);
break;
}
_li_value_clear(val);
}
void li_value_free(liValue* val) {
if (NULL == val) return;
li_value_clear(val);
g_slice_free(liValue, val);
}
void li_value_move(liValue *dest, liValue *src) {
assert(NULL != dest && NULL != src && dest != src);
li_value_clear(dest);
*dest = *src;
_li_value_clear(src);
}
const char* li_common_valuetype_string_(liValueType type) {
switch(type) {
case LI_VALUE_NONE:
return "none";
case LI_VALUE_BOOLEAN:
return "boolean";
case LI_VALUE_NUMBER:
return "number";
case LI_VALUE_STRING:
return "string";
case LI_VALUE_LIST:
return "list";
case LI_VALUE_HASH:
return "hash";
}
return "<unknown>";
}
void li_value_list_free(GPtrArray *vallist) {
if (NULL == vallist) return;
for (gsize i = 0; i < vallist->len; i++) {
li_value_free(g_ptr_array_index(vallist, i));
}
g_ptr_array_free(vallist, TRUE);
}
GString *li_common_value_to_string_(liValue *val) {
GString *str = NULL;
switch (val->type) {
case LI_VALUE_NONE:
str = g_string_new("null");
case LI_VALUE_BOOLEAN:
str = g_string_new(val->data.boolean ? "true" : "false");
break;
case LI_VALUE_NUMBER:
str = g_string_sized_new(0);
g_string_printf(str, "%" G_GINT64_FORMAT, val->data.number);
break;
case LI_VALUE_STRING:
str = g_string_new_len(CONST_STR_LEN("\""));
g_string_append_len(str, GSTR_LEN(val->data.string));
g_string_append_c(str, '"');
break;
case LI_VALUE_LIST:
str = g_string_new_len(CONST_STR_LEN("("));
if (val->data.list->len) {
GString *tmp = li_value_to_string(g_ptr_array_index(val->data.list, 0));
g_string_append(str, tmp->str);
g_string_free(tmp, TRUE);
for (guint i = 1; i < val->data.list->len; i++) {
tmp = li_value_to_string(g_ptr_array_index(val->data.list, i));
g_string_append_len(str, CONST_STR_LEN(", "));
g_string_append(str, tmp->str);
g_string_free(tmp, TRUE);
}
}
g_string_append_c(str, ')');
break;
case LI_VALUE_HASH:
{
GHashTableIter iter;
gpointer k, v;
GString *tmp;
guint i = 0;
str = g_string_new_len(CONST_STR_LEN("["));
g_hash_table_iter_init(&iter, val->data.hash);
while (g_hash_table_iter_next(&iter, &k, &v)) {
if (i)
g_string_append_len(str, CONST_STR_LEN(", "));
tmp = li_value_to_string((liValue*)v);
g_string_append_len(str, GSTR_LEN((GString*)k));
g_string_append_len(str, CONST_STR_LEN(" => "));
g_string_append_len(str, GSTR_LEN(tmp));
g_string_free(tmp, TRUE);
i++;
}
g_string_append_c(str, ']');
}
break;
}
return str;
}
gpointer li_common_value_extract_ptr_(liValue *val) {
gpointer ptr = NULL;
if (NULL == val) return NULL;
switch (val->type) {
case LI_VALUE_NONE:
break;
case LI_VALUE_BOOLEAN:
break;
case LI_VALUE_NUMBER:
break;
case LI_VALUE_STRING:
ptr = val->data.string;
break;
case LI_VALUE_LIST:
ptr = val->data.list;
break;
case LI_VALUE_HASH:
ptr = val->data.hash;
break;
}
_li_value_clear(val);
return ptr;
}
GString* li_value_extract_string(liValue *val) {
GString* result;
if (NULL == val || val->type != LI_VALUE_STRING) return NULL;
result = val->data.string;
_li_value_clear(val);
return result;
}
GPtrArray* li_value_extract_list(liValue *val) {
GPtrArray* result;
if (NULL == val || val->type != LI_VALUE_LIST) return NULL;
result = val->data.list;
_li_value_clear(val);
return result;
}
GHashTable* li_value_extract_hash(liValue *val) {
GHashTable* result;
if (NULL == val || val->type != LI_VALUE_HASH) return NULL;
result = val->data.hash;
_li_value_clear(val);
return result;
}
liValue* li_value_extract(liValue *val) {
liValue *v;
if (NULL == val) return NULL;
v = li_value_new_none();
*v = *val;
_li_value_clear(val);
return v;
}
liValue* li_value_to_key_value_list(liValue *val) {
if (NULL == val) return NULL;
if (LI_VALUE_HASH == val->type) {
GHashTable *table = li_value_extract_hash(val);
GPtrArray *list;
GHashTableIter hti;
gpointer hkey, hvalue;
{
/* convert val to list */
liValue *vlist = li_value_new_list();
li_value_move(val, vlist);
li_value_free(vlist);
}
list = val->data.list;
g_hash_table_iter_init(&hti, table);
while (g_hash_table_iter_next(&hti, &hkey, &hvalue)) {
GString *htkey = hkey; liValue *htval = hvalue;
liValue *hkeyval = li_value_new_string(htkey);
liValue *pair = li_value_new_list();
g_ptr_array_add(pair->data.list, hkeyval);
g_ptr_array_add(pair->data.list, htval);
g_ptr_array_add(list, pair);
}
g_hash_table_steal_all(table); /* content was moved to list */
g_hash_table_destroy(table);
return val;
} else if (LI_VALUE_LIST == val->type) {
if (li_value_list_has_len(val, 2) &&
(LI_VALUE_STRING == li_value_list_type_at(val, 0) || LI_VALUE_NONE == li_value_list_type_at(val, 0))) {
/* single key-value pair */
li_value_wrap_in_list(val);
return val;
}
/* verify key-value list properties */
LI_VALUE_FOREACH(lentry, val)
if (!li_value_list_has_len(lentry, 2)) return NULL;
if (LI_VALUE_STRING != li_value_list_type_at(lentry, 0) && LI_VALUE_NONE != li_value_list_type_at(lentry, 0)) return NULL;
LI_VALUE_END_FOREACH()
return val;
}
return NULL;
}

4
src/main/config_lua.c

@ -19,10 +19,10 @@ static liValue* lua_params_to_value(liServer *srv, lua_State *L) {
return NULL;
default:
val = li_value_new_list();
g_array_set_size(val->data.list, lua_gettop(L) - 1);
g_ptr_array_set_size(val->data.list, lua_gettop(L) - 1);
while (lua_gettop(L) > 1) {
subval = li_value_from_lua(srv, L);
g_array_index(val->data.list, liValue*, lua_gettop(L) - 1) = subval;
g_ptr_array_index(val->data.list, lua_gettop(L) - 1) = subval;
}
return val;
}

5
src/main/config_parser.rl

@ -810,10 +810,7 @@ static gboolean op_execute(liValue **vresult, liConfigToken op, liValue *v1, liV
case LI_VALUE_LIST:
switch (op) {
case TK_PLUS:
*vresult = li_value_new_list();
LI_VALUE_FOREACH(entry, v1)
li_value_list_append(*vresult, li_value_extract(entry));
LI_VALUE_END_FOREACH()
*vresult = li_value_extract(v1);
LI_VALUE_FOREACH(entry, v2)
li_value_list_append(*vresult, li_value_extract(entry));
LI_VALUE_END_FOREACH()

61
src/main/plugin_core.c

@ -393,7 +393,7 @@ static liHandlerResult core_handle_index(liVRequest *vr, gpointer param, gpointe
struct stat st;
gint err;
GString *file, *tmp_docroot, *tmp_path;
GArray *files = param;
GPtrArray *files = param;
gint contextNdx = GPOINTER_TO_INT(*context);
UNUSED(context);
@ -433,7 +433,7 @@ static liHandlerResult core_handle_index(liVRequest *vr, gpointer param, gpointe
/* loop through the list to find a possible index file */
for (i = contextNdx - 1; i < files->len; i++) {
file = g_array_index(files, liValue*, i)->data.string;
file = ((liValue*)g_ptr_array_index(files, i))->data.string;
if (file->str[0] == '/') {
/* entries beginning with a slash shall be looked up directly at the docroot */
@ -478,15 +478,8 @@ static liHandlerResult core_handle_index(liVRequest *vr, gpointer param, gpointe
}
static void core_index_free(liServer *srv, gpointer param) {
guint i;
GArray *files = param;
UNUSED(srv);
for (i = 0; i < files->len; i++)
li_value_free(g_array_index(files, liValue*, i));
g_array_free(files, TRUE);
li_value_list_free((GPtrArray*) param);
}
static liAction* core_index(liServer *srv, liWorker *wrk, liPlugin* p, liValue *val, gpointer userdata) {
@ -522,7 +515,7 @@ static liHandlerResult core_handle_static(liVRequest *vr, gpointer param, gpoint
struct stat st;
int err;
liHandlerResult res;
GArray *exclude_arr = CORE_OPTIONPTR(LI_CORE_OPTION_STATIC_FILE_EXCLUDE_EXTENSIONS).list;
GPtrArray *exclude_arr = CORE_OPTIONPTR(LI_CORE_OPTION_STATIC_FILE_EXCLUDE_EXTENSIONS).list;
static const gchar boundary[] = "fkj49sn38dcn3";
gboolean no_fail = GPOINTER_TO_INT(param);
@ -559,7 +552,7 @@ static liHandlerResult core_handle_static(liVRequest *vr, gpointer param, gpoint
g_free(basep);
for (i = 0; i < exclude_arr->len; i++) {
liValue *v = g_array_index(exclude_arr, liValue*, i);
liValue *v = g_ptr_array_index(exclude_arr, i);
if (li_string_suffix(tmp_str, GSTR_LEN(v->data.string))) {
if (no_fail) return LI_HANDLER_GO_ON;
@ -974,19 +967,23 @@ fail:
return NULL;
}
typedef struct {
GString *key;
liPattern *pattern;
} env_set_add_ctx;
static void core_env_set_free(liServer *srv, gpointer param) {
GArray *arr = param;
static void core_env_set_add_free(liServer *srv, gpointer param) {
env_set_add_ctx *ctx = param;
UNUSED(srv);
li_value_free(g_array_index(arr, liValue*, 0));
li_pattern_free(g_array_index(arr, liPattern*, 1));
g_array_free(arr, TRUE);
g_string_free(ctx->key, TRUE);
li_pattern_free(ctx->pattern);
g_slice_free(env_set_add_ctx, ctx);
}
static liHandlerResult core_handle_env_set(liVRequest *vr, gpointer param, gpointer *context) {
GArray *arr = param;
env_set_add_ctx *ctx = param;
GMatchInfo *match_info = NULL;
UNUSED(context);
@ -997,14 +994,15 @@ static liHandlerResult core_handle_env_set(liVRequest *vr, gpointer param, gpoin
}
g_string_truncate(vr->wrk->tmp_str, 0);
li_pattern_eval(vr, vr->wrk->tmp_str, g_array_index(arr, liPattern*, 1), NULL, NULL, li_pattern_regex_cb, match_info);
li_environment_set(&vr->env, GSTR_LEN(g_array_index(arr, liValue*, 0)->data.string), GSTR_LEN(vr->wrk->tmp_str));
li_pattern_eval(vr, vr->wrk->tmp_str, ctx->pattern, NULL, NULL, li_pattern_regex_cb, match_info);
li_environment_set(&vr->env, GSTR_LEN(ctx->key), GSTR_LEN(vr->wrk->tmp_str));
return LI_HANDLER_GO_ON;
}
static liAction* core_env_set(liServer *srv, liWorker *wrk, liPlugin* p, liValue *val, gpointer userdata) {
liPattern *pattern;
env_set_add_ctx *ctx;
UNUSED(wrk); UNUSED(p); UNUSED(userdata);
/* first argument is a key value list - list of list of list of strings */
@ -1021,16 +1019,16 @@ static liAction* core_env_set(liServer *srv, liWorker *wrk, liPlugin* p, liValue
if (NULL == (pattern = li_pattern_new(srv, li_value_list_at(val, 1)->data.string->str)))
return NULL;
/* exchange second parameter (string) with the new pattern */
li_value_free(li_value_list_at(val, 1));
g_array_index(val->data.list, liPattern*, 1) = pattern;
ctx = g_slice_new0(env_set_add_ctx);
ctx->key = li_value_extract_string(li_value_list_at(val, 0));
ctx->pattern = pattern;
return li_action_new_function(core_handle_env_set, NULL, core_env_set_free, li_value_extract_list(val));
return li_action_new_function(core_handle_env_set, NULL, core_env_set_add_free, ctx);
}
static liHandlerResult core_handle_env_add(liVRequest *vr, gpointer param, gpointer *context) {
GArray *arr = param;
env_set_add_ctx *ctx = param;
GMatchInfo *match_info = NULL;
UNUSED(context);
@ -1041,14 +1039,15 @@ static liHandlerResult core_handle_env_add(liVRequest *vr, gpointer param, gpoin
}
g_string_truncate(vr->wrk->tmp_str, 0);
li_pattern_eval(vr, vr->wrk->tmp_str, g_array_index(arr, liPattern*, 1), NULL, NULL, li_pattern_regex_cb, match_info);
li_environment_insert(&vr->env, GSTR_LEN(g_array_index(arr, liValue*, 0)->data.string), GSTR_LEN(vr->wrk->tmp_str));
li_pattern_eval(vr, vr->wrk->tmp_str, ctx->pattern, NULL, NULL, li_pattern_regex_cb, match_info);
li_environment_insert(&vr->env, GSTR_LEN(ctx->key), GSTR_LEN(vr->wrk->tmp_str));
return LI_HANDLER_GO_ON;
}
static liAction* core_env_add(liServer *srv, liWorker *wrk, liPlugin* p, liValue *val, gpointer userdata) {
liPattern *pattern;
env_set_add_ctx *ctx;
UNUSED(wrk); UNUSED(p); UNUSED(userdata);
/* first argument is a key value list - list of list of list of strings */
@ -1065,11 +1064,11 @@ static liAction* core_env_add(liServer *srv, liWorker *wrk, liPlugin* p, liValue
if (NULL == (pattern = li_pattern_new(srv, li_value_list_at(val, 1)->data.string->str)))
return NULL;
/* exchange second parameter (string) with the new pattern */
li_value_free(li_value_list_at(val, 1));
g_array_index(val->data.list, liPattern*, 1) = pattern;
ctx = g_slice_new0(env_set_add_ctx);
ctx->key = li_value_extract_string(li_value_list_at(val, 0));
ctx->pattern = pattern;
return li_action_new_function(core_handle_env_add, NULL, core_env_set_free, li_value_extract_list(val));
return li_action_new_function(core_handle_env_add, NULL, core_env_set_add_free, ctx);
}

325
src/main/value.c

@ -1,54 +1,5 @@
#include <lighttpd/base.h>
liValue* li_value_new_none(void) {
liValue *v = g_slice_new0(liValue);
v->type = LI_VALUE_NONE;
return v;
}
liValue* li_value_new_bool(gboolean val) {
liValue *v = g_slice_new0(liValue);
v->data.boolean = val;
v->type = LI_VALUE_BOOLEAN;
return v;
}
liValue* li_value_new_number(gint64 val) {
liValue *v = g_slice_new0(liValue);
v->data.number = val;
v->type = LI_VALUE_NUMBER;
return v;
}
liValue* li_value_new_string(GString *val) {
liValue *v = g_slice_new0(liValue);
v->data.string = val;
v->type = LI_VALUE_STRING;
return v;
}
liValue* li_value_new_list(void) {
liValue *v = g_slice_new0(liValue);
v->data.list = g_array_new(FALSE, TRUE, sizeof(liValue*));
v->type = LI_VALUE_LIST;
return v;
}
static void _value_hash_free_key(gpointer data) {
g_string_free((GString*) data, TRUE);
}
static void _value_hash_free_value(gpointer data) {
li_value_free((liValue*) data);
}
liValue* li_value_new_hash(void) {
liValue *v = g_slice_new0(liValue);
v->data.hash = li_value_new_hashtable();
v->type = LI_VALUE_HASH;
return v;
}
liValue* li_value_new_action(liServer *srv, liAction *a) {
liValue *v = g_slice_new0(liValue);
v->data.val_action.srv = srv;
@ -65,55 +16,11 @@ liValue* li_value_new_condition(liServer *srv, liCondition *c) {
return v;
}
GHashTable *li_value_new_hashtable(void) {
return g_hash_table_new_full(
(GHashFunc) g_string_hash, (GEqualFunc) g_string_equal,
_value_hash_free_key, _value_hash_free_value);
}
void li_value_list_append(liValue *list, liValue *item) {
assert(LI_VALUE_LIST == list->type);
g_array_append_val(list->data.list, item);
}
void li_value_wrap_in_list(liValue *val) {
liValue *item;
assert(NULL != val);
item = li_value_extract(val);
val->type = LI_VALUE_LIST;
val->data.list = g_array_new(FALSE, TRUE, sizeof(liValue*));
g_array_append_val(val->data.list, item);
}
liValue* li_value_copy(liValue* val) {
liValue *n;
if (NULL == val) return NULL;
switch (val->type) {
case LI_VALUE_NONE: return li_value_new_none();
case LI_VALUE_BOOLEAN: return li_value_new_bool(val->data.boolean);
case LI_VALUE_NUMBER: return li_value_new_number(val->data.number);
case LI_VALUE_STRING: return li_value_new_string(g_string_new_len(GSTR_LEN(val->data.string)));
/* list: we have to copy every value in the list! */
case LI_VALUE_LIST:
n = li_value_new_list();
g_array_set_size(n->data.list, val->data.list->len);
for (guint i = 0; i < val->data.list->len; i++) {
g_array_index(n->data.list, liValue*, i) = li_value_copy(g_array_index(val->data.list, liValue*, i));
}
return n;
/* hash: iterate over hashtable, clone each value */
case LI_VALUE_HASH:
n = li_value_new_hash();
{
GHashTableIter iter;
gpointer k, v;
g_hash_table_iter_init(&iter, val->data.hash);
while (g_hash_table_iter_next(&iter, &k, &v))
g_hash_table_insert(n->data.hash, g_string_new_len(GSTR_LEN((GString*)k)), li_value_copy((liValue*)v));
}
return n;
case LI_VALUE_ACTION:
li_action_acquire(val->data.val_action.action);
n = li_value_new_action(val->data.val_action.srv, val->data.val_action.action);
@ -122,6 +29,8 @@ liValue* li_value_copy(liValue* val) {
li_condition_acquire(val->data.val_cond.cond);
n = li_value_new_condition(val->data.val_cond.srv, val->data.val_cond.cond);
return n;
default:
return li_common_value_copy_(val);
}
return NULL;
}
@ -135,198 +44,58 @@ void li_value_clear(liValue *val) {
if (NULL == val) return;
switch (val->type) {
case LI_VALUE_NONE:
case LI_VALUE_BOOLEAN:
case LI_VALUE_NUMBER:
/* Nothing to free */
break;
case LI_VALUE_STRING:
g_string_free(val->data.string, TRUE);
break;
case LI_VALUE_LIST:
li_value_list_free(val->data.list);
break;
case LI_VALUE_HASH:
g_hash_table_destroy(val->data.hash);
break;
case LI_VALUE_ACTION:
li_action_release(val->data.val_action.srv, val->data.val_action.action);
_li_value_clear(val);
break;
case LI_VALUE_CONDITION:
li_condition_release(val->data.val_cond.srv, val->data.val_cond.cond);
_li_value_clear(val);
break;
default:
li_common_value_clear_(val);
}
_li_value_clear(val);
}
void li_value_free(liValue* val) {
if (NULL == val) return;
li_value_clear(val);
g_slice_free(liValue, val);
}
void li_value_move(liValue *dest, liValue *src) {
assert(NULL != dest && NULL != src && dest != src);
li_value_clear(dest);
*dest = *src;
_li_value_clear(src);
}
const char* li_valuetype_string(liValueType type) {
switch(type) {
case LI_VALUE_NONE:
return "none";
case LI_VALUE_BOOLEAN:
return "boolean";
case LI_VALUE_NUMBER:
return "number";
case LI_VALUE_STRING:
return "string";
case LI_VALUE_LIST:
return "list";
case LI_VALUE_HASH:
return "hash";
case LI_VALUE_ACTION:
return "action";
case LI_VALUE_CONDITION:
return "condition";
default:
return li_common_valuetype_string_(type);
}
return "<unknown>";
}
void li_value_list_free(GArray *vallist) {
if (NULL == vallist) return;
for (gsize i = 0; i < vallist->len; i++) {
li_value_free(g_array_index(vallist, liValue*, i));
}
g_array_free(vallist, TRUE);
}
GString *li_value_to_string(liValue *val) {
GString *str;
switch (val->type) {
case LI_VALUE_NONE:
return NULL;
case LI_VALUE_BOOLEAN:
str = g_string_new(val->data.boolean ? "true" : "false");
break;
case LI_VALUE_NUMBER:
str = g_string_sized_new(0);
g_string_printf(str, "%" G_GINT64_FORMAT, val->data.number);
break;
case LI_VALUE_STRING:
str = g_string_new_len(CONST_STR_LEN("\""));
g_string_append_len(str, GSTR_LEN(val->data.string));
g_string_append_c(str, '"');
break;
case LI_VALUE_LIST:
str = g_string_new_len(CONST_STR_LEN("("));
if (val->data.list->len) {
GString *tmp = li_value_to_string(g_array_index(val->data.list, liValue*, 0));
g_string_append(str, tmp->str);
g_string_free(tmp, TRUE);
for (guint i = 1; i < val->data.list->len; i++) {
tmp = li_value_to_string(g_array_index(val->data.list, liValue*, i));
g_string_append_len(str, CONST_STR_LEN(", "));
g_string_append(str, tmp->str);
g_string_free(tmp, TRUE);
}
}
g_string_append_c(str, ')');
break;
case LI_VALUE_HASH:
{
GHashTableIter iter;
gpointer k, v;
GString *tmp;
guint i = 0;
str = g_string_new_len(CONST_STR_LEN("["));
g_hash_table_iter_init(&iter, val->data.hash);
while (g_hash_table_iter_next(&iter, &k, &v)) {
if (i)
g_string_append_len(str, CONST_STR_LEN(", "));
tmp = li_value_to_string((liValue*)v);
g_string_append_len(str, GSTR_LEN((GString*)k));
g_string_append_len(str, CONST_STR_LEN(" => "));
g_string_append_len(str, GSTR_LEN(tmp));
g_string_free(tmp, TRUE);
i++;
}
g_string_append_c(str, ']');
break;
}
case LI_VALUE_ACTION:
str = g_string_new_len(CONST_STR_LEN("<action>"));
break;
return g_string_new_len(CONST_STR_LEN("<action>"));
case LI_VALUE_CONDITION:
str = g_string_new_len(CONST_STR_LEN("<condition>"));
break;
return g_string_new_len(CONST_STR_LEN("<condition>"));
default:
return NULL;
return li_common_value_to_string_(val);
}
return str;
}
gpointer li_value_extract_ptr(liValue *val) {
gpointer ptr = NULL;
gpointer ptr;
if (NULL == val) return NULL;
switch (val->type) {
case LI_VALUE_NONE:
break;
case LI_VALUE_BOOLEAN:
break;
case LI_VALUE_NUMBER:
break;
case LI_VALUE_STRING:
ptr = val->data.string;
break;
case LI_VALUE_LIST:
ptr = val->data.list;
break;
case LI_VALUE_HASH:
ptr = val->data.hash;
break;
case LI_VALUE_ACTION:
ptr = val->data.val_action.action;
break;
_li_value_clear(val);
return ptr;
case LI_VALUE_CONDITION:
ptr = val->data.val_action.action;
break;
_li_value_clear(val);
return ptr;
default:
return li_common_value_extract_ptr_(val);
}
_li_value_clear(val);
return ptr;
}
GString* li_value_extract_string(liValue *val) {
GString* result;
if (NULL == val || val->type != LI_VALUE_STRING) return NULL;
result = val->data.string;
_li_value_clear(val);
return result;
}
GArray* li_value_extract_list(liValue *val) {
GArray* result;
if (NULL == val || val->type != LI_VALUE_LIST) return NULL;
result = val->data.list;
_li_value_clear(val);
return result;
}
GHashTable* li_value_extract_hash(liValue *val) {
GHashTable* result;
if (NULL == val || val->type != LI_VALUE_HASH) return NULL;
result = val->data.hash;
_li_value_clear(val);
return result;
}
liAction* li_value_extract_action(liValue *val) {
@ -344,61 +113,3 @@ liCondition* li_value_extract_condition(liValue *val) {
_li_value_clear(val);
return result;
}
liValue* li_value_extract(liValue *val) {
liValue *v;
if (NULL == val) return NULL;
v = li_value_new_none();
*v = *val;
_li_value_clear(val);
return v;
}
liValue* li_value_to_key_value_list(liValue *val) {
if (NULL == val) return NULL;
if (LI_VALUE_HASH == val->type) {
GHashTable *table = li_value_extract_hash(val);
GArray *list;
GHashTableIter hti;
gpointer hkey, hvalue;
{
/* convert val to list */
liValue *vlist = li_value_new_list();
li_value_move(val, vlist);
li_value_free(vlist);
}
list = val->data.list;
g_hash_table_iter_init(&hti, table);
while (g_hash_table_iter_next(&hti, &hkey, &hvalue)) {
GString *htkey = hkey; liValue *htval = hvalue;
liValue *hkeyval = li_value_new_string(htkey);
liValue *pair = li_value_new_list();
g_array_append_val(pair->data.list, hkeyval);
g_array_append_val(pair->data.list, htval);
g_array_append_val(list, pair);
}
g_hash_table_steal_all(table); /* content was moved to list */
g_hash_table_destroy(table);
return val;
} else if (LI_VALUE_LIST == val->type) {
if (li_value_list_has_len(val, 2) &&
(LI_VALUE_STRING == li_value_list_type_at(val, 0) || LI_VALUE_NONE == li_value_list_type_at(val, 0))) {
/* single key-value pair */
li_value_wrap_in_list(val);
return val;
}
/* verify key-value list properties */
LI_VALUE_FOREACH(lentry, val)
if (!li_value_list_has_len(lentry, 2)) return NULL;
if (LI_VALUE_STRING != li_value_list_type_at(lentry, 0) && LI_VALUE_NONE != li_value_list_type_at(lentry, 0)) return NULL;
LI_VALUE_END_FOREACH()
return val;
}
return NULL;
}

17
src/main/value_lua.c

@ -67,7 +67,7 @@ static void lua_push_kvlist_metatable(lua_State *L) {
static liValue* li_value_from_lua_table(liServer *srv, lua_State *L, int ndx) {
liValue *val = NULL, *sub_option;
GArray *list = NULL;
GPtrArray *list = NULL;
GHashTable *hash = NULL;
int ikey;
GString *skey;
@ -91,9 +91,9 @@ static liValue* li_value_from_lua_table(liServer *srv, lua_State *L, int ndx) {
sub_option = li_value_from_lua(srv, L);
if (!