code_twain/sane/gb_json.h

314 lines
11 KiB
C++

#pragma once
#if defined(WIN32) || defined(_WIN64)
#include <Windows.h>
#include "../../code_device/hgsane/cJSON.h"
#define PATH_SYMBOL "\\"
#else
#include "cJSON.h"
#define PATH_SYMBOL "/"
#define NULL nullptr
#define DWORD_PTR char*
#define _countof(a) sizeof(a) / sizeof(a[0])
#endif
//
#include <vector>
#include <string>
#include <map>
#include <algorithm>
namespace gb
{
class scanner_cfg;
class refer
{
volatile long ref_;
protected:
refer();
virtual ~refer();
public:
long add_ref(void);
long release(void);
};
class json : public refer
{
enum val_type
{
VAL_TYPE_NULL = 0,
VAL_TYPE_BOOL,
VAL_TYPE_INT,
VAL_TYPE_FLOAT,
VAL_TYPE_STRING,
VAL_TYPE_OBJECT,
VAL_TYPE_ARRAY,
};
val_type type_;
std::string key_;
union
{
bool bval;
int nval;
double dval;
}simple_val_;
std::string strval_;
std::vector<json*> arr_val_;
size_t cur_child_;
static std::string object_key(json* jsn);
static std::string array_key(json* jsn);
void from_cjson(cJSON* cj);
json* find_child(const char* key, bool remove = false);
public:
json(char* json_txt = 0);
protected:
json(const char* key, bool val);
json(const char* key, int val);
json(const char* key, double val);
json(const char* key, const char* val);
json(json& r);
~json();
public:
// parse/un-parse ...
void copy_from(json& r);
bool attach_text(char* json_txt);
void clear(bool as_array = false);
std::string to_string(void);
// attributes ...
std::string& key(void);
bool is_array(void);
bool is_leaf_node(void); // whether this object is a leaf node contains final value
// value access ...
bool get_value(const char* key, bool& val);
bool get_value(const char* key, int& val);
bool get_value(const char* key, double& val);
bool get_value(const char* key, std::string& val);
bool get_value(const char* key, json*& val);
// enumeration ...
size_t children(void); // return children count if was object or array, or else -1 returned
json* child(size_t ind);
json* first_child(void);
json* next_child(void);
// change the item matching 'key', otherwise add a new item
bool set_value(const char* key, bool val);
bool set_value(const char* key, int val);
bool set_value(const char* key, double val);
bool set_value(const char* key, const char* val);
bool set_value(const char* key, json* val);
// operator+= only for array
json& operator+=(bool val);
json& operator+=(int val);
json& operator+=(double val);
json& operator+=(const char* val);
json& operator+=(json* val);
// remove item
json& operator-=(int ind);
bool remove(const char* key);
bool remove(json* child);
bool remove(int ind);
// position management
int index(json* child);
int index_move_to(json* child, int ind);
// leaf node value ...
bool value(bool& val);
bool value(int& val);
bool value(double& val);
bool value(std::string& val);
json& operator=(bool val);
json& operator=(int val);
json& operator=(double val);
json& operator=(const char* val);
};
class base64
{
char base64_ind_[128];
char base64_char_[80];
char padding_char_;
bool is_valid_base64_table(const char* table);
bool initialize_base64_table(const char* table);
public:
base64();
~base64();
public:
bool set_base64_table(const char* table = NULL);
std::string encode(const char* data, size_t bytes, unsigned int line_bytes = -1, bool need_padding = true);
std::string decode(const char* data, size_t bytes);
};
// NOTE: 2021-01-28 all stored string value are in default language (i.e. Chinese-Simplified), user should call app_language::to_default_language/from_default_language for real value
class sane_config_schm : public refer
{
std::string scheme_name_;
scanner_cfg *scanner_;
std::string file_;
json* jsn_;
json* bkp_;
json* def_val_; // name_id: id, name_val: val
bool in_setting_;
void clear();
std::string default_value(const char* name);
protected:
~sane_config_schm();
public:
sane_config_schm(scanner_cfg* scanner = nullptr);
static std::string opt_data_appendix_;
static std::string opt_def_id_appendix_;
static std::string opt_def_val_appendix_;
static std::string opt_def_type_appendix_;
static std::string opt_def_title_appendix_;
static bool hex(unsigned char ch, unsigned char* val);
static bool hex_char(const char* data, unsigned char* val);
static std::string to_hex_letter(const char* data, size_t bytes);
static std::string from_hex_letter(const char* data, size_t bytes);
static bool is_option_data(std::string& name); // reset baase option name into 'name' if name was option data, and return true
static void set_default_value(json* jsn, int id, const char* name, const char* title, void* data, size_t bytes, int type);
static int option_name_2_id(json* jsn, const char* name);
static int option_type(json* jsn, const char* name);
static std::string option_title(json* jsn, const char* name);
static std::string option_default_value(json* jsn, const char* name);
static std::string sane_option_value_2_string(void* val, size_t bytes, int type);
public:
sane_config_schm* copy(void);
bool load_from_file(const char* file);
bool load_from_mem(const char* mem, bool in_b64 = true);
bool save_to(const char* file);
void set_default_value(int sn, const char* name, const char* title, const char* val, size_t bytes, int type);
bool first_config(std::string& name, std::string& val);
bool next_config(std::string& name, std::string& val);
bool get_config(const char* name, std::string& val);
void begin_setting(bool restore = false);
void config_changed(const char* name, const char* val, size_t bytes, bool extra = false);
void config_changed(int sn, const char* val, size_t bytes, bool extra = false);
void remove_config(const char* name);
void set_value(const char* name, const char* val, size_t bytes, bool extra = false);
bool has_changed(int* items = nullptr);
void end_setting(bool cancel);
int id_from_name(const char* name);
std::string to_text_stream(bool b64 = true, bool with_ver = true);
std::string get_version(void);
std::string get_scheme_name(void);
void set_scheme_name(const char* name);
std::string auto_gen_scheme_name(const char* (__stdcall* lang_trans)(const char*, bool/*true - default language to cur language*/, void*), void* param, bool replace_name = true);
};
class scanner_cfg : public refer
{
// format: in base64
//
// {
// "global": {
// "ver": "4.33",
// "cur": -1
// },
// "scheme_1": sane_config_schm*,
// "scheme_2": sane_config_schm*,
// "scheme_3": sane_config_schm*,
// ...
// }
//
std::string path_;
std::string scanner_name_; // scanner type: HUAGOSCAN G100 - 0100
json *global_; // version, current scheme, ...
json *opt_default_value_;
const char* (__stdcall* lang_trans_)(const char*, bool/*true - default language to cur language*/, void*);
void* lang_param_;
typedef struct _cfg_schm
{
std::string name;
bool should_rename;
sane_config_schm* schm;
struct _cfg_schm()
{
name = "";
should_rename = false;
schm = nullptr;
}
bool operator==(const char* n)
{
return name == n;
}
}CFGSCHM;
std::vector<CFGSCHM> schemes_;
static const char* __stdcall language_trans(const char* in, bool from_def, void* param);
void clear(void);
void init_version(void);
void init_select(void);
const char* trans_language(const char* in, bool from_default);
protected:
~scanner_cfg();
public:
scanner_cfg();
typedef struct _update_func
{
void(* trans_number)(const char* name, std::string& val, void* param);
const char* (* title2name)(const char* title, void* param);
std::string discard_msg; // update failed items ...
void* func_param;
}UDF, *LPUDF;
static bool update(const char* file, LPUDF func);
static std::string global_name_;
static std::string cur_sel_;
static std::string default_setting_name_;
public:
int load_file(const char* file);
int load_mem(const char* mem);
int save(const char* file = nullptr);
void set_language_transform(const char* (__stdcall* lang_trans)(const char*, bool/*true - default language to cur language*/, void*), void* param);
json* get_option_default_value(void);
void get_all_schemes(std::vector<std::string>& schemes); // return all schemes name queue, the first is always be 'Default settings'
sane_config_schm* get_scheme(const char* scheme_name = nullptr/*return current scheme if was null*/); // call sane_config_schm::release() if not use anymore
sane_config_schm* create_empty_scheme(bool selected); // create an empty scheme and add to scheme queue
std::string get_current_scheme_name(void);
std::string to_text_stream(void);
void set_default_value(int id, const char* name, const char* title, void* data, size_t bytes, int type);
int option_value_type(const char* name);
std::string option_title(const char* name);
bool remove_scheme(const char* scheme_name);
void remove_all_schemes(void);
bool select_scheme(const char* scheme_name);
sane_config_schm* copy_scheme(const char* cp_from_name); // for UI setting, call release() if not use anymore
bool add_scheme(sane_config_schm* schm, const char* name = nullptr, bool should_rename = false);
bool rename_scheme(const char* from, const char* to);
};
};