00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include <ctype.h>
00021 #include "Units.H"
00022
00023
00024
00025
00026
00027 #define DEC_ONE_K CONST_UINT_64(1000)
00028 #define DEC_ONE_M CONST_UINT_64(1000000)
00029 #define DEC_ONE_G CONST_UINT_64(1000000000)
00030 #define DEC_ONE_T CONST_UINT_64(1000000000000)
00031 #define DEC_ONE_P CONST_UINT_64(1000000000000000)
00032 #define DEC_ONE_E CONST_UINT_64(1000000000000000000)
00033
00034
00035
00036
00037
00038 #define BIN_ONE_K (CONST_UINT_64(1)<<10)
00039 #define BIN_ONE_M (CONST_UINT_64(1)<<20)
00040 #define BIN_ONE_G (CONST_UINT_64(1)<<30)
00041 #define BIN_ONE_T (CONST_UINT_64(1)<<40)
00042 #define BIN_ONE_P (CONST_UINT_64(1)<<50)
00043 #define BIN_ONE_E (CONST_UINT_64(1)<<60)
00044
00045 Text Basics::FormatUnitVal(Basics::uint64 val, bool decimal) throw ()
00046 {
00047 const Basics::uint64 OneK = decimal ? DEC_ONE_K : BIN_ONE_K;
00048 const Basics::uint64 OneM = decimal ? DEC_ONE_M : BIN_ONE_M;
00049 const Basics::uint64 OneG = decimal ? DEC_ONE_G : BIN_ONE_G;
00050 const Basics::uint64 OneT = decimal ? DEC_ONE_T : BIN_ONE_T;
00051 const Basics::uint64 OneP = decimal ? DEC_ONE_P : BIN_ONE_P;
00052 const Basics::uint64 OneE = decimal ? DEC_ONE_E : BIN_ONE_E;
00053
00054 char buff[20];
00055 if (val < OneK) {
00056 sprintf(buff, "%"FORMAT_LENGTH_INT_64"u", val);
00057 } else {
00058
00059 char suffix = decimal ? 'k' : 'K';
00060 if (val >= OneE)
00061 {
00062 val /= OneP;
00063 suffix = 'E';
00064 }
00065 else if (val >= OneP)
00066 {
00067 val /= OneT;
00068 suffix = 'P';
00069 }
00070 else if (val >= OneT)
00071 {
00072 val /= OneG;
00073 suffix = 'T';
00074 }
00075 else if (val >= OneG)
00076 {
00077 val /= OneM;
00078 suffix = 'G';
00079 }
00080 else if (val >= OneM)
00081 {
00082 val /= OneK;
00083 suffix = 'M';
00084 }
00085
00086 float ratio = ((float)val) / ((float)OneK);
00087 if (ratio < 9.95) {
00088 sprintf(buff, "%.1f%c", ratio, suffix);
00089 } else {
00090 val = (val + (OneK / 2)) / OneK;
00091 sprintf(buff, "%"FORMAT_LENGTH_INT_64"u%c", val, suffix);
00092 }
00093 }
00094 return Text(buff);
00095 }
00096
00097 Basics::uint64 Basics::ParseUnitVal(const char *val, bool decimal)
00098 throw (Basics::ParseUnitValFailure)
00099 {
00100 const Basics::uint64 OneK = decimal ? DEC_ONE_K : BIN_ONE_K;
00101 const Basics::uint64 OneM = decimal ? DEC_ONE_M : BIN_ONE_M;
00102 const Basics::uint64 OneG = decimal ? DEC_ONE_G : BIN_ONE_G;
00103 const Basics::uint64 OneT = decimal ? DEC_ONE_T : BIN_ONE_T;
00104 const Basics::uint64 OneP = decimal ? DEC_ONE_P : BIN_ONE_P;
00105 const Basics::uint64 OneE = decimal ? DEC_ONE_E : BIN_ONE_E;
00106
00107
00108 if(!isdigit(*val))
00109 {
00110 ParseUnitValFailure err;
00111 err.val = val;
00112 err.emsg = (Text("Value '") + val + "' doesn't start with a number");
00113 throw err;
00114 }
00115
00116 char *end;
00117
00118 unsigned long long result = strtoul(val, &end, 0);
00119 switch(*end)
00120 {
00121 case 'k':
00122 case 'K':
00123 result *= OneK;
00124 break;
00125 case 'm':
00126 case 'M':
00127 result *= OneM;
00128 break;
00129 case 'g':
00130 case 'G':
00131 result *= OneG;
00132 break;
00133 case 't':
00134 case 'T':
00135 result *= OneT;
00136 break;
00137 case 'p':
00138 case 'P':
00139 result *= OneP;
00140 break;
00141 case 'e':
00142 case 'E':
00143 result *= OneE;
00144 break;
00145 default:
00146
00147
00148 {
00149 ParseUnitValFailure err;
00150 err.val = val;
00151 err.emsg = ("Unknown unit multiplier '" + Text(*end) +
00152 "' in value '" + val + "'");
00153 throw err;
00154 }
00155 }
00156 end++;
00157
00158 if(*end != 0)
00159 {
00160 ParseUnitValFailure err;
00161 err.val = val;
00162 err.emsg = ("Extra characters '" + Text(end) +
00163 "' after unit multiplier in value '" + val + "'");
00164 throw err;
00165 }
00166 return result;
00167 }