diff options
Diffstat (limited to 'epan/ftypes/ftype-ieee-11073-float.c')
-rw-r--r-- | epan/ftypes/ftype-ieee-11073-float.c | 1058 |
1 files changed, 1058 insertions, 0 deletions
diff --git a/epan/ftypes/ftype-ieee-11073-float.c b/epan/ftypes/ftype-ieee-11073-float.c new file mode 100644 index 0000000..bb4d628 --- /dev/null +++ b/epan/ftypes/ftype-ieee-11073-float.c @@ -0,0 +1,1058 @@ +/* FLOATs as specified by ISO/IEEE Std. 11073-20601-2014 + * + * Personal Health Devices Transcoding White Paper v1.5 + * https://www.bluetooth.org/DocMan/handlers/DownloadDoc.ashx?doc_id=272346 + * + * Wireshark - Network traffic analyzer + * By Gerald Combs <gerald@wireshark.org> + * Copyright 2001 Gerald Combs + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include "config.h" + +#include <ftypes-int.h> +#include <inttypes.h> +#include <stdio.h> +#include <math.h> +#include <float.h> + +#include "strutil.h" + +#define DOUBLE_REPR_LENGTH 27 + +#define SFLOAT_VALUE_INFINITY_PLUS 0x07FE +#define SFLOAT_VALUE_NAN 0x07FF +#define SFLOAT_VALUE_NRES 0x0800 +#define SFLOAT_VALUE_RFU 0x0801 +#define SFLOAT_VALUE_INFINITY_MINUS 0x0802 + +#define FLOAT_VALUE_INFINITY_PLUS 0x007FFFFE +#define FLOAT_VALUE_NAN 0x007FFFFF +#define FLOAT_VALUE_NRES 0x00800000 +#define FLOAT_VALUE_RFU 0x00800001 +#define FLOAT_VALUE_INFINITY_MINUS 0x00800002 + +static void +sfloat_ieee_11073_fvalue_new(fvalue_t *fv) +{ + fv->value.sfloat_ieee_11073 = 0x0000; +} + +static bool +sfloat_ieee_11073_val_from_literal(fvalue_t *fv, const char *s, bool allow_partial_value _U_, char **err_msg _U_) +{ + const char *i_char = s; + char c; + uint8_t mantissa_sign = 0; + uint32_t mantissa = 0; + int8_t exponent = 0; + bool fraction_mode = false; + const uint16_t mantissa_max = 0x07FF; + + c = *i_char; + + if (c== '\0') + return false; + + if (c == '.') + return false; + + if (c == '-' && s[1] == '.') + return false; + + if (c == '-' && (s[1] == 'I' || s[1] == 'i')) { + if (!g_ascii_strcasecmp(s, "-INFINITY")) { + fv->value.sfloat_ieee_11073 = SFLOAT_VALUE_INFINITY_MINUS; + return true; + } + + return false; + } else if (c == 'R' || c == 'r') { + if (!g_ascii_strcasecmp(s, "RFU")) { + fv->value.sfloat_ieee_11073 = SFLOAT_VALUE_RFU; + return true; + } + + return false; + } else if (c == 'N' || c == 'n') { + if (!g_ascii_strcasecmp(s, "NRes")) { + fv->value.sfloat_ieee_11073 = SFLOAT_VALUE_NRES; + return true; + } + + if (!g_ascii_strcasecmp(s, "NaN")) { + fv->value.sfloat_ieee_11073 = SFLOAT_VALUE_NAN; + return true; + } + + return false; + } else if (c == '+') { + if (!g_ascii_strcasecmp(s, "+INFINITY")) { + fv->value.sfloat_ieee_11073 = SFLOAT_VALUE_INFINITY_PLUS; + return true; + } + + return false; + } + + if (c == '-') { + if (s[1] == '\0') + return false; + + mantissa_sign = 1; + i_char += 1; + } + + while (*i_char == '0') { + i_char += 1; + } + + c = *i_char; + + do { + if (c == '0') { + if (mantissa * 10 > (uint32_t) mantissa_max + mantissa_sign) { + exponent += 1; + if (exponent > 7) + return false; + } else { + mantissa *= 10; + } + } else if (c == '1') { + mantissa *= 10; + mantissa += 1; + } else if (c == '2') { + mantissa *= 10; + mantissa += 2; + } else if (c == '3') { + mantissa *= 10; + mantissa += 3; + } else if (c == '4') { + mantissa *= 10; + mantissa += 4; + } else if (c == '5') { + mantissa *= 10; + mantissa += 5; + } else if (c == '6') { + mantissa *= 10; + mantissa += 6; + } else if (c == '7') { + mantissa *= 10; + mantissa += 7; + } else if (c == '8') { + mantissa *= 10; + mantissa += 8; + } else if (c == '9') { + mantissa *= 10; + mantissa += 9; + } else if (c == '.') { + if (fraction_mode) + return false; + fraction_mode = true; + i_char += 1; + + while (*i_char == '0') { + i_char += 1; + if (mantissa * 10 <= (uint32_t) mantissa_max + mantissa_sign) { + mantissa *= 10; + if (exponent > -8 - 4) /* -8 is min exponent; 4 is mantissa size */ + exponent -= 1; + } + } + + i_char -= 1; + } else if (c != '\0') { + /* NOTE: Maybe 5e-10, 5e3 notation should be also supported */ + return false; + } + + if (mantissa > (uint32_t) mantissa_max + mantissa_sign) + return false; + + if (c != '.' && fraction_mode) + exponent -= 1; + + i_char += 1; + } while ((c = *i_char)); + + if (mantissa_sign) { + mantissa = ~(mantissa - 1); + mantissa &= 0x0FFF; + } + + /* Transform to normal form */ + + if (mantissa == 0) + exponent = 0; + + while (mantissa > 0 && mantissa % 10 == 0 && exponent < 7) { + mantissa /= 10; + exponent += 1; + } + + if (exponent < -8) + return false; + + fv->value.sfloat_ieee_11073 = ((exponent & 0x0F) << 12) | mantissa; + + return true; +} + +static char * +sfloat_ieee_11073_val_to_repr(wmem_allocator_t *scope, const fvalue_t *fv, ftrepr_t rtype _U_, int field_display _U_) +{ + int8_t exponent; + uint16_t mantissa; + uint16_t mantissa_sign; + uint32_t offset = 0; + char mantissa_buf[5]; + char *mantissa_str; + uint8_t mantissa_digits; + + /* Predefinied: +INFINITY, -INFINITY, RFU, NRes, NaN */ + if (fv->value.sfloat_ieee_11073 >= 0x07FE && fv->value.sfloat_ieee_11073 <= 0x0802) { + char *s = NULL; + + switch (fv->value.sfloat_ieee_11073) { + case SFLOAT_VALUE_INFINITY_PLUS: + s = "+INFINITY"; + break; + case SFLOAT_VALUE_NAN: + s = "NaN"; + break; + case SFLOAT_VALUE_NRES: + s = "NRes"; + break; + case SFLOAT_VALUE_RFU: + s = "RFU"; + break; + case SFLOAT_VALUE_INFINITY_MINUS: + s = "-INFINITY"; + break; + } + return wmem_strdup(scope, s); + } + + /* Longest Signed Float Number: -0.00002048 (11 characters without NULL) */ + /* Longest Signed Float Number -0.00000001 */ + /* Longest Signed Nonfloat Number: -20480000000 (12 characters without NULL) */ + char buf[13]; + + exponent = fv->value.sfloat_ieee_11073 >> 12; + if (exponent & 0x8) + exponent |= 0xF0; /* It is signed (4bits), so make it signed in int8_t */ + mantissa = fv->value.sfloat_ieee_11073 & 0x07FF; + mantissa_sign = (fv->value.sfloat_ieee_11073 & 0x0800); + if (mantissa_sign) + mantissa = -((int16_t)mantissa | 0xF800); + + if (mantissa == 0) { + return wmem_strdup(scope, "0"); + } + + if (mantissa_sign) { + buf[0] = '-'; + offset += 1; + } + + mantissa_digits = snprintf(mantissa_buf, sizeof(mantissa_buf), "%"PRIu16, mantissa); + mantissa_str = mantissa_buf; + + if (exponent == 0) { + memcpy(buf + offset, mantissa_str, mantissa_digits); + offset += mantissa_digits; + } else if (exponent > 0) { + memcpy(buf + offset, mantissa_str, mantissa_digits); + offset += mantissa_digits; + + memset(buf + offset, '0', exponent); + offset += exponent; + } else /* if (exponent < 0)*/ { + if (-exponent < mantissa_digits) { + memcpy(buf + offset, mantissa_str, mantissa_digits + exponent); + offset += mantissa_digits + exponent; + + buf[offset] = '.'; + offset += 1; + + memcpy(buf + offset, mantissa_str + mantissa_digits + exponent, -exponent); + offset += -exponent; + } else { + buf[offset] = '0'; + offset += 1; + + buf[offset] = '.'; + offset += 1; + + if (-exponent - mantissa_digits > 0) { + memset(buf + offset, '0', -exponent - mantissa_digits); + offset += -exponent - mantissa_digits; + } + + memcpy(buf + offset, mantissa_str, mantissa_digits); + offset += mantissa_digits; + } + } + + buf[offset] = '\0'; + return wmem_strdup(scope, buf); +} + +static void +sfloat_ieee_11073_value_set(fvalue_t *fv, uint32_t value) +{ + fv->value.sfloat_ieee_11073 = (uint16_t) value; +} + +static uint32_t +sfloat_ieee_11073_value_get(fvalue_t *fv) +{ + return (uint32_t) fv->value.sfloat_ieee_11073; +} + +static uint16_t sfloat_to_normal_form(uint16_t value) +{ + int8_t exponent; + uint16_t mantissa; + uint8_t mantissa_sign; + + if (value >= 0x07FE && value <= 0x0802) /* Save special values */ + return value; + + mantissa = value & 0x07FF; + if (value & 0x0800) { + mantissa = -((int16_t)mantissa | 0xF800); + mantissa_sign = 1; + } else { + mantissa_sign = 0; + } + + exponent = value >> 12; + + if (exponent & 0x08) { + exponent |= 0xF0; + } + + while ((!(mantissa % 10)) && mantissa != 0) { + mantissa /= 10; + + if (exponent == 7) + break; + + exponent += 1; + } + + return ((((exponent & 0x80) ? 0x8 : 0x0 ) | (exponent & 0x7)) << 12) | (mantissa_sign << 11) | mantissa; +} + +static bool +sfloat_ieee_11073_cmp_eq(const fvalue_t *a, const fvalue_t *b) +{ + return sfloat_to_normal_form(a->value.sfloat_ieee_11073) == sfloat_to_normal_form(b->value.sfloat_ieee_11073); +} + +static bool +sfloat_ieee_11073_cmp_lt(const fvalue_t *a, const fvalue_t *b) +{ + uint16_t a_norm; + uint16_t b_norm; + int16_t a_norm_mantissa; + int16_t b_norm_mantissa; + int8_t a_norm_exponent; + int8_t b_norm_exponent; + + a_norm = sfloat_to_normal_form(a->value.sfloat_ieee_11073); + b_norm = sfloat_to_normal_form(b->value.sfloat_ieee_11073); + + if (a_norm == b_norm) + return false; + + switch (a_norm) { + case SFLOAT_VALUE_NAN: + case SFLOAT_VALUE_NRES: + case SFLOAT_VALUE_RFU: + case SFLOAT_VALUE_INFINITY_PLUS: + return false; + case SFLOAT_VALUE_INFINITY_MINUS: + switch (b_norm) { + case SFLOAT_VALUE_NAN: + case SFLOAT_VALUE_NRES: + case SFLOAT_VALUE_RFU: + case SFLOAT_VALUE_INFINITY_MINUS: /* Dead, informative case */ + return false; + case SFLOAT_VALUE_INFINITY_PLUS: + default: + return true; + } + } + + a_norm_mantissa = a_norm & 0x0FFF; + b_norm_mantissa = b_norm & 0x0FFF; + if (a_norm & 0x0800) + a_norm_mantissa |= 0xFFFFF000; + + if (b_norm & 0x0800) + b_norm_mantissa |= 0xFFFFF000; + + a_norm_exponent = a_norm >> 12; + b_norm_exponent = b_norm >> 12; + + if (a_norm_exponent & 0x08) { + a_norm_exponent |= 0xF0; + } + + if (b_norm_exponent & 0x08) { + b_norm_exponent |= 0xF0; + } + + if (a_norm_mantissa == b_norm_mantissa && a_norm_exponent < b_norm_exponent) + return true; + + if (a_norm_exponent == b_norm_exponent && a_norm_mantissa < b_norm_mantissa) + return true; + + if (a_norm_exponent < b_norm_exponent) { + uint8_t exponent_difference; + + exponent_difference = b_norm_exponent - a_norm_exponent; + + if (exponent_difference >= 4) + return true; + + while (exponent_difference--) { + b_norm_mantissa *= 10; + } + } else { + uint8_t exponent_difference; + + exponent_difference = a_norm_exponent - b_norm_exponent; + + if (exponent_difference >= 4) + return false; + + while (exponent_difference--) { + a_norm_mantissa *= 10; + } + } + + if (a_norm_mantissa < b_norm_mantissa) + return true; + + return false; +} + +static enum ft_result +sfloat_ieee_11073_cmp_order(const fvalue_t *a, const fvalue_t *b, int *cmp) +{ + if (sfloat_ieee_11073_cmp_lt(a, b)) + *cmp = -1; + else + *cmp = sfloat_ieee_11073_cmp_eq(a, b) ? 0 : 1; + + return FT_OK; +} + +static bool +sfloat_ieee_11073_is_zero(const fvalue_t *a) +{ + return a->value.sfloat_ieee_11073 == 0; +} + +static unsigned +sfloat_ieee_11073_hash(const fvalue_t *fv) +{ + int64_t value = fv->value.sfloat_ieee_11073; + return g_int64_hash(&value); +} + +/*============================================================================*/ + +static void +float_ieee_11073_fvalue_new(fvalue_t *fv) +{ + fv->value.float_ieee_11073 = 0x0000; +} + +static bool +float_ieee_11073_val_from_literal(fvalue_t *fv, const char *s, bool allow_partial_value _U_, char **err_msg _U_) +{ + const char *i_char = s; + char c; + uint8_t mantissa_sign = 0; + uint32_t mantissa = 0; + int16_t exponent = 0; + bool fraction_mode = false; + const uint32_t mantissa_max = 0x007FFFFF; + + c = *i_char; + + if (c== '\0') + return false; + + if (c == '.') + return false; + + if (c == '-' && s[1] == '.') + return false; + + if (c == '-' && (s[1] == 'I' || s[1] == 'i')) { + if (!g_ascii_strcasecmp(s, "-INFINITY")) { + fv->value.float_ieee_11073 = FLOAT_VALUE_INFINITY_MINUS; + return true; + } + + return false; + } else if (c == 'R' || c == 'r') { + if (!g_ascii_strcasecmp(s, "RFU")) { + fv->value.float_ieee_11073 = FLOAT_VALUE_RFU; + return true; + } + + return false; + } else if (c == 'N' || c == 'n') { + if (!g_ascii_strcasecmp(s, "NRes")) { + fv->value.float_ieee_11073 = FLOAT_VALUE_NRES; + return true; + } + + if (!g_ascii_strcasecmp(s, "NaN")) { + fv->value.float_ieee_11073 = FLOAT_VALUE_NAN; + return true; + } + + return false; + } else if (c == '+') { + if (!g_ascii_strcasecmp(s, "+INFINITY")) { + fv->value.float_ieee_11073 = FLOAT_VALUE_INFINITY_PLUS; + return true; + } + + return false; + } + + if (c == '-') { + if (s[1] == '\0') + return false; + + mantissa_sign = 1; + i_char += 1; + } + + while (*i_char == '0') { + i_char += 1; + } + + c = *i_char; + + do { + if (c == '0') { + if (mantissa * 10 > mantissa_sign + mantissa_max) { + exponent += 1; + if (exponent <= 127) + return false; + } else { + mantissa *= 10; + } + } else if (c == '1') { + mantissa *= 10; + mantissa += 1; + } else if (c == '2') { + mantissa *= 10; + mantissa += 2; + } else if (c == '3') { + mantissa *= 10; + mantissa += 3; + } else if (c == '4') { + mantissa *= 10; + mantissa += 4; + } else if (c == '5') { + mantissa *= 10; + mantissa += 5; + } else if (c == '6') { + mantissa *= 10; + mantissa += 6; + } else if (c == '7') { + mantissa *= 10; + mantissa += 7; + } else if (c == '8') { + mantissa *= 10; + mantissa += 8; + } else if (c == '9') { + mantissa *= 10; + mantissa += 9; + } else if (c == '.') { + if (fraction_mode) + return false; + fraction_mode = true; + i_char += 1; + + while (*i_char == '0') { + i_char += 1; + if (mantissa * 10 <= mantissa_max + mantissa_sign) { + mantissa *= 10; + if (exponent > -128 - 7) /* -8 is min exponent; 4 is mantissa size */ + exponent -= 1; + } + } + + i_char -= 1; + } else if (c != '\0') { + /* NOTE: Maybe 5e-10, 5e3 notation should be also supported */ + return false; + } + + if (mantissa > mantissa_max + mantissa_sign) + return false; + + if (c != '.' && fraction_mode) + exponent -= 1; + + i_char += 1; + } while ((c = *i_char)); + + if (mantissa_sign) { + mantissa = ~(mantissa - 1); + mantissa &= 0x00FFFFFF; + } + + /* Transform to normal form */ + + if (mantissa == 0) + exponent = 0; + + while (mantissa > 0 && mantissa % 10 == 0 && exponent < 127) { + mantissa /= 10; + exponent += 1; + } + + if (exponent < -128) + return false; + + fv->value.float_ieee_11073 = ((exponent & 0xFF) << 24) | mantissa; + + return true; +} + +static char * +float_ieee_11073_val_to_repr(wmem_allocator_t *scope, const fvalue_t *fv, ftrepr_t rtype _U_, int field_display _U_) +{ + int8_t exponent; + uint32_t mantissa; + uint32_t mantissa_sign; + uint32_t offset = 0; + char mantissa_buf[8]; + char *mantissa_str; + uint8_t mantissa_digits; + + /* Predefinied: +INFINITY, -INFINITY, RFU, NRes, NaN */ + if (fv->value.float_ieee_11073 >= 0x007FFFFE && fv->value.float_ieee_11073 <= 0x00800002) { + char *s = NULL; + switch (fv->value.float_ieee_11073) { + case FLOAT_VALUE_INFINITY_PLUS: + s = "+INFINITY"; + break; + case FLOAT_VALUE_NAN: + s = "NaN"; + break; + case FLOAT_VALUE_NRES: + s = "NRes"; + break; + case FLOAT_VALUE_RFU: + s = "RFU"; + break; + case FLOAT_VALUE_INFINITY_MINUS: + s = "-INFINITY"; + break; + } + return wmem_strdup(scope, s); + } + + /* Longest Signed Nonfloat Number: -8388608*(10^-128) (1 character for sign, 7 for mantisa digits, 127 zeros, 1 character for NULL) */ + char buf[136]; + + exponent = fv->value.float_ieee_11073 >> 24; + + mantissa = fv->value.float_ieee_11073 & 0x007FFFFF; + mantissa_sign = (fv->value.float_ieee_11073 & 0x00800000); + if (mantissa_sign) + mantissa = (uint32_t)(-((int32_t)(mantissa | 0xFF000000))); + + if (mantissa == 0) { + return wmem_strdup(scope, "0"); + } + + if (mantissa_sign) { + buf[0] = '-'; + offset += 1; + } + + mantissa_digits = snprintf(mantissa_buf, sizeof(mantissa_buf), "%"PRIu32, mantissa); + mantissa_str = mantissa_buf; + + if (exponent == 0) { + memcpy(buf + offset, mantissa_str, mantissa_digits); + offset += mantissa_digits; + } else if (exponent > 0) { + memcpy(buf + offset, mantissa_str, mantissa_digits); + offset += mantissa_digits; + + memset(buf + offset, '0', exponent); + offset += exponent; + } else /* if (exponent < 0)*/ { + if (-exponent < mantissa_digits) { + memcpy(buf + offset, mantissa_str, mantissa_digits + exponent); + offset += mantissa_digits + exponent; + + buf[offset] = '.'; + offset += 1; + + memcpy(buf + offset, mantissa_str + mantissa_digits + exponent, -exponent); + offset += -exponent; + } else { + buf[offset] = '0'; + offset += 1; + + buf[offset] = '.'; + offset += 1; + + if (-exponent - mantissa_digits > 0) { + memset(buf + offset, '0', -exponent - mantissa_digits); + offset += -exponent - mantissa_digits; + } + + memcpy(buf + offset, mantissa_str, mantissa_digits); + offset += mantissa_digits; + } + } + + buf[offset] = '\0'; + return wmem_strdup(scope, buf); +} + +static void +float_ieee_11073_value_set(fvalue_t *fv, uint32_t value) +{ + fv->value.float_ieee_11073 = value; +} + +static uint32_t +float_ieee_11073_value_get(fvalue_t *fv) +{ + return fv->value.float_ieee_11073; +} + +static uint32_t float_to_normal_form(uint32_t value) +{ + int8_t exponent; + uint16_t mantissa; + uint8_t mantissa_sign; + + if (value >= 0x007FFFFE && value <= 0x00800002) /* Save special values */ + return value; + + mantissa = value & 0x907FFFFF; + if (value & 0x00800000) { + mantissa = (uint32_t)(-((int32_t)(mantissa | 0xFF000000))); + mantissa_sign = 1; + } else { + mantissa_sign = 0; + } + + exponent = value >> 24; + + while ((!(mantissa % 10)) && mantissa != 0) { + mantissa /= 10; + + if (exponent == 127) + break; + + exponent += 1; + } + + return (exponent << 24) | (mantissa_sign << 23) | mantissa; +} + +static bool +float_ieee_11073_cmp_eq(const fvalue_t *a, const fvalue_t *b) +{ + return float_to_normal_form(a->value.float_ieee_11073) == float_to_normal_form(b->value.float_ieee_11073); +} + +static bool +float_ieee_11073_cmp_lt(const fvalue_t *a, const fvalue_t *b) +{ + uint32_t a_norm; + uint32_t b_norm; + int32_t a_norm_mantissa; + int32_t b_norm_mantissa; + int8_t a_norm_exponent; + int8_t b_norm_exponent; + + a_norm = float_to_normal_form(a->value.float_ieee_11073); + b_norm = float_to_normal_form(b->value.float_ieee_11073); + + if (a_norm == b_norm) + return false; + + switch (a_norm) { + case FLOAT_VALUE_NAN: + case FLOAT_VALUE_NRES: + case FLOAT_VALUE_RFU: + case FLOAT_VALUE_INFINITY_PLUS: + return false; + case FLOAT_VALUE_INFINITY_MINUS: + switch (b_norm) { + case FLOAT_VALUE_NAN: + case FLOAT_VALUE_NRES: + case FLOAT_VALUE_RFU: + case FLOAT_VALUE_INFINITY_MINUS: /* Dead, informative case */ + return false; + case FLOAT_VALUE_INFINITY_PLUS: + default: + return true; + } + } + + a_norm_mantissa = a_norm & 0x00FFFFFF; + b_norm_mantissa = b_norm & 0x00FFFFFF; + if (a_norm & 0x00800000) + a_norm_mantissa |= 0xFF000000; + + if (b_norm & 0x00800000) + b_norm_mantissa |= 0xFF000000; + + a_norm_exponent = a_norm >> 24; + b_norm_exponent = b_norm >> 24; + + if (a_norm_mantissa == b_norm_mantissa && a_norm_exponent < b_norm_exponent) + return true; + + if (a_norm_exponent == b_norm_exponent && a_norm_mantissa < b_norm_mantissa) + return true; + + if (a_norm_exponent < b_norm_exponent) { + uint8_t exponent_difference; + + exponent_difference = b_norm_exponent - a_norm_exponent; + + if (exponent_difference >= 7) + return true; + + while (exponent_difference--) { + b_norm_mantissa *= 10; + } + } else { + uint8_t exponent_difference; + + exponent_difference = a_norm_exponent - b_norm_exponent; + + if (exponent_difference >= 7) + return false; + + while (exponent_difference--) { + a_norm_mantissa *= 10; + } + } + + if (a_norm_mantissa < b_norm_mantissa) + return true; + + return false; +} + +static enum ft_result +float_ieee_11073_cmp_order(const fvalue_t *a, const fvalue_t *b, int *cmp) +{ + if (float_ieee_11073_cmp_lt(a, b)) + *cmp = -1; + else + *cmp = float_ieee_11073_cmp_eq(a, b) ? 0 : 1; + + return FT_OK; +} + +static bool +float_ieee_11073_is_zero(const fvalue_t *a) +{ + return a->value.float_ieee_11073 == 0; +} + +static unsigned +float_ieee_11073_hash(const fvalue_t *fv) +{ + int64_t value = fv->value.float_ieee_11073; + return g_int64_hash(&value); +} + +/*============================================================================*/ + +void +ftype_register_ieee_11073_float(void) +{ +/* +Size: 16bits = 2 octets + +Exponent: 4 bits (signed integer - 2's complement) +Mantissa: 12 bits (signed integer - 2's complement) +Base: 10 + +x = M * (10 ^ E) + +Exponent range: from -8 to 7 +Mantissa range: from -2048 to 2047 (4 digits) + +Special values: + + INFINITY [exponent 0, mantissa +(2^11 -2) = 0x07FE] + NaN (Not a Number) [exponent 0, mantissa +(2^11 -1) = 0x07FF] + NRes (Not at this Resolution) [exponent 0, mantissa -(2^11) = 0x0800] + Reserved for future use [exponent 0, mantissa -(2^11 -1) = 0x0801] + - INFINITY [exponent 0, mantissa -(2^11 -2) = 0x0802] + +Note: +be carefour when comparing: 1e == 10e-1 == 10e-2 == ... (solution: compare only if the lowest mantissa % 10 != 0) + +Example: 114 is 0x0072 + +*/ + static ftype_t sfloat_type = { + FT_IEEE_11073_SFLOAT, /* ftype */ + "FT_IEEE_11073_SFLOAT", /* name */ + "IEEE-11073 floating point (16-bit)", /* pretty_name */ + 2, /* wire_size */ + + sfloat_ieee_11073_fvalue_new, /* new_value */ + NULL, /* copy_value */ + NULL, /* free_value */ + sfloat_ieee_11073_val_from_literal, /* val_from_literal */ + NULL, /* val_from_string */ + NULL, /* val_from_charconst */ + sfloat_ieee_11073_val_to_repr, /* val_to_string_repr */ + + NULL, /* val_to_uinteger64 */ + NULL, /* val_to_sinteger64 */ + + { .set_value_uinteger = sfloat_ieee_11073_value_set }, /* union set_value */ + { .get_value_uinteger = sfloat_ieee_11073_value_get }, /* union get_value */ + + sfloat_ieee_11073_cmp_order, + NULL, /* cmp_contains */ + NULL, /* cmp_matches */ + + sfloat_ieee_11073_hash, /* hash */ + sfloat_ieee_11073_is_zero, /* is_zero */ + NULL, /* is_negative */ + NULL, /* len */ + NULL, /* slice */ + NULL, /* bitwise_and */ + NULL, /* unary_minus */ + NULL, /* add */ + NULL, /* subtract */ + NULL, /* multiply */ + NULL, /* divide */ + NULL, /* modulo */ + }; + +/* +Size: 32bits = 4 octets + +Exponent: 1 octet (signed integer - 2's complement) +Mantissa: 3 octets (signed integer - 2's complement) +Base: 10 + +x = M * (10 ^ E) + +Exponent range: from -128 to 127 +Mantissa range: from -8388608 to 8388607 (7 digits) + +Special values: + + INFINITY [exponent 0, mantissa +(2^23 -2) = 0x007FFFFE] + NaN (Not a Number) [exponent 0, mantissa +(2^23 -1) = 0x007FFFFF] + NRes (Not at this Resolution) [exponent 0, mantissa -(2^23) = 0x00800000] + Reserved for future use [exponent 0, mantissa -(2^23-1) = 0x00800001] + - INFINITY [exponent 0, mantissa -(2^23 -2) = 0x00800002] + +Note: +be carefour when comparing: 1e == 10e-1 == 10e-2 == ... (solution: compare only if the lowest mantissa % 10 != 0) + +Example: 36.4 is 0xFF00016C + +*/ + + static ftype_t float_type = { + FT_IEEE_11073_FLOAT, /* ftype */ + "FT_IEEE_11073_FLOAT", /* name */ + "IEEE-11073 Floating point (32-bit)", /* pretty_name */ + 4, /* wire_size */ + + float_ieee_11073_fvalue_new, /* new_value */ + NULL, /* copy_value */ + NULL, /* free_value */ + float_ieee_11073_val_from_literal, /* val_from_literal */ + NULL, /* val_from_string */ + NULL, /* val_from_charconst */ + float_ieee_11073_val_to_repr, /* val_to_string_repr */ + + NULL, /* val_to_uinteger64 */ + NULL, /* val_to_sinteger64 */ + + { .set_value_uinteger = float_ieee_11073_value_set }, /* union set_value */ + { .get_value_uinteger = float_ieee_11073_value_get }, /* union get_value */ + + float_ieee_11073_cmp_order, + NULL, /* cmp_contains */ + NULL, /* cmp_matches */ + + float_ieee_11073_hash, /* hash */ + float_ieee_11073_is_zero, /* is_zero */ + NULL, /* is_negative */ + NULL, /* len */ + NULL, /* slice */ + NULL, /* bitwise_and */ + NULL, /* unary_minus */ + NULL, /* add */ + NULL, /* subtract */ + NULL, /* multiply */ + NULL, /* divide */ + NULL, /* modulo */ + }; + + ftype_register(FT_IEEE_11073_SFLOAT, &sfloat_type); + ftype_register(FT_IEEE_11073_FLOAT, &float_type); +} + +void +ftype_register_pseudofields_ieee_11073_float(int proto) +{ + static int hf_ft_ieee_11073_sfloat; + static int hf_ft_ieee_11073_float; + + static hf_register_info hf_ftypes[] = { + { &hf_ft_ieee_11073_sfloat, + { "FT_IEEE_11073_SFLOAT", "_ws.ftypes.ieee_11073_sfloat", + FT_IEEE_11073_SFLOAT, BASE_NONE, NULL, 0x00, + NULL, HFILL } + }, + { &hf_ft_ieee_11073_float, + { "FT_IEEE_11073_FLOAT", "_ws.ftypes.ieee_11073_float", + FT_IEEE_11073_FLOAT, BASE_NONE, NULL, 0x00, + NULL, HFILL } + }, + }; + + proto_register_field_array(proto, hf_ftypes, array_length(hf_ftypes)); +} + +/* + * Editor modelines - https://www.wireshark.org/tools/modelines.html + * + * Local variables: + * c-basic-offset: 4 + * tab-width: 8 + * indent-tabs-mode: nil + * End: + * + * vi: set shiftwidth=4 tabstop=8 expandtab: + * :indentSize=4:tabSize=8:noTabs=true: + */ |