File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / iperf / src / units.c
Revision 1.1.1.2 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Wed Mar 17 00:36:46 2021 UTC (3 years, 4 months ago) by misho
Branches: iperf, MAIN
CVS tags: v3_3_9, v3_15, HEAD
iperf 3.3.9

    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>