/// <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);
        }
Beispiel #5
0
 /// <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;
            }
        }