constexpr auto
__from_chars_alnum_to_val_table()
{
- constexpr unsigned char __lower_letters[]
- = { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j',
- 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't',
- 'u', 'v', 'w', 'x', 'y', 'z' };
- constexpr unsigned char __upper_letters[]
- = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J',
- 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',
- 'U', 'V', 'W', 'X', 'Y', 'Z' };
+ constexpr unsigned char __lower_letters[27] = "abcdefghijklmnopqrstuvwxyz";
+ constexpr unsigned char __upper_letters[27] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
struct { unsigned char __data[1u << __CHAR_BIT__] = {}; } __table;
for (auto& __entry : __table.__data)
__entry = 127;
// return its corresponding base-10 value, otherwise return a value >= 127.
// If _DecOnly is false: if the character is an alphanumeric digit, then
// return its corresponding base-36 value, otherwise return a value >= 127.
- template<bool _DecOnly>
+ template<bool _DecOnly = false>
unsigned char
__from_chars_alnum_to_val(unsigned char __c)
{
// Prefer to use std::pmr::string if possible, which requires the cxx11 ABI.
#define _GLIBCXX_USE_CXX11_ABI 1
+#include <array>
#include <charconv>
#include <bit>
#include <string>
#if _GLIBCXX_FLOAT_IS_IEEE_BINARY32 && _GLIBCXX_DOUBLE_IS_IEEE_BINARY64
// Return true iff [FIRST,LAST) begins with PREFIX, ignoring case.
+ // PREFIX is assumed to not contain any uppercase letters.
bool
starts_with_ci(const char* first, const char* last, string_view prefix)
{
__glibcxx_requires_valid_range(first, last);
- for (char ch : prefix)
+ // A lookup table that maps uppercase letters to lowercase and
+ // is otherwise the identity mapping.
+ static constexpr auto upper_to_lower_table = [] {
+ constexpr unsigned char lower_letters[27] = "abcdefghijklmnopqrstuvwxyz";
+ constexpr unsigned char upper_letters[27] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+ std::array<unsigned char, (1u << __CHAR_BIT__)> table = {};
+ for (unsigned i = 0; i < table.size(); ++i)
+ table[i] = i;
+ for (unsigned i = 0; i < 26; ++i)
+ table[upper_letters[i]] = lower_letters[i];
+ return table;
+ }();
+
+ if (last - first < static_cast<ptrdiff_t>(prefix.length()))
+ return false;
+
+ for (const unsigned char pch : prefix)
{
- __glibcxx_assert(ch >= 'a' && ch <= 'z');
- if (first == last || (*first != ch && *first != ch - 32))
+ // __glibcxx_assert(pch == upper_to_lower_table[pch]);
+ const unsigned char ch = *first;
+ if (ch != pch && upper_to_lower_table[ch] != pch)
return false;
++first;
}
++first;
break;
}
- else if ((ch >= '0' && ch <= '9')
- || (ch >= 'a' && ch <= 'z')
- || (ch >= 'A' && ch <= 'Z')
- || ch == '_')
+ else if (ch == '_'
+ || __detail::__from_chars_alnum_to_val(ch) < 127)
continue;
else
{
continue;
}
- int hexit = __detail::__from_chars_alnum_to_val<false>(ch);
+ int hexit = __detail::__from_chars_alnum_to_val(ch);
if (hexit >= 16)
break;
seen_hexit = true;