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 public NameTable name_table = new NameTable ();
421 private Loader loader;
422 private object ExtraInfo;
423 // Directory of the database file.
424 // -1:unknown, 0:absolute, 1:DBDirs[1], 2:DBDirs[2], 3:DBDirs[3]
425 private int DirIndex;
426 // Directory of the mdb.dir defining the database file.
427 // 0: EXPLICIT or UNKNOWN, 1:DBDirs[1], 2:DBDirs[2], 3:DBDirs[3]
428 private int ListIndex;
429 private MDBType DBType;
430 private MDBStatus DBStatus;
431 internal MDatabaseInfo Info;
432 // File in which the database contents is stored. This is null
433 // when DBStatus is NOT_READY.
434 internal FileInfo FileInfo;
435 // When the database file is loaded last.
436 internal DateTime LastLoaded = DateTime.Now;
438 public enum LoadStatus
447 public LoadStatus LastLoadStatus = LoadStatus.None;
451 string share_dir = (Environment.GetFolderPath
452 (Environment.SpecialFolder.CommonApplicationData));
453 string usr_dir = (Environment.GetFolderPath
454 (Environment.SpecialFolder.ApplicationData));
457 string dir = Environment.GetEnvironmentVariable ("M17NDIR");
458 DBDirs[1] = new MDatabaseDir (dir);
461 DBDirs[1] = new MDatabaseDir (Path.Combine (usr_dir, ".m17n.d"));
462 } catch (ArgumentException) {
463 DBDirs[1] = new MDatabaseDir (Path.Combine (usr_dir, "_m17n_d"));
466 DBDirs[2] = new MDatabaseDir (null);
467 DBDirs[3] = new MDatabaseDir (Path.Combine (share_dir, "m17n"));
471 public static string ApplicationDir
473 get { return (DBDirs[1].Dirname); }
474 set { DBDirs[2] = new MDatabaseDir (value); update_all (true); }
477 // Update all listing and directories. Return true iff some are
479 private static bool update_all (bool force)
481 if (! force && DateTime.Now - LastUpdateTime < CheckInterval)
484 bool updated = false;
485 for (int i = 1; i < 4; i++)
486 if (DBDirs[i].Dirname != null)
488 DBDirs[i].Refresh ();
489 if (LastUpdateTime < DBDirs[i].ListChangeTime)
494 if (LastUpdateTime < DBDirs[i].DirChangeTime)
501 LastUpdateTime = DateTime.Now;
505 public static void Dump ()
508 Console.WriteLine ("[DBDirs]");
509 for (int i = 1; i < 4; i++)
510 if (DBDirs[i].Dirname != null)
512 if (DBDirs[i].DirInfo != null)
514 Console.Write ("{0}:{1}", i, DBDirs[i].DirInfo.FullName);
515 if (DBDirs[i].ListInfo != null)
516 Console.WriteLine (" {0}", DBDirs[i].ListInfo);
518 Console.WriteLine (" .. no mdb.dir");
521 Console.WriteLine ("{0}:{1} .. not exist", i, DBDirs[i].Dirname);
524 Console.WriteLine ("[WDICT]");
525 foreach (KeyValuePair<Tag, List<MDatabase>> kv in wdict)
526 foreach (MDatabase mdb in kv.Value)
527 Console.WriteLine (mdb);
529 Console.WriteLine ("[NDICT]");
530 foreach (KeyValuePair<Tag, List<MDatabase>> kv in ndict)
531 foreach (MDatabase mdb in kv.Value)
532 Console.WriteLine (mdb);
535 private static void register (MDatabase mdb)
537 Dictionary<MDatabase.Tag, List<MDatabase>> dict
538 = mdb.DBType == MDBType.WILDCARD ? wdict : ndict;
539 List<MDatabase> mdbs;
541 if (dict.TryGetValue (mdb.tag, out mdbs))
543 for (int i = 0; i < mdbs.Count; i++)
544 if (mdbs[i].ListIndex == mdb.ListIndex)
546 mdbs[i].DBStatus = MDBStatus.INVALID;
554 mdbs = new List<MDatabase> (1);
556 dict.Add (mdb.tag, mdbs);
560 private static void register (int list_idx, int dir_idx,
561 Tag tag, MDatabaseInfo info)
563 Dictionary<MDatabase.Tag, List<MDatabase>> dict
564 = tag.HasWildcard ? wdict : ndict;
565 List<MDatabase> mdbs;
568 if (dict.TryGetValue (tag, out mdbs))
569 for (int i = 0; i < mdbs.Count; i++)
572 if (mdb.ListIndex == list_idx && mdb.DirIndex >= dir_idx)
574 mdb.DirIndex = dir_idx;
577 mdb.DBType = MDBType.WILDCARD;
578 mdb.DBStatus = MDBStatus.NOT_READY;
580 else if (dir_idx == -1)
582 mdb.DBType = MDBType.AUTO;
583 mdb.DBStatus = MDBStatus.NOT_READY;
587 mdb.DBType = MDBType.MULTIPLE;
588 mdb.DBStatus = MDBStatus.READY;
591 if (mdb.DBStatus == MDBStatus.INVALID)
592 M17n.DebugPrint ("registering: {0}\n", mdb);
594 M17n.DebugPrint ("updating: {0}\n", mdb);
600 mdbs = new List<MDatabase> (1);
601 dict.Add (tag, mdbs);
603 mdb = new MDatabase (list_idx, dir_idx, tag, info);
604 M17n.DebugPrint ("registering: {0}\n", mdb);
608 public MDatabase (Tag tag, Loader loader, object extra_info)
611 this.loader = loader;
612 DBType = MDBType.UNKNOWN;
613 DBStatus = MDBStatus.READY;
616 ExtraInfo = extra_info;
620 public MDatabase (Tag tag, string filename)
623 DBType = MDBType.EXPLICIT;
624 if (Path.IsPathRooted (filename))
627 if (File.Exists (filename))
628 DBStatus = MDBStatus.READY;
630 DBStatus = MDBStatus.INVALID;
635 DBStatus = MDBStatus.NOT_READY;
638 Info = new MDatabaseInfo ();
639 Info.Filename = filename;
643 private MDatabase (int list_idx, int dir_idx, Tag tag, MDatabaseInfo info)
647 DBType = this.tag.HasWildcard ? MDBType.WILDCARD : MDBType.AUTO;
648 if (tag[0] == Mchar_table || tag[0] == Mcharset)
649 Info.Format = tag[0];
650 ListIndex = list_idx;
652 if (Path.IsPathRooted (Info.Filename))
653 DBStatus = MDBStatus.READY;
655 DBStatus = MDBStatus.NOT_READY;
656 if (Info.Format == Mchar_table)
657 MCharProp.Define (tag[2], this);
660 public override String ToString () {
661 string str = ("#<MDataBase (" + ListIndex + "," + DirIndex + ") "
662 + tag + " " + DBType + " " + DBStatus);
664 if (DBType != MDBType.EXPLICIT && DBType != MDBType.UNKNOWN)
669 // Update (or disable) databases defined by "mdb.dir" in
671 private static void update_list (int list_idx)
673 M17n.DebugPrint ("Updating list: {0}\n", list_idx);
674 // At first disable all target databases.
675 foreach (KeyValuePair<Tag, List<MDatabase>> kv in wdict)
676 foreach (MDatabase mdb in kv.Value)
677 if (mdb.ListIndex == list_idx)
679 M17n.DebugPrint ("deleting: {0}\n", mdb);
680 mdb.DBStatus = MDBStatus.INVALID;
683 foreach (KeyValuePair<Tag, List<MDatabase>> kv in ndict)
684 foreach (MDatabase mdb in kv.Value)
685 if (mdb.ListIndex == list_idx)
687 M17n.DebugPrint ("deleting: {0}\n", mdb);
688 mdb.DBStatus = MDBStatus.INVALID;
692 FileInfo dblist = DBDirs[list_idx].ListInfo;
697 using (FileStream stream = File.OpenRead (dblist.FullName))
699 plist = new MPlist (stream);
703 foreach (MPlist pl in plist)
709 Tag tag = new Tag (ref p);
710 MDatabaseInfo info = new MDatabaseInfo (p);
711 int dir_idx = Path.IsPathRooted (info.Filename) ? 0 : -1;
712 register (list_idx, dir_idx, tag, info);
716 Console.WriteLine (e.Message + ": " + pl.Plist);
721 // Update (or disable) databases in DBDirs[dir_idx].
722 private static void update_dir (int dir_idx)
724 M17n.DebugPrint ("Updating dir: {0}\n", dir_idx);
725 // Reset all databases in DBDirs[dir_idx].
726 foreach (KeyValuePair<Tag, List<MDatabase>> kv in ndict)
727 foreach (MDatabase mdb in kv.Value)
728 if (mdb.DirIndex >= dir_idx)
730 M17n.DebugPrint ("disabling: {0}\n", mdb);
731 mdb.DBStatus = MDBStatus.NOT_READY;
734 // Re-expand all WILDCARD databases in DBDirs[dir_idx].
735 if (DBDirs[dir_idx].DirInfo != null)
736 foreach (KeyValuePair<Tag, List<MDatabase>> kv in wdict)
737 foreach (MDatabase mdb in kv.Value)
738 if (mdb.DBStatus == MDBStatus.READY)
740 M17n.DebugPrint ("re-expanding: {0}\n", mdb);
741 register_files (DBDirs[dir_idx].Dirname, dir_idx, mdb);
745 private static bool parse_plist_header (FileInfo fileinfo, MDatabase mdb,
746 out Tag tag, out MDatabaseInfo info)
750 tag = new Tag (MSymbol.nil);
752 using (FileStream stream = fileinfo.OpenRead ())
754 try { plist = new MPlist (stream, 1); } catch { }
756 if (plist == null || ! plist.IsPlist)
759 tag = new Tag (ref plist);
760 if (tag.HasWildcard || ! tag.Match (mdb.tag))
762 info = new MDatabaseInfo (plist);
766 private static bool parse_xml_header (FileInfo fileinfo, MDatabase mdb,
767 out Tag tag, out MDatabaseInfo info)
769 tag = new Tag (MSymbol.nil);
771 using (FileStream stream = fileinfo.OpenRead ())
774 MPlist plist = new MPlist ();
775 XmlTextReader reader = new XmlTextReader (stream);
777 reader.WhitespaceHandling = WhitespaceHandling.None;
780 } while (reader.NodeType != XmlNodeType.Element);
781 plist.Add (MSymbol.symbol, (MSymbol) reader.Name);
783 if (reader.NodeType == XmlNodeType.Element && reader.Name == "tags")
786 while (reader.NodeType == XmlNodeType.Element)
789 plist.Add (MSymbol.symbol, (MSymbol) reader.Value);
793 tag = new Tag (ref plist);
794 if (tag.HasWildcard || ! tag.Match (mdb.tag))
796 info = new MDatabaseInfo (plist);
799 } catch (Exception e) {
800 Console.WriteLine ("error {0}", e);
806 private static void register_files (string dir, int dir_idx, MDatabase mdb)
808 int list_idx = mdb.ListIndex;
809 List<FileInfo> files = new List<FileInfo> ();
810 MGlob.FileList (ref files, dir, mdb.Info.Filename);
811 foreach (FileInfo fileinfo in files)
816 if (mdb.Info.Format == MSymbol.plist
817 ? parse_plist_header (fileinfo, mdb, out tag, out info)
818 : parse_xml_header (fileinfo, mdb, out tag, out info))
820 info.Merge (mdb.Info);
821 if (Path.IsPathRooted (mdb.Info.Filename))
822 info.Filename = fileinfo.FullName;
824 info.Filename = fileinfo.Name;
825 register (list_idx, dir_idx, tag, info);
830 private void expand_wildcard ()
832 M17n.DebugPrint ("expanding: {0}\n", this);
835 register_files (null, DirIndex, this);
837 for (int i = 1; i < 4; i++)
838 if (DBDirs[i].DirInfo != null)
839 register_files (DBDirs[i].DirInfo.FullName, i, this);
840 DBStatus = MDBStatus.READY;
843 private static void maybe_expand_wildcard (Tag tag)
845 foreach (KeyValuePair<Tag, List<MDatabase>> kv in wdict)
847 M17n.DebugPrint ("expand check: {0}\n", kv.Key);
848 if (kv.Key.Match (tag))
850 foreach (MDatabase mdb in kv.Value)
852 if (mdb.DBStatus == MDBStatus.NOT_READY)
853 mdb.expand_wildcard ();
859 // Update the status. Return true iff the database file is
860 // readable but changed.
862 private bool update_status ()
864 if (DBType == MDBType.UNKNOWN)
867 if (DBStatus == MDBStatus.INVALID)
869 if (DBStatus != MDBStatus.NOT_READY)
874 DBStatus = MDBStatus.INVALID;
877 if (LastLoaded >= FileInfo.LastWriteTime)
879 DBStatus = MDBStatus.READY;
882 for (int i = 1; i < 4; i++)
883 if (DBDirs[i] != null && DBDirs[i].Dirname != null)
885 string filename = Path.Combine (DBDirs[i].Dirname, Info.Filename);
886 if (File.Exists (filename))
888 FileInfo = new FileInfo (filename);
890 DBStatus = MDBStatus.READY;
897 public static MDatabase Find (Tag tag)
899 List<MDatabase> mdbs;
900 MDatabase mdb = null;
903 throw new ArgumentException ("Wildcard not allowed: " + tag);
905 if (ndict.TryGetValue (tag, out mdbs))
908 for (int i = 0; i < mdbs.Count; i++)
911 if (mdb.ListIndex == 0)
913 if (mdb.DBStatus == MDBStatus.READY)
917 if (! update_all (false) && mdb != null)
919 maybe_expand_wildcard (tag);
920 if (! ndict.TryGetValue (tag, out mdbs))
922 for (int i = 0; i < mdbs.Count; i++)
925 mdb.update_status ();
926 if (mdb.DBStatus == MDBStatus.READY)
932 public static List<MDatabase> List (Tag tag)
934 List<MDatabase> list = new List<MDatabase> ();
937 maybe_expand_wildcard (tag);
941 foreach (KeyValuePair<Tag, List<MDatabase>> kv in ndict)
942 if (kv.Key.Match (tag))
943 foreach (MDatabase mdb in kv.Value)
945 mdb.update_status ();
946 if (mdb.DBStatus == MDBStatus.READY)
955 List<MDatabase> mdbs;
956 if (ndict.TryGetValue (tag, out mdbs))
957 foreach (MDatabase mdb in mdbs)
959 mdb.update_status ();
960 if (mdb.DBStatus == MDBStatus.READY)
970 private FileStream get_stream ()
973 || (Info.Format != MSymbol.plist && Info.Format != Mxml))
975 LastLoadStatus = LoadStatus.InvalidLoadMethod;
978 if (DBStatus != MDBStatus.READY)
980 LastLoadStatus = LoadStatus.NotAvailable;
984 FileStream stream = null;
986 stream = FileInfo.OpenRead ();
988 LastLoadStatus = LoadStatus.NotReadable;
993 public object Load ()
996 return loader (tag, ExtraInfo);
997 if (Info.Format == Mxml)
999 XmlDocument doc = new XmlDocument (name_table);
1001 XmlTextReader reader
1002 = new XmlTextReader (FileInfo.FullName, name_table);
1004 LastLoaded = DateTime.Now;
1005 } catch (Exception e) {
1006 Console.WriteLine (e);
1007 LastLoadStatus = LoadStatus.InvalidContents;
1012 FileStream stream = get_stream ();
1015 MPlist plist = null;
1017 plist = new MPlist (stream);
1018 LastLoaded = DateTime.Now;
1020 LastLoadStatus = LoadStatus.InvalidContents;
1027 public object Load (MSymbol key, MSymbol stop)
1029 FileStream stream = get_stream ();
1033 if (Info.Format == Mxml)
1035 XmlDocument doc = new XmlDocument (name_table);
1036 XmlTextReader reader = new XmlTextReader (stream, name_table);
1038 reader.WhitespaceHandling = WhitespaceHandling.None;
1041 while (reader.NodeType != XmlNodeType.Element)
1043 doc.LoadXml ("<" + reader.Name + "></" + reader.Name + ">");
1045 XmlNode node = doc.DocumentElement;
1046 while (reader.NodeType == XmlNodeType.Element
1047 ? reader.Name != stop.Name
1048 : reader.NodeType != XmlNodeType.EndElement)
1049 if (reader.NodeType == XmlNodeType.Element
1050 && reader.Name == key.Name)
1051 node = doc.DocumentElement.InsertAfter (doc.ReadNode (reader),
1060 MPlist plist = null;
1062 plist = new MPlist (stream, key, stop);
1063 LastLoaded = DateTime.Now;
1065 LastLoadStatus = LoadStatus.InvalidContents;
1072 public object Load (MSymbol stop)
1074 FileStream stream = get_stream ();
1078 if (Info.Format == Mxml)
1080 XmlDocument doc = new XmlDocument (name_table);
1081 XmlTextReader reader = new XmlTextReader (stream, name_table);
1083 reader.WhitespaceHandling = WhitespaceHandling.None;
1086 while (reader.NodeType != XmlNodeType.Element)
1088 doc.LoadXml ("<" + reader.Name + "></" + reader.Name + ">");
1090 XmlNode node = null;
1091 while (reader.NodeType == XmlNodeType.Element
1092 ? reader.Name != stop.Name
1093 : reader.NodeType != XmlNodeType.EndElement)
1094 if (reader.NodeType == XmlNodeType.Element)
1095 node = doc.DocumentElement.InsertAfter (doc.ReadNode (reader),
1097 } catch (Exception e) {
1098 Console.WriteLine (e);
1106 MPlist plist = null;
1108 plist = new MPlist (stream, stop);
1109 LastLoaded = DateTime.Now;
1110 } catch (Exception e) {
1111 Console.WriteLine (e);
1112 LastLoadStatus = LoadStatus.InvalidContents;
1119 public XmlNode Load (string id, params string[] nodes)
1121 FileStream stream = get_stream ();
1124 if (Info.Format != Mxml)
1125 throw new Exception ("Not an XML format");
1127 XmlDocument doc = new XmlDocument (name_table);
1128 XmlTextReader reader = new XmlTextReader (stream, name_table);
1129 int len = nodes.Length;
1131 reader.WhitespaceHandling = WhitespaceHandling.None;
1134 } while (reader.NodeType != XmlNodeType.Element);
1136 if (reader.Name != nodes[0])
1139 string ns = reader.GetAttribute ("xmlns");
1140 XmlNode top = doc.CreateNode (XmlNodeType.Element, nodes[0], ns);
1146 for (i = 1; i + 1 < len; i++)
1148 if (! reader.ReadToDescendant (nodes[i]))
1150 node = node.InsertAfter (doc.CreateNode (XmlNodeType.Element,
1151 nodes[i], ns), null);
1153 if (! reader.ReadToDescendant (nodes[i]))
1155 XmlNode ref_node = null;
1156 while (reader.NodeType != XmlNodeType.EndElement)
1158 if (reader.NodeType == XmlNodeType.Element)
1160 if (reader.Name == nodes[i]
1161 && (id == null || id == reader.GetAttribute ("id")))
1162 ref_node = node.InsertAfter (doc.ReadNode (reader), ref_node);
1170 } catch (Exception e) {
1171 Console.WriteLine (e);
1179 /// <summary>Return a list of currently available database
1180 /// directory names</summary>.
1181 public static string[] DirectoryList ()
1183 List<string> dirs = new List<string> ();
1185 for (int i = 1; i < 4; i++)
1186 if (DBDirs[i].Dirname != null)
1187 dirs.Add (DBDirs[i].Dirname);
1188 return dirs.ToArray ();
1191 public MSymbol Format { get { return Info.Format; } }
1193 public static bool Changed (DateTime time)
1196 return (time < LastUpdateTime);
1199 public bool NeedReload ()
1201 return update_status ();
1204 // For IComparable<MDatabase>
1205 public int CompareTo (MDatabase other)
1207 return (ListIndex == other.ListIndex
1208 ? DirIndex - other.DirIndex
1209 : ListIndex - other.ListIndex);