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