From 589873417b4aa8452121ffc36332c9d618adf708 Mon Sep 17 00:00:00 2001
From: Vladislav Shpilevoy <v.shpilevoy@tarantool.org>
Date: Fri, 15 Sep 2017 21:05:23 +0300
Subject: [PATCH] Add callback for OPT_DEF_ENUM to process special cases

---
 src/box/alter.cc    |  7 ++++++-
 src/box/index_def.c |  3 ++-
 src/box/opt_def.h   | 12 ++++++++----
 3 files changed, 16 insertions(+), 6 deletions(-)

diff --git a/src/box/alter.cc b/src/box/alter.cc
index 613aec3b48..88b785a3c6 100644
--- a/src/box/alter.cc
+++ b/src/box/alter.cc
@@ -225,7 +225,12 @@ opt_set(void *opts, const struct opt_def *def, const char **val,
 		if (mp_typeof(**val) != MP_STR)
 			return -1;
 		str = mp_decode_str(val, &str_len);
-		ival = strnindex(def->enum_strs, str, str_len, def->enum_max);
+		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);
diff --git a/src/box/index_def.c b/src/box/index_def.c
index 53689caa20..1d4b51510f 100644
--- a/src/box/index_def.c
+++ b/src/box/index_def.c
@@ -50,7 +50,8 @@ const struct index_opts index_opts_default = {
 const struct opt_def index_opts_reg[] = {
 	OPT_DEF("unique", OPT_BOOL, struct index_opts, is_unique),
 	OPT_DEF("dimension", OPT_INT, struct index_opts, dimension),
-	OPT_DEF_ENUM("distance", rtree_index_distance_type, struct index_opts, distance),
+	OPT_DEF_ENUM("distance", rtree_index_distance_type, struct index_opts,
+		     distance, NULL),
 	OPT_DEF("range_size", OPT_INT, struct index_opts, range_size),
 	OPT_DEF("page_size", OPT_INT, struct index_opts, page_size),
 	OPT_DEF("run_count_per_level", OPT_INT, struct index_opts, run_count_per_level),
diff --git a/src/box/opt_def.h b/src/box/opt_def.h
index e858f7bbbd..479add838b 100644
--- a/src/box/opt_def.h
+++ b/src/box/opt_def.h
@@ -46,6 +46,8 @@ enum opt_type {
 
 extern const char *opt_type_strs[];
 
+typedef int64_t (*opt_def_to_enum_cb)(const char *str, uint32_t len);
+
 struct opt_def {
 	const char *name;
 	enum opt_type type;
@@ -56,16 +58,18 @@ struct opt_def {
 	int enum_size;
 	const char **enum_strs;
 	uint32_t enum_max;
+	/** If not NULL, used to get a enum value by a string. */
+	opt_def_to_enum_cb to_enum;
 };
 
 #define OPT_DEF(key, type, opts, field) \
 	{ key, type, offsetof(opts, field), sizeof(((opts *)0)->field), \
-	  NULL, 0, NULL, 0 }
+	  NULL, 0, NULL, 0, NULL }
 
-#define OPT_DEF_ENUM(key, enum_name, opts, field) \
+#define OPT_DEF_ENUM(key, enum_name, opts, field, to_enum) \
 	{ key, OPT_ENUM, offsetof(opts, field), sizeof(int), #enum_name, \
-	  sizeof(enum enum_name), enum_name##_strs, enum_name##_MAX }
+	  sizeof(enum enum_name), enum_name##_strs, enum_name##_MAX, to_enum }
 
-#define OPT_END {NULL, opt_type_MAX, 0, 0, NULL, 0, NULL, 0}
+#define OPT_END {NULL, opt_type_MAX, 0, 0, NULL, 0, NULL, 0, NULL}
 
 #endif /* TARANTOOL_BOX_OPT_DEF_H_INCLUDED */
-- 
GitLab