diff options
author | Berthold Stoeger <bstoeger@mail.tuwien.ac.at> | 2020-06-17 22:45:33 +0200 |
---|---|---|
committer | Dirk Hohndel <dirk@hohndel.org> | 2020-09-29 16:13:03 -0700 |
commit | 41cf83583d129edde607654592a52fe7bff57dc7 (patch) | |
tree | 7127476f88358f2248b22684c01f127997380d43 /core | |
parent | cef15c978d466af37a0f453c50f2e8942ed7cdc2 (diff) | |
download | subsurface-41cf83583d129edde607654592a52fe7bff57dc7.tar.gz |
filter: load filter presets from XML files
This is a bit painful: since we don't want to modify the filter
presets when the user imports (as opposed to opens) a log,
we have to provide a table where the parser stores the presets.
Calling the parser is getting quite unwieldy, since many tables
are passed. We probably should introduce a structure representing
a full log-book at one point, which collects all the things that
are saved to the log.
Apart from that, this is simply the counterpart to saving to XML.
The interpretation of the string data is performed by core
functions, not the parser itself to avoid code duplication with
the git parser.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Diffstat (limited to 'core')
-rw-r--r-- | core/file.c | 27 | ||||
-rw-r--r-- | core/file.h | 6 | ||||
-rw-r--r-- | core/import-csv.c | 30 | ||||
-rw-r--r-- | core/import-csv.h | 11 | ||||
-rw-r--r-- | core/parse-xml.c | 62 | ||||
-rw-r--r-- | core/parse.c | 67 | ||||
-rw-r--r-- | core/parse.h | 21 |
7 files changed, 190 insertions, 34 deletions
diff --git a/core/file.c b/core/file.c index 619ec5724..0878d4c42 100644 --- a/core/file.c +++ b/core/file.c @@ -76,7 +76,8 @@ out: } -static void zip_read(struct zip_file *file, const char *filename, struct dive_table *table, struct trip_table *trips, struct dive_site_table *sites) +static void zip_read(struct zip_file *file, const char *filename, struct dive_table *table, struct trip_table *trips, + struct dive_site_table *sites, filter_preset_table_t *filter_presets) { int size = 1024, n, read = 0; char *mem = malloc(size); @@ -87,11 +88,12 @@ static void zip_read(struct zip_file *file, const char *filename, struct dive_ta mem = realloc(mem, size); } mem[read] = 0; - (void) parse_xml_buffer(filename, mem, read, table, trips, sites, NULL); + (void) parse_xml_buffer(filename, mem, read, table, trips, sites, filter_presets, NULL); free(mem); } -int try_to_open_zip(const char *filename, struct dive_table *table, struct trip_table *trips, struct dive_site_table *sites) +int try_to_open_zip(const char *filename, struct dive_table *table, struct trip_table *trips, struct dive_site_table *sites, + filter_preset_table_t *filter_presets) { int success = 0; /* Grr. libzip needs to re-open the file, it can't take a buffer */ @@ -106,7 +108,7 @@ int try_to_open_zip(const char *filename, struct dive_table *table, struct trip_ /* skip parsing the divelogs.de pictures */ if (strstr(zip_get_name(zip, index, 0), "pictures/")) continue; - zip_read(file, filename, table, trips, sites); + zip_read(file, filename, table, trips, sites, filter_presets); zip_fclose(file); success++; } @@ -126,7 +128,6 @@ static int db_test_func(void *param, int columns, char **data, char **column) return *data[0] == '0'; } - static int try_to_open_db(const char *filename, struct memblock *mem, struct dive_table *table, struct trip_table *trips, struct dive_site_table *sites) { sqlite3 *handle; @@ -225,7 +226,8 @@ static int try_to_open_db(const char *filename, struct memblock *mem, struct div * Followed by the data values (all comma-separated, all one long line). */ static int open_by_filename(const char *filename, const char *fmt, struct memblock *mem, - struct dive_table *table, struct trip_table *trips, struct dive_site_table *sites) + struct dive_table *table, struct trip_table *trips, struct dive_site_table *sites, + filter_preset_table_t *filter_presets) { // hack to be able to provide a comment for the translated string static char *csv_warning = QT_TRANSLATE_NOOP3("gettextFromC", @@ -234,7 +236,7 @@ static int open_by_filename(const char *filename, const char *fmt, struct memblo /* Suunto Dive Manager files: SDE, ZIP; divelogs.de files: DLD */ if (!strcasecmp(fmt, "SDE") || !strcasecmp(fmt, "ZIP") || !strcasecmp(fmt, "DLD")) - return try_to_open_zip(filename, table, trips, sites); + return try_to_open_zip(filename, table, trips, sites, filter_presets); /* CSV files */ if (!strcasecmp(fmt, "CSV")) @@ -255,17 +257,18 @@ static int open_by_filename(const char *filename, const char *fmt, struct memblo return 0; } -static int parse_file_buffer(const char *filename, struct memblock *mem, struct dive_table *table, struct trip_table *trips, struct dive_site_table *sites) +static int parse_file_buffer(const char *filename, struct memblock *mem, struct dive_table *table, + struct trip_table *trips, struct dive_site_table *sites, filter_preset_table_t *filter_presets) { int ret; char *fmt = strrchr(filename, '.'); - if (fmt && (ret = open_by_filename(filename, fmt + 1, mem, table, trips, sites)) != 0) + if (fmt && (ret = open_by_filename(filename, fmt + 1, mem, table, trips, sites, filter_presets)) != 0) return ret; if (!mem->size || !mem->buffer) return report_error("Out of memory parsing file %s\n", filename); - return parse_xml_buffer(filename, mem->buffer, mem->size, table, trips, sites, NULL); + return parse_xml_buffer(filename, mem->buffer, mem->size, table, trips, sites, filter_presets, NULL); } int check_git_sha(const char *filename, struct git_repository **git_p, const char **branch_p) @@ -302,7 +305,7 @@ int check_git_sha(const char *filename, struct git_repository **git_p, const cha return 1; } -int parse_file(const char *filename, struct dive_table *table, struct trip_table *trips, struct dive_site_table *sites) +int parse_file(const char *filename, struct dive_table *table, struct trip_table *trips, struct dive_site_table *sites, filter_preset_table_t *filter_presets) { struct git_repository *git; const char *branch = NULL; @@ -372,7 +375,7 @@ int parse_file(const char *filename, struct dive_table *table, struct trip_table return 0; } - ret = parse_file_buffer(filename, &mem, table, trips, sites); + ret = parse_file_buffer(filename, &mem, table, trips, sites, filter_presets); free(mem.buffer); return ret; } diff --git a/core/file.h b/core/file.h index d282eb38b..1f692eb79 100644 --- a/core/file.h +++ b/core/file.h @@ -2,6 +2,8 @@ #ifndef FILE_H #define FILE_H +#include "filterpreset.h" + #include <sys/stat.h> #include <stdio.h> @@ -24,8 +26,8 @@ extern int datatrak_import(struct memblock *mem, struct memblock *wl_mem, struct extern void ostctools_import(const char *file, struct dive_table *table, struct trip_table *trips, struct dive_site_table *sites); extern int readfile(const char *filename, struct memblock *mem); -extern int parse_file(const char *filename, struct dive_table *table, struct trip_table *trips, struct dive_site_table *sites); -extern int try_to_open_zip(const char *filename, struct dive_table *table, struct trip_table *trips, struct dive_site_table *sites); +extern int parse_file(const char *filename, struct dive_table *table, struct trip_table *trips, struct dive_site_table *sites, filter_preset_table_t *filter_presets); +extern int try_to_open_zip(const char *filename, struct dive_table *table, struct trip_table *trips, struct dive_site_table *sites, filter_preset_table_t *filter_presets); // Platform specific functions extern int subsurface_rename(const char *path, const char *newpath); diff --git a/core/import-csv.c b/core/import-csv.c index db7754c87..ab5353109 100644 --- a/core/import-csv.c +++ b/core/import-csv.c @@ -104,7 +104,8 @@ static char *parse_dan_new_line(char *buf, const char *NL) static int try_to_xslt_open_csv(const char *filename, struct memblock *mem, const char *tag); static int parse_dan_format(const char *filename, char **params, int pnr, struct dive_table *table, - struct trip_table *trips, struct dive_site_table *sites) + struct trip_table *trips, filter_preset_table_t *filter_presets, + struct dive_site_table *sites) { int ret = 0, i; size_t end_ptr = 0; @@ -214,7 +215,7 @@ static int parse_dan_format(const char *filename, char **params, int pnr, struct } } params[pnr_local] = NULL; - ret |= parse_xml_buffer(filename, "<csv></csv>", 11, table, trips, sites, (const char **)params); + ret |= parse_xml_buffer(filename, "<csv></csv>", 11, table, trips, sites, filter_presets, (const char **)params); continue; } @@ -271,7 +272,7 @@ static int parse_dan_format(const char *filename, char **params, int pnr, struct if (try_to_xslt_open_csv(filename, &mem_csv, "csv")) return -1; - ret |= parse_xml_buffer(filename, mem_csv.buffer, mem_csv.size, table, trips, sites, (const char **)params); + ret |= parse_xml_buffer(filename, mem_csv.buffer, mem_csv.size, table, trips, sites, filter_presets, (const char **)params); end_ptr += ptr - (char *)mem_csv.buffer; free(mem_csv.buffer); } @@ -284,7 +285,8 @@ static int parse_dan_format(const char *filename, char **params, int pnr, struct } int parse_csv_file(const char *filename, char **params, int pnr, const char *csvtemplate, - struct dive_table *table, struct trip_table *trips, struct dive_site_table *sites) + struct dive_table *table, struct trip_table *trips, struct dive_site_table *sites, + filter_preset_table_t *filter_presets) { int ret, i; struct memblock mem; @@ -304,7 +306,7 @@ int parse_csv_file(const char *filename, char **params, int pnr, const char *csv mem.size = 0; if (!strcmp("DL7", csvtemplate)) { - return parse_dan_format(filename, params, pnr, table, trips, sites); + return parse_dan_format(filename, params, pnr, table, trips, sites, filter_presets); } else if (strcmp(params[0], "date")) { time(&now); timep = localtime(&now); @@ -339,7 +341,7 @@ int parse_csv_file(const char *filename, char **params, int pnr, const char *csv fprintf(stderr, "%s/xslt/%s -\n", SUBSURFACE_SOURCE, csvtemplate); } #endif - ret = parse_xml_buffer(filename, mem.buffer, mem.size, table, trips, sites, (const char **)params); + ret = parse_xml_buffer(filename, mem.buffer, mem.size, table, trips, sites, filter_presets, (const char **)params); free(mem.buffer); for (i = 0; params[i]; i += 2) @@ -806,15 +808,15 @@ int parse_txt_file(const char *filename, const char *csv, struct dive_table *tab #define SBPARAMS 40 static int parse_seabear_csv_file(const char *filename, char **params, int pnr, const char *csvtemplate, - struct dive_table *table, struct trip_table *trips, struct dive_site_table *sites); -int parse_seabear_log(const char *filename, struct dive_table *table, struct trip_table *trips, struct dive_site_table *sites) + struct dive_table *table, struct trip_table *trips, struct dive_site_table *sites, filter_preset_table_t *filter_presets); +int parse_seabear_log(const char *filename, struct dive_table *table, struct trip_table *trips, struct dive_site_table *sites, filter_preset_table_t *filter_presets) { char *params[SBPARAMS]; int pnr = 0; pnr = parse_seabear_header(filename, params, pnr); - if (parse_seabear_csv_file(filename, params, pnr, "csv", table, trips, sites) < 0) { + if (parse_seabear_csv_file(filename, params, pnr, "csv", table, trips, sites, filter_presets) < 0) { return -1; } @@ -823,7 +825,8 @@ int parse_seabear_log(const char *filename, struct dive_table *table, struct tri static int parse_seabear_csv_file(const char *filename, char **params, int pnr, const char *csvtemplate, - struct dive_table *table, struct trip_table *trips, struct dive_site_table *sites) + struct dive_table *table, struct trip_table *trips, struct dive_site_table *sites, + filter_preset_table_t *filter_presets) { int ret, i; struct memblock mem; @@ -942,7 +945,7 @@ static int parse_seabear_csv_file(const char *filename, char **params, int pnr, fprintf(stderr, "xslt/csv2xml.xslt\n"); } - ret = parse_xml_buffer(filename, mem.buffer, mem.size, table, trips, sites, (const char **)params); + ret = parse_xml_buffer(filename, mem.buffer, mem.size, table, trips, sites, filter_presets, (const char **)params); free(mem.buffer); for (i = 0; params[i]; i += 2) free(params[i + 1]); @@ -950,7 +953,8 @@ static int parse_seabear_csv_file(const char *filename, char **params, int pnr, return ret; } -int parse_manual_file(const char *filename, char **params, int pnr, struct dive_table *table, struct trip_table *trips, struct dive_site_table *sites) +int parse_manual_file(const char *filename, char **params, int pnr, struct dive_table *table, struct trip_table *trips, + struct dive_site_table *sites, filter_preset_table_t *filter_presets) { struct memblock mem; time_t now; @@ -989,7 +993,7 @@ int parse_manual_file(const char *filename, char **params, int pnr, struct dive_ fprintf(stderr, "%s/xslt/manualcsv2xml.xslt -\n", SUBSURFACE_SOURCE); } #endif - ret = parse_xml_buffer(filename, mem.buffer, mem.size, table, trips, sites, (const char **)params); + ret = parse_xml_buffer(filename, mem.buffer, mem.size, table, trips, sites, filter_presets, (const char **)params); free(mem.buffer); for (i = 0; i < pnr - 2; ++i) diff --git a/core/import-csv.h b/core/import-csv.h index 38bd30b62..749849286 100644 --- a/core/import-csv.h +++ b/core/import-csv.h @@ -2,6 +2,8 @@ #ifndef IMPORTCSV_H #define IMPORTCSV_H +#include "filterpreset.h" + enum csv_format { CSV_DEPTH, CSV_TEMP, @@ -21,12 +23,15 @@ enum csv_format { extern "C" { #endif -int parse_csv_file(const char *filename, char **params, int pnr, const char *csvtemplate, struct dive_table *table, struct trip_table *trips, struct dive_site_table *sites); +int parse_csv_file(const char *filename, char **params, int pnr, const char *csvtemplate, struct dive_table *table, + struct trip_table *trips, struct dive_site_table *sites, filter_preset_table_t *filter_presets); int try_to_open_csv(struct memblock *mem, enum csv_format type, struct dive_table *table, struct trip_table *trips, struct dive_site_table *sites); int parse_txt_file(const char *filename, const char *csv, struct dive_table *table, struct trip_table *trips, struct dive_site_table *sites); -int parse_seabear_log(const char *filename, struct dive_table *table, struct trip_table *trips, struct dive_site_table *sites); -int parse_manual_file(const char *filename, char **params, int pnr, struct dive_table *table, struct trip_table *trips, struct dive_site_table *sites); +int parse_seabear_log(const char *filename, struct dive_table *table, struct trip_table *trips, struct dive_site_table *sites, + filter_preset_table_t *filter_presets); +int parse_manual_file(const char *filename, char **params, int pnr, struct dive_table *table, struct trip_table *trips, + struct dive_site_table *sites, filter_preset_table_t *filter_presets); #ifdef __cplusplus } diff --git a/core/parse-xml.c b/core/parse-xml.c index 22de449cc..61af0f617 100644 --- a/core/parse-xml.c +++ b/core/parse-xml.c @@ -1416,6 +1416,50 @@ static void try_to_fill_dive_site(struct parser_state *state, const char *name, nonmatch("divesite", name, buf); } +static void try_to_fill_filter(struct filter_preset *filter, const char *name, char *buf) +{ + start_match("filterpreset", name, buf); + + char *s = NULL; + if (MATCH("name", utf8_string, &s)) { + filter_preset_set_name(filter, s); + free(s); + return; + } + + nonmatch("filterpreset", name, buf); +} + +static void try_to_fill_fulltext(const char *name, char *buf, struct parser_state *state) +{ + start_match("fulltext", name, buf); + + if (MATCH("mode", utf8_string, &state->fulltext_string_mode)) + return; + if (MATCH("fulltext", utf8_string, &state->fulltext)) + return; + + nonmatch("fulltext", name, buf); +} + +static void try_to_fill_filter_constraint(const char *name, char *buf, struct parser_state *state) +{ + start_match("fulltext", name, buf); + + if (MATCH("type", utf8_string, &state->filter_constraint_type)) + return; + if (MATCH("string_mode", utf8_string, &state->filter_constraint_string_mode)) + return; + if (MATCH("range_mode", utf8_string, &state->filter_constraint_range_mode)) + return; + if (MATCH("negate", get_bool, &state->filter_constraint_negate)) + return; + if (MATCH("constraint", utf8_string, &state->filter_constraint)) + return; + + nonmatch("fulltext", name, buf); +} + static bool entry(const char *name, char *buf, struct parser_state *state) { if (!strncmp(name, "version.program", sizeof("version.program") - 1) || @@ -1435,6 +1479,18 @@ static bool entry(const char *name, char *buf, struct parser_state *state) try_to_fill_dive_site(state, name, buf); return true; } + if (state->in_filter_constraint) { + try_to_fill_filter_constraint(name, buf, state); + return true; + } + if (state->in_fulltext) { + try_to_fill_fulltext(name, buf, state); + return true; + } + if (state->cur_filter) { + try_to_fill_filter(state->cur_filter, name, buf); + return true; + } if (!state->cur_event.deleted) { try_to_fill_event(name, buf, state); return true; @@ -1567,6 +1623,9 @@ static struct nesting { { "divecomputerid", dc_settings_start, dc_settings_end }, { "settings", settings_start, settings_end }, { "site", dive_site_start, dive_site_end }, + { "filterpreset", filter_preset_start, filter_preset_end }, + { "fulltext", fulltext_start, fulltext_end }, + { "constraint", filter_constraint_start, filter_constraint_end }, { "dive", dive_start, dive_end }, { "Dive", dive_start, dive_end }, { "trip", trip_start, trip_end }, @@ -1662,7 +1721,7 @@ static const char *preprocess_divelog_de(const char *buffer) int parse_xml_buffer(const char *url, const char *buffer, int size, struct dive_table *table, struct trip_table *trips, struct dive_site_table *sites, - const char **params) + filter_preset_table_t *filter_presets, const char **params) { UNUSED(size); xmlDoc *doc; @@ -1674,6 +1733,7 @@ int parse_xml_buffer(const char *url, const char *buffer, int size, state.target_table = table; state.trips = trips; state.sites = sites; + state.filter_presets = filter_presets; doc = xmlReadMemory(res, strlen(res), url, NULL, 0); if (!doc) doc = xmlReadMemory(res, strlen(res), url, "latin1", 0); diff --git a/core/parse.c b/core/parse.c index 1ddb49d60..281e9c3bc 100644 --- a/core/parse.c +++ b/core/parse.c @@ -31,6 +31,7 @@ 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); @@ -39,6 +40,12 @@ void free_parser_state(struct parser_state *state) 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); } /* @@ -223,7 +230,64 @@ void dive_site_end(struct parser_state *state) state->cur_dive_site = NULL; } -// now we need to add the code to parse the parts of the divesite enry +void filter_preset_start(struct parser_state *state) +{ + if (state->cur_filter) + return; + state->cur_filter = alloc_filter_preset(); +} + +void filter_preset_end(struct parser_state *state) +{ + add_filter_preset_to_table(state->cur_filter, state->filter_presets); + free_filter_preset(state->cur_filter); + state->cur_filter = NULL; +} + +void fulltext_start(struct parser_state *state) +{ + if (!state->cur_filter) + return; + state->in_fulltext = true; +} + +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; + state->in_fulltext = false; +} + +void filter_constraint_start(struct parser_state *state) +{ + if (!state->cur_filter) + return; + state->in_filter_constraint = true; +} + +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); + + state->filter_constraint_type = NULL; + state->filter_constraint_string_mode = NULL; + state->filter_constraint_range_mode = NULL; + state->filter_constraint_negate = false; + state->filter_constraint = NULL; + state->in_filter_constraint = false; +} void dive_start(struct parser_state *state) { @@ -456,4 +520,3 @@ int atoi_n(char *ptr, unsigned int len) } return 0; } - diff --git a/core/parse.h b/core/parse.h index e291d7e2c..899a006f7 100644 --- a/core/parse.h +++ b/core/parse.h @@ -5,6 +5,7 @@ #define MAX_EVENT_NAME 128 #include "dive.h" // for struct event! +#include "filterpreset.h" #include <sqlite3.h> @@ -51,11 +52,21 @@ struct parser_state { 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; 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; @@ -65,6 +76,7 @@ struct parser_state { struct dive_table *target_table; /* non-owning */ struct trip_table *trips; /* non-owning */ struct dive_site_table *sites; /* non-owning */ + filter_preset_table_t *filter_presets; /* non-owning */ sqlite3 *sql_handle; /* for SQL based parsers */ event_allocation_t event_allocation; @@ -100,6 +112,12 @@ void dive_site_start(struct parser_state *state); void dive_site_end(struct parser_state *state); void dive_start(struct parser_state *state); void dive_end(struct parser_state *state); +void filter_preset_start(struct parser_state *state); +void filter_preset_end(struct parser_state *state); +void filter_constraint_start(struct parser_state *state); +void filter_constraint_end(struct parser_state *state); +void fulltext_start(struct parser_state *state); +void fulltext_end(struct parser_state *state); void trip_start(struct parser_state *state); void trip_end(struct parser_state *state); void picture_start(struct parser_state *state); @@ -121,7 +139,8 @@ void add_dive_site(char *ds_name, struct dive *dive, struct parser_state *state) int atoi_n(char *ptr, unsigned int len); void parse_xml_init(void); -int parse_xml_buffer(const char *url, const char *buf, int size, struct dive_table *table, struct trip_table *trips, struct dive_site_table *sites, const char **params); +int parse_xml_buffer(const char *url, const char *buf, int size, struct dive_table *table, struct trip_table *trips, struct dive_site_table *sites, + filter_preset_table_t *filter_presets, const char **params); void parse_xml_exit(void); int parse_dm4_buffer(sqlite3 *handle, const char *url, const char *buf, int size, struct dive_table *table, struct trip_table *trips, struct dive_site_table *sites); int parse_dm5_buffer(sqlite3 *handle, const char *url, const char *buf, int size, struct dive_table *table, struct trip_table *trips, struct dive_site_table *sites); |