diff options
author | Miika Turkia <miika.turkia@gmail.com> | 2017-11-27 19:41:10 +0200 |
---|---|---|
committer | Dirk Hohndel <dirk@hohndel.org> | 2017-11-27 13:42:10 -0800 |
commit | 02c80a60b0cb7e2144ff8ef8564587299c9540b9 (patch) | |
tree | 8b8f9f1aaded96530b04325f953b3d730277d9c5 | |
parent | 0c564a4579c96704cbc2f2aa290edc538a9d5c6a (diff) | |
download | subsurface-02c80a60b0cb7e2144ff8ef8564587299c9540b9.tar.gz |
Refactore parse-xml.c into parse.c and parse-xml.c
This should help us to move parsing that is not XML related to other
files, hopefully making the code cleaner.
Signed-off-by: Miika Turkia <miika.turkia@gmail.com>
-rw-r--r-- | core/CMakeLists.txt | 1 | ||||
-rw-r--r-- | core/membuffer.h | 1 | ||||
-rw-r--r-- | core/parse-xml.c | 447 | ||||
-rw-r--r-- | core/parse.c | 449 | ||||
-rw-r--r-- | core/parse.h | 96 | ||||
-rw-r--r-- | packaging/ios/Subsurface-mobile/Subsurface-mobile.pro | 1 | ||||
-rw-r--r-- | tests/testparse.cpp | 1 |
7 files changed, 550 insertions, 446 deletions
diff --git a/core/CMakeLists.txt b/core/CMakeLists.txt index f063f3aa5..31b82ebbb 100644 --- a/core/CMakeLists.txt +++ b/core/CMakeLists.txt @@ -50,6 +50,7 @@ set(SUBSURFACE_CORE_LIB_SRCS membuffer.c ostctools.c parse-xml.c + parse.c planner.c plannernotes.c profile.c diff --git a/core/membuffer.h b/core/membuffer.h index fd59d7140..bd0a46d3a 100644 --- a/core/membuffer.h +++ b/core/membuffer.h @@ -7,6 +7,7 @@ extern "C" { #endif #include <ctype.h> +#include "units.h" struct membuffer { unsigned int len, alloc; diff --git a/core/parse-xml.c b/core/parse-xml.c index 6fd298710..4de4ab867 100644 --- a/core/parse-xml.c +++ b/core/parse-xml.c @@ -22,6 +22,7 @@ #include "gettext.h" #include "dive.h" +#include "parse.h" #include "divelist.h" #include "device.h" #include "membuffer.h" @@ -33,148 +34,10 @@ int diveid = -1; static xmlDoc *test_xslt_transforms(xmlDoc *doc, const char **params); -/* the dive table holds the overall dive list; target table points at - * the table we are currently filling */ -struct dive_table dive_table; -struct dive_table *target_table = NULL; - -/* Trim a character string by removing leading and trailing white space characters. - * Parameter: a pointer to a null-terminated character string (buffer); - * Return value: length of the trimmed string, excluding the terminal 0x0 byte - * The original pointer (buffer) remains valid after this function has been called - * and points to the trimmed string */ -int trimspace(char *buffer) -{ - int i, size, start, end; - size = strlen(buffer); - - if (!size) - return 0; - for(start = 0; isspace(buffer[start]); start++) - if (start >= size) return 0; // Find 1st character following leading whitespace - for(end = size - 1; isspace(buffer[end]); end--) // Find last character before trailing whitespace - if (end <= 0) return 0; - for(i = start; i <= end; i++) // Move the nonspace characters to the start of the string - buffer[i-start] = buffer[i]; - size = end - start + 1; - buffer[size] = 0x0; // then terminate the string - return size; // return string length -} - -/* - * Clear a dive_table - */ -void clear_table(struct dive_table *table) -{ - for (int i = 0; i < table->nr; i++) - free(table->dives[i]); - table->nr = 0; -} - -/* - * Add a dive into the dive_table array - */ -void record_dive_to_table(struct dive *dive, struct dive_table *table) -{ - assert(table != NULL); - struct dive **dives = grow_dive_table(table); - int nr = table->nr; - - dives[nr] = fixup_dive(dive); - table->nr = nr + 1; -} - -void record_dive(struct dive *dive) -{ - record_dive_to_table(dive, &dive_table); -} - -static void start_match(const char *type, const char *name, char *buffer) -{ - if (verbose > 2) - printf("Matching %s '%s' (%s)\n", - type, name, buffer); -} - -static void nonmatch(const char *type, const char *name, char *buffer) -{ - if (verbose > 1) - printf("Unable to match %s '%s' (%s)\n", - type, name, buffer); -} - -typedef void (*matchfn_t)(char *buffer, void *); - -static int match(const char *pattern, int plen, - const char *name, - matchfn_t fn, char *buf, void *data) -{ - switch (name[plen]) { - case '\0': - case '.': - break; - default: - return 0; - } - if (memcmp(pattern, name, plen)) - return 0; - fn(buf, data); - return 1; -} - - struct units xml_parsing_units; const struct units SI_units = SI_UNITS; const struct units IMPERIAL_units = IMPERIAL_UNITS; -/* - * Dive info as it is being built up.. - */ -#define MAX_EVENT_NAME 128 -static struct divecomputer *cur_dc; -static struct dive *cur_dive; -static struct dive_site *cur_dive_site; -degrees_t cur_latitude, cur_longitude; -static dive_trip_t *cur_trip = NULL; -static struct sample *cur_sample; -static struct picture *cur_picture; -static union { - struct event event; - char allocation[sizeof(struct event)+MAX_EVENT_NAME]; -} event_allocation = { .event.deleted = 1 }; -#define cur_event event_allocation.event -static struct { - struct { - const char *model; - uint32_t deviceid; - const char *nickname, *serial_nr, *firmware; - } dc; -} cur_settings; -static bool in_settings = false; -static bool in_userid = false; -static struct tm cur_tm; -static int cur_cylinder_index, cur_ws_index; -static int lastcylinderindex, next_o2_sensor; -static int o2pressure_sensor; -static struct extra_data cur_extra_data; - -/* - * If we don't have an explicit dive computer, - * we use the implicit one that every dive has.. - */ -static struct divecomputer *get_dc(void) -{ - return cur_dc ?: &cur_dive->dc; -} - -static enum import_source { - UNKNOWN, - LIBDIVECOMPUTER, - DIVINGLOG, - UDDF, - SSRF_WS, -} import_source; - static void divedate(const char *buffer, timestamp_t *when) { int d, m, y; @@ -561,15 +424,6 @@ static void cylindersize(char *buffer, volume_t *volume) } } -static void utf8_string(char *buffer, void *_res) -{ - char **res = _res; - int size; - size = trimspace(buffer); - if(size) - *res = strdup(buffer); -} - static void event_name(char *buffer, char *name) { int size = trimspace(buffer); @@ -1537,305 +1391,6 @@ static void try_to_fill_dive_site(struct dive_site **ds_p, const char *name, cha nonmatch("divesite", name, buf); } -/* - * While in some formats file boundaries are dive boundaries, in many - * others (as for example in our native format) there are - * multiple dives per file, so there can be other events too that - * trigger a "new dive" marker and you may get some nesting due - * to that. Just ignore nesting levels. - * On the flipside it is possible that we start an XML file that ends - * up having no dives in it at all - don't create a bogus empty dive - * for those. It's not entirely clear what is the minimum set of data - * to make a dive valid, but if it has no location, no date and no - * samples I'm pretty sure it's useless. - */ -static bool is_dive(void) -{ - return (cur_dive && - (cur_dive->dive_site_uuid || cur_dive->when || cur_dive->dc.samples)); -} - -static void reset_dc_info(struct divecomputer *dc) -{ - /* WARN: reset dc info does't touch the dc? */ - (void) dc; - lastcylinderindex = 0; -} - -static void reset_dc_settings(void) -{ - free((void *)cur_settings.dc.model); - free((void *)cur_settings.dc.nickname); - free((void *)cur_settings.dc.serial_nr); - free((void *)cur_settings.dc.firmware); - cur_settings.dc.model = NULL; - cur_settings.dc.nickname = NULL; - cur_settings.dc.serial_nr = NULL; - cur_settings.dc.firmware = NULL; - cur_settings.dc.deviceid = 0; -} - -static void settings_start(void) -{ - in_settings = true; -} - -static void settings_end(void) -{ - in_settings = false; -} - -static void dc_settings_start(void) -{ - reset_dc_settings(); -} - -static void dc_settings_end(void) -{ - create_device_node(cur_settings.dc.model, cur_settings.dc.deviceid, cur_settings.dc.serial_nr, - cur_settings.dc.firmware, cur_settings.dc.nickname); - reset_dc_settings(); -} - -static void dive_site_start(void) -{ - if (cur_dive_site) - return; - cur_dive_site = calloc(1, sizeof(struct dive_site)); -} - -static void dive_site_end(void) -{ - if (!cur_dive_site) - return; - if (cur_dive_site->taxonomy.nr == 0) { - free(cur_dive_site->taxonomy.category); - cur_dive_site->taxonomy.category = NULL; - } - if (cur_dive_site->uuid) { - struct dive_site *ds = alloc_or_get_dive_site(cur_dive_site->uuid); - merge_dive_site(ds, cur_dive_site); - - if (verbose > 3) - printf("completed dive site uuid %x8 name {%s}\n", ds->uuid, ds->name); - } - free_taxonomy(&cur_dive_site->taxonomy); - free(cur_dive_site); - cur_dive_site = NULL; -} - -// now we need to add the code to parse the parts of the divesite enry - -static void dive_start(void) -{ - if (cur_dive) - return; - cur_dive = alloc_dive(); - reset_dc_info(&cur_dive->dc); - memset(&cur_tm, 0, sizeof(cur_tm)); - if (cur_trip) { - add_dive_to_trip(cur_dive, cur_trip); - cur_dive->tripflag = IN_TRIP; - } - o2pressure_sensor = 1; -} - -static void dive_end(void) -{ - if (!cur_dive) - return; - if (!is_dive()) - free(cur_dive); - else - record_dive_to_table(cur_dive, target_table); - cur_dive = NULL; - cur_dc = NULL; - cur_latitude.udeg = 0; - cur_longitude.udeg = 0; - cur_cylinder_index = 0; - cur_ws_index = 0; -} - -static void trip_start(void) -{ - if (cur_trip) - return; - dive_end(); - cur_trip = calloc(1, sizeof(dive_trip_t)); - memset(&cur_tm, 0, sizeof(cur_tm)); -} - -static void trip_end(void) -{ - if (!cur_trip) - return; - insert_trip(&cur_trip); - cur_trip = NULL; -} - -static void event_start(void) -{ - memset(&cur_event, 0, sizeof(cur_event)); - cur_event.deleted = 0; /* Active */ -} - -static void event_end(void) -{ - struct divecomputer *dc = get_dc(); - if (cur_event.type == 123) { - struct picture *pic = alloc_picture(); - pic->filename = strdup(cur_event.name); - /* theoretically this could fail - but we didn't support multi year offsets */ - pic->offset.seconds = cur_event.time.seconds; - dive_add_picture(cur_dive, pic); - } else { - struct event *ev; - /* At some point gas change events did not have any type. Thus we need to add - * one on import, if we encounter the type one missing. - */ - if (cur_event.type == 0 && strcmp(cur_event.name, "gaschange") == 0) - cur_event.type = cur_event.value >> 16 > 0 ? SAMPLE_EVENT_GASCHANGE2 : SAMPLE_EVENT_GASCHANGE; - ev = add_event(dc, cur_event.time.seconds, - cur_event.type, cur_event.flags, - cur_event.value, cur_event.name); - - /* - * Older logs might mark the dive to be CCR by having an "SP change" event at time 0:00. Better - * to mark them being CCR on import so no need for special treatments elsewhere on the code. - */ - if (ev && cur_event.time.seconds == 0 && cur_event.type == SAMPLE_EVENT_PO2 && cur_event.value && dc->divemode==OC) { - dc->divemode = CCR; - } - - if (ev && event_is_gaschange(ev)) { - /* See try_to_fill_event() on why the filled-in index is one too big */ - ev->gas.index = cur_event.gas.index-1; - if (cur_event.gas.mix.o2.permille || cur_event.gas.mix.he.permille) - ev->gas.mix = cur_event.gas.mix; - } - } - cur_event.deleted = 1; /* No longer active */ -} - -static void picture_start(void) -{ - cur_picture = alloc_picture(); -} - -static void picture_end(void) -{ - dive_add_picture(cur_dive, cur_picture); - cur_picture = NULL; -} - -static void cylinder_start(void) -{ -} - -static void cylinder_end(void) -{ - cur_cylinder_index++; -} - -static void ws_start(void) -{ -} - -static void ws_end(void) -{ - cur_ws_index++; -} - -/* - * By default the sample data does not change unless the - * save-file gives an explicit new value. So we copy the - * data from the previous sample if one exists, and then - * the parsing will update it as necessary. - * - * There are a few exceptions, like the sample pressure: - * missing sample pressure doesn't mean "same as last - * time", but "interpolate". We clear those ones - * explicitly. - * - * NOTE! We default sensor use to 0, 1 respetively for - * the two sensors, but for CCR dives with explicit - * OXYGEN bottles we set the secondary sensor to that. - * Then the primary sensor will be either the first - * or the second cylinder depending on what isn't an - * oxygen cylinder. - */ -static void sample_start(void) -{ - struct divecomputer *dc = get_dc(); - struct sample *sample = prepare_sample(dc); - - if (sample != dc->sample) { - memcpy(sample, sample-1, sizeof(struct sample)); - sample->pressure[0].mbar = 0; - sample->pressure[1].mbar = 0; - } else { - sample->sensor[0] = !o2pressure_sensor; - sample->sensor[1] = o2pressure_sensor; - } - cur_sample = sample; - next_o2_sensor = 0; -} - -static void sample_end(void) -{ - if (!cur_dive) - return; - - finish_sample(get_dc()); - cur_sample = NULL; -} - -static void divecomputer_start(void) -{ - struct divecomputer *dc; - - /* Start from the previous dive computer */ - dc = &cur_dive->dc; - while (dc->next) - dc = dc->next; - - /* Did we already fill that in? */ - if (dc->samples || dc->model || dc->when) { - struct divecomputer *newdc = calloc(1, sizeof(*newdc)); - if (newdc) { - dc->next = newdc; - dc = newdc; - } - } - - /* .. this is the one we'll use */ - cur_dc = dc; - reset_dc_info(dc); -} - -static void divecomputer_end(void) -{ - if (!cur_dc->when) - cur_dc->when = cur_dive->when; - cur_dc = NULL; -} - -static void userid_start(void) -{ - in_userid = true; - //if the xml contains userid, keep saving it. - // don't call the prefs method here as we don't wanna - // actually change the preferences, this is temporary and - // will be reverted when the file finishes. - - prefs.save_userid_local = true; -} - -static void userid_stop(void) -{ - in_userid = false; -} - static bool entry(const char *name, char *buf) { if (!strncmp(name, "version.program", sizeof("version.program") - 1) || diff --git a/core/parse.c b/core/parse.c new file mode 100644 index 000000000..ba440f1b9 --- /dev/null +++ b/core/parse.c @@ -0,0 +1,449 @@ +#include <stdio.h> +#include <assert.h> +#include "membuffer.h" +#include <stdlib.h> +#include <unistd.h> +#include <libdivecomputer/parser.h> + +#include "dive.h" +#include "parse.h" +#include "divelist.h" +#include "device.h" + +/* +static union { + struct event event; + char allocation[sizeof(struct event)+MAX_EVENT_NAME]; +} event_allocation = { .event.deleted = 1 }; + +static event_allocation cur_event = { .event.deleted = 1 }; +static inline union { + struct event event; + char allocation[sizeof(struct event)+MAX_EVENT_NAME]; +} event_allocation = { .event.deleted = 1 }; +#define cur_event event_allocation.event +*/ +event_allocation_t event_allocation = { .event.deleted = 1 }; + + +struct divecomputer *cur_dc = NULL; +struct dive *cur_dive = NULL; +struct dive_site *cur_dive_site = NULL; +degrees_t cur_latitude, cur_longitude; +dive_trip_t *cur_trip = NULL; +struct sample *cur_sample = NULL; +struct picture *cur_picture = NULL; + +bool in_settings = false; +bool in_userid = false; +struct tm cur_tm; +int cur_cylinder_index, cur_ws_index; +int lastcylinderindex, next_o2_sensor; +int o2pressure_sensor; +struct extra_data cur_extra_data; + +struct dive_table dive_table; +struct dive_table *target_table = NULL; + +/* + * If we don't have an explicit dive computer, + * we use the implicit one that every dive has.. + */ +struct divecomputer *get_dc(void) +{ + return cur_dc ?: &cur_dive->dc; +} + + +/* Trim a character string by removing leading and trailing white space characters. + * Parameter: a pointer to a null-terminated character string (buffer); + * Return value: length of the trimmed string, excluding the terminal 0x0 byte + * The original pointer (buffer) remains valid after this function has been called + * and points to the trimmed string */ +int trimspace(char *buffer) +{ + int i, size, start, end; + size = strlen(buffer); + + if (!size) + return 0; + for(start = 0; isspace(buffer[start]); start++) + if (start >= size) return 0; // Find 1st character following leading whitespace + for(end = size - 1; isspace(buffer[end]); end--) // Find last character before trailing whitespace + if (end <= 0) return 0; + for(i = start; i <= end; i++) // Move the nonspace characters to the start of the string + buffer[i-start] = buffer[i]; + size = end - start + 1; + buffer[size] = 0x0; // then terminate the string + return size; // return string length +} + +/* + * Clear a dive_table + */ +void clear_table(struct dive_table *table) +{ + for (int i = 0; i < table->nr; i++) + free(table->dives[i]); + table->nr = 0; +} + +/* + * Add a dive into the dive_table array + */ +void record_dive_to_table(struct dive *dive, struct dive_table *table) +{ + assert(table != NULL); + struct dive **dives = grow_dive_table(table); + int nr = table->nr; + + dives[nr] = fixup_dive(dive); + table->nr = nr + 1; +} + +void record_dive(struct dive *dive) +{ + record_dive_to_table(dive, &dive_table); +} + +void start_match(const char *type, const char *name, char *buffer) +{ + if (verbose > 2) + printf("Matching %s '%s' (%s)\n", + type, name, buffer); +} + +void nonmatch(const char *type, const char *name, char *buffer) +{ + if (verbose > 1) + printf("Unable to match %s '%s' (%s)\n", + type, name, buffer); +} + +typedef void (*matchfn_t)(char *buffer, void *); + +int match(const char *pattern, int plen, + const char *name, + matchfn_t fn, char *buf, void *data) +{ + switch (name[plen]) { + case '\0': + case '.': + break; + default: + return 0; + } + if (memcmp(pattern, name, plen)) + return 0; + fn(buf, data); + return 1; +} + +void event_start(void) +{ + memset(&cur_event, 0, sizeof(cur_event)); + cur_event.deleted = 0; /* Active */ +} + +void event_end(void) +{ + struct divecomputer *dc = get_dc(); + if (cur_event.type == 123) { + struct picture *pic = alloc_picture(); + pic->filename = strdup(cur_event.name); + /* theoretically this could fail - but we didn't support multi year offsets */ + pic->offset.seconds = cur_event.time.seconds; + dive_add_picture(cur_dive, pic); + } else { + struct event *ev; + /* At some point gas change events did not have any type. Thus we need to add + * one on import, if we encounter the type one missing. + */ + if (cur_event.type == 0 && strcmp(cur_event.name, "gaschange") == 0) + cur_event.type = cur_event.value >> 16 > 0 ? SAMPLE_EVENT_GASCHANGE2 : SAMPLE_EVENT_GASCHANGE; + ev = add_event(dc, cur_event.time.seconds, + cur_event.type, cur_event.flags, + cur_event.value, cur_event.name); + + /* + * Older logs might mark the dive to be CCR by having an "SP change" event at time 0:00. Better + * to mark them being CCR on import so no need for special treatments elsewhere on the code. + */ + if (ev && cur_event.time.seconds == 0 && cur_event.type == SAMPLE_EVENT_PO2 && cur_event.value && dc->divemode==OC) { + dc->divemode = CCR; + } + + if (ev && event_is_gaschange(ev)) { + /* See try_to_fill_event() on why the filled-in index is one too big */ + ev->gas.index = cur_event.gas.index-1; + if (cur_event.gas.mix.o2.permille || cur_event.gas.mix.he.permille) + ev->gas.mix = cur_event.gas.mix; + } + } + cur_event.deleted = 1; /* No longer active */ +} + +/* + * While in some formats file boundaries are dive boundaries, in many + * others (as for example in our native format) there are + * multiple dives per file, so there can be other events too that + * trigger a "new dive" marker and you may get some nesting due + * to that. Just ignore nesting levels. + * On the flipside it is possible that we start an XML file that ends + * up having no dives in it at all - don't create a bogus empty dive + * for those. It's not entirely clear what is the minimum set of data + * to make a dive valid, but if it has no location, no date and no + * samples I'm pretty sure it's useless. + */ +bool is_dive(void) +{ + return (cur_dive && + (cur_dive->dive_site_uuid || cur_dive->when || cur_dive->dc.samples)); +} + +void reset_dc_info(struct divecomputer *dc) +{ + /* WARN: reset dc info does't touch the dc? */ + (void) dc; + lastcylinderindex = 0; +} + +void reset_dc_settings(void) +{ + free((void *)cur_settings.dc.model); + free((void *)cur_settings.dc.nickname); + free((void *)cur_settings.dc.serial_nr); + free((void *)cur_settings.dc.firmware); + cur_settings.dc.model = NULL; + cur_settings.dc.nickname = NULL; + cur_settings.dc.serial_nr = NULL; + cur_settings.dc.firmware = NULL; + cur_settings.dc.deviceid = 0; +} + +void settings_start(void) +{ + in_settings = true; +} + +void settings_end(void) +{ + in_settings = false; +} + +void dc_settings_start(void) +{ + reset_dc_settings(); +} + +void dc_settings_end(void) +{ + create_device_node(cur_settings.dc.model, cur_settings.dc.deviceid, cur_settings.dc.serial_nr, + cur_settings.dc.firmware, cur_settings.dc.nickname); + reset_dc_settings(); +} + +void dive_site_start(void) +{ + if (cur_dive_site) + return; + cur_dive_site = calloc(1, sizeof(struct dive_site)); +} + +void dive_site_end(void) +{ + if (!cur_dive_site) + return; + if (cur_dive_site->taxonomy.nr == 0) { + free(cur_dive_site->taxonomy.category); + cur_dive_site->taxonomy.category = NULL; + } + if (cur_dive_site->uuid) { + struct dive_site *ds = alloc_or_get_dive_site(cur_dive_site->uuid); + merge_dive_site(ds, cur_dive_site); + + if (verbose > 3) + printf("completed dive site uuid %x8 name {%s}\n", ds->uuid, ds->name); + } + free_taxonomy(&cur_dive_site->taxonomy); + free(cur_dive_site); + cur_dive_site = NULL; +} + +// now we need to add the code to parse the parts of the divesite enry + +void dive_start(void) +{ + if (cur_dive) + return; + cur_dive = alloc_dive(); + reset_dc_info(&cur_dive->dc); + memset(&cur_tm, 0, sizeof(cur_tm)); + if (cur_trip) { + add_dive_to_trip(cur_dive, cur_trip); + cur_dive->tripflag = IN_TRIP; + } + o2pressure_sensor = 1; +} + +void dive_end(void) +{ + if (!cur_dive) + return; + if (!is_dive()) + free(cur_dive); + else + record_dive_to_table(cur_dive, target_table); + cur_dive = NULL; + cur_dc = NULL; + cur_latitude.udeg = 0; + cur_longitude.udeg = 0; + cur_cylinder_index = 0; + cur_ws_index = 0; +} + +void trip_start(void) +{ + if (cur_trip) + return; + dive_end(); + cur_trip = calloc(1, sizeof(dive_trip_t)); + memset(&cur_tm, 0, sizeof(cur_tm)); +} + +void trip_end(void) +{ + if (!cur_trip) + return; + insert_trip(&cur_trip); + cur_trip = NULL; +} + +void picture_start(void) +{ + cur_picture = alloc_picture(); +} + +void picture_end(void) +{ + dive_add_picture(cur_dive, cur_picture); + cur_picture = NULL; +} + +void cylinder_start(void) +{ +} + +void cylinder_end(void) +{ + cur_cylinder_index++; +} + +void ws_start(void) +{ +} + +void ws_end(void) +{ + cur_ws_index++; +} + +/* + * By default the sample data does not change unless the + * save-file gives an explicit new value. So we copy the + * data from the previous sample if one exists, and then + * the parsing will update it as necessary. + * + * There are a few exceptions, like the sample pressure: + * missing sample pressure doesn't mean "same as last + * time", but "interpolate". We clear those ones + * explicitly. + * + * NOTE! We default sensor use to 0, 1 respetively for + * the two sensors, but for CCR dives with explicit + * OXYGEN bottles we set the secondary sensor to that. + * Then the primary sensor will be either the first + * or the second cylinder depending on what isn't an + * oxygen cylinder. + */ +void sample_start(void) +{ + struct divecomputer *dc = get_dc(); + struct sample *sample = prepare_sample(dc); + + if (sample != dc->sample) { + memcpy(sample, sample-1, sizeof(struct sample)); + sample->pressure[0].mbar = 0; + sample->pressure[1].mbar = 0; + } else { + sample->sensor[0] = !o2pressure_sensor; + sample->sensor[1] = o2pressure_sensor; + } + cur_sample = sample; + next_o2_sensor = 0; +} + +void sample_end(void) +{ + if (!cur_dive) + return; + + finish_sample(get_dc()); + cur_sample = NULL; +} + +void divecomputer_start(void) +{ + struct divecomputer *dc; + + /* Start from the previous dive computer */ + dc = &cur_dive->dc; + while (dc->next) + dc = dc->next; + + /* Did we already fill that in? */ + if (dc->samples || dc->model || dc->when) { + struct divecomputer *newdc = calloc(1, sizeof(*newdc)); + if (newdc) { + dc->next = newdc; + dc = newdc; + } + } + + /* .. this is the one we'll use */ + cur_dc = dc; + reset_dc_info(dc); +} + +void divecomputer_end(void) +{ + if (!cur_dc->when) + cur_dc->when = cur_dive->when; + cur_dc = NULL; +} + +void userid_start(void) +{ + in_userid = true; + //if the xml contains userid, keep saving it. + // don't call the prefs method here as we don't wanna + // actually change the preferences, this is temporary and + // will be reverted when the file finishes. + + prefs.save_userid_local = true; +} + +void userid_stop(void) +{ + in_userid = false; +} + +void utf8_string(char *buffer, void *_res) +{ + char **res = _res; + int size; + size = trimspace(buffer); + if(size) + *res = strdup(buffer); +} + diff --git a/core/parse.h b/core/parse.h new file mode 100644 index 000000000..003ef9929 --- /dev/null +++ b/core/parse.h @@ -0,0 +1,96 @@ +// SPDX-License-Identifier: GPL-2.0 +#ifndef PARSE_H +#define PARSE_H + +#define MAX_EVENT_NAME 128 + +typedef union { + struct event event; + char allocation[sizeof(struct event) + MAX_EVENT_NAME]; +} event_allocation_t; + +extern event_allocation_t event_allocation; +#define cur_event event_allocation.event + +/* + * Dive info as it is being built up.. + */ +extern struct divecomputer *cur_dc; +extern struct dive *cur_dive; +extern struct dive_site *cur_dive_site; +extern degrees_t cur_latitude, cur_longitude; +extern dive_trip_t *cur_trip; +extern struct sample *cur_sample; +extern struct picture *cur_picture; + + +struct { + struct { + const char *model; + uint32_t deviceid; + const char *nickname, *serial_nr, *firmware; + } dc; +} cur_settings; + +extern bool in_settings; +extern bool in_userid; +extern struct tm cur_tm; +extern int cur_cylinder_index, cur_ws_index; +extern int lastcylinderindex, next_o2_sensor; +extern int o2pressure_sensor; +extern struct extra_data cur_extra_data; + +enum import_source { + UNKNOWN, + LIBDIVECOMPUTER, + DIVINGLOG, + UDDF, + SSRF_WS, +} import_source; + +/* the dive table holds the overall dive list; target table points at + * the table we are currently filling */ +extern struct dive_table dive_table; +extern struct dive_table *target_table; + +int trimspace(char *buffer); +void clear_table(struct dive_table *table); +void record_dive_to_table(struct dive *dive, struct dive_table *table); +void record_dive(struct dive *dive); +void start_match(const char *type, const char *name, char *buffer); +void nonmatch(const char *type, const char *name, char *buffer); +typedef void (*matchfn_t)(char *buffer, void *); +int match(const char *pattern, int plen, const char *name, matchfn_t fn, char *buf, void *data); +void event_start(void); +void event_end(void); +struct divecomputer *get_dc(void); + +bool is_dive(void); +void reset_dc_info(struct divecomputer *dc); +void reset_dc_settings(void); +void settings_start(void); +void settings_end(void); +void dc_settings_start(void); +void dc_settings_end(void); +void dive_site_start(void); +void dive_site_end(void); +void dive_start(void); +void dive_end(void); +void trip_start(void); +void trip_end(void); +void picture_start(void); +void picture_end(void); +void cylinder_start(void); +void cylinder_end(void); +void ws_start(void); +void ws_end(void); + +void sample_start(void); +void sample_end(void); +void divecomputer_start(void); +void divecomputer_end(void); +void userid_start(void); +void userid_stop(void); +void utf8_string(char *buffer, void *_res); + +#endif diff --git a/packaging/ios/Subsurface-mobile/Subsurface-mobile.pro b/packaging/ios/Subsurface-mobile/Subsurface-mobile.pro index 8332f3759..836057c67 100644 --- a/packaging/ios/Subsurface-mobile/Subsurface-mobile.pro +++ b/packaging/ios/Subsurface-mobile/Subsurface-mobile.pro @@ -46,6 +46,7 @@ SOURCES += ../../../subsurface-mobile-main.cpp \ ../../../core/liquivision.c \ ../../../core/load-git.c \ ../../../core/parse-xml.c \ + ../../../core/parse.c \ ../../../core/save-html.c \ ../../../core/statistics.c \ ../../../core/worldmap-save.c \ diff --git a/tests/testparse.cpp b/tests/testparse.cpp index b614560b5..49d98f66e 100644 --- a/tests/testparse.cpp +++ b/tests/testparse.cpp @@ -1,6 +1,7 @@ // SPDX-License-Identifier: GPL-2.0 #include "testparse.h" #include "core/dive.h" +#include "core/parse.h" #include "core/file.h" #include "core/divelist.h" #include <QTextStream> |