mirror of
https://github.com/subsurface/subsurface.git
synced 2025-02-19 22:16:15 +00:00
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:
parent
2f4dbf1848
commit
cf7c54bd56
12 changed files with 233 additions and 285 deletions
|
@ -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 \
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -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"));
|
|
@ -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
|
||||
|
|
117
core/file.cpp
117
core/file.cpp
|
@ -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);
|
||||
}
|
||||
|
|
22
core/file.h
22
core/file.h
|
@ -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
|
||||
|
|
|
@ -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</%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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)
|
|
@ -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;
|
||||
|
|
@ -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);
|
||||
|
|
Loading…
Add table
Reference in a new issue