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