From f2566ba561ff8eb560e71dd89de5e66e46e7143d Mon Sep 17 00:00:00 2001 From: Dirk Hohndel Date: Sun, 2 Oct 2011 17:47:20 -0700 Subject: First steps towards integrating SDA files into the default XML loading Signed-off-by: Dirk Hohndel --- uemis.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'uemis.c') diff --git a/uemis.c b/uemis.c index 25d1b8ab7..259d30c53 100644 --- a/uemis.c +++ b/uemis.c @@ -180,7 +180,7 @@ bail: /* * parse uemis base64 data blob into struct dive */ -static void parse_divelog_binary(char *base64, struct dive **divep) { +void uemis_parse_divelog_binary(char *base64, struct dive **divep) { int datalen; int i; uint8_t *data; @@ -271,7 +271,7 @@ parse_uemis_file(char *divelogfilename) { /* some error handling */ goto bail; } - parse_divelog_binary(found,&dive); + uemis_parse_divelog_binary(found,&dive); record_dive(dive); bail: if (found) -- cgit v1.2.3-70-g09d2 From 254b851e44a31e2028a2fdddfb4f6989a8e59374 Mon Sep 17 00:00:00 2001 From: Dirk Hohndel Date: Sun, 2 Oct 2011 21:59:54 -0700 Subject: Integrate loading of uemis SDA files into the regular xml parsing There are a few interesting issues with this: - this requires a change to the SDA file format; thankfully I control that format, too (the default files are not valid XML files) - once again, the fact that adding samples can change the dive pointer messes with me - I decided to change the interface of ALL of the XXX_dive_match functions to take a struct dive** I know this is not ideal as all the other functions don't need that - but I would have hated the inconsistency - there is the issue that we now overload two _different_ uemis formats in the same function - that's certainly a potential point of confusion - a minor detail is the problem that the SDA format is kinda odd to parse and that we trigger on the duration field by it being the only float. Yeah, that's not ideal - but again, I control the format, so I _know_ this is true. Signed-off-by: Dirk Hohndel --- parse-xml.c | 50 +++++++++++++++++++++++++++++++++++++++----------- uemis.c | 3 ++- uemis.h | 2 +- 3 files changed, 42 insertions(+), 13 deletions(-) (limited to 'uemis.c') diff --git a/parse-xml.c b/parse-xml.c index 4e68e8ee2..6a08a3845 100644 --- a/parse-xml.c +++ b/parse-xml.c @@ -3,6 +3,7 @@ #include #include #include +#define __USE_XOPEN #include #include #include @@ -640,8 +641,10 @@ static void try_to_fill_sample(struct sample *sample, const char *name, char *bu /* * Crazy suunto xml. Look at how those o2/he things match up. */ -static int suunto_dive_match(struct dive *dive, const char *name, int len, char *buf) +static int suunto_dive_match(struct dive **divep, const char *name, int len, char *buf) { + struct dive *dive = *divep; + return MATCH(".o2pct", percent, &dive->cylinder[0].gasmix.o2) || MATCH(".hepct_0", percent, &dive->cylinder[0].gasmix.he) || MATCH(".o2pct_2", percent, &dive->cylinder[1].gasmix.o2) || @@ -679,8 +682,10 @@ static void divinglog_place(char *place, void *_location) country = NULL; } -static int divinglog_dive_match(struct dive *dive, const char *name, int len, char *buf) +static int divinglog_dive_match(struct dive **divep, const char *name, int len, char *buf) { + struct dive *dive = *divep; + return MATCH(".divedate", divedate, &dive->when) || MATCH(".entrytime", divetime, &dive->when) || MATCH(".depth", depth, &dive->maxdepth) || @@ -771,6 +776,21 @@ static void uemis_time_zone(char *buffer, void *_when) #endif } +static void uemis_ts(char *buffer, void *_when) +{ + struct tm tm; + time_t *when = _when; + + strptime(buffer, "%Y-%m-%dT%H:%M:%S", &tm); + *when = utc_mktime(&tm); +} + +static void uemis_duration(char *buffer, void *_duration) +{ + duration_t *duration = _duration; + duration->seconds = atof(buffer) * 60 + 0.5; +} + /* 0 - air ; 1 - nitrox1 ; 2 - nitrox2 ; 3 = nitrox3 */ static int uemis_gas_template; @@ -835,8 +855,10 @@ static void uemis_percent(char *buffer, void *_cylinder) percent(buffer, &dive->cylinder[index].gasmix.o2); } -static int uemis_dive_match(struct dive *dive, const char *name, int len, char *buf) +static int uemis_dive_match(struct dive **divep, const char *name, int len, char *buf) { + struct dive *dive = *divep; + return MATCH(".units.length", uemis_length_unit, &input_units) || MATCH(".units.volume", uemis_volume_unit, &input_units) || MATCH(".units.pressure", uemis_pressure_unit, &input_units) || @@ -862,7 +884,9 @@ static int uemis_dive_match(struct dive *dive, const char *name, int len, char * MATCH(".nitrox_3.deco_tank.oxygen", uemis_percent, dive->cylinder + 5) || MATCH(".nitrox_3.travel_tank.size", uemis_cylindersize, dive->cylinder + 6) || MATCH(".nitrox_3.travel_tank.oxygen", uemis_percent, dive->cylinder + 6) || - MATCH(".dive.val.bin", uemis_parse_divelog_binary, &dive) || + MATCH(".dive.val.float", uemis_duration, &dive->duration) || + MATCH(".dive.val.ts", uemis_ts, &dive->when) || + MATCH(".dive.val.bin", uemis_parse_divelog_binary, divep) || 0; } @@ -910,8 +934,10 @@ success: free(buffer); } -static int uddf_dive_match(struct dive *dive, const char *name, int len, char *buf) +static int uddf_dive_match(struct dive **divep, const char *name, int len, char *buf) { + struct dive *dive = *divep; + return MATCH(".datetime", uddf_datetime, &dive->when) || MATCH(".diveduration", duration, &dive->duration) || MATCH(".greatestdepth", depth, &dive->maxdepth) || @@ -933,7 +959,7 @@ static void gps_location(char *buffer, void *_dive) } /* We're in the top-level dive xml. Try to convert whatever value to a dive value */ -static void try_to_fill_dive(struct dive *dive, const char *name, char *buf) +static void try_to_fill_dive(struct dive **divep, const char *name, char *buf) { int len = strlen(name); @@ -941,22 +967,22 @@ static void try_to_fill_dive(struct dive *dive, const char *name, char *buf) switch (import_source) { case SUUNTO: - if (suunto_dive_match(dive, name, len, buf)) + if (suunto_dive_match(divep, name, len, buf)) return; break; case UEMIS: - if (uemis_dive_match(dive, name, len, buf)) + if (uemis_dive_match(divep, name, len, buf)) return; break; case DIVINGLOG: - if (divinglog_dive_match(dive, name, len, buf)) + if (divinglog_dive_match(divep, name, len, buf)) return; break; case UDDF: - if (uddf_dive_match(dive, name, len, buf)) + if (uddf_dive_match(divep, name, len, buf)) return; break; @@ -964,6 +990,8 @@ static void try_to_fill_dive(struct dive *dive, const char *name, char *buf) break; } + struct dive *dive = *divep; + if (MATCH(".number", get_index, &dive->number)) return; if (MATCH(".date", divedate, &dive->when)) @@ -1224,7 +1252,7 @@ static void entry(const char *name, int size, const char *raw) return; } if (dive) { - try_to_fill_dive(dive, name, buf); + try_to_fill_dive(&dive, name, buf); return; } } diff --git a/uemis.c b/uemis.c index 259d30c53..769752915 100644 --- a/uemis.c +++ b/uemis.c @@ -180,11 +180,12 @@ bail: /* * parse uemis base64 data blob into struct dive */ -void uemis_parse_divelog_binary(char *base64, struct dive **divep) { +void uemis_parse_divelog_binary(char *base64, void *datap) { int datalen; int i; uint8_t *data; struct sample *sample; + struct dive **divep = datap; struct dive *dive = *divep; int template, gasoffset; diff --git a/uemis.h b/uemis.h index 62aeb5422..99cf44445 100644 --- a/uemis.h +++ b/uemis.h @@ -9,6 +9,6 @@ #define DEVICE_TYPE_UEMIS (-1) void uemis_import(); -void uemis_parse_divelog_binary(char *base64, struct dive **divep); +void uemis_parse_divelog_binary(char *base64, void *divep); #endif /* DIVE_H */ -- cgit v1.2.3-70-g09d2 From c15f798a85db53dae404a9113266a4d2bc72fbc6 Mon Sep 17 00:00:00 2001 From: Dirk Hohndel Date: Mon, 3 Oct 2011 08:27:36 -0700 Subject: Remove the ability to 'Import' .SDA files We can instead 'Open' these files as they are just bastardized XML files. This gets us back to a more consistent point where 'Import' gets data directly from the dive computer (and hopefully soon we will add the ability to load a dive directly from a uemis SDA to libdivecomputer), and 'Open' loads a file from the filesystem of the computer we are running on (this last sentence phrased so awkwardly as the uemis Zurich SDA is a computer and presents a file system when connected via USB - it just doesn't have the dive data in an accessible format in that file system). As a bonus we get to throw away quite a bit of code (the uemis specific file handling, mini-XML parser with helper functions, the file open dialog in the importer). Yay! Signed-off-by: Dirk Hohndel --- dive.h | 2 - gtk-gui.c | 42 +------------------- libdivecomputer.c | 4 -- uemis.c | 113 ------------------------------------------------------ uemis.h | 4 -- 5 files changed, 2 insertions(+), 163 deletions(-) (limited to 'uemis.c') diff --git a/dive.h b/dive.h index 42d91d630..40fc5ca2c 100644 --- a/dive.h +++ b/dive.h @@ -262,8 +262,6 @@ extern void report_error(GError* error); extern void dive_list_update_dives(void); extern void flush_divelist(struct dive *dive); -extern int open_import_file_dialog(char *filterpattern, char *filtertext, - void(* parse_function)(char *)); #define DIVE_ERROR_PARSE 1 const char *weekday(int wday); diff --git a/gtk-gui.c b/gtk-gui.c index 87cd8bf87..002b80414 100644 --- a/gtk-gui.c +++ b/gtk-gui.c @@ -103,6 +103,8 @@ static void file_open(GtkWidget *w, gpointer data) filter = gtk_file_filter_new(); gtk_file_filter_add_pattern(filter, "*.xml"); gtk_file_filter_add_pattern(filter, "*.XML"); + gtk_file_filter_add_pattern(filter, "*.sda"); + gtk_file_filter_add_pattern(filter, "*.SDA"); gtk_file_filter_add_mime_type(filter, "text/xml"); gtk_file_filter_set_name(filter, "XML file"); gtk_file_chooser_set_filter(GTK_FILE_CHOOSER(dialog), filter); @@ -632,46 +634,6 @@ void run_ui(void) gtk_main(); } -/* get the filenames the user selects and call the parsing function - * on them - * return 0 if the user cancelled the dialog - */ -int open_import_file_dialog(char *filterpattern, char *filtertext, - void(* parse_function)(char *)) -{ - int ret=0; - - GtkWidget *dialog; - GtkFileFilter *filter = gtk_file_filter_new (); - gtk_file_filter_add_pattern (filter, filterpattern); - gtk_file_filter_set_name(filter, filtertext); - dialog = gtk_file_chooser_dialog_new("Open File", - GTK_WINDOW(main_window), - GTK_FILE_CHOOSER_ACTION_OPEN, - GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, - GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, - NULL); - gtk_file_chooser_set_select_multiple(GTK_FILE_CHOOSER(dialog), TRUE); - gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(dialog),filter); - - if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) { - GSList *filenames; - char *filename; - filenames = gtk_file_chooser_get_filenames(GTK_FILE_CHOOSER(dialog)); - while(filenames != NULL) { - filename = (char *)filenames->data; - parse_function(filename); - g_free(filename); - filenames = g_slist_next(filenames); - } - g_slist_free(filenames); - ret = 1; - } - gtk_widget_destroy(dialog); - - return ret; -} - static gboolean expose_event(GtkWidget *widget, GdkEventExpose *event, gpointer data) { struct dive *dive = current_dive; diff --git a/libdivecomputer.c b/libdivecomputer.c index 5fea5c28c..78be2019a 100644 --- a/libdivecomputer.c +++ b/libdivecomputer.c @@ -497,9 +497,6 @@ void do_import(device_data_t *data) pthread_t pthread; void *retval; - if (data->type == DEVICE_TYPE_UEMIS) - return uemis_import(); - /* I'm sure there is some better interface for waiting on a thread in a UI main loop */ import_thread_done = 0; pthread_create(&pthread, NULL, pthread_wrapper, data); @@ -542,6 +539,5 @@ struct device_list device_list[] = { { "Cressi Edy", DEVICE_TYPE_CRESSI_EDY }, { "Zeagle N2iTiON 3", DEVICE_TYPE_ZEAGLE_N2ITION3 }, { "Atomics Cobalt", DEVICE_TYPE_ATOMICS_COBALT }, - { "Uemis Zurich SDA", DEVICE_TYPE_UEMIS }, { NULL } }; diff --git a/uemis.c b/uemis.c index 769752915..1be48f33e 100644 --- a/uemis.c +++ b/uemis.c @@ -73,64 +73,6 @@ static void decode( uint8_t *inbuf, uint8_t *outbuf, int inbuf_len ) { } /* end code from Bob Trower */ -/* small helper functions */ -/* simpleregex allocates (and reallocates) the found buffer - * don't forget to free it when you are done - */ -static int simpleregex(char *buffer, char *regex, char **found) { - int status; - regex_t re; - regmatch_t match[5]; - - if (regcomp(&re, regex, 0) !=0) { - fprintf(stderr,"internal error, regex failed!\n"); - exit(1); - } - status = regexec(&re,buffer,5,match,0); - if(status == 0) { - *found = realloc(*found,match[1].rm_eo-match[1].rm_so + 1); - strncpy(*found,buffer+match[1].rm_so,match[1].rm_eo-match[1].rm_so); - (*found)[match[1].rm_eo-match[1].rm_so] = '\0'; - } - return(status == 0); -} - -/* read in line of arbitrary length (important for SDA files that can - * have lines that are tens of kB long - * don't forget to free it when you are done - */ -#define MYGETL_INCR 1024 -static char * mygetline(FILE * f) { - size_t size = 0; - size_t len = 0; - char * buf = NULL; - - do { - size += MYGETL_INCR; - if ((buf = realloc(buf,size)) == NULL) - break; - fgets(buf+len,MYGETL_INCR,f); - len = strlen(buf); - } while (!feof(f) && buf[len-1]!='\n'); - return buf; -} - -/* text matching, used to build very poor man's XML parser */ -int matchit(FILE *infd, char *regex, char *typeregex, char **found) { - char *buffer; - - while (!feof(infd)) { - buffer = mygetline(infd); - if (buffer && simpleregex(buffer,regex,found)) { - buffer = mygetline(infd); - if (buffer && simpleregex(buffer,typeregex,found)) { - return 1; - } - } - } - return 0; -} - /* * pressure_to_depth: In centibar. And when converting to * depth, I'm just going to always use saltwater, because I @@ -233,58 +175,3 @@ void uemis_parse_divelog_binary(char *base64, void *datap) { dive->duration.seconds = sample->time.seconds - 1; return; } - -/* parse a single file - * TODO: we don't report any errors when the parse fails - we simply don't add them to the list - */ -void -parse_uemis_file(char *divelogfilename) { - char *found=NULL; - struct tm tm; - struct dive *dive; - - FILE *divelogfile = fopen(divelogfilename,"r"); - - dive = alloc_dive(); - - if (! matchit(divelogfile,"val key=\"date\"","\\([^<]*\\)",&found)) { - /* some error handling */ - goto bail; - } - strptime(found, "%Y-%m-%dT%H:%M:%S", &tm); - dive->when = utc_mktime(&tm); - if (! matchit(divelogfile,"", - "\\([0-9.]*\\)", &found)) { - /* some error handling */ - goto bail; - } - dive->duration.seconds = 60.0 * atof(found); - - if (! matchit(divelogfile,"", - "\\([0-9.]*\\)", &found)) { - /* some error handling */ - goto bail; - } - dive->maxdepth.mm = pressure_to_depth(atoi(found)); - - if (! matchit(divelogfile,"", - ">\\([a-zA-Z0-9+/=]*\\)<", &found)) { - /* some error handling */ - goto bail; - } - uemis_parse_divelog_binary(found,&dive); - record_dive(dive); -bail: - if (found) - free(found); -} - -/* - * parse the two files extracted from the SDA - */ -void -uemis_import() { - if (open_import_file_dialog("*.SDA","uemis Zurich SDA files", - &parse_uemis_file)) - report_dives(); -} diff --git a/uemis.h b/uemis.h index 99cf44445..e4e8532c2 100644 --- a/uemis.h +++ b/uemis.h @@ -3,12 +3,8 @@ /* * defines and prototypes for the uemis Zurich SDA file parser - * we add this to the list of dive computers that is supported - * in libdivecomputer by using a negative value for the type enum */ -#define DEVICE_TYPE_UEMIS (-1) -void uemis_import(); void uemis_parse_divelog_binary(char *base64, void *divep); #endif /* DIVE_H */ -- cgit v1.2.3-70-g09d2