LCOV - code coverage report
Current view: top level - include/llvm/ADT - StringSwitch.h (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 31 31 100.0 %
Date: 2017-09-14 15:23:50 Functions: 0 0 -
Legend: Lines: hit not hit

          Line data    Source code
       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:
      52             :   LLVM_ATTRIBUTE_ALWAYS_INLINE
      53        2722 :   explicit StringSwitch(StringRef S)
      54        2769 :   : Str(S), Result(nullptr) { }
      55             : 
      56             :   // StringSwitch is not copyable.
      57             :   StringSwitch(const StringSwitch &) = delete;
      58             :   void operator=(const StringSwitch &) = delete;
      59             : 
      60             :   StringSwitch(StringSwitch &&other) {
      61             :     *this = std::move(other);
      62             :   }
      63             :   StringSwitch &operator=(StringSwitch &&other) {
      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>
      73             :   LLVM_ATTRIBUTE_ALWAYS_INLINE
      74             :   StringSwitch& Case(const char (&S)[N], const T& Value) {
      75             :     assert(N);
      76   432849984 :     if (!Result && N-1 == Str.size() &&
      77    33510372 :         (N == 1 || std::memcmp(S, Str.data(), N-1) == 0)) {
      78         205 :       Result = &Value;
      79             :     }
      80             :     return *this;
      81             :   }
      82             : 
      83             :   template<unsigned N>
      84             :   LLVM_ATTRIBUTE_ALWAYS_INLINE
      85             :   StringSwitch& EndsWith(const char (&S)[N], const T &Value) {
      86             :     assert(N);
      87     1911635 :     if (!Result && Str.size() >= N-1 &&
      88      476807 :         (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>
      95             :   LLVM_ATTRIBUTE_ALWAYS_INLINE
      96             :   StringSwitch& StartsWith(const char (&S)[N], const T &Value) {
      97             :     assert(N);
      98    33573383 :     if (!Result && Str.size() >= N-1 &&
      99     5885139 :         (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>
     106             :   LLVM_ATTRIBUTE_ALWAYS_INLINE
     107             :   StringSwitch &Cases(const char (&S0)[N0], const char (&S1)[N1],
     108             :                       const T& Value) {
     109    20850840 :     return Case(S0, Value).Case(S1, Value);
     110             :   }
     111             : 
     112             :   template<unsigned N0, unsigned N1, unsigned N2>
     113             :   LLVM_ATTRIBUTE_ALWAYS_INLINE
     114             :   StringSwitch &Cases(const char (&S0)[N0], const char (&S1)[N1],
     115             :                       const char (&S2)[N2], const T& Value) {
     116    10416170 :     return Case(S0, Value).Cases(S1, S2, Value);
     117             :   }
     118             : 
     119             :   template<unsigned N0, unsigned N1, unsigned N2, unsigned N3>
     120             :   LLVM_ATTRIBUTE_ALWAYS_INLINE
     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     3832198 :     return Case(S0, Value).Cases(S1, S2, S3, Value);
     125             :   }
     126             : 
     127             :   template<unsigned N0, unsigned N1, unsigned N2, unsigned N3, unsigned N4>
     128             :   LLVM_ATTRIBUTE_ALWAYS_INLINE
     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      260366 :     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>
     137             :   LLVM_ATTRIBUTE_ALWAYS_INLINE
     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      108114 :     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>
     147             :   LLVM_ATTRIBUTE_ALWAYS_INLINE
     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       98470 :     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>
     157             :   LLVM_ATTRIBUTE_ALWAYS_INLINE
     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       98470 :     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>
     168             :   LLVM_ATTRIBUTE_ALWAYS_INLINE
     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       98470 :     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>
     179             :   LLVM_ATTRIBUTE_ALWAYS_INLINE
     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         896 :     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>
     191             :   LLVM_ATTRIBUTE_ALWAYS_INLINE StringSwitch &CaseLower(const char (&S)[N],
     192             :                                                        const T &Value) {
     193       15252 :     if (!Result && Str.equals_lower(StringRef(S, N - 1)))
     194        2263 :       Result = &Value;
     195             : 
     196             :     return *this;
     197             :   }
     198             : 
     199             :   template <unsigned N>
     200             :   LLVM_ATTRIBUTE_ALWAYS_INLINE StringSwitch &EndsWithLower(const char (&S)[N],
     201             :                                                            const T &Value) {
     202          58 :     if (!Result && Str.endswith_lower(StringRef(S, N - 1)))
     203           5 :       Result = &Value;
     204             : 
     205             :     return *this;
     206             :   }
     207             : 
     208             :   template <unsigned N>
     209             :   LLVM_ATTRIBUTE_ALWAYS_INLINE StringSwitch &StartsWithLower(const char (&S)[N],
     210             :                                                              const T &Value) {
     211          88 :     if (!Result && Str.startswith_lower(StringRef(S, N - 1)))
     212           8 :       Result = &Value;
     213             : 
     214             :     return *this;
     215             :   }
     216             :   template <unsigned N0, unsigned N1>
     217             :   LLVM_ATTRIBUTE_ALWAYS_INLINE StringSwitch &
     218             :   CasesLower(const char (&S0)[N0], const char (&S1)[N1], const T &Value) {
     219        5084 :     return CaseLower(S0, Value).CaseLower(S1, Value);
     220             :   }
     221             : 
     222             :   template <unsigned N0, unsigned N1, unsigned N2>
     223             :   LLVM_ATTRIBUTE_ALWAYS_INLINE StringSwitch &
     224             :   CasesLower(const char (&S0)[N0], const char (&S1)[N1], const char (&S2)[N2],
     225             :              const T &Value) {
     226        5084 :     return CaseLower(S0, Value).CasesLower(S1, S2, Value);
     227             :   }
     228             : 
     229             :   template <unsigned N0, unsigned N1, unsigned N2, unsigned N3>
     230             :   LLVM_ATTRIBUTE_ALWAYS_INLINE StringSwitch &
     231             :   CasesLower(const char (&S0)[N0], const char (&S1)[N1], const char (&S2)[N2],
     232             :              const char (&S3)[N3], const T &Value) {
     233          22 :     return CaseLower(S0, Value).CasesLower(S1, S2, S3, Value);
     234             :   }
     235             : 
     236             :   template <unsigned N0, unsigned N1, unsigned N2, unsigned N3, unsigned N4>
     237             :   LLVM_ATTRIBUTE_ALWAYS_INLINE StringSwitch &
     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             : 
     243             :   LLVM_ATTRIBUTE_ALWAYS_INLINE
     244             :   R Default(const T &Value) const {
     245    23208934 :     if (Result)
     246     6663463 :       return *Result;
     247       16049 :     return Value;
     248             :   }
     249             : 
     250             :   LLVM_ATTRIBUTE_ALWAYS_INLINE
     251             :   operator R() const {
     252             :     assert(Result && "Fell off the end of a string-switch");
     253       11561 :     return *Result;
     254             :   }
     255             : };
     256             : 
     257             : } // end namespace llvm
     258             : 
     259             : #endif // LLVM_ADT_STRINGSWITCH_H

Generated by: LCOV version 1.13