X-Git-Url: http://git.tdb.fi/?a=blobdiff_plain;f=parse-xml.c;h=36db7e74453dcd8b6f1f4796daab1df6ae51c367;hb=c0a429457ab9fae5e6995777b869b111ef32be74;hp=700f0d80fd1ab355524e1afcc5f3a6b3bcf6d064;hpb=4f5e3a06ab9ea8dea656b07bff9d0f4022c5b6ba;p=ext%2Fsubsurface.git diff --git a/parse-xml.c b/parse-xml.c index 700f0d8..36db7e7 100644 --- a/parse-xml.c +++ b/parse-xml.c @@ -91,9 +91,16 @@ static int alloc_samples; static struct dive *dive; static struct sample *sample; static struct tm tm; -static int suunto, uemis; static int event_index, cylinder_index; +static enum import_source { + UNKNOWN, + LIBDIVECOMPUTER, + SUUNTO, + UEMIS, + DIVINGLOG, +} import_source; + static time_t utc_mktime(struct tm *tm) { static const int mdays[] = { @@ -467,6 +474,35 @@ static int uemis_fill_sample(struct sample *sample, const char *name, int len, c 0; } +/* + * Divinglog is crazy. The temperatures are in celsius. EXCEPT + * for the sample temperatures, that are in Fahrenheit. + * WTF? + */ +static void fahrenheit(char *buffer, void *_temperature) +{ + temperature_t *temperature = _temperature; + union int_or_float val; + + switch (integer_or_float(buffer, &val)) { + case FLOAT: + temperature->mkelvin = (val.fp + 459.67) * 5000/9; + break; + default: + fprintf(stderr, "Crazy Diving Log temperature reading %s\n", buffer); + } + free(buffer); +} + +static int divinglog_fill_sample(struct sample *sample, const char *name, int len, char *buf) +{ + return MATCH(".p.time", sampletime, &sample->time) || + MATCH(".p.depth", depth, &sample->depth) || + MATCH(".p.temp", fahrenheit, &sample->temperature) || + MATCH(".p.press1", pressure, &sample->cylinderpressure) || + 0; +} + /* We're in samples - try to convert the random xml value to something useful */ static void try_to_fill_sample(struct sample *sample, const char *name, char *buf) { @@ -488,9 +524,19 @@ static void try_to_fill_sample(struct sample *sample, const char *name, char *bu if (MATCH(".sample.time", sampletime, &sample->time)) return; - if (uemis) { + switch (import_source) { + case UEMIS: if (uemis_fill_sample(sample, name, len, buf)) return; + break; + + case DIVINGLOG: + if (divinglog_fill_sample(sample, name, len, buf)) + return; + break; + + default: + break; } nonmatch("sample", name, buf); @@ -514,6 +560,44 @@ static int suunto_dive_match(struct dive *dive, const char *name, int len, char 0; } +static const char *country, *city; + +static void divinglog_place(char *place, void *_location) +{ + char **location = _location; + char buffer[256], *p; + int len; + + len = snprintf(buffer, sizeof(buffer), + "%s%s%s%s%s", + place, + city ? ", " : "", + city ? city : "", + country ? ", " : "", + country ? country : ""); + + p = malloc(len+1); + memcpy(p, buffer, len+1); + *location = p; + + city = NULL; + country = NULL; +} + +static int divinglog_dive_match(struct dive *dive, const char *name, int len, char *buf) +{ + return MATCH(".divedate", divedate, &dive->when) || + MATCH(".entrytime", divetime, &dive->when) || + MATCH(".depth", depth, &dive->maxdepth) || + MATCH(".tanksize", cylindersize, &dive->cylinder[0].type.size) || + MATCH(".tanktype", utf8_string, &dive->cylinder[0].type.description) || + MATCH(".comments", utf8_string, &dive->notes) || + MATCH(".country.name", utf8_string, &country) || + MATCH(".city.name", utf8_string, &city) || + MATCH(".place.name", divinglog_place, &dive->location) || + 0; +} + static int buffer_value(char *buffer) { int val = atoi(buffer); @@ -564,7 +648,7 @@ static void uemis_date_time(char *buffer, void *_when) switch (integer_or_float(buffer, &val)) { case FLOAT: - *when = (val.fp - 40587.5) * 86400; + *when = (val.fp - 40587) * 86400; break; default: fprintf(stderr, "Strange julian date: %s", buffer); @@ -581,10 +665,14 @@ static void uemis_date_time(char *buffer, void *_when) */ static void uemis_time_zone(char *buffer, void *_when) { +#if 0 /* seems like this is only used to display it correctly + * the stored time appears to be UTC */ + time_t *when = _when; signed char tz = atoi(buffer); *when += tz * 3600; +#endif } /* 0 - air ; 1 - nitrox1 ; 2 - nitrox2 ; 3 = nitrox3 */ @@ -687,6 +775,27 @@ static void try_to_fill_dive(struct dive *dive, const char *name, char *buf) int len = strlen(name); start_match("dive", name, buf); + + switch (import_source) { + case SUUNTO: + if (suunto_dive_match(dive, name, len, buf)) + return; + break; + + case UEMIS: + if (uemis_dive_match(dive, name, len, buf)) + return; + break; + + case DIVINGLOG: + if (divinglog_dive_match(dive, name, len, buf)) + return; + break; + + default: + break; + } + if (MATCH(".date", divedate, &dive->when)) return; if (MATCH(".time", divetime, &dive->when)) @@ -744,13 +853,6 @@ static void try_to_fill_dive(struct dive *dive, const char *name, char *buf) if (MATCH(".he", gasmix, &dive->cylinder[cylinder_index].gasmix.he)) return; - /* Suunto XML files are some crazy sh*t. */ - if (suunto && suunto_dive_match(dive, name, len, buf)) - return; - - if (uemis && uemis_dive_match(dive, name, len, buf)) - return; - nonmatch("dive", name, buf); } @@ -898,27 +1000,6 @@ static void dive_end(void) cylinder_index = 0; } -static void suunto_start(void) -{ - suunto++; - units = SI_units; -} - -static void suunto_end(void) -{ - suunto--; -} - -static void uemis_start(void) -{ - uemis++; - units = SI_units; -} - -static void uemis_end(void) -{ -} - static void event_start(void) { } @@ -1063,6 +1144,33 @@ static void visit(xmlNode *n) traverse(n->children); } +static void suunto_importer(void) +{ + import_source = SUUNTO; + units = SI_units; +} + +static void uemis_importer(void) +{ + import_source = UEMIS; + units = SI_units; +} + +static void DivingLog_importer(void) +{ + import_source = DIVINGLOG; + + /* + * Diving Log units are really strange. + * + * Temperatures are in C, except in samples, + * when they are in Fahrenheit. Depths are in + * meters, but pressure is in PSI. + */ + units = SI_units; + units.pressure = PSI; +} + /* * I'm sure this could be done as some fancy DTD rules. * It's just not worth the headache. @@ -1072,14 +1180,20 @@ static struct nesting { void (*start)(void), (*end)(void); } nesting[] = { { "dive", dive_start, dive_end }, - { "SUUNTO", suunto_start, suunto_end }, + { "Dive", dive_start, dive_end }, { "sample", sample_start, sample_end }, { "SAMPLE", sample_start, sample_end }, { "reading", sample_start, sample_end }, { "event", event_start, event_end }, { "gasmix", cylinder_start, cylinder_end }, { "cylinder", cylinder_start, cylinder_end }, - { "pre_dive", uemis_start, uemis_end }, + { "P", sample_start, sample_end }, + + /* Import type recognition */ + { "SUUNTO", suunto_importer }, + { "Divinglog", DivingLog_importer }, + { "pre_dive", uemis_importer }, + { NULL, } }; @@ -1115,17 +1229,23 @@ static void reset_all(void) * dive for that format. */ units = SI_units; - suunto = 0; - uemis = 0; + import_source = UNKNOWN; } -void parse_xml_file(const char *filename) +void parse_xml_file(const char *filename, GError **error) { xmlDoc *doc; doc = xmlReadFile(filename, NULL, 0); if (!doc) { fprintf(stderr, "Failed to parse '%s'.\n", filename); + if (error != NULL) + { + *error = g_error_new(g_quark_from_string("divelog"), + DIVE_ERROR_PARSE, + "Failed to parse '%s'", + filename); + } return; }