Example #1
0
/**
 * Populate key options from their msgpack-encoded representation
 * (msgpack map).
 */
int
opts_decode(void *opts, const struct opt_def *reg, const char **map,
	    uint32_t errcode, uint32_t field_no, struct region *region)
{
	assert(mp_typeof(**map) == MP_MAP);

	/*
	 * The implementation below has O(map_size * reg_size) complexity.
	 * DDL is not performance-critical, so this is not a problem.
	 */
	uint32_t map_size = mp_decode_map(map);
	for (uint32_t i = 0; i < map_size; i++) {
		if (mp_typeof(**map) != MP_STR) {
			diag_set(ClientError, errcode, field_no,
				 "key must be a string");
			return -1;
		}
		uint32_t key_len;
		const char *key = mp_decode_str(map, &key_len);
		if (opts_parse_key(opts, reg, key, key_len, map, errcode,
				   field_no, region, false) != 0)
			return -1;
	}
	return 0;
}
Example #2
0
/*
 * For each UINT key in arguments create or increment counter in
 * box.space.test space.
 */
int
multi_inc(box_function_ctx_t *ctx, const char *args, const char *args_end)
{
	static const char *SPACE_NAME = "test";
	static const char *INDEX_NAME = "primary";

	uint32_t space_id = box_space_id_by_name(SPACE_NAME, strlen(SPACE_NAME));
	uint32_t index_id = box_index_id_by_name(space_id, INDEX_NAME,
		strlen(INDEX_NAME));
	if (space_id == BOX_ID_NIL || index_id == BOX_ID_NIL) {
		return box_error_raise(ER_PROC_C,
			"Can't find index %s in space %s",
			INDEX_NAME, SPACE_NAME);
	}
	say_debug("space_id = %u, index_id = %u", space_id, index_id);

	uint32_t arg_count = mp_decode_array(&args);
	box_txn_begin();
	for (uint32_t i = 0; i < arg_count; i++) {
		/* Decode next argument */
		if (mp_typeof(*args) != MP_UINT)
			return box_error_raise(ER_PROC_C, "Expected uint keys");
		uint32_t key = mp_decode_uint(&args);
		(void) key;

		/* Prepare MsgPack key for search */
		char key_buf[16];
		char *key_end = key_buf;
		key_end = mp_encode_array(key_end, 1);
		key_end = mp_encode_uint(key_end, key);
		assert(key_end < key_buf + sizeof(key_buf));

		/* Get current value from space */
		uint64_t counter = 0;
		box_tuple_t *tuple;
		if (box_index_get(space_id, index_id, key_buf, key_end,
				  &tuple) != 0) {
			return -1; /* error */
		} else if (tuple != NULL) {
			const char *field = box_tuple_field(tuple, 1);
			if (field == NULL || mp_typeof(*field) != MP_UINT)
				return box_error_raise(ER_PROC_LUA, "Invalid tuple");
			counter = mp_decode_uint(&field) + 1;
		}

		/* Replace value */
		char tuple_buf[16];
		char *tuple_end = tuple_buf;
		tuple_end = mp_encode_array(tuple_end, 2);
		tuple_end = mp_encode_uint(tuple_end, key); /* key */
		tuple_end = mp_encode_uint(tuple_end, counter); /* counter */
		assert(tuple_end <= tuple_buf + sizeof(tuple_buf));

		if (box_replace(space_id, tuple_buf, tuple_end, NULL) != 0)
			return -1;
	}
	box_txn_commit();
	return 0;
}
Example #3
0
int
args(box_function_ctx_t *ctx, const char *args, const char *args_end)
{
	uint32_t arg_count = mp_decode_array(&args);
	if (arg_count < 1) {
		return box_error_set(__FILE__, __LINE__, ER_PROC_C, "%s",
			"invalid argument count");
	}

	if (mp_typeof(*args) != MP_UINT) {
		return box_error_set(__FILE__, __LINE__, ER_PROC_C, "%s",
			"first tuple field must be uint");
	}

	uint32_t num = mp_decode_uint(&args);

	char tuple_buf[512];
	char *d = tuple_buf;
	d = mp_encode_array(d, 2);
	d = mp_encode_uint(d, num);
	d = mp_encode_str(d, "hello", strlen("hello"));
	assert(d <= tuple_buf + sizeof(tuple_buf));

	box_tuple_format_t *fmt = box_tuple_format_default();
	box_tuple_t *tuple = box_tuple_new(fmt, tuple_buf, d);
	if (tuple == NULL)
		return -1;
	return box_return_tuple(ctx, tuple);
}
Example #4
0
int64_t php_tp_response(struct tnt_response *r, char *buf, size_t size)
{
	memset(r, 0, sizeof(*r));
	const char *p = buf;
	/* len */
	uint32_t len = size;
	/* header */
	if (mp_typeof(*p) != MP_MAP)
		return -1;
	uint32_t n = mp_decode_map(&p);
	while (n-- > 0) {
		if (mp_typeof(*p) != MP_UINT)
			return -1;
		uint32_t key = mp_decode_uint(&p);
		if (mp_typeof(*p) != MP_UINT)
			return -1;
		switch (key) {
		case TNT_SYNC:
			r->sync = mp_decode_uint(&p);
			break;
		case TNT_CODE:
			r->code = mp_decode_uint(&p);
			break;
		default:
			return -1;
		}
		r->bitmap |= (1ULL << key);
	}
	/* body */
	if (mp_typeof(*p) != MP_MAP)
		return -1;
	n = mp_decode_map(&p);
	while (n-- > 0) {
		uint32_t key = mp_decode_uint(&p);
		switch (key) {
		case TNT_ERROR:
			if (mp_typeof(*p) != MP_STR)
				return -1;
			uint32_t elen = 0;
			r->error = mp_decode_str(&p, &elen);
			r->error_len = elen;
			r->code &= ((1 << 15) - 1);
			break;
		case TNT_DATA:
			if (mp_typeof(*p) != MP_ARRAY)
				return -1;
			r->data = p;
			mp_next(&p);
			r->data_len = p - r->data;
			break;
		}
		r->bitmap |= (1ULL << key);
	}
	return p - buf;
}
Example #5
0
struct tnt_iter *
tnt_iter_array(struct tnt_iter *i, const char *data, size_t size)
{
	const char *tmp_data = data;
	if (mp_check(&tmp_data, data + size) != 0)
		return NULL;
	if (!data || !size || mp_typeof(*data) != MP_ARRAY)
		return NULL;
	i = tnt_iter_init(i);
	if (i == NULL)
		return NULL;
	i->type = TNT_ITER_ARRAY;
	i->next = tnt_iter_array_next;
	i->rewind = tnt_iter_array_rewind;
	i->free = NULL;
	struct tnt_iter_array *itr = TNT_IARRAY(i);
	itr->data = data;
	itr->first_elem = data;
	itr->elem_count = mp_decode_array(&itr->first_elem);
	itr->cur_index = -1;
	return i;
}
Example #6
0
struct tnt_iter *
tnt_iter_map(struct tnt_iter *i, const char *data, size_t size)
{
	const char *tmp_data = data;
	if (mp_check(&tmp_data, data + size) != 0)
		return NULL;
	if (!data || !size || mp_typeof(*data) != MP_MAP)
		return NULL;
	i = tnt_iter_init(i);
	if (i == NULL)
		return NULL;
	i->type = TNT_ITER_MAP;
	i->next = tnt_iter_map_next;
	i->rewind = tnt_iter_map_rewind;
	i->free = NULL;
	struct tnt_iter_map *itr = TNT_IMAP(i);
	itr->data = data;
	itr->first_key = data;
	itr->pair_count = mp_decode_map(&itr->first_key);
	itr->cur_index = -1;
	return i;
}
Example #7
0
static int
test_format(void)
{
	plan(282);
	header();

	const size_t buf_size = 1024;
	char buf[buf_size];
	size_t sz;
	const char *fmt;
	const char *p, *c, *e;
	uint32_t len = 0;

	fmt = "%d %u %i  %ld %lu %li  %lld %llu %lli"
	      "%hd %hu %hi  %hhd %hhu %hhi";
	sz = mp_format(buf, buf_size, fmt, 1, 2, 3,
		       (long)4, (long)5, (long)6,
		       (long long)7, (long long)8, (long long)9,
		       (short)10, (short)11, (short)12,
		       (char)13, (char)14, (char)15);
	p = buf;
	for (unsigned i = 0; i < 15; i++) {
		ok(mp_typeof(*p) == MP_UINT, "Test type on step %d", i);
		ok(mp_decode_uint(&p) == i + 1, "Test value on step %d", i);
	}
	sz = mp_format(buf, buf_size, fmt, -1, -2, -3,
		       (long)-4, (long)-5, (long)-6,
		       (long long)-7, (long long)-8, (long long)-9,
		       (short)-10, (unsigned short)-11, (short)-12,
		       (signed char)-13, (unsigned char)-14, (signed char)-15);
	p = buf;
	for (int i = 0; i < 15; i++) {
		uint64_t expects[5] = { UINT_MAX - 1,
					ULONG_MAX - 4,
					ULLONG_MAX - 7,
					USHRT_MAX - 10,
					UCHAR_MAX - 13 };
		if (i % 3 == 1) {
			ok(mp_typeof(*p) == MP_UINT, "Test type on step %d", i);
			ok(mp_decode_uint(&p) == expects[i / 3],
			   "Test value on step %d", i);
		} else {
			ok(mp_typeof(*p) == MP_INT, "Test type on step %d", i);
			ok(mp_decode_int(&p) == - i - 1,
			   "Test value on step %d", i);
		}
	}

	char data1[32];
	char *data1_end = data1;
	data1_end = mp_encode_array(data1_end, 2);
	data1_end = mp_encode_str(data1_end, "ABC", 3);
	data1_end = mp_encode_uint(data1_end, 11);
	size_t data1_len = data1_end - data1;
	assert(data1_len <= sizeof(data1));

	char data2[32];
	char *data2_end = data2;
	data2_end = mp_encode_int(data2_end, -1234567890);
	data2_end = mp_encode_str(data2_end, "DEFGHIJKLMN", 11);
	data2_end = mp_encode_uint(data2_end, 321);
	size_t data2_len = data2_end - data2;
	assert(data2_len <= sizeof(data2));

	fmt = "%d NIL [%d %b %b] this is test"
		"[%d %%%% [[ %d {%s %f %%  %.*s %lf %.*s NIL}"
		"%p %d %.*p ]] %d%d%d]";
#define TEST_PARAMS 0, 1, true, false, -1, 2, \
	"flt", 0.1, 6, "double#ignored", 0.2, 0, "ignore", \
	data1, 3, data2_len, data2, 4, 5, 6
	sz = mp_format(buf, buf_size, fmt, TEST_PARAMS);
	p = buf;
	e = buf + sz;

	c = p;
	ok(mp_check(&c, e) == 0, "check");
	ok(mp_typeof(*p) == MP_UINT, "type");
	ok(mp_decode_uint(&p) == 0, "decode");

	c = p;
	ok(mp_check(&c, e) == 0, "check");
	ok(mp_typeof(*p) == MP_NIL, "type");
	mp_decode_nil(&p);

	c = p;
	ok(mp_check(&c, e) == 0, "check");
	ok(mp_typeof(*p) == MP_ARRAY, "type");
	ok(mp_decode_array(&p) == 3, "decode");

	c = p;
	ok(mp_check(&c, e) == 0, "check");
	ok(mp_typeof(*p) == MP_UINT, "type");
	ok(mp_decode_uint(&p) == 1, "decode");

	c = p;
	ok(mp_check(&c, e) == 0, "check");
	ok(mp_typeof(*p) == MP_BOOL, "type");
	ok(mp_decode_bool(&p) == true, "decode");

	c = p;
	ok(mp_check(&c, e) == 0, "check");
	ok(mp_typeof(*p) == MP_BOOL, "type");
	ok(mp_decode_bool(&p) == false, "decode");

	c = p;
	ok(mp_check(&c, e) == 0, "check");
	ok(mp_typeof(*p) == MP_ARRAY, "type");
	ok(mp_decode_array(&p) == 5, "decode");

	c = p;
	ok(mp_check(&c, e) == 0, "check");
	ok(mp_typeof(*p) == MP_INT, "type");
	ok(mp_decode_int(&p) == -1, "decode");

	c = p;
	ok(mp_check(&c, e) == 0, "check");
	ok(mp_typeof(*p) == MP_ARRAY, "type");
	ok(mp_decode_array(&p) == 1, "decode");

	c = p;
	ok(mp_check(&c, e) == 0, "check");
	ok(mp_typeof(*p) == MP_ARRAY, "type");
	ok(mp_decode_array(&p) == 5, "decode");

	c = p;
	ok(mp_check(&c, e) == 0, "check");
	ok(mp_typeof(*p) == MP_UINT, "type");
	ok(mp_decode_uint(&p) == 2, "decode");

	c = p;
	ok(mp_check(&c, e) == 0, "check");
	ok(mp_typeof(*p) == MP_MAP, "type");
	ok(mp_decode_map(&p) == 3, "decode");

	c = p;
	ok(mp_check(&c, e) == 0, "check");
	ok(mp_typeof(*p) == MP_STR, "type");
	c = mp_decode_str(&p, &len);
	ok(len == 3, "decode");
	ok(memcmp(c, "flt", 3) == 0, "compare");

	c = p;
	ok(mp_check(&c, e) == 0, "check");
	ok(mp_typeof(*p) == MP_FLOAT, "type");
	ok(fequal(mp_decode_float(&p), 0.1), "decode");

	c = p;
	ok(mp_check(&c, e) == 0, "check");
	ok(mp_typeof(*p) == MP_STR, "type");
	c = mp_decode_str(&p, &len);
	ok(len == 6, "decode");
	ok(memcmp(c, "double", 6) == 0, "compare");

	c = p;
	ok(mp_check(&c, e) == 0, "check");
	ok(mp_typeof(*p) == MP_DOUBLE, "type");
	ok(dequal(mp_decode_double(&p), 0.2), "decode");

	c = p;
	ok(mp_check(&c, e) == 0, "check");
	ok(mp_typeof(*p) == MP_STR, "type");
	c = mp_decode_str(&p, &len);
	ok(len == 0, "decode");

	c = p;
	ok(mp_check(&c, e) == 0, "check");
	ok(mp_typeof(*p) == MP_NIL, "type");
	mp_decode_nil(&p);

	c = p;
	ok(mp_check(&c, e) == 0, "check");
	ok(((size_t)(c - p) == data1_len) &&
	   memcmp(p, data1, data1_len) == 0, "compare");
	p = c;

	c = p;
	ok(mp_check(&c, e) == 0, "check");
	ok(mp_typeof(*p) == MP_UINT, "type");
	ok(mp_decode_uint(&p) == 3, "decode");

	c = p;
	ok(mp_check(&c, e) == 0, "check");
	ok(mp_typeof(*p) == MP_INT, "type");
	ok(mp_decode_int(&p) == -1234567890, "decode");

	c = p;
	ok(mp_check(&c, e) == 0, "check");
	ok(mp_typeof(*p) == MP_STR, "type");
	c = mp_decode_str(&p, &len);
	ok(len == 11, "decode");
	ok(memcmp(c, "DEFGHIJKLMN", 11) == 0, "compare");

	c = p;
	ok(mp_check(&c, e) == 0, "check");
	ok(mp_typeof(*p) == MP_UINT, "type");
	ok(mp_decode_uint(&p) == 321, "decode");

	c = p;
	ok(mp_check(&c, e) == 0, "check");
	ok(mp_typeof(*p) == MP_UINT, "type");
	ok(mp_decode_uint(&p) == 4, "decode");

	c = p;
	ok(mp_check(&c, e) == 0, "check");
	ok(mp_typeof(*p) == MP_UINT, "type");
	ok(mp_decode_uint(&p) == 5, "decode");

	c = p;
	ok(mp_check(&c, e) == 0, "check");
	ok(mp_typeof(*p) == MP_UINT, "type");
	ok(mp_decode_uint(&p) == 6, "decode");

	ok(p == e, "nothing more");

	ok(sz < 70, "no magic detected");

	for (size_t lim = 0; lim <= 70; lim++) {
		memset(buf, 0, buf_size);
		size_t test_sz = mp_format(buf, lim, fmt, TEST_PARAMS);
		ok(test_sz == sz, "return value on step %d", (int)lim);
		bool all_zero = true;
		for(size_t z = lim; z < buf_size; z++)
			all_zero = all_zero && (buf[z] == 0);
		ok(all_zero, "buffer overflow on step %d", (int)lim);

	}

#undef TEST_PARAMS

	footer();
	return check_plan();
}
Example #8
0
const char *
_munpack_item(const char *p, size_t len, SV **res, HV *ext, int utf)
{
	if (!len || !p)
		croak("Internal error: out of pointer");

	const char *pe = p + len;

	switch(mp_typeof(*p)) {
		case MP_UINT:
			*res = newSViv( mp_decode_uint(&p) );
			break;
		case MP_INT:
			*res = newSViv( mp_decode_int(&p) );
			break;
		case MP_FLOAT:
			*res = newSVnv( mp_decode_float(&p) );
			break;
		case MP_DOUBLE:
			*res = newSVnv( mp_decode_double(&p) );
			break;
		case MP_STR: {
			const char *s;
			uint32_t len;
			s = mp_decode_str(&p, &len);
			*res = newSVpvn_flags(s, len, utf ? SVf_UTF8 : 0);
			break;
		}
		case MP_NIL: {
			mp_decode_nil(&p);
			*res = newSV(0);
			break;
		}
		case MP_BOOL:
			if (mp_decode_bool(&p)) {
				*res = newSViv(1);
			} else {
				*res = newSViv(0);
			}
			break;
		case MP_MAP: {
			uint32_t l, i;
			l = mp_decode_map(&p);
			HV * h = newHV();
			sv_2mortal((SV *)h);
			for (i = 0; i < l; i++) {
				SV *k = 0;
				SV *v = 0;
				if (p >= pe)
					croak("Unexpected EOF msgunpack str");
				p = _munpack_item(p, pe - p, &k, ext, utf);
				sv_2mortal(k);
				if (p >= pe)
					croak("Unexpected EOF msgunpack str");
				p = _munpack_item(p, pe - p, &v, ext, utf);
				hv_store_ent(h, k, v, 0);
			}
			*res = newRV((SV *)h);
			break;
		}
		case MP_ARRAY: {
			uint32_t l, i;
			l = mp_decode_array(&p);
			AV *a = newAV();
			sv_2mortal((SV *)a);
			for (i = 0; i < l; i++) {
				SV *item = 0;
				if (p >= pe)
					croak("Unexpected EOF msgunpack str");
				p = _munpack_item(p, pe - p, &item, ext, utf);
				av_push(a, item);

			}
			*res = newRV((SV *)a);
			break;
		}
		case MP_EXT: {
			croak("Isn't defined yet");
		}
		default:
			croak("Unexpected symbol 0x%02x", 0xFF & (int)(*p));

	}
	return p;
}
Example #9
0
static int
opt_set(void *opts, const struct opt_def *def, const char **val,
	struct region *region, uint32_t errcode, uint32_t field_no)
{
	int64_t ival;
	uint64_t uval;
	char *errmsg = tt_static_buf();
	double dval;
	uint32_t str_len;
	const char *str;
	char *ptr;
	char *opt = ((char *) opts) + def->offset;
	switch (def->type) {
	case OPT_BOOL:
		if (mp_typeof(**val) != MP_BOOL)
			goto type_mismatch_err;
		store_bool(opt, mp_decode_bool(val));
		break;
	case OPT_UINT32:
		if (mp_typeof(**val) != MP_UINT)
			goto type_mismatch_err;
		uval = mp_decode_uint(val);
		if (uval > UINT32_MAX)
			goto type_mismatch_err;
		store_u32(opt, uval);
		break;
	case OPT_INT64:
		if (mp_read_int64(val, &ival) != 0)
			goto type_mismatch_err;
		store_u64(opt, ival);
		break;
	case OPT_FLOAT:
		if (mp_read_double(val, &dval) != 0)
			goto type_mismatch_err;
		store_double(opt, dval);
		break;
	case OPT_STR:
		if (mp_typeof(**val) != MP_STR)
			goto type_mismatch_err;
		str = mp_decode_str(val, &str_len);
		str_len = MIN(str_len, def->len - 1);
		memcpy(opt, str, str_len);
		opt[str_len] = '\0';
		break;
	case OPT_STRPTR:
		if (mp_typeof(**val) != MP_STR)
			goto type_mismatch_err;
		str = mp_decode_str(val, &str_len);
		if (str_len > 0) {
			ptr = (char *) region_alloc(region, str_len + 1);
			if (ptr == NULL) {
				diag_set(OutOfMemory, str_len + 1, "region",
					 "opt string");
				return -1;
			}
			memcpy(ptr, str, str_len);
			ptr[str_len] = '\0';
			assert (strlen(ptr) == str_len);
		} else {
			ptr = NULL;
		}
		*(const char **)opt = ptr;
		break;
	case OPT_ENUM:
		if (mp_typeof(**val) != MP_STR)
			goto type_mismatch_err;
		str = mp_decode_str(val, &str_len);
		if (def->to_enum == NULL) {
			ival = strnindex(def->enum_strs, str, str_len,
					 def->enum_max);
		} else {
			ival = def->to_enum(str, str_len);
		}
		switch(def->enum_size) {
		case sizeof(uint8_t):
			store_u8(opt, (uint8_t)ival);
			break;
		case sizeof(uint16_t):
			store_u16(opt, (uint16_t)ival);
			break;
		case sizeof(uint32_t):
			store_u32(opt, (uint32_t)ival);
			break;
		case sizeof(uint64_t):
			store_u64(opt, (uint64_t)ival);
			break;
		default:
			unreachable();
		};
		break;
	case OPT_ARRAY:
		if (mp_typeof(**val) != MP_ARRAY)
			goto type_mismatch_err;
		ival = mp_decode_array(val);
		assert(def->to_array != NULL);
		if (def->to_array(val, ival, opt, errcode, field_no) != 0)
			return -1;
		break;
	case OPT_LEGACY:
		mp_next(val);
		break;
	default:
		unreachable();
	}
	return 0;

type_mismatch_err:
	snprintf(errmsg, TT_STATIC_BUF_LEN, "'%s' must be %s", def->name,
		 opt_type_strs[def->type]);
	diag_set(ClientError, errcode, field_no, errmsg);
	return -1;
}