*** empty log message ***
[m17n/m17n-lib-cs.git] / MSymbol.cs
index 06e5370..c687a0f 100644 (file)
 using System;
+using System.Collections.Generic;
 using M17N.Core;
 
 namespace M17N.Core
 {
-  public class MPlist
+  public sealed class MSymbol
   {
-    private MSymbol key;
-    private object val;
-    private MPlist next;
-
-    public MPlist ()
+    private static Dictionary<string, MSymbol> pool
+      = new Dictionary<string, MSymbol> ();
+
+    public readonly string Name;
+    private MPlist Plist;
+    internal MProperty.Flags? flags;
+
+    public static MSymbol nil = MSymbol.Of ("nil");
+    public static MSymbol t = MSymbol.Of ("t");
+    public static MSymbol symbol = MSymbol.Of ("symbol");
+    public static MSymbol mtext = MSymbol.Of ("mtext");
+    public static MSymbol mstring = MSymbol.Of ("string");
+    public static MSymbol plist = MSymbol.Of ("plist");
+    public static MSymbol integer = MSymbol.Of ("integer");
+
+    private MSymbol (string name)
     {
-      key = null;
-      val = null;
-      next = null;
+      Name = name;
     }
 
-    public bool tailp { get { return (object) key == null; } }
-
-    public new string ToString ()
+    public static implicit operator MSymbol (string name)
     {
-      string str = "";
-
-      for (MPlist p = this; ! p.tailp; p = p.next)
-       {
-         str += (p == this ? "(" : " ") + p.key.ToString () + ":";
-         if (p.val is MSymbol)
-           str += ((MSymbol) p.val).ToString ();
-         else if (p.val is MPlist)
-           str += ((MPlist) p.val).ToString ();
-       }
-      return str + ")";
+      return Of (name);
     }
 
-    public object get (MSymbol key)
+    public static explicit operator string (MSymbol sym)
     {
-      if ((object) key == null)
-       return null;
-      for (MPlist p = this; ! p.tailp; p = p.next)
-       if (p.key == key)
-         return p.val;
-      return null;
+      return sym.Name;
     }
 
-    public object put (MSymbol key, object val)
+    public static MSymbol Of (string name)
     {
-      MPlist p;
-
-      for (p = this; ! p.tailp; p = p.next)
-       if (p.key == key)
-         {
-           if (val != null)
-             p.val = val;
-           else
-             p.pop ();
-           return val;
-         }
-      if (val != null)
+      lock (pool)
        {
-         p.key = key;
-         p.val = val;
-         p.next = new MPlist ();
+         MSymbol sym;
+
+         if (! pool.TryGetValue (name, out sym))
+           {
+             sym = new MSymbol (name);
+             pool[name] = sym;
+           }
+         return sym;
        }
-      return val;
     }
 
-    public object push (MSymbol key, object val)
+    public static MSymbol PropertyKey (string name)
     {
-      MPlist p = new MPlist ();
+      MSymbol sym = MSymbol.Of (name);
 
-      p.key = this.key;
-      p.val = this.val;
-      p.next = this.next;
-      this.key = key;
-      this.val = val;
-      this.next = p;
-
-      return val;
+      if (sym.flags == null)
+       sym.flags = MProperty.Flags.None;;
+      return sym;
     }
 
-    public object pop ()
+    public static MSymbol PropertyKey (string name, MProperty.Flags flags)
     {
-      if (tailp)
-       return null;
-
-      object val = this.val;
-
-      this.key = this.next.key;
-      this.val = this.next.val;
-      this.next = this.next.next;
-      return val;
+      MSymbol sym = MSymbol.Of (name);
+
+      if ((flags & MProperty.Flags.BothSticky) != MProperty.Flags.None
+         && (flags & MProperty.Flags.Sensitive) != MProperty.Flags.None)
+       throw new Exception ("A property can't be both sticky and sensitve");
+      if (sym.flags == null)
+       sym.flags = flags;
+      else if (sym.flags != flags)
+       throw new Exception ("Flags of PropertyKey mismatch");
+      return sym;
     }
 
-    public object add (MSymbol key, object val)
+    public override string ToString ()
     {
-      MPlist p;
+      string str = "";
 
-      for (p = this; ! p.tailp; p = p.next);
-      if (val != null)
+      foreach (char c in Name)
        {
-         p.key = key;
-         p.val = val;
-         p.next = new MPlist ();
+         if (c == '\\' || c == ' ' || c == '\'' || c == '\"'
+             || c == '(' || c == ')')
+           str += "\\";
+         str += c;
        }
-      return val;
-    }
-  }
-
-  public class MSymbol
-  {
-    internal class MSymbolData
-    {
-      public string name;
-      public MPlist plist;
-      public MSymbolData next;
-
-      public MSymbolData (string name, MSymbolData next)
-      {
-       this.name = name;
-       this.next = next;
-      }
-    }
-
-    static internal class MSymbolPool
-    {
-      const int MSYMBOL_POOL_SIZE = 1024;
-      static MSymbolData[] pool = new MSymbolData[MSYMBOL_POOL_SIZE];
-      static int[] used = new int[MSYMBOL_POOL_SIZE];
-      
-      static public MSymbolData get_data (string name)
-      {
-       MSymbolData data;
-
-       if (used[0] > 0)
-         {
-           data = pool[0];
-           for (int i = 0; i < used[0]; i++, data = data.next)
-             if (data.name == name)
-               return data;
-         }
-       pool[0] = data = new MSymbolData (name, pool[0]);
-       used[0]++;
-       return data;
-      }
-    }
-
-    static public MSymbol nil = new MSymbol ("nil");
-    static public MSymbol t = new MSymbol ("t");
-
-    private MSymbolData data;
-
-    public MSymbol (string name)
-    {
-      data = MSymbolPool.get_data (name);
-    }
-
-    public new string ToString () { return data.name; }
-
-    public new bool Equals (object sym) { return ((object) this == sym); }
-
-    public new int GetHashCode () { return 0; }
-
-    public static bool operator== (MSymbol sym1, MSymbol sym2)
-    {
-      return ((object) sym1.data == (object) sym2.data);
+      return str;
     }
 
-    public static bool operator!= (MSymbol sym1, MSymbol sym2)
+    public MPlist Find (MSymbol key)
     {
-      return ((object) sym1.data != (object) sym2.data);
+      return (Plist == null ? null : Plist.Find (key));
     }
 
-    public object get (MSymbol key)
+    public object Get (MSymbol key)
     {
-      return (data.plist == null ? null : data.plist.get (key));
+      return (Plist == null ? null : Plist.Get (key));
     }
 
-    public object put (MSymbol key, object val)
+    public object Put (MSymbol key, object val)
     {
-      if (data.plist == null)
-       data.plist = new MPlist ();
-      return data.plist.put (key, val);
+      if (Plist == null)
+       Plist = new MPlist ();
+      return Plist.Put (key, val);
     }
   }
 }