| //===--- StringSwitch.h - Switch-on-literal-string Construct --------------===/ | |
| // | |
| // The LLVM Compiler Infrastructure | |
| // | |
| // This file is distributed under the University of Illinois Open Source | |
| // License. See LICENSE.TXT for details. | |
| //===----------------------------------------------------------------------===/ | |
| // | |
| // This file implements the StringSwitch template, which mimics a switch() | |
| // statement whose cases are string literals. | |
| // | |
| //===----------------------------------------------------------------------===/ | |
| #ifndef LLVM_ADT_STRINGSWITCH_H | |
| #define LLVM_ADT_STRINGSWITCH_H | |
| #include "llvm/ADT/StringRef.h" | |
| #include <cassert> | |
| #include <cstring> | |
| namespace llvm { | |
| /// \brief A switch()-like statement whose cases are string literals. | |
| /// | |
| /// The StringSwitch class is a simple form of a switch() statement that | |
| /// determines whether the given string matches one of the given string | |
| /// literals. The template type parameter \p T is the type of the value that | |
| /// will be returned from the string-switch expression. For example, | |
| /// the following code switches on the name of a color in \c argv[i]: | |
| /// | |
| /// \code | |
| /// Color color = StringSwitch<Color>(argv[i]) | |
| /// .Case("red", Red) | |
| /// .Case("orange", Orange) | |
| /// .Case("yellow", Yellow) | |
| /// .Case("green", Green) | |
| /// .Case("blue", Blue) | |
| /// .Case("indigo", Indigo) | |
| /// .Cases("violet", "purple", Violet) | |
| /// .Default(UnknownColor); | |
| /// \endcode | |
| template<typename T, typename R = T> | |
| class StringSwitch { | |
| /// \brief The string we are matching. | |
| StringRef Str; | |
| /// \brief The pointer to the result of this switch statement, once known, | |
| /// null before that. | |
| const T *Result; | |
| public: | |
| explicit StringSwitch(StringRef Str) | |
| : Str(Str), Result(0) { } | |
| template<unsigned N> | |
| StringSwitch& Case(const char (&S)[N], const T& Value) { | |
| if (!Result && N-1 == Str.size() && | |
| (std::memcmp(S, Str.data(), N-1) == 0)) { | |
| Result = &Value; | |
| } | |
| return *this; | |
| } | |
| template<unsigned N> | |
| StringSwitch& EndsWith(const char (&S)[N], const T &Value) { | |
| if (!Result && Str.size() >= N-1 && | |
| std::memcmp(S, Str.data() + Str.size() + 1 - N, N-1) == 0) { | |
| Result = &Value; | |
| } | |
| return *this; | |
| } | |
| template<unsigned N> | |
| StringSwitch& StartsWith(const char (&S)[N], const T &Value) { | |
| if (!Result && Str.size() >= N-1 && | |
| std::memcmp(S, Str.data(), N-1) == 0) { | |
| Result = &Value; | |
| } | |
| return *this; | |
| } | |
| template<unsigned N0, unsigned N1> | |
| StringSwitch& Cases(const char (&S0)[N0], const char (&S1)[N1], | |
| const T& Value) { | |
| return Case(S0, Value).Case(S1, Value); | |
| } | |
| template<unsigned N0, unsigned N1, unsigned N2> | |
| StringSwitch& Cases(const char (&S0)[N0], const char (&S1)[N1], | |
| const char (&S2)[N2], const T& Value) { | |
| return Case(S0, Value).Case(S1, Value).Case(S2, Value); | |
| } | |
| template<unsigned N0, unsigned N1, unsigned N2, unsigned N3> | |
| StringSwitch& Cases(const char (&S0)[N0], const char (&S1)[N1], | |
| const char (&S2)[N2], const char (&S3)[N3], | |
| const T& Value) { | |
| return Case(S0, Value).Case(S1, Value).Case(S2, Value).Case(S3, Value); | |
| } | |
| template<unsigned N0, unsigned N1, unsigned N2, unsigned N3, unsigned N4> | |
| 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) { | |
| return Case(S0, Value).Case(S1, Value).Case(S2, Value).Case(S3, Value) | |
| .Case(S4, Value); | |
| } | |
| R Default(const T& Value) const { | |
| if (Result) | |
| return *Result; | |
| return Value; | |
| } | |
| operator R() const { | |
| assert(Result && "Fell off the end of a string-switch"); | |
| return *Result; | |
| } | |
| }; | |
| } // end namespace llvm | |
| #endif // LLVM_ADT_STRINGSWITCH_H |