/*
* Nocturne
* Copyright (c) 2015-2016, Lapis <https://github.com/LapisBlue>
*
* The MIT License
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package blue.lapis.nocturne.mapping.io.reader;
import static blue.lapis.nocturne.util.Constants.CLASS_PATH_SEPARATOR_CHAR;
import blue.lapis.nocturne.Main;
import blue.lapis.nocturne.jar.model.attribute.MethodDescriptor;
import blue.lapis.nocturne.mapping.MappingContext;
import blue.lapis.nocturne.processor.index.model.signature.FieldSignature;
import blue.lapis.nocturne.processor.index.model.signature.MethodSignature;
import blue.lapis.nocturne.util.helper.MappingsHelper;
import java.io.BufferedReader;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
/**
* The mappings reader, for the SRG format.
*/
public class SrgReader extends MappingsReader {
private static final String CLASS_MAPPING_KEY = "CL:";
private static final String FIELD_MAPPING_KEY = "FD:";
private static final String METHOD_MAPPING_KEY = "MD:";
private static final int CLASS_MAPPING_ELEMENT_COUNT = 3;
private static final int FIELD_MAPPING_ELEMENT_COUNT = 3;
private static final int METHOD_MAPPING_ELEMENT_COUNT = 5;
public SrgReader(BufferedReader reader) {
super(reader);
}
@Override
public MappingContext read() {
MappingContext mappings = new MappingContext();
Pattern spacePattern = Pattern.compile(" ", Pattern.LITERAL);
List<String> rawClassMappings = new ArrayList<>();
List<String> rawFieldMappings = new ArrayList<>();
List<String> rawMethodMappings = new ArrayList<>();
for (String line : reader.lines().collect(Collectors.toList())) {
String trim = line.trim();
if (trim.charAt(0) == '#' || trim.isEmpty()) {
continue;
}
if (line.length() < 4) {
Main.getLogger().warning("Found bogus line in mappings file - ignoring");
continue;
}
int len = spacePattern.split(line).length;
String key = line.substring(0, 3);
if (key.equals(CLASS_MAPPING_KEY) && len == CLASS_MAPPING_ELEMENT_COUNT) {
rawClassMappings.add(line);
} else if (key.equals(FIELD_MAPPING_KEY) && len == FIELD_MAPPING_ELEMENT_COUNT) {
rawFieldMappings.add(line);
} else if (key.equals(METHOD_MAPPING_KEY) && len == METHOD_MAPPING_ELEMENT_COUNT) {
rawMethodMappings.add(line);
} else {
Main.getLogger().warning("Discovered unrecognized key \"" + key + "\" in mappings file - ignoring");
}
}
// we need to sort the class mappings in order of ascending nesting level
rawClassMappings.sort((s1, s2) -> getClassNestingLevel(s1) - getClassNestingLevel(s2));
genClassMappings(mappings, rawClassMappings);
genFieldMappings(mappings, rawFieldMappings);
genMethodMappings(mappings, rawMethodMappings);
return mappings;
}
private void genClassMappings(MappingContext context, List<String> classMappings) {
for (String mapping : classMappings) {
String[] arr = mapping.split(" ");
String obf = arr[1];
String deobf = arr[2];
MappingsHelper.genClassMapping(context, obf, deobf, false);
}
}
private void genFieldMappings(MappingContext context, List<String> fieldMappings) {
for (String mapping : fieldMappings) {
String[] arr = mapping.split(" ");
int lastIndex = arr[1].lastIndexOf(CLASS_PATH_SEPARATOR_CHAR);
String owningClass = arr[1].substring(0, lastIndex);
String obf = arr[1].substring(lastIndex + 1);
String deobf = arr[2].substring(arr[2].lastIndexOf(CLASS_PATH_SEPARATOR_CHAR) + 1);
// SRG doesn't support field types so we just pass a null type arg and let the helper method figure it out
MappingsHelper.genFieldMapping(context, owningClass, new FieldSignature(obf, null), deobf);
}
}
private void genMethodMappings(MappingContext context, List<String> methodMappings) {
for (String mapping : methodMappings) {
String[] arr = mapping.split(" ");
int lastIndex = arr[1].lastIndexOf(CLASS_PATH_SEPARATOR_CHAR);
String owningClass = arr[1].substring(0, lastIndex);
String obf = arr[1].substring(lastIndex + 1);
String descriptor = arr[2];
String deobf = arr[3].substring(arr[3].lastIndexOf(CLASS_PATH_SEPARATOR_CHAR) + 1);
MappingsHelper.genMethodMapping(context, owningClass,
new MethodSignature(obf, MethodDescriptor.fromString(descriptor)), deobf, false);
}
}
}