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