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); settings_start(state);
dc_settings_start(state); dc_settings_start(state);
if (data[9]) { 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.deviceid = atoi(data[9]);
state->cur_settings.dc.model = strdup("Cobalt import"); 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; int retval;
struct parser_state state; struct parser_state state;
init_parser_state(&state);
state.log = log; state.log = log;
state.sql_handle = handle; 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"; 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); retval = sqlite3_exec(handle, get_dives, &cobalt_dive, &state, NULL);
free_parser_state(&state);
if (retval != SQLITE_OK) { if (retval != SQLITE_OK) {
fprintf(stderr, "Database query failed '%s'.\n", url); 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; int retval;
struct parser_state state; struct parser_state state;
init_parser_state(&state);
state.log = log; state.log = log;
state.sql_handle = handle; 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)"; 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); retval = sqlite3_exec(handle, get_dives, &divinglog_dive, &state, NULL);
free_parser_state(&state);
if (retval != SQLITE_OK) { if (retval != SQLITE_OK) {
fprintf(stderr, "Database query failed '%s'.\n", url); 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); settings_start(state);
dc_settings_start(state); dc_settings_start(state);
utf8_string(data[1], &state->cur_dive->dc.serial); // These dc values are const char *, therefore we have to cast.
utf8_string(data[12], &state->cur_dive->dc.fw_version); // 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.model = strdup("Seac Action");
state->cur_dive->dc.deviceid = calculate_string_hash(data[1]); 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; char *err = NULL;
struct parser_state state; struct parser_state state;
init_parser_state(&state);
state.log = log; state.log = log;
state.sql_handle = handle; 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); retval = sqlite3_exec(handle, get_dives, &seac_dive, &state, &err);
free_parser_state(&state);
if (retval != SQLITE_OK) { if (retval != SQLITE_OK) {
fprintf(stderr, "Database query failed '%s'.\n", url); 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); settings_start(state);
dc_settings_start(state); dc_settings_start(state);
if (data[9]) 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]) { if (data[10]) {
switch (atoi(data[10])) { switch (atoi(data[10])) {
case 2: case 2:
@ -392,7 +392,7 @@ static int shearwater_cloud_dive(void *param, int, char **data, char **)
settings_start(state); settings_start(state);
dc_settings_start(state); dc_settings_start(state);
if (data[9]) 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]) { if (data[10]) {
switch (atoi(data[10])) { switch (atoi(data[10])) {
case 2: case 2:
@ -477,7 +477,6 @@ extern "C" int parse_shearwater_buffer(sqlite3 *handle, const char *url, const c
int retval; int retval;
struct parser_state state; struct parser_state state;
init_parser_state(&state);
state.log = log; state.log = log;
state.sql_handle = handle; 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"; 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); retval = sqlite3_exec(handle, get_dives, &shearwater_dive, &state, NULL);
free_parser_state(&state);
if (retval != SQLITE_OK) { if (retval != SQLITE_OK) {
fprintf(stderr, "Database query failed '%s'.\n", url); 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; int retval;
struct parser_state state; struct parser_state state;
init_parser_state(&state);
state.log = log; state.log = log;
state.sql_handle = handle; 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"; 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); retval = sqlite3_exec(handle, get_dives, &shearwater_cloud_dive, &state, NULL);
free_parser_state(&state);
if (retval != SQLITE_OK) { if (retval != SQLITE_OK) {
fprintf(stderr, "Database query failed '%s'.\n", url); 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); settings_start(state);
dc_settings_start(state); dc_settings_start(state);
if (data[4]) 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]) 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; state->cur_settings.dc.deviceid = 0xffffffff;
dc_settings_end(state); dc_settings_end(state);
@ -293,7 +293,6 @@ extern "C" int parse_dm4_buffer(sqlite3 *handle, const char *url, const char *,
char *err = NULL; char *err = NULL;
struct parser_state state; struct parser_state state;
init_parser_state(&state);
state.log = log; state.log = log;
state.sql_handle = handle; 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"; 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); retval = sqlite3_exec(handle, get_dives, &dm4_dive, &state, &err);
free_parser_state(&state);
if (retval != SQLITE_OK) { if (retval != SQLITE_OK) {
fprintf(stderr, "Database query failed '%s'.\n", url); 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); settings_start(state);
dc_settings_start(state); dc_settings_start(state);
if (data[4]) { 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]); state->cur_settings.dc.deviceid = atoi(data[4]);
} }
if (data[5]) 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); dc_settings_end(state);
settings_end(state); settings_end(state);
@ -410,8 +408,10 @@ static int dm5_dive(void *param, int, char **data, char **)
if (data[4]) { if (data[4]) {
state->cur_dive->dc.deviceid = atoi(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]) 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]) { if (data[25]) {
switch(atoi(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; char *err = NULL;
struct parser_state state; struct parser_state state;
init_parser_state(&state);
state.log = log; state.log = log;
state.sql_handle = handle; 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"; 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); retval = sqlite3_exec(handle, get_dives, &dm5_dive, &state, &err);
free_parser_state(&state);
if (retval != SQLITE_OK) { if (retval != SQLITE_OK) {
fprintf(stderr, "Database query failed '%s'.\n", url); 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; 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; * store the dive time as 44.00 instead of 44:00;
* This attempts to parse this in a fairly robust way */ * This attempts to parse this in a fairly robust way */
if (!strchr(buffer, ':') && strchr(buffer, '.')) { if (!strchr(buffer, ':') && strchr(buffer, '.')) {
char *mybuffer = strdup(buffer); std::string mybuffer(buffer);
char *dot = strchr(mybuffer, '.'); char *dot = strchr(mybuffer.data(), '.');
*dot = ':'; *dot = ':';
sampletime(mybuffer, time); sampletime(mybuffer.data(), time);
free(mybuffer);
} else { } else {
sampletime(buffer, time); 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) static void try_to_fill_dc_settings(const char *name, char *buf, struct parser_state *state)
{ {
start_match("divecomputerid", name, buf); 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; return;
if (MATCH("deviceid.divecomputerid", hex_value, &state->cur_settings.dc.deviceid)) if (MATCH("deviceid.divecomputerid", hex_value, &state->cur_settings.dc.deviceid))
return; 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; 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; 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; return;
nonmatch("divecomputerid", name, buf); nonmatch("divecomputerid", name, buf);
@ -764,7 +763,7 @@ static void try_to_fill_fingerprint(const char *name, char *buf, struct parser_s
return; return;
if (MATCH("diveid.fingerprint", hex_value, &state->cur_settings.fingerprint.fdiveid)) if (MATCH("diveid.fingerprint", hex_value, &state->cur_settings.fingerprint.fdiveid))
return; 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; return;
nonmatch("fingerprint", name, buf); nonmatch("fingerprint", name, buf);
} }
@ -830,9 +829,9 @@ static int match_dc_data_fields(struct divecomputer *dc, const char *name, char
return 1; return 1;
if (MATCH("salinity.water", salinity, &dc->salinity)) if (MATCH("salinity.water", salinity, &dc->salinity))
return 1; 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; 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; return 1;
if (MATCH("divemode", get_dc_type, &dc->divemode)) if (MATCH("divemode", get_dc_type, &dc->divemode))
return 1; return 1;
@ -854,7 +853,7 @@ static void try_to_fill_dc(struct divecomputer *dc, const char *name, char *buf,
return; return;
if (MATCH_STATE("time", divetime, &dc->when)) if (MATCH_STATE("time", divetime, &dc->when))
return; return;
if (MATCH("model", utf8_string, &dc->model)) if (MATCH("model", utf8_string, (char **)&dc->model))
return; return;
if (MATCH("deviceid", hex_value, &deviceid)) if (MATCH("deviceid", hex_value, &deviceid))
return; return;
@ -968,11 +967,11 @@ static void try_to_fill_sample(struct sample *sample, const char *name, char *bu
return; return;
switch (state->import_source) { switch (state->import_source) {
case DIVINGLOG: case parser_state::DIVINGLOG:
if (divinglog_fill_sample(sample, name, buf, state)) if (divinglog_fill_sample(sample, name, buf, state))
return; return;
break; break;
case UDDF: case parser_state::UDDF:
if (uddf_fill_sample(sample, name, buf, state)) if (uddf_fill_sample(sample, name, buf, state))
return; return;
break; break;
@ -992,27 +991,25 @@ static void divinglog_place(const char *place, struct dive *d, struct parser_sta
snprintf(buffer, sizeof(buffer), snprintf(buffer, sizeof(buffer),
"%s%s%s%s%s", "%s%s%s%s%s",
place, place,
state->city ? ", " : "", !state->city.empty() ? ", " : "",
state->city ? state->city : "", !state->city.empty() ? state->city.c_str() : "",
state->country ? ", " : "", !state->country.empty() ? ", " : "",
state->country ? state->country : ""); !state->country.empty() ? state->country.c_str() : "");
ds = get_dive_site_by_name(buffer, state->log->sites); ds = get_dive_site_by_name(buffer, state->log->sites);
if (!ds) if (!ds)
ds = create_dive_site(buffer, state->log->sites); ds = create_dive_site(buffer, state->log->sites);
add_dive_to_dive_site(d, ds); add_dive_to_dive_site(d, ds);
// TODO: capture the country / city info in the taxonomy instead // TODO: capture the country / city info in the taxonomy instead
free(state->city); state->city.clear();
free(state->country); state->country.clear();
state->city = NULL;
state->country = NULL;
} }
static int divinglog_dive_match(struct dive *dive, const char *name, char *buf, struct parser_state *state) 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. */ /* For cylinder related fields, we might have to create a cylinder first. */
cylinder_t cyl = empty_cylinder; 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); cylinder_t *cyl0 = get_or_create_cylinder(dive, 0);
free((void *)cyl0->type.description); free((void *)cyl0->type.description);
cyl0->type.description = cyl.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_STATE("depthavg", depth, &dive->dc.meandepth) ||
MATCH("comments", utf8_string, &dive->notes) || MATCH("comments", utf8_string, &dive->notes) ||
MATCH("names.buddy", utf8_string, &dive->buddy) || MATCH("names.buddy", utf8_string, &dive->buddy) ||
MATCH("name.country", utf8_string, &state->country) || MATCH("name.country", utf8_string_std, &state->country) ||
MATCH("name.city", utf8_string, &state->city) || MATCH("name.city", utf8_string_std, &state->city) ||
MATCH_STATE("name.place", divinglog_place, dive) || MATCH_STATE("name.place", divinglog_place, dive) ||
0; 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); start_match("dive", name, buf);
switch (state->import_source) { switch (state->import_source) {
case DIVINGLOG: case parser_state::DIVINGLOG:
if (divinglog_dive_match(dive, name, buf, state)) if (divinglog_dive_match(dive, name, buf, state))
return; return;
break; break;
case UDDF: case parser_state::UDDF:
if (uddf_dive_match(dive, name, buf, state)) if (uddf_dive_match(dive, name, buf, state))
return; return;
break; 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)) if (MATCH_STATE("airpressure.dive", pressure, &dive->surface_pressure))
return; return;
if (ws) { if (ws) {
if (MATCH("description.weightsystem", utf8_string, &ws->description)) if (MATCH("description.weightsystem", utf8_string, (char **)&ws->description))
return; return;
if (MATCH_STATE("weight.weightsystem", weight, &ws->weight)) if (MATCH_STATE("weight.weightsystem", weight, &ws->weight))
return; return;
@ -1378,7 +1375,7 @@ static void try_to_fill_dive(struct dive *dive, const char *name, char *buf, str
return; return;
if (MATCH_STATE("workpressure.cylinder", pressure, &cyl->type.workingpressure)) if (MATCH_STATE("workpressure.cylinder", pressure, &cyl->type.workingpressure))
return; return;
if (MATCH("description.cylinder", utf8_string, &cyl->type.description)) if (MATCH("description.cylinder", utf8_string, (char **)&cyl->type.description))
return; return;
if (MATCH_STATE("start.cylinder", pressure, &cyl->start)) if (MATCH_STATE("start.cylinder", pressure, &cyl->start))
return; 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) static void try_to_fill_dive_site(struct parser_state *state, const char *name, char *buf)
{ {
struct dive_site *ds = state->cur_dive_site; struct dive_site *ds = state->cur_dive_site;
char *taxonomy_value = NULL; std::string taxonomy_value;
start_match("divesite", name, buf); start_match("divesite", name, buf);
@ -1442,7 +1439,7 @@ static void try_to_fill_dive_site(struct parser_state *state, const char *name,
return; return;
if (MATCH("origin.geo", get_index, &state->taxonomy_origin)) if (MATCH("origin.geo", get_index, &state->taxonomy_origin))
return; 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 code assumes that "value.geo" comes last, which is against
* the expectations of an XML file. Let's at least make sure that * the expectations of an XML file. Let's at least make sure that
* cat and origin have been set! */ * 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"); report_error("Warning: taxonomy value without origin or category");
} else { } else {
taxonomy_set_category(&ds->taxonomy, (taxonomy_category)state->taxonomy_category, 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; state->taxonomy_category = state->taxonomy_origin = -1;
free(taxonomy_value);
return; return;
} }
@ -1464,10 +1460,9 @@ static void try_to_fill_filter(struct filter_preset *filter, const char *name, c
{ {
start_match("filterpreset", name, buf); start_match("filterpreset", name, buf);
char *s = NULL; std::string s;
if (MATCH("name", utf8_string, &s)) { if (MATCH("name", utf8_string_std, &s)) {
filter_preset_set_name(filter, s); filter_preset_set_name(filter, s.c_str());
free(s);
return; return;
} }
@ -1478,9 +1473,9 @@ static void try_to_fill_fulltext(const char *name, char *buf, struct parser_stat
{ {
start_match("fulltext", name, buf); 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; return;
if (MATCH("fulltext", utf8_string, &state->fulltext)) if (MATCH("fulltext", utf8_string_std, &state->fulltext))
return; return;
nonmatch("fulltext", name, buf); 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); 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; 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; 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; return;
if (MATCH("negate", get_bool, &state->filter_constraint_negate)) if (MATCH("negate", get_bool, &state->filter_constraint_negate))
return; return;
if (MATCH("constraint", utf8_string, &state->filter_constraint)) if (MATCH("constraint", utf8_string_std, &state->filter_constraint))
return; return;
nonmatch("fulltext", name, buf); 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); try_to_fill_filter(state->cur_filter, name, buf);
return true; return true;
} }
if (!state->cur_event.deleted) { if (state->event_active) {
try_to_fill_event(name, buf, state); try_to_fill_event(name, buf, state);
return true; return true;
} }
@ -1633,7 +1628,7 @@ static bool visit(xmlNode *n, struct parser_state *state)
static void DivingLog_importer(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. * 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) 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 = SI_units;
state->xml_parsing_units.pressure = units::PASCALS; state->xml_parsing_units.pressure = units::PASCALS;
state->xml_parsing_units.temperature = units::KELVIN; state->xml_parsing_units.temperature = units::KELVIN;
@ -1737,7 +1732,7 @@ static void reset_all(struct parser_state *state)
* dive for that format. * dive for that format.
*/ */
state->xml_parsing_units = SI_units; 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 /* 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; int ret = 0;
struct parser_state state; struct parser_state state;
init_parser_state(&state);
state.log = log; state.log = log;
state.fingerprints = &fingerprint_table; // simply use the global table for now state.fingerprints = &fingerprint_table; // simply use the global table for now
doc = xmlReadMemory(res, strlen(res), url, NULL, XML_PARSE_HUGE | XML_PARSE_RECOVER); 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; ret = -1;
} }
dive_end(&state); dive_end(&state);
free_parser_state(&state);
xmlFreeDoc(doc); xmlFreeDoc(doc);
return ret; return ret;
} }
@ -1837,7 +1830,6 @@ extern "C" int parse_dlf_buffer(unsigned char *buffer, size_t size, struct divel
cylinder_t *cyl; cylinder_t *cyl;
struct parser_state state; struct parser_state state;
init_parser_state(&state);
state.log = log; state.log = log;
// Check for the correct file magic // 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); divecomputer_end(&state);
dive_end(&state); dive_end(&state);
free_parser_state(&state);
return 0; return 0;
} }

View file

@ -19,41 +19,21 @@
#include "device.h" #include "device.h"
#include "gettext.h" #include "gettext.h"
extern "C" void init_parser_state(struct parser_state *state) parser_state::~parser_state()
{ {
memset(state, 0, sizeof(*state)); free_dive(cur_dive);
state->metric = true; free_trip(cur_trip);
state->cur_event.deleted = 1; free_dive_site(cur_dive_site);
state->sample_rate = 0; free_filter_preset(cur_filter);
} free((void *)cur_extra_data.key);
free((void *)cur_extra_data.value);
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);
} }
/* /*
* If we don't have an explicit dive computer, * If we don't have an explicit dive computer,
* we use the implicit one that every dive has.. * 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; 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); 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)); 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); struct divecomputer *dc = get_dc(state);
if (state->cur_event.type == 123) { 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; 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 * to make a dive valid, but if it has no location, no date and no
* samples I'm pretty sure it's useless. * 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 && return state->cur_dive &&
(state->cur_dive->dive_site || state->cur_dive->when || state->cur_dive->dc.samples); (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? */ /* WARN: reset dc info does't touch the dc? */
state->lastcylinderindex = 0; 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); state->cur_settings.dc.model.clear();
free((void *)state->cur_settings.dc.nickname); state->cur_settings.dc.nickname.clear();
free((void *)state->cur_settings.dc.serial_nr); state->cur_settings.dc.serial_nr.clear();
free((void *)state->cur_settings.dc.firmware); state->cur_settings.dc.firmware.clear();
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.deviceid = 0; 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.clear();
state->cur_settings.fingerprint.data = NULL;
state->cur_settings.fingerprint.model = 0; state->cur_settings.fingerprint.model = 0;
state->cur_settings.fingerprint.serial = 0; state->cur_settings.fingerprint.serial = 0;
state->cur_settings.fingerprint.fdeviceid = 0; state->cur_settings.fingerprint.fdeviceid = 0;
state->cur_settings.fingerprint.fdiveid = 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; state->in_settings = true;
} }
extern "C" void settings_end(struct parser_state *state) void settings_end(struct parser_state *state)
{ {
state->in_settings = false; 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); 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, create_fingerprint_node_from_hex(state->fingerprints,
state->cur_settings.fingerprint.model, state->cur_settings.fingerprint.model,
state->cur_settings.fingerprint.serial, 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.fdeviceid,
state->cur_settings.fingerprint.fdiveid); 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); 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, create_device_node(state->log->devices,
state->cur_settings.dc.model, state->cur_settings.dc.model.c_str(),
state->cur_settings.dc.serial_nr, state->cur_settings.dc.serial_nr.c_str(),
state->cur_settings.dc.nickname); state->cur_settings.dc.nickname.c_str());
reset_dc_settings(state); 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) if (state->cur_dive_site)
return; 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)); 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) if (!state->cur_dive_site)
return; return;
@ -234,66 +209,60 @@ extern "C" void dive_site_end(struct parser_state *state)
state->cur_dive_site = NULL; 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) if (state->cur_filter)
return; return;
state->cur_filter = alloc_filter_preset(); 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); add_filter_preset_to_table(state->cur_filter, state->log->filter_presets);
free_filter_preset(state->cur_filter); free_filter_preset(state->cur_filter);
state->cur_filter = NULL; state->cur_filter = NULL;
} }
extern "C" void fulltext_start(struct parser_state *state) void fulltext_start(struct parser_state *state)
{ {
if (!state->cur_filter) if (!state->cur_filter)
return; return;
state->in_fulltext = true; state->in_fulltext = true;
} }
extern "C" void fulltext_end(struct parser_state *state) void fulltext_end(struct parser_state *state)
{ {
if (!state->in_fulltext) if (!state->in_fulltext)
return; return;
filter_preset_set_fulltext(state->cur_filter, state->fulltext, state->fulltext_string_mode); filter_preset_set_fulltext(state->cur_filter, state->fulltext.c_str(), state->fulltext_string_mode.c_str());
free(state->fulltext); state->fulltext.clear();
free(state->fulltext_string_mode); state->fulltext_string_mode.clear();
state->fulltext = NULL;
state->fulltext_string_mode = NULL;
state->in_fulltext = false; 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) if (!state->cur_filter)
return; return;
state->in_filter_constraint = true; 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) if (!state->in_filter_constraint)
return; return;
filter_preset_add_constraint(state->cur_filter, state->filter_constraint_type, state->filter_constraint_string_mode, 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, state->filter_constraint_negate, state->filter_constraint); state->filter_constraint_range_mode.c_str(), state->filter_constraint_negate, state->filter_constraint.c_str());
free(state->filter_constraint_type);
free(state->filter_constraint_string_mode);
free(state->filter_constraint_range_mode);
free(state->filter_constraint);
state->filter_constraint_type = NULL; state->filter_constraint_type.clear();
state->filter_constraint_string_mode = NULL; state->filter_constraint_string_mode.clear();
state->filter_constraint_range_mode = NULL; state->filter_constraint_range_mode.clear();
state->filter_constraint_negate = false; state->filter_constraint_negate = false;
state->filter_constraint = NULL; state->filter_constraint.clear();
state->in_filter_constraint = false; 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) if (state->cur_dive)
return; return;
@ -303,7 +272,7 @@ extern "C" void dive_start(struct parser_state *state)
state->o2pressure_sensor = 1; state->o2pressure_sensor = 1;
} }
extern "C" void dive_end(struct parser_state *state) void dive_end(struct parser_state *state)
{ {
if (!state->cur_dive) if (!state->cur_dive)
return; return;
@ -320,7 +289,7 @@ extern "C" void dive_end(struct parser_state *state)
state->cur_location.lon.udeg = 0; 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) if (state->cur_trip)
return; return;
@ -329,7 +298,7 @@ extern "C" void trip_start(struct parser_state *state)
memset(&state->cur_tm, 0, sizeof(state->cur_tm)); 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) if (!state->cur_trip)
return; return;
@ -337,32 +306,32 @@ extern "C" void trip_end(struct parser_state *state)
state->cur_trip = NULL; 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); add_picture(&state->cur_dive->pictures, state->cur_picture);
/* dive_add_picture took ownership, we can just clear out copy of the data */ /* dive_add_picture took ownership, we can just clear out copy of the data */
state->cur_picture = empty_picture; 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); 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); 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 * or the second cylinder depending on what isn't an
* oxygen cylinder. * 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 divecomputer *dc = get_dc(state);
struct sample *sample = prepare_sample(dc); struct sample *sample = prepare_sample(dc);
@ -409,7 +378,7 @@ extern "C" void sample_start(struct parser_state *state)
state->next_o2_sensor = 0; 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) if (!state->cur_dive)
return; return;
@ -418,7 +387,7 @@ extern "C" void sample_end(struct parser_state *state)
state->cur_sample = NULL; state->cur_sample = NULL;
} }
extern "C" void divecomputer_start(struct parser_state *state) void divecomputer_start(struct parser_state *state)
{ {
struct divecomputer *dc; struct divecomputer *dc;
@ -441,19 +410,19 @@ extern "C" void divecomputer_start(struct parser_state *state)
reset_dc_info(dc, 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) if (!state->cur_dc->when)
state->cur_dc->when = state->cur_dive->when; state->cur_dc->when = state->cur_dive->when;
state->cur_dc = NULL; state->cur_dc = NULL;
} }
extern "C" void userid_start(struct parser_state *state) void userid_start(struct parser_state *state)
{ {
state->in_userid = true; state->in_userid = true;
} }
extern "C" void userid_stop(struct parser_state *state) void userid_stop(struct parser_state *state)
{ {
state->in_userid = false; 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 * therefore make sure to only pass in to NULL-initialized pointers or pointers
* to owned strings * 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); free(*res);
while (isspace(*buffer)) while (isspace(*buffer))
++buffer; ++buffer;
@ -496,7 +464,7 @@ void utf8_string_std(const char *buffer, std::string *res)
*res = std::string(buffer, end - buffer); *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; const char *buffer = ds_name;
std::string trimmed = trimspace(buffer); std::string trimmed = trimspace(buffer);

View file

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