public ElementInfo Next() { if((lastElementPos != ~VIntConsts.UNKNOWN_LENGTH && nextElementPos >= lastElementPos) || nextElementPos == ~VIntConsts.UNKNOWN_LENGTH || dataSrc.EOF) return null; if(dataSrc.Position != nextElementPos) dataSrc.Position = nextElementPos; ElementInfo elemInfo; var docElementId = dataSrc.ReadIdentifier(); var vintPos = dataSrc.Position; var dataLength = dataSrc.ReadVInt(); var dataPos = dataSrc.Position; var isDocElementInvalid = docElementId < 0 && (~docElementId & VIntConsts.ERROR) != 0; var isDataLengthInvalid = dataLength < 0 && (~dataLength & VIntConsts.ERROR) != 0; var isOutOfBounds = lastElementPos != ~VIntConsts.UNKNOWN_LENGTH && dataPos + dataLength > lastElementPos; if(isDocElementInvalid || isDataLengthInvalid || isOutOfBounds) { elemInfo = new ElementInfo(EBMLDocElement.Unknown, nextElementPos, vintPos, dataPos, 0); dataSrc.SyncTo(bytePatterns, lastElementPos); nextElementPos = dataSrc.Position; return elemInfo; } var docElem = docType.RetrieveDocElement(docElementId); elemInfo = new ElementInfo(docElem, nextElementPos, vintPos, dataPos, dataLength < 0 ? default(Int64?) : dataLength); nextElementPos = dataLength < 0 ? ~VIntConsts.UNKNOWN_LENGTH : dataPos + dataLength; //Trace.WriteLine(elemInfo.ToDetailedString()); return elemInfo; }
public Object RetrieveValue(ElementInfo elem) { if(elem == null) throw new ArgumentNullException("elem"); if(!elem.DataLength.HasValue) throw new InvalidOperationException("Cannot retrieve value: Length unknown"); if(elem.DataLength.Value == 0) return new byte[0]; if(dataSrc.Position != elem.DataPos) throw new InvalidOperationException("Cannot retrieve value: Current position doesn't match element data position"); Int64 offset; var valueData = dataSrc.GetData(elem.DataLength.Value, out offset); return docType.RetrieveValue(elem.DocElement, valueData, offset, elem.DataLength.Value); }
public ElementInfo WriteElement(EBMLDocElement elem, Stream data) { Int64 idPos = dataSrc.Position; dataSrc.WriteIdentifier(elem.Id); Int64 vIntPos = dataSrc.Position; dataSrc.WriteFakeVInt(8); Int64 dataPos = dataSrc.Position; dataSrc.Write(data); var elemInfo = new ElementInfo(elem, idPos, vIntPos, dataPos, null); UpdateElementLength(elemInfo); return elemInfo; }
private void UpdateElementLength(ElementInfo elemInfo) { var currentPos = dataSrc.Position; var dataLength = currentPos - elemInfo.DataPos; elemInfo.DataLength = dataLength; dataSrc.Position = elemInfo.VIntPos; dataSrc.WriteVInt(dataLength, 8); dataSrc.Position = currentPos; }
public IDisposable EnterElement(ElementInfo elemInfo) { var disposable = new PreviousState { NextElementPos = nextElementPos, LastElementPos = lastElementPos }; disposable.Disposed += (s, e) => { var d = (PreviousState)s; if(nextElementPos < d.LastElementPos) nextElementPos = d.NextElementPos; lastElementPos = d.LastElementPos; }; nextElementPos = elemInfo.DataPos; lastElementPos = elemInfo.DataLength.HasValue ? elemInfo.DataPos + elemInfo.DataLength.Value : ~VIntConsts.UNKNOWN_LENGTH; return disposable; }