rvm 1.08
|
00001 #ifndef __strfmt_h__ 00002 #define __strfmt_h__ 00003 00004 #include "asserts.h" 00005 #include "types.h" 00006 #include "estring.h" 00007 #include "rmath.h" 00008 00009 /** Given an integral number, return a string with the number formatted as a 00010 human-readable machine-type size. (Ex: 10240 becomes "10Kb") */ 00011 template<class T> 00012 std::string size_to_string( 00013 T a_t, 00014 const std::string& a_base_size_unit = "b", 00015 uint16 a_width = 8, 00016 uint16 a_precision = 1, 00017 uint16 a_kilo = 1024 00018 ) 00019 { 00020 enum { 00021 ones = 0, 00022 kilo, 00023 mega, 00024 giga, 00025 tera, 00026 peta, 00027 exa, 00028 zetta, 00029 yotta 00030 }; 00031 const char* units[] = { 00032 " ", 00033 "K", 00034 "M", 00035 "G", 00036 "T", 00037 "P", 00038 "E", 00039 "Z", 00040 "Y" 00041 }; 00042 std::string es; 00043 int resolution = ones; 00044 std::string str; 00045 safe_num<T> quotient = a_t; 00046 safe_num<T> remainder = 0; 00047 safe_num<T> rmul = 10; 00048 safe_num<T> tmp; 00049 00050 TRY_nomem(es = "Could not generate size-string: \""); 00051 TRY_nomem(es += estring(a_t)); 00052 TRY_nomem(es += "\""); 00053 00054 for (tmp = 1; tmp < a_precision; ++tmp) { 00055 rmul *= 10; 00056 } 00057 while ((quotient >= a_kilo) && (resolution < yotta)) { 00058 TRY( 00059 tmp = quotient; 00060 tmp *= rmul; 00061 // 00062 // *** NOT SURE ABOUT THIS: 00063 // This involves a conversion from uint16 to T 00064 // for safe_num<T>(a_kilo) 00065 // 00066 remainder = (tmp / safe_num<T>(a_kilo)) % rmul; 00067 quotient /= a_kilo; 00068 ,es); 00069 resolution++; 00070 } 00071 00072 if (resolution > ones) { 00073 TRY( 00074 str += estring(quotient.value()).fmt_str( 00075 a_width-(a_precision+1)-2,estring::right,' ','x'), 00076 es); 00077 TRY_nomem(str += "."); 00078 TRY( 00079 str += estring(remainder.value()).fmt_str(a_precision,estring::right,'0','x'), 00080 es); 00081 } 00082 else { 00083 TRY( 00084 str += estring(quotient.value()).fmt_str(a_width-2,estring::right,' ','x'), 00085 es); 00086 } 00087 TRY_nomem(str += units[resolution]); 00088 TRY_nomem(str += a_base_size_unit); 00089 00090 return(str); 00091 } 00092 00093 /** Given an integral number, return a string with the number formatted in a 00094 generic, human-readable format. (Ex: 10240 becomes "10,240") */ 00095 template<class T> 00096 std::string num_to_string(T a_t, uint16 a_width = 0) 00097 { 00098 std::string es; 00099 std::string tstr; 00100 estring str; 00101 std::string::size_type n; 00102 00103 TRY_nomem(tstr = estring(a_t)); 00104 TRY_nomem(es = "Could not generate num-string: \""); 00105 TRY_nomem(es += tstr); 00106 TRY_nomem(es += "\""); 00107 00108 if (tstr.size() == 0) { 00109 return(tstr); 00110 } 00111 00112 n = tstr.size(); 00113 while (n > 0) { 00114 if (str.size() > 0) { 00115 TRY_nomem(str = "," + str); 00116 } 00117 str = tstr[(n--)-1] + str; if (n == 0) break; 00118 str = tstr[(n--)-1] + str; if (n == 0) break; 00119 str = tstr[(n--)-1] + str; 00120 } 00121 00122 if (a_width == 0) { 00123 return(str); 00124 } 00125 str.width(a_width); 00126 str.align(estring::right); 00127 TRY_nomem(tstr = str.fmt_str()); 00128 00129 return(tstr); 00130 } 00131 00132 /** Given an integral number, return a string with the number formated as a 00133 number of machine-type size per second. (Ex: 10240 becomes "10Kb/s") */ 00134 template<class T> 00135 std::string throughput_to_string( 00136 T a_t, 00137 const std::string& a_base_size_unit = "b", 00138 const std::string& a_base_time_unit = "s", 00139 uint16 a_width = 10, 00140 uint16 a_precision = 1, 00141 uint16 a_kilo = 1024 00142 ) 00143 { 00144 std::string str; 00145 00146 TRY_nomem( 00147 str = size_to_string(a_t, a_base_size_unit, a_width-2, a_precision, a_kilo) 00148 ); 00149 TRY_nomem(str += "/"); 00150 TRY_nomem(str += a_base_time_unit); 00151 00152 return(str); 00153 } 00154 00155 /** Given a count complete and a count total, calculate a percentage */ 00156 template<typename T> 00157 std::string percent_string(const T& a_complete, const T& a_total) 00158 { 00159 safe_num<double> percent; 00160 estring es; 00161 estring estr; 00162 std::string str; 00163 00164 es = "Could not calculate percentage"; 00165 if (a_complete == static_cast<T>(0)) { 00166 percent = static_cast<T>(0); 00167 } 00168 else if (a_total == static_cast<T>(0)) { 00169 TRY_nomem(str = "??.?%"); 00170 return(str); 00171 } 00172 else { 00173 TRY ( 00174 percent = static_cast<double>(a_complete); 00175 percent *= 100; 00176 percent /= static_cast<double>(a_total); 00177 ,es); 00178 } 00179 estr.width(5); 00180 estr.align(estring::right); 00181 estr.fillchar(' '); 00182 estr.precision(1); 00183 estr = percent.value(); 00184 TRY_nomem(str = estr.fmt_str()); 00185 TRY_nomem(str += "%"); 00186 00187 return(str); 00188 } 00189 00190 #endif