| 78 | } |
| 79 | |
| 80 | uintmax_t |
| 81 | svtou(TextView src, TextView *out, int base) { |
| 82 | uintmax_t zret = 0; |
| 83 | |
| 84 | if (out) { |
| 85 | out->clear(); |
| 86 | } |
| 87 | |
| 88 | if (src.ltrim_if(&isspace).size()) { |
| 89 | auto origin = src.data(); // cache to handle prefix skipping. |
| 90 | // If base is 0, it wasn't specified - check for standard base prefixes |
| 91 | if (0 == base) { |
| 92 | base = 10; |
| 93 | if ('0' == *src) { |
| 94 | ++src; |
| 95 | base = 8; |
| 96 | if (src) { |
| 97 | switch (*src) { |
| 98 | case 'x': |
| 99 | case 'X': |
| 100 | ++src; |
| 101 | base = 16; |
| 102 | break; |
| 103 | case 'b': |
| 104 | case 'B': |
| 105 | ++src; |
| 106 | base = 2; |
| 107 | break; |
| 108 | } |
| 109 | } |
| 110 | } |
| 111 | } |
| 112 | if (!(1 <= base && base <= 36)) { |
| 113 | return 0; |
| 114 | } |
| 115 | |
| 116 | // For performance in common cases, use the templated conversion. |
| 117 | switch (base) { |
| 118 | case 2: |
| 119 | zret = svto_radix<2>(src); |
| 120 | break; |
| 121 | case 8: |
| 122 | zret = svto_radix<8>(src); |
| 123 | break; |
| 124 | case 10: |
| 125 | zret = svto_radix<10>(src); |
| 126 | break; |
| 127 | case 16: |
| 128 | zret = svto_radix<16>(src); |
| 129 | break; |
| 130 | default: { |
| 131 | static constexpr auto MAX = std::numeric_limits<uintmax_t>::max(); |
| 132 | const auto OVERFLOW_LIMIT = MAX / base; |
| 133 | intmax_t v = 0; |
| 134 | while (src.size() && (0 <= (v = svtoi_convert[static_cast<unsigned char>(*src)])) && v < base) { |
| 135 | ++src; |
| 136 | if (zret <= OVERFLOW_LIMIT && uintmax_t(v) <= (MAX - (zret *= base))) { |
| 137 | zret += v; |
no test coverage detected