Skip to content

Commit

Permalink
Add JAM reader and writer (#90)
Browse files Browse the repository at this point in the history
  • Loading branch information
NebelNidas authored Mar 7, 2024
1 parent f7ace94 commit 8f976ac
Show file tree
Hide file tree
Showing 16 changed files with 464 additions and 8 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased]
- Added CSRG writer
- Added TSRG and TSRG2 writer
- Added JAM reader and writer
- Added Recaf Simple reader and writer
- Added `MappingFormat#hasWriter` boolean

Expand Down
11 changes: 10 additions & 1 deletion src/main/java/net/fabricmc/mappingio/MappingReader.java
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
import net.fabricmc.mappingio.format.enigma.EnigmaFileReader;
import net.fabricmc.mappingio.format.proguard.ProGuardFileReader;
import net.fabricmc.mappingio.format.simple.RecafSimpleFileReader;
import net.fabricmc.mappingio.format.srg.JamFileReader;
import net.fabricmc.mappingio.format.srg.SrgFileReader;
import net.fabricmc.mappingio.format.srg.TsrgFileReader;
import net.fabricmc.mappingio.format.tiny.Tiny1FileReader;
Expand Down Expand Up @@ -83,9 +84,14 @@ public static MappingFormat detectFormat(Reader reader) throws IOException {
return MappingFormat.ENIGMA_FILE;
case "PK:":
case "CL:":
case "MD:":
case "FD:":
case "MD:":
return detectSrgOrXsrg(br);
case "CL ":
case "FD ":
case "MD ":
case "MP ":
return MappingFormat.JAM_FILE;
}

String headerStr = String.valueOf(buffer, 0, pos);
Expand Down Expand Up @@ -262,6 +268,9 @@ public static void read(Reader reader, MappingFormat format, MappingVisitor visi
case XSRG_FILE:
SrgFileReader.read(reader, visitor);
break;
case JAM_FILE:
JamFileReader.read(reader, visitor);
break;
case CSRG_FILE:
case TSRG_FILE:
case TSRG_2_FILE:
Expand Down
2 changes: 2 additions & 0 deletions src/main/java/net/fabricmc/mappingio/MappingWriter.java
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
import net.fabricmc.mappingio.format.enigma.EnigmaFileWriter;
import net.fabricmc.mappingio.format.proguard.ProGuardFileWriter;
import net.fabricmc.mappingio.format.simple.RecafSimpleFileWriter;
import net.fabricmc.mappingio.format.srg.JamFileWriter;
import net.fabricmc.mappingio.format.srg.CsrgFileWriter;
import net.fabricmc.mappingio.format.srg.SrgFileWriter;
import net.fabricmc.mappingio.format.srg.TsrgFileWriter;
Expand Down Expand Up @@ -58,6 +59,7 @@ static MappingWriter create(Writer writer, MappingFormat format) throws IOExcept
case ENIGMA_FILE: return new EnigmaFileWriter(writer);
case SRG_FILE: return new SrgFileWriter(writer, false);
case XSRG_FILE: return new SrgFileWriter(writer, true);
case JAM_FILE: return new JamFileWriter(writer);
case CSRG_FILE: return new CsrgFileWriter(writer);
case TSRG_FILE: return new TsrgFileWriter(writer, false);
case TSRG_2_FILE: return new TsrgFileWriter(writer, true);
Expand Down
22 changes: 18 additions & 4 deletions src/main/java/net/fabricmc/mappingio/format/MappingFormat.java
Original file line number Diff line number Diff line change
Expand Up @@ -46,16 +46,16 @@
* <td>✔</td>
* <td>src</td>
* <td>✔</td>
* <td></td>
* <td></td>
* <td>lvIdx & srcName</td>
* <td>lvIdx, lvtIdx, startOpIdx & srcName</td>
* <td>✔</td>
* </tr>
* <tr>
* <td>Enigma</td>
* <td>-</td>
* <td>src</td>
* <td>✔</td>
* <td></td>
* <td>lvIdx</td>
* <td>-</td>
* <td>-</td>
* </tr>
Expand All @@ -78,6 +78,15 @@
* <td>-</td>
* </tr>
* <tr>
* <td>JAM</td>
* <td>-</td>
* <td>src</td>
* <td>-</td>
* <td>argPos</td>
* <td>-</td>
* <td>-</td>
* </tr>
* <tr>
* <td>CSRG/TSRG</td>
* <td>-</td>
* <td>-</td>
Expand All @@ -91,7 +100,7 @@
* <td>✔</td>
* <td>src</td>
* <td>-</td>
* <td></td>
* <td>lvIdx & srcName</td>
* <td>-</td>
* <td>-</td>
* </tr>
Expand Down Expand Up @@ -148,6 +157,11 @@ public enum MappingFormat {
*/
XSRG_FILE("XSRG file", "xsrg", false, true, false, false, false, true),

/**
* The {@code JAM} ("Java Associated Mapping"; formerly {@code SRGX}) mapping format, as specified <a href="https://github.com/caseif/JAM">here</a>.
*/
JAM_FILE("JAM file", "jam", false, true, false, true, false, true),

/**
* The {@code CSRG} ("Compact SRG", since it saves disk space over SRG) mapping format, as specified <a href="https://github.com/MinecraftForge/SrgUtils/blob/67f30647ece29f18256ca89a23cda6216d6bd21e/src/main/java/net/minecraftforge/srgutils/InternalUtils.java#L196-L207">here</a>.
*/
Expand Down
169 changes: 169 additions & 0 deletions src/main/java/net/fabricmc/mappingio/format/srg/JamFileReader.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,169 @@
/*
* Copyright (c) 2023 FabricMC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package net.fabricmc.mappingio.format.srg;

import java.io.IOException;
import java.io.Reader;
import java.util.Collections;
import java.util.Set;

import net.fabricmc.mappingio.MappedElementKind;
import net.fabricmc.mappingio.MappingFlag;
import net.fabricmc.mappingio.MappingUtil;
import net.fabricmc.mappingio.MappingVisitor;
import net.fabricmc.mappingio.format.ColumnFileReader;
import net.fabricmc.mappingio.format.MappingFormat;
import net.fabricmc.mappingio.tree.MappingTree;
import net.fabricmc.mappingio.tree.MemoryMappingTree;

/**
* {@linkplain MappingFormat#JAM_FILE JAM file} reader.
*
* <p>Crashes if a second visit pass is requested without
* {@link MappingFlag#NEEDS_MULTIPLE_PASSES} having been passed beforehand.
*/
public final class JamFileReader {
private JamFileReader() {
}

public static void read(Reader reader, MappingVisitor visitor) throws IOException {
read(reader, MappingUtil.NS_SOURCE_FALLBACK, MappingUtil.NS_TARGET_FALLBACK, visitor);
}

public static void read(Reader reader, String sourceNs, String targetNs, MappingVisitor visitor) throws IOException {
read(new ColumnFileReader(reader, ' '), sourceNs, targetNs, visitor);
}

private static void read(ColumnFileReader reader, String sourceNs, String targetNs, MappingVisitor visitor) throws IOException {
Set<MappingFlag> flags = visitor.getFlags();
MappingVisitor parentVisitor = null;

if (flags.contains(MappingFlag.NEEDS_ELEMENT_UNIQUENESS)) {
parentVisitor = visitor;
visitor = new MemoryMappingTree();
} else if (flags.contains(MappingFlag.NEEDS_MULTIPLE_PASSES)) {
reader.mark();
}

for (;;) {
if (visitor.visitHeader()) {
visitor.visitNamespaces(sourceNs, Collections.singletonList(targetNs));
}

if (visitor.visitContent()) {
String lastClass = null;
boolean visitLastClass = false;

do {
boolean isMethod;
boolean isArg = false;

if (reader.nextCol("CL")) { // class: CL <src> <dst>
String srcName = reader.nextCol();
if (srcName == null || srcName.isEmpty()) throw new IOException("missing class-name-a in line "+reader.getLineNumber());

if (!srcName.equals(lastClass)) {
lastClass = srcName;
visitLastClass = visitor.visitClass(srcName);

if (visitLastClass) {
String dstName = reader.nextCol();
if (dstName == null || dstName.isEmpty()) throw new IOException("missing class-name-b in line "+reader.getLineNumber());

visitor.visitDstName(MappedElementKind.CLASS, 0, dstName);
visitLastClass = visitor.visitElementContent(MappedElementKind.CLASS);
}
}
} else if ((isMethod = reader.nextCol("MD")) || reader.nextCol("FD") // method/field: MD/FD <cls-a> <name-a> <desc-a> <name-b>
|| (isArg = reader.nextCol("MP"))) { // parameter: MP <cls-a> <mth-name-a> <mth-desc-a> <arg-pos> [<arg-desc-a>] <name-b>
String clsSrcClsName = reader.nextCol();
if (clsSrcClsName == null) throw new IOException("missing class-name-a in line "+reader.getLineNumber());

String memberSrcName = reader.nextCol();
if (memberSrcName == null || memberSrcName.isEmpty()) throw new IOException("missing member-name-a in line "+reader.getLineNumber());

String memberSrcDesc = reader.nextCol();
if (memberSrcDesc == null || memberSrcDesc.isEmpty()) throw new IOException("missing member-desc-a in line "+reader.getLineNumber());

String col5 = reader.nextCol();
String col6 = reader.nextCol();
String col7 = reader.nextCol();

int argSrcPos = -1;
String dstName;
String argSrcDesc;

if (!isArg) {
dstName = col5;
} else {
argSrcPos = Integer.parseInt(col5);

if (col7 == null || col7.isEmpty()) {
dstName = col6;
} else {
argSrcDesc = col6;
if (argSrcDesc == null || argSrcDesc.isEmpty()) throw new IOException("missing parameter-desc-a in line "+reader.getLineNumber());

dstName = col7;
}
}

if (dstName == null || dstName.isEmpty()) throw new IOException("missing name-b in line "+reader.getLineNumber());

if (!clsSrcClsName.equals(lastClass)) {
lastClass = clsSrcClsName;
visitLastClass = visitor.visitClass(clsSrcClsName);

if (visitLastClass) {
visitLastClass = visitor.visitElementContent(MappedElementKind.CLASS);
}
}

if (!visitLastClass) continue;
boolean visitMethod = false;

if (isMethod || isArg) {
visitMethod = visitor.visitMethod(memberSrcName, memberSrcDesc);
}

if (visitMethod) {
if (isMethod) {
visitor.visitDstName(MappedElementKind.METHOD, 0, dstName);
visitor.visitElementContent(MappedElementKind.METHOD);
} else {
visitor.visitMethodArg(argSrcPos, -1, null);
visitor.visitDstName(MappedElementKind.METHOD_ARG, 0, dstName);
visitor.visitElementContent(MappedElementKind.METHOD_ARG);
}
} else if (!isMethod && !isArg && visitor.visitField(memberSrcName, memberSrcDesc)) {
visitor.visitDstName(MappedElementKind.FIELD, 0, dstName);
visitor.visitElementContent(MappedElementKind.FIELD);
}
}
} while (reader.nextLine(0));
}

if (visitor.visitEnd()) break;

reader.reset();
}

if (parentVisitor != null) {
((MappingTree) visitor).accept(parentVisitor);
}
}
}
Loading

0 comments on commit 8f976ac

Please sign in to comment.