yum-mirror/slang

Making it easier to work with shaders

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

Ellie HermaszewskaMove switch statement bodies to their own lines (#5493)b118451e3

master
8.9 KiB334 linesraw
1
2#include "slang-name-convention-util.h"
3
4#include "../core/slang-char-util.h"
5#include "../core/slang-string-util.h"
6
7namespace Slang
8{
9
10/* static */ NameConvention NameConventionUtil::inferConventionFromText(
11    const UnownedStringSlice& slice)
12{
13    // If no chars, or first char isn't alpha we don't know what it is
14    if (slice.getLength() <= 0 || !CharUtil::isAlpha(slice[0]))
15    {
16        return NameConvention::Invalid;
17    }
18
19    typedef int Flags;
20    struct Flag
21    {
22        enum Enum : Flags
23        {
24            Underscore = 0x1,
25            Dash = 0x2,
26            Upper = 0x4,
27            Lower = 0x8,
28        };
29    };
30
31    Flags flags = 0;
32
33    for (const char c : slice)
34    {
35        switch (c)
36        {
37        case '-':
38            flags |= Flag::Dash;
39            break;
40        case '_':
41            flags |= Flag::Underscore;
42            break;
43        default:
44            {
45                if (CharUtil::isLower(c))
46                {
47                    flags |= Flag::Lower;
48                }
49                else if (CharUtil::isUpper(c))
50                {
51                    flags |= Flag::Upper;
52                }
53                else if (CharUtil::isDigit(c))
54                {
55                    // Is okay as long as not first char (which we already tested is alpha)
56                }
57                else
58                {
59                    // Don't know what this style is
60                    return NameConvention::Invalid;
61                }
62            }
63        }
64    }
65
66    // Use flags to determine what convention is used
67    switch (flags)
68    {
69    // We'll assume it's lower camel.
70    case Flag::Lower:
71        return NameConvention::LowerCamel;
72    // We'll assume it's upper snake. It almost certainly isn't camel, and snake is more usual
73    // than kabab.
74    case Flag::Upper:
75        return NameConvention::UpperSnake;
76    case Flag::Upper | Flag::Lower:
77        {
78            // Looks like camel, choose the right case based on first char
79            return CharUtil::isUpper(slice[0]) ? NameConvention::UpperCamel
80                                               : NameConvention::LowerCamel;
81        }
82    case Flag::Lower | Flag::Dash:
83        return NameConvention::LowerKabab;
84    case Flag::Upper | Flag::Dash:
85        return NameConvention::UpperKabab;
86    case Flag::Lower | Flag::Underscore:
87        return NameConvention::LowerSnake;
88    case Flag::Upper | Flag::Underscore:
89        return NameConvention::UpperSnake;
90    default:
91        break;
92    }
93
94    // Don't know what this style is
95    return NameConvention::Invalid;
96}
97
98/* static */ NameStyle NameConventionUtil::inferStyleFromText(const UnownedStringSlice& slice)
99{
100    for (const char c : slice)
101    {
102        switch (c)
103        {
104        case '-':
105            return NameStyle::Kabab;
106        case '_':
107            return NameStyle::Snake;
108        default:
109            break;
110        }
111    }
112    return NameStyle::Camel;
113}
114
115/* static */ void NameConventionUtil::split(
116    NameStyle style,
117    const UnownedStringSlice& slice,
118    List<UnownedStringSlice>& out)
119{
120    switch (style)
121    {
122    case NameStyle::Kabab:
123        {
124            StringUtil::split(slice, '-', out);
125            break;
126        }
127    case NameStyle::Snake:
128        {
129            StringUtil::split(slice, '_', out);
130            break;
131        }
132    case NameStyle::Camel:
133        {
134            typedef CharUtil::Flags CharFlags;
135            typedef CharUtil::Flag CharFlag;
136
137            CharFlags prevFlags = 0;
138            const char* const end = slice.end();
139
140            const char* start = slice.begin();
141            for (const char* cur = start; cur < end; ++cur)
142            {
143                const char c = *cur;
144                const CharUtil::Flags flags = CharUtil::getFlags(c);
145
146                if (flags & CharFlag::Upper)
147                {
148                    if (prevFlags & CharFlag::Lower)
149                    {
150                        // If we go from lower to upper, we have a transition
151                        out.add(UnownedStringSlice(start, cur));
152                        start = cur;
153                    }
154                    else if ((prevFlags & CharFlag::Upper) && cur + 1 < end)
155                    {
156                        // This works with capital or uncapitalized acronyms, but if we have two
157                        // capitalized acronyms following each other - it can't split.
158                        //
159                        // For example
160                        // "IAABBSystem" -> "IAABB", "System"
161                        //
162                        // If it only accepted lower case acronyms the logic could be changed such
163                        // that the following could be produced "IAabbSystem" -> "I", "Aabb",
164                        // "System"
165                        //
166                        // Since Slang source largely goes with upper case acronyms, we work with
167                        // the heuristic here..
168
169                        if (CharUtil::isLower(cur[1]))
170                        {
171                            out.add(UnownedStringSlice(start, cur));
172                            start = cur;
173                        }
174                    }
175                }
176
177                prevFlags = flags;
178            }
179
180            // Add any end section
181            if (start < end)
182            {
183                out.add(UnownedStringSlice(start, end));
184            }
185            break;
186        }
187    case NameStyle::Unknown:
188        {
189            out.add(slice);
190            break;
191        }
192    }
193}
194
195void NameConventionUtil::split(const UnownedStringSlice& slice, List<UnownedStringSlice>& out)
196{
197    split(inferStyleFromText(slice), slice, out);
198}
199
200/* static */ void NameConventionUtil::join(
201    const UnownedStringSlice* slices,
202    Index slicesCount,
203    NameConvention convention,
204    char joinChar,
205    StringBuilder& out)
206{
207    if (slicesCount <= 0)
208    {
209        return;
210    }
211
212    Index totalSize = slicesCount - 1;
213    for (Index i = 0; i < slicesCount; ++i)
214    {
215        totalSize += slices[i].getLength();
216    }
217
218    char* const dstStart = out.prepareForAppend(totalSize);
219    char* dst = dstStart;
220
221    const bool upper = isUpper(convention);
222
223    for (Index i = 0; i < slicesCount; ++i)
224    {
225        const UnownedStringSlice& slice = slices[i];
226        const Index count = slice.getLength();
227        const char* const src = slice.begin();
228
229        if (i > 0)
230        {
231            *dst++ = joinChar;
232        }
233
234        if (upper)
235        {
236            for (Index j = 0; j < count; ++j)
237            {
238                dst[j] = CharUtil::toUpper(src[j]);
239            }
240        }
241        else
242        {
243            for (Index j = 0; j < count; ++j)
244            {
245                dst[j] = CharUtil::toLower(src[j]);
246            }
247        }
248
249        dst += count;
250    }
251
252    SLANG_ASSERT(dstStart + totalSize == dst);
253    out.appendInPlace(dstStart, totalSize);
254}
255
256/* static */ void NameConventionUtil::join(
257    const UnownedStringSlice* slices,
258    Index slicesCount,
259    NameConvention convention,
260    StringBuilder& out)
261{
262    const auto style = getNameStyle(convention);
263
264    switch (style)
265    {
266    case NameStyle::Kabab:
267        return join(slices, slicesCount, convention, '-', out);
268    case NameStyle::Snake:
269        return join(slices, slicesCount, convention, '_', out);
270    case NameStyle::Camel:
271        {
272            Index totalSize = 0;
273
274            for (Index i = 0; i < slicesCount; ++i)
275            {
276                totalSize += slices[i].getLength();
277            }
278
279            char* const dstStart = out.prepareForAppend(totalSize);
280            char* dst = dstStart;
281
282            for (Index i = 0; i < slicesCount; ++i)
283            {
284                const UnownedStringSlice& slice = slices[i];
285                Index count = slice.getLength();
286                const char* src = slice.begin();
287
288                Int j = 0;
289
290                if (count > 0 && !(i == 0 && isLower(convention)))
291                {
292                    // Capitalize first letter of each word, unless on first word and 'lower'
293                    dst[j] = CharUtil::toUpper(src[j]);
294                    j++;
295                }
296
297                for (; j < count; ++j)
298                {
299                    dst[j] = CharUtil::toLower(src[j]);
300                }
301
302                dst += count;
303            }
304
305            SLANG_ASSERT(dstStart + totalSize == dst);
306            out.appendInPlace(dstStart, totalSize);
307            break;
308        }
309    }
310}
311
312/* static */ void NameConventionUtil::convert(
313    NameStyle fromStyle,
314    const UnownedStringSlice& slice,
315    NameConvention toConvention,
316    StringBuilder& out)
317{
318    // Split into slices
319    List<UnownedStringSlice> slices;
320    split(fromStyle, slice, slices);
321
322    // Join the slices in the toConvention
323    join(slices.getBuffer(), slices.getCount(), toConvention, out);
324}
325
326/* static */ void NameConventionUtil::convert(
327    const UnownedStringSlice& slice,
328    NameConvention toConvention,
329    StringBuilder& out)
330{
331    convert(inferStyleFromText(slice), slice, toConvention, out);
332}
333
334} // namespace Slang