diff --git a/hgsane/CMakeLists.txt b/hgsane/CMakeLists.txt index 2957940..e0fb275 100644 --- a/hgsane/CMakeLists.txt +++ b/hgsane/CMakeLists.txt @@ -11,7 +11,7 @@ add_compile_options(-std=c++11) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIC -O2") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC -O2") aux_source_directory(${PROJECT_SOURCE_DIR} DIR_SRCS) -file(GLOB DIR_HEADS "${PROJECT_SOURCE_DIR}/*.h" "${PROJECT_SOURCE_DIR}/*.hpp") +file(GLOB DIR_HEADS "${PROJECT_SOURCE_DIR}/*.h" "${PROJECT_SOURCE_DIR}/*.hpp" "${PROJECT_SOURCE_DIR}/../*.h" "${PROJECT_SOURCE_DIR}/../*.c" "${PROJECT_SOURCE_DIR}/../*.cpp") set(DIR_SRCS ${DIR_SRCS} ${DIR_HEADS}) add_library(${PROJECT_NAME} SHARED ${DIR_SRCS}) link_directories(${PROJECT_NAME} PRIVATE @@ -26,6 +26,7 @@ target_link_libraries(${PROJECT_NAME} PRIVATE hgdriver target_link_libraries(${PROJECT_NAME} PRIVATE -static-libgcc -static-libstdc++ -Wl,--exclude-libs,ALL -zdefs -Bdirect pthread dl -Wl,-rpath,$ORIGIN) target_include_directories(${PROJECT_NAME} PRIVATE ${PROJECT_SOURCE_DIR} ${PROJECT_SOURCE_DIR}/../sdk/hginclude + ${PROJECT_SOURCE_DIR}/../sdk/json ${PROJECT_SOURCE_DIR}/../../sdk/include ) diff --git a/hgsane/entry.cpp b/hgsane/entry.cpp new file mode 100644 index 0000000..6a6521c --- /dev/null +++ b/hgsane/entry.cpp @@ -0,0 +1,121 @@ +#include "sane_hg_mdw.h" + +#include "../sdk/hginclude/huagaoxxx_warraper_ex.h" // for log-api +#include "../sdk/hginclude/utils.h" // for log-level + +/// +/// SANE API entrance ... +/// +extern "C" { // avoid compiler exporting name in C++ style !!! + const char* inner_sane_err_desc(SANE_Status err) + { + return hg_scanner_err_description(local_utility::sane_statu_2_scanner_err(err)); + } + + SANE_Status inner_sane_init(SANE_Int* version_code, SANE_Auth_Callback authorize) + { + hg_sane_middleware::set_app_callback((void*)authorize); + if (!hg_sane_middleware::instance()->is_ready()) + return (SANE_Status)SCANNER_ERR_LANG_PAK_LOST; + + hg_sane_middleware::get_version(version_code); + + return SANE_STATUS_GOOD; + } + void inner_sane_exit(void) + { + hg_sane_middleware::clear(); + } + SANE_Status inner_sane_get_devices(const SANE_Device*** device_list, SANE_Bool local_only) + { + SANE_Status code = hg_sane_middleware::instance()->get_devices(device_list, local_only); + + return code; + } + SANE_Status inner_sane_open(SANE_String_Const devicename, SANE_Handle* handle) + { + return hg_sane_middleware::instance()->open_device(devicename, handle); + } + void inner_sane_close(SANE_Handle handle) + { + hg_sane_middleware::instance()->close_device(handle); + } + const SANE_Option_Descriptor* + inner_sane_get_option_descriptor(SANE_Handle handle, const void* option) + { + return hg_sane_middleware::instance()->get_option_descriptor(handle, option); + } + SANE_Status inner_sane_control_option(SANE_Handle handle, const void* option, SANE_Action action, void* value, SANE_Int* info) + { + return hg_sane_middleware::instance()->set_option(handle, option, action, value, info); + } + SANE_Status inner_sane_get_parameters(SANE_Handle handle, SANE_Parameters* params) + { + return hg_sane_middleware::instance()->get_image_parameters(handle, params); + } + SANE_Status inner_sane_start(SANE_Handle handle) + { + utils::to_log_with_api(hg_scanner_log_is_enable, hg_scanner_log, LOG_LEVEL_ALL, "sane_start\n"); + + return hg_sane_middleware::instance()->start(handle, NULL); + } + SANE_Status inner_sane_read(SANE_Handle handle, SANE_Byte* data, SANE_Int max_length, SANE_Int* length) + { + if (!length) + length = &max_length; + else + *length = max_length; + + return hg_sane_middleware::instance()->read(handle, data, length); + } + void inner_sane_cancel(SANE_Handle handle) + { + utils::to_log_with_api(hg_scanner_log_is_enable, hg_scanner_log, LOG_LEVEL_ALL, "sane_cancel\n"); + + hg_sane_middleware::instance()->stop(handle); + } + SANE_Status inner_sane_set_io_mode(SANE_Handle handle, SANE_Bool non_blocking) + { + utils::to_log_with_api(hg_scanner_log_is_enable, hg_scanner_log, LOG_LEVEL_ALL, "sane_set_io_mode\n"); + + return non_blocking ? SANE_STATUS_UNSUPPORTED : SANE_STATUS_GOOD; + } + SANE_Status inner_sane_get_select_fd(SANE_Handle handle, SANE_Int* fd) + { + return SANE_STATUS_UNSUPPORTED; + } + SANE_String_Const inner_sane_strstatus(SANE_Status status) + { + // return hg_scanner_err_name(status); + return inner_sane_err_desc(status); + } + + void sanei_debug_msg(int level, int max_level, const char* be, const char* fmt, va_list ap) + { + } + + + + + /// following are extensions for standard ... + SANE_Status inner_sane_init_ex(SANE_Int* version_code, sane_callback cb, void* param) + { + hg_sane_middleware::set_app_callback(cb, param, hg_sane_middleware::APP_CALLBACK_EX); + if (!hg_sane_middleware::instance()->is_ready()) + return (SANE_Status)SCANNER_ERR_LANG_PAK_LOST; + + hg_sane_middleware::get_version(version_code); + + return SANE_STATUS_GOOD; + } + SANE_Status inner_sane_io_control(SANE_Handle h, unsigned long code, void* data, unsigned* len) + { + return hg_sane_middleware::instance()->io_control(h, code, data, len); + } + SANE_Status inner_sane_read_ext(SANE_Img_Ext_Info* ext_info, SANE_Int* len) + { + return SANE_STATUS_UNSUPPORTED; + } +} + + diff --git a/hgsane/json.cpp b/hgsane/json.cpp deleted file mode 100644 index ce981e9..0000000 --- a/hgsane/json.cpp +++ /dev/null @@ -1,364 +0,0 @@ - -#include "json.h" -#include -#include - -#if defined(WIN32) || defined(_WIN64) -#define bzero(b, s) memset(b, 0, s) -#endif - -json::json(char* json_txt) : obj_(0), cur_child_(0) -{ - attach_text(json_txt); -} -json::~json() -{ - clear(); -} - -std::string json::to_string(cJSON* root) -{ - char* txt = cJSON_Print(root); - std::string ret(txt ? txt : ""); - - if (txt) - free(txt); - - return ret; -} -std::string json::get_value_as_string(cJSON* root, bool integer) -{ - std::string ret(""); - - switch (root->type) - { - case cJSON_False: - ret = "false"; - break; - case cJSON_True: - ret = "true"; - break; - case cJSON_NULL: - ret = "null"; - break; - case cJSON_Number: - { - char buf[40]; - if (integer) - sprintf(buf, "%d", root->valueint); - else - sprintf(buf, "%f", root->valuedouble); - ret = buf; - } - break; - case cJSON_String: - if (root->valuestring) - ret = root->valuestring; - break; - default: - ret = json::to_string(root); - break; - } - - return ret; -} - -cJSON* json::find_child(cJSON *parent, const char* child_name) -{ - if (!parent) - return 0; - - cJSON *child = parent->child; - - while (child) - { - if (child->string && strcmp(child->string, child_name) == 0) - break; - - child = child->next; - } - - return child; -} -cJSON* json::find(const char* path) -{ - cJSON *found = obj_; - - if (path && *path) - { - std::string all(path); - char *cur = strtok(&all[0], "/"); - - while (cur) - { - found = find_child(found, cur); - if (!found) - break; - - cur = strtok(0, "/"); - } - } - - return found; -} - -bool json::attach_text(char* json_txt) -{ - clear(); - - obj_ = cJSON_Parse(json_txt); - - return obj_ != 0; -} -bool json::attach_cjson(cJSON* cjson) -{ - clear(); - - if (cjson) - { - std::string txt(json::to_string(cjson)); - if (txt.length()) - obj_ = cJSON_Parse(txt.c_str()); - } - - return obj_ != 0; -} -void json::clear(void) -{ - if (obj_) - { - cJSON_Delete(obj_); - obj_ = 0; - } -} -std::string json::to_string(void) -{ - if (obj_) - return json::to_string(obj_); - else - return ""; -} - -std::string json::key(void) -{ - if (obj_ && obj_->string) - return obj_->string; - else - return ""; -} -bool json::get_value(const char* key, bool& val) -{ - cJSON* obj = find(key); - - if (!obj) - return false; - - if (obj->type == cJSON_True) - val = true; - else if (obj->type == cJSON_False) - val = false; - else - return false; - - return true; -} -bool json::get_value(const char* key, int& val) -{ - cJSON* obj = find(key); - - if (!obj) - return false; - - if (obj->type != cJSON_Number) - return false; - - val = obj->valueint; - - return true; -} -bool json::get_value(const char* key, double& val) -{ - cJSON *obj = find(key); - - if (!obj) - return false; - - if (obj->type != cJSON_Number) - return false; - - val = obj->valuedouble; - - return true; -} -bool json::get_value(const char* key, std::string& val) -{ - cJSON *obj = find(key); - - if (!obj) - return false; - - if (obj->type != cJSON_String) - return false; - - val = obj->valuestring ? obj->valuestring : ""; - - return true; -} -bool json::get_value(const char* key, json*& val) -{ - cJSON *obj = find(key); - - if (!obj) - return false; - - val = new json(); - if (!val->attach_cjson(obj)) - { - delete val; - - return false; - } - - return true; -} -bool json::get_value_as_string(const char* key, std::string& val, bool integer) -{ - cJSON* obj = find(key); - - if (!obj) - return false; - - val = json::get_value_as_string(obj, integer); - - return true; -} -bool json::get_as_array(const char* key, std::vector& val) -{ - cJSON *obj = find(key); - - val.clear(); - if (obj && obj->type == cJSON_Array) - { - cJSON *child = obj->child; - while (child) - { - if (child->type == cJSON_Number) - { - char buf[40]; - sprintf(buf, "%d", child->valueint); - val.push_back(buf); - } - else if (child->type == cJSON_String) - val.push_back(child->valuestring ? child->valuestring : ""); - else - { - char *text = cJSON_Print(child); - val.push_back(text); - free(text); - } - - child = child->next; - } - - return true; - } - - return false; -} - -bool json::first_child(std::string& val) -{ - cur_child_ = obj_->child; - val = ""; - if (cur_child_) - { - val = json::get_value_as_string(cur_child_); - - return true; - } - else - { - return false; - } -} -bool json::next_child(std::string& val) -{ - if (cur_child_) - cur_child_ = cur_child_->next; - - val = ""; - if (cur_child_) - { - val = json::get_value_as_string(cur_child_); - - return true; - } - else - { - return false; - } -} - -bool json::set_value(const char* key, bool val) -{ - cJSON* ele = this->find(key); - - if (!ele) - return false; - - if (ele->type == cJSON_String) - free(ele->valuestring); - - if (val) - ele->type = cJSON_True; - else - ele->type = cJSON_False; - - return true; -} -bool json::set_value(const char* key, int val) -{ - cJSON* ele = this->find(key); - - if (!ele) - return false; - - if (ele->type == cJSON_String) - free(ele->valuestring); - - ele->type = cJSON_Number; - ele->valuedouble = ele->valueint = val; - - return true; -} -bool json::set_value(const char* key, double val) -{ - cJSON* ele = this->find(key); - - if (!ele) - return false; - - if (ele->type == cJSON_String) - free(ele->valuestring); - - ele->type = cJSON_Number; - ele->valuedouble = val; - - return true; -} -bool json::set_value(const char* key, std::string val) -{ - cJSON* ele = this->find(key); - - if (!ele) - return false; - - if (ele->type == cJSON_String) - free(ele->valuestring); - ele->type = cJSON_String; - ele->valuestring = (char*)malloc(val.length() + 4); - bzero(ele->valuestring, val.length() + 4); - strcpy(ele->valuestring, val.c_str()); - - return true; -} diff --git a/hgsane/json.h b/hgsane/json.h deleted file mode 100644 index 958ab50..0000000 --- a/hgsane/json.h +++ /dev/null @@ -1,50 +0,0 @@ -#pragma once - -#if defined(WIN32) || defined(_WIN64) -#include -#endif - -#include "cJSON.h" -#include -#include - -class json -{ - cJSON *obj_; - cJSON* cur_child_; - - cJSON* find_child(cJSON *parent, const char* child_name); - cJSON* find(const char* path); - -public: - json(char* json_txt = 0); - ~json(); - - static std::string to_string(cJSON* root); - static std::string get_value_as_string(cJSON* root, bool integer = false); - -public: - bool attach_text(char* json_txt); - bool attach_cjson(cJSON* cjson); - void clear(void); - std::string to_string(void); - - // can be path: child/value ... - std::string key(void); - 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); // caller shoud call "delete" to free the returned object !!! - bool get_value_as_string(const char* key, std::string& val, bool integer); - bool get_as_array(const char* key, std::vector& val); - - bool first_child(std::string& val); - bool next_child(std::string& val); - - 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, std::string val); - -}; diff --git a/hgsane/sane_hg_mdw.cpp b/hgsane/sane_hg_mdw.cpp index bc69122..67a0405 100644 --- a/hgsane/sane_hg_mdw.cpp +++ b/hgsane/sane_hg_mdw.cpp @@ -1,6 +1,7 @@ #include "sane_hg_mdw.h" -#include "json.h" +#include "../sdk/json/gb_json.h" + #include #include #include @@ -35,9 +36,6 @@ #define iconv_t void* #endif -static std::string g_sane_path(""); -static std::string g_sane_name(GET_BACKEND_NAME); - namespace local_utility { ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -124,7 +122,7 @@ namespace local_utility ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - // json parser ... + // gb_json parser ... bool is_space(char ch) { return ch == ' ' || ch == '\t'; @@ -433,9 +431,9 @@ namespace local_utility } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - static sane_callback cb_ui_ = NULL; - static void* cb_ui_parm_ = NULL; - static SANE_Auth_Callback cb_auth_ = NULL; + static sane_callback cb_ui_ = nullptr; + static void* cb_ui_parm_ = nullptr; + static SANE_Auth_Callback cb_auth_ = nullptr; static std::mutex cb_lock_; static std::string sane_event(SANE_Event ev) @@ -461,9 +459,9 @@ namespace local_utility } int ui_cb(scanner_handle dev, int code, void* data, unsigned int* len, void* unused) { - sane_callback cb_ui = NULL; - void* cb_ui_parm = NULL; - SANE_Auth_Callback cb_auth = NULL; + sane_callback cb_ui = nullptr; + void* cb_ui_parm = nullptr; + SANE_Auth_Callback cb_auth = nullptr; { std::lock_guard lck(cb_lock_); @@ -477,7 +475,7 @@ namespace local_utility SANE_Handle h = hg_sane_middleware::scanner_handle_to_sane(dev); - // local_utility::to_log(LOG_LEVEL_ALL, "sane callback invoked of event %s\n", sane_event((SANE_Event)code).c_str()); + // utils::to_log_with_api(hg_scanner_log_is_enable, hg_scanner_log, LOG_LEVEL_ALL, "sane callback invoked of event %s\n", sane_event((SANE_Event)code).c_str()); if (cb_ui) { @@ -506,9 +504,9 @@ namespace local_utility void stop_work(void) { std::lock_guard lck(cb_lock_); - cb_ui_ = NULL; - cb_ui_parm_ = NULL; - cb_auth_ = NULL; + cb_ui_ = nullptr; + cb_ui_parm_ = nullptr; + cb_auth_ = nullptr; } static void trans_language_if_was_word_id(std::string& val) @@ -538,8 +536,8 @@ namespace local_utility ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -hg_sane_middleware* hg_sane_middleware::inst_ = NULL; -const SANE_Device** hg_sane_middleware::dev_list_ = NULL; +hg_sane_middleware* hg_sane_middleware::inst_ = nullptr; +const SANE_Device** hg_sane_middleware::dev_list_ = nullptr; hg_sane_middleware::hg_sane_middleware(void) : opt_0_(nullptr), init_ok_(false) { @@ -548,20 +546,19 @@ hg_sane_middleware::hg_sane_middleware(void) : opt_0_(nullptr), init_ok_(false) init_ok_ = true; sprintf(sane_ver, "%u.%u.%u", SANE_CURRENT_MAJOR, SANE_CURRENT_MINOR, VERSION_BUILD); +#if defined(WIN32) + hg_scanner_set_sane_info("sane", sane_ver); +#else signal(SIGUSR1, &hg_sane_middleware::device_pnp); - hg_scanner_set_sane_info(g_sane_name.c_str(), sane_ver); - hg_scanner_initialize(local_utility::ui_cb, NULL); - register_language_changed_notify(&hg_sane_middleware::language_changed, true); + hg_scanner_set_sane_info(GET_BACKEND_NAME, sane_ver); +#endif + hg_scanner_initialize(local_utility::ui_cb, nullptr); + register_language_changed_notify(&hg_sane_middleware::language_changed, true); -#if !defined(WIN32) && !defined(_WIN64) char path[512] = { 0 }; size_t pos = 0; - g_sane_path = local_utility::get_module_full_path((std::string(GET_BACKEND_NAME) + ".so").c_str()); - pos = g_sane_path.rfind('/'); - if (pos++ != std::string::npos) - g_sane_path.erase(pos); -#endif + std::this_thread::sleep_for(std::chrono::milliseconds(500)); // wait for device OK } hg_sane_middleware::~hg_sane_middleware() { @@ -584,7 +581,7 @@ void hg_sane_middleware::language_changed(int cp, void* param) // hg_sane_middleware::free_device_inst(v, false); // // long count = 0; - // hg_scanner_get_parameter(v->dev, nullptr, NULL, &count); + // hg_scanner_get_parameter(v->dev, nullptr, nullptr, &count); // for (long ind = 1; ind < count; ++ind) // hg_sane_middleware::instance()->get_option_descriptor(hg_sane_middleware::scanner_handle_to_sane(v->dev), (void*)ind); //} @@ -592,8 +589,8 @@ void hg_sane_middleware::language_changed(int cp, void* param) const SANE_Device** hg_sane_middleware::to_sane_device(ScannerInfo* hgscanner, int count) { // 将多级指针安排在一个连续的内存空间存放 - SANE_Device** ret = NULL, * dev = NULL; - SANE_String val = NULL; + SANE_Device** ret = nullptr, * dev = nullptr; + SANE_String val = nullptr; unsigned long bytes = (count + 1) * (sizeof(SANE_Device) + sizeof(SANE_Device*)), total = 0; // calculate space ... @@ -609,7 +606,7 @@ const SANE_Device** hg_sane_middleware::to_sane_device(ScannerInfo* hgscanner, i dev = (SANE_Device*)local_utility::acquire_memory(bytes, "hg_sane_middleware::to_sane_device"); total = bytes; if (!dev) - return NULL; + return nullptr; memset(dev, 0, bytes); ret = (SANE_Device**)dev; @@ -631,7 +628,7 @@ const SANE_Device** hg_sane_middleware::to_sane_device(ScannerInfo* hgscanner, i COPY_DEVICE_MEMBER(type); } - //local_utility::to_log(LOG_LEVEL_ALL, "Memory usage: %u / %u\n", val - (char*)ret, total); + //utils::to_log_with_api(hg_scanner_log_is_enable, hg_scanner_log, LOG_LEVEL_ALL, "Memory usage: %u / %u\n", val - (char*)ret, total); return (const SANE_Device**)ret; } @@ -646,7 +643,7 @@ void hg_sane_middleware::free_sane_device(SANE_Device** dev) } void hg_sane_middleware::device_pnp(int sig) { - local_utility::to_log(LOG_LEVEL_DEBUG, "Device list changed (%d)...", sig); + utils::to_log_with_api(hg_scanner_log_is_enable, hg_scanner_log, LOG_LEVEL_DEBUG, "Device list changed (%d)...", sig); } SANE_Fixed hg_sane_middleware::double_2_sane_fixed(double v) { @@ -701,6 +698,45 @@ std::string hg_sane_middleware::option_value_2_string(SANE_Value_Type type, void return ret; } +std::string hg_sane_middleware::string_value_from_json(gb_json* jsn, bool curval) +{ + std::string type(""), key(curval ? "cur" : "default"); + + if (jsn->get_value("type", type)) + { + if (type == "bool") + { + bool val = true; + jsn->get_value(key.c_str(), val); + + return val ? "true" : "false"; + } + else if (type == "int") + { + int val = 0; + jsn->get_value(key.c_str(), val); + + return std::to_string(val); + } + else if (type == "float") + { + double val = 0; + jsn->get_value(key.c_str(), val); + + return std::to_string(val); + } + else if (type == "string") + { + std::string val(""); + jsn->get_value(key.c_str(), val); + + return std::move(val); + } + + } + + return ""; +} scanner_handle hg_sane_middleware::sane_handle_to_scanner(SANE_Handle h) { if (!h) @@ -863,7 +899,7 @@ SANE_Option_Descriptor* hg_sane_middleware::number_option_to_SANE_descriptor(con for (size_t i = 0; i < values.size(); ++i) val[i] = values[i]; } - //local_utility::to_log(LOG_LEVEL_ALL, "Memory usage: %u/%u\n", str - (char*)sod, bytes); + //utils::to_log_with_api(hg_scanner_log_is_enable, hg_scanner_log, LOG_LEVEL_ALL, "Memory usage: %u/%u\n", str - (char*)sod, bytes); return sod; } @@ -891,7 +927,7 @@ SANE_Option_Descriptor* hg_sane_middleware::number_option_to_SANE_descriptor(con return sod; } -std::string hg_sane_middleware::get_string_in_json(json* jsn, const char* key, bool* has) +std::string hg_sane_middleware::get_string_in_json(gb_json* jsn, const char* key, bool* has) { std::string str(""); int id = -1; @@ -915,9 +951,16 @@ std::string hg_sane_middleware::get_string_in_json(json* jsn, const char* key, b return std::move(str); } -std::string hg_sane_middleware::sane_path(void) +void hg_sane_middleware::set_app_callback(void* cb, void* param, int type) { - return g_sane_path; + if (type == APP_CALLBACK_EX) + local_utility::set_callback((sane_callback)cb, param); + else + local_utility::cb_auth_ = (SANE_Auth_Callback)cb; +} +void hg_sane_middleware::get_version(SANE_Int* ver) +{ + local_utility::get_version(ver); } hg_sane_middleware* hg_sane_middleware::instance(void) { @@ -936,7 +979,7 @@ void hg_sane_middleware::clear(void) if (hg_sane_middleware::inst_) { delete hg_sane_middleware::inst_; - hg_sane_middleware::inst_ = NULL; + hg_sane_middleware::inst_ = nullptr; } } @@ -951,7 +994,7 @@ void hg_sane_middleware::reload_options(scanner_handle dev) long count = 0; hg_sane_middleware::free_device_inst(v, false); - hg_scanner_get_parameter(v->dev, nullptr, NULL, &count); + hg_scanner_get_parameter(v->dev, nullptr, nullptr, &count); for (long ind = 1; ind < count; ++ind) { get_option_descriptor(hg_sane_middleware::scanner_handle_to_sane(v->dev), (void*)ind); @@ -1002,13 +1045,13 @@ void hg_sane_middleware::set_status_by_depends(scanner_handle hdev, SLAVEOP& so, } SANE_Status hg_sane_middleware::open(SANE_String_Const devicename, SANE_Handle* handle, const char* name, const char* pwd, const char* method, char* rsc) { - scanner_handle h = NULL; + scanner_handle h = nullptr; scanner_err err = SCANNER_ERR_OK; - if (handle == NULL) + if (handle == nullptr) return SANE_STATUS_INVAL; - err = hg_scanner_open(&h, devicename, false, NULL, NULL, NULL, rsc); + err = hg_scanner_open(&h, devicename, false, nullptr, nullptr, nullptr, rsc); if (err == SCANNER_ERR_OK) { LPDEVINST inst = new DEVINST; @@ -1021,7 +1064,7 @@ SANE_Status hg_sane_middleware::open(SANE_String_Const devicename, SANE_Handle* if (!local_utility::cb_ui_) { long count = 0; - hg_scanner_get_parameter(h, 0, NULL, &count); + hg_scanner_get_parameter(h, 0, nullptr, &count); inst->std_opt = new sane_std_opts(count); } @@ -1034,7 +1077,7 @@ SANE_Status hg_sane_middleware::open(SANE_String_Const devicename, SANE_Handle* else return (SANE_Status)err; // SANE_STATUS_UNSUPPORTED; } -SANE_Option_Descriptor* hg_sane_middleware::from_json(scanner_handle h, const std::string& name, json* jsn) +SANE_Option_Descriptor* hg_sane_middleware::from_json(scanner_handle h, const std::string& name, gb_json* jsn) { std::string title(hg_sane_middleware::get_string_in_json(jsn, "title")), desc(hg_sane_middleware::get_string_in_json(jsn, "desc")), @@ -1045,31 +1088,31 @@ SANE_Option_Descriptor* hg_sane_middleware::from_json(scanner_handle h, const st int opt_val_size = 0; if (!jsn->get_value("type", val)) - return NULL; + return nullptr; - SANE_Option_Descriptor* ret = NULL; + SANE_Option_Descriptor* ret = nullptr; if (val == "string") { - json* range = NULL; + gb_json* range = nullptr; std::vector constraints; jsn->get_value("range", range); if (range) { - if (range->first_child(val)) + gb_json* child = range->first_child(); + while(child) { - local_utility::trans_language_if_was_word_id(val); - constraints.push_back(val); - opt_val_size = val.length(); - while (range->next_child(val)) + if (child->value(val)) { local_utility::trans_language_if_was_word_id(val); constraints.push_back(val); if (opt_val_size < val.length()) opt_val_size = val.length(); } + child->release(); + child = range->next_child(); } - delete range; + range->release(); } ret = hg_sane_middleware::string_option_to_SANE_descriptor(name.c_str(), title.c_str(), desc.c_str() @@ -1077,7 +1120,7 @@ SANE_Option_Descriptor* hg_sane_middleware::from_json(scanner_handle h, const st } else if (val == "int" || val == "float") { - json* range = NULL; + gb_json* range = nullptr, * child = nullptr; jsn->get_value("range", range); if (range) @@ -1093,20 +1136,21 @@ SANE_Option_Descriptor* hg_sane_middleware::from_json(scanner_handle h, const st lower = l; upper = u; step = s; - local_utility::to_log(LOG_LEVEL_DEBUG, "%s range: [%d, +%d, %d]\n", name.c_str(), l, s, u); + utils::to_log_with_api(hg_scanner_log_is_enable, hg_scanner_log, LOG_LEVEL_DEBUG, "%s range: [%d, +%d, %d]\n", name.c_str(), l, s, u); ret = hg_sane_middleware::number_option_to_SANE_descriptor(name.c_str(), title.c_str(), desc.c_str() , false, &lower, &upper, &step); } else { std::vector constraints; - if (range->first_child(val)) + child = range->first_child(); + while(child) { - constraints.push_back(atoi(val.c_str())); - while (range->next_child(val)) - { - constraints.push_back(atoi(val.c_str())); - } + int v = 0; + if(child->value(v)) + constraints.push_back(v); + child->release(); + child = range->next_child(); } ret = hg_sane_middleware::number_option_to_SANE_descriptor(name.c_str(), title.c_str(), desc.c_str() , constraints); @@ -1119,49 +1163,50 @@ SANE_Option_Descriptor* hg_sane_middleware::from_json(scanner_handle h, const st range->get_value("max", upper); step = (upper - lower) / 10.0f; range->get_value("step", step); - local_utility::to_log(LOG_LEVEL_DEBUG, "%s range: (%f, +%f, %f)\n", name.c_str(), lower, step, upper); + utils::to_log_with_api(hg_scanner_log_is_enable, hg_scanner_log, LOG_LEVEL_DEBUG, "%s range: (%f, +%f, %f)\n", name.c_str(), lower, step, upper); ret = hg_sane_middleware::number_option_to_SANE_descriptor(name.c_str(), title.c_str(), desc.c_str() , true, &lower, &upper, &step); } else { std::vector constraints; - if (range->first_child(val)) + child = range->first_child(); + while (child) { - constraints.push_back(atof(val.c_str())); - while (range->next_child(val)) - { - constraints.push_back(atof(val.c_str())); - } + double v = .0f; + if (child->value(v)) + constraints.push_back(v); + child->release(); + child = range->next_child(); } ret = hg_sane_middleware::number_option_to_SANE_descriptor(name.c_str(), title.c_str(), desc.c_str() , constraints); } } - delete range; + range->release(); } else { ret = hg_sane_middleware::number_option_to_SANE_descriptor(name.c_str(), title.c_str(), desc.c_str() - , false, NULL, NULL, NULL); + , false, nullptr, nullptr, nullptr); } } else if (val == "bool") { ret = hg_sane_middleware::number_option_to_SANE_descriptor(name.c_str(), title.c_str(), desc.c_str() - , false, NULL, NULL, NULL); + , false, nullptr, nullptr, nullptr); ret->type = SANE_TYPE_BOOL; } else if (val == "button") { ret = hg_sane_middleware::number_option_to_SANE_descriptor(name.c_str(), title.c_str(), desc.c_str() - , false, NULL, NULL, NULL); + , false, nullptr, nullptr, nullptr); ret->type = SANE_TYPE_BUTTON; } else if (val == "group") { ret = hg_sane_middleware::number_option_to_SANE_descriptor(name.c_str(), title.c_str(), desc.c_str() - , false, NULL, NULL, NULL); + , false, nullptr, nullptr, nullptr); ret->type = SANE_TYPE_GROUP; } @@ -1175,7 +1220,7 @@ SANE_Option_Descriptor* hg_sane_middleware::from_json(scanner_handle h, const st if (bytes < opt_val_size) { opt_val_size = ALIGN_INT(opt_val_size + 4); - local_utility::to_log(LOG_LEVEL_DEBUG, "Resize size of '%s' from %d to %d\n", name.c_str(), bytes, opt_val_size); + utils::to_log_with_api(hg_scanner_log_is_enable, hg_scanner_log, LOG_LEVEL_DEBUG, "Resize size of '%s' from %d to %d\n", name.c_str(), bytes, opt_val_size); bytes = opt_val_size; } ret->size = bytes; @@ -1208,7 +1253,7 @@ SANE_Option_Descriptor* hg_sane_middleware::from_json(scanner_handle h, const st // ret->cap |= SANE_CAP_INACTIVE; // 关联? - json* depend = NULL; + gb_json* depend = nullptr; SLAVEOP so; if (jsn->get_value("depend_or", depend)) { @@ -1226,31 +1271,9 @@ SANE_Option_Descriptor* hg_sane_middleware::from_json(scanner_handle h, const st so.enable_now = (ret->cap & SANE_CAP_INACTIVE) != SANE_CAP_INACTIVE; so.name = name; - // initializing status ... move to set_status_by_depends (2023-06-21) - //if (so.master.size()) - //{ - // //std::string master(get_option_json(h, (void *)so.master[0].name.c_str())); - // //json* m = new json(); - // //if (m->attach_text(&master[0])) - // //{ - // // bool integer = false, str = false; - // - // // master = ""; - // // m->get_value("type", master); - // // integer = master == "int"; - // // str = master == "string"; - // // master = ""; - // // m->get_value_as_string("cur", master, integer); - // // local_utility::trans_language_if_was_word_id(val); - // so.enable_now = so.is_enable(h, so.master, (*it)->cur_vals); - // if (!so.enable_now) - // ret->cap |= SANE_CAP_INACTIVE; - // //} - // //delete m; - //} (*it)->slaves.push_back(so); } - delete depend; + depend->release(); } } @@ -1283,7 +1306,7 @@ scanner_handle hg_sane_middleware::find_openning_device(SANE_Handle h, bool rmv, std::vector::iterator it = find_openning_device_in_que(handle); if (it == openning_.end()) - handle = NULL; + handle = nullptr; else { if (dev) @@ -1300,7 +1323,7 @@ scanner_handle hg_sane_middleware::find_openning_device(SANE_Handle h, bool rmv, } std::string hg_sane_middleware::get_option_json(scanner_handle handle, void *opt, std::string* key, SANE_Int* id) { - char* json_txt = NULL; + char* json_txt = nullptr; long length = 0; scanner_err err = hg_scanner_get_parameter(handle, (const char*)opt, json_txt, &length); std::string ret(""); @@ -1392,7 +1415,7 @@ SANE_Option_Descriptor* hg_sane_middleware::find_stored_descriptor(scanner_handl } } - return NULL; + return nullptr; } void hg_sane_middleware::reload_current_value(scanner_handle handle, std::vector* changed) @@ -1402,19 +1425,19 @@ void hg_sane_middleware::reload_current_value(scanner_handle handle, std::vector if (changed) changed->clear(); - hg_scanner_get_parameter(handle, 0, NULL, &count); + hg_scanner_get_parameter(handle, 0, nullptr, &count); for (int i = 1; i < count; ++i) { std::string key(""), val(get_option_json(handle, (void *)i, &key)); - json* jsn = new json(); + gb_json* jsn = new gb_json(); if (jsn->attach_text(&val[0]) && jsn->get_value("type", val)) { if (refresh_current_value(*it, key.c_str(), jsn)) changed->push_back(key); } - delete jsn; + jsn->release(); } } bool hg_sane_middleware::get_current_value(scanner_handle handle, const void* option, void(*setv)(void*, size_t, void*), void* value, SANE_Value_Type* type) @@ -1447,7 +1470,7 @@ bool hg_sane_middleware::get_current_value(scanner_handle handle, const void* op std::string name(""), val(get_option_json(handle, (void *)option, &name)); - json* jsn = new json(); + gb_json* jsn = new gb_json(); int estimate = 20; bool ret = false; @@ -1505,10 +1528,10 @@ bool hg_sane_middleware::get_current_value(scanner_handle handle, const void* op if (setv == &hg_sane_middleware::set_value_to_new) value = *(void**)value; - local_utility::to_log(LOG_LEVEL_ALL, "<--Get option(%d - %s) value: %s\n", option, val.c_str(), hg_sane_middleware::option_value_2_string(t, value).c_str()); + utils::to_log_with_api(hg_scanner_log_is_enable, hg_scanner_log, LOG_LEVEL_ALL, "<--Get option(%d - %s) value: %s\n", option, val.c_str(), hg_sane_middleware::option_value_2_string(t, value).c_str()); } - delete jsn; + jsn->release(); return ret; } @@ -1516,7 +1539,7 @@ void* hg_sane_middleware::get_default_value(scanner_handle handle, const void* o { std::string val(get_option_json(handle, (void *)option)); void* data = nullptr; - json* jsn = new json(); + gb_json* jsn = new gb_json(); if (jsn->attach_text(&val[0]) && jsn->get_value("type", val)) @@ -1542,7 +1565,7 @@ void* hg_sane_middleware::get_default_value(scanner_handle handle, const void* o *bytes = sizeof(SANE_Bool); if (log) { - local_utility::to_log(LOG_LEVEL_DEBUG, "option %d(%s) default value is: %s\n", option, title.c_str(), v ? "true" : "false"); + utils::to_log_with_api(hg_scanner_log_is_enable, hg_scanner_log, LOG_LEVEL_DEBUG, "option %d(%s) default value is: %s\n", option, title.c_str(), v ? "true" : "false"); } } else if (val == "int") @@ -1556,7 +1579,7 @@ void* hg_sane_middleware::get_default_value(scanner_handle handle, const void* o *bytes = sizeof(v); if (log) { - local_utility::to_log(LOG_LEVEL_DEBUG, "option %d(%s) default value is: %d\n", option, title.c_str(), v); + utils::to_log_with_api(hg_scanner_log_is_enable, hg_scanner_log, LOG_LEVEL_DEBUG, "option %d(%s) default value is: %d\n", option, title.c_str(), v); } } else if (val == "float") @@ -1572,7 +1595,7 @@ void* hg_sane_middleware::get_default_value(scanner_handle handle, const void* o memcpy(data, &sd, sizeof(sd)); if (log) { - local_utility::to_log(LOG_LEVEL_DEBUG, "option %d(%s) default value is: %f\n", option, title.c_str(), v); + utils::to_log_with_api(hg_scanner_log_is_enable, hg_scanner_log, LOG_LEVEL_DEBUG, "option %d(%s) default value is: %f\n", option, title.c_str(), v); } } else if (val == "string") @@ -1590,15 +1613,15 @@ void* hg_sane_middleware::get_default_value(scanner_handle handle, const void* o *bytes = val.length() + 1; if (log) { - local_utility::to_log(LOG_LEVEL_DEBUG, "option %d(%s) default value is: %s\n", option, title.c_str(), (char*)data); + utils::to_log_with_api(hg_scanner_log_is_enable, hg_scanner_log, LOG_LEVEL_DEBUG, "option %d(%s) default value is: %s\n", option, title.c_str(), (char*)data); } } else { - local_utility::to_log(LOG_LEVEL_DEBUG, "option %d(%s) is '%s' and no value action.\n", option, title.c_str(), val.c_str()); + utils::to_log_with_api(hg_scanner_log_is_enable, hg_scanner_log, LOG_LEVEL_DEBUG, "option %d(%s) is '%s' and no value action.\n", option, title.c_str(), val.c_str()); } } - delete jsn; + jsn->release(); if (!data) { @@ -1618,7 +1641,7 @@ SANE_Status hg_sane_middleware::get_devices(const SANE_Device*** device_list, SA if (!device_list) return SANE_STATUS_INVAL; - ScannerInfo * dev = NULL; + ScannerInfo * dev = nullptr; long count = 0; scanner_err hgerr = hg_scanner_enum(dev, &count, local_only); SANE_Status ret = SANE_STATUS_GOOD; @@ -1631,7 +1654,7 @@ SANE_Status hg_sane_middleware::get_devices(const SANE_Device*** device_list, SA if (hgerr != SCANNER_ERR_OK) { local_utility::free_memory(dev); - dev = NULL; + dev = nullptr; } } @@ -1656,13 +1679,13 @@ SANE_Status hg_sane_middleware::open_device(SANE_String_Const devicename, SANE_H SANE_Status ret = SANE_STATUS_GOOD; bzero(rsc, sizeof(rsc)); - ret = open(devicename, handle, NULL, NULL, NULL, rsc); + ret = open(devicename, handle, nullptr, nullptr, nullptr, rsc); if (ret == SANE_STATUS_ACCESS_DENIED && rsc[0]) { SANEAUTH auth; bzero(&auth, sizeof(auth)); auth.resource = rsc; - if (local_utility::ui_cb(NULL, SANE_EVENT_NEED_AUTH, (void*)&auth, NULL, NULL)) + if (local_utility::ui_cb(nullptr, SANE_EVENT_NEED_AUTH, (void*)&auth, nullptr, nullptr)) { return SANE_STATUS_CANCELLED; } @@ -1755,7 +1778,7 @@ SANE_Option_Descriptor* hg_sane_middleware::get_option_descriptor(SANE_Handle h, opt_0_->type = SANE_TYPE_INT; opt_0_->size = sizeof(SANE_TYPE_INT); } - local_utility::to_log(LOG_LEVEL_DEBUG, "get_option_descriptor(0)\n"); + utils::to_log_with_api(hg_scanner_log_is_enable, hg_scanner_log, LOG_LEVEL_DEBUG, "get_option_descriptor(0)\n"); return opt_0_; } @@ -1767,7 +1790,7 @@ SANE_Option_Descriptor* hg_sane_middleware::get_option_descriptor(SANE_Handle h, if (json_txt.length()) { - json* jsn = new json(); + gb_json* jsn = new gb_json(); if (jsn->attach_text(&json_txt[0])) { ret = from_json(handle, key, jsn); @@ -1791,7 +1814,7 @@ SANE_Option_Descriptor* hg_sane_middleware::get_option_descriptor(SANE_Handle h, refresh_current_value(*it, ret->name, jsn); } } - delete jsn; + jsn->release(); } if(!ret && (*it)->std_opt) ret = (*it)->std_opt->get_option(id); @@ -1835,10 +1858,10 @@ SANE_Status hg_sane_middleware::set_option(SANE_Handle h, const void* option, SA if (option == 0) { long count = 0; - hg_scanner_get_parameter(handle, (const char*)option, NULL, &count); + hg_scanner_get_parameter(handle, (const char*)option, nullptr, &count); *((SANE_Int*)value) = count; ret = SANE_STATUS_GOOD; - local_utility::to_log(LOG_LEVEL_WARNING, "get option count = %d.\n", count); + utils::to_log_with_api(hg_scanner_log_is_enable, hg_scanner_log, LOG_LEVEL_WARNING, "get option count = %d.\n", count); } else { @@ -1908,7 +1931,7 @@ SANE_Status hg_sane_middleware::set_option(SANE_Handle h, const void* option, SA if (action == SANE_ACTION_SET_AUTO && desc && desc->type != SANE_TYPE_BUTTON && desc->type != SANE_TYPE_GROUP) // we assume the driver can set the option properbly, and no work to do { - local_utility::to_log(LOG_LEVEL_WARNING, "Option %d(%s) call SANE_ACTION_SET_AUTO, we set default value.\n", option, desc->title); + utils::to_log_with_api(hg_scanner_log_is_enable, hg_scanner_log, LOG_LEVEL_WARNING, "Option %d(%s) call SANE_ACTION_SET_AUTO, we set default value.\n", option, desc->title); int len = 0; bool can_auto = true; @@ -1939,7 +1962,7 @@ SANE_Status hg_sane_middleware::set_option(SANE_Handle h, const void* option, SA SANE_Option_Descriptor* known = dev->std_opt->get_option(id); unsigned char* cont = (unsigned char*)value; prev = hg_sane_middleware::option_value_2_string(known->type, value); - local_utility::to_log(LOG_LEVEL_DEBUG, "$First 4-bytes of origin value for option %d is: %02X%02X%02X%02X\n", option, cont[0], cont[1], cont[2], cont[3]); + utils::to_log_with_api(hg_scanner_log_is_enable, hg_scanner_log, LOG_LEVEL_DEBUG, "$First 4-bytes of origin value for option %d is: %02X%02X%02X%02X\n", option, cont[0], cont[1], cont[2], cont[3]); err = dev->std_opt->set_value(handle, id, value); v = hg_sane_middleware::option_value_2_string(known->type, value); } @@ -1956,14 +1979,14 @@ SANE_Status hg_sane_middleware::set_option(SANE_Handle h, const void* option, SA return local_utility::scanner_err_2_sane_statu(hg_scanner_set_parameter(handle, name.c_str(), value, 0)); } - local_utility::to_log(LOG_LEVEL_FATAL, "Option descriptor %d not found.\n", option); + utils::to_log_with_api(hg_scanner_log_is_enable, hg_scanner_log, LOG_LEVEL_FATAL, "Option descriptor %d not found.\n", option); return SANE_STATUS_UNSUPPORTED; } else if (!value && desc->type != SANE_TYPE_BUTTON) { //if (action == SANE_ACTION_SET_AUTO) // we assume the driver can set the option properbly, and no work to do //{ - // local_utility::to_log(LOG_LEVEL_WARNING, "Option %d(%s) call SANE_ACTION_SET_AUTO, we set default value.\n", option, desc->title); + // utils::to_log_with_api(hg_scanner_log_is_enable, hg_scanner_log, LOG_LEVEL_WARNING, "Option %d(%s) call SANE_ACTION_SET_AUTO, we set default value.\n", option, desc->title); // // value = get_default_value(handle, option); // if (!value) @@ -1972,7 +1995,7 @@ SANE_Status hg_sane_middleware::set_option(SANE_Handle h, const void* option, SA //} //else { - local_utility::to_log(LOG_LEVEL_WARNING, "Option descriptor %d(%s) need a value!.\n", option, desc->title); + utils::to_log_with_api(hg_scanner_log_is_enable, hg_scanner_log, LOG_LEVEL_WARNING, "Option descriptor %d(%s) need a value!.\n", option, desc->title); return SANE_STATUS_INVAL; } @@ -2012,11 +2035,11 @@ SANE_Status hg_sane_middleware::set_option(SANE_Handle h, const void* option, SA if (prev == v) { - local_utility::to_log(LOG_LEVEL_ALL, "-->Set option(%d - %s) value: %s\n", option, desc_title.c_str(), v.c_str()); + utils::to_log_with_api(hg_scanner_log_is_enable, hg_scanner_log, LOG_LEVEL_ALL, "-->Set option(%d - %s) value: %s\n", option, desc_title.c_str(), v.c_str()); } else { - local_utility::to_log(LOG_LEVEL_ALL, "-->Set option(%d - %s) value: %s(Applied: %s)\n", option, desc_title.c_str(), prev.c_str(), v.c_str()); + utils::to_log_with_api(hg_scanner_log_is_enable, hg_scanner_log, LOG_LEVEL_ALL, "-->Set option(%d - %s) value: %s(Applied: %s)\n", option, desc_title.c_str(), prev.c_str(), v.c_str()); } if (err == SCANNER_ERR_OK) @@ -2029,7 +2052,7 @@ SANE_Status hg_sane_middleware::set_option(SANE_Handle h, const void* option, SA } else if (err == SCANNER_ERR_CONFIGURATION_CHANGED) { - local_utility::to_log(LOG_LEVEL_DEBUG, "the setting '%s' affects other options value, RELOAD ...\n", desc_title.c_str()); + utils::to_log_with_api(hg_scanner_log_is_enable, hg_scanner_log, LOG_LEVEL_DEBUG, "the setting '%s' affects other options value, RELOAD ...\n", desc_title.c_str()); //on_SCANNER_ERR_CONFIGURATION_CHANGED(dev); if(dev->fixed_id.count(SANE_OPT_ID_LANGUAGE) == 0 || dev->fixed_id[SANE_OPT_ID_LANGUAGE] != id) // language reload by callback already reload_options(handle); @@ -2037,12 +2060,12 @@ SANE_Status hg_sane_middleware::set_option(SANE_Handle h, const void* option, SA } else if(err == SCANNER_ERR_RELOAD_IMAGE_PARAM) { - local_utility::to_log(LOG_LEVEL_DEBUG, "the setting '%s' affects image parameter, APP should re-get ...\n", desc_title.c_str()); + utils::to_log_with_api(hg_scanner_log_is_enable, hg_scanner_log, LOG_LEVEL_DEBUG, "the setting '%s' affects image parameter, APP should re-get ...\n", desc_title.c_str()); err = (scanner_err)SANE_INFO_RELOAD_PARAMS; } else if(err == SCANNER_ERR_RELOAD_OPT_PARAM) { - local_utility::to_log(LOG_LEVEL_DEBUG, "the setting '%s' affects image parameter and options, APP should re-get image info and reload options...\n", desc_title.c_str()); + utils::to_log_with_api(hg_scanner_log_is_enable, hg_scanner_log, LOG_LEVEL_DEBUG, "the setting '%s' affects image parameter and options, APP should re-get image info and reload options...\n", desc_title.c_str()); //on_SCANNER_ERR_CONFIGURATION_CHANGED(dev); if (dev->fixed_id.count(SANE_OPT_ID_LANGUAGE) == 0 || dev->fixed_id[SANE_OPT_ID_LANGUAGE] != id) // language reload by callback already reload_options(handle); @@ -2084,7 +2107,7 @@ void* hg_sane_middleware::get_cur_value(SANE_Handle handle, void* option, SANE_V void* buf = nullptr; if (!h) - return NULL; + return nullptr; get_current_value(h, option, &hg_sane_middleware::set_value_to_new, &buf, type); @@ -2095,7 +2118,7 @@ void* hg_sane_middleware::get_def_value(SANE_Handle handle, void* option, int* b scanner_handle h = find_openning_device(handle); if (!h) - return NULL; + return nullptr; return get_default_value(h, option, bytes, log); } @@ -2113,7 +2136,7 @@ SANE_Status hg_sane_middleware::io_control(SANE_Handle h, unsigned long code, vo if (ret == SCANNER_ERR_CONFIGURATION_CHANGED) { int nc = code; - local_utility::to_log(LOG_LEVEL_DEBUG, "the setting '0x%08x' affects other options value, RELOAD ...\n", nc); + utils::to_log_with_api(hg_scanner_log_is_enable, hg_scanner_log, LOG_LEVEL_DEBUG, "the setting '0x%08x' affects other options value, RELOAD ...\n", nc); on_SCANNER_ERR_CONFIGURATION_CHANGED(dev); } @@ -2169,7 +2192,7 @@ bool hg_sane_middleware::is_enable_and(scanner_handle hdev, const std::vector::iterator it = std::find(curvals.begin(), curvals.end(), master[i].name); if (it == curvals.end()) { - local_utility::to_log(LOG_LEVEL_WARNING, "option %s's current value is not found, other options depend it maybe in wrong status.\n", master[i].name.c_str()); + utils::to_log_with_api(hg_scanner_log_is_enable, hg_scanner_log, LOG_LEVEL_WARNING, "option %s's current value is not found, other options depend it maybe in wrong status.\n", master[i].name.c_str()); continue; } @@ -2191,7 +2214,7 @@ bool hg_sane_middleware::is_enable_or(scanner_handle hdev, const std::vector::iterator it = std::find(curvals.begin(), curvals.end(), master[i].name); if (it == curvals.end()) { - local_utility::to_log(LOG_LEVEL_WARNING, "option %s's current value is not found, other options depend it maybe in wrong status.\n", master[i].name.c_str()); + utils::to_log_with_api(hg_scanner_log_is_enable, hg_scanner_log, LOG_LEVEL_WARNING, "option %s's current value is not found, other options depend it maybe in wrong status.\n", master[i].name.c_str()); continue; } @@ -2303,17 +2326,16 @@ bool hg_sane_middleware::parse_master_option(const char* depend_str, MASTEROP& m return ret; } -bool hg_sane_middleware::parse_depends(scanner_handle h, json* jsn, SLAVEOP& so, std::vector& master) +bool hg_sane_middleware::parse_depends(scanner_handle h, gb_json* jsn, SLAVEOP& so, std::vector& master) { std::string val(""), mn(""); - bool ret = jsn->first_child(val); + gb_json* child = jsn->first_child(); - while(ret) + while(child) { MASTEROP mo; - ret = parse_master_option(val.c_str(), mo); - if (!ret) + if (!child->value(val) || !parse_master_option(val.c_str(), mo)) break; if (mo.name.empty()) @@ -2330,8 +2352,11 @@ bool hg_sane_middleware::parse_depends(scanner_handle h, json* jsn, SLAVEOP& so, master.push_back(mo.name); std::sort(master.begin(), master.end()); } - ret = jsn->next_child(val); + child->release(); + child = jsn->next_child(); } + if (child) + child->release(); return so.master.size() > 0; } @@ -2404,7 +2429,7 @@ int hg_sane_middleware::something_after_do(LPDEVINST dev, const char* master_nam continue; OPTEN* op = get_control_enalbe_data(dev, dev->slaves[slave]); - hg_scanner_control(dev->dev, HG_CONTROL_CODE_OPTION_ENABLE, op, NULL); + hg_scanner_control(dev->dev, HG_CONTROL_CODE_OPTION_ENABLE, op, nullptr); free_control_enable_data(op); if (std::find(changed_options.begin(), changed_options.end(), dev->slaves[slave].name) != changed_options.end()) @@ -2421,7 +2446,7 @@ int hg_sane_middleware::something_after_do(LPDEVINST dev, const char* master_nam return after; } -bool hg_sane_middleware::refresh_current_value(LPDEVINST dev, const char* name, json* jsn) +bool hg_sane_middleware::refresh_current_value(LPDEVINST dev, const char* name, gb_json* jsn) { std::vector::iterator it = std::find(dev->cur_vals.begin(), dev->cur_vals.end(), name); if (it == dev->cur_vals.end()) @@ -2429,7 +2454,7 @@ bool hg_sane_middleware::refresh_current_value(LPDEVINST dev, const char* name, CURVAL cv; jsn->get_value("type", cv.type); cv.name = name; - jsn->get_value_as_string("cur", cv.val, cv.type == "int"); + cv.val = hg_sane_middleware::string_value_from_json(jsn, true); if (cv.type == "string") local_utility::trans_language_if_was_word_id(cv.val); dev->cur_vals.push_back(cv); @@ -2439,7 +2464,7 @@ bool hg_sane_middleware::refresh_current_value(LPDEVINST dev, const char* name, else { std::string old(it->val); - jsn->get_value_as_string("cur", it->val, it->type == "int"); + it->val = hg_sane_middleware::string_value_from_json(jsn, true); if (it->type == "string") local_utility::trans_language_if_was_word_id(it->val); @@ -2463,7 +2488,7 @@ bool hg_sane_middleware::refresh_current_value(LPDEVINST dev, const char* name, OPTEN* hg_sane_middleware::get_control_enalbe_data(LPDEVINST dev, const SLAVEOP& slave) { std::vector master; - OPTEN* opt = NULL; + OPTEN* opt = nullptr; size_t size = sizeof(OPTEN); for (size_t i = 0; i < slave.master.size(); ++i) @@ -2552,147 +2577,3 @@ std::vector::iterator hg_sane_middleware::find_openning_device_in_que return openning_.end(); } -/// - -/// -/// 导出接口 -/// -extern "C" { // avoid compiler exporting name in C++ style !!! - const char* inner_sane_err_desc(SANE_Status err) - { - return hg_scanner_err_description(local_utility::sane_statu_2_scanner_err(err)); - } - - SANE_Status inner_sane_init(SANE_Int* version_code, SANE_Auth_Callback authorize) - { - local_utility::cb_auth_ = authorize; - if (!hg_sane_middleware::instance()->is_ready()) - return (SANE_Status)SCANNER_ERR_LANG_PAK_LOST; - - local_utility::get_version(version_code); - std::this_thread::sleep_for(std::chrono::milliseconds(500)); - return SANE_STATUS_GOOD; - } - void inner_sane_exit(void) - { - hg_sane_middleware::clear(); - } - SANE_Status inner_sane_get_devices(const SANE_Device*** device_list, SANE_Bool local_only) - { - SANE_Status code = hg_sane_middleware::instance()->get_devices(device_list, local_only); - - return code; - } - SANE_Status inner_sane_open(SANE_String_Const devicename, SANE_Handle* handle) - { - return hg_sane_middleware::instance()->open_device(devicename, handle); - } - void inner_sane_close(SANE_Handle handle) - { - hg_sane_middleware::instance()->close_device(handle); - } - const SANE_Option_Descriptor* - inner_sane_get_option_descriptor(SANE_Handle handle, const void* option) - { - return hg_sane_middleware::instance()->get_option_descriptor(handle, option); - } - SANE_Status inner_sane_control_option(SANE_Handle handle, const void* option, SANE_Action action, void* value, SANE_Int* info) - { - return hg_sane_middleware::instance()->set_option(handle, option, action, value, info); - } - SANE_Status inner_sane_get_parameters(SANE_Handle handle, SANE_Parameters* params) - { - return hg_sane_middleware::instance()->get_image_parameters(handle, params); - } - SANE_Status inner_sane_start(SANE_Handle handle) - { - local_utility::to_log(LOG_LEVEL_ALL, "sane_start\n"); - - return hg_sane_middleware::instance()->start(handle, NULL); - } - SANE_Status inner_sane_read(SANE_Handle handle, SANE_Byte* data, SANE_Int max_length, SANE_Int* length) - { - if (!length) - length = &max_length; - else - *length = max_length; - - return hg_sane_middleware::instance()->read(handle, data, length); - } - void inner_sane_cancel(SANE_Handle handle) - { - local_utility::to_log(LOG_LEVEL_ALL, "sane_cancel\n"); - - hg_sane_middleware::instance()->stop(handle); - } - SANE_Status inner_sane_set_io_mode(SANE_Handle handle, SANE_Bool non_blocking) - { - local_utility::to_log(LOG_LEVEL_ALL, "sane_set_io_mode\n"); - - return non_blocking ? SANE_STATUS_UNSUPPORTED : SANE_STATUS_GOOD; - } - SANE_Status inner_sane_get_select_fd(SANE_Handle handle, SANE_Int* fd) - { - return SANE_STATUS_UNSUPPORTED; - } - SANE_String_Const inner_sane_strstatus(SANE_Status status) - { - // return hg_scanner_err_name(status); - return inner_sane_err_desc(status); - } - - SANE_Status inner_sane_init_ex(SANE_Int* version_code, sane_callback cb, void* param) - { - local_utility::set_callback(cb, param); - if (!hg_sane_middleware::instance()->is_ready()) - return (SANE_Status)SCANNER_ERR_LANG_PAK_LOST; - - local_utility::get_version(version_code); - std::this_thread::sleep_for(std::chrono::milliseconds(500)); - return SANE_STATUS_GOOD; - } - SANE_Status inner_sane_io_control(SANE_Handle h, unsigned long code, void* data, unsigned* len) - { - return hg_sane_middleware::instance()->io_control(h, code, data, len); - } - SANE_Status inner_sane_read_ext(SANE_Img_Ext_Info* ext_info, SANE_Int* len) - { - return SANE_STATUS_UNSUPPORTED; - } - - void sanei_debug_msg(int level, int max_level, const char* be, const char* fmt, va_list ap) - { - } -} - - -#if defined(WIN32) || defined(_WIN64) -HMODULE g_my_inst = NULL; -BOOL WINAPI DllMain(HINSTANCE inst, DWORD reason, LPVOID reserved) -{ - if (reason == DLL_PROCESS_ATTACH) - { - g_my_inst = inst; - if (g_sane_path.empty()) - { - char path[MAX_PATH] = { 0 }; - - GetModuleFileNameA(inst, path, _countof(path) - 1); - if (strrchr(path, '\\')) - { - g_sane_name = strrchr(path, '\\') + 1; - strrchr(path, '\\')[1] = 0; - g_sane_path = path; - if (g_sane_name.rfind('.') != std::string::npos) - g_sane_name.erase(g_sane_name.rfind('.')); - } - } - } - else if (reason == DLL_PROCESS_DETACH) - { - inner_sane_exit(); - } - - return TRUE; -} -#endif diff --git a/hgsane/sane_hg_mdw.h b/hgsane/sane_hg_mdw.h index 62cd506..9f0cf1d 100644 --- a/hgsane/sane_hg_mdw.h +++ b/hgsane/sane_hg_mdw.h @@ -25,7 +25,7 @@ #define hg_sane_middleware lsc_sane_middleware #endif -class json; +class gb_json; class sane_std_opts; typedef struct _device_option { @@ -144,7 +144,7 @@ class hg_sane_middleware void reload_options(scanner_handle dev = nullptr); void set_status_by_depends(scanner_handle hdev, SLAVEOP& so, std::vector& vals, SANE_Option_Descriptor* desc); SANE_Status open(SANE_String_Const devicename, SANE_Handle* handle, const char* name, const char* pwd, const char* method, char* rsc); - SANE_Option_Descriptor* from_json(scanner_handle h, const std::string& name, json* jsn); + SANE_Option_Descriptor* from_json(scanner_handle h, const std::string& name, gb_json* jsn); std::string get_option_json(scanner_handle handle, void* opt, std::string* key = nullptr, SANE_Int* id = nullptr); SANE_Option_Descriptor* find_stored_descriptor(scanner_handle handle, const void* option, SANE_Int* id = nullptr, SANE_Int* fix_id = nullptr); @@ -157,7 +157,7 @@ class hg_sane_middleware // 添加对多依赖项的支持 - 2022-03-10 //std::vector cur_vals_; - bool refresh_current_value(LPDEVINST dev, const char* name, json* jsn); // return whether changed old value + bool refresh_current_value(LPDEVINST dev, const char* name, gb_json* jsn); // return whether changed old value bool refresh_current_value(LPDEVINST dev, const char* name, const char* val); static bool compare_val_equal(const char* cur_val, const char* limit_l, const char* limit_r); @@ -176,7 +176,7 @@ class hg_sane_middleware bool parse_master_option(const char* depend_str, MASTEROP& mo); - bool parse_depends(scanner_handle h, json* jsn, SLAVEOP& so, std::vector& master); + bool parse_depends(scanner_handle h, gb_json* jsn, SLAVEOP& so, std::vector& master); bool is_associatived(const SLAVEOP& slave, const char* master_name); bool set_stored_option_enabled(scanner_handle h, const void* option, bool enable, int* size = NULL); @@ -198,11 +198,19 @@ protected: ~hg_sane_middleware(); public: - static std::string sane_path(void); + enum + { + APP_CALLBACK_AUTH = 0, + APP_CALLBACK_EX, + }; + static void set_app_callback(void* cb, void* param = nullptr, int type = APP_CALLBACK_AUTH); + static void get_version(SANE_Int* ver); + static hg_sane_middleware* instance(void); static void set_callback(sane_callback cb, void* param); static void clear(void); static std::string option_value_2_string(SANE_Value_Type type, void* val); + static std::string string_value_from_json(gb_json* jsn, bool curval); static scanner_handle sane_handle_to_scanner(SANE_Handle h); static SANE_Handle scanner_handle_to_sane(scanner_handle h); static SANE_Option_Descriptor* allocate_descriptor(const char* name, const char* title, const char* desc); @@ -215,7 +223,7 @@ public: , const std::vector& values); // NO constraint if values was empty static SANE_Option_Descriptor* number_option_to_SANE_descriptor(const char* name, const char* title, const char* desc , const std::vector& values); // NO constraint if values was empty - static std::string get_string_in_json(json* jsn, const char* key, bool* has = nullptr); + static std::string get_string_in_json(gb_json* jsn, const char* key, bool* has = nullptr); // methods ... public: diff --git a/hgsane/sane_option.cpp b/hgsane/sane_option.cpp index 69b2e20..4e9e289 100644 --- a/hgsane/sane_option.cpp +++ b/hgsane/sane_option.cpp @@ -3,6 +3,7 @@ #include #include "../sdk/hginclude/huagaoxxx_warraper_ex.h" #include "../sdk/hginclude/utils.h" +#include "../sdk/json/gb_json.h" #include "../../sdk/include/lang/app_language.h" @@ -52,7 +53,7 @@ static void match_paper(char* buf, int cx, int cy) else strcpy(buf, from_default_language(g_paper[index].title, NULL)); - local_utility::to_log(LOG_LEVEL_DEBUG, "match paper(%u * %u) to '%s'\n", cx, cy, (char*)buf); + utils::to_log_with_api(hg_scanner_log_is_enable, hg_scanner_log, LOG_LEVEL_DEBUG, "match paper(%u * %u) to '%s'\n", cx, cy, (char*)buf); } @@ -174,11 +175,11 @@ void* sane_std_opts::from_known_opt_value(OPTMAP* opmap, const void* known_data, return buf; } -json* sane_std_opts::get_opt_json(scanner_handle h, int opt) +gb_json* sane_std_opts::get_opt_json(scanner_handle h, int opt) { char* buf = nullptr; long len = 0; - json* jsn = nullptr; + gb_json* jsn = nullptr; if (hg_scanner_get_parameter(h, (const char*)opt, buf, &len) == SCANNER_ERR_INSUFFICIENT_MEMORY) { @@ -186,10 +187,10 @@ json* sane_std_opts::get_opt_json(scanner_handle h, int opt) memset(buf, 0, len + 8); if (hg_scanner_get_parameter(h, (const char*)opt, buf, &len) == SCANNER_ERR_OK) { - jsn = new json(); + jsn = new gb_json(); if (!jsn->attach_text(buf)) { - delete jsn; + jsn->release(); jsn = nullptr; } } @@ -200,7 +201,7 @@ json* sane_std_opts::get_opt_json(scanner_handle h, int opt) } void* sane_std_opts::get_current_value(scanner_handle h, int opt) { - json* jsn = sane_std_opts::get_opt_json(h, opt); + gb_json* jsn = sane_std_opts::get_opt_json(h, opt); void* ret = nullptr; if (jsn) @@ -238,7 +239,7 @@ void* sane_std_opts::get_current_value(scanner_handle h, int opt) ret = local_utility::acquire_memory(sizeof(SANE_Fixed), ""); *((SANE_Fixed*)ret) = SANE_FIX(v); } - delete jsn; + jsn->release(); } return ret; @@ -397,7 +398,7 @@ scanner_err sane_std_opts::set_value(scanner_handle h, int opt, void* buf) long len = 0; void* data = from_known_opt_value(op, buf, &len); - local_utility::to_log(LOG_LEVEL_DEBUG, "%d->%d: %s\n", opt, op->user.opt, (char*)data); + utils::to_log_with_api(hg_scanner_log_is_enable, hg_scanner_log, LOG_LEVEL_DEBUG, "%d->%d: %s\n", opt, op->user.opt, (char*)data); statu = hg_scanner_set_parameter(h, (const char*)op->user.opt, data, &len); if (statu == SCANNER_ERR_NOT_EXACT) diff --git a/hgsane/sane_option.h b/hgsane/sane_option.h index 354a42a..b8dd913 100644 --- a/hgsane/sane_option.h +++ b/hgsane/sane_option.h @@ -14,25 +14,15 @@ #endif #include "../sdk/hginclude/huagaoxxx_warraper_ex.h" #include "sane/sane_ex.h" -#include "json.h" #include namespace local_utility { void* acquire_memory(size_t bytes, const char* info); void free_memory(void* m); - - template - void to_log(int level, const char* fmt, Args ... args) - { - size_t size = snprintf(nullptr, 0, fmt, args ...) + 2; - std::unique_ptr buf(new char[size]); - - snprintf(buf.get(), size, fmt, args ...); - hg_scanner_log(buf.get(), level); - } }; +class gb_json; class sane_std_opts { typedef struct _sane_opt @@ -61,7 +51,7 @@ public: ~sane_std_opts(); public: - static json* get_opt_json(scanner_handle h, int opt); // call delete to free the returned object + static gb_json* get_opt_json(scanner_handle h, int opt); // call delete to free the returned object static void* get_current_value(scanner_handle h, int opt); // call local_utility::free_memory to free the returned buffer public: diff --git a/sdk/hginclude/utils.cpp b/sdk/hginclude/utils.cpp index a43323b..849d349 100644 --- a/sdk/hginclude/utils.cpp +++ b/sdk/hginclude/utils.cpp @@ -839,6 +839,38 @@ namespace utils return str.c_str(); } + HMODULE load_dll(const char* path_file, int flag) + { +#if OS_WIN + HMODULE h = LoadLibraryA(path_file); + int ret = GetLastError(); + + utils::to_log(1, "[TWAIN]Load: LoadLibraryA(%s) = %d\r\n", path_file, ret); + if (!h && (ret == ERROR_MOD_NOT_FOUND || ret == ERROR_BAD_EXE_FORMAT)) + { + std::string dir(path_file); + size_t pos = dir.rfind('\\'); + char path[MAX_PATH] = { 0 }; + + GetDllDirectoryA(_countof(path) - 1, path); + if (pos != std::wstring::npos) + dir.erase(pos); + utils::to_log(LOG_LEVEL_FATAL, "[TWAIN]Load: change directory to '%s' and retry LoadLibraryA(%s) ...\r\n", dir.c_str(), path_file); + SetDllDirectoryA(dir.c_str()); + h = LoadLibraryA(path_file); + // h = LoadLibraryExW(path_dll, NULL, LOAD_WITH_ALTERED_SEARCH_PATH); + ret = GetLastError(); + utils::to_log(1, "[TWAIN]Load: trying LoadLibraryA(%s) = %d, restore directory to '%s'\r\n", path_file, ret, path); + SetDllDirectoryA(path); + } + + errno = GetLastError(); + + return h; +#else + return dlopen(path_file, flag); +#endif + } bool create_folder(const char* folder) { int ret = MKDIR(folder, S_IREAD | S_IWRITE | S_IEXEC); diff --git a/sdk/hginclude/utils.h b/sdk/hginclude/utils.h index d1d3abf..69b823d 100644 --- a/sdk/hginclude/utils.h +++ b/sdk/hginclude/utils.h @@ -43,6 +43,7 @@ namespace utils const char* to_lower(std::string& str); // return str.c_str() const char* trim(std::string& str, const char* sp = "\r\n\t "); // return str.c_str() + HMODULE load_dll(const char* path_file, int flag); bool create_folder(const char* folder); void set_ini_value(const char* seg, const char* key, const char* val, const char* cfg_file); int enum_file(const char* folder, bool recursive, bool/*return false to stop enumeration*/(STDCALL* found)(const char* path_name, bool dir, void* param), void* param); @@ -72,6 +73,19 @@ namespace utils log_info(buf.get(), (log_level)level); } } + + template + void to_log_with_api(bool(*is_enable)(int), void(*log_api)(const char*, int), int level, const char* fmt, Args ... args) + { + if (is_enable(level)) + { + size_t size = snprintf(nullptr, 0, fmt, args ...) + 2; + std::unique_ptr buf(new char[size]); + + snprintf(buf.get(), size, fmt, args ...); + log_api(buf.get(), (log_level)level); + } + } }; #if OS_WIN diff --git a/hgsane/cJSON.c b/sdk/json/cJSON.c similarity index 97% rename from hgsane/cJSON.c rename to sdk/json/cJSON.c index cd60134..594376b 100644 --- a/hgsane/cJSON.c +++ b/sdk/json/cJSON.c @@ -776,19 +776,19 @@ cJSON *cJSON_Duplicate(cJSON *item,int recurse) return newitem; } -void cJSON_Minify(char *json) +void cJSON_Minify(char *gb_json) { - char *into=json; - while (*json) + char *into=gb_json; + while (*gb_json) { - if (*json==' ') json++; - else if (*json=='\t') json++; /* Whitespace characters. */ - else if (*json=='\r') json++; - else if (*json=='\n') json++; - else if (*json=='/' && json[1]=='/') while (*json && *json!='\n') json++; /* double-slash comments, to end of line. */ - else if (*json=='/' && json[1]=='*') {while (*json && !(*json=='*' && json[1]=='/')) json++;json+=2;} /* multiline comments. */ - else if (*json=='\"'){*into++=*json++;while (*json && *json!='\"'){if (*json=='\\') *into++=*json++;*into++=*json++;}*into++=*json++;} /* string literals, which are \" sensitive. */ - else *into++=*json++; /* All other characters. */ + if (*gb_json==' ') gb_json++; + else if (*gb_json=='\t') gb_json++; /* Whitespace characters. */ + else if (*gb_json=='\r') gb_json++; + else if (*gb_json=='\n') gb_json++; + else if (*gb_json=='/' && gb_json[1]=='/') while (*gb_json && *gb_json!='\n') gb_json++; /* double-slash comments, to end of line. */ + else if (*gb_json=='/' && gb_json[1]=='*') {while (*gb_json && !(*gb_json=='*' && gb_json[1]=='/')) gb_json++;gb_json+=2;} /* multiline comments. */ + else if (*gb_json=='\"'){*into++=*gb_json++;while (*gb_json && *gb_json!='\"'){if (*gb_json=='\\') *into++=*gb_json++;*into++=*gb_json++;}*into++=*gb_json++;} /* string literals, which are \" sensitive. */ + else *into++=*gb_json++; /* All other characters. */ } *into=0; /* and null-terminate. */ } diff --git a/hgsane/cJSON.h b/sdk/json/cJSON.h similarity index 99% rename from hgsane/cJSON.h rename to sdk/json/cJSON.h index 913bc1e..9fdbf9b 100644 --- a/hgsane/cJSON.h +++ b/sdk/json/cJSON.h @@ -133,7 +133,7 @@ The item->next and ->prev pointers are always zero on return from Duplicate. */ /* ParseWithOpts allows you to require (and check) that the JSON is null terminated, and to retrieve the pointer to the final byte parsed. */ extern cJSON *cJSON_ParseWithOpts(const char *value,const char **return_parse_end,int require_null_terminated); -extern void cJSON_Minify(char *json); +extern void cJSON_Minify(char *gb_json); // convert e681a2 to \u6062, call 'free' to free the returned value extern char* cJSON_utf8_2_unic(const char* utf8); diff --git a/sdk/json/gb_json.cpp b/sdk/json/gb_json.cpp new file mode 100644 index 0000000..ea7ec94 --- /dev/null +++ b/sdk/json/gb_json.cpp @@ -0,0 +1,817 @@ + +#include "gb_json.h" +#include "cJSON.h" +#include +#include + +namespace special_char_trans +{ + struct + { + const char* writedown_text; + char readable_char; + }transferred_chars[] = { { "\\\"", '\"' } + , { "\\'", '\'' } + , { "\\a", '\a' } + , { "\\b", '\b' } + , { "\\f", '\f' } + , { "\\n", '\n' } + , { "\\r", '\r' } + , { "\\t", '\t' } + , { "\\v", '\v' } + // , { "\\?", '\?' } + , { "\\\\", '\\' } + , { "\\/", '/' } + // , { "\\0", '\0' } + }; + + void to_writedown(std::string& str) + { + std::string trans(str); + const char* ptr = trans.c_str(); + + str.clear(); + while (*ptr) + { + bool rep = false; + if (*ptr == '\\') + { + if (ptr[1] == '\\') + { + str += "\\\\"; + ptr++; + rep = true; + } + else if( ptr[1] == '/' || + ptr[1] == 'a' || + ptr[1] == 'b' || + ptr[1] == 'f' || + ptr[1] == 'n' || + ptr[1] == 'r' || + ptr[1] == 't' || + ptr[1] == 'u' || + ptr[1] == 'v') + { + str += "\\"; + ptr++; + } + else + { + str += "\\\\"; + rep = true; + } + } + else + { + for (size_t i = 0; i < sizeof(transferred_chars) / sizeof(transferred_chars[0]); ++i) + { + if (*ptr == transferred_chars[i].readable_char) + { + str += transferred_chars[i].writedown_text; + rep = true; + break; + } + } + } + if (!rep) + str.append(1, *ptr); + ptr++; + } + } +} + + +gb_json::gb_json(char* json_txt) : ref_(1), type_(VAL_TYPE_OBJECT), key_(""), strval_(""), cur_child_(-1) +{ + simple_val_.dval = .0f; + if(json_txt) + attach_text(json_txt); +} +gb_json::gb_json(const char* key, bool val) : ref_(1), type_(VAL_TYPE_BOOL), key_(key ? key : ""), strval_(""), cur_child_(-1) +{ + simple_val_.bval = val; +} +gb_json::gb_json(const char* key, int val) : ref_(1), type_(VAL_TYPE_INT), key_(key ? key : ""), strval_(""), cur_child_(-1) +{ + simple_val_.nval = val; +} +gb_json::gb_json(const char* key, double val) : ref_(1), type_(VAL_TYPE_FLOAT), key_(key ? key : ""), strval_(""), cur_child_(-1) +{ + simple_val_.dval = val; +} +gb_json::gb_json(const char* key, const char* val) : ref_(1), type_(VAL_TYPE_STRING), key_(key ? key : ""), strval_(val ? val : ""), cur_child_(-1) +{} +gb_json::~gb_json() +{ + clear(); +} + +std::string gb_json::object_key(gb_json* jsn) +{ + return "\"" + jsn->key() + "\":"; +} +std::string gb_json::array_key(gb_json* jsn) +{ + return ""; +} + +void gb_json::from_cjson(cJSON* cj) +{ + key_ = cj && cj->string ? cj->string : ""; + while (cj) + { + gb_json* child = nullptr; + if (cj->type == cJSON_True) + { + child = new gb_json(cj->string, true); + } + else if(cj->type == cJSON_False) + { + child = new gb_json(cj->string, false); + } + else if (cj->type == cJSON_Number) + { + if (cj->valuedouble - (int)cj->valuedouble < .00001) + { + child = new gb_json(cj->string, cj->valueint); + } + else + { + child = new gb_json(cj->string, cj->valuedouble); + } + } + else if (cj->type == cJSON_String) + { + child = new gb_json(cj->string, cj->valuestring); + } + else if (cj->type == cJSON_Object || cj->type == cJSON_Array) + { + child = new gb_json(); + child->from_cjson(cj->child); + child->key_ = cj->string ? cj->string : ""; + } + arr_val_.push_back(child); + cj = cj->next; + } + + if (arr_val_.size() == 1 && arr_val_[0]->arr_val_.size() == 0) + { + gb_json* child = arr_val_[0]; + + if (!child->key_.empty()) // array + { + arr_val_.clear(); + type_ = child->type_; + key_ = child->key_; + simple_val_.dval = child->simple_val_.dval; + strval_ = child->strval_; + for (auto& v : child->arr_val_) + arr_val_.push_back(v); + child->arr_val_.clear(); + child->release(); + } + } + + if (arr_val_.size()) + { + type_ = arr_val_[0]->key().empty() ? VAL_TYPE_ARRAY : VAL_TYPE_OBJECT; + } +} +gb_json* gb_json::find_child(const char* key, bool remove) +{ + gb_json* ret = nullptr; + + if (type_ == VAL_TYPE_OBJECT) + { + for (size_t i = 0; i < arr_val_.size(); ++i) + { + if (arr_val_[i]->key() == key) + { + ret = arr_val_[i]; + if (remove) + arr_val_.erase(arr_val_.begin() + i); + else + ret->add_ref(); + + break; + } + } + } + + return ret; +} + +int32_t gb_json::add_ref() +{ + std::lock_guard lock(ref_mutex_); + int32_t ref = ++ref_; + + return ref; +} +int32_t gb_json::release() +{ + int32_t ref = 0; + + { + std::lock_guard lock(ref_mutex_); + ref = --ref_; + } + + if (ref == 0) + delete this; + + return ref; +} + +bool gb_json::attach_text(char* json_txt) +{ + clear(); + + cJSON* jsn = cJSON_Parse(json_txt); + if (jsn) + { + char *text = cJSON_Print(jsn); + if (text) + free(text); + + from_cjson(jsn->child); + cJSON_Delete(jsn); + + return true; + } + + return false; +} +void gb_json::clear(bool as_array) +{ + if (type_ == VAL_TYPE_ARRAY || type_ == VAL_TYPE_OBJECT) + { + for (auto& v : arr_val_) + v->release(); + } + type_ = as_array ? VAL_TYPE_ARRAY : VAL_TYPE_OBJECT; + simple_val_.dval = .0f; + key_ = ""; + strval_ = ""; + arr_val_.clear(); + cur_child_ = -1; +} +std::string gb_json::to_string(void) +{ + if (type_ == VAL_TYPE_NULL) + return ""; + if (type_ == VAL_TYPE_BOOL) + return (simple_val_.bval ? "true" : "false"); + if (type_ == VAL_TYPE_INT) + return std::to_string(simple_val_.nval); + if (type_ == VAL_TYPE_FLOAT) + return std::to_string(simple_val_.dval); + if (type_ == VAL_TYPE_STRING) + { + char* u = cJSON_utf8_2_unic(strval_.c_str()); + std::string r(u); + + free(u); + special_char_trans::to_writedown(r); + + return "\"" + r + "\""; + } + + std::string(*k)(gb_json*) = type_ == VAL_TYPE_OBJECT ? gb_json::object_key : gb_json::array_key; + std::string str(type_ == VAL_TYPE_OBJECT ? "{" : "["); + + if (arr_val_.size()) + { + str += k(arr_val_[0]) + arr_val_[0]->to_string(); + for(size_t i = 1; i < arr_val_.size(); ++i) + str += "," + k(arr_val_[i]) + arr_val_[i]->to_string(); + } + str += type_ == VAL_TYPE_OBJECT ? "}" : "]"; + + return str; +} + +std::string& gb_json::key(void) +{ + return key_; +} +bool gb_json::is_array(void) +{ + return type_ == VAL_TYPE_ARRAY; +} +bool gb_json::is_leaf_node(void) +{ + return type_ == VAL_TYPE_BOOL || + type_ == VAL_TYPE_INT || + type_ == VAL_TYPE_FLOAT || + type_ == VAL_TYPE_STRING; +} + +bool gb_json::get_value(const char* key, bool& val) +{ + bool ret = false; + gb_json* child = find_child(key); + + if (child) + { + if (child->type_ == VAL_TYPE_BOOL) + { + val = child->simple_val_.bval; + ret = true; + } + child->release(); + } + else if (type_ == VAL_TYPE_BOOL && key_ == key) + { + val = simple_val_.bval; + ret = true; + } + + return ret; +} +bool gb_json::get_value(const char* key, int& val) +{ + bool ret = false; + gb_json* child = find_child(key); + + if (child) + { + if (child->type_ == VAL_TYPE_INT) + { + val = child->simple_val_.nval; + ret = true; + } + child->release(); + } + else if (type_ == VAL_TYPE_INT && key_ == key) + { + val = simple_val_.nval; + ret = true; + } + + return ret; +} +bool gb_json::get_value(const char* key, double& val) +{ + bool ret = false; + gb_json* child = find_child(key); + + if (child) + { + if (child->type_ == VAL_TYPE_FLOAT) + { + val = child->simple_val_.dval; + ret = true; + } + child->release(); + } + else if (type_ == VAL_TYPE_FLOAT && key_ == key) + { + val = simple_val_.dval; + ret = true; + } + + // added on 2023-04-27: for cJSON consider both int and float as CJSON_Number, we consider int if the value is just an integer + if(!ret) + { + int v = 0; + ret = get_value(key, v); + if(ret) + val = v; + } + + return ret; +} +bool gb_json::get_value(const char* key, std::string& val) +{ + bool ret = false; + gb_json* child = find_child(key); + + if (child) + { + if (child->type_ == VAL_TYPE_STRING) + { + val = child->strval_; + ret = true; + } + child->release(); + } + else if (type_ == VAL_TYPE_STRING && key_ == key) + { + val = strval_; + ret = true; + } + + return ret; +} +bool gb_json::get_value(const char* key, gb_json*& val) +{ + bool ret = false; + gb_json *child = find_child(key); + + if (child) + { + if (child->type_ == VAL_TYPE_OBJECT || child->type_ == VAL_TYPE_ARRAY) + { + val = child; + ret = true; + } + else + { + child->release(); + } + } + + return ret; +} + +size_t gb_json::children(void) +{ + if (type_ == VAL_TYPE_ARRAY || type_ == VAL_TYPE_OBJECT) + return arr_val_.size(); + else + return -1; +} +gb_json* gb_json::child(size_t ind) +{ + if (type_ == VAL_TYPE_ARRAY || type_ == VAL_TYPE_OBJECT) + { + if (ind >= 0 && ind < arr_val_.size()) + { + arr_val_[ind]->add_ref(); + + return arr_val_[ind]; + } + } + + return nullptr; +} +gb_json* gb_json::first_child(void) +{ + if (type_ == VAL_TYPE_OBJECT || type_ == VAL_TYPE_ARRAY) + { + cur_child_ = 0; + if (arr_val_.size()) + { + arr_val_[0]->add_ref(); + + return arr_val_[0]; + } + } + + return nullptr; +} +gb_json* gb_json::next_child(void) +{ + if (type_ == VAL_TYPE_OBJECT || type_ == VAL_TYPE_ARRAY) + { + if (++cur_child_ < arr_val_.size()) + { + arr_val_[cur_child_]->add_ref(); + + return arr_val_[cur_child_]; + } + } + + return nullptr; +} + +bool gb_json::set_value(const char* key, bool val) +{ + if (type_ != VAL_TYPE_OBJECT) + return false; + + gb_json* child = find_child(key); + + if (child) + { + child->clear(); + child->type_ = VAL_TYPE_BOOL; + child->key() = key ? key : ""; + child->simple_val_.bval = val; + child->release(); + } + else + { + child = new gb_json(key, val); + arr_val_.push_back(child); + } + + return true; +} +bool gb_json::set_value(const char* key, int val) +{ + if (type_ != VAL_TYPE_OBJECT) + return false; + + gb_json* child = find_child(key); + + if (child) + { + child->clear(); + child->type_ = VAL_TYPE_INT; + child->key() = key ? key : ""; + child->simple_val_.nval = val; + child->release(); + } + else + { + child = new gb_json(key, val); + arr_val_.push_back(child); + } + + return true; +} +bool gb_json::set_value(const char* key, double val) +{ + if (type_ != VAL_TYPE_OBJECT) + return false; + + gb_json* child = find_child(key); + + if (child) + { + child->clear(); + child->type_ = VAL_TYPE_FLOAT; + child->key() = key ? key : ""; + child->simple_val_.dval = val; + child->release(); + } + else + { + child = new gb_json(key, val); + arr_val_.push_back(child); + } + + return true; +} +bool gb_json::set_value(const char* key, const char* val) +{ + if (type_ != VAL_TYPE_OBJECT) + return false; + + gb_json* child = find_child(key); + + if (child) + { + child->clear(); + child->type_ = VAL_TYPE_STRING; + child->key() = key ? key : ""; + child->strval_ = val ? val : ""; + child->release(); + } + else + { + child = new gb_json(key, val); + arr_val_.push_back(child); + } + + return true; +} +bool gb_json::set_value(const char* key, gb_json* val) +{ + if (type_ != VAL_TYPE_OBJECT) + return false; + + for (size_t i = 0; i < arr_val_.size(); ++i) + { + if (arr_val_[i]->key() == key) + { + arr_val_[i]->release(); + arr_val_[i] = val; + val->add_ref(); + return true; + } + } + + arr_val_.push_back(val); + val->key() = key; + val->add_ref(); + + return true; +} + +gb_json& gb_json::operator+=(bool val) +{ + if (type_ == VAL_TYPE_ARRAY) + { + gb_json* child = new gb_json(nullptr, val); + arr_val_.push_back(child); + } + + return *this; +} +gb_json& gb_json::operator+=(int val) +{ + if (type_ == VAL_TYPE_ARRAY) + { + gb_json* child = new gb_json(nullptr, val); + arr_val_.push_back(child); + } + + return *this; +} +gb_json& gb_json::operator+=(double val) +{ + if (type_ == VAL_TYPE_ARRAY) + { + gb_json* child = new gb_json(nullptr, val); + arr_val_.push_back(child); + } + + return *this; +} +gb_json& gb_json::operator+=(const char* val) +{ + if (type_ == VAL_TYPE_ARRAY) + { + gb_json* child = new gb_json(nullptr, val); + arr_val_.push_back(child); + } + + return *this; +} +gb_json& gb_json::operator+=(gb_json* val) +{ + if (type_ == VAL_TYPE_ARRAY) + { + val->add_ref(); + arr_val_.push_back(val); + } + + return *this; +} + +gb_json& gb_json::operator-=(int ind) +{ + remove(ind); + + return *this; +} +bool gb_json::remove(const char* key) +{ + gb_json* child = find_child(key, true); + + if (child) + { + child->release(); + return true; + } + else + { + return false; + } +} +bool gb_json::remove(gb_json* child) +{ + if (type_ == VAL_TYPE_ARRAY || type_ == VAL_TYPE_OBJECT) + { + for (size_t i = 0; i < arr_val_.size(); ++i) + { + if (arr_val_[i] == child) + { + arr_val_[i]->release(); + arr_val_.erase(arr_val_.begin() + i); + + return true; + } + } + } + + return false; +} +bool gb_json::remove(int ind) +{ + bool ret = false; + + if (type_ == VAL_TYPE_ARRAY || type_ == VAL_TYPE_OBJECT) + { + if (ind >= 0 && ind < arr_val_.size()) + { + arr_val_[ind]->release(); + arr_val_.erase(arr_val_.begin() + ind); + ret = true; + } + } + + return ret; +} + +int gb_json::index(gb_json* child) +{ + if (type_ == VAL_TYPE_ARRAY || type_ == VAL_TYPE_OBJECT) + { + for (int i = 0; i < arr_val_.size(); ++i) + { + if (arr_val_[i] == child) + return i; + } + } + + return -1; +} +int gb_json::index_move_to(gb_json* child, int ind) +{ + int i = index(child); + + if (i == -1) + return -1; + + arr_val_.erase(arr_val_.begin() + i); + if (ind < 0) + ind = 0; + if (ind > arr_val_.size()) + ind = arr_val_.size(); + arr_val_.insert(arr_val_.begin() + ind, child); + + return ind; +} + +bool gb_json::value(bool& val) +{ + bool ret = false; + + if (is_leaf_node() && type_ == VAL_TYPE_BOOL) + { + val = simple_val_.bval; + ret = true; + } + + return ret; +} +bool gb_json::value(int& val) +{ + bool ret = false; + + if (is_leaf_node() && type_ == VAL_TYPE_INT) + { + val = simple_val_.nval; + ret = true; + } + + return ret; +} +bool gb_json::value(double& val) +{ + bool ret = false; + + if (is_leaf_node() && type_ == VAL_TYPE_FLOAT) + { + val = simple_val_.dval; + ret = true; + } + + return ret; +} +bool gb_json::value(std::string& val) +{ + bool ret = false; + + if (is_leaf_node() && type_ == VAL_TYPE_STRING) + { + val = strval_; + ret = true; + } + + return ret; +} +gb_json& gb_json::operator=(bool val) +{ + if (is_leaf_node()) + { + simple_val_.bval = val; + type_ = VAL_TYPE_BOOL; + } + + return *this; +} +gb_json& gb_json::operator=(int val) +{ + if (is_leaf_node()) + { + simple_val_.nval = val; + type_ = VAL_TYPE_INT; + } + + return *this; +} +gb_json& gb_json::operator=(double val) +{ + if (is_leaf_node()) + { + simple_val_.dval = val; + type_ = VAL_TYPE_FLOAT; + } + + return *this; +} +gb_json& gb_json::operator=(const char* val) +{ + if (is_leaf_node()) + { + strval_ = val ? val : ""; + type_ = VAL_TYPE_STRING; + } + + return *this; +} diff --git a/sdk/json/gb_json.h b/sdk/json/gb_json.h new file mode 100644 index 0000000..f86dca9 --- /dev/null +++ b/sdk/json/gb_json.h @@ -0,0 +1,113 @@ +#pragma once + +#include +#include +#include + +struct cJSON; + +class gb_json +{ + volatile int32_t ref_; + std::mutex ref_mutex_; + + 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 arr_val_; + size_t cur_child_; + + static std::string object_key(gb_json* jsn); + static std::string array_key(gb_json* jsn); + + void from_cjson(cJSON* cj); + gb_json* find_child(const char* key, bool remove = false); + +public: + gb_json(char* json_txt = 0); + +protected: + gb_json(const char* key, bool val); + gb_json(const char* key, int val); + gb_json(const char* key, double val); + gb_json(const char* key, const char* val); + ~gb_json(); + +public: + int32_t add_ref(); + int32_t release(); + +public: + // parse/un-parse ... + 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, gb_json*& val); + + // enumeration ... + size_t children(void); // return children count if was object or array, or else -1 returned + gb_json* child(size_t ind); + gb_json* first_child(void); + gb_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, gb_json* val); + + // operator+= only for array + gb_json& operator+=(bool val); + gb_json& operator+=(int val); + gb_json& operator+=(double val); + gb_json& operator+=(const char* val); + gb_json& operator+=(gb_json* val); + + // remove item + gb_json& operator-=(int ind); + bool remove(const char* key); + bool remove(gb_json* child); + bool remove(int ind); + + // position management + int index(gb_json* child); + int index_move_to(gb_json* child, int ind); + + // leaf node value ... + bool value(bool& val); + bool value(int& val); + bool value(double& val); + bool value(std::string& val); + gb_json& operator=(bool val); + gb_json& operator=(int val); + gb_json& operator=(double val); + gb_json& operator=(const char* val); +}; diff --git a/twain/ds/sane_helper.cpp b/twain/ds/sane_helper.cpp index 8301e9f..9261d1b 100644 --- a/twain/ds/sane_helper.cpp +++ b/twain/ds/sane_helper.cpp @@ -40,35 +40,6 @@ namespace win_util return ret; } - HMODULE load_dll(const char* path_dll, int flag, int* err) - { - HMODULE h = LoadLibraryA(path_dll); - int ret = GetLastError(); - - utils::to_log(1, "[TWAIN]Load: LoadLibraryA(%s) = %d\r\n", path_dll, ret); - if (!h && (ret == ERROR_MOD_NOT_FOUND || ret == ERROR_BAD_EXE_FORMAT)) - { - std::string dir(path_dll); - size_t pos = dir.rfind('\\'); - char path[MAX_PATH] = { 0 }; - - GetDllDirectoryA(_countof(path) - 1, path); - if (pos != std::wstring::npos) - dir.erase(pos); - utils::to_log(LOG_LEVEL_FATAL, "[TWAIN]Load: change directory to '%s' and retry LoadLibraryA(%s) ...\r\n", dir.c_str(), path_dll); - SetDllDirectoryA(dir.c_str()); - h = LoadLibraryA(path_dll); - // h = LoadLibraryExW(path_dll, NULL, LOAD_WITH_ALTERED_SEARCH_PATH); - ret = GetLastError(); - utils::to_log(1, "[TWAIN]Load: trying LoadLibraryA(%s) = %d, restore directory to '%s'\r\n", path_dll, ret, path); - SetDllDirectoryA(path); - } - - if (err) - *err = ret; - - return h; - } }; #else #include @@ -128,15 +99,16 @@ void sane_helper::clear(void) bool sane_helper::load_sane(const char* vendor) // libsane_hgsane.so.1, and vendor is 'hgsane' { + bool ok = true; + + clear(); + #if OS_WIN std::string file(dll_root_ + "sane.dll"), func("sane_"); #else std::string file(dll_root_ + "libsane-" + vendor + ".so.1"), func("sane_"); #endif - bool ok = true; - - clear(); - dll_handle_ = LOAD_LIB(file.c_str(), LOAD_WITH_ALTERED_SEARCH_PATH); + dll_handle_ = utils::load_dll(file.c_str(), LOAD_WITH_ALTERED_SEARCH_PATH); if(!dll_handle_) { utils::to_log(7, "load sane library(%s) = %s\n", file.c_str(), strerror(errno)); diff --git a/twain/ds/scanned_img.cpp b/twain/ds/scanned_img.cpp index bf254af..50824c4 100644 --- a/twain/ds/scanned_img.cpp +++ b/twain/ds/scanned_img.cpp @@ -1,5 +1,7 @@ #include "scanned_img.h" + #include "sane_helper.h" +#include "../../sdk/hginclude/utils.h" #include @@ -14,7 +16,7 @@ namespace local_trans int load_lang_pak(const char* dll) { - HMODULE h = LOAD_LIB(dll, LOAD_WITH_ALTERED_SEARCH_PATH); + HMODULE h = utils::load_dll(dll, LOAD_WITH_ALTERED_SEARCH_PATH); if(!h) return GetLastError(); diff --git a/twain/ds/scanner.cpp b/twain/ds/scanner.cpp index 5beb382..e22e663 100644 --- a/twain/ds/scanner.cpp +++ b/twain/ds/scanner.cpp @@ -280,7 +280,7 @@ namespace callback FreeLibrary(hui); // hui = LoadLibraryExA(root.c_str(), nullptr, LOAD_WITH_ALTERED_SEARCH_PATH); - hui = LOAD_LIB(root.c_str(), LOAD_WITH_ALTERED_SEARCH_PATH); + hui = utils::load_dll(root.c_str(), LOAD_WITH_ALTERED_SEARCH_PATH); if (!hui) { std::string info("Load '" + root);