yum-mirror/slang

Making it easier to work with shaders

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

Ellie Hermaszewskaformatf65d756bf

master
4.6 KiB199 linesraw
1// slang-offset-container.cpp
2#include "slang-offset-container.h"
3
4namespace Slang
5{
6
7/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! OffsetString !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */
8
9size_t OffsetString::calcEncodedSize(size_t size, uint8_t encode[kMaxSizeEncodeSize])
10{
11    SLANG_ASSERT(size <= 0xffffffff);
12    if (size <= kSizeBase)
13    {
14        encode[0] = uint8_t(size);
15        return 1;
16    }
17    // Encode
18    int num = 0;
19    while (size)
20    {
21        encode[num + 1] = uint8_t(size);
22        size >>= 8;
23        num++;
24    }
25
26    // It might be one byte past the front, if its < 0x100 but greater than kSizeBase
27    SLANG_ASSERT(num >= 1);
28
29    encode[0] = uint8_t(kSizeBase + num);
30    return num + 1;
31}
32
33/* static */ const char* OffsetString::decodeSize(const char* in, size_t& outSize)
34{
35    const uint8_t* cur = (const uint8_t*)in;
36    if (*cur <= kSizeBase)
37    {
38        outSize = *cur;
39        return in + 1;
40    }
41
42    int numBytes = *cur - kSizeBase;
43    switch (numBytes)
44    {
45    case 1:
46        {
47            outSize = cur[1];
48            return in + 2;
49        }
50    case 2:
51        {
52            outSize = cur[1] | (uint32_t(cur[2]) << 8);
53            return in + 3;
54        }
55    case 3:
56        {
57            outSize = cur[1] | (uint32_t(cur[2]) << 8) | (uint32_t(cur[3]) << 16);
58            return in + 4;
59        }
60    case 4:
61        {
62            outSize = cur[1] | (uint32_t(cur[2]) << 8) | (uint32_t(cur[3]) << 16) |
63                      (uint32_t(cur[4]) << 24);
64            return in + 5;
65        }
66    default:
67        {
68            outSize = 0;
69            return nullptr;
70        }
71    }
72}
73
74/* static */ size_t OffsetString::calcAllocationSize(size_t stringSize)
75{
76    uint8_t encode[kMaxSizeEncodeSize];
77    size_t encodeSize = calcEncodedSize(stringSize, encode);
78    // Add 1 for terminating 0
79    return encodeSize + stringSize + 1;
80}
81
82/* static */ size_t OffsetString::calcAllocationSize(const UnownedStringSlice& slice)
83{
84    return calcAllocationSize(slice.getLength());
85}
86
87UnownedStringSlice OffsetString::getSlice() const
88{
89    size_t size;
90    const char* chars = decodeSize(m_sizeThenContents, size);
91
92    return UnownedStringSlice(chars, size);
93}
94
95const char* OffsetString::getCstr() const
96{
97    return getSlice().begin();
98}
99
100/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! OffsetContainer !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
101 */
102
103OffsetContainer::OffsetContainer()
104{
105    m_capacity = 0;
106    m_data = nullptr;
107
108    // We need to allocate some of the first bytes 0 can be used for nullptr.
109    allocateAndZero(kStartOffset, 1);
110}
111
112OffsetContainer::~OffsetContainer()
113{
114    if (m_data)
115    {
116        ::free(m_data);
117    }
118}
119
120void* OffsetContainer::allocate(size_t size)
121{
122    return allocate(size, 1);
123}
124
125void OffsetContainer::fixAlignment(size_t alignment)
126{
127    allocate(0, alignment);
128}
129
130void* OffsetContainer::allocate(size_t size, size_t alignment)
131{
132    size_t offset = (m_dataSize + alignment - 1) & ~(alignment - 1);
133
134    if (offset + size > m_capacity)
135    {
136        const size_t minSize = offset + size;
137
138        size_t calcSize = m_capacity;
139        if (calcSize < 2048)
140        {
141            calcSize = 2048;
142        }
143        else
144        {
145            // Expand geometrically, but lets not double in size...
146            calcSize = calcSize + (calcSize / 2);
147        }
148
149        // We must be at least minSize
150        size_t newSize = (calcSize < minSize) ? minSize : calcSize;
151
152        // Reallocate space
153        m_data = (uint8_t*)::realloc(m_data, newSize);
154        m_capacity = newSize;
155    }
156
157    SLANG_ASSERT(offset + size <= m_capacity);
158
159    m_dataSize = offset + size;
160    return m_data + offset;
161}
162
163void* OffsetContainer::allocateAndZero(size_t size, size_t alignment)
164{
165    void* data = allocate(size, alignment);
166    memset(data, 0, size);
167    return data;
168}
169
170Offset32Ptr<OffsetString> OffsetContainer::newString(const UnownedStringSlice& slice)
171{
172    size_t stringSize = slice.getLength();
173
174    uint8_t head[OffsetString::kMaxSizeEncodeSize];
175    size_t headSize = OffsetString::calcEncodedSize(stringSize, head);
176
177    size_t allocSize = headSize + stringSize + 1;
178    uint8_t* bytes = (uint8_t*)allocate(allocSize);
179
180    ::memcpy(bytes, head, headSize);
181    ::memcpy(bytes + headSize, slice.begin(), stringSize);
182
183    // 0 terminate
184    bytes[headSize + stringSize] = 0;
185
186    return Offset32Ptr<OffsetString>(getOffset(bytes));
187}
188
189Offset32Ptr<OffsetString> OffsetContainer::newString(const char* contents)
190{
191    Offset32Ptr<OffsetString> relString;
192    if (contents)
193    {
194        relString = newString(UnownedStringSlice(contents));
195    }
196    return relString;
197}
198
199} // namespace Slang