*** empty log message ***
authorhanda <handa>
Sat, 30 May 2009 00:36:05 +0000 (00:36 +0000)
committerhanda <handa>
Sat, 30 May 2009 00:36:05 +0000 (00:36 +0000)
MDatabase.cs
MPlist.cs
MText.cs
Makefile
symbol.cs

index 5557257..dca37f6 100644 (file)
@@ -6,147 +6,202 @@ using M17N.Core;
 
 namespace M17N.Core
 {
+  internal class MDatabaseDir
+  {
+    private const string ListFileName = "mdb.dir";
+
+    public string Dirname;
+    public DirectoryInfo DirInfo;
+    public FileInfo ListInfo;
+    public DateTime LastScanned;
+
+    public MDatabaseDir (string dirname)
+    {
+      Dirname = dirname;
+      if (dirname != null)
+       {
+         try {
+           DirInfo = new DirectoryInfo (dirname);
+           try {
+             ListInfo = DirInfo.GetFiles (ListFileName)[0];
+           } catch {
+             ListInfo = null;
+           }
+         } catch {
+           DirInfo = null;
+           ListInfo = null;
+         }
+       }
+    }
+
+    public bool CheckStatus ()
+    {
+      if (DirInfo != null)
+       {
+         try {
+           DirInfo.Refresh ();
+         } catch {
+           DirInfo = null;
+           ListInfo = null;
+           LastScanned = new DateTime (0);
+           return true;
+         }
+         if (ListInfo != null)
+           try {
+             ListInfo.Refresh ();
+           } catch {
+             ListInfo = null;
+             return true;
+           }
+         else
+           {
+             try {
+               ListInfo = DirInfo.GetFiles (ListFileName)[0];
+               return true;
+             } catch {
+               ListInfo = null;
+             }
+           }
+         return (LastScanned < DirInfo.LastWriteTime
+                 || (ListInfo != null
+                     && LastScanned < ListInfo.LastWriteTime));
+       }
+      else
+       {
+         if (Dirname != null && Directory.Exists (Dirname))
+           {
+             DirInfo = new DirectoryInfo (Dirname);
+             try {
+               ListInfo = DirInfo.GetFiles (ListFileName)[0];
+             } catch {
+               ListInfo = null;
+             }
+             return true;
+           }
+         return false;
+       }
+    }
+
+    public void UpdateStatus ()
+    {
+      if (DirInfo != null)
+       LastScanned = DateTime.UtcNow;
+    }
+
+    public FileInfo[] Scan (string filename)
+    {
+      if (DirInfo == null)
+       return null;
+      DirInfo.Refresh ();
+      return DirInfo.GetFiles (filename);
+    }
+  }
+
   public class MDatabase
   {
+    /// Tags to identify a MDatabase.
     public struct Tag
     {
-      public MSymbol Tag0, Tag1, Tag2, Tag3;
+      public MSymbol[] Tags;
 
       public Tag (MSymbol tag0)
        {
-         Tag0 = tag0; Tag1 = Tag2 = Tag3 = MSymbol.nil;
+         Tags = new MSymbol[4];
+         Tags[0] = tag0; Tags[1] = Tags[2] = Tags[3] = MSymbol.nil;
        }
 
       public Tag (MSymbol tag0, MSymbol tag1)
        {
-         Tag0 = tag0; Tag1 = tag1; Tag2 = Tag3 = MSymbol.nil;
+         Tags = new MSymbol[4];
+         Tags[0] = tag0; Tags[1] = tag1; Tags[2] = Tags[3] = MSymbol.nil;
        }
 
       public Tag (MSymbol tag0, MSymbol tag1, MSymbol tag2)
        {
-         Tag0 = tag0; Tag1 = tag1; Tag2 = tag2; Tag3 = MSymbol.nil;
+         Tags = new MSymbol[4];
+         Tags[0] = tag0; Tags[1] = tag1; Tags[2] = tag2; Tags[3] = MSymbol.nil;
        }
 
       public Tag (MSymbol tag0, MSymbol tag1, MSymbol tag2, MSymbol tag3)
        {
-         Tag0 = tag0; Tag1 = tag1; Tag2 = tag2; Tag3 = tag3;
+         Tags = new MSymbol[4];
+         Tags[0] = tag0; Tags[1] = tag1; Tags[2] = tag2; Tags[3] = tag3;
        }
-    }
-
-    public delegate object Loader (Tag tag, object extra_info);
-
-    private class MDatabaseDir
-    {
-      private const string ListFileName = "mdb.dir";
 
-      public string Dirname;
-      public DirectoryInfo DirInfo;
-      public DateTime LastScanned;
-      public FileInfo ListInfo;
-
-      private static void GetInfo (string dirname, out DirectoryInfo dirinfo,
-                                  out FileInfo listinfo)
+      public bool Match (Tag tag)
       {
-       if (Directory.Exists (dirname))
-         try { dirinfo = new DirectoryInfo (dirname);
-           try { listinfo = dirinfo.GetFiles (ListFileName)[0];
-           } catch { listinfo = null; }
-         } catch { dirinfo = null; listinfo = null; }
-       else
+       for (int i = 0; i < 4; i++)
          {
-           dirinfo = null;
-           listinfo = null;
-         }
-      }
-
-      public MDatabaseDir (string dirname)
-      {
-       Dirname = dirname;
-       GetInfo (dirname, out DirInfo, out ListInfo);
-      }
-
-      public bool StatusChanged {
-       get {
-         bool exists = Directory.Exists (Dirname);
-
-         if (DirInfo != null)
-           {
-             if (! exists)
-               {
-                 DirInfo = null;
-                 ListInfo = null;
-                 LastScanned = new DateTime (0);
-               }
-             if (LastScanned.Year == 0)
-               return true;
-             DirInfo.Refresh ();
-             if (ListInfo != null)
-               ListInfo.Refresh ();
-             return (LastScanned < DirInfo.LastWriteTime
-                     || LastScanned < ListInfo.LastWriteTime);
-           }
-         else
-           {
-             if (exists)
-               {
-                 DirInfo = new DirectoryInfo (Dirname);
-                 try {
-                   ListInfo = DirInfo.GetFiles (ListFileName)[0];
-                 } catch {
-                   ListInfo = null;
-                 }
-                 return true;
-               }
+           if (tag.Tags[i] == Mwildcard || Tags[i] == Mwildcard)
+             return true;
+           if (tag.Tags[i] != Tags[i])
              return false;
-           }
-       }
-      }
-
-      public void UpdateStatus ()
-      {
-       if (DirInfo != null)
-         LastScanned = DateTime.UtcNow;
+         }
+       return true;
       }
 
-      public FileInfo[] Scan (string filename)
+      public override string ToString ()
       {
-       if (DirInfo == null)
-         return null;
-       DirInfo.Refresh ();
-       return DirInfo.GetFiles (filename);
+       return ("<"
+               + Tags[0] + "," + Tags[1] + "," + Tags[2] + "," + Tags[3]
+               + ">");
       }
     }
 
+    public delegate object Loader (Tag tag, object extra_info);
+
     internal class MDatabaseInfo {
-      internal DirectoryInfo Dir;
+      // -2: absolute, -1: unknown 0: DBDirs[0], 1: DBDirs[1], 2: DBDirs[2]
+      internal int DirIndex;
       internal string Description;
-      internal MText Filename;
+      internal string Filename;
       internal FileInfo FileInfo;
       internal FileInfo Validater;
       internal int Version;
       internal MSymbol Format;
       internal MSymbol Schema;
-      internal MText SchemaFile;
+      internal string SchemaFile;
       internal DateTime ModifiedTime;
       internal MPlist Props;
+
+      public MDatabaseInfo ()
+      {
+       Format = Schema = MSymbol.nil;
+       DirIndex = -1;
+      }
+
+      public override string ToString ()
+      {
+       string str = ("#<Info " + Format + " \"" + Filename
+                     + "\" (" + DirIndex + ")");
+       if (Schema != MSymbol.nil)
+         str += " " + Schema;
+       return str + ">";
+      }
     }
 
-    private static Dictionary<MDatabase.Tag, MDatabase> DBDict
-      = new Dictionary<MDatabase.Tag, MDatabase> ();
+    private static Dictionary<MDatabase.Tag, MDatabase[]> DBDict
+      = new Dictionary<MDatabase.Tag, MDatabase[]> ();
+
+    private static Dictionary<MDatabase.Tag, MDatabase[]> DBDictMulti
+      = new Dictionary<MDatabase.Tag, MDatabase[]> ();
 
     private static MDatabaseDir[] DBDirs = new MDatabaseDir[3];
 
-    private const string SystemDirectory = "/usr/share/m17n";
     private static readonly MSymbol Mversion = MSymbol.Of ("version");
 
+    private static readonly MSymbol Mwildcard = MSymbol.Of ("*");
+    private static readonly MSymbol Mchar_table = MSymbol.Of ("char-table");
+    private static readonly MSymbol Mcharset = MSymbol.Of ("charset");
+
     /// Type of database
     private enum MDBType
       {
-       /// The database was defined automatically from mdb.dir
-       /// file(s) with no wildcard tag.
+       /// The database was defined automatically from one of mdb.dir
+       /// files with no wildcard tag.
        AUTO,
-       /// The database was defined automatically from mdb.dir
-       /// file(s) with a wildcard tag to define multiple databases
+       /// The database was defined automatically from one of mdb.dir
+       /// files with a wildcard tag to define multiple databases
        /// of the same kind.
        MULTIPLE,
        /// The database was defined explicitely by MDatabase.Define
@@ -155,6 +210,9 @@ namespace M17N.Core
        /// The database was defined explicitely by MDatabase.Define
        /// to use a special loader.
        UNKNOWN,
+       /// The database is for defining multiple databases of the
+       /// same kind with a wildcard tag.
+       WILDCARD,
       };
 
     /// Status of database
@@ -175,7 +233,7 @@ namespace M17N.Core
        INVALID,
       };
 
-    public readonly Tag tag;
+    public Tag tag;
     private Loader loader;
     private object ExtraInfo;
     private MDBType DBType;
@@ -183,8 +241,6 @@ namespace M17N.Core
     internal DateTime LoadedTime;
     internal MDatabaseInfo Info;
 
-    public static string ApplicationDirectory;
-
     static MDatabase ()
     {
       string share_dir = (Environment.GetFolderPath
@@ -197,37 +253,107 @@ namespace M17N.Core
       } catch (ArgumentException) {
        DBDirs[0] = new MDatabaseDir (Path.Combine (usr_dir, "_m17n_d"));
       }
-      DBDirs[1] = null;
+      DBDirs[1] = new MDatabaseDir (null);
       DBDirs[2] = new MDatabaseDir (Path.Combine (share_dir, "m17n"));
     }
 
-    private MDatabase (Tag tag, Loader loader, object extra_info)
+    public static string ApplicationDir
+    { get { return (DBDirs[1].Dirname); }
+      set { DBDirs[1].Dirname = value; DBDirs[1].CheckStatus (); } }
+
+    private static bool update_database_directories ()
+    {
+      bool updated = false;
+      for (int i = 0; i < 3; i++)
+       if (DBDirs[i].CheckStatus ())
+         {
+           delete_databases (i);
+           if (DBDirs[i].ListInfo != null)
+             update_databases (i);
+           updated = true;
+         }
+      return updated;
+    }
+
+    public static void ListDirs ()
+    {
+      update_database_directories ();
+      for (int i = 0; i < 3; i++)
+       if (DBDirs[i].Dirname != null)
+         {
+           Console.Write ("{0}:{1}", i, DBDirs[i].Dirname);
+           if (DBDirs[i].DirInfo != null)
+             {
+               if (DBDirs[i].ListInfo != null)
+                 Console.WriteLine (" {0}", DBDirs[i].ListInfo);
+               else
+                 Console.WriteLine (".. no mdb.dir");
+             }
+           else
+             Console.WriteLine (".. not exist");
+         }
+    }
+
+    private void register (int priority)
+    {
+      Dictionary<MDatabase.Tag, MDatabase[]> dict
+       = DBType == MDBType.WILDCARD ? DBDictMulti : DBDict;
+      MDatabase[] mdbs;
+
+      if (! dict.TryGetValue (tag, out mdbs))
+       {
+         mdbs = new MDatabase[4];
+         dict.Add (tag, mdbs);
+       }
+      mdbs[priority] = this;
+    }
+
+    public MDatabase (Tag tag, Loader loader, object extra_info)
     {
       this.tag = tag;
       this.loader = loader;
+      DBType = MDBType.UNKNOWN;
+      DBStatus = MDBStatus.UPDATED;
       ExtraInfo = extra_info;
+      this.register (0);
     }
 
-    private MDatabase (Tag tag, string filename)
+    public MDatabase (Tag tag, string filename)
     {
       this.tag = tag;
+      DBType = MDBType.EXPLICIT;
+      DBStatus = MDBStatus.OUTDATED;
       Info = new MDatabaseInfo ();
-      Info.Filename = new MText (filename);
+      Info.Filename = filename;
+      Info.DirIndex = Path.IsPathRooted (filename) ? -2 : -1;
+      this.register (0);
     }
 
-    private MDatabase (MPlist plist)
+    private MDatabase (MPlist plist, int priority)
     {
-      MSymbol[] tags = new MSymbol[4];
-      int i;
-
-      for (i = 0; plist.IsSymbol; i++, plist = plist.Next)
-       tags[i] = plist.Symbol;
-      while (i < 4)
-       tags[i++] = MSymbol.nil;
-      tag = new Tag (tags[0], tags[1], tags[2], tags[3]);
+      tag = new Tag (MSymbol.nil);
+      DBType = MDBType.AUTO;
+      DBStatus = MDBStatus.OUTDATED;
+      for (int i = 0; plist.IsSymbol; i++, plist = plist.Next)
+       {
+         if (DBType == MDBType.WILDCARD)
+           tag.Tags[i] = MSymbol.nil;      
+         else
+           {
+             tag.Tags[i] = plist.Symbol;
+             if (tag.Tags[i] == Mwildcard)
+               DBType = MDBType.WILDCARD;
+           }
+       }
+
+      Info = new MDatabaseInfo ();
+      if (tag.Tags[0] == Mchar_table || tag.Tags[0] == Mcharset)
+       Info.Format = tag.Tags[0];
+      else
+       Info.Format = MSymbol.plist;
       if (plist.IsMText)
        {
-         Info.Filename = plist.Text;
+         Info.Filename = plist.Text.ToString ();
          plist = plist.Next;
        }
       else if (plist.IsPlist)
@@ -235,7 +361,7 @@ namespace M17N.Core
          MPlist p = plist.Plist;
 
          if (p.IsMText)
-           Info.Filename = plist.Text;
+           Info.Filename = plist.Text.ToString ();
          p = p.Next;
          if (! p.IsEmpty)
            {
@@ -248,12 +374,15 @@ namespace M17N.Core
                    Info.Schema = p.Symbol;
                  p = p.Next;
                  if (p.IsMText)
-                   Info.SchemaFile = p.Text;
+                   Info.SchemaFile = p.Text.ToString ();
                }                   
            }
          plist = plist.Next;
        }
-      DBStatus = MDBStatus.OUTDATED;;
+      else
+       throw new Exception ("Invalid source definition:" + plist);     
+
+      Info.DirIndex = Path.IsPathRooted (Info.Filename) ? -2 : -1;
       Info.Version = 0;
       Info.Props = new MPlist ();
       foreach (MPlist pl in plist)
@@ -271,6 +400,15 @@ namespace M17N.Core
            }
          Info.Props.Put (pl.Key, pl.Val);
        }
+      this.register (priority);
+    }
+
+    public override String ToString () {
+      string str = "#<MDataBase " + tag + " " + DBType + " " + DBStatus;
+
+      if (DBType != MDBType.EXPLICIT && DBType != MDBType.UNKNOWN)
+       str += " " + Info;
+      return str + ">";
     }
 
     private static int parse_version (MPlist plist)
@@ -289,53 +427,127 @@ namespace M17N.Core
       return ((major << 16) | (minor << 8) | release);
     }
 
-    public static MDatabase Define (Tag tag, Loader loader, object extra_info)
+    private static void delete_databases (int list_idx)
     {
-      MDatabase db = MDatabase.Find (tag);
+      foreach (KeyValuePair<Tag, MDatabase[]> item in DBDict)
+       item.Value[list_idx + 1] = null;
+      foreach (KeyValuePair<Tag, MDatabase[]> item in DBDictMulti)
+       item.Value[list_idx + 1] = null;
+    }
 
-      if (db != null)
+    private static void update_databases (int list_idx)
+    {
+      MDatabaseDir dbdir = DBDirs[list_idx];
+      FileInfo dblist = dbdir.ListInfo;
+      MPlist plist = null;
+
+      using (FileStream stream = File.OpenRead (dblist.FullName))
        {
-         db.loader = loader;
-         db.ExtraInfo = extra_info;
-         db.DBType = MDBType.EXPLICIT;
-         db.DBStatus = MDBStatus.OUTDATED;
-         db.Info = null;
-         return db;
+         MStreamReader reader = new MStreamReader (stream);
+         plist = new MPlist (reader);
+       }
+      if (plist == null)
+       return;
+      foreach (MPlist pl in plist)
+       {
+         if (! pl.IsPlist)
+           continue;
+         try
+           {
+             new MDatabase (pl.Plist, list_idx + 1);
+           }
+         catch (Exception e)
+           {
+             Console.WriteLine (e.Message);
+           }
        }
-      return new MDatabase (tag, loader, extra_info);
     }
 
-    public static  MDatabase Define (Tag tag, string filename)
+    private void expand_wildcard (int priority)
     {
-      MDatabase db = MDatabase.Find (tag);
-
-      if (db != null)
+      if (Info.DirIndex == -2)
        {
-         db.loader = null;
-         db.DBType = MDBType.EXPLICIT;
-         db.DBStatus = MDBStatus.OUTDATED;
-         db.Info = new MDatabaseInfo ();
-         db.Info.Filename = new MText (filename);
-
-         return db;
+         
        }
-      return new MDatabase (tag, filename);
+
     }
 
-    private void update ()
+    private void update_status ()
     {
-      for (int i = 0; i < 3; i++)
+      if (Info.DirIndex == -2)
        {
-         if (DBDirs[0].StatusChanged)
-           break;
        }
     }
 
     public static MDatabase Find (Tag tag)
     {
-      MDatabase db;
+      MDatabase[] mdbs;
+      MDatabase mdb = null;
+
+      if (DBDict.TryGetValue (tag, out mdbs))
+       {
+         if (mdbs[0] != null)
+           return mdbs[0];
+         for (int i = 1; i < 4; i++)
+           if ((mdb = mdbs[i]) != null)
+             break;
+       }
+      if (! update_database_directories ())
+       return mdb;
+      if (! DBDict.TryGetValue (tag, out mdbs))
+       return null;
+      for (int i = 1; i < 4; i++)
+       if (mdbs[i] != null)
+         return mdbs[i];
+      return null;
+    }
 
-      return (DBDict.TryGetValue (tag, out db) ? db : null);
+    public static List<MDatabase> List (Tag tag)
+    {
+      List<MDatabase> list = new List<MDatabase> ();
+
+      update_database_directories ();
+      foreach (KeyValuePair<Tag, MDatabase[]> item in DBDictMulti)
+       if (item.Key.Match (tag))
+         for (j = 0; j < 4; j++)
+           if (item.Value[j] != null)
+             if (item.Value[j].DBStatus == MDBStatus.OUTDATED)
+               item.Value[j].expand_wildcard (j);
+
+      for (int i = 0; i < 4 && tag.Tags[i] == Mwildcard; i++);
+      if (i == 4)
+       {
+         // No wildcard.
+         if (DBDict.TryGetValue (tag, out mdbs))
+           for (int j = 0; j < 4; j++)
+             if (mdbs[j] != null)
+               {
+                 mdbs[j].update_status ();
+                 if (mdbs[j].DBStatus != MDBStatus.DISABLED)
+                   {
+                     list.Add (mdbs[j]);
+                     break;
+                   }
+               }
+       }
+      else
+       {
+         // With wildcard.  We must scan all databases.
+         foreach (KeyValuePair<Tag, MDatabase[]> item in DBDict)
+           if (item.Key.Match (tag))
+             for (int j = 0; j < 4; j++)
+               if (item.Value[j] != null)
+                 {
+                   MDatabase mdb = item.Value[j];
+                   mdb.update_status ();
+                   if (mdb.DBStatus != MDBStatus.DISABLED)
+                     {
+                       list.Add (mdb);
+                       break;
+                     }
+                 }
+       }
+      return list;
     }
 
     public object Load ()
@@ -355,8 +567,6 @@ namespace M17N.Core
     {
       LoadedTime = DateTime.UtcNow;
 
-      
-
       return null;
     }
   }
index 67977b3..f607bc7 100644 (file)
--- a/MPlist.cs
+++ b/MPlist.cs
@@ -82,7 +82,10 @@ namespace M17N.Core
                && p.Key != MSymbol.plist
                && p.Key != MSymbol.mtext)
              str += p.Key + ":";
-           str += p.Val;
+           if (p.Key == MSymbol.mtext)
+             str += "\"" + p.Val + "\"";
+           else
+             str += p.Val;
          }
        return str + ")";
     }
index f8d7379..a46a95d 100644 (file)
--- a/MText.cs
+++ b/MText.cs
@@ -186,7 +186,7 @@ namespace M17N.Core
       return this.sb.ToString ().CompareTo (other.sb.ToString ());
     }
 
-    public override String ToString () { return "\"" + sb.ToString () + "\""; }
+    public override string ToString () { return sb.ToString (); }
 
     private static bool surrogate_high_p (char c)
     {
index 8cb4029..3b4f590 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -2,7 +2,7 @@ CS=gmcs
 
 M17N_SRC = M17N.cs
 CORE_SRC = MSymbol.cs MPlist.cs MText.cs MDatabase.cs
-TEST_PROG = symbol.exe plist.exe mtext.exe textprop.exe \
+TEST_PROG = symbol.exe plist.exe mtext.exe textprop.exe database.exe \
        rearsticky.exe frontsticky.exe sensitive.exe
 
 all: ${TEST_PROG}
index 32be8e3..d6b8b18 100644 (file)
--- a/symbol.cs
+++ b/symbol.cs
@@ -34,5 +34,6 @@ public class Test
     }
     sym4 = MSymbol.PropertyKey ("symbol", MProperty.Flags.None);
     sym4 = MSymbol.PropertyKey ("symbol");
+    Console.WriteLine (sym4);
   }
 }