regen pidl all: rm epan/dissectors/pidl/*-stamp; pushd epan/dissectors/pidl/ && make...
[wireshark-sm.git] / epan / ftypes / ftype-ieee-11073-float.c
blob34adf175cf6210946c678cfc39c6dd086a69dc49
1 /* FLOATs as specified by ISO/IEEE Std. 11073-20601-2014
3 * Personal Health Devices Transcoding White Paper v1.5
4 * https://www.bluetooth.org/DocMan/handlers/DownloadDoc.ashx?doc_id=272346
6 * Wireshark - Network traffic analyzer
7 * By Gerald Combs <gerald@wireshark.org>
8 * Copyright 2001 Gerald Combs
10 * SPDX-License-Identifier: GPL-2.0-or-later
13 #include "config.h"
15 #include <ftypes-int.h>
16 #include <inttypes.h>
17 #include <math.h>
18 #include <stdio.h>
19 #include <wsutil/array.h>
21 #define DOUBLE_REPR_LENGTH 27
23 #define SFLOAT_VALUE_INFINITY_PLUS 0x07FE
24 #define SFLOAT_VALUE_NAN 0x07FF
25 #define SFLOAT_VALUE_NRES 0x0800
26 #define SFLOAT_VALUE_RFU 0x0801
27 #define SFLOAT_VALUE_INFINITY_MINUS 0x0802
29 #define FLOAT_VALUE_INFINITY_PLUS 0x007FFFFE
30 #define FLOAT_VALUE_NAN 0x007FFFFF
31 #define FLOAT_VALUE_NRES 0x00800000
32 #define FLOAT_VALUE_RFU 0x00800001
33 #define FLOAT_VALUE_INFINITY_MINUS 0x00800002
35 static void
36 sfloat_ieee_11073_fvalue_new(fvalue_t *fv)
38 fv->value.sfloat_ieee_11073 = 0x0000;
41 static bool
42 sfloat_ieee_11073_val_from_literal(fvalue_t *fv, const char *s, bool allow_partial_value _U_, char **err_msg _U_)
44 const char *i_char = s;
45 char c;
46 uint8_t mantissa_sign = 0;
47 uint32_t mantissa = 0;
48 int8_t exponent = 0;
49 bool fraction_mode = false;
50 const uint16_t mantissa_max = 0x07FF;
52 c = *i_char;
54 if (c== '\0')
55 return false;
57 if (c == '.')
58 return false;
60 if (c == '-' && s[1] == '.')
61 return false;
63 if (c == '-' && (s[1] == 'I' || s[1] == 'i')) {
64 if (!g_ascii_strcasecmp(s, "-INFINITY")) {
65 fv->value.sfloat_ieee_11073 = SFLOAT_VALUE_INFINITY_MINUS;
66 return true;
69 return false;
70 } else if (c == 'R' || c == 'r') {
71 if (!g_ascii_strcasecmp(s, "RFU")) {
72 fv->value.sfloat_ieee_11073 = SFLOAT_VALUE_RFU;
73 return true;
76 return false;
77 } else if (c == 'N' || c == 'n') {
78 if (!g_ascii_strcasecmp(s, "NRes")) {
79 fv->value.sfloat_ieee_11073 = SFLOAT_VALUE_NRES;
80 return true;
83 if (!g_ascii_strcasecmp(s, "NaN")) {
84 fv->value.sfloat_ieee_11073 = SFLOAT_VALUE_NAN;
85 return true;
88 return false;
89 } else if (c == '+') {
90 if (!g_ascii_strcasecmp(s, "+INFINITY")) {
91 fv->value.sfloat_ieee_11073 = SFLOAT_VALUE_INFINITY_PLUS;
92 return true;
95 return false;
98 if (c == '-') {
99 if (s[1] == '\0')
100 return false;
102 mantissa_sign = 1;
103 i_char += 1;
106 while (*i_char == '0') {
107 i_char += 1;
110 c = *i_char;
112 do {
113 if (c == '0') {
114 if (mantissa * 10 > (uint32_t) mantissa_max + mantissa_sign) {
115 exponent += 1;
116 if (exponent > 7)
117 return false;
118 } else {
119 mantissa *= 10;
121 } else if (c == '1') {
122 mantissa *= 10;
123 mantissa += 1;
124 } else if (c == '2') {
125 mantissa *= 10;
126 mantissa += 2;
127 } else if (c == '3') {
128 mantissa *= 10;
129 mantissa += 3;
130 } else if (c == '4') {
131 mantissa *= 10;
132 mantissa += 4;
133 } else if (c == '5') {
134 mantissa *= 10;
135 mantissa += 5;
136 } else if (c == '6') {
137 mantissa *= 10;
138 mantissa += 6;
139 } else if (c == '7') {
140 mantissa *= 10;
141 mantissa += 7;
142 } else if (c == '8') {
143 mantissa *= 10;
144 mantissa += 8;
145 } else if (c == '9') {
146 mantissa *= 10;
147 mantissa += 9;
148 } else if (c == '.') {
149 if (fraction_mode)
150 return false;
151 fraction_mode = true;
152 i_char += 1;
154 while (*i_char == '0') {
155 i_char += 1;
156 if (mantissa * 10 <= (uint32_t) mantissa_max + mantissa_sign) {
157 mantissa *= 10;
158 if (exponent > -8 - 4) /* -8 is min exponent; 4 is mantissa size */
159 exponent -= 1;
163 i_char -= 1;
164 } else if (c != '\0') {
165 /* NOTE: Maybe 5e-10, 5e3 notation should be also supported */
166 return false;
169 if (mantissa > (uint32_t) mantissa_max + mantissa_sign)
170 return false;
172 if (c != '.' && fraction_mode)
173 exponent -= 1;
175 i_char += 1;
176 } while ((c = *i_char));
178 if (mantissa_sign) {
179 mantissa = ~(mantissa - 1);
180 mantissa &= 0x0FFF;
183 /* Transform to normal form */
185 if (mantissa == 0)
186 exponent = 0;
188 while (mantissa > 0 && mantissa % 10 == 0 && exponent < 7) {
189 mantissa /= 10;
190 exponent += 1;
193 if (exponent < -8)
194 return false;
196 fv->value.sfloat_ieee_11073 = ((exponent & 0x0F) << 12) | mantissa;
198 return true;
201 static bool
202 sfloat_ieee_11073_val_from_uinteger64(fvalue_t *fv, const char *s, uint64_t value _U_, char **err_msg)
204 return sfloat_ieee_11073_val_from_literal(fv, s, FALSE, err_msg);
207 static bool
208 sfloat_ieee_11073_val_from_sinteger64(fvalue_t *fv, const char *s, int64_t value _U_, char **err_msg)
210 return sfloat_ieee_11073_val_from_literal(fv, s, FALSE, err_msg);
213 static bool
214 sfloat_ieee_11073_val_from_double(fvalue_t *fv, const char *s, double value _U_, char **err_msg)
216 return sfloat_ieee_11073_val_from_literal(fv, s, FALSE, err_msg);
219 static char *
220 sfloat_ieee_11073_val_to_repr(wmem_allocator_t *scope, const fvalue_t *fv, ftrepr_t rtype _U_, int field_display _U_)
222 int8_t exponent;
223 uint16_t mantissa;
224 uint16_t mantissa_sign;
225 uint32_t offset = 0;
226 char mantissa_buf[5];
227 char *mantissa_str;
228 uint8_t mantissa_digits;
230 /* Predefined: +INFINITY, -INFINITY, RFU, NRes, NaN */
231 if (fv->value.sfloat_ieee_11073 >= 0x07FE && fv->value.sfloat_ieee_11073 <= 0x0802) {
232 char *s = NULL;
234 switch (fv->value.sfloat_ieee_11073) {
235 case SFLOAT_VALUE_INFINITY_PLUS:
236 s = "+INFINITY";
237 break;
238 case SFLOAT_VALUE_NAN:
239 s = "NaN";
240 break;
241 case SFLOAT_VALUE_NRES:
242 s = "NRes";
243 break;
244 case SFLOAT_VALUE_RFU:
245 s = "RFU";
246 break;
247 case SFLOAT_VALUE_INFINITY_MINUS:
248 s = "-INFINITY";
249 break;
251 return wmem_strdup(scope, s);
254 /* Longest Signed Float Number: -0.00002048 (11 characters without NULL) */
255 /* Longest Signed Float Number -0.00000001 */
256 /* Longest Signed Nonfloat Number: -20480000000 (12 characters without NULL) */
257 char buf[13];
259 exponent = fv->value.sfloat_ieee_11073 >> 12;
260 if (exponent & 0x8)
261 exponent |= 0xF0; /* It is signed (4bits), so make it signed in int8_t */
262 mantissa = fv->value.sfloat_ieee_11073 & 0x07FF;
263 mantissa_sign = (fv->value.sfloat_ieee_11073 & 0x0800);
264 if (mantissa_sign)
265 mantissa = -((int16_t)mantissa | 0xF800);
267 if (mantissa == 0) {
268 return wmem_strdup(scope, "0");
271 if (mantissa_sign) {
272 buf[0] = '-';
273 offset += 1;
276 mantissa_digits = snprintf(mantissa_buf, sizeof(mantissa_buf), "%"PRIu16, mantissa);
277 mantissa_str = mantissa_buf;
279 if (exponent == 0) {
280 memcpy(buf + offset, mantissa_str, mantissa_digits);
281 offset += mantissa_digits;
282 } else if (exponent > 0) {
283 memcpy(buf + offset, mantissa_str, mantissa_digits);
284 offset += mantissa_digits;
286 memset(buf + offset, '0', exponent);
287 offset += exponent;
288 } else /* if (exponent < 0)*/ {
289 if (-exponent < mantissa_digits) {
290 memcpy(buf + offset, mantissa_str, mantissa_digits + exponent);
291 offset += mantissa_digits + exponent;
293 buf[offset] = '.';
294 offset += 1;
296 memcpy(buf + offset, mantissa_str + mantissa_digits + exponent, -exponent);
297 offset += -exponent;
298 } else {
299 buf[offset] = '0';
300 offset += 1;
302 buf[offset] = '.';
303 offset += 1;
305 if (-exponent - mantissa_digits > 0) {
306 memset(buf + offset, '0', -exponent - mantissa_digits);
307 offset += -exponent - mantissa_digits;
310 memcpy(buf + offset, mantissa_str, mantissa_digits);
311 offset += mantissa_digits;
315 buf[offset] = '\0';
316 return wmem_strdup(scope, buf);
319 static enum ft_result
320 sfloat_ieee_11073_val_to_double(const fvalue_t *fv, double *repr)
322 int8_t exponent;
323 uint16_t mantissa;
324 uint16_t mantissa_sign;
326 switch (fv->value.sfloat_ieee_11073) {
327 case SFLOAT_VALUE_INFINITY_PLUS:
328 *repr = INFINITY;
329 return FT_OK;
330 case SFLOAT_VALUE_NAN:
331 case SFLOAT_VALUE_NRES:
332 case SFLOAT_VALUE_RFU:
333 *repr = NAN;
334 return FT_OK;
335 case SFLOAT_VALUE_INFINITY_MINUS:
336 *repr = -INFINITY;
337 return FT_OK;
338 default:
339 break;
342 mantissa = fv->value.sfloat_ieee_11073 & 0x07FF;
344 if (mantissa == 0) {
345 *repr = 0;
346 return FT_OK;
349 mantissa_sign = (fv->value.sfloat_ieee_11073 & 0x0800);
350 if (mantissa_sign)
351 mantissa = -((int16_t)mantissa | 0xF800);
353 exponent = fv->value.sfloat_ieee_11073 >> 12;
354 if (exponent & 0x8)
355 exponent |= 0xF0; /* It is signed (4bits), so make it signed in int8_t */
357 *repr = mantissa * pow(10, exponent);
359 return FT_OK;
362 static void
363 sfloat_ieee_11073_value_set(fvalue_t *fv, uint32_t value)
365 fv->value.sfloat_ieee_11073 = (uint16_t) value;
368 static uint32_t
369 sfloat_ieee_11073_value_get(fvalue_t *fv)
371 return (uint32_t) fv->value.sfloat_ieee_11073;
374 static uint16_t sfloat_to_normal_form(uint16_t value)
376 int8_t exponent;
377 uint16_t mantissa;
378 uint8_t mantissa_sign;
380 if (value >= 0x07FE && value <= 0x0802) /* Save special values */
381 return value;
383 mantissa = value & 0x07FF;
384 if (value & 0x0800) {
385 mantissa = -((int16_t)mantissa | 0xF800);
386 mantissa_sign = 1;
387 } else {
388 mantissa_sign = 0;
391 exponent = value >> 12;
393 if (exponent & 0x08) {
394 exponent |= 0xF0;
397 while ((!(mantissa % 10)) && mantissa != 0) {
398 mantissa /= 10;
400 if (exponent == 7)
401 break;
403 exponent += 1;
406 return ((((exponent & 0x80) ? 0x8 : 0x0 ) | (exponent & 0x7)) << 12) | (mantissa_sign << 11) | mantissa;
409 static bool
410 sfloat_ieee_11073_cmp_eq(const fvalue_t *a, const fvalue_t *b)
412 return sfloat_to_normal_form(a->value.sfloat_ieee_11073) == sfloat_to_normal_form(b->value.sfloat_ieee_11073);
415 static bool
416 sfloat_ieee_11073_cmp_lt(const fvalue_t *a, const fvalue_t *b)
418 uint16_t a_norm;
419 uint16_t b_norm;
420 int16_t a_norm_mantissa;
421 int16_t b_norm_mantissa;
422 int8_t a_norm_exponent;
423 int8_t b_norm_exponent;
425 a_norm = sfloat_to_normal_form(a->value.sfloat_ieee_11073);
426 b_norm = sfloat_to_normal_form(b->value.sfloat_ieee_11073);
428 if (a_norm == b_norm)
429 return false;
431 switch (a_norm) {
432 case SFLOAT_VALUE_NAN:
433 case SFLOAT_VALUE_NRES:
434 case SFLOAT_VALUE_RFU:
435 case SFLOAT_VALUE_INFINITY_PLUS:
436 return false;
437 case SFLOAT_VALUE_INFINITY_MINUS:
438 switch (b_norm) {
439 case SFLOAT_VALUE_NAN:
440 case SFLOAT_VALUE_NRES:
441 case SFLOAT_VALUE_RFU:
442 case SFLOAT_VALUE_INFINITY_MINUS: /* Dead, informative case */
443 return false;
444 case SFLOAT_VALUE_INFINITY_PLUS:
445 default:
446 return true;
450 a_norm_mantissa = a_norm & 0x0FFF;
451 b_norm_mantissa = b_norm & 0x0FFF;
452 if (a_norm & 0x0800)
453 a_norm_mantissa |= 0xFFFFF000;
455 if (b_norm & 0x0800)
456 b_norm_mantissa |= 0xFFFFF000;
458 a_norm_exponent = a_norm >> 12;
459 b_norm_exponent = b_norm >> 12;
461 if (a_norm_exponent & 0x08) {
462 a_norm_exponent |= 0xF0;
465 if (b_norm_exponent & 0x08) {
466 b_norm_exponent |= 0xF0;
469 if (a_norm_mantissa == b_norm_mantissa && a_norm_exponent < b_norm_exponent)
470 return true;
472 if (a_norm_exponent == b_norm_exponent && a_norm_mantissa < b_norm_mantissa)
473 return true;
475 if (a_norm_exponent < b_norm_exponent) {
476 uint8_t exponent_difference;
478 exponent_difference = b_norm_exponent - a_norm_exponent;
480 if (exponent_difference >= 4)
481 return true;
483 while (exponent_difference--) {
484 b_norm_mantissa *= 10;
486 } else {
487 uint8_t exponent_difference;
489 exponent_difference = a_norm_exponent - b_norm_exponent;
491 if (exponent_difference >= 4)
492 return false;
494 while (exponent_difference--) {
495 a_norm_mantissa *= 10;
499 if (a_norm_mantissa < b_norm_mantissa)
500 return true;
502 return false;
505 static enum ft_result
506 sfloat_ieee_11073_cmp_order(const fvalue_t *a, const fvalue_t *b, int *cmp)
508 if (sfloat_ieee_11073_cmp_lt(a, b))
509 *cmp = -1;
510 else
511 *cmp = sfloat_ieee_11073_cmp_eq(a, b) ? 0 : 1;
513 return FT_OK;
516 static bool
517 sfloat_ieee_11073_is_zero(const fvalue_t *a)
519 return a->value.sfloat_ieee_11073 == 0;
522 static unsigned
523 sfloat_ieee_11073_hash(const fvalue_t *fv)
525 int64_t value = fv->value.sfloat_ieee_11073;
526 return g_int64_hash(&value);
529 /*============================================================================*/
531 static void
532 float_ieee_11073_fvalue_new(fvalue_t *fv)
534 fv->value.float_ieee_11073 = 0x0000;
537 static bool
538 float_ieee_11073_val_from_literal(fvalue_t *fv, const char *s, bool allow_partial_value _U_, char **err_msg _U_)
540 const char *i_char = s;
541 char c;
542 uint8_t mantissa_sign = 0;
543 uint32_t mantissa = 0;
544 int16_t exponent = 0;
545 bool fraction_mode = false;
546 const uint32_t mantissa_max = 0x007FFFFF;
548 c = *i_char;
550 if (c== '\0')
551 return false;
553 if (c == '.')
554 return false;
556 if (c == '-' && s[1] == '.')
557 return false;
559 if (c == '-' && (s[1] == 'I' || s[1] == 'i')) {
560 if (!g_ascii_strcasecmp(s, "-INFINITY")) {
561 fv->value.float_ieee_11073 = FLOAT_VALUE_INFINITY_MINUS;
562 return true;
565 return false;
566 } else if (c == 'R' || c == 'r') {
567 if (!g_ascii_strcasecmp(s, "RFU")) {
568 fv->value.float_ieee_11073 = FLOAT_VALUE_RFU;
569 return true;
572 return false;
573 } else if (c == 'N' || c == 'n') {
574 if (!g_ascii_strcasecmp(s, "NRes")) {
575 fv->value.float_ieee_11073 = FLOAT_VALUE_NRES;
576 return true;
579 if (!g_ascii_strcasecmp(s, "NaN")) {
580 fv->value.float_ieee_11073 = FLOAT_VALUE_NAN;
581 return true;
584 return false;
585 } else if (c == '+') {
586 if (!g_ascii_strcasecmp(s, "+INFINITY")) {
587 fv->value.float_ieee_11073 = FLOAT_VALUE_INFINITY_PLUS;
588 return true;
591 return false;
594 if (c == '-') {
595 if (s[1] == '\0')
596 return false;
598 mantissa_sign = 1;
599 i_char += 1;
602 while (*i_char == '0') {
603 i_char += 1;
606 c = *i_char;
608 do {
609 if (c == '0') {
610 if (mantissa * 10 > mantissa_sign + mantissa_max) {
611 exponent += 1;
612 if (exponent <= 127)
613 return false;
614 } else {
615 mantissa *= 10;
617 } else if (c == '1') {
618 mantissa *= 10;
619 mantissa += 1;
620 } else if (c == '2') {
621 mantissa *= 10;
622 mantissa += 2;
623 } else if (c == '3') {
624 mantissa *= 10;
625 mantissa += 3;
626 } else if (c == '4') {
627 mantissa *= 10;
628 mantissa += 4;
629 } else if (c == '5') {
630 mantissa *= 10;
631 mantissa += 5;
632 } else if (c == '6') {
633 mantissa *= 10;
634 mantissa += 6;
635 } else if (c == '7') {
636 mantissa *= 10;
637 mantissa += 7;
638 } else if (c == '8') {
639 mantissa *= 10;
640 mantissa += 8;
641 } else if (c == '9') {
642 mantissa *= 10;
643 mantissa += 9;
644 } else if (c == '.') {
645 if (fraction_mode)
646 return false;
647 fraction_mode = true;
648 i_char += 1;
650 while (*i_char == '0') {
651 i_char += 1;
652 if (mantissa * 10 <= mantissa_max + mantissa_sign) {
653 mantissa *= 10;
654 if (exponent > -128 - 7) /* -8 is min exponent; 4 is mantissa size */
655 exponent -= 1;
659 i_char -= 1;
660 } else if (c != '\0') {
661 /* NOTE: Maybe 5e-10, 5e3 notation should be also supported */
662 return false;
665 if (mantissa > mantissa_max + mantissa_sign)
666 return false;
668 if (c != '.' && fraction_mode)
669 exponent -= 1;
671 i_char += 1;
672 } while ((c = *i_char));
674 if (mantissa_sign) {
675 mantissa = ~(mantissa - 1);
676 mantissa &= 0x00FFFFFF;
679 /* Transform to normal form */
681 if (mantissa == 0)
682 exponent = 0;
684 while (mantissa > 0 && mantissa % 10 == 0 && exponent < 127) {
685 mantissa /= 10;
686 exponent += 1;
689 if (exponent < -128)
690 return false;
692 fv->value.float_ieee_11073 = ((exponent & 0xFF) << 24) | mantissa;
694 return true;
697 static bool
698 float_ieee_11073_val_from_uinteger64(fvalue_t *fv, const char *s, uint64_t value _U_, char **err_msg)
700 return float_ieee_11073_val_from_literal(fv, s, FALSE, err_msg);
703 static bool
704 float_ieee_11073_val_from_sinteger64(fvalue_t *fv, const char *s, int64_t value _U_, char **err_msg)
706 return float_ieee_11073_val_from_literal(fv, s, FALSE, err_msg);
709 static bool
710 float_ieee_11073_val_from_double(fvalue_t *fv, const char *s, double value _U_, char **err_msg)
712 return float_ieee_11073_val_from_literal(fv, s, FALSE, err_msg);
715 static char *
716 float_ieee_11073_val_to_repr(wmem_allocator_t *scope, const fvalue_t *fv, ftrepr_t rtype _U_, int field_display _U_)
718 int8_t exponent;
719 uint32_t mantissa;
720 uint32_t mantissa_sign;
721 uint32_t offset = 0;
722 char mantissa_buf[8];
723 char *mantissa_str;
724 uint8_t mantissa_digits;
726 /* Predefined: +INFINITY, -INFINITY, RFU, NRes, NaN */
727 if (fv->value.float_ieee_11073 >= 0x007FFFFE && fv->value.float_ieee_11073 <= 0x00800002) {
728 char *s = NULL;
729 switch (fv->value.float_ieee_11073) {
730 case FLOAT_VALUE_INFINITY_PLUS:
731 s = "+INFINITY";
732 break;
733 case FLOAT_VALUE_NAN:
734 s = "NaN";
735 break;
736 case FLOAT_VALUE_NRES:
737 s = "NRes";
738 break;
739 case FLOAT_VALUE_RFU:
740 s = "RFU";
741 break;
742 case FLOAT_VALUE_INFINITY_MINUS:
743 s = "-INFINITY";
744 break;
746 return wmem_strdup(scope, s);
749 /* Longest Signed Nonfloat Number: -8388608*(10^-128) (1 character for sign, 7 for mantisa digits, 127 zeros, 1 character for NULL) */
750 char buf[136];
752 exponent = fv->value.float_ieee_11073 >> 24;
754 mantissa = fv->value.float_ieee_11073 & 0x007FFFFF;
755 mantissa_sign = (fv->value.float_ieee_11073 & 0x00800000);
756 if (mantissa_sign)
757 mantissa = (uint32_t)(-((int32_t)(mantissa | 0xFF000000)));
759 if (mantissa == 0) {
760 return wmem_strdup(scope, "0");
763 if (mantissa_sign) {
764 buf[0] = '-';
765 offset += 1;
768 mantissa_digits = snprintf(mantissa_buf, sizeof(mantissa_buf), "%"PRIu32, mantissa);
769 mantissa_str = mantissa_buf;
771 if (exponent == 0) {
772 memcpy(buf + offset, mantissa_str, mantissa_digits);
773 offset += mantissa_digits;
774 } else if (exponent > 0) {
775 memcpy(buf + offset, mantissa_str, mantissa_digits);
776 offset += mantissa_digits;
778 memset(buf + offset, '0', exponent);
779 offset += exponent;
780 } else /* if (exponent < 0)*/ {
781 if (-exponent < mantissa_digits) {
782 memcpy(buf + offset, mantissa_str, mantissa_digits + exponent);
783 offset += mantissa_digits + exponent;
785 buf[offset] = '.';
786 offset += 1;
788 memcpy(buf + offset, mantissa_str + mantissa_digits + exponent, -exponent);
789 offset += -exponent;
790 } else {
791 buf[offset] = '0';
792 offset += 1;
794 buf[offset] = '.';
795 offset += 1;
797 if (-exponent - mantissa_digits > 0) {
798 memset(buf + offset, '0', -exponent - mantissa_digits);
799 offset += -exponent - mantissa_digits;
802 memcpy(buf + offset, mantissa_str, mantissa_digits);
803 offset += mantissa_digits;
807 buf[offset] = '\0';
808 return wmem_strdup(scope, buf);
811 static enum ft_result
812 float_ieee_11073_val_to_double(const fvalue_t *fv, double *repr)
814 int8_t exponent;
815 uint16_t mantissa;
816 uint16_t mantissa_sign;
818 switch (fv->value.float_ieee_11073) {
819 case FLOAT_VALUE_INFINITY_PLUS:
820 *repr = INFINITY;
821 return FT_OK;
822 case FLOAT_VALUE_NAN:
823 case FLOAT_VALUE_NRES:
824 case FLOAT_VALUE_RFU:
825 *repr = NAN;
826 return FT_OK;
827 case FLOAT_VALUE_INFINITY_MINUS:
828 *repr = -INFINITY;
829 return FT_OK;
830 default:
831 break;
834 mantissa = fv->value.float_ieee_11073 & 0x007FFFFF;
835 if (mantissa == 0) {
836 *repr = 0;
837 return FT_OK;
840 mantissa_sign = (fv->value.float_ieee_11073 & 0x00800000);
841 if (mantissa_sign)
842 mantissa = (uint32_t)(-((int32_t)(mantissa | 0xFF000000)));
844 exponent = fv->value.float_ieee_11073 >> 24;
846 *repr = mantissa * pow(10, exponent);
848 return FT_OK;
851 static void
852 float_ieee_11073_value_set(fvalue_t *fv, uint32_t value)
854 fv->value.float_ieee_11073 = value;
857 static uint32_t
858 float_ieee_11073_value_get(fvalue_t *fv)
860 return fv->value.float_ieee_11073;
863 static uint32_t float_to_normal_form(uint32_t value)
865 int8_t exponent;
866 uint16_t mantissa;
867 uint8_t mantissa_sign;
869 if (value >= 0x007FFFFE && value <= 0x00800002) /* Save special values */
870 return value;
872 mantissa = value & 0x907FFFFF;
873 if (value & 0x00800000) {
874 mantissa = (uint32_t)(-((int32_t)(mantissa | 0xFF000000)));
875 mantissa_sign = 1;
876 } else {
877 mantissa_sign = 0;
880 exponent = value >> 24;
882 while ((!(mantissa % 10)) && mantissa != 0) {
883 mantissa /= 10;
885 if (exponent == 127)
886 break;
888 exponent += 1;
891 return (exponent << 24) | (mantissa_sign << 23) | mantissa;
894 static bool
895 float_ieee_11073_cmp_eq(const fvalue_t *a, const fvalue_t *b)
897 return float_to_normal_form(a->value.float_ieee_11073) == float_to_normal_form(b->value.float_ieee_11073);
900 static bool
901 float_ieee_11073_cmp_lt(const fvalue_t *a, const fvalue_t *b)
903 uint32_t a_norm;
904 uint32_t b_norm;
905 int32_t a_norm_mantissa;
906 int32_t b_norm_mantissa;
907 int8_t a_norm_exponent;
908 int8_t b_norm_exponent;
910 a_norm = float_to_normal_form(a->value.float_ieee_11073);
911 b_norm = float_to_normal_form(b->value.float_ieee_11073);
913 if (a_norm == b_norm)
914 return false;
916 switch (a_norm) {
917 case FLOAT_VALUE_NAN:
918 case FLOAT_VALUE_NRES:
919 case FLOAT_VALUE_RFU:
920 case FLOAT_VALUE_INFINITY_PLUS:
921 return false;
922 case FLOAT_VALUE_INFINITY_MINUS:
923 switch (b_norm) {
924 case FLOAT_VALUE_NAN:
925 case FLOAT_VALUE_NRES:
926 case FLOAT_VALUE_RFU:
927 case FLOAT_VALUE_INFINITY_MINUS: /* Dead, informative case */
928 return false;
929 case FLOAT_VALUE_INFINITY_PLUS:
930 default:
931 return true;
935 a_norm_mantissa = a_norm & 0x00FFFFFF;
936 b_norm_mantissa = b_norm & 0x00FFFFFF;
937 if (a_norm & 0x00800000)
938 a_norm_mantissa |= 0xFF000000;
940 if (b_norm & 0x00800000)
941 b_norm_mantissa |= 0xFF000000;
943 a_norm_exponent = a_norm >> 24;
944 b_norm_exponent = b_norm >> 24;
946 if (a_norm_mantissa == b_norm_mantissa && a_norm_exponent < b_norm_exponent)
947 return true;
949 if (a_norm_exponent == b_norm_exponent && a_norm_mantissa < b_norm_mantissa)
950 return true;
952 if (a_norm_exponent < b_norm_exponent) {
953 uint8_t exponent_difference;
955 exponent_difference = b_norm_exponent - a_norm_exponent;
957 if (exponent_difference >= 7)
958 return true;
960 while (exponent_difference--) {
961 b_norm_mantissa *= 10;
963 } else {
964 uint8_t exponent_difference;
966 exponent_difference = a_norm_exponent - b_norm_exponent;
968 if (exponent_difference >= 7)
969 return false;
971 while (exponent_difference--) {
972 a_norm_mantissa *= 10;
976 if (a_norm_mantissa < b_norm_mantissa)
977 return true;
979 return false;
982 static enum ft_result
983 float_ieee_11073_cmp_order(const fvalue_t *a, const fvalue_t *b, int *cmp)
985 if (float_ieee_11073_cmp_lt(a, b))
986 *cmp = -1;
987 else
988 *cmp = float_ieee_11073_cmp_eq(a, b) ? 0 : 1;
990 return FT_OK;
993 static bool
994 float_ieee_11073_is_zero(const fvalue_t *a)
996 return a->value.float_ieee_11073 == 0;
999 static unsigned
1000 float_ieee_11073_hash(const fvalue_t *fv)
1002 int64_t value = fv->value.float_ieee_11073;
1003 return g_int64_hash(&value);
1006 /*============================================================================*/
1008 void
1009 ftype_register_ieee_11073_float(void)
1012 Size: 16bits = 2 octets
1014 Exponent: 4 bits (signed integer - 2's complement)
1015 Mantissa: 12 bits (signed integer - 2's complement)
1016 Base: 10
1018 x = M * (10 ^ E)
1020 Exponent range: from -8 to 7
1021 Mantissa range: from -2048 to 2047 (4 digits)
1023 Special values:
1024 + INFINITY [exponent 0, mantissa +(2^11 -2) = 0x07FE]
1025 NaN (Not a Number) [exponent 0, mantissa +(2^11 -1) = 0x07FF]
1026 NRes (Not at this Resolution) [exponent 0, mantissa -(2^11) = 0x0800]
1027 Reserved for future use [exponent 0, mantissa -(2^11 -1) = 0x0801]
1028 - INFINITY [exponent 0, mantissa -(2^11 -2) = 0x0802]
1030 Note:
1031 be carefour when comparing: 1e == 10e-1 == 10e-2 == ... (solution: compare only if the lowest mantissa % 10 != 0)
1033 Example: 114 is 0x0072
1036 static const ftype_t sfloat_type = {
1037 FT_IEEE_11073_SFLOAT, /* ftype */
1038 2, /* wire_size */
1040 sfloat_ieee_11073_fvalue_new, /* new_value */
1041 NULL, /* copy_value */
1042 NULL, /* free_value */
1043 sfloat_ieee_11073_val_from_literal, /* val_from_literal */
1044 NULL, /* val_from_string */
1045 NULL, /* val_from_charconst */
1046 sfloat_ieee_11073_val_from_uinteger64, /* val_from_uinteger64 */
1047 sfloat_ieee_11073_val_from_sinteger64, /* val_from_sinteger64 */
1048 sfloat_ieee_11073_val_from_double, /* val_from_double */
1049 sfloat_ieee_11073_val_to_repr, /* val_to_string_repr */
1051 NULL, /* val_to_uinteger64 */
1052 NULL, /* val_to_sinteger64 */
1053 sfloat_ieee_11073_val_to_double, /* val_to_double */
1055 { .set_value_uinteger = sfloat_ieee_11073_value_set }, /* union set_value */
1056 { .get_value_uinteger = sfloat_ieee_11073_value_get }, /* union get_value */
1058 sfloat_ieee_11073_cmp_order,
1059 NULL, /* cmp_contains */
1060 NULL, /* cmp_matches */
1062 sfloat_ieee_11073_hash, /* hash */
1063 sfloat_ieee_11073_is_zero, /* is_zero */
1064 NULL, /* is_negative */
1065 NULL, /* len */
1066 NULL, /* slice */
1067 NULL, /* bitwise_and */
1068 NULL, /* unary_minus */
1069 NULL, /* add */
1070 NULL, /* subtract */
1071 NULL, /* multiply */
1072 NULL, /* divide */
1073 NULL, /* modulo */
1077 Size: 32bits = 4 octets
1079 Exponent: 1 octet (signed integer - 2's complement)
1080 Mantissa: 3 octets (signed integer - 2's complement)
1081 Base: 10
1083 x = M * (10 ^ E)
1085 Exponent range: from -128 to 127
1086 Mantissa range: from -8388608 to 8388607 (7 digits)
1088 Special values:
1089 + INFINITY [exponent 0, mantissa +(2^23 -2) = 0x007FFFFE]
1090 NaN (Not a Number) [exponent 0, mantissa +(2^23 -1) = 0x007FFFFF]
1091 NRes (Not at this Resolution) [exponent 0, mantissa -(2^23) = 0x00800000]
1092 Reserved for future use [exponent 0, mantissa -(2^23-1) = 0x00800001]
1093 - INFINITY [exponent 0, mantissa -(2^23 -2) = 0x00800002]
1095 Note:
1096 be carefour when comparing: 1e == 10e-1 == 10e-2 == ... (solution: compare only if the lowest mantissa % 10 != 0)
1098 Example: 36.4 is 0xFF00016C
1102 static const ftype_t float_type = {
1103 FT_IEEE_11073_FLOAT, /* ftype */
1104 4, /* wire_size */
1106 float_ieee_11073_fvalue_new, /* new_value */
1107 NULL, /* copy_value */
1108 NULL, /* free_value */
1109 float_ieee_11073_val_from_literal, /* val_from_literal */
1110 NULL, /* val_from_string */
1111 NULL, /* val_from_charconst */
1112 float_ieee_11073_val_from_uinteger64, /* val_from_uinteger64 */
1113 float_ieee_11073_val_from_sinteger64, /* val_from_sinteger64 */
1114 float_ieee_11073_val_from_double, /* val_from_double */
1115 float_ieee_11073_val_to_repr, /* val_to_string_repr */
1117 NULL, /* val_to_uinteger64 */
1118 NULL, /* val_to_sinteger64 */
1119 float_ieee_11073_val_to_double, /* val_to_double */
1121 { .set_value_uinteger = float_ieee_11073_value_set }, /* union set_value */
1122 { .get_value_uinteger = float_ieee_11073_value_get }, /* union get_value */
1124 float_ieee_11073_cmp_order,
1125 NULL, /* cmp_contains */
1126 NULL, /* cmp_matches */
1128 float_ieee_11073_hash, /* hash */
1129 float_ieee_11073_is_zero, /* is_zero */
1130 NULL, /* is_negative */
1131 NULL, /* len */
1132 NULL, /* slice */
1133 NULL, /* bitwise_and */
1134 NULL, /* unary_minus */
1135 NULL, /* add */
1136 NULL, /* subtract */
1137 NULL, /* multiply */
1138 NULL, /* divide */
1139 NULL, /* modulo */
1142 ftype_register(FT_IEEE_11073_SFLOAT, &sfloat_type);
1143 ftype_register(FT_IEEE_11073_FLOAT, &float_type);
1146 void
1147 ftype_register_pseudofields_ieee_11073_float(int proto)
1149 static int hf_ft_ieee_11073_sfloat;
1150 static int hf_ft_ieee_11073_float;
1152 static hf_register_info hf_ftypes[] = {
1153 { &hf_ft_ieee_11073_sfloat,
1154 { "FT_IEEE_11073_SFLOAT", "_ws.ftypes.ieee_11073_sfloat",
1155 FT_IEEE_11073_SFLOAT, BASE_NONE, NULL, 0x00,
1156 NULL, HFILL }
1158 { &hf_ft_ieee_11073_float,
1159 { "FT_IEEE_11073_FLOAT", "_ws.ftypes.ieee_11073_float",
1160 FT_IEEE_11073_FLOAT, BASE_NONE, NULL, 0x00,
1161 NULL, HFILL }
1165 proto_register_field_array(proto, hf_ftypes, array_length(hf_ftypes));
1169 * Editor modelines - https://www.wireshark.org/tools/modelines.html
1171 * Local variables:
1172 * c-basic-offset: 4
1173 * tab-width: 8
1174 * indent-tabs-mode: nil
1175 * End:
1177 * vi: set shiftwidth=4 tabstop=8 expandtab:
1178 * :indentSize=4:tabSize=8:noTabs=true: