yum-mirror/slang

Making it easier to work with shaders

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

Ellie Hermaszewskaformatf65d756bf

master
5.9 KiB253 linesraw
1#include "slang-source-map.h"
2
3namespace Slang
4{
5
6void SourceMap::clear()
7{
8    const String empty;
9
10    m_file = empty;
11    m_sourceRoot = empty;
12
13    m_sources.clear();
14
15    m_names.clear();
16
17    m_sourcesContent.clear();
18
19    m_lineStarts.setCount(1);
20    m_lineStarts[0] = 0;
21
22    m_lineEntries.clear();
23
24    m_slicePool.clear();
25}
26
27void SourceMap::swapWith(ThisType& rhs)
28{
29    m_file.swapWith(rhs.m_file);
30    m_sourceRoot.swapWith(rhs.m_sourceRoot);
31    m_sources.swapWith(rhs.m_sources);
32    m_names.swapWith(rhs.m_names);
33    m_sourcesContent.swapWith(rhs.m_sourcesContent);
34    m_lineStarts.swapWith(rhs.m_lineStarts);
35    m_lineEntries.swapWith(rhs.m_lineEntries);
36    m_slicePool.swapWith(rhs.m_slicePool);
37}
38
39static bool _areEqual(
40    const List<StringSlicePool::Handle>& a,
41    const List<StringSlicePool::Handle>& b,
42    const List<Index>& bToAMap)
43{
44    const auto count = a.getCount();
45    if (count != b.getCount())
46    {
47        return false;
48    }
49
50    const auto* as = a.getBuffer();
51    const auto* bs = a.getBuffer();
52
53    for (Index i = 0; i < count; ++i)
54    {
55        if (StringSlicePool::asIndex(as[i]) != bToAMap[StringSlicePool::asIndex(bs[i])])
56        {
57            return false;
58        }
59    }
60
61    return true;
62}
63
64static bool _areEqual(
65    const SourceMap::Entry& a,
66    const SourceMap::Entry& b,
67    const List<Index>& bToAMap)
68{
69    return a.generatedColumn == b.generatedColumn && a.sourceLine == b.sourceLine &&
70           a.sourceColumn == b.sourceColumn && a.sourceFileIndex == bToAMap[b.sourceFileIndex] &&
71           a.nameIndex == bToAMap[b.nameIndex];
72}
73
74static bool _areEqual(
75    const List<SourceMap::Entry>& a,
76    const List<SourceMap::Entry>& b,
77    const List<Index>& bToAMap)
78{
79    const auto count = a.getCount();
80    if (count != b.getCount())
81    {
82        return false;
83    }
84
85    for (Index i = 0; i < count; ++i)
86    {
87        if (!_areEqual(a[i], b[i], bToAMap))
88        {
89            return false;
90        }
91    }
92
93    return true;
94}
95
96bool SourceMap::operator==(const ThisType& rhs) const
97{
98    if (this == &rhs)
99    {
100        return true;
101    }
102
103    if (m_file != rhs.m_file || m_sourceRoot != rhs.m_sourceRoot ||
104        m_lineStarts != rhs.m_lineStarts)
105    {
106        return false;
107    }
108
109    if (m_slicePool == rhs.m_slicePool)
110    {
111        // If the slice pools are the same we can just compare indices directly
112        return m_sources == rhs.m_sources && m_sourcesContent == rhs.m_sourcesContent &&
113               m_names == rhs.m_names && m_lineEntries == rhs.m_lineEntries;
114    }
115    else
116    {
117        // Otherwise we need to remap the indices
118        // Maps a pool handle from the rhs source map to the
119        List<Index> rhsMap;
120
121        Count count = rhs.m_slicePool.getSlicesCount();
122
123        rhsMap.setCount(count);
124
125        const auto startIndex = rhs.m_slicePool.getFirstAddedIndex();
126
127        // Work out the map
128        for (Index i = 0; i < startIndex; ++i)
129        {
130            const auto rhsSlice = rhs.m_slicePool.getSlice(StringSlicePool::Handle(i));
131            rhsMap[i] = (i < startIndex) ? i : m_slicePool.findIndex(rhsSlice);
132        }
133
134        // Do the comparison taking into account the mapping.
135        return _areEqual(m_sources, rhs.m_sources, rhsMap) &&
136               _areEqual(m_sourcesContent, rhs.m_sourcesContent, rhsMap) &&
137               _areEqual(m_names, rhs.m_names, rhsMap) &&
138               _areEqual(m_lineEntries, rhs.m_lineEntries, rhsMap);
139    }
140}
141
142void SourceMap::advanceToLine(Index nextLineIndex)
143{
144    const Count currentLineIndex = getGeneratedLineCount() - 1;
145
146    SLANG_ASSERT(nextLineIndex >= currentLineIndex);
147
148    if (nextLineIndex <= currentLineIndex)
149    {
150        return;
151    }
152
153    const auto lastEntryIndex = m_lineEntries.getCount();
154
155    // For all the new entries they will need to point to the end
156    m_lineStarts.growToCount(nextLineIndex + 1);
157
158    Index* starts = m_lineStarts.getBuffer();
159    for (Index i = currentLineIndex + 1; i < nextLineIndex + 1; ++i)
160    {
161        starts[i] = lastEntryIndex;
162    }
163}
164
165Index SourceMap::getNameIndex(const UnownedStringSlice& slice)
166{
167    StringSlicePool::Handle handle;
168
169    if (!m_slicePool.findOrAdd(slice, handle))
170    {
171        // We know it can't possibly be used, so must be new (!)
172
173        m_names.add(handle);
174        return m_names.getCount() - 1;
175    }
176
177    // Okay, could already be in the list
178    const auto index = m_names.indexOf(handle);
179    if (index >= 0)
180    {
181        return index;
182    }
183
184    m_names.add(handle);
185    return m_names.getCount() - 1;
186}
187
188UnownedStringSlice SourceMap::getSourceFileName(Index sourceFileIndex) const
189{
190    return m_slicePool.getSlice(m_sources[sourceFileIndex]);
191}
192
193Index SourceMap::getSourceFileIndex(const UnownedStringSlice& slice)
194{
195    StringSlicePool::Handle handle;
196
197    if (!m_slicePool.findOrAdd(slice, handle))
198    {
199        // We know it can't possibly be used, so must be new (!)
200
201        m_sources.add(handle);
202        return m_sources.getCount() - 1;
203    }
204
205    // Okay, could already be in the list
206    const auto index = m_sources.indexOf(handle);
207    if (index >= 0)
208    {
209        return index;
210    }
211
212    m_sources.add(handle);
213    return m_sources.getCount() - 1;
214}
215
216Index SourceMap::findEntry(Index lineIndex, Index colIndex) const
217{
218    auto entries = getEntriesForLine(lineIndex);
219
220    Index closestDist = 0x7fffffff;
221    Index bestIndex = -1;
222
223    const Count count = entries.getCount();
224    for (Index i = 0; i < count; ++i)
225    {
226        const Entry& entry = entries[i];
227
228        // We found an exact match
229        if (entry.generatedColumn == colIndex)
230        {
231            bestIndex = i;
232            break;
233        }
234
235        Index dist = entry.generatedColumn - colIndex;
236        dist = (dist < 0) ? -dist : dist;
237
238        if (dist < closestDist)
239        {
240            closestDist = dist;
241            bestIndex = i;
242        }
243    }
244
245    if (bestIndex < 0)
246    {
247        return bestIndex;
248    }
249
250    return m_lineStarts[lineIndex] + bestIndex;
251}
252
253} // namespace Slang