Fix SNBT Parsing and writing of single quoted strings, and strings with quotes or single quotes within.
This commit is contained in:
parent
bdb087fabc
commit
18e98ca918
9 changed files with 93 additions and 14 deletions
|
@ -503,18 +503,31 @@ class StringReader {
|
|||
return result.toString();
|
||||
}
|
||||
|
||||
// Read a string enclosed in double quotes
|
||||
/// Read a string enclosed in double quotes
|
||||
String readQuotedString() {
|
||||
_quotedString = true;
|
||||
if (next() != '"') {
|
||||
throw Exception('Expected double quotes at the start of a string');
|
||||
var nxtChar = next();
|
||||
|
||||
if (nxtChar != '"' && nxtChar != "'") {
|
||||
throw Exception(
|
||||
'Expected double quotes or single quotes at the start of a string');
|
||||
}
|
||||
StringBuffer result = StringBuffer();
|
||||
bool escaping = false;
|
||||
String quoteDigit = nxtChar;
|
||||
|
||||
while (canRead) {
|
||||
String char = next();
|
||||
if (char == '"') {
|
||||
|
||||
if (char == '"' && quoteDigit == "\"") {
|
||||
break;
|
||||
} else if (char == '\\' && peek() == '\'' && quoteDigit == '\'') {
|
||||
escaping = true;
|
||||
continue;
|
||||
} else if (char == '\'' && quoteDigit == '\'') {
|
||||
if (!escaping) break;
|
||||
}
|
||||
escaping = false;
|
||||
result.write(char);
|
||||
}
|
||||
_quotedString = false;
|
||||
|
@ -552,13 +565,15 @@ class StringReader {
|
|||
}
|
||||
|
||||
String readString() {
|
||||
if (peek() == "\"") {
|
||||
if (peek() == "\"" || peek() == "'") {
|
||||
return readQuotedString();
|
||||
} else
|
||||
return readUnquotedString();
|
||||
}
|
||||
|
||||
// Read a specific character and throw an exception if it's not found
|
||||
/// Read a specific character and throw an exception if it's not found
|
||||
///
|
||||
/// Parameter is case-insensitive
|
||||
void expect(String expectedChar) {
|
||||
if (next().toLowerCase() != expectedChar.toLowerCase()) {
|
||||
throw Exception('Expected $expectedChar');
|
||||
|
@ -573,4 +588,10 @@ class StringReader {
|
|||
_position = _lastPostion;
|
||||
_lastPostion = 0;
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
// Returns the entire value starting from position
|
||||
return _buffer.substring(_position);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -67,6 +67,12 @@ enum TagType {
|
|||
break;
|
||||
}
|
||||
|
||||
if (val == "'") {
|
||||
reader.next();
|
||||
isQuoted = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (val == '{') {
|
||||
ret = TagType.Compound; // Detected a CompoundTag
|
||||
reader.next(); // Consume '{'
|
||||
|
@ -251,7 +257,13 @@ abstract class Tag {
|
|||
TagType type = TagType.getStringifiedTagType(string);
|
||||
Tag tag = Tag.makeTagOfType(type);
|
||||
tag._key = name;
|
||||
tag.readStringifiedValue(string);
|
||||
try {
|
||||
tag.readStringifiedValue(string);
|
||||
} catch (E, stack) {
|
||||
print(E);
|
||||
print(string.getSnapshot());
|
||||
print(stack);
|
||||
}
|
||||
|
||||
return tag;
|
||||
}
|
||||
|
@ -286,6 +298,14 @@ abstract class Tag {
|
|||
}
|
||||
}
|
||||
|
||||
bool shouldUseSingleQuotes(String value) {
|
||||
return value.contains("\"");
|
||||
}
|
||||
|
||||
bool shouldEscapeSingleQuotes(String value) {
|
||||
return value.contains("'");
|
||||
}
|
||||
|
||||
void writeStringifiedValue(StringBuilder builder, int indent, bool isList);
|
||||
void readStringifiedValue(StringReader reader);
|
||||
|
||||
|
|
|
@ -66,6 +66,11 @@ class IntArrayTag extends Tag {
|
|||
while (reader.peek() != "]") {
|
||||
value.add(int.parse(reader.readNumber()));
|
||||
|
||||
// The SNBT standard does not require a integer to be suffixed by a 'I'.
|
||||
// This implementation honors that by making it optional.
|
||||
// FIX 1/21/25 @Aria: Int Array was lacking the skipping of the I digit when it might possibly be present
|
||||
if (reader.peek().toLowerCase() == "i") reader.expect("I");
|
||||
|
||||
if (reader.peek() == ",") reader.next();
|
||||
}
|
||||
reader.expect("]");
|
||||
|
|
|
@ -46,10 +46,17 @@ class StringTag extends Tag {
|
|||
|
||||
@override
|
||||
void writeStringifiedValue(StringBuilder builder, int indent, bool isList) {
|
||||
if (shouldQuote(value))
|
||||
builder.append("${isList ? "".padLeft(indent, '\t') : ""}\"${value}\"");
|
||||
else
|
||||
builder.append("${isList ? "".padLeft(indent, '\t') : ""}${value}");
|
||||
final useSingleQuotes = shouldUseSingleQuotes(value);
|
||||
final quote = useSingleQuotes ? '\'' : '"';
|
||||
final escapeQuote = useSingleQuotes ? '\\\'' : '\\"';
|
||||
|
||||
String escapedValue = value;
|
||||
if (shouldEscapeSingleQuotes(value) && useSingleQuotes) {
|
||||
escapedValue = value.replaceAll('\'', escapeQuote);
|
||||
}
|
||||
|
||||
builder.append(
|
||||
"${isList ? "".padLeft(indent, '\t') : ""}${quote}${escapedValue}${quote}");
|
||||
}
|
||||
|
||||
@override
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue