Tag0 = tag0; Tag1 = tag1; Tag2 = tag2; Tag3 = MSymbol.nil;
}
- public MDatabaseTag (MSymbol tag0, MSymbol tag1, MSymbol tag2, MSymbol tag3)
+ public MDatabaseTag (MSymbol tag0, MSymbol tag1,
+ MSymbol tag2, MSymbol tag3)
{
Tag0 = tag0; Tag1 = tag1; Tag2 = tag2; Tag3 = tag3;
}
public class MDatabase
{
+ 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)
+ {
+ if (Directory.Exists (dirname))
+ try { dirinfo = new DirectoryInfo (dirname);
+ try { listinfo = dirinfo.GetFiles (ListFileName)[0];
+ } catch { listinfo = null; }
+ } catch { dirinfo = null; listinfo = null; }
+ else
+ {
+ 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;
+ }
+ 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);
+ }
+ }
+
+ internal class MDatabaseInfo {
+ internal DirectoryInfo Dir;
+ internal string Description;
+ internal MText Filename;
+ internal FileInfo FileInfo;
+ internal FileInfo Validater;
+ internal int Version;
+ internal MSymbol Format;
+ internal MSymbol Schema;
+ internal MText SchemaFile;
+ internal DateTime ModifiedTime;
+ internal MPlist Props;
+ }
+
+ private static Dictionary<MDatabaseTag, MDatabase> DBDict
+ = new Dictionary<MDatabaseTag, MDatabase> ();
+
+ private static MDatabaseDir[] DBDirs = new MDatabaseDir[3];
+
+ private const string SystemDirectory = "/usr/share/m17n";
+ private readonly MSymbol Mversion = MSymbol.Of ("version");
+
/// 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 mdb.dir
+ /// file(s) 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 mdb.dir
+ /// file(s) with a wildcard tag to define multiple databases
/// of the same kind.
- AUTO_WILDCARD,
- /// The database was defined explicitely (by MDatabaseDefine).
- EXPLICIT
+ MULTIPLE,
+ /// The database was defined explicitely by MDatabase.Define
+ /// without a special loader.
+ EXPLICIT,
+ /// The database was defined explicitely by MDatabase.Define
+ /// with a special loader.
+ UNKNOWN,
};
/// Status of database
// The database file has not been modified after the previous
// loading.
UPDATED,
- // The database file is updated but the validation was failed.
- // If this is for a database directory, the directory is
- // readable but "mdb.dir" doesn't exist in it.
- INVALID
+ // The database file is updated but the validation was failed
+ // or the version is not supported by the current system.
+ INVALID,
};
- private static Dictionary<MDatabaseTag, MDatabase> db_dict
- = new Dictionary<MDatabaseTag, MDatabase> ();
-
- private MDatabaseTag tag;
- private MDatabaseLoader loader;
- private object extra_info;
-
- private bool system_database;
- private DirectoryInfo dir;
- private FileInfo file;
- private FileInfo validater;
- private int major_version, minor_version, release_number;
- private MDBType type;
- private MDBStatus status;
- private MSymbol format;
- private MSymbol schema;
- private DateTime mtime;
- private DateTime ltime;
- private MPlist props;
+ public readonly MDatabaseTag Tag;
+ private MDatabaseLoader Loader;
+ private object ExtraInfo;
+ private MDBType DBType;
+ private MDBStatus DBStatus;
+ internal DateTime LoadedTime;
+ internal MDatabaseInfo Info;
public static string ApplicationDirectory;
- public MDatabase (MDatabaseTag tag, MDatabaseLoader loader,
+ private MDatabase (MDatabaseTag tag, MDatabaseLoader loader,
object extra_info)
{
- this.tag = tag;
- this.loader = loader;
- this.extra_info = extra_info;
+ Tag = tag;
+ Loader = loader;
+ ExtraInfo = extra_info;
}
- public MDatabase (MDatabaseTag tag, string filename)
+ private MDatabase (MDatabaseTag tag, string filename)
{
- this.tag = tag;
- this.loader = load;
+ Tag = tag;
+ Info = new MDatabaseInfo ();
+ Info.Filename = new MText (filename);
}
- public MDatabaseTag Tag { get { return tag; } }
+ private MDatabase (MPlist plist)
+ {
+ 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 MDatabaseTag (tags[0], tags[1], tags[2], tags[3]);
+ if (plist.IsMText)
+ {
+ Info.Filename = plist.Text;
+ plist = plist.Next;
+ }
+ else if (plist.IsPlist)
+ {
+ MPlist p = plist.Plist;
+
+ if (p.IsMText)
+ Info.Filename = plist.Text;
+ 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;
+ }
+ }
+ plist = plist.Next;
+ }
+ DBStatus = MDBStatus.OUTDATED;;
+ 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);
+ }
+ }
+
+ 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 static MDatabase Define (MDatabaseTag tag, MDatabaseLoader loader,
+ object extra_info)
+ {
+ MDatabase db = MDatabase.Find (tag);
+
+ if (db != null)
+ {
+ db.Loader = loader;
+ db.ExtraInfo = extra_info;
+ db.DBType = MDBType.EXPLICIT;
+ db.DBStatus = MDBStatus.OUTDATED;
+ db.Info = null;
+ return db;
+ }
+ return new MDatabase (tag, loader, extra_info);
+ }
+
+ public static MDatabase Define (MDatabaseTag tag, string filename)
+ {
+ MDatabase db = MDatabase.Find (tag);
+
+ if (db != null)
+ {
+ 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);
+ }
+
+ static MDatabase ()
+ {
+ string share_dir = (Environment.GetFolderPath
+ (Environment.SpecialFolder.CommonApplicationData));
+ string usr_dir = (Environment.GetFolderPath
+ (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"));
+ }
+ DBDirs[1] = null;
+ DBDirs[2] = new MDatabaseDir (Path.Combine (share_dir, "m17n"));
+ }
public static MDatabase Find (MDatabaseTag tag)
{
MDatabase db;
- return (db_dict.TryGetValue (tag, out db) ? db : null);
+ return (DBDict.TryGetValue (tag, out db) ? db : null);
}
public object Load ()
{
- return loader (tag, extra_info);
+ return (Loader != null ? Loader (Tag, ExtraInfo)
+ : load (MSymbol.nil, MSymbol.nil));
+ }
+
+ public object Load (MSymbol key, MSymbol stop)
+ {
+ if (Loader != null)
+ return null;
+ return load (key, stop);
}
- private object load (MDatabaseTag tag, object extra_info)
+ private object load (MSymbol key, MSymbol stop)
{
- ltime = DateTime.Now;
+ LoadedTime = DateTime.UtcNow;
+
+
+
return null;
}