9#ifndef FORTRAN_EVALUATE_CHARACTER_VALUE_IMPL_H_
10#define FORTRAN_EVALUATE_CHARACTER_VALUE_IMPL_H_
12#include "flang/Evaluate/common.h"
13#include "llvm/Support/ErrorHandling.h"
20namespace Fortran::evaluate::value {
22class CharacterValueImpl {
24 std::variant<std::monostate, std::string, std::u16string, std::u32string>;
28 ~CharacterValueImpl() =
default;
29 CharacterValueImpl(
const CharacterValueImpl &) =
default;
30 CharacterValueImpl(CharacterValueImpl &&) =
default;
31 CharacterValueImpl &operator=(
const CharacterValueImpl &) =
default;
32 CharacterValueImpl &operator=(CharacterValueImpl &&) =
default;
34 CharacterValueImpl() =
default;
35 explicit CharacterValueImpl(
int kind, std::string s) {
36 WithCharProto(kind, [&](
auto c) {
37 using CharT = std::decay_t<
decltype(c)>;
38 using StringT = std::basic_string<CharT>;
39 if (std::is_same_v<StringT, std::string>) {
40 storage_ = std::move(s);
43 buf.resize(s.length());
44 for (
auto [i, c] : llvm::enumerate(s)) {
47 buf[i] =
static_cast<unsigned char>(c);
49 storage_ = std::move(buf);
53 CHECK(this->kind() == kind);
56 explicit CharacterValueImpl(
int kind, std::u16string s)
57 : storage_{std::move(s)} {
59 CHECK(this->kind() == kind);
62 explicit CharacterValueImpl(
int kind, std::u32string s)
63 : storage_{std::move(s)} {
65 CHECK(this->kind() == kind);
69 CharacterValueImpl(
int kind, std::size_t n,
char32_t c);
71 static CharacterValueImpl Zero(
int kind);
73 static CharacterValueImpl FromRawBytes(
74 int kind,
const void *raw,
size_t byteSize);
76 void print(llvm::raw_ostream &os)
const;
78#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
79 LLVM_DUMP_METHOD
void dump()
const;
82 std::optional<llvm::StringRef> AsStringRef()
const;
86 std::optional<std::u16string> AsU16String()
const;
87 std::optional<std::u32string> AsU32String()
const;
89 std::string ToStdString()
const;
91 bool IsNull()
const {
return storage_.index() == 0; }
98 std::size_t
size()
const;
107 void *
data() {
return charData(); }
108 const void *
data()
const {
return charData(); }
110 const void *charData()
const;
113 Ordering Compare(
const CharacterValueImpl &y)
const;
114 bool operator<(
const CharacterValueImpl &y)
const;
115 bool operator<=(
const CharacterValueImpl &y)
const {
return !(y < *
this); }
116 bool operator==(
const CharacterValueImpl &y)
const;
117 bool operator!=(
const CharacterValueImpl &y)
const {
return !(*
this == y); }
118 bool operator>=(
const CharacterValueImpl &y)
const {
return !(*
this < y); }
119 bool operator>(
const CharacterValueImpl &y)
const {
return y < *
this; }
122 void assign(
int kind, std::size_t n,
char32_t c);
125 void assign(
const char *p, std::size_t n) { storage_ = std::string(p, n); }
126 void assign(
const char16_t *p, std::size_t n) {
127 storage_ = std::u16string(p, n);
129 void assign(
const char32_t *p, std::size_t n) {
130 storage_ = std::u32string(p, n);
134 void erase(std::size_t pos);
137 void append(std::size_t n,
char32_t c);
141 std::size_t pos, std::size_t len,
const CharacterValueImpl &other);
144 CharacterValueImpl
substr(std::size_t pos)
const;
147 CharacterValueImpl
substr(std::size_t pos, std::size_t len)
const;
149 CharacterValueImpl ToAscii(
int kind)
const;
158 CharacterValueImpl
operator+(
const CharacterValueImpl &y)
const;
161 CharacterValueImpl &
operator+=(
const CharacterValueImpl &y);
167 static constexpr std::size_t
npos{std::string::npos};
173 std::size_t find_first_not_of(
char c)
const {
174 return find_first_not_of(
static_cast<char32_t>(c));
176 std::size_t find_first_not_of(
char16_t c)
const {
177 return find_first_not_of(
static_cast<char32_t>(c));
179 std::size_t find_first_not_of(
char32_t c)
const;
180 std::size_t find_last_not_of(
char c)
const {
181 return find_last_not_of(
static_cast<char32_t>(c));
183 std::size_t find_last_not_of(
char16_t c)
const {
184 return find_last_not_of(
static_cast<char32_t>(c));
186 std::size_t find_last_not_of(
char32_t c)
const;
187 std::size_t find_first_not_of(
const CharacterValueImpl &set)
const;
188 std::size_t find_last_not_of(
const CharacterValueImpl &set)
const;
189 std::size_t find_first_of(
const CharacterValueImpl &set)
const;
190 std::size_t find_last_of(
const CharacterValueImpl &set)
const;
193 void *dst, std::size_t
size,
bool *changed =
nullptr)
const;
197 template <
typename CharT,
typename = std::
void_t<std::basic_
string<CharT>>>
198 const std::basic_string<CharT> &GetBasicString()
const;
200 template <
typename F>
201 auto WithCharProto(F &&f)
const
202 ->
decltype(std::declval<F>()(std::declval<char>())) {
203 return WithCharProto(kind(), f);
206 template <
typename F>
207 static auto WithCharProto(
int kind, F &&f)
208 ->
decltype(std::declval<F>()(std::declval<char>())) {
213 return f(
char16_t{});
215 return f(
char32_t{});
217 DIE(
"unsupported character kind/null state");
221 template <
typename F>
222 auto WithBasicString(F &&f)
const
223 ->
decltype(f(std::declval<const std::string &>())) {
224 return common::visit(
226 [](std::monostate) ->
decltype(f(
227 std::declval<const std::string &>())) {
228 DIE(
"operation on uninitialized CharacterValueImpl");
243inline raw_ostream &operator<<(
244 raw_ostream &os,
const Fortran::evaluate::value::CharacterValueImpl &v) {
Definition character-value-impl.h:22
void append(std::size_t n, char32_t c)
Append n copies of the given character.
Definition character-value-impl.cpp:216
void * data()
Raw byte pointer to the underlying character data.
Definition character-value-impl.h:107
std::size_t charSize() const
Byte size of one character unit (1, 2, or 4).
Definition character-value-impl.cpp:79
CharacterValueImpl & replace(std::size_t pos, std::size_t len, const CharacterValueImpl &other)
Replace the substring [pos, pos+len) with characters from other.
Definition character-value-impl.cpp:230
void reserve(std::size_t n)
Reserve storage for at least n characters.
Definition character-value-impl.cpp:368
static constexpr std::size_t npos
Sentinel value for "not found" positions (same as std::string::npos).
Definition character-value-impl.h:167
void erase(std::size_t pos)
Erase from position pos to end.
Definition character-value-impl.cpp:203
CharacterValueImpl & operator+=(const CharacterValueImpl &y)
Append another same-kind string.
Definition character-value-impl.cpp:414
void assign(int kind, std::size_t n, char32_t c)
Assign n copies of the given character.
Definition character-value-impl.cpp:196
bool empty() const
True when the string is empty.
Definition character-value-impl.h:104
std::size_t size() const
Number of characters in this string.
Definition character-value-impl.cpp:92
std::optional< std::string > AsStdString() const
Return the string as std::string if kind==1, or nullopt otherwise.
Definition character-value-impl.cpp:289
char32_t operator[](std::size_t i) const
Return the character at position i as char32_t (safe for all kinds).
Definition character-value-impl.cpp:379
void assign(const char *p, std::size_t n)
Assign from a raw character pointer and length.
Definition character-value-impl.h:125
std::size_t length() const
String length (synonym for size()).
Definition character-value-impl.h:101
CharacterValueImpl operator+(const CharacterValueImpl &y) const
Concatenate two same-kind strings.
Definition character-value-impl.cpp:396
CharacterValueImpl substr(std::size_t pos) const
Return a suffix starting at pos.
Definition character-value-impl.cpp:249