From a7aa796c076061161f49027f3042faba91e5b07b Mon Sep 17 00:00:00 2001 From: handa Date: Sat, 6 Jun 2009 14:34:35 +0000 Subject: [PATCH] *** empty log message *** --- MDatabase.cs | 858 ++++++++++++++++++++++++++++++++++++++-------------------- MPlist.cs | 57 +++- MSymbol.cs | 3 +- database.cs | 21 +- 4 files changed, 645 insertions(+), 294 deletions(-) diff --git a/MDatabase.cs b/MDatabase.cs index e19ebc4..83c3db2 100644 --- a/MDatabase.cs +++ b/MDatabase.cs @@ -1,4 +1,5 @@ using System; +using System.Collections; using System.Collections.Generic; using System.IO; using M17N; @@ -6,103 +7,142 @@ using M17N.Core; namespace M17N.Core { + internal class MGlob + { + static readonly char sep = Path.DirectorySeparatorChar; + + public static void FileList (ref List files, + string dir, string pattern) + { + int len = pattern.Length; + + if (Path.IsPathRooted (pattern)) + { + int headsep = 0; + int i; + + for (i = 1; i < len && (pattern[i] != '*' && pattern[i] != '?'); i++) + if (pattern[i] == sep) + headsep = i; + if (i == len) + { + if (File.Exists (pattern)) + files.Add (new FileInfo (pattern)); + return; + } + dir = pattern.Substring (0, headsep); + pattern = pattern.Substring (headsep + 1); + } + else + { + if (dir == null) + dir = Directory.GetCurrentDirectory (); + } + if (Directory.Exists (dir)) + list (ref files, new DirectoryInfo (dir), pattern); + } + + private static void list (ref List files, + DirectoryInfo dirinfo, string pattern) + { + int len = pattern.Length; + int i; + + for (i = 0; i < len && pattern[i] != sep; i++); + try { + if (i == len) + { + FileInfo[] listing = dirinfo.GetFiles (pattern); + foreach (FileInfo elt in listing) + files.Add (elt); + } + else + { + string tail = pattern.Substring (i + 1); + pattern = pattern.Substring (0, i); + DirectoryInfo[] listing = dirinfo.GetDirectories (pattern); + foreach (DirectoryInfo elt in listing) + list (ref files, elt, tail); + } + } catch { + } + } + } + internal class MDatabaseDir { private const string ListFileName = "mdb.dir"; public string Dirname; public DirectoryInfo DirInfo; + public DateTime DirChangeTime; public FileInfo ListInfo; - public DateTime LastScanned; + public DateTime ListChangeTime; 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; - } - } + DirChangeTime = ListChangeTime = DateTime.Now; } - public bool CheckStatus () + public void Refresh () { 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; + if (Dirname != null && Directory.Exists (Dirname)) + { + DirInfo.Refresh (); + if (DirChangeTime < DirInfo.LastWriteTime) + DirChangeTime = DirInfo.LastWriteTime; } else { - try { - ListInfo = DirInfo.GetFiles (ListFileName)[0]; - return true; - } catch { - ListInfo = null; - } + DirInfo = null; + DirChangeTime = DateTime.Now; } - return (LastScanned < DirInfo.LastWriteTime - || (ListInfo != null - && LastScanned < ListInfo.LastWriteTime)); } else { if (Dirname != null && Directory.Exists (Dirname)) { DirInfo = new DirectoryInfo (Dirname); + DirChangeTime = DateTime.Now; + } + } + if (DirInfo == null) + { + if (ListInfo != null) + { + ListInfo = null; + ListChangeTime = DateTime.Now; + } + } + else + { + if (ListInfo != null) + { + ListInfo.Refresh (); + if (ListChangeTime < ListInfo.LastWriteTime) + ListChangeTime = ListInfo.LastWriteTime; + } + else + { try { ListInfo = DirInfo.GetFiles (ListFileName)[0]; + ListChangeTime = DateTime.Now; } 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 + public class MDatabase : IComparable { - /// Tags to identify a MDatabase. - public struct Tag + /// Identifier of a MDatabase. + public struct Tag : IEquatable { - public MSymbol[] Tags; + private MSymbol[] Tags; public Tag (MSymbol tag0) { @@ -128,68 +168,200 @@ namespace M17N.Core Tags[0] = tag0; Tags[1] = tag1; Tags[2] = tag2; Tags[3] = tag3; } - public bool Match (Tag tag) + public Tag (ref MPlist plist) + { + Tags = new MSymbol[4]; + + for (int i = 0; i < 4; i++) + { + if (plist.IsSymbol) + { + Tags[i] = plist.Symbol; + plist = plist.Next; + } + else + Tags[i] = MSymbol.nil; + } + } + + public bool Equals (Tag tag) { for (int i = 0; i < 4; i++) - { - if (tag.Tags[i] == Mwildcard || Tags[i] == Mwildcard) - return true; - if (tag.Tags[i] != Tags[i]) - return false; - } + if (tag[i] != Tags[i]) + return false; return true; } + public override int GetHashCode () + { + return (Tags[0].GetHashCode () ^ Tags[1].GetHashCode () + ^ Tags[2].GetHashCode () ^ Tags[3].GetHashCode ()); + } + public override string ToString () { return ("<" + Tags[0] + "," + Tags[1] + "," + Tags[2] + "," + Tags[3] + ">"); } + + public MSymbol this[int i] + { + set { Tags[i] = value; } + get { return Tags[i]; } + } + + public bool Match (Tag tag) + { + for (int i = 0; i < 4; i++) + { + if (tag[i] == Mwildcard || Tags[i] == Mwildcard) + return true; + if (tag[i] != Tags[i]) + return false; + } + return true; + } + + public bool HasWildcard { + get { + for (int i = 0; i < 4; i++) + if (Tags[i] == Mwildcard) + return true; + return false; + } + } } public delegate object Loader (Tag tag, object extra_info); - internal class MDatabaseInfo { - // -2: absolute, -1: unknown 0: DBDirs[0], 1: DBDirs[1], 2: DBDirs[2] - internal int DirIndex; + internal class MDatabaseInfo + { + // These come from the declartion plist of the database. internal string Description; internal string Filename; - internal FileInfo FileInfo; internal FileInfo Validater; internal int Version; internal MSymbol Format; internal MSymbol Schema; internal string SchemaFile; - internal DateTime ModifiedTime; internal MPlist Props; public MDatabaseInfo () { Format = Schema = MSymbol.nil; - DirIndex = -1; + } + + private static int parse_version (MPlist plist) + { + string[] str; + int major, minor, release; + + if (! plist.IsMText) + return 0xFFFFFF; + str = plist.Text.ToString ().Split ('.'); + if (str.Length != 3) + return 0xFFFFFF; + try { major = int.Parse (str[0]); } catch { return 0xFFFFFF; } + try { minor = int.Parse (str[1]); } catch { return 0xFFFFFF; } + try { release = int.Parse (str[2]); } catch { return 0xFFFFFF; } + return ((major << 16) | (minor << 8) | release); + } + + public MDatabaseInfo (MPlist plist) + { + Format = MSymbol.plist; + if (plist.IsMText) + { + Filename = plist.Text.ToString (); + plist = plist.Next; + } + else if (plist.IsPlist) + { + MPlist p = plist.Plist; + + if (p.IsMText) + Filename = p.Text.ToString (); + p = p.Next; + if (! p.IsEmpty) + { + if (p.IsSymbol) + Format = p.Symbol; + p = p.Next; + if (! p.IsEmpty) + { + if (p.IsSymbol) + Schema = p.Symbol; + p = p.Next; + if (p.IsMText) + SchemaFile = p.Text.ToString (); + } + } + plist = plist.Next; + } + + Version = 0; + Props = new MPlist (); + foreach (MPlist pl in plist) + { + if (pl.IsPlist) + { + MPlist p = pl.Plist; + + if (p.IsSymbol && p.Symbol == Mversion) + Version = parse_version (p.Next); + else + Props.Put (pl.Key, pl.Val); + } + else if (pl.IsSymbol) + { + MPlist p = new MPlist (); + p.Add (MSymbol.symbol, pl.Symbol); + p.Add (MSymbol.symbol, MSymbol.t); + Props.Put (MSymbol.plist, p); + } + } + } + + public void Merge (MDatabaseInfo src) + { + if (Validater == null) + Validater = src.Validater; + if (Version == 0) + Version = src.Version; + if (Format == MSymbol.nil) + Format = src.Format; + if (Schema == MSymbol.nil) + Schema = src.Schema; + if (SchemaFile == null) + SchemaFile = src.SchemaFile; + foreach (MPlist p in src.Props) + if (Props.Assq (p.Plist.Symbol) == null) + Props.Push (p.Key, p.Val); } public override string ToString () { - string str = ("#"; } } - private static Dictionary DBDict - = new Dictionary (); + // Dictionaries for normal databases. + private static Dictionary> ndict + = new Dictionary> (); - private static Dictionary DBDictMulti - = new Dictionary (); + // Dictionaries for databases of DBType WILDCARD + private static Dictionary> wdict + = new Dictionary> (); - private static MDatabaseDir[] DBDirs = new MDatabaseDir[3]; + private static MDatabaseDir[] DBDirs = new MDatabaseDir[4]; - private static readonly MSymbol Mversion = MSymbol.Of ("version"); + private static DateTime LastUpdateTime = new DateTime (0); + 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"); @@ -218,28 +390,37 @@ namespace M17N.Core /// Status of database private enum MDBStatus { - // The database file is currently disabled. It means that the - // database file is not readable or the database is deleted by - // the modification of "mdb.dir". + // The database file has not yet been decided, or is not yet + // expanded if DBType is WILDCARD. + NOT_READY, + // The database file was decided, or has been expanded if + // DBType is WILDCARD. + READY, + // The database is disabled. It means that the database file + // is not readable, the version is not supported by the + // current system, or the validation was failed. DISABLED, - // The database file has not yet been loaded, or was modified - // after the previous loading. - OUTDATED, - // The database file has not been modified after the previous - // loading. - UPDATED, - // The database file is updated but the validation was failed - // or the version is not supported by the current system. + // The database is deleted by the modificaiton of mdb.dir, or + // is overwritten by a new explicit definition.. INVALID, }; public Tag tag; private Loader loader; private object ExtraInfo; + // Directory of the database file. + // -1:unknown, 0:absolute, 1:DBDirs[1], 2:DBDirs[2], 3:DBDirs[3] + private int DirIndex; + // Directory of the mdb.dir defining the database file. + // 0: EXPLICIT or UNKNOWN, 1:DBDirs[1], 2:DBDirs[2], 3:DBDirs[3] + private int ListIndex; private MDBType DBType; private MDBStatus DBStatus; - internal DateTime LoadedTime; internal MDatabaseInfo Info; + // File in which the database contents is stored. + internal FileInfo FileInfo; + // When the database file is checked (or validated). + internal DateTime CheckedTime; static MDatabase () { @@ -249,63 +430,137 @@ namespace M17N.Core (Environment.SpecialFolder.ApplicationData)); try { - DBDirs[0] = new MDatabaseDir (Path.Combine (usr_dir, ".m17n.d")); - } catch (ArgumentException) { - DBDirs[0] = new MDatabaseDir (Path.Combine (usr_dir, "_m17n_d")); + string dir = Environment.GetEnvironmentVariable ("M17NDIR"); + DBDirs[1] = new MDatabaseDir (dir); + } catch { + try { + DBDirs[1] = new MDatabaseDir (Path.Combine (usr_dir, ".m17n.d")); + } catch (ArgumentException) { + DBDirs[1] = new MDatabaseDir (Path.Combine (usr_dir, "_m17n_d")); + } } - DBDirs[1] = new MDatabaseDir (null); - DBDirs[2] = new MDatabaseDir (Path.Combine (share_dir, "m17n")); + DBDirs[2] = new MDatabaseDir (null); + DBDirs[3] = new MDatabaseDir (Path.Combine (share_dir, "m17n")); + update_all (); } public static string ApplicationDir - { get { return (DBDirs[1].Dirname); } - set { DBDirs[1].Dirname = value; DBDirs[1].CheckStatus (); } } + { + get { return (DBDirs[1].Dirname); } + set { DBDirs[2] = new MDatabaseDir (value); update_all (); } + } - private static bool update_database_directories () + private static bool update_all () { bool updated = false; - for (int i = 0; i < 3; i++) - if (DBDirs[i].CheckStatus ()) + + for (int i = 1; i < 4; i++) + if (DBDirs[i].Dirname != null) { - delete_databases (i); - if (DBDirs[i].ListInfo != null) - update_databases (i); - updated = true; + DBDirs[i].Refresh (); + if (LastUpdateTime < DBDirs[i].ListChangeTime) + { + update_list (i); + updated = true; + } + if (LastUpdateTime < DBDirs[i].DirChangeTime) + { + update_dir (i); + updated = true; + } } + LastUpdateTime = DateTime.Now; return updated; } - public static void ListDirs () + public static void Dump () { - update_database_directories (); - for (int i = 0; i < 3; i++) + update_all (); + Console.WriteLine ("[DBDirs]"); + for (int i = 1; i < 4; i++) if (DBDirs[i].Dirname != null) { - Console.Write ("{0}:{1}", i, DBDirs[i].Dirname); if (DBDirs[i].DirInfo != null) { + Console.Write ("{0}:{1}", i, DBDirs[i].DirInfo.FullName); if (DBDirs[i].ListInfo != null) Console.WriteLine (" {0}", DBDirs[i].ListInfo); else - Console.WriteLine (".. no mdb.dir"); + Console.WriteLine (" .. no mdb.dir"); } else - Console.WriteLine (".. not exist"); + Console.WriteLine ("{0}:{1} .. not exist", i, DBDirs[i].Dirname); } + + Console.WriteLine ("[WDICT]"); + foreach (KeyValuePair> kv in wdict) + foreach (MDatabase mdb in kv.Value) + Console.WriteLine (mdb); + + Console.WriteLine ("[NDITCT]"); + foreach (KeyValuePair> kv in ndict) + foreach (MDatabase mdb in kv.Value) + Console.WriteLine (mdb); } - private void register (int priority) + private static void register (MDatabase mdb) { - Dictionary dict - = DBType == MDBType.WILDCARD ? DBDictMulti : DBDict; - MDatabase[] mdbs; + Dictionary> dict + = mdb.DBType == MDBType.WILDCARD ? wdict : ndict; + List mdbs; - if (! dict.TryGetValue (tag, out mdbs)) + if (dict.TryGetValue (mdb.tag, out mdbs)) + { + for (int i = 0; i < mdbs.Count; i++) + if (mdbs[i].ListIndex == mdb.ListIndex) + { + mdbs[i].DBStatus = MDBStatus.INVALID; + mdbs[i] = mdb; + return; + } + mdbs.Add (mdb); + } + else { - mdbs = new MDatabase[4]; - dict.Add (tag, mdbs); + mdbs = new List (1); + mdbs.Add (mdb); + dict.Add (mdb.tag, mdbs); } - mdbs[priority] = this; + } + + private static void register (int list_idx, int dir_idx, + Tag tag, MDatabaseInfo info) + { + List mdbs; + MDatabase mdb; + + if (ndict.TryGetValue (tag, out mdbs)) + for (int i = 0; i < mdbs.Count; i++) + { + mdb = mdbs[i]; + if (mdb.ListIndex == list_idx + && (dir_idx > 0 && dir_idx <= mdb.DirIndex)) + { + if (mdb.DBStatus == MDBStatus.INVALID) + M17n.DebugPrint ("registering: {0}\n", mdb); + else + M17n.DebugPrint ("updating: {0}\n", mdb); + if (mdb.DBStatus != MDBStatus.DISABLED) + mdb.DBStatus = (dir_idx < 0 + ? MDBStatus.NOT_READY : MDBStatus.READY); + mdb.DirIndex = dir_idx; + mdb.Info = info; + return; + } + } + else + { + mdbs = new List (1); + ndict.Add (tag, mdbs); + } + mdb = new MDatabase (list_idx, dir_idx, tag, info); + M17n.DebugPrint ("registering: {0}\n", mdb); + mdbs.Add (mdb); } public MDatabase (Tag tag, Loader loader, object extra_info) @@ -313,134 +568,84 @@ namespace M17N.Core this.tag = tag; this.loader = loader; DBType = MDBType.UNKNOWN; - DBStatus = MDBStatus.UPDATED; + DBStatus = MDBStatus.READY; + DirIndex = 0; + ListIndex = 0; ExtraInfo = extra_info; - this.register (0); + register (this); } public MDatabase (Tag tag, string filename) { this.tag = tag; DBType = MDBType.EXPLICIT; - DBStatus = MDBStatus.OUTDATED; - Info = new MDatabaseInfo (); - Info.Filename = filename; - Info.DirIndex = Path.IsPathRooted (filename) ? -2 : -1; - this.register (0); - } - - private MDatabase (MPlist plist, int priority) - { - tag = new Tag (MSymbol.nil); - DBType = MDBType.AUTO; - DBStatus = MDBStatus.OUTDATED; - for (int i = 0; plist.IsSymbol; i++, plist = plist.Next) + if (Path.IsPathRooted (filename)) { - if (DBType == MDBType.WILDCARD) - tag.Tags[i] = MSymbol.nil; - else - { - tag.Tags[i] = plist.Symbol; - if (tag.Tags[i] == Mwildcard) - DBType = MDBType.WILDCARD; - } + DirIndex = 0; + DBStatus = MDBStatus.READY; } - - 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.ToString (); - plist = plist.Next; + DirIndex = -1; + DBStatus = MDBStatus.NOT_READY; } - else if (plist.IsPlist) - { - MPlist p = plist.Plist; + ListIndex = 0; + Info = new MDatabaseInfo (); + Info.Filename = filename; + register (this); + } - if (p.IsMText) - Info.Filename = plist.Text.ToString (); - p = p.Next; - if (! p.IsEmpty) - { - if (p.IsSymbol) - Info.Format = p.Symbol; - p = p.Next; - if (! p.IsEmpty) - { - if (p.IsSymbol) - Info.Schema = p.Symbol; - p = p.Next; - if (p.IsMText) - Info.SchemaFile = p.Text.ToString (); - } - } - plist = plist.Next; - } + private MDatabase (int list_idx, int dir_idx, Tag tag, MDatabaseInfo info) + { + this.tag = tag; + this.Info = info; + DBType = this.tag.HasWildcard ? MDBType.WILDCARD : MDBType.AUTO; + if (this.tag[0] == Mchar_table || this.tag[0] == Mcharset) + Info.Format = this.tag[0]; + ListIndex = list_idx; + DirIndex = dir_idx; + if (Path.IsPathRooted (Info.Filename)) + DBStatus = MDBStatus.READY; 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) - { - if (pl.IsPlist) - { - MPlist p = pl.Plist; - - if (p.IsSymbol && p.Symbol == Mversion) - { - Info.Version = parse_version (p.Next); - if (M17n.Version < Info.Version) - DBStatus = MDBStatus.DISABLED; - } - } - Info.Props.Put (pl.Key, pl.Val); - } - this.register (priority); + DBStatus = MDBStatus.NOT_READY; } public override String ToString () { - string str = "#"; } - private static int parse_version (MPlist plist) + // Update (or disable) databases defined by "mdb.dir" in + // DBDirs[list_idx]. + private static void update_list (int list_idx) { - string[] str; - int major, minor, release; - - if (! plist.IsMText) - return 0xFFFFFF; - str = plist.Text.ToString ().Split ('.'); - if (str.Length != 3) - return 0xFFFFFF; - try { major = int.Parse (str[0]); } catch { return 0xFFFFFF; } - try { minor = int.Parse (str[1]); } catch { return 0xFFFFFF; } - try { release = int.Parse (str[2]); } catch { return 0xFFFFFF; } - return ((major << 16) | (minor << 8) | release); - } + // At first disable all target databases. + foreach (KeyValuePair> kv in wdict) + foreach (MDatabase mdb in kv.Value) + if (mdb.ListIndex == list_idx) + { + M17n.DebugPrint ("deleting: {0}\n", mdb); + mdb.DBStatus = MDBStatus.INVALID; + break; + } + foreach (KeyValuePair> kv in ndict) + foreach (MDatabase mdb in kv.Value) + if (mdb.ListIndex == list_idx) + { + M17n.DebugPrint ("deleting: {0}\n", mdb); + mdb.DBStatus = MDBStatus.INVALID; + break; + } - private static void delete_databases (int list_idx) - { - foreach (KeyValuePair item in DBDict) - item.Value[list_idx + 1] = null; - foreach (KeyValuePair item in DBDictMulti) - item.Value[list_idx + 1] = null; - } + FileInfo dblist = DBDirs[list_idx].ListInfo; + if (dblist == null) + return; - 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)) { MStreamReader reader = new MStreamReader (stream); @@ -449,56 +654,149 @@ namespace M17N.Core if (plist == null) return; foreach (MPlist pl in plist) + if (pl.IsPlist) + { + try + { + MPlist p = pl.Plist; + Tag tag = new Tag (ref p); + MDatabaseInfo info = new MDatabaseInfo (p); + int dir_idx = Path.IsPathRooted (info.Filename) ? 0 : -1; + register (list_idx, dir_idx, tag, info); + } + catch (Exception e) + { + Console.WriteLine (e.Message + ": " + pl.Plist); + } + } + } + + // Update (or disable) databases in DBDirs[dir_idx]. + private static void update_dir (int dir_idx) + { + // Reset all databases in DBDirs[dir_idx]. + foreach (KeyValuePair> kv in ndict) + foreach (MDatabase mdb in kv.Value) + if (mdb.DirIndex >= dir_idx) + { + M17n.DebugPrint ("disabling: {0}\n", mdb); + mdb.DBStatus = MDBStatus.NOT_READY; + mdb.DirIndex = -1; + } + // Re-expand all WILDCARD databases in DBDirs[dir_idx]. + if (DBDirs[dir_idx].DirInfo != null) + foreach (KeyValuePair> kv in wdict) + foreach (MDatabase mdb in kv.Value) + if (mdb.DBStatus == MDBStatus.READY) + { + M17n.DebugPrint ("re-expanding: {0}\n", mdb); + register_files (DBDirs[dir_idx].Dirname, mdb.ListIndex, + dir_idx, mdb.Info); + } + } + + private static void register_files (string dir, int list_idx, int dir_idx, + MDatabaseInfo base_info) + { + List files = new List (); + MGlob.FileList (ref files, dir, base_info.Filename); + foreach (FileInfo fileinfo in files) { - if (! pl.IsPlist) - continue; - try + MPlist plist = null; + using (FileStream stream = fileinfo.OpenRead ()) { - new MDatabase (pl.Plist, list_idx + 1); + MStreamReader reader = new MStreamReader (stream); + plist = new MPlist (reader, 1); } - catch (Exception e) + if (plist != null && plist.IsPlist) { - Console.WriteLine (e.Message); + plist = plist.Plist; + Tag tag = new Tag (ref plist); + + if (! tag.HasWildcard && tag.Match (tag)) + { + MDatabaseInfo info = new MDatabaseInfo (plist); + info.Merge (base_info); + if (Path.IsPathRooted (base_info.Filename)) + info.Filename = fileinfo.FullName; + else + info.Filename = fileinfo.Name; + register (list_idx, dir_idx, tag, info); + } } } } - private void expand_wildcard (int priority) + private void expand_wildcard () { - if (Info.DirIndex == -2) - { - - } + M17n.DebugPrint ("expanding: {0}\n", this); + + if (DirIndex == 0) + register_files (null, ListIndex, DirIndex, Info); + else + for (int i = 1; i < 4; i++) + if (DBDirs[i].DirInfo != null) + register_files (DBDirs[i].DirInfo.FullName, ListIndex, i, Info); + DBStatus = MDBStatus.READY; + } + private static void maybe_expand_wildcard (Tag tag) + { + foreach (KeyValuePair> kv in wdict) + if (kv.Key.Match (tag)) + foreach (MDatabase mdb in kv.Value) + if (mdb.DBStatus == MDBStatus.NOT_READY) + mdb.expand_wildcard (); + } + + private bool check_file () + { + if (DBDirs[DirIndex].DirInfo == null) + return false; + FileInfo[] files = DBDirs[DirIndex].DirInfo.GetFiles (Info.Filename); + if (files.Length == 0) + return false; + FileInfo = files[0]; + return true; } - private void update_status () + private bool find_file () { - if (Info.DirIndex == -2) + if (DirIndex == 0) { + } + return true; } public static MDatabase Find (Tag tag) { - MDatabase[] mdbs; + List mdbs; MDatabase mdb = null; - if (DBDict.TryGetValue (tag, out mdbs)) + if (tag.HasWildcard) + throw new ArgumentException ("Wildcard not allowed: " + tag); + + if (ndict.TryGetValue (tag, out mdbs)) { - if (mdbs[0] != null) - return mdbs[0]; - for (int i = 1; i < 4; i++) - if ((mdb = mdbs[i]) != null) - break; + mdbs.Sort (); + for (int i = 0; i < mdbs.Count; i++) + { + mdb = mdbs[i]; + if (mdb.ListIndex == 0) + return mdb; + if (mdb.DBStatus == MDBStatus.READY) + break; + } } - if (! update_database_directories ()) + if (! update_all () && mdb != null) return mdb; - if (! DBDict.TryGetValue (tag, out mdbs)) + maybe_expand_wildcard (tag); + if (! ndict.TryGetValue (tag, out mdbs)) return null; - for (int i = 1; i < 4; i++) - if (mdbs[i] != null) - return mdbs[i]; + for (int i = 0; i < mdbs.Count; i++) + if ((mdb = mdbs[i]).check_file ()) + return mdb; return null; } @@ -506,48 +804,30 @@ namespace M17N.Core { List list = new List (); - update_database_directories (); - foreach (KeyValuePair item in DBDictMulti) - if (item.Key.Match (tag)) - for (int j = 0; j < 4; j++) - if (item.Value[j] != null) - if (item.Value[j].DBStatus == MDBStatus.OUTDATED) - item.Value[j].expand_wildcard (j); + update_all (); + maybe_expand_wildcard (tag); - int i; - for (i = 0; i < 4 && tag.Tags[i] == Mwildcard; i++); - if (i == 4) + if (tag.HasWildcard) { - // No wildcard. - MDatabase[] mdbs; - 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; - } - } + foreach (KeyValuePair> kv in ndict) + if (kv.Key.Match (tag)) + foreach (MDatabase mdb in kv.Value) + if (mdb.check_file ()) + { + list.Add (mdb); + break; + } } else { - // With wildcard. We must scan all databases. - foreach (KeyValuePair 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; - } - } + List mdbs; + if (ndict.TryGetValue (tag, out mdbs)) + foreach (MDatabase mdb in mdbs) + if (mdb.check_file ()) + { + list.Add (mdb); + break; + } } return list; } @@ -567,9 +847,15 @@ namespace M17N.Core private object load (MSymbol key, MSymbol stop) { - LoadedTime = DateTime.UtcNow; - return null; } + + // For IComparable + public int CompareTo (MDatabase other) + { + return (ListIndex == other.ListIndex + ? DirIndex - other.DirIndex + : ListIndex - other.ListIndex); + } } } \ No newline at end of file diff --git a/MPlist.cs b/MPlist.cs index f607bc7..8a040ec 100644 --- a/MPlist.cs +++ b/MPlist.cs @@ -30,6 +30,53 @@ namespace M17N.Core next = new MPlist (reader); } + public MPlist (MStreamReader reader, int count) + { + MSymbol key; + object val; + bool result = reader.ReadElement (out key, out val); + + Key = key; + Val = val; + if (result && --count > 0) + next = new MPlist (reader, count); + else + next = new MPlist (); + } + + public MPlist (MStreamReader reader, MSymbol target, MSymbol stop) + { + MSymbol key; + object val; + bool result; + + Key = MSymbol.nil; + Val = null; + while (true) + { + result = reader.ReadElement (out key, out val); + if (! result) + return; + if (key == MSymbol.plist) + { + MPlist plist = (MPlist) val; + + if (plist.IsSymbol) + { + if (plist.Symbol == stop) + return; + if (plist.Symbol == target) + { + Key = target; + Val = val; + next = new MPlist (); + return; + } + } + } + } + } + private MPlist (MSymbol key, object val) { Key = key; @@ -112,6 +159,14 @@ namespace M17N.Core return find (key).Val; } + internal MPlist Assq (MSymbol key) + { + foreach (MPlist p in this) + if (p.IsPlist && p.Plist.IsSymbol && p.Plist.Symbol == key) + return p; + return null; + } + private delegate MPlist MPlistDelegate (MSymbol key, object val); private MPlist mplist_op (MPlistDelegate op, object val) @@ -372,7 +427,7 @@ namespace M17N.Core { int c = Peek (); - if (c == -1 || c == '(' || c == ' ' || c == '\n' || c == '"') + if (c == -1 || c == '(' || c == ')' || c == ' ' || c == '\n' || c == '"') return ""; Read (); if (c == '\\') diff --git a/MSymbol.cs b/MSymbol.cs index 4aeffb4..c41fda9 100644 --- a/MSymbol.cs +++ b/MSymbol.cs @@ -66,7 +66,8 @@ namespace M17N.Core foreach (char c in Name) { - if (c == '\\' || c == ' ' || c == '\'' || c == '\"' || c == ':') + if (c == '\\' || c == ' ' || c == '\'' || c == '\"' + || c == '(' || c == ')') str += "\\"; str += c; } diff --git a/database.cs b/database.cs index cc0f258..ce44154 100644 --- a/database.cs +++ b/database.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.IO; using M17N; using M17N.Core; @@ -9,12 +10,20 @@ public class Test { M17n.debug = true; MDatabase.ApplicationDir = "/usr/local/share/m17n"; + MDatabase.Tag tag = new MDatabase.Tag (MSymbol.Of ("input-method"), + MSymbol.t, + MSymbol.Of ("unicode")); + DirectoryInfo dirinfo = new DirectoryInfo ("/home/handa/.m17n.d"); - MDatabase.ListDirs (); - List mdb_list - = MDatabase.List (new MDatabase.Tag (MSymbol.Of ("*"))); - Console.WriteLine ("Total {0} databases:", mdb_list.Count); - foreach (MDatabase db in mdb_list) - Console.WriteLine (db); + while (true) + { + Console.Write ("mdb> "); + string str = Console.ReadLine (); + if (str == null || str == "quit" || str == "exit") + break; + dirinfo.Refresh (); + Console.WriteLine (dirinfo.LastWriteTimeUtc + + ":" + MDatabase.Find (tag)); + } } } -- 1.7.10.4