FLANG
character-value.h
1//===-- include/flang/Evaluate/character-value.h ----------------*- C++ -*-===//
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-exception
6//
7//===----------------------------------------------------------------------===//
8
9#ifndef FORTRAN_EVALUATE_CHARACTER_VALUE_H_
10#define FORTRAN_EVALUATE_CHARACTER_VALUE_H_
11
12#include "flang/Evaluate/common.h"
13#include "flang/Evaluate/object-sizes.h"
14#include "flang/Evaluate/type.h"
15#include "llvm/Support/Compiler.h"
16#include "llvm/Support/raw_ostream.h"
17#include <cstddef>
18#include <iosfwd>
19#include <optional>
20#include <string>
21
22namespace Fortran::evaluate::value {
24
34class CharacterValue {
35public:
36 // rule-of-five
37 ~CharacterValue();
38 CharacterValue(const CharacterValue &);
39 CharacterValue(CharacterValue &&);
40 CharacterValue &operator=(const CharacterValue &);
41 CharacterValue &operator=(CharacterValue &&);
42
43 // ctors
44
49
50 explicit CharacterValue(int kind, std::string s);
51 explicit CharacterValue(int kind, std::u16string s);
52 explicit CharacterValue(int kind, std::u32string s);
53
55 CharacterValue(int kind, std::size_t n, char32_t c);
56
57 // Named ctors
58 static CharacterValue Zero(int kind);
59
60 static CharacterValue FromRawBytes(
61 int kind, const void *raw, size_t byteSize);
62
63 void print(llvm::raw_ostream &os) const;
64
65#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
66 LLVM_DUMP_METHOD void dump() const;
67#endif
68
71 bool IsNull() const;
72
74 int kind() const;
75
76 bool empty() const;
77 std::size_t size() const;
78 std::size_t length() const { return size(); }
79
81 std::size_t charSize() const { return kind(); }
82
84 size_t bytesStored() const { return length() * charSize(); }
85
86 // Casting to other representations
87 std::optional<llvm::StringRef> AsStringRef() const;
88 std::optional<std::string> AsStdString() const {
89 if (auto str{AsStringRef()}) {
90 return str->str();
91 }
92 return std::nullopt;
93 }
94 std::optional<std::u16string> AsU16String() const;
95 std::optional<std::u32string> AsU32String() const;
96
98 std::string ToStdString() const;
99
100 template <typename CharT, typename = std::void_t<std::basic_string<CharT>>>
101 std::optional<std::basic_string<CharT>> AsBasicString() const {
102 if constexpr (std::is_same_v<char, CharT>) {
103 return AsStdString();
104 } else if constexpr (std::is_same_v<char16_t, CharT>) {
105 return AsU16String();
106 } else if constexpr (std::is_same_v<char32_t, CharT>) {
107 return AsU32String();
108 } else {
109 static_assert(
110 !sizeof(CharT), "Must be one of the supported character types");
111 }
112 }
113
114 // Comparisons
115 Ordering Compare(const CharacterValue &y) const;
116 bool operator<(const CharacterValue &y) const;
117 bool operator<=(const CharacterValue &y) const { return !(y < *this); }
118 bool operator==(const CharacterValue &y) const;
119 bool operator!=(const CharacterValue &y) const { return !(*this == y); }
120 bool operator>=(const CharacterValue &y) const { return !(*this < y); }
121 bool operator>(const CharacterValue &y) const { return y < *this; }
122
123 CharacterValue ToAscii(int kind) const;
124
127 void assign(int kind, std::size_t n, char32_t c);
128
130 void assign(const char *p, std::size_t n);
131 void assign(const char16_t *p, std::size_t n);
132 void assign(const char32_t *p, std::size_t n);
133
135 void erase(std::size_t pos);
136
138 void append(std::size_t n, char32_t c);
139
141 CharacterValue &replace(
142 std::size_t pos, std::size_t len, const CharacterValue &other);
143
145 CharacterValue substr(std::size_t pos) const;
146
148 CharacterValue substr(std::size_t pos, std::size_t len) const;
149
151 void reserve(std::size_t n);
152
154 char32_t operator[](std::size_t i) const;
155
157 CharacterValue operator+(const CharacterValue &y) const;
158
160 CharacterValue &operator+=(const CharacterValue &y);
161
163 CharacterValue &operator+=(char32_t c);
164
166 static constexpr std::size_t npos{std::string::npos};
167
168 // Find-family methods; return npos when not found.
169 std::size_t find(const CharacterValue &pattern) const;
170 std::size_t rfind(const CharacterValue &pattern) const;
171 std::size_t find_first_of(const CharacterValue &set) const;
172 std::size_t find_last_of(const CharacterValue &set) const;
173 std::size_t find_first_not_of(char32_t c) const;
174 std::size_t find_last_not_of(char32_t c) const;
175 std::size_t find_first_not_of(const CharacterValue &set) const;
176 std::size_t find_last_not_of(const CharacterValue &set) const;
177
179 void *data();
180 const void *data() const;
181
183 char *charData() { return static_cast<char *>(data()); }
184 const char *charData() const { return static_cast<const char *>(data()); }
185
186 void *at(size_t pos) { return &charData()[pos * charSize()]; }
187 const void *at(size_t pos) const { return &charData()[pos * charSize()]; }
188
195 void StoreRawBytes(void *dst, size_t size, bool *changed = nullptr) const;
196
197 template <typename F>
198 static auto withCharProto(int kind, F &&f)
199 -> decltype(std::declval<F>()(std::declval<char>())) {
200 switch (kind) {
201 case 1:
202 return f(char{});
203 case 2:
204 return f(char16_t{});
205 case 4:
206 return f(char32_t{});
207 default:
208 DIE("unsupported character kind/null state");
209 }
210 }
211
212 template <typename F> decltype(auto) withStdString(F &&f) const {
213 switch (kind()) {
214 case 1:
215 return f(*AsStdString());
216 case 2:
217 return f(*AsU16String());
218 case 4:
219 return f(*AsU32String());
220 default:
221 DIE("unsupported kind/null state");
222 }
223 }
224
225private:
226 static CharacterValue FromImpl(const CharacterValueImpl &y);
227 static CharacterValue FromImpl(CharacterValueImpl &&y);
228
229 CharacterValueImpl &impl() {
230 return *reinterpret_cast<CharacterValueImpl *>(this);
231 }
232 const CharacterValueImpl &impl() const {
233 return *reinterpret_cast<const CharacterValueImpl *>(this);
234 }
235
236 [[maybe_unused]] alignas(
237 detail::kCharacterObjectAlign) char opaque_[detail::kCharacterObjectSize];
238};
239
240} // namespace Fortran::evaluate::value
241
242namespace llvm {
244inline raw_ostream &operator<<(
245 raw_ostream &os, const Fortran::evaluate::value::CharacterValue &v) {
246 v.print(os);
247 return os;
248}
249} // namespace llvm
250
251#endif // FORTRAN_EVALUATE_CHARACTER_VALUE_H_
Definition character-value-impl.h:22
Definition character-value.h:34
int kind() const
The kind of the value currently stored.
Definition character-value.cpp:83
std::string ToStdString() const
Force conversion to Ascii even if this means loss of information.
Definition character-value.cpp:97
void * data()
Raw byte pointer to the underlying character data.
Definition character-value.cpp:201
char * charData()
Like data(), but pre-casted to char.
Definition character-value.h:183
CharacterValue & operator+=(const CharacterValue &y)
Append another same-kind string.
Definition character-value.cpp:159
void append(std::size_t n, char32_t c)
Append n copies of the given character (widened to the stored type).
Definition character-value.cpp:133
CharacterValue()
Definition character-value.cpp:22
size_t bytesStored() const
Number of bytes accessed by FromRawBytes/StoreRawBytes.
Definition character-value.h:84
char32_t operator[](std::size_t i) const
Return the character at position i.
Definition character-value.cpp:151
std::size_t charSize() const
Byte size of one character unit (1, 2, or 4).
Definition character-value.h:81
void reserve(std::size_t n)
Reserve storage for at least n characters.
Definition character-value.cpp:149
CharacterValue operator+(const CharacterValue &y) const
Concatenate two same-kind strings.
Definition character-value.cpp:155
void assign(int kind, std::size_t n, char32_t c)
Definition character-value.cpp:115
static constexpr std::size_t npos
Sentinel value for "not found" positions (same as std::string::npos).
Definition character-value.h:166
CharacterValue substr(std::size_t pos) const
Return a suffix starting at pos.
Definition character-value.cpp:141
void erase(std::size_t pos)
Erase from position pos to end.
Definition character-value.cpp:131
bool IsNull() const
Definition character-value.cpp:77
CharacterValue & replace(std::size_t pos, std::size_t len, const CharacterValue &other)
Replace the substring [pos, pos+len) with characters from other.
Definition character-value.cpp:135
void StoreRawBytes(void *dst, size_t size, bool *changed=nullptr) const
Definition character-value.cpp:204