diff options
Diffstat (limited to 'src/main/java/cuchaz/enigma/mapping/MappingsEnigmaReader.java')
| -rw-r--r-- | src/main/java/cuchaz/enigma/mapping/MappingsEnigmaReader.java | 167 |
1 files changed, 88 insertions, 79 deletions
diff --git a/src/main/java/cuchaz/enigma/mapping/MappingsEnigmaReader.java b/src/main/java/cuchaz/enigma/mapping/MappingsEnigmaReader.java index a0d4313..ddbee76 100644 --- a/src/main/java/cuchaz/enigma/mapping/MappingsEnigmaReader.java +++ b/src/main/java/cuchaz/enigma/mapping/MappingsEnigmaReader.java | |||
| @@ -5,8 +5,14 @@ import com.google.common.collect.Queues; | |||
| 5 | import cuchaz.enigma.throwables.MappingConflict; | 5 | import cuchaz.enigma.throwables.MappingConflict; |
| 6 | import cuchaz.enigma.throwables.MappingParseException; | 6 | import cuchaz.enigma.throwables.MappingParseException; |
| 7 | 7 | ||
| 8 | import java.io.*; | 8 | import java.io.BufferedReader; |
| 9 | import java.io.File; | ||
| 10 | import java.io.FileInputStream; | ||
| 11 | import java.io.IOException; | ||
| 12 | import java.io.InputStream; | ||
| 13 | import java.io.InputStreamReader; | ||
| 9 | import java.util.Deque; | 14 | import java.util.Deque; |
| 15 | import java.util.function.Supplier; | ||
| 10 | 16 | ||
| 11 | public class MappingsEnigmaReader { | 17 | public class MappingsEnigmaReader { |
| 12 | 18 | ||
| @@ -39,92 +45,95 @@ public class MappingsEnigmaReader { | |||
| 39 | } | 45 | } |
| 40 | 46 | ||
| 41 | public Mappings readFile(Mappings mappings, File file) throws IOException, MappingParseException { | 47 | public Mappings readFile(Mappings mappings, File file) throws IOException, MappingParseException { |
| 48 | return readFileStream(mappings, new FileInputStream(file), file::getAbsolutePath); | ||
| 49 | } | ||
| 42 | 50 | ||
| 43 | BufferedReader in = new BufferedReader(new InputStreamReader(new FileInputStream(file), Charsets.UTF_8)); | 51 | public Mappings readFileStream(Mappings mappings, InputStream stream, Supplier<String> filenameSupplier) throws IOException, MappingParseException { |
| 44 | Deque<Object> mappingStack = Queues.newArrayDeque(); | 52 | try (BufferedReader in = new BufferedReader(new InputStreamReader(stream, Charsets.UTF_8))) { |
| 53 | Deque<Object> mappingStack = Queues.newArrayDeque(); | ||
| 45 | 54 | ||
| 46 | int lineNumber = 0; | 55 | int lineNumber = 0; |
| 47 | String line; | 56 | String line; |
| 48 | while ((line = in.readLine()) != null) { | 57 | while ((line = in.readLine()) != null) { |
| 49 | lineNumber++; | 58 | lineNumber++; |
| 50 | 59 | ||
| 51 | // strip comments | 60 | // strip comments |
| 52 | int commentPos = line.indexOf('#'); | 61 | int commentPos = line.indexOf('#'); |
| 53 | if (commentPos >= 0) { | 62 | if (commentPos >= 0) { |
| 54 | line = line.substring(0, commentPos); | 63 | line = line.substring(0, commentPos); |
| 55 | } | 64 | } |
| 56 | 65 | ||
| 57 | // skip blank lines | 66 | // skip blank lines |
| 58 | if (line.trim().length() <= 0) { | 67 | if (line.trim().length() <= 0) { |
| 59 | continue; | 68 | continue; |
| 60 | } | 69 | } |
| 61 | 70 | ||
| 62 | // get the indent of this line | 71 | // get the indent of this line |
| 63 | int indent = 0; | 72 | int indent = 0; |
| 64 | for (int i = 0; i < line.length(); i++) { | 73 | for (int i = 0; i < line.length(); i++) { |
| 65 | if (line.charAt(i) != '\t') { | 74 | if (line.charAt(i) != '\t') { |
| 66 | break; | 75 | break; |
| 76 | } | ||
| 77 | indent++; | ||
| 67 | } | 78 | } |
| 68 | indent++; | ||
| 69 | } | ||
| 70 | 79 | ||
| 71 | // handle stack pops | 80 | // handle stack pops |
| 72 | while (indent < mappingStack.size()) { | 81 | while (indent < mappingStack.size()) { |
| 73 | mappingStack.pop(); | 82 | mappingStack.pop(); |
| 74 | } | 83 | } |
| 75 | 84 | ||
| 76 | String[] parts = line.trim().split("\\s"); | 85 | String[] parts = line.trim().split("\\s"); |
| 77 | try { | 86 | try { |
| 78 | // read the first token | 87 | // read the first token |
| 79 | String token = parts[0]; | 88 | String token = parts[0]; |
| 80 | 89 | ||
| 81 | if (token.equalsIgnoreCase("CLASS")) { | 90 | if (token.equalsIgnoreCase("CLASS")) { |
| 82 | ClassMapping classMapping; | 91 | ClassMapping classMapping; |
| 83 | if (indent <= 0) { | 92 | if (indent <= 0) { |
| 84 | // outer class | 93 | // outer class |
| 85 | classMapping = readClass(parts, false); | 94 | classMapping = readClass(parts, false); |
| 86 | mappings.addClassMapping(classMapping); | 95 | mappings.addClassMapping(classMapping); |
| 87 | } else { | 96 | } else { |
| 88 | 97 | ||
| 89 | // inner class | 98 | // inner class |
| 90 | if (!(mappingStack.peek() instanceof ClassMapping)) { | 99 | if (!(mappingStack.peek() instanceof ClassMapping)) { |
| 91 | throw new MappingParseException(file, lineNumber, "Unexpected CLASS entry here!"); | 100 | throw new MappingParseException(filenameSupplier, lineNumber, "Unexpected CLASS entry here!"); |
| 101 | } | ||
| 102 | |||
| 103 | classMapping = readClass(parts, true); | ||
| 104 | ((ClassMapping) mappingStack.peek()).addInnerClassMapping(classMapping); | ||
| 92 | } | 105 | } |
| 93 | 106 | mappingStack.push(classMapping); | |
| 94 | classMapping = readClass(parts, true); | 107 | } else if (token.equalsIgnoreCase("FIELD")) { |
| 95 | ((ClassMapping) mappingStack.peek()).addInnerClassMapping(classMapping); | 108 | if (mappingStack.isEmpty() || !(mappingStack.peek() instanceof ClassMapping)) { |
| 96 | } | 109 | throw new MappingParseException(filenameSupplier, lineNumber, "Unexpected FIELD entry here!"); |
| 97 | mappingStack.push(classMapping); | 110 | } |
| 98 | } else if (token.equalsIgnoreCase("FIELD")) { | 111 | ((ClassMapping) mappingStack.peek()).addFieldMapping(readField(parts)); |
| 99 | if (mappingStack.isEmpty() || !(mappingStack.peek() instanceof ClassMapping)) { | 112 | } else if (token.equalsIgnoreCase("METHOD")) { |
| 100 | throw new MappingParseException(file, lineNumber, "Unexpected FIELD entry here!"); | 113 | if (mappingStack.isEmpty() || !(mappingStack.peek() instanceof ClassMapping)) { |
| 101 | } | 114 | throw new MappingParseException(filenameSupplier, lineNumber, "Unexpected METHOD entry here!"); |
| 102 | ((ClassMapping) mappingStack.peek()).addFieldMapping(readField(parts)); | 115 | } |
| 103 | } else if (token.equalsIgnoreCase("METHOD")) { | 116 | MethodMapping methodMapping = readMethod(parts); |
| 104 | if (mappingStack.isEmpty() || !(mappingStack.peek() instanceof ClassMapping)) { | 117 | ((ClassMapping) mappingStack.peek()).addMethodMapping(methodMapping); |
| 105 | throw new MappingParseException(file, lineNumber, "Unexpected METHOD entry here!"); | 118 | mappingStack.push(methodMapping); |
| 106 | } | 119 | } else if (token.equalsIgnoreCase("ARG")) { |
| 107 | MethodMapping methodMapping = readMethod(parts); | 120 | if (mappingStack.isEmpty() || !(mappingStack.peek() instanceof MethodMapping)) { |
| 108 | ((ClassMapping) mappingStack.peek()).addMethodMapping(methodMapping); | 121 | throw new MappingParseException(filenameSupplier, lineNumber, "Unexpected ARG entry here!"); |
| 109 | mappingStack.push(methodMapping); | 122 | } |
| 110 | } else if (token.equalsIgnoreCase("ARG")) { | 123 | ((MethodMapping) mappingStack.peek()).addArgumentMapping(readArgument(parts)); |
| 111 | if (mappingStack.isEmpty() || !(mappingStack.peek() instanceof MethodMapping)) { | ||
| 112 | throw new MappingParseException(file, lineNumber, "Unexpected ARG entry here!"); | ||
| 113 | } | 124 | } |
| 114 | ((MethodMapping) mappingStack.peek()).addArgumentMapping(readArgument(parts)); | 125 | } catch (ArrayIndexOutOfBoundsException | IllegalArgumentException ex) { |
| 126 | throw new MappingParseException(filenameSupplier, lineNumber, "Malformed line:\n" + line); | ||
| 127 | } catch (MappingConflict e) { | ||
| 128 | throw new MappingParseException(filenameSupplier, lineNumber, e.getMessage()); | ||
| 115 | } | 129 | } |
| 116 | } catch (ArrayIndexOutOfBoundsException | IllegalArgumentException ex) { | ||
| 117 | throw new MappingParseException(file, lineNumber, "Malformed line:\n" + line); | ||
| 118 | } catch (MappingConflict e) { | ||
| 119 | throw new MappingParseException(file, lineNumber, e.getMessage()); | ||
| 120 | } | 130 | } |
| 131 | return mappings; | ||
| 121 | } | 132 | } |
| 122 | in.close(); | ||
| 123 | return mappings; | ||
| 124 | } | 133 | } |
| 125 | 134 | ||
| 126 | private ArgumentMapping readArgument(String[] parts) { | 135 | private LocalVariableMapping readArgument(String[] parts) { |
| 127 | return new ArgumentMapping(Integer.parseInt(parts[1]), parts[2]); | 136 | return new LocalVariableMapping(Integer.parseInt(parts[1]), parts[2]); |
| 128 | } | 137 | } |
| 129 | 138 | ||
| 130 | private ClassMapping readClass(String[] parts, boolean makeSimple) { | 139 | private ClassMapping readClass(String[] parts, boolean makeSimple) { |
| @@ -150,27 +159,27 @@ public class MappingsEnigmaReader { | |||
| 150 | if (parts.length == 4) { | 159 | if (parts.length == 4) { |
| 151 | boolean access = parts[3].startsWith("ACC:"); | 160 | boolean access = parts[3].startsWith("ACC:"); |
| 152 | if (access) | 161 | if (access) |
| 153 | mapping = new FieldMapping(parts[1], new Type(parts[2]), null, | 162 | mapping = new FieldMapping(parts[1], new TypeDescriptor(parts[2]), null, |
| 154 | Mappings.EntryModifier.valueOf(parts[3].substring(4))); | 163 | Mappings.EntryModifier.valueOf(parts[3].substring(4))); |
| 155 | else | 164 | else |
| 156 | mapping = new FieldMapping(parts[1], new Type(parts[3]), parts[2], Mappings.EntryModifier.UNCHANGED); | 165 | mapping = new FieldMapping(parts[1], new TypeDescriptor(parts[3]), parts[2], Mappings.EntryModifier.UNCHANGED); |
| 157 | } else if (parts.length == 5) | 166 | } else if (parts.length == 5) |
| 158 | mapping = new FieldMapping(parts[1], new Type(parts[3]), parts[2], Mappings.EntryModifier.valueOf(parts[4].substring(4))); | 167 | mapping = new FieldMapping(parts[1], new TypeDescriptor(parts[3]), parts[2], Mappings.EntryModifier.valueOf(parts[4].substring(4))); |
| 159 | return mapping; | 168 | return mapping; |
| 160 | } | 169 | } |
| 161 | 170 | ||
| 162 | private MethodMapping readMethod(String[] parts) { | 171 | private MethodMapping readMethod(String[] parts) { |
| 163 | MethodMapping mapping = null; | 172 | MethodMapping mapping = null; |
| 164 | if (parts.length == 3) | 173 | if (parts.length == 3) |
| 165 | mapping = new MethodMapping(parts[1], new Signature(parts[2])); | 174 | mapping = new MethodMapping(parts[1], new MethodDescriptor(parts[2])); |
| 166 | else if (parts.length == 4) { | 175 | else if (parts.length == 4) { |
| 167 | boolean access = parts[3].startsWith("ACC:"); | 176 | boolean access = parts[3].startsWith("ACC:"); |
| 168 | if (access) | 177 | if (access) |
| 169 | mapping = new MethodMapping(parts[1], new Signature(parts[2]), null, Mappings.EntryModifier.valueOf(parts[3].substring(4))); | 178 | mapping = new MethodMapping(parts[1], new MethodDescriptor(parts[2]), null, Mappings.EntryModifier.valueOf(parts[3].substring(4))); |
| 170 | else | 179 | else |
| 171 | mapping = new MethodMapping(parts[1], new Signature(parts[3]), parts[2]); | 180 | mapping = new MethodMapping(parts[1], new MethodDescriptor(parts[3]), parts[2]); |
| 172 | } else if (parts.length == 5) | 181 | } else if (parts.length == 5) |
| 173 | mapping = new MethodMapping(parts[1], new Signature(parts[3]), parts[2], | 182 | mapping = new MethodMapping(parts[1], new MethodDescriptor(parts[3]), parts[2], |
| 174 | Mappings.EntryModifier.valueOf(parts[4].substring(4))); | 183 | Mappings.EntryModifier.valueOf(parts[4].substring(4))); |
| 175 | return mapping; | 184 | return mapping; |
| 176 | } | 185 | } |