/// <summary> /// Create a configuration by parsing the given ini lines /// </summary> /// <param name="iniLines"></param> /// <param name="configuration"></param> /// <returns></returns> public static bool TryParse(IEnumerable <string> iniLines, out Configuration?configuration) { var lines = new List <ConfigurationLine>(); ConfigurationLine? previousLine = null; ConfigurationSection?currentSection = null; foreach (var iniLine in iniLines) { if (ConfigurationLine.TryPrase(iniLine, previousLine, out var line)) { if (line != previousLine) { line.Index = lines.Count; lines.Add(line); previousLine = line; if (line is ConfigurationSection section) { currentSection = section; } else if (line is ConfigurationValue value) { if (currentSection == null) { // Section expected configuration = null; return(false); } currentSection.Add(value); } } } else { configuration = null; return(false); } } configuration = new Configuration(lines); return(true); }
public static bool TryPrase(string iniLine, ConfigurationLine?previousLine, out ConfigurationLine line) { var indentation = ""; var i = 0; while (i < iniLine.Length && IsWhitespace(iniLine[i])) { indentation += iniLine[i]; ++i; } // Empty or whitespace-only if (i == iniLine.Length) { line = new ConfigurationLine(indentation); return(true); } // Comment if (iniLine[i] == '#' || iniLine[i] == ';') { var delimiter = iniLine[i]; ++i; var leadingWhitespace = ""; while (i < iniLine.Length && IsWhitespace(iniLine[i])) { leadingWhitespace += iniLine[i]; ++i; } var text = iniLine.Substring(i); line = new ConfigurationComment(indentation, delimiter, leadingWhitespace, text); return(true); } // Section if (iniLine[i] == '[') { var name = ""; ++i; while (i < iniLine.Length && iniLine[i] != ']') { name += iniLine[i]; ++i; } if (iniLine[i] == ']') { ++i; var trailingWhitespace = ""; while (i < iniLine.Length && IsWhitespace(iniLine[i])) { trailingWhitespace += iniLine[i]; ++i; } if (i == iniLine.Length) { var trimmedName = name.TrimStart(); var nameLeadingWhitespace = name.Substring(0, name.Length - trimmedName.Length); trimmedName = trimmedName.TrimEnd(); var nameTrailingWhitespace = name.Substring(nameLeadingWhitespace.Length + trimmedName.Length); line = new ConfigurationSection(indentation, nameLeadingWhitespace, trimmedName, nameTrailingWhitespace, trailingWhitespace); return(true); } } line = null !; return(false); } // Value var key = ""; var keyTrailingWhitespace = ""; char keyValueDelimiter = '='; var delimiterTrailingWhitespace = ""; string?value = null; var valueTrailingWhitespace = ""; while (i < iniLine.Length && iniLine[i] != ':' && iniLine[i] != '=') { key += iniLine[i]; ++i; } var j = key.Length - 1; while (j >= 0 && IsWhitespace(key[j])) { keyTrailingWhitespace = key[j] + keyTrailingWhitespace; --j; } key = key.Substring(0, j + 1); if (i < iniLine.Length && (iniLine[i] == ':' || iniLine[i] == '=')) { if (key.Length == 0) { // Expecting key before = or : line = null !; return(false); } keyValueDelimiter = iniLine[i]; ++i; while (i < iniLine.Length && IsWhitespace(iniLine[i])) { delimiterTrailingWhitespace += iniLine[i]; ++i; } value = iniLine.Substring(i); j = value.Length - 1; while (j >= 0 && IsWhitespace(value[j])) { valueTrailingWhitespace = value[j] + valueTrailingWhitespace; --j; } value = value.Substring(0, j + 1); } else { // Blank line if (key.Length == 0) { line = new ConfigurationLine(indentation); return(true); } } // Check for wrapped lines and unwrap into the previous line's value if (previousLine is ConfigurationValue previousValueLine) { if (indentation.Length > previousValueLine.Indentation.Length) { previousValueLine.Value += " " + key; previousValueLine.ValueTrailingWhitespace = valueTrailingWhitespace; line = previousValueLine; return(true); } } line = new ConfigurationValue(indentation, key, keyTrailingWhitespace, keyValueDelimiter, delimiterTrailingWhitespace, value, valueTrailingWhitespace); return(true); }