From 3da92ab80d4dacd38df41ff76bcc345cb0fda1ce Mon Sep 17 00:00:00 2001 From: NebelNidas <48808497+NebelNidas@users.noreply.github.com> Date: Sun, 14 Apr 2024 14:07:37 +0200 Subject: [PATCH 1/4] Fix and update Javadocs (#98) --- .../mappingio/format/MappingFormat.java | 144 ++++-------------- .../format/enigma/EnigmaDirReader.java | 2 +- .../format/enigma/EnigmaDirWriter.java | 2 +- .../format/simple/RecafSimpleFileReader.java | 2 +- .../format/simple/RecafSimpleFileWriter.java | 2 +- .../mappingio/format/srg/JamFileWriter.java | 3 +- .../mappingio/format/srg/SrgFileWriter.java | 5 +- .../format/tiny/Tiny1FileReader.java | 2 +- .../format/tiny/Tiny1FileWriter.java | 2 +- .../format/tiny/Tiny2FileReader.java | 2 +- .../format/tiny/Tiny2FileWriter.java | 2 +- 11 files changed, 45 insertions(+), 123 deletions(-) diff --git a/src/main/java/net/fabricmc/mappingio/format/MappingFormat.java b/src/main/java/net/fabricmc/mappingio/format/MappingFormat.java index 4ecf455a..70c2677b 100644 --- a/src/main/java/net/fabricmc/mappingio/format/MappingFormat.java +++ b/src/main/java/net/fabricmc/mappingio/format/MappingFormat.java @@ -21,122 +21,15 @@ /** * Represents a supported mapping format. Every format can be assumed to have an associated reader available. * - *

Feature comparison table: - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - *
FormatNamespacesField descriptorsCommentsParametersLocal variablesMetadata
Tiny v1src---✔ (Currently limited support)
Tiny v2srclvIdx & srcNamelvIdx, lvtIdx, startOpIdx & srcName
Enigma-srclvIdx--
SRG------
XSRG-src & dst----
JAM-src-argPos--
CSRG/TSRG------
TSRG2src-lvIdx & srcName--
ProGuard-src----
Recaf Simple-src & dst----
JOBF-src----
+ *

A feature comparison table can be found here. */ -// Format order is determined by importance to Fabric tooling, format family and release order therein. +// Format order is determined by importance to Fabric tooling, format family and release order therein (synced with the table linked above). public enum MappingFormat { /** * The {@code Tiny} mapping format, as specified here. + * + *

Implementation notes

+ * File metadata only has limited support as of now, and is hardcoded to intermediary counters. */ TINY_FILE("Tiny file", "tiny", true, true, false, false, false, true), @@ -147,22 +40,34 @@ public enum MappingFormat { /** * Enigma's mapping format, as specified here. + * + *

Implementation notes

+ * Access modifiers are currently not supported. */ ENIGMA_FILE("Enigma file", "mapping", false, true, true, true, false, true), /** * Enigma's mapping format (in directory form), as specified here. + * + *

Implementation notes

+ * Access modifiers are currently not supported. */ ENIGMA_DIR("Enigma directory", null, false, true, true, true, false, true), /** * The {@code SRG} ("Searge RetroGuard") mapping format, as specified here. + * + *

Implementation notes

+ * Package mappings are currently not supported. */ SRG_FILE("SRG file", "srg", false, false, false, false, false, true), /** * The {@code XSRG} ("Extended SRG") mapping format, as specified here. * Same as SRG, but with field descriptors. + * + *

Implementation notes

+ * Package mappings are currently not supported. */ XSRG_FILE("XSRG file", "xsrg", false, true, false, false, false, true), @@ -173,22 +78,34 @@ public enum MappingFormat { /** * The {@code CSRG} ("Compact SRG", since it saves disk space over SRG) mapping format, as specified here. + * + *

Implementation notes

+ * Package mappings are currently not supported. */ CSRG_FILE("CSRG file", "csrg", false, false, false, false, false, true), /** * The {@code TSRG} ("Tiny SRG", since it saves disk space over SRG) mapping format, as specified here. * Same as CSRG, but hierarchical instead of flat. + * + *

Implementation notes

+ * Package mappings are currently not supported. */ TSRG_FILE("TSRG file", "tsrg", false, false, false, false, false, true), /** * The {@code TSRG v2} mapping format, as specified here. + * + *

Implementation notes

+ * Package mappings and static markers for methods are currently not supported. */ TSRG_2_FILE("TSRG2 file", "tsrg", true, true, false, true, false, true), /** * ProGuard's mapping format, as specified here. + * + *

Implementation notes

+ * Line numbers are currently not supported. */ PROGUARD_FILE("ProGuard file", "txt", false, true, false, false, false, true), @@ -199,6 +116,9 @@ public enum MappingFormat { /** * The {@code JOBF} mapping format, as specified here. + * + *

Implementation notes

+ * Package mappings are currently not supported. */ JOBF_FILE("JOBF file", "jobf", false, true, false, false, false, true); diff --git a/src/main/java/net/fabricmc/mappingio/format/enigma/EnigmaDirReader.java b/src/main/java/net/fabricmc/mappingio/format/enigma/EnigmaDirReader.java index 376a50d8..c668cb51 100644 --- a/src/main/java/net/fabricmc/mappingio/format/enigma/EnigmaDirReader.java +++ b/src/main/java/net/fabricmc/mappingio/format/enigma/EnigmaDirReader.java @@ -34,7 +34,7 @@ import net.fabricmc.mappingio.tree.MemoryMappingTree; /** - * {@linkplain MappingFormat#ENIGMA_DIRECTORY Enigma directory} reader. + * {@linkplain MappingFormat#ENIGMA_DIR Enigma directory} reader. * *

Crashes if a second visit pass is requested without * {@link MappingFlag#NEEDS_MULTIPLE_PASSES} having been passed beforehand. diff --git a/src/main/java/net/fabricmc/mappingio/format/enigma/EnigmaDirWriter.java b/src/main/java/net/fabricmc/mappingio/format/enigma/EnigmaDirWriter.java index 4a5aa2a6..48709835 100644 --- a/src/main/java/net/fabricmc/mappingio/format/enigma/EnigmaDirWriter.java +++ b/src/main/java/net/fabricmc/mappingio/format/enigma/EnigmaDirWriter.java @@ -32,7 +32,7 @@ import net.fabricmc.mappingio.format.MappingFormat; /** - * {@linkplain MappingFormat#ENIGMA_DIRECTORY Enigma directory} writer. + * {@linkplain MappingFormat#ENIGMA_DIR Enigma directory} writer. */ public final class EnigmaDirWriter extends EnigmaWriterBase { public EnigmaDirWriter(Path dir, boolean deleteExistingFiles) throws IOException { diff --git a/src/main/java/net/fabricmc/mappingio/format/simple/RecafSimpleFileReader.java b/src/main/java/net/fabricmc/mappingio/format/simple/RecafSimpleFileReader.java index 4bff3ee1..4d4c3c59 100644 --- a/src/main/java/net/fabricmc/mappingio/format/simple/RecafSimpleFileReader.java +++ b/src/main/java/net/fabricmc/mappingio/format/simple/RecafSimpleFileReader.java @@ -31,7 +31,7 @@ import net.fabricmc.mappingio.tree.MemoryMappingTree; /** - * {@linkplain MappingFormat#RECAF_SIMPLE Recaf Simple file} reader. + * {@linkplain MappingFormat#RECAF_SIMPLE_FILE Recaf Simple file} reader. */ public final class RecafSimpleFileReader { private RecafSimpleFileReader() { diff --git a/src/main/java/net/fabricmc/mappingio/format/simple/RecafSimpleFileWriter.java b/src/main/java/net/fabricmc/mappingio/format/simple/RecafSimpleFileWriter.java index 61f28b21..47e16586 100644 --- a/src/main/java/net/fabricmc/mappingio/format/simple/RecafSimpleFileWriter.java +++ b/src/main/java/net/fabricmc/mappingio/format/simple/RecafSimpleFileWriter.java @@ -28,7 +28,7 @@ import net.fabricmc.mappingio.format.MappingFormat; /** - * {@linkplain MappingFormat#RECAF_SIMPLE Recaf Simple file} writer. + * {@linkplain MappingFormat#RECAF_SIMPLE_FILE Recaf Simple file} writer. */ public final class RecafSimpleFileWriter implements MappingWriter { public RecafSimpleFileWriter(Writer writer) { diff --git a/src/main/java/net/fabricmc/mappingio/format/srg/JamFileWriter.java b/src/main/java/net/fabricmc/mappingio/format/srg/JamFileWriter.java index d9c993d9..3fb20cbc 100644 --- a/src/main/java/net/fabricmc/mappingio/format/srg/JamFileWriter.java +++ b/src/main/java/net/fabricmc/mappingio/format/srg/JamFileWriter.java @@ -27,9 +27,10 @@ import net.fabricmc.mappingio.MappedElementKind; import net.fabricmc.mappingio.MappingFlag; import net.fabricmc.mappingio.MappingWriter; +import net.fabricmc.mappingio.format.MappingFormat; /** - * {@linkplain net.fabricmc.mappingio.format.MappingFormat#JAM_FILE JAM file} writer. + * {@linkplain MappingFormat#JAM_FILE JAM file} writer. */ public final class JamFileWriter implements MappingWriter { public JamFileWriter(Writer writer) { diff --git a/src/main/java/net/fabricmc/mappingio/format/srg/SrgFileWriter.java b/src/main/java/net/fabricmc/mappingio/format/srg/SrgFileWriter.java index b74db414..377d3876 100644 --- a/src/main/java/net/fabricmc/mappingio/format/srg/SrgFileWriter.java +++ b/src/main/java/net/fabricmc/mappingio/format/srg/SrgFileWriter.java @@ -27,10 +27,11 @@ import net.fabricmc.mappingio.MappedElementKind; import net.fabricmc.mappingio.MappingFlag; import net.fabricmc.mappingio.MappingWriter; +import net.fabricmc.mappingio.format.MappingFormat; /** - * {@linkplain net.fabricmc.mappingio.format.MappingFormat#SRG_FILE SRG file} and - * {@linkplain net.fabricmc.mappingio.format.MappingFormat#XSRG_FILE XSRG file} writer. + * {@linkplain MappingFormat#SRG_FILE SRG file} and + * {@linkplain MappingFormat#XSRG_FILE XSRG file} writer. */ public final class SrgFileWriter implements MappingWriter { public SrgFileWriter(Writer writer, boolean xsrg) { diff --git a/src/main/java/net/fabricmc/mappingio/format/tiny/Tiny1FileReader.java b/src/main/java/net/fabricmc/mappingio/format/tiny/Tiny1FileReader.java index f74f7f7b..522dce65 100644 --- a/src/main/java/net/fabricmc/mappingio/format/tiny/Tiny1FileReader.java +++ b/src/main/java/net/fabricmc/mappingio/format/tiny/Tiny1FileReader.java @@ -31,7 +31,7 @@ import net.fabricmc.mappingio.tree.MemoryMappingTree; /** - * {@linkplain MappingFormat#TINY_1 Tiny v1 file} reader. + * {@linkplain MappingFormat#TINY_FILE Tiny v1 file} reader. * *

Crashes if a second visit pass is requested without * {@link MappingFlag#NEEDS_MULTIPLE_PASSES} having been passed beforehand. diff --git a/src/main/java/net/fabricmc/mappingio/format/tiny/Tiny1FileWriter.java b/src/main/java/net/fabricmc/mappingio/format/tiny/Tiny1FileWriter.java index f419e3ef..511afaa2 100644 --- a/src/main/java/net/fabricmc/mappingio/format/tiny/Tiny1FileWriter.java +++ b/src/main/java/net/fabricmc/mappingio/format/tiny/Tiny1FileWriter.java @@ -31,7 +31,7 @@ import net.fabricmc.mappingio.format.MappingFormat; /** - * {@linkplain MappingFormat#TINY_1 Tiny v1 file} writer. + * {@linkplain MappingFormat#TINY_FILE Tiny v1 file} writer. */ public final class Tiny1FileWriter implements MappingWriter { public Tiny1FileWriter(Writer writer) { diff --git a/src/main/java/net/fabricmc/mappingio/format/tiny/Tiny2FileReader.java b/src/main/java/net/fabricmc/mappingio/format/tiny/Tiny2FileReader.java index be4b408b..ff3687c2 100644 --- a/src/main/java/net/fabricmc/mappingio/format/tiny/Tiny2FileReader.java +++ b/src/main/java/net/fabricmc/mappingio/format/tiny/Tiny2FileReader.java @@ -28,7 +28,7 @@ import net.fabricmc.mappingio.format.MappingFormat; /** - * {@linkplain MappingFormat#TINY_2 Tiny v2 file} reader. + * {@linkplain MappingFormat#TINY_2_FILE Tiny v2 file} reader. * *

Crashes if a second visit pass is requested without * {@link MappingFlag#NEEDS_MULTIPLE_PASSES} having been passed beforehand. diff --git a/src/main/java/net/fabricmc/mappingio/format/tiny/Tiny2FileWriter.java b/src/main/java/net/fabricmc/mappingio/format/tiny/Tiny2FileWriter.java index f2b5b017..6b049925 100644 --- a/src/main/java/net/fabricmc/mappingio/format/tiny/Tiny2FileWriter.java +++ b/src/main/java/net/fabricmc/mappingio/format/tiny/Tiny2FileWriter.java @@ -31,7 +31,7 @@ import net.fabricmc.mappingio.format.MappingFormat; /** - * {@linkplain MappingFormat#TINY_2 Tiny v2 file} writer. + * {@linkplain MappingFormat#TINY_2_FILE Tiny v2 file} writer. */ public final class Tiny2FileWriter implements MappingWriter { public Tiny2FileWriter(Writer writer, boolean escapeNames) { From a182551c2cabb7266dfdd0cba20ef5598d08e983 Mon Sep 17 00:00:00 2001 From: NebelNidas <48808497+NebelNidas@users.noreply.github.com> Date: Sun, 14 Apr 2024 14:07:57 +0200 Subject: [PATCH 2/4] Fix CSRG and JAM writers skipping elements whose parents have incomplete destination names (#97) * Fix CSRG and JAM writer bugs * Add changes to changelog * Reword changelog entry --- CHANGELOG.md | 1 + .../mappingio/format/srg/CsrgFileWriter.java | 30 +++++++++---------- .../mappingio/format/srg/JamFileWriter.java | 4 ++- .../mappingio/SubsetAssertingVisitor.java | 10 +++---- .../resources/read/valid-with-holes/jam.jam | 2 ++ 5 files changed, 26 insertions(+), 21 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c3b43ede..bc3965c4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ## [Unreleased] +- Fixed CSRG and JAM writers sometimes skipping elements whose parents have incomplete destination names ## [0.6.0] - 2024-4-12 - Added CSRG writer diff --git a/src/main/java/net/fabricmc/mappingio/format/srg/CsrgFileWriter.java b/src/main/java/net/fabricmc/mappingio/format/srg/CsrgFileWriter.java index a434d4cf..7bd17a82 100644 --- a/src/main/java/net/fabricmc/mappingio/format/srg/CsrgFileWriter.java +++ b/src/main/java/net/fabricmc/mappingio/format/srg/CsrgFileWriter.java @@ -93,27 +93,27 @@ public void visitDstName(MappedElementKind targetKind, int namespace, String nam @Override public boolean visitElementContent(MappedElementKind targetKind) throws IOException { - if (dstName == null) return false; + if (dstName != null) { + write(classSrcName); - write(classSrcName); + if (targetKind != MappedElementKind.CLASS) { + writeSpace(); + write(memberSrcName); - if (targetKind != MappedElementKind.CLASS) { - writeSpace(); - write(memberSrcName); + if (targetKind == MappedElementKind.METHOD) { + writeSpace(); + write(methodSrcDesc); + } - if (targetKind == MappedElementKind.METHOD) { - writeSpace(); - write(methodSrcDesc); + memberSrcName = methodSrcDesc = null; } - memberSrcName = methodSrcDesc = null; - } - - writeSpace(); - write(dstName); - writeLn(); + writeSpace(); + write(dstName); + writeLn(); - dstName = null; + dstName = null; + } return targetKind == MappedElementKind.CLASS; // only members are supported, skip anything but class contents } diff --git a/src/main/java/net/fabricmc/mappingio/format/srg/JamFileWriter.java b/src/main/java/net/fabricmc/mappingio/format/srg/JamFileWriter.java index 3fb20cbc..81d6861a 100644 --- a/src/main/java/net/fabricmc/mappingio/format/srg/JamFileWriter.java +++ b/src/main/java/net/fabricmc/mappingio/format/srg/JamFileWriter.java @@ -125,7 +125,9 @@ public boolean visitElementContent(MappedElementKind targetKind) throws IOExcept } else if (targetKind == MappedElementKind.FIELD || (isMethod = targetKind == MappedElementKind.METHOD) || (isArg = targetKind == MappedElementKind.METHOD_ARG)) { - if (classOnlyPass || memberSrcDesc == null || memberDstName == null) { + if (classOnlyPass) { + return false; + } else if (memberSrcDesc == null || (!isArg && memberDstName == null)) { return isMethod; } diff --git a/src/test/java/net/fabricmc/mappingio/SubsetAssertingVisitor.java b/src/test/java/net/fabricmc/mappingio/SubsetAssertingVisitor.java index 907bc033..074760e7 100644 --- a/src/test/java/net/fabricmc/mappingio/SubsetAssertingVisitor.java +++ b/src/test/java/net/fabricmc/mappingio/SubsetAssertingVisitor.java @@ -80,7 +80,7 @@ public boolean visitClass(String srcName, String[] dstNames) throws IOException if (supCls == null) { String[] tmpDst = supHasNamespaces ? dstNames : new String[]{dstNames[0]}; - if (!Arrays.stream(tmpDst).anyMatch(Objects::nonNull)) return false; + if (!Arrays.stream(tmpDst).anyMatch(Objects::nonNull)) return true; throw new RuntimeException("SubTree class not contained in SupTree: " + srcName); } @@ -111,7 +111,7 @@ public boolean visitField(String srcClsName, String srcName, String srcDesc, if (supFld == null) { String[] tmpDst = supHasNamespaces ? dstNames : new String[]{dstNames[0]}; - if (!Arrays.stream(tmpDst).anyMatch(Objects::nonNull)) return false; + if (!Arrays.stream(tmpDst).anyMatch(Objects::nonNull)) return true; throw new RuntimeException("SubTree field not contained in SupTree: " + srcName); } @@ -149,7 +149,7 @@ public boolean visitMethod(String srcClsName, String srcName, String srcDesc, if (supMth == null) { String[] tmpDst = supHasNamespaces ? dstNames : new String[]{dstNames[0]}; - if (!Arrays.stream(tmpDst).anyMatch(Objects::nonNull)) return false; + if (!Arrays.stream(tmpDst).anyMatch(Objects::nonNull)) return true; throw new RuntimeException("SubTree method not contained in SupTree: " + srcName); } @@ -187,7 +187,7 @@ public boolean visitMethodArg(String srcClsName, String srcMethodName, String sr if (supArg == null) { String[] tmpDst = supHasNamespaces ? dstNames : new String[]{dstNames[0]}; - if (!Arrays.stream(tmpDst).anyMatch(Objects::nonNull)) return false; + if (!Arrays.stream(tmpDst).anyMatch(Objects::nonNull)) return true; throw new RuntimeException("SubTree arg not contained in SupTree: " + srcName); } @@ -221,7 +221,7 @@ public boolean visitMethodVar(String srcClsName, String srcMethodName, String sr if (supVar == null) { String[] tmpDst = supHasNamespaces ? dstNames : new String[]{dstNames[0]}; - if (!Arrays.stream(tmpDst).anyMatch(Objects::nonNull)) return false; + if (!Arrays.stream(tmpDst).anyMatch(Objects::nonNull)) return true; throw new RuntimeException("SubTree var not contained in SupTree: " + srcName); } diff --git a/src/test/resources/read/valid-with-holes/jam.jam b/src/test/resources/read/valid-with-holes/jam.jam index bd2f77fd..47c37514 100644 --- a/src/test/resources/read/valid-with-holes/jam.jam +++ b/src/test/resources/read/valid-with-holes/jam.jam @@ -8,3 +8,5 @@ FD class_32 field_2 I field2Ns0Rename FD class_32 field_5 I field5Ns0Rename MD class_32 method_2 ()I method2Ns0Rename MD class_32 method_5 ()I method5Ns0Rename +MP class_32 method_7 ()I 4 param3Ns0Rename +MP class_32 method_7 ()I 8 param5Ns0Rename From dcf8fbd41c6d1da9a5267108b2895bf07ca0dd6f Mon Sep 17 00:00:00 2001 From: modmuss Date: Mon, 15 Apr 2024 18:03:23 +0100 Subject: [PATCH 3/4] Bump version --- CHANGELOG.md | 5 ++++- gradle.properties | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index bc3965c4..8fc05537 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,9 +4,12 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ## [Unreleased] + +## [0.6.1] - 2024-04-15 - Fixed CSRG and JAM writers sometimes skipping elements whose parents have incomplete destination names +- Fixed incorrect Javadoc link -## [0.6.0] - 2024-4-12 +## [0.6.0] - 2024-04-12 - Added CSRG writer - Added TSRG and TSRG2 writer - Added JAM reader and writer diff --git a/gradle.properties b/gradle.properties index 5f19e5ca..6e59dc67 100644 --- a/gradle.properties +++ b/gradle.properties @@ -2,7 +2,7 @@ org.gradle.jvmargs = -Xmx2G # Project properties -version = 0.6.0 +version = 0.6.1 # Dependencies asm_version = 9.6 From 36c52a537a06b812b8855c6d5cf176dd58c14540 Mon Sep 17 00:00:00 2001 From: NebelNidas <48808497+NebelNidas@users.noreply.github.com> Date: Wed, 17 Apr 2024 13:50:36 +0200 Subject: [PATCH 4/4] Overhaul `ColumnFileReader` (#82) * Overhaul `ColumnFileReader` * Return null also when freshly encountering EOL as first char Achieved in part by not always seeking to the start of the next column * Fix issue with start offset * Add changes to changelog --- CHANGELOG.md | 1 + .../mappingio/format/ColumnFileReader.java | 346 +++++++++++------- .../format/enigma/EnigmaFileReader.java | 2 +- .../mappingio/format/jobf/JobfFileReader.java | 2 +- .../format/simple/RecafSimpleFileReader.java | 2 +- .../mappingio/format/srg/JamFileReader.java | 2 +- .../mappingio/format/srg/SrgFileReader.java | 2 +- .../mappingio/format/srg/TsrgFileReader.java | 74 ++-- .../format/tiny/Tiny1FileReader.java | 4 +- .../format/tiny/Tiny2FileReader.java | 8 +- 10 files changed, 268 insertions(+), 175 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8fc05537..02e41f10 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ## [Unreleased] +- Overhauled the internal `ColumnFileReader` to behave more consistently and future-proof ## [0.6.1] - 2024-04-15 - Fixed CSRG and JAM writers sometimes skipping elements whose parents have incomplete destination names diff --git a/src/main/java/net/fabricmc/mappingio/format/ColumnFileReader.java b/src/main/java/net/fabricmc/mappingio/format/ColumnFileReader.java index 8b3b996a..4d26aa0b 100644 --- a/src/main/java/net/fabricmc/mappingio/format/ColumnFileReader.java +++ b/src/main/java/net/fabricmc/mappingio/format/ColumnFileReader.java @@ -31,8 +31,9 @@ */ @ApiStatus.Internal public final class ColumnFileReader implements Closeable { - public ColumnFileReader(Reader reader, char columnSeparator) { + public ColumnFileReader(Reader reader, char indentationChar, char columnSeparator) { this.reader = reader; + this.indentationChar = indentationChar; this.columnSeparator = columnSeparator; } @@ -46,44 +47,17 @@ public void close() throws IOException { * *

The reader will point to the next column or end of line if successful, otherwise remains unchanged. * - * @param expect Content to expect. - * @return {@code true} if the column was read and had the expected content, false otherwise. + * @param expected Content to expect. + * @return {@code true} if the column was read and had the expected content, {@code false} otherwise. */ - public boolean nextCol(String expect) throws IOException { - if (eol) return false; - - int len = expect.length(); - if (!fillBuffer(len)) return false; - - for (int i = 0; i < len; i++) { - if (buffer[bufferPos + i] != expect.charAt(i)) return false; // read failed, not all of expect available - } - - char trailing = 0; - - if (fillBuffer(len + 1) // not eof - && (trailing = buffer[bufferPos + len]) != columnSeparator // not end of column - && trailing != '\n' // not end of line - && trailing != '\r') { - return false; // read failed, column contains data beyond expect - } - - // successful read - - bufferPos += expect.length(); - - // seek to the start of the next column - if (trailing == columnSeparator) { - bufferPos++; - } else { - eol = true; - } - - return true; + public boolean nextCol(String expected) throws IOException { + return read(false, false, true, expected) != noMatch; } /** * Read and consume a column without unescaping. + * + * @return {@code null} if nothing has been read (first char was EOL), otherwise the read string (may be empty). */ @Nullable public String nextCol() throws IOException { @@ -91,36 +65,80 @@ public String nextCol() throws IOException { } /** - * Read and consume a column with unescaping. + * Read and consume a column, and unescape it if requested. + * + * @return {@code null} if nothing has been read (first char was EOL), otherwise the read string (may be empty). */ @Nullable - public String nextEscapedCol() throws IOException { - return nextCol(true); + public String nextCol(boolean unescape) throws IOException { + return read(unescape, true, true, null); } /** - * Read and consume a column and unescape it if requested. + * Read a column without consuming, and unescape if requested. + * Since it doesn't consume, it won't (un)mark BOF, EOL or EOF. + * + * @return {@code null} if nothing has been read (first char was EOL), otherwise the read string (may be empty). */ @Nullable - public String nextCol(boolean unescape) throws IOException { - if (eol) return null; + public String peekCol(boolean unescape) throws IOException { + return read(unescape, false, true, null); + } + + /** + * @param unescape Whether to unescape the read string. + * @param consume Whether to advance the bufferPos. + * @param stopAtNextCol Whether to only read one column. + * @param expected If not {@code null}, the read string must match this exactly, otherwise we early-exit with {@link #noMatch}. Always consumes if matched. + * + * @return {@code null} if nothing has been read (first char was EOL), otherwise the read string (may be empty). + * If {@code expected} is not {@code null}, it will be returned if matched, otherwise {@link #noMatch}. + */ + @Nullable + private String read(boolean unescape, boolean consume, boolean stopAtNextCol, @Nullable String expected) throws IOException { + if (eol) return expected == null ? null : noMatch; + + int expectedLength = expected != null ? expected.length() : -1; + + // Check if the buffer needs to be filled and if we hit EOF while doing so + if (expectedLength > 0 && bufferPos + expectedLength >= bufferLimit) { + if (!fillBuffer(expectedLength, !consume, false)) return noMatch; + } int start; - int end = bufferPos; + int end = this.bufferPos; int firstEscaped = -1; + int contentCharsRead = 0; + int modifiedBufferPos = -1; + int startOffset = 0; + boolean readAnything = false; + boolean filled = true; readLoop: for (;;) { while (end < bufferLimit) { char c = buffer[end]; + boolean isColumnSeparator = (c == columnSeparator); + + // skip leading column separator + if (isColumnSeparator && !readAnything) { + startOffset = 1; + contentCharsRead = -1; + } + + readAnything = true; + + if (expected != null && contentCharsRead > -1) { + if ((contentCharsRead < expectedLength && c != expected.charAt(contentCharsRead)) + || contentCharsRead > expectedLength) { + return noMatch; + } + } - if (c == columnSeparator || c == '\n' || c == '\r') { // end of the current column + if (c == '\n' || c == '\r' || (isColumnSeparator && stopAtNextCol && contentCharsRead > -1)) { // stop reading start = bufferPos; - bufferPos = end; + modifiedBufferPos = end; - // seek to the start of the next column - if (c == columnSeparator) { - bufferPos++; - } else { + if (!isColumnSeparator && (consume || expected != null)) { eol = true; } @@ -129,13 +147,14 @@ public String nextCol(boolean unescape) throws IOException { firstEscaped = bufferPos; } + contentCharsRead++; end++; } // buffer ran out, refill int oldStart = bufferPos; - boolean filled = fillBuffer(end - bufferPos + 1); + filled = fillBuffer(end - bufferPos + 1, !consume, consume); int posShift = bufferPos - oldStart; // fillBuffer may compact the data, shifting it to the buffer start assert posShift <= 0; end += posShift; @@ -143,74 +162,70 @@ public String nextCol(boolean unescape) throws IOException { if (!filled) { start = bufferPos; - bufferPos = end; - eol = true; break; } } - int len = end - start; + start += startOffset; + String ret; - if (len == 0) { - return ""; - } else if (firstEscaped >= 0) { - return Tiny2Util.unescape(String.valueOf(buffer, start, len)); + if (expected != null) { + consume = true; + ret = expected; } else { - return String.valueOf(buffer, start, len); + int len = end - start; + + if (len == 0) { + ret = readAnything ? "" : null; + } else if (firstEscaped >= 0) { + ret = Tiny2Util.unescape(String.valueOf(buffer, start, len)); + } else { + ret = String.valueOf(buffer, start, len); + } } - } - - /** - * Read and consume all column until eol and unescape if requested. - */ - @Nullable - public String nextCols(boolean unescape) throws IOException { - if (eol) return null; - int end = bufferPos; - int firstEscaped = -1; - boolean filled; + if (consume) { + if (readAnything) bof = false; + if (!filled) eof = eol = true; + if (modifiedBufferPos != -1) bufferPos = modifiedBufferPos; - readLoop: do { - while (end < bufferLimit) { - char c = buffer[end]; + if (eol && !eof) { // manually check for EOF + int charsToRead = buffer[bufferPos] == '\r' ? 2 : 1; // 2 for \r\n, 1 for just \n - if (c == '\n' || c == '\r') { // end of the current column - break readLoop; - } else if (unescape && c == '\\' && firstEscaped < 0) { - firstEscaped = bufferPos; + if (end >= bufferLimit - charsToRead) { + fillBuffer(charsToRead, false, true); } - - end++; } + } - // buffer ran out, refill - - int oldStart = bufferPos; - filled = fillBuffer(end - bufferPos + 1); - int posShift = bufferPos - oldStart; // fillBuffer may compact the data, shifting it to the buffer start - assert posShift <= 0; - end += posShift; - if (firstEscaped >= 0) firstEscaped += posShift; - } while (filled); - - int start = bufferPos; - bufferPos = end; - eol = true; + return ret; + } - int len = end - start; + /** + * Read and consume all columns until EOL, and unescape if requested. + * + * @return {@code null} if nothing has been read (first char was EOL), otherwise the read string (may be empty). + */ + @Nullable + public String nextCols(boolean unescape) throws IOException { + return read(unescape, true, false, null); + } - if (len == 0) { - return ""; - } else if (firstEscaped >= 0) { - return Tiny2Util.unescape(String.valueOf(buffer, start, len)); - } else { - return String.valueOf(buffer, start, len); - } + /** + * Read all columns until EOL without consuming, and unescape if requested. + * Since it doesn't consume, it won't (un)mark BOF, EOL or EOF. + * + * @return {@code null} if nothing has been read (first char was EOL), otherwise the read string (may be empty). + */ + @Nullable + public String peekCols(boolean unescape) throws IOException { + return read(unescape, false, false, null); } /** * Read and consume a column and convert it to integer. + * + * @return -1 if nothing has been read (first char was EOL), otherwise the number present. */ public int nextIntCol() throws IOException { String str = nextCol(false); @@ -223,87 +238,167 @@ public int nextIntCol() throws IOException { } public boolean nextLine(int indent) throws IOException { - fillLopo: do { + fillLoop: do { while (bufferPos < bufferLimit) { char c = buffer[bufferPos]; if (c == '\n') { if (indent == 0) { // skip empty lines if indent is 0 - if (!fillBuffer(2)) break fillLopo; + if (!fillBuffer(2, false, true)) break fillLoop; c = buffer[bufferPos + 1]; if (c == '\n' || c == '\r') { // 2+ consecutive new lines, consume first nl and retry bufferPos++; lineNumber++; + bof = false; continue; } } - if (!fillBuffer(indent + 1)) return false; + if (!fillBuffer(indent + 1, false, true)) return false; for (int i = 1; i <= indent; i++) { - if (buffer[bufferPos + i] != '\t') return false; + if (buffer[bufferPos + i] != indentationChar) return false; } bufferPos += indent + 1; lineNumber++; + bof = false; eol = false; return true; } bufferPos++; + bof = false; } - } while (fillBuffer(1)); + } while (fillBuffer(1, false, true)); return false; } public boolean hasExtraIndents() throws IOException { - return fillBuffer(1) && buffer[bufferPos] == '\t'; + return fillBuffer(1, false, false) && buffer[bufferPos] == indentationChar; } public int getLineNumber() { return lineNumber; } + /** + * Whether or not EOL has been encountered in the current line yet. + */ + public boolean isAtEol() { + return eol; + } + + public boolean isAtBof() { + return bof; + } + public boolean isAtEof() { return eof; } - public void mark() { - if (bufferPos > 0) { + /** + * Marks the present position in the stream. Subsequent calls to + * {@link #reset()} will reposition the stream to this point. + * In comparison to {@link java.io.Reader#mark(int)} this method stacks, + * so don't forget to call {@link #discardMark()} if you don't need the mark anymore. + * + * @return the mark index (starting at 1) + */ + public int mark() { + if (markIdx == 0 && bufferPos > 0) { // save memory int available = bufferLimit - bufferPos; System.arraycopy(buffer, bufferPos, buffer, 0, available); bufferPos = 0; bufferLimit = available; - markedLineNumber = lineNumber; - markedEol = eol; - markedEof = eof; } - mark = bufferPos; + if (markIdx == markedBufferPositions.length) { + markedBufferPositions = Arrays.copyOf(markedBufferPositions, markedBufferPositions.length * 2); + markedLineNumbers = Arrays.copyOf(markedLineNumbers, markedLineNumbers.length * 2); + markedBofs = Arrays.copyOf(markedBofs, markedBofs.length * 2); + markedEols = Arrays.copyOf(markedEols, markedEols.length * 2); + markedEofs = Arrays.copyOf(markedEofs, markedEofs.length * 2); + } + + markedBufferPositions[markIdx] = bufferPos; + markedLineNumbers[markIdx] = lineNumber; + markedBofs[markIdx] = bof; + markedEols[markIdx] = eol; + markedEofs[markIdx] = eof; + + return ++markIdx; } - public void reset() { - if (mark < 0) throw new IllegalStateException("not marked"); + /** + * Discard the last mark. + */ + public void discardMark() { + discardMark(markIdx); + } + + /** + * Discard the mark at specified index and all above, if present. + */ + private void discardMark(int index) { + if (markIdx == 0) throw new IllegalStateException("no mark to discard"); + if (index < 1 || index > markIdx) throw new IllegalStateException("index out of bounds"); + + for (int i = markIdx; i >= index; i--) { + markedBufferPositions[i-1] = 0; + markedLineNumbers[i-1] = 0; + } + + markIdx = index - 1; + } + + /** + * Reset to last mark. The marked data isn't discarded, so can be called multiple times. + * If you want to reset to an older mark, use {@link #reset(int)}. + * + * @return The index of the mark that was reset to. + */ + public int reset() { + reset(markIdx); + return markIdx; + } + + /** + * Reset to the mark with the specified index. + * Unless reset to 0, the marked data isn't discarded afterwards, + * so can be called multiple times. + * Use negative indices to reset to a mark relative to the current one. + */ + public void reset(int indexToResetTo) { + if (markIdx == 0) throw new IllegalStateException("no mark to reset to"); + if (indexToResetTo < -markIdx || indexToResetTo > markIdx) throw new IllegalStateException("index out of bounds"); + + if (indexToResetTo < 0) indexToResetTo += markIdx; + int arrayIdx = indexToResetTo == 0 ? indexToResetTo : indexToResetTo - 1; + + bufferPos = markedBufferPositions[arrayIdx]; + lineNumber = markedLineNumbers[arrayIdx]; + bof = markedBofs[arrayIdx]; + eol = markedEols[arrayIdx]; + eof = markedEofs[arrayIdx]; - bufferPos = mark; - lineNumber = markedLineNumber; - eol = markedEol; - eof = markedEof; + if (indexToResetTo == 0) discardMark(1); + markIdx = indexToResetTo; } - private boolean fillBuffer(int count) throws IOException { + private boolean fillBuffer(int count, boolean preventCompaction, boolean markEof) throws IOException { int available = bufferLimit - bufferPos; int req = count - available; if (req <= 0) return true; if (bufferPos + count > buffer.length) { // not enough remaining buffer space - if (mark >= 0) { // marked for rewind -> grow + if (markIdx > 0 || preventCompaction) { // can't compact -> grow buffer = Arrays.copyOf(buffer, Math.max(bufferPos + count, buffer.length * 2)); - } else { // not marked, compact and grow as needed + } else { // compact and grow as needed if (count > buffer.length) { // too small for compacting to suffice -> grow and compact char[] newBuffer = new char[Math.max(count, buffer.length * 2)]; System.arraycopy(buffer, bufferPos, newBuffer, 0, available); @@ -323,7 +418,7 @@ private boolean fillBuffer(int count) throws IOException { int read = reader.read(buffer, bufferLimit, buffer.length - bufferLimit); if (read < 0) { - eof = eol = true; + if (markEof) eof = eol = true; return false; } @@ -333,16 +428,21 @@ private boolean fillBuffer(int count) throws IOException { return true; } + private static final String noMatch = new String(); private final Reader reader; + private final char indentationChar; private final char columnSeparator; private char[] buffer = new char[4096 * 4]; private int bufferPos; private int bufferLimit; - private int mark = -1; private int lineNumber = 1; + private boolean bof = true; private boolean eol; // tracks whether the last column has been read, otherwise ambiguous if the last col is empty private boolean eof; - private int markedLineNumber; - private boolean markedEol; - private boolean markedEof; + private int markIdx = 0; // 0 means no mark + private int[] markedBufferPositions = new int[3]; + private int[] markedLineNumbers = new int[3]; + private boolean[] markedBofs = new boolean[3]; + private boolean[] markedEols = new boolean[3]; + private boolean[] markedEofs = new boolean[3]; } diff --git a/src/main/java/net/fabricmc/mappingio/format/enigma/EnigmaFileReader.java b/src/main/java/net/fabricmc/mappingio/format/enigma/EnigmaFileReader.java index 3590ccde..c44e64a1 100644 --- a/src/main/java/net/fabricmc/mappingio/format/enigma/EnigmaFileReader.java +++ b/src/main/java/net/fabricmc/mappingio/format/enigma/EnigmaFileReader.java @@ -45,7 +45,7 @@ public static void read(Reader reader, MappingVisitor visitor) throws IOExceptio } public static void read(Reader reader, String sourceNs, String targetNs, MappingVisitor visitor) throws IOException { - read(new ColumnFileReader(reader, ' '), sourceNs, targetNs, visitor); + read(new ColumnFileReader(reader, '\t', ' '), sourceNs, targetNs, visitor); } public static void read(ColumnFileReader reader, String sourceNs, String targetNs, MappingVisitor visitor) throws IOException { diff --git a/src/main/java/net/fabricmc/mappingio/format/jobf/JobfFileReader.java b/src/main/java/net/fabricmc/mappingio/format/jobf/JobfFileReader.java index 76b4a842..7700db8b 100644 --- a/src/main/java/net/fabricmc/mappingio/format/jobf/JobfFileReader.java +++ b/src/main/java/net/fabricmc/mappingio/format/jobf/JobfFileReader.java @@ -39,7 +39,7 @@ public static void read(Reader reader, MappingVisitor visitor) throws IOExceptio } public static void read(Reader reader, String sourceNs, String targetNs, MappingVisitor visitor) throws IOException { - read(new ColumnFileReader(reader, ' '), sourceNs, targetNs, visitor); + read(new ColumnFileReader(reader, '\t', ' '), sourceNs, targetNs, visitor); } private static void read(ColumnFileReader reader, String sourceNs, String targetNs, MappingVisitor visitor) throws IOException { diff --git a/src/main/java/net/fabricmc/mappingio/format/simple/RecafSimpleFileReader.java b/src/main/java/net/fabricmc/mappingio/format/simple/RecafSimpleFileReader.java index 4d4c3c59..8b4c9358 100644 --- a/src/main/java/net/fabricmc/mappingio/format/simple/RecafSimpleFileReader.java +++ b/src/main/java/net/fabricmc/mappingio/format/simple/RecafSimpleFileReader.java @@ -42,7 +42,7 @@ public static void read(Reader reader, MappingVisitor visitor) throws IOExceptio } public static void read(Reader reader, String sourceNs, String targetNs, MappingVisitor visitor) throws IOException { - read(new ColumnFileReader(reader, ' '), sourceNs, targetNs, visitor); + read(new ColumnFileReader(reader, '\t', ' '), sourceNs, targetNs, visitor); } private static void read(ColumnFileReader reader, String sourceNs, String targetNs, MappingVisitor visitor) throws IOException { diff --git a/src/main/java/net/fabricmc/mappingio/format/srg/JamFileReader.java b/src/main/java/net/fabricmc/mappingio/format/srg/JamFileReader.java index 2f9b57a4..8ad1eb47 100644 --- a/src/main/java/net/fabricmc/mappingio/format/srg/JamFileReader.java +++ b/src/main/java/net/fabricmc/mappingio/format/srg/JamFileReader.java @@ -45,7 +45,7 @@ public static void read(Reader reader, MappingVisitor visitor) throws IOExceptio } public static void read(Reader reader, String sourceNs, String targetNs, MappingVisitor visitor) throws IOException { - read(new ColumnFileReader(reader, ' '), sourceNs, targetNs, visitor); + read(new ColumnFileReader(reader, '\t', ' '), sourceNs, targetNs, visitor); } private static void read(ColumnFileReader reader, String sourceNs, String targetNs, MappingVisitor visitor) throws IOException { diff --git a/src/main/java/net/fabricmc/mappingio/format/srg/SrgFileReader.java b/src/main/java/net/fabricmc/mappingio/format/srg/SrgFileReader.java index 912fc6a7..77b0360c 100644 --- a/src/main/java/net/fabricmc/mappingio/format/srg/SrgFileReader.java +++ b/src/main/java/net/fabricmc/mappingio/format/srg/SrgFileReader.java @@ -46,7 +46,7 @@ public static void read(Reader reader, MappingVisitor visitor) throws IOExceptio } public static void read(Reader reader, String sourceNs, String targetNs, MappingVisitor visitor) throws IOException { - read(new ColumnFileReader(reader, ' '), sourceNs, targetNs, visitor); + read(new ColumnFileReader(reader, '\t', ' '), sourceNs, targetNs, visitor); } private static void read(ColumnFileReader reader, String sourceNs, String targetNs, MappingVisitor visitor) throws IOException { diff --git a/src/main/java/net/fabricmc/mappingio/format/srg/TsrgFileReader.java b/src/main/java/net/fabricmc/mappingio/format/srg/TsrgFileReader.java index dec67e7a..c50ba709 100644 --- a/src/main/java/net/fabricmc/mappingio/format/srg/TsrgFileReader.java +++ b/src/main/java/net/fabricmc/mappingio/format/srg/TsrgFileReader.java @@ -16,7 +16,6 @@ package net.fabricmc.mappingio.format.srg; -import java.io.CharArrayReader; import java.io.IOException; import java.io.Reader; import java.util.ArrayList; @@ -44,7 +43,7 @@ private TsrgFileReader() { } public static List getNamespaces(Reader reader) throws IOException { - return getNamespaces(new ColumnFileReader(reader, ' ')); + return getNamespaces(new ColumnFileReader(reader, '\t', ' ')); } private static List getNamespaces(ColumnFileReader reader) throws IOException { @@ -66,47 +65,38 @@ public static void read(Reader reader, MappingVisitor visitor) throws IOExceptio read(reader, MappingUtil.NS_SOURCE_FALLBACK, MappingUtil.NS_TARGET_FALLBACK, visitor); } - public static void read(Reader r, String sourceNs, String targetNs, MappingVisitor visitor) throws IOException { - ColumnFileReader reader; - CharArrayReader parentReader = null; + public static void read(Reader reader, String sourceNs, String targetNs, MappingVisitor visitor) throws IOException { + read(new ColumnFileReader(reader, '\t', ' '), sourceNs, targetNs, visitor); + } - if (visitor.getFlags().contains(MappingFlag.NEEDS_MULTIPLE_PASSES)) { - char[] buffer = new char[100_000]; - int pos = 0; - int len; + public static void read(ColumnFileReader reader, String sourceNs, String targetNs, MappingVisitor visitor) throws IOException { + MappingFormat format = reader.nextCol("tsrg2") ? format = MappingFormat.TSRG_2_FILE : MappingFormat.TSRG_FILE; + String srcNamespace; + List dstNamespaces; - while ((len = r.read(buffer, pos, buffer.length - pos)) >= 0) { - pos += len; - if (pos == buffer.length) buffer = Arrays.copyOf(buffer, buffer.length * 2); + if (format == MappingFormat.TSRG_2_FILE) { + srcNamespace = reader.nextCol(); + dstNamespaces = new ArrayList<>(); + String dstNamespace; + + while ((dstNamespace = reader.nextCol()) != null) { + dstNamespaces.add(dstNamespace); } - parentReader = new CharArrayReader(buffer, 0, pos); - reader = new ColumnFileReader(parentReader, ' '); + reader.nextLine(0); } else { - reader = new ColumnFileReader(r, ' '); + srcNamespace = sourceNs; + dstNamespaces = Collections.singletonList(targetNs); } - MappingFormat format = MappingFormat.TSRG_FILE; - String srcNamespace = sourceNs; - List dstNamespaces = Collections.singletonList(targetNs); - - for (;;) { - if (reader.nextCol("tsrg2")) { // tsrg2 magic - format = MappingFormat.TSRG_2_FILE; - srcNamespace = reader.nextCol(); - dstNamespaces = new ArrayList<>(); - String dstNamespace; - - while ((dstNamespace = reader.nextCol()) != null) { - dstNamespaces.add(dstNamespace); - } - - reader.nextLine(0); - } + if (visitor.getFlags().contains(MappingFlag.NEEDS_MULTIPLE_PASSES)) { + reader.mark(); + } - int dstNsCount = dstNamespaces.size(); - List nameTmp = dstNamespaces.size() > 1 ? new ArrayList<>(dstNamespaces.size() - 1) : null; + int dstNsCount = dstNamespaces.size(); + List nameTmp = dstNamespaces.size() > 1 ? new ArrayList<>(dstNamespaces.size() - 1) : null; + for (;;) { if (visitor.visitHeader()) { visitor.visitNamespaces(srcNamespace, dstNamespaces); } @@ -119,8 +109,14 @@ public static void read(Reader r, String sourceNs, String targetNs, MappingVisit if (reader.hasExtraIndents()) continue; reader.mark(); String line = reader.nextCols(false); - if (line == null && reader.isAtEof()) continue; + + if ((line == null || line.isEmpty()) && reader.isAtEof()) { + reader.discardMark(); + continue; + } + reader.reset(); + reader.discardMark(); String[] parts = line.split("((?<= )|(?= ))"); // Split on spaces, but keep them if (format != MappingFormat.TSRG_2_FILE && parts.length >= 4 && !parts[3].startsWith("#")) { // CSRG @@ -182,12 +178,8 @@ public static void read(Reader r, String sourceNs, String targetNs, MappingVisit if (visitor.visitEnd()) break; - if (parentReader == null) { - throw new IllegalStateException("repeated visitation requested without NEEDS_MULTIPLE_PASSES"); - } else { - parentReader.reset(); - reader = new ColumnFileReader(parentReader, ' '); - } + int markIdx = reader.reset(); + assert markIdx == 1; } } diff --git a/src/main/java/net/fabricmc/mappingio/format/tiny/Tiny1FileReader.java b/src/main/java/net/fabricmc/mappingio/format/tiny/Tiny1FileReader.java index 522dce65..69a6330c 100644 --- a/src/main/java/net/fabricmc/mappingio/format/tiny/Tiny1FileReader.java +++ b/src/main/java/net/fabricmc/mappingio/format/tiny/Tiny1FileReader.java @@ -41,7 +41,7 @@ private Tiny1FileReader() { } public static List getNamespaces(Reader reader) throws IOException { - return getNamespaces(new ColumnFileReader(reader, '\t')); + return getNamespaces(new ColumnFileReader(reader, '\t', '\t')); } private static List getNamespaces(ColumnFileReader reader) throws IOException { @@ -60,7 +60,7 @@ private static List getNamespaces(ColumnFileReader reader) throws IOExce } public static void read(Reader reader, MappingVisitor visitor) throws IOException { - read(new ColumnFileReader(reader, '\t'), visitor); + read(new ColumnFileReader(reader, '\t', '\t'), visitor); } private static void read(ColumnFileReader reader, MappingVisitor visitor) throws IOException { diff --git a/src/main/java/net/fabricmc/mappingio/format/tiny/Tiny2FileReader.java b/src/main/java/net/fabricmc/mappingio/format/tiny/Tiny2FileReader.java index ff3687c2..e6405018 100644 --- a/src/main/java/net/fabricmc/mappingio/format/tiny/Tiny2FileReader.java +++ b/src/main/java/net/fabricmc/mappingio/format/tiny/Tiny2FileReader.java @@ -38,7 +38,7 @@ private Tiny2FileReader() { } public static List getNamespaces(Reader reader) throws IOException { - return getNamespaces(new ColumnFileReader(reader, '\t')); + return getNamespaces(new ColumnFileReader(reader, '\t', '\t')); } private static List getNamespaces(ColumnFileReader reader) throws IOException { @@ -59,7 +59,7 @@ private static List getNamespaces(ColumnFileReader reader) throws IOExce } public static void read(Reader reader, MappingVisitor visitor) throws IOException { - read(new ColumnFileReader(reader, '\t'), visitor); + read(new ColumnFileReader(reader, '\t', '\t'), visitor); } private static void read(ColumnFileReader reader, MappingVisitor visitor) throws IOException { @@ -102,7 +102,7 @@ private static void read(ColumnFileReader reader, MappingVisitor visitor) throws } else { String key = reader.nextCol(); if (key == null) throw new IOException("missing property key in line "+reader.getLineNumber()); - String value = reader.nextEscapedCol(); // may be missing -> null + String value = reader.nextCol(true); // may be missing -> null if (key.equals(Tiny2Util.escapedNamesProperty)) { escapeNames = true; @@ -208,7 +208,7 @@ private static void readElement(ColumnFileReader reader, MappedElementKind kind, } private static void readComment(ColumnFileReader reader, MappedElementKind subjectKind, MappingVisitor visitor) throws IOException { - String comment = reader.nextEscapedCol(); + String comment = reader.nextCol(true); if (comment == null) throw new IOException("missing comment in line "+reader.getLineNumber()); visitor.visitComment(subjectKind, comment);