27fba9aaf4117261b51132062a63f3998f158df7
[obnox/wireshark/wip.git] / epan / ftypes / ftype-double.c
1 /*
2  * $Id: ftype-double.c,v 1.11 2003/08/27 15:23:06 gram Exp $
3  *
4  * Ethereal - Network traffic analyzer
5  * By Gerald Combs <gerald@ethereal.com>
6  * Copyright 2001 Gerald Combs
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License
10  * as published by the Free Software Foundation; either version 2
11  * of the License, or (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
21  */
22
23 #ifdef HAVE_CONFIG_H
24 #include "config.h"
25 #endif
26
27 #include <ftypes-int.h>
28 #include <stdlib.h>
29 #include <math.h>
30 #include <errno.h>
31 #include <float.h>
32
33 #include "strutil.h"
34
35 static void
36 double_fvalue_new(fvalue_t *fv)
37 {
38         fv->value.floating = 0.0;
39 }
40
41 static void
42 double_fvalue_set_floating(fvalue_t *fv, gdouble value)
43 {
44         fv->value.floating = value;
45 }
46
47 static double
48 value_get_floating(fvalue_t *fv)
49 {
50         return fv->value.floating;
51 }
52
53 static gboolean
54 val_from_unparsed(fvalue_t *fv, char *s, gboolean allow_partial_value _U_, LogFunc logfunc)
55 {
56         char    *endptr = NULL;
57
58         fv->value.floating = strtod(s, &endptr);
59
60         if (endptr == s || *endptr != '\0') {
61                 /* This isn't a valid number. */
62                 logfunc("\"%s\" is not a valid number.", s);
63                 return FALSE;
64         }
65         if (errno == ERANGE) {
66                 if (fv->value.floating == 0) {
67                         logfunc("\"%s\" causes floating-point underflow.", s);
68                 }
69                 else if (fv->value.floating == HUGE_VAL) {
70                         logfunc("\"%s\" causes floating-point overflow.", s);
71                 }
72                 else {
73                         logfunc("\"%s\" is not a valid floating-point number.",
74                             s);
75                 }
76                 return FALSE;
77         }
78
79         return TRUE;
80 }
81
82 static int
83 float_val_repr_len(fvalue_t *fv _U_, ftrepr_t rtype _U_)
84 {
85         /*
86          * 1 character for a sign.
87          * 26 characters for a Really Big Number.
88          * XXX - is that platform-dependent?
89          * XXX - smaller for float than for double?
90          * XXX - can we compute it from FLT_DIG and the like?
91          */
92         return 1 + 26;
93 }
94
95 static void
96 float_val_to_repr(fvalue_t *fv, ftrepr_t rtype _U_, char *buf)
97 {
98         sprintf(buf, "%." STRINGIFY(FLT_DIG) "g", fv->value.floating);
99 }
100
101 static int
102 double_val_repr_len(fvalue_t *fv _U_, ftrepr_t rtype _U_)
103 {
104         /*
105          * 1 character for a sign.
106          * 26 characters for a Really Big Number.
107          * XXX - is that platform-dependent?
108          * XXX - can we compute it from DBL_DIG and the like?
109          */
110         return 1 + 26;
111 }
112
113 static void
114 double_val_to_repr(fvalue_t *fv, ftrepr_t rtype _U_, char *buf)
115 {
116         sprintf(buf, "%." STRINGIFY(DBL_DIG) "g", fv->value.floating);
117 }
118
119 static gboolean
120 cmp_eq(fvalue_t *a, fvalue_t *b)
121 {
122         return a->value.floating == b->value.floating;
123 }
124
125 static gboolean
126 cmp_ne(fvalue_t *a, fvalue_t *b)
127 {
128         return a->value.floating != b->value.floating;
129 }
130
131 static gboolean
132 cmp_gt(fvalue_t *a, fvalue_t *b)
133 {
134         return a->value.floating > b->value.floating;
135 }
136
137 static gboolean
138 cmp_ge(fvalue_t *a, fvalue_t *b)
139 {
140         return a->value.floating >= b->value.floating;
141 }
142
143 static gboolean
144 cmp_lt(fvalue_t *a, fvalue_t *b)
145 {
146         return a->value.floating < b->value.floating;
147 }
148
149 static gboolean
150 cmp_le(fvalue_t *a, fvalue_t *b)
151 {
152         return a->value.floating <= b->value.floating;
153 }
154
155 void
156 ftype_register_double(void)
157 {
158
159         static ftype_t float_type = {
160                 "FT_FLOAT",
161                 "floating point (single-precision)",
162                 0,
163                 double_fvalue_new,
164                 NULL,
165                 val_from_unparsed,              /* val_from_unparsed */
166                 NULL,                           /* val_from_string */
167                 float_val_to_repr,              /* val_to_string_repr */
168                 float_val_repr_len,             /* len_string_repr */
169
170                 NULL,
171                 NULL,
172                 double_fvalue_set_floating,
173
174                 NULL,
175                 NULL,
176                 value_get_floating,
177
178                 cmp_eq,
179                 cmp_ne,
180                 cmp_gt,
181                 cmp_ge,
182                 cmp_lt,
183                 cmp_le,
184                 NULL,                           /* cmp_contains */
185
186                 NULL,
187                 NULL,
188         };
189
190         static ftype_t double_type = {
191                 "FT_DOUBLE",
192                 "floating point (double-precision)",
193                 0,
194                 double_fvalue_new,
195                 NULL,
196                 val_from_unparsed,              /* val_from_unparsed */
197                 NULL,                           /* val_from_string */
198                 double_val_to_repr,             /* val_to_string_repr */
199                 double_val_repr_len,            /* len_string_repr */
200
201                 NULL,
202                 NULL,
203                 double_fvalue_set_floating,
204
205                 NULL,
206                 NULL,
207                 value_get_floating,
208
209                 cmp_eq,
210                 cmp_ne,
211                 cmp_gt,
212                 cmp_ge,
213                 cmp_lt,
214                 cmp_le,
215                 NULL,                           /* cmp_contains */
216
217                 NULL,
218                 NULL,
219         };
220
221         ftype_register(FT_FLOAT, &float_type);
222         ftype_register(FT_DOUBLE, &double_type);
223 }