mirror of
https://github.com/subsurface/subsurface.git
synced 2025-02-19 22:16:15 +00:00
uemis: replace C-strings by std::string and std::string_view
The string code of uemis-downloader.cpp was broken in more ways than can be listed here. Notably, it brazenly refused to free any memory allocated for the parameters buffer. Using std::string and std::string_view should plug all those memory holes. That made it necessary to do some major refactoring. This was done blind and therefore will break. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
This commit is contained in:
parent
17f768b69c
commit
a62b8a3a9b
9 changed files with 384 additions and 403 deletions
|
@ -1,8 +1,10 @@
|
||||||
#include "downloadfromdcthread.h"
|
#include "downloadfromdcthread.h"
|
||||||
#include "core/errorhelper.h"
|
#include "core/errorhelper.h"
|
||||||
|
#include "core/format.h"
|
||||||
#include "core/libdivecomputer.h"
|
#include "core/libdivecomputer.h"
|
||||||
#include "core/qthelper.h"
|
#include "core/qthelper.h"
|
||||||
#include "core/range.h"
|
#include "core/range.h"
|
||||||
|
#include "core/uemis.h"
|
||||||
#include "core/settings/qPrefDiveComputer.h"
|
#include "core/settings/qPrefDiveComputer.h"
|
||||||
#include "core/divelist.h"
|
#include "core/divelist.h"
|
||||||
#if defined(Q_OS_ANDROID)
|
#if defined(Q_OS_ANDROID)
|
||||||
|
@ -15,16 +17,6 @@ static QHash<QString, QStringList> mobileProductList; // BT, BLE or FTDI support
|
||||||
QMap<QString, dc_descriptor_t *> descriptorLookup;
|
QMap<QString, dc_descriptor_t *> descriptorLookup;
|
||||||
ConnectionListModel connectionListModel;
|
ConnectionListModel connectionListModel;
|
||||||
|
|
||||||
static QString str_error(const char *fmt, ...)
|
|
||||||
{
|
|
||||||
va_list args;
|
|
||||||
va_start(args, fmt);
|
|
||||||
const QString str = QString::vasprintf(fmt, args);
|
|
||||||
va_end(args);
|
|
||||||
|
|
||||||
return str;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void updateRememberedDCs()
|
static void updateRememberedDCs()
|
||||||
{
|
{
|
||||||
QString current = qPrefDiveComputer::vendor() + " - " + qPrefDiveComputer::product() + " - " + qPrefDiveComputer::device();
|
QString current = qPrefDiveComputer::vendor() + " - " + qPrefDiveComputer::product() + " - " + qPrefDiveComputer::device();
|
||||||
|
@ -108,19 +100,20 @@ void DownloadThread::run()
|
||||||
clear_divelog(&log);
|
clear_divelog(&log);
|
||||||
|
|
||||||
Q_ASSERT(internalData->log != nullptr);
|
Q_ASSERT(internalData->log != nullptr);
|
||||||
const char *errorText;
|
std::string errorText;
|
||||||
import_thread_cancelled = false;
|
import_thread_cancelled = false;
|
||||||
error.clear();
|
error.clear();
|
||||||
if (!strcmp(internalData->vendor, "Uemis"))
|
if (!strcmp(internalData->vendor, "Uemis"))
|
||||||
errorText = do_uemis_import(internalData);
|
errorText = do_uemis_import(internalData);
|
||||||
else
|
else
|
||||||
errorText = do_libdivecomputer_import(internalData);
|
errorText = do_libdivecomputer_import(internalData);
|
||||||
if (errorText) {
|
if (!errorText.empty()) {
|
||||||
error = str_error(errorText, internalData->devname, internalData->vendor, internalData->product);
|
error = format_string_std(errorText.c_str(), internalData->devname.c_str(),
|
||||||
report_info("Finishing download thread: %s", qPrintable(error));
|
internalData->vendor.c_str(), internalData->product.c_str());
|
||||||
|
report_info("Finishing download thread: %s", error.c_str());
|
||||||
} else {
|
} else {
|
||||||
if (!log.dives->nr)
|
if (!log.dives->nr)
|
||||||
error = tr("No new dives downloaded from dive computer");
|
error = tr("No new dives downloaded from dive computer").toStdString();
|
||||||
report_info("Finishing download thread: %d dives downloaded", log.dives->nr);
|
report_info("Finishing download thread: %d dives downloaded", log.dives->nr);
|
||||||
}
|
}
|
||||||
qPrefDiveComputer::set_vendor(internalData->vendor);
|
qPrefDiveComputer::set_vendor(internalData->vendor);
|
||||||
|
|
|
@ -74,7 +74,7 @@ public:
|
||||||
void run() override;
|
void run() override;
|
||||||
|
|
||||||
DCDeviceData *data();
|
DCDeviceData *data();
|
||||||
QString error;
|
std::string error;
|
||||||
struct divelog log;
|
struct divelog log;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -1141,7 +1141,7 @@ static int cancel_cb(void *)
|
||||||
return import_thread_cancelled;
|
return import_thread_cancelled;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char *do_device_import(device_data_t *data)
|
static std::string do_device_import(device_data_t *data)
|
||||||
{
|
{
|
||||||
dc_status_t rc;
|
dc_status_t rc;
|
||||||
dc_device_t *device = data->device;
|
dc_device_t *device = data->device;
|
||||||
|
@ -1202,7 +1202,7 @@ static const char *do_device_import(device_data_t *data)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* All good */
|
/* All good */
|
||||||
return NULL;
|
return std::string();
|
||||||
}
|
}
|
||||||
|
|
||||||
static dc_timer_t *logfunc_timer = NULL;
|
static dc_timer_t *logfunc_timer = NULL;
|
||||||
|
@ -1465,10 +1465,9 @@ static dc_status_t sync_divecomputer_time(dc_device_t *device)
|
||||||
return dc_device_timesync(device, &now);
|
return dc_device_timesync(device, &now);
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *do_libdivecomputer_import(device_data_t *data)
|
std::string do_libdivecomputer_import(device_data_t *data)
|
||||||
{
|
{
|
||||||
dc_status_t rc;
|
dc_status_t rc;
|
||||||
const char *err;
|
|
||||||
FILE *fp = NULL;
|
FILE *fp = NULL;
|
||||||
|
|
||||||
import_dive_number = 0;
|
import_dive_number = 0;
|
||||||
|
@ -1495,7 +1494,7 @@ const char *do_libdivecomputer_import(device_data_t *data)
|
||||||
fprintf(data->libdc_logfile, "built with libdivecomputer v%s\n", dc_version(NULL));
|
fprintf(data->libdc_logfile, "built with libdivecomputer v%s\n", dc_version(NULL));
|
||||||
}
|
}
|
||||||
|
|
||||||
err = translate("gettextFromC", "Unable to open %s %s (%s)");
|
std::string err = translate("gettextFromC", "Unable to open %s %s (%s)");
|
||||||
|
|
||||||
rc = divecomputer_device_open(data);
|
rc = divecomputer_device_open(data);
|
||||||
|
|
||||||
|
@ -1518,7 +1517,7 @@ const char *do_libdivecomputer_import(device_data_t *data)
|
||||||
/* TODO: Show the logfile to the user on error. */
|
/* TODO: Show the logfile to the user on error. */
|
||||||
dev_info(data, "Import complete");
|
dev_info(data, "Import complete");
|
||||||
|
|
||||||
if (!err && data->sync_time) {
|
if (err.empty() && data->sync_time) {
|
||||||
dev_info(data, "Syncing dive computer time ...");
|
dev_info(data, "Syncing dive computer time ...");
|
||||||
rc = sync_divecomputer_time(data->device);
|
rc = sync_divecomputer_time(data->device);
|
||||||
|
|
||||||
|
|
|
@ -52,8 +52,7 @@ typedef struct {
|
||||||
} device_data_t;
|
} device_data_t;
|
||||||
|
|
||||||
const char *errmsg (dc_status_t rc);
|
const char *errmsg (dc_status_t rc);
|
||||||
const char *do_libdivecomputer_import(device_data_t *data);
|
std::string do_libdivecomputer_import(device_data_t *data);
|
||||||
const char *do_uemis_import(device_data_t *data);
|
|
||||||
dc_status_t libdc_buffer_parser(struct dive *dive, device_data_t *data, unsigned char *buffer, int size);
|
dc_status_t libdc_buffer_parser(struct dive *dive, device_data_t *data, unsigned char *buffer, int size);
|
||||||
void logfunc(dc_context_t *context, dc_loglevel_t loglevel, const char *file, unsigned int line, const char *function, const char *msg, void *userdata);
|
void logfunc(dc_context_t *context, dc_loglevel_t loglevel, const char *file, unsigned int line, const char *function, const char *msg, void *userdata);
|
||||||
dc_descriptor_t *get_descriptor(dc_family_t type, unsigned int model);
|
dc_descriptor_t *get_descriptor(dc_family_t type, unsigned int model);
|
||||||
|
|
|
@ -59,16 +59,17 @@ extern double ascii_strtod(const char *str, const char **ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <string_view>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
// Sadly, starts_with only with C++20!
|
// Sadly, starts_with only with C++20!
|
||||||
inline bool starts_with(const std::string &s, const char *s2)
|
inline bool starts_with(std::string_view s, const char *s2)
|
||||||
{
|
{
|
||||||
return s.rfind(s2, 0) == 0;
|
return s.rfind(s2, 0) == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sadly, std::string::contains only with C++23!
|
// Sadly, std::string::contains only with C++23!
|
||||||
inline bool contains(const std::string &s, char c)
|
inline bool contains(std::string_view s, char c)
|
||||||
{
|
{
|
||||||
return s.find(c) != std::string::npos;
|
return s.find(c) != std::string::npos;
|
||||||
}
|
}
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -109,18 +109,18 @@ static void decode(uint8_t *inbuf, uint8_t *outbuf, int inbuf_len)
|
||||||
/*
|
/*
|
||||||
* convert the base64 data blog
|
* convert the base64 data blog
|
||||||
*/
|
*/
|
||||||
static std::vector<uint8_t> convert_base64(char *base64)
|
static std::vector<uint8_t> convert_base64(std::string_view base64)
|
||||||
{
|
{
|
||||||
int len, datalen;
|
int datalen;
|
||||||
|
int len = (int)base64.size();
|
||||||
|
|
||||||
len = strlen(base64);
|
|
||||||
datalen = (len / 4 + 1) * 3;
|
datalen = (len / 4 + 1) * 3;
|
||||||
if (datalen < 0x123 + 0x25)
|
if (datalen < 0x123 + 0x25)
|
||||||
/* less than header + 1 sample??? */
|
/* less than header + 1 sample??? */
|
||||||
report_info("suspiciously short data block %d", datalen);
|
report_info("suspiciously short data block %d", datalen);
|
||||||
|
|
||||||
std::vector<uint8_t> res(datalen);
|
std::vector<uint8_t> res(datalen);
|
||||||
decode((unsigned char *)base64, res.data(), len);
|
decode((unsigned char *)base64.begin(), res.data(), len);
|
||||||
|
|
||||||
if (memcmp(res.data(), "Dive\01\00\00", 7))
|
if (memcmp(res.data(), "Dive\01\00\00", 7))
|
||||||
report_info("Missing Dive100 header");
|
report_info("Missing Dive100 header");
|
||||||
|
@ -159,14 +159,14 @@ int uemis::get_divespot_id_by_diveid(uint32_t diveid) const
|
||||||
return it != helper_table.end() ? it->second.divespot : -1;
|
return it != helper_table.end() ? it->second.divespot : -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void uemis::set_divelocation(int divespot, char *text, double longitude, double latitude)
|
void uemis::set_divelocation(int divespot, const std::string &text, double longitude, double latitude)
|
||||||
{
|
{
|
||||||
for (auto it: helper_table) {
|
for (auto it: helper_table) {
|
||||||
if (it.second.divespot == divespot) {
|
if (it.second.divespot == divespot) {
|
||||||
struct dive_site *ds = it.second.dive_site;
|
struct dive_site *ds = it.second.dive_site;
|
||||||
if (ds) {
|
if (ds) {
|
||||||
free(ds->name);
|
free(ds->name);
|
||||||
ds->name = strdup(text);
|
ds->name = strdup(text.c_str());
|
||||||
ds->location = create_location(latitude, longitude);
|
ds->location = create_location(latitude, longitude);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -279,7 +279,7 @@ void uemis::event(struct dive *dive, struct divecomputer *dc, struct sample *sam
|
||||||
/*
|
/*
|
||||||
* parse uemis base64 data blob into struct dive
|
* parse uemis base64 data blob into struct dive
|
||||||
*/
|
*/
|
||||||
void uemis::parse_divelog_binary(char *base64, struct dive *dive)
|
void uemis::parse_divelog_binary(std::string_view base64, struct dive *dive)
|
||||||
{
|
{
|
||||||
struct sample *sample = NULL;
|
struct sample *sample = NULL;
|
||||||
uemis_sample *u_sample;
|
uemis_sample *u_sample;
|
||||||
|
|
|
@ -6,9 +6,12 @@
|
||||||
#ifndef UEMIS_H
|
#ifndef UEMIS_H
|
||||||
#define UEMIS_H
|
#define UEMIS_H
|
||||||
|
|
||||||
|
#include "libdivecomputer.h" // for device_data_t, which is a typedef, not a struct :(
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <string_view>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
|
||||||
|
@ -17,10 +20,10 @@ struct uemis_sample;
|
||||||
struct dive_site;
|
struct dive_site;
|
||||||
|
|
||||||
struct uemis {
|
struct uemis {
|
||||||
void parse_divelog_binary(char *base64, struct dive *dive);
|
void parse_divelog_binary(std::string_view base64, struct dive *dive);
|
||||||
int get_weight_unit(uint32_t diveid) const;
|
int get_weight_unit(uint32_t diveid) const;
|
||||||
void mark_divelocation(int diveid, int divespot, struct dive_site *ds);
|
void mark_divelocation(int diveid, int divespot, struct dive_site *ds);
|
||||||
void set_divelocation(int divespot, char *text, double longitude, double latitude);
|
void set_divelocation(int divespot, const std::string &text, double longitude, double latitude);
|
||||||
int get_divespot_id_by_diveid(uint32_t diveid) const;
|
int get_divespot_id_by_diveid(uint32_t diveid) const;
|
||||||
private:
|
private:
|
||||||
struct helper {
|
struct helper {
|
||||||
|
@ -37,6 +40,7 @@ private:
|
||||||
void weight_unit(int diveid, int lbs);
|
void weight_unit(int diveid, int lbs);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
std::string do_uemis_import(device_data_t *data);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -330,7 +330,8 @@ void DownloadFromDCWidget::updateState(states state)
|
||||||
else if (state == ERRORED) {
|
else if (state == ERRORED) {
|
||||||
timer->stop();
|
timer->stop();
|
||||||
|
|
||||||
QMessageBox::critical(this, TITLE_OR_TEXT(tr("Error"), diveImportedModel->thread.error), QMessageBox::Ok);
|
QMessageBox::critical(this, TITLE_OR_TEXT(tr("Error"),
|
||||||
|
QString::fromStdString(diveImportedModel->thread.error)), QMessageBox::Ok);
|
||||||
markChildrenAsEnabled();
|
markChildrenAsEnabled();
|
||||||
progress_bar_text = "";
|
progress_bar_text = "";
|
||||||
ui.progressBar->hide();
|
ui.progressBar->hide();
|
||||||
|
@ -533,7 +534,7 @@ void DownloadFromDCWidget::onDownloadThreadFinished()
|
||||||
showRememberedDCs();
|
showRememberedDCs();
|
||||||
|
|
||||||
if (currentState == DOWNLOADING) {
|
if (currentState == DOWNLOADING) {
|
||||||
if (diveImportedModel->thread.error.isEmpty())
|
if (diveImportedModel->thread.error.empty())
|
||||||
updateState(DONE);
|
updateState(DONE);
|
||||||
else
|
else
|
||||||
updateState(ERRORED);
|
updateState(ERRORED);
|
||||||
|
|
Loading…
Add table
Reference in a new issue