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:
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:
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:
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:
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
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>