LLVM API Documentation
00001 //===--- StringSwitch.h - Switch-on-literal-string Construct --------------===/ 00002 // 00003 // The LLVM Compiler Infrastructure 00004 // 00005 // This file is distributed under the University of Illinois Open Source 00006 // License. See LICENSE.TXT for details. 00007 //===----------------------------------------------------------------------===/ 00008 // 00009 // This file implements the StringSwitch template, which mimics a switch() 00010 // statement whose cases are string literals. 00011 // 00012 //===----------------------------------------------------------------------===/ 00013 #ifndef LLVM_ADT_STRINGSWITCH_H 00014 #define LLVM_ADT_STRINGSWITCH_H 00015 00016 #include "llvm/ADT/StringRef.h" 00017 #include <cassert> 00018 #include <cstring> 00019 00020 namespace llvm { 00021 00022 /// \brief A switch()-like statement whose cases are string literals. 00023 /// 00024 /// The StringSwitch class is a simple form of a switch() statement that 00025 /// determines whether the given string matches one of the given string 00026 /// literals. The template type parameter \p T is the type of the value that 00027 /// will be returned from the string-switch expression. For example, 00028 /// the following code switches on the name of a color in \c argv[i]: 00029 /// 00030 /// \code 00031 /// Color color = StringSwitch<Color>(argv[i]) 00032 /// .Case("red", Red) 00033 /// .Case("orange", Orange) 00034 /// .Case("yellow", Yellow) 00035 /// .Case("green", Green) 00036 /// .Case("blue", Blue) 00037 /// .Case("indigo", Indigo) 00038 /// .Cases("violet", "purple", Violet) 00039 /// .Default(UnknownColor); 00040 /// \endcode 00041 template<typename T, typename R = T> 00042 class StringSwitch { 00043 /// \brief The string we are matching. 00044 StringRef Str; 00045 00046 /// \brief The pointer to the result of this switch statement, once known, 00047 /// null before that. 00048 const T *Result; 00049 00050 public: 00051 explicit StringSwitch(StringRef S) 00052 : Str(S), Result(nullptr) { } 00053 00054 template<unsigned N> 00055 StringSwitch& Case(const char (&S)[N], const T& Value) { 00056 if (!Result && N-1 == Str.size() && 00057 (std::memcmp(S, Str.data(), N-1) == 0)) { 00058 Result = &Value; 00059 } 00060 00061 return *this; 00062 } 00063 00064 template<unsigned N> 00065 StringSwitch& EndsWith(const char (&S)[N], const T &Value) { 00066 if (!Result && Str.size() >= N-1 && 00067 std::memcmp(S, Str.data() + Str.size() + 1 - N, N-1) == 0) { 00068 Result = &Value; 00069 } 00070 00071 return *this; 00072 } 00073 00074 template<unsigned N> 00075 StringSwitch& StartsWith(const char (&S)[N], const T &Value) { 00076 if (!Result && Str.size() >= N-1 && 00077 std::memcmp(S, Str.data(), N-1) == 0) { 00078 Result = &Value; 00079 } 00080 00081 return *this; 00082 } 00083 00084 template<unsigned N0, unsigned N1> 00085 StringSwitch& Cases(const char (&S0)[N0], const char (&S1)[N1], 00086 const T& Value) { 00087 return Case(S0, Value).Case(S1, Value); 00088 } 00089 00090 template<unsigned N0, unsigned N1, unsigned N2> 00091 StringSwitch& Cases(const char (&S0)[N0], const char (&S1)[N1], 00092 const char (&S2)[N2], const T& Value) { 00093 return Case(S0, Value).Case(S1, Value).Case(S2, Value); 00094 } 00095 00096 template<unsigned N0, unsigned N1, unsigned N2, unsigned N3> 00097 StringSwitch& Cases(const char (&S0)[N0], const char (&S1)[N1], 00098 const char (&S2)[N2], const char (&S3)[N3], 00099 const T& Value) { 00100 return Case(S0, Value).Case(S1, Value).Case(S2, Value).Case(S3, Value); 00101 } 00102 00103 template<unsigned N0, unsigned N1, unsigned N2, unsigned N3, unsigned N4> 00104 StringSwitch& Cases(const char (&S0)[N0], const char (&S1)[N1], 00105 const char (&S2)[N2], const char (&S3)[N3], 00106 const char (&S4)[N4], const T& Value) { 00107 return Case(S0, Value).Case(S1, Value).Case(S2, Value).Case(S3, Value) 00108 .Case(S4, Value); 00109 } 00110 00111 R Default(const T& Value) const { 00112 if (Result) 00113 return *Result; 00114 00115 return Value; 00116 } 00117 00118 operator R() const { 00119 assert(Result && "Fell off the end of a string-switch"); 00120 return *Result; 00121 } 00122 }; 00123 00124 } // end namespace llvm 00125 00126 #endif // LLVM_ADT_STRINGSWITCH_H