Exemple #1
0
/*
 * Convert a value from the given index into the lua stack to an nvpair, adding
 * it to an nvlist with the given key.
 *
 * Values are converted as follows:
 *
 *   string -> string
 *   number -> int64
 *   boolean -> boolean
 *   nil -> boolean (no value)
 *
 * Lua tables are converted to nvlists and then inserted. The table's keys
 * are converted to strings then used as keys in the nvlist to store each table
 * element.  Keys are converted as follows:
 *
 *   string -> no change
 *   number -> "%lld"
 *   boolean -> "true" | "false"
 *   nil -> error
 *
 * In the case of a key collision, an error is thrown.
 *
 * If an error is encountered, a nonzero error code is returned, and an error
 * string will be pushed onto the Lua stack.
 */
static int
zcp_lua_to_nvlist_impl(lua_State *state, int index, nvlist_t *nvl,
    const char *key, int depth)
{
	/*
	 * Verify that we have enough remaining space in the lua stack to parse
	 * a key-value pair and push an error.
	 */
	if (!lua_checkstack(state, 3)) {
		(void) lua_pushstring(state, "Lua stack overflow");
		return (1);
	}

	index = lua_absindex(state, index);

	switch (lua_type(state, index)) {
	case LUA_TNIL:
		fnvlist_add_boolean(nvl, key);
		break;
	case LUA_TBOOLEAN:
		fnvlist_add_boolean_value(nvl, key,
		    lua_toboolean(state, index));
		break;
	case LUA_TNUMBER:
		fnvlist_add_int64(nvl, key, lua_tonumber(state, index));
		break;
	case LUA_TSTRING:
		fnvlist_add_string(nvl, key, lua_tostring(state, index));
		break;
	case LUA_TTABLE: {
		nvlist_t *value_nvl = zcp_table_to_nvlist(state, index, depth);
		if (value_nvl == NULL)
			return (EINVAL);

		fnvlist_add_nvlist(nvl, key, value_nvl);
		fnvlist_free(value_nvl);
		break;
	}
	default:
		(void) lua_pushfstring(state,
		    "Invalid value type '%s' for key '%s'",
		    lua_typename(state, lua_type(state, index)), key);
		return (EINVAL);
	}

	return (0);
}
Exemple #2
0
static void
run_tests(void)
{
	const char *key = "key";

	/* Note: maximum nvlist key length is 32KB */
	int len = 1024 * 31;
	char *bigstring = malloc(len);
	for (int i = 0; i < len; i++)
		bigstring[i] = 'a' + i % 26;
	bigstring[len - 1] = '\0';

	nvl = fnvlist_alloc();

	fnvlist_add_boolean(nvl, key);
	test("boolean", B_TRUE, B_FALSE);

	fnvlist_add_boolean_value(nvl, key, B_TRUE);
	test("boolean_value", B_FALSE, B_FALSE);

	fnvlist_add_byte(nvl, key, 1);
	test("byte", B_FALSE, B_FALSE);

	fnvlist_add_int8(nvl, key, 1);
	test("int8", B_FALSE, B_FALSE);

	fnvlist_add_uint8(nvl, key, 1);
	test("uint8", B_FALSE, B_FALSE);

	fnvlist_add_int16(nvl, key, 1);
	test("int16", B_FALSE, B_FALSE);

	fnvlist_add_uint16(nvl, key, 1);
	test("uint16", B_FALSE, B_FALSE);

	fnvlist_add_int32(nvl, key, 1);
	test("int32", B_FALSE, B_FALSE);

	fnvlist_add_uint32(nvl, key, 1);
	test("uint32", B_FALSE, B_FALSE);

	fnvlist_add_int64(nvl, key, 1);
	test("int64", B_TRUE, B_TRUE);

	fnvlist_add_uint64(nvl, key, 1);
	test("uint64", B_FALSE, B_FALSE);

	fnvlist_add_string(nvl, key, "1");
	test("string", B_TRUE, B_TRUE);


	{
		nvlist_t *val = fnvlist_alloc();
		fnvlist_add_string(val, "subkey", "subvalue");
		fnvlist_add_nvlist(nvl, key, val);
		fnvlist_free(val);
		test("nvlist", B_TRUE, B_TRUE);
	}
	{
		boolean_t val[2] = { B_FALSE, B_TRUE };
		fnvlist_add_boolean_array(nvl, key, val, 2);
		test("boolean_array", B_FALSE, B_FALSE);
	}
	{
		uchar_t val[2] = { 0, 1 };
		fnvlist_add_byte_array(nvl, key, val, 2);
		test("byte_array", B_FALSE, B_FALSE);
	}
	{
		int8_t val[2] = { 0, 1 };
		fnvlist_add_int8_array(nvl, key, val, 2);
		test("int8_array", B_FALSE, B_FALSE);
	}
	{
		uint8_t val[2] = { 0, 1 };
		fnvlist_add_uint8_array(nvl, key, val, 2);
		test("uint8_array", B_FALSE, B_FALSE);
	}
	{
		int16_t val[2] = { 0, 1 };
		fnvlist_add_int16_array(nvl, key, val, 2);
		test("int16_array", B_FALSE, B_FALSE);
	}
	{
		uint16_t val[2] = { 0, 1 };
		fnvlist_add_uint16_array(nvl, key, val, 2);
		test("uint16_array", B_FALSE, B_FALSE);
	}
	{
		int32_t val[2] = { 0, 1 };
		fnvlist_add_int32_array(nvl, key, val, 2);
		test("int32_array", B_FALSE, B_FALSE);
	}
	{
		uint32_t val[2] = { 0, 1 };
		fnvlist_add_uint32_array(nvl, key, val, 2);
		test("uint32_array", B_FALSE, B_FALSE);
	}
	{
		int64_t val[2] = { 0, 1 };
		fnvlist_add_int64_array(nvl, key, val, 2);
		test("int64_array", B_TRUE, B_FALSE);
	}
	{
		uint64_t val[2] = { 0, 1 };
		fnvlist_add_uint64_array(nvl, key, val, 2);
		test("uint64_array", B_FALSE, B_FALSE);
	}
	{
		char *const val[2] = { "0", "1" };
		fnvlist_add_string_array(nvl, key, val, 2);
		test("string_array", B_TRUE, B_FALSE);
	}
	{
		nvlist_t *val[2];
		val[0] = fnvlist_alloc();
		fnvlist_add_string(val[0], "subkey", "subvalue");
		val[1] = fnvlist_alloc();
		fnvlist_add_string(val[1], "subkey2", "subvalue2");
		fnvlist_add_nvlist_array(nvl, key, val, 2);
		fnvlist_free(val[0]);
		fnvlist_free(val[1]);
		test("nvlist_array", B_FALSE, B_FALSE);
	}
	{
		fnvlist_add_string(nvl, bigstring, "1");
		test("large_key", B_TRUE, B_TRUE);
	}
	{
		fnvlist_add_string(nvl, key, bigstring);
		test("large_value", B_TRUE, B_TRUE);
	}
	{
		for (int i = 0; i < 1024; i++) {
			char buf[32];
			(void) snprintf(buf, sizeof (buf), "key-%u", i);
			fnvlist_add_int64(nvl, buf, i);
		}
		test("many_keys", B_TRUE, B_TRUE);
	}
#ifndef __sparc__
	{
		for (int i = 0; i < 10; i++) {
			nvlist_t *newval = fnvlist_alloc();
			fnvlist_add_nvlist(newval, "key", nvl);
			fnvlist_free(nvl);
			nvl = newval;
		}
		test("deeply_nested_pos", B_TRUE, B_TRUE);
	}
	{
		for (int i = 0; i < 90; i++) {
			nvlist_t *newval = fnvlist_alloc();
			fnvlist_add_nvlist(newval, "key", nvl);
			fnvlist_free(nvl);
			nvl = newval;
		}
		test("deeply_nested_neg", B_FALSE, B_FALSE);
	}
#endif
	free(bigstring);
	fnvlist_free(nvl);
}