// PROCESS CHUNKS private static void ProcessChunks(SequentialReader reader, long maxPosition, IRiffHandler handler) { // Processing chunks. Each chunk is 8 bytes header (4 bytes CC code + 4 bytes length of chunk) + data of the chunk while (reader.Position < maxPosition - 8) { string chunkFourCc = reader.GetString(4, Encoding.ASCII); int chunkSize = reader.GetInt32(); // NOTE we fail a negative chunk size here (greater than 0x7FFFFFFF) as we cannot allocate arrays larger than this if (chunkSize < 0 || chunkSize + reader.Position > maxPosition) { throw new RiffProcessingException("Invalid RIFF chunk size"); } if (chunkFourCc == "LIST" || chunkFourCc == "RIFF") { string listName = reader.GetString(4, Encoding.ASCII); if (handler.ShouldAcceptList(listName)) { ProcessChunks(reader, reader.Position + chunkSize - 4, handler); } else { reader.Skip(chunkSize - 4); } } else { if (handler.ShouldAcceptChunk(chunkFourCc)) { // TODO is it feasible to avoid copying the chunk here, and to pass the sequential reader to the handler? handler.ProcessChunk(chunkFourCc, reader.GetBytes(chunkSize)); } else { reader.Skip(chunkSize); } // Skip any padding byte added to keep chunks aligned to even numbers of bytes if (chunkSize % 2 == 1) { reader.Skip(1); } } } }
// PROCESS CHUNKS public void ProcessChunks([NotNull] SequentialReader reader, int sizeLeft, [NotNull] IRiffHandler handler) { // Processing chunks. Each chunk is 8 bytes header (4 bytes CC code + 4 bytes length of chunk) + data of the chunk while (reader.Position < sizeLeft) { // Check if end of the file is closer then 8 bytes if (reader.IsCloserToEnd(8)) { return; } string chunkFourCc = reader.GetString(4, Encoding.ASCII); int chunkSize = reader.GetInt32(); sizeLeft -= 8; // NOTE we fail a negative chunk size here (greater than 0x7FFFFFFF) as we cannot allocate arrays larger than this if (chunkSize < 0 || sizeLeft < chunkSize) { throw new RiffProcessingException("Invalid RIFF chunk size"); } // Check if end of the file is closer then chunkSize bytes if (reader.IsCloserToEnd(chunkSize)) { return; } if (chunkFourCc == "LIST" || chunkFourCc == "RIFF") { string listName = reader.GetString(4, Encoding.ASCII); if (handler.ShouldAcceptList(listName)) { ProcessChunks(reader, sizeLeft - 4, handler); } else { reader.Skip(sizeLeft - 4); } sizeLeft -= chunkSize; } else { if (handler.ShouldAcceptChunk(chunkFourCc)) { // TODO is it feasible to avoid copying the chunk here, and to pass the sequential reader to the handler? handler.ProcessChunk(chunkFourCc, reader.GetBytes(chunkSize)); } else { reader.Skip(chunkSize); } sizeLeft -= chunkSize; // Skip any padding byte added to keep chunks aligned to even numbers of bytes if (chunkSize % 2 == 1) { reader.GetSByte(); sizeLeft--; } } } }