core: turn a memblock in the parser to std::string

This avoid memory-management troubles. Had to convert a few
of the parsers (cochran, datatrak, liquivision) to C++.
Also had to convert libdivecomputer.c. This was less
painful than expected.

std::string is used because parts of the code assumes
that the data is null terminated after the last character
of the data. std::string does precisely that.

One disadvantage is that std::string clears its memory
when resizing / initializing. Thus we read the file onto
freshly cleared data, which some might thing is a
performance regression. Until someone shows me that this
matters, I don't care.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
This commit is contained in:
Berthold Stoeger 2024-03-01 13:09:20 +01:00 committed by Michael Keller
parent 2f4dbf1848
commit cf7c54bd56
12 changed files with 233 additions and 285 deletions

View file

@ -60,7 +60,7 @@ SOURCES += subsurface-mobile-main.cpp \
core/gaspressures.c \
core/git-access.cpp \
core/globals.cpp \
core/liquivision.c \
core/liquivision.cpp \
core/load-git.cpp \
core/parse-xml.cpp \
core/parse.cpp \
@ -76,14 +76,14 @@ SOURCES += subsurface-mobile-main.cpp \
core/save-html.c \
core/statistics.c \
core/worldmap-save.c \
core/libdivecomputer.c \
core/libdivecomputer.cpp \
core/version.c \
core/save-git.cpp \
core/datatrak.c \
core/datatrak.cpp \
core/ostctools.c \
core/planner.c \
core/save-xml.cpp \
core/cochran.c \
core/cochran.cpp \
core/deco.c \
core/divesite.c \
core/equipment.c \

View file

@ -41,7 +41,7 @@ set(SUBSURFACE_CORE_LIB_SRCS
checkcloudconnection.h
cloudstorage.cpp
cloudstorage.h
cochran.c
cochran.cpp
cochran.h
color.cpp
color.h
@ -51,7 +51,7 @@ set(SUBSURFACE_CORE_LIB_SRCS
configuredivecomputerthreads.h
connectionlistmodel.cpp
connectionlistmodel.h
datatrak.c
datatrak.cpp
datatrak.h
deco.c
deco.h
@ -121,9 +121,9 @@ set(SUBSURFACE_CORE_LIB_SRCS
import-suunto.cpp
import-seac.cpp
interpolate.h
libdivecomputer.c
libdivecomputer.cpp
libdivecomputer.h
liquivision.c
liquivision.cpp
load-git.cpp
membuffer.cpp
membuffer.h

View file

@ -207,7 +207,7 @@ static void cochran_debug_sample(const char *s, unsigned int sample_cnt)
static void cochran_parse_header(const unsigned char *decode, unsigned mod,
const unsigned char *in, unsigned size)
{
unsigned char *buf = malloc(size);
unsigned char *buf = (unsigned char *)malloc(size);
/* Do the "null decode" using a one-byte decode array of '\0' */
/* Copies in plaintext, will be overwritten later */
@ -441,7 +441,7 @@ static void cochran_parse_samples(struct dive *dive, const unsigned char *log,
const unsigned char *s;
unsigned int offset = 0, profile_period = 1, sample_cnt = 0;
double depth = 0, temp = 0, depth_sample = 0, psi = 0, sgc_rate = 0;
int ascent_rate = 0;
//int ascent_rate = 0;
unsigned int ndl = 0;
unsigned int in_deco = 0, deco_ceiling = 0, deco_time = 0;
@ -517,8 +517,8 @@ static void cochran_parse_samples(struct dive *dive, const unsigned char *log,
switch (config.type) {
case TYPE_COMMANDER:
switch (sample_cnt % 2) {
case 0: // Ascent rate
ascent_rate = (s[1] & 0x7f) * (s[1] & 0x80 ? 1: -1);
case 0: // Ascent rate (unused)
//ascent_rate = (s[1] & 0x7f) * (s[1] & 0x80 ? 1: -1);
break;
case 1: // Temperature
temp = s[1] / 2 + 20;
@ -528,8 +528,8 @@ static void cochran_parse_samples(struct dive *dive, const unsigned char *log,
case TYPE_GEMINI:
// Gemini with tank pressure and SAC rate.
switch (sample_cnt % 4) {
case 0: // Ascent rate
ascent_rate = (s[1] & 0x7f) * (s[1] & 0x80 ? 1 : -1);
case 0: // Ascent rate (unused)
//ascent_rate = (s[1] & 0x7f) * (s[1] & 0x80 ? 1 : -1);
break;
case 2: // PSI change
psi -= (double)(s[1] & 0x7f) * (s[1] & 0x80 ? 1 : -1) / 4;
@ -544,8 +544,8 @@ static void cochran_parse_samples(struct dive *dive, const unsigned char *log,
break;
case TYPE_EMC:
switch (sample_cnt % 2) {
case 0: // Ascent rate
ascent_rate = (s[1] & 0x7f) * (s[1] & 0x80 ? 1: -1);
case 0: // Ascent rate (unused)
//ascent_rate = (s[1] & 0x7f) * (s[1] & 0x80 ? 1: -1);
break;
case 1: // Temperature
temp = (double)s[1] / 2 + 20;
@ -597,7 +597,6 @@ static void cochran_parse_samples(struct dive *dive, const unsigned char *log,
offset += config.sample_size;
sample_cnt++;
}
UNUSED(ascent_rate); // mark the variable as unused
if (sample_cnt > 0)
*duration = sample_cnt * profile_period - 1;
@ -607,7 +606,7 @@ static void cochran_parse_dive(const unsigned char *decode, unsigned mod,
const unsigned char *in, unsigned size,
struct dive_table *table)
{
unsigned char *buf = malloc(size);
unsigned char *buf = (unsigned char *)malloc(size);
struct dive *dive;
struct divecomputer *dc;
struct tm tm = {0};
@ -800,26 +799,25 @@ static void cochran_parse_dive(const unsigned char *decode, unsigned mod,
free(buf);
}
int try_to_open_cochran(const char *filename, struct memblock *mem, struct divelog *log)
int try_to_open_cochran(const char *, std::string &mem, struct divelog *log)
{
UNUSED(filename);
unsigned int i;
unsigned int mod;
unsigned int *offsets, dive1, dive2;
unsigned char *decode = mem->buffer + 0x40001;
unsigned char *decode = (unsigned char *)mem.data() + 0x40001;
if (mem->size < 0x40000)
if (mem.size() < 0x40000)
return 0;
offsets = (unsigned int *) mem->buffer;
offsets = (unsigned int *) mem.data();
dive1 = offsets[0];
dive2 = offsets[1];
if (dive1 < 0x40000 || dive2 < dive1 || dive2 > mem->size)
if (dive1 < 0x40000 || dive2 < dive1 || dive2 > mem.size())
return 0;
mod = decode[0x100] + 1;
cochran_parse_header(decode, mod, mem->buffer + 0x40000, dive1 - 0x40000);
cochran_parse_header(decode, mod, (unsigned char *)mem.data() + 0x40000, dive1 - 0x40000);
// Decode each dive
for (i = 0; i < 65534; i++) {
@ -827,10 +825,10 @@ int try_to_open_cochran(const char *filename, struct memblock *mem, struct divel
dive2 = offsets[i + 1];
if (dive2 < dive1)
break;
if (dive2 > mem->size)
if (dive2 > mem.size())
break;
cochran_parse_dive(decode, mod, mem->buffer + dive1,
cochran_parse_dive(decode, mod, (unsigned char *)mem.data() + dive1,
dive2 - dive1, log->dives);
}

View file

@ -67,7 +67,7 @@ static char *to_utf8(unsigned char *in_string)
inlen = strlen((char *)in_string);
outlen = inlen * 2 + 1;
char *out_string = calloc(outlen, 1);
char *out_string = (char *)calloc(outlen, 1);
for (i = 0; i < inlen; i++) {
if (in_string[i] < 127) {
out_string[j] = in_string[i];
@ -158,7 +158,7 @@ static dc_status_t dt_libdc_buffer(unsigned char *ptr, int prf_length, int dc_mo
* Parses a mem buffer extracting its data and filling a subsurface's dive structure.
* Returns a pointer to last position in buffer, or NULL on failure.
*/
static unsigned char *dt_dive_parser(unsigned char *runner, struct dive *dt_dive, struct divelog *log, long maxbuf)
static char *dt_dive_parser(unsigned char *runner, struct dive *dt_dive, struct divelog *log, char *maxbuf)
{
int rc, profile_length, libdc_model;
char *tmp_notes_str = NULL;
@ -174,7 +174,7 @@ static unsigned char *dt_dive_parser(unsigned char *runner, struct dive *dt_dive
struct dive_site *ds;
char is_nitrox = 0, is_O2 = 0, is_SCR = 0;
device_data_t *devdata = calloc(1, sizeof(device_data_t));
device_data_t *devdata = (device_data_t *)calloc(1, sizeof(device_data_t));
devdata->log = log;
/*
@ -478,8 +478,8 @@ static unsigned char *dt_dive_parser(unsigned char *runner, struct dive *dt_dive
tmp_notes_str ? tmp_notes_str : "",
QT_TRANSLATE_NOOP("gettextFromC", "Datatrak/Wlog notes"),
tmp_string1);
dt_dive->notes = calloc((len +1), 1);
dt_dive->notes = memcpy(dt_dive->notes, buffer, len);
dt_dive->notes = (char *)calloc((len +1), 1);
memcpy(dt_dive->notes, buffer, len);
free(tmp_string1);
}
free(tmp_notes_str);
@ -571,7 +571,7 @@ static unsigned char *dt_dive_parser(unsigned char *runner, struct dive *dt_dive
((get_cylinder(dt_dive, 0)->gas_used.mliter / get_cylinder(dt_dive, 0)->type.size.mliter) * 1000);
}
free(devdata);
return membuf;
return (char *)membuf;
bail:
free(locality);
free(devdata);
@ -582,10 +582,10 @@ bail:
* Parses the header of the .add file, returns the number of dives in
* the archive (must be the same than number of dives in .log file).
*/
static int wlog_header_parser (struct memblock *mem)
static int wlog_header_parser (std::string &mem)
{
int tmp;
unsigned char *runner = (unsigned char *) mem->buffer;
unsigned char *runner = (unsigned char *) mem.data();
if (!runner)
return -1;
if (!memcmp(runner, "\x52\x02", 2)) {
@ -600,7 +600,7 @@ static int wlog_header_parser (struct memblock *mem)
#define NOTES_LENGTH 256
#define SUIT_LENGTH 26
static void wlog_compl_parser(struct memblock *wl_mem, struct dive *dt_dive, int dcount)
static void wlog_compl_parser(std::string &wl_mem, struct dive *dt_dive, int dcount)
{
int tmp = 0, offset = 12 + (dcount * 850),
pos_weight = offset + 256,
@ -608,7 +608,7 @@ static void wlog_compl_parser(struct memblock *wl_mem, struct dive *dt_dive, int
pos_tank_init = offset + 266,
pos_suit = offset + 268;
char *wlog_notes = NULL, *wlog_suit = NULL, *buffer = NULL;
unsigned char *runner = (unsigned char *) wl_mem->buffer;
unsigned char *runner = (unsigned char *) wl_mem.data();
/*
* Extended notes string. Fixed length 256 bytes. 0 padded if not complete
@ -620,7 +620,7 @@ static void wlog_compl_parser(struct memblock *wl_mem, struct dive *dt_dive, int
wlog_notes = to_utf8((unsigned char *) wlog_notes_temp);
}
if (dt_dive->notes && wlog_notes) {
buffer = calloc (strlen(dt_dive->notes) + strlen(wlog_notes) + 1, 1);
buffer = (char *)calloc (strlen(dt_dive->notes) + strlen(wlog_notes) + 1, 1);
sprintf(buffer, "%s%s", dt_dive->notes, wlog_notes);
free(dt_dive->notes);
dt_dive->notes = copy_string(buffer);
@ -635,7 +635,7 @@ static void wlog_compl_parser(struct memblock *wl_mem, struct dive *dt_dive, int
*/
tmp = (int) two_bytes_to_int(runner[pos_weight + 1], runner[pos_weight]);
if (tmp != 0x7fff) {
weightsystem_t ws = { {lrint(tmp * 10)}, QT_TRANSLATE_NOOP("gettextFromC", "unknown"), false };
weightsystem_t ws = { {tmp * 10}, QT_TRANSLATE_NOOP("gettextFromC", "unknown"), false };
add_cloned_weightsystem(&dt_dive->weightsystems, ws);
}
@ -675,42 +675,40 @@ static void wlog_compl_parser(struct memblock *wl_mem, struct dive *dt_dive, int
}
/*
* Main function call from file.c memblock is allocated (and freed) there.
* Main function call from file.c data is allocated (and freed) there.
* If parsing is aborted due to errors, stores correctly parsed dives.
*/
int datatrak_import(struct memblock *mem, struct memblock *wl_mem, struct divelog *log)
int datatrak_import(std::string &mem, std::string &wl_mem, struct divelog *log)
{
unsigned char *runner;
char *runner;
int i = 0, numdives = 0, rc = 0;
long maxbuf = (long) mem->buffer + mem->size;
char *maxbuf = mem.data() + mem.size();
// Verify fileheader, get number of dives in datatrak divelog, zero on error
numdives = read_file_header((unsigned char *)mem->buffer);
numdives = read_file_header((unsigned char *)mem.data());
if (!numdives) {
report_error(translate("gettextFromC", "[Error] File is not a DataTrak file. Aborted"));
goto bail;
}
// Verify WLog .add file, Beginning sequence and Nº dives
if(wl_mem) {
if(!wl_mem.empty()) {
int compl_dives_n = wlog_header_parser(wl_mem);
if (compl_dives_n != numdives) {
report_error("ERROR: Not the same number of dives in .log %d and .add file %d.\nWill not parse .add file", numdives , compl_dives_n);
free(wl_mem->buffer);
wl_mem->buffer = NULL;
wl_mem = NULL;
wl_mem.clear();
}
}
// Point to the expected begining of 1st. dive data
runner = (unsigned char *)mem->buffer;
runner = mem.data();
JUMP(runner, 12);
// Secuential parsing. Abort if received NULL from dt_dive_parser.
while ((i < numdives) && ((long) runner < maxbuf)) {
while ((i < numdives) && (runner < maxbuf)) {
struct dive *ptdive = alloc_dive();
runner = dt_dive_parser(runner, ptdive, log, maxbuf);
if (wl_mem)
runner = dt_dive_parser((unsigned char *)runner, ptdive, log, maxbuf);
if (!wl_mem.empty())
wlog_compl_parser(wl_mem, ptdive, i);
if (runner == NULL) {
report_error(translate("gettextFromC", "Error: no dive"));

View file

@ -41,8 +41,8 @@ static const struct models_table_t g_models[] = {
{0xEE, 0x44, "Uwatec Unknown model", DC_FAMILY_UWATEC_ALADIN},
};
#define JUMP(_ptr, _n) if ((long) (_ptr += _n) > maxbuf) goto bail
#define CHECK(_ptr, _n) if ((long) _ptr + _n > maxbuf) goto bail
#define JUMP(_ptr, _n) if ((char *) (_ptr += _n) > (char *)maxbuf) goto bail
#define CHECK(_ptr, _n) if ((char *) _ptr + _n > (char *)maxbuf) goto bail
#define read_bytes(_n) \
switch (_n) { \
case 1: \
@ -62,10 +62,12 @@ static const struct models_table_t g_models[] = {
#define read_string(_property) \
CHECK(membuf, tmp_1byte); \
{ \
unsigned char *_property##tmp = (unsigned char *)calloc(tmp_1byte + 1, 1); \
_property##tmp = memcpy(_property##tmp, membuf, tmp_1byte);\
_property##tmp = (unsigned char*)memcpy(_property##tmp, membuf, tmp_1byte);\
_property = (unsigned char *)strcat(to_utf8(_property##tmp), ""); \
free(_property##tmp);\
JUMP(membuf, tmp_1byte);
JUMP(membuf, tmp_1byte); \
}
#endif // DATATRAK_HEADER_H

View file

@ -31,61 +31,47 @@
#define O_BINARY 0
#endif
extern "C" int readfile(const char *filename, struct memblock *mem)
std::pair<std::string, int> readfile(const char *filename)
{
int ret, fd;
struct stat st;
char *buf;
mem->buffer = NULL;
mem->size = 0;
std::string res;
fd = subsurface_open(filename, O_RDONLY | O_BINARY, 0);
if (fd < 0)
return fd;
return std::make_pair(res, fd);
ret = fstat(fd, &st);
if (ret < 0)
goto out;
ret = -EINVAL;
return std::make_pair(res, ret);
if (!S_ISREG(st.st_mode))
goto out;
ret = 0;
return std::make_pair(res, -EINVAL);
if (!st.st_size)
goto out;
buf = (char *)malloc(st.st_size + 1);
ret = -1;
errno = ENOMEM;
if (!buf)
goto out;
mem->buffer = buf;
mem->size = st.st_size;
ret = read(fd, buf, mem->size);
return std::make_pair(res, 0);
// Sadly, this 0-initializes the string, just before overwriting it.
// However, we use std::string, because that automatically 0-terminates
// the data and the code expects that.
res.resize(st.st_size);
ret = read(fd, res.data(), res.size());
if (ret < 0)
goto free;
buf[ret] = 0;
if (ret == (int)mem->size) // converting to int loses a bit but size will never be that big
goto out;
errno = EIO;
ret = -1;
free:
free(mem->buffer);
mem->buffer = NULL;
mem->size = 0;
out:
close(fd);
return ret;
return std::make_pair(res, ret);
// converting to int loses a bit but size will never be that big
if (ret == (int)res.size()) {
return std::make_pair(res, ret);
} else {
errno = EIO;
return std::make_pair(res, -1);
}
}
static void zip_read(struct zip_file *file, const char *filename, struct divelog *log)
{
int size = 1024, n, read = 0;
std::vector<char> mem(size);
std::vector<char> mem(size + 1);
while ((n = zip_fread(file, mem.data() + read, size - read)) > 0) {
read += n;
size = read * 3 / 2;
mem.resize(size);
mem.resize(size + 1);
}
mem[read] = 0;
(void) parse_xml_buffer(filename, mem.data(), read, log, NULL);
@ -123,7 +109,7 @@ static int db_test_func(void *, int, char **data, char **)
return *data[0] == '0';
}
static int try_to_open_db(const char *filename, struct memblock *mem, struct divelog *log)
static int try_to_open_db(const char *filename, std::string &mem, struct divelog *log)
{
sqlite3 *handle;
char dm4_test[] = "select count(*) from sqlite_master where type='table' and name='Dive' and sql like '%ProfileBlob%'";
@ -145,7 +131,7 @@ static int try_to_open_db(const char *filename, struct memblock *mem, struct div
/* Testing if DB schema resembles Suunto DM5 database format */
retval = sqlite3_exec(handle, dm5_test, &db_test_func, 0, NULL);
if (!retval) {
retval = parse_dm5_buffer(handle, filename, (char *)mem->buffer, mem->size, log);
retval = parse_dm5_buffer(handle, filename, mem.data(), mem.size(), log);
sqlite3_close(handle);
return retval;
}
@ -153,7 +139,7 @@ static int try_to_open_db(const char *filename, struct memblock *mem, struct div
/* Testing if DB schema resembles Suunto DM4 database format */
retval = sqlite3_exec(handle, dm4_test, &db_test_func, 0, NULL);
if (!retval) {
retval = parse_dm4_buffer(handle, filename, (char *)mem->buffer, mem->size, log);
retval = parse_dm4_buffer(handle, filename, mem.data(), mem.size(), log);
sqlite3_close(handle);
return retval;
}
@ -161,7 +147,7 @@ static int try_to_open_db(const char *filename, struct memblock *mem, struct div
/* Testing if DB schema resembles Shearwater database format */
retval = sqlite3_exec(handle, shearwater_test, &db_test_func, 0, NULL);
if (!retval) {
retval = parse_shearwater_buffer(handle, filename, (char *)mem->buffer, mem->size, log);
retval = parse_shearwater_buffer(handle, filename, mem.data(), mem.size(), log);
sqlite3_close(handle);
return retval;
}
@ -169,7 +155,7 @@ static int try_to_open_db(const char *filename, struct memblock *mem, struct div
/* Testing if DB schema resembles Shearwater cloud database format */
retval = sqlite3_exec(handle, shearwater_cloud_test, &db_test_func, 0, NULL);
if (!retval) {
retval = parse_shearwater_cloud_buffer(handle, filename, (char *)mem->buffer, mem->size, log);
retval = parse_shearwater_cloud_buffer(handle, filename, mem.data(), mem.size(), log);
sqlite3_close(handle);
return retval;
}
@ -177,7 +163,7 @@ static int try_to_open_db(const char *filename, struct memblock *mem, struct div
/* Testing if DB schema resembles Atomic Cobalt database format */
retval = sqlite3_exec(handle, cobalt_test, &db_test_func, 0, NULL);
if (!retval) {
retval = parse_cobalt_buffer(handle, filename, (char *)mem->buffer, mem->size, log);
retval = parse_cobalt_buffer(handle, filename, mem.data(), mem.size(), log);
sqlite3_close(handle);
return retval;
}
@ -185,7 +171,7 @@ static int try_to_open_db(const char *filename, struct memblock *mem, struct div
/* Testing if DB schema resembles Divinglog database format */
retval = sqlite3_exec(handle, divinglog_test, &db_test_func, 0, NULL);
if (!retval) {
retval = parse_divinglog_buffer(handle, filename, (char *)mem->buffer, mem->size, log);
retval = parse_divinglog_buffer(handle, filename, mem.data(), mem.size(), log);
sqlite3_close(handle);
return retval;
}
@ -193,7 +179,7 @@ static int try_to_open_db(const char *filename, struct memblock *mem, struct div
/* Testing if DB schema resembles Seac database format */
retval = sqlite3_exec(handle, seacsync_test, &db_test_func, 0, NULL);
if (!retval) {
retval = parse_seac_buffer(handle, filename, (char *)mem->buffer, mem->size, log);
retval = parse_seac_buffer(handle, filename, mem.data(), mem.size(), log);
sqlite3_close(handle);
return retval;
}
@ -220,7 +206,7 @@ static int try_to_open_db(const char *filename, struct memblock *mem, struct div
*
* Followed by the data values (all comma-separated, all one long line).
*/
static int open_by_filename(const char *filename, const char *fmt, struct memblock *mem, struct divelog *log)
static int open_by_filename(const char *filename, const char *fmt, std::string &mem, struct divelog *log)
{
// hack to be able to provide a comment for the translated string
static struct { const char *s; const char *comment; } csv_warning =
@ -251,17 +237,17 @@ static int open_by_filename(const char *filename, const char *fmt, struct memblo
return 0;
}
static int parse_file_buffer(const char *filename, struct memblock *mem, struct divelog *log)
static int parse_file_buffer(const char *filename, std::string &mem, struct divelog *log)
{
int ret;
const char *fmt = strrchr(filename, '.');
if (fmt && (ret = open_by_filename(filename, fmt + 1, mem, log)) != 0)
return ret;
if (!mem->size || !mem->buffer)
if (mem.empty())
return report_error("Out of memory parsing file %s\n", filename);
return parse_xml_buffer(filename, (char *)mem->buffer, mem->size, log, NULL);
return parse_xml_buffer(filename, mem.data(), mem.size(), log, NULL);
}
extern "C" bool remote_repo_uptodate(const char *filename, struct git_info *info)
@ -284,9 +270,7 @@ extern "C" bool remote_repo_uptodate(const char *filename, struct git_info *info
extern "C" int parse_file(const char *filename, struct divelog *log)
{
struct git_info info;
struct memblock mem;
const char *fmt;
int ret;
if (is_git_repository(filename, &info)) {
if (!open_git_repository(&info)) {
@ -300,60 +284,49 @@ extern "C" int parse_file(const char *filename, struct divelog *log)
}
}
ret = git_load_dives(&info, log);
int ret = git_load_dives(&info, log);
cleanup_git_info(&info);
return ret;
}
if ((ret = readfile(filename, &mem)) < 0) {
auto [mem, err] = readfile(filename);
if (err < 0) {
/* we don't want to display an error if this was the default file */
if (same_string(filename, prefs.default_filename))
return 0;
return report_error(translate("gettextFromC", "Failed to read '%s'"), filename);
} else if (ret == 0) {
} else if (err == 0) {
return report_error(translate("gettextFromC", "Empty file '%s'"), filename);
}
fmt = strrchr(filename, '.');
if (fmt && (!strcasecmp(fmt + 1, "DB") || !strcasecmp(fmt + 1, "BAK") || !strcasecmp(fmt + 1, "SQL"))) {
if (!try_to_open_db(filename, &mem, log)) {
free(mem.buffer);
if (!try_to_open_db(filename, mem, log))
return 0;
}
}
/* Divesoft Freedom */
if (fmt && (!strcasecmp(fmt + 1, "DLF"))) {
ret = parse_dlf_buffer((unsigned char *)mem.buffer, mem.size, log);
free(mem.buffer);
return ret;
}
if (fmt && (!strcasecmp(fmt + 1, "DLF")))
return parse_dlf_buffer((unsigned char *)mem.data(), mem.size(), log);
/* DataTrak/Wlog */
if (fmt && !strcasecmp(fmt + 1, "LOG")) {
struct memblock wl_mem;
const char *t = strrchr(filename, '.');
std::string wl_name = std::string(filename, t - filename) + ".add";
if((ret = readfile(wl_name.c_str(), &wl_mem)) < 0) {
auto [wl_mem, err] = readfile(wl_name.c_str());
if (err < 0) {
fprintf(stderr, "No file %s found. No WLog extensions.\n", wl_name.c_str());
ret = datatrak_import(&mem, NULL, log);
} else {
ret = datatrak_import(&mem, &wl_mem, log);
free(wl_mem.buffer);
wl_mem.clear();
}
free(mem.buffer);
return ret;
return datatrak_import(mem, wl_mem, log);
}
/* OSTCtools */
if (fmt && (!strcasecmp(fmt + 1, "DIVE"))) {
free(mem.buffer);
ostctools_import(filename, log);
return 0;
}
ret = parse_file_buffer(filename, &mem, log);
free(mem.buffer);
return ret;
return parse_file_buffer(filename, mem, log);
}

View file

@ -7,23 +7,14 @@
#include <sys/stat.h>
#include <stdio.h>
struct memblock {
void *buffer;
size_t size;
};
struct divelog;
struct zip;
#ifdef __cplusplus
extern "C" {
#endif
extern int try_to_open_cochran(const char *filename, struct memblock *mem, struct divelog *log);
extern int try_to_open_liquivision(const char *filename, struct memblock *mem, struct divelog *log);
extern int datatrak_import(struct memblock *mem, struct memblock *wl_mem, struct divelog *log);
extern void ostctools_import(const char *file, struct divelog *log);
extern int readfile(const char *filename, struct memblock *mem);
extern int parse_file(const char *filename, struct divelog *log);
extern int try_to_open_zip(const char *filename, struct divelog *log);
@ -39,7 +30,20 @@ extern struct zip *subsurface_zip_open_readonly(const char *path, int flags, int
extern int subsurface_zip_close(struct zip *zip);
#ifdef __cplusplus
}
// C++ only functions
#include <vector>
#include <utility>
// return data, errorcode pair.
extern std::pair<std::string, int> readfile(const char *filename);
extern int try_to_open_cochran(const char *filename, std::string &mem, struct divelog *log);
extern int try_to_open_liquivision(const char *filename, std::string &mem, struct divelog *log);
extern int datatrak_import(std::string &mem, std::string &wl_mem, struct divelog *log);
#endif
#endif // FILE_H

View file

@ -106,12 +106,11 @@ static char *parse_dan_new_line(char *buf, const char *NL)
return iter;
}
static int try_to_xslt_open_csv(const char *filename, struct memblock *mem, const char *tag);
static int try_to_xslt_open_csv(const char *filename, std::string &mem, const char *tag);
static int parse_dan_format(const char *filename, struct xml_params *params, struct divelog *log)
{
int ret = 0, i;
size_t end_ptr = 0;
struct memblock mem, mem_csv;
char tmpbuf[MAXCOLDIGITS];
int params_orig_size = xml_params_count(params);
@ -119,26 +118,24 @@ static int parse_dan_format(const char *filename, struct xml_params *params, str
const char *NL = NULL;
char *iter = NULL;
if (readfile(filename, &mem) < 0)
auto [mem, err] = readfile(filename);
if (err < 0)
return report_error(translate("gettextFromC", "Failed to read '%s'"), filename);
/* Determine NL (new line) character and the start of CSV data */
if ((ptr = strstr((char *)mem.buffer, "\r\n")) != NULL) {
if ((ptr = strstr(mem.data(), "\r\n")) != NULL) {
NL = "\r\n";
} else if ((ptr = strstr((char *)mem.buffer, "\n")) != NULL) {
} else if ((ptr = strstr(mem.data(), "\n")) != NULL) {
NL = "\n";
} else {
fprintf(stderr, "DEBUG: failed to detect NL\n");
return -1;
}
while ((end_ptr < mem.size) && (ptr = strstr((char *)mem.buffer + end_ptr, "ZDH"))) {
while ((end_ptr < mem.size()) && (ptr = strstr(mem.data() + end_ptr, "ZDH"))) {
xml_params_resize(params, params_orig_size); // restart with original parameter block
char *iter_end = NULL;
mem_csv.buffer = malloc(mem.size + 1);
mem_csv.size = mem.size;
iter = ptr + 4;
iter = strchr(iter, '|');
if (iter) {
@ -195,7 +192,7 @@ static int parse_dan_format(const char *filename, struct xml_params *params, str
/* We got a trailer, no samples on this dive */
if (strncmp(iter, "ZDT", 3) == 0) {
end_ptr = iter - (char *)mem.buffer;
end_ptr = iter - mem.data();
/* Water temperature */
memset(tmpbuf, 0, sizeof(tmpbuf));
@ -218,7 +215,7 @@ static int parse_dan_format(const char *filename, struct xml_params *params, str
/* After ZDH we should get either ZDT (above) or ZDP */
if (strncmp(iter, "ZDP{", 4) != 0) {
fprintf(stderr, "DEBUG: Input appears to violate DL7 specification\n");
end_ptr = iter - (char *)mem.buffer;
end_ptr = iter - mem.data();
continue;
}
@ -230,19 +227,20 @@ static int parse_dan_format(const char *filename, struct xml_params *params, str
if (!ptr)
return -1;
end_ptr = ptr - (char *)mem.buffer;
end_ptr = ptr - mem.data();
/* Copy the current dive data to start of mem_csv buffer */
memcpy(mem_csv.buffer, ptr, mem.size - (ptr - (char *)mem.buffer));
ptr = strstr((char *)mem_csv.buffer, "ZDP}");
std::string mem_csv(ptr, mem.size() - (ptr - mem.data()));
ptr = strstr(mem_csv.data(), "ZDP}");
if (ptr) {
*ptr = 0;
} else {
fprintf(stderr, "DEBUG: failed to find end ZDP\n");
return -1;
}
mem_csv.size = ptr - (char*)mem_csv.buffer;
end_ptr += ptr - (char *)mem_csv.buffer;
mem_csv.resize(ptr - mem_csv.data());
end_ptr += ptr - mem_csv.data();
iter = parse_dan_new_line(ptr + 1, NL);
if (iter && strncmp(iter, "ZDT", 3) == 0) {
@ -262,23 +260,19 @@ static int parse_dan_format(const char *filename, struct xml_params *params, str
}
}
if (try_to_xslt_open_csv(filename, &mem_csv, "csv"))
if (try_to_xslt_open_csv(filename, mem_csv, "csv"))
return -1;
ret |= parse_xml_buffer(filename, (char *)mem_csv.buffer, mem_csv.size, log, params);
free(mem_csv.buffer);
ret |= parse_xml_buffer(filename, mem_csv.data(), mem_csv.size(), log, params);
}
free(mem.buffer);
return ret;
}
extern "C" int parse_csv_file(const char *filename, struct xml_params *params, const char *csvtemplate, struct divelog *log)
{
int ret;
struct memblock mem;
std::string mem;
time_t now;
struct tm *timep = NULL;
char tmpbuf[MAXCOLDIGITS];
@ -293,7 +287,6 @@ extern "C" int parse_csv_file(const char *filename, struct xml_params *params, c
if (filename == NULL)
return report_error("No CSV filename");
mem.size = 0;
if (!strcmp("DL7", csvtemplate)) {
return parse_dan_format(filename, params, log);
} else if (strcmp(xml_params_get_key(params, 0), "date")) {
@ -305,12 +298,11 @@ extern "C" int parse_csv_file(const char *filename, struct xml_params *params, c
/* As the parameter is numeric, we need to ensure that the leading zero
* is not discarded during the transform, thus prepend time with 1 */
strftime(tmpbuf, MAXCOLDIGITS, "1%H%M", timep);
xml_params_add(params, "time", tmpbuf);
}
if (try_to_xslt_open_csv(filename, &mem, csvtemplate))
if (try_to_xslt_open_csv(filename, mem, csvtemplate))
return -1;
/*
@ -327,25 +319,28 @@ extern "C" int parse_csv_file(const char *filename, struct xml_params *params, c
fprintf(stderr, "%s/xslt/%s -\n", SUBSURFACE_SOURCE, csvtemplate);
}
#endif
ret = parse_xml_buffer(filename, (char *)mem.buffer, mem.size, log, params);
free(mem.buffer);
ret = parse_xml_buffer(filename, mem.data(), mem.size(), log, params);
return ret;
}
static int try_to_xslt_open_csv(const char *filename, struct memblock *mem, const char *tag)
static int try_to_xslt_open_csv(const char *filename, std::string &mem, const char *tag)
{
char *buf;
size_t i, amp = 0, rest = 0;
size_t amp = 0;
if (mem->size == 0 && readfile(filename, mem) < 0)
return report_error(translate("gettextFromC", "Failed to read '%s'"), filename);
if (mem.empty()) {
auto [mem2, err] = readfile(filename);
if (err < 0)
return report_error(translate("gettextFromC", "Failed to read '%s'"), filename);
if (mem2.empty())
return 0; // Empty file - nothing to do. Guess that's a "success".
mem = std::move(mem2);
}
/* Count ampersand characters */
for (i = 0; i < mem->size; ++i) {
if (((char *)mem->buffer)[i] == '&') {
for (size_t i = 0; i < mem.size(); ++i) {
if (mem[i] == '&') {
++amp;
}
}
@ -356,57 +351,49 @@ static int try_to_xslt_open_csv(const char *filename, struct memblock *mem, cons
*
* Tag markers take: strlen("<></>") = 5
* Reserve also room for encoding ampersands "&" => "&amp;"
*
* Attention: This code is quite subtle, because we reserve one
* more byte than we use and put a '\0' there.
*/
buf = (char *)realloc((char *)mem->buffer, mem->size + 7 + strlen(tag) * 2 + amp * 4);
if (buf != NULL) {
char *starttag = NULL;
char *endtag = NULL;
starttag = (char *)malloc(3 + strlen(tag));
endtag = (char *)malloc(5 + strlen(tag));
size_t tag_name_size = strlen(tag);
size_t old_size = mem.size();
mem.resize(mem.size() + tag_name_size * 2 + 5 + amp * 4);
const char *ptr_in = mem.data() + old_size;
char *ptr_out = mem.data() + mem.size();
if (starttag == NULL || endtag == NULL) {
/* this is fairly silly - so the malloc fails, but we strdup the error?
* let's complete the silliness by freeing the two pointers in case one malloc succeeded
* and the other one failed - this will make static analysis tools happy */
free(starttag);
free(endtag);
free(buf);
return report_error("Memory allocation failed in %s", __func__);
/* Add end tag */
*--ptr_out = '>';
ptr_out -= tag_name_size;
memcpy(ptr_out, tag, tag_name_size);
*--ptr_out = '/';
*--ptr_out = '<';
while (--ptr_in >= mem.data()) {
if (*ptr_in == '&') {
*--ptr_out = ';';
*--ptr_out = 'p';
*--ptr_out = 'm';
*--ptr_out = 'a';
}
sprintf(starttag, "<%s>", tag);
sprintf(endtag, "\n</%s>", tag);
memmove(buf + 2 + strlen(tag), buf, mem->size);
memcpy(buf, starttag, 2 + strlen(tag));
memcpy(buf + mem->size + 2 + strlen(tag), endtag, 5 + strlen(tag));
mem->size += (6 + 2 * strlen(tag));
mem->buffer = buf;
free(starttag);
free(endtag);
/* Expand ampersands to encoded version */
for (i = mem->size, rest = 0; i > 0; --i, ++rest) {
if (((char *)mem->buffer)[i] == '&') {
memmove(((char *)mem->buffer) + i + 4 + 1, ((char *)mem->buffer) + i + 1, rest);
memcpy(((char *)mem->buffer) + i + 1, "amp;", 4);
rest += 4;
mem->size += 4;
}
}
} else {
free(mem->buffer);
return report_error("realloc failed in %s", __func__);
*--ptr_out = *ptr_in;
}
/* Add start tag */
*--ptr_out = '>';
ptr_out -= tag_name_size;
memcpy(ptr_out, tag, tag_name_size);
*--ptr_out = '<';
if (ptr_out != mem.data())
fprintf(stderr, "try_to_xslt_open_csv(): ptr_out off by %ld. This shouldn't happen\n", ptr_out - mem.data());
return 0;
}
int try_to_open_csv(struct memblock *mem, enum csv_format type, struct divelog *log)
int try_to_open_csv(std::string &mem, enum csv_format type, struct divelog *log)
{
char *p = (char *)mem->buffer;
char *p = mem.data();
char *header[8];
int i, time;
timestamp_t date;
@ -498,16 +485,15 @@ static char *next_mkvi_key(char *haystack)
int parse_txt_file(const char *filename, const char *csv, struct divelog *log)
{
struct memblock memtxt, memcsv;
if (readfile(filename, &memtxt) < 0)
auto [memtxt, err] = readfile(filename);
if (err < 0)
return report_error(translate("gettextFromC", "Failed to read '%s'"), filename);
/*
* MkVI stores some information in .txt file but the whole profile and events are stored in .csv file. First
* make sure the input .txt looks like proper MkVI file, then start parsing the .csv.
*/
if (MATCH(memtxt.buffer, "MkVI_Config") == 0) {
if (MATCH(memtxt.data(), "MkVI_Config") == 0) {
int d, m, y, he;
int hh = 0, mm = 0, ss = 0;
int prev_depth = 0, cur_sampletime = 0, prev_setpoint = -1, prev_ndl = -1;
@ -520,7 +506,7 @@ int parse_txt_file(const char *filename, const char *csv, struct divelog *log)
struct divecomputer *dc;
struct tm cur_tm;
value = parse_mkvi_value((char *)memtxt.buffer, "Dive started at");
value = parse_mkvi_value(memtxt.data(), "Dive started at");
if (sscanf(value, "%d-%d-%d %d:%d:%d", &y, &m, &d, &hh, &mm, &ss) != 6) {
free(value);
return -1;
@ -536,7 +522,7 @@ int parse_txt_file(const char *filename, const char *csv, struct divelog *log)
dive = alloc_dive();
dive->when = utc_mktime(&cur_tm);;
dive->dc.model = strdup("Poseidon MkVI Discovery");
value = parse_mkvi_value((char *)memtxt.buffer, "Rig Serial number");
value = parse_mkvi_value(memtxt.data(), "Rig Serial number");
dive->dc.deviceid = atoi(value);
free(value);
dive->dc.divemode = CCR;
@ -556,16 +542,16 @@ int parse_txt_file(const char *filename, const char *csv, struct divelog *log)
cyl.type.size.mliter = 3000;
cyl.type.workingpressure.mbar = 200000;
cyl.type.description = "3l Mk6";
value = parse_mkvi_value((char *)memtxt.buffer, "Helium percentage");
value = parse_mkvi_value(memtxt.data(), "Helium percentage");
he = atoi(value);
free(value);
value = parse_mkvi_value((char *)memtxt.buffer, "Nitrogen percentage");
value = parse_mkvi_value(memtxt.data(), "Nitrogen percentage");
cyl.gasmix.o2.permille = (100 - atoi(value) - he) * 10;
free(value);
cyl.gasmix.he.permille = he * 10;
add_cloned_cylinder(&dive->cylinders, cyl);
lineptr = strstr((char *)memtxt.buffer, "Dive started at");
lineptr = strstr(memtxt.data(), "Dive started at");
while (!empty_string(lineptr) && (lineptr = strchr(lineptr, '\n'))) {
++lineptr; // Skip over '\n'
key = next_mkvi_key(lineptr);
@ -599,11 +585,12 @@ int parse_txt_file(const char *filename, const char *csv, struct divelog *log)
* 39 water temp
*/
if (readfile(csv, &memcsv) < 0) {
auto [memcsv, err] = readfile(csv);
if (err < 0) {
free_dive(dive);
return report_error(translate("gettextFromC", "Poseidon import failed: unable to read '%s'"), csv);
}
lineptr = (char *)memcsv.buffer;
lineptr = memcsv.data();
for (;;) {
struct sample *sample;
int type;
@ -808,7 +795,6 @@ int parse_seabear_log(const char *filename, struct divelog *log)
static int parse_seabear_csv_file(const char *filename, struct xml_params *params, const char *csvtemplate, struct divelog *log)
{
int ret, i;
struct memblock mem;
time_t now;
struct tm *timep = NULL;
char *ptr, *ptr_old = NULL;
@ -836,11 +822,12 @@ static int parse_seabear_csv_file(const char *filename, struct xml_params *param
if (filename == NULL)
return report_error("No CSV filename");
if (readfile(filename, &mem) < 0)
auto [mem, err] = readfile(filename);
if (err < 0)
return report_error(translate("gettextFromC", "Failed to read '%s'"), filename);
/* Determine NL (new line) character and the start of CSV data */
ptr = (char *)mem.buffer;
ptr = (char *)mem.data();
while ((ptr = strstr(ptr, "\r\n\r\n")) != NULL) {
ptr_old = ptr;
ptr += 1;
@ -848,7 +835,7 @@ static int parse_seabear_csv_file(const char *filename, struct xml_params *param
}
if (!ptr_old) {
ptr = (char *)mem.buffer;
ptr = (char *)mem.data();
while ((ptr = strstr(ptr, "\n\n")) != NULL) {
ptr_old = ptr;
ptr += 1;
@ -872,7 +859,7 @@ static int parse_seabear_csv_file(const char *filename, struct xml_params *param
* line and step through from there. That is the line after
* Serial number.
*/
ptr = strstr((char *)mem.buffer, "Serial number:");
ptr = strstr((char *)mem.data(), "Serial number:");
if (ptr)
ptr = strstr(ptr, NL);
@ -904,10 +891,10 @@ static int parse_seabear_csv_file(const char *filename, struct xml_params *param
}
/* Move the CSV data to the start of mem buffer */
memmove(mem.buffer, ptr_old, mem.size - (ptr_old - (char*)mem.buffer));
mem.size = (int)mem.size - (ptr_old - (char*)mem.buffer);
memmove(mem.data(), ptr_old, mem.size() - (ptr_old - mem.data()));
mem.resize(mem.size() - (ptr_old - mem.data()));
if (try_to_xslt_open_csv(filename, &mem, csvtemplate))
if (try_to_xslt_open_csv(filename, mem, csvtemplate))
return -1;
/*
@ -923,15 +910,14 @@ static int parse_seabear_csv_file(const char *filename, struct xml_params *param
fprintf(stderr, "xslt/csv2xml.xslt\n");
}
ret = parse_xml_buffer(filename, (char *)mem.buffer, mem.size, log, params);
free(mem.buffer);
ret = parse_xml_buffer(filename, mem.data(), mem.size(), log, params);
return ret;
}
int parse_manual_file(const char *filename, struct xml_params *params, struct divelog *log)
{
struct memblock mem;
std::string mem;
time_t now;
struct tm *timep;
char curdate[9];
@ -953,8 +939,7 @@ int parse_manual_file(const char *filename, struct xml_params *params, struct di
if (filename == NULL)
return report_error("No manual CSV filename");
mem.size = 0;
if (try_to_xslt_open_csv(filename, &mem, "manualCSV"))
if (try_to_xslt_open_csv(filename, mem, "manualCSV"))
return -1;
#ifndef SUBSURFACE_MOBILE
@ -965,8 +950,7 @@ int parse_manual_file(const char *filename, struct xml_params *params, struct di
fprintf(stderr, "%s/xslt/manualcsv2xml.xslt -\n", SUBSURFACE_SOURCE);
}
#endif
ret = parse_xml_buffer(filename, (char *)mem.buffer, mem.size, log, params);
ret = parse_xml_buffer(filename, mem.data(), mem.size(), log, params);
free(mem.buffer);
return ret;
}

View file

@ -26,7 +26,7 @@ extern "C" {
#endif
int parse_csv_file(const char *filename, struct xml_params *params, const char *csvtemplate, struct divelog *log);
int try_to_open_csv(struct memblock *mem, enum csv_format type, struct divelog *log);
int try_to_open_csv(std::string &mem, enum csv_format type, struct divelog *log);
int parse_txt_file(const char *filename, const char *csv, struct divelog *log);
int parse_seabear_log(const char *filename, struct divelog *log);

View file

@ -40,6 +40,7 @@
#include "core/membuffer.h"
#include "core/file.h"
#include <QtGlobal>
#include <array>
char *dumpfile_name;
char *logfile_name;
@ -139,7 +140,7 @@ static struct gasmix get_deeper_gasmix(struct gasmix a, struct gasmix b)
* @param ngases The number of gas mixes to process.
* @return DC_STATUS_SUCCESS on success, otherwise an error code.
*/
static int parse_gasmixes(device_data_t *devdata, struct dive *dive, dc_parser_t *parser, unsigned int ngases)
static dc_status_t parse_gasmixes(device_data_t *devdata, struct dive *dive, dc_parser_t *parser, unsigned int ngases)
{
static bool shown_warning = false;
unsigned int i;
@ -330,7 +331,7 @@ static void handle_event(struct divecomputer *dc, struct sample *sample, dc_samp
[SAMPLE_EVENT_SAFETYSTOP_MANDATORY] = QT_TRANSLATE_NOOP("gettextFromC", "safety stop (mandatory)"),
[SAMPLE_EVENT_DEEPSTOP] = QT_TRANSLATE_NOOP("gettextFromC", "deepstop"),
[SAMPLE_EVENT_CEILING_SAFETYSTOP] = QT_TRANSLATE_NOOP("gettextFromC", "ceiling (safety stop)"),
[SAMPLE_EVENT_FLOOR] = QT_TRANSLATE_NOOP3("gettextFromC", "below floor", "event showing dive is below deco floor and adding deco time"),
[SAMPLE_EVENT_FLOOR] = std::array<const char *, 2>{QT_TRANSLATE_NOOP3("gettextFromC", "below floor", "event showing dive is below deco floor and adding deco time")}[1],
[SAMPLE_EVENT_DIVETIME] = QT_TRANSLATE_NOOP("gettextFromC", "divetime"),
[SAMPLE_EVENT_MAXDEPTH] = QT_TRANSLATE_NOOP("gettextFromC", "maxdepth"),
[SAMPLE_EVENT_OLF] = QT_TRANSLATE_NOOP("gettextFromC", "OLF"),
@ -379,7 +380,7 @@ sample_cb(dc_sample_type_t type, const dc_sample_value_t *pvalue, void *userdata
{
static unsigned int nsensor = 0;
dc_sample_value_t value = *pvalue;
struct divecomputer *dc = userdata;
struct divecomputer *dc = (divecomputer *)userdata;
struct sample *sample;
/*
@ -494,9 +495,8 @@ sample_cb(dc_sample_type_t type, const dc_sample_value_t *pvalue, void *userdata
}
}
static void dev_info(device_data_t *devdata, const char *fmt, ...)
static void dev_info(device_data_t *, const char *fmt, ...)
{
UNUSED(devdata);
static char buffer[1024];
va_list ap;
@ -524,9 +524,8 @@ static void download_error(const char *fmt, ...)
report_error("Dive %d: %s", import_dive_number, buffer);
}
static int parse_samples(device_data_t *devdata, struct divecomputer *dc, dc_parser_t *parser)
static int parse_samples(device_data_t *, struct divecomputer *dc, dc_parser_t *parser)
{
UNUSED(devdata);
// Parse the sample data.
return dc_parser_samples_foreach(parser, sample_cb, dc);
}
@ -661,7 +660,7 @@ static void parse_string_field(device_data_t *devdata, struct dive *dive, dc_fie
static dc_status_t libdc_header_parser(dc_parser_t *parser, device_data_t *devdata, struct dive *dive)
{
dc_status_t rc = 0;
dc_status_t rc = static_cast<dc_status_t>(0);
dc_datetime_t dt = { 0 };
struct tm tm;
@ -827,7 +826,7 @@ static int dive_cb(const unsigned char *data, unsigned int size,
{
int rc;
dc_parser_t *parser = NULL;
device_data_t *devdata = userdata;
device_data_t *devdata = (device_data_t *)userdata;
struct dive *dive = NULL;
/* reset static data, that is only valid per dive */
@ -873,7 +872,7 @@ static int dive_cb(const unsigned char *data, unsigned int size,
* we have the final deviceid here.
*/
if (fingerprint && fsize && !devdata->fingerprint) {
devdata->fingerprint = calloc(fsize, 1);
devdata->fingerprint = (unsigned char *)calloc(fsize, 1);
if (devdata->fingerprint) {
devdata->fsize = fsize;
devdata->fdeviceid = dive->dc.deviceid;
@ -941,7 +940,7 @@ static void do_save_fingerprint(device_data_t *devdata, const char *tmp, const c
if (close(fd) < 0)
written = -1;
if (written == devdata->fsize) {
if (written == (int)devdata->fsize) {
if (!subsurface_rename(tmp, final))
return;
}
@ -1052,7 +1051,6 @@ 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)
{
char *cachename;
struct memblock mem;
const unsigned char *raw_data;
if (devdata->force_download)
@ -1070,11 +1068,11 @@ static void lookup_fingerprint(dc_device_t *device, device_data_t *devdata)
cachename = fingerprint_file(devdata);
if (verbose)
dev_info(devdata, "Looking for fingerprint in '%s'", cachename);
if (readfile(cachename, &mem) > 0) {
auto [mem, err] = readfile(cachename);
if (err > 0) {
if (verbose)
dev_info(devdata, " ... got %zu bytes", mem.size);
verify_fingerprint(device, devdata, mem.buffer, mem.size);
free(mem.buffer);
dev_info(devdata, " ... got %zu bytes", mem.size());
verify_fingerprint(device, devdata, (unsigned char *)mem.data(), mem.size());
}
free(cachename);
}
@ -1082,11 +1080,11 @@ static void lookup_fingerprint(dc_device_t *device, device_data_t *devdata)
static void event_cb(dc_device_t *device, dc_event_type_t event, const void *data, void *userdata)
{
static unsigned int last = 0;
const dc_event_progress_t *progress = data;
const dc_event_devinfo_t *devinfo = data;
const dc_event_clock_t *clock = data;
const dc_event_vendor_t *vendor = data;
device_data_t *devdata = userdata;
const dc_event_progress_t *progress = (dc_event_progress_t *)data;
const dc_event_devinfo_t *devinfo = (dc_event_devinfo_t *)data;
const dc_event_clock_t *clock = (dc_event_clock_t *)data;
const dc_event_vendor_t *vendor = (dc_event_vendor_t *)data;
device_data_t *devdata = (device_data_t *)userdata;
switch (event) {
case DC_EVENT_WAITING:
@ -1158,9 +1156,8 @@ static void event_cb(dc_device_t *device, dc_event_type_t event, const void *dat
int import_thread_cancelled;
static int cancel_cb(void *userdata)
static int cancel_cb(void *)
{
UNUSED(userdata);
return import_thread_cancelled;
}
@ -1219,9 +1216,8 @@ static const char *do_device_import(device_data_t *data)
}
static dc_timer_t *logfunc_timer = NULL;
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 *, dc_loglevel_t loglevel, const char *file, unsigned int line, const char *function, const char *msg, void *userdata)
{
UNUSED(context);
const char *loglevels[] = { "NONE", "ERROR", "WARNING", "INFO", "DEBUG", "ALL" };
if (logfunc_timer == NULL)

View file

@ -38,13 +38,8 @@ struct lv_sensor_ids {
struct lv_sensor_ids sensor_ids;
static int handle_event_ver2(int code, const unsigned char *ps, unsigned int ps_ptr, struct lv_event *event)
static int handle_event_ver2(int, const unsigned char *, unsigned int, struct lv_event *)
{
UNUSED(code);
UNUSED(ps);
UNUSED(ps_ptr);
UNUSED(event);
// Skip 4 bytes
return 4;
}
@ -99,7 +94,7 @@ static int handle_event_ver3(int code, const unsigned char *ps, unsigned int ps_
// 1 byte ST
skip = 10;
break;
case 0x0010:
case 0x0010: {
// 4 byte time
// 2 byte primary transmitter S/N
// 2 byte buddy transmitter S/N
@ -124,6 +119,7 @@ static int handle_event_ver3(int code, const unsigned char *ps, unsigned int ps_
skip = 26;
break;
}
case 0x0015: // Unknown
skip = 2;
break;
@ -184,7 +180,7 @@ static void parse_dives(int log_version, const unsigned char *buf, unsigned int
place_len = array_uint32_le(buf + ptr + len);
if (len && place_len) {
location = malloc(len + place_len + 4);
location = (char *)malloc(len + place_len + 4);
memset(location, 0, len + place_len + 4);
memcpy(location, buf + ptr, len);
memcpy(location + len, ", ", 2);
@ -266,8 +262,9 @@ static void parse_dives(int log_version, const unsigned char *buf, unsigned int
sample_interval = intervals[*(buf + ptr)];
ptr += 1;
float start_cns = 0;
unsigned char dive_mode = 0, algorithm = 0;
[[maybe_unused]] float start_cns = 0;
[[maybe_unused]] unsigned char dive_mode = 0;
[[maybe_unused]] unsigned char algorithm = 0;
if (array_uint32_le(buf + ptr) != sample_count) {
// Xeo, with CNS and OTU
start_cns = *(float *) (buf + ptr);
@ -290,9 +287,6 @@ static void parse_dives(int log_version, const unsigned char *buf, unsigned int
break;
}
// we aren't using the start_cns, dive_mode, and algorithm, yet
UNUSED(start_cns);
UNUSED(dive_mode);
UNUSED(algorithm);
ptr += 4;
@ -438,11 +432,10 @@ static void parse_dives(int log_version, const unsigned char *buf, unsigned int
free_dive(dive);
}
int try_to_open_liquivision(const char *filename, struct memblock *mem, struct divelog *log)
int try_to_open_liquivision(const char *, std::string &mem, struct divelog *log)
{
UNUSED(filename);
const unsigned char *buf = mem->buffer;
unsigned int buf_size = mem->size;
const unsigned char *buf = (unsigned char *)mem.data();
unsigned int buf_size = (unsigned int)mem.size();
unsigned int ptr;
int log_version;

View file

@ -237,10 +237,10 @@ void TestParse::testParseNewFormat()
void TestParse::testParseDLD()
{
struct memblock mem;
QString filename = SUBSURFACE_TEST_DATA "/dives/TestDiveDivelogsDE.DLD";
QVERIFY(readfile(filename.toLatin1().data(), &mem) > 0);
auto [mem, err] = readfile(filename.toLatin1().data());
QVERIFY(err > 0);
QVERIFY(try_to_open_zip(filename.toLatin1().data(), &divelog) > 0);
fprintf(stderr, "number of dives from DLD: %d \n", divelog.dives->nr);