yum-mirror/slang

Making it easier to work with shaders

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

Ellie Hermaszewskaformatf65d756bf

master
5.4 KiB245 linesraw
1#include "slang-string-slice-pool.h"
2
3namespace Slang
4{
5
6/* static */ const StringSlicePool::Handle StringSlicePool::kNullHandle;
7/* static */ const StringSlicePool::Handle StringSlicePool::kEmptyHandle;
8
9/* static */ const Index StringSlicePool::kDefaultHandlesCount;
10
11StringSlicePool::StringSlicePool(Style style)
12    : m_style(style), m_arena(1024)
13{
14    clear();
15}
16
17StringSlicePool::StringSlicePool(const ThisType& rhs)
18    : m_style(rhs.m_style), m_arena(1024)
19{
20    // Set with rhs
21    _set(rhs);
22}
23
24void StringSlicePool::operator=(const ThisType& rhs)
25{
26    if (&rhs != this)
27    {
28        _set(rhs);
29    }
30}
31
32void StringSlicePool::_set(const ThisType& rhs)
33{
34    SLANG_ASSERT(this != &rhs);
35    m_style = rhs.m_style;
36
37    clear();
38
39    const Index startIndex = rhs.getFirstAddedIndex();
40    const Count count = rhs.m_slices.getCount();
41
42    if (count == 0)
43        return;
44
45    // We need the same amount of slices
46    m_slices.setCount(count);
47
48    // Work out the total size to store all slices including terminating 0
49    // (which *isn't* part of the slice size)
50    size_t totalSize = 0;
51
52    for (Index i = startIndex; i < count; ++i)
53    {
54        const auto slice = rhs.m_slices[i];
55        totalSize += slice.getLength() + 1;
56    }
57
58    char* dst = (char*)m_arena.allocate(totalSize);
59
60    for (Index i = startIndex; i < count; ++i)
61    {
62        const auto srcSlice = rhs.m_slices[i];
63        const auto sliceSize = srcSlice.getLength();
64
65        // Copy over the src slices contents
66        ::memcpy(dst, srcSlice.begin(), sliceSize);
67        // Zero terminate
68        dst[sliceSize] = 0;
69
70        const UnownedStringSlice dstSlice(dst, sliceSize);
71        // Set the slice
72        m_slices[i] = dstSlice;
73
74        // Add to the map
75        m_map.add(dstSlice, Handle(i));
76
77        // Skip to next slices storage
78        dst += sliceSize + 1;
79    }
80}
81
82bool StringSlicePool::operator==(const ThisType& rhs) const
83{
84    if (this == &rhs)
85    {
86        return true;
87    }
88
89    if (m_style != rhs.m_style)
90    {
91        return false;
92    }
93
94    const auto count = m_slices.getCount();
95
96    if (count != rhs.m_slices.getCount())
97    {
98        return false;
99    }
100
101    for (Index i = 0; i < count; ++i)
102    {
103        if (m_slices[i] != rhs.m_slices[i])
104        {
105            return false;
106        }
107    }
108
109    return true;
110}
111
112void StringSlicePool::clear()
113{
114    m_map.clear();
115    m_arena.deallocateAll();
116
117    switch (m_style)
118    {
119    case Style::Default:
120        {
121            // Add the defaults
122            m_slices.setCount(2);
123
124            m_slices[0] = UnownedStringSlice((const char*)nullptr, (const char*)nullptr);
125            m_slices[1] = UnownedStringSlice::fromLiteral("");
126
127            // Add the empty entry
128            m_map.add(m_slices[1], kEmptyHandle);
129            break;
130        }
131    case Style::Empty:
132        {
133            // There are no defaults
134            m_slices.clear();
135            break;
136        }
137    }
138}
139
140void StringSlicePool::swapWith(ThisType& rhs)
141{
142    Swap(m_style, rhs.m_style);
143    m_slices.swapWith(rhs.m_slices);
144    m_map.swapWith(rhs.m_map);
145    m_arena.swapWith(rhs.m_arena);
146}
147
148StringSlicePool::Handle StringSlicePool::add(const Slice& slice)
149{
150    const Handle* handlePtr = m_map.tryGetValue(slice);
151    if (handlePtr)
152    {
153        return *handlePtr;
154    }
155
156    // Create a scoped copy
157    UnownedStringSlice scopePath(
158        m_arena.allocateString(slice.begin(), slice.getLength()),
159        slice.getLength());
160
161    const auto index = m_slices.getCount();
162
163    m_slices.add(scopePath);
164    m_map.add(scopePath, Handle(index));
165    return Handle(index);
166}
167
168bool StringSlicePool::findOrAdd(const Slice& slice, Handle& outHandle)
169{
170    const Handle* handlePtr = m_map.tryGetValue(slice);
171    if (handlePtr)
172    {
173        outHandle = *handlePtr;
174        return true;
175    }
176
177    // Need to add.
178
179    // Make a copy stored in the arena
180    UnownedStringSlice scopeSlice(
181        m_arena.allocateString(slice.begin(), slice.getLength()),
182        slice.getLength());
183
184    // Add using the arenas copy
185    Handle newHandle = Handle(m_slices.getCount());
186    m_map.add(scopeSlice, newHandle);
187
188    // Add to slices list
189    m_slices.add(scopeSlice);
190    outHandle = newHandle;
191    return false;
192}
193
194StringSlicePool::Handle StringSlicePool::add(StringRepresentation* stringRep)
195{
196    if (stringRep == nullptr && m_style == Style::Default)
197    {
198        return kNullHandle;
199    }
200    return add(StringRepresentation::asSlice(stringRep));
201}
202
203StringSlicePool::Handle StringSlicePool::add(const char* chars)
204{
205    switch (m_style)
206    {
207    case Style::Default:
208        {
209            if (!chars)
210            {
211                return kNullHandle;
212            }
213            if (chars[0] == 0)
214            {
215                return kEmptyHandle;
216            }
217            break;
218        }
219    case Style::Empty:
220        {
221            if (chars == nullptr)
222            {
223                SLANG_ASSERT(!"Empty style doesn't support nullptr");
224                // Return an invalid handle
225                return Handle(~HandleIntegral(0));
226            }
227        }
228    }
229
230    return add(UnownedStringSlice(chars));
231}
232
233Index StringSlicePool::findIndex(const Slice& slice) const
234{
235    const Handle* handlePtr = m_map.tryGetValue(slice);
236    return handlePtr ? Index(*handlePtr) : -1;
237}
238
239ConstArrayView<UnownedStringSlice> StringSlicePool::getAdded() const
240{
241    const Index firstIndex = getFirstAddedIndex();
242    return makeConstArrayView(m_slices.getBuffer() + firstIndex, m_slices.getCount() - firstIndex);
243}
244
245} // namespace Slang