mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2024-11-27 07:31:28 +00:00
[libc++] Refactor char_traits
This allows us to reuse workarounds for compilers that don't provide the builtins or constexpr support. Reviewed By: ldionne, Mordante, #libc Spies: libcxx-commits Differential Revision: https://reviews.llvm.org/D139555
This commit is contained in:
parent
1b41074508
commit
72173469dd
@ -210,25 +210,22 @@ struct _LIBCPP_TEMPLATE_VIS char_traits<char>
|
||||
static inline _LIBCPP_CONSTEXPR bool lt(char_type __c1, char_type __c2) _NOEXCEPT
|
||||
{return (unsigned char)__c1 < (unsigned char)__c2;}
|
||||
|
||||
static _LIBCPP_CONSTEXPR_SINCE_CXX17
|
||||
int compare(const char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT;
|
||||
static _LIBCPP_CONSTEXPR_SINCE_CXX17 int compare(const char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT {
|
||||
if (__n == 0)
|
||||
return 0;
|
||||
return std::__constexpr_memcmp(__s1, __s2, __n);
|
||||
}
|
||||
|
||||
static inline size_t _LIBCPP_CONSTEXPR_SINCE_CXX17 length(const char_type* __s) _NOEXCEPT {
|
||||
// GCC currently does not support __builtin_strlen during constant evaluation.
|
||||
// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=70816
|
||||
#ifdef _LIBCPP_COMPILER_GCC
|
||||
if (__libcpp_is_constant_evaluated()) {
|
||||
size_t __i = 0;
|
||||
for (; __s[__i] != char_type('\0'); ++__i)
|
||||
;
|
||||
return __i;
|
||||
}
|
||||
#endif
|
||||
return __builtin_strlen(__s);
|
||||
}
|
||||
static inline size_t _LIBCPP_CONSTEXPR_SINCE_CXX17 length(const char_type* __s) _NOEXCEPT {
|
||||
return std::__constexpr_strlen(__s);
|
||||
}
|
||||
|
||||
static _LIBCPP_CONSTEXPR_SINCE_CXX17
|
||||
const char_type* find(const char_type* __s, size_t __n, const char_type& __a) _NOEXCEPT;
|
||||
static _LIBCPP_CONSTEXPR_SINCE_CXX17
|
||||
const char_type* find(const char_type* __s, size_t __n, const char_type& __a) _NOEXCEPT {
|
||||
if (__n == 0)
|
||||
return nullptr;
|
||||
return std::__constexpr_char_memchr(__s, static_cast<int>(__a), __n);
|
||||
}
|
||||
|
||||
static inline _LIBCPP_CONSTEXPR_SINCE_CXX20
|
||||
char_type* move(char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT {
|
||||
@ -261,49 +258,6 @@ struct _LIBCPP_TEMPLATE_VIS char_traits<char>
|
||||
{return int_type(EOF);}
|
||||
};
|
||||
|
||||
inline _LIBCPP_CONSTEXPR_SINCE_CXX17
|
||||
int
|
||||
char_traits<char>::compare(const char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT
|
||||
{
|
||||
if (__n == 0)
|
||||
return 0;
|
||||
#if __has_feature(cxx_constexpr_string_builtins)
|
||||
return __builtin_memcmp(__s1, __s2, __n);
|
||||
#elif _LIBCPP_STD_VER <= 14
|
||||
return _VSTD::memcmp(__s1, __s2, __n);
|
||||
#else
|
||||
for (; __n; --__n, ++__s1, ++__s2)
|
||||
{
|
||||
if (lt(*__s1, *__s2))
|
||||
return -1;
|
||||
if (lt(*__s2, *__s1))
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
inline _LIBCPP_CONSTEXPR_SINCE_CXX17
|
||||
const char*
|
||||
char_traits<char>::find(const char_type* __s, size_t __n, const char_type& __a) _NOEXCEPT
|
||||
{
|
||||
if (__n == 0)
|
||||
return nullptr;
|
||||
#if __has_feature(cxx_constexpr_string_builtins)
|
||||
return __builtin_char_memchr(__s, to_int_type(__a), __n);
|
||||
#elif _LIBCPP_STD_VER <= 14
|
||||
return (const char_type*) _VSTD::memchr(__s, to_int_type(__a), __n);
|
||||
#else
|
||||
for (; __n; --__n)
|
||||
{
|
||||
if (eq(*__s, __a))
|
||||
return __s;
|
||||
++__s;
|
||||
}
|
||||
return nullptr;
|
||||
#endif
|
||||
}
|
||||
|
||||
// char_traits<wchar_t>
|
||||
|
||||
#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
|
||||
@ -326,12 +280,22 @@ struct _LIBCPP_TEMPLATE_VIS char_traits<wchar_t>
|
||||
static inline _LIBCPP_CONSTEXPR bool lt(char_type __c1, char_type __c2) _NOEXCEPT
|
||||
{return __c1 < __c2;}
|
||||
|
||||
static _LIBCPP_CONSTEXPR_SINCE_CXX17
|
||||
int compare(const char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT;
|
||||
static _LIBCPP_CONSTEXPR_SINCE_CXX17
|
||||
size_t length(const char_type* __s) _NOEXCEPT;
|
||||
static _LIBCPP_CONSTEXPR_SINCE_CXX17
|
||||
const char_type* find(const char_type* __s, size_t __n, const char_type& __a) _NOEXCEPT;
|
||||
static _LIBCPP_CONSTEXPR_SINCE_CXX17 int compare(const char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT {
|
||||
if (__n == 0)
|
||||
return 0;
|
||||
return std::__constexpr_wmemcmp(__s1, __s2, __n);
|
||||
}
|
||||
|
||||
static _LIBCPP_CONSTEXPR_SINCE_CXX17 size_t length(const char_type* __s) _NOEXCEPT {
|
||||
return std::__constexpr_wcslen(__s);
|
||||
}
|
||||
|
||||
static _LIBCPP_CONSTEXPR_SINCE_CXX17
|
||||
const char_type* find(const char_type* __s, size_t __n, const char_type& __a) _NOEXCEPT {
|
||||
if (__n == 0)
|
||||
return nullptr;
|
||||
return std::__constexpr_wmemchr(__s, __a, __n);
|
||||
}
|
||||
|
||||
static inline _LIBCPP_CONSTEXPR_SINCE_CXX20
|
||||
char_type* move(char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT {
|
||||
@ -363,65 +327,6 @@ struct _LIBCPP_TEMPLATE_VIS char_traits<wchar_t>
|
||||
static inline _LIBCPP_CONSTEXPR int_type eof() _NOEXCEPT
|
||||
{return int_type(WEOF);}
|
||||
};
|
||||
|
||||
inline _LIBCPP_CONSTEXPR_SINCE_CXX17
|
||||
int
|
||||
char_traits<wchar_t>::compare(const char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT
|
||||
{
|
||||
if (__n == 0)
|
||||
return 0;
|
||||
#if __has_feature(cxx_constexpr_string_builtins)
|
||||
return __builtin_wmemcmp(__s1, __s2, __n);
|
||||
#elif _LIBCPP_STD_VER <= 14
|
||||
return _VSTD::wmemcmp(__s1, __s2, __n);
|
||||
#else
|
||||
for (; __n; --__n, ++__s1, ++__s2)
|
||||
{
|
||||
if (lt(*__s1, *__s2))
|
||||
return -1;
|
||||
if (lt(*__s2, *__s1))
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
inline _LIBCPP_CONSTEXPR_SINCE_CXX17
|
||||
size_t
|
||||
char_traits<wchar_t>::length(const char_type* __s) _NOEXCEPT
|
||||
{
|
||||
#if __has_feature(cxx_constexpr_string_builtins)
|
||||
return __builtin_wcslen(__s);
|
||||
#elif _LIBCPP_STD_VER <= 14
|
||||
return _VSTD::wcslen(__s);
|
||||
#else
|
||||
size_t __len = 0;
|
||||
for (; !eq(*__s, char_type(0)); ++__s)
|
||||
++__len;
|
||||
return __len;
|
||||
#endif
|
||||
}
|
||||
|
||||
inline _LIBCPP_CONSTEXPR_SINCE_CXX17
|
||||
const wchar_t*
|
||||
char_traits<wchar_t>::find(const char_type* __s, size_t __n, const char_type& __a) _NOEXCEPT
|
||||
{
|
||||
if (__n == 0)
|
||||
return nullptr;
|
||||
#if __has_feature(cxx_constexpr_string_builtins)
|
||||
return __builtin_wmemchr(__s, __a, __n);
|
||||
#elif _LIBCPP_STD_VER <= 14
|
||||
return _VSTD::wmemchr(__s, __a, __n);
|
||||
#else
|
||||
for (; __n; --__n)
|
||||
{
|
||||
if (eq(*__s, __a))
|
||||
return __s;
|
||||
++__s;
|
||||
}
|
||||
return nullptr;
|
||||
#endif
|
||||
}
|
||||
#endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
|
||||
|
||||
#ifndef _LIBCPP_HAS_NO_CHAR8_T
|
||||
@ -445,8 +350,10 @@ struct _LIBCPP_TEMPLATE_VIS char_traits<char8_t>
|
||||
static inline constexpr bool lt(char_type __c1, char_type __c2) noexcept
|
||||
{return __c1 < __c2;}
|
||||
|
||||
static constexpr
|
||||
int compare(const char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT;
|
||||
static _LIBCPP_HIDE_FROM_ABI constexpr int
|
||||
compare(const char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT {
|
||||
return std::__constexpr_memcmp(__s1, __s2, __n);
|
||||
}
|
||||
|
||||
static constexpr
|
||||
size_t length(const char_type* __s) _NOEXCEPT;
|
||||
@ -496,24 +403,6 @@ char_traits<char8_t>::length(const char_type* __s) _NOEXCEPT
|
||||
return __len;
|
||||
}
|
||||
|
||||
inline constexpr
|
||||
int
|
||||
char_traits<char8_t>::compare(const char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT
|
||||
{
|
||||
#if __has_feature(cxx_constexpr_string_builtins)
|
||||
return __builtin_memcmp(__s1, __s2, __n);
|
||||
#else
|
||||
for (; __n; --__n, ++__s1, ++__s2)
|
||||
{
|
||||
if (lt(*__s1, *__s2))
|
||||
return -1;
|
||||
if (lt(*__s2, *__s1))
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
// TODO use '__builtin_char_memchr' if it ever supports char8_t ??
|
||||
inline constexpr
|
||||
const char8_t*
|
||||
|
@ -58,6 +58,7 @@ size_t strlen(const char* s);
|
||||
|
||||
#include <__assert> // all public C++ headers provide the assertion handler
|
||||
#include <__config>
|
||||
#include <__type_traits/is_constant_evaluated.h>
|
||||
|
||||
#include <string.h>
|
||||
|
||||
@ -99,6 +100,53 @@ using ::memset _LIBCPP_USING_IF_EXISTS;
|
||||
using ::strerror _LIBCPP_USING_IF_EXISTS;
|
||||
using ::strlen _LIBCPP_USING_IF_EXISTS;
|
||||
|
||||
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 size_t __constexpr_strlen(const char* __str) {
|
||||
// GCC currently doesn't support __builtin_strlen for heap-allocated memory during constant evaluation.
|
||||
// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=70816
|
||||
#ifdef _LIBCPP_COMPILER_GCC
|
||||
if (__libcpp_is_constant_evaluated()) {
|
||||
size_t __i = 0;
|
||||
for (; __str[__i] != '\0'; ++__i)
|
||||
;
|
||||
return __i;
|
||||
}
|
||||
#endif
|
||||
return __builtin_strlen(__str);
|
||||
}
|
||||
|
||||
template <class _Tp>
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 int
|
||||
__constexpr_memcmp(const _Tp* __lhs, const _Tp* __rhs, size_t __count) {
|
||||
#ifdef _LIBCPP_COMPILER_GCC
|
||||
if (__libcpp_is_constant_evaluated()) {
|
||||
for (; __count; --__count, ++__lhs, ++__rhs) {
|
||||
if (*__lhs < *__rhs)
|
||||
return -1;
|
||||
if (*__rhs < *__lhs)
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
return __builtin_memcmp(__lhs, __rhs, __count);
|
||||
}
|
||||
|
||||
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 const char*
|
||||
__constexpr_char_memchr(const char* __str, int __char, size_t __count) {
|
||||
#if __has_builtin(__builtin_char_memchr)
|
||||
return __builtin_char_memchr(__str, __char, __count);
|
||||
#else
|
||||
if (!__libcpp_is_constant_evaluated())
|
||||
return static_cast<const char*>(std::memchr(__str, __char, __count));
|
||||
for (; __count; --__count) {
|
||||
if (*__str == __char)
|
||||
return __str;
|
||||
++__str;
|
||||
}
|
||||
return nullptr;
|
||||
#endif
|
||||
}
|
||||
|
||||
_LIBCPP_END_NAMESPACE_STD
|
||||
|
||||
#endif // _LIBCPP_CSTRING
|
||||
|
@ -104,6 +104,7 @@ size_t wcsrtombs(char* restrict dst, const wchar_t** restrict src, size_t len,
|
||||
|
||||
#include <__assert> // all public C++ headers provide the assertion handler
|
||||
#include <__config>
|
||||
#include <__type_traits/is_constant_evaluated.h>
|
||||
#include <cwctype>
|
||||
|
||||
#include <wchar.h>
|
||||
@ -189,6 +190,55 @@ using ::putwchar _LIBCPP_USING_IF_EXISTS;
|
||||
using ::vwprintf _LIBCPP_USING_IF_EXISTS;
|
||||
using ::wprintf _LIBCPP_USING_IF_EXISTS;
|
||||
|
||||
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 size_t __constexpr_wcslen(const wchar_t* __str) {
|
||||
#if __has_builtin(__builtin_wcslen)
|
||||
return __builtin_wcslen(__str);
|
||||
#else
|
||||
if (!__libcpp_is_constant_evaluated())
|
||||
return std::wcslen(__str);
|
||||
|
||||
size_t __len = 0;
|
||||
for (; *__str != L'\0'; ++__str)
|
||||
++__len;
|
||||
return __len;
|
||||
#endif
|
||||
}
|
||||
|
||||
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 int
|
||||
__constexpr_wmemcmp(const wchar_t* __lhs, const wchar_t* __rhs, size_t __count) {
|
||||
#if __has_builtin(__builtin_wmemcmp)
|
||||
return __builtin_wmemcmp(__lhs, __rhs, __count);
|
||||
#else
|
||||
if (!__libcpp_is_constant_evaluated())
|
||||
return std::wmemcmp(__lhs, __rhs, __count);
|
||||
|
||||
for (; __count; --__count, ++__lhs, ++__rhs) {
|
||||
if (*__lhs < *__rhs)
|
||||
return -1;
|
||||
if (*__rhs < *__lhs)
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 const wchar_t*
|
||||
__constexpr_wmemchr(const wchar_t* __str, wchar_t __char, size_t __count) {
|
||||
#if __has_feature(cxx_constexpr_string_builtins)
|
||||
return __builtin_wmemchr(__str, __char, __count);
|
||||
#else
|
||||
if (!__libcpp_is_constant_evaluated())
|
||||
return std::wmemchr(__str, __char, __count);
|
||||
|
||||
for (; __count; --__count) {
|
||||
if (*__str == __char)
|
||||
return __str;
|
||||
++__str;
|
||||
}
|
||||
return nullptr;
|
||||
#endif
|
||||
}
|
||||
|
||||
_LIBCPP_END_NAMESPACE_STD
|
||||
|
||||
#endif // _LIBCPP_CWCHAR
|
||||
|
@ -0,0 +1,24 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++03, c++11
|
||||
|
||||
// Check that __constexpr_* cstring functions are actually constexpr
|
||||
|
||||
#include <cstring>
|
||||
|
||||
static_assert(std::__constexpr_strlen("Banane") == 6, "");
|
||||
static_assert(std::__constexpr_memcmp("Banane", "Banand", 6) == 1, "");
|
||||
static_assert(std::__constexpr_memcmp("Banane", "Banane", 6) == 0, "");
|
||||
static_assert(std::__constexpr_memcmp("Banane", "Bananf", 6) == -1, "");
|
||||
|
||||
constexpr bool test_constexpr_wmemchr() {
|
||||
const char str[] = "Banane";
|
||||
return std::__constexpr_char_memchr(str, 'n', 6) == str + 2;
|
||||
}
|
||||
static_assert(test_constexpr_wmemchr(), "");
|
@ -0,0 +1,26 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++03, c++11
|
||||
|
||||
// UNSUPPORTED: no-wide-characters
|
||||
|
||||
// Check that __constexpr_* cwchar functions are actually constexpr
|
||||
|
||||
#include <cwchar>
|
||||
|
||||
static_assert(std::__constexpr_wcslen(L"Banane") == 6, "");
|
||||
static_assert(std::__constexpr_wmemcmp(L"Banane", L"Banand", 6) == 1, "");
|
||||
static_assert(std::__constexpr_wmemcmp(L"Banane", L"Banane", 6) == 0, "");
|
||||
static_assert(std::__constexpr_wmemcmp(L"Banane", L"Bananf", 6) == -1, "");
|
||||
|
||||
constexpr bool test_constexpr_wmemchr() {
|
||||
const wchar_t str[] = L"Banane";
|
||||
return std::__constexpr_wmemchr(str, 'n', 6) == str + 2;
|
||||
}
|
||||
static_assert(test_constexpr_wmemchr(), "");
|
Loading…
Reference in New Issue
Block a user