# HG changeset patch # User cin # Date 1461319688 -10800 # Node ID 1c2a16d071a75a5d8470a5aae0ec1aa0274a16ad # Parent 2a8466f0cb8aacae858116af47493d1126bfeecc# Parent b60643b47078137088a6822efa6321d6caa863b3 Слияние с ref20160224 diff -r 2a8466f0cb8a -r 1c2a16d071a7 .hgignore --- a/.hgignore Fri Feb 19 18:07:17 2016 +0300 +++ b/.hgignore Fri Apr 22 13:08:08 2016 +0300 @@ -15,3 +15,6 @@ Implab.Diagnostics.Interactive/obj/ MonoPlay/bin/ MonoPlay/obj/ +Implab.Test/Implab.Format.Test/bin/ +Implab.Test/Implab.Format.Test/obj/ +*.suo diff -r 2a8466f0cb8a -r 1c2a16d071a7 Implab.Test/Implab.Format.Test/Implab.Format.Test.csproj --- a/Implab.Test/Implab.Format.Test/Implab.Format.Test.csproj Fri Feb 19 18:07:17 2016 +0300 +++ b/Implab.Test/Implab.Format.Test/Implab.Format.Test.csproj Fri Apr 22 13:08:08 2016 +0300 @@ -10,6 +10,7 @@ Implab.Format.Test Implab.Format.Test v4.5 + 0.2 true @@ -32,7 +33,7 @@ - ..\..\packages\NUnit.3.0.1\lib\net45\nunit.framework.dll + ..\..\packages\NUnit.2.6.4\lib\nunit.framework.dll @@ -40,6 +41,12 @@ + + {F550F1F8-8746-4AD0-9614-855F4C4B7F05} + Implab + + + \ No newline at end of file diff -r 2a8466f0cb8a -r 1c2a16d071a7 Implab.Test/Implab.Format.Test/JsonTests.cs --- a/Implab.Test/Implab.Format.Test/JsonTests.cs Fri Feb 19 18:07:17 2016 +0300 +++ b/Implab.Test/Implab.Format.Test/JsonTests.cs Fri Apr 22 13:08:08 2016 +0300 @@ -1,11 +1,87 @@ using NUnit.Framework; using System; +using Implab.Formats.JSON; +using Implab.Automaton; namespace Implab.Format.Test { - [TestFixture()] + [TestFixture] public class JsonTests { - [Test()] - public void TestCase() { + [Test] + public void TestScannerValidTokens() { + using (var scanner = new JSONScanner(@"9123, -123, 0, 0.1, -0.2, -0.1e3, 1.3E-3, ""some \t\n\u0020 text"", literal []{}:")) { + + Tuple[] expexted = { + new Tuple(JsonTokenType.Number, 9123d), + new Tuple(JsonTokenType.ValueSeparator, ", "), + new Tuple(JsonTokenType.Number, -123d), + new Tuple(JsonTokenType.ValueSeparator, ", "), + new Tuple(JsonTokenType.Number, 0d), + new Tuple(JsonTokenType.ValueSeparator, ", "), + new Tuple(JsonTokenType.Number, 0.1d), + new Tuple(JsonTokenType.ValueSeparator, ", "), + new Tuple(JsonTokenType.Number, -0.2d), + new Tuple(JsonTokenType.ValueSeparator, ", "), + new Tuple(JsonTokenType.Number, -0.1e3d), + new Tuple(JsonTokenType.ValueSeparator, ", "), + new Tuple(JsonTokenType.Number, 1.3E-3d), + new Tuple(JsonTokenType.ValueSeparator, ", "), + new Tuple(JsonTokenType.String, "some \t\n text"), + new Tuple(JsonTokenType.ValueSeparator, ", "), + new Tuple(JsonTokenType.Literal, "literal"), + new Tuple(JsonTokenType.BeginArray, " ["), + new Tuple(JsonTokenType.EndArray, "]"), + new Tuple(JsonTokenType.BeginObject, "{"), + new Tuple(JsonTokenType.EndObject, "}"), + new Tuple(JsonTokenType.NameSeparator, ":") + }; + + object value; + JsonTokenType tokenType; + for (var i = 0; i < expexted.Length; i++) { + + Assert.IsTrue(scanner.ReadToken(out value, out tokenType)); + Assert.AreEqual(expexted[i].Item1, tokenType); + Assert.AreEqual(expexted[i].Item2, value); + } + + Assert.IsFalse(scanner.ReadToken(out value, out tokenType)); + } + } + + [Test] + public void TestScannerBadTokens() { + var bad = new [] { + " 1", + " literal", + " \"", + "\"unclosed string", + "1.bad", + "001", // should be read as three numbers + "--10", + "+10", + "1.0.0", + "1e1.0", + "l1teral0", + ".123", + "-.123" + }; + + foreach (var json in bad) + using (var scanner = new JSONScanner(json)) { + try { + object value; + JsonTokenType token; + scanner.ReadToken(out value, out token); + if (!Object.Equals(value,json)) { + Console.WriteLine("'{0}' is read as {1}", json, value is String ? String.Format("'{0}'", value) : value ); + continue; + } + Assert.Fail("Token '{0}' shouldn't pass", json); + } catch (ParserException e) { + Console.WriteLine(e.Message); + } + } + } } } diff -r 2a8466f0cb8a -r 1c2a16d071a7 Implab.Test/Implab.Format.Test/packages.config --- a/Implab.Test/Implab.Format.Test/packages.config Fri Feb 19 18:07:17 2016 +0300 +++ b/Implab.Test/Implab.Format.Test/packages.config Fri Apr 22 13:08:08 2016 +0300 @@ -1,4 +1,4 @@  - + \ No newline at end of file diff -r 2a8466f0cb8a -r 1c2a16d071a7 Implab.Test/Implab.Test.csproj --- a/Implab.Test/Implab.Test.csproj Fri Feb 19 18:07:17 2016 +0300 +++ b/Implab.Test/Implab.Test.csproj Fri Apr 22 13:08:08 2016 +0300 @@ -62,8 +62,10 @@ + + diff -r 2a8466f0cb8a -r 1c2a16d071a7 Implab.Test/Implab.Test.mono.csproj --- a/Implab.Test/Implab.Test.mono.csproj Fri Feb 19 18:07:17 2016 +0300 +++ b/Implab.Test/Implab.Test.mono.csproj Fri Apr 22 13:08:08 2016 +0300 @@ -58,6 +58,7 @@ + diff -r 2a8466f0cb8a -r 1c2a16d071a7 Implab.Test/RunnableComponentTests.cs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Implab.Test/RunnableComponentTests.cs Fri Apr 22 13:08:08 2016 +0300 @@ -0,0 +1,195 @@ +using System; +using System.Reflection; +using System.Threading; +using Implab.Parallels; +using Implab.Components; + +#if MONO + +using NUnit.Framework; +using TestClassAttribute = NUnit.Framework.TestFixtureAttribute; +using TestMethodAttribute = NUnit.Framework.TestAttribute; +using AssertFailedException = NUnit.Framework.AssertionException; +#else + +using Microsoft.VisualStudio.TestTools.UnitTesting; + +#endif + +namespace Implab.Test { + [TestClass] + public class RunnableComponentTests { + + static void ShouldThrow(Action action) { + try { + action(); + Assert.Fail(); + } catch (AssertFailedException) { + throw; + } catch { + } + } + + class Runnable : RunnableComponent { + public Runnable(bool initialized) : base(initialized) { + } + + public Action MockInit { + get; + set; + } + + public Func MockStart { + get; + set; + } + + public Func MockStop { + get; + set; + } + + protected override IPromise OnStart() { + return MockStart != null ? MockStart() : base.OnStart(); + } + + protected override IPromise OnStop() { + return MockStop != null ? MockStop() : base.OnStart(); + } + + protected override void OnInitialize() { + if (MockInit != null) + MockInit(); + } + } + + [TestMethod] + public void NormalFlowTest() { + var comp = new Runnable(false); + + Assert.AreEqual(ExecutionState.Created, comp.State); + + comp.Init(); + + Assert.AreEqual(ExecutionState.Ready, comp.State); + + comp.Start().Join(1000); + + Assert.AreEqual(ExecutionState.Running, comp.State); + + comp.Stop().Join(1000); + + Assert.AreEqual(ExecutionState.Disposed, comp.State); + + } + + [TestMethod] + public void InitFailTest() { + var comp = new Runnable(false) { + MockInit = () => { + throw new Exception("BAD"); + } + }; + + ShouldThrow(() => comp.Start()); + ShouldThrow(() => comp.Stop()); + Assert.AreEqual(ExecutionState.Created, comp.State); + + ShouldThrow(comp.Init); + + Assert.AreEqual(ExecutionState.Failed, comp.State); + + ShouldThrow(() => comp.Start()); + ShouldThrow(() => comp.Stop()); + Assert.AreEqual(ExecutionState.Failed, comp.State); + + comp.Dispose(); + Assert.AreEqual(ExecutionState.Disposed, comp.State); + } + + [TestMethod] + public void DisposedTest() { + + var comp = new Runnable(false); + comp.Dispose(); + + ShouldThrow(() => comp.Start()); + ShouldThrow(() => comp.Stop()); + ShouldThrow(comp.Init); + + Assert.AreEqual(ExecutionState.Disposed, comp.State); + } + + [TestMethod] + public void StartCancelTest() { + var comp = new Runnable(true) { + MockStart = () => PromiseHelper.Sleep(100000, 0) + }; + + var p = comp.Start(); + Assert.AreEqual(ExecutionState.Starting, comp.State); + p.Cancel(); + ShouldThrow(() => p.Join(1000)); + Assert.AreEqual(ExecutionState.Failed, comp.State); + + Assert.IsInstanceOfType(comp.LastError, typeof(OperationCanceledException)); + + comp.Dispose(); + } + + [TestMethod] + public void StartStopTest() { + var stop = new Signal(); + var comp = new Runnable(true) { + MockStart = () => PromiseHelper.Sleep(100000, 0), + MockStop = () => AsyncPool.RunThread(stop.Wait) + }; + + var p1 = comp.Start(); + var p2 = comp.Stop(); + // should enter stopping state + + ShouldThrow(p1.Join); + Assert.IsTrue(p1.IsCancelled); + Assert.AreEqual(ExecutionState.Stopping, comp.State); + + stop.Set(); + p2.Join(1000); + Assert.AreEqual(ExecutionState.Disposed, comp.State); + } + + [TestMethod] + public void StartStopFailTest() { + var comp = new Runnable(true) { + MockStart = () => PromiseHelper.Sleep(100000, 0).Then(null,null,x => { throw new Exception("I'm dead"); }) + }; + + comp.Start(); + var p = comp.Stop(); + // if Start fails to cancel, should fail to stop + ShouldThrow(() => p.Join(1000)); + Assert.AreEqual(ExecutionState.Failed, comp.State); + Assert.IsNotNull(comp.LastError); + Assert.AreEqual("I'm dead", comp.LastError.Message); + } + + [TestMethod] + public void StopCancelTest() { + var comp = new Runnable(true) { + MockStop = () => PromiseHelper.Sleep(100000, 0) + }; + + comp.Start(); + var p = comp.Stop(); + Assert.AreEqual(ExecutionState.Stopping, comp.State); + p.Cancel(); + ShouldThrow(() => p.Join(1000)); + Assert.AreEqual(ExecutionState.Failed, comp.State); + Assert.IsInstanceOfType(comp.LastError, typeof(OperationCanceledException)); + + comp.Dispose(); + } + + } +} + diff -r 2a8466f0cb8a -r 1c2a16d071a7 Implab/AbstractEvent.cs --- a/Implab/AbstractEvent.cs Fri Feb 19 18:07:17 2016 +0300 +++ b/Implab/AbstractEvent.cs Fri Apr 22 13:08:08 2016 +0300 @@ -78,13 +78,9 @@ /// Данное обещание уже выполнено protected void SetError(Exception error) { if (BeginTransit()) { - if (error is OperationCanceledException) { - m_error = error.InnerException; - CompleteTransit(CANCELLED_STATE); - } else { - m_error = error is PromiseTransientException ? error.InnerException : error; - CompleteTransit(REJECTED_STATE); - } + m_error = error; + CompleteTransit(REJECTED_STATE); + Signal(); } else { WaitTransition(); @@ -139,11 +135,11 @@ case SUCCEEDED_STATE: return; case CANCELLED_STATE: - throw new OperationCanceledException(); + throw new OperationCanceledException("The operation has been cancelled", m_error); case REJECTED_STATE: throw new TargetInvocationException(m_error); default: - throw new ApplicationException(String.Format("Invalid promise state {0}", m_state)); + throw new ApplicationException(String.Format("The promise state {0} is invalid", m_state)); } } #endregion diff -r 2a8466f0cb8a -r 1c2a16d071a7 Implab/AbstractPromise.cs --- a/Implab/AbstractPromise.cs Fri Feb 19 18:07:17 2016 +0300 +++ b/Implab/AbstractPromise.cs Fri Apr 22 13:08:08 2016 +0300 @@ -134,8 +134,8 @@ } protected void SetResult() { - BeginSetResult(); - EndSetResult(); + if(BeginSetResult()) + EndSetResult(); } } } diff -r 2a8466f0cb8a -r 1c2a16d071a7 Implab/AbstractTask.cs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Implab/AbstractTask.cs Fri Apr 22 13:08:08 2016 +0300 @@ -0,0 +1,45 @@ +using System; +using System.Threading; + +namespace Implab { + /// + /// Базовый класс для реализации задачь. Задача представляет собой некторое + /// действие, которое можно иницировать и обработать результат его выполнения + /// в виде обещания, для этого оно реализует интерфейс . + /// + /// + /// Данный класс определяет стандартное поведение при обработки результатов, в частности + /// обработку и + /// + public abstract class AbstractTask : AbstractPromise { + int m_cancelationLock; + + /// + /// Получает эксклюзивное право отмены задания, используется для отмены задания до начала его выполнения. + /// + /// true, if cancelation was locked, false otherwise. + protected bool LockCancelation() { + return 0 == Interlocked.CompareExchange(ref m_cancelationLock, 1, 0); + } + + + + protected void SetErrorInternal(Exception error) { + // unwrap + while (error is PromiseTransientException && error.InnerException != null) + error = error.InnerException; + + if (error is OperationCanceledException) + SetCancelled(error); + else + SetError(error); + } + + protected void SetCancelledInternal(Exception reason) { + SetCancelled( + reason == null ? new OperationCanceledException() : reason is OperationCanceledException ? reason : new OperationCanceledException(null, reason) + ); + } + } +} + diff -r 2a8466f0cb8a -r 1c2a16d071a7 Implab/AbstractTaskT.cs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Implab/AbstractTaskT.cs Fri Apr 22 13:08:08 2016 +0300 @@ -0,0 +1,36 @@ +using System; +using System.Threading; + +namespace Implab { + public abstract class AbstractTask : AbstractPromise { + int m_cancelationLock; + + /// + /// Получает эксклюзивное право отмены задания, используется для отмены задания до начала его выполнения. + /// + /// true, if cancelation was locked, false otherwise. + protected bool LockCancelation() { + return 0 == Interlocked.CompareExchange(ref m_cancelationLock, 1, 0); + } + + + + protected void SetErrorInternal(Exception error) { + // unwrap + while (error is PromiseTransientException && error.InnerException != null) + error = error.InnerException; + + if (error is OperationCanceledException) + SetCancelled(error); + else + SetError(error); + } + + protected void SetCancelledInternal(Exception reason) { + SetCancelled( + reason == null ? new OperationCanceledException() : reason is OperationCanceledException ? reason : new OperationCanceledException(null, reason) + ); + } + } +} + diff -r 2a8466f0cb8a -r 1c2a16d071a7 Implab/ActionChainTask.cs --- a/Implab/ActionChainTask.cs Fri Feb 19 18:07:17 2016 +0300 +++ b/Implab/ActionChainTask.cs Fri Apr 22 13:08:08 2016 +0300 @@ -4,6 +4,15 @@ public class ActionChainTask : ActionChainTaskBase, IDeferred { readonly Func m_task; + /// + /// Initializes a new instance of the class. + /// + /// The operation which will be performed when the is called. + /// The error handler which will invoke when the is called or when the task fails with an error. + /// The cancellation handler. + /// If set to true will automatically accept + /// all cancel requests before the task is started with , + /// after that all requests are directed to the task. public ActionChainTask(Func task, Func error, Func cancel, bool autoCancellable) : base(error,cancel, autoCancellable) { m_task = task; } @@ -12,8 +21,10 @@ if (m_task != null && LockCancelation()) { try { var p = m_task(); - p.On(SetResult, HandleErrorInternal, SetCancelled); + p.On(SetResult, HandleErrorInternal, HandleCancelInternal); CancellationRequested(p.Cancel); + } catch (OperationCanceledException reason){ + HandleCancelInternal(reason); } catch(Exception err) { HandleErrorInternal(err); } diff -r 2a8466f0cb8a -r 1c2a16d071a7 Implab/ActionChainTaskBase.cs --- a/Implab/ActionChainTaskBase.cs Fri Feb 19 18:07:17 2016 +0300 +++ b/Implab/ActionChainTaskBase.cs Fri Apr 22 13:08:08 2016 +0300 @@ -2,12 +2,10 @@ using System.Threading; namespace Implab { - public class ActionChainTaskBase : AbstractPromise { + public class ActionChainTaskBase : AbstractTask { readonly Func m_error; readonly Func m_cancel; - int m_cancelationLock; - protected ActionChainTaskBase(Func error, Func cancel, bool autoCancellable) { m_error = error; m_cancel = cancel; @@ -20,19 +18,28 @@ HandleErrorInternal(error); } - + public override void CancelOperation(Exception reason) { + if (LockCancelation()) + // отмена вызвана до начала выполнения задачи + HandleCancelInternal(reason); + } - public override void CancelOperation(Exception reason) { - if (LockCancelation()) { - if (m_cancel != null) { - try { - m_cancel(reason).On(SetResult, SetError, SetCancelled); - } catch (Exception err) { - HandleErrorInternal(err); - } - } else { - SetCancelled(reason); + protected void HandleCancelInternal(Exception reason) { + if (m_cancel != null) { + try { + // вызываем обработчик отмены + var p = m_cancel(reason); + p.On(SetResult, HandleErrorInternal, SetCancelledInternal); + // сообщаем асинхронной операции, что клиент уже не хочет получать результат + // т.е. если он инициировал отмену, задача отменилась, вызвался обрабочик отмены + // отбработчику сообщили, что результат уже не нужен и уже сам обработчик решает + // отдавать ли результат или подтвердить отмену (или вернуть ошибку). + CancellationRequested(p.Cancel); + } catch (Exception err) { + HandleErrorInternal(err); } + } else { + HandleErrorInternal(reason ?? new OperationCanceledException()); } } @@ -40,19 +47,16 @@ if (m_error != null) { try { var p = m_error(error); - p.On(SetResult,SetError,SetCancelled); + p.On(SetResult, SetErrorInternal, SetCancelledInternal); CancellationRequested(p.Cancel); } catch (Exception err) { - SetError(err); + SetErrorInternal(error); } } else { - SetError(error); + SetErrorInternal(error); } } - protected bool LockCancelation() { - return 0 == Interlocked.CompareExchange(ref m_cancelationLock, 1, 0); - } } } diff -r 2a8466f0cb8a -r 1c2a16d071a7 Implab/ActionChainTaskT.cs --- a/Implab/ActionChainTaskT.cs Fri Feb 19 18:07:17 2016 +0300 +++ b/Implab/ActionChainTaskT.cs Fri Apr 22 13:08:08 2016 +0300 @@ -12,8 +12,10 @@ if (m_task != null && LockCancelation()) { try { var p = m_task(value); - p.On(SetResult, HandleErrorInternal, SetCancelled); + p.On(SetResult, HandleErrorInternal, HandleCancelInternal); CancellationRequested(p.Cancel); + } catch (OperationCanceledException reason) { + HandleCancelInternal(reason); } catch(Exception err) { HandleErrorInternal(err); } diff -r 2a8466f0cb8a -r 1c2a16d071a7 Implab/ActionTask.cs --- a/Implab/ActionTask.cs Fri Feb 19 18:07:17 2016 +0300 +++ b/Implab/ActionTask.cs Fri Apr 22 13:08:08 2016 +0300 @@ -12,6 +12,8 @@ try { m_task(); SetResult(); + } catch(OperationCanceledException reason) { + HandleCancelInternal(reason); } catch(Exception err) { HandleErrorInternal(err); } diff -r 2a8466f0cb8a -r 1c2a16d071a7 Implab/ActionTaskBase.cs --- a/Implab/ActionTaskBase.cs Fri Feb 19 18:07:17 2016 +0300 +++ b/Implab/ActionTaskBase.cs Fri Apr 22 13:08:08 2016 +0300 @@ -1,13 +1,10 @@ using System; -using System.Threading; namespace Implab { - public class ActionTaskBase : AbstractPromise { + public class ActionTaskBase : AbstractTask { readonly Action m_cancel; readonly Action m_error; - int m_cancelationLock; - protected ActionTaskBase( Action error, Action cancel, bool autoCancellable) { m_error = error; m_cancel = cancel; @@ -21,37 +18,36 @@ HandleErrorInternal(error); } + public override void CancelOperation(Exception reason) { + if (LockCancelation()) + HandleCancelInternal(reason); + } + protected void HandleErrorInternal(Exception error) { if (m_error != null) { try { m_error(error); SetResult(); } catch(Exception err) { - SetError(err); + SetErrorInternal(err); } } else { - SetError(error); + SetErrorInternal(error); } } - public override void CancelOperation(Exception reason) { - if (LockCancelation()) { - if (m_cancel != null) { - try { - m_cancel(reason); - SetResult(); - } catch (Exception err) { - HandleErrorInternal(err); - } - } else { - SetCancelled(reason); + protected void HandleCancelInternal(Exception error) { + if (m_cancel != null) { + try { + m_cancel(error); + SetResult(); + } catch(Exception err) { + HandleErrorInternal(err); } + } else { + HandleErrorInternal(error ?? new OperationCanceledException()); } } - - protected bool LockCancelation() { - return 0 == Interlocked.CompareExchange(ref m_cancelationLock, 1, 0); - } } } diff -r 2a8466f0cb8a -r 1c2a16d071a7 Implab/ActionTaskT.cs --- a/Implab/ActionTaskT.cs Fri Feb 19 18:07:17 2016 +0300 +++ b/Implab/ActionTaskT.cs Fri Apr 22 13:08:08 2016 +0300 @@ -12,6 +12,8 @@ try { m_task(value); SetResult(); + } catch(OperationCanceledException reason) { + HandleCancelInternal(reason); } catch(Exception err) { HandleErrorInternal(err); } diff -r 2a8466f0cb8a -r 1c2a16d071a7 Implab/Automaton/AutomatonConst.cs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Implab/Automaton/AutomatonConst.cs Fri Apr 22 13:08:08 2016 +0300 @@ -0,0 +1,9 @@ + +namespace Implab.Automaton { + public static class AutomatonConst { + public const int UNREACHABLE_STATE = -1; + + public const int UNCLASSIFIED_INPUT = 0; + } +} + diff -r 2a8466f0cb8a -r 1c2a16d071a7 Implab/Automaton/AutomatonTransition.cs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Implab/Automaton/AutomatonTransition.cs Fri Apr 22 13:08:08 2016 +0300 @@ -0,0 +1,33 @@ +using System; + +namespace Implab.Automaton { + public struct AutomatonTransition : IEquatable { + public readonly int s1; + public readonly int s2; + public readonly int edge; + + public AutomatonTransition(int s1, int s2, int edge) { + this.s1 = s1; + this.s2 = s2; + this.edge = edge; + } + + + #region IEquatable implementation + public bool Equals(AutomatonTransition other) { + return other.s1 == s1 && other.s2 == s2 && other.edge == edge ; + } + #endregion + + public override bool Equals(object obj) { + if (obj is AutomatonTransition) + return Equals((AutomatonTransition)obj); + return base.Equals(obj); + } + + public override int GetHashCode() { + return s1 + s2 + edge; + } + } +} + diff -r 2a8466f0cb8a -r 1c2a16d071a7 Implab/Automaton/DFATable.cs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Implab/Automaton/DFATable.cs Fri Apr 22 13:08:08 2016 +0300 @@ -0,0 +1,348 @@ +using Implab; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Diagnostics; +using System.IO; +using System.CodeDom.Compiler; +using System.CodeDom; + +namespace Implab.Automaton { + public class DFATable : IDFATableBuilder { + int m_stateCount; + int m_symbolCount; + int m_initialState; + + readonly HashSet m_finalStates = new HashSet(); + readonly HashSet m_transitions = new HashSet(); + + + #region IDFADefinition implementation + + public bool IsFinalState(int s) { + Safe.ArgumentInRange(s, 0, m_stateCount, "s"); + + return m_finalStates.Contains(s); + } + + public IEnumerable FinalStates { + get { + return m_finalStates; + } + } + + public int StateCount { + get { return m_stateCount; } + } + + public int AlphabetSize { + get { return m_symbolCount; } + } + + public int InitialState { + get { return m_initialState; } + } + + #endregion + + public void SetInitialState(int s) { + Safe.ArgumentAssert(s >= 0, "s"); + m_stateCount = Math.Max(m_stateCount, s + 1); + m_initialState = s; + } + + public void MarkFinalState(int state) { + m_stateCount = Math.Max(m_stateCount, state + 1); + m_finalStates.Add(state); + } + + public void Add(AutomatonTransition item) { + Safe.ArgumentAssert(item.s1 >= 0, "item"); + Safe.ArgumentAssert(item.s2 >= 0, "item"); + Safe.ArgumentAssert(item.edge >= 0, "item"); + + m_stateCount = Math.Max(m_stateCount, Math.Max(item.s1, item.s2) + 1); + m_symbolCount = Math.Max(m_symbolCount, item.edge + 1); + + m_transitions.Add(item); + } + + public void Clear() { + m_stateCount = 0; + m_symbolCount = 0; + m_finalStates.Clear(); + m_transitions.Clear(); + } + + public bool Contains(AutomatonTransition item) { + return m_transitions.Contains(item); + } + + public void CopyTo(AutomatonTransition[] array, int arrayIndex) { + m_transitions.CopyTo(array, arrayIndex); + } + + public bool Remove(AutomatonTransition item) { + return m_transitions.Remove(item); + } + + public int Count { + get { + return m_transitions.Count; + } + } + + public bool IsReadOnly { + get { + return false; + } + } + + public IEnumerator GetEnumerator() { + return m_transitions.GetEnumerator(); + } + + System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { + return GetEnumerator(); + } + + public void AddSymbol(int symbol) { + Safe.ArgumentAssert(symbol >= 0, "symbol"); + m_symbolCount = Math.Max(symbol + 1, m_symbolCount); + } + + public int[,] CreateTransitionTable() { + var table = new int[StateCount,AlphabetSize]; + + for (int i = 0; i < StateCount; i++) + for (int j = 0; j < AlphabetSize; j++) + table[i, j] = AutomatonConst.UNREACHABLE_STATE; + + foreach (var t in this) + table[t.s1,t.edge] = t.s2; + + return table; + } + + public bool[] CreateFinalStateTable() { + var table = new bool[StateCount]; + + foreach (var s in FinalStates) + table[s] = true; + + return table; + } + + /// Формирует множества конечных состояний перед началом работы алгоритма минимизации. + /// + /// В процессе построения минимального автомата требуется разделить множество состояний, + /// на два подмножества - конечные состояния и все остальные, после чего эти подмножества + /// будут резделены на более мелкие. Иногда требуется гарантировать различия конечных сосотяний, + /// для этого необходимо переопределить даннцю фукнцию, для получения множеств конечных состояний. + /// + /// The final states. + protected virtual IEnumerable> SplitFinalStates(IEnumerable states) { + return new [] { new HashSet(states) }; + } + + protected void Optimize( + IDFATableBuilder optimalDFA, + IDictionary alphabetMap, + IDictionary stateMap + ) { + Safe.ArgumentNotNull(optimalDFA, "dfa"); + Safe.ArgumentNotNull(alphabetMap, "alphabetMap"); + Safe.ArgumentNotNull(stateMap, "stateMap"); + + + var setComparer = new CustomEqualityComparer>( + (x, y) => x.SetEquals(y), + s => s.Sum(x => x.GetHashCode()) + ); + + var optimalStates = new HashSet>(setComparer); + var queue = new HashSet>(setComparer); + + optimalStates.Add(new HashSet(FinalStates)); + + var state = new HashSet( + Enumerable + .Range(0, m_stateCount) + .Where(i => !m_finalStates.Contains(i)) + ); + + optimalStates.Add(state); + queue.Add(state); + + var rmap = m_transitions + .GroupBy(t => t.s2) + .ToDictionary( + g => g.Key, // s2 + g => g.ToLookup(t => t.edge, t => t.s1)//.ToDictionary(p => p.Key) + ); + + while (queue.Count > 0) { + var stateA = queue.First(); + queue.Remove(stateA); + + for (int c = 0; c < m_symbolCount; c++) { + var stateX = new HashSet(); + foreach(var a in stateA.Where(rmap.ContainsKey)) + stateX.UnionWith(rmap[a][c]); // all states from wich the symbol 'c' leads to the state 'a' + + var tmp = optimalStates.ToArray(); + foreach (var stateY in tmp) { + var stateR1 = new HashSet(stateY); + var stateR2 = new HashSet(stateY); + + stateR1.IntersectWith(stateX); + stateR2.ExceptWith(stateX); + + if (stateR1.Count > 0 && stateR2.Count > 0) { + + + optimalStates.Remove(stateY); + optimalStates.Add(stateR1); + optimalStates.Add(stateR2); + + if (queue.Contains(stateY)) { + queue.Remove(stateY); + queue.Add(stateR1); + queue.Add(stateR2); + } else { + queue.Add(stateR1.Count <= stateR2.Count ? stateR1 : stateR2); + } + } + } + } + } + + // дополнительно разбиваем конечные состояния + foreach (var final in optimalStates.Where(s => s.Overlaps(m_finalStates)).ToArray()) { + optimalStates.Remove(final); + foreach (var split in SplitFinalStates(final)) + optimalStates.Add(split); + } + + + // карта получения оптимального состояния по соотвествующему ему простому состоянию + var nextState = 0; + foreach (var item in optimalStates) { + var id = nextState++; + foreach (var s in item) + stateMap[s] = id; + } + + // получаем минимальный алфавит + // входные символы не различимы, если Move(s,a1) == Move(s,a2), для любого s + // для этого используем алгоритм кластеризации, сначала + // считаем, что все символы не различимы + + var minClasses = new HashSet>(setComparer); + var alphaQueue = new Queue>(); + alphaQueue.Enqueue(new HashSet(Enumerable.Range(0,AlphabetSize))); + + // для всех состояний, будем проверять каждый класс на различимость, + // т.е. символы различимы, если они приводят к разным состояниям + for (int s = 0 ; s < optimalStates.Count; s++) { + var newQueue = new Queue>(); + + foreach (var A in alphaQueue) { + // классы из одного символа делить бесполезно, переводим их сразу в + // результирующий алфавит + if (A.Count == 1) { + minClasses.Add(A); + continue; + } + + // различаем классы символов, которые переводят в различные оптимальные состояния + // optimalState -> alphaClass + var classes = new Dictionary>(); + + foreach (var term in A) { + // ищем все переходы класса по символу term + var s2 = m_transitions.Where(t => stateMap[t.s1] == s && t.edge == term).Select(t => stateMap[t.s2]).DefaultIfEmpty(-1).First(); + + HashSet a2; + if (!classes.TryGetValue(s2, out a2)) { + a2 = new HashSet(); + newQueue.Enqueue(a2); + classes[s2] = a2; + } + a2.Add(term); + } + } + + if (newQueue.Count == 0) + break; + alphaQueue = newQueue; + } + + // после окончания работы алгоритма в очереди останутся минимальные различимые классы + // входных символов + foreach (var A in alphaQueue) + minClasses.Add(A); + + // построение отображения алфавитов входных символов. + // поскольку символ DFAConst.UNCLASSIFIED_INPUT может иметь + // специальное значение, тогда сохраним минимальный класс, + // содержащий этот символ на томже месте. + + var nextCls = 0; + foreach (var item in minClasses) { + if (nextCls == AutomatonConst.UNCLASSIFIED_INPUT) + nextCls++; + + // сохраняем DFAConst.UNCLASSIFIED_INPUT + var cls = item.Contains(AutomatonConst.UNCLASSIFIED_INPUT) ? AutomatonConst.UNCLASSIFIED_INPUT : nextCls++; + optimalDFA.AddSymbol(cls); + + foreach (var a in item) + alphabetMap[a] = cls; + } + + // построение автомата + optimalDFA.SetInitialState(stateMap[m_initialState]); + + foreach (var sf in m_finalStates.Select(s => stateMap[s]).Distinct()) + optimalDFA.MarkFinalState(sf); + + foreach (var t in m_transitions.Select(t => new AutomatonTransition(stateMap[t.s1],stateMap[t.s2],alphabetMap[t.edge])).Distinct()) + optimalDFA.Add(t); + } + + protected string PrintDFA(IAlphabet inputAlphabet, IAlphabet stateAlphabet) { + Safe.ArgumentNotNull(inputAlphabet, "inputAlphabet"); + Safe.ArgumentNotNull(stateAlphabet, "stateAlphabet"); + + var data = new List(); + + data.Add("digraph dfa {"); + + foreach (var final in m_finalStates) + data.Add(String.Format("{0} [shape=box];",String.Join("", stateAlphabet.GetSymbols(final)))); + + foreach (var t in m_transitions) + data.Add(String.Format( + "{0} -> {2} [label={1}];", + String.Join("", stateAlphabet.GetSymbols(t.s1)), + ToLiteral(ToLiteral(String.Join("", t.edge == AutomatonConst.UNCLASSIFIED_INPUT ? new [] { "@" } : inputAlphabet.GetSymbols(t.edge).Select(x => x.ToString())))), + String.Join("", stateAlphabet.GetSymbols(t.s2)) + )); + data.Add("}"); + return String.Join("\n", data); + } + + static string ToLiteral(string input) + { + using (var writer = new StringWriter()) + { + using (var provider = CodeDomProvider.CreateProvider("CSharp")) + { + provider.GenerateCodeFromExpression(new CodePrimitiveExpression(input), writer, null); + return writer.ToString(); + } + } + } + } +} diff -r 2a8466f0cb8a -r 1c2a16d071a7 Implab/Automaton/EnumAlphabet.cs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Implab/Automaton/EnumAlphabet.cs Fri Apr 22 13:08:08 2016 +0300 @@ -0,0 +1,66 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Globalization; +using System.Linq; +using System.Diagnostics.CodeAnalysis; + +namespace Implab.Automaton { + /// + /// Алфавит символами которого являются элементы перечислений. + /// + /// Тип перечислений + public class EnumAlphabet : IndexedAlphabetBase where T : struct, IConvertible { + [SuppressMessage("Microsoft.Design", "CA1000:DoNotDeclareStaticMembersOnGenericTypes")] + static readonly Lazy _symbols = new Lazy(GetSymbols); + + [SuppressMessage("Microsoft.Design", "CA1000:DoNotDeclareStaticMembersOnGenericTypes")] + static readonly Lazy> _fullAlphabet = new Lazy>(CreateEnumAlphabet); + + static EnumAlphabet CreateEnumAlphabet() { + var symbols = _symbols.Value; + + if ( + symbols[symbols.Length - 1].ToInt32(CultureInfo.InvariantCulture) >= symbols.Length + || symbols[0].ToInt32(CultureInfo.InvariantCulture) != 0 + ) + throw new InvalidOperationException("The specified enumeration must be zero-based and continuously numbered"); + + return new EnumAlphabet(symbols.Select(x => x.ToInt32(CultureInfo.InvariantCulture)).ToArray()); + } + + static T[] GetSymbols() { + if (!typeof(T).IsEnum) + throw new InvalidOperationException("Invalid generic parameter, enumeration is required"); + + if (Enum.GetUnderlyingType(typeof(T)) != typeof(Int32)) + throw new InvalidOperationException("Only enums based on Int32 are supported"); + + return ((T[])Enum.GetValues(typeof(T))) + .OrderBy(x => x.ToInt32(CultureInfo.InvariantCulture)) + .ToArray(); + } + + public static EnumAlphabet FullAlphabet { + get { + return _fullAlphabet.Value; + } + } + + + public EnumAlphabet() + : base(_symbols.Value.Length) { + } + + public EnumAlphabet(int[] map) + : base(map) { + Debug.Assert(map.Length == _symbols.Value.Length); + } + + + public override int GetSymbolIndex(T symbol) { + return symbol.ToInt32(CultureInfo.InvariantCulture); + } + + } +} diff -r 2a8466f0cb8a -r 1c2a16d071a7 Implab/Automaton/IAlphabet.cs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Implab/Automaton/IAlphabet.cs Fri Apr 22 13:08:08 2016 +0300 @@ -0,0 +1,34 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Implab.Automaton { + /// + /// Алфавит. Множество символов, которые разбиты на классы, при этом классы имеют непрерывную нумерацию, + /// что позволяет использовать их в качестве индексов массивов. + /// + /// + /// Алфавит является сюрьективным отображением множества символов в множество индексов, это позволяет сократить размер таблицы переходов автомата + /// для входных символов, которые для него не различимы. + /// + /// Тип символов. + public interface IAlphabet { + /// + /// Количество классов символов в алфавите. + /// + int Count { get; } + + /// + /// Преобразует входной символ в индекс символа из алфавита. + /// + /// Исходный символ + /// Индекс в алфавите + int Translate(TSymbol symobl); + + bool Contains(TSymbol symbol); + + IEnumerable GetSymbols(int cls); + } +} diff -r 2a8466f0cb8a -r 1c2a16d071a7 Implab/Automaton/IAlphabetBuilder.cs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Implab/Automaton/IAlphabetBuilder.cs Fri Apr 22 13:08:08 2016 +0300 @@ -0,0 +1,26 @@ + +using System.Collections.Generic; + +namespace Implab.Automaton { + public interface IAlphabetBuilder : IAlphabet { + /// + /// Добавляет новый символ в алфавит, если символ уже был добавлен, то + /// возвращается ранее сопоставленный с символом класс. + /// + /// Символ для добавления. + /// Индекс класса, который попоставлен с символом. + int DefineSymbol(TSymbol symbol); + + int DefineSymbol(TSymbol symbol, int cls); + /// + /// Доабвляем класс символов. Множеству указанных исходных символов + /// будет сопоставлен символ в алфавите. + /// + /// Множестов исходных символов + /// Идентификатор символа алфавита. + int DefineClass(IEnumerable symbols); + + int DefineClass(IEnumerable symbols, int cls); + } +} + diff -r 2a8466f0cb8a -r 1c2a16d071a7 Implab/Automaton/IDFATable.cs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Implab/Automaton/IDFATable.cs Fri Apr 22 13:08:08 2016 +0300 @@ -0,0 +1,53 @@ +using System.Collections.Generic; + + +namespace Implab.Automaton { + /// + /// Полностью описывает DFA автомат, его поведение, состояние и входные символы. + /// + /// + /// class MyAutomaton { + /// int m_current; + /// readonly DFAStateDescriptor[] m_automaton; + /// readonly IAlphabet m_commands; + /// + /// public MyAutomaton(IDFADefinition<MyCommands,MyStates,string> definition) { + /// m_current = definition.StateAlphabet.Translate(MyStates.Initial); + /// m_automaton = definition.GetTransitionTable(); + /// m_commands = definition.InputAlphabet; + /// } + /// + /// // defined a method which will move the automaton to the next state + /// public void Move(MyCommands cmd) { + /// // use transition map to determine the next state + /// var next = m_automaton[m_current].transitions[m_commands.Translate(cmd)]; + /// + /// // validate that we aren't in the unreachable state + /// if (next == DFAConst.UNREACHABLE_STATE) + /// throw new InvalidOperationException("The specified command is invalid"); + /// + /// // if everything is ok + /// m_current = next; + /// } + /// } + /// + public interface IDFATable : IEnumerable { + int StateCount { + get; + } + + int AlphabetSize { + get; + } + + int InitialState { + get; + } + + bool IsFinalState(int s); + + IEnumerable FinalStates { + get; + } + } +} diff -r 2a8466f0cb8a -r 1c2a16d071a7 Implab/Automaton/IDFATableBuilder.cs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Implab/Automaton/IDFATableBuilder.cs Fri Apr 22 13:08:08 2016 +0300 @@ -0,0 +1,26 @@ +using System; +using System.Collections.Generic; + +namespace Implab.Automaton { + public interface IDFATableBuilder : IDFATable, ICollection { + /// + /// Marks the state as final. + /// + /// State. + void MarkFinalState(int state); + + void SetInitialState(int s); + + /// + /// Increases if needed the input alphabet size to hold the specified symbol. + /// + /// + /// + /// AlphabetSize = Math.Max(AlphabetSize, symbol + 1) + /// + /// + /// Symbol. + void AddSymbol(int symbol); + } +} + diff -r 2a8466f0cb8a -r 1c2a16d071a7 Implab/Automaton/IndexedAlphabetBase.cs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Implab/Automaton/IndexedAlphabetBase.cs Fri Apr 22 13:08:08 2016 +0300 @@ -0,0 +1,50 @@ +using Implab; +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; + +namespace Implab.Automaton { + /// + /// Indexed alphabet is the finite set of symbols where each symbol has a zero-based unique index. + /// + /// + /// Indexed alphabets are usefull in bulting efficient translations from source alphabet + /// to the input alphabet of the automaton. It's assumed that the index to the symbol match + /// is well known and documented. + /// + public abstract class IndexedAlphabetBase : MapAlphabet { + + protected IndexedAlphabetBase() :base(true, null) { + } + + public abstract int GetSymbolIndex(T symbol); + + /// + /// Gets the translation map from the index of the symbol to it's class this is usefull for the optimized input symbols transtaion. + /// + /// + /// The map is continous and start from the symbol with zero code. The last symbol + /// in the map is the last classified symbol in the alphabet, i.e. the map can be + /// shorter then the whole alphabet. + /// + /// The translation map. + public int[] GetTranslationMap() { + var map = new Dictionary(); + + int max = 0; + foreach (var p in Mappings) { + var index = GetSymbolIndex(p.Key); + max = Math.Max(max, index); + map[index] = p.Value; + } + + var result = new int[max + 1]; + + for (int i = 0; i < result.Length; i++) + map.TryGetValue(i, out result[i]); + + return result; + } + } +} diff -r 2a8466f0cb8a -r 1c2a16d071a7 Implab/Automaton/MapAlphabet.cs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Implab/Automaton/MapAlphabet.cs Fri Apr 22 13:08:08 2016 +0300 @@ -0,0 +1,84 @@ +using System; +using System.Collections.Generic; +using System.Linq; + +namespace Implab.Automaton { + public class MapAlphabet : IAlphabetBuilder { + readonly Dictionary m_map; + int m_nextCls; + readonly bool m_supportUnclassified; + + public MapAlphabet(bool supportUnclassified, IEqualityComparer comparer) { + m_map = comparer != null ? new Dictionary(comparer) : new Dictionary(); + m_supportUnclassified = supportUnclassified; + m_nextCls = supportUnclassified ? 1 : 0; + } + + #region IAlphabetBuilder implementation + + public int DefineSymbol(T symbol) { + int cls; + return m_map.TryGetValue(symbol, out cls) ? cls : DefineSymbol(symbol, m_nextCls); + } + + public int DefineSymbol(T symbol, int cls) { + Safe.ArgumentAssert(cls >= 0, "cls"); + + m_nextCls = Math.Max(cls + 1, m_nextCls); + m_map.Add(symbol, cls); + return cls; + } + + public int DefineClass(IEnumerable symbols) { + return DefineClass(symbols, m_nextCls); + } + + public int DefineClass(IEnumerable symbols, int cls) { + Safe.ArgumentAssert(cls >= 0, "cls"); + Safe.ArgumentNotNull(symbols, "symbols"); + + m_nextCls = Math.Max(cls + 1, m_nextCls); + + foreach (var symbol in symbols) + m_map[symbol] = cls; + return cls; + } + + #endregion + + #region IAlphabet implementation + + public int Translate(T symbol) { + int cls; + if (m_map.TryGetValue(symbol, out cls)) + return cls; + if (!m_supportUnclassified) + throw new ArgumentOutOfRangeException("symbol", "The specified symbol isn't in the alphabet"); + return AutomatonConst.UNCLASSIFIED_INPUT; + } + + public int Count { + get { + return m_nextCls; + } + } + + public bool Contains(T symbol) { + return m_supportUnclassified || m_map.ContainsKey(symbol); + } + + + public IEnumerable GetSymbols(int cls) { + Safe.ArgumentAssert(!m_supportUnclassified || cls > 0, "cls"); + return m_map.Where(p => p.Value == cls).Select(p => p.Key); + } + #endregion + + public IEnumerable> Mappings { + get { + return m_map; + } + } + } +} + diff -r 2a8466f0cb8a -r 1c2a16d071a7 Implab/Automaton/ParserException.cs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Implab/Automaton/ParserException.cs Fri Apr 22 13:08:08 2016 +0300 @@ -0,0 +1,17 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace Implab.Automaton { + [Serializable] + public class ParserException : Exception { + public ParserException() { } + public ParserException(string message) : base(message) { } + public ParserException(string message, Exception inner) : base(message, inner) { } + protected ParserException( + System.Runtime.Serialization.SerializationInfo info, + System.Runtime.Serialization.StreamingContext context) + : base(info, context) { } + } +} diff -r 2a8466f0cb8a -r 1c2a16d071a7 Implab/Automaton/RegularExpressions/AltToken.cs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Implab/Automaton/RegularExpressions/AltToken.cs Fri Apr 22 13:08:08 2016 +0300 @@ -0,0 +1,17 @@ +using System; + +namespace Implab.Automaton.RegularExpressions { + public class AltToken: BinaryToken { + public AltToken(Token left, Token right) + : base(left, right) { + } + + public override void Accept(IVisitor visitor) { + Safe.ArgumentNotNull(visitor, "visitor"); + visitor.Visit(this); + } + public override string ToString() { + return String.Format(Right is BinaryToken ? "{0}|({1})" : "{0}|{1}", Left, Right); + } + } +} diff -r 2a8466f0cb8a -r 1c2a16d071a7 Implab/Automaton/RegularExpressions/BinaryToken.cs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Implab/Automaton/RegularExpressions/BinaryToken.cs Fri Apr 22 13:08:08 2016 +0300 @@ -0,0 +1,21 @@ +using Implab; + +namespace Implab.Automaton.RegularExpressions { + public abstract class BinaryToken: Token { + readonly Token m_left; + readonly Token m_right; + + public Token Left { + get { return m_left; } + } + + public Token Right { + get { return m_right; } + } + + protected BinaryToken(Token left, Token right) { + Safe.ArgumentNotNull(m_left = left, "left"); + Safe.ArgumentNotNull(m_right = right, "right"); + } + } +} diff -r 2a8466f0cb8a -r 1c2a16d071a7 Implab/Automaton/RegularExpressions/CatToken.cs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Implab/Automaton/RegularExpressions/CatToken.cs Fri Apr 22 13:08:08 2016 +0300 @@ -0,0 +1,22 @@ +using System; + +namespace Implab.Automaton.RegularExpressions { + public class CatToken : BinaryToken { + public CatToken(Token left, Token right) + : base(left, right) { + } + + public override void Accept(IVisitor visitor) { + Safe.ArgumentNotNull(visitor, "visitor"); + visitor.Visit(this); + } + + public override string ToString() { + return String.Format("{0}{1}", FormatToken(Left), FormatToken(Right)); + } + + static string FormatToken(Token token) { + return String.Format(token is AltToken ? "({0})" : "{0}", token); + } + } +} diff -r 2a8466f0cb8a -r 1c2a16d071a7 Implab/Automaton/RegularExpressions/EmptyToken.cs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Implab/Automaton/RegularExpressions/EmptyToken.cs Fri Apr 22 13:08:08 2016 +0300 @@ -0,0 +1,13 @@ +using Implab; + +namespace Implab.Automaton.RegularExpressions { + public class EmptyToken: Token { + public override void Accept(IVisitor visitor) { + Safe.ArgumentNotNull(visitor, "visitor"); + visitor.Visit(this); + } + public override string ToString() { + return "$"; + } + } +} diff -r 2a8466f0cb8a -r 1c2a16d071a7 Implab/Automaton/RegularExpressions/EndToken.cs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Implab/Automaton/RegularExpressions/EndToken.cs Fri Apr 22 13:08:08 2016 +0300 @@ -0,0 +1,18 @@ +using Implab; + +namespace Implab.Automaton.RegularExpressions { + /// + /// Конечный символ расширенного регулярного выражения, при построении ДКА + /// используется для определения конечных состояний. + /// + public class EndToken: Token { + + public override void Accept(IVisitor visitor) { + Safe.ArgumentNotNull(visitor, "visitor"); + visitor.Visit(this); + } + public override string ToString() { + return "#"; + } + } +} diff -r 2a8466f0cb8a -r 1c2a16d071a7 Implab/Automaton/RegularExpressions/EndTokenT.cs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Implab/Automaton/RegularExpressions/EndTokenT.cs Fri Apr 22 13:08:08 2016 +0300 @@ -0,0 +1,23 @@ +namespace Implab.Automaton.RegularExpressions { + /// + /// Конечный символ расширенного регулярного выражения, при построении ДКА + /// используется для определения конечных состояний. + /// + public class EndToken: EndToken { + + readonly TTag m_tag; + + public EndToken(TTag tag) { + m_tag = tag; + } + + public EndToken() + : this(default(TTag)) { + } + + public TTag Tag { + get { return m_tag; } + } + + } +} diff -r 2a8466f0cb8a -r 1c2a16d071a7 Implab/Automaton/RegularExpressions/ITaggedDFABuilder.cs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Implab/Automaton/RegularExpressions/ITaggedDFABuilder.cs Fri Apr 22 13:08:08 2016 +0300 @@ -0,0 +1,7 @@ + +namespace Implab.Automaton.RegularExpressions { + public interface ITaggedDFABuilder : IDFATableBuilder { + void SetStateTag(int s, TTag[] tags); + } +} + diff -r 2a8466f0cb8a -r 1c2a16d071a7 Implab/Automaton/RegularExpressions/IVisitor.cs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Implab/Automaton/RegularExpressions/IVisitor.cs Fri Apr 22 13:08:08 2016 +0300 @@ -0,0 +1,13 @@ +namespace Implab.Automaton.RegularExpressions { + /// + /// Интерфейс обходчика синтаксического дерева регулярного выражения + /// + public interface IVisitor { + void Visit(AltToken token); + void Visit(StarToken token); + void Visit(CatToken token); + void Visit(EmptyToken token); + void Visit(EndToken token); + void Visit(SymbolToken token); + } +} diff -r 2a8466f0cb8a -r 1c2a16d071a7 Implab/Automaton/RegularExpressions/RegularDFA.cs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Implab/Automaton/RegularExpressions/RegularDFA.cs Fri Apr 22 13:08:08 2016 +0300 @@ -0,0 +1,91 @@ +using System.Collections.Generic; +using System.Linq; + +namespace Implab.Automaton.RegularExpressions { + public class RegularDFA : DFATable, ITaggedDFABuilder { + + readonly Dictionary m_tags = new Dictionary(); + readonly IAlphabet m_alphabet; + + public RegularDFA(IAlphabet alphabet) { + Safe.ArgumentNotNull(alphabet, "aplhabet"); + + m_alphabet = alphabet; + } + + + public IAlphabet InputAlphabet { + get { + return m_alphabet; + } + } + + public void MarkFinalState(int s, TTag[] tags) { + MarkFinalState(s); + SetStateTag(s, tags); + } + + public void SetStateTag(int s, TTag[] tags) { + Safe.ArgumentNotNull(tags, "tags"); + m_tags[s] = tags; + } + + public TTag[] GetStateTag(int s) { + TTag[] tags; + return m_tags.TryGetValue(s, out tags) ? tags : new TTag[0]; + } + + public TTag[][] CreateTagTable() { + var table = new TTag[StateCount][]; + + foreach (var pair in m_tags) + table[pair.Key] = pair.Value; + + return table; + } + + /// + /// Optimize the specified alphabet. + /// + /// Пустой алфавит, который будет зполнен в процессе оптимизации. + public RegularDFA Optimize(IAlphabetBuilder alphabet) { + Safe.ArgumentNotNull(alphabet, "alphabet"); + + var dfa = new RegularDFA(alphabet); + + var alphaMap = new Dictionary(); + var stateMap = new Dictionary(); + + Optimize(dfa, alphaMap, stateMap); + + // mark tags in the new DFA + foreach (var g in m_tags.Where(x => x.Key < StateCount).GroupBy(x => stateMap[x.Key], x => x.Value )) + dfa.SetStateTag(g.Key, g.SelectMany(x => x).ToArray()); + + // make the alphabet for the new DFA + // skip all unclassified symbols + foreach (var pair in alphaMap.Where(x => x.Value != 0)) + alphabet.DefineClass(m_alphabet.GetSymbols(pair.Key), pair.Value); + return dfa; + } + + protected override IEnumerable> SplitFinalStates(IEnumerable states) { + var arrayComparer = new CustomEqualityComparer( + (x,y) => x.Length == y.Length && x.All(it => y.Contains(it)), + x => x.Sum(it => x.GetHashCode()) + ); + return states.GroupBy(x => m_tags[x] ?? new TTag[0], arrayComparer).Select(g => new HashSet(g)); + } + + public override string ToString() { + var states = new MapAlphabet(false, null); + + for (int i = 0; i < StateCount; i++) + states.DefineSymbol(string.Format("s{0}", i), i); + + return string.Format("//[RegularDFA {1} x {2}]\n{0}", PrintDFA(InputAlphabet, states),StateCount, AlphabetSize); + } + + } +} + diff -r 2a8466f0cb8a -r 1c2a16d071a7 Implab/Automaton/RegularExpressions/RegularExpressionVisitor.cs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Implab/Automaton/RegularExpressions/RegularExpressionVisitor.cs Fri Apr 22 13:08:08 2016 +0300 @@ -0,0 +1,212 @@ +using Implab; +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; + +namespace Implab.Automaton.RegularExpressions { + /// + /// Используется для построения ДКА по регулярному выражению, сначала обходит + /// регулярное выражение и вычисляет followpos, затем используется метод + /// для построения автомата. + /// + public class RegularExpressionVisitor : IVisitor { + int m_idx; + Token m_root; + HashSet m_firstpos; + HashSet m_lastpos; + + readonly Dictionary> m_followpos = new Dictionary>(); + readonly Dictionary m_indexes = new Dictionary(); + readonly HashSet m_ends = new HashSet(); + + readonly IDFATableBuilder m_builder; + readonly IAlphabetBuilder> m_states = new MapAlphabet>( + false, + new CustomEqualityComparer>( + (x, y) => x.SetEquals(y), + x => x.Sum(n => n.GetHashCode()) + ) + ); + + public RegularExpressionVisitor(IDFATableBuilder builder) { + Safe.ArgumentNotNull(builder, "builder"); + + m_builder = builder; + } + + HashSet Followpos(int pos) { + HashSet set; + return m_followpos.TryGetValue(pos, out set) ? set : m_followpos[pos] = new HashSet(); + } + + bool Nullable(object n) { + if (n is EmptyToken || n is StarToken) + return true; + var altToken = n as AltToken; + if (altToken != null) + return Nullable(altToken.Left) || Nullable(altToken.Right); + var catToken = n as CatToken; + if (catToken != null) + return Nullable(catToken.Left) && Nullable(catToken.Right); + return false; + } + + protected int Index { + get { return m_idx; } + } + + public void Visit(AltToken token) { + if (m_root == null) + m_root = token; + var firtspos = new HashSet(); + var lastpos = new HashSet(); + + token.Left.Accept(this); + firtspos.UnionWith(m_firstpos); + lastpos.UnionWith(m_lastpos); + + token.Right.Accept(this); + firtspos.UnionWith(m_firstpos); + lastpos.UnionWith(m_lastpos); + + m_firstpos = firtspos; + m_lastpos = lastpos; + } + + public void Visit(StarToken token) { + if (m_root == null) + m_root = token; + token.Token.Accept(this); + + foreach (var i in m_lastpos) + Followpos(i).UnionWith(m_firstpos); + } + + public void Visit(CatToken token) { + if (m_root == null) + m_root = token; + + var firtspos = new HashSet(); + var lastpos = new HashSet(); + token.Left.Accept(this); + firtspos.UnionWith(m_firstpos); + var leftLastpos = m_lastpos; + + token.Right.Accept(this); + lastpos.UnionWith(m_lastpos); + var rightFirstpos = m_firstpos; + + if (Nullable(token.Left)) + firtspos.UnionWith(rightFirstpos); + + if (Nullable(token.Right)) + lastpos.UnionWith(leftLastpos); + + m_firstpos = firtspos; + m_lastpos = lastpos; + + foreach (var i in leftLastpos) + Followpos(i).UnionWith(rightFirstpos); + + } + + public void Visit(EmptyToken token) { + if (m_root == null) + m_root = token; + } + + public void Visit(SymbolToken token) { + if (m_root == null) + m_root = token; + m_idx++; + m_indexes[m_idx] = token.Value; + m_firstpos = new HashSet(new[] { m_idx }); + m_lastpos = new HashSet(new[] { m_idx }); + } + + public virtual void Visit(EndToken token) { + if (m_root == null) + m_root = token; + m_idx++; + m_indexes[m_idx] = AutomatonConst.UNCLASSIFIED_INPUT; + m_firstpos = new HashSet(new[] { m_idx }); + m_lastpos = new HashSet(new[] { m_idx }); + Followpos(m_idx); + m_ends.Add(m_idx); + } + + public void BuildDFA() { + AddState(m_firstpos); + SetInitialState(m_firstpos); + + if(IsFinal(m_firstpos)) + MarkFinalState(m_firstpos); + + var inputMax = m_indexes.Values.Max(); + var queue = new Queue>(); + + queue.Enqueue(m_firstpos); + + while (queue.Count > 0) { + var s1 = queue.Dequeue(); + + for (int a = 0; a <= inputMax; a++) { + var s2 = new HashSet(); + foreach (var p in s1) { + if (m_indexes[p] == a) { + s2.UnionWith(Followpos(p)); + } + } + if (s2.Count > 0) { + if (!HasState(s2)) { + AddState(s2); + if (IsFinal(s2)) + MarkFinalState(s2); + + queue.Enqueue(s2); + } + + DefineTransition(s1, s2, a); + } + + } + } + } + + protected bool HasState(HashSet state) { + return m_states.Contains(state); + } + + protected void AddState(HashSet state) { + Debug.Assert(!HasState(state)); + + m_states.DefineSymbol(state); + } + + protected int Translate(HashSet state) { + Debug.Assert(HasState(state)); + + return m_states.Translate(state); + } + + protected virtual void SetInitialState(HashSet state) { + m_builder.SetInitialState(Translate(state)); + } + + protected virtual void MarkFinalState(HashSet state) { + m_builder.MarkFinalState(Translate(state)); + } + + protected virtual void DefineTransition(HashSet s1, HashSet s2, int ch) { + + m_builder.Add(new AutomatonTransition(Translate(s1), Translate(s2), ch)); + } + + bool IsFinal(IEnumerable state) { + Debug.Assert(state != null); + return state.Any(m_ends.Contains); + } + + } +} diff -r 2a8466f0cb8a -r 1c2a16d071a7 Implab/Automaton/RegularExpressions/RegularExpressionVisitorT.cs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Implab/Automaton/RegularExpressions/RegularExpressionVisitorT.cs Fri Apr 22 13:08:08 2016 +0300 @@ -0,0 +1,37 @@ +using Implab; +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; + +namespace Implab.Automaton.RegularExpressions { + /// + /// + public class RegularExpressionVisitor : RegularExpressionVisitor { + readonly Dictionary m_tags = new Dictionary(); + + readonly ITaggedDFABuilder m_builder; + + public RegularExpressionVisitor(ITaggedDFABuilder builder) : base(builder) { + m_builder = builder; + } + + public override void Visit(EndToken token) { + base.Visit(token); + var tagged = token as EndToken; + if (tagged != null) + m_tags.Add(Index, tagged.Tag); + } + + protected override void MarkFinalState(HashSet state) { + base.MarkFinalState(state); + m_builder.SetStateTag(Translate(state), GetStateTags(state)); + } + + TTag[] GetStateTags(IEnumerable state) { + Debug.Assert(state != null); + return state.Where(m_tags.ContainsKey).Select(pos => m_tags[pos]).ToArray(); + } + + } +} diff -r 2a8466f0cb8a -r 1c2a16d071a7 Implab/Automaton/RegularExpressions/StarToken.cs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Implab/Automaton/RegularExpressions/StarToken.cs Fri Apr 22 13:08:08 2016 +0300 @@ -0,0 +1,31 @@ +using Implab; +using System; + + +namespace Implab.Automaton.RegularExpressions { + /// + /// Замыкание выражения с 0 и более повторов. + /// + public class StarToken: Token { + + Token m_token; + + public Token Token { + get { return m_token; } + } + + public StarToken(Token token) { + Safe.ArgumentNotNull(token, "token"); + m_token = token; + } + + public override void Accept(IVisitor visitor) { + Safe.ArgumentNotNull(visitor, "visitor"); + visitor.Visit(this); + } + + public override string ToString() { + return String.Format("({0})*", Token); + } + } +} diff -r 2a8466f0cb8a -r 1c2a16d071a7 Implab/Automaton/RegularExpressions/SymbolToken.cs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Implab/Automaton/RegularExpressions/SymbolToken.cs Fri Apr 22 13:08:08 2016 +0300 @@ -0,0 +1,27 @@ +using Implab; + +namespace Implab.Automaton.RegularExpressions { + /// + /// Выражение, соответсвующее одному символу. + /// + public class SymbolToken: Token { + int m_value; + + public int Value { + get { return m_value; } + } + + public SymbolToken(int value) { + m_value = value; + } + public override void Accept(IVisitor visitor) { + Safe.ArgumentNotNull(visitor, "visitor"); + + visitor.Visit(this); + } + + public override string ToString() { + return Value.ToString(); + } + } +} diff -r 2a8466f0cb8a -r 1c2a16d071a7 Implab/Automaton/RegularExpressions/Token.cs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Implab/Automaton/RegularExpressions/Token.cs Fri Apr 22 13:08:08 2016 +0300 @@ -0,0 +1,63 @@ +using Implab; +using System; +using System.Linq; + +namespace Implab.Automaton.RegularExpressions { + public abstract class Token { + public abstract void Accept(IVisitor visitor); + + public Token End() { + return Cat(new EndToken()); + } + + public Token Tag(TTag tag) { + return Cat(new EndToken(tag)); + } + + public Token Cat(Token right) { + return new CatToken(this, right); + } + + public Token Or(Token right) { + return new AltToken(this, right); + } + + public Token Optional() { + return Or(new EmptyToken()); + } + + public Token EClosure() { + return new StarToken(this); + } + + public Token Closure() { + return Cat(new StarToken(this)); + } + + public Token Repeat(int count) { + Token token = null; + + for (int i = 0; i < count; i++) + token = token != null ? token.Cat(this) : this; + return token ?? new EmptyToken(); + } + + public Token Repeat(int min, int max) { + if (min > max || min < 1) + throw new ArgumentOutOfRangeException(); + var token = Repeat(min); + + for (int i = min; i < max; i++) + token = token.Cat( Optional() ); + return token; + } + + public static Token New(params int[] set) { + Safe.ArgumentNotNull(set, "set"); + Token token = null; + foreach(var c in set.Distinct()) + token = token == null ? new SymbolToken(c) : token.Or(new SymbolToken(c)); + return token; + } + } +} diff -r 2a8466f0cb8a -r 1c2a16d071a7 Implab/Components/ExecutionState.cs --- a/Implab/Components/ExecutionState.cs Fri Feb 19 18:07:17 2016 +0300 +++ b/Implab/Components/ExecutionState.cs Fri Apr 22 13:08:08 2016 +0300 @@ -1,14 +1,24 @@ namespace Implab.Components { public enum ExecutionState { - Reserved = 0, - Uninitialized, + Undefined = 0, + + Created, + + Initializing, + Ready, + Starting, + Running, + Stopping, - Stopped, + + Failed, + Disposed, - Failed + + Last = Disposed } } \ No newline at end of file diff -r 2a8466f0cb8a -r 1c2a16d071a7 Implab/Components/IInitializable.cs --- a/Implab/Components/IInitializable.cs Fri Feb 19 18:07:17 2016 +0300 +++ b/Implab/Components/IInitializable.cs Fri Apr 22 13:08:08 2016 +0300 @@ -11,7 +11,7 @@ /// Completes initialization. /// /// - /// Normally virtual shouldn't be called from the constructor, due to the incomplete object state, but + /// Normally virtual methods shouldn't be called from the constructor, due to the incomplete object state, but /// they can be called from this method. This method is also usefull when we constructing a complex grpah /// of components where cyclic references may take place. /// diff -r 2a8466f0cb8a -r 1c2a16d071a7 Implab/Components/LazyAndWeak.cs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Implab/Components/LazyAndWeak.cs Fri Apr 22 13:08:08 2016 +0300 @@ -0,0 +1,64 @@ +using System; +using System.Threading; + +namespace Implab.Components { + /// + /// Creates an instace on-demand and allows it to be garbage collected. + /// + /// + /// Usefull when dealing with memory-intensive objects which are frequently used. + /// This class is similar to except it is a singleton. + /// + public class LazyAndWeak where T : class { + + readonly Func m_factory; + readonly object m_lock; + WeakReference m_reference; + + + public LazyAndWeak(Func factory, bool useLock) { + Safe.ArgumentNotNull(factory, "factory"); + m_factory = factory; + m_lock = useLock ? new object() : null; + } + + public LazyAndWeak(Func factory) : this(factory, false) { + } + + public T Value { + get { + while (true) { + var weak = m_reference; + T value; + if (weak != null) { + value = weak.Target as T; + if (value != null) + return value; + } + + if (m_lock == null) { + value = m_factory(); + + if (Interlocked.CompareExchange(ref m_reference, new WeakReference(value), weak) == weak) + return value; + } else { + lock (m_lock) { + // double check + weak = m_reference; + if (weak != null) { + value = weak.Target as T; + if (value != null) + return value; + } + // we are safe to write + value = m_factory(); + m_reference = new WeakReference(value); + return value; + } + } + } + } + } + } +} + diff -r 2a8466f0cb8a -r 1c2a16d071a7 Implab/Components/RunnableComponent.cs --- a/Implab/Components/RunnableComponent.cs Fri Feb 19 18:07:17 2016 +0300 +++ b/Implab/Components/RunnableComponent.cs Fri Apr 22 13:08:08 2016 +0300 @@ -1,24 +1,164 @@ using System; -using Implab.Parsing; namespace Implab.Components { - public class RunnableComponent : Disposable, IRunnable, IInitializable { - + public abstract class RunnableComponent : IDisposable, IRunnable, IInitializable { + enum Commands { + Ok = 0, + Fail, + Init, + Start, + Stop, + Dispose, + Last = Dispose + } + + class StateMachine { + static readonly ExecutionState[,] _transitions; + + static StateMachine() { + _transitions = new ExecutionState[(int)ExecutionState.Last + 1, (int)Commands.Last + 1]; + + Edge(ExecutionState.Created, ExecutionState.Initializing, Commands.Init); + Edge(ExecutionState.Created, ExecutionState.Disposed, Commands.Dispose); + + Edge(ExecutionState.Initializing, ExecutionState.Ready, Commands.Ok); + Edge(ExecutionState.Initializing, ExecutionState.Failed, Commands.Fail); + + Edge(ExecutionState.Ready, ExecutionState.Starting, Commands.Start); + Edge(ExecutionState.Ready, ExecutionState.Disposed, Commands.Dispose); + + Edge(ExecutionState.Starting, ExecutionState.Running, Commands.Ok); + Edge(ExecutionState.Starting, ExecutionState.Failed, Commands.Fail); + Edge(ExecutionState.Starting, ExecutionState.Stopping, Commands.Stop); + Edge(ExecutionState.Starting, ExecutionState.Disposed, Commands.Dispose); + Edge(ExecutionState.Running, ExecutionState.Failed, Commands.Fail); + Edge(ExecutionState.Running, ExecutionState.Stopping, Commands.Stop); + Edge(ExecutionState.Running, ExecutionState.Disposed, Commands.Dispose); + Edge(ExecutionState.Stopping, ExecutionState.Failed, Commands.Fail); + Edge(ExecutionState.Stopping, ExecutionState.Disposed, Commands.Ok); + + Edge(ExecutionState.Failed, ExecutionState.Disposed, Commands.Dispose); + } + + static void Edge(ExecutionState s1, ExecutionState s2, Commands cmd) { + _transitions[(int)s1, (int)cmd] = s2; + } - + public ExecutionState State { + get; + private set; + } + + public StateMachine(ExecutionState initial) { + State = initial; + } + + public bool Move(Commands cmd) { + var next = _transitions[(int)State, (int)cmd]; + if (next == ExecutionState.Undefined) + return false; + State = next; + return true; + } + } + IPromise m_pending; Exception m_lastError; + readonly StateMachine m_stateMachine; + protected RunnableComponent(bool initialized) { + m_stateMachine = new StateMachine(initialized ? ExecutionState.Ready : ExecutionState.Created); + } + + protected virtual int DisposeTimeout { + get { + return 10000; + } + } + + void ThrowInvalidCommand(Commands cmd) { + if (m_stateMachine.State == ExecutionState.Disposed) + throw new ObjectDisposedException(ToString()); + + throw new InvalidOperationException(String.Format("Commnd {0} is not allowed in the state {1}", cmd, m_stateMachine.State)); + } + + void Move(Commands cmd) { + if (!m_stateMachine.Move(cmd)) + ThrowInvalidCommand(cmd); + } + + void Invoke(Commands cmd, Action action) { + lock (m_stateMachine) + Move(cmd); + try { + action(); + lock(m_stateMachine) + Move(Commands.Ok); + + } catch (Exception err) { + lock (m_stateMachine) { + Move(Commands.Fail); + m_lastError = err; + } + throw; + } } + IPromise InvokeAsync(Commands cmd, Func action, Action chain) { + IPromise promise = null; + IPromise prev; + + var task = new ActionChainTask(action, null, null, true); + + lock (m_stateMachine) { + Move(cmd); + + prev = m_pending; + + promise = task.Then( + () => { + lock(m_stateMachine) { + if (m_pending == promise) { + Move(Commands.Ok); + m_pending = null; + } + } + }, e => { + lock(m_stateMachine) { + if (m_pending == promise) { + Move(Commands.Fail); + m_pending = null; + m_lastError = e; + } + } + throw new PromiseTransientException(e); + } + ); + + m_pending = promise; + } + + if (prev == null) + task.Resolve(); + else + chain(prev, task); + + return promise; + } + + #region IInitializable implementation public void Init() { - + Invoke(Commands.Init, OnInitialize); + } + + protected virtual void OnInitialize() { } #endregion @@ -26,33 +166,92 @@ #region IRunnable implementation public IPromise Start() { - throw new NotImplementedException(); + return InvokeAsync(Commands.Start, OnStart, null); } protected virtual IPromise OnStart() { return Promise.SUCCESS; } - protected virtual void Run() { + public IPromise Stop() { + return InvokeAsync(Commands.Stop, OnStop, StopPending).Then(Dispose); + } + + protected virtual IPromise OnStop() { + return Promise.SUCCESS; } - public IPromise Stop() { - throw new NotImplementedException(); + /// + /// Stops the current operation if one exists. + /// + /// Current. + /// Stop. + protected virtual void StopPending(IPromise current, IDeferred stop) { + if (current == null) { + stop.Resolve(); + } else { + // связваем текущую операцию с операцией остановки + current.On( + stop.Resolve, // если текущая операция заверщилась, то можно начинать остановку + stop.Reject, // если текущая операция дала ошибку - то все плохо, нельзя продолжать + e => stop.Resolve() // если текущая отменилась, то можно начинать остановку + ); + // посылаем текущей операции сигнал остановки + current.Cancel(); + } } public ExecutionState State { get { - throw new NotImplementedException(); + return m_stateMachine.State; } } public Exception LastError { get { - throw new NotImplementedException(); + return m_lastError; } } #endregion + + #region IDisposable implementation + + public void Dispose() { + IPromise pending; + lock (m_stateMachine) { + if (m_stateMachine.State == ExecutionState.Disposed) + return; + + Move(Commands.Dispose); + + GC.SuppressFinalize(this); + + pending = m_pending; + m_pending = null; + } + if (pending != null) { + pending.Cancel(); + pending.Timeout(DisposeTimeout).On( + () => Dispose(true, null), + err => Dispose(true, err), + reason => Dispose(true, new OperationCanceledException("The operation is cancelled", reason)) + ); + } else { + Dispose(true, m_lastError); + } + } + + ~RunnableComponent() { + Dispose(false, null); + } + + #endregion + + protected virtual void Dispose(bool disposing, Exception lastError) { + + } + } } diff -r 2a8466f0cb8a -r 1c2a16d071a7 Implab/Formats/ByteAlphabet.cs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Implab/Formats/ByteAlphabet.cs Fri Apr 22 13:08:08 2016 +0300 @@ -0,0 +1,23 @@ +using System.Collections.Generic; +using System.Linq; +using Implab.Automaton; + +namespace Implab.Formats { + public class ByteAlphabet : IndexedAlphabetBase { + + #region implemented abstract members of IndexedAlphabetBase + + public override int GetSymbolIndex(byte symbol) { + return (int)symbol; + } + + public IEnumerable InputSymbols { + get { + return Enumerable.Range(byte.MinValue, byte.MaxValue).Cast(); + } + } + + #endregion + } +} + diff -r 2a8466f0cb8a -r 1c2a16d071a7 Implab/Formats/CharAlphabet.cs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Implab/Formats/CharAlphabet.cs Fri Apr 22 13:08:08 2016 +0300 @@ -0,0 +1,16 @@ +using System.Collections.Generic; +using System.Linq; +using Implab.Automaton; + +namespace Implab.Formats { + public class CharAlphabet: IndexedAlphabetBase { + + public override int GetSymbolIndex(char symbol) { + return symbol; + } + + public IEnumerable InputSymbols { + get { return Enumerable.Range(char.MinValue, char.MaxValue).Cast(); } + } + } +} diff -r 2a8466f0cb8a -r 1c2a16d071a7 Implab/Formats/Grammar.cs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Implab/Formats/Grammar.cs Fri Apr 22 13:08:08 2016 +0300 @@ -0,0 +1,99 @@ +using Implab; +using System; +using System.Collections.Generic; +using System.Linq; +using Implab.Automaton; +using Implab.Automaton.RegularExpressions; + +namespace Implab.Formats { + /// + /// Базовый абстрактный класс. Грамматика, позволяет формулировать выражения над алфавитом типа char. + /// + public abstract class Grammar { + + protected abstract IAlphabetBuilder AlphabetBuilder { + get; + } + + protected SymbolToken UnclassifiedToken() { + return new SymbolToken(AutomatonConst.UNCLASSIFIED_INPUT); + } + + protected void DefineAlphabet(IEnumerable alphabet) { + Safe.ArgumentNotNull(alphabet, "alphabet"); + + foreach (var ch in alphabet) + AlphabetBuilder.DefineSymbol(ch); + } + + protected Token SymbolToken(TSymbol symbol) { + return Token.New(TranslateOrAdd(symbol)); + } + + protected Token SymbolToken(IEnumerable symbols) { + Safe.ArgumentNotNull(symbols, "symbols"); + + return Token.New(TranslateOrAdd(symbols).ToArray()); + } + + protected Token SymbolSetToken(params TSymbol[] set) { + return SymbolToken(set); + } + + int TranslateOrAdd(TSymbol ch) { + var t = AlphabetBuilder.Translate(ch); + if (t == AutomatonConst.UNCLASSIFIED_INPUT) + t = AlphabetBuilder.DefineSymbol(ch); + return t; + } + + IEnumerable TranslateOrAdd(IEnumerable symbols) { + return symbols.Distinct().Select(TranslateOrAdd); + } + + int TranslateOrDie(TSymbol ch) { + var t = AlphabetBuilder.Translate(ch); + if (t == AutomatonConst.UNCLASSIFIED_INPUT) + throw new ApplicationException(String.Format("Symbol '{0}' is UNCLASSIFIED", ch)); + return t; + } + + IEnumerable TranslateOrDie(IEnumerable symbols) { + return symbols.Distinct().Select(TranslateOrDie); + } + + protected Token SymbolTokenExcept(IEnumerable symbols) { + Safe.ArgumentNotNull(symbols, "symbols"); + + return Token.New( Enumerable.Range(0, AlphabetBuilder.Count).Except(TranslateOrDie(symbols)).ToArray() ); + } + + protected abstract IndexedAlphabetBase CreateAlphabet(); + + protected ScannerContext BuildScannerContext(Token regexp) { + + var dfa = new RegularDFA(AlphabetBuilder); + + var visitor = new RegularExpressionVisitor(dfa); + regexp.Accept(visitor); + visitor.BuildDFA(); + + if (dfa.IsFinalState(dfa.InitialState)) + throw new ApplicationException("The specified language contains empty token"); + + var ab = CreateAlphabet(); + var optimal = dfa.Optimize(ab); + + return new ScannerContext( + optimal.CreateTransitionTable(), + optimal.CreateFinalStateTable(), + optimal.CreateTagTable(), + optimal.InitialState, + ab.GetTranslationMap() + ); + } + + } + + +} diff -r 2a8466f0cb8a -r 1c2a16d071a7 Implab/Formats/JSON/JSONElementContext.cs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Implab/Formats/JSON/JSONElementContext.cs Fri Apr 22 13:08:08 2016 +0300 @@ -0,0 +1,11 @@ +namespace Implab.Formats.JSON { + /// + /// internal + /// + enum JSONElementContext { + None, + Object, + Array, + Closed + } +} diff -r 2a8466f0cb8a -r 1c2a16d071a7 Implab/Formats/JSON/JSONElementType.cs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Implab/Formats/JSON/JSONElementType.cs Fri Apr 22 13:08:08 2016 +0300 @@ -0,0 +1,28 @@ +namespace Implab.Formats.JSON { + /// + /// Тип элемента на котором находится парсер + /// + public enum JSONElementType { + None, + /// + /// Начало объекта + /// + BeginObject, + /// + /// Конец объекта + /// + EndObject, + /// + /// Начало массива + /// + BeginArray, + /// + /// Конец массива + /// + EndArray, + /// + /// Простое значение + /// + Value + } +} diff -r 2a8466f0cb8a -r 1c2a16d071a7 Implab/Formats/JSON/JSONGrammar.cs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Implab/Formats/JSON/JSONGrammar.cs Fri Apr 22 13:08:08 2016 +0300 @@ -0,0 +1,121 @@ +using System.Linq; +using Implab.Automaton.RegularExpressions; +using System; +using Implab.Automaton; +using Implab.Components; + +namespace Implab.Formats.JSON { + class JSONGrammar : Grammar { + public enum TokenType { + None, + BeginObject, + EndObject, + BeginArray, + EndArray, + String, + Number, + Literal, + NameSeparator, + ValueSeparator, + Whitespace, + + StringBound, + EscapedChar, + UnescapedChar, + EscapedUnicode + } + + static LazyAndWeak _instance = new LazyAndWeak(() => new JSONGrammar()); + + public static JSONGrammar Instance { + get { return _instance.Value; } + } + + readonly ScannerContext m_jsonExpression; + readonly ScannerContext m_stringExpression; + readonly CharAlphabet m_defaultAlphabet = new CharAlphabet(); + + public JSONGrammar() { + DefineAlphabet(Enumerable.Range(0, 0x20).Select(x => (char)x)); + var hexDigit = SymbolRangeToken('a','f').Or(SymbolRangeToken('A','F')).Or(SymbolRangeToken('0','9')); + var digit9 = SymbolRangeToken('1', '9'); + var zero = SymbolToken('0'); + var digit = zero.Or(digit9); + var dot = SymbolToken('.'); + var minus = SymbolToken('-'); + var sign = SymbolSetToken('-', '+'); + var expSign = SymbolSetToken('e', 'E'); + var letters = SymbolRangeToken('a', 'z'); + var integer = zero.Or(digit9.Cat(digit.EClosure())); + var frac = dot.Cat(digit.Closure()); + var exp = expSign.Cat(sign.Optional()).Cat(digit.Closure()); + var quote = SymbolToken('"'); + var backSlash = SymbolToken('\\'); + var specialEscapeChars = SymbolSetToken('\\', '"', '/', 'b', 'f', 't', 'n', 'r'); + var unicodeEspace = SymbolToken('u').Cat(hexDigit.Repeat(4)); + var whitespace = SymbolSetToken('\n', '\r', '\t', ' ').EClosure(); + var beginObject = whitespace.Cat(SymbolToken('{')).Cat(whitespace); + var endObject = whitespace.Cat(SymbolToken('}')).Cat(whitespace); + var beginArray = whitespace.Cat(SymbolToken('[')).Cat(whitespace); + var endArray = whitespace.Cat(SymbolToken(']')).Cat(whitespace); + var nameSep = whitespace.Cat(SymbolToken(':')).Cat(whitespace); + var valueSep = whitespace.Cat(SymbolToken(',')).Cat(whitespace); + + var number = minus.Optional().Cat(integer).Cat(frac.Optional()).Cat(exp.Optional()); + var literal = letters.Closure(); + var unescaped = SymbolTokenExcept(Enumerable.Range(0, 0x20).Union(new int[] { '\\', '"' }).Select(x => (char)x)); + + var jsonExpression = + number.Tag(TokenType.Number) + .Or(literal.Tag(TokenType.Literal)) + .Or(quote.Tag(TokenType.StringBound)) + .Or(beginObject.Tag(TokenType.BeginObject)) + .Or(endObject.Tag(TokenType.EndObject)) + .Or(beginArray.Tag(TokenType.BeginArray)) + .Or(endArray.Tag(TokenType.EndArray)) + .Or(nameSep.Tag(TokenType.NameSeparator)) + .Or(valueSep.Tag(TokenType.ValueSeparator)) + .Or(SymbolSetToken('\n', '\r', '\t', ' ').Closure().Tag(TokenType.Whitespace)); + + + var jsonStringExpression = + quote.Tag(TokenType.StringBound) + .Or(backSlash.Cat(specialEscapeChars).Tag(TokenType.EscapedChar)) + .Or(backSlash.Cat(unicodeEspace).Tag(TokenType.EscapedUnicode)) + .Or(unescaped.Closure().Tag(TokenType.UnescapedChar)); + + + m_jsonExpression = BuildScannerContext(jsonExpression); + m_stringExpression = BuildScannerContext(jsonStringExpression); + + + } + + protected override IAlphabetBuilder AlphabetBuilder { + get { + return m_defaultAlphabet; + } + } + + public ScannerContext JsonExpression { + get { + return m_jsonExpression; + } + } + + public ScannerContext JsonStringExpression { + get { + return m_stringExpression; + } + } + + Token SymbolRangeToken(char start, char stop) { + return SymbolToken(Enumerable.Range(start, stop - start + 1).Select(x => (char)x)); + } + + protected override IndexedAlphabetBase CreateAlphabet() { + return new CharAlphabet(); + } + + } +} diff -r 2a8466f0cb8a -r 1c2a16d071a7 Implab/Formats/JSON/JSONParser.cs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Implab/Formats/JSON/JSONParser.cs Fri Apr 22 13:08:08 2016 +0300 @@ -0,0 +1,293 @@ +using System; +using System.Diagnostics; +using System.IO; +using Implab.Automaton; +using Implab.Automaton.RegularExpressions; +using System.Linq; +using Implab.Components; +using System.Collections.Generic; + +namespace Implab.Formats.JSON { + /// + /// Pull парсер JSON данных. + /// + /// + /// Следует отметить отдельную интерпретацию свойства , + /// оно означает текущий уровень вложенности объектов, однако закрывающий + /// элемент объекта и массива имеет уровень меньше, чем сам объект. + /// + /// { // Level = 1 + /// "name" : "Peter", // Level = 1 + /// "address" : { // Level = 2 + /// city : "Stern" // Level = 2 + /// } // Level = 1 + /// } // Level = 0 + /// + /// + public class JSONParser : Disposable { + + enum MemberContext { + MemberName, + MemberValue + } + + #region Parser rules + struct ParserContext { + readonly int[,] m_dfa; + int m_state; + + readonly JSONElementContext m_elementContext; + + public ParserContext(int[,] dfa, int state, JSONElementContext context) { + m_dfa = dfa; + m_state = state; + m_elementContext = context; + } + + public bool Move(JsonTokenType token) { + var next = m_dfa[m_state, (int)token]; + if (next == AutomatonConst.UNREACHABLE_STATE) + return false; + m_state = next; + return true; + } + + public JSONElementContext ElementContext { + get { return m_elementContext; } + } + } + + static readonly ParserContext _jsonContext; + static readonly ParserContext _objectContext; + static readonly ParserContext _arrayContext; + + static JSONParser() { + + var valueExpression = MakeToken(JsonTokenType.BeginArray, JsonTokenType.BeginObject, JsonTokenType.Literal, JsonTokenType.Number, JsonTokenType.String); + var memberExpression = MakeToken(JsonTokenType.String).Cat(MakeToken(JsonTokenType.NameSeparator)).Cat(valueExpression); + + var objectExpression = memberExpression + .Cat( + MakeToken(JsonTokenType.ValueSeparator) + .Cat(memberExpression) + .EClosure() + ) + .Optional() + .Cat(MakeToken(JsonTokenType.EndObject)) + .End(); + + var arrayExpression = valueExpression + .Cat( + MakeToken(JsonTokenType.ValueSeparator) + .Cat(valueExpression) + .EClosure() + ) + .Optional() + .Cat(MakeToken(JsonTokenType.EndArray)) + .End(); + + var jsonExpression = valueExpression.End(); + + _jsonContext = CreateParserContext(jsonExpression, JSONElementContext.None); + _objectContext = CreateParserContext(objectExpression, JSONElementContext.Object); + _arrayContext = CreateParserContext(arrayExpression, JSONElementContext.Array); + } + + static Token MakeToken(params JsonTokenType[] input) { + return Token.New( input.Select(t => (int)t).ToArray() ); + } + + static ParserContext CreateParserContext(Token expr, JSONElementContext context) { + + var dfa = new DFATable(); + var builder = new RegularExpressionVisitor(dfa); + expr.Accept(builder); + builder.BuildDFA(); + + return new ParserContext(dfa.CreateTransitionTable(), dfa.InitialState, context); + } + + #endregion + + readonly JSONScanner m_scanner; + MemberContext m_memberContext; + + JSONElementType m_elementType; + object m_elementValue; + string m_memberName = String.Empty; + + Stack m_stack = new Stack(); + ParserContext m_context = _jsonContext; + + /// + /// Создает новый парсер на основе строки, содержащей JSON + /// + /// + public JSONParser(string text) { + Safe.ArgumentNotEmpty(text, "text"); + m_scanner = new JSONScanner(text); + } + + /// + /// Создает новый экземпляр парсера, на основе текстового потока. + /// + /// Текстовый поток. + public JSONParser(TextReader reader) { + Safe.ArgumentNotNull(reader, "reader"); + m_scanner = new JSONScanner(reader); + } + + public int Level { + get { return m_stack.Count; } + } + + /// + /// Тип текущего элемента на котором стоит парсер. + /// + public JSONElementType ElementType { + get { return m_elementType; } + } + + /// + /// Имя элемента - имя свойства родительского контейнера. Для элементов массивов и корневого всегда + /// пустая строка. + /// + public string ElementName { + get { return m_memberName; } + } + + /// + /// Значение элемента. Только для элементов типа , для остальных null + /// + public object ElementValue { + get { return m_elementValue; } + } + + /// + /// Читает слеюудущий объект из потока + /// + /// true - операция чтения прошла успешно, false - конец данных + public bool Read() { + object tokenValue; + JsonTokenType tokenType; + + m_memberName = String.Empty; + + while (m_scanner.ReadToken(out tokenValue, out tokenType)) { + if(!m_context.Move(tokenType)) + UnexpectedToken(tokenValue, tokenType); + + switch (tokenType) { + case JsonTokenType.BeginObject: + m_stack.Push(m_context); + m_context = _objectContext; + + m_elementValue = null; + m_memberContext = MemberContext.MemberName; + m_elementType = JSONElementType.BeginObject; + return true; + case JsonTokenType.EndObject: + if (m_stack.Count == 0) + UnexpectedToken(tokenValue, tokenType); + m_context = m_stack.Pop(); + + m_elementValue = null; + m_elementType = JSONElementType.EndObject; + return true; + case JsonTokenType.BeginArray: + m_stack.Push(m_context); + m_context = _arrayContext; + + m_elementValue = null; + m_memberContext = MemberContext.MemberValue; + m_elementType = JSONElementType.BeginArray; + return true; + case JsonTokenType.EndArray: + if (m_stack.Count == 0) + UnexpectedToken(tokenValue, tokenType); + m_context = m_stack.Pop(); + + m_elementValue = null; + m_elementType = JSONElementType.EndArray; + return true; + case JsonTokenType.String: + if (m_memberContext == MemberContext.MemberName) { + m_memberName = (string)tokenValue; + break; + } + m_elementType = JSONElementType.Value; + m_elementValue = tokenValue; + return true; + case JsonTokenType.Number: + m_elementType = JSONElementType.Value; + m_elementValue = tokenValue; + return true; + case JsonTokenType.Literal: + m_elementType = JSONElementType.Value; + m_elementValue = ParseLiteral((string)tokenValue); + return true; + case JsonTokenType.NameSeparator: + m_memberContext = MemberContext.MemberValue; + break; + case JsonTokenType.ValueSeparator: + m_memberContext = m_context.ElementContext == JSONElementContext.Object ? MemberContext.MemberName : MemberContext.MemberValue; + break; + default: + UnexpectedToken(tokenValue, tokenType); + break; + } + } + if (m_context.ElementContext != JSONElementContext.None) + throw new ParserException("Unexpedted end of data"); + + EOF = true; + + return false; + } + + object ParseLiteral(string literal) { + switch (literal) { + case "null": + return null; + case "false": + return false; + case "true": + return true; + default: + UnexpectedToken(literal, JsonTokenType.Literal); + return null; // avoid compliler error + } + } + + void UnexpectedToken(object value, JsonTokenType tokenType) { + throw new ParserException(String.Format("Unexpected token {0}: '{1}'", tokenType, value)); + } + + + /// + /// Признак конца потока + /// + public bool EOF { + get; + private set; + } + + protected override void Dispose(bool disposing) { + if (disposing) + Safe.Dispose(m_scanner); + } + + /// + /// Переходит в конец текущего объекта. + /// + public void SeekElementEnd() { + var level = Level - 1; + + Debug.Assert(level >= 0); + + while (Level != level) + Read(); + } + } + +} diff -r 2a8466f0cb8a -r 1c2a16d071a7 Implab/Formats/JSON/JSONScanner.cs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Implab/Formats/JSON/JSONScanner.cs Fri Apr 22 13:08:08 2016 +0300 @@ -0,0 +1,109 @@ +using System; +using System.Globalization; +using Implab.Automaton; +using System.Text; +using Implab.Components; +using System.IO; + +namespace Implab.Formats.JSON { + /// + /// Сканнер (лексер), разбивающий поток символов на токены JSON. + /// + public class JSONScanner : Disposable { + readonly StringBuilder m_builder = new StringBuilder(); + + readonly ScannerContext m_jsonContext = JSONGrammar.Instance.JsonExpression; + readonly ScannerContext m_stringContext = JSONGrammar.Instance.JsonStringExpression; + + + readonly TextScanner m_scanner; + + /// + /// Создает новый экземпляр сканнера + /// + public JSONScanner(string text) { + Safe.ArgumentNotEmpty(text, "text"); + + m_scanner = new StringScanner(text); + } + + public JSONScanner(TextReader reader, int bufferMax, int chunkSize) { + Safe.ArgumentNotNull(reader, "reader"); + + m_scanner = new ReaderScanner(reader, bufferMax, chunkSize); + } + + public JSONScanner(TextReader reader) : this(reader, 1024*1024, 1024){ + } + + /// + /// Читает следующий лексический элемент из входных данных. + /// + /// Возвращает значение прочитанного токена. + /// Возвращает тип прочитанного токена. + /// true - чтение произведено успешно. false - достигнут конец входных данных + /// В случе если токен не распознается, возникает исключение. Значения токенов обрабатываются, т.е. + /// в строках обрабатываются экранированные символы, числа становтся типа double. + public bool ReadToken(out object tokenValue, out JsonTokenType tokenType) { + JSONGrammar.TokenType[] tag; + while (m_jsonContext.Execute(m_scanner, out tag)) { + switch (tag[0]) { + case JSONGrammar.TokenType.StringBound: + tokenValue = ReadString(); + tokenType = JsonTokenType.String; + break; + case JSONGrammar.TokenType.Number: + tokenValue = Double.Parse(m_scanner.GetTokenValue(), CultureInfo.InvariantCulture); + tokenType = JsonTokenType.Number; + break; + case JSONGrammar.TokenType.Whitespace: + continue; + default: + tokenType = (JsonTokenType)tag[0]; + tokenValue = m_scanner.GetTokenValue(); + break; + } + return true; + } + tokenValue = null; + tokenType = JsonTokenType.None; + return false; + } + + string ReadString() { + int pos = 0; + var buf = new char[6]; // the buffer for unescaping chars + + JSONGrammar.TokenType[] tag; + m_builder.Clear(); + + while (m_stringContext.Execute(m_scanner, out tag)) { + switch (tag[0]) { + case JSONGrammar.TokenType.StringBound: + return m_builder.ToString(); + case JSONGrammar.TokenType.UnescapedChar: + m_scanner.CopyTokenTo(m_builder); + break; + case JSONGrammar.TokenType.EscapedUnicode: // \xXXXX - unicode escape sequence + m_scanner.CopyTokenTo(buf, 0); + m_builder.Append(StringTranslator.TranslateHexUnicode(buf, 2)); + pos++; + break; + case JSONGrammar.TokenType.EscapedChar: // \t - escape sequence + m_scanner.CopyTokenTo(buf, 0); + m_builder.Append(StringTranslator.TranslateEscapedChar(buf[1])); + break; + } + + } + + throw new ParserException("Unexpected end of data"); + } + + protected override void Dispose(bool disposing) { + if (disposing) + Safe.Dispose(m_scanner); + base.Dispose(disposing); + } + } +} diff -r 2a8466f0cb8a -r 1c2a16d071a7 Implab/Formats/JSON/JSONWriter.cs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Implab/Formats/JSON/JSONWriter.cs Fri Apr 22 13:08:08 2016 +0300 @@ -0,0 +1,319 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Globalization; +using System.Diagnostics; + +namespace Implab.Formats.JSON { + public class JSONWriter { + struct Context { + public bool needComma; + public JSONElementContext element; + } + Stack m_contextStack = new Stack(); + Context m_context; + + const int BUFFER_SIZE = 64; + + TextWriter m_writer; + readonly bool m_indent = true; + readonly int m_indentSize = 4; + readonly char[] m_buffer = new char[BUFFER_SIZE]; + int m_bufferPos; + + static readonly char [] _hex = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' }; + static readonly char [] _escapeBKS, + _escapeFWD, + _escapeCR, + _escapeNL, + _escapeTAB, + _escapeBSLASH, + _escapeQ; + + static JSONWriter() { + _escapeBKS = "\\b".ToCharArray(); + _escapeFWD = "\\f".ToCharArray(); + _escapeCR = "\\r".ToCharArray(); + _escapeNL = "\\n".ToCharArray(); + _escapeTAB = "\\t".ToCharArray(); + _escapeBSLASH = "\\\\".ToCharArray(); + _escapeQ = "\\\"".ToCharArray(); + } + + public JSONWriter(TextWriter writer) { + Safe.ArgumentNotNull(writer, "writer"); + m_writer = writer; + } + + public JSONWriter(TextWriter writer, bool indent) { + Safe.ArgumentNotNull(writer, "writer"); + + m_writer = writer; + m_indent = indent; + } + + void WriteIndent() { + if (m_indent) { + var indent = new char[m_contextStack.Count * m_indentSize + 1]; + indent[0] = '\n'; + for (int i = 1; i < indent.Length; i++) + indent[i] = ' '; + m_writer.Write(new String(indent)); + } else { + m_writer.Write(' '); + } + } + + void WriteMemberName(string name) { + Safe.ArgumentNotEmpty(name, "name"); + if (m_context.element != JSONElementContext.Object) + OperationNotApplicable("WriteMember"); + if (m_context.needComma) + m_writer.Write(","); + + WriteIndent(); + m_context.needComma = true; + Write(name); + m_writer.Write(" : "); + } + + public void WriteValue(string name, string value) { + WriteMemberName(name); + Write(value); + } + + public void WriteValue(string name, bool value) { + WriteMemberName(name); + Write(value); + } + + public void WriteValue(string name, double value) { + WriteMemberName(name); + Write(value); + } + + public void WriteValue(string value) { + if (m_context.element == JSONElementContext.Array) { + + if (m_context.needComma) + m_writer.Write(","); + WriteIndent(); + m_context.needComma = true; + + Write(value); + } else if (m_context.element == JSONElementContext.None) { + Write(value); + m_context.element = JSONElementContext.Closed; + } else { + OperationNotApplicable("WriteValue"); + } + } + + public void WriteValue(bool value) { + if (m_context.element == JSONElementContext.Array) { + + if (m_context.needComma) + m_writer.Write(","); + WriteIndent(); + m_context.needComma = true; + + Write(value); + } else if (m_context.element == JSONElementContext.None) { + Write(value); + m_context.element = JSONElementContext.Closed; + } else { + OperationNotApplicable("WriteValue"); + } + } + + public void WriteValue(double value) { + if (m_context.element == JSONElementContext.Array) { + + if (m_context.needComma) + m_writer.Write(","); + WriteIndent(); + m_context.needComma = true; + + Write(value); + } else if (m_context.element == JSONElementContext.None) { + Write(value); + m_context.element = JSONElementContext.Closed; + } else { + OperationNotApplicable("WriteValue"); + } + } + + public void BeginObject() { + if (m_context.element != JSONElementContext.None && m_context.element != JSONElementContext.Array) + OperationNotApplicable("BeginObject"); + if (m_context.needComma) + m_writer.Write(","); + + WriteIndent(); + + m_context.needComma = true; + + m_contextStack.Push(m_context); + + m_context = new Context { element = JSONElementContext.Object, needComma = false }; + m_writer.Write("{"); + } + + public void BeginObject(string name) { + WriteMemberName(name); + + m_contextStack.Push(m_context); + + m_context = new Context { element = JSONElementContext.Object, needComma = false }; + m_writer.Write("{"); + } + + public void EndObject() { + if (m_context.element != JSONElementContext.Object) + OperationNotApplicable("EndObject"); + + m_context = m_contextStack.Pop(); + if (m_contextStack.Count == 0) + m_context.element = JSONElementContext.Closed; + WriteIndent(); + m_writer.Write("}"); + } + + public void BeginArray() { + if (m_context.element != JSONElementContext.None && m_context.element != JSONElementContext.Array) + throw new InvalidOperationException(); + if (m_context.needComma) { + m_writer.Write(","); + + } + m_context.needComma = true; + + WriteIndent(); + m_contextStack.Push(m_context); + m_context = new Context { element = JSONElementContext.Array, needComma = false }; + m_writer.Write("["); + } + + public void BeginArray(string name) { + WriteMemberName(name); + + m_contextStack.Push(m_context); + + m_context = new Context { element = JSONElementContext.Array, needComma = false }; + m_writer.Write("["); + } + + public void EndArray() { + if (m_context.element != JSONElementContext.Array) + OperationNotApplicable("EndArray"); + + m_context = m_contextStack.Pop(); + if (m_contextStack.Count == 0) + m_context.element = JSONElementContext.Closed; + WriteIndent(); + m_writer.Write("]"); + } + + void Write(bool value) { + m_writer.Write(value ? "true" : "false"); + } + + void FlushBuffer() { + if (m_bufferPos > 0) { + m_writer.Write(m_buffer, 0, m_bufferPos); + m_bufferPos = 0; + } + } + + void Write(string value) { + if (value == null) { + m_writer.Write("null"); + return; + } + + Debug.Assert(m_bufferPos == 0); + + var chars = value.ToCharArray(); + m_buffer[m_bufferPos++] = '"'; + + // Analysis disable once ForCanBeConvertedToForeach + for (int i = 0; i < chars.Length; i++) { + var ch = chars[i]; + + char[] escapeSeq; + + switch (ch) { + case '\b': + escapeSeq = _escapeBKS; + break; + case '\f': + escapeSeq = _escapeFWD; + break; + case '\r': + escapeSeq = _escapeCR; + break; + case '\n': + escapeSeq = _escapeNL; + break; + case '\t': + escapeSeq = _escapeTAB; + break; + case '\\': + escapeSeq = _escapeBSLASH; + break; + case '"': + escapeSeq = _escapeQ; + break; + default: + if (ch < 0x20) { + if (m_bufferPos + 6 > BUFFER_SIZE) + FlushBuffer(); + + m_buffer[m_bufferPos++] = '\\'; + m_buffer[m_bufferPos++] = 'u'; + m_buffer[m_bufferPos++] = '0'; + m_buffer[m_bufferPos++] = '0'; + m_buffer[m_bufferPos++] = _hex[ch >> 4 & 0xf]; + m_buffer[m_bufferPos++] = _hex[ch & 0xf]; + + } else { + if (m_bufferPos >= BUFFER_SIZE) + FlushBuffer(); + m_buffer[m_bufferPos++] = ch; + } + continue; + } + + if (m_bufferPos + escapeSeq.Length > BUFFER_SIZE) + FlushBuffer(); + + Array.Copy(escapeSeq, 0, m_buffer, m_bufferPos, escapeSeq.Length); + m_bufferPos += escapeSeq.Length; + + } + + if (m_bufferPos >= BUFFER_SIZE) + FlushBuffer(); + + m_buffer[m_bufferPos++] = '"'; + + FlushBuffer(); + } + + void Write(double value) { + if (double.IsNaN(value)) + Write("NaN"); + else if (double.IsNegativeInfinity(value)) + Write("-Infinity"); + else if (double.IsPositiveInfinity(value)) + Write("Infinity"); + else + m_writer.Write(value.ToString(CultureInfo.InvariantCulture)); + } + + void OperationNotApplicable(string opName) { + throw new InvalidOperationException(String.Format("The operation '{0}' isn't applicable in the context of '{1}'", opName, m_context.element )); + } + + } +} diff -r 2a8466f0cb8a -r 1c2a16d071a7 Implab/Formats/JSON/JSONXmlReader.cs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Implab/Formats/JSON/JSONXmlReader.cs Fri Apr 22 13:08:08 2016 +0300 @@ -0,0 +1,335 @@ +using Implab; +using System; +using System.Collections.Generic; +using System.Globalization; +using System.IO; +using System.Xml; + +namespace Implab.Formats.JSON { + public class JSONXmlReader : XmlReader { + + enum ValueContext { + Undefined, + ElementStart, + ElementValue, + ElementEnd, + ElementEmpty + } + + struct LocalNameContext { + public string localName; + public bool isArray; + } + + JSONParser m_parser; + ValueContext m_valueContext; + ReadState m_state = ReadState.Initial; + Stack m_localNameStack = new Stack(); + LocalNameContext m_localName; + int m_depthCorrection; + + readonly string m_rootName; + readonly string m_prefix; + readonly string m_namespaceUri; + readonly bool m_flattenArrays; + readonly string m_arrayItemName; + readonly XmlNameTable m_nameTable; + + JSONXmlReader(JSONParser parser, JSONXmlReaderOptions options) { + m_parser = parser; + + if (options != null) { + m_prefix = options.NodesPrefix ?? String.Empty; + m_namespaceUri = options.NamespaceURI ?? String.Empty; + m_rootName = options.RootName ?? "json"; + m_flattenArrays = options.FlattenArrays; + m_arrayItemName = options.ArrayItemName ?? "item"; + m_nameTable = options.NameTable ?? new NameTable(); + } else { + m_prefix = String.Empty; + m_namespaceUri = String.Empty; + m_rootName = "json"; + m_flattenArrays = false; + m_arrayItemName = "item"; + m_nameTable = new NameTable(); + } + } + + /// + /// Always 0, JSON doesn't support attributes + /// + public override int AttributeCount { + get { return 0; } + } + + public override string BaseURI { + get { return String.Empty; } + } + + public override int Depth { + get { + return m_localNameStack.Count + m_depthCorrection; + } + } + + public override bool EOF { + get { return m_parser.EOF; } + } + + /// + /// Always throws an exception + /// + /// + /// + public override string GetAttribute(int i) { + throw new ArgumentOutOfRangeException(); + } + + /// + /// Always returns empty string + /// + /// + /// + /// + public override string GetAttribute(string name, string namespaceURI) { + return String.Empty; + } + + /// + /// Always returns empty string + /// + /// + /// + public override string GetAttribute(string name) { + return String.Empty; + } + + public override bool IsEmptyElement { + get { return m_parser.ElementType == JSONElementType.Value && m_valueContext == ValueContext.ElementEmpty; } + } + + public override string LocalName { + get { return m_localName.localName; } + } + + public override string LookupNamespace(string prefix) { + if (String.IsNullOrEmpty(prefix) || prefix == m_prefix) + return m_namespaceUri; + + return String.Empty; + } + + public override bool MoveToAttribute(string name, string ns) { + return false; + } + + public override bool MoveToAttribute(string name) { + return false; + } + + public override bool MoveToElement() { + return false; + } + + public override bool MoveToFirstAttribute() { + return false; + } + + public override bool MoveToNextAttribute() { + return false; + } + + public override XmlNameTable NameTable { + get { return m_nameTable; } + } + + public override string NamespaceURI { + get { return m_namespaceUri; } + } + + public override XmlNodeType NodeType { + get { + switch (m_parser.ElementType) { + case JSONElementType.BeginObject: + case JSONElementType.BeginArray: + return XmlNodeType.Element; + case JSONElementType.EndObject: + case JSONElementType.EndArray: + return XmlNodeType.EndElement; + case JSONElementType.Value: + switch (m_valueContext) { + case ValueContext.ElementStart: + case ValueContext.ElementEmpty: + return XmlNodeType.Element; + case ValueContext.ElementValue: + return XmlNodeType.Text; + case ValueContext.ElementEnd: + return XmlNodeType.EndElement; + default: + throw new InvalidOperationException(); + } + default: + throw new InvalidOperationException(); + } + } + } + + public override string Prefix { + get { return m_prefix; } + } + + public override bool Read() { + if (m_state != ReadState.Interactive && m_state != ReadState.Initial) + return false; + + if (m_state == ReadState.Initial) + m_state = ReadState.Interactive; + + try { + switch (m_parser.ElementType) { + case JSONElementType.Value: + switch (m_valueContext) { + case ValueContext.ElementStart: + SetLocalName(String.Empty); + m_valueContext = ValueContext.ElementValue; + return true; + case ValueContext.ElementValue: + RestoreLocalName(); + m_valueContext = ValueContext.ElementEnd; + return true; + case ValueContext.ElementEmpty: + case ValueContext.ElementEnd: + RestoreLocalName(); + break; + } + break; + case JSONElementType.EndArray: + case JSONElementType.EndObject: + RestoreLocalName(); + break; + } + string itemName = m_parser.ElementType == JSONElementType.None ? m_rootName : m_flattenArrays ? m_localName.localName : m_arrayItemName; + while (m_parser.Read()) { + if (!String.IsNullOrEmpty(m_parser.ElementName)) + itemName = m_parser.ElementName; + + switch (m_parser.ElementType) { + case JSONElementType.BeginArray: + if (m_flattenArrays && !m_localName.isArray) { + m_depthCorrection--; + SetLocalName(itemName, true); + continue; + } + SetLocalName(itemName, true); + break; + case JSONElementType.BeginObject: + SetLocalName(itemName); + break; + case JSONElementType.EndArray: + if (m_flattenArrays && !m_localNameStack.Peek().isArray) { + RestoreLocalName(); + m_depthCorrection++; + continue; + } + break; + case JSONElementType.EndObject: + break; + case JSONElementType.Value: + SetLocalName(itemName); + m_valueContext = m_parser.ElementValue == null ? ValueContext.ElementEmpty : ValueContext.ElementStart; + break; + } + return true; + } + + m_state = ReadState.EndOfFile; + return false; + } catch { + m_state = ReadState.Error; + throw; + } + } + + public override bool ReadAttributeValue() { + return false; + } + + public override ReadState ReadState { + get { return m_state; } + } + + public override void ResolveEntity() { + // do nothing + } + + public override string Value { + get { + if (m_parser.ElementValue == null) + return String.Empty; + if (Convert.GetTypeCode(m_parser.ElementValue) == TypeCode.Double) + return ((double)m_parser.ElementValue).ToString(CultureInfo.InvariantCulture); + return m_parser.ElementValue.ToString(); + } + } + + void SetLocalName(string name) { + m_localNameStack.Push(m_localName); + m_localName.localName = name; + m_localName.isArray = false; + } + + void SetLocalName(string name, bool isArray) { + m_localNameStack.Push(m_localName); + m_localName.localName = name; + m_localName.isArray = isArray; + } + + void RestoreLocalName() { + m_localName = m_localNameStack.Pop(); + } + + public override void Close() { + + } + + protected override void Dispose(bool disposing) { + #if MONO + disposing = true; + #endif + if (disposing) { + m_parser.Dispose(); + } + base.Dispose(disposing); + } + + public static JSONXmlReader Create(string file, JSONXmlReaderOptions options) { + return Create(File.OpenText(file), options); + } + + /// + /// Creates the XmlReader for the specified text stream with JSON data. + /// + /// Text reader. + /// Options. + /// + /// The reader will be disposed when the XmlReader is disposed. + /// + public static JSONXmlReader Create(TextReader reader, JSONXmlReaderOptions options) { + return new JSONXmlReader(new JSONParser(reader), options); + } + + /// + /// Creates the XmlReader for the specified stream with JSON data. + /// + /// Stream. + /// Options. + /// + /// The stream will be disposed when the XmlReader is disposed. + /// + public static JSONXmlReader Create(Stream stream, JSONXmlReaderOptions options) { + Safe.ArgumentNotNull(stream, "stream"); + // HACK don't dispose StreaReader to keep stream opened + return Create(new StreamReader(stream), options); + } + } +} diff -r 2a8466f0cb8a -r 1c2a16d071a7 Implab/Formats/JSON/JSONXmlReaderOptions.cs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Implab/Formats/JSON/JSONXmlReaderOptions.cs Fri Apr 22 13:08:08 2016 +0300 @@ -0,0 +1,62 @@ + +using System.Xml; + +namespace Implab.Formats.JSON { + /// + /// Набор необязательных параметров для , позволяющий управлять процессом + /// интерпретации JSON документа. + /// + public class JSONXmlReaderOptions { + /// + /// Пространство имен в котором будут располагаться читаемые элементы документа + /// + public string NamespaceURI { + get; + set; + } + + /// + /// Интерпретировать массивы как множественные элементы (убирает один уровень вложенности), иначе массив + /// представляется в виде узла, дочерними элементами которого являются элементы массива, имена дочерних элементов + /// определяются свойством . По умолчанию false. + /// + public bool FlattenArrays { + get; + set; + } + + /// + /// Префикс, для узлов документа + /// + public string NodesPrefix { + get; + set; + } + + /// + /// Имя корневого элемента в xml документе + /// + public string RootName { + get; + set; + } + + /// + /// Имя элемента для массивов, если не включена опция . + /// По умолчанию item. + /// + public string ArrayItemName { + get; + set; + } + + /// + /// Таблица атомизированных строк для построения документа. + /// + public XmlNameTable NameTable { + get; + set; + } + + } +} diff -r 2a8466f0cb8a -r 1c2a16d071a7 Implab/Formats/JSON/JsonTokenType.cs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Implab/Formats/JSON/JsonTokenType.cs Fri Apr 22 13:08:08 2016 +0300 @@ -0,0 +1,44 @@ +namespace Implab.Formats.JSON { + /// + /// Тип токенов, возвращаемых . + /// + public enum JsonTokenType : int { + None = 0, + /// + /// Начало объекта + /// + BeginObject, + /// + /// Конец объекта + /// + EndObject, + /// + /// Начало массива + /// + BeginArray, + /// + /// Конец массива + /// + EndArray, + /// + /// Строка + /// + String, + /// + /// Число + /// + Number, + /// + /// Литерал + /// + Literal, + /// + /// Разделитель имени : + /// + NameSeparator, + /// + /// Разделитель имени , + /// + ValueSeparator + } +} diff -r 2a8466f0cb8a -r 1c2a16d071a7 Implab/Formats/JSON/StringTranslator.cs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Implab/Formats/JSON/StringTranslator.cs Fri Apr 22 13:08:08 2016 +0300 @@ -0,0 +1,52 @@ +using Implab; +using Implab.Formats; +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Implab.Formats.JSON { + /// + /// Класс для преобразования экранированной строки JSON + /// + static class StringTranslator { + static readonly char[] _escMap; + static readonly int[] _hexMap; + + static StringTranslator() { + var chars = new char[] { 'b', 'f', 't', 'r', 'n', '\\', '/' }; + var vals = new char[] { '\b', '\f', '\t', '\r', '\n', '\\', '/' }; + + _escMap = new char[chars.Max() + 1]; + + for (int i = 0; i < chars.Length; i++) + _escMap[chars[i]] = vals[i]; + + var hexs = new char[] { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f', 'A', 'B', 'C', 'D', 'E', 'F' }; + var ints = new int[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 10, 11, 12, 13, 14, 15 }; + + _hexMap = new int[hexs.Max() + 1]; + + for (int i = 0; i < hexs.Length; i++) + _hexMap[hexs[i]] = ints[i]; + + } + + internal static char TranslateEscapedChar(char symbol) { + return _escMap[symbol]; + } + + internal static char TranslateHexUnicode(char[] symbols, int offset) { + Debug.Assert(symbols != null); + Debug.Assert(symbols.Length - offset >= 4); + + int value = (_hexMap[symbols[offset]] << 12) + | (_hexMap[symbols[offset + 1]] << 8) + | (_hexMap[symbols[offset + 2]] << 4) + | (_hexMap[symbols[offset + 3]]); + return (char)value; + } + } +} diff -r 2a8466f0cb8a -r 1c2a16d071a7 Implab/Formats/ReaderScanner.cs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Implab/Formats/ReaderScanner.cs Fri Apr 22 13:08:08 2016 +0300 @@ -0,0 +1,30 @@ +using System; +using System.IO; + +namespace Implab.Formats { + public class ReaderScanner: TextScanner { + const int CHUNK_SIZE = 1024*4; + const int BUFFER_MAX = CHUNK_SIZE*1024; + + readonly TextReader m_reader; + + public ReaderScanner(TextReader reader, int limit, int chunk) : base(limit, chunk) { + Safe.ArgumentNotNull(reader, "reader"); + m_reader = reader; + } + + public ReaderScanner(TextReader reader) : this(reader, BUFFER_MAX, CHUNK_SIZE) { + } + + protected override int Read(char[] buffer, int offset, int size) { + return m_reader.Read(buffer, offset, size); + } + + protected override void Dispose(bool disposing) { + if (disposing) + Safe.Dispose(m_reader); + base.Dispose(disposing); + } + } +} + diff -r 2a8466f0cb8a -r 1c2a16d071a7 Implab/Formats/ScannerContext.cs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Implab/Formats/ScannerContext.cs Fri Apr 22 13:08:08 2016 +0300 @@ -0,0 +1,30 @@ +namespace Implab.Formats { + /// + /// Represents a scanner configuration usefull to recongnize token, based on the DFA. + /// + public class ScannerContext { + + public int[,] Dfa { get; private set; } + + public bool[] Final { get; private set; } + + public TTag[][] Tags { get; private set; } + + public int State { get; private set; } + + public int[] Alphabet { get; private set; } + + public ScannerContext(int[,] dfa, bool[] final, TTag[][] tags, int state, int[] alphabet) { + Dfa = dfa; + Final = final; + Tags = tags; + State = state; + Alphabet = alphabet; + } + + public bool Execute(TextScanner scanner, out TTag[] tag) { + return scanner.ReadToken(Dfa, Final, Tags, State, Alphabet, out tag); + } + } +} + diff -r 2a8466f0cb8a -r 1c2a16d071a7 Implab/Formats/StringScanner.cs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Implab/Formats/StringScanner.cs Fri Apr 22 13:08:08 2016 +0300 @@ -0,0 +1,18 @@ +using System; + +namespace Implab.Formats { + public class StringScanner: TextScanner { + const int CHUNK_SIZE = 1024; + + public StringScanner(string text) : base(null) { + Safe.ArgumentNotNull(text, "text"); + var data = text.ToCharArray(); + Feed(data, 0, data.Length); + } + + protected override int Read(char[] buffer, int offset, int size) { + return 0; + } + } +} + diff -r 2a8466f0cb8a -r 1c2a16d071a7 Implab/Formats/TextScanner.cs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Implab/Formats/TextScanner.cs Fri Apr 22 13:08:08 2016 +0300 @@ -0,0 +1,157 @@ +using System; +using Implab.Components; +using System.Diagnostics; +using Implab.Automaton; +using System.Text; + +namespace Implab.Formats { + public abstract class TextScanner : Disposable { + readonly int m_bufferMax; + readonly int m_chunkSize; + + char[] m_buffer; + int m_bufferOffset; + int m_bufferSize; + int m_tokenOffset; + int m_tokenLength; + + /// + /// Initializes a new instance of the class. + /// + /// Buffer max. + /// Chunk size. + protected TextScanner(int bufferMax, int chunkSize) { + Debug.Assert(m_chunkSize <= m_bufferMax); + + m_bufferMax = bufferMax; + m_chunkSize = chunkSize; + } + + /// + /// Initializes a new instance of the class. + /// + /// Buffer. + protected TextScanner(char[] buffer) { + if (buffer != null) { + m_buffer = buffer; + m_bufferSize = buffer.Length; + } + } + + /// + /// (hungry) Reads the next token. + /// + /// true, if token internal was read, false if there is no more tokens in the stream. + /// The transition map for the automaton + /// Final states of the automaton. + /// Tags. + /// The initial state for the automaton. + /// + /// + internal bool ReadToken(int[,] dfa, bool[] final, TTag[][] tags, int state, int[] alphabet, out TTag[] tag) { + m_tokenLength = 0; + tag = null; + + var maxSymbol = alphabet.Length - 1; + int next; + do { + // after the next chunk is read the offset in the buffer may change + int pos = m_bufferOffset + m_tokenLength; + next = state; + while (pos < m_bufferSize) { + var ch = m_buffer[pos]; + + next = dfa[next, ch > maxSymbol ? AutomatonConst.UNCLASSIFIED_INPUT : alphabet[ch]]; + + if (next == AutomatonConst.UNREACHABLE_STATE) + break; + + state = next; + pos++; + } + m_tokenLength = pos - m_bufferOffset; + } while (next != AutomatonConst.UNREACHABLE_STATE && Feed()); + + m_tokenOffset = m_bufferOffset; + m_bufferOffset += m_tokenLength; + + if (final[state]) { + tag = tags[state]; + return true; + } + + if (m_bufferOffset == m_bufferSize) { + if (m_tokenLength == 0) //EOF + return false; + + throw new ParserException(); + } + + throw new ParserException(String.Format("Unexpected symbol '{0}'", m_buffer[m_bufferOffset])); + + } + + protected void Feed(char[] buffer, int offset, int length) { + m_buffer = buffer; + m_bufferOffset = offset; + m_bufferSize = offset + length; + } + + protected bool Feed() { + if (m_chunkSize <= 0) + return false; + + if (m_buffer != null) { + var free = m_buffer.Length - m_bufferSize; + + if (free < m_chunkSize) { + free += m_chunkSize; + var used = m_bufferSize - m_bufferOffset; + var size = used + free; + + if (size > m_bufferMax) + throw new ParserException(String.Format("The buffer limit ({0} Kb) is reached", m_bufferMax / 1024)); + + var temp = new char[size]; + + var read = Read(temp, used, m_chunkSize); + if (read == 0) + return false; + + Array.Copy(m_buffer, m_bufferOffset, temp, 0, used); + + m_bufferOffset = 0; + m_bufferSize = used + read; + m_buffer = temp; + } else { + var read = Read(m_buffer, m_bufferSize, m_chunkSize); + if (read == 0) + return false; + m_bufferSize += m_chunkSize; + } + return true; + } else { + Debug.Assert(m_bufferOffset == 0); + m_buffer = new char[m_chunkSize]; + m_bufferSize = Read(m_buffer, 0, m_chunkSize); + return (m_bufferSize != 0); + } + } + + protected abstract int Read(char[] buffer, int offset, int size); + + public string GetTokenValue() { + return new String(m_buffer, m_tokenOffset, m_tokenLength); + } + + public void CopyTokenTo(char[] buffer, int offset) { + Array.Copy(m_buffer, m_tokenOffset,buffer, offset, m_tokenLength); + } + + public void CopyTokenTo(StringBuilder sb) { + sb.Append(m_buffer, m_tokenOffset, m_tokenLength); + } + + } +} + diff -r 2a8466f0cb8a -r 1c2a16d071a7 Implab/FuncChainTask.cs --- a/Implab/FuncChainTask.cs Fri Feb 19 18:07:17 2016 +0300 +++ b/Implab/FuncChainTask.cs Fri Apr 22 13:08:08 2016 +0300 @@ -13,8 +13,10 @@ if (m_task != null && LockCancelation()) { try { var operation = m_task(); - operation.On(SetResult, HandleErrorInternal, SetCancelled); + operation.On(SetResult, HandleErrorInternal, HandleCancelInternal); CancellationRequested(operation.Cancel); + } catch (OperationCanceledException reason) { + HandleCancelInternal(reason); } catch (Exception err) { HandleErrorInternal(err); } diff -r 2a8466f0cb8a -r 1c2a16d071a7 Implab/FuncChainTaskBase.cs --- a/Implab/FuncChainTaskBase.cs Fri Feb 19 18:07:17 2016 +0300 +++ b/Implab/FuncChainTaskBase.cs Fri Apr 22 13:08:08 2016 +0300 @@ -1,13 +1,10 @@ using System; -using System.Threading; namespace Implab { - public class FuncChainTaskBase : AbstractPromise { + public class FuncChainTaskBase : AbstractTask { readonly Func> m_error; readonly Func> m_cancel; - int m_cancelationLock; - protected FuncChainTaskBase( Func> error, Func> cancel, bool autoCancellable) { m_error = error; m_cancel = cancel; @@ -21,37 +18,36 @@ } public override void CancelOperation(Exception reason) { - if (LockCancelation()) { - if (m_cancel != null) { - try { - m_cancel(reason).On(SetResult, HandleErrorInternal, SetCancelled); - } catch (Exception err) { - HandleErrorInternal(err); - } - } else { - SetCancelled(reason); - } - } - + if (LockCancelation()) + HandleCancelInternal(reason); } protected void HandleErrorInternal(Exception error) { if (m_error != null) { try { - var operation = m_error(error); - - operation.On(SetResult, SetError, SetCancelled); - CancellationRequested(operation.Cancel); + var p = m_error(error); + p.On(SetResult, SetErrorInternal, SetCancelledInternal); + CancellationRequested(p.Cancel); } catch(Exception err) { - SetError(err); + SetErrorInternal(err); } } else { - SetError(error); + SetErrorInternal(error); } } - protected bool LockCancelation() { - return 0 == Interlocked.CompareExchange(ref m_cancelationLock, 1, 0); + protected void HandleCancelInternal(Exception reason) { + if (m_cancel != null) { + try { + var p = m_cancel(reason); + p.On(SetResult, HandleErrorInternal, SetCancelledInternal); + CancellationRequested(p.Cancel); + } catch (Exception err) { + HandleErrorInternal(err); + } + } else { + HandleErrorInternal(reason ?? new OperationCanceledException()); + } } } } diff -r 2a8466f0cb8a -r 1c2a16d071a7 Implab/FuncChainTaskT.cs --- a/Implab/FuncChainTaskT.cs Fri Feb 19 18:07:17 2016 +0300 +++ b/Implab/FuncChainTaskT.cs Fri Apr 22 13:08:08 2016 +0300 @@ -14,6 +14,8 @@ var operation = m_task(value); operation.On(SetResult, HandleErrorInternal, SetCancelled); CancellationRequested(operation.Cancel); + } catch (OperationCanceledException reason) { + HandleCancelInternal(reason); } catch (Exception err) { HandleErrorInternal(err); } diff -r 2a8466f0cb8a -r 1c2a16d071a7 Implab/FuncTask.cs --- a/Implab/FuncTask.cs Fri Feb 19 18:07:17 2016 +0300 +++ b/Implab/FuncTask.cs Fri Apr 22 13:08:08 2016 +0300 @@ -13,6 +13,8 @@ if (m_task != null && LockCancelation()) { try { SetResult(m_task()); + } catch(OperationCanceledException reason) { + HandleCancelInternal(reason); } catch(Exception err) { HandleErrorInternal(err); } diff -r 2a8466f0cb8a -r 1c2a16d071a7 Implab/FuncTaskBase.cs --- a/Implab/FuncTaskBase.cs Fri Feb 19 18:07:17 2016 +0300 +++ b/Implab/FuncTaskBase.cs Fri Apr 22 13:08:08 2016 +0300 @@ -1,13 +1,10 @@ using System; -using System.Threading; namespace Implab { - public class FuncTaskBase : AbstractPromise { + public class FuncTaskBase : AbstractTask { readonly Func m_cancel; readonly Func m_error; - int m_cancelationLock; - protected FuncTaskBase( Func error, Func cancel, bool autoCancellable) { m_error = error; m_cancel = cancel; @@ -26,30 +23,30 @@ try { SetResult(m_error(error)); } catch(Exception err) { - SetError(err); + SetErrorInternal(err); } } else { - SetError(error); + SetErrorInternal(error); } } public override void CancelOperation(Exception reason) { - if (LockCancelation()) { - if (m_cancel != null) { - try { - SetResult(m_cancel(reason)); - } catch (Exception err) { - HandleErrorInternal(err); - } - } else { - SetCancelled(reason); + if (LockCancelation()) + HandleCancelInternal(reason); + } + + protected void HandleCancelInternal(Exception reason) { + if (m_cancel != null) { + try { + SetResult(m_cancel(reason)); + } catch (Exception err) { + HandleErrorInternal(err); } + } else { + HandleErrorInternal(reason ?? new OperationCanceledException()); } } - protected bool LockCancelation() { - return 0 == Interlocked.CompareExchange(ref m_cancelationLock, 1, 0); - } } } diff -r 2a8466f0cb8a -r 1c2a16d071a7 Implab/FuncTaskT.cs --- a/Implab/FuncTaskT.cs Fri Feb 19 18:07:17 2016 +0300 +++ b/Implab/FuncTaskT.cs Fri Apr 22 13:08:08 2016 +0300 @@ -12,7 +12,9 @@ if (m_task != null && LockCancelation()) { try { SetResult(m_task(value)); - } catch (Exception err) { + } catch(OperationCanceledException reason) { + HandleCancelInternal(reason); + } catch(Exception err) { HandleErrorInternal(err); } } diff -r 2a8466f0cb8a -r 1c2a16d071a7 Implab/Implab.csproj --- a/Implab/Implab.csproj Fri Feb 19 18:07:17 2016 +0300 +++ b/Implab/Implab.csproj Fri Apr 22 13:08:08 2016 +0300 @@ -8,6 +8,9 @@ Implab Implab v4.5 + 0.2 + 8.0.30703 + 2.0 true @@ -88,40 +91,10 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -178,11 +151,50 @@ - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -257,5 +269,8 @@ + + + \ No newline at end of file diff -r 2a8466f0cb8a -r 1c2a16d071a7 Implab/JSON/JSONElementContext.cs --- a/Implab/JSON/JSONElementContext.cs Fri Feb 19 18:07:17 2016 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,17 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Implab.JSON { - /// - /// internal - /// - public enum JSONElementContext { - None, - Object, - Array, - Closed - } -} diff -r 2a8466f0cb8a -r 1c2a16d071a7 Implab/JSON/JSONElementType.cs --- a/Implab/JSON/JSONElementType.cs Fri Feb 19 18:07:17 2016 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,34 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Implab.JSON { - /// - /// Тип элемента на котором находится парсер - /// - public enum JSONElementType { - None, - /// - /// Начало объекта - /// - BeginObject, - /// - /// Конец объекта - /// - EndObject, - /// - /// Начало массива - /// - BeginArray, - /// - /// Конец массива - /// - EndArray, - /// - /// Простое значение - /// - Value - } -} diff -r 2a8466f0cb8a -r 1c2a16d071a7 Implab/JSON/JSONGrammar.cs --- a/Implab/JSON/JSONGrammar.cs Fri Feb 19 18:07:17 2016 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,99 +0,0 @@ -using Implab.Parsing; -using System.Linq; - -namespace Implab.JSON { - class JSONGrammar : Grammar { - public enum TokenType { - None, - BeginObject, - EndObject, - BeginArray, - EndArray, - String, - Number, - Literal, - NameSeparator, - ValueSeparator, - - StringBound, - EscapedChar, - UnescapedChar, - EscapedUnicode, - - Minus, - Plus, - Sign, - Integer, - Dot, - Exp - } - - readonly CDFADefinition m_jsonDFA; - readonly CDFADefinition m_stringDFA; - - public JSONGrammar() { - DefineAlphabet(Enumerable.Range(0, 0x20).Select(x => (char)x)); - var hexDigit = SymbolRangeToken('a','f').Or(SymbolRangeToken('A','F')).Or(SymbolRangeToken('0','9')); - var digit9 = SymbolRangeToken('1', '9'); - var zero = SymbolToken('0'); - var digit = zero.Or(digit9); - var dot = SymbolToken('.'); - var minus = SymbolToken('-'); - var sign = SymbolSetToken('-', '+'); - var expSign = SymbolSetToken('e', 'E'); - var letters = SymbolRangeToken('a', 'z'); - var integer = zero.Or(digit9.Cat(digit.EClosure())); - var frac = dot.Cat(digit.Closure()); - var exp = expSign.Cat(sign.Optional()).Cat(digit.Closure()); - var quote = SymbolToken('"'); - var backSlash = SymbolToken('\\'); - var specialEscapeChars = SymbolSetToken('\\', '"', '/', 'b', 'f', 't', 'n', 'r'); - var unicodeEspace = SymbolToken('u').Cat(hexDigit.Repeat(4)); - var whitespace = SymbolSetToken('\n', '\r', '\t', ' ').EClosure(); - var beginObject = whitespace.Cat(SymbolToken('{')).Cat(whitespace); - var endObject = whitespace.Cat(SymbolToken('}')).Cat(whitespace); - var beginArray = whitespace.Cat(SymbolToken('[')).Cat(whitespace); - var endArray = whitespace.Cat(SymbolToken(']')).Cat(whitespace); - var nameSep = whitespace.Cat(SymbolToken(':')).Cat(whitespace); - var valueSep = whitespace.Cat(SymbolToken(',')).Cat(whitespace); - - var number = minus.Optional().Cat(integer).Cat(frac.Optional()).Cat(exp.Optional()); - var literal = letters.Closure(); - var unescaped = SymbolTokenExcept(Enumerable.Range(0, 0x20).Union(new int[] { '\\', '"' }).Select(x => (char)x)); - - var jsonExpression = - number.Tag(TokenType.Number) - .Or(literal.Tag(TokenType.Literal)) - .Or(quote.Tag(TokenType.StringBound)) - .Or(beginObject.Tag(TokenType.BeginObject)) - .Or(endObject.Tag(TokenType.EndObject)) - .Or(beginArray.Tag(TokenType.BeginArray)) - .Or(endArray.Tag(TokenType.EndArray)) - .Or(nameSep.Tag(TokenType.NameSeparator)) - .Or(valueSep.Tag(TokenType.ValueSeparator)); - - - var jsonStringExpression = - quote.Tag(TokenType.StringBound) - .Or(backSlash.Cat(specialEscapeChars).Tag(TokenType.EscapedChar)) - .Or(backSlash.Cat(unicodeEspace).Tag(TokenType.EscapedUnicode)) - .Or(unescaped.Closure().Tag(TokenType.UnescapedChar)); - - - m_jsonDFA = BuildDFA(jsonExpression); - m_stringDFA = BuildDFA(jsonStringExpression); - } - - public CDFADefinition JsonDFA { - get { - return m_jsonDFA; - } - } - - public CDFADefinition JsonStringDFA { - get { - return m_stringDFA; - } - } - } -} diff -r 2a8466f0cb8a -r 1c2a16d071a7 Implab/JSON/JSONParser.cs --- a/Implab/JSON/JSONParser.cs Fri Feb 19 18:07:17 2016 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,277 +0,0 @@ -using Implab.Parsing; -using System; -using System.Diagnostics; -using System.IO; - -namespace Implab.JSON { - /// - /// internal - /// - public struct JSONParserContext { - public string memberName; - public JSONElementContext elementContext; - } - - /// - /// Pull парсер JSON данных. - /// - /// - /// Следует отметить отдельную интерпретацию свойства , - /// оно означает текущий уровень вложенности объектов, однако закрывающий - /// элемент объекта и массива имеет уровень меньше, чем сам объект. - /// - /// { // Level = 1 - /// "name" : "Peter", // Level = 1 - /// "address" : { // Level = 2 - /// city : "Stern" // Level = 2 - /// } // Level = 1 - /// } // Level = 0 - /// - /// - public class JSONParser : DFAutomaton, IDisposable { - - enum MemberContext { - MemberName, - MemberValue - } - - static readonly EnumAlphabet _alphabet = EnumAlphabet.FullAlphabet; - static readonly DFAStateDescriptior[] _jsonDFA; - static readonly DFAStateDescriptior[] _objectDFA; - static readonly DFAStateDescriptior[] _arrayDFA; - - static JSONParser() { - - - var valueExpression = Token.New(JsonTokenType.BeginArray, JsonTokenType.BeginObject, JsonTokenType.Literal, JsonTokenType.Number, JsonTokenType.String); - var memberExpression = Token.New(JsonTokenType.String).Cat(Token.New(JsonTokenType.NameSeparator)).Cat(valueExpression); - - var objectExpression = memberExpression - .Cat( - Token.New(JsonTokenType.ValueSeparator) - .Cat(memberExpression) - .EClosure() - ) - .Optional() - .Cat(Token.New(JsonTokenType.EndObject)) - .Tag(0); - var arrayExpression = valueExpression - .Cat( - Token.New(JsonTokenType.ValueSeparator) - .Cat(valueExpression) - .EClosure() - ) - .Optional() - .Cat(Token.New(JsonTokenType.EndArray)) - .Tag(0); - - var jsonExpression = valueExpression.Tag(0); - - _jsonDFA = BuildDFA(jsonExpression).States; - _objectDFA = BuildDFA(objectExpression).States; - _arrayDFA = BuildDFA(arrayExpression).States; - } - - static EDFADefinition BuildDFA(Token expr) { - var builder = new DFABuilder(); - var dfa = new EDFADefinition(_alphabet); - expr.Accept(builder); - - builder.BuildDFA(dfa); - return dfa; - } - - JSONScanner m_scanner; - MemberContext m_memberContext; - - JSONElementType m_elementType; - object m_elementValue; - - /// - /// Создает новый парсер на основе строки, содержащей JSON - /// - /// - public JSONParser(string text) - : base(_jsonDFA, INITIAL_STATE, new JSONParserContext { elementContext = JSONElementContext.None, memberName = String.Empty }) { - Safe.ArgumentNotEmpty(text, "text"); - m_scanner = new JSONScanner(); - m_scanner.Feed(text.ToCharArray()); - } - - /// - /// Создает новый экземпляр парсера, на основе текстового потока. - /// - /// Текстовый поток. - /// Признак того, что парсер должен конролировать время жизни входного потока. - public JSONParser(TextReader reader, bool dispose) - : base(_jsonDFA, INITIAL_STATE, new JSONParserContext { elementContext = JSONElementContext.None, memberName = String.Empty }) { - Safe.ArgumentNotNull(reader, "reader"); - m_scanner = new JSONScanner(); - m_scanner.Feed(reader, dispose); - } - - /// - /// Тип текущего элемента на котором стоит парсер. - /// - public JSONElementType ElementType { - get { return m_elementType; } - } - - /// - /// Имя элемента - имя свойства родительского контейнера. Для элементов массивов и корневого всегда - /// пустая строка. - /// - public string ElementName { - get { return m_context.info.memberName; } - } - - /// - /// Значение элемента. Только для элементов типа , для остальных null - /// - public object ElementValue { - get { return m_elementValue; } - } - - /// - /// Читает слеюудущий объект из потока - /// - /// true - операция чтения прошла успешно, false - конец данных - public bool Read() { - if (m_context.current == UNREACHEBLE_STATE) - throw new InvalidOperationException("The parser is in invalid state"); - object tokenValue; - JsonTokenType tokenType; - m_context.info.memberName = String.Empty; - while (m_scanner.ReadToken(out tokenValue, out tokenType)) { - Move((int)tokenType); - if (m_context.current == UNREACHEBLE_STATE) - UnexpectedToken(tokenValue, tokenType); - switch (tokenType) { - case JsonTokenType.BeginObject: - Switch( - _objectDFA, - INITIAL_STATE, - new JSONParserContext { - memberName = m_context.info.memberName, - elementContext = JSONElementContext.Object - } - ); - m_elementValue = null; - m_memberContext = MemberContext.MemberName; - m_elementType = JSONElementType.BeginObject; - return true; - case JsonTokenType.EndObject: - Restore(); - m_elementValue = null; - m_elementType = JSONElementType.EndObject; - return true; - case JsonTokenType.BeginArray: - Switch( - _arrayDFA, - INITIAL_STATE, - new JSONParserContext { - memberName = m_context.info.memberName, - elementContext = JSONElementContext.Array - } - ); - m_elementValue = null; - m_memberContext = MemberContext.MemberValue; - m_elementType = JSONElementType.BeginArray; - return true; - case JsonTokenType.EndArray: - Restore(); - m_elementValue = null; - m_elementType = JSONElementType.EndArray; - return true; - case JsonTokenType.String: - if (m_memberContext == MemberContext.MemberName) { - m_context.info.memberName = (string)tokenValue; - break; - } - m_elementType = JSONElementType.Value; - m_elementValue = tokenValue; - return true; - case JsonTokenType.Number: - m_elementType = JSONElementType.Value; - m_elementValue = tokenValue; - return true; - case JsonTokenType.Literal: - m_elementType = JSONElementType.Value; - m_elementValue = ParseLiteral((string)tokenValue); - return true; - case JsonTokenType.NameSeparator: - m_memberContext = MemberContext.MemberValue; - break; - case JsonTokenType.ValueSeparator: - m_memberContext = m_context.info.elementContext == JSONElementContext.Object ? MemberContext.MemberName : MemberContext.MemberValue; - break; - default: - UnexpectedToken(tokenValue, tokenType); - break; - } - } - if (m_context.info.elementContext != JSONElementContext.None) - throw new ParserException("Unexpedted end of data"); - return false; - } - - object ParseLiteral(string literal) { - switch (literal) { - case "null": - return null; - case "false": - return false; - case "true": - return true; - default: - UnexpectedToken(literal, JsonTokenType.Literal); - return null; // avoid compliler error - } - } - - void UnexpectedToken(object value, JsonTokenType tokenType) { - throw new ParserException(String.Format("Unexpected token {0}: '{1}'", tokenType, value)); - } - - - /// - /// Признак конца потока - /// - public bool EOF { - get { - return m_scanner.EOF; - } - } - - protected virtual void Dispose(bool disposing) { - if (disposing) { - m_scanner.Dispose(); - } - } - - /// - /// Освобождает парсер и связанный с ним сканнер. - /// - public void Dispose() { - Dispose(true); - GC.SuppressFinalize(this); - } - - ~JSONParser() { - Dispose(false); - } - - /// - /// Переходит в конец текущего объекта. - /// - public void SeekElementEnd() { - var level = Level - 1; - - Debug.Assert(level >= 0); - - while (Level != level) - Read(); - } - } - -} diff -r 2a8466f0cb8a -r 1c2a16d071a7 Implab/JSON/JSONScanner.cs --- a/Implab/JSON/JSONScanner.cs Fri Feb 19 18:07:17 2016 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,100 +0,0 @@ -using Implab.Parsing; -using System; -using System.Collections.Generic; -using System.Globalization; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Implab.JSON { - /// - /// Сканнер (лексер), разбивающий поток символов на токены JSON. - /// - public class JSONScanner : Scanner { - char[] m_stringBuffer; - DFAStateDescriptior[] m_stringDFA; - int[] m_stringAlphabet; - - /// - /// Создает новый экземпляр сканнера - /// - public JSONScanner() - : base(JSONGrammar.Instance.JsonDFA.States, JSONGrammar.Instance.JsonDFA.Alphabet.GetTranslationMap()) { - m_stringBuffer = new char[1024]; - var dfa = JSONGrammar.Instance.JsonStringDFA; - m_stringAlphabet = dfa.Alphabet.GetTranslationMap(); - m_stringDFA = dfa.States; - } - - /// - /// Читает следующий лексический элемент из входных данных. - /// - /// Возвращает значение прочитанного токена. - /// Возвращает тип прочитанного токена. - /// true - чтение произведено успешно. false - достигнут конец входных данных - /// В случе если токен не распознается, возникает исключение. Значения токенов обрабатываются, т.е. - /// в строках обрабатываются экранированные символы, числа становтся типа double. - public bool ReadToken(out object tokenValue, out JsonTokenType tokenType) { - if (ReadTokenInternal()) { - switch ((JSONGrammar.TokenType)m_currentState.tag[0]) { - case JSONGrammar.TokenType.StringBound: - tokenValue = ReadString(); - tokenType = JsonTokenType.String; - break; - case JSONGrammar.TokenType.Number: - tokenValue = Double.Parse(new String(m_buffer, m_tokenOffset, m_tokenLen), CultureInfo.InvariantCulture); - tokenType = JsonTokenType.Number; - break; - default: - tokenType = (JsonTokenType)m_currentState.tag[0]; - tokenValue = new String(m_buffer, m_tokenOffset, m_tokenLen); - break; - } - return true; - } - tokenValue = null; - tokenType = JsonTokenType.None; - return false; - } - - string ReadString() { - int pos = 0; - Switch(m_stringDFA, m_stringAlphabet); - while (ReadTokenInternal()) { - switch ((JSONGrammar.TokenType)m_currentState.tag[0]) { - case JSONGrammar.TokenType.StringBound: - Restore(); - return new String(m_stringBuffer, 0, pos); - case JSONGrammar.TokenType.UnescapedChar: - EnsureStringBufferSize(pos + m_tokenLen); - Array.Copy(m_buffer, m_tokenOffset, m_stringBuffer, pos, m_tokenLen); - pos += m_tokenLen; - break; - case JSONGrammar.TokenType.EscapedUnicode: - EnsureStringBufferSize(pos + 1); - m_stringBuffer[pos] = StringTranslator.TranslateHexUnicode(m_buffer, m_tokenOffset + 2); - pos++; - break; - case JSONGrammar.TokenType.EscapedChar: - EnsureStringBufferSize(pos + 1); - m_stringBuffer[pos] = StringTranslator.TranslateEscapedChar(m_buffer[m_tokenOffset + 1]); - pos++; - break; - default: - break; - } - - } - - throw new ParserException("Unexpected end of data"); - } - - void EnsureStringBufferSize(int size) { - if (size > m_stringBuffer.Length) { - var newBuffer = new char[size]; - m_stringBuffer.CopyTo(newBuffer, 0); - m_stringBuffer = newBuffer; - } - } - } -} diff -r 2a8466f0cb8a -r 1c2a16d071a7 Implab/JSON/JSONWriter.cs --- a/Implab/JSON/JSONWriter.cs Fri Feb 19 18:07:17 2016 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,319 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Globalization; -using System.Diagnostics; - -namespace Implab.JSON { - public class JSONWriter { - struct Context { - public bool needComma; - public JSONElementContext element; - } - Stack m_contextStack = new Stack(); - Context m_context; - - const int BUFFER_SIZE = 64; - - TextWriter m_writer; - readonly bool m_indent = true; - readonly int m_indentSize = 4; - readonly char[] m_buffer = new char[BUFFER_SIZE]; - int m_bufferPos; - - static readonly char [] _hex = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' }; - static readonly char [] _escapeBKS, - _escapeFWD, - _escapeCR, - _escapeNL, - _escapeTAB, - _escapeBSLASH, - _escapeQ; - - static JSONWriter() { - _escapeBKS = "\\b".ToCharArray(); - _escapeFWD = "\\f".ToCharArray(); - _escapeCR = "\\r".ToCharArray(); - _escapeNL = "\\n".ToCharArray(); - _escapeTAB = "\\t".ToCharArray(); - _escapeBSLASH = "\\\\".ToCharArray(); - _escapeQ = "\\\"".ToCharArray(); - } - - public JSONWriter(TextWriter writer) { - Safe.ArgumentNotNull(writer, "writer"); - m_writer = writer; - } - - public JSONWriter(TextWriter writer, bool indent) { - Safe.ArgumentNotNull(writer, "writer"); - - m_writer = writer; - m_indent = indent; - } - - void WriteIndent() { - if (m_indent) { - var indent = new char[m_contextStack.Count * m_indentSize + 1]; - indent[0] = '\n'; - for (int i = 1; i < indent.Length; i++) - indent[i] = ' '; - m_writer.Write(new String(indent)); - } else { - m_writer.Write(' '); - } - } - - void WriteMemberName(string name) { - Safe.ArgumentNotEmpty(name, "name"); - if (m_context.element != JSONElementContext.Object) - OperationNotApplicable("WriteMember"); - if (m_context.needComma) - m_writer.Write(","); - - WriteIndent(); - m_context.needComma = true; - Write(name); - m_writer.Write(" : "); - } - - public void WriteValue(string name, string value) { - WriteMemberName(name); - Write(value); - } - - public void WriteValue(string name, bool value) { - WriteMemberName(name); - Write(value); - } - - public void WriteValue(string name, double value) { - WriteMemberName(name); - Write(value); - } - - public void WriteValue(string value) { - if (m_context.element == JSONElementContext.Array) { - - if (m_context.needComma) - m_writer.Write(","); - WriteIndent(); - m_context.needComma = true; - - Write(value); - } else if (m_context.element == JSONElementContext.None) { - Write(value); - m_context.element = JSONElementContext.Closed; - } else { - OperationNotApplicable("WriteValue"); - } - } - - public void WriteValue(bool value) { - if (m_context.element == JSONElementContext.Array) { - - if (m_context.needComma) - m_writer.Write(","); - WriteIndent(); - m_context.needComma = true; - - Write(value); - } else if (m_context.element == JSONElementContext.None) { - Write(value); - m_context.element = JSONElementContext.Closed; - } else { - OperationNotApplicable("WriteValue"); - } - } - - public void WriteValue(double value) { - if (m_context.element == JSONElementContext.Array) { - - if (m_context.needComma) - m_writer.Write(","); - WriteIndent(); - m_context.needComma = true; - - Write(value); - } else if (m_context.element == JSONElementContext.None) { - Write(value); - m_context.element = JSONElementContext.Closed; - } else { - OperationNotApplicable("WriteValue"); - } - } - - public void BeginObject() { - if (m_context.element != JSONElementContext.None && m_context.element != JSONElementContext.Array) - OperationNotApplicable("BeginObject"); - if (m_context.needComma) - m_writer.Write(","); - - WriteIndent(); - - m_context.needComma = true; - - m_contextStack.Push(m_context); - - m_context = new Context { element = JSONElementContext.Object, needComma = false }; - m_writer.Write("{"); - } - - public void BeginObject(string name) { - WriteMemberName(name); - - m_contextStack.Push(m_context); - - m_context = new Context { element = JSONElementContext.Object, needComma = false }; - m_writer.Write("{"); - } - - public void EndObject() { - if (m_context.element != JSONElementContext.Object) - OperationNotApplicable("EndObject"); - - m_context = m_contextStack.Pop(); - if (m_contextStack.Count == 0) - m_context.element = JSONElementContext.Closed; - WriteIndent(); - m_writer.Write("}"); - } - - public void BeginArray() { - if (m_context.element != JSONElementContext.None && m_context.element != JSONElementContext.Array) - throw new InvalidOperationException(); - if (m_context.needComma) { - m_writer.Write(","); - - } - m_context.needComma = true; - - WriteIndent(); - m_contextStack.Push(m_context); - m_context = new Context { element = JSONElementContext.Array, needComma = false }; - m_writer.Write("["); - } - - public void BeginArray(string name) { - WriteMemberName(name); - - m_contextStack.Push(m_context); - - m_context = new Context { element = JSONElementContext.Array, needComma = false }; - m_writer.Write("["); - } - - public void EndArray() { - if (m_context.element != JSONElementContext.Array) - OperationNotApplicable("EndArray"); - - m_context = m_contextStack.Pop(); - if (m_contextStack.Count == 0) - m_context.element = JSONElementContext.Closed; - WriteIndent(); - m_writer.Write("]"); - } - - void Write(bool value) { - m_writer.Write(value ? "true" : "false"); - } - - void FlushBuffer() { - if (m_bufferPos > 0) { - m_writer.Write(m_buffer, 0, m_bufferPos); - m_bufferPos = 0; - } - } - - void Write(string value) { - if (value == null) { - m_writer.Write("null"); - return; - } - - Debug.Assert(m_bufferPos == 0); - - var chars = value.ToCharArray(); - m_buffer[m_bufferPos++] = '"'; - - // Analysis disable once ForCanBeConvertedToForeach - for (int i = 0; i < chars.Length; i++) { - var ch = chars[i]; - - char[] escapeSeq; - - switch (ch) { - case '\b': - escapeSeq = _escapeBKS; - break; - case '\f': - escapeSeq = _escapeFWD; - break; - case '\r': - escapeSeq = _escapeCR; - break; - case '\n': - escapeSeq = _escapeNL; - break; - case '\t': - escapeSeq = _escapeTAB; - break; - case '\\': - escapeSeq = _escapeBSLASH; - break; - case '"': - escapeSeq = _escapeQ; - break; - default: - if (ch < 0x20) { - if (m_bufferPos + 6 > BUFFER_SIZE) - FlushBuffer(); - - m_buffer[m_bufferPos++] = '\\'; - m_buffer[m_bufferPos++] = 'u'; - m_buffer[m_bufferPos++] = '0'; - m_buffer[m_bufferPos++] = '0'; - m_buffer[m_bufferPos++] = _hex[ch >> 4 & 0xf]; - m_buffer[m_bufferPos++] = _hex[ch & 0xf]; - - } else { - if (m_bufferPos >= BUFFER_SIZE) - FlushBuffer(); - m_buffer[m_bufferPos++] = ch; - } - continue; - } - - if (m_bufferPos + escapeSeq.Length > BUFFER_SIZE) - FlushBuffer(); - - Array.Copy(escapeSeq, 0, m_buffer, m_bufferPos, escapeSeq.Length); - m_bufferPos += escapeSeq.Length; - - } - - if (m_bufferPos >= BUFFER_SIZE) - FlushBuffer(); - - m_buffer[m_bufferPos++] = '"'; - - FlushBuffer(); - } - - void Write(double value) { - if (double.IsNaN(value)) - Write("NaN"); - else if (double.IsNegativeInfinity(value)) - Write("-Infinity"); - else if (double.IsPositiveInfinity(value)) - Write("Infinity"); - else - m_writer.Write(value.ToString(CultureInfo.InvariantCulture)); - } - - void OperationNotApplicable(string opName) { - throw new InvalidOperationException(String.Format("The operation '{0}' isn't applicable in the context of '{1}'", opName, m_context.element )); - } - - } -} diff -r 2a8466f0cb8a -r 1c2a16d071a7 Implab/JSON/JSONXmlReader.cs --- a/Implab/JSON/JSONXmlReader.cs Fri Feb 19 18:07:17 2016 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,343 +0,0 @@ -using Implab; -using Implab.Parsing; -using System; -using System.Collections.Generic; -using System.Globalization; -using System.IO; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using System.Xml; - -namespace Implab.JSON { - public class JSONXmlReader : XmlReader { - - enum ValueContext { - Undefined, - ElementStart, - ElementValue, - ElementEnd, - ElementEmpty - } - - struct LocalNameContext { - public string localName; - public bool isArray; - } - - JSONParser m_parser; - ValueContext m_valueContext; - ReadState m_state = ReadState.Initial; - Stack m_localNameStack = new Stack(); - LocalNameContext m_localName; - int m_depthCorrection = 0; - - readonly string m_rootName; - readonly string m_prefix; - readonly string m_namespaceUri; - readonly bool m_flattenArrays; - readonly string m_arrayItemName; - readonly XmlNameTable m_nameTable; - - JSONXmlReader(JSONParser parser, JSONXmlReaderOptions options) { - m_parser = parser; - - if (options != null) { - m_prefix = options.NodesPrefix ?? String.Empty; - m_namespaceUri = options.NamespaceURI ?? String.Empty; - m_rootName = options.RootName ?? "json"; - m_flattenArrays = options.FlattenArrays; - m_arrayItemName = options.ArrayItemName ?? "item"; - m_nameTable = options.NameTable ?? new NameTable(); - } else { - m_prefix = String.Empty; - m_namespaceUri = String.Empty; - m_rootName = "json"; - m_flattenArrays = false; - m_arrayItemName = "item"; - m_nameTable = new NameTable(); - } - } - - /// - /// Always 0, JSON doesn't support attributes - /// - public override int AttributeCount { - get { return 0; } - } - - public override string BaseURI { - get { return String.Empty; } - } - - public override int Depth { - get { - return m_localNameStack.Count + m_depthCorrection; - } - } - - public override bool EOF { - get { return m_parser.EOF; } - } - - /// - /// Always throws an exception - /// - /// - /// - public override string GetAttribute(int i) { - throw new ArgumentOutOfRangeException(); - } - - /// - /// Always returns empty string - /// - /// - /// - /// - public override string GetAttribute(string name, string namespaceURI) { - return String.Empty; - } - - /// - /// Always returns empty string - /// - /// - /// - public override string GetAttribute(string name) { - return String.Empty; - } - - public override bool IsEmptyElement { - get { return m_parser.ElementType == JSONElementType.Value && m_valueContext == ValueContext.ElementEmpty; } - } - - public override string LocalName { - get { return m_localName.localName; } - } - - public override string LookupNamespace(string prefix) { - if (String.IsNullOrEmpty(prefix) || prefix == m_prefix) - return m_namespaceUri; - else - return String.Empty; - } - - public override bool MoveToAttribute(string name, string ns) { - return false; - } - - public override bool MoveToAttribute(string name) { - return false; - } - - public override bool MoveToElement() { - return false; - } - - public override bool MoveToFirstAttribute() { - return false; - } - - public override bool MoveToNextAttribute() { - return false; - } - - public override XmlNameTable NameTable { - get { return m_nameTable; } - } - - public override string NamespaceURI { - get { return m_namespaceUri; } - } - - public override XmlNodeType NodeType { - get { - switch (m_parser.ElementType) { - case JSONElementType.BeginObject: - case JSONElementType.BeginArray: - return XmlNodeType.Element; - case JSONElementType.EndObject: - case JSONElementType.EndArray: - return XmlNodeType.EndElement; - case JSONElementType.Value: - switch (m_valueContext) { - case ValueContext.ElementStart: - case ValueContext.ElementEmpty: - return XmlNodeType.Element; - case ValueContext.ElementValue: - return XmlNodeType.Text; - case ValueContext.ElementEnd: - return XmlNodeType.EndElement; - default: - throw new InvalidOperationException(); - } - default: - throw new InvalidOperationException(); - } - } - } - - public override string Prefix { - get { return m_prefix; } - } - - public override bool Read() { - if (m_state != System.Xml.ReadState.Interactive && m_state != System.Xml.ReadState.Initial) - return false; - - if (m_state == ReadState.Initial) - m_state = System.Xml.ReadState.Interactive; - - try { - switch (m_parser.ElementType) { - case JSONElementType.Value: - switch (m_valueContext) { - case ValueContext.ElementStart: - SetLocalName(String.Empty); - m_valueContext = ValueContext.ElementValue; - return true; - case ValueContext.ElementValue: - RestoreLocalName(); - m_valueContext = ValueContext.ElementEnd; - return true; - case ValueContext.ElementEmpty: - case ValueContext.ElementEnd: - RestoreLocalName(); - break; - } - break; - case JSONElementType.EndArray: - case JSONElementType.EndObject: - RestoreLocalName(); - break; - } - string itemName = m_parser.ElementType == JSONElementType.None ? m_rootName : m_flattenArrays ? m_localName.localName : m_arrayItemName; - while (m_parser.Read()) { - if (!String.IsNullOrEmpty(m_parser.ElementName)) - itemName = m_parser.ElementName; - - switch (m_parser.ElementType) { - case JSONElementType.BeginArray: - if (m_flattenArrays && !m_localName.isArray) { - m_depthCorrection--; - SetLocalName(itemName, true); - continue; - } else { - SetLocalName(itemName, true); - } - break; - case JSONElementType.BeginObject: - SetLocalName(itemName); - break; - case JSONElementType.EndArray: - if (m_flattenArrays && !m_localNameStack.Peek().isArray) { - RestoreLocalName(); - m_depthCorrection++; - continue; - } - break; - case JSONElementType.EndObject: - break; - case JSONElementType.Value: - SetLocalName(itemName); - m_valueContext = m_parser.ElementValue == null ? ValueContext.ElementEmpty : ValueContext.ElementStart; - break; - default: - break; - } - return true; - } - - m_state = System.Xml.ReadState.EndOfFile; - return false; - } catch { - m_state = System.Xml.ReadState.Error; - throw; - } - } - - public override bool ReadAttributeValue() { - return false; - } - - public override ReadState ReadState { - get { return m_state; } - } - - public override void ResolveEntity() { - // do nothing - } - - public override string Value { - get { - if (m_parser.ElementValue == null) - return String.Empty; - if (Convert.GetTypeCode(m_parser.ElementValue) == TypeCode.Double) - return ((double)m_parser.ElementValue).ToString(CultureInfo.InvariantCulture); - else - return m_parser.ElementValue.ToString(); - } - } - - void SetLocalName(string name) { - m_localNameStack.Push(m_localName); - m_localName.localName = name; - m_localName.isArray = false; - } - - void SetLocalName(string name, bool isArray) { - m_localNameStack.Push(m_localName); - m_localName.localName = name; - m_localName.isArray = isArray; - } - - void RestoreLocalName() { - m_localName = m_localNameStack.Pop(); - } - - public override void Close() { - - } - - protected override void Dispose(bool disposing) { - #if MONO - disposing = true; - #endif - if (disposing) { - m_parser.Dispose(); - } - base.Dispose(disposing); - } - - public static JSONXmlReader Create(string file, JSONXmlReaderOptions options) { - return Create(File.OpenText(file), options); - } - - /// - /// Creates the XmlReader for the specified text stream with JSON data. - /// - /// Text reader. - /// Options. - /// - /// The reader will be disposed when the XmlReader is disposed. - /// - public static JSONXmlReader Create(TextReader reader, JSONXmlReaderOptions options) { - return new JSONXmlReader(new JSONParser(reader, true), options); - } - - /// - /// Creates the XmlReader for the specified stream with JSON data. - /// - /// Stream. - /// Options. - /// - /// The stream will be disposed when the XmlReader is disposed. - /// - public static JSONXmlReader Create(Stream stream, JSONXmlReaderOptions options) { - Safe.ArgumentNotNull(stream, "stream"); - // HACK don't dispose StreaReader to keep stream opened - return Create(new StreamReader(stream), options); - } - } -} diff -r 2a8466f0cb8a -r 1c2a16d071a7 Implab/JSON/JSONXmlReaderOptions.cs --- a/Implab/JSON/JSONXmlReaderOptions.cs Fri Feb 19 18:07:17 2016 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,65 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Xml; - -namespace Implab.JSON { - /// - /// Набор необязательных параметров для , позволяющий управлять процессом - /// интерпретации JSON документа. - /// - public class JSONXmlReaderOptions { - /// - /// Пространство имен в котором будут располагаться читаемые элементы документа - /// - public string NamespaceURI { - get; - set; - } - - /// - /// Интерпретировать массивы как множественные элементы (убирает один уровень вложенности), иначе массив - /// представляется в виде узла, дочерними элементами которого являются элементы массива, имена дочерних элементов - /// определяются свойством . По умолчанию false. - /// - public bool FlattenArrays { - get; - set; - } - - /// - /// Префикс, для узлов документа - /// - public string NodesPrefix { - get; - set; - } - - /// - /// Имя корневого элемента в xml документе - /// - public string RootName { - get; - set; - } - - /// - /// Имя элемента для массивов, если не включена опция . - /// По умолчанию item. - /// - public string ArrayItemName { - get; - set; - } - - /// - /// Таблица атомизированных строк для построения документа. - /// - public XmlNameTable NameTable { - get; - set; - } - - } -} diff -r 2a8466f0cb8a -r 1c2a16d071a7 Implab/JSON/JsonTokenType.cs --- a/Implab/JSON/JsonTokenType.cs Fri Feb 19 18:07:17 2016 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,50 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Implab.JSON { - /// - /// Тип токенов, возвращаемых . - /// - public enum JsonTokenType : int { - None = 0, - /// - /// Начало объекта - /// - BeginObject, - /// - /// Конец объекта - /// - EndObject, - /// - /// Начало массива - /// - BeginArray, - /// - /// Конец массива - /// - EndArray, - /// - /// Строка - /// - String, - /// - /// Число - /// - Number, - /// - /// Литерал - /// - Literal, - /// - /// Разделитель имени : - /// - NameSeparator, - /// - /// Разделитель имени , - /// - ValueSeparator - } -} diff -r 2a8466f0cb8a -r 1c2a16d071a7 Implab/JSON/StringTranslator.cs --- a/Implab/JSON/StringTranslator.cs Fri Feb 19 18:07:17 2016 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,96 +0,0 @@ -using Implab; -using Implab.Parsing; -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Implab.JSON { - /// - /// Класс для преобразования экранированной строки JSON - /// - public class StringTranslator : Scanner { - static readonly char[] _escMap; - static readonly int[] _hexMap; - - static StringTranslator() { - var chars = new char[] { 'b', 'f', 't', 'r', 'n', '\\', '/' }; - var vals = new char[] { '\b', '\f', '\t', '\r', '\n', '\\', '/' }; - - _escMap = new char[chars.Max() + 1]; - - for (int i = 0; i < chars.Length; i++) - _escMap[chars[i]] = vals[i]; - - var hexs = new char[] { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f', 'A', 'B', 'C', 'D', 'E', 'F' }; - var ints = new int[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 10, 11, 12, 13, 14, 15 }; - - _hexMap = new int[hexs.Max() + 1]; - - for (int i = 0; i < hexs.Length; i++) - _hexMap[hexs[i]] = ints[i]; - - } - - public StringTranslator() - : base(JSONGrammar.Instance.JsonStringDFA.States, JSONGrammar.Instance.JsonStringDFA.Alphabet.GetTranslationMap()) { - } - - public string Translate(string data) { - Safe.ArgumentNotNull(data, "data"); - return Translate(data.ToCharArray()); - } - - public string Translate(char[] data) { - Safe.ArgumentNotNull(data, "data"); - return Translate(data, data.Length); - } - - public string Translate(char[] data, int length) { - Safe.ArgumentNotNull(data, "data"); - Safe.ArgumentInRange(length, 0, data.Length, "length"); - - var translated = new char[length]; - - Feed(data,length); - - int pos = 0; - - while (ReadTokenInternal()) { - switch ((JSONGrammar.TokenType)TokenTags[0]) { - case JSONGrammar.TokenType.UnescapedChar: - Array.Copy(m_buffer,m_tokenOffset,translated,pos,m_tokenLen); - pos += m_tokenLen; - break; - case JSONGrammar.TokenType.EscapedChar: - translated[pos] = _escMap[m_buffer[m_tokenOffset + 1]]; - pos++; - break; - case JSONGrammar.TokenType.EscapedUnicode: - translated[pos] = TranslateHexUnicode(m_buffer,m_tokenOffset + 2); - pos++; - break; - } - } - - return new String(translated, 0, pos); - } - - internal static char TranslateEscapedChar(char symbol) { - return _escMap[symbol]; - } - - internal static char TranslateHexUnicode(char[] symbols, int offset) { - Debug.Assert(symbols != null); - Debug.Assert(symbols.Length - offset >= 4); - - int value = (_hexMap[symbols[offset]] << 12) - | (_hexMap[symbols[offset + 1]] << 8) - | (_hexMap[symbols[offset + 2]] << 4) - | (_hexMap[symbols[offset + 3]]); - return (char)value; - } - } -} diff -r 2a8466f0cb8a -r 1c2a16d071a7 Implab/Parsing/AltToken.cs --- a/Implab/Parsing/AltToken.cs Fri Feb 19 18:07:17 2016 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,17 +0,0 @@ -using System; - -namespace Implab.Parsing { - public class AltToken: BinaryToken { - public AltToken(Token left, Token right) - : base(left, right) { - } - - public override void Accept(IVisitor visitor) { - Safe.ArgumentNotNull(visitor, "visitor"); - visitor.Visit(this); - } - public override string ToString() { - return String.Format(Right is BinaryToken ? "{0}|({1})" : "{0}|{1}", Left, Right); - } - } -} diff -r 2a8466f0cb8a -r 1c2a16d071a7 Implab/Parsing/BinaryToken.cs --- a/Implab/Parsing/BinaryToken.cs Fri Feb 19 18:07:17 2016 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,26 +0,0 @@ -using Implab; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Implab.Parsing { - public abstract class BinaryToken : Token { - Token m_left; - Token m_right; - - public Token Left { - get { return m_left; } - } - - public Token Right { - get { return m_right; } - } - - protected BinaryToken(Token left, Token right) { - Safe.ArgumentNotNull(m_left = left, "left"); - Safe.ArgumentNotNull(m_right = right, "right"); - } - } -} diff -r 2a8466f0cb8a -r 1c2a16d071a7 Implab/Parsing/CDFADefinition.cs --- a/Implab/Parsing/CDFADefinition.cs Fri Feb 19 18:07:17 2016 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,22 +0,0 @@ -namespace Implab.Parsing { - public class CDFADefinition : DFADefinition { - readonly CharAlphabet m_alphabet; - - public CharAlphabet Alphabet { - get { return m_alphabet; } - } - - public CDFADefinition(CharAlphabet alphabet): base(alphabet.Count) { - m_alphabet = alphabet; - } - - public CDFADefinition Optimize() { - - return (CDFADefinition)Optimize(alphabet => new CDFADefinition((CharAlphabet)alphabet), m_alphabet, new CharAlphabet()); - } - - public void PrintDFA() { - PrintDFA(m_alphabet); - } - } -} diff -r 2a8466f0cb8a -r 1c2a16d071a7 Implab/Parsing/CatToken.cs --- a/Implab/Parsing/CatToken.cs Fri Feb 19 18:07:17 2016 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,22 +0,0 @@ -using System; - -namespace Implab.Parsing { - public class CatToken : BinaryToken { - public CatToken(Token left, Token right) - : base(left, right) { - } - - public override void Accept(IVisitor visitor) { - Safe.ArgumentNotNull(visitor, "visitor"); - visitor.Visit(this); - } - - public override string ToString() { - return String.Format("{0}{1}", FormatToken(Left), FormatToken(Right)); - } - - string FormatToken(Token token) { - return String.Format(token is AltToken ? "({0})" : "{0}", token); - } - } -} diff -r 2a8466f0cb8a -r 1c2a16d071a7 Implab/Parsing/CharAlphabet.cs --- a/Implab/Parsing/CharAlphabet.cs Fri Feb 19 18:07:17 2016 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,23 +0,0 @@ -using Implab; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Implab.Parsing { - public class CharAlphabet: IndexedAlphabetBase { - - public CharAlphabet() - : base(char.MaxValue + 1) { - } - - public override int GetSymbolIndex(char symbol) { - return symbol; - } - - public override IEnumerable InputSymbols { - get { return Enumerable.Range(char.MinValue, char.MaxValue).Select(x => (char)x); } - } - } -} diff -r 2a8466f0cb8a -r 1c2a16d071a7 Implab/Parsing/DFABuilder.cs --- a/Implab/Parsing/DFABuilder.cs Fri Feb 19 18:07:17 2016 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,180 +0,0 @@ -using Implab; -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.Linq; - -namespace Implab.Parsing { - /// - /// Используется для построения ДКА по регулярному выражению, сначала обходит - /// регулярное выражение и вычисляет followpos, затем используется метод - /// для построения автомата. - /// - public class DFABuilder : IVisitor { - int m_idx = 0; - Token m_root; - HashSet m_firstpos; - HashSet m_lastpos; - - Dictionary> m_followpos = new Dictionary>(); - Dictionary m_indexes = new Dictionary(); - Dictionary m_ends = new Dictionary(); - - public Dictionary> FollowposMap { - get { return m_followpos; } - } - - public HashSet Followpos(int pos) { - HashSet set; - if (m_followpos.TryGetValue(pos, out set)) - return set; - return m_followpos[pos] = new HashSet(); - } - - bool Nullable(object n) { - if (n is EmptyToken || n is StarToken) - return true; - if (n is AltToken) - return Nullable(((AltToken)n).Left) || Nullable(((AltToken)n).Right); - if (n is CatToken) - return Nullable(((CatToken)n).Left) && Nullable(((CatToken)n).Right); - return false; - } - - - public void Visit(AltToken token) { - if (m_root == null) - m_root = token; - var firtspos = new HashSet(); - var lastpos = new HashSet(); - - token.Left.Accept(this); - firtspos.UnionWith(m_firstpos); - lastpos.UnionWith(m_lastpos); - - token.Right.Accept(this); - firtspos.UnionWith(m_firstpos); - lastpos.UnionWith(m_lastpos); - - m_firstpos = firtspos; - m_lastpos = lastpos; - } - - public void Visit(StarToken token) { - if (m_root == null) - m_root = token; - token.Token.Accept(this); - - foreach (var i in m_lastpos) - Followpos(i).UnionWith(m_firstpos); - } - - public void Visit(CatToken token) { - if (m_root == null) - m_root = token; - - var firtspos = new HashSet(); - var lastpos = new HashSet(); - token.Left.Accept(this); - firtspos.UnionWith(m_firstpos); - var leftLastpos = m_lastpos; - - token.Right.Accept(this); - lastpos.UnionWith(m_lastpos); - var rightFirstpos = m_firstpos; - - if (Nullable(token.Left)) - firtspos.UnionWith(rightFirstpos); - - if (Nullable(token.Right)) - lastpos.UnionWith(leftLastpos); - - m_firstpos = firtspos; - m_lastpos = lastpos; - - foreach (var i in leftLastpos) - Followpos(i).UnionWith(rightFirstpos); - - } - - public void Visit(EmptyToken token) { - if (m_root == null) - m_root = token; - ; - } - - public void Visit(SymbolToken token) { - if (m_root == null) - m_root = token; - m_idx++; - m_indexes[m_idx] = token.Value; - m_firstpos = new HashSet(new[] { m_idx }); - m_lastpos = new HashSet(new[] { m_idx }); - } - - public void Visit(EndToken token) { - if (m_root == null) - m_root = token; - m_idx++; - m_indexes[m_idx] = IndexedAlphabetBase.UNCLASSIFIED; - m_firstpos = new HashSet(new[] { m_idx }); - m_lastpos = new HashSet(new[] { m_idx }); - Followpos(m_idx); - m_ends.Add(m_idx, token.Tag); - } - - public void BuildDFA(IDFADefinition dfa) { - Safe.ArgumentNotNull(dfa,"dfa"); - - var stateMap = new Dictionary, int>(new CustomEqualityComparer>( - (x, y) => x.SetEquals(y), - (x) => x.Sum(n => n.GetHashCode()) - )); - - stateMap[m_firstpos] = DefineState( dfa, m_firstpos); - Debug.Assert(stateMap[m_firstpos] == DFADefinition.INITIAL_STATE); - - var queue = new Queue>(); - - queue.Enqueue(m_firstpos); - - while (queue.Count > 0) { - var state = queue.Dequeue(); - var s1 = stateMap[state]; - - for (int a = 0; a < dfa.AlphabetSize; a++) { - var next = new HashSet(); - foreach (var p in state) { - if (m_indexes[p] == a) { - next.UnionWith(Followpos(p)); - } - } - if (next.Count > 0) { - int s2; - if (!stateMap.TryGetValue(next, out s2)) { - stateMap[next] = s2 = DefineState(dfa, next); - queue.Enqueue(next); - } - dfa.DefineTransition(s1, s2, a); - } - } - - } - } - - int[] GetStateTags(HashSet state) { - Debug.Assert(state != null); - return state.Where(m_ends.ContainsKey).Select(pos => m_ends[pos]).ToArray(); - } - - int DefineState(IDFADefinition automa, HashSet state) { - Debug.Assert(automa != null); - Debug.Assert(state != null); - - var tags = GetStateTags(state); - - return tags.Length > 0 ? automa.AddState(tags) : automa.AddState(); - } - - } -} diff -r 2a8466f0cb8a -r 1c2a16d071a7 Implab/Parsing/DFADefinition.cs --- a/Implab/Parsing/DFADefinition.cs Fri Feb 19 18:07:17 2016 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,285 +0,0 @@ -using Implab; -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.Linq; - -namespace Implab.Parsing { - public class DFADefinition : IDFADefinition { - readonly List> m_states; - - public const int INITIAL_STATE = 1; - public const int UNREACHEBLE_STATE = 0; - - DFAStateDescriptior[] m_statesArray; - readonly int m_alpabetSize; - - public DFADefinition(int alphabetSize) { - m_states = new List>(); - m_alpabetSize = alphabetSize; - - m_states.Add(new DFAStateDescriptior()); - } - - public bool InitialStateIsFinal { - get { - return m_states[INITIAL_STATE].final; - } - } - - public int AddState() { - var index = m_states.Count; - m_states.Add(new DFAStateDescriptior { - final = false, - transitions = new int[AlphabetSize] - }); - m_statesArray = null; - - return index; - } - - public int AddState(TTag[] tag) { - var index = m_states.Count; - bool final = tag != null && tag.Length != 0; - m_states.Add(new DFAStateDescriptior { - final = final, - transitions = new int[AlphabetSize], - tag = final ? tag : null - }); - m_statesArray = null; - return index; - } - - public void DefineTransition(TState s1, TState s2, TInput symbol) { - int is1 = StateAlphabet.Translate(s1); - int is2 = StateAlphabet.Translate(s2); - int isym = InputAlphabet.Translate(symbol); - - Safe.ArgumentAssert(is1 != 0, "s1"); - Safe.ArgumentAssert(is2 != 0, "s2"); - Safe.ArgumentAssert(isym != 0, "symbol"); - - m_states[is1].transitions[isym] = is2; - } - - #region IDFADefinition implementation - - public DFAStateDescriptior[] GetTransitionTable() { - if (m_statesArray == null) - m_statesArray = m_states.ToArray(); - return m_statesArray; - } - - public IAlphabet InputAlphabet { - get { - throw new NotImplementedException(); - } - } - - public IAlphabet StateAlphabet { - get { - throw new NotImplementedException(); - } - } - - #endregion - - protected IDFADefinition<> Optimize(Func, IDFADefinition> dfaFactory,IAlphabet sourceAlphabet, IAlphabet minimalAlphabet) { - Safe.ArgumentNotNull(dfaFactory, "dfaFactory"); - Safe.ArgumentNotNull(minimalAlphabet, "minimalAlphabet"); - - var setComparer = new CustomEqualityComparer>( - (x, y) => x.SetEquals(y), - (s) => s.Sum(x => x.GetHashCode()) - ); - - var arrayComparer = new CustomEqualityComparer( - (x,y) => (new HashSet(x)).SetEquals(new HashSet(y)), - (a) => a.Sum(x => x.GetHashCode()) - ); - - var optimalStates = new HashSet>(setComparer); - var queue = new HashSet>(setComparer); - - foreach (var g in Enumerable - .Range(INITIAL_STATE, m_states.Count-1) - .Select(i => new { - index = i, - descriptor = m_states[i] - }) - .Where(x => x.descriptor.final) - .GroupBy(x => x.descriptor.tag, arrayComparer) - ) { - optimalStates.Add(new HashSet(g.Select(x => x.index))); - } - - var state = new HashSet( - Enumerable - .Range(INITIAL_STATE, m_states.Count - 1) - .Where(i => !m_states[i].final) - ); - optimalStates.Add(state); - queue.Add(state); - - while (queue.Count > 0) { - var stateA = queue.First(); - queue.Remove(stateA); - - for (int c = 0; c < AlphabetSize; c++) { - var stateX = new HashSet(); - - for(int s = 1; s < m_states.Count; s++) { - if (stateA.Contains(m_states[s].transitions[c])) - stateX.Add(s); - } - - foreach (var stateY in optimalStates.ToArray()) { - if (stateX.Overlaps(stateY) && !stateY.IsSubsetOf(stateX)) { - var stateR1 = new HashSet(stateY); - var stateR2 = new HashSet(stateY); - - stateR1.IntersectWith(stateX); - stateR2.ExceptWith(stateX); - - optimalStates.Remove(stateY); - optimalStates.Add(stateR1); - optimalStates.Add(stateR2); - - if (queue.Contains(stateY)) { - queue.Remove(stateY); - queue.Add(stateR1); - queue.Add(stateR2); - } else { - queue.Add(stateR1.Count <= stateR2.Count ? stateR1 : stateR2); - } - } - } - } - } - - // строим карты соотвествия оптимальных состояний с оригинальными - - var initialState = optimalStates.Single(x => x.Contains(INITIAL_STATE)); - - // карта получения оптимального состояния по соотвествующему ему простому состоянию - int[] reveseOptimalMap = new int[m_states.Count]; - // карта с индексами оптимальных состояний - HashSet[] optimalMap = new HashSet[optimalStates.Count + 1]; - { - optimalMap[0] = new HashSet(); // unreachable state - optimalMap[1] = initialState; // initial state - foreach (var ss in initialState) - reveseOptimalMap[ss] = 1; - - int i = 2; - foreach (var s in optimalStates) { - if (s.SetEquals(initialState)) - continue; - optimalMap[i] = s; - foreach (var ss in s) - reveseOptimalMap[ss] = i; - i++; - } - } - - // получаем минимальный алфавит - - var minClasses = new HashSet>(setComparer); - var alphaQueue = new Queue>(); - alphaQueue.Enqueue(new HashSet(Enumerable.Range(0,AlphabetSize))); - - for (int s = 1 ; s < optimalMap.Length; s++) { - var newQueue = new Queue>(); - - foreach (var A in alphaQueue) { - if (A.Count == 1) { - minClasses.Add(A); - continue; - } - - // различаем классы символов, которые переводят в различные оптимальные состояния - // optimalState -> alphaClass - var classes = new Dictionary>(); - - foreach (var term in A) { - // ищем все переходы класса по символу term - var s2 = reveseOptimalMap[ - optimalMap[s].Select(x => m_states[x].transitions[term]).FirstOrDefault(x => x != 0) // первое допустимое элементарное состояние, если есть - ]; - - HashSet A2; - if (!classes.TryGetValue(s2, out A2)) { - A2 = new HashSet(); - newQueue.Enqueue(A2); - classes[s2] = A2; - } - A2.Add(term); - } - } - - if (newQueue.Count == 0) - break; - alphaQueue = newQueue; - } - - foreach (var A in alphaQueue) - minClasses.Add(A); - - var alphabetMap = sourceAlphabet.Reclassify(minimalAlphabet, minClasses); - - // построение автомата - - var minimalDFA = dfaFactory(minimalAlphabet); - - var states = new int[ optimalMap.Length ]; - states[0] = UNREACHEBLE_STATE; - - for(var s = INITIAL_STATE; s < states.Length; s++) { - var tags = optimalMap[s].SelectMany(x => m_states[x].tag ?? Enumerable.Empty()).Distinct().ToArray(); - if (tags.Length > 0) - states[s] = minimalDFA.AddState(tags); - else - states[s] = minimalDFA.AddState(); - } - - Debug.Assert(states[INITIAL_STATE] == INITIAL_STATE); - - for (int s1 = 1; s1 < m_states.Count; s1++) { - for (int c = 0; c < AlphabetSize; c++) { - var s2 = m_states[s1].transitions[c]; - if (s2 != UNREACHEBLE_STATE) { - minimalDFA.DefineTransition( - reveseOptimalMap[s1], - reveseOptimalMap[s2], - alphabetMap[c] - ); - } - } - } - - return minimalDFA; - } - - public void PrintDFA(IAlphabet alphabet) { - - var reverseMap = alphabet.CreateReverseMap(); - - for (int i = 1; i < reverseMap.Length; i++) { - Console.WriteLine("C{0}: {1}", i, String.Join(",", reverseMap[i])); - } - - for (int i = 1; i < m_states.Count; i++) { - var s = m_states[i]; - for (int c = 0; c < AlphabetSize; c++) - if (s.transitions[c] != UNREACHEBLE_STATE) - Console.WriteLine("S{0} -{1}-> S{2}{3}", i, String.Join(",", reverseMap[c]), s.transitions[c], m_states[s.transitions[c]].final ? "$" : ""); - } - } - - public int AlphabetSize { - get { - return m_alpabetSize; - } - } - } -} diff -r 2a8466f0cb8a -r 1c2a16d071a7 Implab/Parsing/DFAStateDescriptor.cs --- a/Implab/Parsing/DFAStateDescriptor.cs Fri Feb 19 18:07:17 2016 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,13 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Implab.Parsing { - public struct DFAStateDescriptior { - public bool final; - public TTag[] tag; - public int[] transitions; - } -} diff -r 2a8466f0cb8a -r 1c2a16d071a7 Implab/Parsing/DFAutomaton.cs --- a/Implab/Parsing/DFAutomaton.cs Fri Feb 19 18:07:17 2016 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,61 +0,0 @@ -using Implab; -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Implab.Parsing { - public abstract class DFAutomaton { - protected struct ContextFrame { - public DFAStateDescriptior[] states; - public int current; - public T info; - } - - public const int INITIAL_STATE = DFADefinition.INITIAL_STATE; - public const int UNREACHEBLE_STATE = DFADefinition.UNREACHEBLE_STATE; - - protected ContextFrame m_context; - Stack m_contextStack = new Stack(); - - protected int Level { - get { return m_contextStack.Count; } - } - - protected DFAutomaton(DFAStateDescriptior[] states, int startState, T info) { - Safe.ArgumentNotNull(states, "states"); - Safe.ArgumentInRange(startState, 0, states.Length - 1, "startState"); - - m_context.states = states; - m_context.current = startState; - m_context.info = info; - } - - protected void Switch(DFAStateDescriptior[] states, int current, T info) { - Debug.Assert(states != null); - Debug.Assert(current >= 0 && current < states.Length); - m_contextStack.Push(m_context); - m_context.states = states; - m_context.current = current; - m_context.info = info; - } - - protected void Restore() { - Debug.Assert(m_contextStack.Count > 0); - - m_context = m_contextStack.Pop(); - } - - protected void Move(int input) { - Debug.Assert(input > 0 && input < m_context.states[m_context.current].transitions.Length); - m_context.current = m_context.states[m_context.current].transitions[input]; - } - - protected bool CanMove(int input) { - Debug.Assert(input > 0 && input < m_context.states[m_context.current].transitions.Length); - return m_context.states[m_context.current].transitions[input] != UNREACHEBLE_STATE; - } - } -} diff -r 2a8466f0cb8a -r 1c2a16d071a7 Implab/Parsing/EDFADefinition.cs --- a/Implab/Parsing/EDFADefinition.cs Fri Feb 19 18:07:17 2016 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,29 +0,0 @@ -using Implab; -using System; - -namespace Implab.Parsing { - public class EDFADefinition : DFADefinition where T : struct, IConvertible { - readonly EnumAlphabet m_alphabet; - - public EnumAlphabet Alphabet { - get { return m_alphabet; } - } - - public EDFADefinition(EnumAlphabet alphabet) : base(alphabet.Count) { - m_alphabet = alphabet; - } - - public void DefineTransition(int s1, int s2, T input) { - DefineTransition(s1, s2, m_alphabet.Translate(input)); - } - - public EDFADefinition Optimize() { - - return (EDFADefinition)Optimize(alphabet => new EDFADefinition((EnumAlphabet)alphabet), m_alphabet, new EnumAlphabet()); - } - - public void PrintDFA() { - PrintDFA(m_alphabet); - } - } -} diff -r 2a8466f0cb8a -r 1c2a16d071a7 Implab/Parsing/EmptyToken.cs --- a/Implab/Parsing/EmptyToken.cs Fri Feb 19 18:07:17 2016 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,18 +0,0 @@ -using Implab; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Implab.Parsing { - public class EmptyToken : Token { - public override void Accept(IVisitor visitor) { - Safe.ArgumentNotNull(visitor, "visitor"); - visitor.Visit(this); - } - public override string ToString() { - return "$"; - } - } -} diff -r 2a8466f0cb8a -r 1c2a16d071a7 Implab/Parsing/EndToken.cs --- a/Implab/Parsing/EndToken.cs Fri Feb 19 18:07:17 2016 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,37 +0,0 @@ -using Implab; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Implab.Parsing { - /// - /// Конечный символ расширенного регулярного выражения, при построении ДКА - /// используется для определения конечных состояний. - /// - public class EndToken: Token { - - int m_tag; - - public EndToken(int tag) { - m_tag = tag; - } - - public EndToken() - : this(0) { - } - - public int Tag { - get { return m_tag; } - } - - public override void Accept(IVisitor visitor) { - Safe.ArgumentNotNull(visitor, "visitor"); - visitor.Visit(this); - } - public override string ToString() { - return "#"; - } - } -} diff -r 2a8466f0cb8a -r 1c2a16d071a7 Implab/Parsing/EnumAlphabet.cs --- a/Implab/Parsing/EnumAlphabet.cs Fri Feb 19 18:07:17 2016 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,67 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.Globalization; -using System.Linq; -using System.Diagnostics.CodeAnalysis; - -namespace Implab.Parsing { - /// - /// Алфавит символами которого являются элементы перечислений. - /// - /// Тип перечислений - public class EnumAlphabet : IndexedAlphabetBase where T : struct, IConvertible { - [SuppressMessage("Microsoft.Design", "CA1000:DoNotDeclareStaticMembersOnGenericTypes")] - static readonly T[] _symbols; - static readonly EnumAlphabet _fullAlphabet; - - [SuppressMessage("Microsoft.Design", "CA1065:DoNotRaiseExceptionsInUnexpectedLocations")] - static EnumAlphabet() { - if (!typeof(T).IsEnum) - throw new InvalidOperationException("Invalid generic parameter, enumeration is required"); - - if (Enum.GetUnderlyingType(typeof(T)) != typeof(Int32)) - throw new InvalidOperationException("Only enums based on Int32 are supported"); - - _symbols = ((T[])Enum.GetValues(typeof(T))) - .OrderBy(x => x.ToInt32(CultureInfo.InvariantCulture)) - .ToArray(); - - if ( - _symbols[_symbols.Length - 1].ToInt32(CultureInfo.InvariantCulture) >= _symbols.Length - || _symbols[0].ToInt32(CultureInfo.InvariantCulture) != 0 - ) - throw new InvalidOperationException("The specified enumeration must be zero-based and continuously numbered"); - - _fullAlphabet = new EnumAlphabet(_symbols.Select(x => x.ToInt32(CultureInfo.InvariantCulture)).ToArray()); - } - - - - public static EnumAlphabet FullAlphabet { - get { - return _fullAlphabet; - } - } - - - public EnumAlphabet() - : base(_symbols.Length) { - } - - public EnumAlphabet(int[] map) - : base(map) { - Debug.Assert(map.Length == _symbols.Length); - } - - - public override int GetSymbolIndex(T symbol) { - return symbol.ToInt32(CultureInfo.InvariantCulture); - } - - public override IEnumerable InputSymbols { - get { return _symbols; } - } - - } -} diff -r 2a8466f0cb8a -r 1c2a16d071a7 Implab/Parsing/Grammar.cs --- a/Implab/Parsing/Grammar.cs Fri Feb 19 18:07:17 2016 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,108 +0,0 @@ -using Implab; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Implab.Parsing { - /// - /// Базовый абстрактный класс. Грамматика, позволяет формулировать выражения над алфавитом типа char. - /// - /// - public abstract class Grammar where TGrammar: Grammar, new() { - static TGrammar _instance; - - public static TGrammar Instance{ - get { - if (_instance == null) - _instance = new TGrammar(); - return _instance; - } - } - - readonly CharAlphabet m_alphabet = new CharAlphabet(); - - public CharAlphabet Alphabet { - get { return m_alphabet; } - } - - public SymbolToken UnclassifiedToken() { - return new SymbolToken(CharAlphabet.UNCLASSIFIED); - } - - public void DefineAlphabet(IEnumerable alphabet) { - Safe.ArgumentNotNull(alphabet, "alphabet"); - - foreach (var ch in alphabet) - m_alphabet.DefineSymbol(ch); - } - public Token SymbolRangeToken(char start, char end) { - return SymbolToken(Enumerable.Range(start, end - start + 1).Select(x => (char)x)); - } - - public Token SymbolToken(char symbol) { - return Token.New(TranslateOrAdd(symbol)); - } - - public Token SymbolToken(IEnumerable symbols) { - Safe.ArgumentNotNull(symbols, "symbols"); - - return Token.New(TranslateOrAdd(symbols).ToArray()); - } - - public Token SymbolSetToken(params char[] set) { - return SymbolToken(set); - } - - int TranslateOrAdd(char ch) { - var t = m_alphabet.Translate(ch); - if (t == CharAlphabet.UNCLASSIFIED) - t = m_alphabet.DefineSymbol(ch); - return t; - } - - IEnumerable TranslateOrAdd(IEnumerable symbols) { - return symbols.Distinct().Select(TranslateOrAdd); - } - - int TranslateOrDie(char ch) { - var t = m_alphabet.Translate(ch); - if (t == CharAlphabet.UNCLASSIFIED) - throw new ApplicationException(String.Format("Symbol '{0}' is UNCLASSIFIED", ch)); - return t; - } - - IEnumerable TranslateOrDie(IEnumerable symbols) { - return symbols.Distinct().Select(TranslateOrDie); - } - - public Token SymbolTokenExcept(IEnumerable symbols) { - Safe.ArgumentNotNull(symbols, "symbols"); - - return Token.New( Enumerable.Range(0, m_alphabet.Count).Except(TranslateOrDie(symbols)).ToArray()); - } - - protected CDFADefinition BuildDFA(Token lang) { - Safe.ArgumentNotNull(lang, "lang"); - - var dfa = new CDFADefinition(m_alphabet); - - var builder = new DFABuilder(); - - lang.Accept( builder ); - - builder.BuildDFA(dfa); - if (dfa.InitialStateIsFinal) - throw new ApplicationException("The specified language contains empty token"); - - return dfa.Optimize(); - } - - - - //protected abstract TGrammar CreateInstance(); - } - - -} diff -r 2a8466f0cb8a -r 1c2a16d071a7 Implab/Parsing/IAlphabet.cs --- a/Implab/Parsing/IAlphabet.cs Fri Feb 19 18:07:17 2016 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,48 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Implab.Parsing { - /// - /// Алфавит. Множество символов, которые разбиты на классы, при этом классы имеют непрерывную нумерацию, - /// что позволяет использовать их в качестве индексов массивов. - /// - /// - /// Алфавит является сюрьективным отображением множества символов в множество индексов, это позволяет сократить размер таблицы переходов автомата - /// для входных символов, которые для него не различимы. - /// - /// Тип символов. - public interface IAlphabet { - /// - /// Количество классов символов в алфавите. - /// - int Count { get; } - - /// - /// Создает карту обратного сопоставления класса символов алфавита и сопоставленным - /// ему исходным символам. - /// - /// - List[] CreateReverseMap(); - - /// - /// Создает новый алфавит на основе текущего, горппируя его сиволы в более - /// крупные непересекающиеся классы символов. - /// - /// Новый, пустой алфавит, в котором быдут определены классы. - /// Множество классов символов текущего алфавита. - /// Карта для перехода классов текущего - /// алфавита к классам нового. - /// Ползволяет укрупнить алфавит, объединив классы в текущем алфавите. Используется при оптимизации автомата. - int[] Reclassify(IAlphabetBuilder newAlphabet, IEnumerable> classes); - - /// - /// Преобразует входной символ в индекс символа из алфавита. - /// - /// Исходный символ - /// Индекс в алфавите - int Translate(TSymbol symobl); - } -} diff -r 2a8466f0cb8a -r 1c2a16d071a7 Implab/Parsing/IAlphabetBuilder.cs --- a/Implab/Parsing/IAlphabetBuilder.cs Fri Feb 19 18:07:17 2016 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,25 +0,0 @@ -using System; -using System.Collections.Generic; - -namespace Implab.Parsing { - public interface IAlphabetBuilder : IAlphabet { - /// - /// Добавляет новый символ в алфавит, если символ уже был добавлен, то - /// возвращается ранее сопоставленный с символом класс. - /// - /// Символ для добавления. - /// Индекс класса, который попоставлен с символом. - int DefineSymbol(TSymbol symbol); - /// - /// Доабвляем класс символов. Множеству указанных исходных символов - /// будет сопоставлен символ в алфавите. - /// - /// Множестов исходных символов - /// Идентификатор символа алфавита. - int DefineClass(IEnumerable symbols); - - - - } -} - diff -r 2a8466f0cb8a -r 1c2a16d071a7 Implab/Parsing/IDFADefinition.cs --- a/Implab/Parsing/IDFADefinition.cs Fri Feb 19 18:07:17 2016 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,61 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Implab.Parsing { - /// - /// Полностью описывает DFA автомат, его поведение, состояние и входные символы. - /// - /// - /// class MyAutomaton { - /// int m_current; - /// readonly DFAStateDescriptor[] m_automaton; - /// readonly IAlphabet m_commands; - /// - /// public MyAutomaton(IDFADefinition<MyCommands,MyStates,string> definition) { - /// m_current = definition.StateAlphabet.Translate(MyStates.Initial); - /// m_automaton = definition.GetTransitionTable(); - /// m_commands = definition.InputAlphabet; - /// } - /// - /// // defined a method which will move the automaton to the next state - /// public void Move(MyCommands cmd) { - /// // use transition map to determine the next state - /// var next = m_automaton[m_current].transitions[m_commands.Translate(cmd)]; - /// - /// // validate that we aren't in the unreachable state - /// if (next == DFAConst.UNREACHABLE_STATE) - /// throw new InvalidOperationException("The specified command is invalid"); - /// - /// // if everything is ok - /// m_current = next; - /// } - /// } - /// - public interface IDFADefinition { - /// - /// Алфавит входных символов - /// - /// The input alphabet. - IAlphabet InputAlphabet { - get; - } - - /// - /// Алфавит состояний автомата - /// - /// The state alphabet. - IAlphabet StateAlphabet { - get; - } - - /// - /// Таблица переходов состояний автомата - /// - /// The transition table. - DFAStateDescriptior[] GetTransitionTable(); - - } -} diff -r 2a8466f0cb8a -r 1c2a16d071a7 Implab/Parsing/IDFADefinitionBuilder.cs --- a/Implab/Parsing/IDFADefinitionBuilder.cs Fri Feb 19 18:07:17 2016 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,9 +0,0 @@ -using System; - -namespace Implab.Parsing { - public interface IDFADefinitionBuilder : IDFADefinition { - - - } -} - diff -r 2a8466f0cb8a -r 1c2a16d071a7 Implab/Parsing/IVisitor.cs --- a/Implab/Parsing/IVisitor.cs Fri Feb 19 18:07:17 2016 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,19 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Implab.Parsing { - /// - /// Интерфейс обходчика синтаксического дерева регулярного выражения - /// - public interface IVisitor { - void Visit(AltToken token); - void Visit(StarToken token); - void Visit(CatToken token); - void Visit(EmptyToken token); - void Visit(EndToken token); - void Visit(SymbolToken token); - } -} diff -r 2a8466f0cb8a -r 1c2a16d071a7 Implab/Parsing/IndexedAlphabetBase.cs --- a/Implab/Parsing/IndexedAlphabetBase.cs Fri Feb 19 18:07:17 2016 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,107 +0,0 @@ -using Implab; -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Implab.Parsing { - /// - /// Indexed alphabet is the finite set of symbols where each symbol has a zero-based unique index. - /// - public abstract class IndexedAlphabetBase : IAlphabet { - public const int UNCLASSIFIED = 0; - - int m_nextId = 1; - readonly int[] m_map; - - public int Count { - get { return m_nextId; } - } - - protected IndexedAlphabetBase(int mapSize) { - m_map = new int[mapSize]; - } - - protected IndexedAlphabetBase(int[] map) { - Debug.Assert(map != null); - - m_map = map; - m_nextId = map.Max() + 1; - } - - public int DefineSymbol(T symbol) { - var index = GetSymbolIndex(symbol); - if (m_map[index] == UNCLASSIFIED) - m_map[index] = m_nextId++; - return m_map[index]; - } - - public int DefineClass(IEnumerable symbols) { - Safe.ArgumentNotNull(symbols, "symbols"); - symbols = symbols.Distinct(); - - foreach (var symbol in symbols) { - var index = GetSymbolIndex(symbol); - if (m_map[index] == UNCLASSIFIED) - m_map[GetSymbolIndex(symbol)] = m_nextId; - else - throw new InvalidOperationException(String.Format("Symbol '{0}' already in use", symbol)); - } - return m_nextId++; - } - - public List[] CreateReverseMap() { - return - Enumerable.Range(UNCLASSIFIED, Count) - .Select( - i => InputSymbols - .Where(x => i != UNCLASSIFIED && m_map[GetSymbolIndex(x)] == i) - .ToList() - ) - .ToArray(); - } - - public int[] Reclassify(IAlphabet newAlphabet, IEnumerable> classes) { - Safe.ArgumentNotNull(newAlphabet, "newAlphabet"); - Safe.ArgumentNotNull(classes, "classes"); - var reverseMap = CreateReverseMap(); - - int[] translationMap = new int[Count]; - - foreach (var scl in classes) { - // skip if the supper class contains the unclassified element - if (scl.Contains(UNCLASSIFIED)) - continue; - var range = new List(); - foreach (var cl in scl) { - if (cl < 0 || cl >= reverseMap.Length) - throw new ArgumentOutOfRangeException(String.Format("Class {0} is not valid for the current alphabet", cl)); - range.AddRange(reverseMap[cl]); - } - var newClass = newAlphabet.DefineClass(range); - foreach (var cl in scl) - translationMap[cl] = newClass; - } - - return translationMap; - } - - public virtual int Translate(T symbol) { - return m_map[GetSymbolIndex(symbol)]; - } - - public abstract int GetSymbolIndex(T symbol); - - public abstract IEnumerable InputSymbols { get; } - - /// - /// Gets the translation map from the index of the symbol to it's class this is usefull for the optimized input symbols transtaion. - /// - /// The translation map. - public int[] GetTranslationMap() { - return m_map; - } - } -} diff -r 2a8466f0cb8a -r 1c2a16d071a7 Implab/Parsing/ParserException.cs --- a/Implab/Parsing/ParserException.cs Fri Feb 19 18:07:17 2016 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,17 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; - -namespace Implab.Parsing { - [Serializable] - public class ParserException : Exception { - public ParserException() { } - public ParserException(string message) : base(message) { } - public ParserException(string message, Exception inner) : base(message, inner) { } - protected ParserException( - System.Runtime.Serialization.SerializationInfo info, - System.Runtime.Serialization.StreamingContext context) - : base(info, context) { } - } -} diff -r 2a8466f0cb8a -r 1c2a16d071a7 Implab/Parsing/Scanner.cs --- a/Implab/Parsing/Scanner.cs Fri Feb 19 18:07:17 2016 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,259 +0,0 @@ -using Implab; -using System; -using System.Collections.Generic; -using System.IO; -using Implab.Components; - -namespace Implab.Parsing { - /// - /// Базовый класс для разбора потока входных символов на токены. - /// - /// - /// Сканнер имеет внутри буффер с симолами входного текста, по которому перемещаются два - /// указателя, начала и конца токена, при перемещении искользуется ДКА для определения - /// конца токена и допустимости текущего символа. - /// - public abstract class Scanner : Disposable { - struct ScannerConfig { - public DFAStateDescriptior[] states; - public int[] alphabetMap; - } - - Stack m_defs = new Stack(); - - DFAStateDescriptior[] m_states; - int[] m_alphabetMap; - - protected DFAStateDescriptior m_currentState; - int m_previewCode; - - protected int m_tokenLen = 0; - protected int m_tokenOffset; - - protected char[] m_buffer; - protected int m_bufferSize; - protected int m_pointer; - - TextReader m_reader; - bool m_disposeReader; - int m_chunkSize = 1024; // 1k - int m_limit = 10 * 1024 * 1024; // 10Mb - - protected Scanner(DFAStateDescriptior[] states, int[] alphabet) { - Safe.ArgumentNotEmpty(states, "states"); - Safe.ArgumentNotNull(alphabet, "alphabet"); - - m_states = states; - m_alphabetMap = alphabet; - - Feed(new char[0]); - } - - /// - /// Заполняет входными данными буффер. - /// - /// Данные для обработки. - /// Копирование данных не происходит, переданный массив используется в - /// качестве входного буффера. - public void Feed(char[] data) { - Safe.ArgumentNotNull(data, "data"); - - Feed(data, data.Length); - } - - /// - /// Заполняет буффур чтения входными данными. - /// - /// Данные для обработки. - /// Длина данных для обработки. - /// Копирование данных не происходит, переданный массив используется в - /// качестве входного буффера. - public void Feed(char[] data, int length) { - Safe.ArgumentNotNull(data, "data"); - Safe.ArgumentInRange(length, 0, data.Length, "length"); - AssertNotDisposed(); - - m_pointer = -1; - m_buffer = data; - m_bufferSize = length; - Shift(); - } - - public void Feed(TextReader reader, bool dispose) { - Safe.ArgumentNotNull(reader, "reader"); - AssertNotDisposed(); - - if (m_reader != null && m_disposeReader) - m_reader.Dispose(); - - m_reader = reader; - m_disposeReader = dispose; - m_pointer = -1; - m_buffer = new char[m_chunkSize]; - m_bufferSize = 0; - Shift(); - } - - /// - /// Получает текущий токен в виде строки. - /// - /// - protected string GetTokenValue() { - return new String(m_buffer, m_tokenOffset, m_tokenLen); - } - - /// - /// Метки текущего токена, которые были назначены в регулярном выражении. - /// - protected int[] TokenTags { - get { - return m_currentState.tag; - } - } - - /// - /// Признак конца данных - /// - public bool EOF { - get { - return m_pointer >= m_bufferSize; - } - } - - /// - /// Читает следующий токен, при этом указывает на начало токена, - /// на длину токена, - массив символов, в - /// котором находится токен. - /// - /// false - достигнут конец данных, токен не прочитан. - protected bool ReadTokenInternal() { - if (m_pointer >= m_bufferSize) - return false; - - m_currentState = m_states[DFADefinition.INITIAL_STATE]; - m_tokenLen = 0; - m_tokenOffset = m_pointer; - int nextState; - do { - nextState = m_currentState.transitions[m_previewCode]; - if (nextState == DFADefinition.UNREACHEBLE_STATE) { - if (m_currentState.final) - return true; - else - throw new ParserException( - String.Format( - "Unexpected symbol '{0}', at pos {1}", - m_buffer[m_pointer], - Position - ) - ); - } else { - m_currentState = m_states[nextState]; - m_tokenLen++; - } - - } while (Shift()); - - // END OF DATA - if (!m_currentState.final) - throw new ParserException("Unexpected end of data"); - - return true; - } - - - bool Shift() { - m_pointer++; - - if (m_pointer >= m_bufferSize) { - if (!ReadNextChunk()) - return false; - } - - m_previewCode = m_alphabetMap[m_buffer[m_pointer]]; - - return true; - } - - bool ReadNextChunk() { - if (m_reader == null) - return false; - - // extend buffer if nesessary - if (m_pointer + m_chunkSize > m_buffer.Length) { - // trim unused buffer head - var size = m_tokenLen + m_chunkSize; - if (size >= m_limit) - throw new ParserException(String.Format("Input buffer {0} bytes limit exceeded", m_limit)); - var temp = new char[size]; - Array.Copy(m_buffer, m_tokenOffset, temp, 0, m_tokenLen); - m_pointer -= m_tokenOffset; - m_bufferSize -= m_tokenOffset; - m_tokenOffset = 0; - m_buffer = temp; - } - - var read = m_reader.Read(m_buffer, m_tokenLen, m_chunkSize); - if (read == 0) - return false; - - m_bufferSize += read; - - return true; - } - - /// - /// Позиция сканнера во входном буфере - /// - public int Position { - get { - return m_pointer + 1; - } - } - - /// - /// Преключает внутренний ДКА на указанный, позволяет реализовать подобие захватывающей - /// группировки. - /// - /// Таблица состояний нового ДКА - /// Таблица входных символов для нового ДКА - protected void Switch(DFAStateDescriptior[] states, int[] alphabet) { - Safe.ArgumentNotNull(states, "dfa"); - - m_defs.Push(new ScannerConfig { - states = m_states, - alphabetMap = m_alphabetMap - }); - - m_states = states; - m_alphabetMap = alphabet; - - m_previewCode = m_alphabetMap[m_buffer[m_pointer]]; - } - - /// - /// Восстанавливает предыдущей ДКА сканнера. - /// - protected void Restore() { - if (m_defs.Count == 0) - throw new InvalidOperationException(); - var prev = m_defs.Pop(); - m_states = prev.states; - m_alphabetMap = prev.alphabetMap; - m_previewCode = m_alphabetMap[m_buffer[m_pointer]]; - } - - protected override void Dispose(bool disposing) { - if (disposing) { - if (m_reader != null && m_disposeReader) - m_reader.Dispose(); - m_buffer = null; - m_bufferSize = 0; - m_pointer = 0; - m_tokenLen = 0; - m_tokenOffset = 0; - } - base.Dispose(disposing); - } - } -} diff -r 2a8466f0cb8a -r 1c2a16d071a7 Implab/Parsing/StarToken.cs --- a/Implab/Parsing/StarToken.cs Fri Feb 19 18:07:17 2016 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,34 +0,0 @@ -using Implab; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Implab.Parsing { - /// - /// Замыкание выражения с 0 и более повторов. - /// - public class StarToken: Token { - - Token m_token; - - public Token Token { - get { return m_token; } - } - - public StarToken(Token token) { - Safe.ArgumentNotNull(token, "token"); - m_token = token; - } - - public override void Accept(IVisitor visitor) { - Safe.ArgumentNotNull(visitor, "visitor"); - visitor.Visit(this); - } - - public override string ToString() { - return String.Format("({0})*", Token.ToString()); - } - } -} diff -r 2a8466f0cb8a -r 1c2a16d071a7 Implab/Parsing/SymbolToken.cs --- a/Implab/Parsing/SymbolToken.cs Fri Feb 19 18:07:17 2016 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,33 +0,0 @@ -using Implab; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Implab.Parsing { - /// - /// Выражение, соответсвующее одному символу. - /// - public class SymbolToken : Token { - int m_value; - - public int Value { - get { return m_value; } - } - - public SymbolToken(int value) { - m_value = value; - } - public override void Accept(IVisitor visitor) { - Safe.ArgumentNotNull(visitor, "visitor"); - - visitor.Visit(this); - - } - - public override string ToString() { - return Value.ToString(); - } - } -} diff -r 2a8466f0cb8a -r 1c2a16d071a7 Implab/Parsing/Token.cs --- a/Implab/Parsing/Token.cs Fri Feb 19 18:07:17 2016 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,67 +0,0 @@ -using Implab; -using System; -using System.Collections.Generic; -using System.Globalization; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Implab.Parsing { - public abstract class Token { - public abstract void Accept(IVisitor visitor); - - public Token Extend() { - return new CatToken(this, new EndToken()); - } - - public Token Tag(T tag) where T : IConvertible { - return new CatToken(this, new EndToken(tag.ToInt32(CultureInfo.InvariantCulture))); - } - - public Token Cat(Token right) { - return new CatToken(this, right); - } - - public Token Or(Token right) { - return new AltToken(this, right); - } - - public Token Optional() { - return Or(new EmptyToken()); - } - - public Token EClosure() { - return new StarToken(this); - } - - public Token Closure() { - return new CatToken(this, new StarToken(this)); - } - - public Token Repeat(int count) { - Token token = null; - - for (int i = 0; i < count; i++) - token = token != null ? token.Cat(this) : this; - return token ?? new EmptyToken(); - } - - public Token Repeat(int min, int max) { - if (min > max || min < 1) - throw new ArgumentOutOfRangeException(); - var token = Repeat(min); - - for (int i = min; i < max; i++) - token = token.Cat( this.Optional() ); - return token; - } - - public static Token New(params T[] set) where T : struct, IConvertible { - Safe.ArgumentNotNull(set, "set"); - Token token = null; - foreach(var c in set.Distinct()) - token = token == null ? new SymbolToken(c.ToInt32(CultureInfo.InvariantCulture)) : token.Or(new SymbolToken(c.ToInt32(CultureInfo.InvariantCulture))); - return token; - } - } -} diff -r 2a8466f0cb8a -r 1c2a16d071a7 Implab/PromiseExtensions.cs --- a/Implab/PromiseExtensions.cs Fri Feb 19 18:07:17 2016 +0300 +++ b/Implab/PromiseExtensions.cs Fri Apr 22 13:08:08 2016 +0300 @@ -3,11 +3,6 @@ using Implab.Diagnostics; using System.Collections.Generic; - -#if NET_4_5 -using System.Threading.Tasks; -#endif - namespace Implab { public static class PromiseExtensions { public static IPromise DispatchToCurrentContext(this IPromise that) { @@ -17,12 +12,12 @@ return that; var p = new SyncContextPromise(context); - p.On(that.Cancel, PromiseEventType.Cancelled); + p.CancellationRequested(that.Cancel); that.On( p.Resolve, p.Reject, - p.Cancel + p.CancelOperation ); return p; } @@ -32,13 +27,12 @@ Safe.ArgumentNotNull(context, "context"); var p = new SyncContextPromise(context); - p.On(that.Cancel, PromiseEventType.Cancelled); - + p.CancellationRequested(that.Cancel); that.On( p.Resolve, p.Reject, - p.Cancel + p.CancelOperation ); return p; } @@ -77,8 +71,8 @@ }; } - static void CancelCallback(object cookie) { - ((ICancellable)cookie).Cancel(); + static void CancelByTimeoutCallback(object cookie) { + ((ICancellable)cookie).Cancel(new TimeoutException()); } /// @@ -89,7 +83,7 @@ /// The 1st type parameter. public static TPromise Timeout(this TPromise that, int milliseconds) where TPromise : IPromise { Safe.ArgumentNotNull(that, "that"); - var timer = new Timer(CancelCallback, that, milliseconds, -1); + var timer = new Timer(CancelByTimeoutCallback, that, milliseconds, -1); that.On(timer.Dispose, PromiseEventType.All); return that; } @@ -180,8 +174,7 @@ var d = new ActionTask(success, error, cancel, false); that.On(d.Resolve, d.Reject, d.CancelOperation); - if (success != null) - d.CancellationRequested(that.Cancel); + d.CancellationRequested(that.Cancel); return d; } @@ -198,8 +191,7 @@ var d = new FuncTask(success, error, cancel, false); that.On(d.Resolve, d.Reject, d.CancelOperation); - if (success != null) - d.CancellationRequested(that.Cancel); + d.CancellationRequested(that.Cancel); return d; } @@ -215,8 +207,7 @@ Safe.ArgumentNotNull(that, "that"); var d = new FuncTask(success, error, cancel, false); that.On(d.Resolve, d.Reject, d.CancelOperation); - if (success != null) - d.CancellationRequested(that.Cancel); + d.CancellationRequested(that.Cancel); return d; } @@ -234,8 +225,7 @@ var d = new ActionChainTask(success, error, cancel, false); that.On(d.Resolve, d.Reject, d.CancelOperation); - if (success != null) - d.CancellationRequested(that.Cancel); + d.CancellationRequested(that.Cancel); return d; } diff -r 2a8466f0cb8a -r 1c2a16d071a7 Implab/Safe.cs --- a/Implab/Safe.cs Fri Feb 19 18:07:17 2016 +0300 +++ b/Implab/Safe.cs Fri Apr 22 13:08:08 2016 +0300 @@ -41,6 +41,11 @@ throw new ArgumentOutOfRangeException(paramName); } + public static void ArgumentOfType(object value, Type type, string paramName) { + if (!type.IsInstanceOfType(value)) + throw new ArgumentException(String.Format("The parameter must be of type {0}", type), paramName); + } + public static void Dispose(params IDisposable[] objects) { foreach (var d in objects) if (d != null) diff -r 2a8466f0cb8a -r 1c2a16d071a7 MonoPlay/MonoPlay.csproj --- a/MonoPlay/MonoPlay.csproj Fri Feb 19 18:07:17 2016 +0300 +++ b/MonoPlay/MonoPlay.csproj Fri Apr 22 13:08:08 2016 +0300 @@ -32,6 +32,9 @@ + + ..\packages\System.Text.Json.2.0.0.11\lib\net40\System.Text.Json.dll + @@ -44,4 +47,7 @@ Implab + + + \ No newline at end of file diff -r 2a8466f0cb8a -r 1c2a16d071a7 MonoPlay/Program.cs --- a/MonoPlay/Program.cs Fri Feb 19 18:07:17 2016 +0300 +++ b/MonoPlay/Program.cs Fri Apr 22 13:08:08 2016 +0300 @@ -1,6 +1,9 @@ using System; using Implab; using System.Threading.Tasks; +using Implab.Formats.JSON; +using System.IO; +using System.Text.Json; namespace MonoPlay { class MainClass { @@ -9,28 +12,33 @@ public static void Main(string[] args) { if (args == null) throw new ArgumentNullException("args"); - - var t1 = Environment.TickCount; - - DoWork().GetAwaiter().GetResult(); + int t1, t2; - var t2 = Environment.TickCount; - Console.WriteLine("done: {0} ms, {1:.00} Mb, {2} GC", t2 - t1, GC.GetTotalMemory(false) / (1024*1024), GC.CollectionCount(0) ); + for (int i = 0; i < 2; i++) { + t1 = Environment.TickCount; + int elements =0; + using (var reader = new JSONParser(File.OpenText("/home/sergey/temp/citylots.json"))) { + while (reader.Read()) + elements++; + } - } + t2 = Environment.TickCount; + Console.WriteLine("attempt {0} done: {1} ms, {2:.00} Mb, {3} GC, Elements: {4}",i+1, t2 - t1, GC.GetTotalMemory(false) / (1024*1024), GC.CollectionCount(0), elements ); + } - static IPromise DoItem(int x) { - //return Promise.FromResult(x + 1); - var p = new Promise(); - p.Resolve(x+1); - return p; - } + Console.WriteLine("Syste.Text.Json"); + var paraser = new JsonParser(); + for (int i = 0; i < 2; i++) { + t1 = Environment.TickCount; + using (var reader = File.OpenText("/home/sergey/temp/citylots.json")) { + paraser.Parse(reader); + } - static async Task DoWork() { - var c = 0; - for (int i = 0; i < 10000000; i++) - c = await DoItem(c); - return c; + t2 = Environment.TickCount; + Console.WriteLine("attempt {0} done: {1} ms, {2:.00} Mb, {3} GC, ",i+1, t2 - t1, GC.GetTotalMemory(false) / (1024*1024), GC.CollectionCount(0)); + } + + } } diff -r 2a8466f0cb8a -r 1c2a16d071a7 MonoPlay/packages.config --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/MonoPlay/packages.config Fri Apr 22 13:08:08 2016 +0300 @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff -r 2a8466f0cb8a -r 1c2a16d071a7 packages/NUnit.2.6.4/NUnit.2.6.4.nupkg Binary file packages/NUnit.2.6.4/NUnit.2.6.4.nupkg has changed diff -r 2a8466f0cb8a -r 1c2a16d071a7 packages/NUnit.2.6.4/lib/nunit.framework.dll Binary file packages/NUnit.2.6.4/lib/nunit.framework.dll has changed diff -r 2a8466f0cb8a -r 1c2a16d071a7 packages/NUnit.2.6.4/lib/nunit.framework.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/packages/NUnit.2.6.4/lib/nunit.framework.xml Fri Apr 22 13:08:08 2016 +0300 @@ -0,0 +1,10984 @@ + + + + nunit.framework + + + + + The different targets a test action attribute can be applied to + + + + + Default target, which is determined by where the action attribute is attached + + + + + Target a individual test case + + + + + Target a suite of test cases + + + + + Delegate used by tests that execute code and + capture any thrown exception. + + + + + The Assert class contains a collection of static methods that + implement the most common assertions used in NUnit. + + + + + We don't actually want any instances of this object, but some people + like to inherit from it to add other static methods. Hence, the + protected constructor disallows any instances of this object. + + + + + The Equals method throws an AssertionException. This is done + to make sure there is no mistake by calling this function. + + + + + + + override the default ReferenceEquals to throw an AssertionException. This + implementation makes sure there is no mistake in calling this function + as part of Assert. + + + + + + + Throws a with the message and arguments + that are passed in. This allows a test to be cut short, with a result + of success returned to NUnit. + + The message to initialize the with. + Arguments to be used in formatting the message + + + + Throws a with the message and arguments + that are passed in. This allows a test to be cut short, with a result + of success returned to NUnit. + + The message to initialize the with. + + + + Throws a with the message and arguments + that are passed in. This allows a test to be cut short, with a result + of success returned to NUnit. + + + + + Throws an with the message and arguments + that are passed in. This is used by the other Assert functions. + + The message to initialize the with. + Arguments to be used in formatting the message + + + + Throws an with the message that is + passed in. This is used by the other Assert functions. + + The message to initialize the with. + + + + Throws an . + This is used by the other Assert functions. + + + + + Throws an with the message and arguments + that are passed in. This causes the test to be reported as ignored. + + The message to initialize the with. + Arguments to be used in formatting the message + + + + Throws an with the message that is + passed in. This causes the test to be reported as ignored. + + The message to initialize the with. + + + + Throws an . + This causes the test to be reported as ignored. + + + + + Throws an with the message and arguments + that are passed in. This causes the test to be reported as inconclusive. + + The message to initialize the with. + Arguments to be used in formatting the message + + + + Throws an with the message that is + passed in. This causes the test to be reported as inconclusive. + + The message to initialize the with. + + + + Throws an . + This causes the test to be reported as Inconclusive. + + + + + Apply a constraint to an actual value, succeeding if the constraint + is satisfied and throwing an assertion exception on failure. + + The actual value to test + A Constraint to be applied + + + + Apply a constraint to an actual value, succeeding if the constraint + is satisfied and throwing an assertion exception on failure. + + The actual value to test + A Constraint to be applied + The message that will be displayed on failure + + + + Apply a constraint to an actual value, succeeding if the constraint + is satisfied and throwing an assertion exception on failure. + + The actual value to test + A Constraint expression to be applied + The message that will be displayed on failure + Arguments to be used in formatting the message + + + + Asserts that a condition is true. If the condition is false the method throws + an . + + The evaluated condition + The message to display if the condition is false + Arguments to be used in formatting the message + + + + Asserts that a condition is true. If the condition is false the method throws + an . + + The evaluated condition + The message to display if the condition is false + + + + Asserts that a condition is true. If the condition is false the method throws + an . + + The evaluated condition + + + + Apply a constraint to an actual value, succeeding if the constraint + is satisfied and throwing an assertion exception on failure. + + An ActualValueDelegate returning the value to be tested + A Constraint expression to be applied + + + + Apply a constraint to an actual value, succeeding if the constraint + is satisfied and throwing an assertion exception on failure. + + An ActualValueDelegate returning the value to be tested + A Constraint expression to be applied + The message that will be displayed on failure + + + + Apply a constraint to an actual value, succeeding if the constraint + is satisfied and throwing an assertion exception on failure. + + An ActualValueDelegate returning the value to be tested + A Constraint expression to be applied + The message that will be displayed on failure + Arguments to be used in formatting the message + + + + Apply a constraint to a referenced value, succeeding if the constraint + is satisfied and throwing an assertion exception on failure. + + The actual value to test + A Constraint to be applied + + + + Apply a constraint to a referenced value, succeeding if the constraint + is satisfied and throwing an assertion exception on failure. + + The actual value to test + A Constraint to be applied + The message that will be displayed on failure + + + + Apply a constraint to a referenced value, succeeding if the constraint + is satisfied and throwing an assertion exception on failure. + + The actual value to test + A Constraint to be applied + The message that will be displayed on failure + Arguments to be used in formatting the message + + + + Asserts that the code represented by a delegate throws an exception + that satisfies the constraint provided. + + A TestDelegate to be executed + A ThrowsConstraint used in the test + + + + Apply a constraint to an actual value, succeeding if the constraint + is satisfied and throwing an assertion exception on failure. + Used as a synonym for That in rare cases where a private setter + causes a Visual Basic compilation error. + + The actual value to test + A Constraint to be applied + + + + Apply a constraint to an actual value, succeeding if the constraint + is satisfied and throwing an assertion exception on failure. + Used as a synonym for That in rare cases where a private setter + causes a Visual Basic compilation error. + + The actual value to test + A Constraint to be applied + The message that will be displayed on failure + + + + Apply a constraint to an actual value, succeeding if the constraint + is satisfied and throwing an assertion exception on failure. + Used as a synonym for That in rare cases where a private setter + causes a Visual Basic compilation error. + + + This method is provided for use by VB developers needing to test + the value of properties with private setters. + + The actual value to test + A Constraint expression to be applied + The message that will be displayed on failure + Arguments to be used in formatting the message + + + + Verifies that a delegate throws a particular exception when called. + + A constraint to be satisfied by the exception + A TestDelegate + The message that will be displayed on failure + Arguments to be used in formatting the message + + + + Verifies that a delegate throws a particular exception when called. + + A constraint to be satisfied by the exception + A TestDelegate + The message that will be displayed on failure + + + + Verifies that a delegate throws a particular exception when called. + + A constraint to be satisfied by the exception + A TestDelegate + + + + Verifies that a delegate throws a particular exception when called. + + The exception Type expected + A TestDelegate + The message that will be displayed on failure + Arguments to be used in formatting the message + + + + Verifies that a delegate throws a particular exception when called. + + The exception Type expected + A TestDelegate + The message that will be displayed on failure + + + + Verifies that a delegate throws a particular exception when called. + + The exception Type expected + A TestDelegate + + + + Verifies that a delegate throws a particular exception when called. + + Type of the expected exception + A TestDelegate + The message that will be displayed on failure + Arguments to be used in formatting the message + + + + Verifies that a delegate throws a particular exception when called. + + Type of the expected exception + A TestDelegate + The message that will be displayed on failure + + + + Verifies that a delegate throws a particular exception when called. + + Type of the expected exception + A TestDelegate + + + + Verifies that a delegate throws an exception when called + and returns it. + + A TestDelegate + The message that will be displayed on failure + Arguments to be used in formatting the message + + + + Verifies that a delegate throws an exception when called + and returns it. + + A TestDelegate + The message that will be displayed on failure + + + + Verifies that a delegate throws an exception when called + and returns it. + + A TestDelegate + + + + Verifies that a delegate throws an exception of a certain Type + or one derived from it when called and returns it. + + The expected Exception Type + A TestDelegate + The message that will be displayed on failure + Arguments to be used in formatting the message + + + + Verifies that a delegate throws an exception of a certain Type + or one derived from it when called and returns it. + + The expected Exception Type + A TestDelegate + The message that will be displayed on failure + + + + Verifies that a delegate throws an exception of a certain Type + or one derived from it when called and returns it. + + The expected Exception Type + A TestDelegate + + + + Verifies that a delegate throws an exception of a certain Type + or one derived from it when called and returns it. + + The expected Exception Type + A TestDelegate + The message that will be displayed on failure + Arguments to be used in formatting the message + + + + Verifies that a delegate throws an exception of a certain Type + or one derived from it when called and returns it. + + The expected Exception Type + A TestDelegate + The message that will be displayed on failure + + + + Verifies that a delegate throws an exception of a certain Type + or one derived from it when called and returns it. + + The expected Exception Type + A TestDelegate + + + + Verifies that a delegate does not throw an exception + + A TestDelegate + The message that will be displayed on failure + Arguments to be used in formatting the message + + + + Verifies that a delegate does not throw an exception. + + A TestDelegate + The message that will be displayed on failure + + + + Verifies that a delegate does not throw an exception. + + A TestDelegate + + + + Asserts that a condition is true. If the condition is false the method throws + an . + + The evaluated condition + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Asserts that a condition is true. If the condition is false the method throws + an . + + The evaluated condition + The message to display in case of failure + + + + Asserts that a condition is true. If the condition is false the method throws + an . + + The evaluated condition + + + + Asserts that a condition is true. If the condition is false the method throws + an . + + The evaluated condition + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Asserts that a condition is true. If the condition is false the method throws + an . + + The evaluated condition + The message to display in case of failure + + + + Asserts that a condition is true. If the condition is false the method throws + an . + + The evaluated condition + + + + Asserts that a condition is false. If the condition is true the method throws + an . + + The evaluated condition + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Asserts that a condition is false. If the condition is true the method throws + an . + + The evaluated condition + The message to display in case of failure + + + + Asserts that a condition is false. If the condition is true the method throws + an . + + The evaluated condition + + + + Asserts that a condition is false. If the condition is true the method throws + an . + + The evaluated condition + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Asserts that a condition is false. If the condition is true the method throws + an . + + The evaluated condition + The message to display in case of failure + + + + Asserts that a condition is false. If the condition is true the method throws + an . + + The evaluated condition + + + + Verifies that the object that is passed in is not equal to null + If the object is null then an + is thrown. + + The object that is to be tested + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that the object that is passed in is not equal to null + If the object is null then an + is thrown. + + The object that is to be tested + The message to display in case of failure + + + + Verifies that the object that is passed in is not equal to null + If the object is null then an + is thrown. + + The object that is to be tested + + + + Verifies that the object that is passed in is not equal to null + If the object is null then an + is thrown. + + The object that is to be tested + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that the object that is passed in is not equal to null + If the object is null then an + is thrown. + + The object that is to be tested + The message to display in case of failure + + + + Verifies that the object that is passed in is not equal to null + If the object is null then an + is thrown. + + The object that is to be tested + + + + Verifies that the object that is passed in is equal to null + If the object is not null then an + is thrown. + + The object that is to be tested + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that the object that is passed in is equal to null + If the object is not null then an + is thrown. + + The object that is to be tested + The message to display in case of failure + + + + Verifies that the object that is passed in is equal to null + If the object is not null then an + is thrown. + + The object that is to be tested + + + + Verifies that the object that is passed in is equal to null + If the object is not null then an + is thrown. + + The object that is to be tested + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that the object that is passed in is equal to null + If the object is not null then an + is thrown. + + The object that is to be tested + The message to display in case of failure + + + + Verifies that the object that is passed in is equal to null + If the object is not null then an + is thrown. + + The object that is to be tested + + + + Verifies that two ints are equal. If they are not, then an + is thrown. + + The expected value + The actual value + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that two ints are equal. If they are not, then an + is thrown. + + The expected value + The actual value + The message to display in case of failure + + + + Verifies that two ints are equal. If they are not, then an + is thrown. + + The expected value + The actual value + + + + Verifies that two longs are equal. If they are not, then an + is thrown. + + The expected value + The actual value + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that two longs are equal. If they are not, then an + is thrown. + + The expected value + The actual value + The message to display in case of failure + + + + Verifies that two longs are equal. If they are not, then an + is thrown. + + The expected value + The actual value + + + + Verifies that two unsigned ints are equal. If they are not, then an + is thrown. + + The expected value + The actual value + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that two unsigned ints are equal. If they are not, then an + is thrown. + + The expected value + The actual value + The message to display in case of failure + + + + Verifies that two unsigned ints are equal. If they are not, then an + is thrown. + + The expected value + The actual value + + + + Verifies that two unsigned longs are equal. If they are not, then an + is thrown. + + The expected value + The actual value + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that two unsigned longs are equal. If they are not, then an + is thrown. + + The expected value + The actual value + The message to display in case of failure + + + + Verifies that two unsigned longs are equal. If they are not, then an + is thrown. + + The expected value + The actual value + + + + Verifies that two decimals are equal. If they are not, then an + is thrown. + + The expected value + The actual value + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that two decimals are equal. If they are not, then an + is thrown. + + The expected value + The actual value + The message to display in case of failure + + + + Verifies that two decimals are equal. If they are not, then an + is thrown. + + The expected value + The actual value + + + + Verifies that two doubles are equal considering a delta. If the + expected value is infinity then the delta value is ignored. If + they are not equal then an is + thrown. + + The expected value + The actual value + The maximum acceptable difference between the + the expected and the actual + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that two doubles are equal considering a delta. If the + expected value is infinity then the delta value is ignored. If + they are not equal then an is + thrown. + + The expected value + The actual value + The maximum acceptable difference between the + the expected and the actual + The message to display in case of failure + + + + Verifies that two doubles are equal considering a delta. If the + expected value is infinity then the delta value is ignored. If + they are not equal then an is + thrown. + + The expected value + The actual value + The maximum acceptable difference between the + the expected and the actual + + + + Verifies that two doubles are equal considering a delta. If the + expected value is infinity then the delta value is ignored. If + they are not equal then an is + thrown. + + The expected value + The actual value + The maximum acceptable difference between the + the expected and the actual + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that two doubles are equal considering a delta. If the + expected value is infinity then the delta value is ignored. If + they are not equal then an is + thrown. + + The expected value + The actual value + The maximum acceptable difference between the + the expected and the actual + The message to display in case of failure + + + + Verifies that two doubles are equal considering a delta. If the + expected value is infinity then the delta value is ignored. If + they are not equal then an is + thrown. + + The expected value + The actual value + The maximum acceptable difference between the + the expected and the actual + + + + Verifies that two objects are equal. Two objects are considered + equal if both are null, or if both have the same value. NUnit + has special semantics for some object types. + If they are not equal an is thrown. + + The value that is expected + The actual value + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that two objects are equal. Two objects are considered + equal if both are null, or if both have the same value. NUnit + has special semantics for some object types. + If they are not equal an is thrown. + + The value that is expected + The actual value + The message to display in case of failure + + + + Verifies that two objects are equal. Two objects are considered + equal if both are null, or if both have the same value. NUnit + has special semantics for some object types. + If they are not equal an is thrown. + + The value that is expected + The actual value + + + + Verifies that two ints are not equal. If they are equal, then an + is thrown. + + The expected value + The actual value + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that two ints are not equal. If they are equal, then an + is thrown. + + The expected value + The actual value + The message to display in case of failure + + + + Verifies that two ints are not equal. If they are equal, then an + is thrown. + + The expected value + The actual value + + + + Verifies that two longs are not equal. If they are equal, then an + is thrown. + + The expected value + The actual value + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that two longs are not equal. If they are equal, then an + is thrown. + + The expected value + The actual value + The message to display in case of failure + + + + Verifies that two longs are not equal. If they are equal, then an + is thrown. + + The expected value + The actual value + + + + Verifies that two unsigned ints are not equal. If they are equal, then an + is thrown. + + The expected value + The actual value + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that two unsigned ints are not equal. If they are equal, then an + is thrown. + + The expected value + The actual value + The message to display in case of failure + + + + Verifies that two unsigned ints are not equal. If they are equal, then an + is thrown. + + The expected value + The actual value + + + + Verifies that two unsigned longs are not equal. If they are equal, then an + is thrown. + + The expected value + The actual value + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that two unsigned longs are not equal. If they are equal, then an + is thrown. + + The expected value + The actual value + The message to display in case of failure + + + + Verifies that two unsigned longs are not equal. If they are equal, then an + is thrown. + + The expected value + The actual value + + + + Verifies that two decimals are not equal. If they are equal, then an + is thrown. + + The expected value + The actual value + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that two decimals are not equal. If they are equal, then an + is thrown. + + The expected value + The actual value + The message to display in case of failure + + + + Verifies that two decimals are not equal. If they are equal, then an + is thrown. + + The expected value + The actual value + + + + Verifies that two floats are not equal. If they are equal, then an + is thrown. + + The expected value + The actual value + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that two floats are not equal. If they are equal, then an + is thrown. + + The expected value + The actual value + The message to display in case of failure + + + + Verifies that two floats are not equal. If they are equal, then an + is thrown. + + The expected value + The actual value + + + + Verifies that two doubles are not equal. If they are equal, then an + is thrown. + + The expected value + The actual value + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that two doubles are not equal. If they are equal, then an + is thrown. + + The expected value + The actual value + The message to display in case of failure + + + + Verifies that two doubles are not equal. If they are equal, then an + is thrown. + + The expected value + The actual value + + + + Verifies that two objects are not equal. Two objects are considered + equal if both are null, or if both have the same value. NUnit + has special semantics for some object types. + If they are equal an is thrown. + + The value that is expected + The actual value + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that two objects are not equal. Two objects are considered + equal if both are null, or if both have the same value. NUnit + has special semantics for some object types. + If they are equal an is thrown. + + The value that is expected + The actual value + The message to display in case of failure + + + + Verifies that two objects are not equal. Two objects are considered + equal if both are null, or if both have the same value. NUnit + has special semantics for some object types. + If they are equal an is thrown. + + The value that is expected + The actual value + + + + Asserts that two objects refer to the same object. If they + are not the same an is thrown. + + The expected object + The actual object + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Asserts that two objects refer to the same object. If they + are not the same an is thrown. + + The expected object + The actual object + The message to display in case of failure + + + + Asserts that two objects refer to the same object. If they + are not the same an is thrown. + + The expected object + The actual object + + + + Asserts that two objects do not refer to the same object. If they + are the same an is thrown. + + The expected object + The actual object + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Asserts that two objects do not refer to the same object. If they + are the same an is thrown. + + The expected object + The actual object + The message to display in case of failure + + + + Asserts that two objects do not refer to the same object. If they + are the same an is thrown. + + The expected object + The actual object + + + + Verifies that the double that is passed in is an NaN value. + If the object is not NaN then an + is thrown. + + The value that is to be tested + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that the double that is passed in is an NaN value. + If the object is not NaN then an + is thrown. + + The value that is to be tested + The message to display in case of failure + + + + Verifies that the double that is passed in is an NaN value. + If the object is not NaN then an + is thrown. + + The value that is to be tested + + + + Verifies that the double that is passed in is an NaN value. + If the object is not NaN then an + is thrown. + + The value that is to be tested + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that the double that is passed in is an NaN value. + If the object is not NaN then an + is thrown. + + The value that is to be tested + The message to display in case of failure + + + + Verifies that the double that is passed in is an NaN value. + If the object is not NaN then an + is thrown. + + The value that is to be tested + + + + Assert that a string is empty - that is equal to string.Empty + + The string to be tested + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Assert that a string is empty - that is equal to string.Empty + + The string to be tested + The message to display in case of failure + + + + Assert that a string is empty - that is equal to string.Empty + + The string to be tested + + + + Assert that an array, list or other collection is empty + + An array, list or other collection implementing ICollection + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Assert that an array, list or other collection is empty + + An array, list or other collection implementing ICollection + The message to display in case of failure + + + + Assert that an array, list or other collection is empty + + An array, list or other collection implementing ICollection + + + + Assert that a string is not empty - that is not equal to string.Empty + + The string to be tested + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Assert that a string is not empty - that is not equal to string.Empty + + The string to be tested + The message to display in case of failure + + + + Assert that a string is not empty - that is not equal to string.Empty + + The string to be tested + + + + Assert that an array, list or other collection is not empty + + An array, list or other collection implementing ICollection + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Assert that an array, list or other collection is not empty + + An array, list or other collection implementing ICollection + The message to display in case of failure + + + + Assert that an array, list or other collection is not empty + + An array, list or other collection implementing ICollection + + + + Assert that a string is either null or equal to string.Empty + + The string to be tested + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Assert that a string is either null or equal to string.Empty + + The string to be tested + The message to display in case of failure + + + + Assert that a string is either null or equal to string.Empty + + The string to be tested + + + + Assert that a string is not null or empty + + The string to be tested + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Assert that a string is not null or empty + + The string to be tested + The message to display in case of failure + + + + Assert that a string is not null or empty + + The string to be tested + + + + Asserts that an object may be assigned a value of a given Type. + + The expected Type. + The object under examination + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Asserts that an object may be assigned a value of a given Type. + + The expected Type. + The object under examination + The message to display in case of failure + + + + Asserts that an object may be assigned a value of a given Type. + + The expected Type. + The object under examination + + + + Asserts that an object may be assigned a value of a given Type. + + The expected Type. + The object under examination + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Asserts that an object may be assigned a value of a given Type. + + The expected Type. + The object under examination + The message to display in case of failure + + + + Asserts that an object may be assigned a value of a given Type. + + The expected Type. + The object under examination + + + + Asserts that an object may not be assigned a value of a given Type. + + The expected Type. + The object under examination + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Asserts that an object may not be assigned a value of a given Type. + + The expected Type. + The object under examination + The message to display in case of failure + + + + Asserts that an object may not be assigned a value of a given Type. + + The expected Type. + The object under examination + + + + Asserts that an object may not be assigned a value of a given Type. + + The expected Type. + The object under examination + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Asserts that an object may not be assigned a value of a given Type. + + The expected Type. + The object under examination + The message to display in case of failure + + + + Asserts that an object may not be assigned a value of a given Type. + + The expected Type. + The object under examination + + + + Asserts that an object is an instance of a given type. + + The expected Type + The object being examined + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Asserts that an object is an instance of a given type. + + The expected Type + The object being examined + The message to display in case of failure + + + + Asserts that an object is an instance of a given type. + + The expected Type + The object being examined + + + + Asserts that an object is an instance of a given type. + + The expected Type + The object being examined + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Asserts that an object is an instance of a given type. + + The expected Type + The object being examined + The message to display in case of failure + + + + Asserts that an object is an instance of a given type. + + The expected Type + The object being examined + + + + Asserts that an object is an instance of a given type. + + The expected Type + The object being examined + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Asserts that an object is an instance of a given type. + + The expected Type + The object being examined + The message to display in case of failure + + + + Asserts that an object is an instance of a given type. + + The expected Type + The object being examined + + + + Asserts that an object is not an instance of a given type. + + The expected Type + The object being examined + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Asserts that an object is not an instance of a given type. + + The expected Type + The object being examined + The message to display in case of failure + + + + Asserts that an object is not an instance of a given type. + + The expected Type + The object being examined + + + + Asserts that an object is not an instance of a given type. + + The expected Type + The object being examined + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Asserts that an object is not an instance of a given type. + + The expected Type + The object being examined + The message to display in case of failure + + + + Asserts that an object is not an instance of a given type. + + The expected Type + The object being examined + + + + Asserts that an object is not an instance of a given type. + + The expected Type + The object being examined + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Asserts that an object is not an instance of a given type. + + The expected Type + The object being examined + The message to display in case of failure + + + + Asserts that an object is not an instance of a given type. + + The expected Type + The object being examined + + + + Verifies that the first value is greater than the second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that the first value is greater than the second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + The message to display in case of failure + + + + Verifies that the first value is greater than the second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + + + + Verifies that the first value is greater than the second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that the first value is greater than the second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + The message to display in case of failure + + + + Verifies that the first value is greater than the second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + + + + Verifies that the first value is greater than the second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that the first value is greater than the second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + The message to display in case of failure + + + + Verifies that the first value is greater than the second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + + + + Verifies that the first value is greater than the second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that the first value is greater than the second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + The message to display in case of failure + + + + Verifies that the first value is greater than the second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + + + + Verifies that the first value is greater than the second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that the first value is greater than the second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + The message to display in case of failure + + + + Verifies that the first value is greater than the second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + + + + Verifies that the first value is greater than the second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that the first value is greater than the second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + The message to display in case of failure + + + + Verifies that the first value is greater than the second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + + + + Verifies that the first value is greater than the second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that the first value is greater than the second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + The message to display in case of failure + + + + Verifies that the first value is greater than the second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + + + + Verifies that the first value is greater than the second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that the first value is greater than the second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + The message to display in case of failure + + + + Verifies that the first value is greater than the second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + + + + Verifies that the first value is less than the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that the first value is less than the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + The message to display in case of failure + + + + Verifies that the first value is less than the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + + + + Verifies that the first value is less than the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that the first value is less than the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + The message to display in case of failure + + + + Verifies that the first value is less than the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + + + + Verifies that the first value is less than the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that the first value is less than the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + The message to display in case of failure + + + + Verifies that the first value is less than the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + + + + Verifies that the first value is less than the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that the first value is less than the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + The message to display in case of failure + + + + Verifies that the first value is less than the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + + + + Verifies that the first value is less than the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that the first value is less than the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + The message to display in case of failure + + + + Verifies that the first value is less than the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + + + + Verifies that the first value is less than the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that the first value is less than the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + The message to display in case of failure + + + + Verifies that the first value is less than the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + + + + Verifies that the first value is less than the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that the first value is less than the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + The message to display in case of failure + + + + Verifies that the first value is less than the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + + + + Verifies that the first value is less than the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that the first value is less than the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + The message to display in case of failure + + + + Verifies that the first value is less than the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + + + + Verifies that the first value is greater than or equal tothe second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that the first value is greater than or equal tothe second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + The message to display in case of failure + + + + Verifies that the first value is greater than or equal tothe second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + + + + Verifies that the first value is greater than or equal tothe second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that the first value is greater than or equal tothe second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + The message to display in case of failure + + + + Verifies that the first value is greater than or equal tothe second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + + + + Verifies that the first value is greater than or equal tothe second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that the first value is greater than or equal tothe second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + The message to display in case of failure + + + + Verifies that the first value is greater than or equal tothe second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + + + + Verifies that the first value is greater than or equal tothe second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that the first value is greater than or equal tothe second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + The message to display in case of failure + + + + Verifies that the first value is greater than or equal tothe second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + + + + Verifies that the first value is greater than or equal tothe second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that the first value is greater than or equal tothe second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + The message to display in case of failure + + + + Verifies that the first value is greater than or equal tothe second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + + + + Verifies that the first value is greater than or equal tothe second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that the first value is greater than or equal tothe second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + The message to display in case of failure + + + + Verifies that the first value is greater than or equal tothe second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + + + + Verifies that the first value is greater than or equal tothe second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that the first value is greater than or equal tothe second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + The message to display in case of failure + + + + Verifies that the first value is greater than or equal tothe second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + + + + Verifies that the first value is greater than or equal tothe second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that the first value is greater than or equal tothe second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + The message to display in case of failure + + + + Verifies that the first value is greater than or equal tothe second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + + + + Verifies that the first value is less than or equal to the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that the first value is less than or equal to the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + The message to display in case of failure + + + + Verifies that the first value is less than or equal to the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + + + + Verifies that the first value is less than or equal to the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that the first value is less than or equal to the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + The message to display in case of failure + + + + Verifies that the first value is less than or equal to the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + + + + Verifies that the first value is less than or equal to the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that the first value is less than or equal to the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + The message to display in case of failure + + + + Verifies that the first value is less than or equal to the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + + + + Verifies that the first value is less than or equal to the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that the first value is less than or equal to the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + The message to display in case of failure + + + + Verifies that the first value is less than or equal to the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + + + + Verifies that the first value is less than or equal to the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that the first value is less than or equal to the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + The message to display in case of failure + + + + Verifies that the first value is less than or equal to the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + + + + Verifies that the first value is less than or equal to the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that the first value is less than or equal to the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + The message to display in case of failure + + + + Verifies that the first value is less than or equal to the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + + + + Verifies that the first value is less than or equal to the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that the first value is less than or equal to the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + The message to display in case of failure + + + + Verifies that the first value is less than or equal to the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + + + + Verifies that the first value is less than or equal to the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that the first value is less than or equal to the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + The message to display in case of failure + + + + Verifies that the first value is less than or equal to the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + + + + Asserts that an object is contained in a list. + + The expected object + The list to be examined + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Asserts that an object is contained in a list. + + The expected object + The list to be examined + The message to display in case of failure + + + + Asserts that an object is contained in a list. + + The expected object + The list to be examined + + + + Helper for Assert.AreEqual(double expected, double actual, ...) + allowing code generation to work consistently. + + The expected value + The actual value + The maximum acceptable difference between the + the expected and the actual + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Gets the number of assertions executed so far and + resets the counter to zero. + + + + + AssertionHelper is an optional base class for user tests, + allowing the use of shorter names for constraints and + asserts and avoiding conflict with the definition of + , from which it inherits much of its + behavior, in certain mock object frameworks. + + + + + Helper class with properties and methods that supply + a number of constraints used in Asserts. + + + + + Returns a ConstraintExpression, which will apply + the following constraint to all members of a collection, + succeeding only if a specified number of them succeed. + + + + + Returns a new PropertyConstraintExpression, which will either + test for the existence of the named property on the object + being tested or apply any following constraint to that property. + + + + + Returns a new AttributeConstraint checking for the + presence of a particular attribute on an object. + + + + + Returns a new AttributeConstraint checking for the + presence of a particular attribute on an object. + + + + + Returns a constraint that tests two items for equality + + + + + Returns a constraint that tests that two references are the same object + + + + + Returns a constraint that tests whether the + actual value is greater than the suppled argument + + + + + Returns a constraint that tests whether the + actual value is greater than or equal to the suppled argument + + + + + Returns a constraint that tests whether the + actual value is greater than or equal to the suppled argument + + + + + Returns a constraint that tests whether the + actual value is less than the suppled argument + + + + + Returns a constraint that tests whether the + actual value is less than or equal to the suppled argument + + + + + Returns a constraint that tests whether the + actual value is less than or equal to the suppled argument + + + + + Returns a constraint that tests whether the actual + value is of the exact type supplied as an argument. + + + + + Returns a constraint that tests whether the actual + value is of the exact type supplied as an argument. + + + + + Returns a constraint that tests whether the actual value + is of the type supplied as an argument or a derived type. + + + + + Returns a constraint that tests whether the actual value + is of the type supplied as an argument or a derived type. + + + + + Returns a constraint that tests whether the actual value + is of the type supplied as an argument or a derived type. + + + + + Returns a constraint that tests whether the actual value + is of the type supplied as an argument or a derived type. + + + + + Returns a constraint that tests whether the actual value + is assignable from the type supplied as an argument. + + + + + Returns a constraint that tests whether the actual value + is assignable from the type supplied as an argument. + + + + + Returns a constraint that tests whether the actual value + is assignable from the type supplied as an argument. + + + + + Returns a constraint that tests whether the actual value + is assignable from the type supplied as an argument. + + + + + Returns a constraint that tests whether the actual value + is a collection containing the same elements as the + collection supplied as an argument. + + + + + Returns a constraint that tests whether the actual value + is a subset of the collection supplied as an argument. + + + + + Returns a new CollectionContainsConstraint checking for the + presence of a particular object in the collection. + + + + + Returns a new CollectionContainsConstraint checking for the + presence of a particular object in the collection. + + + + + Returns a new ContainsConstraint. This constraint + will, in turn, make use of the appropriate second-level + constraint, depending on the type of the actual argument. + This overload is only used if the item sought is a string, + since any other type implies that we are looking for a + collection member. + + + + + Returns a constraint that succeeds if the actual + value contains the substring supplied as an argument. + + + + + Returns a constraint that succeeds if the actual + value contains the substring supplied as an argument. + + + + + Returns a constraint that fails if the actual + value contains the substring supplied as an argument. + + + + + Returns a constraint that succeeds if the actual + value starts with the substring supplied as an argument. + + + + + Returns a constraint that succeeds if the actual + value starts with the substring supplied as an argument. + + + + + Returns a constraint that fails if the actual + value starts with the substring supplied as an argument. + + + + + Returns a constraint that succeeds if the actual + value ends with the substring supplied as an argument. + + + + + Returns a constraint that succeeds if the actual + value ends with the substring supplied as an argument. + + + + + Returns a constraint that fails if the actual + value ends with the substring supplied as an argument. + + + + + Returns a constraint that succeeds if the actual + value matches the regular expression supplied as an argument. + + + + + Returns a constraint that succeeds if the actual + value matches the regular expression supplied as an argument. + + + + + Returns a constraint that fails if the actual + value matches the pattern supplied as an argument. + + + + + Returns a constraint that tests whether the path provided + is the same as an expected path after canonicalization. + + + + + Returns a constraint that tests whether the path provided + is the same path or under an expected path after canonicalization. + + + + + Returns a constraint that tests whether the path provided + is the same path or under an expected path after canonicalization. + + + + + Returns a constraint that tests whether the actual value falls + within a specified range. + + + + + Returns a ConstraintExpression that negates any + following constraint. + + + + + Returns a ConstraintExpression that negates any + following constraint. + + + + + Returns a ConstraintExpression, which will apply + the following constraint to all members of a collection, + succeeding if all of them succeed. + + + + + Returns a ConstraintExpression, which will apply + the following constraint to all members of a collection, + succeeding if at least one of them succeeds. + + + + + Returns a ConstraintExpression, which will apply + the following constraint to all members of a collection, + succeeding if all of them fail. + + + + + Returns a new ConstraintExpression, which will apply the following + constraint to the Length property of the object being tested. + + + + + Returns a new ConstraintExpression, which will apply the following + constraint to the Count property of the object being tested. + + + + + Returns a new ConstraintExpression, which will apply the following + constraint to the Message property of the object being tested. + + + + + Returns a new ConstraintExpression, which will apply the following + constraint to the InnerException property of the object being tested. + + + + + Returns a constraint that tests for null + + + + + Returns a constraint that tests for True + + + + + Returns a constraint that tests for False + + + + + Returns a constraint that tests for a positive value + + + + + Returns a constraint that tests for a negative value + + + + + Returns a constraint that tests for NaN + + + + + Returns a constraint that tests for empty + + + + + Returns a constraint that tests whether a collection + contains all unique items. + + + + + Returns a constraint that tests whether an object graph is serializable in binary format. + + + + + Returns a constraint that tests whether an object graph is serializable in xml format. + + + + + Returns a constraint that tests whether a collection is ordered + + + + + Apply a constraint to an actual value, succeeding if the constraint + is satisfied and throwing an assertion exception on failure. Works + identically to Assert.That. + + The actual value to test + A Constraint to be applied + + + + Apply a constraint to an actual value, succeeding if the constraint + is satisfied and throwing an assertion exception on failure. Works + identically to Assert.That. + + The actual value to test + A Constraint to be applied + The message to be displayed in case of failure + + + + Apply a constraint to an actual value, succeeding if the constraint + is satisfied and throwing an assertion exception on failure. Works + identically to Assert.That. + + The actual value to test + A Constraint to be applied + The message to be displayed in case of failure + Arguments to use in formatting the message + + + + Asserts that a condition is true. If the condition is false the method throws + an . Works Identically to + . + + The evaluated condition + The message to display if the condition is false + Arguments to be used in formatting the message + + + + Asserts that a condition is true. If the condition is false the method throws + an . Works Identically to + . + + The evaluated condition + The message to display if the condition is false + + + + Asserts that a condition is true. If the condition is false the method throws + an . Works Identically to . + + The evaluated condition + + + + Apply a constraint to an actual value, succeeding if the constraint + is satisfied and throwing an assertion exception on failure. + + A Constraint expression to be applied + An ActualValueDelegate returning the value to be tested + + + + Apply a constraint to an actual value, succeeding if the constraint + is satisfied and throwing an assertion exception on failure. + + A Constraint expression to be applied + An ActualValueDelegate returning the value to be tested + The message that will be displayed on failure + + + + Apply a constraint to an actual value, succeeding if the constraint + is satisfied and throwing an assertion exception on failure. + + An ActualValueDelegate returning the value to be tested + A Constraint expression to be applied + The message that will be displayed on failure + Arguments to be used in formatting the message + + + + Apply a constraint to a referenced value, succeeding if the constraint + is satisfied and throwing an assertion exception on failure. + + The actual value to test + A Constraint to be applied + + + + Apply a constraint to a referenced value, succeeding if the constraint + is satisfied and throwing an assertion exception on failure. + + The actual value to test + A Constraint to be applied + The message that will be displayed on failure + + + + Apply a constraint to a referenced value, succeeding if the constraint + is satisfied and throwing an assertion exception on failure. + + The actual value to test + A Constraint to be applied + The message that will be displayed on failure + Arguments to be used in formatting the message + + + + Asserts that the code represented by a delegate throws an exception + that satisfies the constraint provided. + + A TestDelegate to be executed + A ThrowsConstraint used in the test + + + + Returns a ListMapper based on a collection. + + The original collection + + + + + Provides static methods to express the assumptions + that must be met for a test to give a meaningful + result. If an assumption is not met, the test + should produce an inconclusive result. + + + + + The Equals method throws an AssertionException. This is done + to make sure there is no mistake by calling this function. + + + + + + + override the default ReferenceEquals to throw an AssertionException. This + implementation makes sure there is no mistake in calling this function + as part of Assert. + + + + + + + Apply a constraint to an actual value, succeeding if the constraint + is satisfied and throwing an InconclusiveException on failure. + + A Constraint expression to be applied + The actual value to test + + + + Apply a constraint to an actual value, succeeding if the constraint + is satisfied and throwing an InconclusiveException on failure. + + A Constraint expression to be applied + The actual value to test + The message that will be displayed on failure + + + + Apply a constraint to an actual value, succeeding if the constraint + is satisfied and throwing an InconclusiveException on failure. + + A Constraint expression to be applied + The actual value to test + The message that will be displayed on failure + Arguments to be used in formatting the message + + + + Asserts that a condition is true. If the condition is false the method throws + an . + + The evaluated condition + The message to display if the condition is false + Arguments to be used in formatting the message + + + + Asserts that a condition is true. If the condition is false the method throws + an . + + The evaluated condition + The message to display if the condition is false + + + + Asserts that a condition is true. If the condition is false the + method throws an . + + The evaluated condition + + + + Apply a constraint to an actual value, succeeding if the constraint + is satisfied and throwing an InconclusiveException on failure. + + A Constraint expression to be applied + An ActualValueDelegate returning the value to be tested + + + + Apply a constraint to an actual value, succeeding if the constraint + is satisfied and throwing an InconclusiveException on failure. + + A Constraint expression to be applied + An ActualValueDelegate returning the value to be tested + The message that will be displayed on failure + + + + Apply a constraint to an actual value, succeeding if the constraint + is satisfied and throwing an InconclusiveException on failure. + + An ActualValueDelegate returning the value to be tested + A Constraint expression to be applied + The message that will be displayed on failure + Arguments to be used in formatting the message + + + + Apply a constraint to a referenced value, succeeding if the constraint + is satisfied and throwing an InconclusiveException on failure. + + A Constraint expression to be applied + The actual value to test + + + + Apply a constraint to a referenced value, succeeding if the constraint + is satisfied and throwing an InconclusiveException on failure. + + A Constraint expression to be applied + The actual value to test + The message that will be displayed on failure + + + + Apply a constraint to a referenced value, succeeding if the constraint + is satisfied and throwing an InconclusiveException on failure. + + A Constraint expression to be applied + The actual value to test + The message that will be displayed on failure + Arguments to be used in formatting the message + + + + Asserts that the code represented by a delegate throws an exception + that satisfies the constraint provided. + + A TestDelegate to be executed + A ThrowsConstraint used in the test + + + + Waits for pending asynchronous operations to complete, if appropriate, + and returns a proper result of the invocation by unwrapping task results + + The raw result of the method invocation + The unwrapped result, if necessary + + + + A set of Assert methods operationg on one or more collections + + + + + The Equals method throws an AssertionException. This is done + to make sure there is no mistake by calling this function. + + + + + + + override the default ReferenceEquals to throw an AssertionException. This + implementation makes sure there is no mistake in calling this function + as part of Assert. + + + + + + + Asserts that all items contained in collection are of the type specified by expectedType. + + IEnumerable containing objects to be considered + System.Type that all objects in collection must be instances of + + + + Asserts that all items contained in collection are of the type specified by expectedType. + + IEnumerable containing objects to be considered + System.Type that all objects in collection must be instances of + The message that will be displayed on failure + + + + Asserts that all items contained in collection are of the type specified by expectedType. + + IEnumerable containing objects to be considered + System.Type that all objects in collection must be instances of + The message that will be displayed on failure + Arguments to be used in formatting the message + + + + Asserts that all items contained in collection are not equal to null. + + IEnumerable containing objects to be considered + + + + Asserts that all items contained in collection are not equal to null. + + IEnumerable containing objects to be considered + The message that will be displayed on failure + + + + Asserts that all items contained in collection are not equal to null. + + IEnumerable of objects to be considered + The message that will be displayed on failure + Arguments to be used in formatting the message + + + + Ensures that every object contained in collection exists within the collection + once and only once. + + IEnumerable of objects to be considered + + + + Ensures that every object contained in collection exists within the collection + once and only once. + + IEnumerable of objects to be considered + The message that will be displayed on failure + + + + Ensures that every object contained in collection exists within the collection + once and only once. + + IEnumerable of objects to be considered + The message that will be displayed on failure + Arguments to be used in formatting the message + + + + Asserts that expected and actual are exactly equal. The collections must have the same count, + and contain the exact same objects in the same order. + + The first IEnumerable of objects to be considered + The second IEnumerable of objects to be considered + + + + Asserts that expected and actual are exactly equal. The collections must have the same count, + and contain the exact same objects in the same order. + If comparer is not null then it will be used to compare the objects. + + The first IEnumerable of objects to be considered + The second IEnumerable of objects to be considered + The IComparer to use in comparing objects from each IEnumerable + + + + Asserts that expected and actual are exactly equal. The collections must have the same count, + and contain the exact same objects in the same order. + + The first IEnumerable of objects to be considered + The second IEnumerable of objects to be considered + The message that will be displayed on failure + + + + Asserts that expected and actual are exactly equal. The collections must have the same count, + and contain the exact same objects in the same order. + If comparer is not null then it will be used to compare the objects. + + The first IEnumerable of objects to be considered + The second IEnumerable of objects to be considered + The IComparer to use in comparing objects from each IEnumerable + The message that will be displayed on failure + + + + Asserts that expected and actual are exactly equal. The collections must have the same count, + and contain the exact same objects in the same order. + + The first IEnumerable of objects to be considered + The second IEnumerable of objects to be considered + The message that will be displayed on failure + Arguments to be used in formatting the message + + + + Asserts that expected and actual are exactly equal. The collections must have the same count, + and contain the exact same objects in the same order. + If comparer is not null then it will be used to compare the objects. + + The first IEnumerable of objects to be considered + The second IEnumerable of objects to be considered + The IComparer to use in comparing objects from each IEnumerable + The message that will be displayed on failure + Arguments to be used in formatting the message + + + + Asserts that expected and actual are equivalent, containing the same objects but the match may be in any order. + + The first IEnumerable of objects to be considered + The second IEnumerable of objects to be considered + + + + Asserts that expected and actual are equivalent, containing the same objects but the match may be in any order. + + The first IEnumerable of objects to be considered + The second IEnumerable of objects to be considered + The message that will be displayed on failure + + + + Asserts that expected and actual are equivalent, containing the same objects but the match may be in any order. + + The first IEnumerable of objects to be considered + The second IEnumerable of objects to be considered + The message that will be displayed on failure + Arguments to be used in formatting the message + + + + Asserts that expected and actual are not exactly equal. + + The first IEnumerable of objects to be considered + The second IEnumerable of objects to be considered + + + + Asserts that expected and actual are not exactly equal. + If comparer is not null then it will be used to compare the objects. + + The first IEnumerable of objects to be considered + The second IEnumerable of objects to be considered + The IComparer to use in comparing objects from each IEnumerable + + + + Asserts that expected and actual are not exactly equal. + + The first IEnumerable of objects to be considered + The second IEnumerable of objects to be considered + The message that will be displayed on failure + + + + Asserts that expected and actual are not exactly equal. + If comparer is not null then it will be used to compare the objects. + + The first IEnumerable of objects to be considered + The second IEnumerable of objects to be considered + The IComparer to use in comparing objects from each IEnumerable + The message that will be displayed on failure + + + + Asserts that expected and actual are not exactly equal. + + The first IEnumerable of objects to be considered + The second IEnumerable of objects to be considered + The message that will be displayed on failure + Arguments to be used in formatting the message + + + + Asserts that expected and actual are not exactly equal. + If comparer is not null then it will be used to compare the objects. + + The first IEnumerable of objects to be considered + The second IEnumerable of objects to be considered + The IComparer to use in comparing objects from each IEnumerable + The message that will be displayed on failure + Arguments to be used in formatting the message + + + + Asserts that expected and actual are not equivalent. + + The first IEnumerable of objects to be considered + The second IEnumerable of objects to be considered + + + + Asserts that expected and actual are not equivalent. + + The first IEnumerable of objects to be considered + The second IEnumerable of objects to be considered + The message that will be displayed on failure + + + + Asserts that expected and actual are not equivalent. + + The first IEnumerable of objects to be considered + The second IEnumerable of objects to be considered + The message that will be displayed on failure + Arguments to be used in formatting the message + + + + Asserts that collection contains actual as an item. + + IEnumerable of objects to be considered + Object to be found within collection + + + + Asserts that collection contains actual as an item. + + IEnumerable of objects to be considered + Object to be found within collection + The message that will be displayed on failure + + + + Asserts that collection contains actual as an item. + + IEnumerable of objects to be considered + Object to be found within collection + The message that will be displayed on failure + Arguments to be used in formatting the message + + + + Asserts that collection does not contain actual as an item. + + IEnumerable of objects to be considered + Object that cannot exist within collection + + + + Asserts that collection does not contain actual as an item. + + IEnumerable of objects to be considered + Object that cannot exist within collection + The message that will be displayed on failure + + + + Asserts that collection does not contain actual as an item. + + IEnumerable of objects to be considered + Object that cannot exist within collection + The message that will be displayed on failure + Arguments to be used in formatting the message + + + + Asserts that the superset does not contain the subset + + The IEnumerable subset to be considered + The IEnumerable superset to be considered + + + + Asserts that the superset does not contain the subset + + The IEnumerable subset to be considered + The IEnumerable superset to be considered + The message that will be displayed on failure + + + + Asserts that the superset does not contain the subset + + The IEnumerable subset to be considered + The IEnumerable superset to be considered + The message that will be displayed on failure + Arguments to be used in formatting the message + + + + Asserts that the superset contains the subset. + + The IEnumerable subset to be considered + The IEnumerable superset to be considered + + + + Asserts that the superset contains the subset. + + The IEnumerable subset to be considered + The IEnumerable superset to be considered + The message that will be displayed on failure + + + + Asserts that the superset contains the subset. + + The IEnumerable subset to be considered + The IEnumerable superset to be considered + The message that will be displayed on failure + Arguments to be used in formatting the message + + + + Assert that an array, list or other collection is empty + + An array, list or other collection implementing IEnumerable + The message to be displayed on failure + Arguments to be used in formatting the message + + + + Assert that an array, list or other collection is empty + + An array, list or other collection implementing IEnumerable + The message to be displayed on failure + + + + Assert that an array,list or other collection is empty + + An array, list or other collection implementing IEnumerable + + + + Assert that an array, list or other collection is empty + + An array, list or other collection implementing IEnumerable + The message to be displayed on failure + Arguments to be used in formatting the message + + + + Assert that an array, list or other collection is empty + + An array, list or other collection implementing IEnumerable + The message to be displayed on failure + + + + Assert that an array,list or other collection is empty + + An array, list or other collection implementing IEnumerable + + + + Assert that an array, list or other collection is ordered + + An array, list or other collection implementing IEnumerable + The message to be displayed on failure + Arguments to be used in formatting the message + + + + Assert that an array, list or other collection is ordered + + An array, list or other collection implementing IEnumerable + The message to be displayed on failure + + + + Assert that an array, list or other collection is ordered + + An array, list or other collection implementing IEnumerable + + + + Assert that an array, list or other collection is ordered + + An array, list or other collection implementing IEnumerable + A custom comparer to perform the comparisons + The message to be displayed on failure + Arguments to be used in formatting the message + + + + Assert that an array, list or other collection is ordered + + An array, list or other collection implementing IEnumerable + A custom comparer to perform the comparisons + The message to be displayed on failure + + + + Assert that an array, list or other collection is ordered + + An array, list or other collection implementing IEnumerable + A custom comparer to perform the comparisons + + + + Helper class with properties and methods that supply + a number of constraints used in Asserts. + + + + + Returns a new CollectionContainsConstraint checking for the + presence of a particular object in the collection. + + + + + Returns a constraint that succeeds if the actual + value contains the substring supplied as an argument. + + + + + Summary description for DirectoryAssert + + + + + The Equals method throws an AssertionException. This is done + to make sure there is no mistake by calling this function. + + + + + + + override the default ReferenceEquals to throw an AssertionException. This + implementation makes sure there is no mistake in calling this function + as part of Assert. + + + + + + + We don't actually want any instances of this object, but some people + like to inherit from it to add other static methods. Hence, the + protected constructor disallows any instances of this object. + + + + + Verifies that two directories are equal. Two directories are considered + equal if both are null, or if both have the same value byte for byte. + If they are not equal an is thrown. + + A directory containing the value that is expected + A directory containing the actual value + The message to display if directories are not equal + Arguments to be used in formatting the message + + + + Verifies that two directories are equal. Two directories are considered + equal if both are null, or if both have the same value byte for byte. + If they are not equal an is thrown. + + A directory containing the value that is expected + A directory containing the actual value + The message to display if directories are not equal + + + + Verifies that two directories are equal. Two directories are considered + equal if both are null, or if both have the same value byte for byte. + If they are not equal an is thrown. + + A directory containing the value that is expected + A directory containing the actual value + + + + Verifies that two directories are equal. Two directories are considered + equal if both are null, or if both have the same value byte for byte. + If they are not equal an is thrown. + + A directory path string containing the value that is expected + A directory path string containing the actual value + The message to display if directories are not equal + Arguments to be used in formatting the message + + + + Verifies that two directories are equal. Two directories are considered + equal if both are null, or if both have the same value byte for byte. + If they are not equal an is thrown. + + A directory path string containing the value that is expected + A directory path string containing the actual value + The message to display if directories are not equal + + + + Verifies that two directories are equal. Two directories are considered + equal if both are null, or if both have the same value byte for byte. + If they are not equal an is thrown. + + A directory path string containing the value that is expected + A directory path string containing the actual value + + + + Asserts that two directories are not equal. If they are equal + an is thrown. + + A directory containing the value that is expected + A directory containing the actual value + The message to display if directories are not equal + Arguments to be used in formatting the message + + + + Asserts that two directories are not equal. If they are equal + an is thrown. + + A directory containing the value that is expected + A directory containing the actual value + The message to display if directories are not equal + + + + Asserts that two directories are not equal. If they are equal + an is thrown. + + A directory containing the value that is expected + A directory containing the actual value + + + + Asserts that two directories are not equal. If they are equal + an is thrown. + + A directory path string containing the value that is expected + A directory path string containing the actual value + The message to display if directories are equal + Arguments to be used in formatting the message + + + + Asserts that two directories are not equal. If they are equal + an is thrown. + + A directory path string containing the value that is expected + A directory path string containing the actual value + The message to display if directories are equal + + + + Asserts that two directories are not equal. If they are equal + an is thrown. + + A directory path string containing the value that is expected + A directory path string containing the actual value + + + + Asserts that the directory is empty. If it is not empty + an is thrown. + + A directory to search + The message to display if directories are not equal + Arguments to be used in formatting the message + + + + Asserts that the directory is empty. If it is not empty + an is thrown. + + A directory to search + The message to display if directories are not equal + + + + Asserts that the directory is empty. If it is not empty + an is thrown. + + A directory to search + + + + Asserts that the directory is empty. If it is not empty + an is thrown. + + A directory to search + The message to display if directories are not equal + Arguments to be used in formatting the message + + + + Asserts that the directory is empty. If it is not empty + an is thrown. + + A directory to search + The message to display if directories are not equal + + + + Asserts that the directory is empty. If it is not empty + an is thrown. + + A directory to search + + + + Asserts that the directory is not empty. If it is empty + an is thrown. + + A directory to search + The message to display if directories are not equal + Arguments to be used in formatting the message + + + + Asserts that the directory is not empty. If it is empty + an is thrown. + + A directory to search + The message to display if directories are not equal + + + + Asserts that the directory is not empty. If it is empty + an is thrown. + + A directory to search + + + + Asserts that the directory is not empty. If it is empty + an is thrown. + + A directory to search + The message to display if directories are not equal + Arguments to be used in formatting the message + + + + Asserts that the directory is not empty. If it is empty + an is thrown. + + A directory to search + The message to display if directories are not equal + + + + Asserts that the directory is not empty. If it is empty + an is thrown. + + A directory to search + + + + Asserts that path contains actual as a subdirectory or + an is thrown. + + A directory to search + sub-directory asserted to exist under directory + The message to display if directory is not within the path + Arguments to be used in formatting the message + + + + Asserts that path contains actual as a subdirectory or + an is thrown. + + A directory to search + sub-directory asserted to exist under directory + The message to display if directory is not within the path + + + + Asserts that path contains actual as a subdirectory or + an is thrown. + + A directory to search + sub-directory asserted to exist under directory + + + + Asserts that path contains actual as a subdirectory or + an is thrown. + + A directory to search + sub-directory asserted to exist under directory + The message to display if directory is not within the path + Arguments to be used in formatting the message + + + + Asserts that path contains actual as a subdirectory or + an is thrown. + + A directory to search + sub-directory asserted to exist under directory + The message to display if directory is not within the path + + + + Asserts that path contains actual as a subdirectory or + an is thrown. + + A directory to search + sub-directory asserted to exist under directory + + + + Asserts that path does not contain actual as a subdirectory or + an is thrown. + + A directory to search + sub-directory asserted to exist under directory + The message to display if directory is not within the path + Arguments to be used in formatting the message + + + + Asserts that path does not contain actual as a subdirectory or + an is thrown. + + A directory to search + sub-directory asserted to exist under directory + The message to display if directory is not within the path + + + + Asserts that path does not contain actual as a subdirectory or + an is thrown. + + A directory to search + sub-directory asserted to exist under directory + + + + Asserts that path does not contain actual as a subdirectory or + an is thrown. + + A directory to search + sub-directory asserted to exist under directory + The message to display if directory is not within the path + Arguments to be used in formatting the message + + + + Asserts that path does not contain actual as a subdirectory or + an is thrown. + + A directory to search + sub-directory asserted to exist under directory + The message to display if directory is not within the path + + + + Asserts that path does not contain actual as a subdirectory or + an is thrown. + + A directory to search + sub-directory asserted to exist under directory + + + + Summary description for FileAssert. + + + + + The Equals method throws an AssertionException. This is done + to make sure there is no mistake by calling this function. + + + + + + + override the default ReferenceEquals to throw an AssertionException. This + implementation makes sure there is no mistake in calling this function + as part of Assert. + + + + + + + We don't actually want any instances of this object, but some people + like to inherit from it to add other static methods. Hence, the + protected constructor disallows any instances of this object. + + + + + Verifies that two Streams are equal. Two Streams are considered + equal if both are null, or if both have the same value byte for byte. + If they are not equal an is thrown. + + The expected Stream + The actual Stream + The message to display if Streams are not equal + Arguments to be used in formatting the message + + + + Verifies that two Streams are equal. Two Streams are considered + equal if both are null, or if both have the same value byte for byte. + If they are not equal an is thrown. + + The expected Stream + The actual Stream + The message to display if objects are not equal + + + + Verifies that two Streams are equal. Two Streams are considered + equal if both are null, or if both have the same value byte for byte. + If they are not equal an is thrown. + + The expected Stream + The actual Stream + + + + Verifies that two files are equal. Two files are considered + equal if both are null, or if both have the same value byte for byte. + If they are not equal an is thrown. + + A file containing the value that is expected + A file containing the actual value + The message to display if Streams are not equal + Arguments to be used in formatting the message + + + + Verifies that two files are equal. Two files are considered + equal if both are null, or if both have the same value byte for byte. + If they are not equal an is thrown. + + A file containing the value that is expected + A file containing the actual value + The message to display if objects are not equal + + + + Verifies that two files are equal. Two files are considered + equal if both are null, or if both have the same value byte for byte. + If they are not equal an is thrown. + + A file containing the value that is expected + A file containing the actual value + + + + Verifies that two files are equal. Two files are considered + equal if both are null, or if both have the same value byte for byte. + If they are not equal an is thrown. + + The path to a file containing the value that is expected + The path to a file containing the actual value + The message to display if Streams are not equal + Arguments to be used in formatting the message + + + + Verifies that two files are equal. Two files are considered + equal if both are null, or if both have the same value byte for byte. + If they are not equal an is thrown. + + The path to a file containing the value that is expected + The path to a file containing the actual value + The message to display if objects are not equal + + + + Verifies that two files are equal. Two files are considered + equal if both are null, or if both have the same value byte for byte. + If they are not equal an is thrown. + + The path to a file containing the value that is expected + The path to a file containing the actual value + + + + Asserts that two Streams are not equal. If they are equal + an is thrown. + + The expected Stream + The actual Stream + The message to be displayed when the two Stream are the same. + Arguments to be used in formatting the message + + + + Asserts that two Streams are not equal. If they are equal + an is thrown. + + The expected Stream + The actual Stream + The message to be displayed when the Streams are the same. + + + + Asserts that two Streams are not equal. If they are equal + an is thrown. + + The expected Stream + The actual Stream + + + + Asserts that two files are not equal. If they are equal + an is thrown. + + A file containing the value that is expected + A file containing the actual value + The message to display if Streams are not equal + Arguments to be used in formatting the message + + + + Asserts that two files are not equal. If they are equal + an is thrown. + + A file containing the value that is expected + A file containing the actual value + The message to display if objects are not equal + + + + Asserts that two files are not equal. If they are equal + an is thrown. + + A file containing the value that is expected + A file containing the actual value + + + + Asserts that two files are not equal. If they are equal + an is thrown. + + The path to a file containing the value that is expected + The path to a file containing the actual value + The message to display if Streams are not equal + Arguments to be used in formatting the message + + + + Asserts that two files are not equal. If they are equal + an is thrown. + + The path to a file containing the value that is expected + The path to a file containing the actual value + The message to display if objects are not equal + + + + Asserts that two files are not equal. If they are equal + an is thrown. + + The path to a file containing the value that is expected + The path to a file containing the actual value + + + + GlobalSettings is a place for setting default values used + by the framework in performing asserts. + + + + + Default tolerance for floating point equality + + + + + Class used to guard against unexpected argument values + by throwing an appropriate exception. + + + + + Throws an exception if an argument is null + + The value to be tested + The name of the argument + + + + Throws an exception if a string argument is null or empty + + The value to be tested + The name of the argument + + + + Helper class with properties and methods that supply + a number of constraints used in Asserts. + + + + + Returns a ConstraintExpression, which will apply + the following constraint to all members of a collection, + succeeding only if a specified number of them succeed. + + + + + Returns a new PropertyConstraintExpression, which will either + test for the existence of the named property on the object + being tested or apply any following constraint to that property. + + + + + Returns a new AttributeConstraint checking for the + presence of a particular attribute on an object. + + + + + Returns a new AttributeConstraint checking for the + presence of a particular attribute on an object. + + + + + Returns a new CollectionContainsConstraint checking for the + presence of a particular object in the collection. + + + + + Returns a ConstraintExpression that negates any + following constraint. + + + + + Returns a ConstraintExpression, which will apply + the following constraint to all members of a collection, + succeeding if all of them succeed. + + + + + Returns a ConstraintExpression, which will apply + the following constraint to all members of a collection, + succeeding if at least one of them succeeds. + + + + + Returns a ConstraintExpression, which will apply + the following constraint to all members of a collection, + succeeding if all of them fail. + + + + + Returns a new ConstraintExpression, which will apply the following + constraint to the Length property of the object being tested. + + + + + Returns a new ConstraintExpression, which will apply the following + constraint to the Count property of the object being tested. + + + + + Returns a new ConstraintExpression, which will apply the following + constraint to the Message property of the object being tested. + + + + + Returns a new ConstraintExpression, which will apply the following + constraint to the InnerException property of the object being tested. + + + + + Interface implemented by a user fixture in order to + validate any expected exceptions. It is only called + for test methods marked with the ExpectedException + attribute. + + + + + Method to handle an expected exception + + The exception to be handled + + + + Helper class with properties and methods that supply + a number of constraints used in Asserts. + + + + + Returns a constraint that tests two items for equality + + + + + Returns a constraint that tests that two references are the same object + + + + + Returns a constraint that tests whether the + actual value is greater than the suppled argument + + + + + Returns a constraint that tests whether the + actual value is greater than or equal to the suppled argument + + + + + Returns a constraint that tests whether the + actual value is greater than or equal to the suppled argument + + + + + Returns a constraint that tests whether the + actual value is less than the suppled argument + + + + + Returns a constraint that tests whether the + actual value is less than or equal to the suppled argument + + + + + Returns a constraint that tests whether the + actual value is less than or equal to the suppled argument + + + + + Returns a constraint that tests whether the actual + value is of the exact type supplied as an argument. + + + + + Returns a constraint that tests whether the actual + value is of the exact type supplied as an argument. + + + + + Returns a constraint that tests whether the actual value + is of the type supplied as an argument or a derived type. + + + + + Returns a constraint that tests whether the actual value + is of the type supplied as an argument or a derived type. + + + + + Returns a constraint that tests whether the actual value + is of the type supplied as an argument or a derived type. + + + + + Returns a constraint that tests whether the actual value + is of the type supplied as an argument or a derived type. + + + + + Returns a constraint that tests whether the actual value + is assignable from the type supplied as an argument. + + + + + Returns a constraint that tests whether the actual value + is assignable from the type supplied as an argument. + + + + + Returns a constraint that tests whether the actual value + is assignable from the type supplied as an argument. + + + + + Returns a constraint that tests whether the actual value + is assignable from the type supplied as an argument. + + + + + Returns a constraint that tests whether the actual value + is a collection containing the same elements as the + collection supplied as an argument. + + + + + Returns a constraint that tests whether the actual value + is a subset of the collection supplied as an argument. + + + + + Returns a constraint that succeeds if the actual + value contains the substring supplied as an argument. + + + + + Returns a constraint that succeeds if the actual + value starts with the substring supplied as an argument. + + + + + Returns a constraint that succeeds if the actual + value ends with the substring supplied as an argument. + + + + + Returns a constraint that succeeds if the actual + value matches the regular expression supplied as an argument. + + + + + Returns a constraint that tests whether the path provided + is the same as an expected path after canonicalization. + + + + + Returns a constraint that tests whether the path provided + is under an expected path after canonicalization. + + + + + Returns a constraint that tests whether the path provided + is the same path or under an expected path after canonicalization. + + + + + Returns a constraint that tests whether the actual value falls + within a specified range. + + + + + Returns a ConstraintExpression that negates any + following constraint. + + + + + Returns a ConstraintExpression, which will apply + the following constraint to all members of a collection, + succeeding if all of them succeed. + + + + + Returns a constraint that tests for null + + + + + Returns a constraint that tests for True + + + + + Returns a constraint that tests for False + + + + + Returns a constraint that tests for a positive value + + + + + Returns a constraint that tests for a negative value + + + + + Returns a constraint that tests for NaN + + + + + Returns a constraint that tests for empty + + + + + Returns a constraint that tests whether a collection + contains all unique items. + + + + + Returns a constraint that tests whether an object graph is serializable in binary format. + + + + + Returns a constraint that tests whether an object graph is serializable in xml format. + + + + + Returns a constraint that tests whether a collection is ordered + + + + + The ITestCaseData interface is implemented by a class + that is able to return complete testcases for use by + a parameterized test method. + + NOTE: This interface is used in both the framework + and the core, even though that results in two different + types. However, sharing the source code guarantees that + the various implementations will be compatible and that + the core is able to reflect successfully over the + framework implementations of ITestCaseData. + + + + + Gets the argument list to be provided to the test + + + + + Gets the expected result + + + + + Indicates whether a result has been specified. + This is necessary because the result may be + null, so it's value cannot be checked. + + + + + Gets the expected exception Type + + + + + Gets the FullName of the expected exception + + + + + Gets the name to be used for the test + + + + + Gets the description of the test + + + + + Gets a value indicating whether this is ignored. + + true if ignored; otherwise, false. + + + + Gets a value indicating whether this is explicit. + + true if explicit; otherwise, false. + + + + Gets the ignore reason. + + The ignore reason. + + + + The Iz class is a synonym for Is intended for use in VB, + which regards Is as a keyword. + + + + + The List class is a helper class with properties and methods + that supply a number of constraints used with lists and collections. + + + + + List.Map returns a ListMapper, which can be used to map + the original collection to another collection. + + + + + + + ListMapper is used to transform a collection used as an actual argument + producing another collection to be used in the assertion. + + + + + Construct a ListMapper based on a collection + + The collection to be transformed + + + + Produces a collection containing all the values of a property + + The collection of property values + + + + + Randomizer returns a set of random values in a repeatable + way, to allow re-running of tests if necessary. + + + + + Get a randomizer for a particular member, returning + one that has already been created if it exists. + This ensures that the same values are generated + each time the tests are reloaded. + + + + + Get a randomizer for a particular parameter, returning + one that has already been created if it exists. + This ensures that the same values are generated + each time the tests are reloaded. + + + + + Construct a randomizer using a random seed + + + + + Construct a randomizer using a specified seed + + + + + Return an array of random doubles between 0.0 and 1.0. + + + + + + + Return an array of random doubles with values in a specified range. + + + + + Return an array of random ints with values in a specified range. + + + + + Get a random seed for use in creating a randomizer. + + + + + The SpecialValue enum is used to represent TestCase arguments + that cannot be used as arguments to an Attribute. + + + + + Null represents a null value, which cannot be used as an + argument to an attribute under .NET 1.x + + + + + Basic Asserts on strings. + + + + + The Equals method throws an AssertionException. This is done + to make sure there is no mistake by calling this function. + + + + + + + override the default ReferenceEquals to throw an AssertionException. This + implementation makes sure there is no mistake in calling this function + as part of Assert. + + + + + + + Asserts that a string is found within another string. + + The expected string + The string to be examined + The message to display in case of failure + Arguments used in formatting the message + + + + Asserts that a string is found within another string. + + The expected string + The string to be examined + The message to display in case of failure + + + + Asserts that a string is found within another string. + + The expected string + The string to be examined + + + + Asserts that a string is not found within another string. + + The expected string + The string to be examined + The message to display in case of failure + Arguments used in formatting the message + + + + Asserts that a string is found within another string. + + The expected string + The string to be examined + The message to display in case of failure + + + + Asserts that a string is found within another string. + + The expected string + The string to be examined + + + + Asserts that a string starts with another string. + + The expected string + The string to be examined + The message to display in case of failure + Arguments used in formatting the message + + + + Asserts that a string starts with another string. + + The expected string + The string to be examined + The message to display in case of failure + + + + Asserts that a string starts with another string. + + The expected string + The string to be examined + + + + Asserts that a string does not start with another string. + + The expected string + The string to be examined + The message to display in case of failure + Arguments used in formatting the message + + + + Asserts that a string does not start with another string. + + The expected string + The string to be examined + The message to display in case of failure + + + + Asserts that a string does not start with another string. + + The expected string + The string to be examined + + + + Asserts that a string ends with another string. + + The expected string + The string to be examined + The message to display in case of failure + Arguments used in formatting the message + + + + Asserts that a string ends with another string. + + The expected string + The string to be examined + The message to display in case of failure + + + + Asserts that a string ends with another string. + + The expected string + The string to be examined + + + + Asserts that a string does not end with another string. + + The expected string + The string to be examined + The message to display in case of failure + Arguments used in formatting the message + + + + Asserts that a string does not end with another string. + + The expected string + The string to be examined + The message to display in case of failure + + + + Asserts that a string does not end with another string. + + The expected string + The string to be examined + + + + Asserts that two strings are equal, without regard to case. + + The expected string + The actual string + The message to display in case of failure + Arguments used in formatting the message + + + + Asserts that two strings are equal, without regard to case. + + The expected string + The actual string + The message to display in case of failure + + + + Asserts that two strings are equal, without regard to case. + + The expected string + The actual string + + + + Asserts that two strings are not equal, without regard to case. + + The expected string + The actual string + The message to display in case of failure + Arguments used in formatting the message + + + + Asserts that two strings are Notequal, without regard to case. + + The expected string + The actual string + The message to display in case of failure + + + + Asserts that two strings are not equal, without regard to case. + + The expected string + The actual string + + + + Asserts that a string matches an expected regular expression pattern. + + The regex pattern to be matched + The actual string + The message to display in case of failure + Arguments used in formatting the message + + + + Asserts that a string matches an expected regular expression pattern. + + The regex pattern to be matched + The actual string + The message to display in case of failure + + + + Asserts that a string matches an expected regular expression pattern. + + The regex pattern to be matched + The actual string + + + + Asserts that a string does not match an expected regular expression pattern. + + The regex pattern to be used + The actual string + The message to display in case of failure + Arguments used in formatting the message + + + + Asserts that a string does not match an expected regular expression pattern. + + The regex pattern to be used + The actual string + The message to display in case of failure + + + + Asserts that a string does not match an expected regular expression pattern. + + The regex pattern to be used + The actual string + + + + The TestCaseData class represents a set of arguments + and other parameter info to be used for a parameterized + test case. It provides a number of instance modifiers + for use in initializing the test case. + + Note: Instance modifiers are getters that return + the same instance after modifying it's state. + + + + + The argument list to be provided to the test + + + + + The expected result to be returned + + + + + Set to true if this has an expected result + + + + + The expected exception Type + + + + + The FullName of the expected exception + + + + + The name to be used for the test + + + + + The description of the test + + + + + A dictionary of properties, used to add information + to tests without requiring the class to change. + + + + + If true, indicates that the test case is to be ignored + + + + + If true, indicates that the test case is marked explicit + + + + + The reason for ignoring a test case + + + + + Initializes a new instance of the class. + + The arguments. + + + + Initializes a new instance of the class. + + The argument. + + + + Initializes a new instance of the class. + + The first argument. + The second argument. + + + + Initializes a new instance of the class. + + The first argument. + The second argument. + The third argument. + + + + Sets the expected result for the test + + The expected result + A modified TestCaseData + + + + Sets the expected exception type for the test + + Type of the expected exception. + The modified TestCaseData instance + + + + Sets the expected exception type for the test + + FullName of the expected exception. + The modified TestCaseData instance + + + + Sets the name of the test case + + The modified TestCaseData instance + + + + Sets the description for the test case + being constructed. + + The description. + The modified TestCaseData instance. + + + + Applies a category to the test + + + + + + + Applies a named property to the test + + + + + + + + Applies a named property to the test + + + + + + + + Applies a named property to the test + + + + + + + + Ignores this TestCase. + + + + + + Ignores this TestCase, specifying the reason. + + The reason. + + + + + Marks this TestCase as Explicit + + + + + + Marks this TestCase as Explicit, specifying the reason. + + The reason. + + + + + Gets the argument list to be provided to the test + + + + + Gets the expected result + + + + + Returns true if the result has been set + + + + + Gets the expected exception Type + + + + + Gets the FullName of the expected exception + + + + + Gets the name to be used for the test + + + + + Gets the description of the test + + + + + Gets a value indicating whether this is ignored. + + true if ignored; otherwise, false. + + + + Gets a value indicating whether this is explicit. + + true if explicit; otherwise, false. + + + + Gets the ignore reason. + + The ignore reason. + + + + Gets a list of categories associated with this test. + + + + + Gets the property dictionary for this test + + + + + Provide the context information of the current test + + + + + Constructs a TestContext using the provided context dictionary + + A context dictionary + + + + Get the current test context. This is created + as needed. The user may save the context for + use within a test, but it should not be used + outside the test for which it is created. + + + + + Gets a TestAdapter representing the currently executing test in this context. + + + + + Gets a ResultAdapter representing the current result for the test + executing in this context. + + + + + Gets the directory containing the current test assembly. + + + + + Gets the directory to be used for outputing files created + by this test run. + + + + + TestAdapter adapts a Test for consumption by + the user test code. + + + + + Constructs a TestAdapter for this context + + The context dictionary + + + + The name of the test. + + + + + The FullName of the test + + + + + The properties of the test. + + + + + ResultAdapter adapts a TestResult for consumption by + the user test code. + + + + + Construct a ResultAdapter for a context + + The context holding the result + + + + The TestState of current test. This maps to the ResultState + used in nunit.core and is subject to change in the future. + + + + + The TestStatus of current test. This enum will be used + in future versions of NUnit and so is to be preferred + to the TestState value. + + + + + Provides details about a test + + + + + Creates an instance of TestDetails + + The fixture that the test is a member of, if available. + The method that implements the test, if available. + The full name of the test. + A string representing the type of test, e.g. "Test Case". + Indicates if the test represents a suite of tests. + + + + The fixture that the test is a member of, if available. + + + + + The method that implements the test, if available. + + + + + The full name of the test. + + + + + A string representing the type of test, e.g. "Test Case". + + + + + Indicates if the test represents a suite of tests. + + + + + The ResultState enum indicates the result of running a test + + + + + The result is inconclusive + + + + + The test was not runnable. + + + + + The test has been skipped. + + + + + The test has been ignored. + + + + + The test succeeded + + + + + The test failed + + + + + The test encountered an unexpected exception + + + + + The test was cancelled by the user + + + + + The TestStatus enum indicates the result of running a test + + + + + The test was inconclusive + + + + + The test has skipped + + + + + The test succeeded + + + + + The test failed + + + + + Helper class with static methods used to supply constraints + that operate on strings. + + + + + Returns a constraint that succeeds if the actual + value contains the substring supplied as an argument. + + + + + Returns a constraint that fails if the actual + value contains the substring supplied as an argument. + + + + + Returns a constraint that succeeds if the actual + value starts with the substring supplied as an argument. + + + + + Returns a constraint that fails if the actual + value starts with the substring supplied as an argument. + + + + + Returns a constraint that succeeds if the actual + value ends with the substring supplied as an argument. + + + + + Returns a constraint that fails if the actual + value ends with the substring supplied as an argument. + + + + + Returns a constraint that succeeds if the actual + value matches the Regex pattern supplied as an argument. + + + + + Returns a constraint that fails if the actual + value matches the pattern supplied as an argument. + + + + + Returns a ConstraintExpression, which will apply + the following constraint to all members of a collection, + succeeding if all of them succeed. + + + + + TextMessageWriter writes constraint descriptions and messages + in displayable form as a text stream. It tailors the display + of individual message components to form the standard message + format of NUnit assertion failure messages. + + + + + MessageWriter is the abstract base for classes that write + constraint descriptions and messages in some form. The + class has separate methods for writing various components + of a message, allowing implementations to tailor the + presentation as needed. + + + + + Construct a MessageWriter given a culture + + + + + Method to write single line message with optional args, usually + written to precede the general failure message. + + The message to be written + Any arguments used in formatting the message + + + + Method to write single line message with optional args, usually + written to precede the general failure message, at a givel + indentation level. + + The indentation level of the message + The message to be written + Any arguments used in formatting the message + + + + Display Expected and Actual lines for a constraint. This + is called by MessageWriter's default implementation of + WriteMessageTo and provides the generic two-line display. + + The constraint that failed + + + + Display Expected and Actual lines for given values. This + method may be called by constraints that need more control over + the display of actual and expected values than is provided + by the default implementation. + + The expected value + The actual value causing the failure + + + + Display Expected and Actual lines for given values, including + a tolerance value on the Expected line. + + The expected value + The actual value causing the failure + The tolerance within which the test was made + + + + Display the expected and actual string values on separate lines. + If the mismatch parameter is >=0, an additional line is displayed + line containing a caret that points to the mismatch point. + + The expected string value + The actual string value + The point at which the strings don't match or -1 + If true, case is ignored in locating the point where the strings differ + If true, the strings should be clipped to fit the line + + + + Writes the text for a connector. + + The connector. + + + + Writes the text for a predicate. + + The predicate. + + + + Writes the text for an expected value. + + The expected value. + + + + Writes the text for a modifier + + The modifier. + + + + Writes the text for an actual value. + + The actual value. + + + + Writes the text for a generalized value. + + The value. + + + + Writes the text for a collection value, + starting at a particular point, to a max length + + The collection containing elements to write. + The starting point of the elements to write + The maximum number of elements to write + + + + Abstract method to get the max line length + + + + + Prefix used for the expected value line of a message + + + + + Prefix used for the actual value line of a message + + + + + Length of a message prefix + + + + + Construct a TextMessageWriter + + + + + Construct a TextMessageWriter, specifying a user message + and optional formatting arguments. + + + + + + + Method to write single line message with optional args, usually + written to precede the general failure message, at a givel + indentation level. + + The indentation level of the message + The message to be written + Any arguments used in formatting the message + + + + Display Expected and Actual lines for a constraint. This + is called by MessageWriter's default implementation of + WriteMessageTo and provides the generic two-line display. + + The constraint that failed + + + + Display Expected and Actual lines for given values. This + method may be called by constraints that need more control over + the display of actual and expected values than is provided + by the default implementation. + + The expected value + The actual value causing the failure + + + + Display Expected and Actual lines for given values, including + a tolerance value on the expected line. + + The expected value + The actual value causing the failure + The tolerance within which the test was made + + + + Display the expected and actual string values on separate lines. + If the mismatch parameter is >=0, an additional line is displayed + line containing a caret that points to the mismatch point. + + The expected string value + The actual string value + The point at which the strings don't match or -1 + If true, case is ignored in string comparisons + If true, clip the strings to fit the max line length + + + + Writes the text for a connector. + + The connector. + + + + Writes the text for a predicate. + + The predicate. + + + + Write the text for a modifier. + + The modifier. + + + + Writes the text for an expected value. + + The expected value. + + + + Writes the text for an actual value. + + The actual value. + + + + Writes the text for a generalized value. + + The value. + + + + Writes the text for a collection value, + starting at a particular point, to a max length + + The collection containing elements to write. + The starting point of the elements to write + The maximum number of elements to write + + + + Write the generic 'Expected' line for a constraint + + The constraint that failed + + + + Write the generic 'Expected' line for a given value + + The expected value + + + + Write the generic 'Expected' line for a given value + and tolerance. + + The expected value + The tolerance within which the test was made + + + + Write the generic 'Actual' line for a constraint + + The constraint for which the actual value is to be written + + + + Write the generic 'Actual' line for a given value + + The actual value causing a failure + + + + Gets or sets the maximum line length for this writer + + + + + Helper class with properties and methods that supply + constraints that operate on exceptions. + + + + + Creates a constraint specifying the exact type of exception expected + + + + + Creates a constraint specifying the exact type of exception expected + + + + + Creates a constraint specifying the type of exception expected + + + + + Creates a constraint specifying the type of exception expected + + + + + Creates a constraint specifying an expected exception + + + + + Creates a constraint specifying an exception with a given InnerException + + + + + Creates a constraint specifying an expected TargetInvocationException + + + + + Creates a constraint specifying an expected TargetInvocationException + + + + + Creates a constraint specifying an expected TargetInvocationException + + + + + Creates a constraint specifying that no exception is thrown + + + + + Attribute used to apply a category to a test + + + + + The name of the category + + + + + Construct attribute for a given category based on + a name. The name may not contain the characters ',', + '+', '-' or '!'. However, this is not checked in the + constructor since it would cause an error to arise at + as the test was loaded without giving a clear indication + of where the problem is located. The error is handled + in NUnitFramework.cs by marking the test as not + runnable. + + The name of the category + + + + Protected constructor uses the Type name as the name + of the category. + + + + + The name of the category + + + + + Used to mark a field for use as a datapoint when executing a theory + within the same fixture that requires an argument of the field's Type. + + + + + Used to mark an array as containing a set of datapoints to be used + executing a theory within the same fixture that requires an argument + of the Type of the array elements. + + + + + Attribute used to provide descriptive text about a + test case or fixture. + + + + + Construct the attribute + + Text describing the test + + + + Gets the test description + + + + + Enumeration indicating how the expected message parameter is to be used + + + + Expect an exact match + + + Expect a message containing the parameter string + + + Match the regular expression provided as a parameter + + + Expect a message that starts with the parameter string + + + + ExpectedExceptionAttribute + + + + + + Constructor for a non-specific exception + + + + + Constructor for a given type of exception + + The type of the expected exception + + + + Constructor for a given exception name + + The full name of the expected exception + + + + Gets or sets the expected exception type + + + + + Gets or sets the full Type name of the expected exception + + + + + Gets or sets the expected message text + + + + + Gets or sets the user message displayed in case of failure + + + + + Gets or sets the type of match to be performed on the expected message + + + + + Gets the name of a method to be used as an exception handler + + + + + ExplicitAttribute marks a test or test fixture so that it will + only be run if explicitly executed from the gui or command line + or if it is included by use of a filter. The test will not be + run simply because an enclosing suite is run. + + + + + Default constructor + + + + + Constructor with a reason + + The reason test is marked explicit + + + + The reason test is marked explicit + + + + + Attribute used to mark a test that is to be ignored. + Ignored tests result in a warning message when the + tests are run. + + + + + Constructs the attribute without giving a reason + for ignoring the test. + + + + + Constructs the attribute giving a reason for ignoring the test + + The reason for ignoring the test + + + + The reason for ignoring a test + + + + + Abstract base for Attributes that are used to include tests + in the test run based on environmental settings. + + + + + Constructor with no included items specified, for use + with named property syntax. + + + + + Constructor taking one or more included items + + Comma-delimited list of included items + + + + Name of the item that is needed in order for + a test to run. Multiple itemss may be given, + separated by a comma. + + + + + Name of the item to be excluded. Multiple items + may be given, separated by a comma. + + + + + The reason for including or excluding the test + + + + + PlatformAttribute is used to mark a test fixture or an + individual method as applying to a particular platform only. + + + + + Constructor with no platforms specified, for use + with named property syntax. + + + + + Constructor taking one or more platforms + + Comma-deliminted list of platforms + + + + CultureAttribute is used to mark a test fixture or an + individual method as applying to a particular Culture only. + + + + + Constructor with no cultures specified, for use + with named property syntax. + + + + + Constructor taking one or more cultures + + Comma-deliminted list of cultures + + + + Marks a test to use a combinatorial join of any argument data + provided. NUnit will create a test case for every combination of + the arguments provided. This can result in a large number of test + cases and so should be used judiciously. This is the default join + type, so the attribute need not be used except as documentation. + + + + + PropertyAttribute is used to attach information to a test as a name/value pair.. + + + + + Construct a PropertyAttribute with a name and string value + + The name of the property + The property value + + + + Construct a PropertyAttribute with a name and int value + + The name of the property + The property value + + + + Construct a PropertyAttribute with a name and double value + + The name of the property + The property value + + + + Constructor for derived classes that set the + property dictionary directly. + + + + + Constructor for use by derived classes that use the + name of the type as the property name. Derived classes + must ensure that the Type of the property value is + a standard type supported by the BCL. Any custom + types will cause a serialization Exception when + in the client. + + + + + Gets the property dictionary for this attribute + + + + + Default constructor + + + + + Marks a test to use pairwise join of any argument data provided. + NUnit will attempt too excercise every pair of argument values at + least once, using as small a number of test cases as it can. With + only two arguments, this is the same as a combinatorial join. + + + + + Default constructor + + + + + Marks a test to use a sequential join of any argument data + provided. NUnit will use arguements for each parameter in + sequence, generating test cases up to the largest number + of argument values provided and using null for any arguments + for which it runs out of values. Normally, this should be + used with the same number of arguments for each parameter. + + + + + Default constructor + + + + + Summary description for MaxTimeAttribute. + + + + + Construct a MaxTimeAttribute, given a time in milliseconds. + + The maximum elapsed time in milliseconds + + + + RandomAttribute is used to supply a set of random values + to a single parameter of a parameterized test. + + + + + ValuesAttribute is used to provide literal arguments for + an individual parameter of a test. + + + + + Abstract base class for attributes that apply to parameters + and supply data for the parameter. + + + + + Gets the data to be provided to the specified parameter + + + + + The collection of data to be returned. Must + be set by any derived attribute classes. + We use an object[] so that the individual + elements may have their type changed in GetData + if necessary. + + + + + Construct with one argument + + + + + + Construct with two arguments + + + + + + + Construct with three arguments + + + + + + + + Construct with an array of arguments + + + + + + Get the collection of values to be used as arguments + + + + + Construct a set of doubles from 0.0 to 1.0, + specifying only the count. + + + + + + Construct a set of doubles from min to max + + + + + + + + Construct a set of ints from min to max + + + + + + + + Get the collection of values to be used as arguments + + + + + RangeAttribute is used to supply a range of values to an + individual parameter of a parameterized test. + + + + + Construct a range of ints using default step of 1 + + + + + + + Construct a range of ints specifying the step size + + + + + + + + Construct a range of longs + + + + + + + + Construct a range of doubles + + + + + + + + Construct a range of floats + + + + + + + + RepeatAttribute may be applied to test case in order + to run it multiple times. + + + + + Construct a RepeatAttribute + + The number of times to run the test + + + + RequiredAddinAttribute may be used to indicate the names of any addins + that must be present in order to run some or all of the tests in an + assembly. If the addin is not loaded, the entire assembly is marked + as NotRunnable. + + + + + Initializes a new instance of the class. + + The required addin. + + + + Gets the name of required addin. + + The required addin name. + + + + Summary description for SetCultureAttribute. + + + + + Construct given the name of a culture + + + + + + Summary description for SetUICultureAttribute. + + + + + Construct given the name of a culture + + + + + + SetUpAttribute is used in a TestFixture to identify a method + that is called immediately before each test is run. It is + also used in a SetUpFixture to identify the method that is + called once, before any of the subordinate tests are run. + + + + + Attribute used to mark a class that contains one-time SetUp + and/or TearDown methods that apply to all the tests in a + namespace or an assembly. + + + + + Attribute used to mark a static (shared in VB) property + that returns a list of tests. + + + + + Attribute used in a TestFixture to identify a method that is + called immediately after each test is run. It is also used + in a SetUpFixture to identify the method that is called once, + after all subordinate tests have run. In either case, the method + is guaranteed to be called, even if an exception is thrown. + + + + + Provide actions to execute before and after tests. + + + + + When implemented by an attribute, this interface implemented to provide actions to execute before and after tests. + + + + + Executed before each test is run + + Provides details about the test that is going to be run. + + + + Executed after each test is run + + Provides details about the test that has just been run. + + + + Provides the target for the action attribute + + The target for the action attribute + + + + Method called before each test + + Info about the test to be run + + + + Method called after each test + + Info about the test that was just run + + + + Gets or sets the ActionTargets for this attribute + + + + + Adding this attribute to a method within a + class makes the method callable from the NUnit test runner. There is a property + called Description which is optional which you can provide a more detailed test + description. This class cannot be inherited. + + + + [TestFixture] + public class Fixture + { + [Test] + public void MethodToTest() + {} + + [Test(Description = "more detailed description")] + publc void TestDescriptionMethod() + {} + } + + + + + + Descriptive text for this test + + + + + TestCaseAttribute is used to mark parameterized test cases + and provide them with their arguments. + + + + + Construct a TestCaseAttribute with a list of arguments. + This constructor is not CLS-Compliant + + + + + + Construct a TestCaseAttribute with a single argument + + + + + + Construct a TestCaseAttribute with a two arguments + + + + + + + Construct a TestCaseAttribute with a three arguments + + + + + + + + Gets the list of arguments to a test case + + + + + Gets or sets the expected result. Use + ExpectedResult by preference. + + The result. + + + + Gets or sets the expected result. + + The result. + + + + Gets a flag indicating whether an expected + result has been set. + + + + + Gets a list of categories associated with this test; + + + + + Gets or sets the category associated with this test. + May be a single category or a comma-separated list. + + + + + Gets or sets the expected exception. + + The expected exception. + + + + Gets or sets the name the expected exception. + + The expected name of the exception. + + + + Gets or sets the expected message of the expected exception + + The expected message of the exception. + + + + Gets or sets the type of match to be performed on the expected message + + + + + Gets or sets the description. + + The description. + + + + Gets or sets the name of the test. + + The name of the test. + + + + Gets or sets the ignored status of the test + + + + + Gets or sets the ignored status of the test + + + + + Gets or sets the explicit status of the test + + + + + Gets or sets the reason for not running the test + + + + + Gets or sets the reason for not running the test. + Set has the side effect of marking the test as ignored. + + The ignore reason. + + + + FactoryAttribute indicates the source to be used to + provide test cases for a test method. + + + + + Construct with the name of the data source, which must + be a property, field or method of the test class itself. + + An array of the names of the factories that will provide data + + + + Construct with a Type, which must implement IEnumerable + + The Type that will provide data + + + + Construct with a Type and name. + that don't support params arrays. + + The Type that will provide data + The name of the method, property or field that will provide data + + + + The name of a the method, property or fiend to be used as a source + + + + + A Type to be used as a source + + + + + Gets or sets the category associated with this test. + May be a single category or a comma-separated list. + + + + + [TestFixture] + public class ExampleClass + {} + + + + + Default constructor + + + + + Construct with a object[] representing a set of arguments. + In .NET 2.0, the arguments may later be separated into + type arguments and constructor arguments. + + + + + + Descriptive text for this fixture + + + + + Gets and sets the category for this fixture. + May be a comma-separated list of categories. + + + + + Gets a list of categories for this fixture + + + + + The arguments originally provided to the attribute + + + + + Gets or sets a value indicating whether this should be ignored. + + true if ignore; otherwise, false. + + + + Gets or sets the ignore reason. May set Ignored as a side effect. + + The ignore reason. + + + + Get or set the type arguments. If not set + explicitly, any leading arguments that are + Types are taken as type arguments. + + + + + Attribute used to identify a method that is + called before any tests in a fixture are run. + + + + + Attribute used to identify a method that is called after + all the tests in a fixture have run. The method is + guaranteed to be called, even if an exception is thrown. + + + + + Adding this attribute to a method within a + class makes the method callable from the NUnit test runner. There is a property + called Description which is optional which you can provide a more detailed test + description. This class cannot be inherited. + + + + [TestFixture] + public class Fixture + { + [Test] + public void MethodToTest() + {} + + [Test(Description = "more detailed description")] + publc void TestDescriptionMethod() + {} + } + + + + + + Used on a method, marks the test with a timeout value in milliseconds. + The test will be run in a separate thread and is cancelled if the timeout + is exceeded. Used on a method or assembly, sets the default timeout + for all contained test methods. + + + + + Construct a TimeoutAttribute given a time in milliseconds + + The timeout value in milliseconds + + + + Marks a test that must run in the STA, causing it + to run in a separate thread if necessary. + + On methods, you may also use STAThreadAttribute + to serve the same purpose. + + + + + Construct a RequiresSTAAttribute + + + + + Marks a test that must run in the MTA, causing it + to run in a separate thread if necessary. + + On methods, you may also use MTAThreadAttribute + to serve the same purpose. + + + + + Construct a RequiresMTAAttribute + + + + + Marks a test that must run on a separate thread. + + + + + Construct a RequiresThreadAttribute + + + + + Construct a RequiresThreadAttribute, specifying the apartment + + + + + ValueSourceAttribute indicates the source to be used to + provide data for one parameter of a test method. + + + + + Construct with the name of the factory - for use with languages + that don't support params arrays. + + The name of the data source to be used + + + + Construct with a Type and name - for use with languages + that don't support params arrays. + + The Type that will provide data + The name of the method, property or field that will provide data + + + + The name of a the method, property or fiend to be used as a source + + + + + A Type to be used as a source + + + + + AllItemsConstraint applies another constraint to each + item in a collection, succeeding if they all succeed. + + + + + Abstract base class used for prefixes + + + + + The Constraint class is the base of all built-in constraints + within NUnit. It provides the operator overloads used to combine + constraints. + + + + + The IConstraintExpression interface is implemented by all + complete and resolvable constraints and expressions. + + + + + Return the top-level constraint for this expression + + + + + + Static UnsetObject used to detect derived constraints + failing to set the actual value. + + + + + The actual value being tested against a constraint + + + + + The display name of this Constraint for use by ToString() + + + + + Argument fields used by ToString(); + + + + + The builder holding this constraint + + + + + Construct a constraint with no arguments + + + + + Construct a constraint with one argument + + + + + Construct a constraint with two arguments + + + + + Sets the ConstraintBuilder holding this constraint + + + + + Write the failure message to the MessageWriter provided + as an argument. The default implementation simply passes + the constraint and the actual value to the writer, which + then displays the constraint description and the value. + + Constraints that need to provide additional details, + such as where the error occured can override this. + + The MessageWriter on which to display the message + + + + Test whether the constraint is satisfied by a given value + + The value to be tested + True for success, false for failure + + + + Test whether the constraint is satisfied by an + ActualValueDelegate that returns the value to be tested. + The default implementation simply evaluates the delegate + but derived classes may override it to provide for delayed + processing. + + An + True for success, false for failure + + + + Test whether the constraint is satisfied by a given reference. + The default implementation simply dereferences the value but + derived classes may override it to provide for delayed processing. + + A reference to the value to be tested + True for success, false for failure + + + + Write the constraint description to a MessageWriter + + The writer on which the description is displayed + + + + Write the actual value for a failing constraint test to a + MessageWriter. The default implementation simply writes + the raw value of actual, leaving it to the writer to + perform any formatting. + + The writer on which the actual value is displayed + + + + Default override of ToString returns the constraint DisplayName + followed by any arguments within angle brackets. + + + + + + Returns the string representation of this constraint + + + + + This operator creates a constraint that is satisfied only if both + argument constraints are satisfied. + + + + + This operator creates a constraint that is satisfied if either + of the argument constraints is satisfied. + + + + + This operator creates a constraint that is satisfied if the + argument constraint is not satisfied. + + + + + Returns a DelayedConstraint with the specified delay time. + + The delay in milliseconds. + + + + + Returns a DelayedConstraint with the specified delay time + and polling interval. + + The delay in milliseconds. + The interval at which to test the constraint. + + + + + The display name of this Constraint for use by ToString(). + The default value is the name of the constraint with + trailing "Constraint" removed. Derived classes may set + this to another name in their constructors. + + + + + Returns a ConstraintExpression by appending And + to the current constraint. + + + + + Returns a ConstraintExpression by appending And + to the current constraint. + + + + + Returns a ConstraintExpression by appending Or + to the current constraint. + + + + + Class used to detect any derived constraints + that fail to set the actual value in their + Matches override. + + + + + The base constraint + + + + + Construct given a base constraint + + + + + + Construct an AllItemsConstraint on top of an existing constraint + + + + + + Apply the item constraint to each item in the collection, + failing if any item fails. + + + + + + + Write a description of this constraint to a MessageWriter + + + + + + AndConstraint succeeds only if both members succeed. + + + + + BinaryConstraint is the abstract base of all constraints + that combine two other constraints in some fashion. + + + + + The first constraint being combined + + + + + The second constraint being combined + + + + + Construct a BinaryConstraint from two other constraints + + The first constraint + The second constraint + + + + Create an AndConstraint from two other constraints + + The first constraint + The second constraint + + + + Apply both member constraints to an actual value, succeeding + succeeding only if both of them succeed. + + The actual value + True if the constraints both succeeded + + + + Write a description for this contraint to a MessageWriter + + The MessageWriter to receive the description + + + + Write the actual value for a failing constraint test to a + MessageWriter. The default implementation simply writes + the raw value of actual, leaving it to the writer to + perform any formatting. + + The writer on which the actual value is displayed + + + + AssignableFromConstraint is used to test that an object + can be assigned from a given Type. + + + + + TypeConstraint is the abstract base for constraints + that take a Type as their expected value. + + + + + The expected Type used by the constraint + + + + + Construct a TypeConstraint for a given Type + + + + + + Write the actual value for a failing constraint test to a + MessageWriter. TypeConstraints override this method to write + the name of the type. + + The writer on which the actual value is displayed + + + + Construct an AssignableFromConstraint for the type provided + + + + + + Test whether an object can be assigned from the specified type + + The object to be tested + True if the object can be assigned a value of the expected Type, otherwise false. + + + + Write a description of this constraint to a MessageWriter + + The MessageWriter to use + + + + AssignableToConstraint is used to test that an object + can be assigned to a given Type. + + + + + Construct an AssignableToConstraint for the type provided + + + + + + Test whether an object can be assigned to the specified type + + The object to be tested + True if the object can be assigned a value of the expected Type, otherwise false. + + + + Write a description of this constraint to a MessageWriter + + The MessageWriter to use + + + + AttributeConstraint tests that a specified attribute is present + on a Type or other provider and that the value of the attribute + satisfies some other constraint. + + + + + Constructs an AttributeConstraint for a specified attriute + Type and base constraint. + + + + + + + Determines whether the Type or other provider has the + expected attribute and if its value matches the + additional constraint specified. + + + + + Writes a description of the attribute to the specified writer. + + + + + Writes the actual value supplied to the specified writer. + + + + + Returns a string representation of the constraint. + + + + + AttributeExistsConstraint tests for the presence of a + specified attribute on a Type. + + + + + Constructs an AttributeExistsConstraint for a specific attribute Type + + + + + + Tests whether the object provides the expected attribute. + + A Type, MethodInfo, or other ICustomAttributeProvider + True if the expected attribute is present, otherwise false + + + + Writes the description of the constraint to the specified writer + + + + + BasicConstraint is the abstract base for constraints that + perform a simple comparison to a constant value. + + + + + Initializes a new instance of the class. + + The expected. + The description. + + + + Test whether the constraint is satisfied by a given value + + The value to be tested + True for success, false for failure + + + + Write the constraint description to a MessageWriter + + The writer on which the description is displayed + + + + BinarySerializableConstraint tests whether + an object is serializable in binary format. + + + + + Test whether the constraint is satisfied by a given value + + The value to be tested + True for success, false for failure + + + + Write the constraint description to a MessageWriter + + The writer on which the description is displayed + + + + Write the actual value for a failing constraint test to a + MessageWriter. The default implementation simply writes + the raw value of actual, leaving it to the writer to + perform any formatting. + + The writer on which the actual value is displayed + + + + Returns the string representation + + + + + CollectionConstraint is the abstract base class for + constraints that operate on collections. + + + + + Construct an empty CollectionConstraint + + + + + Construct a CollectionConstraint + + + + + + Determines whether the specified enumerable is empty. + + The enumerable. + + true if the specified enumerable is empty; otherwise, false. + + + + + Test whether the constraint is satisfied by a given value + + The value to be tested + True for success, false for failure + + + + Protected method to be implemented by derived classes + + + + + + + CollectionContainsConstraint is used to test whether a collection + contains an expected object as a member. + + + + + CollectionItemsEqualConstraint is the abstract base class for all + collection constraints that apply some notion of item equality + as a part of their operation. + + + + + Construct an empty CollectionConstraint + + + + + Construct a CollectionConstraint + + + + + + Flag the constraint to use the supplied EqualityAdapter. + NOTE: For internal use only. + + The EqualityAdapter to use. + Self. + + + + Flag the constraint to use the supplied IComparer object. + + The IComparer object to use. + Self. + + + + Flag the constraint to use the supplied IComparer object. + + The IComparer object to use. + Self. + + + + Flag the constraint to use the supplied Comparison object. + + The IComparer object to use. + Self. + + + + Flag the constraint to use the supplied IEqualityComparer object. + + The IComparer object to use. + Self. + + + + Flag the constraint to use the supplied IEqualityComparer object. + + The IComparer object to use. + Self. + + + + Compares two collection members for equality + + + + + Return a new CollectionTally for use in making tests + + The collection to be included in the tally + + + + Flag the constraint to ignore case and return self. + + + + + Construct a CollectionContainsConstraint + + + + + + Test whether the expected item is contained in the collection + + + + + + + Write a descripton of the constraint to a MessageWriter + + + + + + CollectionEquivalentCOnstraint is used to determine whether two + collections are equivalent. + + + + + Construct a CollectionEquivalentConstraint + + + + + + Test whether two collections are equivalent + + + + + + + Write a description of this constraint to a MessageWriter + + + + + + CollectionOrderedConstraint is used to test whether a collection is ordered. + + + + + Construct a CollectionOrderedConstraint + + + + + Modifies the constraint to use an IComparer and returns self. + + + + + Modifies the constraint to use an IComparer<T> and returns self. + + + + + Modifies the constraint to use a Comparison<T> and returns self. + + + + + Modifies the constraint to test ordering by the value of + a specified property and returns self. + + + + + Test whether the collection is ordered + + + + + + + Write a description of the constraint to a MessageWriter + + + + + + Returns the string representation of the constraint. + + + + + + If used performs a reverse comparison + + + + + CollectionSubsetConstraint is used to determine whether + one collection is a subset of another + + + + + Construct a CollectionSubsetConstraint + + The collection that the actual value is expected to be a subset of + + + + Test whether the actual collection is a subset of + the expected collection provided. + + + + + + + Write a description of this constraint to a MessageWriter + + + + + + CollectionTally counts (tallies) the number of + occurences of each object in one or more enumerations. + + + + + Construct a CollectionTally object from a comparer and a collection + + + + + Try to remove an object from the tally + + The object to remove + True if successful, false if the object was not found + + + + Try to remove a set of objects from the tally + + The objects to remove + True if successful, false if any object was not found + + + + The number of objects remaining in the tally + + + + + ComparisonAdapter class centralizes all comparisons of + values in NUnit, adapting to the use of any provided + IComparer, IComparer<T> or Comparison<T> + + + + + Returns a ComparisonAdapter that wraps an IComparer + + + + + Returns a ComparisonAdapter that wraps an IComparer<T> + + + + + Returns a ComparisonAdapter that wraps a Comparison<T> + + + + + Compares two objects + + + + + Gets the default ComparisonAdapter, which wraps an + NUnitComparer object. + + + + + Construct a ComparisonAdapter for an IComparer + + + + + Compares two objects + + + + + + + + Construct a default ComparisonAdapter + + + + + ComparisonAdapter<T> extends ComparisonAdapter and + allows use of an IComparer<T> or Comparison<T> + to actually perform the comparison. + + + + + Construct a ComparisonAdapter for an IComparer<T> + + + + + Compare a Type T to an object + + + + + Construct a ComparisonAdapter for a Comparison<T> + + + + + Compare a Type T to an object + + + + + Abstract base class for constraints that compare values to + determine if one is greater than, equal to or less than + the other. This class supplies the Using modifiers. + + + + + ComparisonAdapter to be used in making the comparison + + + + + Initializes a new instance of the class. + + + + + Initializes a new instance of the class. + + + + + Modifies the constraint to use an IComparer and returns self + + + + + Modifies the constraint to use an IComparer<T> and returns self + + + + + Modifies the constraint to use a Comparison<T> and returns self + + + + + Delegate used to delay evaluation of the actual value + to be used in evaluating a constraint + + + + + ConstraintBuilder maintains the stacks that are used in + processing a ConstraintExpression. An OperatorStack + is used to hold operators that are waiting for their + operands to be reognized. a ConstraintStack holds + input constraints as well as the results of each + operator applied. + + + + + Initializes a new instance of the class. + + + + + Appends the specified operator to the expression by first + reducing the operator stack and then pushing the new + operator on the stack. + + The operator to push. + + + + Appends the specified constraint to the expresson by pushing + it on the constraint stack. + + The constraint to push. + + + + Sets the top operator right context. + + The right context. + + + + Reduces the operator stack until the topmost item + precedence is greater than or equal to the target precedence. + + The target precedence. + + + + Resolves this instance, returning a Constraint. If the builder + is not currently in a resolvable state, an exception is thrown. + + The resolved constraint + + + + Gets a value indicating whether this instance is resolvable. + + + true if this instance is resolvable; otherwise, false. + + + + + OperatorStack is a type-safe stack for holding ConstraintOperators + + + + + Initializes a new instance of the class. + + The builder. + + + + Pushes the specified operator onto the stack. + + The op. + + + + Pops the topmost operator from the stack. + + + + + + Gets a value indicating whether this is empty. + + true if empty; otherwise, false. + + + + Gets the topmost operator without modifying the stack. + + The top. + + + + ConstraintStack is a type-safe stack for holding Constraints + + + + + Initializes a new instance of the class. + + The builder. + + + + Pushes the specified constraint. As a side effect, + the constraint's builder field is set to the + ConstraintBuilder owning this stack. + + The constraint. + + + + Pops this topmost constrait from the stack. + As a side effect, the constraint's builder + field is set to null. + + + + + + Gets a value indicating whether this is empty. + + true if empty; otherwise, false. + + + + Gets the topmost constraint without modifying the stack. + + The topmost constraint + + + + ConstraintExpression represents a compound constraint in the + process of being constructed from a series of syntactic elements. + + Individual elements are appended to the expression as they are + reognized. Once an actual Constraint is appended, the expression + returns a resolvable Constraint. + + + + + ConstraintExpressionBase is the abstract base class for the + ConstraintExpression class, which represents a + compound constraint in the process of being constructed + from a series of syntactic elements. + + NOTE: ConstraintExpressionBase is separate because the + ConstraintExpression class was generated in earlier + versions of NUnit. The two classes may be combined + in a future version. + + + + + The ConstraintBuilder holding the elements recognized so far + + + + + Initializes a new instance of the class. + + + + + Initializes a new instance of the + class passing in a ConstraintBuilder, which may be pre-populated. + + The builder. + + + + Returns a string representation of the expression as it + currently stands. This should only be used for testing, + since it has the side-effect of resolving the expression. + + + + + + Appends an operator to the expression and returns the + resulting expression itself. + + + + + Appends a self-resolving operator to the expression and + returns a new ResolvableConstraintExpression. + + + + + Appends a constraint to the expression and returns that + constraint, which is associated with the current state + of the expression being built. + + + + + Initializes a new instance of the class. + + + + + Initializes a new instance of the + class passing in a ConstraintBuilder, which may be pre-populated. + + The builder. + + + + Returns a ConstraintExpression, which will apply + the following constraint to all members of a collection, + succeeding only if a specified number of them succeed. + + + + + Returns a new PropertyConstraintExpression, which will either + test for the existence of the named property on the object + being tested or apply any following constraint to that property. + + + + + Returns a new AttributeConstraint checking for the + presence of a particular attribute on an object. + + + + + Returns a new AttributeConstraint checking for the + presence of a particular attribute on an object. + + + + + Returns the constraint provided as an argument - used to allow custom + custom constraints to easily participate in the syntax. + + + + + Returns the constraint provided as an argument - used to allow custom + custom constraints to easily participate in the syntax. + + + + + Returns a constraint that tests two items for equality + + + + + Returns a constraint that tests that two references are the same object + + + + + Returns a constraint that tests whether the + actual value is greater than the suppled argument + + + + + Returns a constraint that tests whether the + actual value is greater than or equal to the suppled argument + + + + + Returns a constraint that tests whether the + actual value is greater than or equal to the suppled argument + + + + + Returns a constraint that tests whether the + actual value is less than the suppled argument + + + + + Returns a constraint that tests whether the + actual value is less than or equal to the suppled argument + + + + + Returns a constraint that tests whether the + actual value is less than or equal to the suppled argument + + + + + Returns a constraint that tests whether the actual + value is of the exact type supplied as an argument. + + + + + Returns a constraint that tests whether the actual + value is of the exact type supplied as an argument. + + + + + Returns a constraint that tests whether the actual value + is of the type supplied as an argument or a derived type. + + + + + Returns a constraint that tests whether the actual value + is of the type supplied as an argument or a derived type. + + + + + Returns a constraint that tests whether the actual value + is of the type supplied as an argument or a derived type. + + + + + Returns a constraint that tests whether the actual value + is of the type supplied as an argument or a derived type. + + + + + Returns a constraint that tests whether the actual value + is assignable from the type supplied as an argument. + + + + + Returns a constraint that tests whether the actual value + is assignable from the type supplied as an argument. + + + + + Returns a constraint that tests whether the actual value + is assignable from the type supplied as an argument. + + + + + Returns a constraint that tests whether the actual value + is assignable from the type supplied as an argument. + + + + + Returns a constraint that tests whether the actual value + is a collection containing the same elements as the + collection supplied as an argument. + + + + + Returns a constraint that tests whether the actual value + is a subset of the collection supplied as an argument. + + + + + Returns a new CollectionContainsConstraint checking for the + presence of a particular object in the collection. + + + + + Returns a new CollectionContainsConstraint checking for the + presence of a particular object in the collection. + + + + + Returns a new ContainsConstraint. This constraint + will, in turn, make use of the appropriate second-level + constraint, depending on the type of the actual argument. + This overload is only used if the item sought is a string, + since any other type implies that we are looking for a + collection member. + + + + + Returns a constraint that succeeds if the actual + value contains the substring supplied as an argument. + + + + + Returns a constraint that succeeds if the actual + value contains the substring supplied as an argument. + + + + + Returns a constraint that succeeds if the actual + value starts with the substring supplied as an argument. + + + + + Returns a constraint that succeeds if the actual + value starts with the substring supplied as an argument. + + + + + Returns a constraint that succeeds if the actual + value ends with the substring supplied as an argument. + + + + + Returns a constraint that succeeds if the actual + value ends with the substring supplied as an argument. + + + + + Returns a constraint that succeeds if the actual + value matches the regular expression supplied as an argument. + + + + + Returns a constraint that succeeds if the actual + value matches the regular expression supplied as an argument. + + + + + Returns a constraint that tests whether the path provided + is the same as an expected path after canonicalization. + + + + + Returns a constraint that tests whether the path provided + is the same path or under an expected path after canonicalization. + + + + + Returns a constraint that tests whether the path provided + is the same path or under an expected path after canonicalization. + + + + + Returns a constraint that tests whether the actual value falls + within a specified range. + + + + + Returns a ConstraintExpression that negates any + following constraint. + + + + + Returns a ConstraintExpression that negates any + following constraint. + + + + + Returns a ConstraintExpression, which will apply + the following constraint to all members of a collection, + succeeding if all of them succeed. + + + + + Returns a ConstraintExpression, which will apply + the following constraint to all members of a collection, + succeeding if at least one of them succeeds. + + + + + Returns a ConstraintExpression, which will apply + the following constraint to all members of a collection, + succeeding if all of them fail. + + + + + Returns a new ConstraintExpression, which will apply the following + constraint to the Length property of the object being tested. + + + + + Returns a new ConstraintExpression, which will apply the following + constraint to the Count property of the object being tested. + + + + + Returns a new ConstraintExpression, which will apply the following + constraint to the Message property of the object being tested. + + + + + Returns a new ConstraintExpression, which will apply the following + constraint to the InnerException property of the object being tested. + + + + + With is currently a NOP - reserved for future use. + + + + + Returns a constraint that tests for null + + + + + Returns a constraint that tests for True + + + + + Returns a constraint that tests for False + + + + + Returns a constraint that tests for a positive value + + + + + Returns a constraint that tests for a negative value + + + + + Returns a constraint that tests for NaN + + + + + Returns a constraint that tests for empty + + + + + Returns a constraint that tests whether a collection + contains all unique items. + + + + + Returns a constraint that tests whether an object graph is serializable in binary format. + + + + + Returns a constraint that tests whether an object graph is serializable in xml format. + + + + + Returns a constraint that tests whether a collection is ordered + + + + + ContainsConstraint tests a whether a string contains a substring + or a collection contains an object. It postpones the decision of + which test to use until the type of the actual argument is known. + This allows testing whether a string is contained in a collection + or as a substring of another string using the same syntax. + + + + + Initializes a new instance of the class. + + The expected. + + + + Test whether the constraint is satisfied by a given value + + The value to be tested + True for success, false for failure + + + + Write the constraint description to a MessageWriter + + The writer on which the description is displayed + + + + Flag the constraint to use the supplied IComparer object. + + The IComparer object to use. + Self. + + + + Flag the constraint to use the supplied IComparer object. + + The IComparer object to use. + Self. + + + + Flag the constraint to use the supplied Comparison object. + + The IComparer object to use. + Self. + + + + Flag the constraint to use the supplied IEqualityComparer object. + + The IComparer object to use. + Self. + + + + Flag the constraint to use the supplied IEqualityComparer object. + + The IComparer object to use. + Self. + + + + Flag the constraint to ignore case and return self. + + + + + Applies a delay to the match so that a match can be evaluated in the future. + + + + + Creates a new DelayedConstraint + + The inner constraint two decorate + The time interval after which the match is performed + If the value of is less than 0 + + + + Creates a new DelayedConstraint + + The inner constraint two decorate + The time interval after which the match is performed + The time interval used for polling + If the value of is less than 0 + + + + Test whether the constraint is satisfied by a given value + + The value to be tested + True for if the base constraint fails, false if it succeeds + + + + Test whether the constraint is satisfied by a delegate + + The delegate whose value is to be tested + True for if the base constraint fails, false if it succeeds + + + + Test whether the constraint is satisfied by a given reference. + Overridden to wait for the specified delay period before + calling the base constraint with the dereferenced value. + + A reference to the value to be tested + True for success, false for failure + + + + Write the constraint description to a MessageWriter + + The writer on which the description is displayed + + + + Write the actual value for a failing constraint test to a MessageWriter. + + The writer on which the actual value is displayed + + + + Returns the string representation of the constraint. + + + + + EmptyCollectionConstraint tests whether a collection is empty. + + + + + Check that the collection is empty + + + + + + + Write the constraint description to a MessageWriter + + + + + + EmptyConstraint tests a whether a string or collection is empty, + postponing the decision about which test is applied until the + type of the actual argument is known. + + + + + Test whether the constraint is satisfied by a given value + + The value to be tested + True for success, false for failure + + + + Write the constraint description to a MessageWriter + + The writer on which the description is displayed + + + + EmptyDirectoryConstraint is used to test that a directory is empty + + + + + Test whether the constraint is satisfied by a given value + + The value to be tested + True for success, false for failure + + + + Write the constraint description to a MessageWriter + + The writer on which the description is displayed + + + + Write the actual value for a failing constraint test to a + MessageWriter. The default implementation simply writes + the raw value of actual, leaving it to the writer to + perform any formatting. + + The writer on which the actual value is displayed + + + + EmptyStringConstraint tests whether a string is empty. + + + + + Test whether the constraint is satisfied by a given value + + The value to be tested + True for success, false for failure + + + + Write the constraint description to a MessageWriter + + The writer on which the description is displayed + + + + EndsWithConstraint can test whether a string ends + with an expected substring. + + + + + StringConstraint is the abstract base for constraints + that operate on strings. It supports the IgnoreCase + modifier for string operations. + + + + + The expected value + + + + + Indicates whether tests should be case-insensitive + + + + + Constructs a StringConstraint given an expected value + + The expected value + + + + Test whether the constraint is satisfied by a given value + + The value to be tested + True for success, false for failure + + + + Test whether the constraint is satisfied by a given string + + The string to be tested + True for success, false for failure + + + + Modify the constraint to ignore case in matching. + + + + + Initializes a new instance of the class. + + The expected string + + + + Test whether the constraint is matched by the actual value. + This is a template method, which calls the IsMatch method + of the derived class. + + + + + + + Write the constraint description to a MessageWriter + + The writer on which the description is displayed + + + + EqualConstraint is able to compare an actual value with the + expected value provided in its constructor. Two objects are + considered equal if both are null, or if both have the same + value. NUnit has special semantics for some object types. + + + + + If true, strings in error messages will be clipped + + + + + NUnitEqualityComparer used to test equality. + + + + + Initializes a new instance of the class. + + The expected value. + + + + Flag the constraint to use a tolerance when determining equality. + + Tolerance value to be used + Self. + + + + Flag the constraint to use the supplied IComparer object. + + The IComparer object to use. + Self. + + + + Flag the constraint to use the supplied IComparer object. + + The IComparer object to use. + Self. + + + + Flag the constraint to use the supplied IComparer object. + + The IComparer object to use. + Self. + + + + Flag the constraint to use the supplied Comparison object. + + The IComparer object to use. + Self. + + + + Flag the constraint to use the supplied IEqualityComparer object. + + The IComparer object to use. + Self. + + + + Flag the constraint to use the supplied IEqualityComparer object. + + The IComparer object to use. + Self. + + + + Test whether the constraint is satisfied by a given value + + The value to be tested + True for success, false for failure + + + + Write a failure message. Overridden to provide custom + failure messages for EqualConstraint. + + The MessageWriter to write to + + + + Write description of this constraint + + The MessageWriter to write to + + + + Display the failure information for two collections that did not match. + + The MessageWriter on which to display + The expected collection. + The actual collection + The depth of this failure in a set of nested collections + + + + Displays a single line showing the types and sizes of the expected + and actual enumerations, collections or arrays. If both are identical, + the value is only shown once. + + The MessageWriter on which to display + The expected collection or array + The actual collection or array + The indentation level for the message line + + + + Displays a single line showing the point in the expected and actual + arrays at which the comparison failed. If the arrays have different + structures or dimensions, both values are shown. + + The MessageWriter on which to display + The expected array + The actual array + Index of the failure point in the underlying collections + The indentation level for the message line + + + + Display the failure information for two IEnumerables that did not match. + + The MessageWriter on which to display + The expected enumeration. + The actual enumeration + The depth of this failure in a set of nested collections + + + + Flag the constraint to ignore case and return self. + + + + + Flag the constraint to suppress string clipping + and return self. + + + + + Flag the constraint to compare arrays as collections + and return self. + + + + + Switches the .Within() modifier to interpret its tolerance as + a distance in representable values (see remarks). + + Self. + + Ulp stands for "unit in the last place" and describes the minimum + amount a given value can change. For any integers, an ulp is 1 whole + digit. For floating point values, the accuracy of which is better + for smaller numbers and worse for larger numbers, an ulp depends + on the size of the number. Using ulps for comparison of floating + point results instead of fixed tolerances is safer because it will + automatically compensate for the added inaccuracy of larger numbers. + + + + + Switches the .Within() modifier to interpret its tolerance as + a percentage that the actual values is allowed to deviate from + the expected value. + + Self + + + + Causes the tolerance to be interpreted as a TimeSpan in days. + + Self + + + + Causes the tolerance to be interpreted as a TimeSpan in hours. + + Self + + + + Causes the tolerance to be interpreted as a TimeSpan in minutes. + + Self + + + + Causes the tolerance to be interpreted as a TimeSpan in seconds. + + Self + + + + Causes the tolerance to be interpreted as a TimeSpan in milliseconds. + + Self + + + + Causes the tolerance to be interpreted as a TimeSpan in clock ticks. + + Self + + + + EqualityAdapter class handles all equality comparisons + that use an IEqualityComparer, IEqualityComparer<T> + or a ComparisonAdapter. + + + + + Compares two objects, returning true if they are equal + + + + + Returns true if the two objects can be compared by this adapter. + The base adapter cannot handle IEnumerables except for strings. + + + + + Returns an EqualityAdapter that wraps an IComparer. + + + + + Returns an EqualityAdapter that wraps an IEqualityComparer. + + + + + Returns an EqualityAdapter that wraps an IEqualityComparer<T>. + + + + + Returns an EqualityAdapter that wraps an IComparer<T>. + + + + + Returns an EqualityAdapter that wraps a Comparison<T>. + + + + + EqualityAdapter that wraps an IComparer. + + + + + Returns true if the two objects can be compared by this adapter. + Generic adapter requires objects of the specified type. + + + + + EqualityAdapter that wraps an IComparer. + + + + + EqualityAdapterList represents a list of EqualityAdapters + in a common class across platforms. + + + + + ExactCountConstraint applies another constraint to each + item in a collection, succeeding only if a specified + number of items succeed. + + + + + Construct an ExactCountConstraint on top of an existing constraint + + + + + + + Apply the item constraint to each item in the collection, + succeeding only if the expected number of items pass. + + + + + + + Write a description of this constraint to a MessageWriter + + + + + + ExactTypeConstraint is used to test that an object + is of the exact type provided in the constructor + + + + + Construct an ExactTypeConstraint for a given Type + + The expected Type. + + + + Test that an object is of the exact type specified + + The actual value. + True if the tested object is of the exact type provided, otherwise false. + + + + Write the description of this constraint to a MessageWriter + + The MessageWriter to use + + + + ExceptionTypeConstraint is a special version of ExactTypeConstraint + used to provided detailed info about the exception thrown in + an error message. + + + + + Constructs an ExceptionTypeConstraint + + + + + Write the actual value for a failing constraint test to a + MessageWriter. Overriden to write additional information + in the case of an Exception. + + The MessageWriter to use + + + + FailurePoint class represents one point of failure + in an equality test. + + + + + The location of the failure + + + + + The expected value + + + + + The actual value + + + + + Indicates whether the expected value is valid + + + + + Indicates whether the actual value is valid + + + + + FailurePointList represents a set of FailurePoints + in a cross-platform way. + + + + + FalseConstraint tests that the actual value is false + + + + + Initializes a new instance of the class. + + + + Helper routines for working with floating point numbers + + + The floating point comparison code is based on this excellent article: + http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm + + + "ULP" means Unit in the Last Place and in the context of this library refers to + the distance between two adjacent floating point numbers. IEEE floating point + numbers can only represent a finite subset of natural numbers, with greater + accuracy for smaller numbers and lower accuracy for very large numbers. + + + If a comparison is allowed "2 ulps" of deviation, that means the values are + allowed to deviate by up to 2 adjacent floating point values, which might be + as low as 0.0000001 for small numbers or as high as 10.0 for large numbers. + + + + + Compares two floating point values for equality + First floating point value to be compared + Second floating point value t be compared + + Maximum number of representable floating point values that are allowed to + be between the left and the right floating point values + + True if both numbers are equal or close to being equal + + + Floating point values can only represent a finite subset of natural numbers. + For example, the values 2.00000000 and 2.00000024 can be stored in a float, + but nothing inbetween them. + + + This comparison will count how many possible floating point values are between + the left and the right number. If the number of possible values between both + numbers is less than or equal to maxUlps, then the numbers are considered as + being equal. + + + Implementation partially follows the code outlined here: + http://www.anttirt.net/2007/08/19/proper-floating-point-comparisons/ + + + + + Compares two double precision floating point values for equality + First double precision floating point value to be compared + Second double precision floating point value t be compared + + Maximum number of representable double precision floating point values that are + allowed to be between the left and the right double precision floating point values + + True if both numbers are equal or close to being equal + + + Double precision floating point values can only represent a limited series of + natural numbers. For example, the values 2.0000000000000000 and 2.0000000000000004 + can be stored in a double, but nothing inbetween them. + + + This comparison will count how many possible double precision floating point + values are between the left and the right number. If the number of possible + values between both numbers is less than or equal to maxUlps, then the numbers + are considered as being equal. + + + Implementation partially follows the code outlined here: + http://www.anttirt.net/2007/08/19/proper-floating-point-comparisons/ + + + + + + Reinterprets the memory contents of a floating point value as an integer value + + + Floating point value whose memory contents to reinterpret + + + The memory contents of the floating point value interpreted as an integer + + + + + Reinterprets the memory contents of a double precision floating point + value as an integer value + + + Double precision floating point value whose memory contents to reinterpret + + + The memory contents of the double precision floating point value + interpreted as an integer + + + + + Reinterprets the memory contents of an integer as a floating point value + + Integer value whose memory contents to reinterpret + + The memory contents of the integer value interpreted as a floating point value + + + + + Reinterprets the memory contents of an integer value as a double precision + floating point value + + Integer whose memory contents to reinterpret + + The memory contents of the integer interpreted as a double precision + floating point value + + + + Union of a floating point variable and an integer + + + The union's value as a floating point variable + + + The union's value as an integer + + + The union's value as an unsigned integer + + + Union of a double precision floating point variable and a long + + + The union's value as a double precision floating point variable + + + The union's value as a long + + + The union's value as an unsigned long + + + + Tests whether a value is greater than the value supplied to its constructor + + + + + The value against which a comparison is to be made + + + + + Initializes a new instance of the class. + + The expected value. + + + + Write the constraint description to a MessageWriter + + The writer on which the description is displayed + + + + Test whether the constraint is satisfied by a given value + + The value to be tested + True for success, false for failure + + + + Tests whether a value is greater than or equal to the value supplied to its constructor + + + + + The value against which a comparison is to be made + + + + + Initializes a new instance of the class. + + The expected value. + + + + Write the constraint description to a MessageWriter + + The writer on which the description is displayed + + + + Test whether the constraint is satisfied by a given value + + The value to be tested + True for success, false for failure + + + + InstanceOfTypeConstraint is used to test that an object + is of the same type provided or derived from it. + + + + + Construct an InstanceOfTypeConstraint for the type provided + + The expected Type + + + + Test whether an object is of the specified type or a derived type + + The object to be tested + True if the object is of the provided type or derives from it, otherwise false. + + + + Write a description of this constraint to a MessageWriter + + The MessageWriter to use + + + + Tests whether a value is less than the value supplied to its constructor + + + + + The value against which a comparison is to be made + + + + + Initializes a new instance of the class. + + The expected value. + + + + Write the constraint description to a MessageWriter + + The writer on which the description is displayed + + + + Test whether the constraint is satisfied by a given value + + The value to be tested + True for success, false for failure + + + + Tests whether a value is less than or equal to the value supplied to its constructor + + + + + The value against which a comparison is to be made + + + + + Initializes a new instance of the class. + + The expected value. + + + + Write the constraint description to a MessageWriter + + The writer on which the description is displayed + + + + Test whether the constraint is satisfied by a given value + + The value to be tested + True for success, false for failure + + + + Static methods used in creating messages + + + + + Static string used when strings are clipped + + + + + Returns the representation of a type as used in NUnitLite. + This is the same as Type.ToString() except for arrays, + which are displayed with their declared sizes. + + + + + + + Converts any control characters in a string + to their escaped representation. + + The string to be converted + The converted string + + + + Return the a string representation for a set of indices into an array + + Array of indices for which a string is needed + + + + Get an array of indices representing the point in a enumerable, + collection or array corresponding to a single int index into the + collection. + + The collection to which the indices apply + Index in the collection + Array of indices + + + + Clip a string to a given length, starting at a particular offset, returning the clipped + string with ellipses representing the removed parts + + The string to be clipped + The maximum permitted length of the result string + The point at which to start clipping + The clipped string + + + + Clip the expected and actual strings in a coordinated fashion, + so that they may be displayed together. + + + + + + + + + Shows the position two strings start to differ. Comparison + starts at the start index. + + The expected string + The actual string + The index in the strings at which comparison should start + Boolean indicating whether case should be ignored + -1 if no mismatch found, or the index where mismatch found + + + + NaNConstraint tests that the actual value is a double or float NaN + + + + + Test that the actual value is an NaN + + + + + + + Write the constraint description to a specified writer + + + + + + NoItemConstraint applies another constraint to each + item in a collection, failing if any of them succeeds. + + + + + Construct a NoItemConstraint on top of an existing constraint + + + + + + Apply the item constraint to each item in the collection, + failing if any item fails. + + + + + + + Write a description of this constraint to a MessageWriter + + + + + + NotConstraint negates the effect of some other constraint + + + + + Initializes a new instance of the class. + + The base constraint to be negated. + + + + Test whether the constraint is satisfied by a given value + + The value to be tested + True for if the base constraint fails, false if it succeeds + + + + Write the constraint description to a MessageWriter + + The writer on which the description is displayed + + + + Write the actual value for a failing constraint test to a MessageWriter. + + The writer on which the actual value is displayed + + + + NullConstraint tests that the actual value is null + + + + + Initializes a new instance of the class. + + + + + NullEmptyStringConstraint tests whether a string is either null or empty. + + + + + Constructs a new NullOrEmptyStringConstraint + + + + + Test whether the constraint is satisfied by a given value + + The value to be tested + True for success, false for failure + + + + Write the constraint description to a MessageWriter + + The writer on which the description is displayed + + + + The Numerics class contains common operations on numeric values. + + + + + Checks the type of the object, returning true if + the object is a numeric type. + + The object to check + true if the object is a numeric type + + + + Checks the type of the object, returning true if + the object is a floating point numeric type. + + The object to check + true if the object is a floating point numeric type + + + + Checks the type of the object, returning true if + the object is a fixed point numeric type. + + The object to check + true if the object is a fixed point numeric type + + + + Test two numeric values for equality, performing the usual numeric + conversions and using a provided or default tolerance. If the tolerance + provided is Empty, this method may set it to a default tolerance. + + The expected value + The actual value + A reference to the tolerance in effect + True if the values are equal + + + + Compare two numeric values, performing the usual numeric conversions. + + The expected value + The actual value + The relationship of the values to each other + + + + NUnitComparer encapsulates NUnit's default behavior + in comparing two objects. + + + + + Compares two objects + + + + + + + + Returns the default NUnitComparer. + + + + + Generic version of NUnitComparer + + + + + + Compare two objects of the same type + + + + + NUnitEqualityComparer encapsulates NUnit's handling of + equality tests between objects. + + + + + + + + + + Compares two objects for equality within a tolerance + + The first object to compare + The second object to compare + The tolerance to use in the comparison + + + + + If true, all string comparisons will ignore case + + + + + If true, arrays will be treated as collections, allowing + those of different dimensions to be compared + + + + + Comparison objects used in comparisons for some constraints. + + + + + List of points at which a failure occured. + + + + + RecursionDetector used to check for recursion when + evaluating self-referencing enumerables. + + + + + Compares two objects for equality within a tolerance, setting + the tolerance to the actual tolerance used if an empty + tolerance is supplied. + + + + + Helper method to compare two arrays + + + + + Method to compare two DirectoryInfo objects + + first directory to compare + second directory to compare + true if equivalent, false if not + + + + Returns the default NUnitEqualityComparer + + + + + Gets and sets a flag indicating whether case should + be ignored in determining equality. + + + + + Gets and sets a flag indicating that arrays should be + compared as collections, without regard to their shape. + + + + + Gets the list of external comparers to be used to + test for equality. They are applied to members of + collections, in place of NUnit's own logic. + + + + + Gets the list of failure points for the last Match performed. + The list consists of objects to be interpreted by the caller. + This generally means that the caller may only make use of + objects it has placed on the list at a particular depthy. + + + + + RecursionDetector detects when a comparison + between two enumerables has reached a point + where the same objects that were previously + compared are again being compared. This allows + the caller to stop the comparison if desired. + + + + + Check whether two objects have previously + been compared, returning true if they have. + The two objects are remembered, so that a + second call will always return true. + + + + + OrConstraint succeeds if either member succeeds + + + + + Create an OrConstraint from two other constraints + + The first constraint + The second constraint + + + + Apply the member constraints to an actual value, succeeding + succeeding as soon as one of them succeeds. + + The actual value + True if either constraint succeeded + + + + Write a description for this contraint to a MessageWriter + + The MessageWriter to receive the description + + + + PathConstraint serves as the abstract base of constraints + that operate on paths and provides several helper methods. + + + + + The expected path used in the constraint + + + + + Flag indicating whether a caseInsensitive comparison should be made + + + + + Construct a PathConstraint for a give expected path + + The expected path + + + + Test whether the constraint is satisfied by a given value + + The value to be tested + True for success, false for failure + + + + Returns true if the expected path and actual path match + + + + + Returns the string representation of this constraint + + + + + Transform the provided path to its canonical form so that it + may be more easily be compared with other paths. + + The original path + The path in canonical form + + + + Test whether one path in canonical form is under another. + + The first path - supposed to be the parent path + The second path - supposed to be the child path + Indicates whether case should be ignored + + + + + Modifies the current instance to be case-insensitve + and returns it. + + + + + Modifies the current instance to be case-sensitve + and returns it. + + + + + Predicate constraint wraps a Predicate in a constraint, + returning success if the predicate is true. + + + + + Construct a PredicateConstraint from a predicate + + + + + Determines whether the predicate succeeds when applied + to the actual value. + + + + + Writes the description to a MessageWriter + + + + + PropertyConstraint extracts a named property and uses + its value as the actual value for a chained constraint. + + + + + Initializes a new instance of the class. + + The name. + The constraint to apply to the property. + + + + Test whether the constraint is satisfied by a given value + + The value to be tested + True for success, false for failure + + + + Write the constraint description to a MessageWriter + + The writer on which the description is displayed + + + + Write the actual value for a failing constraint test to a + MessageWriter. The default implementation simply writes + the raw value of actual, leaving it to the writer to + perform any formatting. + + The writer on which the actual value is displayed + + + + Returns the string representation of the constraint. + + + + + + PropertyExistsConstraint tests that a named property + exists on the object provided through Match. + + Originally, PropertyConstraint provided this feature + in addition to making optional tests on the vaue + of the property. The two constraints are now separate. + + + + + Initializes a new instance of the class. + + The name of the property. + + + + Test whether the property exists for a given object + + The object to be tested + True for success, false for failure + + + + Write the constraint description to a MessageWriter + + The writer on which the description is displayed + + + + Write the actual value for a failing constraint test to a + MessageWriter. + + The writer on which the actual value is displayed + + + + Returns the string representation of the constraint. + + + + + + RangeConstraint tests whether two values are within a + specified range. + + + + + Initializes a new instance of the class. + + From. + To. + + + + Test whether the constraint is satisfied by a given value + + The value to be tested + True for success, false for failure + + + + Write the constraint description to a MessageWriter + + The writer on which the description is displayed + + + + RegexConstraint can test whether a string matches + the pattern provided. + + + + + Initializes a new instance of the class. + + The pattern. + + + + Test whether the constraint is satisfied by a given value + + The value to be tested + True for success, false for failure + + + + Write the constraint description to a MessageWriter + + The writer on which the description is displayed + + + + ResolvableConstraintExpression is used to represent a compound + constraint being constructed at a point where the last operator + may either terminate the expression or may have additional + qualifying constraints added to it. + + It is used, for example, for a Property element or for + an Exception element, either of which may be optionally + followed by constraints that apply to the property or + exception. + + + + + Create a new instance of ResolvableConstraintExpression + + + + + Create a new instance of ResolvableConstraintExpression, + passing in a pre-populated ConstraintBuilder. + + + + + Resolve the current expression to a Constraint + + + + + This operator creates a constraint that is satisfied only if both + argument constraints are satisfied. + + + + + This operator creates a constraint that is satisfied only if both + argument constraints are satisfied. + + + + + This operator creates a constraint that is satisfied only if both + argument constraints are satisfied. + + + + + This operator creates a constraint that is satisfied if either + of the argument constraints is satisfied. + + + + + This operator creates a constraint that is satisfied if either + of the argument constraints is satisfied. + + + + + This operator creates a constraint that is satisfied if either + of the argument constraints is satisfied. + + + + + This operator creates a constraint that is satisfied if the + argument constraint is not satisfied. + + + + + Appends an And Operator to the expression + + + + + Appends an Or operator to the expression. + + + + + ReusableConstraint wraps a constraint expression after + resolving it so that it can be reused consistently. + + + + + Construct a ReusableConstraint from a constraint expression + + The expression to be resolved and reused + + + + Converts a constraint to a ReusableConstraint + + The constraint to be converted + A ReusableConstraint + + + + Returns the string representation of the constraint. + + A string representing the constraint + + + + Resolves the ReusableConstraint by returning the constraint + that it originally wrapped. + + A resolved constraint + + + + SameAsConstraint tests whether an object is identical to + the object passed to its constructor + + + + + Initializes a new instance of the class. + + The expected object. + + + + Test whether the constraint is satisfied by a given value + + The value to be tested + True for success, false for failure + + + + Write the constraint description to a MessageWriter + + The writer on which the description is displayed + + + + Summary description for SamePathConstraint. + + + + + Initializes a new instance of the class. + + The expected path + + + + Test whether the constraint is satisfied by a given value + + The expected path + The actual path + True for success, false for failure + + + + Write the constraint description to a MessageWriter + + The writer on which the description is displayed + + + + SamePathOrUnderConstraint tests that one path is under another + + + + + Initializes a new instance of the class. + + The expected path + + + + Test whether the constraint is satisfied by a given value + + The expected path + The actual path + True for success, false for failure + + + + Write the constraint description to a MessageWriter + + The writer on which the description is displayed + + + + SomeItemsConstraint applies another constraint to each + item in a collection, succeeding if any of them succeeds. + + + + + Construct a SomeItemsConstraint on top of an existing constraint + + + + + + Apply the item constraint to each item in the collection, + succeeding if any item succeeds. + + + + + + + Write a description of this constraint to a MessageWriter + + + + + + StartsWithConstraint can test whether a string starts + with an expected substring. + + + + + Initializes a new instance of the class. + + The expected string + + + + Test whether the constraint is matched by the actual value. + This is a template method, which calls the IsMatch method + of the derived class. + + + + + + + Write the constraint description to a MessageWriter + + The writer on which the description is displayed + + + + SubPathConstraint tests that the actual path is under the expected path + + + + + Initializes a new instance of the class. + + The expected path + + + + Test whether the constraint is satisfied by a given value + + The expected path + The actual path + True for success, false for failure + + + + Write the constraint description to a MessageWriter + + The writer on which the description is displayed + + + + SubstringConstraint can test whether a string contains + the expected substring. + + + + + Initializes a new instance of the class. + + The expected. + + + + Test whether the constraint is satisfied by a given value + + The value to be tested + True for success, false for failure + + + + Write the constraint description to a MessageWriter + + The writer on which the description is displayed + + + + ThrowsConstraint is used to test the exception thrown by + a delegate by applying a constraint to it. + + + + + Initializes a new instance of the class, + using a constraint to be applied to the exception. + + A constraint to apply to the caught exception. + + + + Executes the code of the delegate and captures any exception. + If a non-null base constraint was provided, it applies that + constraint to the exception. + + A delegate representing the code to be tested + True if an exception is thrown and the constraint succeeds, otherwise false + + + + Converts an ActualValueDelegate to a TestDelegate + before calling the primary overload. + + + + + Write the constraint description to a MessageWriter + + The writer on which the description is displayed + + + + Write the actual value for a failing constraint test to a + MessageWriter. The default implementation simply writes + the raw value of actual, leaving it to the writer to + perform any formatting. + + The writer on which the actual value is displayed + + + + Returns the string representation of this constraint + + + + + Get the actual exception thrown - used by Assert.Throws. + + + + + ThrowsNothingConstraint tests that a delegate does not + throw an exception. + + + + + Test whether the constraint is satisfied by a given value + + The value to be tested + True if no exception is thrown, otherwise false + + + + Test whether the constraint is satisfied by a given delegate + + Delegate returning the value to be tested + True if no exception is thrown, otherwise false + + + + Write the constraint description to a MessageWriter + + The writer on which the description is displayed + + + + Write the actual value for a failing constraint test to a + MessageWriter. Overridden in ThrowsNothingConstraint to write + information about the exception that was actually caught. + + The writer on which the actual value is displayed + + + + The Tolerance class generalizes the notion of a tolerance + within which an equality test succeeds. Normally, it is + used with numeric types, but it can be used with any + type that supports taking a difference between two + objects and comparing that difference to a value. + + + + + Constructs a linear tolerance of a specdified amount + + + + + Constructs a tolerance given an amount and ToleranceMode + + + + + Tests that the current Tolerance is linear with a + numeric value, throwing an exception if it is not. + + + + + Returns an empty Tolerance object, equivalent to + specifying no tolerance. In most cases, it results + in an exact match but for floats and doubles a + default tolerance may be used. + + + + + Returns a zero Tolerance object, equivalent to + specifying an exact match. + + + + + Gets the ToleranceMode for the current Tolerance + + + + + Gets the value of the current Tolerance instance. + + + + + Returns a new tolerance, using the current amount as a percentage. + + + + + Returns a new tolerance, using the current amount in Ulps. + + + + + Returns a new tolerance with a TimeSpan as the amount, using + the current amount as a number of days. + + + + + Returns a new tolerance with a TimeSpan as the amount, using + the current amount as a number of hours. + + + + + Returns a new tolerance with a TimeSpan as the amount, using + the current amount as a number of minutes. + + + + + Returns a new tolerance with a TimeSpan as the amount, using + the current amount as a number of seconds. + + + + + Returns a new tolerance with a TimeSpan as the amount, using + the current amount as a number of milliseconds. + + + + + Returns a new tolerance with a TimeSpan as the amount, using + the current amount as a number of clock ticks. + + + + + Returns true if the current tolerance is empty. + + + + + Modes in which the tolerance value for a comparison can be interpreted. + + + + + The tolerance was created with a value, without specifying + how the value would be used. This is used to prevent setting + the mode more than once and is generally changed to Linear + upon execution of the test. + + + + + The tolerance is used as a numeric range within which + two compared values are considered to be equal. + + + + + Interprets the tolerance as the percentage by which + the two compared values my deviate from each other. + + + + + Compares two values based in their distance in + representable numbers. + + + + + TrueConstraint tests that the actual value is true + + + + + Initializes a new instance of the class. + + + + + UniqueItemsConstraint tests whether all the items in a + collection are unique. + + + + + Check that all items are unique. + + + + + + + Write a description of this constraint to a MessageWriter + + + + + + XmlSerializableConstraint tests whether + an object is serializable in XML format. + + + + + Test whether the constraint is satisfied by a given value + + The value to be tested + True for success, false for failure + + + + Write the constraint description to a MessageWriter + + The writer on which the description is displayed + + + + Write the actual value for a failing constraint test to a + MessageWriter. The default implementation simply writes + the raw value of actual, leaving it to the writer to + perform any formatting. + + The writer on which the actual value is displayed + + + + Returns the string representation of this constraint + + + + + Represents a constraint that succeeds if all the + members of a collection match a base constraint. + + + + + Abstract base for operators that indicate how to + apply a constraint to items in a collection. + + + + + PrefixOperator takes a single constraint and modifies + it's action in some way. + + + + + The ConstraintOperator class is used internally by a + ConstraintBuilder to represent an operator that + modifies or combines constraints. + + Constraint operators use left and right precedence + values to determine whether the top operator on the + stack should be reduced before pushing a new operator. + + + + + The precedence value used when the operator + is about to be pushed to the stack. + + + + + The precedence value used when the operator + is on the top of the stack. + + + + + Reduce produces a constraint from the operator and + any arguments. It takes the arguments from the constraint + stack and pushes the resulting constraint on it. + + + + + + The syntax element preceding this operator + + + + + The syntax element folowing this operator + + + + + The precedence value used when the operator + is about to be pushed to the stack. + + + + + The precedence value used when the operator + is on the top of the stack. + + + + + Reduce produces a constraint from the operator and + any arguments. It takes the arguments from the constraint + stack and pushes the resulting constraint on it. + + + + + + Returns the constraint created by applying this + prefix to another constraint. + + + + + + + Constructs a CollectionOperator + + + + + Returns a constraint that will apply the argument + to the members of a collection, succeeding if + they all succeed. + + + + + Operator that requires both it's arguments to succeed + + + + + Abstract base class for all binary operators + + + + + Reduce produces a constraint from the operator and + any arguments. It takes the arguments from the constraint + stack and pushes the resulting constraint on it. + + + + + + Abstract method that produces a constraint by applying + the operator to its left and right constraint arguments. + + + + + Gets the left precedence of the operator + + + + + Gets the right precedence of the operator + + + + + Construct an AndOperator + + + + + Apply the operator to produce an AndConstraint + + + + + Operator that tests for the presence of a particular attribute + on a type and optionally applies further tests to the attribute. + + + + + Abstract base class for operators that are able to reduce to a + constraint whether or not another syntactic element follows. + + + + + Construct an AttributeOperator for a particular Type + + The Type of attribute tested + + + + Reduce produces a constraint from the operator and + any arguments. It takes the arguments from the constraint + stack and pushes the resulting constraint on it. + + + + + Represents a constraint that succeeds if the specified + count of members of a collection match a base constraint. + + + + + Construct an ExactCountOperator for a specified count + + The expected count + + + + Returns a constraint that will apply the argument + to the members of a collection, succeeding if + none of them succeed. + + + + + Represents a constraint that succeeds if none of the + members of a collection match a base constraint. + + + + + Returns a constraint that will apply the argument + to the members of a collection, succeeding if + none of them succeed. + + + + + Negates the test of the constraint it wraps. + + + + + Constructs a new NotOperator + + + + + Returns a NotConstraint applied to its argument. + + + + + Operator that requires at least one of it's arguments to succeed + + + + + Construct an OrOperator + + + + + Apply the operator to produce an OrConstraint + + + + + Operator used to test for the presence of a named Property + on an object and optionally apply further tests to the + value of that property. + + + + + Constructs a PropOperator for a particular named property + + + + + Reduce produces a constraint from the operator and + any arguments. It takes the arguments from the constraint + stack and pushes the resulting constraint on it. + + + + + + Gets the name of the property to which the operator applies + + + + + Represents a constraint that succeeds if any of the + members of a collection match a base constraint. + + + + + Returns a constraint that will apply the argument + to the members of a collection, succeeding if + any of them succeed. + + + + + Operator that tests that an exception is thrown and + optionally applies further tests to the exception. + + + + + Construct a ThrowsOperator + + + + + Reduce produces a constraint from the operator and + any arguments. It takes the arguments from the constraint + stack and pushes the resulting constraint on it. + + + + + Represents a constraint that simply wraps the + constraint provided as an argument, without any + further functionality, but which modifes the + order of evaluation because of its precedence. + + + + + Constructor for the WithOperator + + + + + Returns a constraint that wraps its argument + + + + + Thrown when an assertion failed. + + + + The error message that explains + the reason for the exception + + + The error message that explains + the reason for the exception + The exception that caused the + current exception + + + + Serialization Constructor + + + + + Thrown when an assertion failed. + + + + + + + The error message that explains + the reason for the exception + The exception that caused the + current exception + + + + Serialization Constructor + + + + + Thrown when a test executes inconclusively. + + + + The error message that explains + the reason for the exception + + + The error message that explains + the reason for the exception + The exception that caused the + current exception + + + + Serialization Constructor + + + + + Thrown when an assertion failed. + + + + + + + The error message that explains + the reason for the exception + The exception that caused the + current exception + + + + Serialization Constructor + + + + + + + + + + + Compares two objects of a given Type for equality within a tolerance + + The first object to compare + The second object to compare + The tolerance to use in the comparison + + + + diff -r 2a8466f0cb8a -r 1c2a16d071a7 packages/NUnit.2.6.4/license.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/packages/NUnit.2.6.4/license.txt Fri Apr 22 13:08:08 2016 +0300 @@ -0,0 +1,15 @@ +Copyright 2002-2014 Charlie Poole +Copyright 2002-2004 James W. Newkirk, Michael C. Two, Alexei A. Vorontsov +Copyright 2000-2002 Philip A. Craig + +This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. + +Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment (see the following) in the product documentation is required. + +Portions Copyright 2002-2014 Charlie Poole or Copyright 2002-2004 James W. Newkirk, Michael C. Two, Alexei A. Vorontsov or Copyright 2000-2002 Philip A. Craig + +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. + +3. This notice may not be removed or altered from any source distribution. diff -r 2a8466f0cb8a -r 1c2a16d071a7 packages/System.Text.Json.2.0.0.11/System.Text.Json.2.0.0.11.nupkg Binary file packages/System.Text.Json.2.0.0.11/System.Text.Json.2.0.0.11.nupkg has changed diff -r 2a8466f0cb8a -r 1c2a16d071a7 packages/System.Text.Json.2.0.0.11/lib/net40/System.Text.Json.dll Binary file packages/System.Text.Json.2.0.0.11/lib/net40/System.Text.Json.dll has changed diff -r 2a8466f0cb8a -r 1c2a16d071a7 packages/repositories.config --- a/packages/repositories.config Fri Feb 19 18:07:17 2016 +0300 +++ b/packages/repositories.config Fri Apr 22 13:08:08 2016 +0300 @@ -1,4 +1,5 @@  + \ No newline at end of file