/// <summary> /// Get an unsigned integer (any size from 1 to 8 bytes) from EBML Element's data section. /// </summary> /// <returns>a ulong containing the parsed value.</returns> public ulong GetULong() { if (Data == null) { return(0); } return(Data.ToULong()); }
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> /// Read EBML header and data-size if it is an abstract one. /// It then becomes a non abstract EBML. /// </summary> /// <param name="throwException">Throw exception on invalid EBML read if true (Default: false).</param> /// <returns>True if successful.</returns> public bool Read(bool throwException = false) { if (!Abstract) { return(true); } if (file == null) { throw new ArgumentNullException("file"); } try { var ex = new InvalidOperationException("Invalid EBML format Read"); if (offset >= (ulong)(file.Length) - 1) { throw ex; } // Prepare for Consitency check uint ebml_id_check = ebml_id; ulong ebml_size_check = Size; file.Seek((long)offset); // 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 ex; } // 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) { size_length = 1; // Special: Empty element (all zero state) } else { vector[0] &= (Byte)(mask - 1); // Clear the marker bit } // Now read the rest of the EBML element size if (size_length > 1) { vector.Add(file.ReadBlock(size_length - 1)); } ebml_size = vector.ToULong(); // Special: Auto-size (0xFF byte) if (size_length == 1 && ebml_size == 0x7F) { // Resolve auto-size to fill in to its containing element ulong bound = parent == null ? (ulong)file.Length : parent.Offset + parent.Size; ebml_size = bound - offset - (ulong)(id_length + size_length); } data_offset = offset + id_length + size_length; // Consistency check: Detect descrepencies between read data and abstract data if (ebml_id_check != 0 && ebml_id_check != ebml_id) { throw ex; } if (ebml_size_check != 0 && ebml_size_check != Size) { throw ex; } return(true); } catch (Exception ex) { if (throwException) { throw ex; } return(false); } }
/// <summary> /// Populates the values in the current instance by parsing /// its field data in a specified version. /// </summary> /// <param name="data"> /// A <see cref="ByteVector" /> object containing the /// extracted field data. /// </param> /// <param name="version"> /// A <see cref="byte" /> indicating the ID3v2 version the /// field data is encoded in. /// </param> protected override void ParseFields(ByteVector data, byte version) { play_count = data.ToULong(); }
/// <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; }
protected override void ParseFields(ByteVector data, byte version) { this.play_count = data.ToULong(); }