brintos

brintos / llvm-project-archived public Read only

0
0
Text · 6.0 KiB · c2968f5 Raw
174 lines · c
1//===----------------------------------------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#ifndef TEST_SUPPORT_NASTY_STRING_H10#define TEST_SUPPORT_NASTY_STRING_H11 12#include <algorithm>13#include <cstddef>14#include <string>15#include <type_traits>16 17#include "make_string.h"18#include "test_macros.h"19#include "constexpr_char_traits.h" // is_pointer_in_range20 21// This defines a nasty_string similar to nasty_containers. This string's22// value_type does operator hijacking, which allows us to ensure that the23// library uses the provided `CharTraits` instead of using operations on24// the value_type directly.25 26#if TEST_STD_VER >= 2027// Make sure the char-like operations in strings do not depend on the char-like type.28struct nasty_char {29  template <typename T>30  friend auto operator<=>(T, T) = delete;31 32  template <typename T>33  friend void operator+(T&&) = delete;34 35  template <typename T>36  friend void operator-(T&&) = delete;37 38  template <typename T>39  friend void operator&(T&&) = delete;40 41  char c;42};43 44static_assert(std::is_trivially_copyable<nasty_char>::value, "");45static_assert(std::is_trivially_default_constructible<nasty_char>::value, "");46static_assert(std::is_standard_layout<nasty_char>::value, "");47 48// These traits are based on the constexpr_traits test class.49struct nasty_char_traits {50  typedef nasty_char char_type;51  typedef int int_type;52  typedef std::streamoff off_type;53  typedef std::streampos pos_type;54  typedef std::mbstate_t state_type;55  // The comparison_category is omitted so the class will have weak_ordering56  // in C++20. This is intentional.57 58  static constexpr void assign(char_type& c1, const char_type& c2) noexcept { c1 = c2; }59 60  static constexpr bool eq(char_type c1, char_type c2) noexcept { return c1.c == c2.c; }61 62  static constexpr bool lt(char_type c1, char_type c2) noexcept { return c1.c < c2.c; }63 64  static constexpr int compare(const char_type* s1, const char_type* s2, std::size_t n);65  static constexpr std::size_t length(const char_type* s);66  static constexpr const char_type* find(const char_type* s, std::size_t n, const char_type& a);67  static constexpr char_type* move(char_type* s1, const char_type* s2, std::size_t n);68  static constexpr char_type* copy(char_type* s1, const char_type* s2, std::size_t n);69  static constexpr char_type* assign(char_type* s, std::size_t n, char_type a);70 71  static constexpr int_type not_eof(int_type c) noexcept { return eq_int_type(c, eof()) ? ~eof() : c; }72 73  static constexpr char_type to_char_type(int_type c) noexcept { return char_type(c); }74 75  static constexpr int_type to_int_type(char_type c) noexcept { return int_type(c.c); }76 77  static constexpr bool eq_int_type(int_type c1, int_type c2) noexcept { return c1 == c2; }78 79  static constexpr int_type eof() noexcept { return int_type(EOF); }80};81 82constexpr int nasty_char_traits::compare(const nasty_char* s1, const nasty_char* s2, std::size_t n) {83  for (; n; --n, ++s1, ++s2) {84    if (lt(*s1, *s2))85      return -1;86    if (lt(*s2, *s1))87      return 1;88  }89  return 0;90}91 92constexpr std::size_t nasty_char_traits::length(const nasty_char* s) {93  std::size_t len = 0;94  for (; !eq(*s, nasty_char(0)); ++s)95    ++len;96  return len;97}98 99constexpr const nasty_char* nasty_char_traits::find(const nasty_char* s, std::size_t n, const nasty_char& a) {100  for (; n; --n) {101    if (eq(*s, a))102      return s;103    ++s;104  }105  return 0;106}107 108constexpr nasty_char* nasty_char_traits::move(nasty_char* s1, const nasty_char* s2, std::size_t n) {109  if (s1 == s2)110    return s1;111 112  nasty_char* r = s1;113  if (is_pointer_in_range(s1, s1 + n, s2)) {114    for (; n; --n)115      assign(*s1++, *s2++);116  } else {117    s1 += n;118    s2 += n;119    for (; n; --n)120      assign(*--s1, *--s2);121  }122  return r;123}124 125constexpr nasty_char* nasty_char_traits::copy(nasty_char* s1, const nasty_char* s2, std::size_t n) {126  if (!std::is_constant_evaluated()) // fails in constexpr because we might be comparing unrelated pointers127    assert(s2 < s1 || s2 >= s1 + n);128  nasty_char* r = s1;129  for (; n; --n, ++s1, ++s2)130    assign(*s1, *s2);131  return r;132}133 134constexpr nasty_char* nasty_char_traits::assign(nasty_char* s, std::size_t n, nasty_char a) {135  nasty_char* r = s;136  for (; n; --n, ++s)137    assign(*s, a);138  return r;139}140 141using nasty_string = std::basic_string<nasty_char, nasty_char_traits>;142 143template <std::size_t N>144struct ToNastyChar {145  constexpr ToNastyChar(const char (&r)[N]) {146    std::transform(r, r + N, std::addressof(text[0]), [](char c) { return nasty_char{c}; });147  }148  nasty_char text[N];149};150 151template <std::size_t N>152ToNastyChar(const char (&)[N]) -> ToNastyChar<N>;153 154template <ToNastyChar Str>155inline constexpr auto static_nasty_text = Str;156 157// A macro like MAKE_CSTRING158//159// The difference is this macro can convert the nasty_char too.160//161// The lambda is a template, so the 'if constexpr' false branch is not evaluated for the nasty_char.162#  define CONVERT_TO_CSTRING(CHAR, STR)                                                                                \163    []<class CharT> {                                                                                                  \164      if constexpr (std::is_same_v<CharT, nasty_char>) {                                                               \165        return static_nasty_text<STR>.text;                                                                            \166      } else                                                                                                           \167        return MAKE_CSTRING(CharT, STR);                                                                               \168    }.template operator()<CHAR>() /* */169#else                             // TEST_STD_VER >= 20170#  define CONVERT_TO_CSTRING(CharT, STR) MAKE_CSTRING(CharT, STR)171#endif // TEST_STD_VER >= 20172 173#endif // TEST_SUPPORT_NASTY_STRING_H174