Implemented loading EBML data format (extensive testing still needs to be done)

This commit is contained in:
Michael Becker 2014-10-24 15:57:34 -04:00
parent 970cd02ac7
commit d423e85c05
2 changed files with 201 additions and 0 deletions

View File

@ -0,0 +1,200 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UniversalEditor.Accessors;
using UniversalEditor.IO;
using UniversalEditor.ObjectModels.Markup;
namespace UniversalEditor.DataFormats.Markup.EBML
{
public class EBMLDataFormat : DataFormat
{
private static DataFormatReference _dfr = null;
public override DataFormatReference MakeReference()
{
if (_dfr == null)
{
_dfr = base.MakeReference();
_dfr.Capabilities.Add(typeof(MarkupObjectModel), DataFormatCapabilities.All);
_dfr.Filters.Add("Extensible Binary Meta Language", new byte?[][] { new byte?[] { 0x1A, 0x45, 0xDF, 0xA3 } }, new string[] { "*.ebml" });
_dfr.Sources.Add("http://ebml.sourceforge.net/specs/");
}
return _dfr;
}
protected override void LoadInternal(ref ObjectModel objectModel)
{
MarkupObjectModel mom = (objectModel as MarkupObjectModel);
if (mom == null) throw new ObjectModelNotSupportedException();
Reader reader = base.Accessor.Reader;
reader.Accessor.Seek(0, SeekOrigin.Begin);
while (!reader.EndOfStream)
{
MarkupElement el = ReadEBMLElement(reader);
mom.Elements.Add(el);
}
}
private MarkupElement ReadEBMLElement(Reader reader)
{
long elementID = ReadEBMLElementID(reader);
long dataSize = ReadEBMLElementID(reader);
byte[] data = reader.ReadBytes(dataSize);
MarkupTagElement tag = new MarkupTagElement();
tag.FullName = elementID.ToString();
if (elementID == 0x0A45DFA3)
{
Reader rdr = new Reader(new MemoryAccessor(data));
while (!rdr.EndOfStream)
{
MarkupElement el = ReadEBMLElement(rdr);
tag.Elements.Add(el);
}
reader.Close();
}
else
{
MarkupStringElement mse = new MarkupStringElement();
mse.FullName = "CDATA";
mse.Value = Convert.ToBase64String(data);
tag.Elements.Add(mse);
}
return tag;
}
private long ReadEBMLElementID(Reader reader)
{
byte[] buffer = reader.ReadBytes(8);
reader.Seek(-8, SeekOrigin.Current);
if ((buffer[0] & 0x80) == 0x80)
{
// one byte
buffer[0] = (byte)(buffer[0] & ~0x80);
reader.Seek(1, SeekOrigin.Current);
return (long)buffer[0];
}
else if ((buffer[0] & 0x40) == 0x40)
{
// two bytes
buffer[0] = (byte)(buffer[0] & ~0x40);
reader.Seek(2, SeekOrigin.Current);
byte[] _buffer = new byte[2];
_buffer[0] = buffer[1];
_buffer[1] = buffer[0];
return (long)BitConverter.ToInt16(_buffer, 0);
}
else if ((buffer[0] & 0x20) == 0x20)
{
// three bytes
buffer[0] = (byte)(buffer[0] & ~0x20);
reader.Seek(3, SeekOrigin.Current);
byte[] _buffer = new byte[4];
_buffer[0] = 0;
_buffer[1] = buffer[2];
_buffer[2] = buffer[1];
_buffer[3] = buffer[0];
return (long)BitConverter.ToInt32(_buffer, 0);
}
else if ((buffer[0] & 0x10) == 0x10)
{
// four bytes
buffer[0] = (byte)(buffer[0] & ~0x10);
reader.Seek(4, SeekOrigin.Current);
byte[] _buffer = new byte[4];
_buffer[0] = buffer[3];
_buffer[1] = buffer[2];
_buffer[2] = buffer[1];
_buffer[3] = buffer[0];
return (long)BitConverter.ToInt32(_buffer, 0);
}
else if ((buffer[0] & 0x08) == 0x08)
{
// five bytes
buffer[0] = (byte)(buffer[0] & ~0x08);
reader.Seek(5, SeekOrigin.Current);
byte[] _buffer = new byte[8];
_buffer[0] = 0;
_buffer[1] = 0;
_buffer[2] = 0;
_buffer[3] = buffer[4];
_buffer[4] = buffer[3];
_buffer[5] = buffer[2];
_buffer[6] = buffer[1];
_buffer[7] = buffer[0];
return (long)BitConverter.ToInt64(_buffer, 0);
}
else if ((buffer[0] & 0x04) == 0x04)
{
// six bytes
buffer[0] = (byte)(buffer[0] & ~0x04);
reader.Seek(6, SeekOrigin.Current);
byte[] _buffer = new byte[8];
_buffer[0] = 0;
_buffer[1] = 0;
_buffer[2] = buffer[5];
_buffer[3] = buffer[4];
_buffer[4] = buffer[3];
_buffer[5] = buffer[2];
_buffer[6] = buffer[1];
_buffer[7] = buffer[0];
return (long)BitConverter.ToInt64(_buffer, 0);
}
else if ((buffer[0] & 0x02) == 0x02)
{
// seven bytes
buffer[0] = (byte)(buffer[0] & ~0x02);
reader.Seek(7, SeekOrigin.Current);
byte[] _buffer = new byte[8];
_buffer[0] = 0;
_buffer[1] = buffer[6];
_buffer[2] = buffer[5];
_buffer[3] = buffer[4];
_buffer[4] = buffer[3];
_buffer[5] = buffer[2];
_buffer[6] = buffer[1];
_buffer[7] = buffer[0];
return (long)BitConverter.ToInt64(_buffer, 0);
}
else if ((buffer[0] & 0x01) == 0x01)
{
// eight bytes
buffer[0] = (byte)(buffer[0] & ~0x01);
reader.Seek(8, SeekOrigin.Current);
byte[] _buffer = new byte[8];
_buffer[0] = buffer[7];
_buffer[1] = buffer[6];
_buffer[2] = buffer[5];
_buffer[3] = buffer[4];
_buffer[4] = buffer[3];
_buffer[5] = buffer[2];
_buffer[6] = buffer[1];
_buffer[7] = buffer[0];
return (long)BitConverter.ToInt64(_buffer, 0);
}
// Since modern computers do not easily deal with data coded in sizes greater than 64 bits,
// any larger Element Sizes are left undefined at the moment. Currently, the Element Size
// coding allows for an Element to grow to 72000 To, i.e. 7x10^16 octets or 72000 terabytes,
// which will be sufficient for the time being.
throw new NotImplementedException("Unknown Element Size coding: 0x" + buffer[0].ToString("X"));
}
protected override void SaveInternal(ObjectModel objectModel)
{
throw new NotImplementedException();
}
}
}

View File

@ -48,6 +48,7 @@
<Compile Include="DataFormats\Chunked\RIFF\RIFFDataFormat.cs" />
<Compile Include="DataFormats\FileSystem\UXT\Internal\FileInfo.cs" />
<Compile Include="DataFormats\FileSystem\UXT\UXTDataFormat.cs" />
<Compile Include="DataFormats\Markup\EBML\EBMLDataFormat.cs" />
<Compile Include="DataFormats\Markup\XML\XMLDataFormat.cs" />
<Compile Include="DataFormats\Markup\XML\XMLDataFormatSettings.cs" />
<Compile Include="DataFormats\PropertyList\CoreObject\CoreObjectDataFormat.cs" />