using System.Text; using static System.Net.Mime.MediaTypeNames; namespace pgLabII.PgUtils.ConnectionStrings; public class PqConnectionStringTokenizer : IPqConnectionStringTokenizer { private readonly string input; private int position = 0; public bool Eof { get { ConsumeWhitespace(); return position >= input.Length; } } public PqConnectionStringTokenizer(string input) { this.input = input; position = 0; } public string GetKeyword() { if (Eof) throw new PqConnectionStringParserException($"Unexpected end of file was expecting a keyword at position {position}"); return GetString(forKeyword: true); } public void ConsumeEquals() { ConsumeWhitespace(); if (position < input.Length && input[position] == '=') { position++; } else throw new PqConnectionStringParserException($"Was expecting '=' after keyword at position {position}"); } public string GetValue() { if (Eof) throw new PqConnectionStringParserException($"Unexpected end of file was expecting a keyword at position {position}"); return GetString(forKeyword: false); } private string GetString(bool forKeyword) { if (forKeyword && input[position] == '=') throw new PqConnectionStringParserException($"Unexpected '=' was expecting keyword at position {position}"); if (input[position] == '\'') return ParseQuotedText(); return UnquotedString(forKeyword); } private void ConsumeWhitespace() { while (position < input.Length && char.IsWhiteSpace(input[position])) position++; } private string UnquotedString(bool forKeyword) { int start = position; while (++position < input.Length && !char.IsWhiteSpace(input[position]) && (!forKeyword || input[position] != '=')) { } return input.Substring(start, position - start); } private string ParseQuotedText() { bool escape = false; StringBuilder sb = new(); int start = position; while (++position < input.Length) { char c = input[position]; if (escape) { switch (c) { case '\'': case '\\': sb.Append(c); escape = false; break; default: throw new PqConnectionStringParserException($"Invalid escape sequence at position {position}"); } } else { if (c == '\'') { ++position; return sb.ToString(); } else if (c == '\\') { escape = true; } else { sb.Append(c); } } } throw new PqConnectionStringParserException($"Missing end quote on value starting at {start}"); } }