Option_Descriptor采用二级指针,成员变化时只调整二级指针的内容,以保证一级指针不变

This commit is contained in:
gb 2023-06-19 18:40:05 +08:00
parent fe530a6c8a
commit e6eaefb511
4 changed files with 112 additions and 128 deletions

View File

@ -708,37 +708,54 @@ SANE_Handle hg_sane_middleware::scanner_handle_to_sane(scanner_handle h)
return (SANE_Handle)(v);
}
SANE_Option_Descriptor* hg_sane_middleware::allocate_descriptor(const char* name, const char* title, const char* desc)
{
SANE_Option_Descriptor* opdesc = (SANE_Option_Descriptor*)local_utility::acquire_memory(sizeof(SANE_Option_Descriptor), "SANE_Option_Descriptor");
memset(opdesc, 0, sizeof(SANE_Option_Descriptor));
opdesc->name = (char*)local_utility::acquire_memory(strlen(name) + 1, "SANE_Option_Descriptor::name");
strcpy((char*)opdesc->name, name);
opdesc->title = (char*)local_utility::acquire_memory(strlen(title) + 1, "SANE_Option_Descriptor::title");
strcpy((char*)opdesc->title, title);
opdesc->desc = (char*)local_utility::acquire_memory(strlen(desc) + 1, "SANE_Option_Descriptor::desc");
strcpy((char*)opdesc->desc, desc);
return opdesc;
}
void hg_sane_middleware::free_descriptor(SANE_Option_Descriptor* desc)
{
if (desc)
{
if (desc->name)
local_utility::free_memory((void*)desc->name);
desc->name = nullptr;
if (desc->title)
local_utility::free_memory((void*)desc->title);
desc->title = nullptr;
if (desc->desc)
local_utility::free_memory((void*)desc->desc);
desc->desc = nullptr;
if (desc->constraint.range)
local_utility::free_memory((void*)desc->constraint.range);
desc->constraint.range = nullptr;
local_utility::free_memory(desc);
}
}
SANE_Option_Descriptor* hg_sane_middleware::string_option_to_SANE_descriptor(const char* name, const char* title, const char* desc
, const std::vector<std::string>& values)
{
int bytes = sizeof(SANE_Option_Descriptor) + sizeof(char*);
SANE_Option_Descriptor *sod = NULL;
char *str = NULL, **str_arr = NULL;
int bytes = (values.size() + 1) * sizeof(SANE_String);
SANE_Option_Descriptor *sod = hg_sane_middleware::allocate_descriptor(name, title, desc);
bytes += ALIGN_INT(strlen(name) + 1);
bytes += ALIGN_INT(strlen(title) + 1);
bytes += ALIGN_INT(strlen(desc) + 1);
bytes += sizeof(SANE_Option_Descriptor);
bytes += sizeof(char*);
for (size_t i = 0; i < values.size(); ++i)
bytes += ALIGN_INT(values[i].length() + 1);
bytes += sizeof(char*) * (values.size() + 1);
sod = (SANE_Option_Descriptor*)local_utility::acquire_memory(bytes, "hg_sane_middleware::string_option_to_SANE_descriptor");
bzero(sod, bytes);
str = (char*)sod;
str += sizeof(SANE_Option_Descriptor);
sod->name = str;
strcpy(str, name);
str += ALIGN_INT(strlen(str) + 1);
sod->title = str;
strcpy(str, title);
str += ALIGN_INT(strlen(str) + 1);
sod->desc = str;
strcpy(str, desc);
str += ALIGN_INT(strlen(str) + 1);
sod->type = SANE_TYPE_STRING;
sod->unit = SANE_UNIT_NONE;
@ -747,51 +764,27 @@ SANE_Option_Descriptor* hg_sane_middleware::string_option_to_SANE_descriptor(con
| SANE_CAP_AUTOMATIC; // 硬件可设置默认<E9BB98>?
if (values.size())
{
SANE_String* buf = (SANE_String*)local_utility::acquire_memory(bytes, "string_list");
char* str = (char*)buf + (values.size() + 1) * sizeof(SANE_String);
sod->constraint_type = SANE_CONSTRAINT_STRING_LIST;
sod->constraint.string_list = (char**)str;
str_arr = (char**)str;
str += (values.size() + 1) * sizeof(char*);
sod->constraint.string_list = buf;
for (size_t i = 0; i < values.size(); ++i)
{
str_arr[i] = str;
buf[i] = str;
strcpy(str, values[i].c_str());
str += ALIGN_INT(values[i].length() + 1);
}
}
//VLOG_MINI_2(LOG_LEVEL_ALL, "Memory usage: %u/%u\n", str - (char*)sod, bytes);
return sod;
}
SANE_Option_Descriptor* hg_sane_middleware::number_option_to_SANE_descriptor(const char* name, const char* title, const char* desc
, bool double_val, double* lower, double* upper, double* step)
{
int bytes = sizeof(SANE_Option_Descriptor) + sizeof(SANE_Range);
SANE_Option_Descriptor *sod = NULL;
char *str = NULL;
bytes += ALIGN_INT(strlen(name) + 1);
bytes += ALIGN_INT(strlen(title) + 1);
bytes += ALIGN_INT(strlen(desc) + 1);
bytes += sizeof(SANE_Option_Descriptor);
bytes += sizeof(SANE_Range*) + sizeof(SANE_Range);
sod = (SANE_Option_Descriptor*)local_utility::acquire_memory(bytes, "hg_sane_middleware::number_option_to_SANE_descriptor");
bzero(sod, bytes);
str = (char*)sod;
str += sizeof(SANE_Option_Descriptor);
sod->name = str;
strcpy(str, name);
str += ALIGN_INT(strlen(str) + 1);
sod->title = str;
strcpy(str, title);
str += ALIGN_INT(strlen(str) + 1);
sod->desc = str;
strcpy(str, desc);
str += ALIGN_INT(strlen(str) + 1);
SANE_Option_Descriptor *sod = hg_sane_middleware::allocate_descriptor(name, title, desc);
sod->type = double_val ? SANE_TYPE_FIXED : SANE_TYPE_INT;
sod->unit = SANE_UNIT_NONE;
@ -802,33 +795,33 @@ SANE_Option_Descriptor* hg_sane_middleware::number_option_to_SANE_descriptor(con
{
sod->size = sizeof(SANE_Range);
sod->constraint_type = SANE_CONSTRAINT_RANGE;
sod->constraint.range = (SANE_Range*)str;
SANE_Range* range = (SANE_Range*)local_utility::acquire_memory(sizeof(SANE_Range), "constraint.range");
if (lower)
{
if (double_val)
(*(SANE_Range*)str).min = hg_sane_middleware::double_2_sane_fixed(*lower);
range->min = hg_sane_middleware::double_2_sane_fixed(*lower);
else
(*(SANE_Range*)str).min = (SANE_Word)*lower;
range->min = (SANE_Word)*lower;
}
if (upper)
{
if (double_val)
(*(SANE_Range*)str).max = hg_sane_middleware::double_2_sane_fixed(*upper);
range->max = hg_sane_middleware::double_2_sane_fixed(*upper);
else
(*(SANE_Range*)str).max = (SANE_Word)*upper;
range->max = (SANE_Word)*upper;
}
(*(SANE_Range*)str).quant = 0;
range->quant = 0;
if (step)
{
if(double_val)
(*(SANE_Range*)str).quant = hg_sane_middleware::double_2_sane_fixed(*step);
range->quant = hg_sane_middleware::double_2_sane_fixed(*step);
else
(*(SANE_Range*)str).quant = (SANE_Word)(*step);
range->quant = (SANE_Word)(*step);
}
str = (char*)((SANE_Range*)str + 1);
sod->constraint.range = range;
}
//VLOG_MINI_2(LOG_LEVEL_ALL, "Memory usage: %u/%u\n", str - (char*)sod, bytes);
return sod;
}
@ -836,30 +829,7 @@ SANE_Option_Descriptor* hg_sane_middleware::number_option_to_SANE_descriptor(con
, const std::vector<int>& values)
{
int bytes = sizeof(SANE_Option_Descriptor) + sizeof(SANE_Range);
SANE_Option_Descriptor* sod = NULL;
char* str = NULL;
bytes += ALIGN_INT(strlen(name) + 1);
bytes += ALIGN_INT(strlen(title) + 1);
bytes += ALIGN_INT(strlen(desc) + 1);
bytes += sizeof(SANE_Option_Descriptor);
bytes += sizeof(SANE_Word*) + sizeof(SANE_Word) * (values.size() + 1);
sod = (SANE_Option_Descriptor*)local_utility::acquire_memory(bytes, "hg_sane_middleware::number_option_to_SANE_descriptor");
bzero(sod, bytes);
str = (char*)sod;
str += sizeof(SANE_Option_Descriptor);
sod->name = str;
strcpy(str, name);
str += ALIGN_INT(strlen(str) + 1);
sod->title = str;
strcpy(str, title);
str += ALIGN_INT(strlen(str) + 1);
sod->desc = str;
strcpy(str, desc);
str += ALIGN_INT(strlen(str) + 1);
SANE_Option_Descriptor* sod = hg_sane_middleware::allocate_descriptor(name, title, desc);
sod->type = SANE_TYPE_INT;
sod->unit = SANE_UNIT_NONE;
@ -869,14 +839,12 @@ SANE_Option_Descriptor* hg_sane_middleware::number_option_to_SANE_descriptor(con
if (values.size())
{
SANE_Word *val = (SANE_Word*)str;
sod->constraint.word_list = val;
sod->constraint.word_list = (SANE_Word*)local_utility::acquire_memory(sizeof(SANE_Word) * (values.size() + 1), "word_list");
SANE_Word* val = (SANE_Word*)sod->constraint.word_list;
sod->constraint_type = SANE_CONSTRAINT_WORD_LIST;
*val++ = values.size();
for (size_t i = 0; i < values.size(); ++i)
val[i] = values[i];
str = (char*)(val + values.size());
}
//VLOG_MINI_2(LOG_LEVEL_ALL, "Memory usage: %u/%u\n", str - (char*)sod, bytes);
@ -886,30 +854,7 @@ SANE_Option_Descriptor* hg_sane_middleware::number_option_to_SANE_descriptor(con
, const std::vector<double>& values)
{
int bytes = sizeof(SANE_Option_Descriptor) + sizeof(SANE_Range);
SANE_Option_Descriptor* sod = NULL;
char* str = NULL;
bytes += ALIGN_INT(strlen(name) + 1);
bytes += ALIGN_INT(strlen(title) + 1);
bytes += ALIGN_INT(strlen(desc) + 1);
bytes += sizeof(SANE_Option_Descriptor);
bytes += sizeof(SANE_Word*) + sizeof(SANE_Word) * (values.size() + 1);
sod = (SANE_Option_Descriptor*)local_utility::acquire_memory(bytes, "hg_sane_middleware::number_option_to_SANE_descriptor");
bzero(sod, bytes);
str = (char*)sod;
str += sizeof(SANE_Option_Descriptor);
sod->name = str;
strcpy(str, name);
str += ALIGN_INT(strlen(str) + 1);
sod->title = str;
strcpy(str, title);
str += ALIGN_INT(strlen(str) + 1);
sod->desc = str;
strcpy(str, desc);
str += ALIGN_INT(strlen(str) + 1);
SANE_Option_Descriptor* sod = hg_sane_middleware::allocate_descriptor(name, title, desc);
sod->type = SANE_TYPE_FIXED;
sod->unit = SANE_UNIT_NONE;
@ -919,16 +864,13 @@ SANE_Option_Descriptor* hg_sane_middleware::number_option_to_SANE_descriptor(con
if (values.size())
{
SANE_Word* val = (SANE_Word*)str;
sod->constraint.word_list = val;
sod->constraint.word_list = (SANE_Word*)local_utility::acquire_memory(sizeof(SANE_Word) * (values.size() + 1), "word_list");
SANE_Word* val = (SANE_Word*)sod->constraint.word_list;
sod->constraint_type = SANE_CONSTRAINT_WORD_LIST;
*val++ = values.size();
for (size_t i = 0; i < values.size(); ++i)
val[i] = hg_sane_middleware::double_2_sane_fixed(values[i]);
str = (char*)(val + values.size());
}
//VLOG_MINI_2(LOG_LEVEL_ALL, "Memory usage: %u/%u\n", str - (char*)sod, bytes);
return sod;
}
@ -979,12 +921,39 @@ void hg_sane_middleware::reload_options(scanner_handle dev)
if (dev && dev != v->dev)
continue;
hg_sane_middleware::free_device_inst(v, false);
std::vector<DEVOPT> opts(std::move(v->opts));
long count = 0;
hg_sane_middleware::free_device_inst(v, false);
hg_scanner_get_parameter(v->dev, nullptr, NULL, &count);
for (long ind = 1; ind < count; ++ind)
{
get_option_descriptor(hg_sane_middleware::scanner_handle_to_sane(v->dev), (void*)ind);
int n = v->opts.size() - 1;
if (n >= 0)
{
for (int i = 0; i < opts.size(); ++i)
{
if (v->opts[n].opt_name == opts[i].opt_name)
{
local_utility::free_memory((void*)opts[i].desc->name);
local_utility::free_memory((void*)opts[i].desc->title);
local_utility::free_memory((void*)opts[i].desc->desc);
local_utility::free_memory((void*)opts[i].desc->constraint.range);
*opts[i].desc = *v->opts[n].desc;
v->opts[n].desc->name = v->opts[n].desc->title = v->opts[n].desc->desc = nullptr;
v->opts[n].desc->constraint.range = nullptr;
hg_sane_middleware::free_descriptor(v->opts[n].desc);
v->opts[n].desc = opts[i].desc;
opts.erase(opts.begin() + i);
break;
}
}
}
}
}
}
SANE_Status hg_sane_middleware::open(SANE_String_Const devicename, SANE_Handle* handle, const char* name, const char* pwd, const char* method, char* rsc)
@ -1247,15 +1216,19 @@ SANE_Option_Descriptor* hg_sane_middleware::from_json(scanner_handle h, const st
}
void hg_sane_middleware::free_device_inst(LPDEVINST dev, bool del)
{
if (dev->std_opt)
delete dev->std_opt;
for (auto& v : dev->opts)
local_utility::free_memory(v.desc);
hg_sane_middleware::free_descriptor(v.desc);
if (del)
{
if (dev->std_opt)
delete dev->std_opt;
delete dev;
}
else
{
if (dev->std_opt)
dev->std_opt->clear();
dev->opts.clear();
dev->cur_vals.clear();
dev->slaves.clear();

View File

@ -204,6 +204,8 @@ public:
static std::string option_value_2_string(SANE_Value_Type type, void* val);
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);
static void free_descriptor(SANE_Option_Descriptor* desc);
static SANE_Option_Descriptor* string_option_to_SANE_descriptor(const char* name, const char* title, const char* desc
, const std::vector<std::string>& values);
static SANE_Option_Descriptor* number_option_to_SANE_descriptor(const char* name, const char* title, const char* desc

View File

@ -313,6 +313,14 @@ SANE_Option_Descriptor* sane_std_opts::get_option(int option)
{
return get_known_option(option);
}
void sane_std_opts::clear(void)
{
for (auto& v : known_opts_)
{
delete[] v.known.desc;
}
known_opts_.clear();
}
bool sane_std_opts::is_known_option(int opt, SANE_Option_Descriptor** user)
{

View File

@ -56,6 +56,7 @@ public:
public:
void init_known_opt(int option, SANE_Option_Descriptor* desc);
SANE_Option_Descriptor* get_option(int option);
void clear(void);
bool is_known_option(int opt, SANE_Option_Descriptor** user = nullptr);
void* get_default_value(scanner_handle h, int opt); // call local_utility::free_memory to free the returned buffer