FLANG
character.h
1//===-- lib/Evaluate/character.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_H_
10#define FORTRAN_EVALUATE_CHARACTER_H_
11
12#include "flang/Evaluate/character-value.h"
13#include "flang/Evaluate/type.h"
14#include <cstdint>
15#include <string>
16
17// Provides implementations of intrinsic functions operating on character
18// scalars.
19
20namespace Fortran::evaluate {
21
23 using Character = Scalar<Type<TypeCategory::Character>>;
24 using CharT = char32_t;
25
26public:
27 // CHAR also implements ACHAR under assumption that character encodings
28 // contain ASCII
29 static Character CHAR(int kind, std::uint64_t code) {
30 return Character{kind, 1, static_cast<CharT>(code)};
31 }
32
33 // ICHAR also implements IACHAR under assumption that character encodings
34 // contain ASCII
35 static std::int64_t ICHAR(const Character &c) {
36 CHECK(c.length() == 1);
37 // CharacterValue::operator[] always zero-extends to char32_t. char32_t
38 // itself is defined as unsigned such that only zero-extend widening occurs.
39 return c[0];
40 }
41
42 static Character NEW_LINE(int kind) { return Character{kind, 1, NewLine()}; }
43
44 static Character ADJUSTL(const Character &str) {
45 const int kind{str.kind()};
46 auto pos{str.find_first_not_of(Space())};
47 if (pos != Character::npos && pos != 0) {
48 return Character{str.substr(pos) + Character{kind, pos, Space()}};
49 }
50 // else empty or only spaces, or no leading spaces
51 return str;
52 }
53
54 static Character ADJUSTR(const Character &str) {
55 const int kind{str.kind()};
56 auto pos{str.find_last_not_of(Space())};
57 if (pos != Character::npos && pos != str.length() - 1) {
58 auto delta{str.length() - 1 - pos};
59 return Character{
60 Character{kind, delta, Space()} + str.substr(0, pos + 1)};
61 }
62 // else empty or only spaces, or no trailing spaces
63 return str;
64 }
65
66 static ConstantSubscript INDEX(
67 const Character &str, const Character &substr, bool back = false) {
68 auto pos{back ? str.rfind(substr) : str.find(substr)};
69 return static_cast<ConstantSubscript>(pos == str.npos ? 0 : pos + 1);
70 }
71
72 static ConstantSubscript SCAN(
73 const Character &str, const Character &set, bool back = false) {
74 auto pos{back ? str.find_last_of(set) : str.find_first_of(set)};
75 return static_cast<ConstantSubscript>(pos == str.npos ? 0 : pos + 1);
76 }
77
78 static ConstantSubscript VERIFY(
79 const Character &str, const Character &set, bool back = false) {
80 auto pos{back ? str.find_last_not_of(set) : str.find_first_not_of(set)};
81 return static_cast<ConstantSubscript>(pos == str.npos ? 0 : pos + 1);
82 }
83
84 // Resize adds spaces on the right if the new size is bigger than the
85 // original, or by trimming the rightmost characters otherwise.
86 static Character Resize(const Character &str, std::size_t newLength) {
87 const int kind{str.kind()};
88 auto oldLength{str.length()};
89 if (newLength > oldLength) {
90 return str + Character{kind, newLength - oldLength, Space()};
91 } else {
92 return str.substr(0, newLength);
93 }
94 }
95
96 static ConstantSubscript LEN_TRIM(const Character &str) {
97 auto j{str.length()};
98 for (; j >= 1; --j) {
99 if (str[j - 1] != ' ') {
100 break;
101 }
102 }
103 return static_cast<ConstantSubscript>(j);
104 }
105
106 static Character REPEAT(const Character &str, ConstantSubscript ncopies) {
107 const int kind{str.kind()};
108 Character result{Character::Zero(kind)};
109 if (!str.empty() && ncopies > 0) {
110 result.reserve(ncopies * str.size());
111 while (ncopies-- > 0) {
112 result += str;
113 }
114 }
115 return result;
116 }
117
118 static Character TRIM(const Character &str) {
119 return str.substr(0, LEN_TRIM(str));
120 }
121
122private:
123 // Following helpers assume that character encodings contain ASCII
124 static constexpr CharT Space() { return 0x20; }
125 static constexpr CharT NewLine() { return 0x0a; }
126};
127
128} // namespace Fortran::evaluate
129
130#endif // FORTRAN_EVALUATE_CHARACTER_H_
Definition character.h:22
Definition call.h:34