File indexing completed on 2025-01-18 10:10:50
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012 #ifndef ROOT_StringConv
0013 #define ROOT_StringConv
0014
0015
0016 #include <string_view>
0017 #include "Rtypes.h"
0018 #include "RConfigure.h"
0019 #include <cmath>
0020
0021 namespace ROOT {
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037 template <typename value_type>
0038 void ToHumanReadableSize(value_type bytes,
0039 Bool_t si,
0040 Double_t *coeff,
0041 const char **units)
0042 {
0043
0044 static const char *const suffix[][2] =
0045 { { "B", "B" },
0046 { "KB", "KiB" },
0047 { "MB", "MiB" },
0048 { "GB", "GiB" },
0049 { "TB", "TiB" },
0050 { "EB", "EiB" },
0051 { "ZB", "ZiB" },
0052 { "YB", "YiB" } };
0053 value_type unit = si ? 1000 : 1024;
0054 int exp = 0;
0055 if (bytes == unit) {
0056
0057
0058
0059
0060 exp = 1;
0061 } else if (bytes > 0) {
0062 exp = std::min( (int) (std::log(bytes) / std::log(unit)),
0063 (int) (sizeof(suffix) / sizeof(suffix[0]) - 1));
0064 }
0065 *coeff = bytes / std::pow(unit, exp);
0066 *units = suffix[exp][!si];
0067 }
0068
0069 enum class EFromHumanReadableSize {
0070 kSuccess,
0071 kParseFail,
0072 kOverflow
0073 };
0074
0075
0076
0077
0078
0079
0080
0081
0082
0083
0084
0085 template <typename T>
0086 EFromHumanReadableSize FromHumanReadableSize(std::string_view str, T &value)
0087 {
0088 try {
0089 size_t cur, size = str.size();
0090
0091 const double coeff = stod(std::string(str.data(), str.size()), &cur);
0092
0093
0094 while (cur<size && isspace(str[cur])) ++cur;
0095
0096
0097 int exp = 0, unit = 1000;
0098
0099 auto result = [coeff,&exp,&unit,&value]() {
0100 double v = exp ? coeff * std::pow(unit, exp / 3) : coeff;
0101 if (v < (double) std::numeric_limits<T>::max()) {
0102 value = (T)v;
0103 return EFromHumanReadableSize::kSuccess;
0104 } else {
0105 return EFromHumanReadableSize::kOverflow;
0106 }
0107 };
0108 if (cur==size) return result();
0109
0110 switch (toupper(str[cur])) {
0111 case 'B': exp = 0; break;
0112 case 'K': exp = 3; break;
0113 case 'M': exp = 6; break;
0114 case 'G': exp = 9; break;
0115 case 'T': exp = 12; break;
0116 case 'E': exp = 15; break;
0117 case 'Z': exp = 18; break;
0118 case 'Y': exp = 21; break;
0119
0120 default: return EFromHumanReadableSize::kParseFail;
0121 }
0122 ++cur;
0123
0124
0125 if (cur<size && toupper(str[cur]) == 'I') {
0126 ++cur;
0127 unit = 1024;
0128 }
0129
0130 if (cur==size) return result();
0131
0132
0133 switch (toupper(str[cur])) {
0134 case 'B':
0135 case ' ':
0136 case '\t': ++cur; break;
0137
0138 case '\0': return result();
0139
0140 default: return EFromHumanReadableSize::kParseFail;
0141 }
0142
0143
0144
0145
0146
0147
0148
0149
0150 return result();
0151 } catch (...) {
0152 return EFromHumanReadableSize::kParseFail;
0153 }
0154
0155 }
0156
0157 }
0158
0159 #endif