using System; using System.Diagnostics; using System.IO; using System.Collections; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; using System.Collections.Concurrent; using System.Runtime.Serialization; using glue.Extensions.String; using glue.Extensions.String.Builder; using glue.Debugging; using glue.Extensions.Enumerable; using glue.Collections.XSpinLock; namespace agree { /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /// <summary> /// /// </summary> /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// public struct FsPathPair { public FsPathPair(FsPath path1, FsPath path2) { this.path1 = path1; this.path2 = path2; } public FsPathPair(String s1, String s2) { this.path1 = new FsPath(s1); this.path2 = new FsPath(s2); } public FsPath path1; public FsPath path2; }; /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /// <summary> /// /// </summary> /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// [DebuggerDisplay("{ToString(),nq}")] public sealed class FsPath : IList<String>, IEquatable<FsPath> { static public readonly FsPath Empty = new FsPath(new String[0]); static readonly Char[] dot_space = { '.', ' ' }; static readonly Char[] outer_trim = { '\"', '\'', '(', ')', '[', ']' }; readonly String[] arr; readonly int hc; public FsPath(IEnumerable<String> rgs) { /// interning strings here in guarantee the sufficiency of reference equality in the Equals() override this.arr = rgs.Select(s => String.Intern(s.ToLower().Trim())).Where(s => !String.IsNullOrEmpty(s)).ToArray(); hc = arr.Length; for (int i = 0; i < arr.Length; i++) hc = hc ^ (i + arr[i].GetHashCode()); } public FsPath(String s) : this(s.Trim(outer_trim).Split(dot_space, StringSplitOptions.RemoveEmptyEntries)) { } //public static implicit operator String[](FsPath fsp) { return fsp.arr; } //public static implicit operator FsPath(String[] rgs) { return new FsPath(rgs); } public String this[int index] { get { return arr[index]; } set { throw new InvalidOperationException(); } } public int IndexOf(String item) { return Array.IndexOf<String>(arr, item); } public bool Contains(String item) { return Array.IndexOf<String>(arr, item) != -1; } public void CopyTo(String[] array, int arrayIndex) { Array.Copy(arr, array, arr.Length); } public int Count { get { return arr.Length; } } public bool IsReadOnly { get { return true; } } public IEnumerator<String> GetEnumerator() { return arr.AsEnumerable<String>().GetEnumerator(); } IEnumerator IEnumerable.GetEnumerator() { return arr.GetEnumerator(); } public void Insert(int index, string item) { throw new InvalidOperationException(); } public void RemoveAt(int index) { throw new InvalidOperationException(); } public void Add(String item) { throw new InvalidOperationException(); } public void Clear() { throw new InvalidOperationException(); } public bool Remove(String item) { throw new InvalidOperationException(); } public bool Equals(FsPath other) { Debug.Assert(!Object.Equals(this, null)); if (Object.Equals(other, null) || hc != other.hc || arr.Length != other.arr.Length) return false; for (int i = 0; i < arr.Length; i++) if (!Object.Equals(arr[i], other.arr[i])) return false; return true; } public static bool operator ==(FsPath a, FsPath b) { if (Object.Equals(a, null)) return Object.Equals(b, null); return a.Equals(b); } public static bool operator !=(FsPath a, FsPath b) { if (Object.Equals(a, null)) return !Object.Equals(b, null); return !a.Equals(b); } public bool StartsWith(FsPath b) { if (Object.Equals(this, b)) return true; int n = b.arr.Length; if (arr.Length < n) return false; for (int i = 0; i < n; i++) if (!Object.Equals(arr[i], b.arr[i])) return false; return true; } public override bool Equals(Object obj) { FsPath o = (FsPath)obj; return hc == o.hc && Equals(o); } public override int GetHashCode() { return hc; } public override String ToString() { return arr.StringJoin(".").ToUpper(); } }; /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /// <summary> /// /// </summary> /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// [DebuggerDisplay("{ToString(),nq}")] public class TypeMgrCompiledFsPath : IEquatable<TypeMgrCompiledFsPath> { readonly protected int[] rg_fix; readonly int hc; readonly protected TypeMgr tm; public TypeMgrCompiledFsPath(TypeMgr tm, IEnumerable<int> rgfix) { this.tm = tm; this.rg_fix = rgfix.ToArray(); hc = rg_fix.Length; for (int i = 0; i < rg_fix.Length; i++) hc = hc ^ (i + rg_fix[i].GetHashCode()); } public TypeMgrCompiledFsPath(TypeMgr tm, IEnumerable<String> ies) : this(tm, ies.Select(s => tm.feat_map[s].i_feat)) { } public TypeMgrCompiledFsPath(TypeMgr tm, FsPath fsp) : this(tm, (IEnumerable<String>)fsp) { } public TypeMgr TypeMgr { get { return tm; } } public bool GetEdge(TfsEdge te, out Edge e) { e = te.Edge; ConstraintPool[] rgcp = te.Tray.Pools; foreach (int i in rg_fix) { if (e.Mark == 0 || !rgcp[i].TryGetEdge(e.Mark, out e)) return false; } return true; } public bool GetTfsEdge(TfsEdge te, out TfsEdge te_out) { Tray tr = te.Tray; te_out = tr.CreateTfs(te.Edge); ConstraintPool[] rgcp = tr.Pools; foreach (int i in rg_fix) { int m = te_out.Edge.Mark; if (m == 0 || !rgcp[i].TryGetEdge(m, out te_out.Edge)) return false; } return true; } public Type GetType(TfsEdge te) { Edge e = te.Edge; ConstraintPool[] rgcp = te.Tray.Pools; foreach (int i in rg_fix) if ( e.Mark == 0 || !rgcp[i].TryGetEdge(e.Mark, out e)) return null; return tm.GetEdgeType(e.FlagsId); } public override String ToString() { return rg_fix.Select(i => tm.feat_arr[i].feature).StringJoin("."); } public bool Equals(TypeMgrCompiledFsPath other) { Debug.Assert(!Object.Equals(this, null)); if (Object.Equals(other, null) || hc != other.hc || rg_fix.Length != other.rg_fix.Length) return false; for (int i = 0; i < rg_fix.Length; i++) if (rg_fix[i] != other.rg_fix[i]) return false; return true; } public override bool Equals(object obj) { throw new NotImplementedException(); } public override int GetHashCode() { return hc; } }; /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /// <summary> /// /// </summary> /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// [DebuggerDisplay("{ToString(),nq}")] public sealed class TrayCompiledFsPath : TypeMgrCompiledFsPath, IList<ConstraintPool> { readonly Tray tr; readonly ConstraintPool[] rgcp; public TrayCompiledFsPath(Tray tr, IEnumerable<String> ies) : base(tr.tm, ies) { this.tr = tr; this.rgcp = rg_fix.Select(i => tr.Pools[i]).ToArray(); } public TrayCompiledFsPath(Tray tr, FsPath fsp) : this(tr, (IEnumerable<String>)fsp) { } public bool GetEdge(int m, out Edge e_out) { e_out = new Edge((Edge.Flag)0, m); foreach (ConstraintPool cp in rgcp) { if (e_out.Mark == 0 || !cp.TryGetEdge(e_out.Mark, out e_out)) return false; } return true; } public IEnumerable<Edge> EnumerateEdges(int m) { Edge e = new Edge((Edge.Flag)0, m); foreach (ConstraintPool cp in rgcp) { if (e.Mark == 0 || !cp.TryGetEdge(e.Mark, out e)) yield break; yield return e; } } public IEnumerable<PoolEdge> EnumeratePoolEdges(int m) { PoolEdge pe; pe.Edge = new Edge((Edge.Flag)0, m); foreach (ConstraintPool cp in rgcp) { if (pe.Edge.Mark == 0 || !cp.TryGetEdge(pe.Edge.Mark, out pe.Edge)) yield break; pe.Pool = cp; yield return pe; } } public bool GetTypeId(int m, out Edge.Flag f) { Edge e = new Edge((Edge.Flag)0, m); foreach (ConstraintPool cp in rgcp) { if (e.Mark == 0 || !cp.TryGetEdge(e.Mark, out e)) { f = tm.MultiIdMask; return false; } } f = e.FlagsId; return true; } public Type GetType(int m) { if (rg_fix.Length == 4) return _GetType(m); Edge e = new Edge((Edge.Flag)0, m); foreach (ConstraintPool cp in rgcp) { if (e.Mark == 0 || !cp.TryGetEdge(e.Mark, out e)) return null; } return tm.IsTopId(e) ? tm.TopType : tm.GetEdgeType(e.FlagsId); } Type _GetType(int m) { if (m == 0) throw new Exception(); Edge e; if (!rgcp[0].TryGetEdge(m, out e)) return null; if (e.Mark == 0) return null; if (!rgcp[1].TryGetEdge(e.Mark, out e)) return null; if (e.Mark == 0) return null; if (!rgcp[2].TryGetEdge(e.Mark, out e)) return null; if (e.Mark == 0) return null; if (!rgcp[3].TryGetEdge(e.Mark, out e)) return null; if (e.Mark == 0) return null; return (e.FlagsId & Edge.Flag.EtmMask) == Edge.Flag.EtmString ? tm.StringType : tm.type_arr[(int)(e.FlagsId & tm.MultiIdMask)]; } public ConstraintPool this[int index] { get { return rgcp[index]; } set { throw new InvalidOperationException(); } } public bool Contains(ConstraintPool item) { return Array.IndexOf<ConstraintPool>(rgcp,item) != -1; } public int Count { get { return rgcp.Length; } } public bool IsReadOnly { get { return true; } } public void CopyTo(ConstraintPool[] array, int arrayIndex) { foreach (ConstraintPool cp in rgcp) array[arrayIndex++] = cp; } public IEnumerator<ConstraintPool> GetEnumerator() { return rgcp.AsEnumerable<ConstraintPool>().GetEnumerator(); } IEnumerator IEnumerable.GetEnumerator() { return rgcp.GetEnumerator(); } public int IndexOf(ConstraintPool item) { return Array.IndexOf<ConstraintPool>(rgcp, item); } public void Add(ConstraintPool item) { throw new InvalidOperationException(); } public void Clear() { throw new InvalidOperationException(); } public bool Remove(ConstraintPool item) { throw new InvalidOperationException(); } public void Insert(int index, ConstraintPool item) { throw new InvalidOperationException(); } public void RemoveAt(int index) { throw new InvalidOperationException(); } }; }