Decompiled source of Tommy v3.1.2

plugins/Tommy.dll

Decompiled a week ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Text;
using System.Text.RegularExpressions;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: InternalsVisibleTo("Tommy.Extensions")]
[assembly: InternalsVisibleTo("Tommy.Tests")]
[assembly: AssemblyCompany("Denis Zhidkikh")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyCopyright("Copyright © 2021 Denis Zhidkikh")]
[assembly: AssemblyDescription("\r\n            A simple TOML parser and writer inspired by SimpleJSON.\r\n            Provides minimal and simple API for parsing and writing TOML files.\r\n            Compliant with TOML 1.0.0 format spec.\r\n        ")]
[assembly: AssemblyFileVersion("3.1.2.0")]
[assembly: AssemblyInformationalVersion("3.1.2")]
[assembly: AssemblyProduct("Tommy")]
[assembly: AssemblyTitle("Tommy")]
[assembly: AssemblyVersion("3.1.2.0")]
namespace Tommy;

public abstract class TomlNode : IEnumerable
{
	public virtual bool HasValue { get; }

	public virtual bool IsArray { get; }

	public virtual bool IsTable { get; }

	public virtual bool IsString { get; }

	public virtual bool IsInteger { get; }

	public virtual bool IsFloat { get; }

	public bool IsDateTime
	{
		get
		{
			if (!IsDateTimeLocal)
			{
				return IsDateTimeOffset;
			}
			return true;
		}
	}

	public virtual bool IsDateTimeLocal { get; }

	public virtual bool IsDateTimeOffset { get; }

	public virtual bool IsBoolean { get; }

	public virtual string Comment { get; set; }

	public virtual int CollapseLevel { get; set; }

	public virtual TomlTable AsTable => this as TomlTable;

	public virtual TomlString AsString => this as TomlString;

	public virtual TomlInteger AsInteger => this as TomlInteger;

	public virtual TomlFloat AsFloat => this as TomlFloat;

	public virtual TomlBoolean AsBoolean => this as TomlBoolean;

	public virtual TomlDateTimeLocal AsDateTimeLocal => this as TomlDateTimeLocal;

	public virtual TomlDateTimeOffset AsDateTimeOffset => this as TomlDateTimeOffset;

	public virtual TomlDateTime AsDateTime => this as TomlDateTime;

	public virtual TomlArray AsArray => this as TomlArray;

	public virtual int ChildrenCount => 0;

	public virtual TomlNode this[string key]
	{
		get
		{
			return null;
		}
		set
		{
		}
	}

	public virtual TomlNode this[int index]
	{
		get
		{
			return null;
		}
		set
		{
		}
	}

	public virtual IEnumerable<TomlNode> Children
	{
		get
		{
			yield break;
		}
	}

	public virtual IEnumerable<string> Keys
	{
		get
		{
			yield break;
		}
	}

	public IEnumerator GetEnumerator()
	{
		return Children.GetEnumerator();
	}

	public virtual bool TryGetNode(string key, out TomlNode node)
	{
		node = null;
		return false;
	}

	public virtual bool HasKey(string key)
	{
		return false;
	}

	public virtual bool HasItemAt(int index)
	{
		return false;
	}

	public virtual void Add(string key, TomlNode node)
	{
	}

	public virtual void Add(TomlNode node)
	{
	}

	public virtual void Delete(TomlNode node)
	{
	}

	public virtual void Delete(string key)
	{
	}

	public virtual void Delete(int index)
	{
	}

	public virtual void AddRange(IEnumerable<TomlNode> nodes)
	{
		foreach (TomlNode node in nodes)
		{
			Add(node);
		}
	}

	public virtual void WriteTo(TextWriter tw, string name = null)
	{
		tw.WriteLine(ToInlineToml());
	}

	public virtual string ToInlineToml()
	{
		return ToString();
	}

	public static implicit operator TomlNode(string value)
	{
		return new TomlString
		{
			Value = value
		};
	}

	public static implicit operator TomlNode(bool value)
	{
		return new TomlBoolean
		{
			Value = value
		};
	}

	public static implicit operator TomlNode(long value)
	{
		return new TomlInteger
		{
			Value = value
		};
	}

	public static implicit operator TomlNode(float value)
	{
		return new TomlFloat
		{
			Value = value
		};
	}

	public static implicit operator TomlNode(double value)
	{
		return new TomlFloat
		{
			Value = value
		};
	}

	public static implicit operator TomlNode(DateTime value)
	{
		return new TomlDateTimeLocal
		{
			Value = value
		};
	}

	public static implicit operator TomlNode(DateTimeOffset value)
	{
		return new TomlDateTimeOffset
		{
			Value = value
		};
	}

	public static implicit operator TomlNode(TomlNode[] nodes)
	{
		TomlArray tomlArray = new TomlArray();
		tomlArray.AddRange(nodes);
		return tomlArray;
	}

	public static implicit operator string(TomlNode value)
	{
		return value.ToString();
	}

	public static implicit operator int(TomlNode value)
	{
		return (int)value.AsInteger.Value;
	}

	public static implicit operator long(TomlNode value)
	{
		return value.AsInteger.Value;
	}

	public static implicit operator float(TomlNode value)
	{
		return (float)value.AsFloat.Value;
	}

	public static implicit operator double(TomlNode value)
	{
		return value.AsFloat.Value;
	}

	public static implicit operator bool(TomlNode value)
	{
		return value.AsBoolean.Value;
	}

	public static implicit operator DateTime(TomlNode value)
	{
		return value.AsDateTimeLocal.Value;
	}

	public static implicit operator DateTimeOffset(TomlNode value)
	{
		return value.AsDateTimeOffset.Value;
	}
}
public class TomlString : TomlNode
{
	public override bool HasValue { get; } = true;


	public override bool IsString { get; } = true;


	public bool IsMultiline { get; set; }

	public bool MultilineTrimFirstLine { get; set; }

	public bool PreferLiteral { get; set; }

	public string Value { get; set; }

	public override string ToString()
	{
		return Value;
	}

	public override string ToInlineToml()
	{
		if (Value.IndexOf(new string('\'', (!IsMultiline) ? 1 : 3), StringComparison.Ordinal) != -1 && PreferLiteral)
		{
			PreferLiteral = false;
		}
		string text = new string(PreferLiteral ? '\'' : '"', (!IsMultiline) ? 1 : 3);
		string text2 = (PreferLiteral ? Value : Value.Escape(!IsMultiline));
		if (IsMultiline)
		{
			text2 = text2.Replace("\r\n", "\n").Replace("\n", Environment.NewLine);
		}
		if (IsMultiline && (MultilineTrimFirstLine || (!MultilineTrimFirstLine && text2.StartsWith(Environment.NewLine))))
		{
			text2 = Environment.NewLine + text2;
		}
		return text + text2 + text;
	}
}
public class TomlInteger : TomlNode
{
	public enum Base
	{
		Binary = 2,
		Octal = 8,
		Decimal = 10,
		Hexadecimal = 16
	}

	public override bool IsInteger { get; } = true;


	public override bool HasValue { get; } = true;


	public Base IntegerBase { get; set; } = Base.Decimal;


	public long Value { get; set; }

	public override string ToString()
	{
		return Value.ToString();
	}

	public override string ToInlineToml()
	{
		if (IntegerBase == Base.Decimal)
		{
			return Value.ToString(CultureInfo.InvariantCulture);
		}
		return "0" + TomlSyntax.BaseIdentifiers[(int)IntegerBase] + Convert.ToString(Value, (int)IntegerBase);
	}
}
public class TomlFloat : TomlNode, IFormattable
{
	public override bool IsFloat { get; } = true;


	public override bool HasValue { get; } = true;


	public double Value { get; set; }

	public override string ToString()
	{
		return Value.ToString(CultureInfo.InvariantCulture);
	}

	public string ToString(string format, IFormatProvider formatProvider)
	{
		return Value.ToString(format, formatProvider);
	}

	public string ToString(IFormatProvider formatProvider)
	{
		return Value.ToString(formatProvider);
	}

	public override string ToInlineToml()
	{
		double value = Value;
		if (double.IsNaN(value))
		{
			return "nan";
		}
		if (double.IsPositiveInfinity(value))
		{
			return "inf";
		}
		if (double.IsNegativeInfinity(value))
		{
			return "-inf";
		}
		double num = value;
		return num.ToString("G", CultureInfo.InvariantCulture).ToLowerInvariant();
	}
}
public class TomlBoolean : TomlNode
{
	public override bool IsBoolean { get; } = true;


	public override bool HasValue { get; } = true;


	public bool Value { get; set; }

	public override string ToString()
	{
		return Value.ToString();
	}

	public override string ToInlineToml()
	{
		if (!Value)
		{
			return "false";
		}
		return "true";
	}
}
public class TomlDateTime : TomlNode, IFormattable
{
	public int SecondsPrecision { get; set; }

	public override bool HasValue { get; } = true;


	public virtual string ToString(string format, IFormatProvider formatProvider)
	{
		return string.Empty;
	}

	public virtual string ToString(IFormatProvider formatProvider)
	{
		return string.Empty;
	}

	protected virtual string ToInlineTomlInternal()
	{
		return string.Empty;
	}

	public override string ToInlineToml()
	{
		return ToInlineTomlInternal().Replace(" ", "T").Replace("+00:00", "Z");
	}
}
public class TomlDateTimeOffset : TomlDateTime
{
	public override bool IsDateTimeOffset { get; } = true;


	public DateTimeOffset Value { get; set; }

	public override string ToString()
	{
		return Value.ToString(CultureInfo.CurrentCulture);
	}

	public override string ToString(IFormatProvider formatProvider)
	{
		return Value.ToString(formatProvider);
	}

	public override string ToString(string format, IFormatProvider formatProvider)
	{
		return Value.ToString(format, formatProvider);
	}

	protected override string ToInlineTomlInternal()
	{
		return Value.ToString(TomlSyntax.RFC3339Formats[base.SecondsPrecision]);
	}
}
public class TomlDateTimeLocal : TomlDateTime
{
	public enum DateTimeStyle
	{
		Date,
		Time,
		DateTime
	}

	public override bool IsDateTimeLocal { get; } = true;


	public DateTimeStyle Style { get; set; } = DateTimeStyle.DateTime;


	public DateTime Value { get; set; }

	public override string ToString()
	{
		return Value.ToString(CultureInfo.CurrentCulture);
	}

	public override string ToString(IFormatProvider formatProvider)
	{
		return Value.ToString(formatProvider);
	}

	public override string ToString(string format, IFormatProvider formatProvider)
	{
		return Value.ToString(format, formatProvider);
	}

	public override string ToInlineToml()
	{
		return Style switch
		{
			DateTimeStyle.Date => Value.ToString(TomlSyntax.LocalDateFormat), 
			DateTimeStyle.Time => Value.ToString(TomlSyntax.RFC3339LocalTimeFormats[base.SecondsPrecision]), 
			_ => Value.ToString(TomlSyntax.RFC3339LocalDateTimeFormats[base.SecondsPrecision]), 
		};
	}
}
public class TomlArray : TomlNode
{
	private List<TomlNode> values;

	public override bool HasValue { get; } = true;


	public override bool IsArray { get; } = true;


	public bool IsMultiline { get; set; }

	public bool IsTableArray { get; set; }

	public List<TomlNode> RawArray => values ?? (values = new List<TomlNode>());

	public override TomlNode this[int index]
	{
		get
		{
			if (index < RawArray.Count)
			{
				return RawArray[index];
			}
			return this[index] = new TomlLazy(this);
		}
		set
		{
			if (index == RawArray.Count)
			{
				RawArray.Add(value);
			}
			else
			{
				RawArray[index] = value;
			}
		}
	}

	public override int ChildrenCount => RawArray.Count;

	public override IEnumerable<TomlNode> Children => RawArray.AsEnumerable();

	public override void Add(TomlNode node)
	{
		RawArray.Add(node);
	}

	public override void AddRange(IEnumerable<TomlNode> nodes)
	{
		RawArray.AddRange(nodes);
	}

	public override void Delete(TomlNode node)
	{
		RawArray.Remove(node);
	}

	public override void Delete(int index)
	{
		RawArray.RemoveAt(index);
	}

	public override string ToString()
	{
		return ToString(multiline: false);
	}

	public string ToString(bool multiline)
	{
		StringBuilder stringBuilder = new StringBuilder();
		stringBuilder.Append('[');
		if (ChildrenCount != 0)
		{
			string value = (multiline ? (Environment.NewLine + "  ") : " ");
			string self = (multiline ? $"{','}{Environment.NewLine}  " : $"{','} ");
			string value2 = (multiline ? Environment.NewLine : " ");
			stringBuilder.Append(value).Append(self.Join(RawArray.Select((TomlNode n) => n.ToInlineToml()))).Append(value2);
		}
		stringBuilder.Append(']');
		return stringBuilder.ToString();
	}

	public override void WriteTo(TextWriter tw, string name = null)
	{
		if (!IsTableArray)
		{
			tw.WriteLine(ToString(IsMultiline));
			return;
		}
		if (Comment != null)
		{
			tw.WriteLine();
			Comment.AsComment(tw);
		}
		tw.Write('[');
		tw.Write('[');
		tw.Write(name);
		tw.Write(']');
		tw.Write(']');
		tw.WriteLine();
		bool flag = true;
		foreach (TomlNode item in RawArray)
		{
			TomlTable obj = (item as TomlTable) ?? throw new TomlFormatException("The array is marked as array table but contains non-table nodes!");
			obj.IsInline = false;
			if (!flag)
			{
				tw.WriteLine();
				Comment?.AsComment(tw);
				tw.Write('[');
				tw.Write('[');
				tw.Write(name);
				tw.Write(']');
				tw.Write(']');
				tw.WriteLine();
			}
			flag = false;
			obj.WriteTo(tw, name, writeSectionName: false);
		}
	}
}
public class TomlTable : TomlNode
{
	private Dictionary<string, TomlNode> children;

	public override bool HasValue { get; }

	public override bool IsTable { get; } = true;


	public bool IsInline { get; set; }

	public Dictionary<string, TomlNode> RawTable => children ?? (children = new Dictionary<string, TomlNode>());

	public override TomlNode this[string key]
	{
		get
		{
			if (RawTable.TryGetValue(key, out var value))
			{
				return value;
			}
			TomlLazy tomlLazy = new TomlLazy(this);
			RawTable[key] = tomlLazy;
			return tomlLazy;
		}
		set
		{
			RawTable[key] = value;
		}
	}

	public override int ChildrenCount => RawTable.Count;

	public override IEnumerable<TomlNode> Children => RawTable.Select((KeyValuePair<string, TomlNode> kv) => kv.Value);

	public override IEnumerable<string> Keys => RawTable.Select((KeyValuePair<string, TomlNode> kv) => kv.Key);

	public override bool HasKey(string key)
	{
		return RawTable.ContainsKey(key);
	}

	public override void Add(string key, TomlNode node)
	{
		RawTable.Add(key, node);
	}

	public override bool TryGetNode(string key, out TomlNode node)
	{
		return RawTable.TryGetValue(key, out node);
	}

	public override void Delete(TomlNode node)
	{
		RawTable.Remove(RawTable.First((KeyValuePair<string, TomlNode> kv) => kv.Value == node).Key);
	}

	public override void Delete(string key)
	{
		RawTable.Remove(key);
	}

	public override string ToString()
	{
		StringBuilder stringBuilder = new StringBuilder();
		stringBuilder.Append('{');
		if (ChildrenCount != 0)
		{
			LinkedList<KeyValuePair<string, TomlNode>> linkedList = CollectCollapsedItems("", 0, normalizeOrder: false);
			if (linkedList.Count != 0)
			{
				stringBuilder.Append(' ').Append($"{','} ".Join(linkedList.Select((KeyValuePair<string, TomlNode> n) => $"{n.Key} {'='} {n.Value.ToInlineToml()}")));
			}
			stringBuilder.Append(' ');
		}
		stringBuilder.Append('}');
		return stringBuilder.ToString();
	}

	private LinkedList<KeyValuePair<string, TomlNode>> CollectCollapsedItems(string prefix = "", int level = 0, bool normalizeOrder = true)
	{
		LinkedList<KeyValuePair<string, TomlNode>> linkedList = new LinkedList<KeyValuePair<string, TomlNode>>();
		LinkedList<KeyValuePair<string, TomlNode>> linkedList2 = (normalizeOrder ? new LinkedList<KeyValuePair<string, TomlNode>>() : linkedList);
		foreach (KeyValuePair<string, TomlNode> item in RawTable)
		{
			TomlNode value = item.Value;
			string text = item.Key.AsKey();
			if (value is TomlTable tomlTable)
			{
				LinkedList<KeyValuePair<string, TomlNode>> linkedList3 = tomlTable.CollectCollapsedItems(prefix + text + ".", level + 1, normalizeOrder);
				if (linkedList3.Count == 0 && value.CollapseLevel == level)
				{
					linkedList2.AddLast(new KeyValuePair<string, TomlNode>(prefix + text, value));
				}
				foreach (KeyValuePair<string, TomlNode> item2 in linkedList3)
				{
					linkedList2.AddLast(item2);
				}
			}
			else if (value.CollapseLevel == level)
			{
				linkedList.AddLast(new KeyValuePair<string, TomlNode>(prefix + text, value));
			}
		}
		if (normalizeOrder)
		{
			foreach (KeyValuePair<string, TomlNode> item3 in linkedList2)
			{
				linkedList.AddLast(item3);
			}
		}
		return linkedList;
	}

	public override void WriteTo(TextWriter tw, string name = null)
	{
		WriteTo(tw, name, writeSectionName: true);
	}

	internal void WriteTo(TextWriter tw, string name, bool writeSectionName)
	{
		if (IsInline && name != null)
		{
			tw.WriteLine(ToInlineToml());
			return;
		}
		LinkedList<KeyValuePair<string, TomlNode>> linkedList = CollectCollapsedItems();
		if (linkedList.Count == 0)
		{
			return;
		}
		bool flag = !linkedList.All(delegate(KeyValuePair<string, TomlNode> n)
		{
			TomlNode value2 = n.Value;
			if (value2 is TomlTable tomlTable2)
			{
				if (!tomlTable2.IsInline)
				{
					goto IL_002e;
				}
			}
			else if (value2 is TomlArray tomlArray2 && tomlArray2.IsTableArray)
			{
				goto IL_002e;
			}
			return false;
			IL_002e:
			return true;
		});
		Comment?.AsComment(tw);
		if (name != null && (flag || Comment != null) && writeSectionName)
		{
			tw.Write('[');
			tw.Write(name);
			tw.Write(']');
			tw.WriteLine();
		}
		else if (Comment != null)
		{
			tw.WriteLine();
		}
		string text = ((name == null) ? "" : (name + "."));
		bool flag2 = true;
		foreach (KeyValuePair<string, TomlNode> item in linkedList)
		{
			string key = item.Key;
			TomlNode value = item.Value;
			if (value is TomlArray tomlArray)
			{
				if (tomlArray.IsTableArray)
				{
					goto IL_011e;
				}
			}
			else if (value is TomlTable tomlTable && !tomlTable.IsInline)
			{
				goto IL_011e;
			}
			bool flag3 = false;
			goto IL_0126;
			IL_011e:
			flag3 = true;
			goto IL_0126;
			IL_0126:
			if (flag3)
			{
				if (!flag2)
				{
					tw.WriteLine();
				}
				flag2 = false;
				item.Value.WriteTo(tw, text + key);
			}
			else
			{
				flag2 = false;
				item.Value.Comment?.AsComment(tw);
				tw.Write(key);
				tw.Write(' ');
				tw.Write('=');
				tw.Write(' ');
				item.Value.WriteTo(tw, text + key);
			}
		}
	}
}
internal class TomlLazy : TomlNode
{
	private readonly TomlNode parent;

	private TomlNode replacement;

	public override TomlNode this[int index]
	{
		get
		{
			return Set<TomlArray>()[index];
		}
		set
		{
			Set<TomlArray>()[index] = value;
		}
	}

	public override TomlNode this[string key]
	{
		get
		{
			return Set<TomlTable>()[key];
		}
		set
		{
			Set<TomlTable>()[key] = value;
		}
	}

	public TomlLazy(TomlNode parent)
	{
		this.parent = parent;
	}

	public override void Add(TomlNode node)
	{
		Set<TomlArray>().Add(node);
	}

	public override void Add(string key, TomlNode node)
	{
		Set<TomlTable>().Add(key, node);
	}

	public override void AddRange(IEnumerable<TomlNode> nodes)
	{
		Set<TomlArray>().AddRange(nodes);
	}

	private TomlNode Set<T>() where T : TomlNode, new()
	{
		if (replacement != null)
		{
			return replacement;
		}
		T val = new T
		{
			Comment = Comment
		};
		if (parent.IsTable)
		{
			TomlNode node;
			string text = parent.Keys.FirstOrDefault((string s) => parent.TryGetNode(s, out node) && node.Equals(this));
			if (text == null)
			{
				return null;
			}
			parent[text] = val;
		}
		else
		{
			if (!parent.IsArray)
			{
				return null;
			}
			int num = parent.Children.TakeWhile((TomlNode child) => child != this).Count();
			if (num == parent.ChildrenCount)
			{
				return null;
			}
			parent[num] = val;
		}
		replacement = val;
		return val;
	}
}
public class TOMLParser : IDisposable
{
	public enum ParseState
	{
		None,
		KeyValuePair,
		SkipToNextLine,
		Table
	}

	private readonly TextReader reader;

	private ParseState currentState;

	private int line;

	private int col;

	private List<TomlSyntaxException> syntaxErrors;

	public bool ForceASCII { get; set; }

	public TOMLParser(TextReader reader)
	{
		this.reader = reader;
		line = (col = 0);
	}

	public void Dispose()
	{
		reader?.Dispose();
	}

	public TomlTable Parse()
	{
		syntaxErrors = new List<TomlSyntaxException>();
		line = (col = 1);
		TomlTable tomlTable = new TomlTable();
		TomlTable tomlTable2 = tomlTable;
		currentState = ParseState.None;
		List<string> parts = new List<string>();
		bool flag = false;
		StringBuilder stringBuilder = null;
		bool flag2 = true;
		int num;
		while ((num = reader.Peek()) >= 0)
		{
			char c = (char)num;
			if (currentState != 0)
			{
				goto IL_011d;
			}
			if (!TomlSyntax.IsWhiteSpace(c))
			{
				if (TomlSyntax.IsNewLine(c))
				{
					if (stringBuilder != null && flag2)
					{
						tomlTable.Comment = stringBuilder.ToString().TrimEnd(new char[0]);
						stringBuilder = null;
						flag2 = false;
					}
					if (TomlSyntax.IsLineBreak(c))
					{
						AdvanceLine();
					}
				}
				else
				{
					if (c == '#')
					{
						if (stringBuilder == null)
						{
							stringBuilder = new StringBuilder();
						}
						stringBuilder.AppendLine(ParseComment());
						AdvanceLine(1);
						continue;
					}
					flag2 = false;
					if (c != '[')
					{
						if (TomlSyntax.IsBareKey(c) || TomlSyntax.IsQuoted(c))
						{
							currentState = ParseState.KeyValuePair;
							goto IL_011d;
						}
						AddError($"Unexpected character \"{c}\"");
						continue;
					}
					currentState = ParseState.Table;
				}
			}
			goto IL_0368;
			IL_011d:
			if (currentState == ParseState.KeyValuePair)
			{
				TomlNode tomlNode = ReadKeyValuePair(parts);
				if (tomlNode == null)
				{
					stringBuilder = null;
					parts.Clear();
					if (currentState != 0)
					{
						AddError("Failed to parse key-value pair!");
					}
					continue;
				}
				tomlNode.Comment = stringBuilder?.ToString()?.TrimEnd(new char[0]);
				bool num2 = InsertNode(tomlNode, tomlTable2, parts);
				stringBuilder = null;
				parts.Clear();
				if (num2)
				{
					currentState = ParseState.SkipToNextLine;
				}
				continue;
			}
			if (currentState == ParseState.Table)
			{
				if (parts.Count == 0)
				{
					if (c == '[')
					{
						ConsumeChar();
						flag = true;
					}
					if (!ReadKeyName(ref parts, ']'))
					{
						parts.Clear();
					}
					else if (parts.Count == 0)
					{
						AddError("Table name is emtpy.");
						flag = false;
						stringBuilder = null;
						parts.Clear();
					}
					continue;
				}
				if (c == ']')
				{
					if (flag)
					{
						ConsumeChar();
						int num3 = reader.Peek();
						if (num3 < 0 || (ushort)num3 != 93)
						{
							AddError("Array table " + ".".Join(parts) + " has only one closing bracket.");
							parts.Clear();
							flag = false;
							stringBuilder = null;
							continue;
						}
					}
					tomlTable2 = CreateTable(tomlTable, parts, flag);
					if (tomlTable2 != null)
					{
						tomlTable2.IsInline = false;
						tomlTable2.Comment = stringBuilder?.ToString()?.TrimEnd(new char[0]);
					}
					parts.Clear();
					flag = false;
					stringBuilder = null;
					if (tomlTable2 == null)
					{
						if (currentState != 0)
						{
							AddError("Error creating table array!");
						}
						tomlTable2 = tomlTable;
						continue;
					}
					currentState = ParseState.SkipToNextLine;
					goto IL_0368;
				}
				if (parts.Count != 0)
				{
					AddError($"Unexpected character \"{c}\"");
					parts.Clear();
					flag = false;
					stringBuilder = null;
				}
			}
			if (currentState == ParseState.SkipToNextLine && !TomlSyntax.IsWhiteSpace(c))
			{
				switch (c)
				{
				case '\n':
				case '#':
					currentState = ParseState.None;
					AdvanceLine();
					if (c == '#')
					{
						col++;
						ParseComment();
						continue;
					}
					break;
				default:
					AddError($"Unexpected character \"{c}\" at the end of the line.");
					break;
				case '\r':
					break;
				}
			}
			goto IL_0368;
			IL_0368:
			reader.Read();
			col++;
		}
		if (currentState != 0 && currentState != ParseState.SkipToNextLine)
		{
			AddError("Unexpected end of file!");
		}
		if (syntaxErrors.Count > 0)
		{
			throw new TomlParseException(tomlTable, syntaxErrors);
		}
		return tomlTable;
	}

	private bool AddError(string message, bool skipLine = true)
	{
		syntaxErrors.Add(new TomlSyntaxException(message, currentState, line, col));
		if (skipLine)
		{
			reader.ReadLine();
			AdvanceLine(1);
		}
		currentState = ParseState.None;
		return false;
	}

	private void AdvanceLine(int startCol = 0)
	{
		line++;
		col = startCol;
	}

	private int ConsumeChar()
	{
		col++;
		return reader.Read();
	}

	private TomlNode ReadKeyValuePair(List<string> keyParts)
	{
		int num;
		while ((num = reader.Peek()) >= 0)
		{
			char c = (char)num;
			if (TomlSyntax.IsQuoted(c) || TomlSyntax.IsBareKey(c))
			{
				if (keyParts.Count != 0)
				{
					AddError("Encountered extra characters in key definition!");
					return null;
				}
				if (!ReadKeyName(ref keyParts, '='))
				{
					return null;
				}
				continue;
			}
			if (TomlSyntax.IsWhiteSpace(c))
			{
				ConsumeChar();
				continue;
			}
			if (c == '=')
			{
				ConsumeChar();
				return ReadValue();
			}
			AddError($"Unexpected character \"{c}\" in key name.");
			return null;
		}
		return null;
	}

	private TomlNode ReadValue(bool skipNewlines = false)
	{
		int num;
		while ((num = reader.Peek()) >= 0)
		{
			char c = (char)num;
			if (TomlSyntax.IsWhiteSpace(c))
			{
				ConsumeChar();
				continue;
			}
			if (c == '#')
			{
				AddError("No value found!");
				return null;
			}
			if (TomlSyntax.IsNewLine(c))
			{
				if (skipNewlines)
				{
					reader.Read();
					AdvanceLine(1);
					continue;
				}
				AddError("Encountered a newline when expecting a value!");
				return null;
			}
			if (TomlSyntax.IsQuoted(c))
			{
				char excess;
				bool flag = IsTripleQuote(c, out excess);
				if (currentState == ParseState.None)
				{
					return null;
				}
				string text = (flag ? ReadQuotedValueMultiLine(c) : ReadQuotedValueSingleLine(c, excess));
				if (text == null)
				{
					return null;
				}
				return new TomlString
				{
					Value = text,
					IsMultiline = flag,
					PreferLiteral = (c == '\'')
				};
			}
			return c switch
			{
				'{' => ReadInlineTable(), 
				'[' => ReadArray(), 
				_ => ReadTomlValue(), 
			};
		}
		return null;
	}

	private bool ReadKeyName(ref List<string> parts, char until)
	{
		StringBuilder stringBuilder = new StringBuilder();
		bool flag = false;
		bool flag2 = false;
		int num;
		while ((num = reader.Peek()) >= 0)
		{
			char c = (char)num;
			if (c == until)
			{
				break;
			}
			if (TomlSyntax.IsWhiteSpace(c))
			{
				flag2 = true;
			}
			else
			{
				if (stringBuilder.Length == 0)
				{
					flag2 = false;
				}
				if (c == '.')
				{
					if (stringBuilder.Length == 0 && !flag)
					{
						return AddError("Found an extra subkey separator in " + ".".Join(parts) + "...");
					}
					parts.Add(stringBuilder.ToString());
					stringBuilder.Length = 0;
					flag = false;
					flag2 = false;
				}
				else
				{
					if (flag2)
					{
						return AddError("Invalid spacing in key name");
					}
					if (TomlSyntax.IsQuoted(c))
					{
						if (flag)
						{
							return AddError("Expected a subkey separator but got extra data instead!");
						}
						if (stringBuilder.Length != 0)
						{
							return AddError("Encountered a quote in the middle of subkey name!");
						}
						col++;
						stringBuilder.Append(ReadQuotedValueSingleLine((char)reader.Read()));
						flag = true;
						continue;
					}
					if (!TomlSyntax.IsBareKey(c))
					{
						break;
					}
					stringBuilder.Append(c);
				}
			}
			reader.Read();
			col++;
		}
		if (stringBuilder.Length == 0 && !flag)
		{
			return AddError("Found an extra subkey separator in " + ".".Join(parts) + "...");
		}
		parts.Add(stringBuilder.ToString());
		return true;
	}

	private string ReadRawValue()
	{
		StringBuilder stringBuilder = new StringBuilder();
		int num;
		while ((num = reader.Peek()) >= 0)
		{
			char c = (char)num;
			if (c == '#' || TomlSyntax.IsNewLine(c) || TomlSyntax.IsValueSeparator(c))
			{
				break;
			}
			stringBuilder.Append(c);
			ConsumeChar();
		}
		return stringBuilder.ToString().Trim();
	}

	private TomlNode ReadTomlValue()
	{
		string text = ReadRawValue();
		string text2 = text;
		string text3 = text2;
		int numberBase;
		TomlNode tomlNode = (TomlSyntax.IsBoolean(text3) ? ((TomlNode)bool.Parse(text3)) : (TomlSyntax.IsNaN(text2) ? ((TomlNode)double.NaN) : (TomlSyntax.IsPosInf(text2) ? ((TomlNode)double.PositiveInfinity) : (TomlSyntax.IsNegInf(text2) ? ((TomlNode)double.NegativeInfinity) : (TomlSyntax.IsInteger(text2) ? ((TomlNode)long.Parse(text.RemoveAll('_'), CultureInfo.InvariantCulture)) : (TomlSyntax.IsFloat(text2) ? ((TomlNode)double.Parse(text.RemoveAll('_'), CultureInfo.InvariantCulture)) : ((!TomlSyntax.IsIntegerWithBase(text2, out numberBase)) ? null : new TomlInteger
		{
			Value = Convert.ToInt64(text.Substring(2).RemoveAll('_'), numberBase),
			IntegerBase = (TomlInteger.Base)numberBase
		})))))));
		TomlNode tomlNode2 = tomlNode;
		if (tomlNode2 != null)
		{
			return tomlNode2;
		}
		text = text.Replace(" ", "T");
		if (StringUtils.TryParseDateTime(text, TomlSyntax.RFC3339LocalDateTimeFormats, DateTimeStyles.AssumeLocal, (StringUtils.TryDateParseDelegate<DateTime>)DateTime.TryParseExact, out DateTime dateTime, out int parsedFormat))
		{
			return new TomlDateTimeLocal
			{
				Value = dateTime,
				SecondsPrecision = parsedFormat
			};
		}
		if (DateTime.TryParseExact(text, TomlSyntax.LocalDateFormat, CultureInfo.InvariantCulture, DateTimeStyles.AssumeLocal, out dateTime))
		{
			return new TomlDateTimeLocal
			{
				Value = dateTime,
				Style = TomlDateTimeLocal.DateTimeStyle.Date
			};
		}
		if (StringUtils.TryParseDateTime(text, TomlSyntax.RFC3339LocalTimeFormats, DateTimeStyles.AssumeLocal, (StringUtils.TryDateParseDelegate<DateTime>)DateTime.TryParseExact, out dateTime, out parsedFormat))
		{
			return new TomlDateTimeLocal
			{
				Value = dateTime,
				Style = TomlDateTimeLocal.DateTimeStyle.Time,
				SecondsPrecision = parsedFormat
			};
		}
		if (StringUtils.TryParseDateTime(text, TomlSyntax.RFC3339Formats, DateTimeStyles.None, (StringUtils.TryDateParseDelegate<DateTimeOffset>)DateTimeOffset.TryParseExact, out DateTimeOffset dateTime2, out parsedFormat))
		{
			return new TomlDateTimeOffset
			{
				Value = dateTime2,
				SecondsPrecision = parsedFormat
			};
		}
		AddError("Value \"" + text + "\" is not a valid TOML value!");
		return null;
	}

	private TomlArray ReadArray()
	{
		ConsumeChar();
		TomlArray tomlArray = new TomlArray();
		TomlNode tomlNode = null;
		bool flag = true;
		int num;
		while ((num = reader.Peek()) >= 0)
		{
			char c = (char)num;
			switch (c)
			{
			case ']':
				break;
			case '#':
				reader.ReadLine();
				AdvanceLine(1);
				continue;
			default:
				if (TomlSyntax.IsWhiteSpace(c) || TomlSyntax.IsNewLine(c))
				{
					if (TomlSyntax.IsLineBreak(c))
					{
						AdvanceLine();
					}
				}
				else
				{
					if (c != ',')
					{
						if (!flag)
						{
							AddError("Missing separator between values");
							return null;
						}
						tomlNode = ReadValue(skipNewlines: true);
						if (tomlNode == null)
						{
							if (currentState != 0)
							{
								AddError("Failed to determine and parse a value!");
							}
							return null;
						}
						flag = false;
						continue;
					}
					if (tomlNode == null)
					{
						AddError("Encountered multiple value separators");
						return null;
					}
					tomlArray.Add(tomlNode);
					tomlNode = null;
					flag = true;
				}
				ConsumeChar();
				continue;
			}
			ConsumeChar();
			break;
		}
		if (tomlNode != null)
		{
			tomlArray.Add(tomlNode);
		}
		return tomlArray;
	}

	private TomlNode ReadInlineTable()
	{
		ConsumeChar();
		TomlTable tomlTable = new TomlTable
		{
			IsInline = true
		};
		TomlNode tomlNode = null;
		bool flag = false;
		List<string> list = new List<string>();
		int num;
		while ((num = reader.Peek()) >= 0)
		{
			char c = (char)num;
			switch (c)
			{
			case '}':
				break;
			case '#':
				AddError("Incomplete inline table definition!");
				return null;
			default:
				if (TomlSyntax.IsNewLine(c))
				{
					AddError("Inline tables are only allowed to be on single line");
					return null;
				}
				if (!TomlSyntax.IsWhiteSpace(c))
				{
					if (c != ',')
					{
						flag = false;
						tomlNode = ReadKeyValuePair(list);
						continue;
					}
					if (tomlNode == null)
					{
						AddError("Encountered multiple value separators in inline table!");
						return null;
					}
					if (!InsertNode(tomlNode, tomlTable, list))
					{
						return null;
					}
					list.Clear();
					tomlNode = null;
					flag = true;
				}
				ConsumeChar();
				continue;
			}
			ConsumeChar();
			break;
		}
		if (flag)
		{
			AddError("Trailing commas are not allowed in inline tables.");
			return null;
		}
		if (tomlNode != null && !InsertNode(tomlNode, tomlTable, list))
		{
			return null;
		}
		return tomlTable;
	}

	private bool IsTripleQuote(char quote, out char excess)
	{
		ConsumeChar();
		int num;
		if ((num = reader.Peek()) < 0)
		{
			excess = '\0';
			return AddError("Unexpected end of file!");
		}
		if ((ushort)num != quote)
		{
			excess = '\0';
			return false;
		}
		excess = (char)ConsumeChar();
		if ((num = reader.Peek()) < 0 || (ushort)num != quote)
		{
			return false;
		}
		ConsumeChar();
		excess = '\0';
		return true;
	}

	private bool ProcessQuotedValueCharacter(char quote, bool isNonLiteral, char c, StringBuilder sb, ref bool escaped)
	{
		if (TomlSyntax.MustBeEscaped(c))
		{
			return AddError($"The character U+{(int)c:X8} must be escaped in a string!");
		}
		if (escaped)
		{
			sb.Append(c);
			escaped = false;
			return false;
		}
		if (c == quote)
		{
			return true;
		}
		if (isNonLiteral && c == '\\')
		{
			escaped = true;
		}
		if (c == '\n')
		{
			return AddError("Encountered newline in single line string!");
		}
		sb.Append(c);
		return false;
	}

	private string ReadQuotedValueSingleLine(char quote, char initialData = '\0')
	{
		bool flag = quote == '"';
		StringBuilder stringBuilder = new StringBuilder();
		bool escaped = false;
		if (initialData != 0)
		{
			bool flag2 = ProcessQuotedValueCharacter(quote, flag, initialData, stringBuilder, ref escaped);
			if (currentState == ParseState.None)
			{
				return null;
			}
			if (flag2)
			{
				if (flag)
				{
					if (stringBuilder.ToString().TryUnescape(out var unescaped, out var exception))
					{
						return unescaped;
					}
					AddError(exception.Message);
					return null;
				}
				return stringBuilder.ToString();
			}
		}
		bool flag3 = false;
		int num;
		while ((num = reader.Read()) >= 0)
		{
			col++;
			char c = (char)num;
			flag3 = ProcessQuotedValueCharacter(quote, flag, c, stringBuilder, ref escaped);
			if (flag3)
			{
				if (currentState != 0)
				{
					break;
				}
				return null;
			}
		}
		if (!flag3)
		{
			AddError("Unclosed string.");
			return null;
		}
		if (!flag)
		{
			return stringBuilder.ToString();
		}
		if (stringBuilder.ToString().TryUnescape(out var unescaped2, out var exception2))
		{
			return unescaped2;
		}
		AddError(exception2.Message);
		return null;
	}

	private string ReadQuotedValueMultiLine(char quote)
	{
		bool flag = quote == '"';
		StringBuilder stringBuilder = new StringBuilder();
		bool flag2 = false;
		bool flag3 = false;
		bool flag4 = false;
		int num = 0;
		bool flag5 = true;
		int num2;
		while ((num2 = ConsumeChar()) >= 0)
		{
			char c = (char)num2;
			if (TomlSyntax.MustBeEscaped(c, allowNewLines: true))
			{
				AddError($"The character U+{(int)c:X8} must be escaped!");
				return null;
			}
			if (flag5 && TomlSyntax.IsNewLine(c))
			{
				if (TomlSyntax.IsLineBreak(c))
				{
					flag5 = false;
				}
				else
				{
					AdvanceLine();
				}
				continue;
			}
			flag5 = false;
			if (flag2)
			{
				stringBuilder.Append(c);
				flag2 = false;
				continue;
			}
			if (flag3)
			{
				if (TomlSyntax.IsEmptySpace(c))
				{
					if (TomlSyntax.IsLineBreak(c))
					{
						flag4 = true;
						AdvanceLine();
					}
					continue;
				}
				if (!flag4)
				{
					AddError("Non-whitespace character after trim marker.");
					return null;
				}
				flag4 = false;
				flag3 = false;
			}
			if (flag && c == '\\')
			{
				int num3 = reader.Peek();
				char c2 = (char)num3;
				if (num3 >= 0)
				{
					if (TomlSyntax.IsEmptySpace(c2))
					{
						flag3 = true;
						continue;
					}
					if (c2 == quote || c2 == '\\')
					{
						flag2 = true;
					}
				}
			}
			num = ((c == quote) ? (num + 1) : 0);
			if (num == 3)
			{
				break;
			}
			stringBuilder.Append(c);
		}
		num = 0;
		while ((num2 = reader.Peek()) >= 0)
		{
			char c3 = (char)num2;
			if (c3 != quote || ++num >= 3)
			{
				break;
			}
			stringBuilder.Append(c3);
			ConsumeChar();
		}
		stringBuilder.Length -= 2;
		if (!flag)
		{
			return stringBuilder.ToString();
		}
		if (stringBuilder.ToString().TryUnescape(out var unescaped, out var exception))
		{
			return unescaped;
		}
		AddError(exception.Message);
		return null;
	}

	private bool InsertNode(TomlNode node, TomlNode root, IList<string> path)
	{
		TomlNode tomlNode = root;
		if (path.Count > 1)
		{
			for (int i = 0; i < path.Count - 1; i++)
			{
				string key = path[i];
				if (!tomlNode.TryGetNode(key, out var node2))
				{
					node2 = (tomlNode[key] = new TomlTable());
				}
				else if (node2.HasValue)
				{
					return AddError("The key " + ".".Join(path) + " already has a value assigned to it!");
				}
				tomlNode = node2;
				if (tomlNode is TomlTable tomlTable && tomlTable.IsInline)
				{
					return AddError("Cannot assign " + ".".Join(path) + " because it will edit an immutable table.");
				}
			}
		}
		if (tomlNode.HasKey(path[path.Count - 1]))
		{
			return AddError("The key " + ".".Join(path) + " is already defined!");
		}
		tomlNode[path[path.Count - 1]] = node;
		node.CollapseLevel = path.Count - 1;
		return true;
	}

	private TomlTable CreateTable(TomlNode root, IList<string> path, bool arrayTable)
	{
		if (path.Count == 0)
		{
			return null;
		}
		TomlNode tomlNode = root;
		for (int i = 0; i < path.Count; i++)
		{
			string key = path[i];
			if (tomlNode.TryGetNode(key, out var node))
			{
				if (node.IsArray && arrayTable)
				{
					TomlArray tomlArray = (TomlArray)node;
					if (!tomlArray.IsTableArray)
					{
						AddError("The array " + ".".Join(path) + " cannot be redefined as an array table!");
						return null;
					}
					if (i == path.Count - 1)
					{
						tomlNode = new TomlTable();
						tomlArray.Add(tomlNode);
						break;
					}
					tomlNode = tomlArray[tomlArray.ChildrenCount - 1];
					continue;
				}
				if (node.HasValue)
				{
					if (!(node is TomlArray tomlArray2) || !tomlArray2.IsTableArray)
					{
						AddError("The key " + ".".Join(path) + " has a value assigned to it!");
						return null;
					}
					tomlNode = tomlArray2[tomlArray2.ChildrenCount - 1];
					continue;
				}
				if (i == path.Count - 1)
				{
					if (arrayTable && !node.IsArray)
					{
						AddError("The table " + ".".Join(path) + " cannot be redefined as an array table!");
						return null;
					}
					if (node is TomlTable tomlTable && !tomlTable.IsInline)
					{
						AddError("The table " + ".".Join(path) + " is defined multiple times!");
						return null;
					}
				}
			}
			else
			{
				if (i == path.Count - 1 && arrayTable)
				{
					TomlTable tomlTable2 = new TomlTable();
					TomlArray tomlArray3 = new TomlArray
					{
						IsTableArray = true
					};
					tomlArray3.Add(tomlTable2);
					tomlNode[key] = tomlArray3;
					tomlNode = tomlTable2;
					break;
				}
				node = (tomlNode[key] = new TomlTable
				{
					IsInline = true
				});
			}
			tomlNode = node;
		}
		return (TomlTable)tomlNode;
	}

	private string ParseComment()
	{
		ConsumeChar();
		string obj = reader.ReadLine()?.Trim() ?? "";
		if (obj.Any((char ch) => TomlSyntax.MustBeEscaped(ch)))
		{
			AddError("Comment must not contain control characters other than tab.", skipLine: false);
		}
		return obj;
	}
}
public static class TOML
{
	public static bool ForceASCII { get; set; }

	public static TomlTable Parse(TextReader reader)
	{
		using TOMLParser tOMLParser = new TOMLParser(reader)
		{
			ForceASCII = ForceASCII
		};
		return tOMLParser.Parse();
	}
}
public class TomlFormatException : Exception
{
	public TomlFormatException(string message)
		: base(message)
	{
	}
}
public class TomlParseException : Exception
{
	public TomlTable ParsedTable { get; }

	public IEnumerable<TomlSyntaxException> SyntaxErrors { get; }

	public TomlParseException(TomlTable parsed, IEnumerable<TomlSyntaxException> exceptions)
		: base("TOML file contains format errors")
	{
		ParsedTable = parsed;
		SyntaxErrors = exceptions;
	}
}
public class TomlSyntaxException : Exception
{
	public TOMLParser.ParseState ParseState { get; }

	public int Line { get; }

	public int Column { get; }

	public TomlSyntaxException(string message, TOMLParser.ParseState state, int line, int col)
		: base(message)
	{
		ParseState = state;
		Line = line;
		Column = col;
	}
}
internal static class TomlSyntax
{
	public const string TRUE_VALUE = "true";

	public const string FALSE_VALUE = "false";

	public const string NAN_VALUE = "nan";

	public const string POS_NAN_VALUE = "+nan";

	public const string NEG_NAN_VALUE = "-nan";

	public const string INF_VALUE = "inf";

	public const string POS_INF_VALUE = "+inf";

	public const string NEG_INF_VALUE = "-inf";

	public static readonly Regex IntegerPattern = new Regex("^(\\+|-)?(?!_)(0|(?!0)(_?\\d)*)$", RegexOptions.Compiled);

	public static readonly Regex BasedIntegerPattern = new Regex("^0(?<base>x|b|o)(?!_)(_?[0-9A-F])*$", RegexOptions.IgnoreCase | RegexOptions.Compiled);

	public static readonly Regex FloatPattern = new Regex("^(\\+|-)?(?!_)(0|(?!0)(_?\\d)+)(((e(\\+|-)?(?!_)(_?\\d)+)?)|(\\.(?!_)(_?\\d)+(e(\\+|-)?(?!_)(_?\\d)+)?))$", RegexOptions.IgnoreCase | RegexOptions.Compiled);

	public static readonly Dictionary<string, int> IntegerBases = new Dictionary<string, int>
	{
		["x"] = 16,
		["o"] = 8,
		["b"] = 2
	};

	public static readonly Dictionary<int, string> BaseIdentifiers = new Dictionary<int, string>
	{
		[2] = "b",
		[8] = "o",
		[16] = "x"
	};

	public const string RFC3339EmptySeparator = " ";

	public const string ISO861Separator = "T";

	public const string ISO861ZeroZone = "+00:00";

	public const string RFC3339ZeroZone = "Z";

	public static readonly string[] RFC3339Formats = new string[8] { "yyyy'-'MM-ddTHH':'mm':'ssK", "yyyy'-'MM-ddTHH':'mm':'ss'.'fK", "yyyy'-'MM-ddTHH':'mm':'ss'.'ffK", "yyyy'-'MM-ddTHH':'mm':'ss'.'fffK", "yyyy'-'MM-ddTHH':'mm':'ss'.'ffffK", "yyyy'-'MM-ddTHH':'mm':'ss'.'fffffK", "yyyy'-'MM-ddTHH':'mm':'ss'.'ffffffK", "yyyy'-'MM-ddTHH':'mm':'ss'.'fffffffK" };

	public static readonly string[] RFC3339LocalDateTimeFormats = new string[8] { "yyyy'-'MM-ddTHH':'mm':'ss", "yyyy'-'MM-ddTHH':'mm':'ss'.'f", "yyyy'-'MM-ddTHH':'mm':'ss'.'ff", "yyyy'-'MM-ddTHH':'mm':'ss'.'fff", "yyyy'-'MM-ddTHH':'mm':'ss'.'ffff", "yyyy'-'MM-ddTHH':'mm':'ss'.'fffff", "yyyy'-'MM-ddTHH':'mm':'ss'.'ffffff", "yyyy'-'MM-ddTHH':'mm':'ss'.'fffffff" };

	public static readonly string LocalDateFormat = "yyyy'-'MM'-'dd";

	public static readonly string[] RFC3339LocalTimeFormats = new string[8] { "HH':'mm':'ss", "HH':'mm':'ss'.'f", "HH':'mm':'ss'.'ff", "HH':'mm':'ss'.'fff", "HH':'mm':'ss'.'ffff", "HH':'mm':'ss'.'fffff", "HH':'mm':'ss'.'ffffff", "HH':'mm':'ss'.'fffffff" };

	public const char ARRAY_END_SYMBOL = ']';

	public const char ITEM_SEPARATOR = ',';

	public const char ARRAY_START_SYMBOL = '[';

	public const char BASIC_STRING_SYMBOL = '"';

	public const char COMMENT_SYMBOL = '#';

	public const char ESCAPE_SYMBOL = '\\';

	public const char KEY_VALUE_SEPARATOR = '=';

	public const char NEWLINE_CARRIAGE_RETURN_CHARACTER = '\r';

	public const char NEWLINE_CHARACTER = '\n';

	public const char SUBKEY_SEPARATOR = '.';

	public const char TABLE_END_SYMBOL = ']';

	public const char TABLE_START_SYMBOL = '[';

	public const char INLINE_TABLE_START_SYMBOL = '{';

	public const char INLINE_TABLE_END_SYMBOL = '}';

	public const char LITERAL_STRING_SYMBOL = '\'';

	public const char INT_NUMBER_SEPARATOR = '_';

	public static readonly char[] NewLineCharacters = new char[2] { '\n', '\r' };

	public static bool IsBoolean(string s)
	{
		if (!(s == "true"))
		{
			return s == "false";
		}
		return true;
	}

	public static bool IsPosInf(string s)
	{
		if (!(s == "inf"))
		{
			return s == "+inf";
		}
		return true;
	}

	public static bool IsNegInf(string s)
	{
		return s == "-inf";
	}

	public static bool IsNaN(string s)
	{
		if (!(s == "nan") && !(s == "+nan"))
		{
			return s == "-nan";
		}
		return true;
	}

	public static bool IsInteger(string s)
	{
		return IntegerPattern.IsMatch(s);
	}

	public static bool IsFloat(string s)
	{
		return FloatPattern.IsMatch(s);
	}

	public static bool IsIntegerWithBase(string s, out int numberBase)
	{
		numberBase = 10;
		Match match = BasedIntegerPattern.Match(s);
		if (!match.Success)
		{
			return false;
		}
		IntegerBases.TryGetValue(match.Groups["base"].Value, out numberBase);
		return true;
	}

	public static bool IsQuoted(char c)
	{
		if (c != '"')
		{
			return c == '\'';
		}
		return true;
	}

	public static bool IsWhiteSpace(char c)
	{
		if (c != ' ')
		{
			return c == '\t';
		}
		return true;
	}

	public static bool IsNewLine(char c)
	{
		if (c != '\n')
		{
			return c == '\r';
		}
		return true;
	}

	public static bool IsLineBreak(char c)
	{
		return c == '\n';
	}

	public static bool IsEmptySpace(char c)
	{
		if (!IsWhiteSpace(c))
		{
			return IsNewLine(c);
		}
		return true;
	}

	public static bool IsBareKey(char c)
	{
		switch (c)
		{
		case '-':
		case '0':
		case '1':
		case '2':
		case '3':
		case '4':
		case '5':
		case '6':
		case '7':
		case '8':
		case '9':
		case 'A':
		case 'B':
		case 'C':
		case 'D':
		case 'E':
		case 'F':
		case 'G':
		case 'H':
		case 'I':
		case 'J':
		case 'K':
		case 'L':
		case 'M':
		case 'N':
		case 'O':
		case 'P':
		case 'Q':
		case 'R':
		case 'S':
		case 'T':
		case 'U':
		case 'V':
		case 'W':
		case 'X':
		case 'Y':
		case 'Z':
		case '_':
		case 'a':
		case 'b':
		case 'c':
		case 'd':
		case 'e':
		case 'f':
		case 'g':
		case 'h':
		case 'i':
		case 'j':
		case 'k':
		case 'l':
		case 'm':
		case 'n':
		case 'o':
		case 'p':
		case 'q':
		case 'r':
		case 's':
		case 't':
		case 'u':
		case 'v':
		case 'w':
		case 'x':
		case 'y':
		case 'z':
			return true;
		default:
			return false;
		}
	}

	public static bool MustBeEscaped(char c, bool allowNewLines = false)
	{
		if (c >= '\u000e')
		{
			if (c <= '\u001f' || c == '\u007f')
			{
				goto IL_001f;
			}
		}
		else if (c <= '\b' || c == '\v' || c == '\f')
		{
			goto IL_001f;
		}
		bool flag = false;
		goto IL_0025;
		IL_001f:
		flag = true;
		goto IL_0025;
		IL_0025:
		bool flag2 = flag;
		if (!allowNewLines)
		{
			flag2 = flag2 || (c >= '\n' && c <= '\u000e');
		}
		return flag2;
	}

	public static bool IsValueSeparator(char c)
	{
		if (c != ',' && c != ']')
		{
			return c == '}';
		}
		return true;
	}
}
internal static class StringUtils
{
	public delegate bool TryDateParseDelegate<T>(string s, string format, IFormatProvider ci, DateTimeStyles dts, out T dt);

	public static string AsKey(this string key)
	{
		if (key == string.Empty || key.Any((char c) => !TomlSyntax.IsBareKey(c)))
		{
			return $"{'"'}{key.Escape()}{'"'}";
		}
		return key;
	}

	public static string Join(this string self, IEnumerable<string> subItems)
	{
		StringBuilder stringBuilder = new StringBuilder();
		bool flag = true;
		foreach (string subItem in subItems)
		{
			if (!flag)
			{
				stringBuilder.Append(self);
			}
			flag = false;
			stringBuilder.Append(subItem);
		}
		return stringBuilder.ToString();
	}

	public static bool TryParseDateTime<T>(string s, string[] formats, DateTimeStyles styles, TryDateParseDelegate<T> parser, out T dateTime, out int parsedFormat)
	{
		parsedFormat = 0;
		dateTime = default(T);
		for (int i = 0; i < formats.Length; i++)
		{
			string format = formats[i];
			if (parser(s, format, CultureInfo.InvariantCulture, styles, out dateTime))
			{
				parsedFormat = i;
				return true;
			}
		}
		return false;
	}

	public static void AsComment(this string self, TextWriter tw)
	{
		string[] array = self.Split(new char[1] { '\n' });
		foreach (string text in array)
		{
			tw.WriteLine($"{'#'} {text.Trim()}");
		}
	}

	public static string RemoveAll(this string txt, char toRemove)
	{
		StringBuilder stringBuilder = new StringBuilder(txt.Length);
		foreach (char item in txt.Where((char c) => c != toRemove))
		{
			stringBuilder.Append(item);
		}
		return stringBuilder.ToString();
	}

	public static string Escape(this string txt, bool escapeNewlines = true)
	{
		StringBuilder stringBuilder = new StringBuilder(txt.Length + 2);
		StringBuilder stringBuilder2;
		object value;
		for (int j = 0; j < txt.Length; stringBuilder2.Append(value), j++)
		{
			char c2 = txt[j];
			stringBuilder2 = stringBuilder;
			switch (c2)
			{
			case '\b':
				value = "\\b";
				continue;
			case '\t':
				value = "\\t";
				continue;
			case '\n':
				if (escapeNewlines)
				{
					value = "\\n";
					continue;
				}
				break;
			case '\f':
				value = "\\f";
				continue;
			case '\r':
				if (escapeNewlines)
				{
					value = "\\r";
					continue;
				}
				break;
			case '\\':
				value = "\\\\";
				continue;
			case '"':
				value = "\\\"";
				continue;
			}
			value = ((!TomlSyntax.MustBeEscaped(c2, !escapeNewlines) && (!TOML.ForceASCII || c2 <= '\u007f')) ? ((object)c2) : CodePoint(txt, ref j, c2));
		}
		return stringBuilder.ToString();
		static string CodePoint(string txt, ref int i, char c)
		{
			if (!char.IsSurrogatePair(txt, i))
			{
				return $"\\u{(ushort)c:X4}";
			}
			return $"\\U{char.ConvertToUtf32(txt, i++):X8}";
		}
	}

	public static bool TryUnescape(this string txt, out string unescaped, out Exception exception)
	{
		try
		{
			exception = null;
			unescaped = txt.Unescape();
			return true;
		}
		catch (Exception ex)
		{
			exception = ex;
			unescaped = null;
			return false;
		}
	}

	public static string Unescape(this string txt)
	{
		if (string.IsNullOrEmpty(txt))
		{
			return txt;
		}
		StringBuilder stringBuilder = new StringBuilder(txt.Length);
		int num2 = 0;
		while (num2 < txt.Length)
		{
			int num3 = txt.IndexOf('\\', num2);
			int num4 = num3 + 1;
			if (num3 < 0 || num3 == txt.Length - 1)
			{
				num3 = txt.Length;
			}
			stringBuilder.Append(txt, num2, num3 - num2);
			if (num3 >= txt.Length)
			{
				break;
			}
			char c = txt[num4];
			StringBuilder stringBuilder2 = stringBuilder;
			stringBuilder2.Append(c switch
			{
				'b' => "\b", 
				't' => "\t", 
				'n' => "\n", 
				'f' => "\f", 
				'r' => "\r", 
				'\'' => "'", 
				'"' => "\"", 
				'\\' => "\\", 
				'u' => CodePoint(num4, txt, ref num3, 4), 
				'U' => CodePoint(num4, txt, ref num3, 8), 
				_ => throw new Exception("Undefined escape sequence!"), 
			});
			num2 = num3 + 2;
		}
		return stringBuilder.ToString();
		static string CodePoint(int next, string txt, ref int num, int size)
		{
			if (next + size >= txt.Length)
			{
				throw new Exception("Undefined escape sequence!");
			}
			num += size;
			return char.ConvertFromUtf32(Convert.ToInt32(txt.Substring(next + 1, size), 16));
		}
	}
}