|
24 | 24 | #include <algorithm> |
25 | 25 | #include <chrono> |
26 | 26 | #include <cmath> |
| 27 | +#include <cstring> |
27 | 28 | #include <functional> |
28 | 29 | #include <iterator> |
29 | 30 | #include <locale> |
@@ -3016,18 +3017,37 @@ namespace jwt { |
3016 | 3017 | } |
3017 | 3018 |
|
3018 | 3019 | static std::string to_lower_unicode(const std::string& str, const std::locale& loc) { |
3019 | | -#if __cplusplus > 201103L |
3020 | | - std::wstring_convert<std::codecvt_utf8<wchar_t>, wchar_t> conv; |
3021 | | - auto wide = conv.from_bytes(str); |
| 3020 | + std::mbstate_t state = std::mbstate_t(); |
| 3021 | + const char* in_next = str.data(); |
| 3022 | + const char* in_end = str.data() + str.size(); |
| 3023 | + std::wstring wide; |
| 3024 | + wide.reserve(str.size()); |
| 3025 | + |
| 3026 | + while (in_next != in_end) { |
| 3027 | + wchar_t wc; |
| 3028 | + std::size_t result = std::mbrtowc(&wc, in_next, in_end - in_next, &state); |
| 3029 | + if (result == static_cast<std::size_t>(-1)) { |
| 3030 | + throw std::runtime_error("encoding error: " + std::string(std::strerror(errno))); |
| 3031 | + } else if (result == static_cast<std::size_t>(-2)) { |
| 3032 | + throw std::runtime_error("conversion error: next bytes constitute an incomplete, but so far " |
| 3033 | + "valid, multibyte character."); |
| 3034 | + } |
| 3035 | + in_next += result; |
| 3036 | + wide.push_back(wc); |
| 3037 | + } |
| 3038 | + |
3022 | 3039 | auto& f = std::use_facet<std::ctype<wchar_t>>(loc); |
3023 | 3040 | f.tolower(&wide[0], &wide[0] + wide.size()); |
3024 | | - return conv.to_bytes(wide); |
3025 | | -#else |
3026 | | - std::string result; |
3027 | | - std::transform(str.begin(), str.end(), std::back_inserter(result), |
3028 | | - [&loc](unsigned char c) { return std::tolower(c, loc); }); |
3029 | | - return result; |
3030 | | -#endif |
| 3041 | + |
| 3042 | + std::string out; |
| 3043 | + out.reserve(wide.size()); |
| 3044 | + for (wchar_t wc : wide) { |
| 3045 | + char mb[MB_CUR_MAX]; |
| 3046 | + std::size_t n = std::wcrtomb(mb, wc, &state); |
| 3047 | + if (n != static_cast<std::size_t>(-1)) out.append(mb, n); |
| 3048 | + } |
| 3049 | + |
| 3050 | + return out; |
3031 | 3051 | } |
3032 | 3052 | }; |
3033 | 3053 | } // namespace verify_ops |
|
0 commit comments