FLANG
char-block.h
1//===-- include/flang/Parser/char-block.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_PARSER_CHAR_BLOCK_H_
10#define FORTRAN_PARSER_CHAR_BLOCK_H_
11
12// Describes a contiguous block of characters; does not own their storage.
13
14#include "llvm/ADT/StringRef.h"
15
16#include <algorithm>
17#include <cstddef>
18#include <cstring>
19#include <string>
20
21namespace llvm {
22class raw_ostream;
23}
24
25namespace Fortran::parser {
26
27class CharBlock : public llvm::StringRef {
28public:
29 using llvm::StringRef::StringRef;
30 CharBlock(const char *begin, const char *end)
31 : llvm::StringRef(begin, end - begin) {}
32 CharBlock(const char *begin) : llvm::StringRef(begin, 1) {}
33
34 // Checks whether the address range of "that" is contained in the
35 // address range of "this".
36 bool Contains(const CharBlock &that) const {
37 uintptr_t thisBegin{reinterpret_cast<uintptr_t>(begin())};
38 uintptr_t thisEnd{reinterpret_cast<uintptr_t>(end())};
39 uintptr_t thatBegin{reinterpret_cast<uintptr_t>(that.begin())};
40 uintptr_t thatEnd{reinterpret_cast<uintptr_t>(that.end())};
41 return thisBegin <= thatBegin && thatEnd <= thisEnd;
42 }
43
44 void ExtendToCover(const CharBlock &that) {
45 if (empty()) {
46 *this = that;
47 } else if (!that.empty()) {
48 *this = CharBlock(
49 std::min(begin(), that.begin()), std::max(end(), that.end()));
50 }
51 }
52
53 // Returns the block's first non-blank character, if it has
54 // one; otherwise ' '.
55 char FirstNonBlank() const {
56 size_t idx{LocateFirstNonBlank()};
57 return idx != npos ? data()[idx] : ' ';
58 }
59
60 // Returns the block's only non-blank character, if it has
61 // exactly one non-blank character; otherwise ' '.
62 char OnlyNonBlank() const {
63 char result{' '};
64 for (char ch : *this) {
65 if (ch != ' ' && ch != '\t') {
66 if (result == ' ') {
67 result = ch;
68 } else {
69 return ' ';
70 }
71 }
72 }
73 return result;
74 }
75
76 size_t CountLeadingBlanks() const {
77 size_t idx{LocateFirstNonBlank()};
78 return idx != npos ? idx : size();
79 }
80
81 bool IsBlank() const { return LocateFirstNonBlank() == npos; }
82
83 std::string ToString() const { return str(); }
84
85 // Convert to string, stopping early at any embedded '\0'.
86 std::string NULTerminatedToString() const {
87 return std::string{begin(), strnlen(begin(), size())};
88 }
89
90private:
91 size_t LocateFirstNonBlank() const {
92 return find_if_not([](char c) { return c == ' ' || c == '\t'; });
93 }
94};
95
96// An alternative comparator based on pointer values; use with care!
98 bool operator()(CharBlock x, CharBlock y) const {
99 return x.end() < y.begin();
100 }
101};
102
103llvm::raw_ostream &operator<<(llvm::raw_ostream &os, const CharBlock &x);
104
105} // namespace Fortran::parser
106
107// Specializations to enable std::unordered_map<CharBlock, ...> &c.
108template <> struct std::hash<Fortran::parser::CharBlock> {
109 std::size_t operator()(const Fortran::parser::CharBlock &x) const {
110 std::size_t hash{0}, bytes{x.size()};
111 for (std::size_t j{0}; j < bytes; ++j) {
112 hash = (hash * 31) ^ x[j];
113 }
114 return hash;
115 }
116};
117#endif // FORTRAN_PARSER_CHAR_BLOCK_H_
Definition char-block.h:27
Definition check-expression.h:19
Definition bit-population-count.h:20