using System;
+using System.Collections;
using System.Collections.Generic;
using System.IO;
using M17N;
namespace M17N.Core
{
+ internal class MGlob
+ {
+ static readonly char sep = Path.DirectorySeparatorChar;
+
+ public static void FileList (ref List<FileInfo> 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<FileInfo> 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<MDatabase>
{
- /// Tags to identify a MDatabase.
- public struct Tag
+ /// Identifier of a MDatabase.
+ public struct Tag : IEquatable<Tag>
{
- public MSymbol[] Tags;
+ private MSymbol[] Tags;
public Tag (MSymbol tag0)
{
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 = ("#<Info " + Format + " \"" + Filename
- + "\" (" + DirIndex + ")");
+ string str = ("#<Info " + Format + " \"" + Filename + "\"");
if (Schema != MSymbol.nil)
str += " " + Schema;
return str + ">";
}
}
- private static Dictionary<MDatabase.Tag, MDatabase[]> DBDict
- = new Dictionary<MDatabase.Tag, MDatabase[]> ();
+ // Dictionaries for normal databases.
+ private static Dictionary<MDatabase.Tag, List<MDatabase>> ndict
+ = new Dictionary<MDatabase.Tag, List<MDatabase>> ();
- private static Dictionary<MDatabase.Tag, MDatabase[]> DBDictMulti
- = new Dictionary<MDatabase.Tag, MDatabase[]> ();
+ // Dictionaries for databases of DBType WILDCARD
+ private static Dictionary<MDatabase.Tag, List<MDatabase>> wdict
+ = new Dictionary<MDatabase.Tag, List<MDatabase>> ();
- 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");
/// 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 ()
{
(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<Tag, List<MDatabase>> kv in wdict)
+ foreach (MDatabase mdb in kv.Value)
+ Console.WriteLine (mdb);
+
+ Console.WriteLine ("[NDITCT]");
+ foreach (KeyValuePair<Tag, List<MDatabase>> kv in ndict)
+ foreach (MDatabase mdb in kv.Value)
+ Console.WriteLine (mdb);
}
- private void register (int priority)
+ private static void register (MDatabase mdb)
{
- Dictionary<MDatabase.Tag, MDatabase[]> dict
- = DBType == MDBType.WILDCARD ? DBDictMulti : DBDict;
- MDatabase[] mdbs;
+ Dictionary<MDatabase.Tag, List<MDatabase>> dict
+ = mdb.DBType == MDBType.WILDCARD ? wdict : ndict;
+ List<MDatabase> 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<MDatabase> (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<MDatabase> 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<MDatabase> (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)
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 = "#<MDataBase " + tag + " " + DBType + " " + DBStatus;
+ string str = ("#<MDataBase (" + ListIndex + "," + DirIndex + ") "
+ + tag + " " + DBType + " " + DBStatus);
if (DBType != MDBType.EXPLICIT && DBType != MDBType.UNKNOWN)
str += " " + Info;
return 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<Tag, List<MDatabase>> 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<Tag, List<MDatabase>> 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<Tag, MDatabase[]> item in DBDict)
- item.Value[list_idx + 1] = null;
- foreach (KeyValuePair<Tag, MDatabase[]> 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);
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<Tag, List<MDatabase>> 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<Tag, List<MDatabase>> 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<FileInfo> files = new List<FileInfo> ();
+ 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<Tag, List<MDatabase>> 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<MDatabase> 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;
}
{
List<MDatabase> list = new List<MDatabase> ();
- update_database_directories ();
- foreach (KeyValuePair<Tag, MDatabase[]> 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<Tag, List<MDatabase>> 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<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;
- }
- }
+ List<MDatabase> mdbs;
+ if (ndict.TryGetValue (tag, out mdbs))
+ foreach (MDatabase mdb in mdbs)
+ if (mdb.check_file ())
+ {
+ list.Add (mdb);
+ break;
+ }
}
return list;
}
private object load (MSymbol key, MSymbol stop)
{
- LoadedTime = DateTime.UtcNow;
-
return null;
}
+
+ // For IComparable<MDatabase>
+ public int CompareTo (MDatabase other)
+ {
+ return (ListIndex == other.ListIndex
+ ? DirIndex - other.DirIndex
+ : ListIndex - other.ListIndex);
+ }
}
}
\ No newline at end of file