/// <summary>
/// Read the next RIFF element invoking the correct delegate.
/// Returns true if an element can be read
/// </summary>
/// <param name="bytesleft">Reference to number of bytes left in the current list</param>
/// <param name="chunk">Method to invoke if a chunk is found</param>
/// <param name="list">Method to invoke if a list is found</param>
/// <returns></returns>
public bool ReadElement(ref int bytesleft, ProcessChunkElement chunk, ProcessListElement list)
{
// Are we done?
if (TWODWORDSSIZE > bytesleft)
{
return false;
} //Console.WriteLine(m_stream.Position.ToString() + ", " + bytesleft.ToString()); // We have enough bytes, read
int FourCC;
int size; ReadTwoInts(out FourCC, out size); // Reduce bytes left
bytesleft -= TWODWORDSSIZE; // Do we have enough bytes?
if (bytesleft < size)
{
// Skip the bad data and throw an exception
SkipData(bytesleft);
bytesleft = 0;
throw new RiffParserException("Element size mismatch for element " + FromFourCC(FourCC)
+ " need " + size.ToString() + " but have only " + bytesleft.ToString());
} // Examine the element, is it a list or a chunk
string type = FromFourCC(FourCC);
if (0 == String.Compare(type, LIST4CC))
{
// We have a list
ReadOneInt(out FourCC); if (null == list)
{
SkipData(size - 4);
}
else
{
// Invoke the list method
list(this, FourCC, size - 4);
} // Adjust size
bytesleft -= size;
}
else
{
// Calculated padded size - padded to WORD boundary
int paddedSize = size;
if (0 != (size & 1)) ++paddedSize; if (null == chunk)
{
SkipData(paddedSize);
}
else
{
chunk(this, FourCC, size, paddedSize);
} // Adjust size
bytesleft -= paddedSize;
} return true;
} #region Stream access /// <summary>
/// Non-thread-safe method to read two ints from the stream
/// </summary>
/// <param name="FourCC">Output FourCC int</param>
/// <param name="size">Output chunk/list size</param>
public unsafe void ReadTwoInts(out int FourCC, out int size)
{
try {
int readsize = m_stream.Read(m_eightBytes, 0, TWODWORDSSIZE); if (TWODWORDSSIZE != readsize) {
throw new RiffParserException("Unable to read. Corrupt RIFF file " + FileName);
} fixed (byte* bp = &m_eightBytes[0]) {
FourCC = *((int*)bp);
size = *((int*)(bp + DWORDSIZE));
}
}
catch (Exception ex)
{
throw new RiffParserException("Problem accessing RIFF file " + FileName, ex);
}
} /// <summary>
/// Non-thread-safe read a single int from the stream
/// </summary>
/// <param name="FourCC">Output int</param>
public unsafe void ReadOneInt(out int FourCC)
{
try {
int readsize = m_stream.Read(m_fourBytes, 0, DWORDSIZE); if (DWORDSIZE != readsize) {
throw new RiffParserException("Unable to read. Corrupt RIFF file " + FileName);
} fixed (byte* bp = &m_fourBytes[0]) {
FourCC = *((int*)bp);
}
}
catch (Exception ex)
{
throw new RiffParserException("Problem accessing RIFF file " + FileName, ex);
}
} /// <summary>
/// Skip the specified number of bytes
/// </summary>
/// <param name="skipBytes">Number of bytes to skip</param>
public void SkipData(int skipBytes)
{
try {
m_stream.Seek(skipBytes, SeekOrigin.Current);
}
catch (Exception ex)
{
throw new RiffParserException("Problem seeking in file " + FileName, ex);
}
} /// <summary>
/// Read the specified length into the byte array at the specified
/// offset in the array
/// </summary>
/// <param name="data">Array of bytes to read into</param>
/// <param name="offset">Offset in the array to start from</param>
/// <param name="length">Number of bytes to read</param>
/// <returns>Number of bytes actually read</returns>
public int ReadData(Byte[] data, int offset, int length)
{
try {
return m_stream.Read(data, offset, length);
}
catch (Exception ex)
{
throw new RiffParserException("Problem reading data in file " + FileName, ex);
}
} /// <summary>
/// Close the RIFF file
/// </summary>
public void CloseFile()
{
if (null != m_stream)
{
m_stream.Close();
m_stream = null;
}
} #endregion #region FourCC conversion methods public static string FromFourCC(int FourCC)
{
char[] chars = new char[4];
chars[0] = (char)(FourCC & 0xFF);
chars[1] = (char)((FourCC >> 8) & 0xFF);
chars[2] = (char)((FourCC >> 16) & 0xFF);
chars[3] = (char)((FourCC >> 24) & 0xFF); return new string(chars);
} public static int ToFourCC(string FourCC)
{
if (FourCC.Length != 4)
{
throw new Exception("FourCC strings must be 4 characters long " + FourCC);
} int result = ((int)FourCC[3]) << 24
| ((int)FourCC[2]) << 16
| ((int)FourCC[1]) << 8
| ((int)FourCC[0]); return result;
} public static int ToFourCC(char[] FourCC)
{
if (FourCC.Length != 4)
{
throw new Exception("FourCC char arrays must be 4 characters long " + new string(FourCC));
} int result = ((int)FourCC[3]) << 24
| ((int)FourCC[2]) << 16
| ((int)FourCC[1]) << 8
| ((int)FourCC[0]); return result;
} public static int ToFourCC(char c0, char c1, char c2, char c3)
{
int result = ((int)c3) << 24
| ((int)c2) << 16
| ((int)c1) << 8
| ((int)c0); return result;
}
#endregion }
}
/// Read the next RIFF element invoking the correct delegate.
/// Returns true if an element can be read
/// </summary>
/// <param name="bytesleft">Reference to number of bytes left in the current list</param>
/// <param name="chunk">Method to invoke if a chunk is found</param>
/// <param name="list">Method to invoke if a list is found</param>
/// <returns></returns>
public bool ReadElement(ref int bytesleft, ProcessChunkElement chunk, ProcessListElement list)
{
// Are we done?
if (TWODWORDSSIZE > bytesleft)
{
return false;
} //Console.WriteLine(m_stream.Position.ToString() + ", " + bytesleft.ToString()); // We have enough bytes, read
int FourCC;
int size; ReadTwoInts(out FourCC, out size); // Reduce bytes left
bytesleft -= TWODWORDSSIZE; // Do we have enough bytes?
if (bytesleft < size)
{
// Skip the bad data and throw an exception
SkipData(bytesleft);
bytesleft = 0;
throw new RiffParserException("Element size mismatch for element " + FromFourCC(FourCC)
+ " need " + size.ToString() + " but have only " + bytesleft.ToString());
} // Examine the element, is it a list or a chunk
string type = FromFourCC(FourCC);
if (0 == String.Compare(type, LIST4CC))
{
// We have a list
ReadOneInt(out FourCC); if (null == list)
{
SkipData(size - 4);
}
else
{
// Invoke the list method
list(this, FourCC, size - 4);
} // Adjust size
bytesleft -= size;
}
else
{
// Calculated padded size - padded to WORD boundary
int paddedSize = size;
if (0 != (size & 1)) ++paddedSize; if (null == chunk)
{
SkipData(paddedSize);
}
else
{
chunk(this, FourCC, size, paddedSize);
} // Adjust size
bytesleft -= paddedSize;
} return true;
} #region Stream access /// <summary>
/// Non-thread-safe method to read two ints from the stream
/// </summary>
/// <param name="FourCC">Output FourCC int</param>
/// <param name="size">Output chunk/list size</param>
public unsafe void ReadTwoInts(out int FourCC, out int size)
{
try {
int readsize = m_stream.Read(m_eightBytes, 0, TWODWORDSSIZE); if (TWODWORDSSIZE != readsize) {
throw new RiffParserException("Unable to read. Corrupt RIFF file " + FileName);
} fixed (byte* bp = &m_eightBytes[0]) {
FourCC = *((int*)bp);
size = *((int*)(bp + DWORDSIZE));
}
}
catch (Exception ex)
{
throw new RiffParserException("Problem accessing RIFF file " + FileName, ex);
}
} /// <summary>
/// Non-thread-safe read a single int from the stream
/// </summary>
/// <param name="FourCC">Output int</param>
public unsafe void ReadOneInt(out int FourCC)
{
try {
int readsize = m_stream.Read(m_fourBytes, 0, DWORDSIZE); if (DWORDSIZE != readsize) {
throw new RiffParserException("Unable to read. Corrupt RIFF file " + FileName);
} fixed (byte* bp = &m_fourBytes[0]) {
FourCC = *((int*)bp);
}
}
catch (Exception ex)
{
throw new RiffParserException("Problem accessing RIFF file " + FileName, ex);
}
} /// <summary>
/// Skip the specified number of bytes
/// </summary>
/// <param name="skipBytes">Number of bytes to skip</param>
public void SkipData(int skipBytes)
{
try {
m_stream.Seek(skipBytes, SeekOrigin.Current);
}
catch (Exception ex)
{
throw new RiffParserException("Problem seeking in file " + FileName, ex);
}
} /// <summary>
/// Read the specified length into the byte array at the specified
/// offset in the array
/// </summary>
/// <param name="data">Array of bytes to read into</param>
/// <param name="offset">Offset in the array to start from</param>
/// <param name="length">Number of bytes to read</param>
/// <returns>Number of bytes actually read</returns>
public int ReadData(Byte[] data, int offset, int length)
{
try {
return m_stream.Read(data, offset, length);
}
catch (Exception ex)
{
throw new RiffParserException("Problem reading data in file " + FileName, ex);
}
} /// <summary>
/// Close the RIFF file
/// </summary>
public void CloseFile()
{
if (null != m_stream)
{
m_stream.Close();
m_stream = null;
}
} #endregion #region FourCC conversion methods public static string FromFourCC(int FourCC)
{
char[] chars = new char[4];
chars[0] = (char)(FourCC & 0xFF);
chars[1] = (char)((FourCC >> 8) & 0xFF);
chars[2] = (char)((FourCC >> 16) & 0xFF);
chars[3] = (char)((FourCC >> 24) & 0xFF); return new string(chars);
} public static int ToFourCC(string FourCC)
{
if (FourCC.Length != 4)
{
throw new Exception("FourCC strings must be 4 characters long " + FourCC);
} int result = ((int)FourCC[3]) << 24
| ((int)FourCC[2]) << 16
| ((int)FourCC[1]) << 8
| ((int)FourCC[0]); return result;
} public static int ToFourCC(char[] FourCC)
{
if (FourCC.Length != 4)
{
throw new Exception("FourCC char arrays must be 4 characters long " + new string(FourCC));
} int result = ((int)FourCC[3]) << 24
| ((int)FourCC[2]) << 16
| ((int)FourCC[1]) << 8
| ((int)FourCC[0]); return result;
} public static int ToFourCC(char c0, char c1, char c2, char c3)
{
int result = ((int)c3) << 24
| ((int)c2) << 16
| ((int)c1) << 8
| ((int)c0); return result;
}
#endregion }
}
解决方案 »
免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货