From cf7c54bd56accae35c97eeef2b832cb779fdf48e Mon Sep 17 00:00:00 2001 From: Berthold Stoeger Date: Fri, 1 Mar 2024 13:09:20 +0100 Subject: [PATCH] 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 --- Subsurface-mobile.pro | 8 +- core/CMakeLists.txt | 8 +- core/{cochran.c => cochran.cpp} | 36 ++-- core/{datatrak.c => datatrak.cpp} | 48 +++-- core/datatrak.h | 10 +- core/file.cpp | 117 +++++------ core/file.h | 22 +- core/import-csv.cpp | 190 ++++++++---------- core/import-csv.h | 2 +- ...{libdivecomputer.c => libdivecomputer.cpp} | 46 ++--- core/{liquivision.c => liquivision.cpp} | 27 +-- tests/testparse.cpp | 4 +- 12 files changed, 233 insertions(+), 285 deletions(-) rename core/{cochran.c => cochran.cpp} (96%) rename core/{datatrak.c => datatrak.cpp} (94%) rename core/{libdivecomputer.c => libdivecomputer.cpp} (97%) rename core/{liquivision.c => liquivision.cpp} (95%) diff --git a/Subsurface-mobile.pro b/Subsurface-mobile.pro index 77b999295..07f185606 100644 --- a/Subsurface-mobile.pro +++ b/Subsurface-mobile.pro @@ -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 \ diff --git a/core/CMakeLists.txt b/core/CMakeLists.txt index 6c3b51316..e06f10990 100644 --- a/core/CMakeLists.txt +++ b/core/CMakeLists.txt @@ -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 diff --git a/core/cochran.c b/core/cochran.cpp similarity index 96% rename from core/cochran.c rename to core/cochran.cpp index 7bc1f5fd6..1269ae919 100644 --- a/core/cochran.c +++ b/core/cochran.cpp @@ -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); } diff --git a/core/datatrak.c b/core/datatrak.cpp similarity index 94% rename from core/datatrak.c rename to core/datatrak.cpp index 67aa08ebd..8bc214168 100644 --- a/core/datatrak.c +++ b/core/datatrak.cpp @@ -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")); diff --git a/core/datatrak.h b/core/datatrak.h index 05534fcee..701f16cec 100644 --- a/core/datatrak.h +++ b/core/datatrak.h @@ -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 diff --git a/core/file.cpp b/core/file.cpp index 901e465e8..a4391ebe9 100644 --- a/core/file.cpp +++ b/core/file.cpp @@ -31,61 +31,47 @@ #define O_BINARY 0 #endif -extern "C" int readfile(const char *filename, struct memblock *mem) +std::pair 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 mem(size); + std::vector 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); } diff --git a/core/file.h b/core/file.h index 7edf4572f..3303f224f 100644 --- a/core/file.h +++ b/core/file.h @@ -7,23 +7,14 @@ #include #include -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 +#include + +// return data, errorcode pair. +extern std::pair 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 diff --git a/core/import-csv.cpp b/core/import-csv.cpp index 288587cec..024720be1 100644 --- a/core/import-csv.cpp +++ b/core/import-csv.cpp @@ -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 "&" => "&" + * + * 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", 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; } diff --git a/core/import-csv.h b/core/import-csv.h index 38e413e9b..b71ad2308 100644 --- a/core/import-csv.h +++ b/core/import-csv.h @@ -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); diff --git a/core/libdivecomputer.c b/core/libdivecomputer.cpp similarity index 97% rename from core/libdivecomputer.c rename to core/libdivecomputer.cpp index b72bd2c80..6d2d691b7 100644 --- a/core/libdivecomputer.c +++ b/core/libdivecomputer.cpp @@ -40,6 +40,7 @@ #include "core/membuffer.h" #include "core/file.h" #include +#include 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{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(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) diff --git a/core/liquivision.c b/core/liquivision.cpp similarity index 95% rename from core/liquivision.c rename to core/liquivision.cpp index f998d4fd0..a6bce5668 100644 --- a/core/liquivision.c +++ b/core/liquivision.cpp @@ -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; diff --git a/tests/testparse.cpp b/tests/testparse.cpp index 791c94984..eba98d513 100644 --- a/tests/testparse.cpp +++ b/tests/testparse.cpp @@ -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);