// Copyright 2017 The Abseil Authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #include "absl/strings/ascii.h" #include <climits> #include <cstddef> #include <cstring> #include <string> #include "absl/base/attributes.h" #include "absl/base/config.h" #include "absl/base/nullability.h" #include "absl/base/optimization.h" namespace absl { ABSL_NAMESPACE_BEGIN namespace ascii_internal { // # Table generated by this Python code (bit 0x02 is currently unused): // TODO(mbar) Move Python code for generation of table to BUILD and link here. // NOTE: The kAsciiPropertyBits table used within this code was generated by // Python code of the following form. (Bit 0x02 is currently unused and // available.) // // def Hex2(n): // return '0x' + hex(n/16)[2:] + hex(n%16)[2:] // def IsPunct(ch): // return (ord(ch) >= 32 and ord(ch) < 127 and // not ch.isspace() and not ch.isalnum()) // def IsBlank(ch): // return ch in ' \t' // def IsCntrl(ch): // return ord(ch) < 32 or ord(ch) == 127 // def IsXDigit(ch): // return ch.isdigit() or ch.lower() in 'abcdef' // for i in range(128): // ch = chr(i) // mask = ((ch.isalpha() and 0x01 or 0) | // (ch.isalnum() and 0x04 or 0) | // (ch.isspace() and 0x08 or 0) | // (IsPunct(ch) and 0x10 or 0) | // (IsBlank(ch) and 0x20 or 0) | // (IsCntrl(ch) and 0x40 or 0) | // (IsXDigit(ch) and 0x80 or 0)) // print Hex2(mask) + ',', // if i % 16 == 7: // print ' //', Hex2(i & 0x78) // elif i % 16 == 15: // print // clang-format off // Array of bitfields holding character information. Each bit value corresponds // to a particular character feature. For readability, and because the value // of these bits is tightly coupled to this implementation, the individual bits // are not named. Note that bitfields for all characters above ASCII 127 are // zero-initialized. ABSL_DLL const unsigned char kPropertyBits[256] = …; // Array of characters for the ascii_tolower() function. For values 'A' // through 'Z', return the lower-case character; otherwise, return the // identity of the passed character. ABSL_DLL const char kToLower[256] = …; // Array of characters for the ascii_toupper() function. For values 'a' // through 'z', return the upper-case character; otherwise, return the // identity of the passed character. ABSL_DLL const char kToUpper[256] = …; // clang-format on // Returns whether `c` is in the a-z/A-Z range (w.r.t. `ToUpper`). // Implemented by: // 1. Pushing the a-z/A-Z range to [SCHAR_MIN, SCHAR_MIN + 26). // 2. Comparing to SCHAR_MIN + 26. template <bool ToUpper> constexpr bool AsciiInAZRange(unsigned char c) { … } // Force-inline so the compiler won't merge the short and long implementations. template <bool ToUpper> ABSL_ATTRIBUTE_ALWAYS_INLINE inline constexpr void AsciiStrCaseFoldImpl( absl::Nonnull<char*> dst, absl::Nonnull<const char*> src, size_t size) { … } // The string size threshold for starting using the long string version. constexpr size_t kCaseFoldThreshold = …; // No-inline so the compiler won't merge the short and long implementations. template <bool ToUpper> ABSL_ATTRIBUTE_NOINLINE constexpr void AsciiStrCaseFoldLong( absl::Nonnull<char*> dst, absl::Nonnull<const char*> src, size_t size) { … } // Splitting to short and long strings to allow vectorization decisions // to be made separately in the long and short cases. template <bool ToUpper> constexpr void AsciiStrCaseFold(absl::Nonnull<char*> dst, absl::Nonnull<const char*> src, size_t size) { … } void AsciiStrToLower(absl::Nonnull<char*> dst, absl::Nonnull<const char*> src, size_t n) { … } void AsciiStrToUpper(absl::Nonnull<char*> dst, absl::Nonnull<const char*> src, size_t n) { … } static constexpr size_t ValidateAsciiCasefold() { … } static_assert …; } // namespace ascii_internal void AsciiStrToLower(absl::Nonnull<std::string*> s) { … } void AsciiStrToUpper(absl::Nonnull<std::string*> s) { … } void RemoveExtraAsciiWhitespace(absl::Nonnull<std::string*> str) { … } ABSL_NAMESPACE_END } // namespace absl