private int PushChunkWrite(uint type, uint id, uint size) { ContextNode cn; int err; uint parentType; Chunk chunk; SmallChunk smallChunk; bool firstChunk; byte[] buffer; if ((cn = GetCurrentContext()) != null) { parentType = cn.Type; firstChunk = false; } else if (_newIO) { parentType = 0; firstChunk = true; _newIO = false; /* first chunk must be FORM, CAT, or LIST */ if ((id != GenericChunkIds.ID_FORM) && (id != GenericChunkIds.ID_CAT) && (id != GenericChunkIds.ID_LIST)) { return((int)ParserStatus.NotIFF); } } else { return((int)ParserStatus.EndOfFile); } if (!IdUtility.IsGoodId(id)) { return((int)ParserStatus.SyntaxError); } if (IdUtility.IsGenericId(id)) { if (id == GenericChunkIds.ID_PROP) { /* the containing context for PROP must be a LIST */ if (cn.Id != GenericChunkIds.ID_LIST) { return((int)ParserStatus.SyntaxError); } } /* Generic ID. Check the validity of its subtype. */ if (!IdUtility.IsGoodType(type)) { return((int)ParserStatus.NotIFF); } } else { /* Non-generic ID. Containing context must be PROP or FORM or container */ if ((cn.Id != GenericChunkIds.ID_FORM) && (cn.Id != GenericChunkIds.ID_PROP) && (!IsContainerId(cn.Id))) { return((int)ParserStatus.SyntaxError); } } /* Write the chunk header: ID and size (if IFF_SIZE_UNKNOWN, it will * be patched later by PopChunkW()). */ if ((size >= (uint)ChunkSize.Reserved) && (size != (uint)ChunkSize.Unknown32Bit)) { chunk.Id = id; chunk.Filler = (uint)ChunkSize.Known64Bit; chunk.Size = size; buffer = Marshal.StructToBytes(chunk); if (firstChunk) { err = _streamOperations.Write(_ioContext, buffer, 0, buffer.Length); } else { /* Update parent's count of bytes written. */ err = WriteChunkInternal(cn, buffer, 0, buffer.Length); } } else { smallChunk.Id = id; smallChunk.Size = size; buffer = Marshal.StructToBytes(smallChunk); if (firstChunk) { err = _streamOperations.Write(_ioContext, buffer, 0, buffer.Length); } else { /* Update parent's count of bytes written. */ err = WriteChunkInternal(cn, buffer, 0, buffer.Length); } } if (err < 0) { return(err); } /* Allocate and fill in a ContextNode for the new chunk */ cn = new ContextNode(id, 0); cn.Size = size; cn.Offset = 0; cn.CurrentSize = 0; _stack.AddHead(cn); /* For generic chunks, write the type out now that * the chunk context node is initialized. */ if (IdUtility.IsGenericId(id) || IsContainerId(id)) { if (IdUtility.IsGenericId(id)) { var bigEndianType = type; Swap(ref bigEndianType); buffer = BitConverter.GetBytes(bigEndianType); err = WriteChunkInternal(cn, buffer, 0, buffer.Length); cn.Type = type; } else { cn.Type = 0; } } else { cn.Type = parentType; } return(err); }
private int PushChunkRead(bool firstChunk) { Chunk chunk; int err; byte[] buffer; var top = GetCurrentContext(); if (top == null && !firstChunk) { return((int)ParserStatus.EndOfFile); } var type = top != null ? top.Type : 0; if (firstChunk) { buffer = new byte[Marshal.SizeOf <SmallChunk>()]; err = _streamOperations.Read(_ioContext, buffer, 0, buffer.Length); if (err != Marshal.SizeOf <SmallChunk>()) { if (err >= 0) { err = (int)ParserStatus.NotIFF; } return(err); } var smallChunk = Marshal.BytesToStruct <SmallChunk>(buffer); chunk.Id = smallChunk.Id; chunk.Size = smallChunk.Size; if (chunk.Size == (ulong)ChunkSize.Known64Bit) { buffer = new byte[chunk.Size]; err = _streamOperations.Read(_ioContext, buffer, 0, buffer.Length); if ((ulong)err != chunk.Size) { if (err >= 0) { err = (int)ParserStatus.NotIFF; } return(err); } chunk.Size = BitConverter.ToUInt32(buffer, 0); } else if (chunk.Size >= (ulong)ChunkSize.Reserved) { return((int)ParserStatus.Mangled); } } else { /* Using ReadChunk() causes these bytes to go into the * parent's scan count */ buffer = new byte[Marshal.SizeOf <SmallChunk>()]; err = ReadChunk(buffer, 0, buffer.Length); if (err != Marshal.SizeOf <SmallChunk>()) { if (err >= 0) { err = (int)ParserStatus.PrematureEndOfFile; } return(err); } var smallChunk = Marshal.BytesToStruct <SmallChunk>(buffer); chunk.Id = smallChunk.Id; chunk.Size = smallChunk.Size; if (chunk.Size == (ulong)ChunkSize.Known64Bit) { buffer = new byte[chunk.Size]; err = _streamOperations.Read(_ioContext, buffer, 0, buffer.Length); if ((ulong)err != chunk.Size) { if (err >= 0) { err = (int)ParserStatus.NotIFF; } return(err); } chunk.Size = BitConverter.ToUInt32(buffer, 0); } else if (chunk.Size >= (ulong)ChunkSize.Reserved) { return((int)ParserStatus.Mangled); } if (chunk.Size > (top.Size - top.Offset)) { return((int)ParserStatus.Mangled); } } if (IdUtility.IsGoodId(chunk.Id)) { try { var contextNode = new ContextNode(chunk.Id, type); contextNode.Size = chunk.Size; contextNode.Offset = 0; contextNode.CurrentSize = chunk.Size; _stack.AddHead(contextNode); return(0); } catch (OutOfMemoryException) { return((int)ParserStatus.OutOfMemory); } } if (this._newIO) { return((int)ParserStatus.NotIFF); } return((int)ParserStatus.SyntaxError); }