Counter Strike : Global Offensive Source Code
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

126 lines
3.8 KiB

  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. #include "llvm/ADT/StringRef.h"
  16. #include <cassert>
  17. #include <cstring>
  18. namespace llvm {
  19. /// \brief A switch()-like statement whose cases are string literals.
  20. ///
  21. /// The StringSwitch class is a simple form of a switch() statement that
  22. /// determines whether the given string matches one of the given string
  23. /// literals. The template type parameter \p T is the type of the value that
  24. /// will be returned from the string-switch expression. For example,
  25. /// the following code switches on the name of a color in \c argv[i]:
  26. ///
  27. /// \code
  28. /// Color color = StringSwitch<Color>(argv[i])
  29. /// .Case("red", Red)
  30. /// .Case("orange", Orange)
  31. /// .Case("yellow", Yellow)
  32. /// .Case("green", Green)
  33. /// .Case("blue", Blue)
  34. /// .Case("indigo", Indigo)
  35. /// .Cases("violet", "purple", Violet)
  36. /// .Default(UnknownColor);
  37. /// \endcode
  38. template<typename T, typename R = T>
  39. class StringSwitch {
  40. /// \brief The string we are matching.
  41. StringRef Str;
  42. /// \brief The pointer to the result of this switch statement, once known,
  43. /// null before that.
  44. const T *Result;
  45. public:
  46. explicit StringSwitch(StringRef S)
  47. : Str(S), Result(0) { }
  48. template<unsigned N>
  49. StringSwitch& Case(const char (&S)[N], const T& Value) {
  50. if (!Result && N-1 == Str.size() &&
  51. (std::memcmp(S, Str.data(), N-1) == 0)) {
  52. Result = &Value;
  53. }
  54. return *this;
  55. }
  56. template<unsigned N>
  57. StringSwitch& EndsWith(const char (&S)[N], const T &Value) {
  58. if (!Result && Str.size() >= N-1 &&
  59. std::memcmp(S, Str.data() + Str.size() + 1 - N, N-1) == 0) {
  60. Result = &Value;
  61. }
  62. return *this;
  63. }
  64. template<unsigned N>
  65. StringSwitch& StartsWith(const char (&S)[N], const T &Value) {
  66. if (!Result && Str.size() >= N-1 &&
  67. std::memcmp(S, Str.data(), N-1) == 0) {
  68. Result = &Value;
  69. }
  70. return *this;
  71. }
  72. template<unsigned N0, unsigned N1>
  73. StringSwitch& Cases(const char (&S0)[N0], const char (&S1)[N1],
  74. const T& Value) {
  75. return Case(S0, Value).Case(S1, Value);
  76. }
  77. template<unsigned N0, unsigned N1, unsigned N2>
  78. StringSwitch& Cases(const char (&S0)[N0], const char (&S1)[N1],
  79. const char (&S2)[N2], const T& Value) {
  80. return Case(S0, Value).Case(S1, Value).Case(S2, Value);
  81. }
  82. template<unsigned N0, unsigned N1, unsigned N2, unsigned N3>
  83. StringSwitch& Cases(const char (&S0)[N0], const char (&S1)[N1],
  84. const char (&S2)[N2], const char (&S3)[N3],
  85. const T& Value) {
  86. return Case(S0, Value).Case(S1, Value).Case(S2, Value).Case(S3, Value);
  87. }
  88. template<unsigned N0, unsigned N1, unsigned N2, unsigned N3, unsigned N4>
  89. StringSwitch& Cases(const char (&S0)[N0], const char (&S1)[N1],
  90. const char (&S2)[N2], const char (&S3)[N3],
  91. const char (&S4)[N4], const T& Value) {
  92. return Case(S0, Value).Case(S1, Value).Case(S2, Value).Case(S3, Value)
  93. .Case(S4, Value);
  94. }
  95. R Default(const T& Value) const {
  96. if (Result)
  97. return *Result;
  98. return Value;
  99. }
  100. operator R() const {
  101. assert(Result && "Fell off the end of a string-switch");
  102. return *Result;
  103. }
  104. };
  105. } // end namespace llvm
  106. #endif // LLVM_ADT_STRINGSWITCH_H