yum-mirror/slang
Making it easier to work with shaders
git clone https://git.yummers.dev/yum-mirror/slang
f65d756bf
master
1#include "slang-char-encode.h" 2 3namespace Slang 4{ 5 6class Utf8CharEncoding :public CharEncoding 7{ 8public : 9typedef CharEncoding Super ; 10 11virtual void encode (const UnownedStringSlice & slice ,List < Byte >& ioBuffer )override 12 { 13ioBuffer .addRange ((const Byte * )slice .begin (),slice .getLength ()); 14 } 15virtual void decode (const Byte * bytes ,int length ,List < char >& ioChars )override 16 { 17ioChars .addRange ((const char * )bytes ,length ); 18 } 19Utf8CharEncoding () 20 :Super (CharEncodeType ::UTF8 ) 21 { 22 } 23}; 24 25class Utf32CharEncoding :public CharEncoding 26{ 27public : 28typedef CharEncoding Super ; 29 30virtual void encode (const UnownedStringSlice & slice ,List < Byte >& ioBuffer )override 31 { 32Index ptr = 0 ; 33while (ptr < slice .getLength ()) 34 { 35const Char32 codePoint = getUnicodePointFromUTF8 ( 36 [& ]()-> Byte 37 { 38if (ptr < slice .getLength ()) 39return slice [ptr ++ ]; 40else 41return '\0' ; 42 }); 43// Note: Assumes byte order is same as arch byte order 44ioBuffer .addRange ((const Byte * )& codePoint ,4 ); 45 } 46 } 47virtual void decode (const Byte * bytes ,int length ,List < char >& ioBuffer )override 48 { 49// Note: Assumes bytes is Char32 aligned 50SLANG_ASSERT ((size_t (bytes )& 3 )== 0 ); 51const Char32 * content = (const Char32 * )bytes ; 52for (int i = 0 ;i < (length >>2 );i ++ ) 53 { 54char buf [5 ]; 55int count = encodeUnicodePointToUTF8 (content [i ],buf ); 56for (int j = 0 ;j < count ;j ++ ) 57ioBuffer .addRange (buf ,count ); 58 } 59 } 60 61Utf32CharEncoding () 62 :Super (CharEncodeType ::UTF32 ) 63 { 64 } 65}; 66 67class Utf16CharEncoding :public CharEncoding // UTF16 68{ 69public : 70typedef CharEncoding Super ; 71Utf16CharEncoding (bool reverseOrder ) 72 :Super (reverseOrder ?CharEncodeType ::UTF16Reversed :CharEncodeType ::UTF16 ) 73 ,m_reverseOrder (reverseOrder ) 74 { 75 } 76virtual void encode (const UnownedStringSlice & slice ,List < Byte >& ioBuffer )override 77 { 78Index index = 0 ; 79while (index < slice .getLength ()) 80 { 81const Char32 codePoint = getUnicodePointFromUTF8 ( 82 [& ]()-> Byte 83 { 84if (index < slice .getLength ()) 85return slice [index ++ ]; 86else 87return '\0' ; 88 }); 89 90Char16 buffer [2 ]; 91int count ; 92if (!m_reverseOrder ) 93count = encodeUnicodePointToUTF16 (codePoint ,buffer ); 94else 95count = encodeUnicodePointToUTF16Reversed (codePoint ,buffer ); 96ioBuffer .addRange ((const Byte * )buffer ,count * 2 ); 97 } 98 } 99virtual void decode (const Byte * bytes ,int length ,List < char >& ioBuffer )override 100 { 101Index index = 0 ; 102while (index < length ) 103 { 104auto readByte = [& ]()-> Byte {return (index < length ) ?bytes [index ++ ] :Byte (0 ); }; 105const Char32 codePoint = m_reverseOrder ?getUnicodePointFromUTF16Reversed (readByte ) 106 :getUnicodePointFromUTF16 (readByte ); 107 108char buf [5 ]; 109int count = encodeUnicodePointToUTF8 (codePoint ,buf ); 110ioBuffer .addRange ((const char * )buf ,count ); 111 } 112 } 113 114private : 115bool m_reverseOrder = false; 116}; 117 118/* static */ CharEncodeType CharEncoding ::determineEncoding ( 119const Byte * bytes , 120size_t bytesCount , 121size_t & outOffset ) 122{ 123// TODO(JS): Assumes the bytes are suitably aligned 124 125if (bytesCount >=3 && bytes [0 ]== 0xef && bytes [1 ]== 0xbb && bytes [2 ]== 0xbf ) 126 { 127outOffset = 3 ; 128return CharEncodeType ::UTF8 ; 129 } 130else if (bytesCount >=2 ) 131 { 132Char16 c ; 133 ::memcpy (& c ,bytes ,2 ); 134 135if (c == kUTF16Header ) 136 { 137outOffset = 2 ; 138return CharEncodeType ::UTF16 ; 139 } 140else if (c == kUTF16ReversedHeader ) 141 { 142outOffset = 2 ; 143return CharEncodeType ::UTF16Reversed ; 144 } 145 146// If we don't have a 'mark' byte then we are bit stumped. We'll look for 147// null (non-terminator) bytes and assume they mean we have a 16-bit encoding 148for (size_t i = 0 ;i < (bytesCount - 1 );i += 2 ) 149 { 150#if SLANG_LITTLE_ENDIAN 151const auto low = bytes [i ]; 152const auto high = bytes [i + 1 ]; 153#else 154const auto low = bytes [i + 1 ]; 155const auto high = bytes [i ]; 156#endif 157if ((low == 0 ) ^ (high == 0 )) 158 { 159outOffset = 2 ; 160return (high == 0 ) ?CharEncodeType ::UTF16 :CharEncodeType ::UTF16Reversed ; 161 } 162 } 163 } 164 165// Assume it's UTF8 or 7 bit ascii which UTF8 is a superset of 166outOffset = 0 ; 167return CharEncodeType ::UTF8 ; 168} 169 170static Utf8CharEncoding _utf8Encoding ; 171static Utf16CharEncoding _utf16Encoding (false); 172static Utf16CharEncoding _utf16EncodingReversed (true); 173static Utf32CharEncoding _utf32Encoding ; 174 175/* static */ CharEncoding * const CharEncoding ::g_encoding [Index (CharEncodeType ::CountOf )]{ 176& _utf8Encoding ,// UTF8, 177& _utf16Encoding ,// UTF16, 178& _utf16EncodingReversed ,// UTF16Reversed, 179& _utf32Encoding ,// UTF32, 180}; 181 182CharEncoding * CharEncoding ::UTF8 = & _utf8Encoding ; 183CharEncoding * CharEncoding ::UTF16 = & _utf16Encoding ; 184CharEncoding * CharEncoding ::UTF16Reversed = & _utf16EncodingReversed ; 185CharEncoding * CharEncoding ::UTF32 = & _utf32Encoding ; 186 187/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! UTF8Util !!!!!!!!!!!!!!!!!!!!!!!!! */ 188 189/* static */ Index UTF8Util ::calcCodePointCount (const UnownedStringSlice & in ) 190{ 191Index count = 0 ; 192 193// Analyse with bytes... 194const int8_t * cur = (const int8_t * )in .begin (); 195const int8_t * const end = (const int8_t * )in .end (); 196 197while (cur < end ) 198 { 199const auto c = * cur ++ ; 200 201count ++ ; 202 203// If c < 0 it means the top bit is set... which means we have multiple bytes 204if (c < 0 ) 205 { 206// https://en.wikipedia.org/wiki/UTF-8 207// All continuation bytes contain exactly six bits from the code point.So the next six 208// bits of the code point 209/// are stored in the low order six bits of the next byte, and 10 is stored in the high 210/// order two bits to 211// mark it as a continuation byte(so 10000010). 212 213while (cur < end && (* cur & 0xc0 )== 0x80 ) 214 { 215cur ++ ; 216 } 217 } 218 } 219 220return count ; 221} 222 223Index UTF8Util ::calcUTF16CharCount (const UnownedStringSlice & in ) 224{ 225Index count = 0 ; 226Index readPtr = 0 ; 227for (;;) 228 { 229int c = getUnicodePointFromUTF8 ( 230 [& ]()-> Byte 231 { 232if (readPtr < in .getLength ()) 233return in [readPtr ++ ]; 234else 235return 0 ; 236 }); 237if (c == 0 ) 238break ; 239Char16 buffer [2 ]; 240count += encodeUnicodePointToUTF16 (c ,buffer ); 241if (readPtr >=in .getLength ()) 242break ; 243 } 244return count ; 245} 246 247}// namespace Slang