yum-mirror/slang

Making it easier to work with shaders

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

Theresa FoleyCleanups related to RIFF support (#7041)4c76b2759

master
6.2 KiB251 linesraw
1// slang-semantic-version.cpp
2#include "slang-semantic-version.h"
3
4#include "../core/slang-string-util.h"
5#include "slang-com-helper.h"
6
7namespace Slang
8{
9
10// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! SemanticVersion !!!!!!!!!!!!!!!!!!!!!!!!!!!!!
11
12SlangResult SemanticVersion::parse(
13    const UnownedStringSlice& value,
14    char separatorChar,
15    SemanticVersion& outVersion)
16{
17    outVersion.reset();
18
19    UnownedStringSlice slices[3];
20    Index splitCount;
21    SLANG_RETURN_ON_FAIL(StringUtil::split(value, separatorChar, 3, slices, splitCount));
22    if (splitCount <= 0)
23    {
24        return SLANG_FAIL;
25    }
26
27    Int ints[3] = {0, 0, 0};
28    for (Index i = 0; i < splitCount; i++)
29    {
30        SLANG_RETURN_ON_FAIL(StringUtil::parseInt(slices[i], ints[i]));
31
32        const Int max = (i == 2) ? 0x7fffffff : 0xffff;
33        if (ints[i] < 0 || ints[i] > max)
34        {
35            return SLANG_FAIL;
36        }
37    }
38
39    outVersion.m_major = uint16_t(ints[0]);
40    outVersion.m_minor = uint16_t(ints[1]);
41    outVersion.m_patch = uint32_t(ints[2]);
42
43    return SLANG_OK;
44}
45
46SlangResult SemanticVersion::parse(const UnownedStringSlice& value, SemanticVersion& outVersion)
47{
48    return parse(value, '.', outVersion);
49}
50
51void SemanticVersion::append(StringBuilder& buf) const
52{
53    buf << Int32(m_major) << "." << Int32(m_minor);
54    if (m_patch != 0)
55    {
56        buf << "." << UInt32(m_patch);
57    }
58}
59
60/* static */ SemanticVersion SemanticVersion::getEarliest(const ThisType* versions, Count count)
61{
62    if (count <= 0)
63    {
64        return SemanticVersion();
65    }
66
67    SemanticVersion bestVersion = versions[0];
68    for (const auto version : makeConstArrayView(versions + 1, count - 1))
69    {
70        if (version < bestVersion)
71        {
72            bestVersion = version;
73        }
74    }
75    return bestVersion;
76}
77
78/* static */ SemanticVersion SemanticVersion::getLatest(const ThisType* versions, Count count)
79{
80    if (count <= 0)
81    {
82        return SemanticVersion();
83    }
84
85    SemanticVersion bestVersion = versions[0];
86    for (const auto version : makeConstArrayView(versions + 1, count - 1))
87    {
88        if (version > bestVersion)
89        {
90            bestVersion = version;
91        }
92    }
93    return bestVersion;
94}
95
96bool SemanticVersion::isBackwardsCompatibleWith(const ThisType& otherVersion) const
97{
98    // Compatibility is not guaranteed across major revisions.
99    //
100    if (m_major != otherVersion.m_major)
101        return false;
102
103    // Within a given major revision, a version with a higher
104    // minor revision is backwards-compatible with one that
105    // has a lower minor revision, but not vice-versa.
106    //
107    if (m_minor < otherVersion.m_minor)
108        return false;
109
110    // If the major and minor revisions pass our check, then
111    // we consider it a match. Note that this intentionally
112    // doesn't check the path version at all.
113    //
114    return true;
115}
116
117
118// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! MatchSemanticVersion !!!!!!!!!!!!!!!!!!!!!!!!!!!!!
119
120/* static */ SemanticVersion MatchSemanticVersion::findAnyBest(
121    const SemanticVersion* versions,
122    Count count,
123    const ThisType& matchVersion)
124{
125    // If there aren't any we are done
126    if (count <= 0)
127    {
128        return SemanticVersion();
129    }
130
131    // If there is only one it must be the best
132    if (count == 1)
133    {
134        return versions[0];
135    }
136
137    // Define a version range [start, end)
138    SemanticVersion start, end;
139
140    switch (matchVersion.m_kind)
141    {
142    case Kind::Past:
143        {
144            return SemanticVersion::getEarliest(versions, count);
145        }
146    case Kind::Unknown:
147    case Kind::Future:
148        {
149            // If it's unknown, we just get the latest
150            return SemanticVersion::getLatest(versions, count);
151        }
152    case Kind::Major:
153        {
154            start = SemanticVersion(matchVersion.m_version.m_major, 0, 0);
155            end = SemanticVersion(matchVersion.m_version.m_major + 1, 0, 0);
156            break;
157        }
158    case Kind::MajorMinor:
159        {
160            start =
161                SemanticVersion(matchVersion.m_version.m_major, matchVersion.m_version.m_minor, 0);
162            end = SemanticVersion(
163                matchVersion.m_version.m_major,
164                matchVersion.m_version.m_minor + 1,
165                0);
166            break;
167        }
168    case Kind::MajorMinorPatch:
169        {
170            start = SemanticVersion(matchVersion.m_version);
171            end = SemanticVersion(
172                matchVersion.m_version.m_major,
173                matchVersion.m_version.m_minor,
174                matchVersion.m_version.m_patch + 1);
175            break;
176        }
177    default:
178        break;
179    }
180
181    List<SemanticVersion> sortedVersions;
182    sortedVersions.addRange(versions, count);
183
184    // Sort into increasing values
185    sortedVersions.sort(
186        [&](const SemanticVersion& a, const SemanticVersion& b) -> bool { return a < b; });
187
188    Index startIndex = 0;
189    for (; startIndex < count && sortedVersions[startIndex] < start; ++startIndex)
190        ;
191
192    Index endIndex = startIndex;
193    for (; endIndex < count && sortedVersions[endIndex] < end; ++endIndex)
194        ;
195
196    // If we have a span of versions, get the last in the span
197    if (startIndex < endIndex)
198    {
199        // Get the last one
200        return sortedVersions[endIndex - 1];
201    }
202
203    // Get the next greatest if there is one
204    if (endIndex < count)
205    {
206        return sortedVersions[endIndex];
207    }
208
209    // Get the prior prior to the start
210    if (startIndex > 0)
211    {
212        return sortedVersions[startIndex - 1];
213    }
214
215    // All cases should be covered, but return the last one
216    return sortedVersions[count - 1];
217}
218
219void MatchSemanticVersion::append(StringBuilder& buf) const
220{
221    switch (m_kind)
222    {
223    default:
224    case Kind::Unknown:
225        buf << "unknown";
226        break;
227    case Kind::Past:
228        buf << "past";
229        break;
230    case Kind::Future:
231        buf << "future";
232        break;
233    case Kind::Major:
234        {
235            buf << m_version.m_major;
236            break;
237        }
238    case Kind::MajorMinor:
239        {
240            buf << m_version.m_major << "." << m_version.m_minor;
241            break;
242        }
243    case Kind::MajorMinorPatch:
244        {
245            m_version.append(buf);
246            break;
247        }
248    }
249}
250
251} // namespace Slang