11 static int readfile(const char *filename, struct memblock *mem)
20 fd = open(filename, O_RDONLY);
27 if (!S_ISREG(st.st_mode))
32 buf = malloc(st.st_size+1);
38 mem->size = st.st_size;
39 ret = read(fd, buf, mem->size);
59 static void suunto_read(struct zip_file *file, GError **error)
61 int size = 1024, n, read = 0;
62 char *mem = malloc(size);
64 while ((n = zip_fread(file, mem+read, size-read)) > 0) {
67 mem = realloc(mem, size);
69 parse_xml_buffer("SDE file", mem, read, error);
74 static int try_to_open_suunto(const char *filename, struct memblock *mem, GError **error)
78 /* Grr. libzip needs to re-open the file, it can't take a buffer */
79 struct zip *zip = zip_open(filename, ZIP_CHECKCONS, NULL);
83 for (index = 0; ;index++) {
84 struct zip_file *file = zip_fopen_index(zip, index, 0);
87 suunto_read(file, error);
97 static time_t parse_date(const char *date)
103 memset(&tm, 0, sizeof(tm));
104 tm.tm_mday = strtol(date, &p, 10);
105 if (tm.tm_mday < 1 || tm.tm_mday > 31)
107 for (tm.tm_mon = 0; tm.tm_mon < 12; tm.tm_mon++) {
108 if (!memcmp(p, monthname(tm.tm_mon), 3))
114 tm.tm_year = strtol(date, &p, 10);
119 if (tm.tm_year < 100)
121 if (sscanf(p, "%d:%d:%d", &hour, &min, &sec) != 3)
126 return utc_mktime(&tm);
130 CSV_DEPTH, CSV_TEMP, CSV_PRESSURE
133 static void add_sample_data(struct sample *sample, enum csv_format type, double val)
137 sample->depth.mm = feet_to_mm(val);
140 sample->temperature.mkelvin = F_to_mkelvin(val);
143 sample->cylinderpressure.mbar = psi_to_mbar(val*4);
149 * Cochran comma-separated values: depth in feet, temperature in F, pressure in psi.
151 * They start with eight comma-separated fields like:
153 * filename: {C:\Analyst4\can\T036785.can},{C:\Analyst4\can\K031892.can}
155 * datetime: {03Sep11 16:37:22},{15Dec11 18:27:02}
157 * serialnr??: {CCI134},{CCI207}
158 * computer??: {GeminiII},{CommanderIII}
159 * computer??: {GeminiII},{CommanderIII}
162 * Followed by the data values (all comma-separated, all one long line).
164 static int try_to_open_csv(const char *filename, struct memblock *mem, enum csv_format type)
166 char *p = mem->buffer;
172 for (i = 0; i < 8; i++) {
180 date = parse_date(header[2]);
186 dive->number = atoi(header[1]);
192 struct sample *sample;
195 val = strtod(p,&end);
201 sample = prepare_sample(&dive);
202 sample->time.seconds = time;
203 add_sample_data(sample, type, val);
207 dive->duration.seconds = time;
216 static int open_by_filename(const char *filename, const char *fmt, struct memblock *mem, GError **error)
218 /* Suunto Dive Manager files: SDE */
219 if (!strcasecmp(fmt, "SDE"))
220 return try_to_open_suunto(filename, mem, error);
222 /* Truly nasty intentionally obfuscated Cochran Anal software */
223 if (!strcasecmp(fmt, "CAN"))
224 return try_to_open_cochran(filename, mem, error);
226 /* Cochran export comma-separated-value files */
227 if (!strcasecmp(fmt, "DPT"))
228 return try_to_open_csv(filename, mem, CSV_DEPTH);
229 if (!strcasecmp(fmt, "TMP"))
230 return try_to_open_csv(filename, mem, CSV_TEMP);
231 if (!strcasecmp(fmt, "HP1"))
232 return try_to_open_csv(filename, mem, CSV_PRESSURE);
237 static void parse_file_buffer(const char *filename, struct memblock *mem, GError **error)
239 char *fmt = strrchr(filename, '.');
240 if (fmt && open_by_filename(filename, fmt+1, mem, error))
243 parse_xml_buffer(filename, mem->buffer, mem->size, error);
246 void parse_file(const char *filename, GError **error)
250 if (readfile(filename, &mem) < 0) {
251 fprintf(stderr, "Failed to read '%s'.\n", filename);
253 *error = g_error_new(g_quark_from_string("subsurface"),
255 "Failed to read '%s'",
261 parse_file_buffer(filename, &mem, error);