diff Implab/Automaton/EnumAlphabet.cs @ 190:1c2a16d071a7 v2

Слияние с ref20160224
author cin
date Fri, 22 Apr 2016 13:08:08 +0300
parents c32688129f14
children
line wrap: on
line diff
--- /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 {
+    /// <summary>
+    /// Алфавит символами которого являются элементы перечислений.
+    /// </summary>
+    /// <typeparam name="T">Тип перечислений</typeparam>
+    public class EnumAlphabet<T> : IndexedAlphabetBase<T> where T : struct, IConvertible {
+        [SuppressMessage("Microsoft.Design", "CA1000:DoNotDeclareStaticMembersOnGenericTypes")]
+        static readonly Lazy<T[]> _symbols = new Lazy<T[]>(GetSymbols);
+
+        [SuppressMessage("Microsoft.Design", "CA1000:DoNotDeclareStaticMembersOnGenericTypes")]
+        static readonly Lazy<EnumAlphabet<T>> _fullAlphabet = new Lazy<EnumAlphabet<T>>(CreateEnumAlphabet);
+
+        static EnumAlphabet<T> 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<T>(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<T> 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);
+        }
+
+    }
+}