/// <summary> /// Defaults data to the section (IE, sets it if not present!) /// </summary> /// <param name="key">The key to set data from.</param> /// <param name="data">The key to set data to.</param> public void DefaultData(string key, FDSData data) { int lind = key.LastIndexOf(SectionPathSplit); if (lind < 0) { if (GetRootData(key) == null) { SetRootData(key, data); } return; } if (lind == key.Length - 1) { throw new FDSInputException("Invalid SetData key: Ends in a path splitter!"); } FDSSection sec = GetSectionInternal(key.Substring(0, lind), false, false); string k = key.Substring(lind + 1); if (sec.GetRootData(k) == null) { sec.SetRootData(k, data); } }
/// <summary> /// Gets data from the section. /// Returns null if not found. /// </summary> /// <param name="key">The key to get data from.</param> /// <returns>The data found, or null.</returns> public FDSData GetData(string key) { int lind = key.LastIndexOf(SectionPathSplit); if (lind < 0) { return(GetRootData(key)); } if (lind == key.Length - 1) { return(null); } FDSSection sec = GetSection(key.Substring(0, lind)); if (sec == null) { return(null); } return(sec.GetRootData(key.Substring(lind + 1))); }
/// <summary> /// Gets data from the section. /// Returns null if not found. /// </summary> /// <param name="key">The key to get data from.</param> /// <returns>The data found, or null.</returns> public FDSData GetDataLowered(string key) { key = key.ToLowerFast(); int lind = key.LastIndexOf(SectionPathSplit); if (lind < 0) { return(GetRootDataLowered(key)); } if (lind == key.Length - 1) { return(null); } FDSSection sec = GetSectionInternal(key.Substring(0, lind), true, true); if (sec == null) { return(null); } return(sec.GetRootDataLowered(key.Substring(lind + 1))); }
/// <summary> /// Gets a sub-section of this FDS section. /// </summary> /// <param name="key">The key of the section.</param> /// <param name="allowNull">Whether to allow null returns, otherwise enforce the section's existence. If true, can throw an FDSInputException!</param> /// <param name="lowered">Whether to read lowercase section names. If set, expects lowercased input key!</param> /// <returns>The subsection.</returns> private FDSSection GetSectionInternal(string key, bool allowNull, bool lowered) { if (key == null || key.Length == 0) { return(this); } string[] dat = key.SplitFast(SectionPathSplit); FDSSection current = this; for (int i = 0; i < dat.Length; i++) { FDSData fdat = lowered ? current.GetRootDataLowered(dat[i]) : current.GetRootData(dat[i]); if (fdat != null && fdat.Internal is FDSSection) { current = (FDSSection)fdat.Internal; } else { if (allowNull) { return(null); } if (fdat != null) { throw new FDSInputException("Key contains non-section contents!"); } FDSSection temp = new FDSSection(); current.SetRootData(dat[i], new FDSData() { Internal = temp, PrecedingComments = new List <string>() }); current = temp; } } return(current); }
/// <summary> /// Saves an <see cref="FDSSection"/> into a file. Throws normal exceptions on any issue. /// NOTE: May be removed or switched for journalling logic in the future. /// </summary> /// <param name="section">The data to save.</param> /// <param name="fname">The name of the file to read.</param> public static void SaveToFile(this FDSSection section, string fname) { File.WriteAllBytes(fname, StringConversionHelper.UTF8Encoding.GetBytes(section.SaveToString())); }
// TODO: Clean code base! Current code contains a lot of poorly named variables and messy code. /// <summary> /// Constructs the FDS Section from textual data. /// </summary> /// <param name="contents">The contents of the data file.</param> public FDSSection(string contents) { StartingLine = 1; contents = FDSUtility.CleanFileData(contents); Dictionary <int, FDSSection> spacedsections = new Dictionary <int, FDSSection>() { { 0, this } }; List <string> ccomments = new List <string>(); List <string> seccomments = new List <string>(); FDSSection csection = this; string[] data = contents.SplitFast('\n'); int pspaces = 0; string secwaiting = null; List <FDSData> clist = null; for (int i = 0; i < data.Length; i++) { string line = data[i]; int spaces; for (spaces = 0; spaces < line.Length; spaces++) { if (line[spaces] != ' ') { break; } } if (spaces == line.Length) { continue; } string datum = line.Substring(spaces).TrimEnd(' '); if (datum.StartsWith("#")) { ccomments.Add(datum.Substring(1)); continue; } if (spaces < pspaces) { if (spacedsections.TryGetValue(spaces, out FDSSection temp)) { csection = temp; foreach (int test in new List <int>(spacedsections.Keys)) { if (test > spaces) { spacedsections.Remove(test); } } } else { Exception(i, line, "Spaced incorrectly. Spacing length is less than previous spacing length," + "but does not match the spacing value of any known section, valid: " + string.Join(" / ", spacedsections.Keys) + ", found: " + spaces + ", was: " + pspaces); } } if (datum[0] == '-') { string clistline = datum.Substring(1).TrimStart(' '); if (clist == null) { if (spaces >= pspaces && secwaiting != null) { clist = new List <FDSData>(); csection.SetRootData(FDSUtility.UnEscapeKey(secwaiting), new FDSData() { PrecedingComments = new List <string>(seccomments), Internal = clist }); seccomments.Clear(); secwaiting = null; } else { Exception(i, line, "Line purpose unknown, attempted list entry when not building a list"); } } clist.Add(new FDSData() { PrecedingComments = new List <string>(ccomments), Internal = FDSUtility.InterpretType(FDSUtility.UnEscape(clistline)) }); ccomments.Clear(); continue; } clist = null; string startofline = ""; string endofline = ""; char type = '\0'; for (int spot = 0; spot < datum.Length; spot++) { if (datum[spot] == ':' || datum[spot] == '=') { type = datum[spot]; startofline = datum.Substring(0, spot); endofline = spot == datum.Length - 1 ? "": datum.Substring(spot + 1); break; } } endofline = endofline.TrimStart(' '); if (type == '\0') { Exception(i, line, "Line purpose unknown"); } if (startofline.Length == 0) { Exception(i, line, "Empty key label!"); } if (spaces > pspaces && secwaiting != null) { FDSSection sect = new FDSSection(); csection.SetRootData(FDSUtility.UnEscapeKey(secwaiting), new FDSData() { PrecedingComments = new List <string>(seccomments), Internal = sect }); seccomments.Clear(); csection = sect; spacedsections[spaces] = sect; secwaiting = null; } if (type == '=') { if (endofline.Length == 0) { csection.SetRootData(FDSUtility.UnEscapeKey(startofline), new FDSData() { PrecedingComments = new List <string>(ccomments), Internal = new byte[0] }); } else { csection.SetRootData(FDSUtility.UnEscapeKey(startofline), new FDSData() { PrecedingComments = new List <string>(ccomments), Internal = Convert.FromBase64String(endofline) }); } ccomments.Clear(); } else if (type == ':') { if (endofline.Length == 0) { secwaiting = startofline; seccomments = new List <string>(ccomments); ccomments.Clear(); } else { csection.SetRootData(FDSUtility.UnEscapeKey(startofline), new FDSData() { PrecedingComments = new List <string>(ccomments), Internal = FDSUtility.InterpretType(FDSUtility.UnEscape(endofline)) }); ccomments.Clear(); } } else { Exception(i, line, "Internal issue: unrecognize 'type' value: " + type); } pspaces = spaces; } }