Port NBT impl from LibAC Dart
This commit is contained in:
parent
0a022634c1
commit
ad7b619706
55 changed files with 3226 additions and 2983 deletions
196
NBT/API/StringReader.cs
Normal file
196
NBT/API/StringReader.cs
Normal file
|
@ -0,0 +1,196 @@
|
|||
using System;
|
||||
using System.Text;
|
||||
|
||||
namespace LibAC.NBT.API
|
||||
{
|
||||
public class StringReader
|
||||
{
|
||||
private readonly string _buffer;
|
||||
private int _position = 0;
|
||||
private int _lastPosition = 0;
|
||||
private bool _quotedString = false;
|
||||
|
||||
public StringReader(string buffer)
|
||||
{
|
||||
_buffer = buffer;
|
||||
}
|
||||
|
||||
// Check if there's more to read
|
||||
public bool CanRead => _CanRead();
|
||||
|
||||
private bool _CanRead()
|
||||
{
|
||||
SkipWhitespace();
|
||||
return _position < _buffer.Length;
|
||||
}
|
||||
|
||||
// Get the number of chars seeked
|
||||
public int Seeked => _lastPosition - _position;
|
||||
|
||||
// Read the next character
|
||||
public char Next()
|
||||
{
|
||||
if (CanRead)
|
||||
{
|
||||
SkipWhitespace();
|
||||
return _buffer[_position++];
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new Exception("End of buffer reached");
|
||||
}
|
||||
}
|
||||
|
||||
// Generates a snapshot of the text location if applicable
|
||||
public string GetSnapshot()
|
||||
{
|
||||
if (CanRead)
|
||||
{
|
||||
if (_position + 64 < _buffer.Length)
|
||||
{
|
||||
return _buffer.Substring(_position, 64);
|
||||
}
|
||||
else
|
||||
{
|
||||
return _buffer.Substring(_position);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return string.Empty;
|
||||
}
|
||||
}
|
||||
|
||||
// Peek the next character without advancing the position
|
||||
public char Peek()
|
||||
{
|
||||
SkipWhitespace();
|
||||
if (CanRead)
|
||||
{
|
||||
return _buffer[_position];
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new Exception("End of buffer reached");
|
||||
}
|
||||
}
|
||||
|
||||
// Skip any whitespace characters
|
||||
public void SkipWhitespace()
|
||||
{
|
||||
if (_quotedString) return; // We need whitespace for strings
|
||||
while (_position < _buffer.Length && IsWhitespace(_buffer[_position]))
|
||||
{
|
||||
_position++;
|
||||
}
|
||||
}
|
||||
|
||||
// Check if a character is a whitespace
|
||||
private bool IsWhitespace(char character)
|
||||
{
|
||||
return char.IsWhiteSpace(character);
|
||||
}
|
||||
|
||||
// Read until a specific character is found
|
||||
public string ReadUntil(char stopChar, int maxChars)
|
||||
{
|
||||
var result = new StringBuilder();
|
||||
int index = 0;
|
||||
while (CanRead && Peek() != stopChar && index < maxChars)
|
||||
{
|
||||
result.Append(Next().ToString());
|
||||
index++;
|
||||
}
|
||||
return result.ToString();
|
||||
}
|
||||
|
||||
// Read a string enclosed in double quotes
|
||||
public string ReadQuotedString()
|
||||
{
|
||||
_quotedString = true;
|
||||
if (Next() != '"')
|
||||
{
|
||||
throw new Exception("Expected double quotes at the start of a string");
|
||||
}
|
||||
var result = new StringBuilder();
|
||||
while (CanRead)
|
||||
{
|
||||
char character = Next();
|
||||
if (character == '"')
|
||||
{
|
||||
break;
|
||||
}
|
||||
result.Append(character.ToString());
|
||||
}
|
||||
_quotedString = false;
|
||||
return result.ToString();
|
||||
}
|
||||
|
||||
// Read a number (int or double)
|
||||
public string ReadNumber()
|
||||
{
|
||||
var result = new StringBuilder();
|
||||
while (CanRead && (IsDigit(Peek()) || Peek() == '.' || Peek() == '-'))
|
||||
{
|
||||
result.Append(Next().ToString());
|
||||
}
|
||||
return result.ToString();
|
||||
}
|
||||
|
||||
// Check if a character is a digit
|
||||
private bool IsDigit(char character)
|
||||
{
|
||||
return char.IsDigit(character);
|
||||
}
|
||||
|
||||
// Read an unquoted string (used for keys in SNBT)
|
||||
public string ReadUnquotedString()
|
||||
{
|
||||
var result = new StringBuilder();
|
||||
while (CanRead &&
|
||||
!IsWhitespace(Peek()) &&
|
||||
Peek() != ':' &&
|
||||
Peek() != ',' &&
|
||||
Peek() != '{' &&
|
||||
Peek() != '}' &&
|
||||
Peek() != '[' &&
|
||||
Peek() != ']')
|
||||
{
|
||||
result.Append(Next().ToString());
|
||||
}
|
||||
return result.ToString();
|
||||
}
|
||||
|
||||
public string ReadString()
|
||||
{
|
||||
if (Peek() == '"')
|
||||
{
|
||||
return ReadQuotedString();
|
||||
}
|
||||
else
|
||||
{
|
||||
return ReadUnquotedString();
|
||||
}
|
||||
}
|
||||
|
||||
// Read a specific character and throw an exception if it's not found
|
||||
public void Expect(char expectedChar)
|
||||
{
|
||||
if (char.ToLower(Next()) != char.ToLower(expectedChar))
|
||||
{
|
||||
throw new Exception($"Expected {expectedChar}");
|
||||
}
|
||||
}
|
||||
|
||||
public void StartSeek()
|
||||
{
|
||||
_lastPosition = _position;
|
||||
}
|
||||
|
||||
public void EndSeek()
|
||||
{
|
||||
_position = _lastPosition;
|
||||
_lastPosition = 0;
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue