code_device/hgdriver/hgdev/user-opt/device_opt.h

270 lines
7.4 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//
// device_opt: option manager of device
//
// Created: 2023-09-07
//
#pragma once
#include <sane/sane_ex.h>
#include <string>
#include <vector>
#include <map>
#include <functional>
#include "simple_logic.h"
#include <json/gb_json.h>
class device_option
{
gb_json* origin_;
gb_json* now_;
std::vector<std::string> master_opts_; // options that value changed will affect others
std::map<std::string, simple_logic*> slaver_;
std::function<bool(int)> user_;
typedef struct _expr_calc
{
std::string name;
std::string val1;
std::string val2;
bool not_op;
bool(*compare)(gb_json*, void* val, void* v1, void* v2);
}EXPRCALC;
std::map<std::string, EXPRCALC> compare_; // simple condition compare
class condition_value
{
typedef struct _cond_val
{
simple_logic *logic;
std::string value;
}CONDVAL;
std::vector<CONDVAL> vals_;
void clear(void)
{
for (auto& v : vals_)
{
if (v.logic)
delete v.logic;
}
vals_.clear();
}
public:
condition_value()
{}
~condition_value()
{
clear();
}
public:
bool set_value(gb_json* jsn, const char* type, device_option* parent); // jsn contains only ONE value or its object
std::string value(bool(*compare)(const char*, void*), void* param)
{
for (auto& v : vals_)
{
if (!v.logic)
return v.value;
else if (v.logic->value(compare, param))
return v.value;
}
return "";
}
};
class range_value
{
bool is_range_; // true - range; false - list
int val_ind_;
std::vector<condition_value*> vals_;
void clear(void)
{
for (auto& v : vals_)
delete v;
vals_.clear();
}
public:
range_value() : is_range_(false), val_ind_(0)
{}
~range_value()
{
clear();
}
public:
bool set_value(gb_json* jsn, const char* type, device_option *parent); // jsn contains all range object
int count(void)
{
return vals_.size();
}
bool is_range(void)
{
return is_range_;
}
// return first element in list-value or min-value of range
std::string first_value(bool(*compare)(const char*, void*), void* param)
{
val_ind_ = 0;
if (val_ind_ < count())
return vals_[val_ind_]->value(compare, param);
else
return "";
}
// return next element in list-value or max-value of range
std::string next_value(bool(*compare)(const char*, void*), void* param)
{
if (++val_ind_ < count())
return vals_[val_ind_]->value(compare, param);
else
return "";
}
};
std::map<std::string, range_value*> range_value_;
std::map<std::string, condition_value*> init_value_;
static bool is_equal_b(gb_json* opt, void* val, void* v1, void* v2);
static bool is_equal_i(gb_json* opt, void* val, void* v1, void* v2);
static bool is_equal_f(gb_json* opt, void* val, void* v1, void* v2);
static bool is_equal_s(gb_json* opt, void* val, void* v1, void* v2);
static bool is_less_b(gb_json* opt, void* val, void* v1, void* v2);
static bool is_less_i(gb_json* opt, void* val, void* v1, void* v2);
static bool is_less_f(gb_json* opt, void* val, void* v1, void* v2);
static bool is_less_s(gb_json* opt, void* val, void* v1, void* v2);
static bool is_great_b(gb_json* opt, void* val, void* v1, void* v2);
static bool is_great_i(gb_json* opt, void* val, void* v1, void* v2);
static bool is_great_f(gb_json* opt, void* val, void* v1, void* v2);
static bool is_great_s(gb_json* opt, void* val, void* v1, void* v2);
static bool is_between_b(gb_json* opt, void* val, void* v1, void* v2);
static bool is_between_i(gb_json* opt, void* val, void* v1, void* v2);
static bool is_between_f(gb_json* opt, void* val, void* v1, void* v2);
static bool is_between_s(gb_json* opt, void* val, void* v1, void* v2);
static bool is_opt_enabled(gb_json* opt, void* val, void* v1, void* v2);
static bool get_equal(const char* type, bool(**f)(gb_json*, void*, void*, void*));
static bool get_less(const char* type, bool(**f)(gb_json*, void*, void*, void*));
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*));
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);
static bool calc_simple_logic_expression(const char* expr, void* param);
void clear(void);
gb_json* group_opt(const char* title);
bool arrange_raw_json(const char* txt); // create origin_ and re-arrange groups
void init_depends(gb_json* opt);
gb_json* copy_opt(gb_json* from);
bool to_now(bool init, bool* changed);
protected:
static std::string option_value(gb_json* jsn, bool def_val);
template<class T>
static condition_value* to_condition_value(gb_json* jsn, const char* key, const char* type, device_option* parent)
{
condition_value* ret = nullptr;
gb_json* child = nullptr;
if (!jsn->get_value(key, child))
{
T v;
jsn->get_value(key, v);
child = new gb_json("", v);
}
ret = new condition_value();
if (!ret->set_value(child, type, parent))
{
delete ret;
ret = nullptr;
}
child->release();
return ret;
}
public:
device_option(std::function<bool(int)> user_priv = std::function<bool(int)>());
~device_option();
static std::string trans_group(const char* utf8, bool to_title);
static std::string get_group(int ind, bool title);
public:
bool init(const char* opt_json);
bool refine_data(const char* name, void* value); // return true if the 'value' is out of range and refined it in the range
int update_data(const char* name, void* value); // return scanner_err. name and value would be null if invoked for language changed
int count(void); // return option count
bool is_auto_restore_default(const char* name);
std::string get_name_by_sane_id(int sane_ind);
std::string get_option_value_type(const char* name);
std::string get_option_value(const char* name, int type/*OPT_VAL_xxx*/, int* size = nullptr); // return whole json-text if name was null
std::string get_option_field_string(const char* name, const char* key);
std::string get_option_value_type(int sane_ind);
std::string get_option_value(int sane_ind, int type/*OPT_VAL_xxx*/, int* size = nullptr); // return whole json-text if name was null
};
//{
// "noise-size": {
// "cat": "base",
// "group" : "base",
// "title" : " <20><><EFBFBD><EFBFBD><EFBFBD>Ż<EFBFBD><C5BB>ߴ<EFBFBD>",
// "desc" : "<22><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫȥ<D2AA><C8A5><EFBFBD>ĺ<EFBFBD>",
// "ver" : 0,
// "pos" : 0,
// "fix-id" : 0,
// "type" : "int",
// "unit" : "none",
// "affect" : 0,
// "readonly" : false,
// "visible" : true,
// "enabled" : false,
// "size" : 4,
// "cur" : 10,
// "default" : 10,
// "range" : {
// "min": 1,
// "max" : {
// "paper==A3": 50, // condition value
// "default": 45} ,
// "step" : 1
// },
// "depend_or": ["is-noise-optimize==true"]
// },
//
// "paper": {
// "cat": "base",
// "group" : "base",
// "title" : "ֽ<>ųߴ<C5B3>",
// "desc" : "<22><><EFBFBD>ó<EFBFBD>ͼ<EFBFBD><CDBC>С",
// "ver" : 0,
// "pos" : 0,
// "fix-id" : 0,
// "type" : "string",
// "unit" : "none",
// "affect" : 0,
// "readonly" : false,
// "visible" : true,
// "enabled" : false,
// "size" : 96,
// "cur" : "ƥ<><C6A5>ԭʼ<D4AD>ߴ<EFBFBD>",
// "default" : "ƥ<><C6A5>ԭʼ<D4AD>ߴ<EFBFBD>",
// "range" : ["A3", "8<><38>", {
// "mode==24λ<34><CEBB>ɫ": "A4" // condition value
// }, "A4<41><34><EFBFBD><EFBFBD>", "16<31><36>", "16<31><36><EFBFBD><EFBFBD><EFBFBD><EFBFBD>", "A5", "A5<41><35><EFBFBD><EFBFBD>", "A6", "A6<41><36><EFBFBD><EFBFBD>", "B4", "B5", "B5<42><35><EFBFBD><EFBFBD>", "B6", "B6<42><36><EFBFBD><EFBFBD>", "Letter", "Letter<65><72><EFBFBD><EFBFBD>", "Double Letter", "LEGAL", "ƥ<><C6A5>ԭʼ<D4AD>ߴ<EFBFBD>", "<22><><EFBFBD><EFBFBD>ɨ<EFBFBD><C9A8><EFBFBD>ߴ<EFBFBD><DFB4>Զ<EFBFBD><D4B6><EFBFBD><EFBFBD><EFBFBD>", "<22><><EFBFBD><EFBFBD>ɨ<EFBFBD><C9A8><EFBFBD>ߴ<EFBFBD>", "<22><><EFBFBD><EFBFBD><EFBFBD>Ծ<EFBFBD>"]
// }
//}