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); return n; case LI_VALUE_CONDITION: 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; } return NULL; }
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; } return NULL; }
static liValue* li_value_from_lua_table(liServer *srv, lua_State *L, int ndx) { liValue *val = NULL, *sub_option; GPtrArray *list = NULL; GHashTable *hash = NULL; int ikey; GString *skey; ndx = li_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) { val = li_value_new_list(); list = val->data.list; } ikey = lua_tointeger(L, -2) - 1; if (ikey < 0) { ERROR(srv, "Invalid key < 0: %i - skipping entry", ikey + 1); lua_pop(L, 1); continue; } sub_option = li_value_from_lua(srv, L); if (!sub_option) continue; if ((size_t) ikey >= list->len) { g_ptr_array_set_size(list, ikey + 1); } g_ptr_array_index(list, ikey) = sub_option; break; case LUA_TSTRING: if (list) goto mixerror; if (!hash) { val = li_value_new_hash(); hash = val->data.hash; } skey = li_lua_togstring(L, -2); if (g_hash_table_lookup(hash, skey)) { ERROR(srv, "Key already exists in hash: '%s' - skipping entry", skey->str); lua_pop(L, 1); continue; } sub_option = li_value_from_lua(srv, L); if (!sub_option) { g_string_free(skey, TRUE); continue; } g_hash_table_insert(hash, skey, sub_option); break; default: ERROR(srv, "Unexpted key type in table: %s (%i) - skipping entry", lua_typename(L, lua_type(L, -1)), lua_type(L, -1)); lua_pop(L, 1); break; } } return val; mixerror: ERROR(srv, "%s", "Cannot mix list with hash; skipping remaining part of table"); lua_pop(L, 2); return val; }