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 <[email protected]> 49 * and Ajay Tirumalla <[email protected]> 50 * ------------------------------------------------------------------- 51 * input and output numbers, converting with kilo, mega, giga 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 #include <netinet/tcp.h> 64 65 66 #include "iperf.h" 67 68 #ifdef __cplusplus 69 extern "C" 70 { 71 #endif 72 73 const long KILO_UNIT = 1024; 74 const long MEGA_UNIT = 1024 * 1024; 75 const long GIGA_UNIT = 1024 * 1024 * 1024; 76 77 const long KILO_RATE_UNIT = 1000; 78 const long MEGA_RATE_UNIT = 1000 * 1000; 79 const long GIGA_RATE_UNIT = 1000 * 1000 * 1000; 80 81 /* ------------------------------------------------------------------- 82 * unit_atof 83 * 84 * Given a string of form #x where # is a number and x is a format 85 * character listed below, this returns the interpreted integer. 86 * Gg, Mm, Kk are giga, mega, kilo respectively 87 * ------------------------------------------------------------------- */ 88 89 double unit_atof(const char *s) 90 { 91 double n; 92 char suffix = '\0'; 93 94 assert(s != NULL); 95 96 /* scan the number and any suffices */ 97 sscanf(s, "%lf%c", &n, &suffix); 98 99 /* convert according to [Gg Mm Kk] */ 100 switch (suffix) 101 { 102 case 'g': case 'G': 103 n *= GIGA_UNIT; 104 break; 105 case 'm': case 'M': 106 n *= MEGA_UNIT; 107 break; 108 case 'k': case 'K': 109 n *= KILO_UNIT; 110 break; 111 default: 112 break; 113 } 114 return n; 115 } /* end unit_atof */ 116 117 118 /* ------------------------------------------------------------------- 119 * unit_atof_rate 120 * 121 * Similar to unit_atof, but uses 10-based rather than 2-based 122 * suffixes. 123 * ------------------------------------------------------------------- */ 124 125 double unit_atof_rate(const char *s) 126 { 127 double n; 128 char suffix = '\0'; 129 130 assert(s != NULL); 131 132 /* scan the number and any suffices */ 133 sscanf(s, "%lf%c", &n, &suffix); 134 135 /* convert according to [Gg Mm Kk] */ 136 switch (suffix) 137 { 138 case 'g': case 'G': 139 n *= GIGA_RATE_UNIT; 140 break; 141 case 'm': case 'M': 142 n *= MEGA_RATE_UNIT; 143 break; 144 case 'k': case 'K': 145 n *= KILO_RATE_UNIT; 146 break; 147 default: 148 break; 149 } 150 return n; 151 } /* end unit_atof_rate */ 152 153 154 155 /* ------------------------------------------------------------------- 156 * unit_atoi 157 * 158 * Given a string of form #x where # is a number and x is a format 159 * character listed below, this returns the interpreted integer. 160 * Gg, Mm, Kk are giga, mega, kilo respectively 161 * ------------------------------------------------------------------- */ 162 163 iperf_size_t unit_atoi(const char *s) 164 { 165 double n; 166 char suffix = '\0'; 167 168 assert(s != NULL); 169 170 /* scan the number and any suffices */ 171 sscanf(s, "%lf%c", &n, &suffix); 172 173 /* convert according to [Gg Mm Kk] */ 174 switch (suffix) 175 { 176 case 'g': case 'G': 177 n *= GIGA_UNIT; 178 break; 179 case 'm': case 'M': 180 n *= MEGA_UNIT; 181 break; 182 case 'k': case 'K': 183 n *= KILO_UNIT; 184 break; 185 default: 186 break; 187 } 188 return (iperf_size_t) n; 189 } /* end unit_atof */ 190 191 /* ------------------------------------------------------------------- 192 * constants for byte_printf 193 * ------------------------------------------------------------------- */ 194 195 /* used as indices into conversion_bytes[], label_byte[], and label_bit[] */ 196 enum 197 { 198 UNIT_CONV, 199 KILO_CONV, 200 MEGA_CONV, 201 GIGA_CONV 202 }; 203 204 /* factor to multiply the number by */ 205 const double conversion_bytes[] = 206 { 207 1.0, /* unit */ 208 1.0 / 1024, /* kilo */ 209 1.0 / 1024 / 1024, /* mega */ 210 1.0 / 1024 / 1024 / 1024/* giga */ 211 }; 212 213 /* factor to multiply the number by for bits*/ 214 const double conversion_bits[] = 215 { 216 1.0, /* unit */ 217 1.0 / 1000, /* kilo */ 218 1.0 / 1000 / 1000, /* mega */ 219 1.0 / 1000 / 1000 / 1000/* giga */ 220 }; 221 222 223 /* labels for Byte formats [KMG] */ 224 const char *label_byte[] = 225 { 226 "Byte", 227 "KByte", 228 "MByte", 229 "GByte" 230 }; 231 232 /* labels for bit formats [kmg] */ 233 const char *label_bit[] = 234 { 235 "bit", 236 "Kbit", 237 "Mbit", 238 "Gbit" 239 }; 240 241 /* ------------------------------------------------------------------- 242 * unit_snprintf 243 * 244 * Given a number in bytes and a format, converts the number and 245 * prints it out with a bits or bytes label. 246 * B, K, M, G, A for Byte, Kbyte, Mbyte, Gbyte, adaptive byte 247 * b, k, m, g, a for bit, Kbit, Mbit, Gbit, adaptive bit 248 * adaptive picks the "best" one based on the number. 249 * s should be at least 11 chars long 250 * (4 digits + space + 5 chars max + null) 251 * ------------------------------------------------------------------- */ 252 253 void unit_snprintf(char *s, int inLen, 254 double inNum, char inFormat) 255 { 256 int conv; 257 const char *suffix; 258 const char *format; 259 260 /* convert to bits for [bkmga] */ 261 if (!isupper((int) inFormat)) 262 { 263 inNum *= 8; 264 } 265 switch (toupper((u_char)inFormat)) 266 { 267 case 'B': 268 conv = UNIT_CONV; 269 break; 270 case 'K': 271 conv = KILO_CONV; 272 break; 273 case 'M': 274 conv = MEGA_CONV; 275 break; 276 case 'G': 277 conv = GIGA_CONV; 278 break; 279 280 default: 281 case 'A': 282 { 283 double tmpNum = inNum; 284 conv = UNIT_CONV; 285 286 if (isupper((int) inFormat)) 287 { 288 while (tmpNum >= 1024.0 && conv <= GIGA_CONV) 289 { 290 tmpNum /= 1024.0; 291 conv++; 292 } 293 } else 294 { 295 while (tmpNum >= 1000.0 && conv <= GIGA_CONV) 296 { 297 tmpNum /= 1000.0; 298 conv++; 299 } 300 } 301 break; 302 } 303 } 304 305 if (!isupper((int) inFormat)) 306 { 307 inNum *= conversion_bits[conv]; 308 suffix = label_bit[conv]; 309 } else 310 { 311 inNum *= conversion_bytes[conv]; 312 suffix = label_byte[conv]; 313 } 314 315 /* print such that we always fit in 4 places */ 316 if (inNum < 9.995) 317 { /* 9.995 would be rounded to 10.0 */ 318 format = "%4.2f %s";/* #.## */ 319 } else if (inNum < 99.95) 320 { /* 99.95 would be rounded to 100 */ 321 format = "%4.1f %s";/* ##.# */ 322 } else if (inNum < 999.5) 323 { /* 999.5 would be rounded to 1000 */ 324 format = "%4.0f %s";/* ### */ 325 } else 326 { /* 1000-1024 fits in 4 places If not using 327 * Adaptive sizes then this code will not 328 * control spaces */ 329 format = "%4.0f %s";/* #### */ 330 } 331 snprintf(s, inLen, format, inNum, suffix); 332 } /* end unit_snprintf */ 333 334 #ifdef __cplusplus 335 } /* end extern "C" */ 336 337 #endif 338