| //===--- 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 "llvm/Support/Compiler.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: | 
 |   LLVM_ATTRIBUTE_ALWAYS_INLINE | 
 |   explicit StringSwitch(StringRef S) | 
 |   : Str(S), Result(nullptr) { } | 
 |  | 
 |   // StringSwitch is not copyable. | 
 |   StringSwitch(const StringSwitch &) = delete; | 
 |   void operator=(const StringSwitch &) = delete; | 
 |  | 
 |   StringSwitch(StringSwitch &&other) { | 
 |     *this = std::move(other); | 
 |   } | 
 |   StringSwitch &operator=(StringSwitch &&other) { | 
 |     Str = other.Str; | 
 |     Result = other.Result; | 
 |     return *this; | 
 |   } | 
 |  | 
 |   ~StringSwitch() = default; | 
 |  | 
 |   // Case-sensitive case matchers | 
 |   template<unsigned N> | 
 |   LLVM_ATTRIBUTE_ALWAYS_INLINE | 
 |   StringSwitch& Case(const char (&S)[N], const T& Value) { | 
 |     assert(N); | 
 |     if (!Result && N-1 == Str.size() && | 
 |         (N == 1 || std::memcmp(S, Str.data(), N-1) == 0)) { | 
 |       Result = &Value; | 
 |     } | 
 |     return *this; | 
 |   } | 
 |  | 
 |   template<unsigned N> | 
 |   LLVM_ATTRIBUTE_ALWAYS_INLINE | 
 |   StringSwitch& EndsWith(const char (&S)[N], const T &Value) { | 
 |     assert(N); | 
 |     if (!Result && Str.size() >= N-1 && | 
 |         (N == 1 || std::memcmp(S, Str.data() + Str.size() + 1 - N, N-1) == 0)) { | 
 |       Result = &Value; | 
 |     } | 
 |     return *this; | 
 |   } | 
 |  | 
 |   template<unsigned N> | 
 |   LLVM_ATTRIBUTE_ALWAYS_INLINE | 
 |   StringSwitch& StartsWith(const char (&S)[N], const T &Value) { | 
 |     assert(N); | 
 |     if (!Result && Str.size() >= N-1 && | 
 |         (N == 1 || std::memcmp(S, Str.data(), N-1) == 0)) { | 
 |       Result = &Value; | 
 |     } | 
 |     return *this; | 
 |   } | 
 |  | 
 |   template<unsigned N0, unsigned N1> | 
 |   LLVM_ATTRIBUTE_ALWAYS_INLINE | 
 |   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> | 
 |   LLVM_ATTRIBUTE_ALWAYS_INLINE | 
 |   StringSwitch &Cases(const char (&S0)[N0], const char (&S1)[N1], | 
 |                       const char (&S2)[N2], const T& Value) { | 
 |     return Case(S0, Value).Cases(S1, S2, Value); | 
 |   } | 
 |  | 
 |   template<unsigned N0, unsigned N1, unsigned N2, unsigned N3> | 
 |   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) { | 
 |     return Case(S0, Value).Cases(S1, S2, S3, Value); | 
 |   } | 
 |  | 
 |   template<unsigned N0, unsigned N1, unsigned N2, unsigned N3, unsigned N4> | 
 |   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) { | 
 |     return Case(S0, Value).Cases(S1, S2, S3, S4, Value); | 
 |   } | 
 |  | 
 |   template <unsigned N0, unsigned N1, unsigned N2, unsigned N3, unsigned N4, | 
 |             unsigned N5> | 
 |   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) { | 
 |     return Case(S0, Value).Cases(S1, S2, S3, S4, S5, Value); | 
 |   } | 
 |  | 
 |   template <unsigned N0, unsigned N1, unsigned N2, unsigned N3, unsigned N4, | 
 |             unsigned N5, unsigned N6> | 
 |   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) { | 
 |     return Case(S0, Value).Cases(S1, S2, S3, S4, S5, S6, Value); | 
 |   } | 
 |  | 
 |   template <unsigned N0, unsigned N1, unsigned N2, unsigned N3, unsigned N4, | 
 |             unsigned N5, unsigned N6, unsigned N7> | 
 |   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) { | 
 |     return Case(S0, Value).Cases(S1, S2, S3, S4, S5, S6, S7, Value); | 
 |   } | 
 |  | 
 |   template <unsigned N0, unsigned N1, unsigned N2, unsigned N3, unsigned N4, | 
 |             unsigned N5, unsigned N6, unsigned N7, unsigned N8> | 
 |   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) { | 
 |     return Case(S0, Value).Cases(S1, S2, S3, S4, S5, S6, S7, S8, Value); | 
 |   } | 
 |  | 
 |   template <unsigned N0, unsigned N1, unsigned N2, unsigned N3, unsigned N4, | 
 |             unsigned N5, unsigned N6, unsigned N7, unsigned N8, unsigned N9> | 
 |   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) { | 
 |     return Case(S0, Value).Cases(S1, S2, S3, S4, S5, S6, S7, S8, S9, Value); | 
 |   } | 
 |  | 
 |   // Case-insensitive case matchers. | 
 |   template <unsigned N> | 
 |   LLVM_ATTRIBUTE_ALWAYS_INLINE StringSwitch &CaseLower(const char (&S)[N], | 
 |                                                        const T &Value) { | 
 |     if (!Result && Str.equals_lower(StringRef(S, N - 1))) | 
 |       Result = &Value; | 
 |  | 
 |     return *this; | 
 |   } | 
 |  | 
 |   template <unsigned N> | 
 |   LLVM_ATTRIBUTE_ALWAYS_INLINE StringSwitch &EndsWithLower(const char (&S)[N], | 
 |                                                            const T &Value) { | 
 |     if (!Result && Str.endswith_lower(StringRef(S, N - 1))) | 
 |       Result = &Value; | 
 |  | 
 |     return *this; | 
 |   } | 
 |  | 
 |   template <unsigned N> | 
 |   LLVM_ATTRIBUTE_ALWAYS_INLINE StringSwitch &StartsWithLower(const char (&S)[N], | 
 |                                                              const T &Value) { | 
 |     if (!Result && Str.startswith_lower(StringRef(S, N - 1))) | 
 |       Result = &Value; | 
 |  | 
 |     return *this; | 
 |   } | 
 |   template <unsigned N0, unsigned N1> | 
 |   LLVM_ATTRIBUTE_ALWAYS_INLINE StringSwitch & | 
 |   CasesLower(const char (&S0)[N0], const char (&S1)[N1], const T &Value) { | 
 |     return CaseLower(S0, Value).CaseLower(S1, Value); | 
 |   } | 
 |  | 
 |   template <unsigned N0, unsigned N1, unsigned N2> | 
 |   LLVM_ATTRIBUTE_ALWAYS_INLINE StringSwitch & | 
 |   CasesLower(const char (&S0)[N0], const char (&S1)[N1], const char (&S2)[N2], | 
 |              const T &Value) { | 
 |     return CaseLower(S0, Value).CasesLower(S1, S2, Value); | 
 |   } | 
 |  | 
 |   template <unsigned N0, unsigned N1, unsigned N2, unsigned N3> | 
 |   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) { | 
 |     return CaseLower(S0, Value).CasesLower(S1, S2, S3, Value); | 
 |   } | 
 |  | 
 |   template <unsigned N0, unsigned N1, unsigned N2, unsigned N3, unsigned N4> | 
 |   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) { | 
 |     return CaseLower(S0, Value).CasesLower(S1, S2, S3, S4, Value); | 
 |   } | 
 |  | 
 |   LLVM_ATTRIBUTE_ALWAYS_INLINE | 
 |   R Default(const T &Value) const { | 
 |     if (Result) | 
 |       return *Result; | 
 |     return Value; | 
 |   } | 
 |  | 
 |   LLVM_ATTRIBUTE_ALWAYS_INLINE | 
 |   operator R() const { | 
 |     assert(Result && "Fell off the end of a string-switch"); | 
 |     return *Result; | 
 |   } | 
 | }; | 
 |  | 
 | } // end namespace llvm | 
 |  | 
 | #endif // LLVM_ADT_STRINGSWITCH_H |