1 //===-- lib/Evaluate/character.h --------------------------------*- C++ -*-===//
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
7 //===----------------------------------------------------------------------===//
9 #ifndef FORTRAN_EVALUATE_CHARACTER_H_
10 #define FORTRAN_EVALUATE_CHARACTER_H_
12 #include "flang/Evaluate/type.h"
15 // Provides implementations of intrinsic functions operating on character
16 // scalars. No assumption is made regarding character encodings other than they
17 // must be compatible with ASCII (else, NEW_LINE, ACHAR and IACHAR need to be
20 namespace Fortran::evaluate
{
22 template <int KIND
> class CharacterUtils
{
23 using Character
= Scalar
<Type
<TypeCategory::Character
, KIND
>>;
24 using CharT
= typename
Character::value_type
;
27 // CHAR also implements ACHAR under assumption that character encodings
29 static Character
CHAR(std::uint64_t code
) {
30 return Character
{{static_cast<CharT
>(code
)}};
33 // ICHAR also implements IACHAR under assumption that character encodings
35 static std::int64_t ICHAR(const Character
&c
) {
36 CHECK(c
.length() == 1);
37 if constexpr (std::is_same_v
<CharT
, char>) {
38 // char may be signed, so cast it first to unsigned to avoid having
39 // ichar(char(128_4)) returning -128
40 return static_cast<unsigned char>(c
[0]);
46 static Character
NEW_LINE() { return Character
{{NewLine()}}; }
48 static Character
ADJUSTL(const Character
&str
) {
49 auto pos
{str
.find_first_not_of(Space())};
50 if (pos
!= Character::npos
&& pos
!= 0) {
51 return Character
{str
.substr(pos
) + Character(pos
, Space())};
53 // else empty or only spaces, or no leading spaces
57 static Character
ADJUSTR(const Character
&str
) {
58 auto pos
{str
.find_last_not_of(Space())};
59 if (pos
!= Character::npos
&& pos
!= str
.length() - 1) {
60 auto delta
{str
.length() - 1 - pos
};
61 return Character
{Character(delta
, Space()) + str
.substr(0, pos
+ 1)};
63 // else empty or only spaces, or no trailing spaces
67 static ConstantSubscript
INDEX(
68 const Character
&str
, const Character
&substr
, bool back
= false) {
69 auto pos
{back
? str
.rfind(substr
) : str
.find(substr
)};
70 return static_cast<ConstantSubscript
>(pos
== str
.npos
? 0 : pos
+ 1);
73 static ConstantSubscript
SCAN(
74 const Character
&str
, const Character
&set
, bool back
= false) {
75 auto pos
{back
? str
.find_last_of(set
) : str
.find_first_of(set
)};
76 return static_cast<ConstantSubscript
>(pos
== str
.npos
? 0 : pos
+ 1);
79 static ConstantSubscript
VERIFY(
80 const Character
&str
, const Character
&set
, bool back
= false) {
81 auto pos
{back
? str
.find_last_not_of(set
) : str
.find_first_not_of(set
)};
82 return static_cast<ConstantSubscript
>(pos
== str
.npos
? 0 : pos
+ 1);
85 // Resize adds spaces on the right if the new size is bigger than the
86 // original, or by trimming the rightmost characters otherwise.
87 static Character
Resize(const Character
&str
, std::size_t newLength
) {
88 auto oldLength
{str
.length()};
89 if (newLength
> oldLength
) {
90 return str
+ Character(newLength
- oldLength
, Space());
92 return str
.substr(0, newLength
);
96 static ConstantSubscript
LEN_TRIM(const Character
&str
) {
97 return VERIFY(str
, Character
{' '}, true);
100 static Character
REPEAT(const Character
&str
, ConstantSubscript ncopies
) {
103 while (ncopies
-- > 0) {
110 static Character
TRIM(const Character
&str
) {
111 return str
.substr(0, LEN_TRIM(str
));
115 // Following helpers assume that character encodings contain ASCII
116 static constexpr CharT
Space() { return 0x20; }
117 static constexpr CharT
NewLine() { return 0x0a; }
120 } // namespace Fortran::evaluate
122 #endif // FORTRAN_EVALUATE_CHARACTER_H_