#include "device_opt.h" #include #include #include "../../sdk/hginclude/huagaoxxx_warraper_ex.h" #include //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // image-processing jsons ... #define JSON_SANE_TYPE_BOOL "bool" #define JSON_SANE_TYPE_INT "int" #define JSON_SANE_TYPE_FIXED "float" #define JSON_SANE_TYPE_STRING "string" template static void copy_simple_type(TC* dst, T& src) { *dst = src; } template static bool refine_data_to_range(gb_json* jsn, void* value, void(*cp)(TC*, T&)) { bool refined = false; gb_json* range = nullptr; jsn->get_value("range", range); if (range) { T vl, vu, s; if (range->get_value("min", vl)) { if (*(TC*)value < vl) { cp((TC*)value, vl); refined = true; } else if (range->get_value("max", vu)) { if (*(TC*)value > vu) { cp((TC*)value, vu); refined = true; } else if (range->get_value("step", s)) { T cur(*(TC*)value); vl = cur - vl; vl /= s; if (!IS_DOUBLE_EQUAL(vl, (int)vl)) { vl += .5f; vl = (int)vl * s; if (vl > vu) vl = vu; cp((TC*)value, vl); refined = true; } } } } else { gb_json* val = range->first_child(); bool found = false; while (val) { if (val->value(vl)) { if (*(TC*)value == vl) { found = true; val->release(); break; } } val->release(); val = range->next_child(); } if (!found) { if (jsn->get_value("default", vl)) { refined = true; cp((TC*)value, vl); } } } range->release(); } return refined; } static bool refine_string_data(gb_json* jsn, void* value) { bool refined = false; gb_json* range = nullptr; std::string v((char*)value); jsn->get_value("range", range); if (range) { std::string vl(""), vu(""), s(""); if (range->get_value("min", vl)) { if (v < vl) { strcpy((char*)value, vl.c_str()); refined = true; } else if (range->get_value("max", vu)) { if (v > vu) { strcpy((char*)value, vu.c_str()); refined = true; } //else if (range->get_value("step", s)) //{ // T cur(*(TC*)value); // // vl = cur - vl; // vl /= s; // if (!IS_DOUBLE_EQUAL(vl, (int)vl)) // { // vl += .5f; // vl = (int)vl * s; // if (vl > vu) // vl = vu; // cp((TC*)value, vl); // refined = true; // } //} } } else { gb_json* val = range->first_child(); bool found = false; while (val) { if (val->value(vl)) { if (v == vl) { found = true; val->release(); break; } } val->release(); val = range->next_child(); } if (!found) { if (jsn->get_value("default", vl)) { refined = true; strcpy((char*)value, vl.c_str()); } } } range->release(); } return refined; } template static std::string get_real_value(gb_json* jsn, bool def_val) { T v; jsn->get_value(def_val ? "default" : "cur", v); return std::move(std::string((char*)&v, sizeof(v))); } template static std::string get_real_string(gb_json* jsn, bool def_val) { T v; jsn->get_value(def_val ? "default" : "cur", v); return std::move(v); } static std::string get_real_value(gb_json* jsn, const char* type) { if (strcmp(type, JSON_SANE_TYPE_BOOL) == 0) { bool v = false; jsn->value(v); return std::string((char*)&v, sizeof(v)); } else if (strcmp(type, JSON_SANE_TYPE_INT) == 0) { int v = 0; jsn->value(v); return std::string((char*)&v, sizeof(v)); } else if (strcmp(type, JSON_SANE_TYPE_FIXED) == 0) { double v = .0f; jsn->value(v); return std::string((char*)&v, sizeof(v)); } else if (strcmp(type, JSON_SANE_TYPE_STRING) == 0) { std::string v(""); jsn->value(v); return std::move(v); } return ""; } static struct { std::string name; std::string title; // in UTF8 }g_known_group_with_sn[] = { {"base", "\xE5\x9F\xBA\xE6\x9C\xAC\xE8\xAE\xBE\xE7\xBD\xAE"} , {"bright", "\xE4\xBA\xAE\xE5\xBA\xA6"} , {"imgp", "\xE5\x9B\xBE\xE5\x83\x8F\xE5\xA4\x84\xE7\x90\x86"} , {"feeder", "\xE9\x80\x81\xE7\xBA\xB8\xE6\x96\xB9\xE5\xBC\x8F\xE8\xAE\xBE\xE7\xBD\xAE"} // ÉèÖãº\xE8\xAE\xBE\xE7\xBD\xAE }; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // class device_opt ... bool device_option::condition_value::set_value(gb_json* jsn, const char* type, device_option* parent) // jsn contains only ONE value or its object { bool ret = false; clear(); if (jsn->is_leaf_node()) { CONDVAL cv; cv.logic = nullptr; cv.value = get_real_value(jsn, type); vals_.push_back(cv); ret = true; } else { gb_json* item = jsn->first_child(); CONDVAL val0; // make the default value at last ret = true; val0.logic = nullptr; val0.value = ""; while (item) { // "condition": value std::string cond(item->key()), val(""); CONDVAL cv; if (cond == "default") { val0.logic = nullptr; val0.value = get_real_value(item, type); } else { int end = 0; cv.logic = new simple_logic(); if (cv.logic->parse(cond.c_str(), &end, &device_option::init_condition, parent)) { cv.value = get_real_value(item, type); vals_.push_back(cv); } else { delete cv.logic; item->release(); ret = false; break; } } item->release(); item = jsn->next_child(); } if (!val0.value.empty()) vals_.push_back(val0); } return ret; } bool device_option::range_value::set_value(gb_json* jsn, const char* type, device_option* parent) // jsn contains all range object { bool ret = true; clear(); if (jsn->is_array()) { gb_json* item = jsn->first_child(); while (item) { device_option::condition_value* v = new device_option::condition_value(); if (v->set_value(item, type, parent)) { vals_.push_back(v); } else { delete v; item->release(); ret = false; break; } item->release(); item = jsn->next_child(); } } else { condition_value* cv = nullptr; if (strcmp(type, JSON_SANE_TYPE_BOOL) == 0) { cv = device_option::to_condition_value(jsn, "min", type, parent); ret = false; if (cv) { vals_.push_back(cv); cv = device_option::to_condition_value(jsn, "max", type, parent); if (cv) { vals_.push_back(cv); cv = device_option::to_condition_value(jsn, "step", type, parent); if (cv) { vals_.push_back(cv); ret = true; } } } } else if (strcmp(type, JSON_SANE_TYPE_INT) == 0) { cv = device_option::to_condition_value(jsn, "min", type, parent); ret = false; if (cv) { vals_.push_back(cv); cv = device_option::to_condition_value(jsn, "max", type, parent); if (cv) { vals_.push_back(cv); cv = device_option::to_condition_value(jsn, "step", type, parent); if (cv) { vals_.push_back(cv); ret = true; } } } } else if (strcmp(type, JSON_SANE_TYPE_FIXED) == 0) { cv = device_option::to_condition_value(jsn, "min", type, parent); ret = false; if (cv) { vals_.push_back(cv); cv = device_option::to_condition_value(jsn, "max", type, parent); if (cv) { vals_.push_back(cv); cv = device_option::to_condition_value(jsn, "step", type, parent); if (cv) { vals_.push_back(cv); ret = true; } } } } else if (strcmp(type, JSON_SANE_TYPE_STRING) == 0) { cv = device_option::to_condition_value(jsn, "min", type, parent); ret = false; if (cv) { vals_.push_back(cv); cv = device_option::to_condition_value(jsn, "max", type, parent); if (cv) { vals_.push_back(cv); cv = device_option::to_condition_value(jsn, "step", type, parent); if (cv) { vals_.push_back(cv); ret = true; } } } } } return ret; } device_option::device_option() : origin_(nullptr), now_(nullptr) {} device_option::~device_option() { clear(); } bool device_option::is_equal_b(gb_json* opt, void* val, void* v1, void* v2) { return *(bool*)val == *(bool*)v1; } bool device_option::is_equal_i(gb_json* opt, void* val, void* v1, void* v2) { return *(int*)val == *(int*)v1; } bool device_option::is_equal_f(gb_json* opt, void* val, void* v1, void* v2) { return IS_DOUBLE_EQUAL(*(double*)val, *(double*)v1); } bool device_option::is_equal_s(gb_json* opt, void* val, void* v1, void* v2) { return strcmp((char*)val, from_default_language((char*)v1)) == 0; } bool device_option::is_less_b(gb_json* opt, void* val, void* v1, void* v2) { return *(bool*)val < *(bool*)v1; } bool device_option::is_less_i(gb_json* opt, void* val, void* v1, void* v2) { return *(int*)val < *(int*)v1; } bool device_option::is_less_f(gb_json* opt, void* val, void* v1, void* v2) { return *(double*)val < *(double*)v1; } bool device_option::is_less_s(gb_json* opt, void* val, void* v1, void* v2) { return strcmp((char*)val, from_default_language((char*)v1)) < 0; } bool device_option::is_great_b(gb_json* opt, void* val, void* v1, void* v2) { return *(bool*)val > *(bool*)v1; } bool device_option::is_great_i(gb_json* opt, void* val, void* v1, void* v2) { return *(int*)val > *(int*)v1; } bool device_option::is_great_f(gb_json* opt, void* val, void* v1, void* v2) { return *(double*)val > *(double*)v1; } bool device_option::is_great_s(gb_json* opt, void* val, void* v1, void* v2) { return strcmp((char*)val, from_default_language((char*)v1)) > 0; } bool device_option::is_between_b(gb_json* opt, void* val, void* v1, void* v2) { return *(bool*)val == *(bool*)v1 || *(bool*)val <= *(bool*)v2; } bool device_option::is_between_i(gb_json* opt, void* val, void* v1, void* v2) { return *(int*)val >= *(int*)v1 && *(int*)val <= *(int*)v2; } bool device_option::is_between_f(gb_json* opt, void* val, void* v1, void* v2) { return *(double*)val >= *(double*)v1 && *(double*)val <= *(double*)v2; } bool device_option::is_between_s(gb_json* opt, void* val, void* v1, void* v2) { return strcmp((char*)val, from_default_language((char*)v1)) >= 0 && strcmp((char*)val, from_default_language((char*)v2)) <= 0; } bool device_option::is_opt_enabled(gb_json* opt, void* val, void* v1, void* v2) { bool en = true; if (!opt->get_value("enabled", en)) en = true; return en; } bool device_option::get_equal(const char* type, bool(**f)(gb_json*, void*, void*, void*)) { bool ret = true; if (strcmp(type, JSON_SANE_TYPE_BOOL) == 0) { *f = &device_option::is_equal_b; } else if (strcmp(type, JSON_SANE_TYPE_INT) == 0) { *f = &device_option::is_equal_i; } else if (strcmp(type, JSON_SANE_TYPE_FIXED) == 0) { *f = &device_option::is_equal_f; } else if (strcmp(type, JSON_SANE_TYPE_STRING) == 0) { *f = &device_option::is_equal_s; } else { ret = false; } return ret; } bool device_option::get_less(const char* type, bool(**f)(gb_json*, void*, void*, void*)) { bool ret = true; if (strcmp(type, JSON_SANE_TYPE_BOOL) == 0) { *f = &device_option::is_less_b; } else if (strcmp(type, JSON_SANE_TYPE_INT) == 0) { *f = &device_option::is_less_i; } else if (strcmp(type, JSON_SANE_TYPE_FIXED) == 0) { *f = &device_option::is_less_f; } else if (strcmp(type, JSON_SANE_TYPE_STRING) == 0) { *f = &device_option::is_less_s; } else { ret = false; } return ret; } bool device_option::get_great(const char* type, bool(**f)(gb_json*, void*, void*, void*)) { bool ret = true; if (strcmp(type, JSON_SANE_TYPE_BOOL) == 0) { *f = &device_option::is_great_b; } else if (strcmp(type, JSON_SANE_TYPE_INT) == 0) { *f = &device_option::is_great_i; } else if (strcmp(type, JSON_SANE_TYPE_FIXED) == 0) { *f = &device_option::is_great_f; } else if (strcmp(type, JSON_SANE_TYPE_STRING) == 0) { *f = &device_option::is_great_s; } else { ret = false; } return ret; } bool device_option::get_between(const char* type, bool(**f)(gb_json*, void*, void*, void*)) { bool ret = true; if (strcmp(type, JSON_SANE_TYPE_BOOL) == 0) { *f = &device_option::is_between_b; } else if (strcmp(type, JSON_SANE_TYPE_INT) == 0) { *f = &device_option::is_between_i; } else if (strcmp(type, JSON_SANE_TYPE_FIXED) == 0) { *f = &device_option::is_between_f; } else if (strcmp(type, JSON_SANE_TYPE_STRING) == 0) { *f = &device_option::is_between_s; } else { ret = false; } return ret; } std::string device_option::from_text_value(const char* type, const char* text_val) { std::string real_v(""); if (strcmp(type, JSON_SANE_TYPE_BOOL) == 0) { bool v = STRICMP(text_val, "true") == 0; real_v = std::string((char*)&v, sizeof(v)); } else if (strcmp(type, JSON_SANE_TYPE_INT) == 0) { int v = atoi(text_val); real_v = std::string((char*)&v, sizeof(v)); } else if (strcmp(type, JSON_SANE_TYPE_FIXED) == 0) { double v = atof(text_val); real_v = std::string((char*)&v, sizeof(v)); } else if (strcmp(type, JSON_SANE_TYPE_STRING) == 0) { real_v = text_val; } return std::move(real_v); } bool device_option::parse_simple_logic_expression(gb_json* root, const char* expr, std::string* name, EXPRCALC& calc) { const char* opers[] = { ">", "<", "!", "=", "." }, * tag = nullptr; for (auto& v : opers) { tag = strstr(expr, v); if (tag) break; } if (!tag) return false; std::string n(expr, tag - expr); bool ret = true; gb_json *child = nullptr; if (name) *name = n; calc.name = n; root->get_value(n.c_str(), child); if (!child) return false; if (!child->get_value("type", n)) { child->release(); return false; } child->release(); if (*tag == '>') { if (tag[1] == '=') { if (!device_option::get_less(n.c_str(), &calc.compare)) return false; calc.not_op = true; tag++; } else { if (!device_option::get_great(n.c_str(), &calc.compare)) return false; calc.not_op = false; } tag++; } else if (*tag == '<') { if (tag[1] == '=') { if (!device_option::get_great(n.c_str(), &calc.compare)) return false; calc.not_op = true; tag++; } else { if (!device_option::get_less(n.c_str(), &calc.compare)) return false; calc.not_op = false; } tag++; } else if (*tag == '!') { if (tag[1] == '=') { if (!device_option::get_equal(n.c_str(), &calc.compare)) return false; calc.not_op = true; tag++; } else { return false; } tag++; } else if (*tag == '=') { if (tag[1] == '=') { if (!device_option::get_equal(n.c_str(), &calc.compare)) return false; calc.not_op = false; tag++; } else { return false; } tag++; } else if (*tag++ == '.') { calc.compare = &device_option::is_opt_enabled; if (strcmp(tag, "enabled") == 0) { calc.not_op = false; } else if (strcmp(tag, "!enabled") == 0) { calc.not_op = true; } else { return false; } tag = ""; } else { return false; } // value ... if (*tag) { if (*tag == '[') { const char* next = strstr(tag++, ","); if (next++ == nullptr) { ret = false; } else { std::string v(tag, next - tag - 1); calc.val1 = device_option::from_text_value(n.c_str(), v.c_str()); tag = strstr(next, "]"); if (!tag) ret = false; else { v = std::string(next, tag - next); calc.val2 = device_option::from_text_value(n.c_str(), v.c_str()); } } } else { calc.val1 = device_option::from_text_value(n.c_str(), tag); } } return ret; } void device_option::init_condition(const char* expr, void* param) { if (((device_option*)param)->compare_.count(expr)) return; std::string name(""); EXPRCALC calc; if (device_option::parse_simple_logic_expression(((device_option*)param)->origin_, expr, &name, calc)) { ((device_option*)param)->compare_[expr] = calc; if (std::find(((device_option*)param)->master_opts_.begin(), ((device_option*)param)->master_opts_.end(), name) == ((device_option*)param)->master_opts_.end()) ((device_option*)param)->master_opts_.push_back(name); } } bool device_option::calc_simple_logic_expression(const char* expr, void* param) { device_option* obj = (device_option*)param; bool ret = true; if (obj->compare_.count(expr)) { gb_json* child = nullptr; 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) { bool bv = false; int nv = 0; double dv = .0f; std::string sv(""); void* val = nullptr; child->get_value("type", sv); if (strcmp(sv.c_str(), JSON_SANE_TYPE_BOOL) == 0) { sv = get_real_value(child, false); } else if (strcmp(sv.c_str(), JSON_SANE_TYPE_INT) == 0) { sv = get_real_value(child, false); } else if (strcmp(sv.c_str(), JSON_SANE_TYPE_FIXED) == 0) { sv = get_real_value(child, false); } else if (strcmp(sv.c_str(), JSON_SANE_TYPE_STRING) == 0) { child->get_value("cur", sv); } 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; child->release(); } } return ret; } void device_option::clear(void) { if (origin_) origin_->release(); if (now_) now_->release(); origin_ = now_ = nullptr; master_opts_.clear(); compare_.clear(); for (auto& v : slaver_) delete v.second; slaver_.clear(); for (auto& v : range_value_) delete v.second; range_value_.clear(); for (auto& v : init_value_) delete v.second; init_value_.clear(); } gb_json* device_option::group_opt(const char* title) { gb_json* jsn = new gb_json(); jsn->set_value("title", title); jsn->set_value("type", "group"); return jsn; } bool device_option::arrange_raw_json(const char* txt) { std::vector groups; std::vector ungroup; std::map> ingroup; gb_json* jsn = new gb_json(), *child = nullptr; std::string text(txt), str(""); if (jsn->attach_text(&text[0])) { text.clear(); child = jsn->first_child(); while (child) { child->get_value("group", str); if (str.empty()) ungroup.push_back(child); else if (ingroup.count(str)) ingroup[str].push_back(child); else { std::vector c; c.push_back(child); ingroup[str] = c; } child = jsn->next_child(); } } jsn->release(); if (ungroup.size() || ingroup.size()) { origin_ = new gb_json(); for (auto& v : ungroup) { origin_->set_value(v->key().c_str(), v); v->release(); } // named group ... int grpind = 1; for (auto& v : g_known_group_with_sn) { if (ingroup.count(v.name)) { gb_json* grp = group_opt(v.title.c_str()); origin_->set_value(("grp-" + std::to_string(grpind++)).c_str(), grp); grp->release(); for (auto& opt : ingroup[v.name]) { origin_->set_value(opt->key().c_str(), opt); opt->release(); } ingroup.erase(v.name); } } for (auto& v : ingroup) { gb_json* grp = group_opt(v.first.c_str()); origin_->set_value(("grp-" + std::to_string(grpind++)).c_str(), grp); grp->release(); for (auto& opt : v.second) { origin_->set_value(opt->key().c_str(), opt); opt->release(); } } } return origin_ != nullptr; } void device_option::init_depends(gb_json* opt) { gb_json* range = nullptr; std::string dpnd(""); if (opt->get_value("depend", dpnd) && !dpnd.empty()) { simple_logic* logic = new simple_logic(); int pos = 0; if (logic->parse(dpnd.c_str(), &pos, &device_option::init_condition, this)) slaver_[opt->key().c_str()] = logic; else delete logic; } // values ... opt->get_value("range", range); if (range) { range_value* val = new range_value(); opt->get_value("type", dpnd); if (val->set_value(range, dpnd.c_str(), this)) range_value_[opt->key()] = val; else delete val; range->release(); } // default: range = nullptr; opt->get_value("default", range); opt->get_value("type", dpnd); if (range) { range_value* rv = new range_value(); if (rv->set_value(range, dpnd.c_str(), this)) init_value_[opt->key()] = rv; else delete rv; range->release(); } } gb_json* device_option::copy_opt(gb_json* from) { std::string text(from->to_string()); gb_json* to = new gb_json(); if (!to->attach_text(&text[0])) { to->release(); to = nullptr; } else { std::string val(""); to->key() = from->key(); // 1: language changed ... (title, description, string-list) if (to->get_value("title", val)) to->set_value("title", from_default_language(val.c_str())); if (to->get_value("desc", val)) to->set_value("desc", from_default_language(val.c_str())); // 2: enabled ... if (slaver_.count(to->key())) to->set_value("enabled", slaver_[to->key()]->value(&device_option::calc_simple_logic_expression, this)); // 3: default value ... if (init_value_.count(to->key())) { std::string val(init_value_[to->key()]->first_value(&device_option::calc_simple_logic_expression, this)); for (int i = 0; i < init_value_[to->key()]->count(); ++i) { if (!val.empty()) { std::string type(""); to->get_value("type", type); if (type == JSON_SANE_TYPE_BOOL) to->set_value("default", *(bool*)val.c_str()); else if(type == JSON_SANE_TYPE_INT) to->set_value("default", *(int*)val.c_str()); else if(type == JSON_SANE_TYPE_FIXED) to->set_value("default", *(double*)val.c_str()); else if(type == JSON_SANE_TYPE_STRING) to->set_value("default", (const wchar_t*)val.c_str()); break; } val = init_value_[to->key()]->next_value(&device_option::calc_simple_logic_expression, this); } } // 4: range value ... if (range_value_.count(to->key())) { gb_json* src = nullptr, * dst = nullptr; from->get_value("range", src); to->get_value("range", dst); if (src && dst) { dst->clear(src->is_array()); dst->key() = src->key(); to->get_value("type", val); if (val == JSON_SANE_TYPE_BOOL) { if (dst->is_array()) { val = range_value_[to->key()]->first_value(&device_option::calc_simple_logic_expression, this); for (int i = 0; i < range_value_[to->key()]->count(); ++i) { if (!val.empty()) *dst += *(bool*)&val[0]; val = range_value_[to->key()]->next_value(&device_option::calc_simple_logic_expression, this); } } else { val = range_value_[to->key()]->first_value(&device_option::calc_simple_logic_expression, this); dst->set_value("min", *(bool*)&val[0]); val = range_value_[to->key()]->next_value(&device_option::calc_simple_logic_expression, this); dst->set_value("max", *(bool*)&val[0]); } } else if (val == JSON_SANE_TYPE_INT) { if (dst->is_array()) { val = range_value_[to->key()]->first_value(&device_option::calc_simple_logic_expression, this); for (int i = 0; i < range_value_[to->key()]->count(); ++i) { if (!val.empty()) *dst += *(int*)&val[0]; val = range_value_[to->key()]->next_value(&device_option::calc_simple_logic_expression, this); } } else { val = range_value_[to->key()]->first_value(&device_option::calc_simple_logic_expression, this); dst->set_value("min", *(int*)&val[0]); val = range_value_[to->key()]->next_value(&device_option::calc_simple_logic_expression, this); dst->set_value("max", *(int*)&val[0]); } } else if (val == JSON_SANE_TYPE_FIXED) { if (dst->is_array()) { val = range_value_[to->key()]->first_value(&device_option::calc_simple_logic_expression, this); for (int i = 0; i < range_value_[to->key()]->count(); ++i) { if (!val.empty()) *dst += *(double*)&val[0]; val = range_value_[to->key()]->next_value(&device_option::calc_simple_logic_expression, this); } } else { val = range_value_[to->key()]->first_value(&device_option::calc_simple_logic_expression, this); dst->set_value("min", *(double*)&val[0]); val = range_value_[to->key()]->next_value(&device_option::calc_simple_logic_expression, this); dst->set_value("max", *(double*)&val[0]); } } else if (val == JSON_SANE_TYPE_STRING) { if (dst->is_array()) { val = range_value_[to->key()]->first_value(&device_option::calc_simple_logic_expression, this); for(int i = 0; i < range_value_[to->key()]->count(); ++i) { if(!val.empty()) *dst += from_default_language(val.c_str()); val = range_value_[to->key()]->next_value(&device_option::calc_simple_logic_expression, this); } } else { val = range_value_[to->key()]->first_value(&device_option::calc_simple_logic_expression, this); dst->set_value("min", from_default_language(val.c_str())); val = range_value_[to->key()]->next_value(&device_option::calc_simple_logic_expression, this); dst->set_value("max", from_default_language(val.c_str())); } } } if (src) src->release(); if (dst) dst->release(); } } return to; } bool device_option::to_now(bool init) { if (!origin_) return false; gb_json* from = nullptr, * to = nullptr, * tmp = new gb_json(); from = origin_->first_child(); while (from) { std::string name(from->key()); if (init) init_depends(from); to = copy_opt(from); from->release(); if (to) { // copy cur value ... if (now_) { gb_json* now = nullptr; now_->get_value(to->key().c_str(), now); if (now) { std::string type(""); now->get_value("type", type); if (type == JSON_SANE_TYPE_BOOL) { bool v = false; now->get_value("cur", v); to->set_value("cur", v); } else if (type == JSON_SANE_TYPE_INT) { int v = 0; now->get_value("cur", v); to->set_value("cur", v); } else if (type == JSON_SANE_TYPE_FIXED) { double v = .0f; now->get_value("cur", v); to->set_value("cur", v); } else if (type == JSON_SANE_TYPE_STRING) { std::string v(""); now->get_value("cur", v); to->set_value("cur", v.c_str()); } now->release(); } } tmp->set_value(name.c_str(), to); to->release(); from = origin_->next_child(); } else { tmp->release(); tmp = nullptr; break; } } if (now_) now_->release(); now_ = tmp; return now_ != nullptr; } std::string device_option::option_value(gb_json* jsn, bool def_val) { std::string type(""), key(def_val ? "default" : "cur"); jsn->get_value("type", type); if (type == "bool") { bool v = false; jsn->get_value(key.c_str(), v); type = std::string((char*)&v, sizeof(v)); } else if (type == "int") { int v = 0; jsn->get_value(key.c_str(), v); type = std::string((char*)&v, sizeof(v)); } else if (type == "float") { double v = .0f; jsn->get_value(key.c_str(), v); type = std::string((char*)&v, sizeof(v)); } else if (type == "string") { if (!jsn->get_value(key.c_str(), type)) type = ""; } return std::move(type); } std::string device_option::trans_group(const char* utf8, bool to_title) { if (to_title) { for (auto& v : g_known_group_with_sn) { if (v.name == utf8) return v.title; } } else { for (auto& v : g_known_group_with_sn) { if (v.title == utf8) return v.name; } } return utf8; } std::string device_option::get_group(int ind, bool title) { if (ind >= 0 && ind < _countof(g_known_group_with_sn)) return title ? g_known_group_with_sn[ind].title : g_known_group_with_sn[ind].name; else return ""; } bool device_option::init(const char* opt_json) { bool ret = false; clear(); if (arrange_raw_json(opt_json)) { ret = to_now(true); if (!ret) clear(); } else { clear(); } return ret; } bool device_option::refine_data(const char* name, void* value) { bool refined = false; gb_json* child = nullptr; now_->get_value(name, child); if (child) { std::string type(""); child->get_value("type", type); if (type == JSON_SANE_TYPE_BOOL) { refined = refine_data_to_range(child, value, copy_simple_type); } else if (type == JSON_SANE_TYPE_INT) { refined = refine_data_to_range(child, value, copy_simple_type); } else if (type == JSON_SANE_TYPE_FIXED) { refined = refine_data_to_range(child, value, copy_simple_type); } else if (type == JSON_SANE_TYPE_STRING) { refined = refine_string_data(child, value); } child->release(); } return refined; } int device_option::update_data(const char* name, void* value) { if (!name) { to_now(false); return SCANNER_ERR_RELOAD_OPT_PARAM; } else if(now_) { std::string type(""); gb_json* child = nullptr; now_->get_value(name, child); if (child) { child->get_value("type", type); if (type == JSON_SANE_TYPE_BOOL) child->set_value("cur", *(bool*)value); else if (type == JSON_SANE_TYPE_INT) child->set_value("cur", *(int*)value); else if (type == JSON_SANE_TYPE_FIXED) child->set_value("cur", *(double*)value); else if (type == JSON_SANE_TYPE_STRING) child->set_value("cur", (char*)value); child->release(); if (std::find(master_opts_.begin(), master_opts_.end(), name) != master_opts_.end()) { to_now(false); return SCANNER_ERR_RELOAD_OPT_PARAM; } } } return SCANNER_ERR_OK; } std::string device_option::get_option_value_type(const char* name) { std::string value(""); if (now_) { gb_json* child = nullptr; now_->get_value(name, child); if (child) { child->get_value("type", value); child->release(); } } return std::move(value); } std::string device_option::get_option_value(const char* name, int type) { std::string value(""); if (now_) { if (!name) { value = now_->to_string(); } else { gb_json* child = nullptr; now_->get_value(name, child); if (child) { if (type == OPT_VAL_JSON) value = child->to_string(); else value = device_option::option_value(child, type == OPT_VAL_DEFAULT); child->release(); } } } return std::move(value); }