LLVM  6.0.0svn
StringSwitch.h
Go to the documentation of this file.
1 //===--- StringSwitch.h - Switch-on-literal-string Construct --------------===/
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //===----------------------------------------------------------------------===/
8 //
9 // This file implements the StringSwitch template, which mimics a switch()
10 // statement whose cases are string literals.
11 //
12 //===----------------------------------------------------------------------===/
13 #ifndef LLVM_ADT_STRINGSWITCH_H
14 #define LLVM_ADT_STRINGSWITCH_H
15 
16 #include "llvm/ADT/StringRef.h"
17 #include "llvm/Support/Compiler.h"
18 #include <cassert>
19 #include <cstring>
20 
21 namespace llvm {
22 
23 /// \brief A switch()-like statement whose cases are string literals.
24 ///
25 /// The StringSwitch class is a simple form of a switch() statement that
26 /// determines whether the given string matches one of the given string
27 /// literals. The template type parameter \p T is the type of the value that
28 /// will be returned from the string-switch expression. For example,
29 /// the following code switches on the name of a color in \c argv[i]:
30 ///
31 /// \code
32 /// Color color = StringSwitch<Color>(argv[i])
33 /// .Case("red", Red)
34 /// .Case("orange", Orange)
35 /// .Case("yellow", Yellow)
36 /// .Case("green", Green)
37 /// .Case("blue", Blue)
38 /// .Case("indigo", Indigo)
39 /// .Cases("violet", "purple", Violet)
40 /// .Default(UnknownColor);
41 /// \endcode
42 template<typename T, typename R = T>
43 class StringSwitch {
44  /// \brief The string we are matching.
45  StringRef Str;
46 
47  /// \brief The pointer to the result of this switch statement, once known,
48  /// null before that.
49  const T *Result;
50 
51 public:
53  explicit StringSwitch(StringRef S)
54  : Str(S), Result(nullptr) { }
55 
56  // StringSwitch is not copyable.
57  StringSwitch(const StringSwitch &) = delete;
58  void operator=(const StringSwitch &) = delete;
59 
61  *this = std::move(other);
62  }
64  Str = other.Str;
65  Result = other.Result;
66  return *this;
67  }
68 
69  ~StringSwitch() = default;
70 
71  // Case-sensitive case matchers
72  template<unsigned N>
74  StringSwitch& Case(const char (&S)[N], const T& Value) {
75  assert(N);
76  if (!Result && N-1 == Str.size() &&
77  (N == 1 || std::memcmp(S, Str.data(), N-1) == 0)) {
78  Result = &Value;
79  }
80  return *this;
81  }
82 
83  template<unsigned N>
85  StringSwitch& EndsWith(const char (&S)[N], const T &Value) {
86  assert(N);
87  if (!Result && Str.size() >= N-1 &&
88  (N == 1 || std::memcmp(S, Str.data() + Str.size() + 1 - N, N-1) == 0)) {
89  Result = &Value;
90  }
91  return *this;
92  }
93 
94  template<unsigned N>
96  StringSwitch& StartsWith(const char (&S)[N], const T &Value) {
97  assert(N);
98  if (!Result && Str.size() >= N-1 &&
99  (N == 1 || std::memcmp(S, Str.data(), N-1) == 0)) {
100  Result = &Value;
101  }
102  return *this;
103  }
104 
105  template<unsigned N0, unsigned N1>
107  StringSwitch &Cases(const char (&S0)[N0], const char (&S1)[N1],
108  const T& Value) {
109  return Case(S0, Value).Case(S1, Value);
110  }
111 
112  template<unsigned N0, unsigned N1, unsigned N2>
114  StringSwitch &Cases(const char (&S0)[N0], const char (&S1)[N1],
115  const char (&S2)[N2], const T& Value) {
116  return Case(S0, Value).Cases(S1, S2, Value);
117  }
118 
119  template<unsigned N0, unsigned N1, unsigned N2, unsigned N3>
121  StringSwitch &Cases(const char (&S0)[N0], const char (&S1)[N1],
122  const char (&S2)[N2], const char (&S3)[N3],
123  const T& Value) {
124  return Case(S0, Value).Cases(S1, S2, S3, Value);
125  }
126 
127  template<unsigned N0, unsigned N1, unsigned N2, unsigned N3, unsigned N4>
129  StringSwitch &Cases(const char (&S0)[N0], const char (&S1)[N1],
130  const char (&S2)[N2], const char (&S3)[N3],
131  const char (&S4)[N4], const T& Value) {
132  return Case(S0, Value).Cases(S1, S2, S3, S4, Value);
133  }
134 
135  template <unsigned N0, unsigned N1, unsigned N2, unsigned N3, unsigned N4,
136  unsigned N5>
138  StringSwitch &Cases(const char (&S0)[N0], const char (&S1)[N1],
139  const char (&S2)[N2], const char (&S3)[N3],
140  const char (&S4)[N4], const char (&S5)[N5],
141  const T &Value) {
142  return Case(S0, Value).Cases(S1, S2, S3, S4, S5, Value);
143  }
144 
145  template <unsigned N0, unsigned N1, unsigned N2, unsigned N3, unsigned N4,
146  unsigned N5, unsigned N6>
148  StringSwitch &Cases(const char (&S0)[N0], const char (&S1)[N1],
149  const char (&S2)[N2], const char (&S3)[N3],
150  const char (&S4)[N4], const char (&S5)[N5],
151  const char (&S6)[N6], const T &Value) {
152  return Case(S0, Value).Cases(S1, S2, S3, S4, S5, S6, Value);
153  }
154 
155  template <unsigned N0, unsigned N1, unsigned N2, unsigned N3, unsigned N4,
156  unsigned N5, unsigned N6, unsigned N7>
158  StringSwitch &Cases(const char (&S0)[N0], const char (&S1)[N1],
159  const char (&S2)[N2], const char (&S3)[N3],
160  const char (&S4)[N4], const char (&S5)[N5],
161  const char (&S6)[N6], const char (&S7)[N7],
162  const T &Value) {
163  return Case(S0, Value).Cases(S1, S2, S3, S4, S5, S6, S7, Value);
164  }
165 
166  template <unsigned N0, unsigned N1, unsigned N2, unsigned N3, unsigned N4,
167  unsigned N5, unsigned N6, unsigned N7, unsigned N8>
169  StringSwitch &Cases(const char (&S0)[N0], const char (&S1)[N1],
170  const char (&S2)[N2], const char (&S3)[N3],
171  const char (&S4)[N4], const char (&S5)[N5],
172  const char (&S6)[N6], const char (&S7)[N7],
173  const char (&S8)[N8], const T &Value) {
174  return Case(S0, Value).Cases(S1, S2, S3, S4, S5, S6, S7, S8, Value);
175  }
176 
177  template <unsigned N0, unsigned N1, unsigned N2, unsigned N3, unsigned N4,
178  unsigned N5, unsigned N6, unsigned N7, unsigned N8, unsigned N9>
180  StringSwitch &Cases(const char (&S0)[N0], const char (&S1)[N1],
181  const char (&S2)[N2], const char (&S3)[N3],
182  const char (&S4)[N4], const char (&S5)[N5],
183  const char (&S6)[N6], const char (&S7)[N7],
184  const char (&S8)[N8], const char (&S9)[N9],
185  const T &Value) {
186  return Case(S0, Value).Cases(S1, S2, S3, S4, S5, S6, S7, S8, S9, Value);
187  }
188 
189  // Case-insensitive case matchers.
190  template <unsigned N>
192  const T &Value) {
193  if (!Result && Str.equals_lower(StringRef(S, N - 1)))
194  Result = &Value;
195 
196  return *this;
197  }
198 
199  template <unsigned N>
201  const T &Value) {
202  if (!Result && Str.endswith_lower(StringRef(S, N - 1)))
203  Result = &Value;
204 
205  return *this;
206  }
207 
208  template <unsigned N>
210  const T &Value) {
211  if (!Result && Str.startswith_lower(StringRef(S, N - 1)))
212  Result = &Value;
213 
214  return *this;
215  }
216  template <unsigned N0, unsigned N1>
218  CasesLower(const char (&S0)[N0], const char (&S1)[N1], const T &Value) {
219  return CaseLower(S0, Value).CaseLower(S1, Value);
220  }
221 
222  template <unsigned N0, unsigned N1, unsigned N2>
224  CasesLower(const char (&S0)[N0], const char (&S1)[N1], const char (&S2)[N2],
225  const T &Value) {
226  return CaseLower(S0, Value).CasesLower(S1, S2, Value);
227  }
228 
229  template <unsigned N0, unsigned N1, unsigned N2, unsigned N3>
231  CasesLower(const char (&S0)[N0], const char (&S1)[N1], const char (&S2)[N2],
232  const char (&S3)[N3], const T &Value) {
233  return CaseLower(S0, Value).CasesLower(S1, S2, S3, Value);
234  }
235 
236  template <unsigned N0, unsigned N1, unsigned N2, unsigned N3, unsigned N4>
238  CasesLower(const char (&S0)[N0], const char (&S1)[N1], const char (&S2)[N2],
239  const char (&S3)[N3], const char (&S4)[N4], const T &Value) {
240  return CaseLower(S0, Value).CasesLower(S1, S2, S3, S4, Value);
241  }
242 
244  R Default(const T &Value) const {
245  if (Result)
246  return *Result;
247  return Value;
248  }
249 
251  operator R() const {
252  assert(Result && "Fell off the end of a string-switch");
253  return *Result;
254  }
255 };
256 
257 } // end namespace llvm
258 
259 #endif // LLVM_ADT_STRINGSWITCH_H
LLVM_NODISCARD bool startswith_lower(StringRef Prefix) const
Check if this string starts with the given Prefix, ignoring case.
Definition: StringRef.cpp:62
Compute iterated dominance frontiers using a linear time algorithm.
Definition: AllocatorList.h:24
LLVM_ATTRIBUTE_ALWAYS_INLINE StringSwitch & CaseLower(const char(&S)[N], const T &Value)
Definition: StringSwitch.h:191
LLVM_ATTRIBUTE_ALWAYS_INLINE StringSwitch & CasesLower(const char(&S0)[N0], const char(&S1)[N1], const char(&S2)[N2], const char(&S3)[N3], const char(&S4)[N4], const T &Value)
Definition: StringSwitch.h:238
LLVM_NODISCARD bool equals_lower(StringRef RHS) const
equals_lower - Check for string equality, ignoring case.
Definition: StringRef.h:176
~StringSwitch()=default
LLVM_NODISCARD LLVM_ATTRIBUTE_ALWAYS_INLINE size_t size() const
size - Get the string size.
Definition: StringRef.h:138
LLVM_ATTRIBUTE_ALWAYS_INLINE StringSwitch & Cases(const char(&S0)[N0], const char(&S1)[N1], const char(&S2)[N2], const char(&S3)[N3], const T &Value)
Definition: StringSwitch.h:121
LLVM_NODISCARD bool endswith_lower(StringRef Suffix) const
Check if this string ends with the given Suffix, ignoring case.
Definition: StringRef.cpp:68
LLVM_NODISCARD LLVM_ATTRIBUTE_ALWAYS_INLINE const char * data() const
data - Get a pointer to the start of the string (which may not be null terminated).
Definition: StringRef.h:128
#define LLVM_ATTRIBUTE_ALWAYS_INLINE
LLVM_ATTRIBUTE_ALWAYS_INLINE - On compilers where we have a directive to do so, mark a method "always...
Definition: Compiler.h:198
LLVM_ATTRIBUTE_ALWAYS_INLINE StringSwitch & EndsWith(const char(&S)[N], const T &Value)
Definition: StringSwitch.h:85
LLVM_ATTRIBUTE_ALWAYS_INLINE StringSwitch & Case(const char(&S)[N], const T &Value)
Definition: StringSwitch.h:74
LLVM_ATTRIBUTE_ALWAYS_INLINE StringSwitch & CasesLower(const char(&S0)[N0], const char(&S1)[N1], const char(&S2)[N2], const char(&S3)[N3], const T &Value)
Definition: StringSwitch.h:231
LLVM_ATTRIBUTE_ALWAYS_INLINE StringSwitch & Cases(const char(&S0)[N0], const char(&S1)[N1], const char(&S2)[N2], const char(&S3)[N3], const char(&S4)[N4], const T &Value)
Definition: StringSwitch.h:129
A switch()-like statement whose cases are string literals.
Definition: StringSwitch.h:43
LLVM_ATTRIBUTE_ALWAYS_INLINE StringSwitch & StartsWithLower(const char(&S)[N], const T &Value)
Definition: StringSwitch.h:209
StringSwitch & operator=(StringSwitch &&other)
Definition: StringSwitch.h:63
LLVM_ATTRIBUTE_ALWAYS_INLINE StringSwitch & EndsWithLower(const char(&S)[N], const T &Value)
Definition: StringSwitch.h:200
LLVM_ATTRIBUTE_ALWAYS_INLINE StringSwitch & Cases(const char(&S0)[N0], const char(&S1)[N1], const char(&S2)[N2], const char(&S3)[N3], const char(&S4)[N4], const char(&S5)[N5], const char(&S6)[N6], const char(&S7)[N7], const char(&S8)[N8], const char(&S9)[N9], const T &Value)
Definition: StringSwitch.h:180
LLVM_ATTRIBUTE_ALWAYS_INLINE R Default(const T &Value) const
Definition: StringSwitch.h:244
LLVM_ATTRIBUTE_ALWAYS_INLINE StringSwitch & Cases(const char(&S0)[N0], const char(&S1)[N1], const char(&S2)[N2], const char(&S3)[N3], const char(&S4)[N4], const char(&S5)[N5], const char(&S6)[N6], const char(&S7)[N7], const char(&S8)[N8], const T &Value)
Definition: StringSwitch.h:169
LLVM_ATTRIBUTE_ALWAYS_INLINE StringSwitch & Cases(const char(&S0)[N0], const char(&S1)[N1], const char(&S2)[N2], const char(&S3)[N3], const char(&S4)[N4], const char(&S5)[N5], const char(&S6)[N6], const T &Value)
Definition: StringSwitch.h:148
LLVM_ATTRIBUTE_ALWAYS_INLINE StringSwitch & Cases(const char(&S0)[N0], const char(&S1)[N1], const char(&S2)[N2], const T &Value)
Definition: StringSwitch.h:114
LLVM_ATTRIBUTE_ALWAYS_INLINE StringSwitch & CasesLower(const char(&S0)[N0], const char(&S1)[N1], const char(&S2)[N2], const T &Value)
Definition: StringSwitch.h:224
LLVM_ATTRIBUTE_ALWAYS_INLINE StringSwitch & Cases(const char(&S0)[N0], const char(&S1)[N1], const T &Value)
Definition: StringSwitch.h:107
LLVM_ATTRIBUTE_ALWAYS_INLINE StringSwitch(StringRef S)
Definition: StringSwitch.h:53
Merge contiguous icmps into a memcmp
Definition: MergeICmps.cpp:649
#define N
StringSwitch(StringSwitch &&other)
Definition: StringSwitch.h:60
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
LLVM_ATTRIBUTE_ALWAYS_INLINE StringSwitch & CasesLower(const char(&S0)[N0], const char(&S1)[N1], const T &Value)
Definition: StringSwitch.h:218
LLVM_ATTRIBUTE_ALWAYS_INLINE StringSwitch & Cases(const char(&S0)[N0], const char(&S1)[N1], const char(&S2)[N2], const char(&S3)[N3], const char(&S4)[N4], const char(&S5)[N5], const T &Value)
Definition: StringSwitch.h:138
LLVM Value Representation.
Definition: Value.h:73
void operator=(const StringSwitch &)=delete
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:49
LLVM_ATTRIBUTE_ALWAYS_INLINE StringSwitch & StartsWith(const char(&S)[N], const T &Value)
Definition: StringSwitch.h:96
LLVM_ATTRIBUTE_ALWAYS_INLINE StringSwitch & Cases(const char(&S0)[N0], const char(&S1)[N1], const char(&S2)[N2], const char(&S3)[N3], const char(&S4)[N4], const char(&S5)[N5], const char(&S6)[N6], const char(&S7)[N7], const T &Value)
Definition: StringSwitch.h:158