+static void get_index(char *buffer, void *_i)
+{
+ int *i = _i;
+ *i = atoi(buffer);
+ free(buffer);
+}
+
+static void centibar(char *buffer, void *_pressure)
+{
+ pressure_t *pressure = _pressure;
+ union int_or_float val;
+
+ switch (integer_or_float(buffer, &val)) {
+ case FLOAT:
+ pressure->mbar = val.fp * 10 + 0.5;
+ break;
+ default:
+ fprintf(stderr, "Strange centibar pressure '%s'\n", buffer);
+ }
+ free(buffer);
+}
+
+static void decicelsius(char *buffer, void *_temp)
+{
+ temperature_t *temp = _temp;
+ union int_or_float val;
+
+ switch (integer_or_float(buffer, &val)) {
+ case FLOAT:
+ temp->mkelvin = (val.fp/10 + 273.15) * 1000 + 0.5;
+ break;
+ default:
+ fprintf(stderr, "Strange julian date: %s", buffer);
+ }
+ free(buffer);
+}
+
+static int uemis_fill_sample(struct sample *sample, const char *name, int len, char *buf)
+{
+ return MATCH(".reading.dive_time", sampletime, &sample->time) ||
+ MATCH(".reading.water_pressure", water_pressure, &sample->depth) ||
+ MATCH(".reading.active_tank", get_index, &sample->cylinderindex) ||
+ MATCH(".reading.tank_pressure", centibar, &sample->cylinderpressure) ||
+ MATCH(".reading.dive_temperature", decicelsius, &sample->temperature) ||
+ 0;
+}
+
+/*
+ * Divinglog is crazy. The temperatures are in celsius. EXCEPT
+ * for the sample temperatures, that are in Fahrenheit.
+ * WTF?
+ *
+ * Oh, and I think Diving Log *internally* probably kept them
+ * in celsius, because I'm seeing entries like
+ *
+ * <Temp>32.0</Temp>
+ *
+ * in there. Which is freezing, aka 0 degC. I bet the "0" is
+ * what Diving Log uses for "no temperature".
+ *
+ * So throw away crap like that.
+ */
+static void fahrenheit(char *buffer, void *_temperature)
+{
+ temperature_t *temperature = _temperature;
+ union int_or_float val;
+
+ switch (integer_or_float(buffer, &val)) {
+ case FLOAT:
+ /* Floating point equality is evil, but works for small integers */
+ if (val.fp == 32.0)
+ break;
+ temperature->mkelvin = (val.fp + 459.67) * 5000/9;
+ break;
+ default:
+ fprintf(stderr, "Crazy Diving Log temperature reading %s\n", buffer);
+ }
+ free(buffer);
+}
+
+/*
+ * Did I mention how bat-shit crazy divinglog is? The sample
+ * pressures are in PSI. But the tank working pressure is in
+ * bar. WTF^2?
+ *
+ * Crazy stuff like this is why subsurface has everything in
+ * these inconvenient typed structures, and you have to say
+ * "pressure->mbar" to get the actual value. Exactly so that
+ * you can never have unit confusion.
+ */
+static void psi(char *buffer, void *_pressure)
+{
+ pressure_t *pressure = _pressure;
+ union int_or_float val;
+
+ switch (integer_or_float(buffer, &val)) {
+ case FLOAT:
+ pressure->mbar = val.fp * 68.95 + 0.5;
+ break;
+ default:
+ fprintf(stderr, "Crazy Diving Log PSI 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", psi, &sample->cylinderpressure) ||
+ 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;
+}
+
+static void eventtime(char *buffer, void *_duration)
+{
+ duration_t *duration = _duration;
+ sampletime(buffer, duration);
+ if (cur_sample)
+ duration->seconds += cur_sample->time.seconds;
+}
+
+static void try_to_fill_event(const char *name, char *buf)
+{
+ int len = strlen(name);
+
+ start_match("event", name, buf);
+ if (MATCH(".event", utf8_string, &cur_event.name))
+ return;
+ if (MATCH(".name", utf8_string, &cur_event.name))
+ return;
+ if (MATCH(".time", eventtime, &cur_event.time))
+ return;
+ if (MATCH(".type", get_index, &cur_event.type))
+ return;
+ if (MATCH(".flags", get_index, &cur_event.flags))
+ return;
+ if (MATCH(".value", get_index, &cur_event.value))
+ return;
+ nonmatch("event", name, buf);
+}
+