X-Git-Url: http://git.tdb.fi/?a=blobdiff_plain;f=parse-xml.c;h=6af4a93380ee8112fbfa9b33d234a76f75d70308;hb=1d6903c65a4980ac51a3508db6a388ab07111341;hp=64d79e02288a9e145d6bb6e6824fd47b4a2c0fcd;hpb=61f3114fce0c188b989270a33e476db52b81e810;p=ext%2Fsubsurface.git diff --git a/parse-xml.c b/parse-xml.c index 64d79e0..6af4a93 100644 --- a/parse-xml.c +++ b/parse-xml.c @@ -4,6 +4,8 @@ #include #include #include +#include +#include #define __USE_XOPEN #include #include @@ -110,7 +112,6 @@ static int cylinder_index; static enum import_source { UNKNOWN, LIBDIVECOMPUTER, - SUUNTO, UEMIS, DIVINGLOG, UDDF, @@ -644,26 +645,6 @@ static void try_to_fill_sample(struct sample *sample, const char *name, char *bu nonmatch("sample", name, buf); } -/* - * Crazy suunto xml. Look at how those o2/he things match up. - */ -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) || - MATCH(".hepct_1", percent, &dive->cylinder[1].gasmix.he) || - MATCH(".o2pct_3", percent, &dive->cylinder[2].gasmix.o2) || - MATCH(".hepct_2", percent, &dive->cylinder[2].gasmix.he) || - MATCH(".o2pct_4", percent, &dive->cylinder[3].gasmix.o2) || - MATCH(".hepct_3", percent, &dive->cylinder[3].gasmix.he) || - MATCH(".cylindersize", cylindersize, &dive->cylinder[0].type.size) || - MATCH(".cylinderworkpressure", pressure, &dive->cylinder[0].type.workingpressure) || - 0; -} - static const char *country, *city; static void divinglog_place(char *place, void *_location) @@ -978,11 +959,6 @@ static void try_to_fill_dive(struct dive **divep, const char *name, char *buf) start_match("dive", name, buf); switch (import_source) { - case SUUNTO: - if (suunto_dive_match(divep, name, len, buf)) - return; - break; - case UEMIS: if (uemis_dive_match(divep, name, len, buf)) return; @@ -1050,7 +1026,8 @@ static void try_to_fill_dive(struct dive **divep, const char *name, char *buf) return; if (MATCH(".buddy", utf8_string, &dive->buddy)) return; - + if (MATCH(".rating", get_index, &dive->rating)) + return; if (MATCH(".cylinder.size", cylindersize, &dive->cylinder[cylinder_index].type.size)) return; if (MATCH(".cylinder.workpressure", pressure, &dive->cylinder[cylinder_index].type.workingpressure)) @@ -1086,127 +1063,10 @@ static void dive_start(void) memset(&tm, 0, sizeof(tm)); } -static void sanitize_gasmix(struct gasmix *mix) -{ - unsigned int o2, he; - - o2 = mix->o2.permille; - he = mix->he.permille; - - /* Regular air: leave empty */ - if (!he) { - if (!o2) - return; - /* 20.9% or 21% O2 is just air */ - if (o2 >= 209 && o2 <= 210) { - mix->o2.permille = 0; - return; - } - } - - /* Sane mix? */ - if (o2 <= 1000 && he <= 1000 && o2+he <= 1000) - return; - fprintf(stderr, "Odd gasmix: %d O2 %d He\n", o2, he); - memset(mix, 0, sizeof(*mix)); -} - -/* - * See if the size/workingpressure looks like some standard cylinder - * size, eg "AL80". - */ -static void match_standard_cylinder(cylinder_type_t *type) -{ - double cuft; - int psi, len; - const char *fmt; - char buffer[20], *p; - - /* Do we already have a cylinder description? */ - if (type->description) - return; - - cuft = ml_to_cuft(type->size.mliter); - cuft *= to_ATM(type->workingpressure); - psi = to_PSI(type->workingpressure); - - switch (psi) { - case 2300 ... 2500: /* 2400 psi: LP tank */ - fmt = "LP%d"; - break; - case 2600 ... 2700: /* 2640 psi: LP+10% */ - fmt = "LP%d"; - break; - case 2900 ... 3100: /* 3000 psi: ALx tank */ - fmt = "AL%d"; - break; - case 3400 ... 3500: /* 3442 psi: HP tank */ - fmt = "HP%d"; - break; - case 3700 ... 3850: /* HP+10% */ - fmt = "HP%d+"; - break; - default: - return; - } - len = snprintf(buffer, sizeof(buffer), fmt, (int) (cuft+0.5)); - p = malloc(len+1); - if (!p) - return; - memcpy(p, buffer, len+1); - type->description = p; -} - - -/* - * There are two ways to give cylinder size information: - * - total amount of gas in cuft (depends on working pressure and physical size) - * - physical size - * - * where "physical size" is the one that actually matters and is sane. - * - * We internally use physical size only. But we save the workingpressure - * so that we can do the conversion if required. - */ -static void sanitize_cylinder_type(cylinder_type_t *type) -{ - double volume_of_air, atm, volume; - - /* If we have no working pressure, it had *better* be just a physical size! */ - if (!type->workingpressure.mbar) - return; - - /* No size either? Nothing to go on */ - if (!type->size.mliter) - return; - - if (input_units.volume == CUFT || import_source == SUUNTO) { - /* confusing - we don't really start from ml but millicuft !*/ - volume_of_air = cuft_to_l(type->size.mliter); - atm = to_ATM(type->workingpressure); /* working pressure in atm */ - volume = volume_of_air / atm; /* milliliters at 1 atm: "true size" */ - type->size.mliter = volume + 0.5; - } - - /* Ok, we have both size and pressure: try to match a description */ - match_standard_cylinder(type); -} - -static void sanitize_cylinder_info(struct dive *dive) -{ - int i; - - for (i = 0; i < MAX_CYLINDERS; i++) { - sanitize_gasmix(&dive->cylinder[i].gasmix); - sanitize_cylinder_type(&dive->cylinder[i].type); - } -} - static void dive_end(void) { if (!dive) return; - sanitize_cylinder_info(dive); record_dive(dive); dive = NULL; cylinder_index = 0; @@ -1244,7 +1104,7 @@ static void sample_end(void) if (!dive) return; - finish_sample(dive, sample); + finish_sample(dive); sample = NULL; } @@ -1348,12 +1208,6 @@ static void visit(xmlNode *n) traverse(n->children); } -static void suunto_importer(void) -{ - import_source = SUUNTO; - input_units = SI_units; -} - static void uemis_importer(void) { import_source = UEMIS; @@ -1405,7 +1259,6 @@ static struct nesting { { "P", sample_start, sample_end }, /* Import type recognition */ - { "SUUNTO", suunto_importer }, { "Divinglog", DivingLog_importer }, { "pre_dive", uemis_importer }, { "dives", uemis_importer }, @@ -1449,11 +1302,70 @@ static void reset_all(void) import_source = UNKNOWN; } +struct memblock { + void *buffer; + size_t size; +}; + +static int readfile(const char *filename, struct memblock *mem) +{ + int ret, fd = open(filename, O_RDONLY); + struct stat st; + + mem->buffer = NULL; + mem->size = 0; + + fd = open(filename, O_RDONLY); + if (fd < 0) + return fd; + ret = fstat(fd, &st); + if (ret < 0) + goto out; + ret = -EINVAL; + if (!S_ISREG(st.st_mode)) + goto out; + ret = 0; + if (!st.st_size) + goto out; + mem->buffer = malloc(st.st_size); + ret = -1; + errno = ENOMEM; + if (!mem->buffer) + goto out; + mem->size = st.st_size; + ret = read(fd, mem->buffer, mem->size); + if (ret < 0) + goto free; + if (ret == mem->size) + goto out; + errno = EIO; + ret = -1; +free: + free(mem->buffer); + mem->buffer = NULL; + mem->size = 0; +out: + close(fd); + return ret; +} + void parse_xml_file(const char *filename, GError **error) { xmlDoc *doc; + struct memblock mem; + + if (readfile(filename, &mem) < 0) { + fprintf(stderr, "Failed to read '%s'.\n", filename); + if (error) { + *error = g_error_new(g_quark_from_string("subsurface"), + DIVE_ERROR_PARSE, + "Failed to read '%s'", + filename); + } + return; + } - doc = xmlReadFile(filename, NULL, 0); + doc = xmlReadMemory(mem.buffer, mem.size, filename, NULL, 0); if (!doc) { fprintf(stderr, "Failed to parse '%s'.\n", filename); if (error != NULL)