//-----------------------------------------------------------------------
//
// 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;
}
}
}