Ejemplo n.º 1
0
/* 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;
}
Ejemplo n.º 2
0
/* 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;
}