/// <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(File file, long position, long reserved = 0) { if (file == null) { throw new ArgumentNullException(nameof(file)); } if (position > file.Length || position < 0) { throw new ArgumentOutOfRangeException(nameof(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> /// Write the <see cref="DataSize"/> to the EBML file. /// Resize the data-size length to 8 bytes. /// This will *not* insert extra bytes, but overwrite next contiguous bytes. /// It will claim the size added on the value of the data-size. /// </summary> /// <returns>Offset created in Writing the new data-size</returns> public long WriteDataSize() { ulong value = DataSize; const ulong newsize_length = 8; // Figure out the ID size in bytes ulong mask = 0xFF000000, id_length = 4; while (id_length > 0 && (ebml_id & mask) == 0) { id_length--; mask >>= 8; } if (id_length == 0) { throw new CorruptFileException("invalid EBML ID (zero)"); } // Figure out the Data size length in bytes ulong size_length = DataOffset - offset - id_length; if (size_length > 8) { throw new CorruptFileException("invalid EBML element size"); } // Construct the data-size field ByteVector vector = new ByteVector((int)newsize_length); mask = value; for (int i = (int)newsize_length - 1; i >= 0; i--) { vector[i] = (byte)(mask & 0xFF); mask >>= 8; } // Set the marker bit vector[0] |= 0x100 >> (int)newsize_length; // Write data-size field to file file.Insert(vector, (long)(offset + id_length), (long)newsize_length); // Update fields ulong woffset = newsize_length - size_length; DataOffset += woffset; DataSize = value - woffset; return((long)woffset); }