/// <summary> /// Creates a union stream reader from the supplied data. /// </summary> /// <param name="streams">all of the tables to combine in the union</param> /// <param name="ownsStream">if this class owns the streams, it will call dispose when <see cref="Dispose"/> is called. /// Otherwise, the streams will not be disposed.</param> public UnionTreeStream(IEnumerable <TreeStream <TKey, TValue> > streams, bool ownsStream) { m_firstStream = null; m_ownsStreams = ownsStream; m_tablesOrigList = streams.Select(x => new BufferedTreeStream(x)).ToArray(); m_sortedArchiveStreams = new UnionTreeStreamSortHelper(m_tablesOrigList); m_readWhileUpperBounds.SetMin(); foreach (var table1 in m_sortedArchiveStreams.Items) { table1.EnsureCache(); } m_sortedArchiveStreams.Sort(); //Remove any duplicates RemoveDuplicatesIfExists(); if (m_sortedArchiveStreams.Items.Length > 0) { m_firstTable = m_sortedArchiveStreams[0]; } else { m_firstTable = null; } SetReadWhileUpperBoundsValue(); }
public void Dispose() { if (Stream != null) { Stream.Dispose(); Stream = null; } }
/// <summary> /// Creates a <see cref="DistinctTreeStream{TKey,Value}"/> /// </summary> /// <param name="baseStream">Must be sequential</param> public DistinctTreeStream(TreeStream <TKey, TValue> baseStream) { if (!baseStream.IsAlwaysSequential) { throw new ArgumentException("Must be sequential access", "baseStream"); } m_lastKey = new TKey(); m_lastValue = new TValue(); m_isLastValueValid = false; m_baseStream = baseStream; }
/// <summary> /// Creates the table reader. /// </summary> /// <param name="stream"></param> public BufferedTreeStream(TreeStream <TKey, TValue> stream) { if (!stream.IsAlwaysSequential) { throw new ArgumentException("Stream must gaurentee sequential data access"); } if (!stream.NeverContainsDuplicates) { stream = new DistinctTreeStream <TKey, TValue>(stream); } Stream = stream; EnsureCache(); }
private bool Read2(TKey key, TValue value) { TryAgain: if (m_firstStream == null) { //If m_firstStream == null, this means either: // the value is cached. // or // the end of the stream has occured. if (m_firstTable != null && m_firstTable.IsValid) { //The value is cached. m_firstTable.Read(key, value); m_firstStream = m_firstTable.Stream; return(true); } //The end of the steam has been reached. return(false); } //Condition 1: // The archive stream may no longer be in order and needs to be checked //Response: // Resort the archive stream // //Condition 2: // The end of the frame has been reached //Response: // Advance to the next frame // Also test the edge case where the current point might be equal to the end of the frame // since this is an inclusive filter and ReadWhile is exclusive. // If it's part of the frame, return true after Advancing the frame and the point. // //Since condition 1 and 2 can occur at the same time, verifying the sort of the Archive Stream is a good thing to do. // Will verify that the stream is in the proper order and remove any duplicates that were found. // May be called after every single read, but better to be called // when a ReadWhile function returns false. if (m_sortedArchiveStreams.Items.Length > 1) { //If list is no longer in order int compare = CompareStreams(m_sortedArchiveStreams[0], m_sortedArchiveStreams[1]); if (compare == 0) //A duplicate value was found. { //If a duplicate entry is found, advance the position of the duplicate entry RemoveDuplicatesFromList(); SetReadWhileUpperBoundsValue(); m_firstTable = m_sortedArchiveStreams[0]; } else if (compare > 0) //List is out of order { m_sortedArchiveStreams.SortAssumingIncreased(0); m_firstTable = m_sortedArchiveStreams[0]; SetReadWhileUpperBoundsValue(); } } else { //If only 1 stream, we can't resort, so we are done. if (!m_sortedArchiveStreams[0].IsValid) { return(false); } } m_firstStream = null; //Ensure that the if block is executed when repeating this function call. goto TryAgain; }