summaryrefslogtreecommitdiff
path: root/src/cuchaz/enigma/mapping/MappingsReader.java
diff options
context:
space:
mode:
authorGravatar jeff2015-02-08 21:29:25 -0500
committerGravatar jeff2015-02-08 21:29:25 -0500
commited9b5cdfc648e86fd463bfa8d86b94c41671e14c (patch)
tree2619bbc7e04dfa3b82f8dfd3b1d31f529766cd4b /src/cuchaz/enigma/mapping/MappingsReader.java
downloadenigma-fork-ed9b5cdfc648e86fd463bfa8d86b94c41671e14c.tar.gz
enigma-fork-ed9b5cdfc648e86fd463bfa8d86b94c41671e14c.tar.xz
enigma-fork-ed9b5cdfc648e86fd463bfa8d86b94c41671e14c.zip
switch all classes to new signature/type system
Diffstat (limited to 'src/cuchaz/enigma/mapping/MappingsReader.java')
-rw-r--r--src/cuchaz/enigma/mapping/MappingsReader.java175
1 files changed, 175 insertions, 0 deletions
diff --git a/src/cuchaz/enigma/mapping/MappingsReader.java b/src/cuchaz/enigma/mapping/MappingsReader.java
new file mode 100644
index 0000000..adf460e
--- /dev/null
+++ b/src/cuchaz/enigma/mapping/MappingsReader.java
@@ -0,0 +1,175 @@
1/*******************************************************************************
2 * Copyright (c) 2014 Jeff Martin.
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the GNU Public License v3.0
5 * which accompanies this distribution, and is available at
6 * http://www.gnu.org/licenses/gpl.html
7 *
8 * Contributors:
9 * Jeff Martin - initial API and implementation
10 ******************************************************************************/
11package cuchaz.enigma.mapping;
12
13import java.io.BufferedReader;
14import java.io.IOException;
15import java.io.Reader;
16import java.util.Deque;
17
18import com.google.common.collect.Queues;
19
20import cuchaz.enigma.Constants;
21
22public class MappingsReader {
23
24 public Mappings read(Reader in) throws IOException, MappingParseException {
25 return read(new BufferedReader(in));
26 }
27
28 public Mappings read(BufferedReader in) throws IOException, MappingParseException {
29 Mappings mappings = new Mappings();
30 Deque<Object> mappingStack = Queues.newArrayDeque();
31
32 int lineNumber = 0;
33 String line = null;
34 while ( (line = in.readLine()) != null) {
35 lineNumber++;
36
37 // strip comments
38 int commentPos = line.indexOf('#');
39 if (commentPos >= 0) {
40 line = line.substring(0, commentPos);
41 }
42
43 // skip blank lines
44 if (line.trim().length() <= 0) {
45 continue;
46 }
47
48 // get the indent of this line
49 int indent = 0;
50 for (int i = 0; i < line.length(); i++) {
51 if (line.charAt(i) != '\t') {
52 break;
53 }
54 indent++;
55 }
56
57 // handle stack pops
58 while (indent < mappingStack.size()) {
59 mappingStack.pop();
60 }
61
62 String[] parts = line.trim().split("\\s");
63 try {
64 // read the first token
65 String token = parts[0];
66
67 if (token.equalsIgnoreCase("CLASS")) {
68 ClassMapping classMapping;
69 if (indent == 0) {
70 // outer class
71 classMapping = readClass(parts, false);
72 mappings.addClassMapping(classMapping);
73 } else if (indent == 1) {
74 // inner class
75 if (! (mappingStack.getFirst() instanceof ClassMapping)) {
76 throw new MappingParseException(lineNumber, "Unexpected CLASS entry here!");
77 }
78
79 classMapping = readClass(parts, true);
80 ((ClassMapping)mappingStack.getFirst()).addInnerClassMapping(classMapping);
81 } else {
82 throw new MappingParseException(lineNumber, "Unexpected CLASS entry nesting!");
83 }
84 mappingStack.push(classMapping);
85 } else if (token.equalsIgnoreCase("FIELD")) {
86 if (mappingStack.isEmpty() || ! (mappingStack.getFirst() instanceof ClassMapping)) {
87 throw new MappingParseException(lineNumber, "Unexpected FIELD entry here!");
88 }
89 ((ClassMapping)mappingStack.getFirst()).addFieldMapping(readField(parts));
90 } else if (token.equalsIgnoreCase("METHOD")) {
91 if (mappingStack.isEmpty() || ! (mappingStack.getFirst() instanceof ClassMapping)) {
92 throw new MappingParseException(lineNumber, "Unexpected METHOD entry here!");
93 }
94 MethodMapping methodMapping = readMethod(parts);
95 ((ClassMapping)mappingStack.getFirst()).addMethodMapping(methodMapping);
96 mappingStack.push(methodMapping);
97 } else if (token.equalsIgnoreCase("ARG")) {
98 if (mappingStack.isEmpty() || ! (mappingStack.getFirst() instanceof MethodMapping)) {
99 throw new MappingParseException(lineNumber, "Unexpected ARG entry here!");
100 }
101 ((MethodMapping)mappingStack.getFirst()).addArgumentMapping(readArgument(parts));
102 }
103 } catch (ArrayIndexOutOfBoundsException | NumberFormatException ex) {
104 throw new MappingParseException(lineNumber, "Malformed line!");
105 }
106 }
107
108 return mappings;
109 }
110
111 private ArgumentMapping readArgument(String[] parts) {
112 return new ArgumentMapping(Integer.parseInt(parts[1]), parts[2]);
113 }
114
115 private ClassMapping readClass(String[] parts, boolean makeSimple) {
116 if (parts.length == 2) {
117 String obfName = processName(parts[1], makeSimple);
118 return new ClassMapping(obfName);
119 } else {
120 String obfName = processName(parts[1], makeSimple);
121 String deobfName = processName(parts[2], makeSimple);
122 return new ClassMapping(obfName, deobfName);
123 }
124 }
125
126 private String processName(String name, boolean makeSimple) {
127 if (makeSimple) {
128 return new ClassEntry(name).getSimpleName();
129 } else {
130 return moveClassOutOfDefaultPackage(name, Constants.NonePackage);
131 }
132 }
133
134 private String moveClassOutOfDefaultPackage(String className, String newPackageName) {
135 ClassEntry classEntry = new ClassEntry(className);
136 if (classEntry.isInDefaultPackage()) {
137 return newPackageName + "/" + classEntry.getName();
138 }
139 return className;
140 }
141
142 private FieldMapping readField(String[] parts) {
143 return new FieldMapping(parts[1], parts[2]);
144 }
145
146 private MethodMapping readMethod(String[] parts) {
147 if (parts.length == 3) {
148 String obfName = parts[1];
149 Signature obfSignature = moveSignatureOutOfDefaultPackage(new Signature(parts[2]), Constants.NonePackage);
150 return new MethodMapping(obfName, obfSignature);
151 } else {
152 String obfName = parts[1];
153 String deobfName = parts[2];
154 Signature obfSignature = moveSignatureOutOfDefaultPackage(new Signature(parts[3]), Constants.NonePackage);
155 if (obfName.equals(deobfName)) {
156 return new MethodMapping(obfName, obfSignature);
157 } else {
158 return new MethodMapping(obfName, obfSignature, deobfName);
159 }
160 }
161 }
162
163 private Signature moveSignatureOutOfDefaultPackage(Signature signature, final String newPackageName) {
164 return new Signature(signature, new ClassNameReplacer() {
165 @Override
166 public String replace(String className) {
167 ClassEntry classEntry = new ClassEntry(className);
168 if (classEntry.isInDefaultPackage()) {
169 return newPackageName + "/" + className;
170 }
171 return null;
172 }
173 });
174 }
175}