Cache the parser data internally.
The code to find the offset to the footer and parse the gas mix data is duplicated in multiple places. Move this code to a single place, and cache the data in the parser instead.
This commit is contained in:
parent
c2f86a7806
commit
4f2d71ce49
@ -32,11 +32,19 @@
|
|||||||
#define ICONHD 0x14
|
#define ICONHD 0x14
|
||||||
#define ICONHDNET 0x15
|
#define ICONHDNET 0x15
|
||||||
|
|
||||||
|
#define NGASMIXES 3
|
||||||
|
|
||||||
typedef struct mares_iconhd_parser_t mares_iconhd_parser_t;
|
typedef struct mares_iconhd_parser_t mares_iconhd_parser_t;
|
||||||
|
|
||||||
struct mares_iconhd_parser_t {
|
struct mares_iconhd_parser_t {
|
||||||
dc_parser_t base;
|
dc_parser_t base;
|
||||||
unsigned int model;
|
unsigned int model;
|
||||||
|
// Cached fields.
|
||||||
|
unsigned int cached;
|
||||||
|
unsigned int footer;
|
||||||
|
unsigned int samplesize;
|
||||||
|
unsigned int ngasmixes;
|
||||||
|
unsigned int oxygen[NGASMIXES];
|
||||||
};
|
};
|
||||||
|
|
||||||
static dc_status_t mares_iconhd_parser_set_data (dc_parser_t *abstract, const unsigned char *data, unsigned int size);
|
static dc_status_t mares_iconhd_parser_set_data (dc_parser_t *abstract, const unsigned char *data, unsigned int size);
|
||||||
@ -54,25 +62,63 @@ static const dc_parser_vtable_t mares_iconhd_parser_vtable = {
|
|||||||
mares_iconhd_parser_destroy /* destroy */
|
mares_iconhd_parser_destroy /* destroy */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static dc_status_t
|
||||||
/* Find how many gas mixes are in use */
|
mares_iconhd_parser_cache (mares_iconhd_parser_t *parser)
|
||||||
static unsigned int
|
|
||||||
mares_iconhd_parser_count_active_gas_mixes (const unsigned char *p, unsigned int air)
|
|
||||||
{
|
{
|
||||||
|
const unsigned char *data = parser->base.data;
|
||||||
|
unsigned int size = parser->base.size;
|
||||||
|
|
||||||
|
if (parser->cached) {
|
||||||
|
return DC_STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int footersize = 0x5C;
|
||||||
|
unsigned int samplesize = 8;
|
||||||
|
if (parser->model == ICONHDNET) {
|
||||||
|
footersize = 0x80;
|
||||||
|
samplesize = 12;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (size < 4)
|
||||||
|
return DC_STATUS_DATAFORMAT;
|
||||||
|
|
||||||
|
unsigned int length = array_uint32_le (data);
|
||||||
|
|
||||||
|
if (size < length || length < footersize + 4)
|
||||||
|
return DC_STATUS_DATAFORMAT;
|
||||||
|
|
||||||
|
const unsigned char *p = data + length - footersize;
|
||||||
|
|
||||||
|
// Gas mixes
|
||||||
|
unsigned int ngasmixes = 0;
|
||||||
|
unsigned int oxygen[NGASMIXES] = {0};
|
||||||
|
unsigned int air = (p[0] & 0x02) == 0;
|
||||||
if (air) {
|
if (air) {
|
||||||
return 1;
|
oxygen[0] = 21;
|
||||||
|
ngasmixes = 1;
|
||||||
} else {
|
} else {
|
||||||
// Count the number of active gas mixes. The active gas
|
// Count the number of active gas mixes. The active gas
|
||||||
// mixes are always first, so we stop counting as soon
|
// mixes are always first, so we stop counting as soon
|
||||||
// as the first gas marked as disabled is found.
|
// as the first gas marked as disabled is found.
|
||||||
unsigned int i = 0;
|
ngasmixes = 0;
|
||||||
while (i < 3) {
|
while (ngasmixes < NGASMIXES) {
|
||||||
if (p[0x14 + i * 4 + 1] & 0x80)
|
if (p[0x14 + ngasmixes * 4 + 1] & 0x80)
|
||||||
break;
|
break;
|
||||||
i++;
|
oxygen[ngasmixes] = p[0x14 + ngasmixes * 4];
|
||||||
|
ngasmixes++;
|
||||||
}
|
}
|
||||||
return i;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Cache the data for later use.
|
||||||
|
parser->footer = length - footersize;
|
||||||
|
parser->samplesize = samplesize;
|
||||||
|
parser->ngasmixes = ngasmixes;
|
||||||
|
for (unsigned int i = 0; i < ngasmixes; ++i) {
|
||||||
|
parser->oxygen[i] = oxygen[i];
|
||||||
|
}
|
||||||
|
parser->cached = 1;
|
||||||
|
|
||||||
|
return DC_STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -94,6 +140,13 @@ mares_iconhd_parser_create (dc_parser_t **out, dc_context_t *context, unsigned i
|
|||||||
|
|
||||||
// Set the default values.
|
// Set the default values.
|
||||||
parser->model = model;
|
parser->model = model;
|
||||||
|
parser->cached = 0;
|
||||||
|
parser->footer = 0;
|
||||||
|
parser->samplesize = 0;
|
||||||
|
parser->ngasmixes = 0;
|
||||||
|
for (unsigned int i = 0; i < NGASMIXES; ++i) {
|
||||||
|
parser->oxygen[i] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
*out = (dc_parser_t*) parser;
|
*out = (dc_parser_t*) parser;
|
||||||
|
|
||||||
@ -114,6 +167,17 @@ mares_iconhd_parser_destroy (dc_parser_t *abstract)
|
|||||||
static dc_status_t
|
static dc_status_t
|
||||||
mares_iconhd_parser_set_data (dc_parser_t *abstract, const unsigned char *data, unsigned int size)
|
mares_iconhd_parser_set_data (dc_parser_t *abstract, const unsigned char *data, unsigned int size)
|
||||||
{
|
{
|
||||||
|
mares_iconhd_parser_t *parser = (mares_iconhd_parser_t *) abstract;
|
||||||
|
|
||||||
|
// Reset the cache.
|
||||||
|
parser->cached = 0;
|
||||||
|
parser->footer = 0;
|
||||||
|
parser->samplesize = 0;
|
||||||
|
parser->ngasmixes = 0;
|
||||||
|
for (unsigned int i = 0; i < NGASMIXES; ++i) {
|
||||||
|
parser->oxygen[i] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
return DC_STATUS_SUCCESS;
|
return DC_STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -123,20 +187,12 @@ mares_iconhd_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetime
|
|||||||
{
|
{
|
||||||
mares_iconhd_parser_t *parser = (mares_iconhd_parser_t *) abstract;
|
mares_iconhd_parser_t *parser = (mares_iconhd_parser_t *) abstract;
|
||||||
|
|
||||||
unsigned int header = 0x5C;
|
// Cache the parser data.
|
||||||
if (parser->model == ICONHDNET) {
|
dc_status_t rc = mares_iconhd_parser_cache (parser);
|
||||||
header = 0x80;
|
if (rc != DC_STATUS_SUCCESS)
|
||||||
}
|
return rc;
|
||||||
|
|
||||||
if (abstract->size < 4)
|
const unsigned char *p = abstract->data + parser->footer + 6;
|
||||||
return DC_STATUS_DATAFORMAT;
|
|
||||||
|
|
||||||
unsigned int length = array_uint32_le (abstract->data);
|
|
||||||
|
|
||||||
if (abstract->size < length || length < header + 4)
|
|
||||||
return DC_STATUS_DATAFORMAT;
|
|
||||||
|
|
||||||
const unsigned char *p = abstract->data + length - header + 6;
|
|
||||||
|
|
||||||
if (datetime) {
|
if (datetime) {
|
||||||
datetime->hour = array_uint16_le (p + 0);
|
datetime->hour = array_uint16_le (p + 0);
|
||||||
@ -156,25 +212,15 @@ mares_iconhd_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsi
|
|||||||
{
|
{
|
||||||
mares_iconhd_parser_t *parser = (mares_iconhd_parser_t *) abstract;
|
mares_iconhd_parser_t *parser = (mares_iconhd_parser_t *) abstract;
|
||||||
|
|
||||||
unsigned int header = 0x5C;
|
// Cache the parser data.
|
||||||
if (parser->model == ICONHDNET) {
|
dc_status_t rc = mares_iconhd_parser_cache (parser);
|
||||||
header = 0x80;
|
if (rc != DC_STATUS_SUCCESS)
|
||||||
}
|
return rc;
|
||||||
|
|
||||||
if (abstract->size < 4)
|
const unsigned char *p = abstract->data + parser->footer;
|
||||||
return DC_STATUS_DATAFORMAT;
|
|
||||||
|
|
||||||
unsigned int length = array_uint32_le (abstract->data);
|
|
||||||
|
|
||||||
if (abstract->size < length || length < header + 4)
|
|
||||||
return DC_STATUS_DATAFORMAT;
|
|
||||||
|
|
||||||
const unsigned char *p = abstract->data + length - header;
|
|
||||||
|
|
||||||
dc_gasmix_t *gasmix = (dc_gasmix_t *) value;
|
dc_gasmix_t *gasmix = (dc_gasmix_t *) value;
|
||||||
|
|
||||||
unsigned int air = (p[0] & 0x02) == 0;
|
|
||||||
|
|
||||||
if (value) {
|
if (value) {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case DC_FIELD_DIVETIME:
|
case DC_FIELD_DIVETIME:
|
||||||
@ -184,13 +230,10 @@ mares_iconhd_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsi
|
|||||||
*((double *) value) = array_uint16_le (p + 0x04) / 10.0;
|
*((double *) value) = array_uint16_le (p + 0x04) / 10.0;
|
||||||
break;
|
break;
|
||||||
case DC_FIELD_GASMIX_COUNT:
|
case DC_FIELD_GASMIX_COUNT:
|
||||||
*((unsigned int *) value) = mares_iconhd_parser_count_active_gas_mixes (p, air);
|
*((unsigned int *) value) = parser->ngasmixes;
|
||||||
break;
|
break;
|
||||||
case DC_FIELD_GASMIX:
|
case DC_FIELD_GASMIX:
|
||||||
if (air)
|
gasmix->oxygen = parser->oxygen[flags] / 100.0;
|
||||||
gasmix->oxygen = 0.21;
|
|
||||||
else
|
|
||||||
gasmix->oxygen = p[0x14 + flags * 4] / 100.0;
|
|
||||||
gasmix->helium = 0.0;
|
gasmix->helium = 0.0;
|
||||||
gasmix->nitrogen = 1.0 - gasmix->oxygen - gasmix->helium;
|
gasmix->nitrogen = 1.0 - gasmix->oxygen - gasmix->helium;
|
||||||
break;
|
break;
|
||||||
@ -212,27 +255,12 @@ mares_iconhd_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t
|
|||||||
{
|
{
|
||||||
mares_iconhd_parser_t *parser = (mares_iconhd_parser_t *) abstract;
|
mares_iconhd_parser_t *parser = (mares_iconhd_parser_t *) abstract;
|
||||||
|
|
||||||
unsigned int header = 0x5C;
|
// Cache the parser data.
|
||||||
unsigned int samplesize = 8;
|
dc_status_t rc = mares_iconhd_parser_cache (parser);
|
||||||
if (parser->model == ICONHDNET) {
|
if (rc != DC_STATUS_SUCCESS)
|
||||||
header = 0x80;
|
return rc;
|
||||||
samplesize = 12;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (abstract->size < 4)
|
|
||||||
return DC_STATUS_DATAFORMAT;
|
|
||||||
|
|
||||||
unsigned int length = array_uint32_le (abstract->data);
|
|
||||||
|
|
||||||
if (abstract->size < length || length < header + 4)
|
|
||||||
return DC_STATUS_DATAFORMAT;
|
|
||||||
|
|
||||||
const unsigned char *p = abstract->data + length - header;
|
|
||||||
|
|
||||||
unsigned int air = (p[0] & 0x02) == 0;
|
|
||||||
|
|
||||||
const unsigned char *data = abstract->data;
|
const unsigned char *data = abstract->data;
|
||||||
unsigned int size = length - header;
|
|
||||||
|
|
||||||
unsigned int time = 0;
|
unsigned int time = 0;
|
||||||
unsigned int interval = 5;
|
unsigned int interval = 5;
|
||||||
@ -242,9 +270,8 @@ mares_iconhd_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t
|
|||||||
|
|
||||||
// Previous gas mix - initialize with impossible value
|
// Previous gas mix - initialize with impossible value
|
||||||
unsigned int gasmix_previous = 0xFFFFFFFF;
|
unsigned int gasmix_previous = 0xFFFFFFFF;
|
||||||
unsigned int ngasmixes = mares_iconhd_parser_count_active_gas_mixes (p, air);
|
|
||||||
|
|
||||||
while (offset + samplesize <= size) {
|
while (offset + parser->samplesize <= parser->footer) {
|
||||||
dc_sample_value_t sample = {0};
|
dc_sample_value_t sample = {0};
|
||||||
|
|
||||||
// Time (seconds).
|
// Time (seconds).
|
||||||
@ -264,28 +291,23 @@ mares_iconhd_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t
|
|||||||
|
|
||||||
// Current gas mix
|
// Current gas mix
|
||||||
unsigned int gasmix = (data[offset + 3] & 0xF0) >> 4;
|
unsigned int gasmix = (data[offset + 3] & 0xF0) >> 4;
|
||||||
if (gasmix >= ngasmixes) {
|
if (gasmix >= parser->ngasmixes) {
|
||||||
return DC_STATUS_DATAFORMAT;
|
return DC_STATUS_DATAFORMAT;
|
||||||
}
|
}
|
||||||
if (gasmix != gasmix_previous) {
|
if (gasmix != gasmix_previous) {
|
||||||
unsigned int o2 = 0;
|
|
||||||
if (air)
|
|
||||||
o2 = 21;
|
|
||||||
else
|
|
||||||
o2 = p[0x14 + gasmix * 4];
|
|
||||||
sample.event.type = SAMPLE_EVENT_GASCHANGE;
|
sample.event.type = SAMPLE_EVENT_GASCHANGE;
|
||||||
sample.event.time = 0;
|
sample.event.time = 0;
|
||||||
sample.event.value = o2;
|
sample.event.value = parser->oxygen[gasmix];
|
||||||
if (callback) callback (DC_SAMPLE_EVENT, sample, userdata);
|
if (callback) callback (DC_SAMPLE_EVENT, sample, userdata);
|
||||||
gasmix_previous = gasmix;
|
gasmix_previous = gasmix;
|
||||||
}
|
}
|
||||||
|
|
||||||
offset += samplesize;
|
offset += parser->samplesize;
|
||||||
nsamples++;
|
nsamples++;
|
||||||
|
|
||||||
// Some extra data.
|
// Some extra data.
|
||||||
if (parser->model == ICONHDNET && (nsamples % 4) == 0) {
|
if (parser->model == ICONHDNET && (nsamples % 4) == 0) {
|
||||||
if (offset + 8 > size)
|
if (offset + 8 > parser->footer)
|
||||||
return DC_STATUS_DATAFORMAT;
|
return DC_STATUS_DATAFORMAT;
|
||||||
|
|
||||||
// Pressure (1/100 bar).
|
// Pressure (1/100 bar).
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user