1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146
| /// <summary>
/// Class to handle serialization of Strings in the format of a MFC <c>CArchive</c>.
/// </summary>
static class MFCStringHelper
{
/// <summary>
/// Write a string in the format of a MFC <c>CArchive</c>.
/// </summary>
/// <param name="writer">[modif] Output stream writer.</param>
/// <param name="str">[in] String to write.</param>
public static void WriteMFCString(BinaryWriter writer, String str)
{
if(writer==null)
throw new ArgumentNullException("writer");
if(str==null)
throw new ArgumentNullException("str");
AfxWriteStringLength(writer, str.Length, true);
writer.Write(str.ToCharArray());
}
/// <summary>
/// Read a string from the format of a MFC <c>archive</c>.
/// </summary>
/// <param name="reader">[in/modif] Input stream reader.</param>
/// <returns>String freshly read.</returns>
public static String ReadMFCString(BinaryReader reader)
{
if(reader==null)
throw new ArgumentNullException("reader");
int charSize;
long qwLength = AfxReadStringLength(reader, out charSize);
int length = checked((int)qwLength);
String sRet = null;
if(charSize==1)
{
//Read ANSI chars and convert
byte[] mbChars = reader.ReadBytes(length);
sRet = Encoding.Default.GetString(mbChars);
}
else
{
//Read unicode chars.
char[] wideChars = reader.ReadChars(length);
sRet = new String(wideChars);
}
Debug.Assert(sRet!=null, "The return string shall not be null at this point");
return sRet;
}
/// <summary>
/// Write a string length in the format of a MFC <c>CArchive</c>.
/// </summary>
/// <remarks>This code was converted from MFC source code file <c>arccore.cpp</c>.</remarks>
/// <param name="ar">[modif] Output stream writer.</param>
/// <param name="nLength">[in] Length to write.</param>
/// <param name="bUnicode">[in] if <c>true</c>, prepend with a "unicode" tag.</param>
static void AfxWriteStringLength(BinaryWriter ar, long nLength, bool bUnicode)
{
Debug.Assert(ar != null, "ar is an internal parameter and shall not be null");
Debug.Assert(nLength >=0, "String length shall not be negative");
if(bUnicode)
{
// Tag Unicode strings
ar.Write((Byte)0xFF);
ar.Write((UInt16)0xFFFE);
}
if(nLength < 255)
{
ar.Write((Byte)nLength);
}
else if(nLength < 0xFFFE)
{
ar.Write((Byte)0xFF);
ar.Write((UInt16)nLength);
}
else if(nLength < 0xFFFFFFFF)
{
ar.Write((Byte)0xFF);
ar.Write((UInt16)0xFFFF);
ar.Write((UInt32)nLength);
}
else
{
ar.Write((Byte)0xFF);
ar.Write((UInt16)0xFFFF);
ar.Write((UInt32)0xFFFFFFFF);
ar.Write((UInt64)nLength);
}
}
/// <summary>
/// Read a string length from the format of a MFC <c>archive</c>.
/// </summary>
/// <remarks>This code was converted from MFC source code file <c>arccore.cpp</c>.</remarks>
/// <param name="ar">[in/modif] Input stream reader.</param>
/// <param name="nCharSize">[out] Character size (1 or 2 bytes).</param>
/// <returns>String length.</returns>
static long AfxReadStringLength(BinaryReader ar, out int nCharSize)
{
Debug.Assert(ar != null, "ar is an internal parameter and shall not be null");
UInt64 qwLength;
UInt32 dwLength;
UInt16 wLength;
Byte byLength;
nCharSize = 1;
// First, try to read a one-byte length
byLength = ar.ReadByte();
if(byLength < 0xFF)
return byLength;
// Try a two-byte length
wLength = ar.ReadUInt16();
if(wLength == 0xFFFE)
{
// Unicode string. Start over at 1-byte length
nCharSize = 2;
byLength = ar.ReadByte();
if(byLength < 0xFF)
return byLength;
// Two-byte length
wLength = ar.ReadUInt16();
// Fall through to continue on same branch as ANSI string
}
if(wLength < 0xFFFF)
return wLength;
// 4-byte length
dwLength = ar.ReadUInt32();
if(dwLength < 0xFFFFFFFF)
return dwLength;
// 8-byte length
qwLength = ar.ReadUInt64();
if(qwLength > Int32.MaxValue)
throw new FormatException("String too long");
return checked((long)qwLength);
}
} |
Partager