#ifndef SLANG_CORE_COMMAND_OPTIONS_H #define SLANG_CORE_COMMAND_OPTIONS_H #include "slang-basic.h" #include "slang-name-value.h" #include "slang-string-slice-pool.h" namespace Slang { /* For convenience we encode within "names" flags. "-D..." means that -D *must* be followed by the value "-D?..." means that -D *can* be a prefix, or it might be followed with the arg */ struct CommandOptions { typedef uint32_t Flags; typedef int32_t UserIndex; enum class UserValue : UserIndex; static const UserValue kInvalidUserValue = UserValue(0x80000000); enum class LookupKind : int32_t { Category = -2, ///< Lookup a category name Option = -1, ///< Lookup an option name (all options use the same lookup index even if in ///< different categories) Base = 0, ///< Lookup via category index }; /// A key type that uses the combination of the lookup kind and a name index. /// Maps to a target index that could be a category or an option index. struct NameKey { typedef NameKey ThisType; SLANG_FORCE_INLINE bool operator==(const ThisType& rhs) const { return kind == rhs.kind && nameIndex == rhs.nameIndex; } SLANG_FORCE_INLINE bool operator!=(const ThisType& rhs) const { return !(*this == rhs); } HashCode getHashCode() const { return combineHash(Slang::getHashCode(kind), Slang::getHashCode(nameIndex)); } LookupKind kind; ///< The kind of lookup Index nameIndex; ///< The name index in the pool }; enum class CategoryKind { Option, ///< Command line option (like "-D") Value, ///< One of a set of values (such as an enum or some other kind of list of values) }; struct ValuePair { const char* name; const char* description; }; struct Category { UserValue userValue = kInvalidUserValue; CategoryKind kind; UnownedStringSlice name; UnownedStringSlice description; // Holds the span that defines all of the options associated with the category Index optionStartIndex = 0; Index optionEndIndex = 0; }; struct Flag { enum Enum : Flags { CanPrefix = 0x1, /// Allows -Dfsggf or -D fdsfsd IsPrefix = 0x2, /// Is an option that can only be a prefix }; }; struct Option { UnownedStringSlice names; ///< Comma delimited list of names, first name is the default UnownedStringSlice usage; ///< Describes usage, can be empty UnownedStringSlice description; ///< A description of usage UserValue userValue = kInvalidUserValue; Index categoryIndex = -1; ///< Category this option belongs to Flags flags = 0; ///< Flags about this option }; /// Get the first name UnownedStringSlice getFirstNameForOption(Index optionIndex); /// Get the first name for the category UnownedStringSlice getFirstNameForCategory(Index categoryIndex); /// Get a name key for an opton NameKey getNameKeyForOption(Index optionIndex); /// Get a name key for a category NameKey getNameKeyForCategory(Index optionIndex); /// Add a category Index addCategory( CategoryKind kind, const char* name, const char* description, UserValue userValue = kInvalidUserValue); /// Use an already known category. It's an error if the category isn't found void setCategory(const char* name); void add( const char* name, const char* usage, const char* description, UserValue userValue = kInvalidUserValue); void add( const UnownedStringSlice* names, Count namesCount, const char* usage, const char* description, UserValue userValue = kInvalidUserValue, Flags flags = 0); void addValue(const UnownedStringSlice& name, UserValue userValue = kInvalidUserValue); void addValue( const UnownedStringSlice& name, const UnownedStringSlice& description, UserValue userValue = kInvalidUserValue); void addValue( const char* name, const char* description, UserValue userValue = kInvalidUserValue); void addValue(const char* name, UserValue userValue = kInvalidUserValue); void addValue( const UnownedStringSlice* names, Count namesCount, UserValue userValue = kInvalidUserValue); /// Add values (without UserValue association) void addValues(const ValuePair* pairs, Count pairsCount); /// Add values void addValues(const ConstArrayView& values); void addValues(const ConstArrayView& values); void addValues(const ConstArrayView& values); /// Sometimes values are listed with *names* per value. This method will take into account the /// aliases void addValuesWithAliases(const ConstArrayView& values); /// Get the target index based off the name and the kind Index findTargetIndexByName( LookupKind kind, const UnownedStringSlice& name, NameKey* outNameKey = nullptr) const; /// Given a kind and a user value lookup the target index Index findTargetIndexByUserValue(LookupKind kind, UserValue userValue) const; /// Finds the category by name or -1 if not found Index findCategoryByName(const UnownedStringSlice& name) const { return findTargetIndexByName(LookupKind::Category, name); } /// Finds the option index by name or -1 if not found Index findOptionByName(const UnownedStringSlice& name) const { return findTargetIndexByName(LookupKind::Option, name); } /// Find the option index of a value, using it's category index and the name Index findValueByName(Index categoryIndex, const UnownedStringSlice& name) const { return findTargetIndexByName(LookupKind(categoryIndex), name); } /// Get the category index from a user value Index findCategoryByUserValue(UserValue userValue) const { return findTargetIndexByUserValue(LookupKind::Category, userValue); } /// Can only get options Index findOptionByUserValue(UserValue userValue) const { return findTargetIndexByUserValue(LookupKind::Option, userValue); } /// Get a value associated with a category Index findValueByUserValue(Index categoryIndex, UserValue userValue) const { return findTargetIndexByUserValue(LookupKind(categoryIndex), userValue); } /// Given a category user value, find the associated name /// Returns -1 if not found Index findOptionByCategoryUserValue(UserValue categoryUserValue, const UnownedStringSlice& name) const; /// Find a category by case insensitive name. Returns -1 if not found Index findCategoryByCaseInsensitiveName(const UnownedStringSlice& slice) const; /// Given a category index returns all the options associated. ConstArrayView