2 using System.Collections;
3 using System.Collections.Generic;
14 static readonly char sep = Path.DirectorySeparatorChar;
16 public static void FileList (ref List<FileInfo> files,
17 string dir, string pattern)
19 int len = pattern.Length;
21 if (Path.IsPathRooted (pattern))
26 for (i = 1; i < len && (pattern[i] != '*' && pattern[i] != '?'); i++)
27 if (pattern[i] == sep)
31 if (File.Exists (pattern))
32 files.Add (new FileInfo (pattern));
35 dir = pattern.Substring (0, headsep);
36 pattern = pattern.Substring (headsep + 1);
41 dir = Directory.GetCurrentDirectory ();
43 if (Directory.Exists (dir))
44 list (ref files, new DirectoryInfo (dir), pattern);
47 private static void list (ref List<FileInfo> files,
48 DirectoryInfo dirinfo, string pattern)
50 int len = pattern.Length;
53 M17n.DebugPrint ("Listing {0} in {1} ...", pattern, dirinfo);
54 for (i = 0; i < len && pattern[i] != sep; i++);
58 FileInfo[] listing = dirinfo.GetFiles (pattern);
60 foreach (FileInfo elt in listing)
65 string tail = pattern.Substring (i + 1);
66 pattern = pattern.Substring (0, i);
67 DirectoryInfo[] listing = dirinfo.GetDirectories (pattern);
70 foreach (DirectoryInfo elt in listing)
71 list (ref files, elt, tail);
75 M17n.DebugPrint (" found {0} files\n", i);
79 internal class MDatabaseDir
81 private const string ListFileName = "mdb.dir";
83 public string Dirname;
84 public DirectoryInfo DirInfo;
85 public DateTime DirChangeTime;
86 public FileInfo ListInfo;
87 public DateTime ListChangeTime;
89 public MDatabaseDir (string dirname)
92 DirChangeTime = ListChangeTime = DateTime.Now;
95 public void Refresh ()
99 if (Dirname != null && Directory.Exists (Dirname))
102 if (DirChangeTime < DirInfo.LastWriteTime)
103 DirChangeTime = DirInfo.LastWriteTime;
108 DirChangeTime = DateTime.Now;
113 if (Dirname != null && Directory.Exists (Dirname))
115 DirInfo = new DirectoryInfo (Dirname);
116 DirChangeTime = DateTime.Now;
121 if (ListInfo != null)
124 ListChangeTime = DateTime.Now;
129 if (ListInfo != null)
132 if (ListChangeTime < ListInfo.LastWriteTime)
133 ListChangeTime = ListInfo.LastWriteTime;
138 ListInfo = DirInfo.GetFiles (ListFileName)[0];
139 ListChangeTime = DateTime.Now;
147 public partial class MDatabase : IComparable<MDatabase>
149 /// Identifier of a MDatabase.
150 public struct Tag : IEquatable<Tag>
152 private MSymbol[] Tags;
154 public Tag (MSymbol tag0)
156 Tags = new MSymbol[4];
157 Tags[0] = tag0; Tags[1] = Tags[2] = Tags[3] = MSymbol.nil;
160 public Tag (MSymbol tag0, MSymbol tag1)
162 Tags = new MSymbol[4];
163 Tags[0] = tag0; Tags[1] = tag1; Tags[2] = Tags[3] = MSymbol.nil;
166 public Tag (MSymbol tag0, MSymbol tag1, MSymbol tag2)
168 Tags = new MSymbol[4];
169 Tags[0] = tag0; Tags[1] = tag1; Tags[2] = tag2; Tags[3] = MSymbol.nil;
172 public Tag (MSymbol tag0, MSymbol tag1, MSymbol tag2, MSymbol tag3)
174 Tags = new MSymbol[4];
175 Tags[0] = tag0; Tags[1] = tag1; Tags[2] = tag2; Tags[3] = tag3;
178 public Tag (ref MPlist plist)
180 Tags = new MSymbol[4];
182 for (int i = 0; i < 4; i++)
186 Tags[i] = plist.Symbol;
190 Tags[i] = MSymbol.nil;
194 public bool Equals (Tag tag)
196 for (int i = 0; i < 4; i++)
197 if (tag[i] != Tags[i])
202 public override int GetHashCode ()
204 return (Tags[0].GetHashCode () ^ Tags[1].GetHashCode ()
205 ^ Tags[2].GetHashCode () ^ Tags[3].GetHashCode ());
208 public override string ToString ()
211 + Tags[0] + "," + Tags[1] + "," + Tags[2] + "," + Tags[3]
215 public MSymbol this[int i]
217 set { Tags[i] = value; }
218 get { return Tags[i]; }
221 public bool Match (Tag tag)
223 for (int i = 0; i < 4; i++)
225 if (tag[i] == Mwildcard || Tags[i] == Mwildcard)
227 if (tag[i] != Tags[i])
233 public bool HasWildcard {
235 for (int i = 0; i < 4; i++)
236 if (Tags[i] == Mwildcard)
243 public delegate MPlist Loader (Tag tag, object extra_info);
245 internal class MDatabaseInfo
247 // These come from the declartion plist of the database.
248 internal string Description;
249 internal string Filename;
250 internal FileInfo Validater;
251 internal int Version;
252 internal MSymbol Format;
253 internal MSymbol Schema;
254 internal string SchemaFile;
255 internal MPlist Props;
257 public MDatabaseInfo ()
260 Format = Schema = MSymbol.nil;
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 MDatabaseInfo (MPlist plist) : this ()
283 Format = MSymbol.plist;
284 Filename = plist.Text.ToString ();
287 else if (plist.IsPlist)
289 MPlist p = plist.Plist;
293 Filename = p.Text.ToString ();
307 SchemaFile = p.Text.ToString ();
312 Props = new MPlist ();
313 foreach (MPlist pl in plist)
319 if (p.IsSymbol && p.Symbol == Mversion)
320 Version = parse_version (p.Next);
322 Props.Put (pl.Key, pl.Val);
324 else if (pl.IsSymbol)
326 MPlist p = new MPlist ();
327 p.Add (MSymbol.symbol, pl.Symbol);
328 p.Add (MSymbol.symbol, MSymbol.t);
329 Props.Put (MSymbol.plist, p);
334 public void Merge (MDatabaseInfo src)
336 if (Validater == null)
337 Validater = src.Validater;
339 Version = src.Version;
340 if (Format == MSymbol.nil)
342 if (Schema == MSymbol.nil)
344 if (SchemaFile == null)
345 SchemaFile = src.SchemaFile;
346 foreach (MPlist p in src.Props)
347 if (Props.Assq (p.Plist.Symbol) == null)
348 Props.Push (p.Key, p.Val);
351 public override string ToString ()
353 string str = ("#<Info " + Format + " \"" + Filename + "\"");
354 if (Schema != MSymbol.nil)
360 // Dictionaries for normal databases.
361 private static Dictionary<MDatabase.Tag, List<MDatabase>> ndict
362 = new Dictionary<MDatabase.Tag, List<MDatabase>> ();
364 // Dictionaries for databases of DBType WILDCARD
365 private static Dictionary<MDatabase.Tag, List<MDatabase>> wdict
366 = new Dictionary<MDatabase.Tag, List<MDatabase>> ();
368 private static MDatabaseDir[] DBDirs = new MDatabaseDir[4];
370 private static DateTime LastUpdateTime = new DateTime (0);
372 private static readonly MSymbol Mversion = "version";
373 private static readonly MSymbol Mwildcard = "*";
374 private static readonly MSymbol Mchar_table = "char-table";
375 private static readonly MSymbol Mcharset = "charset";
376 private static readonly MSymbol Mxml = "xml";
378 private static TimeSpan CheckInterval = new TimeSpan (50000000);
383 /// The database was defined automatically from one of mdb.dir
384 /// files with no wildcard tag.
386 /// The database was defined automatically from one of mdb.dir
387 /// files with a wildcard tag to define multiple databases
388 /// of the same kind.
390 /// The database was defined explicitely by MDatabase.Define
391 /// to use the normal loader.
393 /// The database was defined explicitely by MDatabase.Define
394 /// to use a special loader.
396 /// The database is for defining multiple databases of the
397 /// same kind with a wildcard tag.
401 /// Status of database
402 private enum MDBStatus
404 // The database file has not yet been decided, or is not yet
405 // expanded if DBType is WILDCARD.
407 // The database file was decided, or has been expanded if
408 // DBType is WILDCARD.
410 // The database is disabled. It means that the database file
411 // is not readable, the version is not supported by the
412 // current system, or the validation was failed.
414 // The database is deleted by the modificaiton of mdb.dir, or
415 // is overwritten by a new explicit definition.
420 private Loader loader;
421 private object ExtraInfo;
422 // Directory of the database file.
423 // -1:unknown, 0:absolute, 1:DBDirs[1], 2:DBDirs[2], 3:DBDirs[3]
424 private int DirIndex;
425 // Directory of the mdb.dir defining the database file.
426 // 0: EXPLICIT or UNKNOWN, 1:DBDirs[1], 2:DBDirs[2], 3:DBDirs[3]
427 private int ListIndex;
428 private MDBType DBType;
429 private MDBStatus DBStatus;
430 internal MDatabaseInfo Info;
431 // File in which the database contents is stored. This is null
432 // when DBStatus is NOT_READY.
433 internal FileInfo FileInfo;
434 // When the database file is loaded last.
435 internal DateTime LastLoaded = DateTime.Now;
437 public enum LoadStatus
446 public LoadStatus LastLoadStatus = LoadStatus.None;
450 string share_dir = (Environment.GetFolderPath
451 (Environment.SpecialFolder.CommonApplicationData));
452 string usr_dir = (Environment.GetFolderPath
453 (Environment.SpecialFolder.ApplicationData));
456 string dir = Environment.GetEnvironmentVariable ("M17NDIR");
457 DBDirs[1] = new MDatabaseDir (dir);
460 DBDirs[1] = new MDatabaseDir (Path.Combine (usr_dir, ".m17n.d"));
461 } catch (ArgumentException) {
462 DBDirs[1] = new MDatabaseDir (Path.Combine (usr_dir, "_m17n_d"));
465 DBDirs[2] = new MDatabaseDir (null);
466 DBDirs[3] = new MDatabaseDir (Path.Combine (share_dir, "m17n"));
470 public static string ApplicationDir
472 get { return (DBDirs[1].Dirname); }
473 set { DBDirs[2] = new MDatabaseDir (value); update_all (true); }
476 // Update all listing and directories. Return true iff some are
478 private static bool update_all (bool force)
480 if (! force && DateTime.Now - LastUpdateTime < CheckInterval)
483 bool updated = false;
484 for (int i = 1; i < 4; i++)
485 if (DBDirs[i].Dirname != null)
487 DBDirs[i].Refresh ();
488 if (LastUpdateTime < DBDirs[i].ListChangeTime)
493 if (LastUpdateTime < DBDirs[i].DirChangeTime)
500 LastUpdateTime = DateTime.Now;
504 public static void Dump ()
507 Console.WriteLine ("[DBDirs]");
508 for (int i = 1; i < 4; i++)
509 if (DBDirs[i].Dirname != null)
511 if (DBDirs[i].DirInfo != null)
513 Console.Write ("{0}:{1}", i, DBDirs[i].DirInfo.FullName);
514 if (DBDirs[i].ListInfo != null)
515 Console.WriteLine (" {0}", DBDirs[i].ListInfo);
517 Console.WriteLine (" .. no mdb.dir");
520 Console.WriteLine ("{0}:{1} .. not exist", i, DBDirs[i].Dirname);
523 Console.WriteLine ("[WDICT]");
524 foreach (KeyValuePair<Tag, List<MDatabase>> kv in wdict)
525 foreach (MDatabase mdb in kv.Value)
526 Console.WriteLine (mdb);
528 Console.WriteLine ("[NDICT]");
529 foreach (KeyValuePair<Tag, List<MDatabase>> kv in ndict)
530 foreach (MDatabase mdb in kv.Value)
531 Console.WriteLine (mdb);
534 private static void register (MDatabase mdb)
536 Dictionary<MDatabase.Tag, List<MDatabase>> dict
537 = mdb.DBType == MDBType.WILDCARD ? wdict : ndict;
538 List<MDatabase> mdbs;
540 if (dict.TryGetValue (mdb.tag, out mdbs))
542 for (int i = 0; i < mdbs.Count; i++)
543 if (mdbs[i].ListIndex == mdb.ListIndex)
545 mdbs[i].DBStatus = MDBStatus.INVALID;
553 mdbs = new List<MDatabase> (1);
555 dict.Add (mdb.tag, mdbs);
559 private static void register (int list_idx, int dir_idx,
560 Tag tag, MDatabaseInfo info)
562 Dictionary<MDatabase.Tag, List<MDatabase>> dict
563 = tag.HasWildcard ? wdict : ndict;
564 List<MDatabase> mdbs;
567 if (dict.TryGetValue (tag, out mdbs))
568 for (int i = 0; i < mdbs.Count; i++)
571 if (mdb.ListIndex == list_idx && mdb.DirIndex >= dir_idx)
573 mdb.DirIndex = dir_idx;
576 mdb.DBType = MDBType.WILDCARD;
577 mdb.DBStatus = MDBStatus.NOT_READY;
579 else if (dir_idx == -1)
581 mdb.DBType = MDBType.AUTO;
582 mdb.DBStatus = MDBStatus.NOT_READY;
586 mdb.DBType = MDBType.MULTIPLE;
587 mdb.DBStatus = MDBStatus.READY;
590 if (mdb.DBStatus == MDBStatus.INVALID)
591 M17n.DebugPrint ("registering: {0}\n", mdb);
593 M17n.DebugPrint ("updating: {0}\n", mdb);
599 mdbs = new List<MDatabase> (1);
600 dict.Add (tag, mdbs);
602 mdb = new MDatabase (list_idx, dir_idx, tag, info);
603 M17n.DebugPrint ("registering: {0}\n", mdb);
607 public MDatabase (Tag tag, Loader loader, object extra_info)
610 this.loader = loader;
611 DBType = MDBType.UNKNOWN;
612 DBStatus = MDBStatus.READY;
615 ExtraInfo = extra_info;
619 public MDatabase (Tag tag, string filename)
622 DBType = MDBType.EXPLICIT;
623 if (Path.IsPathRooted (filename))
626 if (File.Exists (filename))
627 DBStatus = MDBStatus.READY;
629 DBStatus = MDBStatus.INVALID;
634 DBStatus = MDBStatus.NOT_READY;
637 Info = new MDatabaseInfo ();
638 Info.Filename = filename;
642 private MDatabase (int list_idx, int dir_idx, Tag tag, MDatabaseInfo info)
646 DBType = this.tag.HasWildcard ? MDBType.WILDCARD : MDBType.AUTO;
647 if (tag[0] == Mchar_table || tag[0] == Mcharset)
648 Info.Format = tag[0];
649 ListIndex = list_idx;
651 if (Path.IsPathRooted (Info.Filename))
652 DBStatus = MDBStatus.READY;
654 DBStatus = MDBStatus.NOT_READY;
655 if (Info.Format == Mchar_table)
656 MCharProp.Define (tag[2], this);
659 public override String ToString () {
660 string str = ("#<MDataBase (" + ListIndex + "," + DirIndex + ") "
661 + tag + " " + DBType + " " + DBStatus);
663 if (DBType != MDBType.EXPLICIT && DBType != MDBType.UNKNOWN)
668 // Update (or disable) databases defined by "mdb.dir" in
670 private static void update_list (int list_idx)
672 M17n.DebugPrint ("Updating list: {0}\n", list_idx);
673 // At first disable all target databases.
674 foreach (KeyValuePair<Tag, List<MDatabase>> kv in wdict)
675 foreach (MDatabase mdb in kv.Value)
676 if (mdb.ListIndex == list_idx)
678 M17n.DebugPrint ("deleting: {0}\n", mdb);
679 mdb.DBStatus = MDBStatus.INVALID;
682 foreach (KeyValuePair<Tag, List<MDatabase>> kv in ndict)
683 foreach (MDatabase mdb in kv.Value)
684 if (mdb.ListIndex == list_idx)
686 M17n.DebugPrint ("deleting: {0}\n", mdb);
687 mdb.DBStatus = MDBStatus.INVALID;
691 FileInfo dblist = DBDirs[list_idx].ListInfo;
696 using (FileStream stream = File.OpenRead (dblist.FullName))
698 plist = new MPlist (stream);
702 foreach (MPlist pl in plist)
708 Tag tag = new Tag (ref p);
709 MDatabaseInfo info = new MDatabaseInfo (p);
710 int dir_idx = Path.IsPathRooted (info.Filename) ? 0 : -1;
711 register (list_idx, dir_idx, tag, info);
715 Console.WriteLine (e.Message + ": " + pl.Plist);
720 // Update (or disable) databases in DBDirs[dir_idx].
721 private static void update_dir (int dir_idx)
723 M17n.DebugPrint ("Updating dir: {0}\n", dir_idx);
724 // Reset all databases in DBDirs[dir_idx].
725 foreach (KeyValuePair<Tag, List<MDatabase>> kv in ndict)
726 foreach (MDatabase mdb in kv.Value)
727 if (mdb.DirIndex >= dir_idx)
729 M17n.DebugPrint ("disabling: {0}\n", mdb);
730 mdb.DBStatus = MDBStatus.NOT_READY;
733 // Re-expand all WILDCARD databases in DBDirs[dir_idx].
734 if (DBDirs[dir_idx].DirInfo != null)
735 foreach (KeyValuePair<Tag, List<MDatabase>> kv in wdict)
736 foreach (MDatabase mdb in kv.Value)
737 if (mdb.DBStatus == MDBStatus.READY)
739 M17n.DebugPrint ("re-expanding: {0}\n", mdb);
740 register_files (DBDirs[dir_idx].Dirname, dir_idx, mdb);
744 private static bool parse_plist_header (FileInfo fileinfo, MDatabase mdb,
745 out Tag tag, out MDatabaseInfo info)
749 tag = new Tag (MSymbol.nil);
751 using (FileStream stream = fileinfo.OpenRead ())
753 try { plist = new MPlist (stream, 1); } catch { }
755 if (plist == null || ! plist.IsPlist)
758 tag = new Tag (ref plist);
759 if (tag.HasWildcard || ! tag.Match (mdb.tag))
761 info = new MDatabaseInfo (plist);
765 private static bool parse_xml_header (FileInfo fileinfo, MDatabase mdb,
766 out Tag tag, out MDatabaseInfo info)
768 tag = new Tag (MSymbol.nil);
770 using (FileStream stream = fileinfo.OpenRead ())
773 MPlist plist = new MPlist ();
774 XmlTextReader reader = new XmlTextReader (stream);
776 reader.WhitespaceHandling = WhitespaceHandling.None;
779 } while (reader.NodeType != XmlNodeType.Element);
780 plist.Add (MSymbol.symbol, (MSymbol) reader.Name);
782 if (reader.NodeType == XmlNodeType.Element && reader.Name == "tags")
785 while (reader.NodeType == XmlNodeType.Element)
788 plist.Add (MSymbol.symbol, (MSymbol) reader.Value);
792 tag = new Tag (ref plist);
793 if (tag.HasWildcard || ! tag.Match (mdb.tag))
795 info = new MDatabaseInfo (plist);
798 } catch (Exception e) {
799 Console.WriteLine ("error {0}", e);
805 private static void register_files (string dir, int dir_idx, MDatabase mdb)
807 int list_idx = mdb.ListIndex;
808 List<FileInfo> files = new List<FileInfo> ();
809 MGlob.FileList (ref files, dir, mdb.Info.Filename);
810 foreach (FileInfo fileinfo in files)
815 if (mdb.Info.Format == MSymbol.plist
816 ? parse_plist_header (fileinfo, mdb, out tag, out info)
817 : parse_xml_header (fileinfo, mdb, out tag, out info))
819 info.Merge (mdb.Info);
820 if (Path.IsPathRooted (mdb.Info.Filename))
821 info.Filename = fileinfo.FullName;
823 info.Filename = fileinfo.Name;
824 register (list_idx, dir_idx, tag, info);
829 private void expand_wildcard ()
831 M17n.DebugPrint ("expanding: {0}\n", this);
834 register_files (null, DirIndex, this);
836 for (int i = 1; i < 4; i++)
837 if (DBDirs[i].DirInfo != null)
838 register_files (DBDirs[i].DirInfo.FullName, i, this);
839 DBStatus = MDBStatus.READY;
842 private static void maybe_expand_wildcard (Tag tag)
844 foreach (KeyValuePair<Tag, List<MDatabase>> kv in wdict)
846 M17n.DebugPrint ("expand check: {0}\n", kv.Key);
847 if (kv.Key.Match (tag))
849 foreach (MDatabase mdb in kv.Value)
851 if (mdb.DBStatus == MDBStatus.NOT_READY)
852 mdb.expand_wildcard ();
858 // Update the status. Return true iff the database file is
859 // readable but changed.
861 private bool update_status ()
863 if (DBType == MDBType.UNKNOWN)
866 if (DBStatus == MDBStatus.INVALID)
868 if (DBStatus != MDBStatus.NOT_READY)
873 DBStatus = MDBStatus.INVALID;
876 if (LastLoaded >= FileInfo.LastWriteTime)
878 DBStatus = MDBStatus.READY;
881 for (int i = 1; i < 4; i++)
882 if (DBDirs[i] != null && DBDirs[i].Dirname != null)
884 string filename = Path.Combine (DBDirs[i].Dirname, Info.Filename);
885 if (File.Exists (filename))
887 FileInfo = new FileInfo (filename);
889 DBStatus = MDBStatus.READY;
896 public static MDatabase Find (Tag tag)
898 List<MDatabase> mdbs;
899 MDatabase mdb = null;
902 throw new ArgumentException ("Wildcard not allowed: " + tag);
904 if (ndict.TryGetValue (tag, out mdbs))
907 for (int i = 0; i < mdbs.Count; i++)
910 if (mdb.ListIndex == 0)
912 if (mdb.DBStatus == MDBStatus.READY)
916 if (! update_all (false) && mdb != null)
918 maybe_expand_wildcard (tag);
919 if (! ndict.TryGetValue (tag, out mdbs))
921 for (int i = 0; i < mdbs.Count; i++)
924 mdb.update_status ();
925 if (mdb.DBStatus == MDBStatus.READY)
931 public static List<MDatabase> List (Tag tag)
933 List<MDatabase> list = new List<MDatabase> ();
936 maybe_expand_wildcard (tag);
940 foreach (KeyValuePair<Tag, List<MDatabase>> kv in ndict)
941 if (kv.Key.Match (tag))
942 foreach (MDatabase mdb in kv.Value)
944 mdb.update_status ();
945 if (mdb.DBStatus == MDBStatus.READY)
954 List<MDatabase> mdbs;
955 if (ndict.TryGetValue (tag, out mdbs))
956 foreach (MDatabase mdb in mdbs)
958 mdb.update_status ();
959 if (mdb.DBStatus == MDBStatus.READY)
969 private FileStream get_stream ()
971 if (DBStatus != MDBStatus.READY)
973 LastLoadStatus = LoadStatus.NotAvailable;
977 FileStream stream = null;
979 stream = FileInfo.OpenRead ();
981 LastLoadStatus = LoadStatus.NotReadable;
986 public MPlist Load ()
989 return loader (tag, ExtraInfo);
990 if (Info.Format != MSymbol.plist)
991 throw new Exception ("Not a plist database");
993 FileStream stream = get_stream ();
998 plist = new MPlist (stream);
999 LastLoaded = DateTime.Now;
1001 LastLoadStatus = LoadStatus.InvalidContents;
1008 public MPlist Load (MSymbol key, MSymbol stop)
1011 throw new Exception ("Partial load is impossible");
1012 if (Info.Format != MSymbol.plist)
1013 throw new Exception ("Not a plist database");
1015 FileStream stream = get_stream ();
1019 MPlist plist = new MPlist (stream, key, stop);
1020 LastLoaded = DateTime.Now;
1023 LastLoadStatus = LoadStatus.InvalidContents;
1030 public MPlist Load (MSymbol stop)
1033 throw new Exception ("Partial load is impossible");
1034 if (Info.Format != MSymbol.plist)
1035 throw new Exception ("Not a plist database");
1037 FileStream stream = get_stream ();
1041 MPlist plist = new MPlist (stream, stop);
1042 LastLoaded = DateTime.Now;
1044 } catch (Exception e) {
1045 Console.WriteLine (e);
1046 LastLoadStatus = LoadStatus.InvalidContents;
1053 private XmlTextReader get_reader (XmlDocument doc)
1055 XmlTextReader reader;
1058 if (doc.NameTable != null)
1059 reader = new XmlTextReader (FileInfo.FullName, doc.NameTable);
1061 reader = new XmlTextReader (FileInfo.FullName);
1062 reader.WhitespaceHandling = WhitespaceHandling.None;
1064 LastLoadStatus = LoadStatus.NotReadable;
1070 public bool Load (XmlDocument doc)
1072 if (Info.Format != Mxml)
1073 throw new Exception ("Not an XML database");
1074 XmlTextReader reader = get_reader (doc);
1079 LastLoaded = DateTime.Now;
1081 } catch (Exception e) {
1082 Console.WriteLine (e);
1083 LastLoadStatus = LoadStatus.InvalidContents;
1090 public bool Load (XmlDocument doc, MSymbol key, MSymbol stop)
1092 if (Info.Format != Mxml)
1093 throw new Exception ("Not an XML database");
1094 XmlTextReader reader = get_reader (doc);
1099 while (reader.NodeType != XmlNodeType.Element)
1101 doc.LoadXml ("<" + reader.Name + "></" + reader.Name + ">");
1103 XmlNode node = doc.DocumentElement;
1104 while (reader.NodeType == XmlNodeType.Element
1105 ? reader.Name != stop.Name
1106 : reader.NodeType != XmlNodeType.EndElement)
1107 if (reader.NodeType == XmlNodeType.Element
1108 && reader.Name == key.Name)
1109 node = doc.DocumentElement.InsertAfter (doc.ReadNode (reader),
1112 } catch (Exception e) {
1113 Console.WriteLine (e);
1120 public bool Load (XmlDocument doc, MSymbol stop)
1122 if (Info.Format != Mxml)
1123 throw new Exception ("Not an XML database");
1124 XmlTextReader reader = get_reader (doc);
1129 while (reader.NodeType != XmlNodeType.Element)
1131 doc.LoadXml ("<" + reader.Name + "></" + reader.Name + ">");
1133 XmlNode node = doc.DocumentElement;
1134 while (reader.NodeType == XmlNodeType.Element
1135 ? reader.Name != stop.Name
1136 : reader.NodeType != XmlNodeType.EndElement)
1137 node = doc.DocumentElement.InsertAfter (doc.ReadNode (reader), node);
1139 } catch (Exception e) {
1140 Console.WriteLine (e);
1147 public XmlNode Load (XmlDocument doc, string id, params string[] nodes)
1149 if (Info.Format != Mxml)
1150 throw new Exception ("Not an XML database");
1151 XmlTextReader reader = get_reader (doc);
1155 int len = nodes.Length;
1158 } while (reader.NodeType != XmlNodeType.Element);
1159 if (reader.Name != nodes[0])
1162 string ns = reader.GetAttribute ("xmlns");
1163 XmlNode top = doc.CreateNode (XmlNodeType.Element, nodes[0], ns);
1167 for (i = 1; i + 1 < len; i++)
1169 if (! reader.ReadToDescendant (nodes[i]))
1171 node = node.InsertAfter (doc.CreateNode (XmlNodeType.Element,
1172 nodes[i], ns), null);
1174 if (! reader.ReadToDescendant (nodes[i]))
1176 XmlNode ref_node = null;
1177 while (reader.NodeType != XmlNodeType.EndElement)
1179 if (reader.NodeType == XmlNodeType.Element)
1181 if (reader.Name == nodes[i]
1182 && (id == null || id == reader.GetAttribute ("id")))
1183 ref_node = node.InsertAfter (doc.ReadNode (reader), ref_node);
1191 } catch (Exception e) {
1192 Console.WriteLine (e);
1199 /// <summary>Return a list of currently available database
1200 /// directory names</summary>.
1201 public static string[] DirectoryList ()
1203 List<string> dirs = new List<string> ();
1205 for (int i = 1; i < 4; i++)
1206 if (DBDirs[i].Dirname != null)
1207 dirs.Add (DBDirs[i].Dirname);
1208 return dirs.ToArray ();
1211 public MSymbol Format { get { return Info.Format; } }
1213 public static bool Changed (DateTime time)
1216 return (time < LastUpdateTime);
1219 public bool NeedReload ()
1221 return update_status ();
1224 // For IComparable<MDatabase>
1225 public int CompareTo (MDatabase other)
1227 return (ListIndex == other.ListIndex
1228 ? DirIndex - other.DirIndex
1229 : ListIndex - other.ListIndex);