yum-mirror/slang

Making it easier to work with shaders

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

Ellie HermaszewskaCorrect buffer length calculation in dumpSourceBytes (#6593)1e20eed6e

master
6.9 KiB271 linesraw
1// slang-hex-dump-util.cpp
2#include "slang-hex-dump-util.h"
3
4#include "slang-char-util.h"
5#include "slang-com-helper.h"
6#include "slang-common.h"
7#include "slang-hash.h"
8#include "slang-string-util.h"
9#include "slang-writer.h"
10
11namespace Slang
12{
13
14static const UnownedStringSlice s_start = UnownedStringSlice::fromLiteral("--START--");
15static const UnownedStringSlice s_end = UnownedStringSlice::fromLiteral("--END--");
16static const char s_hex[] = "0123456789abcdef";
17
18/* static */ SlangResult HexDumpUtil::dumpWithMarkers(
19    const List<uint8_t>& data,
20    int maxBytesPerLine,
21    ISlangWriter* writer)
22{
23    return dumpWithMarkers(data.getBuffer(), data.getCount(), maxBytesPerLine, writer);
24}
25
26/* static */ SlangResult HexDumpUtil::dumpWithMarkers(
27    const uint8_t* data,
28    size_t dataCount,
29    int maxBytesPerLine,
30    ISlangWriter* writer)
31{
32    WriterHelper helper(writer);
33    SLANG_RETURN_ON_FAIL(helper.write(s_start.begin(), s_start.getLength()));
34    SLANG_RETURN_ON_FAIL(helper.print(" %zu", dataCount));
35
36    const StableHashCode32 hash = getStableHashCode32((const char*)data, dataCount);
37    SLANG_RETURN_ON_FAIL(helper.print(" %d\n", hash.hash));
38
39    SLANG_RETURN_ON_FAIL(dump(data, dataCount, maxBytesPerLine, writer));
40
41    SLANG_RETURN_ON_FAIL(helper.write(s_end.begin(), s_end.getLength()));
42    SLANG_RETURN_ON_FAIL(helper.put("\n"));
43    return SLANG_OK;
44}
45
46/* static */ void HexDumpUtil::dump(uint32_t value, ISlangWriter* writer)
47{
48    char c[9];
49    for (int i = 0; i < 8; ++i)
50    {
51        c[i] = s_hex[value >> 28];
52        value <<= 4;
53    }
54    writer->write(c, 8);
55}
56
57
58/* static */ SlangResult HexDumpUtil::dump(
59    const List<uint8_t>& data,
60    int maxBytesPerLine,
61    ISlangWriter* writer)
62{
63    return dump(data.getBuffer(), data.getCount(), maxBytesPerLine, writer);
64}
65
66SlangResult HexDumpUtil::dumpSourceBytes(
67    const uint8_t* data,
68    size_t dataCount,
69    int maxBytesPerLine,
70    ISlangWriter* writer)
71{
72    const uint8_t* cur = data;
73    const uint8_t* end = data + dataCount;
74
75    while (cur < end)
76    {
77        size_t count = size_t(end - cur);
78        count = (count > size_t(maxBytesPerLine)) ? size_t(maxBytesPerLine) : count;
79
80        // each byte is output as "0xAA, "
81        // Ends with '\n"
82        const size_t lineBytes = count * 6 + 1;
83
84        char* startDst = writer->beginAppendBuffer(lineBytes);
85        char* dst = startDst;
86
87        for (size_t i = 0; i < count; ++i)
88        {
89            uint8_t byte = cur[i];
90            dst[0] = '0';
91            dst[1] = 'x';
92            dst[2] = s_hex[byte >> 4];
93            dst[3] = s_hex[byte & 0xf];
94            dst[4] = ',';
95            dst[5] = ' ';
96
97            dst += 6;
98        }
99
100        *dst++ = '\n';
101
102        SLANG_RETURN_ON_FAIL(writer->endAppendBuffer(startDst, size_t(dst - startDst)));
103
104        cur += count;
105    }
106
107    return SLANG_OK;
108}
109
110/* static */ SlangResult HexDumpUtil::dump(
111    const uint8_t* data,
112    size_t dataCount,
113    int maxBytesPerLine,
114    ISlangWriter* writer)
115{
116    int maxCharsPerLine = 2 * maxBytesPerLine + 1 + maxBytesPerLine + 1;
117
118    const uint8_t* cur = data;
119    const uint8_t* end = data + dataCount;
120
121    while (cur < end)
122    {
123        size_t count = size_t(end - cur);
124        count = (count > size_t(maxBytesPerLine)) ? size_t(maxBytesPerLine) : count;
125
126        char* startDst = writer->beginAppendBuffer(maxCharsPerLine);
127        char* dst = startDst;
128
129        for (size_t i = 0; i < count; ++i)
130        {
131            uint8_t byte = cur[i];
132            *dst++ = s_hex[byte >> 4];
133            *dst++ = s_hex[byte & 0xf];
134        }
135
136        // If not a complete line write spaces
137        for (size_t i = count; i < size_t(maxBytesPerLine); ++i)
138        {
139            *dst++ = ' ';
140            *dst++ = ' ';
141        }
142
143        *dst++ = ' ';
144
145        for (size_t i = 0; i < count; ++i)
146        {
147            char c = char(cur[i]);
148
149            if ((c >= '0' && c <= '9') || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') ||
150                (c >= 32 && (c & 0x80) == 0))
151            {
152            }
153            else
154            {
155                c = '.';
156            }
157            *dst++ = c;
158        }
159
160        *dst++ = '\n';
161        SLANG_ASSERT(dst <= startDst + maxCharsPerLine);
162
163        SLANG_RETURN_ON_FAIL(writer->endAppendBuffer(startDst, size_t(dst - startDst)));
164
165        cur += count;
166    }
167
168    return SLANG_OK;
169}
170
171/* static */ SlangResult HexDumpUtil::parse(
172    const UnownedStringSlice& lines,
173    List<uint8_t>& outBytes)
174{
175    outBytes.clear();
176
177    LineParser lineParser(lines);
178    for (const auto& line : lineParser)
179    {
180        const char* cur = line.begin();
181        const char* end = line.end();
182
183        while (cur + 2 <= end)
184        {
185            const char c = cur[0];
186            if (c == ' ' || c == '\n' || c == '\r' || c == '\t')
187            {
188                // Skip to next line
189                break;
190            }
191
192            const int hi = CharUtil::getHexDigitValue(c);
193            const int lo = CharUtil::getHexDigitValue(cur[1]);
194            cur += 2;
195
196            if (hi < 0 || lo < 0)
197            {
198                return SLANG_FAIL;
199            }
200            outBytes.add(uint8_t((hi << 4) | lo));
201        }
202    }
203
204    return SLANG_OK;
205}
206
207static SlangResult _findLine(
208    const UnownedStringSlice& find,
209    UnownedStringSlice& ioRemaining,
210    UnownedStringSlice& outLine)
211{
212    // Find the start line
213    UnownedStringSlice line;
214    while (StringUtil::extractLine(ioRemaining, line))
215    {
216        if (line.startsWith(find))
217        {
218            outLine = line;
219            return SLANG_OK;
220        }
221    }
222    return SLANG_FAIL;
223}
224
225/* static */ SlangResult HexDumpUtil::findStartAndEndLines(
226    const UnownedStringSlice& lines,
227    UnownedStringSlice& outStart,
228    UnownedStringSlice& outEnd)
229{
230    UnownedStringSlice remaining(lines);
231    SLANG_RETURN_ON_FAIL(_findLine(s_start, remaining, outStart));
232    SLANG_RETURN_ON_FAIL(_findLine(s_end, remaining, outEnd));
233    return SLANG_OK;
234}
235
236/* static */ SlangResult HexDumpUtil::parseWithMarkers(
237    const UnownedStringSlice& lines,
238    List<uint8_t>& outBytes)
239{
240    UnownedStringSlice startLine, endLine;
241    SLANG_RETURN_ON_FAIL(findStartAndEndLines(lines, startLine, endLine));
242
243    StableHashCode32 hash;
244    size_t size;
245    {
246        // Get the size and the hash
247        List<UnownedStringSlice> slices;
248        StringUtil::split(startLine, ' ', slices);
249        if (slices.getCount() != 3)
250        {
251            return SLANG_FAIL;
252        }
253        // Extract the size
254        size = stringToInt(String(slices[1]));
255        hash = StableHashCode32{stringToUInt(String(slices[2]))};
256    }
257
258    SLANG_RETURN_ON_FAIL(parse(UnownedStringSlice(startLine.end(), endLine.begin()), outBytes));
259
260    // Calc the hash
261    const StableHashCode32 readHash =
262        getStableHashCode32((const char*)outBytes.begin(), outBytes.getCount());
263
264    if (readHash != hash || size_t(outBytes.getCount()) != size)
265    {
266        return SLANG_FAIL;
267    }
268    return SLANG_OK;
269}
270
271} // namespace Slang