From 8b64ce0edccae9099480a190e8daeb199db424d4 Mon Sep 17 00:00:00 2001 From: Jef Driesen Date: Sat, 7 Mar 2015 11:50:24 +0100 Subject: [PATCH] Cache the parser data internally. --- src/uwatec_smart_parser.c | 125 +++++++++++++++++++++++++------------- 1 file changed, 84 insertions(+), 41 deletions(-) diff --git a/src/uwatec_smart_parser.c b/src/uwatec_smart_parser.c index 8a40b4b..ef0e682 100644 --- a/src/uwatec_smart_parser.c +++ b/src/uwatec_smart_parser.c @@ -49,6 +49,8 @@ #define UNSUPPORTED 0xFFFFFFFF +#define NGASMIXES 3 + typedef enum { PRESSURE_DEPTH, RBT, @@ -93,6 +95,11 @@ struct uwatec_smart_parser_t { const uwatec_smart_header_info_t *header; unsigned int headersize; unsigned int nsamples; + // Cached fields. + unsigned int cached; + unsigned int trimix; + unsigned int ngasmixes; + unsigned int oxygen[NGASMIXES]; }; static dc_status_t uwatec_smart_parser_set_data (dc_parser_t *abstract, const unsigned char *data, unsigned int size); @@ -254,6 +261,45 @@ uwatec_smart_sample_info_t uwatec_smart_tec_samples[] = { }; +static dc_status_t +uwatec_smart_parser_cache (uwatec_smart_parser_t *parser) +{ + const unsigned char *data = parser->base.data; + unsigned int size = parser->base.size; + + if (parser->cached) { + return DC_STATUS_SUCCESS; + } + + unsigned int trimix = 0; + if (parser->model == GALILEO || parser->model == GALILEOTRIMIX) { + if (size < 44) + return DC_STATUS_DATAFORMAT; + + if (data[43] & 0x80) { + trimix = 1; + } + } + + // Get the gas mixes. + unsigned int oxygen[NGASMIXES] = {0}; + unsigned int ngasmixes = (trimix ? 0 : parser->header->ngases); + for (unsigned int i = 0; i < ngasmixes; ++i) { + oxygen[i] = data[parser->header->gasmix + i * 2]; + } + + // Cache the data for later use. + parser->trimix = trimix; + parser->ngasmixes = ngasmixes; + for (unsigned int i = 0; i < ngasmixes; ++i) { + parser->oxygen[i] = oxygen[i]; + } + parser->cached = 1; + + return DC_STATUS_SUCCESS; +} + + dc_status_t uwatec_smart_parser_create (dc_parser_t **out, dc_context_t *context, unsigned int model, unsigned int devtime, dc_ticks_t systime) { @@ -321,6 +367,13 @@ uwatec_smart_parser_create (dc_parser_t **out, dc_context_t *context, unsigned i return DC_STATUS_INVALIDARGS; } + parser->cached = 0; + parser->trimix = 0; + parser->ngasmixes = 0; + for (unsigned int i = 0; i < NGASMIXES; ++i) { + parser->oxygen[i] = 0; + } + *out = (dc_parser_t*) parser; return DC_STATUS_SUCCESS; @@ -340,6 +393,16 @@ uwatec_smart_parser_destroy (dc_parser_t *abstract) static dc_status_t uwatec_smart_parser_set_data (dc_parser_t *abstract, const unsigned char *data, unsigned int size) { + uwatec_smart_parser_t *parser = (uwatec_smart_parser_t *) abstract; + + // Reset the cache. + parser->cached = 0; + parser->trimix = 0; + parser->ngasmixes = 0; + for (unsigned int i = 0; i < NGASMIXES; ++i) { + parser->oxygen[i] = 0; + } + return DC_STATUS_SUCCESS; } @@ -369,24 +432,12 @@ uwatec_smart_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsi uwatec_smart_parser_t *parser = (uwatec_smart_parser_t *) abstract; const unsigned char *data = abstract->data; - unsigned int size = abstract->size; - const uwatec_smart_header_info_t *table = parser->header; - unsigned int header = parser->headersize; - unsigned int trimix = 0; - if (parser->model == GALILEO || parser->model == GALILEOTRIMIX) { - if (size < 44) - return DC_STATUS_DATAFORMAT; - - if (data[43] & 0x80) { - header = 0xB1; - trimix = 1; - } - } - - if (size < header) - return DC_STATUS_DATAFORMAT; + // Cache the parser data. + dc_status_t rc = uwatec_smart_parser_cache (parser); + if (rc != DC_STATUS_SUCCESS) + return rc; dc_gasmix_t *gasmix = (dc_gasmix_t *) value; @@ -399,15 +450,15 @@ uwatec_smart_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsi *((double *) value) = array_uint16_le (data + table->maxdepth) / 100.0; break; case DC_FIELD_GASMIX_COUNT: - if (trimix) + if (parser->trimix) return DC_STATUS_UNSUPPORTED; - *((unsigned int *) value) = table->ngases; + *((unsigned int *) value) = parser->ngasmixes; break; case DC_FIELD_GASMIX: - if (trimix) + if (parser->trimix) return DC_STATUS_UNSUPPORTED; gasmix->helium = 0.0; - gasmix->oxygen = data[table->gasmix + flags * 2] / 100.0; + gasmix->oxygen = parser->oxygen[flags] / 100.0; gasmix->nitrogen = 1.0 - gasmix->oxygen - gasmix->helium; break; case DC_FIELD_TEMPERATURE_MINIMUM: @@ -497,19 +548,16 @@ uwatec_smart_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t const unsigned char *data = abstract->data; unsigned int size = abstract->size; + // Cache the parser data. + dc_status_t rc = uwatec_smart_parser_cache (parser); + if (rc != DC_STATUS_SUCCESS) + return rc; + const uwatec_smart_sample_info_t *table = parser->samples; unsigned int entries = parser->nsamples; unsigned int header = parser->headersize; - unsigned int trimix = 0; - - if (parser->model == GALILEO || parser->model == GALILEOTRIMIX) { - if (size < 44) - return DC_STATUS_DATAFORMAT; - - if (data[43] & 0x80) { - header = 0xB1; - trimix = 1; - } + if (parser->trimix) { + header = 0xB1; } // Get the maximum number of alarm bytes. @@ -522,13 +570,6 @@ uwatec_smart_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t } } - // Get all the gas mixes. - unsigned int oxygen[3] = {0}; - unsigned int ngasmix = (trimix ? 0 : parser->header->ngases); - for (unsigned int i = 0; i < ngasmix; ++i) { - oxygen[i] = data[parser->header->gasmix + i * 2]; - } - int complete = 0; int calibrated = 0; @@ -630,7 +671,7 @@ uwatec_smart_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t break; case PRESSURE: if (table[id].absolute) { - if (trimix) { + if (parser->trimix) { tank = (value & 0xF000) >> 24; pressure = (value & 0x0FFF) / 4.0; } else { @@ -705,13 +746,15 @@ uwatec_smart_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t sample.time = time; if (callback) callback (DC_SAMPLE_TIME, sample, userdata); - if (ngasmix && gasmix != gasmix_previous) { - if (gasmix >= ngasmix) + if (parser->ngasmixes && gasmix != gasmix_previous) { + if (gasmix >= parser->ngasmixes) { + ERROR (abstract->context, "Invalid gas mix index."); return DC_STATUS_DATAFORMAT; + } sample.event.type = SAMPLE_EVENT_GASCHANGE; sample.event.time = 0; sample.event.flags = 0; - sample.event.value = oxygen[gasmix]; + sample.event.value = parser->oxygen[gasmix]; if (callback) callback (DC_SAMPLE_EVENT, sample, userdata); gasmix_previous = gasmix; }