diff --git a/Src/Core/EbmlReader.cs b/Src/Core/EbmlReader.cs
index 6256f99..54ac354 100644
--- a/Src/Core/EbmlReader.cs
+++ b/Src/Core/EbmlReader.cs
@@ -84,21 +84,39 @@ public bool ReadNext()
_element = Element.Empty;
return false;
}
+
+ ReadElement();
+ return true;
+ }
- ElementPosition = _source.Position;
- var identifier = ReadVarInt(4);
+ ///
+ /// Reads the next child element of the current container at the specified position and positions the stream at the beginning of the element data.
+ ///
+ /// The exact position in the current container to read the next element from.
+ /// true
if the child element is available; false
otherwise
+ /// if the value of the element identifier or element data size read from the stream is reserved
+ public bool ReadAt(long position)
+ {
+ _container.Remaining -= _element.Size;
+ _element = _container;
- if (identifier.IsReserved)
+ if (_element.Remaining < 1)
{
- throw new EbmlDataFormatException("invalid element identifier value");
+ _element = Element.Empty;
+ return false;
}
- var size = ReadVarInt(8).Value;
- if (size > (ulong)_container.Remaining)
+ // compute the desired position relative to the current position in the container
+ var relativePosition = position - (_container.Size - _container.Remaining);
+
+ if (relativePosition < 0)
{
- throw new EbmlDataFormatException("invalid element size value");
+ throw new EbmlDataFormatException("invalid position, seeking backwards is not supported");
}
- _element = new Element(identifier, (long) size, ElementType.None);
+
+ Skip(relativePosition);
+
+ ReadElement();
return true;
}
@@ -167,10 +185,8 @@ public void LeaveContainer()
throw new InvalidOperationException();
}
_container.Remaining -= _element.Size;
- Skip(_container.Remaining);
- _container.Remaining = 0;
_element = _container;
-
+ Skip(_element.Remaining);
_container = _containers.Pop();
}
@@ -406,6 +422,26 @@ private void Skip(long length)
}
}
+ private void ReadElement()
+ {
+ ElementPosition = _source.Position;
+
+ var identifier = ReadVarInt(4);
+
+ if (identifier.IsReserved)
+ {
+ throw new EbmlDataFormatException("invalid element identifier value");
+ }
+
+ var size = ReadVarInt(8).Value;
+ if (size > (ulong)_container.Remaining)
+ {
+ throw new EbmlDataFormatException("invalid element size value");
+ }
+
+ _element = new Element(identifier, (long) size, ElementType.None);
+ }
+
///
/// Reads the element data as a variable size integer.
///