public void ParseListsChunks(ContainerVisitor visitor, BinaryReader reader, long offset, long stopAt, StructInstance parent) { while (offset < stopAt) { reader.BaseStream.Seek(offset, SeekOrigin.Begin); string id = Util.ReadFourCC(reader); int size = reader.ReadInt32(); if (size % 2 != 0) { size++; } StructInstance inst = null; if (id == "LIST") // 'LIST' listSize listType listData { string listType = Util.ReadFourCC(reader); // a LIST instance is needed to maintain a list of sub LISTs and CHUNKs. StructElement listDef = _chunkDefs["LIST"]; inst = GetChunkInstance(reader, listDef, 0, parent); if (listType != "movi") { visitor.BeginVisitNode( string.Format("LIST ({0})", listType), string.Empty); ParseListsChunks(visitor, reader, reader.BaseStream.Position, offset + size + 8, inst); } else { visitor.BeginVisitNode( string.Format("LIST ({0})", listType), "Content in this list is skipped."); } offset += size + 8; } else // ckID ckSize ckData { StructElement chunkDef = _chunkDefs[id]; inst = GetChunkInstance(reader, chunkDef, size, parent); visitor.BeginVisitNode(id, GetChunkDescription(reader, id, size, inst)); offset += size + 8; } if (parent != null) { // link CHUNK to its parent LIST parent[id] = inst; } visitor.EndVisitNode(); } }
public void ParseAtoms(ContainerVisitor visitor, BinaryReader reader, long offset, long stopAt, StructInstance parent) { while (offset < stopAt) { reader.BaseStream.Seek(offset, SeekOrigin.Begin); uint atomSize = Util.EndianFlip32(reader.ReadUInt32()); string atomType = Util.ReadFourCC(reader); if (_atomDefs.ContainsKey(atomType)) { StructElement atomDef = _atomDefs[atomType]; StructInstance inst = GetAtomInstance(reader, atomDef, atomSize, parent); string desc = GetAtomDesc(atomDef, atomSize, inst); visitor.BeginVisitNode(atomType, desc); // If it is a container atom if (atomDef != null && atomDef.Elements == null) { // parse children atoms recursively ParseAtoms(visitor, reader, reader.BaseStream.Position, offset + atomSize, inst); } if (parent != null) { parent[atomType] = inst; } visitor.EndVisitNode(); } // now set offset to next atom (or end-of-file) in special case // (atomSize = 0 means atom goes to EOF) if (atomSize == 0) { offset = reader.BaseStream.Length; } else { offset += atomSize; } // if a 'udta' container atom, then jump ahead 4 to work around // Apple's QT 1.0 workaround // @see http://developer.apple.com/technotes/qt/qt_03.html if (atomType == "udta") { offset += 4; } } }
public virtual string GetChunkDescription(BinaryReader reader, string id, int chunkSize, StructInstance inst) { StructElement chunkDef = _chunkDefs[id]; StringBuilder sb = new StringBuilder(); if (chunkDef != null && chunkDef.Description != string.Empty) { sb.Append(chunkDef.Description); sb.Append("\r\n\r\n"); } sb.AppendFormat("Chunk size = {0}\r\n\r\n", chunkSize); if (inst != null) { sb.Append(FileSchema.DumpInstance(inst, string.Empty)); } return sb.ToString(); }
private StructInstance GetChunkInstance(BinaryReader reader, StructElement chunkDef, int chunkSize, StructInstance parent) { StructInstance inst = null; if (chunkDef != null) { int size = chunkDef.Size; if (size != 0) { inst = chunkDef.Parse(parent, reader.BaseStream, reader.BaseStream.Position + chunkSize) as StructInstance; } else { inst = chunkDef.Parse(parent, null, 0) as StructInstance; } } return inst; }
private StructInstance GetAtomInstance(BinaryReader reader, StructElement atomDef, uint atomSize, StructInstance parent) { StructInstance inst = null; if (atomDef != null) { int size = atomDef.Size; if (size != 0) { inst = atomDef.Parse(parent, reader.BaseStream, reader.BaseStream.Position + atomSize - 8) as StructInstance; } else { inst = atomDef.Parse(parent, null, 0) as StructInstance; } } return inst; }
private string GetAtomDesc(StructElement atomDef, uint atomSize, StructInstance inst) { StringBuilder sb = new StringBuilder(); if (atomDef != null && atomDef.Description != string.Empty) { sb.Append(atomDef.Description); sb.Append("\r\n\r\n"); } sb.AppendFormat("Atom size = {0}\r\n\r\n", atomSize); if (inst != null) { sb.Append(FileSchema.DumpInstance(inst, string.Empty)); } return sb.ToString(); }
/// <summary> /// Create an instance by specified byte array and start position. /// </summary> public override object Parse(ElementInstance parent, Stream stream, long stopAt) { StructInstance inst = new StructInstance(parent, Elements); if (Elements != null) { foreach (Element elem in Elements) { if (elem.EvalCondition(inst)) { if (stream.Position >= stopAt) { break; // don't read beyond boundary. } object elemInst = elem.Parse(inst, stream, stopAt); // Elements that don't have a name will not be added directly if (elem.Name != null && elem.Name != string.Empty) { inst[elem.Name] = elemInst; } } } } return inst; }