supporting string function in logical expression: name.left(cnt)/name.right(cnt)/name.mid(start, cnt)

This commit is contained in:
gb 2023-11-02 17:07:28 +08:00
parent 71ce3ed2e0
commit b2a999c605
2 changed files with 132 additions and 1 deletions

View File

@ -140,6 +140,32 @@ static std::string get_real_value(gb_json* jsn, const char* type)
return "";
}
static bool pick_bracket(const char* exp, const char** end)
{
bool ret = false;
int balance = 1;
exp = strstr(exp, "[");
if (exp++)
{
while (*exp && balance)
{
if (*exp == '[')
balance++;
else if (*exp == ']')
balance--;
exp++;
}
if (balance == 0)
{
*end = exp - 1;
ret = true;
}
}
return ret;
}
static struct
{
std::string name;
@ -550,6 +576,52 @@ bool device_option::get_between(const char* type, bool(**f)(gb_json*, void*, voi
return ret;
}
bool device_option::is_string_function(const char* expr, std::string& name, int& start, int& cnt)
{
bool ret = false;
std::string exp(expr);
size_t pos = exp.find(".");
cnt = 0;
if (pos != std::string::npos)
{
name = exp.substr(0, pos++);
exp.erase(0, pos);
if (exp.find("left[") == 0)
{
exp.erase(0, 5);
start = 0;
cnt = atoi(exp.c_str());
pos = 0;
}
else if (exp.find("right[") == 0)
{
exp.erase(0, 6);
start = -1 * atoi(exp.c_str());
cnt = -1;
pos = 0;
}
else if (exp.find("mid[") == 0)
{
exp.erase(0, 4);
start = atoi(exp.c_str());
pos = exp.find(",");
if (pos != std::string::npos)
{
exp.erase(0, pos + 1);
cnt = atoi(exp.c_str());
pos = 0;
}
}
if (pos == 0)
{
pos = exp.find("]");
ret = pos != std::string::npos && (cnt > 0 || cnt == -1);
}
}
return ret;
}
std::string device_option::from_text_value(const char* type, const char* text_val)
{
std::string real_v("");
@ -578,7 +650,7 @@ std::string device_option::from_text_value(const char* type, const char* text_va
}
bool device_option::parse_simple_logic_expression(gb_json* root, const char* expr, std::string* name, EXPRCALC& calc)
{
const char* opers[] = { ">", "<", "!", "=", "." }, * tag = nullptr;
const char* opers[] = { ">", "<", "!", "=", "." }, * tag = nullptr, * dot = strstr(expr, ".");
for (auto& v : opers)
{
@ -590,6 +662,10 @@ bool device_option::parse_simple_logic_expression(gb_json* root, const char* exp
if (!tag)
return false;
if (dot && dot < tag) // is mode.!enable ?
{
tag = dot;
}
std::string n(expr, tag - expr);
bool ret = true;
@ -686,6 +762,25 @@ bool device_option::parse_simple_logic_expression(gb_json* root, const char* exp
}
else
{
// substr function ...
if (strstr(tag, "left[") || strstr(tag, "right[") || strstr(tag, "mid["))
{
const char* end = nullptr;
bool ret = pick_bracket(tag, &end);
if (ret)
{
std::string exp(calc.name + (end + 1)),
name1(tag, end - tag + 1);
name1.insert(0, calc.name + ".");
ret = device_option::parse_simple_logic_expression(root, exp.c_str(), name, calc);
if (ret)
calc.name = std::move(name1);
}
return ret;
}
return false;
}
tag = "";
@ -752,11 +847,26 @@ bool device_option::calc_simple_logic_expression(const char* expr, void* param)
if (obj->compare_.count(expr))
{
gb_json* child = nullptr;
bool substr = false;
int start = 0, cnt = 0;
if(obj->now_)
obj->now_->get_value(obj->compare_[expr].name.c_str(), child);
else
obj->origin_->get_value(obj->compare_[expr].name.c_str(), child);
if (!child)
{
// check string function ...
std::string name("");
substr = device_option::is_string_function(expr, name, start, cnt);
if (substr)
{
if (obj->now_)
obj->now_->get_value(name.c_str(), child);
else
obj->origin_->get_value(name.c_str(), child);
}
}
if (child)
{
bool bv = false;
@ -781,6 +891,15 @@ bool device_option::calc_simple_logic_expression(const char* expr, void* param)
else if (strcmp(sv.c_str(), JSON_SANE_TYPE_STRING) == 0)
{
child->get_value("cur", sv);
if (substr)
{
if (start < 0)
start = sv.length() + start;
if (start > 0 && start < sv.length())
sv.erase(0, start);
if (cnt > 0 && cnt < sv.length())
sv.erase(cnt);
}
}
val = &sv[0];
ret = obj->compare_[expr].compare(child, val, &obj->compare_[expr].val1[0], &obj->compare_[expr].val2[0]) ^ obj->compare_[expr].not_op;

View File

@ -155,6 +155,18 @@ class device_option
static bool get_great(const char* type, bool(**f)(gb_json*, void*, void*, void*));
static bool get_between(const char* type, bool(**f)(gb_json*, void*, void*, void*));
// Function: parse string function - .left(cnt), .right(cnt), .mid(start, cnt)
//
// Parameter: expr - expression of string function, e.g. mode.left(2)
//
// name - to receive the final option name, e.g. mode
//
// start - to receive the starting position of the sub-string, negative is for right()
//
// cnt - to receive the length of the sub string, -1 is to end
//
// Return: true if was string function
static bool is_string_function(const char* expr, std::string& name, int& start, int& cnt);
static std::string from_text_value(const char* type, const char* text_val);
static bool parse_simple_logic_expression(gb_json* root, const char* expr, std::string* name, EXPRCALC& calc);
static void init_condition(const char* expr, void* param);