mirror of
https://github.com/subsurface/subsurface.git
synced 2025-01-19 14:25:27 +00:00
import: use C++ primitives in smartrak.cpp
Makes memory management more palatable. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
This commit is contained in:
parent
14cfb17c1a
commit
b89029353f
1 changed files with 264 additions and 343 deletions
|
@ -32,6 +32,9 @@
|
||||||
#include <mdbtools.h>
|
#include <mdbtools.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <locale.h>
|
#include <locale.h>
|
||||||
|
#include <array>
|
||||||
|
#include <string_view>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#if defined(WIN32) || defined(_WIN32)
|
#if defined(WIN32) || defined(_WIN32)
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
|
@ -46,7 +49,7 @@
|
||||||
#include "core/libdivecomputer.h"
|
#include "core/libdivecomputer.h"
|
||||||
#include "core/divesite.h"
|
#include "core/divesite.h"
|
||||||
#include "core/errorhelper.h"
|
#include "core/errorhelper.h"
|
||||||
#include "core/membuffer.h"
|
#include "core/format.h"
|
||||||
#include "core/tag.h"
|
#include "core/tag.h"
|
||||||
#include "core/device.h"
|
#include "core/device.h"
|
||||||
|
|
||||||
|
@ -54,15 +57,6 @@
|
||||||
int smtk_version;
|
int smtk_version;
|
||||||
int tanks;
|
int tanks;
|
||||||
|
|
||||||
/* Freeing temp char arrays utility */
|
|
||||||
static void smtk_free(char **array, int count)
|
|
||||||
{
|
|
||||||
int n;
|
|
||||||
for (n = 0; n < count; n++)
|
|
||||||
free(array[n]);
|
|
||||||
array = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* There are AFAIK three versions of Smarttrak DB format. The newer one supports trimix and up
|
* There are AFAIK three versions of Smarttrak DB format. The newer one supports trimix and up
|
||||||
* to 10 tanks. The intermediate one just 3 tanks and no trimix but only nitrox. This is a
|
* to 10 tanks. The intermediate one just 3 tanks and no trimix but only nitrox. This is a
|
||||||
|
@ -138,7 +132,7 @@ static void smtk_date_to_tm(char *d_buffer, struct tm *tm_date)
|
||||||
* Fills the time part of a tm structure with the string data obtained
|
* Fills the time part of a tm structure with the string data obtained
|
||||||
* from smartrak in format "DD/MM/YY HH:MM:SS" where date is irrelevant.
|
* from smartrak in format "DD/MM/YY HH:MM:SS" where date is irrelevant.
|
||||||
*/
|
*/
|
||||||
static void smtk_time_to_tm(char *t_buffer, struct tm *tm_date)
|
static void smtk_time_to_tm(const char *t_buffer, struct tm *tm_date)
|
||||||
{
|
{
|
||||||
int n, hr, min, sec;
|
int n, hr, min, sec;
|
||||||
|
|
||||||
|
@ -163,7 +157,7 @@ static void smtk_time_to_tm(char *t_buffer, struct tm *tm_date)
|
||||||
* TODO: modify to support times > 24h where date means difference in days
|
* TODO: modify to support times > 24h where date means difference in days
|
||||||
* from 29/12/99.
|
* from 29/12/99.
|
||||||
*/
|
*/
|
||||||
static unsigned int smtk_time_to_secs(char *t_buffer)
|
static unsigned int smtk_time_to_secs(const char *t_buffer)
|
||||||
{
|
{
|
||||||
int n, hr, min, sec;
|
int n, hr, min, sec;
|
||||||
|
|
||||||
|
@ -200,62 +194,94 @@ static time_t smtk_timegm(struct tm *tm)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class SmtkTable {
|
||||||
|
struct Entry {
|
||||||
|
std::array<char, MDB_BIND_SIZE> value;
|
||||||
|
int len;
|
||||||
|
};
|
||||||
|
std::vector<Entry> data;
|
||||||
|
public:
|
||||||
|
MdbTableDef *table;
|
||||||
|
SmtkTable(MdbHandle *mdb, const char *name);
|
||||||
|
~SmtkTable();
|
||||||
|
size_t size() const {
|
||||||
|
return data.size();
|
||||||
|
}
|
||||||
|
operator bool() const {
|
||||||
|
return !!table;
|
||||||
|
}
|
||||||
|
int fetch_row() {
|
||||||
|
return table ? mdb_fetch_row(table) : 0;
|
||||||
|
}
|
||||||
|
const char *get_data(size_t col) const {
|
||||||
|
return data[col].value.data();
|
||||||
|
}
|
||||||
|
std::string_view get_string_view(size_t col) const {
|
||||||
|
return std::string_view(get_data(col));
|
||||||
|
}
|
||||||
|
int get_len(size_t col) const {
|
||||||
|
return data[col].len;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Returns an opened table given its name and mdb. outcol and outbounder have to be allocated
|
* Returns an opened table given its name and mdb.
|
||||||
* by the caller and are filled here.
|
|
||||||
*/
|
*/
|
||||||
static MdbTableDef *smtk_open_table(MdbHandle *mdb, const char *tablename, char **outbounder, int *outlens[])
|
SmtkTable::SmtkTable(MdbHandle *mdb, const char *tablename)
|
||||||
|
: table(nullptr)
|
||||||
{
|
{
|
||||||
MdbCatalogEntry *entry;
|
MdbCatalogEntry *entry;
|
||||||
MdbTableDef *table;
|
|
||||||
|
|
||||||
entry = mdb_get_catalogentry_by_name(mdb, tablename);
|
entry = mdb_get_catalogentry_by_name(mdb, tablename);
|
||||||
if (!entry)
|
if (!entry)
|
||||||
return NULL;
|
return;
|
||||||
table = mdb_read_table(entry);
|
table = mdb_read_table(entry);
|
||||||
if (!table)
|
if (!table)
|
||||||
return NULL;
|
return;
|
||||||
mdb_read_columns(table);
|
mdb_read_columns(table);
|
||||||
for (size_t i = 0; i < table->num_cols; i++) {
|
data.resize(table->num_cols);
|
||||||
outbounder[i] = (char *) g_malloc(MDB_BIND_SIZE);
|
for (size_t i = 0; i < table->num_cols; i++)
|
||||||
if (outlens) {
|
mdb_bind_column(table, i+1, data[i].value.data(), &data[i].len);
|
||||||
outlens[i] = (int *) g_malloc(sizeof(int));
|
|
||||||
mdb_bind_column(table, i+1, outbounder[i], outlens[i]);
|
|
||||||
} else {
|
|
||||||
mdb_bind_column(table, i+1, outbounder[i], NULL);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
mdb_rewind_table(table);
|
mdb_rewind_table(table);
|
||||||
|
}
|
||||||
|
|
||||||
return table;
|
SmtkTable::~SmtkTable()
|
||||||
|
{
|
||||||
|
if (table)
|
||||||
|
mdb_free_tabledef(table);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Utility function which joins three strings, being the second a separator string,
|
* Utility function which joins three strings, being the second a separator string,
|
||||||
* usually a "\n". The third is a format string with an argument list.
|
* usually a "\n". The third is a format string with an argument list.
|
||||||
* If the original string is NULL, then just returns the third.
|
* If the original string is empty, then just returns the third.
|
||||||
* This is based in add_to_string() and add_to_string_va(), and, as its parents
|
* The first argument is overwritten with the concatenated string.
|
||||||
* frees the original string.
|
|
||||||
*/
|
*/
|
||||||
static char *smtk_concat_str(char *orig, const char *sep, const char *fmt, ...)
|
static void concat(std::string &orig, const char *sep, std::string_view s)
|
||||||
{
|
{
|
||||||
char *str;
|
if (!orig.empty())
|
||||||
va_list args;
|
orig += sep;
|
||||||
struct membufferpp out, in;
|
orig += s;
|
||||||
|
}
|
||||||
|
|
||||||
va_start(args, fmt);
|
/*
|
||||||
put_vformat(&in, fmt, args);
|
* Temporary funcion as long as core still has C-strings.
|
||||||
if (orig != NULL) {
|
* Equivalent to concat, but takes a C-string as first argument and
|
||||||
put_format(&out, "%s%s%s", orig, sep, mb_cstring(&in));
|
* frees it. Returns a newly allocated copy.
|
||||||
str = copy_string(mb_cstring(&out));
|
*
|
||||||
} else {
|
* Note: taking "const char * const *" is an ugly hack to
|
||||||
str = copy_string(mb_cstring(&in));
|
* allow passing pointer to "const char *" as well as
|
||||||
}
|
* "char *". Which in turn is necessary, as this function currently
|
||||||
va_end(args);
|
* replaces "const char *" strings.
|
||||||
|
*/
|
||||||
free(orig);
|
static void concat(const char * const *orig_in, const char *sep, std::string_view s)
|
||||||
|
{
|
||||||
return str;
|
char **orig = const_cast<char **>(orig_in);
|
||||||
|
char *to_free = *orig;
|
||||||
|
std::string orig_std(*orig ? *orig : "");
|
||||||
|
concat(orig_std, sep, s);
|
||||||
|
*orig = strdup(orig_std.c_str());
|
||||||
|
free(to_free);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -267,9 +293,7 @@ static char *smtk_concat_str(char *orig, const char *sep, const char *fmt, ...)
|
||||||
*/
|
*/
|
||||||
static void smtk_wreck_site(MdbHandle *mdb, char *site_idx, struct dive_site *ds)
|
static void smtk_wreck_site(MdbHandle *mdb, char *site_idx, struct dive_site *ds)
|
||||||
{
|
{
|
||||||
MdbTableDef *table;
|
std::string notes;
|
||||||
char *bound_values[MDB_MAX_COLS];
|
|
||||||
char *tmp = NULL, *notes = NULL;
|
|
||||||
int i;
|
int i;
|
||||||
uint32_t d;
|
uint32_t d;
|
||||||
const char *wreck_fields[] = {QT_TRANSLATE_NOOP("gettextFromC", "Built"), QT_TRANSLATE_NOOP("gettextFromC", "Sank"), QT_TRANSLATE_NOOP("gettextFromC", "Sank Time"),
|
const char *wreck_fields[] = {QT_TRANSLATE_NOOP("gettextFromC", "Built"), QT_TRANSLATE_NOOP("gettextFromC", "Sank"), QT_TRANSLATE_NOOP("gettextFromC", "Sank Time"),
|
||||||
|
@ -278,54 +302,55 @@ static void smtk_wreck_site(MdbHandle *mdb, char *site_idx, struct dive_site *ds
|
||||||
QT_TRANSLATE_NOOP("gettextFromC", "Draught"), QT_TRANSLATE_NOOP("gettextFromC", "Displacement"), QT_TRANSLATE_NOOP("gettextFromC", "Cargo"),
|
QT_TRANSLATE_NOOP("gettextFromC", "Draught"), QT_TRANSLATE_NOOP("gettextFromC", "Displacement"), QT_TRANSLATE_NOOP("gettextFromC", "Cargo"),
|
||||||
QT_TRANSLATE_NOOP("gettextFromC", "Notes")};
|
QT_TRANSLATE_NOOP("gettextFromC", "Notes")};
|
||||||
|
|
||||||
table = smtk_open_table(mdb, "Wreck", bound_values, NULL);
|
SmtkTable table(mdb, "Wreck");
|
||||||
|
|
||||||
/* Sanity check for table, unlikely but ... */
|
/* Sanity check for table, unlikely but ... */
|
||||||
if (!table)
|
if (!table)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/* Begin parsing. Write strings to notes only if available.*/
|
/* Begin parsing. Write strings to notes only if available.*/
|
||||||
while (mdb_fetch_row(table)) {
|
while (table.fetch_row()) {
|
||||||
if (!strcmp(bound_values[1], site_idx)) {
|
if (!strcmp(table.get_data(1), site_idx)) {
|
||||||
notes = smtk_concat_str(notes, "\n", translate("gettextFromC", "Wreck Data"));
|
concat(notes, "\n", translate("gettextFromC", "Wreck Data"));
|
||||||
for (i = 3; i < 16; i++) {
|
for (i = 3; i < 16; i++) {
|
||||||
switch (i) {
|
switch (i) {
|
||||||
case 3:
|
case 3:
|
||||||
case 4:
|
case 4: {
|
||||||
tmp = copy_string(bound_values[i]);
|
std::string_view tmp = table.get_string_view(i);
|
||||||
if (tmp)
|
if (!tmp.empty()) {
|
||||||
notes = smtk_concat_str(notes, "\n", "%s: %s", wreck_fields[i - 3], strtok(tmp , " "));
|
tmp = tmp.substr(0, tmp.find(' '));
|
||||||
free(tmp);
|
concat(notes, "\n", format_string_std("%s: %s", wreck_fields[i - 3], std::string(tmp).c_str()));
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case 5:
|
}
|
||||||
tmp = copy_string(bound_values[i]);
|
case 5: {
|
||||||
if (tmp)
|
std::string_view tmp = table.get_string_view(i);
|
||||||
notes = smtk_concat_str(notes, "\n", "%s: %s", wreck_fields[i - 3], strrchr(tmp, ' '));
|
if (!tmp.empty()) {
|
||||||
free(tmp);
|
size_t pos = tmp.rfind(' ');
|
||||||
|
tmp.remove_prefix(pos + 1);
|
||||||
|
concat(notes, "\n", format_string_std("%s: %s", wreck_fields[i - 3], std::string(tmp).c_str()));
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
case 6 ... 9:
|
case 6 ... 9:
|
||||||
case 14:
|
case 14:
|
||||||
case 15:
|
case 15: {
|
||||||
tmp = copy_string(bound_values[i]);
|
const char *tmp = table.get_data(i);
|
||||||
if (tmp)
|
if (!empty_string(tmp))
|
||||||
notes = smtk_concat_str(notes, "\n", "%s: %s", wreck_fields[i - 3], tmp);
|
concat(notes, "\n", format_string_std("%s: %s", wreck_fields[i - 3], tmp));
|
||||||
free(tmp);
|
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
d = lrintl(strtold(bound_values[i], NULL));
|
d = lrintl(strtold(table.get_data(1), NULL));
|
||||||
if (d)
|
if (d)
|
||||||
notes = smtk_concat_str(notes, "\n", "%s: %d", wreck_fields[i - 3], d);
|
concat(notes, "\n", format_string_std("%s: %d", wreck_fields[i - 3], d));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ds->notes = smtk_concat_str(ds->notes, "\n", "%s", notes);
|
concat(&ds->notes, "\n", notes);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* Clean up and exit */
|
|
||||||
smtk_free(bound_values, table->num_cols);
|
|
||||||
mdb_free_tabledef(table);
|
|
||||||
free(notes);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -340,117 +365,94 @@ static void smtk_wreck_site(MdbHandle *mdb, char *site_idx, struct dive_site *ds
|
||||||
*/
|
*/
|
||||||
static void smtk_build_location(MdbHandle *mdb, char *idx, struct dive_site **location, struct divelog *log)
|
static void smtk_build_location(MdbHandle *mdb, char *idx, struct dive_site **location, struct divelog *log)
|
||||||
{
|
{
|
||||||
MdbTableDef *table;
|
|
||||||
char *bound_values[MDB_MAX_COLS];
|
|
||||||
int i, rc;
|
int i, rc;
|
||||||
uint32_t d;
|
uint32_t d;
|
||||||
struct dive_site *ds;
|
struct dive_site *ds;
|
||||||
location_t loc;
|
location_t loc;
|
||||||
char *str = NULL, *loc_idx = NULL, *site = NULL, *notes = NULL;
|
std::string str, loc_idx, site, notes;
|
||||||
const char *site_fields[] = {QT_TRANSLATE_NOOP("gettextFromC", "Altitude"), QT_TRANSLATE_NOOP("gettextFromC", "Depth"),
|
const char *site_fields[] = {QT_TRANSLATE_NOOP("gettextFromC", "Altitude"), QT_TRANSLATE_NOOP("gettextFromC", "Depth"),
|
||||||
QT_TRANSLATE_NOOP("gettextFromC", "Notes")};
|
QT_TRANSLATE_NOOP("gettextFromC", "Notes")};
|
||||||
|
|
||||||
/* Read data from Site table. Format notes for the dive site if any.*/
|
/* Read data from Site table. Format notes for the dive site if any.*/
|
||||||
table = smtk_open_table(mdb, "Site", bound_values, NULL);
|
{
|
||||||
if (!table)
|
SmtkTable table(mdb, "Site");
|
||||||
return;
|
if (!table)
|
||||||
do {
|
return;
|
||||||
rc = mdb_fetch_row(table);
|
do {
|
||||||
} while (strcasecmp(bound_values[0], idx) && rc != 0);
|
rc = table.fetch_row();
|
||||||
if (rc == 0) {
|
} while (strcasecmp(table.get_data(0), idx) && rc != 0);
|
||||||
smtk_free(bound_values, table->num_cols);
|
if (rc == 0)
|
||||||
mdb_free_tabledef(table);
|
return;
|
||||||
return;
|
loc_idx = table.get_data(2);
|
||||||
}
|
site = table.get_data(1);
|
||||||
loc_idx = copy_string(bound_values[2]);
|
loc = create_location(strtod(table.get_data(6), NULL), strtod(table.get_data(7), NULL));
|
||||||
site = copy_string(bound_values[1]);
|
|
||||||
loc = create_location(strtod(bound_values[6], NULL), strtod(bound_values[7], NULL));
|
|
||||||
|
|
||||||
for (i = 8; i < 11; i++) {
|
for (i = 8; i < 11; i++) {
|
||||||
switch (i) {
|
switch (i) {
|
||||||
case 8:
|
case 8:
|
||||||
case 9:
|
case 9:
|
||||||
d = lrintl(strtold(bound_values[i], NULL));
|
d = lrintl(strtold(table.get_data(i), NULL));
|
||||||
if (d)
|
if (d)
|
||||||
notes = smtk_concat_str(notes, "\n", "%s: %d m", site_fields[i - 8], d);
|
concat(notes, "\n", format_string_std("%s: %d m", site_fields[i - 8], d));
|
||||||
break;
|
break;
|
||||||
case 10:
|
case 10:
|
||||||
if (memcmp(bound_values[i], "\0", 1))
|
if (!empty_string(table.get_data(i)))
|
||||||
notes = smtk_concat_str(notes, "\n", "%s: %s", site_fields[i - 8], bound_values[i]);
|
concat(notes, "\n", format_string_std("%s: %s", site_fields[i - 8], table.get_data(i)));
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
smtk_free(bound_values, table->num_cols);
|
|
||||||
mdb_free_tabledef(table);
|
|
||||||
|
|
||||||
/* Read data from Location table, linked to Site by loc_idx */
|
/* Read data from Location table, linked to Site by loc_idx */
|
||||||
table = smtk_open_table(mdb, "Location", bound_values, NULL);
|
SmtkTable table(mdb, "Location");
|
||||||
mdb_rewind_table(table);
|
|
||||||
do {
|
do {
|
||||||
rc = mdb_fetch_row(table);
|
rc = table.fetch_row();
|
||||||
} while (strcasecmp(bound_values[0], loc_idx) && rc != 0);
|
} while (strcasecmp(table.get_data(0), loc_idx.c_str()) && rc != 0);
|
||||||
if (rc == 0) {
|
if (rc == 0)
|
||||||
smtk_free(bound_values, table->num_cols);
|
|
||||||
mdb_free_tabledef(table);
|
|
||||||
if(notes)
|
|
||||||
free(notes);
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Create a string for Subsurface's dive site structure with coordinates
|
* Create a string for Subsurface's dive site structure with coordinates
|
||||||
* if available, if the site's name doesn't previously exists.
|
* if available, if the site's name doesn't previously exists.
|
||||||
*/
|
*/
|
||||||
if (memcmp(bound_values[3], "\0", 1))
|
if (!empty_string(table.get_data(3)))
|
||||||
str = smtk_concat_str(str, ", ", "%s", bound_values[3]); // Country
|
concat(str, ", ", table.get_string_view(3)); // Country
|
||||||
if (memcmp(bound_values[2], "\0", 1))
|
if (!empty_string(table.get_data(2)))
|
||||||
str = smtk_concat_str(str, ", ", "%s", bound_values[2]); // State - Province
|
concat(str, ", ", table.get_string_view(2)); // State - Province
|
||||||
if (memcmp(bound_values[1], "\0", 1))
|
if (!empty_string(table.get_data(1)))
|
||||||
str = smtk_concat_str(str, ", ", "%s", bound_values[1]); // Locality
|
concat(str, ", ", table.get_string_view(1)); // Locality
|
||||||
str = smtk_concat_str(str, ", ", "%s", site);
|
concat(str, ", ", site);
|
||||||
|
|
||||||
ds = get_dive_site_by_name(str, log->sites);
|
ds = get_dive_site_by_name(str.c_str(), log->sites);
|
||||||
if (!ds) {
|
if (!ds) {
|
||||||
if (!has_location(&loc))
|
if (!has_location(&loc))
|
||||||
ds = create_dive_site(str, log->sites);
|
ds = create_dive_site(str.c_str(), log->sites);
|
||||||
else
|
else
|
||||||
ds = create_dive_site_with_gps(str, &loc, log->sites);
|
ds = create_dive_site_with_gps(str.c_str(), &loc, log->sites);
|
||||||
}
|
}
|
||||||
*location = ds;
|
*location = ds;
|
||||||
smtk_free(bound_values, table->num_cols);
|
|
||||||
|
|
||||||
/* Insert site notes */
|
/* Insert site notes */
|
||||||
ds->notes = copy_string(notes);
|
free(ds->notes);
|
||||||
free(notes);
|
ds->notes = strdup(notes.c_str());
|
||||||
|
|
||||||
/* Check if we have a wreck */
|
/* Check if we have a wreck */
|
||||||
smtk_wreck_site(mdb, idx, ds);
|
smtk_wreck_site(mdb, idx, ds);
|
||||||
|
|
||||||
/* Clean up and exit */
|
|
||||||
mdb_free_tabledef(table);
|
|
||||||
free(loc_idx);
|
|
||||||
free(site);
|
|
||||||
free(str);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void smtk_build_tank_info(MdbHandle *mdb, cylinder_t *tank, char *idx)
|
static void smtk_build_tank_info(MdbHandle *mdb, cylinder_t *tank, char *idx)
|
||||||
{
|
{
|
||||||
MdbTableDef *table;
|
|
||||||
char *bound_values[MDB_MAX_COLS];
|
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
table = smtk_open_table(mdb, "Tank", bound_values, NULL);
|
SmtkTable table(mdb, "Tank");
|
||||||
if (!table)
|
if (!table)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
for (i = 1; i <= atoi(idx); i++)
|
for (i = 1; i <= atoi(idx); i++)
|
||||||
mdb_fetch_row(table);
|
table.fetch_row();
|
||||||
tank->type.description = copy_string(bound_values[1]);
|
tank->type.description = copy_string(table.get_data(1));
|
||||||
tank->type.size.mliter = lrint(strtod(bound_values[2], NULL) * 1000);
|
tank->type.size.mliter = lrint(strtod(table.get_data(2), NULL) * 1000);
|
||||||
tank->type.workingpressure.mbar = lrint(strtod(bound_values[4], NULL) * 1000);
|
tank->type.workingpressure.mbar = lrint(strtod(table.get_data(4), NULL) * 1000);
|
||||||
|
|
||||||
smtk_free(bound_values, table->num_cols);
|
|
||||||
mdb_free_tabledef(table);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -552,54 +554,6 @@ struct types_list {
|
||||||
struct types_list *next;
|
struct types_list *next;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Head insert types_list items in a list */
|
|
||||||
static void smtk_head_insert(struct types_list **head, int index, char *txt)
|
|
||||||
{
|
|
||||||
struct types_list *item = (struct types_list *) malloc(sizeof(struct types_list));
|
|
||||||
|
|
||||||
item->next = *head;
|
|
||||||
item->idx = index;
|
|
||||||
item->text = txt;
|
|
||||||
*head = item;
|
|
||||||
item = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Clean types_list lists */
|
|
||||||
static void smtk_list_free(struct types_list *head)
|
|
||||||
{
|
|
||||||
struct types_list *p = head;
|
|
||||||
while (p) {
|
|
||||||
struct types_list *nxt = p->next;
|
|
||||||
free(p->text);
|
|
||||||
free(p);
|
|
||||||
p = nxt;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Return the number of rows in a given table */
|
|
||||||
static int get_rows_num(MdbHandle *mdb, const char *table_name)
|
|
||||||
{
|
|
||||||
MdbTableDef *table;
|
|
||||||
char *bound_values[MDB_MAX_COLS];
|
|
||||||
int n = 0, i = 0;
|
|
||||||
|
|
||||||
table = smtk_open_table(mdb, table_name, bound_values, NULL);
|
|
||||||
if (!table)
|
|
||||||
return n;
|
|
||||||
|
|
||||||
/* We can get an sparse array (less rows in the table than
|
|
||||||
* index). Ensure we allocate as many strings as greater
|
|
||||||
* index, at least */
|
|
||||||
while (mdb_fetch_row(table)) {
|
|
||||||
i = atoi(bound_values[0]);
|
|
||||||
if (i > n)
|
|
||||||
n = i;
|
|
||||||
}
|
|
||||||
smtk_free(bound_values, table->num_cols);
|
|
||||||
mdb_free_tabledef(table);
|
|
||||||
return n;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Build a list from a given table_name (Type, Gear, etc)
|
* Build a list from a given table_name (Type, Gear, etc)
|
||||||
* Managed tables formats: Just consider Idx and Text
|
* Managed tables formats: Just consider Idx and Text
|
||||||
|
@ -615,26 +569,26 @@ static int get_rows_num(MdbHandle *mdb, const char *table_name)
|
||||||
* be using some other like Vendor (in Gear) or Latin name (in Fish). I'll take a look at this
|
* be using some other like Vendor (in Gear) or Latin name (in Fish). I'll take a look at this
|
||||||
* in the future, may be something like Buddy table...
|
* in the future, may be something like Buddy table...
|
||||||
*/
|
*/
|
||||||
static void smtk_build_list(MdbHandle *mdb, const char *table_name, char *array[])
|
static std::vector<std::string> smtk_build_list(MdbHandle *mdb, const char *table_name)
|
||||||
{
|
{
|
||||||
MdbTableDef *table;
|
SmtkTable table(mdb, table_name);
|
||||||
char *bound_values[MDB_MAX_COLS], *str;
|
|
||||||
|
|
||||||
table = smtk_open_table(mdb, table_name, bound_values, NULL);
|
|
||||||
if (!table)
|
if (!table)
|
||||||
return;
|
return {};
|
||||||
|
|
||||||
/* Read the table items into the array */
|
/* Read the table items into the array */
|
||||||
while (mdb_fetch_row(table)) {
|
std::vector<std::string> res;
|
||||||
str = bound_values[1];
|
while (table.fetch_row()) {
|
||||||
if (str && (!strcmp(str, "---") || !strcmp(str, "--")))
|
std::string str(table.get_data(1));
|
||||||
str = NULL;
|
if (str == "---" || str == "--")
|
||||||
array[atoi(bound_values[0]) - 1] = copy_string(str);
|
str.clear();
|
||||||
|
int pos = atoi(table.get_data(0)) - 1;
|
||||||
|
if (pos < 0)
|
||||||
|
continue;
|
||||||
|
if (pos >= (int)res.size())
|
||||||
|
res.resize(pos + 1);
|
||||||
|
res[pos] = std::move(str);
|
||||||
}
|
}
|
||||||
|
return res;
|
||||||
/* clean up and exit */
|
|
||||||
smtk_free(bound_values, table->num_cols);
|
|
||||||
mdb_free_tabledef(table);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -644,28 +598,22 @@ static void smtk_build_list(MdbHandle *mdb, const char *table_name, char *array[
|
||||||
* Table relation format:
|
* Table relation format:
|
||||||
* | Diveidx | Idx |
|
* | Diveidx | Idx |
|
||||||
*/
|
*/
|
||||||
static struct types_list *smtk_index_list(MdbHandle *mdb, const char *table_name, char *dive_idx)
|
static std::vector<int> smtk_index_list(MdbHandle *mdb, const char *table_name, char *dive_idx)
|
||||||
{
|
{
|
||||||
MdbTableDef *table;
|
SmtkTable table(mdb, table_name);
|
||||||
char *bounders[MDB_MAX_COLS];
|
|
||||||
struct types_list *head = NULL;
|
|
||||||
|
|
||||||
table = smtk_open_table(mdb, table_name, bounders, NULL);
|
|
||||||
|
|
||||||
/* Sanity check */
|
/* Sanity check */
|
||||||
if (!table)
|
if (!table)
|
||||||
return NULL;
|
return {};
|
||||||
|
|
||||||
/* Parse the table searching for dive_idx */
|
/* Parse the table searching for dive_idx */
|
||||||
while (mdb_fetch_row(table)) {
|
std::vector<int> res;
|
||||||
if (!strcmp(dive_idx, bounders[0]))
|
while (table.fetch_row()) {
|
||||||
smtk_head_insert(&head, atoi(bounders[1]), NULL);
|
if (!strcmp(dive_idx, table.get_data(0)))
|
||||||
|
res.push_back(atoi(table.get_data(1)));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Clean up and exit */
|
return res;
|
||||||
smtk_free(bounders, table->num_cols);
|
|
||||||
mdb_free_tabledef(table);
|
|
||||||
return head;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -676,52 +624,55 @@ static struct types_list *smtk_index_list(MdbHandle *mdb, const char *table_name
|
||||||
* Buddy table format:
|
* Buddy table format:
|
||||||
* | Idx | Text (nickname) | Name | Firstname | Middlename | Title | Picture | Phone | ...
|
* | Idx | Text (nickname) | Name | Firstname | Middlename | Title | Picture | Phone | ...
|
||||||
*/
|
*/
|
||||||
static void smtk_build_buddies(MdbHandle *mdb, char *array[])
|
static std::vector<std::string> smtk_build_buddies(MdbHandle *mdb)
|
||||||
{
|
{
|
||||||
MdbTableDef *table;
|
SmtkTable table(mdb, "Buddy");
|
||||||
char *bound_values[MDB_MAX_COLS], *fullname = NULL, *str = NULL;
|
|
||||||
|
|
||||||
table = smtk_open_table(mdb, "Buddy", bound_values, NULL);
|
|
||||||
if (!table)
|
if (!table)
|
||||||
return;
|
return {};
|
||||||
|
|
||||||
while (mdb_fetch_row(table)) {
|
std::vector<std::string> res;
|
||||||
if (!empty_string(bound_values[3]))
|
while (table.fetch_row()) {
|
||||||
fullname = smtk_concat_str(fullname, " ", "%s", bound_values[3]);
|
std::string fullname;
|
||||||
if (!empty_string(bound_values[4]))
|
if (!empty_string(table.get_data(3)))
|
||||||
fullname = smtk_concat_str(fullname, " ", "%s", bound_values[4]);
|
concat(fullname, " ", table.get_string_view(3));
|
||||||
if (!empty_string(bound_values[2]))
|
if (!empty_string(table.get_data(4)))
|
||||||
fullname = smtk_concat_str(fullname, " ", "%s", bound_values[2]);
|
concat(fullname, " ", table.get_string_view(4));
|
||||||
if (fullname && !same_string(bound_values[1], fullname))
|
if (!empty_string(table.get_data(2)))
|
||||||
array[atoi(bound_values[0]) - 1] = smtk_concat_str(str, "", "%s (%s)", bound_values[1], fullname);
|
concat(fullname, " ", table.get_string_view(2));
|
||||||
else
|
std::string str = !fullname.empty() && fullname != table.get_data(1) ?
|
||||||
array[atoi(bound_values[0]) - 1] = smtk_concat_str(str, "", "%s", bound_values[1]);
|
format_string_std("%s (%s)", table.get_data(1), fullname.c_str()) :
|
||||||
free(fullname);
|
std::string(table.get_string_view(1));
|
||||||
fullname = NULL;
|
int pos = atoi(table.get_data(0)) - 1;
|
||||||
|
if (pos < 0)
|
||||||
|
continue;
|
||||||
|
if (static_cast<size_t>(pos) >= res.size())
|
||||||
|
res.resize(pos + 1);
|
||||||
|
res[pos] = std::move(str);
|
||||||
}
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
free(str);
|
/*
|
||||||
smtk_free(bound_values, table->num_cols);
|
* Helper function that gets an element of a vector or a default constructed value
|
||||||
mdb_free_tabledef(table);
|
* if out-of-bounds.
|
||||||
|
*/
|
||||||
|
template <typename T>
|
||||||
|
T get(const std::vector<T> &v, int idx)
|
||||||
|
{
|
||||||
|
return idx >= 0 && static_cast<size_t>(idx) < v.size() ? v[idx] : T();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Returns string with buddies names as registered in smartrak (may be a nickname).
|
* Returns string with buddies names as registered in smartrak (may be a nickname).
|
||||||
*/
|
*/
|
||||||
static char *smtk_locate_buddy(MdbHandle *mdb, char *dive_idx, char *buddies_list[])
|
static std::string smtk_locate_buddy(MdbHandle *mdb, char *dive_idx, const std::vector<std::string> &buddies_list)
|
||||||
{
|
{
|
||||||
char *str = NULL;
|
std::string str;
|
||||||
struct types_list *rel, *rel_head;
|
|
||||||
|
|
||||||
rel_head = smtk_index_list(mdb, "BuddyRelation", dive_idx);
|
std::vector<int> rel_list = smtk_index_list(mdb, "BuddyRelation", dive_idx);
|
||||||
if (!rel_head)
|
for (int idx: rel_list)
|
||||||
return str;
|
concat(str, ", ", std::string(get(buddies_list, idx - 1)));
|
||||||
|
|
||||||
for (rel = rel_head; rel; rel = rel->next)
|
|
||||||
str = smtk_concat_str(str, ", ", "%s", buddies_list[rel->idx - 1]);
|
|
||||||
|
|
||||||
/* Clean up and exit */
|
|
||||||
smtk_list_free(rel_head);
|
|
||||||
return str;
|
return str;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -731,32 +682,27 @@ static char *smtk_locate_buddy(MdbHandle *mdb, char *dive_idx, char *buddies_lis
|
||||||
* The "tag" parameter is used to mark if we want this table to be imported
|
* The "tag" parameter is used to mark if we want this table to be imported
|
||||||
* into tags or into notes.
|
* into tags or into notes.
|
||||||
*/
|
*/
|
||||||
static void smtk_parse_relations(MdbHandle *mdb, struct dive *dive, char *dive_idx, const char *table_name, const char *rel_table_name, char *list[], bool tag)
|
static void smtk_parse_relations(MdbHandle *mdb, struct dive *dive, char *dive_idx, const char *table_name, const char *rel_table_name, const std::vector<std::string> &list, bool tag)
|
||||||
{
|
{
|
||||||
char *tmp = NULL;
|
std::string tmp;
|
||||||
struct types_list *diverel_head, *d_runner;
|
|
||||||
|
|
||||||
diverel_head = smtk_index_list(mdb, rel_table_name, dive_idx);
|
|
||||||
if (!diverel_head)
|
|
||||||
return;
|
|
||||||
|
|
||||||
/* Get the text associated with the relations */
|
/* Get the text associated with the relations */
|
||||||
for (d_runner = diverel_head; d_runner; d_runner = d_runner->next) {
|
std::vector<int> diverel_list = smtk_index_list(mdb, rel_table_name, dive_idx);
|
||||||
if (!list[d_runner->idx - 1])
|
for (int idx: diverel_list) {
|
||||||
|
const std::string str = get(list, idx - 1);
|
||||||
|
if (str.empty())
|
||||||
continue;
|
continue;
|
||||||
if (tag)
|
if (tag)
|
||||||
taglist_add_tag(&dive->tag_list, list[d_runner->idx - 1]);
|
taglist_add_tag(&dive->tag_list, str.c_str());
|
||||||
else
|
else
|
||||||
tmp = smtk_concat_str(tmp, ", ", "%s", list[d_runner->idx - 1]);
|
concat(tmp, ", ", str);
|
||||||
if (strstr(list[d_runner->idx - 1], "SCR"))
|
if (str.find("SCR") != std::string::npos)
|
||||||
dive->dc.divemode = PSCR;
|
dive->dc.divemode = PSCR;
|
||||||
else if (strstr(list[d_runner->idx -1], "CCR"))
|
else if (str.find("CCR") != std::string::npos)
|
||||||
dive->dc.divemode = CCR;
|
dive->dc.divemode = CCR;
|
||||||
}
|
}
|
||||||
if (tmp)
|
if (!tmp.empty())
|
||||||
dive->notes = smtk_concat_str(dive->notes, "\n", "Smartrak %s: %s", table_name, tmp);
|
concat(&dive->notes, "\n", format_string_std("Smartrak %s: %s", table_name, tmp.c_str()));
|
||||||
free(tmp);
|
|
||||||
smtk_list_free(diverel_head);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -764,17 +710,18 @@ static void smtk_parse_relations(MdbHandle *mdb, struct dive *dive, char *dive_i
|
||||||
* in Subsurface. Write them as tags or dive notes by setting true or false the
|
* in Subsurface. Write them as tags or dive notes by setting true or false the
|
||||||
* boolean parameter "tag".
|
* boolean parameter "tag".
|
||||||
*/
|
*/
|
||||||
static void smtk_parse_other(struct dive *dive, char *list[], const char *data_name, char *idx, bool tag)
|
static void smtk_parse_other(struct dive *dive, const std::vector<std::string> &list, const char *data_name, char *idx, bool tag)
|
||||||
{
|
{
|
||||||
int i = atoi(idx) - 1;
|
int i = atoi(idx) - 1;
|
||||||
char *str = NULL;
|
if (i < 0 || i >= (int)list.size())
|
||||||
|
return;
|
||||||
|
|
||||||
str = list[i];
|
const std::string &str = list[i];
|
||||||
if (str) {
|
if (!str.empty()) {
|
||||||
if (tag)
|
if (tag)
|
||||||
taglist_add_tag(&dive->tag_list, str);
|
taglist_add_tag(&dive->tag_list, str.c_str());
|
||||||
else
|
else
|
||||||
dive->notes = smtk_concat_str(dive->notes, "\n", "Smartrak %s: %s", data_name, str);
|
concat(&dive->notes, "\n", format_string_std("Smartrak %s: %s", data_name, str.c_str()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -805,20 +752,18 @@ static struct event *find_bookmark(struct event *orig, int t)
|
||||||
*/
|
*/
|
||||||
static void smtk_parse_bookmarks(MdbHandle *mdb, struct dive *d, char *dive_idx)
|
static void smtk_parse_bookmarks(MdbHandle *mdb, struct dive *d, char *dive_idx)
|
||||||
{
|
{
|
||||||
MdbTableDef *table;
|
|
||||||
char *bound_values[MDB_MAX_COLS], *tmp = NULL;
|
|
||||||
int time;
|
int time;
|
||||||
struct event *ev;
|
struct event *ev;
|
||||||
|
|
||||||
table = smtk_open_table(mdb, "Marker", bound_values, NULL);
|
SmtkTable table(mdb, "Marker");
|
||||||
if (!table) {
|
if (!table) {
|
||||||
report_error("[smtk-import] Error - Couldn't open table 'Marker', dive %d", d->number);
|
report_error("[smtk-import] Error - Couldn't open table 'Marker', dive %d", d->number);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
while (mdb_fetch_row(table)) {
|
while (table.fetch_row()) {
|
||||||
if (same_string(bound_values[0], dive_idx)) {
|
if (same_string(table.get_data(0), dive_idx)) {
|
||||||
time = lrint(strtod(bound_values[4], NULL) * 60);
|
time = lrint(strtod(table.get_data(4), NULL) * 60);
|
||||||
tmp = strdup(bound_values[2]);
|
const char *tmp = table.get_data(2);
|
||||||
ev = find_bookmark(d->dc.events, time);
|
ev = find_bookmark(d->dc.events, time);
|
||||||
if (ev)
|
if (ev)
|
||||||
update_event_name(d, 0, ev, tmp);
|
update_event_name(d, 0, ev, tmp);
|
||||||
|
@ -828,9 +773,6 @@ static void smtk_parse_bookmarks(MdbHandle *mdb, struct dive *d, char *dive_idx)
|
||||||
d->number, tmp);
|
d->number, tmp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
free(tmp);
|
|
||||||
smtk_free(bound_values, table->num_cols);
|
|
||||||
mdb_free_tabledef(table);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -890,7 +832,7 @@ static dc_status_t prepare_data(int data_model, char *serial, dc_family_t dc_fam
|
||||||
if (dev_data->descriptor) {
|
if (dev_data->descriptor) {
|
||||||
dev_data->vendor = dc_descriptor_get_vendor(dev_data->descriptor);
|
dev_data->vendor = dc_descriptor_get_vendor(dev_data->descriptor);
|
||||||
dev_data->product = dc_descriptor_get_product(dev_data->descriptor);
|
dev_data->product = dc_descriptor_get_product(dev_data->descriptor);
|
||||||
dev_data->model = smtk_concat_str((char *)dev_data->model, "", "%s %s", dev_data->vendor, dev_data->product);
|
concat(&dev_data->model, "", format_string_std("%s %s", dev_data->vendor, dev_data->product));
|
||||||
dev_data->devinfo.serial = (uint32_t) lrint(strtod(serial, NULL));
|
dev_data->devinfo.serial = (uint32_t) lrint(strtod(serial, NULL));
|
||||||
return DC_STATUS_SUCCESS;
|
return DC_STATUS_SUCCESS;
|
||||||
} else {
|
} else {
|
||||||
|
@ -943,10 +885,8 @@ static dc_status_t libdc_buffer_complete(device_data_t *dev_data, unsigned char
|
||||||
extern "C" void smartrak_import(const char *file, struct divelog *log)
|
extern "C" void smartrak_import(const char *file, struct divelog *log)
|
||||||
{
|
{
|
||||||
MdbHandle *mdb, *mdb_clon;
|
MdbHandle *mdb, *mdb_clon;
|
||||||
MdbTableDef *mdb_table;
|
|
||||||
MdbColumn *col[MDB_MAX_COLS];
|
MdbColumn *col[MDB_MAX_COLS];
|
||||||
char *bound_values[MDB_MAX_COLS];
|
int i, dc_model;
|
||||||
int i, dc_model, *bound_lens[MDB_MAX_COLS];
|
|
||||||
|
|
||||||
// Set an european style locale to work date/time conversion
|
// Set an european style locale to work date/time conversion
|
||||||
setlocale(LC_TIME, "POSIX");
|
setlocale(LC_TIME, "POSIX");
|
||||||
|
@ -962,89 +902,72 @@ extern "C" void smartrak_import(const char *file, struct divelog *log)
|
||||||
mdb_clon = mdb_clone_handle(mdb);
|
mdb_clon = mdb_clone_handle(mdb);
|
||||||
mdb_read_catalog(mdb_clon, MDB_TABLE);
|
mdb_read_catalog(mdb_clon, MDB_TABLE);
|
||||||
|
|
||||||
/* Define arrays for the tables */
|
|
||||||
int type_num = get_rows_num(mdb_clon, "Type"),
|
|
||||||
activity_num = get_rows_num(mdb_clon, "Activity"),
|
|
||||||
gear_num = get_rows_num(mdb_clon, "Gear"),
|
|
||||||
fish_num = get_rows_num(mdb_clon, "Fish"),
|
|
||||||
suit_num = get_rows_num(mdb_clon, "Suit"),
|
|
||||||
weather_num = get_rows_num(mdb_clon, "Weather"),
|
|
||||||
underwater_num = get_rows_num(mdb_clon, "Underwater"),
|
|
||||||
surface_num = get_rows_num(mdb_clon, "Surface"),
|
|
||||||
buddy_num = get_rows_num(mdb_clon, "Buddy");
|
|
||||||
|
|
||||||
char *type_list[type_num], *activity_list[activity_num], *gear_list[gear_num],
|
|
||||||
*fish_list[fish_num], *buddy_list[buddy_num], *suit_list[suit_num],
|
|
||||||
*weather_list[weather_num], *underwater_list[underwater_num],
|
|
||||||
*surface_list[surface_num], *smtk_ver[1];
|
|
||||||
|
|
||||||
/* Load auxiliary tables */
|
/* Load auxiliary tables */
|
||||||
smtk_build_list(mdb_clon, "Type", type_list);
|
std::vector<std::string> type_list = smtk_build_list(mdb_clon, "Type");
|
||||||
smtk_build_list(mdb_clon, "Activity", activity_list);
|
std::vector<std::string> activity_list = smtk_build_list(mdb_clon, "Activity");
|
||||||
smtk_build_list(mdb_clon, "Gear", gear_list);
|
std::vector<std::string> gear_list = smtk_build_list(mdb_clon, "Gear");
|
||||||
smtk_build_list(mdb_clon, "Fish", fish_list);
|
std::vector<std::string> fish_list = smtk_build_list(mdb_clon, "Fish");
|
||||||
smtk_build_list(mdb_clon, "SmartTrak", smtk_ver);
|
std::vector<std::string> smtk_ver = smtk_build_list(mdb_clon, "SmartTrak");
|
||||||
smtk_build_list(mdb_clon, "Suit", suit_list);
|
std::vector<std::string> suit_list = smtk_build_list(mdb_clon, "Suit");
|
||||||
smtk_build_list(mdb_clon, "Weather", weather_list);
|
std::vector<std::string> weather_list = smtk_build_list(mdb_clon, "Weather");
|
||||||
smtk_build_list(mdb_clon, "Underwater", underwater_list);
|
std::vector<std::string> underwater_list = smtk_build_list(mdb_clon, "Underwater");
|
||||||
smtk_build_list(mdb_clon, "Surface", surface_list);
|
std::vector<std::string> surface_list = smtk_build_list(mdb_clon, "Surface");
|
||||||
smtk_build_buddies(mdb_clon, buddy_list);
|
std::vector<std::string> buddy_list = smtk_build_buddies(mdb_clon);
|
||||||
|
|
||||||
/* Check Smarttrak version (different number of supported tanks, mixes and so).
|
/* Check Smarttrak version (different number of supported tanks, mixes and so).
|
||||||
* File format 10000 is quite different from other formats, just drop it and give
|
* File format 10000 is quite different from other formats, just drop it and give
|
||||||
* a tip to the user.
|
* a tip to the user.
|
||||||
*/
|
*/
|
||||||
smtk_version = atoi(smtk_ver[0]);
|
smtk_version = atoi(get(smtk_ver, 0).c_str());
|
||||||
if (smtk_version == 10000) {
|
if (smtk_version == 10000) {
|
||||||
report_error("[Error]\t File %s is SmartTrak file format %d which is not supported. Please load the file in a newer SmartTrak software version and upgrade it.", file, smtk_version);
|
report_error("[Error]\t File %s is SmartTrak file format %d which is not supported. Please load the file in a newer SmartTrak software version and upgrade it.", file, smtk_version);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
tanks = (smtk_version < 10213) ? 3 : 10;
|
tanks = (smtk_version < 10213) ? 3 : 10;
|
||||||
|
|
||||||
mdb_table = smtk_open_table(mdb, "Dives", bound_values, bound_lens);
|
SmtkTable mdb_table(mdb, "Dives");
|
||||||
if (!mdb_table) {
|
if (!mdb_table) {
|
||||||
report_error("[Error][smartrak_import]\tFile %s does not seem to be an SmartTrak file.", file);
|
report_error("[Error][smartrak_import]\tFile %s does not seem to be an SmartTrak file.", file);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
while (mdb_fetch_row(mdb_table)) {
|
while (mdb_table.fetch_row()) {
|
||||||
device_data_t *devdata = (device_data_t *)calloc(1, sizeof(device_data_t));
|
device_data_t *devdata = (device_data_t *)calloc(1, sizeof(device_data_t));
|
||||||
dc_family_t dc_fam = DC_FAMILY_NULL;
|
dc_family_t dc_fam = DC_FAMILY_NULL;
|
||||||
unsigned char *prf_buffer, *hdr_buffer, *compl_buffer;
|
unsigned char *prf_buffer, *hdr_buffer;
|
||||||
struct dive *smtkdive = alloc_dive();
|
struct dive *smtkdive = alloc_dive();
|
||||||
struct tm *tm_date = (struct tm *)malloc(sizeof(struct tm));
|
struct tm tm_date;
|
||||||
size_t hdr_length, prf_length;
|
size_t hdr_length, prf_length;
|
||||||
dc_status_t rc = DC_STATUS_SUCCESS;
|
dc_status_t rc = DC_STATUS_SUCCESS;
|
||||||
|
|
||||||
for (size_t j = 0; j < mdb_table->num_cols; j++)
|
for (size_t j = 0; j < mdb_table.table->num_cols; j++)
|
||||||
col[j] = static_cast<MdbColumn *>(g_ptr_array_index(mdb_table->columns, j));
|
col[j] = static_cast<MdbColumn *>(g_ptr_array_index(mdb_table.table->columns, j));
|
||||||
smtkdive->number = lrint(strtod(bound_values[1], NULL));
|
smtkdive->number = lrint(strtod(mdb_table.get_data(1), NULL));
|
||||||
/*
|
/*
|
||||||
* If there is a DC model (no zero) try to create a buffer for the
|
* If there is a DC model (no zero) try to create a buffer for the
|
||||||
* dive and parse it with libdivecomputer
|
* dive and parse it with libdivecomputer
|
||||||
*/
|
*/
|
||||||
dc_model = lrint(strtod(bound_values[coln(DCMODEL)], NULL)) & 0xFF;
|
dc_model = lrint(strtod(mdb_table.get_data(coln(DCMODEL)), NULL)) & 0xFF;
|
||||||
if (*bound_lens[coln(LOG)]) {
|
if (mdb_table.get_len(coln(LOG))) {
|
||||||
hdr_buffer = static_cast<unsigned char *>(mdb_ole_read_full(mdb, col[coln(LOG)], &hdr_length));
|
hdr_buffer = static_cast<unsigned char *>(mdb_ole_read_full(mdb, col[coln(LOG)], &hdr_length));
|
||||||
if (hdr_length > 0 && hdr_length < 20) // We have a profile but it's imported from datatrak
|
if (hdr_length > 0 && hdr_length < 20) // We have a profile but it's imported from datatrak
|
||||||
dc_fam = DC_FAMILY_UWATEC_ALADIN;
|
dc_fam = DC_FAMILY_UWATEC_ALADIN;
|
||||||
}
|
}
|
||||||
rc = prepare_data(dc_model, copy_string((char *)col[coln(DCNUMBER)]->bind_ptr), dc_fam, devdata);
|
rc = prepare_data(dc_model, copy_string((char *)col[coln(DCNUMBER)]->bind_ptr), dc_fam, devdata);
|
||||||
smtkdive->dc.model = copy_string(devdata->model);
|
smtkdive->dc.model = copy_string(devdata->model);
|
||||||
if (rc == DC_STATUS_SUCCESS && *bound_lens[coln(PROFILE)]) {
|
if (rc == DC_STATUS_SUCCESS && mdb_table.get_len(coln(PROFILE))) {
|
||||||
prf_buffer = static_cast<unsigned char *>(mdb_ole_read_full(mdb, col[coln(PROFILE)], &prf_length));
|
prf_buffer = static_cast<unsigned char *>(mdb_ole_read_full(mdb, col[coln(PROFILE)], &prf_length));
|
||||||
if (prf_length > 0) {
|
if (prf_length > 0) {
|
||||||
if (dc_descriptor_get_type(devdata->descriptor) == DC_FAMILY_UWATEC_ALADIN || dc_descriptor_get_type(devdata->descriptor) == DC_FAMILY_UWATEC_MEMOMOUSE)
|
if (dc_descriptor_get_type(devdata->descriptor) == DC_FAMILY_UWATEC_ALADIN || dc_descriptor_get_type(devdata->descriptor) == DC_FAMILY_UWATEC_MEMOMOUSE)
|
||||||
hdr_length = 18;
|
hdr_length = 18;
|
||||||
compl_buffer = (unsigned char *)calloc(hdr_length+prf_length, sizeof(char));
|
std::vector<unsigned char> compl_buffer(hdr_length+prf_length);
|
||||||
rc = libdc_buffer_complete(devdata, hdr_buffer, hdr_length, prf_buffer, prf_length, compl_buffer);
|
rc = libdc_buffer_complete(devdata, hdr_buffer, hdr_length, prf_buffer, prf_length, compl_buffer.data());
|
||||||
if (rc != DC_STATUS_SUCCESS) {
|
if (rc != DC_STATUS_SUCCESS) {
|
||||||
report_error("[Error][smartrak_import]\t- %s - for dive %d", errmsg(rc), smtkdive->number);
|
report_error("[Error][smartrak_import]\t- %s - for dive %d", errmsg(rc), smtkdive->number);
|
||||||
} else {
|
} else {
|
||||||
rc = libdc_buffer_parser(smtkdive, devdata, compl_buffer, hdr_length + prf_length);
|
rc = libdc_buffer_parser(smtkdive, devdata, compl_buffer.data(), hdr_length + prf_length);
|
||||||
if (rc != DC_STATUS_SUCCESS)
|
if (rc != DC_STATUS_SUCCESS)
|
||||||
report_error("[Error][libdc]\t\t- %s - for dive %d", errmsg(rc), smtkdive->number);
|
report_error("[Error][libdc]\t\t- %s - for dive %d", errmsg(rc), smtkdive->number);
|
||||||
}
|
}
|
||||||
free(compl_buffer);
|
|
||||||
} else {
|
} else {
|
||||||
/* Dives without profile samples (usual in older aladin series) */
|
/* Dives without profile samples (usual in older aladin series) */
|
||||||
report_error("[Warning][smartrak_import]\t No profile for dive %d", smtkdive->number);
|
report_error("[Warning][smartrak_import]\t No profile for dive %d", smtkdive->number);
|
||||||
|
@ -1096,10 +1019,9 @@ extern "C" void smartrak_import(const char *file, struct divelog *log)
|
||||||
smtk_clean_cylinders(smtkdive);
|
smtk_clean_cylinders(smtkdive);
|
||||||
|
|
||||||
/* Date issues with libdc parser - Take date time from mdb */
|
/* Date issues with libdc parser - Take date time from mdb */
|
||||||
smtk_date_to_tm((char *)col[coln(_DATE)]->bind_ptr, tm_date);
|
smtk_date_to_tm((char *)col[coln(_DATE)]->bind_ptr, &tm_date);
|
||||||
smtk_time_to_tm((char *)col[coln(INTIME)]->bind_ptr, tm_date);
|
smtk_time_to_tm((char *)col[coln(INTIME)]->bind_ptr, &tm_date);
|
||||||
smtkdive->dc.when = smtkdive->when = smtk_timegm(tm_date);
|
smtkdive->dc.when = smtkdive->when = smtk_timegm(&tm_date);
|
||||||
free(tm_date);
|
|
||||||
smtkdive->dc.surfacetime.seconds = smtk_time_to_secs((char *)col[coln(INTVAL)]->bind_ptr);
|
smtkdive->dc.surfacetime.seconds = smtk_time_to_secs((char *)col[coln(INTVAL)]->bind_ptr);
|
||||||
|
|
||||||
/* Data that user may have registered manually if not supported by DC, or not parsed */
|
/* Data that user may have registered manually if not supported by DC, or not parsed */
|
||||||
|
@ -1114,9 +1036,9 @@ extern "C" void smartrak_import(const char *file, struct divelog *log)
|
||||||
smtkdive->visibility = strtod((char *)col[coln(VISIBILITY)]->bind_ptr, NULL) > 25 ? 5 : lrint(strtod((char *)col[13]->bind_ptr, NULL) / 5);
|
smtkdive->visibility = strtod((char *)col[coln(VISIBILITY)]->bind_ptr, NULL) > 25 ? 5 : lrint(strtod((char *)col[13]->bind_ptr, NULL) / 5);
|
||||||
weightsystem_t ws = { {(int)lrint(strtod((char *)col[coln(WEIGHT)]->bind_ptr, NULL) * 1000)}, "", false };
|
weightsystem_t ws = { {(int)lrint(strtod((char *)col[coln(WEIGHT)]->bind_ptr, NULL) * 1000)}, "", false };
|
||||||
add_cloned_weightsystem(&smtkdive->weightsystems, ws);
|
add_cloned_weightsystem(&smtkdive->weightsystems, ws);
|
||||||
smtkdive->suit = copy_string(suit_list[atoi((char *)col[coln(SUITIDX)]->bind_ptr) - 1]);
|
smtkdive->suit = strdup(get(suit_list, atoi((char *)col[coln(SUITIDX)]->bind_ptr) - 1).c_str());
|
||||||
smtk_build_location(mdb_clon, (char *)col[coln(SITEIDX)]->bind_ptr, &smtkdive->dive_site, log);
|
smtk_build_location(mdb_clon, (char *)col[coln(SITEIDX)]->bind_ptr, &smtkdive->dive_site, log);
|
||||||
smtkdive->buddy = smtk_locate_buddy(mdb_clon, (char *)col[0]->bind_ptr, buddy_list);
|
smtkdive->buddy = strdup(smtk_locate_buddy(mdb_clon, (char *)col[0]->bind_ptr, buddy_list).c_str());
|
||||||
smtk_parse_relations(mdb_clon, smtkdive, (char *)col[0]->bind_ptr, "Type", "TypeRelation", type_list, true);
|
smtk_parse_relations(mdb_clon, smtkdive, (char *)col[0]->bind_ptr, "Type", "TypeRelation", type_list, true);
|
||||||
smtk_parse_relations(mdb_clon, smtkdive, (char *)col[0]->bind_ptr, "Activity", "ActivityRelation", activity_list, false);
|
smtk_parse_relations(mdb_clon, smtkdive, (char *)col[0]->bind_ptr, "Activity", "ActivityRelation", activity_list, false);
|
||||||
smtk_parse_relations(mdb_clon, smtkdive, (char *)col[0]->bind_ptr, "Gear", "GearRelation", gear_list, false);
|
smtk_parse_relations(mdb_clon, smtkdive, (char *)col[0]->bind_ptr, "Gear", "GearRelation", gear_list, false);
|
||||||
|
@ -1125,12 +1047,11 @@ extern "C" void smartrak_import(const char *file, struct divelog *log)
|
||||||
smtk_parse_other(smtkdive, underwater_list, "Underwater", (char *)col[coln(UNDERWATERIDX)]->bind_ptr, false);
|
smtk_parse_other(smtkdive, underwater_list, "Underwater", (char *)col[coln(UNDERWATERIDX)]->bind_ptr, false);
|
||||||
smtk_parse_other(smtkdive, surface_list, "Surface", (char *)col[coln(SURFACEIDX)]->bind_ptr, false);
|
smtk_parse_other(smtkdive, surface_list, "Surface", (char *)col[coln(SURFACEIDX)]->bind_ptr, false);
|
||||||
smtk_parse_bookmarks(mdb_clon, smtkdive, (char *)col[0]->bind_ptr);
|
smtk_parse_bookmarks(mdb_clon, smtkdive, (char *)col[0]->bind_ptr);
|
||||||
smtkdive->notes = smtk_concat_str(smtkdive->notes, "\n", "%s", (char *)col[coln(REMARKS)]->bind_ptr);
|
concat(&smtkdive->notes, "\n", std::string((char *)col[coln(REMARKS)]->bind_ptr));
|
||||||
|
|
||||||
record_dive_to_table(smtkdive, log->dives);
|
record_dive_to_table(smtkdive, log->dives);
|
||||||
device_data_free(devdata);
|
device_data_free(devdata);
|
||||||
}
|
}
|
||||||
mdb_free_tabledef(mdb_table);
|
|
||||||
mdb_free_catalog(mdb_clon);
|
mdb_free_catalog(mdb_clon);
|
||||||
mdb->catalog = NULL;
|
mdb->catalog = NULL;
|
||||||
mdb_close(mdb_clon);
|
mdb_close(mdb_clon);
|
||||||
|
|
Loading…
Add table
Reference in a new issue