11 /* Crazy windows sh*t */
16 static int readfile(const char *filename, struct memblock *mem)
25 fd = open(filename, O_RDONLY | O_BINARY);
32 if (!S_ISREG(st.st_mode))
37 buf = malloc(st.st_size+1);
43 mem->size = st.st_size;
44 ret = read(fd, buf, mem->size);
64 static void suunto_read(struct zip_file *file, GError **error)
66 int size = 1024, n, read = 0;
67 char *mem = malloc(size);
69 while ((n = zip_fread(file, mem+read, size-read)) > 0) {
72 mem = realloc(mem, size);
74 parse_xml_buffer("SDE file", mem, read, error);
79 static int try_to_open_suunto(const char *filename, struct memblock *mem, GError **error)
83 /* Grr. libzip needs to re-open the file, it can't take a buffer */
84 struct zip *zip = zip_open(filename, ZIP_CHECKCONS, NULL);
88 for (index = 0; ;index++) {
89 struct zip_file *file = zip_fopen_index(zip, index, 0);
92 suunto_read(file, error);
102 static time_t parse_date(const char *date)
108 memset(&tm, 0, sizeof(tm));
109 tm.tm_mday = strtol(date, &p, 10);
110 if (tm.tm_mday < 1 || tm.tm_mday > 31)
112 for (tm.tm_mon = 0; tm.tm_mon < 12; tm.tm_mon++) {
113 if (!memcmp(p, monthname(tm.tm_mon), 3))
119 tm.tm_year = strtol(date, &p, 10);
124 if (tm.tm_year < 100)
126 if (sscanf(p, "%d:%d:%d", &hour, &min, &sec) != 3)
131 return utc_mktime(&tm);
135 CSV_DEPTH, CSV_TEMP, CSV_PRESSURE
138 static void add_sample_data(struct sample *sample, enum csv_format type, double val)
142 sample->depth.mm = feet_to_mm(val);
145 sample->temperature.mkelvin = F_to_mkelvin(val);
148 sample->cylinderpressure.mbar = psi_to_mbar(val*4);
154 * Cochran comma-separated values: depth in feet, temperature in F, pressure in psi.
156 * They start with eight comma-separated fields like:
158 * filename: {C:\Analyst4\can\T036785.can},{C:\Analyst4\can\K031892.can}
160 * datetime: {03Sep11 16:37:22},{15Dec11 18:27:02}
162 * serialnr??: {CCI134},{CCI207}
163 * computer??: {GeminiII},{CommanderIII}
164 * computer??: {GeminiII},{CommanderIII}
167 * Followed by the data values (all comma-separated, all one long line).
169 static int try_to_open_csv(const char *filename, struct memblock *mem, enum csv_format type)
171 char *p = mem->buffer;
177 for (i = 0; i < 8; i++) {
185 date = parse_date(header[2]);
191 dive->number = atoi(header[1]);
197 struct sample *sample;
200 val = strtod(p,&end);
206 sample = prepare_sample(&dive);
207 sample->time.seconds = time;
208 add_sample_data(sample, type, val);
212 dive->duration.seconds = time;
221 static int open_by_filename(const char *filename, const char *fmt, struct memblock *mem, GError **error)
223 /* Suunto Dive Manager files: SDE */
224 if (!strcasecmp(fmt, "SDE"))
225 return try_to_open_suunto(filename, mem, error);
227 /* Truly nasty intentionally obfuscated Cochran Anal software */
228 if (!strcasecmp(fmt, "CAN"))
229 return try_to_open_cochran(filename, mem, error);
231 /* Cochran export comma-separated-value files */
232 if (!strcasecmp(fmt, "DPT"))
233 return try_to_open_csv(filename, mem, CSV_DEPTH);
234 if (!strcasecmp(fmt, "TMP"))
235 return try_to_open_csv(filename, mem, CSV_TEMP);
236 if (!strcasecmp(fmt, "HP1"))
237 return try_to_open_csv(filename, mem, CSV_PRESSURE);
242 static void parse_file_buffer(const char *filename, struct memblock *mem, GError **error)
244 char *fmt = strrchr(filename, '.');
245 if (fmt && open_by_filename(filename, fmt+1, mem, error))
248 parse_xml_buffer(filename, mem->buffer, mem->size, error);
251 void parse_file(const char *filename, GError **error)
255 if (readfile(filename, &mem) < 0) {
256 fprintf(stderr, "Failed to read '%s'.\n", filename);
258 *error = g_error_new(g_quark_from_string("subsurface"),
260 "Failed to read '%s'",
266 parse_file_buffer(filename, &mem, error);