#include <stdio.h>
#include <assert.h>
#include <ctype.h>
#include <stdint.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/time.h>
#include "iperf.h"
#include "iperf_api.h"
#ifdef __cplusplus
extern "C"
{
#endif
const double KILO_UNIT = 1024.0;
const double MEGA_UNIT = 1024.0 * 1024.0;
const double GIGA_UNIT = 1024.0 * 1024.0 * 1024.0;
const double TERA_UNIT = 1024.0 * 1024.0 * 1024.0 * 1024.0;
const double KILO_RATE_UNIT = 1000.0;
const double MEGA_RATE_UNIT = 1000.0 * 1000.0;
const double GIGA_RATE_UNIT = 1000.0 * 1000.0 * 1000.0;
const double TERA_RATE_UNIT = 1000.0 * 1000.0 * 1000.0 * 1000.0;
double unit_atof(const char *s)
{
double n;
char suffix = '\0';
assert(s != NULL);
if (sscanf(s, "%lf%c", &n, &suffix) < 1) {
i_errno = IEUNITVAL;
errarg = s;
return 0;
}
switch (suffix)
{
case 't': case 'T':
n *= TERA_UNIT;
break;
case 'g': case 'G':
n *= GIGA_UNIT;
break;
case 'm': case 'M':
n *= MEGA_UNIT;
break;
case 'k': case 'K':
n *= KILO_UNIT;
break;
case '\0':
break;
default:
i_errno = IEUNITVAL;
errarg = s;
break;
}
return n;
}
double unit_atof_rate(const char *s)
{
double n;
char suffix = '\0';
assert(s != NULL);
if (sscanf(s, "%lf%c", &n, &suffix) < 1) {
i_errno = IEUNITVAL;
errarg = s;
return 0;
}
switch (suffix)
{
case 't': case 'T':
n *= TERA_RATE_UNIT;
break;
case 'g': case 'G':
n *= GIGA_RATE_UNIT;
break;
case 'm': case 'M':
n *= MEGA_RATE_UNIT;
break;
case 'k': case 'K':
n *= KILO_RATE_UNIT;
break;
case '\0':
break;
default:
i_errno = IEUNITVAL;
errarg = s;
break;
}
return n;
}
iperf_size_t unit_atoi(const char *s)
{
double n;
char suffix = '\0';
assert(s != NULL);
if (sscanf(s, "%lf%c", &n, &suffix) < 1) {
i_errno = IEUNITVAL;
errarg = s;
return 0;
}
switch (suffix)
{
case 't': case 'T':
n *= TERA_UNIT;
break;
case 'g': case 'G':
n *= GIGA_UNIT;
break;
case 'm': case 'M':
n *= MEGA_UNIT;
break;
case 'k': case 'K':
n *= KILO_UNIT;
break;
case '\0':
break;
default:
i_errno = IEUNITVAL;
errarg = s;
return 0;
}
return (iperf_size_t) n;
}
enum
{
UNIT_CONV,
KILO_CONV,
MEGA_CONV,
GIGA_CONV,
TERA_CONV
};
const double conversion_bytes[] =
{
1.0,
1.0 / 1024,
1.0 / 1024 / 1024,
1.0 / 1024 / 1024 / 1024,
1.0 / 1024 / 1024 / 1024 / 1024
};
const double conversion_bits[] =
{
1.0,
1.0 / 1000,
1.0 / 1000 / 1000,
1.0 / 1000 / 1000 / 1000,
1.0 / 1000 / 1000 / 1000 / 1000
};
const char *label_byte[] =
{
"Byte",
"KByte",
"MByte",
"GByte",
"TByte"
};
const char *label_bit[] =
{
"bit",
"Kbit",
"Mbit",
"Gbit",
"Tbit"
};
void unit_snprintf(char *s, int inLen,
double inNum, char inFormat)
{
int conv;
const char *suffix;
const char *format;
if (!isupper((int) inFormat))
{
inNum *= 8;
}
switch (toupper((u_char)inFormat))
{
case 'B':
conv = UNIT_CONV;
break;
case 'K':
conv = KILO_CONV;
break;
case 'M':
conv = MEGA_CONV;
break;
case 'G':
conv = GIGA_CONV;
break;
case 'T':
conv = TERA_CONV;
break;
default:
case 'A':
{
double tmpNum = inNum;
conv = UNIT_CONV;
if (isupper((int) inFormat))
{
while (tmpNum >= 1024.0 && conv < TERA_CONV)
{
tmpNum /= 1024.0;
conv++;
}
} else
{
while (tmpNum >= 1000.0 && conv < TERA_CONV)
{
tmpNum /= 1000.0;
conv++;
}
}
break;
}
}
if (!isupper((int) inFormat))
{
inNum *= conversion_bits[conv];
suffix = label_bit[conv];
} else
{
inNum *= conversion_bytes[conv];
suffix = label_byte[conv];
}
if (inNum < 9.995)
{
format = "%4.2f %s";
} else if (inNum < 99.95)
{
format = "%4.1f %s";
} else if (inNum < 999.5)
{
format = "%4.0f %s";
} else
{
format = "%4.0f %s";
}
snprintf(s, inLen, format, inNum, suffix);
}
#ifdef __cplusplus
}
#endif