namespace EonaCat.FirstLight.SaveTransfer.VdfGenerator.KeyValue;
///
/// Provides functionality for tokenizing a key-value formatted string input, allowing sequential reading and validation of symbols and quoted strings.
///
/// The input string to tokenize. Must not be null.
public class KeyValueTokenizer(string text)
{
private int _pos;
///
/// Determines whether the next non-whitespace character in the input matches the specified character without advancing the current position.
///
/// The character to compare with the next non-whitespace character in the input.
/// if the next non-whitespace character matches the specified character; otherwise, .
public bool PeekSymbol(char c)
{
SkipWhitespace();
return _pos < text.Length && text[_pos] == c;
}
///
/// Reads the next non-whitespace character from the input and verifies that it matches the specified symbol.
///
/// The character to match at the current position in the input.
/// Thrown if the next non-whitespace character does not match the specified symbol.
public void ReadSymbol(char c)
{
SkipWhitespace();
if (_pos >= text.Length || text[_pos] != c)
throw new Exception($"Expected '{c}' at position {_pos}");
_pos++;
}
///
/// Reads a string enclosed in quotation marks from the current position in the input text.
///
/// The string located between the opening and closing quotation marks or an empty string if there are no characters between the quotes.
/// Thrown when the current position does not contain an opening quotation mark or when a closing quotation mark cannot be found.
public string ReadString()
{
SkipWhitespace();
if (_pos >= text.Length || text[_pos] != '"')
throw new Exception($"Expected '\"' at position {_pos}, but found '{text[_pos]}'!");
_pos++; // skip opening quote
var start = _pos;
while (_pos < text.Length && text[_pos] != '"')
_pos++;
if (_pos >= text.Length)
throw new Exception("Unterminated string literal!");
var result = text.Substring(start, _pos - start);
_pos++; // skip closing quote
return result;
}
///
/// Advances the current position past any consecutive whitespace characters in the input text.
///
private void SkipWhitespace()
{
while (_pos < text.Length)
{
var c = text[_pos];
if (c is ' ' or '\t' or '\n' or '\r')
{
_pos++;
continue;
}
break;
}
}
}