| 69 | template std::optional<std::vector<uint8_t>> TryParseHex(std::string_view); |
| 70 | |
| 71 | bool SplitHostPort(std::string_view in, uint16_t& portOut, std::string& hostOut) |
| 72 | { |
| 73 | bool valid = false; |
| 74 | size_t colon = in.find_last_of(':'); |
| 75 | // if a : is found, and it either follows a [...], or no other : is in the string, treat it as port separator |
| 76 | bool fHaveColon = colon != in.npos; |
| 77 | bool fBracketed = fHaveColon && (in[0] == '[' && in[colon - 1] == ']'); // if there is a colon, and in[0]=='[', colon is not 0, so in[colon-1] is safe |
| 78 | bool fMultiColon{fHaveColon && colon != 0 && (in.find_last_of(':', colon - 1) != in.npos)}; |
| 79 | if (fHaveColon && (colon == 0 || fBracketed || !fMultiColon)) { |
| 80 | if (const auto n{ToIntegral<uint16_t>(in.substr(colon + 1))}) { |
| 81 | in = in.substr(0, colon); |
| 82 | portOut = *n; |
| 83 | valid = (portOut != 0); |
| 84 | } |
| 85 | } else { |
| 86 | valid = true; |
| 87 | } |
| 88 | if (in.size() > 0 && in[0] == '[' && in[in.size() - 1] == ']') { |
| 89 | hostOut = in.substr(1, in.size() - 2); |
| 90 | } else { |
| 91 | hostOut = in; |
| 92 | } |
| 93 | |
| 94 | return valid; |
| 95 | } |
| 96 | |
| 97 | std::string EncodeBase64(std::span<const unsigned char> input) |
| 98 | { |