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