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 object 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 ()
259 Format = Schema = MSymbol.nil;
262 private static int parse_version (MPlist plist)
265 int major, minor, release;
269 str = plist.Text.ToString ().Split ('.');
272 try { major = int.Parse (str[0]); } catch { return 0xFFFFFF; }
273 try { minor = int.Parse (str[1]); } catch { return 0xFFFFFF; }
274 try { release = int.Parse (str[2]); } catch { return 0xFFFFFF; }
275 return ((major << 16) | (minor << 8) | release);
278 public MDatabaseInfo (MPlist plist)
280 Format = MSymbol.nil;
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 ()
972 || (Info.Format != MSymbol.plist && Info.Format != Mxml))
974 LastLoadStatus = LoadStatus.InvalidLoadMethod;
977 if (DBStatus != MDBStatus.READY)
979 LastLoadStatus = LoadStatus.NotAvailable;
983 FileStream stream = null;
985 stream = FileInfo.OpenRead ();
987 LastLoadStatus = LoadStatus.NotReadable;
992 public object Load ()
995 return loader (tag, ExtraInfo);
996 if (Info.Format == Mxml)
998 XmlDocument doc = new XmlDocument ();
1000 XmlReader reader = XmlReader.Create (FileInfo.FullName);
1002 LastLoaded = DateTime.Now;
1003 } catch (Exception e) {
1004 Console.WriteLine (e);
1005 LastLoadStatus = LoadStatus.InvalidContents;
1010 FileStream stream = get_stream ();
1013 MPlist plist = null;
1015 plist = new MPlist (stream);
1016 LastLoaded = DateTime.Now;
1018 LastLoadStatus = LoadStatus.InvalidContents;
1025 public object Load (MSymbol key, MSymbol stop)
1027 FileStream stream = get_stream ();
1031 if (Info.Format == Mxml)
1033 XmlDocument doc = new XmlDocument ();
1034 XmlTextReader reader = new XmlTextReader (stream);
1036 reader.WhitespaceHandling = WhitespaceHandling.None;
1039 while (reader.NodeType != XmlNodeType.Element)
1041 doc.LoadXml ("<" + reader.Name + "></" + reader.Name + ">");
1043 XmlNode node = doc.DocumentElement;
1044 while (reader.NodeType == XmlNodeType.Element
1045 ? reader.Name != stop.Name
1046 : reader.NodeType != XmlNodeType.EndElement)
1047 if (reader.NodeType == XmlNodeType.Element
1048 && reader.Name == key.Name)
1049 node = doc.DocumentElement.InsertAfter (doc.ReadNode (reader),
1058 MPlist plist = null;
1060 plist = new MPlist (stream, key, stop);
1061 LastLoaded = DateTime.Now;
1063 LastLoadStatus = LoadStatus.InvalidContents;
1070 public object Load (MSymbol stop)
1072 FileStream stream = get_stream ();
1076 if (Info.Format == Mxml)
1078 XmlDocument doc = new XmlDocument ();
1079 XmlTextReader reader = new XmlTextReader (stream);
1081 reader.WhitespaceHandling = WhitespaceHandling.None;
1084 while (reader.NodeType != XmlNodeType.Element)
1086 doc.LoadXml ("<" + reader.Name + "></" + reader.Name + ">");
1088 XmlNode node = null;
1089 while (reader.NodeType == XmlNodeType.Element
1090 ? reader.Name != stop.Name
1091 : reader.NodeType != XmlNodeType.EndElement)
1092 if (reader.NodeType == XmlNodeType.Element)
1093 node = doc.DocumentElement.InsertAfter (doc.ReadNode (reader),
1095 } catch (Exception e) {
1096 Console.WriteLine (e);
1104 MPlist plist = null;
1106 plist = new MPlist (stream, stop);
1107 LastLoaded = DateTime.Now;
1108 } catch (Exception e) {
1109 Console.WriteLine (e);
1110 LastLoadStatus = LoadStatus.InvalidContents;
1117 public XmlNode Load (string id, params string[] nodes)
1119 FileStream stream = get_stream ();
1122 if (Info.Format != Mxml)
1123 throw new Exception ("Not an XML format");
1125 XmlDocument doc = new XmlDocument ();
1126 XmlTextReader reader = new XmlTextReader (stream);
1127 int len = nodes.Length;
1129 reader.WhitespaceHandling = WhitespaceHandling.None;
1132 } while (reader.NodeType != XmlNodeType.Element);
1134 if (reader.Name != nodes[0])
1137 string ns = reader.GetAttribute ("xmlns");
1138 XmlNode top = doc.CreateNode (XmlNodeType.Element, nodes[0], ns);
1144 for (i = 1; i + 1 < len; i++)
1146 if (! reader.ReadToDescendant (nodes[i]))
1148 node = node.InsertAfter (doc.CreateNode (XmlNodeType.Element,
1149 nodes[i], ns), null);
1151 if (! reader.ReadToDescendant (nodes[i]))
1153 XmlNode ref_node = null;
1154 while (reader.NodeType != XmlNodeType.EndElement)
1156 if (reader.NodeType == XmlNodeType.Element)
1158 if (reader.Name == nodes[i]
1159 && (id == null || id == reader.GetAttribute ("id")))
1160 ref_node = node.InsertAfter (doc.ReadNode (reader), ref_node);
1168 } catch (Exception e) {
1169 Console.WriteLine (e);
1177 /// <summary>Return a list of currently available database
1178 /// directory names</summary>.
1179 public static string[] DirectoryList ()
1181 List<string> dirs = new List<string> ();
1183 for (int i = 1; i < 4; i++)
1184 if (DBDirs[i].Dirname != null)
1185 dirs.Add (DBDirs[i].Dirname);
1186 return dirs.ToArray ();
1189 public MSymbol Format { get { return Info.Format; } }
1191 public static bool Changed (DateTime time)
1194 return (time < LastUpdateTime);
1197 public bool NeedReload ()
1199 return update_status ();
1202 // For IComparable<MDatabase>
1203 public int CompareTo (MDatabase other)
1205 return (ListIndex == other.ListIndex
1206 ? DirIndex - other.DirIndex
1207 : ListIndex - other.ListIndex);