//----------------------------------------------------------------------- // // Copyright (c) Microsoft Corporation. // //----------------------------------------------------------------------- namespace Microsoft.Isam.Esent.Interop { using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; /// /// Base class for enumerators that walk a table. /// /// The type returned by the enumerator. internal abstract class TableEnumerator : IEnumerator { /// /// True if we are at the end of the table. /// private bool isAtEnd; /// /// True if we need to move to the first record in the table. /// private bool moveToFirst = true; /// /// Initializes a new instance of the class. /// /// /// The session to use. /// protected TableEnumerator(JET_SESID sesid) { this.Sesid = sesid; this.TableidToEnumerate = JET_TABLEID.Nil; } /// /// Gets the current entry. /// public T Current { get; private set; } /// /// Gets the current entry. /// object IEnumerator.Current { [DebuggerStepThrough] get { return this.Current; } } /// /// Gets the session used for the enumeration. /// protected JET_SESID Sesid { get; private set; } /// /// Gets or sets the table being enumerated. /// protected JET_TABLEID TableidToEnumerate { get; set; } /// /// Resets the enumerator. The next call to MoveNext will move /// to the first entry. /// public void Reset() { this.isAtEnd = false; this.moveToFirst = true; } /// /// Disposes of any resources the enumerator is using. /// public void Dispose() { this.CloseTable(); GC.SuppressFinalize(this); } /// /// Move to the next entry. /// /// /// True if an entry was found, false otherwise. /// public bool MoveNext() { // Moving to the end is sticky (until Reset is called) if (this.isAtEnd) { return false; } if (this.TableidToEnumerate.IsInvalid) { Debug.Assert(this.moveToFirst, "Table has not been opened so moveToFirst should be true"); this.OpenTable(); } bool needMoveNext = true; if (this.moveToFirst) { if (!Api.TryMoveFirst(this.Sesid, this.TableidToEnumerate)) { this.isAtEnd = true; return false; } this.moveToFirst = false; needMoveNext = false; } while (needMoveNext || this.SkipCurrent()) { if (!Api.TryMoveNext(this.Sesid, this.TableidToEnumerate)) { this.isAtEnd = true; return false; } needMoveNext = false; } this.Current = this.GetCurrent(); return true; } /// /// Open the table to be enumerated. This should set . /// protected abstract void OpenTable(); /// /// Gets the entry the cursor is currently positioned on. /// /// The entry the cursor is currently positioned on. protected abstract T GetCurrent(); /// /// Determine if the current entry in the table being enumerated should /// be skipped (not returned). By default this is false. /// /// True if the current entry should be skipped. protected virtual bool SkipCurrent() { return false; } /// /// Closes the table being enumerated. /// protected virtual void CloseTable() { if (!this.TableidToEnumerate.IsInvalid) { Api.JetCloseTable(this.Sesid, this.TableidToEnumerate); } this.TableidToEnumerate = JET_TABLEID.Nil; } } }