public EBMLElement(Matroska.File _file, ulong position) { if (_file == null) { throw new ArgumentNullException("file"); } if (position > (ulong)(_file.Length - 4)) { throw new ArgumentOutOfRangeException("position"); } file = _file; file.Seek((long)position); ByteVector vector = file.ReadBlock(1); Byte header_byte = vector[0]; Byte mask = 0x80, id_length = 1; while (id_length <= 4 && (header_byte & mask) == 0) { id_length++; mask >>= 1; } if (id_length > 4) { throw new CorruptFileException("invalid EBML id size"); } if (id_length > 1) { vector.Add(file.ReadBlock(id_length - 1)); } ebml_id = vector.ToUInt(); vector.Clear(); vector = file.ReadBlock(1); header_byte = vector[0]; mask = 0x80; Byte size_length = 1; while (size_length <= 8 && (header_byte & mask) == 0) { size_length++; mask >>= 1; } if (size_length > 8) { throw new CorruptFileException("invalid EBML element size"); } vector[0] &= (Byte)(mask - 1); if (size_length > 1) { vector.Add(file.ReadBlock(size_length - 1)); } ebml_size = vector.ToULong(); offset = position; data_offset = offset + id_length + size_length; }
/// <summary> /// Write the EMBL (and all its data/content) to a file. /// </summary> /// <param name="file">A <see cref="File"/> representing the file to write to.</param> /// <param name="position">The byte-position in the file to write the EBML to.</param> /// <param name="reserved">The reserved size in bytes that the EBML may overwrite from the given position. (Default: 0, insert)</param> public void Write(Matroska.File file, long position, long reserved = 0) { if (file == null) { throw new ArgumentNullException("file"); } if (position > file.Length || position < 0) { throw new ArgumentOutOfRangeException("position"); } if (Data != null && Children != null) { throw new UnsupportedFormatException("EBML element cannot contain both Data and Children"); } // Reserve required size upfront to speed up writing var size = Size; if (size > reserved) { // Extend reserved size file.Insert(size - reserved, position + reserved); reserved = size; } // Write the Header var header = Header; file.Insert(header, position, header.Count); position += header.Count; reserved -= header.Count; // Write the data/content if (Data != null) { file.Insert(Data, position, Data.Count); } else if (Children != null) { foreach (var child in Children) { child.Write(file, position, reserved); var csize = child.Size; position += csize; reserved -= csize; } } }
/// <summary> /// Remove the EBML element from the file /// </summary> /// <returns>Size difference compare to previous EBML size</returns> public long Remove() { long ret = -(long)Size; file.RemoveBlock((long)Offset, (long)Size); // Invalidate this object ebml_id = 0; data_offset = offset; ebml_size = 0; file = null; return(ret); }
/// <summary> /// Constructs a root <see cref="EBMLreader" /> instance, by reading from /// the provided file position. /// </summary> /// <param name="_file"><see cref="File" /> File instance to read from.</param> /// <param name="position">Position in the file to start reading from.</param> public EBMLreader(Matroska.File _file, ulong position) { // Keep a reference to the file file = _file; parent = null; // Initialize attributes offset = position; data_offset = position; ebml_id = 0; ebml_size = 0; // Actually read the EBML on the file Read(true); }
/// <summary> /// Create a new abstract <see cref="EBMLreader" /> with arbitrary attributes, /// without reading its information on the file. /// </summary> /// <param name="parent">The <see cref="EBMLreader" /> that contains the instance to be described.</param> /// <param name="position">Position in the file.</param> /// <param name="ebmlid">EBML ID of the element</param> /// <param name="size">Total size of the EBML, in bytes</param> public EBMLreader(EBMLreader parent, ulong position, MatroskaID ebmlid, ulong size = 0) { // Keep a reference to the file if (parent != null) { file = parent.file; } this.parent = parent; // Initialize attributes offset = position; data_offset = offset; ebml_id = (uint)ebmlid; ebml_size = size; }
/// <summary> /// Constructs a child <see cref="EBMLreader" /> reading the data from the /// EBML parent at the provided file position. /// </summary> /// <param name="parent">The <see cref="EBMLreader" /> that contains the instance to be created.</param> /// <param name="position">Position in the file to start reading from.</param> public EBMLreader(EBMLreader parent, ulong position) { if (parent == null) { throw new ArgumentNullException("file"); } // Keep a reference to the file file = parent.file; this.parent = parent; // Initialize attributes offset = position; data_offset = position; ebml_id = 0; ebml_size = 0; // Actually read the EBML on the file Read(true); }
/// <summary> /// Constructs a <see cref="EBMLElement" /> parsing from provided /// file data. /// </summary> /// <param name="_file"><see cref="File" /> instance to read from.</param> /// <param name="position">Position to start reading from.</param> public EBMLElement(Matroska.File _file, ulong position) { if (_file == null) { throw new ArgumentNullException("file"); } if (position > (ulong)(_file.Length - 4)) { throw new ArgumentOutOfRangeException("position"); } // Keep a reference to the file file = _file; file.Seek((long)position); // Get the header byte ByteVector vector = file.ReadBlock(1); Byte header_byte = vector [0]; // Define a mask Byte mask = 0x80, id_length = 1; // Figure out the size in bytes while (id_length <= 4 && (header_byte & mask) == 0) { id_length++; mask >>= 1; } if (id_length > 4) { throw new CorruptFileException("invalid EBML id size"); } // Now read the rest of the EBML ID if (id_length > 1) { vector.Add(file.ReadBlock(id_length - 1)); } ebml_id = vector.ToUInt(); vector.Clear(); // Get the size length vector = file.ReadBlock(1); header_byte = vector [0]; mask = 0x80; Byte size_length = 1; // Iterate through various possibilities while (size_length <= 8 && (header_byte & mask) == 0) { size_length++; mask >>= 1; } if (size_length > 8) { throw new CorruptFileException("invalid EBML element size"); } // Clear the marker bit vector [0] &= (Byte)(mask - 1); // Now read the rest of the EBML element size if (size_length > 1) { vector.Add(file.ReadBlock(size_length - 1)); } ebml_size = vector.ToULong(); offset = position; data_offset = offset + id_length + size_length; }
/// <summary> /// Constructs a <see cref="EBMLElement" /> parsing from provided /// file data. /// </summary> /// <param name="_file"><see cref="File" /> instance to read from.</param> /// <param name="position">Position to start reading from.</param> public EBMLElement (Matroska.File _file, ulong position) { if (_file == null) throw new ArgumentNullException ("file"); if (position > (ulong) (_file.Length - 4)) throw new ArgumentOutOfRangeException ("position"); // Keep a reference to the file file = _file; file.Seek ((long) position); // Get the header byte ByteVector vector = file.ReadBlock (1); Byte header_byte = vector [0]; // Define a mask Byte mask = 0x80, id_length = 1; // Figure out the size in bytes while (id_length <= 4 && (header_byte & mask) == 0) { id_length++; mask >>= 1; } if (id_length > 4) { throw new CorruptFileException ("invalid EBML id size"); } // Now read the rest of the EBML ID if (id_length > 1) { vector.Add (file.ReadBlock (id_length -1)); } ebml_id = vector.ToUInt (); vector.Clear (); // Get the size length vector = file.ReadBlock (1); header_byte = vector [0]; mask = 0x80; Byte size_length = 1; // Iterate through various possibilities while (size_length <= 8 && (header_byte & mask) == 0) { size_length++; mask >>= 1; } if (size_length > 8) { throw new CorruptFileException ("invalid EBML element size"); } // Clear the marker bit vector [0] &= (Byte) (mask - 1); // Now read the rest of the EBML element size if (size_length > 1) { vector.Add (file.ReadBlock (size_length - 1)); } ebml_size = vector.ToULong (); offset = position; data_offset = offset + id_length + size_length; }