core: convert parser_state to C++

Add constructor, destructor and use std::string for memory
management of text data.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
This commit is contained in:
Berthold Stoeger 2024-02-29 07:56:27 +01:00 committed by Michael Keller
parent 5e466d91f0
commit 8d96b7557d
8 changed files with 179 additions and 227 deletions

View file

@ -131,7 +131,7 @@ static int cobalt_dive(void *param, int, char **data, char **)
settings_start(state);
dc_settings_start(state);
if (data[9]) {
utf8_string(data[9], &state->cur_settings.dc.serial_nr);
utf8_string_std(data[9], &state->cur_settings.dc.serial_nr);
state->cur_settings.dc.deviceid = atoi(data[9]);
state->cur_settings.dc.model = strdup("Cobalt import");
}
@ -211,14 +211,12 @@ extern "C" int parse_cobalt_buffer(sqlite3 *handle, const char *url, const char
int retval;
struct parser_state state;
init_parser_state(&state);
state.log = log;
state.sql_handle = handle;
char get_dives[] = "select Id,strftime('%s',DiveStartTime),LocationId,'buddy','notes',Units,(MaxDepthPressure*10000/SurfacePressure)-10000,DiveMinutes,SurfacePressure,SerialNumber,'model' from Dive where IsViewDeleted = 0";
retval = sqlite3_exec(handle, get_dives, &cobalt_dive, &state, NULL);
free_parser_state(&state);
if (retval != SQLITE_OK) {
fprintf(stderr, "Database query failed '%s'.\n", url);

View file

@ -388,14 +388,12 @@ extern "C" int parse_divinglog_buffer(sqlite3 *handle, const char *url, const ch
int retval;
struct parser_state state;
init_parser_state(&state);
state.log = log;
state.sql_handle = handle;
char get_dives[] = "select Number,strftime('%s',Divedate || ' ' || ifnull(Entrytime,'00:00')),Country || ' - ' || City || ' - ' || Place,Buddy,Comments,Depth,Divetime,Divemaster,Airtemp,Watertemp,Weight,Divesuit,Computer,ID,Visibility,SupplyType from Logbook where UUID not in (select UUID from DeletedRecords)";
retval = sqlite3_exec(handle, get_dives, &divinglog_dive, &state, NULL);
free_parser_state(&state);
if (retval != SQLITE_OK) {
fprintf(stderr, "Database query failed '%s'.\n", url);

View file

@ -205,8 +205,10 @@ static int seac_dive(void *param, int, char **data, char **)
settings_start(state);
dc_settings_start(state);
utf8_string(data[1], &state->cur_dive->dc.serial);
utf8_string(data[12], &state->cur_dive->dc.fw_version);
// These dc values are const char *, therefore we have to cast.
// Will be fixed by converting to std::string
utf8_string(data[1], (char **)&state->cur_dive->dc.serial);
utf8_string(data[12], (char **)&state->cur_dive->dc.fw_version);
state->cur_dive->dc.model = strdup("Seac Action");
state->cur_dive->dc.deviceid = calculate_string_hash(data[1]);
@ -268,7 +270,6 @@ extern "C" int parse_seac_buffer(sqlite3 *handle, const char *url, const char *,
char *err = NULL;
struct parser_state state;
init_parser_state(&state);
state.log = log;
state.sql_handle = handle;
@ -290,7 +291,6 @@ extern "C" int parse_seac_buffer(sqlite3 *handle, const char *url, const char *,
*/
retval = sqlite3_exec(handle, get_dives, &seac_dive, &state, &err);
free_parser_state(&state);
if (retval != SQLITE_OK) {
fprintf(stderr, "Database query failed '%s'.\n", url);

View file

@ -262,7 +262,7 @@ static int shearwater_dive(void *param, int, char **data, char **)
settings_start(state);
dc_settings_start(state);
if (data[9])
utf8_string(data[9], &state->cur_settings.dc.serial_nr);
utf8_string_std(data[9], &state->cur_settings.dc.serial_nr);
if (data[10]) {
switch (atoi(data[10])) {
case 2:
@ -392,7 +392,7 @@ static int shearwater_cloud_dive(void *param, int, char **data, char **)
settings_start(state);
dc_settings_start(state);
if (data[9])
utf8_string(data[9], &state->cur_settings.dc.serial_nr);
utf8_string_std(data[9], &state->cur_settings.dc.serial_nr);
if (data[10]) {
switch (atoi(data[10])) {
case 2:
@ -477,7 +477,6 @@ extern "C" int parse_shearwater_buffer(sqlite3 *handle, const char *url, const c
int retval;
struct parser_state state;
init_parser_state(&state);
state.log = log;
state.sql_handle = handle;
@ -487,7 +486,6 @@ extern "C" int parse_shearwater_buffer(sqlite3 *handle, const char *url, const c
char get_dives[] = "select l.number,timestamp,location||' / '||site,buddy,notes,imperialUnits,maxDepth,maxTime,startSurfacePressure,computerSerial,computerModel,i.diveId FROM dive_info AS i JOIN dive_logs AS l ON i.diveId=l.diveId";
retval = sqlite3_exec(handle, get_dives, &shearwater_dive, &state, NULL);
free_parser_state(&state);
if (retval != SQLITE_OK) {
fprintf(stderr, "Database query failed '%s'.\n", url);
@ -502,14 +500,12 @@ extern "C" int parse_shearwater_cloud_buffer(sqlite3 *handle, const char *url, c
int retval;
struct parser_state state;
init_parser_state(&state);
state.log = log;
state.sql_handle = handle;
char get_dives[] = "select l.number,strftime('%s', DiveDate),location||' / '||site,buddy,notes,imperialUnits,maxDepth,DiveLengthTime,startSurfacePressure,computerSerial,computerModel,d.diveId,l.sampleRateMs / 1000 FROM dive_details AS d JOIN dive_logs AS l ON d.diveId=l.diveId";
retval = sqlite3_exec(handle, get_dives, &shearwater_cloud_dive, &state, NULL);
free_parser_state(&state);
if (retval != SQLITE_OK) {
fprintf(stderr, "Database query failed '%s'.\n", url);

View file

@ -198,9 +198,9 @@ static int dm4_dive(void *param, int, char **data, char **)
settings_start(state);
dc_settings_start(state);
if (data[4])
utf8_string(data[4], &state->cur_settings.dc.serial_nr);
utf8_string_std(data[4], &state->cur_settings.dc.serial_nr);
if (data[5])
utf8_string(data[5], &state->cur_settings.dc.model);
utf8_string_std(data[5], &state->cur_settings.dc.model);
state->cur_settings.dc.deviceid = 0xffffffff;
dc_settings_end(state);
@ -293,7 +293,6 @@ extern "C" int parse_dm4_buffer(sqlite3 *handle, const char *url, const char *,
char *err = NULL;
struct parser_state state;
init_parser_state(&state);
state.log = log;
state.sql_handle = handle;
@ -302,7 +301,6 @@ extern "C" int parse_dm4_buffer(sqlite3 *handle, const char *url, const char *,
char get_dives[] = "select D.DiveId,StartTime/10000000-62135596800,Note,Duration,SourceSerialNumber,Source,MaxDepth,SampleInterval,StartTemperature,BottomTemperature,D.StartPressure,D.EndPressure,Size,CylinderWorkPressure,SurfacePressure,DiveTime,SampleInterval,ProfileBlob,TemperatureBlob,PressureBlob,Oxygen,Helium,MIX.StartPressure,MIX.EndPressure FROM Dive AS D JOIN DiveMixture AS MIX ON D.DiveId=MIX.DiveId";
retval = sqlite3_exec(handle, get_dives, &dm4_dive, &state, &err);
free_parser_state(&state);
if (retval != SQLITE_OK) {
fprintf(stderr, "Database query failed '%s'.\n", url);
@ -391,11 +389,11 @@ static int dm5_dive(void *param, int, char **data, char **)
settings_start(state);
dc_settings_start(state);
if (data[4]) {
utf8_string(data[4], &state->cur_settings.dc.serial_nr);
utf8_string_std(data[4], &state->cur_settings.dc.serial_nr);
state->cur_settings.dc.deviceid = atoi(data[4]);
}
if (data[5])
utf8_string(data[5], &state->cur_settings.dc.model);
utf8_string_std(data[5], &state->cur_settings.dc.model);
dc_settings_end(state);
settings_end(state);
@ -410,8 +408,10 @@ static int dm5_dive(void *param, int, char **data, char **)
if (data[4]) {
state->cur_dive->dc.deviceid = atoi(data[4]);
}
// Ugh. dc.model is const char * -> we are not supposed to write into it. This will
// change when we convert to std::string.
if (data[5])
utf8_string(data[5], &state->cur_dive->dc.model);
utf8_string(data[5], (char **)&state->cur_dive->dc.model);
if (data[25]) {
switch(atoi(data[25])) {
@ -565,7 +565,6 @@ extern "C" int parse_dm5_buffer(sqlite3 *handle, const char *url, const char *,
char *err = NULL;
struct parser_state state;
init_parser_state(&state);
state.log = log;
state.sql_handle = handle;
@ -574,7 +573,6 @@ extern "C" int parse_dm5_buffer(sqlite3 *handle, const char *url, const char *,
char get_dives[] = "select DiveId,StartTime/10000000-62135596800,Note,Duration,coalesce(SourceSerialNumber,SerialNumber),Source,MaxDepth,SampleInterval,StartTemperature,BottomTemperature,StartPressure,EndPressure,'','',SurfacePressure,DiveTime,SampleInterval,ProfileBlob,TemperatureBlob,PressureBlob,'','','','',SampleBlob,Mode FROM Dive where Deleted is null";
retval = sqlite3_exec(handle, get_dives, &dm5_dive, &state, &err);
free_parser_state(&state);
if (retval != SQLITE_OK) {
fprintf(stderr, "Database query failed '%s'.\n", url);
@ -583,4 +581,3 @@ extern "C" int parse_dm5_buffer(sqlite3 *handle, const char *url, const char *,
return 0;
}

View file

@ -383,11 +383,10 @@ static void duration(const char *buffer, duration_t *time)
* store the dive time as 44.00 instead of 44:00;
* This attempts to parse this in a fairly robust way */
if (!strchr(buffer, ':') && strchr(buffer, '.')) {
char *mybuffer = strdup(buffer);
char *dot = strchr(mybuffer, '.');
std::string mybuffer(buffer);
char *dot = strchr(mybuffer.data(), '.');
*dot = ':';
sampletime(mybuffer, time);
free(mybuffer);
sampletime(mybuffer.data(), time);
} else {
sampletime(buffer, time);
}
@ -739,15 +738,15 @@ static void parse_libdc_deco(const char *buffer, struct sample *s)
static void try_to_fill_dc_settings(const char *name, char *buf, struct parser_state *state)
{
start_match("divecomputerid", name, buf);
if (MATCH("model.divecomputerid", utf8_string, &state->cur_settings.dc.model))
if (MATCH("model.divecomputerid", utf8_string_std, &state->cur_settings.dc.model))
return;
if (MATCH("deviceid.divecomputerid", hex_value, &state->cur_settings.dc.deviceid))
return;
if (MATCH("nickname.divecomputerid", utf8_string, &state->cur_settings.dc.nickname))
if (MATCH("nickname.divecomputerid", utf8_string_std, &state->cur_settings.dc.nickname))
return;
if (MATCH("serial.divecomputerid", utf8_string, &state->cur_settings.dc.serial_nr))
if (MATCH("serial.divecomputerid", utf8_string_std, &state->cur_settings.dc.serial_nr))
return;
if (MATCH("firmware.divecomputerid", utf8_string, &state->cur_settings.dc.firmware))
if (MATCH("firmware.divecomputerid", utf8_string_std, &state->cur_settings.dc.firmware))
return;
nonmatch("divecomputerid", name, buf);
@ -764,7 +763,7 @@ static void try_to_fill_fingerprint(const char *name, char *buf, struct parser_s
return;
if (MATCH("diveid.fingerprint", hex_value, &state->cur_settings.fingerprint.fdiveid))
return;
if (MATCH("data.fingerprint", utf8_string, &state->cur_settings.fingerprint.data))
if (MATCH("data.fingerprint", utf8_string_std, &state->cur_settings.fingerprint.data))
return;
nonmatch("fingerprint", name, buf);
}
@ -830,9 +829,9 @@ static int match_dc_data_fields(struct divecomputer *dc, const char *name, char
return 1;
if (MATCH("salinity.water", salinity, &dc->salinity))
return 1;
if (MATCH("key.extradata", utf8_string, &state->cur_extra_data.key))
if (MATCH("key.extradata", utf8_string, (char **)&state->cur_extra_data.key))
return 1;
if (MATCH("value.extradata", utf8_string, &state->cur_extra_data.value))
if (MATCH("value.extradata", utf8_string, (char **)&state->cur_extra_data.value))
return 1;
if (MATCH("divemode", get_dc_type, &dc->divemode))
return 1;
@ -854,7 +853,7 @@ static void try_to_fill_dc(struct divecomputer *dc, const char *name, char *buf,
return;
if (MATCH_STATE("time", divetime, &dc->when))
return;
if (MATCH("model", utf8_string, &dc->model))
if (MATCH("model", utf8_string, (char **)&dc->model))
return;
if (MATCH("deviceid", hex_value, &deviceid))
return;
@ -968,11 +967,11 @@ static void try_to_fill_sample(struct sample *sample, const char *name, char *bu
return;
switch (state->import_source) {
case DIVINGLOG:
case parser_state::DIVINGLOG:
if (divinglog_fill_sample(sample, name, buf, state))
return;
break;
case UDDF:
case parser_state::UDDF:
if (uddf_fill_sample(sample, name, buf, state))
return;
break;
@ -992,27 +991,25 @@ static void divinglog_place(const char *place, struct dive *d, struct parser_sta
snprintf(buffer, sizeof(buffer),
"%s%s%s%s%s",
place,
state->city ? ", " : "",
state->city ? state->city : "",
state->country ? ", " : "",
state->country ? state->country : "");
!state->city.empty() ? ", " : "",
!state->city.empty() ? state->city.c_str() : "",
!state->country.empty() ? ", " : "",
!state->country.empty() ? state->country.c_str() : "");
ds = get_dive_site_by_name(buffer, state->log->sites);
if (!ds)
ds = create_dive_site(buffer, state->log->sites);
add_dive_to_dive_site(d, ds);
// TODO: capture the country / city info in the taxonomy instead
free(state->city);
free(state->country);
state->city = NULL;
state->country = NULL;
state->city.clear();
state->country.clear();
}
static int divinglog_dive_match(struct dive *dive, const char *name, char *buf, struct parser_state *state)
{
/* For cylinder related fields, we might have to create a cylinder first. */
cylinder_t cyl = empty_cylinder;
if (MATCH("tanktype", utf8_string, &cyl.type.description)) {
if (MATCH("tanktype", utf8_string, (char **)&cyl.type.description)) {
cylinder_t *cyl0 = get_or_create_cylinder(dive, 0);
free((void *)cyl0->type.description);
cyl0->type.description = cyl.type.description;
@ -1041,8 +1038,8 @@ static int divinglog_dive_match(struct dive *dive, const char *name, char *buf,
MATCH_STATE("depthavg", depth, &dive->dc.meandepth) ||
MATCH("comments", utf8_string, &dive->notes) ||
MATCH("names.buddy", utf8_string, &dive->buddy) ||
MATCH("name.country", utf8_string, &state->country) ||
MATCH("name.city", utf8_string, &state->city) ||
MATCH("name.country", utf8_string_std, &state->country) ||
MATCH("name.city", utf8_string_std, &state->city) ||
MATCH_STATE("name.place", divinglog_place, dive) ||
0;
}
@ -1259,12 +1256,12 @@ static void try_to_fill_dive(struct dive *dive, const char *name, char *buf, str
start_match("dive", name, buf);
switch (state->import_source) {
case DIVINGLOG:
case parser_state::DIVINGLOG:
if (divinglog_dive_match(dive, name, buf, state))
return;
break;
case UDDF:
case parser_state::UDDF:
if (uddf_dive_match(dive, name, buf, state))
return;
break;
@ -1362,7 +1359,7 @@ static void try_to_fill_dive(struct dive *dive, const char *name, char *buf, str
if (MATCH_STATE("airpressure.dive", pressure, &dive->surface_pressure))
return;
if (ws) {
if (MATCH("description.weightsystem", utf8_string, &ws->description))
if (MATCH("description.weightsystem", utf8_string, (char **)&ws->description))
return;
if (MATCH_STATE("weight.weightsystem", weight, &ws->weight))
return;
@ -1378,7 +1375,7 @@ static void try_to_fill_dive(struct dive *dive, const char *name, char *buf, str
return;
if (MATCH_STATE("workpressure.cylinder", pressure, &cyl->type.workingpressure))
return;
if (MATCH("description.cylinder", utf8_string, &cyl->type.description))
if (MATCH("description.cylinder", utf8_string, (char **)&cyl->type.description))
return;
if (MATCH_STATE("start.cylinder", pressure, &cyl->start))
return;
@ -1424,7 +1421,7 @@ static void try_to_fill_trip(dive_trip_t *dive_trip, const char *name, char *buf
static void try_to_fill_dive_site(struct parser_state *state, const char *name, char *buf)
{
struct dive_site *ds = state->cur_dive_site;
char *taxonomy_value = NULL;
std::string taxonomy_value;
start_match("divesite", name, buf);
@ -1442,7 +1439,7 @@ static void try_to_fill_dive_site(struct parser_state *state, const char *name,
return;
if (MATCH("origin.geo", get_index, &state->taxonomy_origin))
return;
if (MATCH("value.geo", utf8_string, &taxonomy_value)) {
if (MATCH("value.geo", utf8_string_std, &taxonomy_value)) {
/* The code assumes that "value.geo" comes last, which is against
* the expectations of an XML file. Let's at least make sure that
* cat and origin have been set! */
@ -1450,10 +1447,9 @@ static void try_to_fill_dive_site(struct parser_state *state, const char *name,
report_error("Warning: taxonomy value without origin or category");
} else {
taxonomy_set_category(&ds->taxonomy, (taxonomy_category)state->taxonomy_category,
taxonomy_value, (taxonomy_origin)state->taxonomy_origin);
taxonomy_value.c_str(), (taxonomy_origin)state->taxonomy_origin);
}
state->taxonomy_category = state->taxonomy_origin = -1;
free(taxonomy_value);
return;
}
@ -1464,10 +1460,9 @@ static void try_to_fill_filter(struct filter_preset *filter, const char *name, c
{
start_match("filterpreset", name, buf);
char *s = NULL;
if (MATCH("name", utf8_string, &s)) {
filter_preset_set_name(filter, s);
free(s);
std::string s;
if (MATCH("name", utf8_string_std, &s)) {
filter_preset_set_name(filter, s.c_str());
return;
}
@ -1478,9 +1473,9 @@ static void try_to_fill_fulltext(const char *name, char *buf, struct parser_stat
{
start_match("fulltext", name, buf);
if (MATCH("mode", utf8_string, &state->fulltext_string_mode))
if (MATCH("mode", utf8_string_std, &state->fulltext_string_mode))
return;
if (MATCH("fulltext", utf8_string, &state->fulltext))
if (MATCH("fulltext", utf8_string_std, &state->fulltext))
return;
nonmatch("fulltext", name, buf);
@ -1490,15 +1485,15 @@ static void try_to_fill_filter_constraint(const char *name, char *buf, struct pa
{
start_match("fulltext", name, buf);
if (MATCH("type", utf8_string, &state->filter_constraint_type))
if (MATCH("type", utf8_string_std, &state->filter_constraint_type))
return;
if (MATCH("string_mode", utf8_string, &state->filter_constraint_string_mode))
if (MATCH("string_mode", utf8_string_std, &state->filter_constraint_string_mode))
return;
if (MATCH("range_mode", utf8_string, &state->filter_constraint_range_mode))
if (MATCH("range_mode", utf8_string_std, &state->filter_constraint_range_mode))
return;
if (MATCH("negate", get_bool, &state->filter_constraint_negate))
return;
if (MATCH("constraint", utf8_string, &state->filter_constraint))
if (MATCH("constraint", utf8_string_std, &state->filter_constraint))
return;
nonmatch("fulltext", name, buf);
@ -1536,7 +1531,7 @@ static bool entry(const char *name, char *buf, struct parser_state *state)
try_to_fill_filter(state->cur_filter, name, buf);
return true;
}
if (!state->cur_event.deleted) {
if (state->event_active) {
try_to_fill_event(name, buf, state);
return true;
}
@ -1633,7 +1628,7 @@ static bool visit(xmlNode *n, struct parser_state *state)
static void DivingLog_importer(struct parser_state *state)
{
state->import_source = DIVINGLOG;
state->import_source = parser_state::DIVINGLOG;
/*
* Diving Log units are really strange.
@ -1650,7 +1645,7 @@ static void DivingLog_importer(struct parser_state *state)
static void uddf_importer(struct parser_state *state)
{
state->import_source = UDDF;
state->import_source = parser_state::UDDF;
state->xml_parsing_units = SI_units;
state->xml_parsing_units.pressure = units::PASCALS;
state->xml_parsing_units.temperature = units::KELVIN;
@ -1737,7 +1732,7 @@ static void reset_all(struct parser_state *state)
* dive for that format.
*/
state->xml_parsing_units = SI_units;
state->import_source = UNKNOWN;
state->import_source = parser_state::UNKNOWN;
}
/* divelog.de sends us xml files that claim to be iso-8859-1
@ -1773,7 +1768,6 @@ extern "C" int parse_xml_buffer(const char *url, const char *buffer, int, struct
int ret = 0;
struct parser_state state;
init_parser_state(&state);
state.log = log;
state.fingerprints = &fingerprint_table; // simply use the global table for now
doc = xmlReadMemory(res, strlen(res), url, NULL, XML_PARSE_HUGE | XML_PARSE_RECOVER);
@ -1794,7 +1788,6 @@ extern "C" int parse_xml_buffer(const char *url, const char *buffer, int, struct
ret = -1;
}
dive_end(&state);
free_parser_state(&state);
xmlFreeDoc(doc);
return ret;
}
@ -1837,7 +1830,6 @@ extern "C" int parse_dlf_buffer(unsigned char *buffer, size_t size, struct divel
cylinder_t *cyl;
struct parser_state state;
init_parser_state(&state);
state.log = log;
// Check for the correct file magic
@ -2307,7 +2299,6 @@ extern "C" int parse_dlf_buffer(unsigned char *buffer, size_t size, struct divel
divecomputer_end(&state);
dive_end(&state);
free_parser_state(&state);
return 0;
}

View file

@ -19,41 +19,21 @@
#include "device.h"
#include "gettext.h"
extern "C" void init_parser_state(struct parser_state *state)
parser_state::~parser_state()
{
memset(state, 0, sizeof(*state));
state->metric = true;
state->cur_event.deleted = 1;
state->sample_rate = 0;
}
extern "C" void free_parser_state(struct parser_state *state)
{
free_dive(state->cur_dive);
free_trip(state->cur_trip);
free_dive_site(state->cur_dive_site);
free_filter_preset(state->cur_filter);
free((void *)state->cur_extra_data.key);
free((void *)state->cur_extra_data.value);
free((void *)state->cur_settings.dc.model);
free((void *)state->cur_settings.dc.nickname);
free((void *)state->cur_settings.dc.serial_nr);
free((void *)state->cur_settings.dc.firmware);
free(state->country);
free(state->city);
free(state->fulltext);
free(state->fulltext_string_mode);
free(state->filter_constraint_type);
free(state->filter_constraint_string_mode);
free(state->filter_constraint_range_mode);
free(state->filter_constraint);
free_dive(cur_dive);
free_trip(cur_trip);
free_dive_site(cur_dive_site);
free_filter_preset(cur_filter);
free((void *)cur_extra_data.key);
free((void *)cur_extra_data.value);
}
/*
* If we don't have an explicit dive computer,
* we use the implicit one that every dive has..
*/
extern "C" struct divecomputer *get_dc(struct parser_state *state)
struct divecomputer *get_dc(struct parser_state *state)
{
return state->cur_dc ?: &state->cur_dive->dc;
}
@ -80,13 +60,13 @@ extern "C" void nonmatch(const char *type, const char *name, char *buffer)
type, name, buffer);
}
extern "C" void event_start(struct parser_state *state)
void event_start(struct parser_state *state)
{
memset(&state->cur_event, 0, sizeof(state->cur_event));
state->cur_event.deleted = 0; /* Active */
state->event_active = true; /* Active */
}
extern "C" void event_end(struct parser_state *state)
void event_end(struct parser_state *state)
{
struct divecomputer *dc = get_dc(state);
if (state->cur_event.type == 123) {
@ -121,7 +101,7 @@ extern "C" void event_end(struct parser_state *state)
ev->gas.mix = state->cur_event.gas.mix;
}
}
state->cur_event.deleted = 1; /* No longer active */
state->event_active = false; /* No longer active */
}
/*
@ -136,81 +116,76 @@ extern "C" void event_end(struct parser_state *state)
* to make a dive valid, but if it has no location, no date and no
* samples I'm pretty sure it's useless.
*/
extern "C" bool is_dive(struct parser_state *state)
bool is_dive(struct parser_state *state)
{
return state->cur_dive &&
(state->cur_dive->dive_site || state->cur_dive->when || state->cur_dive->dc.samples);
}
extern "C" void reset_dc_info(struct divecomputer *, struct parser_state *state)
void reset_dc_info(struct divecomputer *, struct parser_state *state)
{
/* WARN: reset dc info does't touch the dc? */
state->lastcylinderindex = 0;
}
extern "C" void reset_dc_settings(struct parser_state *state)
void reset_dc_settings(struct parser_state *state)
{
free((void *)state->cur_settings.dc.model);
free((void *)state->cur_settings.dc.nickname);
free((void *)state->cur_settings.dc.serial_nr);
free((void *)state->cur_settings.dc.firmware);
state->cur_settings.dc.model = NULL;
state->cur_settings.dc.nickname = NULL;
state->cur_settings.dc.serial_nr = NULL;
state->cur_settings.dc.firmware = NULL;
state->cur_settings.dc.model.clear();
state->cur_settings.dc.nickname.clear();
state->cur_settings.dc.serial_nr.clear();
state->cur_settings.dc.firmware.clear();
state->cur_settings.dc.deviceid = 0;
}
extern "C" void reset_fingerprint(struct parser_state *state)
void reset_fingerprint(struct parser_state *state)
{
free((void *)state->cur_settings.fingerprint.data);
state->cur_settings.fingerprint.data = NULL;
state->cur_settings.fingerprint.data.clear();
state->cur_settings.fingerprint.model = 0;
state->cur_settings.fingerprint.serial = 0;
state->cur_settings.fingerprint.fdeviceid = 0;
state->cur_settings.fingerprint.fdiveid = 0;
}
extern "C" void settings_start(struct parser_state *state)
void settings_start(struct parser_state *state)
{
state->in_settings = true;
}
extern "C" void settings_end(struct parser_state *state)
void settings_end(struct parser_state *state)
{
state->in_settings = false;
}
extern "C" void fingerprint_settings_start(struct parser_state *state)
void fingerprint_settings_start(struct parser_state *state)
{
reset_fingerprint(state);
}
extern "C" void fingerprint_settings_end(struct parser_state *state)
void fingerprint_settings_end(struct parser_state *state)
{
create_fingerprint_node_from_hex(state->fingerprints,
state->cur_settings.fingerprint.model,
state->cur_settings.fingerprint.serial,
state->cur_settings.fingerprint.data,
state->cur_settings.fingerprint.data.c_str(),
state->cur_settings.fingerprint.fdeviceid,
state->cur_settings.fingerprint.fdiveid);
}
extern "C" void dc_settings_start(struct parser_state *state)
void dc_settings_start(struct parser_state *state)
{
reset_dc_settings(state);
}
extern "C" void dc_settings_end(struct parser_state *state)
void dc_settings_end(struct parser_state *state)
{
create_device_node(state->log->devices,
state->cur_settings.dc.model,
state->cur_settings.dc.serial_nr,
state->cur_settings.dc.nickname);
state->cur_settings.dc.model.c_str(),
state->cur_settings.dc.serial_nr.c_str(),
state->cur_settings.dc.nickname.c_str());
reset_dc_settings(state);
}
extern "C" void dive_site_start(struct parser_state *state)
void dive_site_start(struct parser_state *state)
{
if (state->cur_dive_site)
return;
@ -219,7 +194,7 @@ extern "C" void dive_site_start(struct parser_state *state)
state->cur_dive_site = (dive_site *)calloc(1, sizeof(struct dive_site));
}
extern "C" void dive_site_end(struct parser_state *state)
void dive_site_end(struct parser_state *state)
{
if (!state->cur_dive_site)
return;
@ -234,66 +209,60 @@ extern "C" void dive_site_end(struct parser_state *state)
state->cur_dive_site = NULL;
}
extern "C" void filter_preset_start(struct parser_state *state)
void filter_preset_start(struct parser_state *state)
{
if (state->cur_filter)
return;
state->cur_filter = alloc_filter_preset();
}
extern "C" void filter_preset_end(struct parser_state *state)
void filter_preset_end(struct parser_state *state)
{
add_filter_preset_to_table(state->cur_filter, state->log->filter_presets);
free_filter_preset(state->cur_filter);
state->cur_filter = NULL;
}
extern "C" void fulltext_start(struct parser_state *state)
void fulltext_start(struct parser_state *state)
{
if (!state->cur_filter)
return;
state->in_fulltext = true;
}
extern "C" void fulltext_end(struct parser_state *state)
void fulltext_end(struct parser_state *state)
{
if (!state->in_fulltext)
return;
filter_preset_set_fulltext(state->cur_filter, state->fulltext, state->fulltext_string_mode);
free(state->fulltext);
free(state->fulltext_string_mode);
state->fulltext = NULL;
state->fulltext_string_mode = NULL;
filter_preset_set_fulltext(state->cur_filter, state->fulltext.c_str(), state->fulltext_string_mode.c_str());
state->fulltext.clear();
state->fulltext_string_mode.clear();
state->in_fulltext = false;
}
extern "C" void filter_constraint_start(struct parser_state *state)
void filter_constraint_start(struct parser_state *state)
{
if (!state->cur_filter)
return;
state->in_filter_constraint = true;
}
extern "C" void filter_constraint_end(struct parser_state *state)
void filter_constraint_end(struct parser_state *state)
{
if (!state->in_filter_constraint)
return;
filter_preset_add_constraint(state->cur_filter, state->filter_constraint_type, state->filter_constraint_string_mode,
state->filter_constraint_range_mode, state->filter_constraint_negate, state->filter_constraint);
free(state->filter_constraint_type);
free(state->filter_constraint_string_mode);
free(state->filter_constraint_range_mode);
free(state->filter_constraint);
filter_preset_add_constraint(state->cur_filter, state->filter_constraint_type.c_str(), state->filter_constraint_string_mode.c_str(),
state->filter_constraint_range_mode.c_str(), state->filter_constraint_negate, state->filter_constraint.c_str());
state->filter_constraint_type = NULL;
state->filter_constraint_string_mode = NULL;
state->filter_constraint_range_mode = NULL;
state->filter_constraint_type.clear();
state->filter_constraint_string_mode.clear();
state->filter_constraint_range_mode.clear();
state->filter_constraint_negate = false;
state->filter_constraint = NULL;
state->filter_constraint.clear();
state->in_filter_constraint = false;
}
extern "C" void dive_start(struct parser_state *state)
void dive_start(struct parser_state *state)
{
if (state->cur_dive)
return;
@ -303,7 +272,7 @@ extern "C" void dive_start(struct parser_state *state)
state->o2pressure_sensor = 1;
}
extern "C" void dive_end(struct parser_state *state)
void dive_end(struct parser_state *state)
{
if (!state->cur_dive)
return;
@ -320,7 +289,7 @@ extern "C" void dive_end(struct parser_state *state)
state->cur_location.lon.udeg = 0;
}
extern "C" void trip_start(struct parser_state *state)
void trip_start(struct parser_state *state)
{
if (state->cur_trip)
return;
@ -329,7 +298,7 @@ extern "C" void trip_start(struct parser_state *state)
memset(&state->cur_tm, 0, sizeof(state->cur_tm));
}
extern "C" void trip_end(struct parser_state *state)
void trip_end(struct parser_state *state)
{
if (!state->cur_trip)
return;
@ -337,32 +306,32 @@ extern "C" void trip_end(struct parser_state *state)
state->cur_trip = NULL;
}
extern "C" void picture_start(struct parser_state *state)
void picture_start(struct parser_state *state)
{
}
extern "C" void picture_end(struct parser_state *state)
void picture_end(struct parser_state *state)
{
add_picture(&state->cur_dive->pictures, state->cur_picture);
/* dive_add_picture took ownership, we can just clear out copy of the data */
state->cur_picture = empty_picture;
}
extern "C" cylinder_t *cylinder_start(struct parser_state *state)
cylinder_t *cylinder_start(struct parser_state *state)
{
return add_empty_cylinder(&state->cur_dive->cylinders);
}
extern "C" void cylinder_end(struct parser_state *state)
void cylinder_end(struct parser_state *state)
{
}
extern "C" void ws_start(struct parser_state *state)
void ws_start(struct parser_state *state)
{
add_cloned_weightsystem(&state->cur_dive->weightsystems, empty_weightsystem);
}
extern "C" void ws_end(struct parser_state *state)
void ws_end(struct parser_state *state)
{
}
@ -392,7 +361,7 @@ static int sanitize_sensor_id(const struct dive *d, int nr)
* or the second cylinder depending on what isn't an
* oxygen cylinder.
*/
extern "C" void sample_start(struct parser_state *state)
void sample_start(struct parser_state *state)
{
struct divecomputer *dc = get_dc(state);
struct sample *sample = prepare_sample(dc);
@ -409,7 +378,7 @@ extern "C" void sample_start(struct parser_state *state)
state->next_o2_sensor = 0;
}
extern "C" void sample_end(struct parser_state *state)
void sample_end(struct parser_state *state)
{
if (!state->cur_dive)
return;
@ -418,7 +387,7 @@ extern "C" void sample_end(struct parser_state *state)
state->cur_sample = NULL;
}
extern "C" void divecomputer_start(struct parser_state *state)
void divecomputer_start(struct parser_state *state)
{
struct divecomputer *dc;
@ -441,19 +410,19 @@ extern "C" void divecomputer_start(struct parser_state *state)
reset_dc_info(dc, state);
}
extern "C" void divecomputer_end(struct parser_state *state)
void divecomputer_end(struct parser_state *state)
{
if (!state->cur_dc->when)
state->cur_dc->when = state->cur_dive->when;
state->cur_dc = NULL;
}
extern "C" void userid_start(struct parser_state *state)
void userid_start(struct parser_state *state)
{
state->in_userid = true;
}
extern "C" void userid_stop(struct parser_state *state)
void userid_stop(struct parser_state *state)
{
state->in_userid = false;
}
@ -463,9 +432,8 @@ extern "C" void userid_stop(struct parser_state *state)
* therefore make sure to only pass in to NULL-initialized pointers or pointers
* to owned strings
*/
extern "C" void utf8_string(const char *buffer, void *_res)
extern "C" void utf8_string(const char *buffer, char **res)
{
char **res = (char **)_res;
free(*res);
while (isspace(*buffer))
++buffer;
@ -496,7 +464,7 @@ void utf8_string_std(const char *buffer, std::string *res)
*res = std::string(buffer, end - buffer);
}
extern "C" void add_dive_site(const char *ds_name, struct dive *dive, struct parser_state *state)
void add_dive_site(const char *ds_name, struct dive *dive, struct parser_state *state)
{
const char *buffer = ds_name;
std::string trimmed = trimspace(buffer);

View file

@ -21,89 +21,85 @@ typedef union {
char allocation[sizeof(struct event) + MAX_EVENT_NAME];
} event_allocation_t;
#ifdef __cplusplus
/*
* Dive info as it is being built up..
* C++-only so we can use std::string
*/
struct parser_settings {
struct {
const char *model;
uint32_t deviceid;
const char *nickname, *serial_nr, *firmware;
std::string model;
uint32_t deviceid = 0;
std::string nickname, serial_nr, firmware;
} dc;
struct {
uint32_t model;
uint32_t serial;
uint32_t fdeviceid;
uint32_t fdiveid;
const char *data;
std::string data;
} fingerprint;
};
enum import_source {
UNKNOWN,
LIBDIVECOMPUTER,
DIVINGLOG,
UDDF,
};
/*
* parser_state is the state needed by the parser(s). It is initialized
* with init_parser_state() and resources are freed with free_parser_state().
* "owning" marks pointers to objects that are freed in free_parser_state().
* "owning" marks pointers to objects that are freed in the destructor.
* In contrast, "non-owning" marks pointers to objects that are owned
* by other data-structures.
*/
struct parser_state {
bool metric;
enum import_source {
UNKNOWN,
LIBDIVECOMPUTER,
DIVINGLOG,
UDDF,
};
bool metric = true;
struct parser_settings cur_settings;
enum import_source import_source;
enum import_source import_source = UNKNOWN;
struct divecomputer *cur_dc; /* non-owning */
struct dive *cur_dive; /* owning */
struct dive_site *cur_dive_site; /* owning */
location_t cur_location;
struct dive_trip *cur_trip; /* owning */
struct sample *cur_sample; /* non-owning */
struct picture cur_picture; /* owning */
struct filter_preset *cur_filter; /* owning */
char *fulltext; /* owning */
char *fulltext_string_mode; /* owning */
char *filter_constraint_type; /* owning */
char *filter_constraint_string_mode; /* owning */
char *filter_constraint_range_mode; /* owning */
bool filter_constraint_negate;
char *filter_constraint; /* owning */
char *country, *city; /* owning */
int taxonomy_category, taxonomy_origin;
struct divecomputer *cur_dc = nullptr; /* non-owning */
struct dive *cur_dive = nullptr; /* owning */
struct dive_site *cur_dive_site = nullptr; /* owning */
location_t cur_location { 0 };
struct dive_trip *cur_trip = nullptr; /* owning */
struct sample *cur_sample = nullptr; /* non-owning */
struct picture cur_picture { 0 }; /* owning */
struct filter_preset *cur_filter = nullptr; /* owning */
std::string fulltext; /* owning */
std::string fulltext_string_mode; /* owning */
std::string filter_constraint_type; /* owning */
std::string filter_constraint_string_mode; /* owning */
std::string filter_constraint_range_mode; /* owning */
bool filter_constraint_negate = false;
std::string filter_constraint; /* owning */
std::string country, city; /* owning */
int taxonomy_category = 0, taxonomy_origin = 0;
bool in_settings;
bool in_userid;
bool in_fulltext;
bool in_filter_constraint;
struct tm cur_tm;
int lastcylinderindex, next_o2_sensor;
int o2pressure_sensor;
int sample_rate;
struct extra_data cur_extra_data;
bool in_settings = false;
bool in_userid = false;
bool in_fulltext = false;
bool in_filter_constraint = false;
struct tm cur_tm{ 0 };
int lastcylinderindex = 0, next_o2_sensor = 0;
int o2pressure_sensor = 0;
int sample_rate = 0;
struct extra_data cur_extra_data{ 0 };
struct units xml_parsing_units;
struct divelog *log; /* non-owning */
struct fingerprint_table *fingerprints; /* non-owning */
struct divelog *log = nullptr; /* non-owning */
struct fingerprint_table *fingerprints = nullptr; /* non-owning */
sqlite3 *sql_handle; /* for SQL based parsers */
sqlite3 *sql_handle = nullptr; /* for SQL based parsers */
bool event_active = false;
event_allocation_t event_allocation;
~parser_state();
};
#define cur_event event_allocation.event
#ifdef __cplusplus
extern "C" {
#endif
void init_parser_state(struct parser_state *state);
void free_parser_state(struct parser_state *state);
void start_match(const char *type, const char *name, char *buffer);
void nonmatch(const char *type, const char *name, char *buffer);
void event_start(struct parser_state *state);
void event_end(struct parser_state *state);
struct divecomputer *get_dc(struct parser_state *state);
@ -142,10 +138,18 @@ void divecomputer_start(struct parser_state *state);
void divecomputer_end(struct parser_state *state);
void userid_start(struct parser_state *state);
void userid_stop(struct parser_state *state);
void utf8_string(const char *buffer, void *_res);
void utf8_string_std(const char *buffer, std::string *res);
void add_dive_site(const char *ds_name, struct dive *dive, struct parser_state *state);
extern "C" {
#endif
int trimspace(char *buffer);
void start_match(const char *type, const char *name, char *buffer);
void nonmatch(const char *type, const char *name, char *buffer);
int atoi_n(char *ptr, unsigned int len);
void utf8_string(const char *buffer, char **res);
void parse_xml_init(void);
int parse_xml_buffer(const char *url, const char *buf, int size, struct divelog *log, const struct xml_params *params);