1 /*
2 * Wireshark - Network traffic analyzer
3 * By Gerald Combs <gerald@wireshark.org>
4 * Copyright 2001 Gerald Combs
5 *
6 * SPDX-License-Identifier: GPL-2.0-or-later
7 */
8
9 #include "config.h"
10
11 #include <stdio.h>
12 #include <ftypes-int.h>
13 #include <math.h>
14 #include <errno.h>
15 #include <float.h>
16
17 #include "strutil.h"
18
19 static void
double_fvalue_new(fvalue_t * fv)20 double_fvalue_new(fvalue_t *fv)
21 {
22 fv->value.floating = 0.0;
23 }
24
25 static void
double_fvalue_set_floating(fvalue_t * fv,gdouble value)26 double_fvalue_set_floating(fvalue_t *fv, gdouble value)
27 {
28 fv->value.floating = value;
29 }
30
31 static double
value_get_floating(fvalue_t * fv)32 value_get_floating(fvalue_t *fv)
33 {
34 return fv->value.floating;
35 }
36
37 static gboolean
val_from_unparsed(fvalue_t * fv,const char * s,gboolean allow_partial_value _U_,gchar ** err_msg)38 val_from_unparsed(fvalue_t *fv, const char *s, gboolean allow_partial_value _U_, gchar **err_msg)
39 {
40 char *endptr = NULL;
41
42 fv->value.floating = g_ascii_strtod(s, &endptr);
43
44 if (endptr == s || *endptr != '\0') {
45 /* This isn't a valid number. */
46 if (err_msg != NULL)
47 *err_msg = g_strdup_printf("\"%s\" is not a valid number.", s);
48 return FALSE;
49 }
50 if (errno == ERANGE) {
51 if (fv->value.floating == 0) {
52 if (err_msg != NULL)
53 *err_msg = g_strdup_printf("\"%s\" causes floating-point underflow.", s);
54 }
55 else if (fv->value.floating == HUGE_VAL) {
56 if (err_msg != NULL)
57 *err_msg = g_strdup_printf("\"%s\" causes floating-point overflow.", s);
58 }
59 else {
60 if (err_msg != NULL)
61 *err_msg = g_strdup_printf("\"%s\" is not a valid floating-point number.",
62 s);
63 }
64 return FALSE;
65 }
66
67 return TRUE;
68 }
69
70 static int
float_val_repr_len(fvalue_t * fv _U_,ftrepr_t rtype _U_,int field_display _U_)71 float_val_repr_len(fvalue_t *fv _U_, ftrepr_t rtype _U_, int field_display _U_)
72 {
73 return G_ASCII_DTOSTR_BUF_SIZE;
74 }
75
76 static void
float_val_to_repr(fvalue_t * fv,ftrepr_t rtype _U_,int field_display _U_,char * buf,unsigned int size)77 float_val_to_repr(fvalue_t *fv, ftrepr_t rtype _U_, int field_display _U_, char *buf, unsigned int size)
78 {
79 g_ascii_formatd(buf, size, "%." G_STRINGIFY(FLT_DIG) "g", fv->value.floating);
80 }
81
82 static int
double_val_repr_len(fvalue_t * fv _U_,ftrepr_t rtype _U_,int field_display _U_)83 double_val_repr_len(fvalue_t *fv _U_, ftrepr_t rtype _U_, int field_display _U_)
84 {
85 return G_ASCII_DTOSTR_BUF_SIZE;
86 }
87
88 static void
double_val_to_repr(fvalue_t * fv,ftrepr_t rtype _U_,int field_display _U_,char * buf,unsigned int size)89 double_val_to_repr(fvalue_t *fv, ftrepr_t rtype _U_, int field_display _U_, char *buf, unsigned int size)
90 {
91 g_ascii_formatd(buf, size, "%." G_STRINGIFY(DBL_DIG) "g", fv->value.floating);
92 }
93
94 static gboolean
cmp_eq(const fvalue_t * a,const fvalue_t * b)95 cmp_eq(const fvalue_t *a, const fvalue_t *b)
96 {
97 return a->value.floating == b->value.floating;
98 }
99
100 static gboolean
cmp_ne(const fvalue_t * a,const fvalue_t * b)101 cmp_ne(const fvalue_t *a, const fvalue_t *b)
102 {
103 return a->value.floating != b->value.floating;
104 }
105
106 static gboolean
cmp_gt(const fvalue_t * a,const fvalue_t * b)107 cmp_gt(const fvalue_t *a, const fvalue_t *b)
108 {
109 return a->value.floating > b->value.floating;
110 }
111
112 static gboolean
cmp_ge(const fvalue_t * a,const fvalue_t * b)113 cmp_ge(const fvalue_t *a, const fvalue_t *b)
114 {
115 return a->value.floating >= b->value.floating;
116 }
117
118 static gboolean
cmp_lt(const fvalue_t * a,const fvalue_t * b)119 cmp_lt(const fvalue_t *a, const fvalue_t *b)
120 {
121 return a->value.floating < b->value.floating;
122 }
123
124 static gboolean
cmp_le(const fvalue_t * a,const fvalue_t * b)125 cmp_le(const fvalue_t *a, const fvalue_t *b)
126 {
127 return a->value.floating <= b->value.floating;
128 }
129
130 void
ftype_register_double(void)131 ftype_register_double(void)
132 {
133
134 static ftype_t float_type = {
135 FT_FLOAT, /* ftype */
136 "FT_FLOAT", /* name */
137 "Floating point (single-precision)", /* pretty_name */
138 0, /* wire_size */
139 double_fvalue_new, /* new_value */
140 NULL, /* free_value */
141 val_from_unparsed, /* val_from_unparsed */
142 NULL, /* val_from_string */
143 float_val_to_repr, /* val_to_string_repr */
144 float_val_repr_len, /* len_string_repr */
145
146 { .set_value_floating = double_fvalue_set_floating }, /* union set_value */
147 { .get_value_floating = value_get_floating }, /* union get_value */
148
149 cmp_eq,
150 cmp_ne,
151 cmp_gt,
152 cmp_ge,
153 cmp_lt,
154 cmp_le,
155 NULL, /* cmp_bitwise_and */
156 NULL, /* cmp_contains */
157 NULL, /* cmp_matches */
158
159 NULL,
160 NULL,
161 };
162
163 static ftype_t double_type = {
164 FT_DOUBLE, /* ftype */
165 "FT_DOUBLE", /* name */
166 "Floating point (double-precision)", /* pretty_name */
167 0, /* wire_size */
168 double_fvalue_new, /* new_value */
169 NULL, /* free_value */
170 val_from_unparsed, /* val_from_unparsed */
171 NULL, /* val_from_string */
172 double_val_to_repr, /* val_to_string_repr */
173 double_val_repr_len, /* len_string_repr */
174
175 { .set_value_floating = double_fvalue_set_floating }, /* union set_value */
176 { .get_value_floating = value_get_floating }, /* union get_value */
177
178 cmp_eq,
179 cmp_ne,
180 cmp_gt,
181 cmp_ge,
182 cmp_lt,
183 cmp_le,
184 NULL, /* cmp_bitwise_and */
185 NULL, /* cmp_contains */
186 NULL, /* cmp_matches */
187
188 NULL,
189 NULL,
190 };
191
192 ftype_register(FT_FLOAT, &float_type);
193 ftype_register(FT_DOUBLE, &double_type);
194 }
195
196 /*
197 * Editor modelines - https://www.wireshark.org/tools/modelines.html
198 *
199 * Local variables:
200 * c-basic-offset: 8
201 * tab-width: 8
202 * indent-tabs-mode: t
203 * End:
204 *
205 * vi: set shiftwidth=8 tabstop=8 noexpandtab:
206 * :indentSize=8:tabSize=8:noTabs=false:
207 */
208