]> git.tdb.fi Git - ext/subsurface.git/blobdiff - parse-xml.c
Fix up dive number naming
[ext/subsurface.git] / parse-xml.c
index d53c9b323cc6b49a7cd55d1a1565cfed3ba6ce09..b5f86fa8043c3d26c63e0d1537a3cbf809d97aab 100644 (file)
@@ -62,18 +62,8 @@ static int match(const char *pattern, int plen,
        return 1;
 }
 
-/*
- * We keep our internal data in well-specified units, but
- * the input may come in some random format. This keeps track
- * of the incoming units.
- */
-static struct units {
-       enum { METERS, FEET } length;
-       enum { LITER, CUFT } volume;
-       enum { BAR, PSI, PASCAL } pressure;
-       enum { CELSIUS, FAHRENHEIT, KELVIN } temperature;
-       enum { KG, LBS } weight;
-} units;
+
+struct units input_units;
 
 /*
  * We're going to default to SI units for input. Yes,
@@ -81,7 +71,7 @@ static struct units {
  * we default to bar (10^5 pascal), which people
  * actually use. Similarly, C instead of Kelvin.
  */
-static const struct units SI_units = {
+const struct units SI_units = {
        .length = METERS,
        .volume = LITER,
        .pressure = BAR,
@@ -89,6 +79,14 @@ static const struct units SI_units = {
        .weight = KG
 };
 
+const struct units IMPERIAL_units = {
+       .length = FEET,
+       .volume = CUFT,
+       .pressure = PSI,
+       .temperature = FAHRENHEIT,
+       .weight = LBS
+};
+
 /*
  * Dive info as it is being built up..
  */
@@ -243,7 +241,7 @@ static void pressure(char *buffer, void *_press)
                /* Just ignore zero values */
                if (!val.fp)
                        break;
-               switch (units.pressure) {
+               switch (input_units.pressure) {
                case PASCAL:
                        mbar = val.fp / 100;
                        break;
@@ -275,7 +273,7 @@ static void depth(char *buffer, void *_depth)
 
        switch (integer_or_float(buffer, &val)) {
        case FLOAT:
-               switch (units.length) {
+               switch (input_units.length) {
                case METERS:
                        depth->mm = val.fp * 1000 + 0.5;
                        break;
@@ -301,7 +299,7 @@ static void temperature(char *buffer, void *_temperature)
                if (!val.fp)
                        break;
                /* Celsius */
-               switch (units.temperature) {
+               switch (input_units.temperature) {
                case KELVIN:
                        temperature->mkelvin = val.fp * 1000;
                        break;
@@ -515,6 +513,14 @@ static int divinglog_fill_sample(struct sample *sample, const char *name, int le
                0;
 }
 
+static int uddf_fill_sample(struct sample *sample, const char *name, int len, char *buf)
+{
+       return  MATCH(".divetime", sampletime, &sample->time) ||
+               MATCH(".depth", depth, &sample->depth) ||
+               MATCH(".temperature", temperature, &sample->temperature) ||
+               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)
 {
@@ -547,6 +553,11 @@ static void try_to_fill_sample(struct sample *sample, const char *name, char *bu
                        return;
                break;
 
+       case UDDF:
+               if (uddf_fill_sample(sample, name, len, buf))
+                       return;
+               break;
+
        default:
                break;
        }
@@ -619,29 +630,29 @@ static int buffer_value(char *buffer)
 
 static void uemis_length_unit(char *buffer, void *_unused)
 {
-       units.length = buffer_value(buffer) ? FEET : METERS;
+       input_units.length = buffer_value(buffer) ? FEET : METERS;
 }
 
 static void uemis_volume_unit(char *buffer, void *_unused)
 {
-       units.volume = buffer_value(buffer) ? CUFT : LITER;
+       input_units.volume = buffer_value(buffer) ? CUFT : LITER;
 }
 
 static void uemis_pressure_unit(char *buffer, void *_unused)
 {
 #if 0
-       units.pressure = buffer_value(buffer) ? PSI : BAR;
+       input_units.pressure = buffer_value(buffer) ? PSI : BAR;
 #endif
 }
 
 static void uemis_temperature_unit(char *buffer, void *_unused)
 {
-       units.temperature = buffer_value(buffer) ? FAHRENHEIT : CELSIUS;
+       input_units.temperature = buffer_value(buffer) ? FAHRENHEIT : CELSIUS;
 }
 
 static void uemis_weight_unit(char *buffer, void *_unused)
 {
-       units.weight = buffer_value(buffer) ? LBS : KG;
+       input_units.weight = buffer_value(buffer) ? LBS : KG;
 }
 
 static void uemis_time_unit(char *buffer, void *_unused)
@@ -753,13 +764,13 @@ static void uemis_percent(char *buffer, void *_cylinder)
 
 static int uemis_dive_match(struct dive *dive, const char *name, int len, char *buf)
 {
-       return  MATCH(".units.length", uemis_length_unit, &units) ||
-               MATCH(".units.volume", uemis_volume_unit, &units) ||
-               MATCH(".units.pressure", uemis_pressure_unit, &units) ||
-               MATCH(".units.temperature", uemis_temperature_unit, &units) ||
-               MATCH(".units.weight", uemis_weight_unit, &units) ||
-               MATCH(".units.time", uemis_time_unit, &units) ||
-               MATCH(".units.date", uemis_date_unit, &units) ||
+       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) ||
+               MATCH(".units.temperature", uemis_temperature_unit, &input_units) ||
+               MATCH(".units.weight", uemis_weight_unit, &input_units) ||
+               MATCH(".units.time", uemis_time_unit, &input_units) ||
+               MATCH(".units.date", uemis_date_unit, &input_units) ||
                MATCH(".date_time", uemis_date_time, &dive->when) ||
                MATCH(".time_zone", uemis_time_zone, &dive->when) ||
                MATCH(".ambient.temperature", decicelsius, &dive->airtemp) ||
@@ -781,6 +792,58 @@ static int uemis_dive_match(struct dive *dive, const char *name, int len, char *
                0;
 }
 
+/*
+ * Uddf specifies ISO 8601 time format.
+ *
+ * There are many variations on that. This handles the useful cases.
+ */
+static void uddf_datetime(char *buffer, void *_when)
+{
+       char c;
+       int y,m,d,hh,mm,ss;
+       time_t *when = _when;
+       struct tm tm = { 0 };
+       int i;
+
+       i = sscanf(buffer, "%d-%d-%d%c%d:%d:%d", &y, &m, &d, &c, &hh, &mm, &ss);
+       if (i == 7)
+               goto success;
+       ss = 0;
+       if (i == 6)
+               goto success;
+
+       i = sscanf(buffer, "%04d%02d%02d%c%02d%02d%02d", &y, &m, &d, &c, &hh, &mm, &ss);
+       if (i == 7)
+               goto success;
+       ss = 0;
+       if (i == 6)
+               goto success;
+bad_date:
+       printf("Bad date time %s\n", buffer);
+       free(buffer);
+       return;
+
+success:
+       if (c != 'T' && c != ' ')
+               goto bad_date;
+       tm.tm_year = y;
+       tm.tm_mon = m - 1;
+       tm.tm_mday = d;
+       tm.tm_hour = hh;
+       tm.tm_min = mm;
+       tm.tm_sec = ss;
+       *when = utc_mktime(&tm);
+       free(buffer);
+}
+
+static int uddf_dive_match(struct dive *dive, const char *name, int len, char *buf)
+{
+       return  MATCH(".datetime", uddf_datetime, &dive->when) ||
+               MATCH(".diveduration", duration, &dive->duration) ||
+               MATCH(".greatestdepth", depth, &dive->maxdepth) ||
+               0;
+}
+
 /* 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)
 {
@@ -804,10 +867,17 @@ static void try_to_fill_dive(struct dive *dive, const char *name, char *buf)
                        return;
                break;
 
+       case UDDF:
+               if (uddf_dive_match(dive, name, len, buf))
+                       return;
+               break;
+
        default:
                break;
        }
 
+       if (MATCH(".number", get_index, &dive->number))
+               return;
        if (MATCH(".date", divedate, &dive->when))
                return;
        if (MATCH(".time", divetime, &dive->when))
@@ -985,11 +1055,12 @@ static void sanitize_cylinder_type(cylinder_type_t *type)
        /* Ok, we have both size and pressure: try to match a description */
        match_standard_cylinder(type);
 
-       /* .. and let's assume that the 'size' was cu ft of air */
-       volume_of_air = type->size.mliter * 28.317;     /* milli-cu ft to milliliter */
-       atm = type->workingpressure.mbar / 1013.25;     /* working pressure in atm */
-       volume = volume_of_air / atm;                   /* milliliters at 1 atm: "true size" */
-       type->size.mliter = volume + 0.5;
+       if (input_units.volume == CUFT || import_source == SUUNTO) {
+               volume_of_air = type->size.mliter * 28.317;     /* milli-cu ft to milliliter */
+               atm = type->workingpressure.mbar / 1013.25;     /* working pressure in atm */
+               volume = volume_of_air / atm;                   /* milliliters at 1 atm: "true size" */
+               type->size.mliter = volume + 0.5;
+       }
 }
 
 static void sanitize_cylinder_info(struct dive *dive)
@@ -1159,13 +1230,13 @@ static void visit(xmlNode *n)
 static void suunto_importer(void)
 {
        import_source = SUUNTO;
-       units = SI_units;
+       input_units = SI_units;
 }
 
 static void uemis_importer(void)
 {
        import_source = UEMIS;
-       units = SI_units;
+       input_units = SI_units;
 }
 
 static void DivingLog_importer(void)
@@ -1179,16 +1250,16 @@ static void DivingLog_importer(void)
         * when they are in Fahrenheit. Depths are in
         * meters, but pressure is in PSI.
         */
-       units = SI_units;
-       units.pressure = PSI;
+       input_units = SI_units;
+       input_units.pressure = PSI;
 }
 
 static void uddf_importer(void)
 {
        import_source = UDDF;
-       units = SI_units;
-       units.pressure = PASCAL;
-       units.temperature = KELVIN;
+       input_units = SI_units;
+       input_units.pressure = PASCAL;
+       input_units.temperature = KELVIN;
 }
 
 /*
@@ -1250,7 +1321,7 @@ static void reset_all(void)
         * data within one file, we might have to reset it per
         * dive for that format.
         */
-       units = SI_units;
+       input_units = SI_units;
        import_source = UNKNOWN;
 }