using System; using System.Collections; using System.IO; using System.Text; using System.Globalization; namespace HtmlHelp.ChmDecoding { /// /// The class BinaryReaderHelp implements static helper methods for extracting binary data /// from a binary reader object. /// internal class BinaryReaderHelp { /// /// Internal helper method to extract null-terminated strings from a binary reader /// /// reference to the binary reader /// offset in the stream /// true if the offset value should be used /// encoder used for text encoding /// An extracted string value internal static string ExtractString(ref BinaryReader binReader, int offset, bool noOffset, Encoding encoder) { string strReturn = ""; if(encoder == null) encoder = Encoding.ASCII; ArrayList nameBytes = new ArrayList(); byte curByte; if(!noOffset) binReader.BaseStream.Seek(offset, SeekOrigin.Begin); if(binReader.BaseStream.Position >= binReader.BaseStream.Length) return ""; curByte = binReader.ReadByte(); while( (curByte != (byte)0) && (binReader.BaseStream.Position < binReader.BaseStream.Length) ) { nameBytes.Add( curByte ); curByte = binReader.ReadByte(); } byte[] name = (byte[]) (nameBytes.ToArray(System.Type.GetType("System.Byte"))); strReturn = encoder.GetString(name,0,name.Length); return strReturn; } /// /// Internal helper method to extract a string with a specific length from the binary reader /// /// reference to the binary reader /// length of the string (number of bytes) /// offset in the stream /// true if the offset value should be used /// encoder used for text encoding /// An extracted string value internal static string ExtractString(ref BinaryReader binReader, int length, int offset, bool noOffset, Encoding encoder) { string strReturn = ""; if(length == 0) return ""; if(encoder == null) encoder = Encoding.ASCII; ArrayList nameBytes = new ArrayList(); byte curByte; if(!noOffset) binReader.BaseStream.Seek(offset, SeekOrigin.Begin); if(binReader.BaseStream.Position >= binReader.BaseStream.Length) return ""; curByte = binReader.ReadByte(); while( (curByte != (byte)0) && (nameBytes.Count < length) && (binReader.BaseStream.Position < binReader.BaseStream.Length) ) { nameBytes.Add( curByte ); if(nameBytes.Count < length) curByte = binReader.ReadByte(); } byte[] name = (byte[]) (nameBytes.ToArray(System.Type.GetType("System.Byte"))); strReturn = encoder.GetString(name,0,name.Length); return strReturn; } /// /// Internal helper method to extract a string with a specific length from the binary reader /// /// reference to the binary reader /// reference to a bool vairable which will receive true if the /// string terminator \0 was found. false indicates that the end of the stream was reached. /// offset in the stream /// true if the offset value should be used /// encoder used for text encoding /// An extracted string value internal static string ExtractString(ref BinaryReader binReader, ref bool bFoundTerminator, int offset, bool noOffset, Encoding encoder) { string strReturn = ""; ArrayList nameBytes = new ArrayList(); byte curByte; if(encoder == null) encoder = Encoding.ASCII; if(!noOffset) binReader.BaseStream.Seek(offset, SeekOrigin.Begin); if(binReader.BaseStream.Position >= binReader.BaseStream.Length) return ""; curByte = binReader.ReadByte(); while( (curByte != (byte)0) && (binReader.BaseStream.Position < binReader.BaseStream.Length) ) { nameBytes.Add( curByte ); curByte = binReader.ReadByte(); if( curByte == (byte)0 ) { bFoundTerminator = true; } } byte[] name = (byte[]) (nameBytes.ToArray(System.Type.GetType("System.Byte"))); strReturn = encoder.GetString(name,0,name.Length); return strReturn; } /// /// Internal helper method to extract a null-terminated UTF-16/UCS-2 strings from a binary reader /// /// reference to the binary reader /// offset in the stream /// true if the offset value should be used /// encoder used for text encoding /// An extracted string value internal static string ExtractUTF16String(ref BinaryReader binReader, int offset, bool noOffset, Encoding encoder) { string strReturn = ""; ArrayList nameBytes = new ArrayList(); byte curByte; int lastByte=-1; if(!noOffset) binReader.BaseStream.Seek(offset, SeekOrigin.Begin); if(binReader.BaseStream.Position >= binReader.BaseStream.Length) return ""; if(encoder == null) encoder = Encoding.Unicode; curByte = binReader.ReadByte(); int nCnt = 0; while( ((curByte != (byte)0) || (lastByte != 0) ) && (binReader.BaseStream.Position < binReader.BaseStream.Length) ) { nameBytes.Add( curByte ); if(nCnt%2 == 0) lastByte = (int)curByte; curByte = binReader.ReadByte(); nCnt++; } byte[] name = (byte[]) (nameBytes.ToArray(System.Type.GetType("System.Byte"))); strReturn = Encoding.Unicode.GetString(name,0,name.Length); // apply text encoding name = Encoding.Default.GetBytes(strReturn); strReturn = encoder.GetString(name,0,name.Length); return strReturn; } /// /// Internal helper for reading ENCINT encoded integer values /// /// reference to the reader /// a long value internal static long ReadENCINT(ref BinaryReader binReader) { long nRet = 0; byte buffer = 0; int shift = 0; if(binReader.BaseStream.Position >= binReader.BaseStream.Length) return nRet; do { buffer = binReader.ReadByte(); nRet |= ((long)((buffer & (byte)0x7F))) << shift; shift += 7; }while ( (buffer & (byte)0x80) != 0); return nRet; } /// /// Reads an s/r encoded value from the byte array and decodes it into an integer /// /// a byte array containing all bits (contains only 0 or 1 elements) /// scale param for encoding /// root param for encoding /// current index in the wclBits array /// Returns an decoded integer value. internal static int ReadSRItem(byte[] wclBits, int s, int r, ref int nBitIndex) { int nRet = 0; int q = r; int nPref1Cnt = 0; while( wclBits[nBitIndex++] == 1) { nPref1Cnt++; } if(nPref1Cnt == 0) { int nMask = 0; for(int nbits=0; nbits