Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Solution for new GetPreviousOccurence #108

Open
wants to merge 7 commits into
base: master
Choose a base branch
from
2 changes: 2 additions & 0 deletions NCrontab.Signed/NCrontab.Signed.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@
</PropertyGroup>

<ItemGroup>
<Compile Include="..\NCrontab\Utils\DateTimeComponents.cs" Link="Utils\DateTimeComponents.cs" />
<Compile Include="..\NCrontab\Utils\Incrementor.cs" Link="Utils\Incrementor.cs" />
<Compile Include="..\SolutionInfo.cs" />
<Compile Include="..\NCrontab\*.cs" />
<None Include="..\COPYING.txt" Pack="true" PackagePath="$(PackageLicenseFile)" />
Expand Down
332 changes: 313 additions & 19 deletions NCrontab.Tests/CrontabScheduleTests.cs

Large diffs are not rendered by default.

52 changes: 52 additions & 0 deletions NCrontab/CrontabField.Iterator.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
using NCrontab.Utils;

namespace NCrontab
{
public sealed partial class CrontabField
{
internal sealed class Iterator
{
readonly CrontabField _crontabField;
readonly bool _forwardMoving;

public Iterator(CrontabField crontabField, bool forwardMoving)
{
_crontabField = crontabField;
_forwardMoving = forwardMoving;
}

/// <summary>
/// Returns the first valid value (according to filter) beginning at <paramref name="start"/>.
/// </summary>
/// <param name="start"></param>
/// <returns></returns>
public int Next(int start)
{
if (BeyondLowerBoundValueSet(start))
return LowerBoundValueSet;

var startIndex = _crontabField.ValueToIndex(start);
var lastIndex = _crontabField.ValueToIndex(UpperBoundValueSet);

var incrementor = new Incrementor(_forwardMoving);
for (var i = startIndex; incrementor.BeforeOrEqual(i, lastIndex); i = incrementor.Increment(i))
{
if (_crontabField._bits[i])
return _crontabField.IndexToValue(i);
}

return nil;
}

public int LowerBound => _forwardMoving ? _crontabField.GetFirst() : _crontabField.GetLast();

public int LowerBoundValueSet => _forwardMoving ? _crontabField._minValueSet : _crontabField._maxValueSet;
public int UpperBoundValueSet => _forwardMoving ? _crontabField._maxValueSet : _crontabField._minValueSet;

public bool BeyondLowerBoundValueSet(int start) => _forwardMoving ?
start < _crontabField._minValueSet :
start > _crontabField._maxValueSet;

}
}
}
33 changes: 16 additions & 17 deletions NCrontab/CrontabField.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@

namespace NCrontab
{
using NCrontab.Utils;
#region Imports

using System;
Expand All @@ -37,6 +38,8 @@ namespace NCrontab

public sealed partial class CrontabField : ICrontabField
{
internal const int nil = -1;

readonly BitArray _bits;
/* readonly */ int _minValueSet;
/* readonly */ int _maxValueSet;
Expand Down Expand Up @@ -111,36 +114,32 @@ public static CrontabField DaysOfWeek(string expression) =>
_impl = impl ?? throw new ArgumentNullException(nameof(impl));
_bits = new BitArray(impl.ValueCount);
_minValueSet = int.MaxValue;
_maxValueSet = -1;
_maxValueSet = nil;
}

/// <summary>
/// Gets the first value of the field or -1.
/// </summary>

public int GetFirst() => _minValueSet < int.MaxValue ? _minValueSet : -1;
public int GetFirst() => _minValueSet < int.MaxValue ? _minValueSet : nil;

/// <summary>
/// Gets the last value of the field or -1.
/// </summary>
public int GetLast() => _maxValueSet >= 0 ? _maxValueSet : nil;

/// <summary>
/// Gets the next value of the field that occurs after the given
/// start value or -1 if there is no next value available.
/// </summary>

public int Next(int start)
{
if (start < _minValueSet)
return _minValueSet;

var startIndex = ValueToIndex(start);
var lastIndex = ValueToIndex(_maxValueSet);
public int Next(int start) => new Iterator(this, true).Next(start);

for (var i = startIndex; i <= lastIndex; i++)
{
if (_bits[i])
return IndexToValue(i);
}

return -1;
}
/// <summary>
/// Gets the previous value of the field that occurs before the given
/// start value or -1 if there is no previous value available.
/// </summary>
public int Prev(int start) => new Iterator(this, false).Next(start);

int IndexToValue(int index) => index + _impl.MinValue;
int ValueToIndex(int value) => value - _impl.MinValue;
Expand Down
4 changes: 2 additions & 2 deletions NCrontab/CrontabFieldImpl.cs
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ public void Format(ICrontabField field, TextWriter writer, bool noNames)
var next = field.GetFirst();
var count = 0;

while (next != -1)
while (next != CrontabField.nil)
{
var first = next;
int last;
Expand Down Expand Up @@ -219,7 +219,7 @@ T InternalParse<T>(string str, CrontabFieldAccumulator<T> acc, T success, Func<E

if (str.Length == 1 && str[0] == '*')
{
return acc(-1, -1, every ?? 1, success, errorSelector);
return acc(CrontabField.nil, CrontabField.nil, every ?? 1, success, errorSelector);
}

//
Expand Down
Loading