mirror of
https://github.com/reactos/reactos.git
synced 2024-12-29 10:35:28 +00:00
9dab4509fa
svn path=/trunk/; revision=13064
274 lines
8.1 KiB
C#
274 lines
8.1 KiB
C#
using System;
|
|
using System.Collections;
|
|
using System.IO;
|
|
using System.Text;
|
|
using System.Globalization;
|
|
|
|
namespace HtmlHelp.ChmDecoding
|
|
{
|
|
/// <summary>
|
|
/// The class <c>BinaryReaderHelp</c> implements static helper methods for extracting binary data
|
|
/// from a binary reader object.
|
|
/// </summary>
|
|
internal class BinaryReaderHelp
|
|
{
|
|
/// <summary>
|
|
/// Internal helper method to extract null-terminated strings from a binary reader
|
|
/// </summary>
|
|
/// <param name="binReader">reference to the binary reader</param>
|
|
/// <param name="offset">offset in the stream</param>
|
|
/// <param name="noOffset">true if the offset value should be used</param>
|
|
/// <param name="encoder">encoder used for text encoding</param>
|
|
/// <returns>An extracted string value</returns>
|
|
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;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Internal helper method to extract a string with a specific length from the binary reader
|
|
/// </summary>
|
|
/// <param name="binReader">reference to the binary reader</param>
|
|
/// <param name="length">length of the string (number of bytes)</param>
|
|
/// <param name="offset">offset in the stream</param>
|
|
/// <param name="noOffset">true if the offset value should be used</param>
|
|
/// <param name="encoder">encoder used for text encoding</param>
|
|
/// <returns>An extracted string value</returns>
|
|
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;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Internal helper method to extract a string with a specific length from the binary reader
|
|
/// </summary>
|
|
/// <param name="binReader">reference to the binary reader</param>
|
|
/// <param name="bFoundTerminator">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.</param>
|
|
/// <param name="offset">offset in the stream</param>
|
|
/// <param name="noOffset">true if the offset value should be used</param>
|
|
/// <param name="encoder">encoder used for text encoding</param>
|
|
/// <returns>An extracted string value</returns>
|
|
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;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Internal helper method to extract a null-terminated UTF-16/UCS-2 strings from a binary reader
|
|
/// </summary>
|
|
/// <param name="binReader">reference to the binary reader</param>
|
|
/// <param name="offset">offset in the stream</param>
|
|
/// <param name="noOffset">true if the offset value should be used</param>
|
|
/// <param name="encoder">encoder used for text encoding</param>
|
|
/// <returns>An extracted string value</returns>
|
|
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;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Internal helper for reading ENCINT encoded integer values
|
|
/// </summary>
|
|
/// <param name="binReader">reference to the reader</param>
|
|
/// <returns>a long value</returns>
|
|
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;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Reads an s/r encoded value from the byte array and decodes it into an integer
|
|
/// </summary>
|
|
/// <param name="wclBits">a byte array containing all bits (contains only 0 or 1 elements)</param>
|
|
/// <param name="s">scale param for encoding</param>
|
|
/// <param name="r">root param for encoding</param>
|
|
/// <param name="nBitIndex">current index in the wclBits array</param>
|
|
/// <returns>Returns an decoded integer value.</returns>
|
|
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<q;nbits++)
|
|
{
|
|
nMask |= ( 0x01 & (int)wclBits[nBitIndex]) << (q-nbits-1);
|
|
nBitIndex++;
|
|
}
|
|
|
|
nRet = nMask;
|
|
}
|
|
else
|
|
{
|
|
q += (nPref1Cnt-1);
|
|
|
|
int nMask = 0;
|
|
int nRMaxValue = 0;
|
|
|
|
for(int nbits=0; nbits<q;nbits++)
|
|
{
|
|
nMask |= ( 0x01 & (int)wclBits[nBitIndex]) << (q-nbits-1);
|
|
nBitIndex++;
|
|
}
|
|
|
|
for(int nsv=0; nsv<r; nsv++)
|
|
{
|
|
nRMaxValue = nRMaxValue << 1;
|
|
nRMaxValue |= 0x1;
|
|
}
|
|
|
|
nRMaxValue++; // startvalue of s/r encoding with 1 prefixing '1'
|
|
|
|
nRMaxValue *= (int) Math.Pow((double)2, (double)(nPref1Cnt-1));
|
|
|
|
nRet = nRMaxValue + nMask;
|
|
}
|
|
|
|
return nRet;
|
|
}
|
|
}
|
|
}
|