• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*---------------------------------------------------------------
2  * Copyright (c) 1999,2000,2001,2002,2003
3  * The Board of Trustees of the University of Illinois
4  * All Rights Reserved.
5  *---------------------------------------------------------------
6  * Permission is hereby granted, free of charge, to any person
7  * obtaining a copy of this software (Iperf) and associated
8  * documentation files (the "Software"), to deal in the Software
9  * without restriction, including without limitation the
10  * rights to use, copy, modify, merge, publish, distribute,
11  * sublicense, and/or sell copies of the Software, and to permit
12  * persons to whom the Software is furnished to do
13  * so, subject to the following conditions:
14  *
15  *
16  * Redistributions of source code must retain the above
17  * copyright notice, this list of conditions and
18  * the following disclaimers.
19  *
20  *
21  * Redistributions in binary form must reproduce the above
22  * copyright notice, this list of conditions and the following
23  * disclaimers in the documentation and/or other materials
24  * provided with the distribution.
25  *
26  *
27  * Neither the names of the University of Illinois, NCSA,
28  * nor the names of its contributors may be used to endorse
29  * or promote products derived from this Software without
30  * specific prior written permission.
31  *
32  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
33  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
34  * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
35  * NONINFRINGEMENT. IN NO EVENT SHALL THE CONTIBUTORS OR COPYRIGHT
36  * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
37  * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
38  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE
39  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
40  * ________________________________________________________________
41  * National Laboratory for Applied Network Research
42  * National Center for Supercomputing Applications
43  * University of Illinois at Urbana-Champaign
44  * http://www.ncsa.uiuc.edu
45  * ________________________________________________________________
46  *
47  * stdio.c
48  * by Mark Gates <mgates@nlanr.net>
49  * and Ajay Tirumalla <tirumala@ncsa.uiuc.edu>
50  * -------------------------------------------------------------------
51  * input and output numbers, converting with kilo, mega, giga, tera
52  * ------------------------------------------------------------------- */
53 
54 #include <stdio.h>
55 #include <assert.h>
56 #include <ctype.h>
57 #ifdef HAVE_STDINT_H
58 #include <stdint.h>
59 #endif
60 #include <sys/socket.h>
61 #include <sys/types.h>
62 #include <sys/time.h>
63 
64 
65 #include "iperf.h"
66 
67 #ifdef __cplusplus
68 extern    "C"
69 {
70 #endif
71 
72     const double KILO_UNIT = 1024.0;
73     const double MEGA_UNIT = 1024.0 * 1024.0;
74     const double GIGA_UNIT = 1024.0 * 1024.0 * 1024.0;
75     const double TERA_UNIT = 1024.0 * 1024.0 * 1024.0 * 1024.0;
76 
77     const double KILO_RATE_UNIT = 1000.0;
78     const double MEGA_RATE_UNIT = 1000.0 * 1000.0;
79     const double GIGA_RATE_UNIT = 1000.0 * 1000.0 * 1000.0;
80     const double TERA_RATE_UNIT = 1000.0 * 1000.0 * 1000.0 * 1000.0;
81 
82 /* -------------------------------------------------------------------
83  * unit_atof
84  *
85  * Given a string of form #x where # is a number and x is a format
86  * character listed below, this returns the interpreted integer.
87  * Gg, Mm, Kk are giga, mega, kilo respectively
88  * ------------------------------------------------------------------- */
89 
unit_atof(const char * s)90     double    unit_atof(const char *s)
91     {
92 	double    n;
93 	char      suffix = '\0';
94 
95 	          assert(s != NULL);
96 
97 	/* scan the number and any suffices */
98 	          sscanf(s, "%lf%c", &n, &suffix);
99 
100 	/* convert according to [Tt Gg Mm Kk] */
101 	switch    (suffix)
102 	{
103 	case 't': case 'T':
104 	    n *= TERA_UNIT;
105 	    break;
106 	case 'g': case 'G':
107 	    n *= GIGA_UNIT;
108 	    break;
109 	case 'm': case 'M':
110 	    n *= MEGA_UNIT;
111 	    break;
112 	case 'k': case 'K':
113 	    n *= KILO_UNIT;
114 	    break;
115 	default:
116 	    break;
117 	}
118 	          return n;
119     }				/* end unit_atof */
120 
121 
122 /* -------------------------------------------------------------------
123  * unit_atof_rate
124  *
125  * Similar to unit_atof, but uses 10-based rather than 2-based
126  * suffixes.
127  * ------------------------------------------------------------------- */
128 
unit_atof_rate(const char * s)129     double    unit_atof_rate(const char *s)
130     {
131 	double    n;
132 	char      suffix = '\0';
133 
134 	          assert(s != NULL);
135 
136 	/* scan the number and any suffices */
137 	          sscanf(s, "%lf%c", &n, &suffix);
138 
139 	/* convert according to [Tt Gg Mm Kk] */
140 	switch    (suffix)
141 	{
142 	case 't': case 'T':
143 	    n *= TERA_RATE_UNIT;
144 	    break;
145 	case 'g': case 'G':
146 	    n *= GIGA_RATE_UNIT;
147 	    break;
148 	case 'm': case 'M':
149 	    n *= MEGA_RATE_UNIT;
150 	    break;
151 	case 'k': case 'K':
152 	    n *= KILO_RATE_UNIT;
153 	    break;
154 	default:
155 	    break;
156 	}
157 	          return n;
158     }				/* end unit_atof_rate */
159 
160 
161 
162 /* -------------------------------------------------------------------
163  * unit_atoi
164  *
165  * Given a string of form #x where # is a number and x is a format
166  * character listed below, this returns the interpreted integer.
167  * Tt, Gg, Mm, Kk are tera, giga, mega, kilo respectively
168  * ------------------------------------------------------------------- */
169 
unit_atoi(const char * s)170     iperf_size_t unit_atoi(const char *s)
171     {
172 	double    n;
173 	char      suffix = '\0';
174 
175 	          assert(s != NULL);
176 
177 	/* scan the number and any suffices */
178 	          sscanf(s, "%lf%c", &n, &suffix);
179 
180 	/* convert according to [Tt Gg Mm Kk] */
181 	switch    (suffix)
182 	{
183 	case 't': case 'T':
184 	    n *= TERA_UNIT;
185 	    break;
186 	case 'g': case 'G':
187 	    n *= GIGA_UNIT;
188 	    break;
189 	case 'm': case 'M':
190 	    n *= MEGA_UNIT;
191 	    break;
192 	case 'k': case 'K':
193 	    n *= KILO_UNIT;
194 	    break;
195 	default:
196 	    break;
197 	}
198 	          return (iperf_size_t) n;
199     }				/* end unit_atof */
200 
201 /* -------------------------------------------------------------------
202  * constants for byte_printf
203  * ------------------------------------------------------------------- */
204 
205 /* used as indices into conversion_bytes[], label_byte[], and label_bit[] */
206     enum
207     {
208 	UNIT_CONV,
209 	KILO_CONV,
210 	MEGA_CONV,
211 	GIGA_CONV,
212 	TERA_CONV
213     };
214 
215 /* factor to multiply the number by */
216     const double conversion_bytes[] =
217     {
218 	1.0,			/* unit */
219 	1.0 / 1024,		/* kilo */
220 	1.0 / 1024 / 1024,	/* mega */
221 	1.0 / 1024 / 1024 / 1024, /* giga */
222 	1.0 / 1024 / 1024 / 1024 / 1024 /* tera */
223     };
224 
225 /* factor to multiply the number by for bits*/
226     const double conversion_bits[] =
227     {
228 	1.0,			/* unit */
229 	1.0 / 1000,		/* kilo */
230 	1.0 / 1000 / 1000,	/* mega */
231 	1.0 / 1000 / 1000 / 1000, /* giga */
232 	1.0 / 1000 / 1000 / 1000 / 1000 /* tera */
233     };
234 
235 
236 /* labels for Byte formats [KMGT] */
237     const char *label_byte[] =
238     {
239 	"Byte",
240 	"KByte",
241 	"MByte",
242 	"GByte",
243 	"TByte"
244     };
245 
246 /* labels for bit formats [kmgt] */
247     const char *label_bit[] =
248     {
249 	"bit",
250 	"Kbit",
251 	"Mbit",
252 	"Gbit",
253 	"Tbit"
254     };
255 
256 /* -------------------------------------------------------------------
257  * unit_snprintf
258  *
259  * Given a number in bytes and a format, converts the number and
260  * prints it out with a bits or bytes label.
261  *   B, K, M, G, A for Byte, Kbyte, Mbyte, Gbyte, adaptive byte
262  *   b, k, m, g, a for bit,  Kbit,  Mbit,  Gbit,  adaptive bit
263  * adaptive picks the "best" one based on the number.
264  * s should be at least 11 chars long
265  * (4 digits + space + 5 chars max + null)
266  * ------------------------------------------------------------------- */
267 
unit_snprintf(char * s,int inLen,double inNum,char inFormat)268     void      unit_snprintf(char *s, int inLen,
269 			              double inNum, char inFormat)
270     {
271 	int       conv;
272 	const char *suffix;
273 	const char *format;
274 
275 	/* convert to bits for [bkmga] */
276 	if        (!isupper((int) inFormat))
277 	{
278 	    inNum *= 8;
279 	}
280 	switch    (toupper((u_char)inFormat))
281 	{
282 	case 'B':
283 	    conv = UNIT_CONV;
284 	    break;
285 	case 'K':
286 	    conv = KILO_CONV;
287 	    break;
288 	case 'M':
289 	    conv = MEGA_CONV;
290 	    break;
291 	case 'G':
292 	    conv = GIGA_CONV;
293 	    break;
294 	case 'T':
295 	    conv = TERA_CONV;
296 	    break;
297 
298 	default:
299 	case 'A':
300 	    {
301 		double    tmpNum = inNum;
302 		conv = UNIT_CONV;
303 
304 		if (isupper((int) inFormat))
305 		{
306 		    while (tmpNum >= 1024.0 && conv < TERA_CONV)
307 		    {
308 			tmpNum /= 1024.0;
309 			conv++;
310 		    }
311 		} else
312 		{
313 		    while (tmpNum >= 1000.0 && conv < TERA_CONV)
314 		    {
315 			tmpNum /= 1000.0;
316 			conv++;
317 		    }
318 		}
319 		break;
320 	    }
321 	}
322 
323 	if (!isupper((int) inFormat))
324 	{
325 	    inNum *= conversion_bits[conv];
326 	    suffix = label_bit[conv];
327 	} else
328 	{
329 	    inNum *= conversion_bytes[conv];
330 	    suffix = label_byte[conv];
331 	}
332 
333 	/* print such that we always fit in 4 places */
334 	if (inNum < 9.995)
335 	{			/* 9.995 would be rounded to 10.0 */
336 	    format = "%4.2f %s";/* #.## */
337 	} else if (inNum < 99.95)
338 	{			/* 99.95 would be rounded to 100 */
339 	    format = "%4.1f %s";/* ##.# */
340 	} else if (inNum < 999.5)
341 	{			/* 999.5 would be rounded to 1000 */
342 	    format = "%4.0f %s";/* ### */
343 	} else
344 	{			/* 1000-1024 fits in 4 places If not using
345 				 * Adaptive sizes then this code will not
346 				 * control spaces */
347 	    format = "%4.0f %s";/* #### */
348 	}
349 	snprintf(s, inLen, format, inNum, suffix);
350     }				/* end unit_snprintf */
351 
352 #ifdef __cplusplus
353 }				/* end extern "C" */
354 
355 #endif
356