Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-10 08:43:10

0001 //===--- StringSwitch.h - Switch-on-literal-string Construct --------------===/
0002 //
0003 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
0004 // See https://llvm.org/LICENSE.txt for license information.
0005 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
0006 //===----------------------------------------------------------------------===/
0007 ///
0008 /// \file
0009 ///  This file implements the StringSwitch template, which mimics a switch()
0010 ///  statement whose cases are string literals.
0011 ///
0012 //===----------------------------------------------------------------------===/
0013 #ifndef LLVM_ADT_STRINGSWITCH_H
0014 #define LLVM_ADT_STRINGSWITCH_H
0015 
0016 #include "llvm/ADT/StringRef.h"
0017 #include "llvm/Support/Compiler.h"
0018 #include <cassert>
0019 #include <cstring>
0020 #include <optional>
0021 
0022 namespace llvm {
0023 
0024 /// A switch()-like statement whose cases are string literals.
0025 ///
0026 /// The StringSwitch class is a simple form of a switch() statement that
0027 /// determines whether the given string matches one of the given string
0028 /// literals. The template type parameter \p T is the type of the value that
0029 /// will be returned from the string-switch expression. For example,
0030 /// the following code switches on the name of a color in \c argv[i]:
0031 ///
0032 /// \code
0033 /// Color color = StringSwitch<Color>(argv[i])
0034 ///   .Case("red", Red)
0035 ///   .Case("orange", Orange)
0036 ///   .Case("yellow", Yellow)
0037 ///   .Case("green", Green)
0038 ///   .Case("blue", Blue)
0039 ///   .Case("indigo", Indigo)
0040 ///   .Cases("violet", "purple", Violet)
0041 ///   .Default(UnknownColor);
0042 /// \endcode
0043 template<typename T, typename R = T>
0044 class StringSwitch {
0045   /// The string we are matching.
0046   const StringRef Str;
0047 
0048   /// The pointer to the result of this switch statement, once known,
0049   /// null before that.
0050   std::optional<T> Result;
0051 
0052 public:
0053   explicit StringSwitch(StringRef S)
0054   : Str(S), Result() { }
0055 
0056   // StringSwitch is not copyable.
0057   StringSwitch(const StringSwitch &) = delete;
0058 
0059   // StringSwitch is not assignable due to 'Str' being 'const'.
0060   void operator=(const StringSwitch &) = delete;
0061   void operator=(StringSwitch &&other) = delete;
0062 
0063   StringSwitch(StringSwitch &&other)
0064     : Str(other.Str), Result(std::move(other.Result)) { }
0065 
0066   ~StringSwitch() = default;
0067 
0068   // Case-sensitive case matchers
0069   StringSwitch &Case(StringLiteral S, T Value) {
0070     if (!Result && Str == S) {
0071       Result = std::move(Value);
0072     }
0073     return *this;
0074   }
0075 
0076   StringSwitch& EndsWith(StringLiteral S, T Value) {
0077     if (!Result && Str.ends_with(S)) {
0078       Result = std::move(Value);
0079     }
0080     return *this;
0081   }
0082 
0083   StringSwitch& StartsWith(StringLiteral S, T Value) {
0084     if (!Result && Str.starts_with(S)) {
0085       Result = std::move(Value);
0086     }
0087     return *this;
0088   }
0089 
0090   StringSwitch &Cases(StringLiteral S0, StringLiteral S1, T Value) {
0091     return Case(S0, Value).Case(S1, Value);
0092   }
0093 
0094   StringSwitch &Cases(StringLiteral S0, StringLiteral S1, StringLiteral S2,
0095                       T Value) {
0096     return Case(S0, Value).Cases(S1, S2, Value);
0097   }
0098 
0099   StringSwitch &Cases(StringLiteral S0, StringLiteral S1, StringLiteral S2,
0100                       StringLiteral S3, T Value) {
0101     return Case(S0, Value).Cases(S1, S2, S3, Value);
0102   }
0103 
0104   StringSwitch &Cases(StringLiteral S0, StringLiteral S1, StringLiteral S2,
0105                       StringLiteral S3, StringLiteral S4, T Value) {
0106     return Case(S0, Value).Cases(S1, S2, S3, S4, Value);
0107   }
0108 
0109   StringSwitch &Cases(StringLiteral S0, StringLiteral S1, StringLiteral S2,
0110                       StringLiteral S3, StringLiteral S4, StringLiteral S5,
0111                       T Value) {
0112     return Case(S0, Value).Cases(S1, S2, S3, S4, S5, Value);
0113   }
0114 
0115   StringSwitch &Cases(StringLiteral S0, StringLiteral S1, StringLiteral S2,
0116                       StringLiteral S3, StringLiteral S4, StringLiteral S5,
0117                       StringLiteral S6, T Value) {
0118     return Case(S0, Value).Cases(S1, S2, S3, S4, S5, S6, Value);
0119   }
0120 
0121   StringSwitch &Cases(StringLiteral S0, StringLiteral S1, StringLiteral S2,
0122                       StringLiteral S3, StringLiteral S4, StringLiteral S5,
0123                       StringLiteral S6, StringLiteral S7, T Value) {
0124     return Case(S0, Value).Cases(S1, S2, S3, S4, S5, S6, S7, Value);
0125   }
0126 
0127   StringSwitch &Cases(StringLiteral S0, StringLiteral S1, StringLiteral S2,
0128                       StringLiteral S3, StringLiteral S4, StringLiteral S5,
0129                       StringLiteral S6, StringLiteral S7, StringLiteral S8,
0130                       T Value) {
0131     return Case(S0, Value).Cases(S1, S2, S3, S4, S5, S6, S7, S8, Value);
0132   }
0133 
0134   StringSwitch &Cases(StringLiteral S0, StringLiteral S1, StringLiteral S2,
0135                       StringLiteral S3, StringLiteral S4, StringLiteral S5,
0136                       StringLiteral S6, StringLiteral S7, StringLiteral S8,
0137                       StringLiteral S9, T Value) {
0138     return Case(S0, Value).Cases(S1, S2, S3, S4, S5, S6, S7, S8, S9, Value);
0139   }
0140 
0141   // Case-insensitive case matchers.
0142   StringSwitch &CaseLower(StringLiteral S, T Value) {
0143     if (!Result && Str.equals_insensitive(S))
0144       Result = std::move(Value);
0145 
0146     return *this;
0147   }
0148 
0149   StringSwitch &EndsWithLower(StringLiteral S, T Value) {
0150     if (!Result && Str.ends_with_insensitive(S))
0151       Result = Value;
0152 
0153     return *this;
0154   }
0155 
0156   StringSwitch &StartsWithLower(StringLiteral S, T Value) {
0157     if (!Result && Str.starts_with_insensitive(S))
0158       Result = std::move(Value);
0159 
0160     return *this;
0161   }
0162 
0163   StringSwitch &CasesLower(StringLiteral S0, StringLiteral S1, T Value) {
0164     return CaseLower(S0, Value).CaseLower(S1, Value);
0165   }
0166 
0167   StringSwitch &CasesLower(StringLiteral S0, StringLiteral S1, StringLiteral S2,
0168                            T Value) {
0169     return CaseLower(S0, Value).CasesLower(S1, S2, Value);
0170   }
0171 
0172   StringSwitch &CasesLower(StringLiteral S0, StringLiteral S1, StringLiteral S2,
0173                            StringLiteral S3, T Value) {
0174     return CaseLower(S0, Value).CasesLower(S1, S2, S3, Value);
0175   }
0176 
0177   StringSwitch &CasesLower(StringLiteral S0, StringLiteral S1, StringLiteral S2,
0178                            StringLiteral S3, StringLiteral S4, T Value) {
0179     return CaseLower(S0, Value).CasesLower(S1, S2, S3, S4, Value);
0180   }
0181 
0182   [[nodiscard]] R Default(T Value) {
0183     if (Result)
0184       return std::move(*Result);
0185     return Value;
0186   }
0187 
0188   [[nodiscard]] operator R() {
0189     assert(Result && "Fell off the end of a string-switch");
0190     return std::move(*Result);
0191   }
0192 };
0193 
0194 } // end namespace llvm
0195 
0196 #endif // LLVM_ADT_STRINGSWITCH_H