yum-mirror/slang

Making it easier to work with shaders

git clone https://git.yummers.dev/yum-mirror/slang

Ellie Hermaszewskaformatf65d756bf

master
10.7 KiB306 linesraw
1#ifndef SLANG_CORE_COMMAND_OPTIONS_H
2#define SLANG_CORE_COMMAND_OPTIONS_H
3
4#include "slang-basic.h"
5#include "slang-name-value.h"
6#include "slang-string-slice-pool.h"
7
8namespace Slang
9{
10
11/* For convenience we encode within "names" flags.
12"-D..." means that -D *must* be followed by the value
13"-D?..." means that -D *can* be a prefix, or it might be followed with the arg
14*/
15
16struct CommandOptions
17{
18    typedef uint32_t Flags;
19
20    typedef int32_t UserIndex;
21    enum class UserValue : UserIndex;
22    static const UserValue kInvalidUserValue = UserValue(0x80000000);
23
24    enum class LookupKind : int32_t
25    {
26        Category = -2, ///< Lookup a category name
27        Option = -1,   ///< Lookup an option name (all options use the same lookup index even if in
28                       ///< different categories)
29        Base = 0,      ///< Lookup via category index
30    };
31
32    /// A key type that uses the combination of the lookup kind and a name index.
33    /// Maps to a target index that could be a category or an option index.
34    struct NameKey
35    {
36        typedef NameKey ThisType;
37
38        SLANG_FORCE_INLINE bool operator==(const ThisType& rhs) const
39        {
40            return kind == rhs.kind && nameIndex == rhs.nameIndex;
41        }
42        SLANG_FORCE_INLINE bool operator!=(const ThisType& rhs) const { return !(*this == rhs); }
43        HashCode getHashCode() const
44        {
45            return combineHash(Slang::getHashCode(kind), Slang::getHashCode(nameIndex));
46        }
47
48        LookupKind kind; ///< The kind of lookup
49        Index nameIndex; ///< The name index in the pool
50    };
51
52    enum class CategoryKind
53    {
54        Option, ///< Command line option (like "-D")
55        Value,  ///< One of a set of values (such as an enum or some other kind of list of values)
56    };
57
58    struct ValuePair
59    {
60        const char* name;
61        const char* description;
62    };
63
64    struct Category
65    {
66        UserValue userValue = kInvalidUserValue;
67
68        CategoryKind kind;
69        UnownedStringSlice name;
70        UnownedStringSlice description;
71
72        // Holds the span that defines all of the options associated with the category
73        Index optionStartIndex = 0;
74        Index optionEndIndex = 0;
75    };
76
77    struct Flag
78    {
79        enum Enum : Flags
80        {
81            CanPrefix = 0x1, /// Allows -Dfsggf or -D fdsfsd
82            IsPrefix = 0x2,  /// Is an option that can only be a prefix
83        };
84    };
85
86    struct Option
87    {
88        UnownedStringSlice names; ///< Comma delimited list of names, first name is the default
89        UnownedStringSlice usage; ///< Describes usage, can be empty
90        UnownedStringSlice description; ///< A description of usage
91
92        UserValue userValue = kInvalidUserValue;
93
94        Index categoryIndex = -1; ///< Category this option belongs to
95        Flags flags = 0;          ///< Flags about this option
96    };
97
98    /// Get the first name
99    UnownedStringSlice getFirstNameForOption(Index optionIndex);
100    /// Get the first name for the category
101    UnownedStringSlice getFirstNameForCategory(Index categoryIndex);
102
103    /// Get a name key for an opton
104    NameKey getNameKeyForOption(Index optionIndex);
105    /// Get a name key for a category
106    NameKey getNameKeyForCategory(Index optionIndex);
107
108    /// Add a category
109    Index addCategory(
110        CategoryKind kind,
111        const char* name,
112        const char* description,
113        UserValue userValue = kInvalidUserValue);
114    /// Use an already known category. It's an error if the category isn't found
115    void setCategory(const char* name);
116
117    void add(
118        const char* name,
119        const char* usage,
120        const char* description,
121        UserValue userValue = kInvalidUserValue);
122    void add(
123        const UnownedStringSlice* names,
124        Count namesCount,
125        const char* usage,
126        const char* description,
127        UserValue userValue = kInvalidUserValue,
128        Flags flags = 0);
129
130    void addValue(const UnownedStringSlice& name, UserValue userValue = kInvalidUserValue);
131    void addValue(
132        const UnownedStringSlice& name,
133        const UnownedStringSlice& description,
134        UserValue userValue = kInvalidUserValue);
135    void addValue(
136        const char* name,
137        const char* description,
138        UserValue userValue = kInvalidUserValue);
139    void addValue(const char* name, UserValue userValue = kInvalidUserValue);
140    void addValue(
141        const UnownedStringSlice* names,
142        Count namesCount,
143        UserValue userValue = kInvalidUserValue);
144
145    /// Add values (without UserValue association)
146    void addValues(const ValuePair* pairs, Count pairsCount);
147
148    /// Add values
149    void addValues(const ConstArrayView<NameValue>& values);
150    void addValues(const ConstArrayView<NamesValue>& values);
151    void addValues(const ConstArrayView<NamesDescriptionValue>& values);
152
153    /// Sometimes values are listed with *names* per value. This method will take into account the
154    /// aliases
155    void addValuesWithAliases(const ConstArrayView<NameValue>& values);
156
157    /// Get the target index based off the name and the kind
158    Index findTargetIndexByName(
159        LookupKind kind,
160        const UnownedStringSlice& name,
161        NameKey* outNameKey = nullptr) const;
162    /// Given a kind and a user value lookup the target index
163    Index findTargetIndexByUserValue(LookupKind kind, UserValue userValue) const;
164
165    /// Finds the category by name or -1 if not found
166    Index findCategoryByName(const UnownedStringSlice& name) const
167    {
168        return findTargetIndexByName(LookupKind::Category, name);
169    }
170    /// Finds the option index by name or -1 if not found
171    Index findOptionByName(const UnownedStringSlice& name) const
172    {
173        return findTargetIndexByName(LookupKind::Option, name);
174    }
175    /// Find the option index of a value, using it's category index and the name
176    Index findValueByName(Index categoryIndex, const UnownedStringSlice& name) const
177    {
178        return findTargetIndexByName(LookupKind(categoryIndex), name);
179    }
180
181    /// Get the category index from a user value
182    Index findCategoryByUserValue(UserValue userValue) const
183    {
184        return findTargetIndexByUserValue(LookupKind::Category, userValue);
185    }
186    /// Can only get options
187    Index findOptionByUserValue(UserValue userValue) const
188    {
189        return findTargetIndexByUserValue(LookupKind::Option, userValue);
190    }
191    /// Get a value associated with a category
192    Index findValueByUserValue(Index categoryIndex, UserValue userValue) const
193    {
194        return findTargetIndexByUserValue(LookupKind(categoryIndex), userValue);
195    }
196
197    /// Given a category user value, find the associated name
198    /// Returns -1 if not found
199    Index findOptionByCategoryUserValue(UserValue categoryUserValue, const UnownedStringSlice& name)
200        const;
201
202    /// Find a category by case insensitive name. Returns -1 if not found
203    Index findCategoryByCaseInsensitiveName(const UnownedStringSlice& slice) const;
204
205    /// Given a category index returns all the options associated.
206    ConstArrayView<Option> getOptionsForCategory(Index categoryIndex) const;
207
208    /// Get the categories
209    const List<Category>& getCategories() const { return m_categories; }
210
211    /// Get all the options
212    const List<Option>& getOptions() const { return m_options; }
213
214    /// Get the option at the specified index
215    const Option& getOptionAt(Index index) const { return m_options[index]; }
216
217    /// Find all of the categories in the usage slice
218    void findCategoryIndicesFromUsage(
219        const UnownedStringSlice& usageSlice,
220        List<Index>& outCategories) const;
221
222    /// Splits usage into category slices
223    void splitUsage(const UnownedStringSlice& usageSlice, List<UnownedStringSlice>& outSlices)
224        const;
225
226    /// Get all the option names associated with a category index
227    void getCategoryOptionNames(Index categoryIndex, List<UnownedStringSlice>& outNames) const;
228    void appendCategoryOptionNames(Index categoryIndex, List<UnownedStringSlice>& outNames) const;
229
230    /// Set up a lookup kind from a category index
231    static LookupKind makeLookupKind(Index categoryIndex) { return LookupKind(categoryIndex); }
232
233    /// Returns true, if all values from [start, end) are found for the kind
234    bool hasContiguousUserValueRange(LookupKind kind, UserValue start, UserValue nonInclEnd) const;
235
236    /// Returns the number of options in the range
237    Count getOptionCountInRange(Index categoryIndex, UserValue start, UserValue nonInclEnd) const;
238    Count getOptionCountInRange(LookupKind kind, UserValue start, UserValue nonInclEnd) const;
239
240
241    /// Ctor
242    CommandOptions()
243        : m_pool(StringSlicePool::Style::Default), m_arena(1024 * 2)
244    {
245    }
246
247protected:
248    /// Returns name in the m_optionPool or -1 on error
249    SlangResult _addOptionName(const UnownedStringSlice& name, Flags flags, Index targetIndex);
250    SlangResult _addValueName(
251        const UnownedStringSlice& name,
252        Index categoryIndex,
253        Index targetIndex);
254    SlangResult _addName(LookupKind kind, const UnownedStringSlice& name, Index targetIndex);
255
256    SlangResult _addUserValue(LookupKind kind, UserValue userValue, Index targetIndex);
257
258    Index _addOption(const UnownedStringSlice& name, const Option& inOption);
259    Index _addOption(const UnownedStringSlice* names, Count namesCount, const Option& option);
260
261    Index _addValue(const UnownedStringSlice& name, const Option& inOption);
262
263    UnownedStringSlice _addString(const char* text);
264    UnownedStringSlice _addString(const UnownedStringSlice& slice);
265
266    Index _findTargetIndexByName(
267        LookupKind kind,
268        const UnownedStringSlice& name,
269        NameKey* outNameKey) const;
270
271    struct UserValueKey
272    {
273        typedef UserValueKey ThisType;
274
275        SLANG_FORCE_INLINE bool operator==(const ThisType& rhs) const
276        {
277            return kind == rhs.kind && userValue == rhs.userValue;
278        }
279        SLANG_FORCE_INLINE bool operator!=(const ThisType& rhs) const { return !(*this == rhs); }
280        HashCode getHashCode() const
281        {
282            return combineHash(Slang::getHashCode(kind), Slang::getHashCode(userValue));
283        }
284
285        LookupKind kind;     ///< The kind of lookup
286        UserValue userValue; ///< The user value
287    };
288
289    Index m_currentCategoryIndex = -1;
290
291    List<Category> m_categories;
292
293    // Holds a bit for all valid prefix sizes. Max prefix size is therefore 32 chars
294    uint32_t m_prefixSizes = 0;
295
296    List<Option> m_options; ///< All of the entries describing each of the options
297    StringSlicePool m_pool; ///< Only holds options, and handle therefore matches up to m_entries
298    Dictionary<NameKey, Index> m_nameMap;           ///< Maps a name to an option index
299    Dictionary<UserValueKey, Index> m_userValueMap; ///< Maps a user value (for a kind) to an index
300
301    MemoryArena m_arena; ///< For other misc storage
302};
303
304} // namespace Slang
305
306#endif