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

source code of flang/lib/Evaluate/character.h