From 88aca930f6ac1cf504f3a4e99964a365ae17b747 Mon Sep 17 00:00:00 2001 From: Thog Date: Fri, 24 Mar 2017 08:26:02 +0100 Subject: Document a "little bit" the Tiny Reader --- .../cuchaz/enigma/mapping/MappingsTinyReader.java | 41 +++++++++++++++++----- 1 file changed, 33 insertions(+), 8 deletions(-) (limited to 'src/main/java') diff --git a/src/main/java/cuchaz/enigma/mapping/MappingsTinyReader.java b/src/main/java/cuchaz/enigma/mapping/MappingsTinyReader.java index b2ba191..5e597b0 100644 --- a/src/main/java/cuchaz/enigma/mapping/MappingsTinyReader.java +++ b/src/main/java/cuchaz/enigma/mapping/MappingsTinyReader.java @@ -29,10 +29,9 @@ public class MappingsTinyReader { public Mappings read(File file) throws IOException, MappingParseException { Mappings mappings = new Mappings(Mappings.FormatType.TINY_FILE); - System.out.println(file); List lines = Files.readAllLines(file.toPath(), Charsets.UTF_8); Map classMappingMap = Maps.newHashMap(); - String header = lines.remove(0); + lines.remove(0); // TODO: use the header for (int lineNumber = 0; lineNumber < lines.size(); lineNumber++) { String line = lines.get(lineNumber); String[] parts = line.split("\\s"); @@ -41,26 +40,34 @@ public class MappingsTinyReader { ClassMapping classMapping; switch (token) { case "CLASS": + + // Check for orphan created by field or method entries. It shouldn't be possible but I prefer to handle this case if (classMappingMap.containsKey(parts[1])) { classMapping = classMappingMap.get(parts[1]); + + // We have the full deob name, Enigma only support simple class name so we extract it. String deobName = parts[2].contains("$") ? parts[2].substring(parts[2].lastIndexOf('$') + 1) : parts[2]; + + // Add full deob name to the class mapping to handle inner class after this loop classMappingMap.put(parts[2], classMapping.setDeobInner(parts[2])); classMapping.setDeobfName(deobName); + + // Avoid to make the mapping dirty directly at the startup classMapping.resetDirty(); } else classMapping = readClass(parts); classMappingMap.put(parts[1], classMapping); break; case "FIELD": + // We can have missing classes mappings because they don't have a ob name, so we create it and use it classMapping = classMappingMap.computeIfAbsent(parts[1], k -> new ClassMapping(parts[1])); - //throw new MappingParseException(file, lineNumber, "Cannot find class '" + parts[1] + "' declaration!"); classMapping.addFieldMapping(readField(parts)); break; case "METHOD": + // We can have missing classes mappings because they don't have a ob name, so we create it and use it classMapping = classMappingMap.computeIfAbsent(parts[1], k -> new ClassMapping(parts[1])); - //throw new MappingParseException(file, lineNumber, "Cannot find class '" + parts[1] + "' declaration!"); classMapping.addMethodMapping(readMethod(parts)); break; default: @@ -72,21 +79,39 @@ public class MappingsTinyReader { } List toRegister = new ArrayList<>(classMappingMap.values()); + + // After having completely parsed the file, we need to register it to the real mapping for (ClassMapping classMapping : toRegister) { ClassEntry obEntry = classMapping.getObfEntry(); ClassEntry deobEntry = classMapping.getDeObfEntry(); try { if (obEntry.isInnerClass()) { ClassMapping parent = classMappingMap.get(obEntry.getOuterClassName()); + // Inner class can miss their parent... So we create it and add it to the mappings if (parent == null) { - parent = new ClassMapping(obEntry.getOuterClassName()); + parent = new ClassMapping(obEntry.getOuterClassName()); // FIXME: WE ACTUALLY DON'T MANAGE INNER CLASS OF INNER CLASS classMappingMap.put(obEntry.getOuterClassName(), parent); mappings.addClassMapping(parent); } + // Add the inner class to the parent + parent.addInnerClassMapping(classMapping); + } + // obf class can become deobf inner classs, manage this case. + else if (deobEntry != null && deobEntry.isInnerClass()) { + String outerClassName = deobEntry.getOuterClassName(); + ClassMapping parent = classMappingMap.get(outerClassName); + + // Only the inner is deob??? Okay + if (parent == null) { + parent = classMappingMap.get(outerClassName); + if (parent == null) { + parent = new ClassMapping(outerClassName); // FIXME: WE ACTUALLY DON'T MANAGE INNER CLASS OF INNER CLASS + classMappingMap.put(outerClassName, parent); + mappings.addClassMapping(parent); + } + } parent.addInnerClassMapping(classMapping); - } else if (deobEntry != null && deobEntry.isInnerClass()) - classMappingMap.get(deobEntry.getOuterClassName()).addInnerClassMapping(classMapping); - else + } else mappings.addClassMapping(classMapping); } catch (MappingConflict e) { throw new MappingParseException(file, -1, e.getMessage()); -- cgit v1.2.3