2 using System.Collections.Generic;
9 public delegate object MDatabaseLoader (MDatabaseTag tag,
12 public struct MDatabaseTag
14 public MSymbol Tag0, Tag1, Tag2, Tag3;
16 public MDatabaseTag (MSymbol tag0)
18 Tag0 = tag0; Tag1 = Tag2 = Tag3 = MSymbol.nil;
21 public MDatabaseTag (MSymbol tag0, MSymbol tag1)
23 Tag0 = tag0; Tag1 = tag1; Tag2 = Tag3 = MSymbol.nil;
26 public MDatabaseTag (MSymbol tag0, MSymbol tag1, MSymbol tag2)
28 Tag0 = tag0; Tag1 = tag1; Tag2 = tag2; Tag3 = MSymbol.nil;
31 public MDatabaseTag (MSymbol tag0, MSymbol tag1,
32 MSymbol tag2, MSymbol tag3)
34 Tag0 = tag0; Tag1 = tag1; Tag2 = tag2; Tag3 = tag3;
38 public class MDatabase
40 private class MDatabaseDir
42 private const string ListFileName = "mdb.dir";
44 public string Dirname;
45 public DirectoryInfo DirInfo;
46 public DateTime LastScanned;
47 public FileInfo ListInfo;
49 private static void GetInfo (string dirname, out DirectoryInfo dirinfo,
50 out FileInfo listinfo)
52 if (Directory.Exists (dirname))
53 try { dirinfo = new DirectoryInfo (dirname);
54 try { listinfo = dirinfo.GetFiles (ListFileName)[0];
55 } catch { listinfo = null; }
56 } catch { dirinfo = null; listinfo = null; }
64 public MDatabaseDir (string dirname)
67 GetInfo (dirname, out DirInfo, out ListInfo);
70 public bool StatusChanged {
72 bool exists = Directory.Exists (Dirname);
80 LastScanned = new DateTime (0);
82 if (LastScanned.Year == 0)
87 return (LastScanned < DirInfo.LastWriteTime
88 || LastScanned < ListInfo.LastWriteTime);
94 DirInfo = new DirectoryInfo (Dirname);
96 ListInfo = DirInfo.GetFiles (ListFileName)[0];
107 public void UpdateStatus ()
110 LastScanned = DateTime.UtcNow;
113 public FileInfo[] Scan (string filename)
118 return DirInfo.GetFiles (filename);
122 internal class MDatabaseInfo {
123 internal DirectoryInfo Dir;
124 internal string Description;
125 internal MText Filename;
126 internal FileInfo FileInfo;
127 internal FileInfo Validater;
128 internal int Version;
129 internal MSymbol Format;
130 internal MSymbol Schema;
131 internal MText SchemaFile;
132 internal DateTime ModifiedTime;
133 internal MPlist Props;
136 private static Dictionary<MDatabaseTag, MDatabase> DBDict
137 = new Dictionary<MDatabaseTag, MDatabase> ();
139 private static MDatabaseDir[] DBDirs = new MDatabaseDir[3];
141 private const string SystemDirectory = "/usr/share/m17n";
142 private readonly MSymbol Mversion = new MSymbol ("version");
147 /// The database was defined automatically from mdb.dir
148 /// file(s) with no wildcard tag.
150 /// The database was defined automatically from mdb.dir
151 /// file(s) with a wildcard tag to define multiple databases
152 /// of the same kind.
154 /// The database was defined explicitely by MDatabase.Define
155 /// without a special loader.
157 /// The database was defined explicitely by MDatabase.Define
158 /// with a special loader.
162 /// Status of database
163 private enum MDBStatus
165 // The database file is currently disabled. It means that the
166 // database file is not readable or the database is deleted by
167 // the modification of "mdb.dir".
169 // The database file has not yet been loaded, or was modified
170 // after the previous loading.
172 // The database file has not been modified after the previous
175 // The database file is updated but the validation was failed
176 // or the version is not supported by the current system.
180 public readonly MDatabaseTag Tag;
181 private MDatabaseLoader Loader;
182 private object ExtraInfo;
183 private MDBType DBType;
184 private MDBStatus DBStatus;
185 internal DateTime LoadedTime;
186 internal MDatabaseInfo Info;
188 public static string ApplicationDirectory;
190 private MDatabase (MDatabaseTag tag, MDatabaseLoader loader,
195 ExtraInfo = extra_info;
198 private MDatabase (MDatabaseTag tag, string filename)
201 Info = new MDatabaseInfo ();
202 Info.Filename = new MText (filename);
205 private MDatabase (MPlist plist)
207 MSymbol[] tags = new MSymbol[4];
210 for (i = 0; plist.IsSymbol; i++, plist = plist.Next)
211 tags[i] = plist.Symbol;
213 tags[i++] = MSymbol.nil;
214 Tag = new MDatabaseTag (tags[0], tags[1], tags[2], tags[3]);
217 Info.Filename = plist.Text;
220 else if (plist.IsPlist)
222 MPlist p = plist.Plist;
225 Info.Filename = plist.Text;
230 Info.Format = p.Symbol;
235 Info.Schema = p.Symbol;
238 Info.SchemaFile = p.Text;
243 DBStatus = MDBStatus.OUTDATED;;
245 Info.Props = new MPlist ();
246 foreach (MPlist pl in plist)
252 if (p.IsSymbol && p.Symbol == Mversion)
254 Info.Version = parse_version (p.Next);
255 if (M17n.Version < Info.Version)
256 DBStatus = MDBStatus.DISABLED;
259 Info.Props.Put (pl.Key, pl.Val);
263 private static int parse_version (MPlist plist)
266 int major, minor, release;
270 str = plist.Text.ToString ().Split ('.');
273 try { major = int.Parse (str[0]); } catch { return 0xFFFFFF; }
274 try { minor = int.Parse (str[1]); } catch { return 0xFFFFFF; }
275 try { release = int.Parse (str[2]); } catch { return 0xFFFFFF; }
276 return ((major << 16) | (minor << 8) | release);
279 public static MDatabase Define (MDatabaseTag tag, MDatabaseLoader loader,
282 MDatabase db = MDatabase.Find (tag);
287 db.ExtraInfo = extra_info;
288 db.DBType = MDBType.EXPLICIT;
289 db.DBStatus = MDBStatus.OUTDATED;
293 return new MDatabase (tag, loader, extra_info);
296 public static MDatabase Define (MDatabaseTag tag, string filename)
298 MDatabase db = MDatabase.Find (tag);
303 db.DBType = MDBType.EXPLICIT;
304 db.DBStatus = MDBStatus.OUTDATED;
305 db.Info = new MDatabaseInfo ();
306 db.Info.Filename = new MText (filename);
310 return new MDatabase (tag, filename);
315 string share_dir = (Environment.GetFolderPath
316 (Environment.SpecialFolder.CommonApplicationData));
317 string usr_dir = (Environment.GetFolderPath
318 (Environment.SpecialFolder.ApplicationData));
321 DBDirs[0] = new MDatabaseDir (Path.Combine (usr_dir, ".m17n.d"));
322 } catch (ArgumentException) {
323 DBDirs[0] = new MDatabaseDir (Path.Combine (usr_dir, "_m17n_d"));
326 DBDirs[2] = new MDatabaseDir (Path.Combine (share_dir, "m17n"));
329 public static MDatabase Find (MDatabaseTag tag)
333 return (DBDict.TryGetValue (tag, out db) ? db : null);
336 public object Load ()
338 return (Loader != null ? Loader (Tag, ExtraInfo)
339 : load (MSymbol.nil, MSymbol.nil));
342 public object Load (MSymbol key, MSymbol stop)
346 return load (key, stop);
349 private object load (MSymbol key, MSymbol stop)
351 LoadedTime = DateTime.UtcNow;