diff --git a/core/device.cpp b/core/device.cpp index e9a63cc11..c49e2dd5f 100644 --- a/core/device.cpp +++ b/core/device.cpp @@ -8,7 +8,7 @@ #include "selection.h" #include "core/settings/qPrefDiveComputer.h" -struct fingerprint_table fingerprint_table; +fingerprint_table fingerprints; static bool same_device(const device &dev1, const device &dev2) { @@ -133,111 +133,68 @@ std::string get_dc_nickname(const struct divecomputer *dc) // managing fingerprint data bool fingerprint_record::operator<(const fingerprint_record &a) const { - if (model == a.model) - return serial < a.serial; - return model < a.model; + return std::tie(model, serial) < std::tie(a.model, a.serial); } // annoyingly, the Cressi Edy doesn't support a serial number (it's always 0), but still uses fingerprints // so we can't bail on the serial number being 0 -unsigned int get_fingerprint_data(const struct fingerprint_table *table, uint32_t model, uint32_t serial, const unsigned char **fp_out) +std::pair get_fingerprint_data(const fingerprint_table &table, uint32_t model, uint32_t serial) { - if (model == 0 || fp_out == nullptr) - return 0; + if (model == 0) + return { 0, nullptr }; struct fingerprint_record fpr = { model, serial }; - auto it = std::lower_bound(table->fingerprints.begin(), table->fingerprints.end(), fpr); - if (it != table->fingerprints.end() && it->model == model && it->serial == serial) { + auto it = std::lower_bound(table.begin(), table.end(), fpr); + if (it != table.end() && it->model == model && it->serial == serial) { // std::lower_bound gets us the first element that isn't smaller than what we are looking // for - so if one is found, we still need to check for equality - if (has_dive(it->fdeviceid, it->fdiveid)) { - *fp_out = it->raw_data; - return it->fsize; - } + if (has_dive(it->fdeviceid, it->fdiveid)) + return { it->fsize, it->raw_data.get() }; } - return 0; + return { 0, nullptr }; } -void create_fingerprint_node(struct fingerprint_table *table, uint32_t model, uint32_t serial, - const unsigned char *raw_data_in, unsigned int fsize, uint32_t fdeviceid, uint32_t fdiveid) +void create_fingerprint_node(fingerprint_table &table, uint32_t model, uint32_t serial, + const unsigned char *raw_data_in, unsigned int fsize, uint32_t fdeviceid, uint32_t fdiveid) { // since raw data can contain \0 we copy this manually, not as string - unsigned char *raw_data = (unsigned char *)malloc(fsize); - if (!raw_data) - return; - memcpy(raw_data, raw_data_in, fsize); + auto raw_data = std::make_unique(fsize); + std::copy(raw_data_in, raw_data_in + fsize, raw_data.get()); - struct fingerprint_record fpr = { model, serial, raw_data, fsize, fdeviceid, fdiveid }; - auto it = std::lower_bound(table->fingerprints.begin(), table->fingerprints.end(), fpr); - if (it != table->fingerprints.end() && it->model == model && it->serial == serial) { + struct fingerprint_record fpr = { model, serial, std::move(raw_data), fsize, fdeviceid, fdiveid }; + auto it = std::lower_bound(table.begin(), table.end(), fpr); + if (it != table.end() && it->model == model && it->serial == serial) { // std::lower_bound gets us the first element that isn't smaller than what we are looking // for - so if one is found, we still need to check for equality - and then we // can update the existing entry; first we free the memory for the stored raw data - free(it->raw_data); it->fdeviceid = fdeviceid; it->fdiveid = fdiveid; - it->raw_data = raw_data; + it->raw_data = std::move(fpr.raw_data); it->fsize = fsize; } else { // insert a new one - table->fingerprints.insert(it, fpr); + table.insert(it, std::move(fpr)); } } -void create_fingerprint_node_from_hex(struct fingerprint_table *table, uint32_t model, uint32_t serial, - const char *hex_data, uint32_t fdeviceid, uint32_t fdiveid) +void create_fingerprint_node_from_hex(fingerprint_table &table, uint32_t model, uint32_t serial, + const std::string &hex_data, uint32_t fdeviceid, uint32_t fdiveid) { - QByteArray raw = QByteArray::fromHex(hex_data); + QByteArray raw = QByteArray::fromHex(hex_data.c_str()); create_fingerprint_node(table, model, serial, (const unsigned char *)raw.constData(), raw.size(), fdeviceid, fdiveid); } -int nr_fingerprints(struct fingerprint_table *table) -{ - return table->fingerprints.size(); -} - -uint32_t fp_get_model(struct fingerprint_table *table, unsigned int i) -{ - if (!table || i >= table->fingerprints.size()) - return 0; - return table->fingerprints[i].model; -} - -uint32_t fp_get_serial(struct fingerprint_table *table, unsigned int i) -{ - if (!table || i >= table->fingerprints.size()) - return 0; - return table->fingerprints[i].serial; -} - -uint32_t fp_get_deviceid(struct fingerprint_table *table, unsigned int i) -{ - if (!table || i >= table->fingerprints.size()) - return 0; - return table->fingerprints[i].fdeviceid; -} - -uint32_t fp_get_diveid(struct fingerprint_table *table, unsigned int i) -{ - if (!table || i >= table->fingerprints.size()) - return 0; - return table->fingerprints[i].fdiveid; -} - static char to_hex_digit(unsigned char d) { return d <= 9 ? d + '0' : d - 10 + 'a'; } -std::string fp_get_data(struct fingerprint_table *table, unsigned int i) +std::string fingerprint_record::get_data() const { - if (!table || i >= table->fingerprints.size()) - return std::string(); - struct fingerprint_record *fpr = &table->fingerprints[i]; - std::string res(fpr->fsize * 2, ' '); - for (unsigned int i = 0; i < fpr->fsize; ++i) { - res[2 * i] = to_hex_digit((fpr->raw_data[i] >> 4) & 0xf); - res[2 * i + 1] = to_hex_digit(fpr->raw_data[i] & 0xf); + std::string res(fsize * 2, ' '); + for (unsigned int i = 0; i < fsize; ++i) { + res[2 * i] = to_hex_digit((raw_data[i] >> 4) & 0xf); + res[2 * i + 1] = to_hex_digit(raw_data[i] & 0xf); } return res; } diff --git a/core/device.h b/core/device.h index 0ad1bd617..5616148c8 100644 --- a/core/device.h +++ b/core/device.h @@ -3,6 +3,7 @@ #define DEVICE_H #include +#include #include #include @@ -20,9 +21,6 @@ struct device { using device_table = std::vector; -// global device table -extern struct fingerprint_table fingerprint_table; - extern int create_device_node(device_table &table, const std::string &model, const std::string &serial, const std::string &nickname); std::string get_dc_nickname(const struct divecomputer *dc); extern bool device_used_by_selected_dive(const struct device &dev); @@ -34,20 +32,29 @@ extern int add_to_device_table(device_table &table, const struct device &dev); / extern int remove_device(device_table &table, const struct device &dev); // returns index or -1 if not found extern void remove_from_device_table(device_table &table, int idx); -// create fingerprint entry - raw data remains owned by caller -extern void create_fingerprint_node(struct fingerprint_table *table, uint32_t model, uint32_t serial, - const unsigned char *raw_data, unsigned int fsize, uint32_t fdeviceid, uint32_t fdiveid); -extern void create_fingerprint_node_from_hex(struct fingerprint_table *table, uint32_t model, uint32_t serial, - const char *hex_data, uint32_t fdeviceid, uint32_t fdiveid); -// look up the fingerprint for model/serial - returns the number of bytes in the fingerprint; memory owned by the table -extern unsigned int get_fingerprint_data(const struct fingerprint_table *table, uint32_t model, uint32_t serial, const unsigned char **fp_out); +struct fingerprint_record { + bool operator<(const fingerprint_record &a) const; + uint32_t model; // model and libdivecomputer serial number to + uint32_t serial; // look up the fingerprint + std::unique_ptr raw_data; // fingerprint data as provided by libdivecomputer + unsigned int fsize; // size of raw fingerprint data + unsigned int fdeviceid; // corresponding deviceid + unsigned int fdiveid; // corresponding diveid + std::string get_data() const; // As hex-string +}; -// access the fingerprint data from C -extern int nr_fingerprints(struct fingerprint_table *table); -extern uint32_t fp_get_model(struct fingerprint_table *table, unsigned int i); -extern uint32_t fp_get_serial(struct fingerprint_table *table, unsigned int i); -extern uint32_t fp_get_deviceid(struct fingerprint_table *table, unsigned int i); -extern uint32_t fp_get_diveid(struct fingerprint_table *table, unsigned int i); +using fingerprint_table = std::vector; + +// global device table +extern fingerprint_table fingerprints; + +// create fingerprint entry - raw data remains owned by caller +extern void create_fingerprint_node(fingerprint_table &table, uint32_t model, uint32_t serial, + const unsigned char *raw_data, unsigned int fsize, uint32_t fdeviceid, uint32_t fdiveid); +extern void create_fingerprint_node_from_hex(fingerprint_table &table, uint32_t model, uint32_t serial, + const std::string &hex_data, uint32_t fdeviceid, uint32_t fdiveid); +// look up the fingerprint for model/serial - returns the number of bytes in the fingerprint; memory owned by the table +extern std::pair get_fingerprint_data(const fingerprint_table &table, uint32_t model, uint32_t serial); extern int is_default_dive_computer_device(const char *); @@ -55,21 +62,5 @@ typedef void (*device_callback_t)(const char *name, void *userdata); extern int enumerate_devices(device_callback_t callback, void *userdata, unsigned int transport); -struct fingerprint_record { - bool operator<(const fingerprint_record &a) const; - uint32_t model; // model and libdivecomputer serial number to - uint32_t serial; // look up the fingerprint - unsigned char *raw_data; // fingerprint data as provided by libdivecomputer - unsigned int fsize; // size of raw fingerprint data - unsigned int fdeviceid; // corresponding deviceid - unsigned int fdiveid; // corresponding diveid -}; - -struct fingerprint_table { - // Keep the fingerprint records in a vector sorted by (model, serial) - these are uint32_t here - std::vector fingerprints; -}; - -std::string fp_get_data(struct fingerprint_table *table, unsigned int i); #endif // DEVICE_H diff --git a/core/libdivecomputer.cpp b/core/libdivecomputer.cpp index 0efed9f32..7bb040cb1 100644 --- a/core/libdivecomputer.cpp +++ b/core/libdivecomputer.cpp @@ -1010,13 +1010,11 @@ static void verify_fingerprint(dc_device_t *device, device_data_t *devdata, cons */ static void lookup_fingerprint(dc_device_t *device, device_data_t *devdata) { - const unsigned char *raw_data; - if (devdata->force_download) return; /* first try our in memory data - raw_data is owned by the table, the dc_device_set_fingerprint function copies the data */ - int fsize = get_fingerprint_data(&fingerprint_table, calculate_string_hash(devdata->model.c_str()), devdata->devinfo.serial, &raw_data); + auto [fsize, raw_data] = get_fingerprint_data(fingerprints, calculate_string_hash(devdata->model.c_str()), devdata->devinfo.serial); if (fsize) { if (verbose) dev_info(devdata, "... found fingerprint in dive table"); @@ -1538,7 +1536,7 @@ std::string do_libdivecomputer_import(device_data_t *data) */ save_fingerprint(data); if (data->fingerprint && data->fdiveid) - create_fingerprint_node(&fingerprint_table, calculate_string_hash(data->model.c_str()), data->devinfo.serial, + create_fingerprint_node(fingerprints, calculate_string_hash(data->model.c_str()), data->devinfo.serial, data->fingerprint, data->fsize, data->fdeviceid, data->fdiveid); free(data->fingerprint); data->fingerprint = NULL; diff --git a/core/load-git.cpp b/core/load-git.cpp index 6863ff842..d75e8ccd3 100644 --- a/core/load-git.cpp +++ b/core/load-git.cpp @@ -1042,8 +1042,8 @@ static void parse_settings_fingerprint(char *line, struct git_parser_state *stat } if (verbose > 1) report_info("fingerprint %08x %08x %08x %08x %s\n", fph.model, fph.serial, fph.fdeviceid, fph.fdiveid, fph.hex_data.c_str()); - create_fingerprint_node_from_hex(&fingerprint_table, fph.model, fph.serial, - fph.hex_data.c_str(), fph.fdeviceid, fph.fdiveid); + create_fingerprint_node_from_hex(fingerprints, fph.model, fph.serial, + fph.hex_data, fph.fdeviceid, fph.fdiveid); } static void parse_picture_filename(char *, struct git_parser_state *state) diff --git a/core/parse-xml.cpp b/core/parse-xml.cpp index 78ae13f2a..dccbad640 100644 --- a/core/parse-xml.cpp +++ b/core/parse-xml.cpp @@ -1749,7 +1749,7 @@ int parse_xml_buffer(const char *url, const char *buffer, int, struct divelog *l struct parser_state state; state.log = log; - state.fingerprints = &fingerprint_table; // simply use the global table for now + state.fingerprints = &fingerprints; // simply use the global table for now doc = xmlReadMemory(res, strlen(res), url, NULL, XML_PARSE_HUGE); if (!doc) doc = xmlReadMemory(res, strlen(res), url, "latin1", XML_PARSE_HUGE); diff --git a/core/parse.cpp b/core/parse.cpp index 4e9d3143d..7ce981ed7 100644 --- a/core/parse.cpp +++ b/core/parse.cpp @@ -162,10 +162,10 @@ void fingerprint_settings_start(struct parser_state *state) void fingerprint_settings_end(struct parser_state *state) { - create_fingerprint_node_from_hex(state->fingerprints, + create_fingerprint_node_from_hex(*state->fingerprints, state->cur_settings.fingerprint.model, state->cur_settings.fingerprint.serial, - state->cur_settings.fingerprint.data.c_str(), + state->cur_settings.fingerprint.data, state->cur_settings.fingerprint.fdeviceid, state->cur_settings.fingerprint.fdiveid); } diff --git a/core/parse.h b/core/parse.h index 5a69b9b91..24dbbf5c0 100644 --- a/core/parse.h +++ b/core/parse.h @@ -12,9 +12,11 @@ #include #include #include +#include struct xml_params; struct divelog; +struct fingerprint_record; /* * Dive info as it is being built up.. @@ -82,7 +84,8 @@ struct parser_state { struct { std::string key; std::string value; } cur_extra_data; struct units xml_parsing_units; struct divelog *log = nullptr; /* non-owning */ - struct fingerprint_table *fingerprints = nullptr; /* non-owning */ + std::vector *fingerprints = nullptr; + /* non-owning */ sqlite3 *sql_handle = nullptr; /* for SQL based parsers */ bool event_active = false; diff --git a/core/save-git.cpp b/core/save-git.cpp index 4565ff343..90c16c267 100644 --- a/core/save-git.cpp +++ b/core/save-git.cpp @@ -847,14 +847,10 @@ static void save_one_device(struct membuffer *b, const struct device &d) put_string(b, "\n"); } -static void save_one_fingerprint(struct membuffer *b, int i) +static void save_one_fingerprint(struct membuffer *b, const fingerprint_record &fp) { put_format(b, "fingerprint model=%08x serial=%08x deviceid=%08x diveid=%08x data=\"%s\"\n", - fp_get_model(&fingerprint_table, i), - fp_get_serial(&fingerprint_table, i), - fp_get_deviceid(&fingerprint_table, i), - fp_get_diveid(&fingerprint_table, i), - fp_get_data(&fingerprint_table, i).c_str()); + fp.model, fp.serial, fp.fdeviceid, fp.fdiveid, fp.get_data().c_str()); } static void save_settings(git_repository *repo, struct dir *tree) @@ -865,8 +861,8 @@ static void save_settings(git_repository *repo, struct dir *tree) for (auto &dev: divelog.devices) save_one_device(&b, dev); /* save the fingerprint data */ - for (int i = 0; i < nr_fingerprints(&fingerprint_table); i++) - save_one_fingerprint(&b, i); + for (auto &fp: fingerprints) + save_one_fingerprint(&b, fp); cond_put_format(divelog.autogroup, &b, "autogroup\n"); save_units(&b); diff --git a/core/save-xml.cpp b/core/save-xml.cpp index 604aa89fe..e896586d9 100644 --- a/core/save-xml.cpp +++ b/core/save-xml.cpp @@ -582,14 +582,10 @@ static void save_one_device(struct membuffer *b, const struct device &d) put_format(b, "/>\n"); } -static void save_one_fingerprint(struct membuffer *b, int i) +static void save_one_fingerprint(struct membuffer *b, const fingerprint_record &fp) { put_format(b, "\n", - fp_get_model(&fingerprint_table, i), - fp_get_serial(&fingerprint_table, i), - fp_get_deviceid(&fingerprint_table, i), - fp_get_diveid(&fingerprint_table, i), - fp_get_data(&fingerprint_table, i).c_str()); + fp.model, fp.serial, fp.fdeviceid, fp.fdiveid, fp.get_data().c_str()); } int save_dives(const char *filename) @@ -656,8 +652,8 @@ static void save_dives_buffer(struct membuffer *b, bool select_only, bool anonym save_one_device(b, d); } /* save the fingerprint data */ - for (int i = 0; i < nr_fingerprints(&fingerprint_table); i++) - save_one_fingerprint(b, i); + for (auto &fp: fingerprints) + save_one_fingerprint(b, fp); if (divelog.autogroup) put_format(b, " \n");