summaryrefslogtreecommitdiff
path: root/src/cuchaz/enigma/mapping/MappingsReader.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/cuchaz/enigma/mapping/MappingsReader.java')
-rw-r--r--src/cuchaz/enigma/mapping/MappingsReader.java134
1 files changed, 134 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..0a4b117
--- /dev/null
+++ b/src/cuchaz/enigma/mapping/MappingsReader.java
@@ -0,0 +1,134 @@
1/*******************************************************************************
2 * Copyright (c) 2015 Jeff Martin.
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the GNU Lesser General Public
5 * License v3.0 which accompanies this distribution, and is available at
6 * http://www.gnu.org/licenses/lgpl.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
20public class MappingsReader {
21
22 public Mappings read(Reader in)
23 throws IOException, MappingParseException {
24 return read(new BufferedReader(in));
25 }
26
27 public Mappings read(BufferedReader in)
28 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 {
74
75 // inner class
76 if (!(mappingStack.peek() instanceof ClassMapping)) {
77 throw new MappingParseException(lineNumber, "Unexpected CLASS entry here!");
78 }
79
80 classMapping = readClass(parts, true);
81 ((ClassMapping)mappingStack.peek()).addInnerClassMapping(classMapping);
82 }
83 mappingStack.push(classMapping);
84 } else if (token.equalsIgnoreCase("FIELD")) {
85 if (mappingStack.isEmpty() || ! (mappingStack.peek() instanceof ClassMapping)) {
86 throw new MappingParseException(lineNumber, "Unexpected FIELD entry here!");
87 }
88 ((ClassMapping)mappingStack.peek()).addFieldMapping(readField(parts));
89 } else if (token.equalsIgnoreCase("METHOD")) {
90 if (mappingStack.isEmpty() || ! (mappingStack.peek() instanceof ClassMapping)) {
91 throw new MappingParseException(lineNumber, "Unexpected METHOD entry here!");
92 }
93 MethodMapping methodMapping = readMethod(parts);
94 ((ClassMapping)mappingStack.peek()).addMethodMapping(methodMapping);
95 mappingStack.push(methodMapping);
96 } else if (token.equalsIgnoreCase("ARG")) {
97 if (mappingStack.isEmpty() || ! (mappingStack.peek() instanceof MethodMapping)) {
98 throw new MappingParseException(lineNumber, "Unexpected ARG entry here!");
99 }
100 ((MethodMapping)mappingStack.peek()).addArgumentMapping(readArgument(parts));
101 }
102 } catch (ArrayIndexOutOfBoundsException | IllegalArgumentException ex) {
103 throw new MappingParseException(lineNumber, "Malformed line:\n" + line);
104 }
105 }
106
107 return mappings;
108 }
109
110 private ArgumentMapping readArgument(String[] parts) {
111 return new ArgumentMapping(Integer.parseInt(parts[1]), parts[2]);
112 }
113
114 private ClassMapping readClass(String[] parts, boolean makeSimple) {
115 if (parts.length == 2) {
116 return new ClassMapping(parts[1]);
117 } else {
118 return new ClassMapping(parts[1], parts[2]);
119 }
120 }
121
122 /* TEMP */
123 protected FieldMapping readField(String[] parts) {
124 return new FieldMapping(parts[1], new Type(parts[3]), parts[2]);
125 }
126
127 private MethodMapping readMethod(String[] parts) {
128 if (parts.length == 3) {
129 return new MethodMapping(parts[1], new Signature(parts[2]));
130 } else {
131 return new MethodMapping(parts[1], new Signature(parts[3]), parts[2]);
132 }
133 }
134}