diff --git a/commons-serialize-xml/src/main/java/io/gitlab/jfronny/commons/serialize/xml/NativeXmlReader.java b/commons-serialize-xml/src/main/java/io/gitlab/jfronny/commons/serialize/xml/NativeXmlReader.java index 6b55401..ad48591 100644 --- a/commons-serialize-xml/src/main/java/io/gitlab/jfronny/commons/serialize/xml/NativeXmlReader.java +++ b/commons-serialize-xml/src/main/java/io/gitlab/jfronny/commons/serialize/xml/NativeXmlReader.java @@ -437,6 +437,62 @@ public class NativeXmlReader implements Closeable { } } + public void skipValue() throws IOException { + int count = 0; + do { + int p = peeked; + if (p == PEEKED_NONE) { + p = doPeek(); + } + switch (p) { + case PEEKED_BEGIN_TAG -> { + if (count == 0) { + pathNames[stackSize - 1] = ""; + } + push(XmlScope.TAG_HEAD); + count++; + } + case PEEKED_END_TAG, PEEKED_END_TAG_CONCISE -> { + if (count == 0) { + pathNames[stackSize - 1] = null; + } + stackSize--; + count--; + } + case PEEKED_TEXT -> skipUntil((c, i) -> c == '<'); + case PEEKED_CDATA -> { + skipUntil((c, i) -> c == ']'); + if (pos + 2 < limit || fillBuffer(3)) { + if (buffer[pos] == ']' && buffer[pos + 1] == ']' && buffer[pos + 2] == '>') { + pos += 3; + peeked = PEEKED_NONE; + return; + } + } else { + throw syntaxError("Unterminated CDATA"); + } + } + case PEEKED_ATTRIBUTE_NAME -> { + skipUntil((c, i) -> isName(c, pos + i + 1 < limit ? buffer[pos + i + 1] : '\0') == NameCheck.NONE); + if (count == 0) pathNames[stackSize - 1] = ""; + peeked = PEEKED_NONE; + } + case PEEKED_ATTRIBUTE_VALUE -> { + char quote = buffer[pos++]; + skipUntil((c, i) -> c == quote); + pos++; + peeked = PEEKED_NONE; + } + case PEEKED_EOF -> throw new IllegalStateException("Attempt to skip led outside the document"); + default -> {} + } + peeked = PEEKED_NONE; + } while (count > 0); + + pathIndices[stackSize - 1]++; + if (count < 0) throw new IllegalStateException("Attempt to skip led outside its parent"); + } + private String nextName() throws IOException { return readUntil((c, i) -> isName(c, pos + i + 1 < limit ? buffer[pos + i + 1] : '\0') == NameCheck.NONE, false); } @@ -497,6 +553,38 @@ public class NativeXmlReader implements Closeable { return result; } + private void skipUntil(EndPredicate character) throws IOException { + int i = 0; + findEnd: + while (true) { + for (; pos + i < limit; i++) { + char c = buffer[pos + i]; + if (character.test(c, i)) { + break findEnd; + } else if (c == '\n') { + lineNumber++; + lineStart = pos + i + 1; + } + } + + // Attempt to load the entire name into the buffer at once. + if (i < buffer.length) { + if (fillBuffer(i + 1)) { + continue; + } else { + break; + } + } + + pos += i; + i = 0; + if (!fillBuffer(1)) { + break; + } + } + pos += i; + } + /** * Returns the next character in the stream that is neither whitespace nor a part of a comment. * When this returns, the returned character is always at {@code buffer[pos-1]}; this means the