/// <summary> /// Writes the <paramref name="value"/> to the <see cref="CurrentStream"/>. /// </summary> /// <param name="value">The value to be written.</param> public void WriteFourCharacterCode(FourCharacterCode value) { if (value != null) { value.WriteTo(this.CurrentStream); } }
public static FourCharacterCode ReadFrom(Stream stream) { Contract.Requires(stream != null); Contract.Requires(stream.CanRead); Contract.Ensures(Contract.Result <FourCharacterCode>() != null); Check.IfArgumentNull(stream, "stream"); if (!stream.CanRead) { throw new ArgumentException("The stream does not support reading.", "stream"); } var fourCC = new FourCharacterCode(); fourCC.fourCC = new byte[4]; int bytesRead = stream.Read(fourCC.fourCC, 0, 4); if (bytesRead < 4) { throw new EndOfStreamException(); } return(fourCC); }
/// <summary> /// Creates and fill the data members of the runtime object for the specified <paramref name="chunkId"/>. /// </summary> /// <param name="stream">Must not be null.</param> /// <param name="chunkId">Must not be null.</param> /// <returns>Returns null when no runtime chunk type could be found for the <paramref name="chunkId"/>.</returns> /// <remarks>Note that chunks (types) are never mixed content. They are either containing other chunks /// or the contain data. This method is for reading sub chunks. /// Use the <see cref="M:ReadRuntimteChunkType"/> to read data.</remarks> public object ReadRuntimeContainerChunkType(Stream stream, FourCharacterCode chunkId) { Check.IfArgumentNull(stream, nameof(stream)); Check.IfArgumentNull(chunkId, nameof(chunkId)); var runtimeObject = _chunkTypeFactory.CreateChunkObject(chunkId); if (runtimeObject != null) { var writer = new ObjectMemberWriter(runtimeObject); // read all of the stream while (stream.Position < stream.Length) { object runtimeChildObj = ReadNextChunk(stream); // if null means there was no runtime type found. if (runtimeChildObj != null) { // if returns false means can't find member if (!writer.WriteChunkObject(runtimeChildObj)) { // TODO: Log? // just keep reading the stream... } } } } return(runtimeObject); }
public IFileChunkHandler GetChunkHandler(FourCharacterCode chunkId) { Contract.Requires(chunkId != null); Contract.Ensures(Contract.Result <IFileChunkHandler>() != null); Check.IfArgumentNull(chunkId, "chunkId"); return(GetChunkHandler(chunkId.ToString())); }
/// <summary> /// Reads a four character code. /// </summary> /// <returns>Returns the code read. Never returns null.</returns> public FourCharacterCode ReadFourCharacterCode() { Contract.Ensures(Contract.Result <FourCharacterCode>() != null); var stream = this.CurrentStream; return(FourCharacterCode.ReadFrom(stream)); }
/// <summary> /// Pushes a new initialized header onto the stack. /// </summary> /// <param name="chunkId">Must not be null.</param> /// <returns>Returns the header object. Never returns null.</returns> private FileChunkHeader PushNewHeader(FourCharacterCode chunkId) { var header = new FileChunkHeader(); header.DataStream = new MemoryStream(); header.ChunkId = chunkId; this.context.HeaderStack.Push(header); return(header); }
/// <summary> /// Retrieves the <see cref="FileChunkHandlerAttribute"/> and initializes the <see cref="P:ChunkId"/> property. /// </summary> protected FileChunkHandler() { var attrs = GetType().GetCustomAttributes(typeof(FileChunkHandlerAttribute), true); if (attrs == null || attrs.Length == 0) { throw new InvalidOperationException( "A File Chunk Handler derived class must be marked with the FileChunkHandlerExportAttribute."); } ChunkId = new FourCharacterCode(((FileChunkHandlerAttribute)attrs[0]).ChunkId); }
public FileChunkHeader WriteNextChunk(object chunk) { Contract.Requires(chunk != null); Check.IfArgumentNull(chunk, "chunk"); // find chunk id var chunkId = ChunkAttribute.GetChunkId(chunk); if (String.IsNullOrEmpty(chunkId)) { var msg = String.Format( CultureInfo.InvariantCulture, "No Chunk Attribute was found for the specified runtime object of type '{0}'.", chunk.GetType().FullName); throw new ArgumentException(msg); } if (chunkId.HasWildcard()) { // TODO: this must be pluggable in some way // for now only digits chunkId = chunkId.Merge("0000"); } var chunkTypeId = new FourCharacterCode(chunkId); var chunkHandler = this.handlerMgr.GetChunkHandler(chunkTypeId); if (!chunkHandler.CanWrite(chunk)) { var msg = String.Format( CultureInfo.InvariantCulture, "The chunk handler '{0}' cannot write the specified runtime object.", chunkHandler.ChunkId); throw new ArgumentException(msg); } int stackPos = this.context.HeaderStack.Count; var header = this.PushNewHeader(chunkTypeId); chunkHandler.Write(this.context, chunk); // wind down the stack to the level it was before we started. while (this.context.HeaderStack.Count > stackPos) { var poppedHeader = this.PopHeader(); this.WriteChunkHeader(poppedHeader); } return(header); }
/// <summary> /// Creates and fill the data members of the runtime object for the specified <paramref name="chunkId"/>. /// </summary> /// <param name="stream">Must not be null.</param> /// <param name="chunkId">Must not be null.</param> /// <returns>Returns null when no runtime chunk type could be found for the <paramref name="chunkId"/>.</returns> /// <remarks>Note that chunks (types) are never mixed content. They are either containing other chunks /// or the contain data. This method is for reading data. /// Use the <see cref="M:ReadRuntimteContainerChunkType"/> to read sub chunks.</remarks> public object ReadRuntimeChunkType(Stream stream, FourCharacterCode chunkId) { Check.IfArgumentNull(stream, nameof(stream)); Check.IfArgumentNull(chunkId, nameof(chunkId)); var runtimeObject = _chunkTypeFactory.CreateChunkObject(chunkId); if (runtimeObject != null) { var writer = new ObjectMemberWriter(runtimeObject); writer.ReadFields(this); } return(runtimeObject); }
/// <summary> /// Creates and fill the data members of the runtime object for the specified <paramref name="chunkId"/>. /// </summary> /// <param name="stream">Must not be null.</param> /// <param name="chunkId">Must not be null.</param> /// <returns>Returns null when no runtime chunk type could be found for the <paramref name="chunkId"/>.</returns> /// <remarks>Note that chunks (types) are never mixed content. They are either containing other chunks /// or the contain data. This method is for reading data. /// Use the <see cref="M:ReadRuntimteContainerChunkType"/> to read sub chunks.</remarks> public object ReadRuntimeChunkType(Stream stream, FourCharacterCode chunkId) { Contract.Requires(stream != null); Contract.Requires(chunkId != null); Check.IfArgumentNull(stream, "stream"); Check.IfArgumentNull(chunkId, "chunkId"); var runtimeObject = this.chunkTypeFactory.CreateChunkObject(chunkId); if (runtimeObject != null) { var writer = new ObjectMemberWriter(runtimeObject); writer.ReadFields(this); } return(runtimeObject); }
public FileChunk ReadChunkHeader(Stream stream) { Contract.Requires(stream != null); Check.IfArgumentNull(stream, "stream"); if (this.ValidateStreamPosition(8)) { var chunk = new FileChunk(); chunk.ChunkId = FourCharacterCode.ReadFrom(stream); chunk.DataLength = this.numberReader.ReadUInt32AsInt64(stream); chunk.ParentPosition = stream.Position; chunk.FilePosition = this.context.ChunkFile.BaseStream.Position; chunk.DataStream = new SubStream(stream, chunk.DataLength); return(chunk); } return(null); }
/// <summary> /// Reads the first (header) fields of a chunk from the <paramref name="stream"/>. /// </summary> /// <param name="stream">Must not be null.</param> /// <returns>Returns null when the stream position does not allow to read the header.</returns> /// <remarks>The following properties are set on the returned <see cref="FileChunk"/>. /// <see cref="P:FileChunk.ChunkId"/>, <see cref="P:FileChunk.DataLength"/>, /// <see cref="P:FileChunk.ParentPosition"/>, <see cref="P:FileChunk.FilePosition"/> /// and <see cref="P:FileChunk.DataStream"/>.</remarks> public FileChunk ReadChunkHeader(Stream stream) { Check.IfArgumentNull(stream, nameof(stream)); if (ValidateStreamPosition(8)) { var chunk = new FileChunk { ChunkId = FourCharacterCode.ReadFrom(stream), DataLength = _numberReader.ReadUInt32AsInt64(stream), ParentPosition = stream.Position, FilePosition = Context.ChunkFile.BaseStream.Position }; chunk.DataStream = new SubStream(stream, chunk.DataLength); return(chunk); } return(null); }
/// <summary> /// Reads a four character code from the <paramref name="stream"/>. /// </summary> /// <param name="stream">Must not be null.</param> /// <returns>Never return null.</returns> public static FourCharacterCode ReadFrom(Stream stream) { Check.IfArgumentNull(stream, nameof(stream)); if (!stream.CanRead) { throw new ArgumentException("The stream does not support reading.", nameof(stream)); } var fourCC = new FourCharacterCode { _fourCC = new byte[4] }; int bytesRead = stream.Read(fourCC._fourCC, 0, 4); if (bytesRead < 4) { throw new EndOfStreamException(); } return(fourCC); }
/// <summary> /// Reads a four character code. /// </summary> /// <returns>Returns the code read. Never returns null.</returns> public FourCharacterCode ReadFourCharacterCode() { var stream = CurrentStream; return(FourCharacterCode.ReadFrom(stream)); }
/// <summary> /// Retrieves a handler for the specified <paramref name="chunkId"/>. /// </summary> /// <param name="chunkId">Must not be null.</param> /// <returns>Never returns null.</returns> /// <remarks>If no specific chunk handler could be found, the default handler is returned.</remarks> public IFileChunkHandler GetChunkHandler(FourCharacterCode chunkId) { Check.IfArgumentNull(chunkId, nameof(chunkId)); return(GetChunkHandler(chunkId.ToString())); }