epan/dissectors/pidl/samr/samr.cnf cnf_dissect_lsa_BinaryString => lsarpc_dissect_str...
[wireshark-sm.git] / epan / ftypes / ftype-ieee-11073-float.c
blob5d3ad54facf124c55a51fbe4c2af5c4fd2c15709
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 <stdio.h>
18 #include <wsutil/array.h>
20 #define DOUBLE_REPR_LENGTH 27
22 #define SFLOAT_VALUE_INFINITY_PLUS 0x07FE
23 #define SFLOAT_VALUE_NAN 0x07FF
24 #define SFLOAT_VALUE_NRES 0x0800
25 #define SFLOAT_VALUE_RFU 0x0801
26 #define SFLOAT_VALUE_INFINITY_MINUS 0x0802
28 #define FLOAT_VALUE_INFINITY_PLUS 0x007FFFFE
29 #define FLOAT_VALUE_NAN 0x007FFFFF
30 #define FLOAT_VALUE_NRES 0x00800000
31 #define FLOAT_VALUE_RFU 0x00800001
32 #define FLOAT_VALUE_INFINITY_MINUS 0x00800002
34 static void
35 sfloat_ieee_11073_fvalue_new(fvalue_t *fv)
37 fv->value.sfloat_ieee_11073 = 0x0000;
40 static bool
41 sfloat_ieee_11073_val_from_literal(fvalue_t *fv, const char *s, bool allow_partial_value _U_, char **err_msg _U_)
43 const char *i_char = s;
44 char c;
45 uint8_t mantissa_sign = 0;
46 uint32_t mantissa = 0;
47 int8_t exponent = 0;
48 bool fraction_mode = false;
49 const uint16_t mantissa_max = 0x07FF;
51 c = *i_char;
53 if (c== '\0')
54 return false;
56 if (c == '.')
57 return false;
59 if (c == '-' && s[1] == '.')
60 return false;
62 if (c == '-' && (s[1] == 'I' || s[1] == 'i')) {
63 if (!g_ascii_strcasecmp(s, "-INFINITY")) {
64 fv->value.sfloat_ieee_11073 = SFLOAT_VALUE_INFINITY_MINUS;
65 return true;
68 return false;
69 } else if (c == 'R' || c == 'r') {
70 if (!g_ascii_strcasecmp(s, "RFU")) {
71 fv->value.sfloat_ieee_11073 = SFLOAT_VALUE_RFU;
72 return true;
75 return false;
76 } else if (c == 'N' || c == 'n') {
77 if (!g_ascii_strcasecmp(s, "NRes")) {
78 fv->value.sfloat_ieee_11073 = SFLOAT_VALUE_NRES;
79 return true;
82 if (!g_ascii_strcasecmp(s, "NaN")) {
83 fv->value.sfloat_ieee_11073 = SFLOAT_VALUE_NAN;
84 return true;
87 return false;
88 } else if (c == '+') {
89 if (!g_ascii_strcasecmp(s, "+INFINITY")) {
90 fv->value.sfloat_ieee_11073 = SFLOAT_VALUE_INFINITY_PLUS;
91 return true;
94 return false;
97 if (c == '-') {
98 if (s[1] == '\0')
99 return false;
101 mantissa_sign = 1;
102 i_char += 1;
105 while (*i_char == '0') {
106 i_char += 1;
109 c = *i_char;
111 do {
112 if (c == '0') {
113 if (mantissa * 10 > (uint32_t) mantissa_max + mantissa_sign) {
114 exponent += 1;
115 if (exponent > 7)
116 return false;
117 } else {
118 mantissa *= 10;
120 } else if (c == '1') {
121 mantissa *= 10;
122 mantissa += 1;
123 } else if (c == '2') {
124 mantissa *= 10;
125 mantissa += 2;
126 } else if (c == '3') {
127 mantissa *= 10;
128 mantissa += 3;
129 } else if (c == '4') {
130 mantissa *= 10;
131 mantissa += 4;
132 } else if (c == '5') {
133 mantissa *= 10;
134 mantissa += 5;
135 } else if (c == '6') {
136 mantissa *= 10;
137 mantissa += 6;
138 } else if (c == '7') {
139 mantissa *= 10;
140 mantissa += 7;
141 } else if (c == '8') {
142 mantissa *= 10;
143 mantissa += 8;
144 } else if (c == '9') {
145 mantissa *= 10;
146 mantissa += 9;
147 } else if (c == '.') {
148 if (fraction_mode)
149 return false;
150 fraction_mode = true;
151 i_char += 1;
153 while (*i_char == '0') {
154 i_char += 1;
155 if (mantissa * 10 <= (uint32_t) mantissa_max + mantissa_sign) {
156 mantissa *= 10;
157 if (exponent > -8 - 4) /* -8 is min exponent; 4 is mantissa size */
158 exponent -= 1;
162 i_char -= 1;
163 } else if (c != '\0') {
164 /* NOTE: Maybe 5e-10, 5e3 notation should be also supported */
165 return false;
168 if (mantissa > (uint32_t) mantissa_max + mantissa_sign)
169 return false;
171 if (c != '.' && fraction_mode)
172 exponent -= 1;
174 i_char += 1;
175 } while ((c = *i_char));
177 if (mantissa_sign) {
178 mantissa = ~(mantissa - 1);
179 mantissa &= 0x0FFF;
182 /* Transform to normal form */
184 if (mantissa == 0)
185 exponent = 0;
187 while (mantissa > 0 && mantissa % 10 == 0 && exponent < 7) {
188 mantissa /= 10;
189 exponent += 1;
192 if (exponent < -8)
193 return false;
195 fv->value.sfloat_ieee_11073 = ((exponent & 0x0F) << 12) | mantissa;
197 return true;
200 static bool
201 sfloat_ieee_11073_val_from_uinteger64(fvalue_t *fv, const char *s, uint64_t value _U_, char **err_msg)
203 return sfloat_ieee_11073_val_from_literal(fv, s, FALSE, err_msg);
206 static bool
207 sfloat_ieee_11073_val_from_sinteger64(fvalue_t *fv, const char *s, int64_t value _U_, char **err_msg)
209 return sfloat_ieee_11073_val_from_literal(fv, s, FALSE, err_msg);
212 static bool
213 sfloat_ieee_11073_val_from_double(fvalue_t *fv, const char *s, double value _U_, char **err_msg)
215 return sfloat_ieee_11073_val_from_literal(fv, s, FALSE, err_msg);
218 static char *
219 sfloat_ieee_11073_val_to_repr(wmem_allocator_t *scope, const fvalue_t *fv, ftrepr_t rtype _U_, int field_display _U_)
221 int8_t exponent;
222 uint16_t mantissa;
223 uint16_t mantissa_sign;
224 uint32_t offset = 0;
225 char mantissa_buf[5];
226 char *mantissa_str;
227 uint8_t mantissa_digits;
229 /* Predefined: +INFINITY, -INFINITY, RFU, NRes, NaN */
230 if (fv->value.sfloat_ieee_11073 >= 0x07FE && fv->value.sfloat_ieee_11073 <= 0x0802) {
231 char *s = NULL;
233 switch (fv->value.sfloat_ieee_11073) {
234 case SFLOAT_VALUE_INFINITY_PLUS:
235 s = "+INFINITY";
236 break;
237 case SFLOAT_VALUE_NAN:
238 s = "NaN";
239 break;
240 case SFLOAT_VALUE_NRES:
241 s = "NRes";
242 break;
243 case SFLOAT_VALUE_RFU:
244 s = "RFU";
245 break;
246 case SFLOAT_VALUE_INFINITY_MINUS:
247 s = "-INFINITY";
248 break;
250 return wmem_strdup(scope, s);
253 /* Longest Signed Float Number: -0.00002048 (11 characters without NULL) */
254 /* Longest Signed Float Number -0.00000001 */
255 /* Longest Signed Nonfloat Number: -20480000000 (12 characters without NULL) */
256 char buf[13];
258 exponent = fv->value.sfloat_ieee_11073 >> 12;
259 if (exponent & 0x8)
260 exponent |= 0xF0; /* It is signed (4bits), so make it signed in int8_t */
261 mantissa = fv->value.sfloat_ieee_11073 & 0x07FF;
262 mantissa_sign = (fv->value.sfloat_ieee_11073 & 0x0800);
263 if (mantissa_sign)
264 mantissa = -((int16_t)mantissa | 0xF800);
266 if (mantissa == 0) {
267 return wmem_strdup(scope, "0");
270 if (mantissa_sign) {
271 buf[0] = '-';
272 offset += 1;
275 mantissa_digits = snprintf(mantissa_buf, sizeof(mantissa_buf), "%"PRIu16, mantissa);
276 mantissa_str = mantissa_buf;
278 if (exponent == 0) {
279 memcpy(buf + offset, mantissa_str, mantissa_digits);
280 offset += mantissa_digits;
281 } else if (exponent > 0) {
282 memcpy(buf + offset, mantissa_str, mantissa_digits);
283 offset += mantissa_digits;
285 memset(buf + offset, '0', exponent);
286 offset += exponent;
287 } else /* if (exponent < 0)*/ {
288 if (-exponent < mantissa_digits) {
289 memcpy(buf + offset, mantissa_str, mantissa_digits + exponent);
290 offset += mantissa_digits + exponent;
292 buf[offset] = '.';
293 offset += 1;
295 memcpy(buf + offset, mantissa_str + mantissa_digits + exponent, -exponent);
296 offset += -exponent;
297 } else {
298 buf[offset] = '0';
299 offset += 1;
301 buf[offset] = '.';
302 offset += 1;
304 if (-exponent - mantissa_digits > 0) {
305 memset(buf + offset, '0', -exponent - mantissa_digits);
306 offset += -exponent - mantissa_digits;
309 memcpy(buf + offset, mantissa_str, mantissa_digits);
310 offset += mantissa_digits;
314 buf[offset] = '\0';
315 return wmem_strdup(scope, buf);
318 static void
319 sfloat_ieee_11073_value_set(fvalue_t *fv, uint32_t value)
321 fv->value.sfloat_ieee_11073 = (uint16_t) value;
324 static uint32_t
325 sfloat_ieee_11073_value_get(fvalue_t *fv)
327 return (uint32_t) fv->value.sfloat_ieee_11073;
330 static uint16_t sfloat_to_normal_form(uint16_t value)
332 int8_t exponent;
333 uint16_t mantissa;
334 uint8_t mantissa_sign;
336 if (value >= 0x07FE && value <= 0x0802) /* Save special values */
337 return value;
339 mantissa = value & 0x07FF;
340 if (value & 0x0800) {
341 mantissa = -((int16_t)mantissa | 0xF800);
342 mantissa_sign = 1;
343 } else {
344 mantissa_sign = 0;
347 exponent = value >> 12;
349 if (exponent & 0x08) {
350 exponent |= 0xF0;
353 while ((!(mantissa % 10)) && mantissa != 0) {
354 mantissa /= 10;
356 if (exponent == 7)
357 break;
359 exponent += 1;
362 return ((((exponent & 0x80) ? 0x8 : 0x0 ) | (exponent & 0x7)) << 12) | (mantissa_sign << 11) | mantissa;
365 static bool
366 sfloat_ieee_11073_cmp_eq(const fvalue_t *a, const fvalue_t *b)
368 return sfloat_to_normal_form(a->value.sfloat_ieee_11073) == sfloat_to_normal_form(b->value.sfloat_ieee_11073);
371 static bool
372 sfloat_ieee_11073_cmp_lt(const fvalue_t *a, const fvalue_t *b)
374 uint16_t a_norm;
375 uint16_t b_norm;
376 int16_t a_norm_mantissa;
377 int16_t b_norm_mantissa;
378 int8_t a_norm_exponent;
379 int8_t b_norm_exponent;
381 a_norm = sfloat_to_normal_form(a->value.sfloat_ieee_11073);
382 b_norm = sfloat_to_normal_form(b->value.sfloat_ieee_11073);
384 if (a_norm == b_norm)
385 return false;
387 switch (a_norm) {
388 case SFLOAT_VALUE_NAN:
389 case SFLOAT_VALUE_NRES:
390 case SFLOAT_VALUE_RFU:
391 case SFLOAT_VALUE_INFINITY_PLUS:
392 return false;
393 case SFLOAT_VALUE_INFINITY_MINUS:
394 switch (b_norm) {
395 case SFLOAT_VALUE_NAN:
396 case SFLOAT_VALUE_NRES:
397 case SFLOAT_VALUE_RFU:
398 case SFLOAT_VALUE_INFINITY_MINUS: /* Dead, informative case */
399 return false;
400 case SFLOAT_VALUE_INFINITY_PLUS:
401 default:
402 return true;
406 a_norm_mantissa = a_norm & 0x0FFF;
407 b_norm_mantissa = b_norm & 0x0FFF;
408 if (a_norm & 0x0800)
409 a_norm_mantissa |= 0xFFFFF000;
411 if (b_norm & 0x0800)
412 b_norm_mantissa |= 0xFFFFF000;
414 a_norm_exponent = a_norm >> 12;
415 b_norm_exponent = b_norm >> 12;
417 if (a_norm_exponent & 0x08) {
418 a_norm_exponent |= 0xF0;
421 if (b_norm_exponent & 0x08) {
422 b_norm_exponent |= 0xF0;
425 if (a_norm_mantissa == b_norm_mantissa && a_norm_exponent < b_norm_exponent)
426 return true;
428 if (a_norm_exponent == b_norm_exponent && a_norm_mantissa < b_norm_mantissa)
429 return true;
431 if (a_norm_exponent < b_norm_exponent) {
432 uint8_t exponent_difference;
434 exponent_difference = b_norm_exponent - a_norm_exponent;
436 if (exponent_difference >= 4)
437 return true;
439 while (exponent_difference--) {
440 b_norm_mantissa *= 10;
442 } else {
443 uint8_t exponent_difference;
445 exponent_difference = a_norm_exponent - b_norm_exponent;
447 if (exponent_difference >= 4)
448 return false;
450 while (exponent_difference--) {
451 a_norm_mantissa *= 10;
455 if (a_norm_mantissa < b_norm_mantissa)
456 return true;
458 return false;
461 static enum ft_result
462 sfloat_ieee_11073_cmp_order(const fvalue_t *a, const fvalue_t *b, int *cmp)
464 if (sfloat_ieee_11073_cmp_lt(a, b))
465 *cmp = -1;
466 else
467 *cmp = sfloat_ieee_11073_cmp_eq(a, b) ? 0 : 1;
469 return FT_OK;
472 static bool
473 sfloat_ieee_11073_is_zero(const fvalue_t *a)
475 return a->value.sfloat_ieee_11073 == 0;
478 static unsigned
479 sfloat_ieee_11073_hash(const fvalue_t *fv)
481 int64_t value = fv->value.sfloat_ieee_11073;
482 return g_int64_hash(&value);
485 /*============================================================================*/
487 static void
488 float_ieee_11073_fvalue_new(fvalue_t *fv)
490 fv->value.float_ieee_11073 = 0x0000;
493 static bool
494 float_ieee_11073_val_from_literal(fvalue_t *fv, const char *s, bool allow_partial_value _U_, char **err_msg _U_)
496 const char *i_char = s;
497 char c;
498 uint8_t mantissa_sign = 0;
499 uint32_t mantissa = 0;
500 int16_t exponent = 0;
501 bool fraction_mode = false;
502 const uint32_t mantissa_max = 0x007FFFFF;
504 c = *i_char;
506 if (c== '\0')
507 return false;
509 if (c == '.')
510 return false;
512 if (c == '-' && s[1] == '.')
513 return false;
515 if (c == '-' && (s[1] == 'I' || s[1] == 'i')) {
516 if (!g_ascii_strcasecmp(s, "-INFINITY")) {
517 fv->value.float_ieee_11073 = FLOAT_VALUE_INFINITY_MINUS;
518 return true;
521 return false;
522 } else if (c == 'R' || c == 'r') {
523 if (!g_ascii_strcasecmp(s, "RFU")) {
524 fv->value.float_ieee_11073 = FLOAT_VALUE_RFU;
525 return true;
528 return false;
529 } else if (c == 'N' || c == 'n') {
530 if (!g_ascii_strcasecmp(s, "NRes")) {
531 fv->value.float_ieee_11073 = FLOAT_VALUE_NRES;
532 return true;
535 if (!g_ascii_strcasecmp(s, "NaN")) {
536 fv->value.float_ieee_11073 = FLOAT_VALUE_NAN;
537 return true;
540 return false;
541 } else if (c == '+') {
542 if (!g_ascii_strcasecmp(s, "+INFINITY")) {
543 fv->value.float_ieee_11073 = FLOAT_VALUE_INFINITY_PLUS;
544 return true;
547 return false;
550 if (c == '-') {
551 if (s[1] == '\0')
552 return false;
554 mantissa_sign = 1;
555 i_char += 1;
558 while (*i_char == '0') {
559 i_char += 1;
562 c = *i_char;
564 do {
565 if (c == '0') {
566 if (mantissa * 10 > mantissa_sign + mantissa_max) {
567 exponent += 1;
568 if (exponent <= 127)
569 return false;
570 } else {
571 mantissa *= 10;
573 } else if (c == '1') {
574 mantissa *= 10;
575 mantissa += 1;
576 } else if (c == '2') {
577 mantissa *= 10;
578 mantissa += 2;
579 } else if (c == '3') {
580 mantissa *= 10;
581 mantissa += 3;
582 } else if (c == '4') {
583 mantissa *= 10;
584 mantissa += 4;
585 } else if (c == '5') {
586 mantissa *= 10;
587 mantissa += 5;
588 } else if (c == '6') {
589 mantissa *= 10;
590 mantissa += 6;
591 } else if (c == '7') {
592 mantissa *= 10;
593 mantissa += 7;
594 } else if (c == '8') {
595 mantissa *= 10;
596 mantissa += 8;
597 } else if (c == '9') {
598 mantissa *= 10;
599 mantissa += 9;
600 } else if (c == '.') {
601 if (fraction_mode)
602 return false;
603 fraction_mode = true;
604 i_char += 1;
606 while (*i_char == '0') {
607 i_char += 1;
608 if (mantissa * 10 <= mantissa_max + mantissa_sign) {
609 mantissa *= 10;
610 if (exponent > -128 - 7) /* -8 is min exponent; 4 is mantissa size */
611 exponent -= 1;
615 i_char -= 1;
616 } else if (c != '\0') {
617 /* NOTE: Maybe 5e-10, 5e3 notation should be also supported */
618 return false;
621 if (mantissa > mantissa_max + mantissa_sign)
622 return false;
624 if (c != '.' && fraction_mode)
625 exponent -= 1;
627 i_char += 1;
628 } while ((c = *i_char));
630 if (mantissa_sign) {
631 mantissa = ~(mantissa - 1);
632 mantissa &= 0x00FFFFFF;
635 /* Transform to normal form */
637 if (mantissa == 0)
638 exponent = 0;
640 while (mantissa > 0 && mantissa % 10 == 0 && exponent < 127) {
641 mantissa /= 10;
642 exponent += 1;
645 if (exponent < -128)
646 return false;
648 fv->value.float_ieee_11073 = ((exponent & 0xFF) << 24) | mantissa;
650 return true;
653 static bool
654 float_ieee_11073_val_from_uinteger64(fvalue_t *fv, const char *s, uint64_t value _U_, char **err_msg)
656 return float_ieee_11073_val_from_literal(fv, s, FALSE, err_msg);
659 static bool
660 float_ieee_11073_val_from_sinteger64(fvalue_t *fv, const char *s, int64_t value _U_, char **err_msg)
662 return float_ieee_11073_val_from_literal(fv, s, FALSE, err_msg);
665 static bool
666 float_ieee_11073_val_from_double(fvalue_t *fv, const char *s, double value _U_, char **err_msg)
668 return float_ieee_11073_val_from_literal(fv, s, FALSE, err_msg);
671 static char *
672 float_ieee_11073_val_to_repr(wmem_allocator_t *scope, const fvalue_t *fv, ftrepr_t rtype _U_, int field_display _U_)
674 int8_t exponent;
675 uint32_t mantissa;
676 uint32_t mantissa_sign;
677 uint32_t offset = 0;
678 char mantissa_buf[8];
679 char *mantissa_str;
680 uint8_t mantissa_digits;
682 /* Predefined: +INFINITY, -INFINITY, RFU, NRes, NaN */
683 if (fv->value.float_ieee_11073 >= 0x007FFFFE && fv->value.float_ieee_11073 <= 0x00800002) {
684 char *s = NULL;
685 switch (fv->value.float_ieee_11073) {
686 case FLOAT_VALUE_INFINITY_PLUS:
687 s = "+INFINITY";
688 break;
689 case FLOAT_VALUE_NAN:
690 s = "NaN";
691 break;
692 case FLOAT_VALUE_NRES:
693 s = "NRes";
694 break;
695 case FLOAT_VALUE_RFU:
696 s = "RFU";
697 break;
698 case FLOAT_VALUE_INFINITY_MINUS:
699 s = "-INFINITY";
700 break;
702 return wmem_strdup(scope, s);
705 /* Longest Signed Nonfloat Number: -8388608*(10^-128) (1 character for sign, 7 for mantisa digits, 127 zeros, 1 character for NULL) */
706 char buf[136];
708 exponent = fv->value.float_ieee_11073 >> 24;
710 mantissa = fv->value.float_ieee_11073 & 0x007FFFFF;
711 mantissa_sign = (fv->value.float_ieee_11073 & 0x00800000);
712 if (mantissa_sign)
713 mantissa = (uint32_t)(-((int32_t)(mantissa | 0xFF000000)));
715 if (mantissa == 0) {
716 return wmem_strdup(scope, "0");
719 if (mantissa_sign) {
720 buf[0] = '-';
721 offset += 1;
724 mantissa_digits = snprintf(mantissa_buf, sizeof(mantissa_buf), "%"PRIu32, mantissa);
725 mantissa_str = mantissa_buf;
727 if (exponent == 0) {
728 memcpy(buf + offset, mantissa_str, mantissa_digits);
729 offset += mantissa_digits;
730 } else if (exponent > 0) {
731 memcpy(buf + offset, mantissa_str, mantissa_digits);
732 offset += mantissa_digits;
734 memset(buf + offset, '0', exponent);
735 offset += exponent;
736 } else /* if (exponent < 0)*/ {
737 if (-exponent < mantissa_digits) {
738 memcpy(buf + offset, mantissa_str, mantissa_digits + exponent);
739 offset += mantissa_digits + exponent;
741 buf[offset] = '.';
742 offset += 1;
744 memcpy(buf + offset, mantissa_str + mantissa_digits + exponent, -exponent);
745 offset += -exponent;
746 } else {
747 buf[offset] = '0';
748 offset += 1;
750 buf[offset] = '.';
751 offset += 1;
753 if (-exponent - mantissa_digits > 0) {
754 memset(buf + offset, '0', -exponent - mantissa_digits);
755 offset += -exponent - mantissa_digits;
758 memcpy(buf + offset, mantissa_str, mantissa_digits);
759 offset += mantissa_digits;
763 buf[offset] = '\0';
764 return wmem_strdup(scope, buf);
767 static void
768 float_ieee_11073_value_set(fvalue_t *fv, uint32_t value)
770 fv->value.float_ieee_11073 = value;
773 static uint32_t
774 float_ieee_11073_value_get(fvalue_t *fv)
776 return fv->value.float_ieee_11073;
779 static uint32_t float_to_normal_form(uint32_t value)
781 int8_t exponent;
782 uint16_t mantissa;
783 uint8_t mantissa_sign;
785 if (value >= 0x007FFFFE && value <= 0x00800002) /* Save special values */
786 return value;
788 mantissa = value & 0x907FFFFF;
789 if (value & 0x00800000) {
790 mantissa = (uint32_t)(-((int32_t)(mantissa | 0xFF000000)));
791 mantissa_sign = 1;
792 } else {
793 mantissa_sign = 0;
796 exponent = value >> 24;
798 while ((!(mantissa % 10)) && mantissa != 0) {
799 mantissa /= 10;
801 if (exponent == 127)
802 break;
804 exponent += 1;
807 return (exponent << 24) | (mantissa_sign << 23) | mantissa;
810 static bool
811 float_ieee_11073_cmp_eq(const fvalue_t *a, const fvalue_t *b)
813 return float_to_normal_form(a->value.float_ieee_11073) == float_to_normal_form(b->value.float_ieee_11073);
816 static bool
817 float_ieee_11073_cmp_lt(const fvalue_t *a, const fvalue_t *b)
819 uint32_t a_norm;
820 uint32_t b_norm;
821 int32_t a_norm_mantissa;
822 int32_t b_norm_mantissa;
823 int8_t a_norm_exponent;
824 int8_t b_norm_exponent;
826 a_norm = float_to_normal_form(a->value.float_ieee_11073);
827 b_norm = float_to_normal_form(b->value.float_ieee_11073);
829 if (a_norm == b_norm)
830 return false;
832 switch (a_norm) {
833 case FLOAT_VALUE_NAN:
834 case FLOAT_VALUE_NRES:
835 case FLOAT_VALUE_RFU:
836 case FLOAT_VALUE_INFINITY_PLUS:
837 return false;
838 case FLOAT_VALUE_INFINITY_MINUS:
839 switch (b_norm) {
840 case FLOAT_VALUE_NAN:
841 case FLOAT_VALUE_NRES:
842 case FLOAT_VALUE_RFU:
843 case FLOAT_VALUE_INFINITY_MINUS: /* Dead, informative case */
844 return false;
845 case FLOAT_VALUE_INFINITY_PLUS:
846 default:
847 return true;
851 a_norm_mantissa = a_norm & 0x00FFFFFF;
852 b_norm_mantissa = b_norm & 0x00FFFFFF;
853 if (a_norm & 0x00800000)
854 a_norm_mantissa |= 0xFF000000;
856 if (b_norm & 0x00800000)
857 b_norm_mantissa |= 0xFF000000;
859 a_norm_exponent = a_norm >> 24;
860 b_norm_exponent = b_norm >> 24;
862 if (a_norm_mantissa == b_norm_mantissa && a_norm_exponent < b_norm_exponent)
863 return true;
865 if (a_norm_exponent == b_norm_exponent && a_norm_mantissa < b_norm_mantissa)
866 return true;
868 if (a_norm_exponent < b_norm_exponent) {
869 uint8_t exponent_difference;
871 exponent_difference = b_norm_exponent - a_norm_exponent;
873 if (exponent_difference >= 7)
874 return true;
876 while (exponent_difference--) {
877 b_norm_mantissa *= 10;
879 } else {
880 uint8_t exponent_difference;
882 exponent_difference = a_norm_exponent - b_norm_exponent;
884 if (exponent_difference >= 7)
885 return false;
887 while (exponent_difference--) {
888 a_norm_mantissa *= 10;
892 if (a_norm_mantissa < b_norm_mantissa)
893 return true;
895 return false;
898 static enum ft_result
899 float_ieee_11073_cmp_order(const fvalue_t *a, const fvalue_t *b, int *cmp)
901 if (float_ieee_11073_cmp_lt(a, b))
902 *cmp = -1;
903 else
904 *cmp = float_ieee_11073_cmp_eq(a, b) ? 0 : 1;
906 return FT_OK;
909 static bool
910 float_ieee_11073_is_zero(const fvalue_t *a)
912 return a->value.float_ieee_11073 == 0;
915 static unsigned
916 float_ieee_11073_hash(const fvalue_t *fv)
918 int64_t value = fv->value.float_ieee_11073;
919 return g_int64_hash(&value);
922 /*============================================================================*/
924 void
925 ftype_register_ieee_11073_float(void)
928 Size: 16bits = 2 octets
930 Exponent: 4 bits (signed integer - 2's complement)
931 Mantissa: 12 bits (signed integer - 2's complement)
932 Base: 10
934 x = M * (10 ^ E)
936 Exponent range: from -8 to 7
937 Mantissa range: from -2048 to 2047 (4 digits)
939 Special values:
940 + INFINITY [exponent 0, mantissa +(2^11 -2) = 0x07FE]
941 NaN (Not a Number) [exponent 0, mantissa +(2^11 -1) = 0x07FF]
942 NRes (Not at this Resolution) [exponent 0, mantissa -(2^11) = 0x0800]
943 Reserved for future use [exponent 0, mantissa -(2^11 -1) = 0x0801]
944 - INFINITY [exponent 0, mantissa -(2^11 -2) = 0x0802]
946 Note:
947 be carefour when comparing: 1e == 10e-1 == 10e-2 == ... (solution: compare only if the lowest mantissa % 10 != 0)
949 Example: 114 is 0x0072
952 static const ftype_t sfloat_type = {
953 FT_IEEE_11073_SFLOAT, /* ftype */
954 2, /* wire_size */
956 sfloat_ieee_11073_fvalue_new, /* new_value */
957 NULL, /* copy_value */
958 NULL, /* free_value */
959 sfloat_ieee_11073_val_from_literal, /* val_from_literal */
960 NULL, /* val_from_string */
961 NULL, /* val_from_charconst */
962 sfloat_ieee_11073_val_from_uinteger64, /* val_from_uinteger64 */
963 sfloat_ieee_11073_val_from_sinteger64, /* val_from_sinteger64 */
964 sfloat_ieee_11073_val_from_double, /* val_from_double */
965 sfloat_ieee_11073_val_to_repr, /* val_to_string_repr */
967 NULL, /* val_to_uinteger64 */
968 NULL, /* val_to_sinteger64 */
969 NULL, /* val_to_double */
971 { .set_value_uinteger = sfloat_ieee_11073_value_set }, /* union set_value */
972 { .get_value_uinteger = sfloat_ieee_11073_value_get }, /* union get_value */
974 sfloat_ieee_11073_cmp_order,
975 NULL, /* cmp_contains */
976 NULL, /* cmp_matches */
978 sfloat_ieee_11073_hash, /* hash */
979 sfloat_ieee_11073_is_zero, /* is_zero */
980 NULL, /* is_negative */
981 NULL, /* len */
982 NULL, /* slice */
983 NULL, /* bitwise_and */
984 NULL, /* unary_minus */
985 NULL, /* add */
986 NULL, /* subtract */
987 NULL, /* multiply */
988 NULL, /* divide */
989 NULL, /* modulo */
993 Size: 32bits = 4 octets
995 Exponent: 1 octet (signed integer - 2's complement)
996 Mantissa: 3 octets (signed integer - 2's complement)
997 Base: 10
999 x = M * (10 ^ E)
1001 Exponent range: from -128 to 127
1002 Mantissa range: from -8388608 to 8388607 (7 digits)
1004 Special values:
1005 + INFINITY [exponent 0, mantissa +(2^23 -2) = 0x007FFFFE]
1006 NaN (Not a Number) [exponent 0, mantissa +(2^23 -1) = 0x007FFFFF]
1007 NRes (Not at this Resolution) [exponent 0, mantissa -(2^23) = 0x00800000]
1008 Reserved for future use [exponent 0, mantissa -(2^23-1) = 0x00800001]
1009 - INFINITY [exponent 0, mantissa -(2^23 -2) = 0x00800002]
1011 Note:
1012 be carefour when comparing: 1e == 10e-1 == 10e-2 == ... (solution: compare only if the lowest mantissa % 10 != 0)
1014 Example: 36.4 is 0xFF00016C
1018 static const ftype_t float_type = {
1019 FT_IEEE_11073_FLOAT, /* ftype */
1020 4, /* wire_size */
1022 float_ieee_11073_fvalue_new, /* new_value */
1023 NULL, /* copy_value */
1024 NULL, /* free_value */
1025 float_ieee_11073_val_from_literal, /* val_from_literal */
1026 NULL, /* val_from_string */
1027 NULL, /* val_from_charconst */
1028 float_ieee_11073_val_from_uinteger64, /* val_from_uinteger64 */
1029 float_ieee_11073_val_from_sinteger64, /* val_from_sinteger64 */
1030 float_ieee_11073_val_from_double, /* val_from_double */
1031 float_ieee_11073_val_to_repr, /* val_to_string_repr */
1033 NULL, /* val_to_uinteger64 */
1034 NULL, /* val_to_sinteger64 */
1035 NULL, /* val_to_double */
1037 { .set_value_uinteger = float_ieee_11073_value_set }, /* union set_value */
1038 { .get_value_uinteger = float_ieee_11073_value_get }, /* union get_value */
1040 float_ieee_11073_cmp_order,
1041 NULL, /* cmp_contains */
1042 NULL, /* cmp_matches */
1044 float_ieee_11073_hash, /* hash */
1045 float_ieee_11073_is_zero, /* is_zero */
1046 NULL, /* is_negative */
1047 NULL, /* len */
1048 NULL, /* slice */
1049 NULL, /* bitwise_and */
1050 NULL, /* unary_minus */
1051 NULL, /* add */
1052 NULL, /* subtract */
1053 NULL, /* multiply */
1054 NULL, /* divide */
1055 NULL, /* modulo */
1058 ftype_register(FT_IEEE_11073_SFLOAT, &sfloat_type);
1059 ftype_register(FT_IEEE_11073_FLOAT, &float_type);
1062 void
1063 ftype_register_pseudofields_ieee_11073_float(int proto)
1065 static int hf_ft_ieee_11073_sfloat;
1066 static int hf_ft_ieee_11073_float;
1068 static hf_register_info hf_ftypes[] = {
1069 { &hf_ft_ieee_11073_sfloat,
1070 { "FT_IEEE_11073_SFLOAT", "_ws.ftypes.ieee_11073_sfloat",
1071 FT_IEEE_11073_SFLOAT, BASE_NONE, NULL, 0x00,
1072 NULL, HFILL }
1074 { &hf_ft_ieee_11073_float,
1075 { "FT_IEEE_11073_FLOAT", "_ws.ftypes.ieee_11073_float",
1076 FT_IEEE_11073_FLOAT, BASE_NONE, NULL, 0x00,
1077 NULL, HFILL }
1081 proto_register_field_array(proto, hf_ftypes, array_length(hf_ftypes));
1085 * Editor modelines - https://www.wireshark.org/tools/modelines.html
1087 * Local variables:
1088 * c-basic-offset: 4
1089 * tab-width: 8
1090 * indent-tabs-mode: nil
1091 * End:
1093 * vi: set shiftwidth=4 tabstop=8 expandtab:
1094 * :indentSize=4:tabSize=8:noTabs=true: