/* This function is called for both divelog and dive information that we get * from the SDA (what an insane design, btw). The object_id in the divelog * matches the logfilenr in the dive information (which has its own, often * different object_id) - we use this as the diveid. * We create the dive when parsing the divelog and then later, when we parse * the dive information we locate the already created dive via its diveid. * Most things just get parsed and converted into our internal data structures, * but the dive location API is even more crazy. We just get an id that is an * index into yet another data store that we read out later. In order to * correctly populate the location and gps data from that we need to remember * the adresses of those fields for every dive that references the divespot. */ static bool process_raw_buffer(uint32_t deviceid, char *inbuf, char **max_divenr, bool keep_number, int *for_dive) { char *buf = strdup(inbuf); char *tp, *bp, *tag, *type, *val; bool done = false; int inbuflen = strlen(inbuf); char *endptr = buf + inbuflen; bool log = false; char *sections[10]; int s, nr_sections = 0; struct dive *dive = NULL; #if UEMIS_DEBUG & 4 fprintf(debugfile, "p_r_b %s\n", inbuf); #endif if (for_dive) *for_dive = -1; bp = buf + 1; tp = next_token(&bp); if (strcmp(tp, "divelog") == 0) { /* this is a divelog */ log = true; tp = next_token(&bp); /* is it a valid entry or nothing ? */ if (strcmp(tp, "1.0") != 0 || strstr(inbuf, "divelog{1.0{{{{")) { free(buf); return false; } } else if (strcmp(tp, "dive") == 0) { /* this is dive detail */ tp = next_token(&bp); if (strcmp(tp, "1.0") != 0) { free(buf); return false; } } else { /* don't understand the buffer */ free(buf); return false; } if (log) { dive = uemis_start_dive(deviceid); } else { /* remember, we don't know if this is the right entry, * so first test if this is even a valid entry */ if (strstr(inbuf, "deleted{bool{true")) { #if UEMIS_DEBUG & 4 fprintf(debugfile, "p_r_b entry deleted\n"); #endif /* oops, this one isn't valid, suggest to try the previous one */ return false; } } while (!done) { /* the valid buffer ends with a series of delimiters */ if (bp >= endptr - 2 || !strcmp(bp, "{{")) break; tag = next_token(&bp); /* we also end if we get an empty tag */ if (*tag == '\0') break; for (s = 0; s < nr_sections; s++) if (!strcmp(tag, sections[s])) { tag = next_token(&bp); break; } type = next_token(&bp); if (!strcmp(type, "1.0")) { /* this tells us the sections that will follow; the tag here * is of the format dive-<section> */ sections[nr_sections] = strchr(tag, '-') + 1; #if UEMIS_DEBUG & 4 fprintf(debugfile, "Expect to find section %s\n", sections[nr_sections]); #endif if (nr_sections < sizeof(sections) - 1) nr_sections++; continue; } val = next_token(&bp); if (log && !strcmp(tag, "object_id")) { free(*max_divenr); *max_divenr = strdup(val); dive->dc.diveid = atoi(val); if (keep_number) dive->number = atoi(val); } else if (!log && !strcmp(tag, "logfilenr")) { /* this one tells us which dive we are adding data to */ dive = get_dive_by_uemis_diveid(atoi(val), deviceid); if (for_dive) *for_dive = atoi(val); } else if (!log && dive && !strcmp(tag, "divespot_id")) { track_divespot(val, dive->dc.diveid, &dive->location, &dive->latitude, &dive->longitude); } else if (dive) { parse_tag(dive, tag, val); } if (log && !strcmp(tag, "file_content")) done = true; /* done with one dive (got the file_content tag), but there could be more: * a '{' indicates the end of the record - but we need to see another "{{" * later in the buffer to know that the next record is complete (it could * be a short read because of some error */ if (done && ++bp < endptr && *bp != '{' && strstr(bp, "{{")) { done = false; record_dive(dive); mark_divelist_changed(true); dive = uemis_start_dive(deviceid); } } if (log) { if (dive->dc.diveid) { record_dive(dive); mark_divelist_changed(true); } else { /* partial dive */ free(dive); free(buf); return false; } } free(buf); return true; }
/* This function is called for both divelog and dive information that we get * from the SDA (what an insane design, btw). The object_id in the divelog * matches the logfilenr in the dive information (which has its own, often * different object_id) - we use this as the diveid. * We create the dive when parsing the divelog and then later, when we parse * the dive information we locate the already created dive via its diveid. * Most things just get parsed and converted into our internal data structures, * but the dive location API is even more crazy. We just get an id that is an * index into yet another data store that we read out later. In order to * correctly populate the location and gps data from that we need to remember * the adresses of those fields for every dive that references the divespot. */ static bool process_raw_buffer(device_data_t *devdata, uint32_t deviceid, char *inbuf, char **max_divenr, bool keep_number, int *for_dive) { char *buf = strdup(inbuf); char *tp, *bp, *tag, *type, *val; bool done = false; int inbuflen = strlen(inbuf); char *endptr = buf + inbuflen; bool is_log = false, is_dive = false; char *sections[10]; int s, nr_sections = 0; struct dive *dive = NULL; char dive_no[10]; #if UEMIS_DEBUG & 8 fprintf(debugfile, "p_r_b %s\n", inbuf); #endif if (for_dive) *for_dive = -1; bp = buf + 1; tp = next_token(&bp); if (strcmp(tp, "divelog") == 0) { /* this is a divelog */ is_log = true; tp = next_token(&bp); /* is it a valid entry or nothing ? */ if (strcmp(tp, "1.0") != 0 || strstr(inbuf, "divelog{1.0{{{{")) { free(buf); return false; } } else if (strcmp(tp, "dive") == 0) { /* this is dive detail */ is_dive = true; tp = next_token(&bp); if (strcmp(tp, "1.0") != 0) { free(buf); return false; } } else { /* don't understand the buffer */ free(buf); return false; } if (is_log) { dive = uemis_start_dive(deviceid); } else { /* remember, we don't know if this is the right entry, * so first test if this is even a valid entry */ if (strstr(inbuf, "deleted{bool{true")) { #if UEMIS_DEBUG & 2 fprintf(debugfile, "p_r_b entry deleted\n"); #endif /* oops, this one isn't valid, suggest to try the previous one */ free(buf); return false; } /* quickhack and workaround to capture the original dive_no * i am doing this so I dont have to change the original design * but when parsing a dive we never parse the dive number because * at the time it's being read the *dive varible is not set because * the dive_no tag comes before the object_id in the uemis ans file */ dive_no[0] = '\0'; char *dive_no_buf = strdup(inbuf); char *dive_no_ptr = strstr(dive_no_buf, "dive_no{int{") + 12; if (dive_no_ptr) { char *dive_no_end = strstr(dive_no_ptr, "{"); if (dive_no_end) { *dive_no_end = '\0'; strncpy(dive_no, dive_no_ptr, 9); dive_no[9] = '\0'; } } free(dive_no_buf); } while (!done) { /* the valid buffer ends with a series of delimiters */ if (bp >= endptr - 2 || !strcmp(bp, "{{")) break; tag = next_token(&bp); /* we also end if we get an empty tag */ if (*tag == '\0') break; for (s = 0; s < nr_sections; s++) if (!strcmp(tag, sections[s])) { tag = next_token(&bp); break; } type = next_token(&bp); if (!strcmp(type, "1.0")) { /* this tells us the sections that will follow; the tag here * is of the format dive-<section> */ sections[nr_sections] = strchr(tag, '-') + 1; #if UEMIS_DEBUG & 4 fprintf(debugfile, "Expect to find section %s\n", sections[nr_sections]); #endif if (nr_sections < sizeof(sections) - 1) nr_sections++; continue; } val = next_token(&bp); #if UEMIS_DEBUG & 8 if (strlen(val) < 20) fprintf(debugfile, "Parsed %s, %s, %s\n*************************\n", tag, type, val); #endif if (is_log && strcmp(tag, "object_id") == 0) { free(*max_divenr); *max_divenr = strdup(val); dive->dc.diveid = atoi(val); #if UEMIS_DEBUG % 2 fprintf(debugfile, "Adding new dive from log with object_id %d.\n", atoi(val)); #endif } else if (is_dive && strcmp(tag, "logfilenr") == 0) { /* this one tells us which dive we are adding data to */ dive = get_dive_by_uemis_diveid(devdata, atoi(val)); if (strcmp(dive_no, "0")) dive->number = atoi(dive_no); if (for_dive) *for_dive = atoi(val); } else if (!is_log && dive && !strcmp(tag, "divespot_id")) { int divespot_id = atoi(val); if (divespot_id != -1) { dive->dive_site_uuid = create_dive_site("from Uemis", dive->when); uemis_mark_divelocation(dive->dc.diveid, divespot_id, dive->dive_site_uuid); } #if UEMIS_DEBUG & 2 fprintf(debugfile, "Created divesite %d for diveid : %d\n", dive->dive_site_uuid, dive->dc.diveid); #endif } else if (dive) { parse_tag(dive, tag, val); } if (is_log && !strcmp(tag, "file_content")) done = true; /* done with one dive (got the file_content tag), but there could be more: * a '{' indicates the end of the record - but we need to see another "{{" * later in the buffer to know that the next record is complete (it could * be a short read because of some error */ if (done && ++bp < endptr && *bp != '{' && strstr(bp, "{{")) { done = false; record_uemis_dive(devdata, dive); mark_divelist_changed(true); dive = uemis_start_dive(deviceid); } } if (is_log) { if (dive->dc.diveid) { record_uemis_dive(devdata, dive); mark_divelist_changed(true); } else { /* partial dive */ free(dive); free(buf); return false; } } free(buf); return true; }