From 5a4bd047e5db46c6f9e8afa3a4aadebe349df3e6 Mon Sep 17 00:00:00 2001
From: Vladislav Shpilevoy <v.shpilevoy@tarantool.org>
Date: Wed, 13 Sep 2017 12:49:43 +0300
Subject: [PATCH] Introduce opt_strptr for long string options

Needed for #2754
---
 src/box/alter.cc  | 30 +++++++++++++++++++++++-------
 src/box/opt_def.c |  1 +
 src/box/opt_def.h |  1 +
 3 files changed, 25 insertions(+), 7 deletions(-)

diff --git a/src/box/alter.cc b/src/box/alter.cc
index 573339e6ae..613aec3b48 100644
--- a/src/box/alter.cc
+++ b/src/box/alter.cc
@@ -174,12 +174,14 @@ index_def_check_tuple(const struct tuple *tuple, bool *is_166plus)
 }
 
 static int
-opt_set(void *opts, const struct opt_def *def, const char **val)
+opt_set(void *opts, const struct opt_def *def, const char **val,
+	struct region *region)
 {
 	int64_t ival;
 	double dval;
 	uint32_t str_len;
 	const char *str;
+	char *ptr;
 	char *opt = ((char *) opts) + def->offset;
 	switch (def->type) {
 	case OPT_BOOL:
@@ -205,6 +207,20 @@ opt_set(void *opts, const struct opt_def *def, const char **val)
 		memcpy(opt, str, str_len);
 		opt[str_len] = '\0';
 		break;
+	case OPT_STRPTR:
+		if (mp_typeof(**val) != MP_STR)
+			return -1;
+		str = mp_decode_str(val, &str_len);
+		if (str_len > 0) {
+			ptr = (char *) region_alloc_xc(region, str_len + 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)
 			return -1;
@@ -236,7 +252,7 @@ opt_set(void *opts, const struct opt_def *def, const char **val)
 static void
 opts_parse_key(void *opts, const struct opt_def *reg, const char *key,
 	       uint32_t key_len, const char **data, uint32_t errcode,
-	       uint32_t field_no)
+	       uint32_t field_no, struct region *region)
 {
 	char errmsg[DIAG_ERRMSG_MAX];
 	bool found = false;
@@ -245,7 +261,7 @@ opts_parse_key(void *opts, const struct opt_def *reg, const char *key,
 		    memcmp(key, def->name, key_len) != 0)
 			continue;
 
-		if (opt_set(opts, def, data) != 0) {
+		if (opt_set(opts, def, data, region) != 0) {
 			snprintf(errmsg, sizeof(errmsg), "'%.*s' must be %s",
 				 key_len, key, opt_type_strs[def->type]);
 			tnt_raise(ClientError, errcode, field_no, errmsg);
@@ -266,7 +282,7 @@ opts_parse_key(void *opts, const struct opt_def *reg, const char *key,
  */
 static void
 opts_decode(void *opts, const struct opt_def *reg, const char *map,
-	    uint32_t errcode, uint32_t field_no)
+	    uint32_t errcode, uint32_t field_no, struct region *region)
 {
 	assert(mp_typeof(*map) == MP_MAP);
 
@@ -283,7 +299,7 @@ opts_decode(void *opts, const struct opt_def *reg, const char *map,
 		uint32_t key_len;
 		const char *key = mp_decode_str(&map, &key_len);
 		opts_parse_key(opts, reg, key, key_len, &map, errcode,
-			       field_no);
+			       field_no, region);
 	}
 }
 
@@ -296,7 +312,7 @@ index_opts_decode(struct index_opts *opts, const char *map)
 {
 	index_opts_create(opts);
 	opts_decode(opts, index_opts_reg, map, ER_WRONG_INDEX_OPTIONS,
-		    BOX_INDEX_FIELD_OPTS);
+		    BOX_INDEX_FIELD_OPTS, NULL);
 	if (opts->distance == rtree_index_distance_type_MAX) {
 		tnt_raise(ClientError, ER_WRONG_INDEX_OPTIONS,
 			  BOX_INDEX_FIELD_OPTS, "distance must be either "\
@@ -422,7 +438,7 @@ space_opts_decode(struct space_opts *opts, const char *data)
 		}
 	} else {
 		opts_decode(opts, space_opts_reg, data, ER_WRONG_SPACE_OPTIONS,
-			    BOX_SPACE_FIELD_OPTS);
+			    BOX_SPACE_FIELD_OPTS, NULL);
 	}
 }
 
diff --git a/src/box/opt_def.c b/src/box/opt_def.c
index 5fc4e698e1..3203945347 100644
--- a/src/box/opt_def.c
+++ b/src/box/opt_def.c
@@ -36,5 +36,6 @@ const char *opt_type_strs[] = {
 	/* [OPT_INT]	= */ "integer",
 	/* [OPT_FLOAT]	= */ "float",
 	/* [OPT_STR]	= */ "string",
+	/* [OPT_STRPTR] = */ "string",
 	/* [OPT_ENUM]   = */ "enum",
 };
diff --git a/src/box/opt_def.h b/src/box/opt_def.h
index 73dc4ce48d..e858f7bbbd 100644
--- a/src/box/opt_def.h
+++ b/src/box/opt_def.h
@@ -39,6 +39,7 @@ enum opt_type {
 	OPT_INT,	/* int64_t */
 	OPT_FLOAT,	/* double */
 	OPT_STR,	/* char[] */
+	OPT_STRPTR,	/* char*  */
 	OPT_ENUM,	/* enum */
 	opt_type_MAX,
 };
-- 
GitLab