(ReadCString): support UTF-16 encoding.

This commit is contained in:
morkt 2023-09-14 19:07:00 +04:00
parent 3a11f5fc7a
commit a49710e366
3 changed files with 41 additions and 14 deletions

View File

@ -42,6 +42,13 @@ namespace GameRes
encoding.DecoderFallback = DecoderFallback.ExceptionFallback;
return encoding;
}
public static bool IsUtf16 (this Encoding enc)
{
// enc.WindowsCodePage property might throw an exception for some encodings, while
// CodePage is just a direct field access.
return (enc.CodePage == 1200 || enc.CodePage == 1201); // enc is UnicodeEncoding
}
}
public static class StreamExtension
@ -440,9 +447,7 @@ namespace GameRes
{
byte* s = m_mem + (offset - m_offset);
uint string_length = 0;
// enc.WindowsCodePage property might throw an exception for some encodings, while
// CodePage is just a direct field access.
if (enc.CodePage == 1200 || enc.CodePage == 1201) // for UTF-16 encodings stop marker is 2-bytes long
if (enc.IsUtf16()) // for UTF-16 encodings stop marker is 2-bytes long
{
ushort* u = (ushort*)s;
while (string_length + 1 < size && 0 != u[string_length >> 1])

View File

@ -589,14 +589,13 @@ namespace GameRes
public string ReadCString (int length, Encoding enc)
{
length = Math.Min (length, m_length - m_position);
int start = m_start+m_position;
int i = Array.IndexOf<byte> (m_source, 0, start, length);
if (-1 == i)
i = start+length;
string s = enc.GetString (m_source, start, i-start);
length = Math.Min (length, m_length - m_position);
int eos_pos = FindEoS (start, length, enc);
if (-1 == eos_pos)
eos_pos = start+length;
m_position += length;
return s;
return enc.GetString (m_source, start, eos_pos-start);
}
public string ReadCString ()
@ -607,17 +606,19 @@ namespace GameRes
public string ReadCString (Encoding enc)
{
int start = m_start+m_position;
int eos_pos = Array.IndexOf<byte> (m_source, 0, start, m_length-m_position);
int length = m_length-m_position;
int eos_pos = FindEoS (start, length, enc);
int count;
if (-1 == eos_pos)
{
count = m_length - m_position;
count = length;
m_position = m_length;
}
else
{
count = eos_pos - start;
m_position += count + 1;
int eos_size = enc.IsUtf16() ? 2 : 1;
m_position += count + eos_size;
}
return enc.GetString (m_source, start, count);
}
@ -631,6 +632,27 @@ namespace GameRes
return buffer;
}
internal int FindEoS (int start, int length, Encoding enc)
{
int eos_pos = -1;
if (enc.IsUtf16())
{
for (int i = start+1; i < start+length; i += 2)
{
if (m_source[i-1] == 0 && m_source[i] == 0)
{
eos_pos = i - 1;
break;
}
}
}
else
{
eos_pos = Array.IndexOf<byte> (m_source, 0, start, length);
}
return eos_pos;
}
#region IO.Stream Members
public override bool CanRead { get { return true; } }
public override bool CanSeek { get { return true; } }

View File

@ -32,5 +32,5 @@ using System.Runtime.InteropServices;
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion ("1.0.10.207")]
[assembly: AssemblyFileVersion ("1.0.10.207")]
[assembly: AssemblyVersion ("1.0.10.208")]
[assembly: AssemblyFileVersion ("1.0.10.208")]