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
5.9 KiB217 linesraw
1#ifndef SLANG_CORE_CHAR_ENCODE_H
2#define SLANG_CORE_CHAR_ENCODE_H
3
4#include "slang-basic.h"
5#include "slang-secure-crt.h"
6
7namespace Slang
8{
9
10// NOTE! Order must be kept the same to match up with
11enum class CharEncodeType
12{
13    UTF8,
14    UTF16,
15    UTF16Reversed,
16    UTF32,
17    CountOf,
18};
19
20template<typename ReadByteFunc>
21Char32 getUnicodePointFromUTF8(const ReadByteFunc& readByte)
22{
23    Char32 codePoint = 0;
24    uint32_t leading = uint32_t(readByte());
25    uint32_t mask = 0x80;
26    Index count = 0;
27    while (leading & mask)
28    {
29        count++;
30        mask >>= 1;
31    }
32    codePoint = (leading & (mask - 1));
33    for (Index i = 1; i <= count - 1; i++)
34    {
35        codePoint <<= 6;
36        codePoint += (readByte() & 0x3F);
37    }
38    return codePoint;
39}
40
41template<typename ReadByteFunc>
42Char32 getUnicodePointFromUTF16(const ReadByteFunc& readByte)
43{
44    uint32_t byte0 = Byte(readByte());
45    uint32_t byte1 = Byte(readByte());
46    uint32_t word0 = byte0 + (byte1 << 8);
47    if (word0 >= 0xD800 && word0 <= 0xDFFF)
48    {
49        uint32_t byte2 = Byte(readByte());
50        uint32_t byte3 = Byte(readByte());
51        uint32_t word1 = byte2 + (byte3 << 8);
52        return Char32(((word0 & 0x3FF) << 10) + (word1 & 0x3FF) + 0x10000);
53    }
54    else
55        return Char32(word0);
56}
57
58template<typename ReadByteFunc>
59Char32 getUnicodePointFromUTF16Reversed(const ReadByteFunc& readByte)
60{
61    uint32_t byte0 = Byte(readByte());
62    uint32_t byte1 = Byte(readByte());
63    uint32_t word0 = (byte0 << 8) + byte1;
64    if (word0 >= 0xD800 && word0 <= 0xDFFF)
65    {
66        uint32_t byte2 = Byte(readByte());
67        uint32_t byte3 = Byte(readByte());
68        uint32_t word1 = (byte2 << 8) + byte3;
69        return Char32(((word0 & 0x3FF) << 10) + (word1 & 0x3FF));
70    }
71    else
72        return Char32(word0);
73}
74
75template<typename ReadByteFunc>
76Char32 getUnicodePointFromUTF32(const ReadByteFunc& readByte)
77{
78    uint32_t byte0 = Byte(readByte());
79    uint32_t byte1 = Byte(readByte());
80    uint32_t byte2 = Byte(readByte());
81    uint32_t byte3 = Byte(readByte());
82    return Char32(byte0 + (byte1 << 8) + (byte2 << 16) + (byte3 << 24));
83}
84
85// Encode functions return the amount of elements output to the buffer
86inline int encodeUnicodePointToUTF8(Char32 codePoint, char* outBuffer)
87{
88    char* const dst = outBuffer;
89    // TODO(JS): This supports 4 + 6 * 3 = 22 bits.
90    // The standard allows up to 0x10FFFF.
91    if (codePoint <= 0x7F)
92    {
93        dst[0] = char(codePoint);
94        return 1;
95    }
96    else if (codePoint <= 0x7FF)
97    {
98        dst[0] = char(0xC0 + (codePoint >> 6));
99        dst[1] = char(0x80 + (codePoint & 0x3F));
100        return 2;
101    }
102    else if (codePoint <= 0xFFFF)
103    {
104        dst[0] = char(0xE0 + (codePoint >> 12));
105        dst[1] = char(0x80 + ((codePoint >> 6) & (0x3F)));
106        dst[2] = char(0x80 + (codePoint & 0x3F));
107        return 3;
108    }
109    else
110    {
111        dst[0] = char(0xF0 + (codePoint >> 18));
112        dst[1] = char(0x80 + ((codePoint >> 12) & 0x3F));
113        dst[2] = char(0x80 + ((codePoint >> 6) & 0x3F));
114        dst[3] = char(0x80 + (codePoint & 0x3F));
115        return 4;
116    }
117}
118
119inline int encodeUnicodePointToUTF16(Char32 codePoint, Char16* outBuffer)
120{
121    Char16* const dst = outBuffer;
122    if (codePoint <= 0xD7FF || (codePoint >= 0xE000 && codePoint <= 0xFFFF))
123    {
124        dst[0] = Char16(codePoint);
125        return 1;
126    }
127    else
128    {
129        const uint32_t sub = codePoint - 0x10000;
130        dst[0] = Char16((sub >> 10) + 0xD800);
131        dst[1] = Char16((sub & 0x3FF) + 0xDC00);
132        return 2;
133    }
134}
135
136SLANG_FORCE_INLINE Char16 reverseByteOrder(Char16 val)
137{
138    return (val >> 8) | (val << 8);
139}
140
141inline int encodeUnicodePointToUTF16Reversed(Char32 codePoint, Char16* outBuffer)
142{
143    Char16* const dst = outBuffer;
144    if (codePoint <= 0xD7FF || (codePoint >= 0xE000 && codePoint <= 0xFFFF))
145    {
146        dst[0] = reverseByteOrder(Char16(codePoint));
147        return 1;
148    }
149    else
150    {
151        const uint32_t sub = codePoint - 0x10000;
152        const uint32_t high = (sub >> 10) + 0xD800;
153        const uint32_t low = (sub & 0x3FF) + 0xDC00;
154        dst[0] = reverseByteOrder(Char16(high));
155        dst[1] = reverseByteOrder(Char16(low));
156        return 2;
157    }
158}
159
160static const Char16 kUTF16Header = 0xFEFF;
161static const Char16 kUTF16ReversedHeader = 0xFFFE;
162
163class CharEncoding
164{
165public:
166    static CharEncoding *UTF8, *UTF16, *UTF16Reversed, *UTF32;
167
168    /// Encode Utf8 held in slice append into ioBuffer
169    virtual void encode(const UnownedStringSlice& str, List<Byte>& ioBuffer) = 0;
170    /// Decode buffer into Utf8 held in ioBuffer
171    virtual void decode(const Byte* buffer, int length, List<char>& ioBuffer) = 0;
172
173    virtual ~CharEncoding() {}
174
175    /// Get the encoding type
176    CharEncodeType getEncodingType() const { return m_encodingType; }
177
178    /// Given some bytes determines a character encoding type, based on the initial bytes.
179    /// If can't be determined will assume UTF8.
180    /// Outputs the offset to the first non mark in outOffset
181    static CharEncodeType determineEncoding(
182        const Byte* bytes,
183        size_t bytesCount,
184        size_t& outOffset);
185
186    /// Get the
187    static CharEncoding* getEncoding(CharEncodeType type) { return g_encoding[Index(type)]; }
188
189    CharEncoding(CharEncodeType encodingType)
190        : m_encodingType(encodingType)
191    {
192    }
193
194protected:
195    CharEncodeType m_encodingType;
196
197    static CharEncoding* const g_encoding[Index(CharEncodeType::CountOf)];
198};
199
200struct UTF8Util
201{
202    /// Given a slice calculate the number of code points (unicode chars)
203    ///
204    /// NOTE! This doesn't check the *validity* of code points/encoding.
205    /// Non valid utf8 input or ending starting in partial characters, will produce
206    /// undefined results without error.
207    static Index calcCodePointCount(const UnownedStringSlice& in);
208
209
210    /// Given a slice in UTF8, calculate the number of UTF16 characters needed to represent the
211    /// string.
212    static Index calcUTF16CharCount(const UnownedStringSlice& in);
213};
214
215} // namespace Slang
216
217#endif