aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/ftbsc/lll/mapper/AbstractMapper.java
blob: 037e7c9d29bed2abc5728b3eb348cdb4d13cffed (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
package ftbsc.lll.mapper;

import ftbsc.lll.exceptions.MalformedMappingsException;
import ftbsc.lll.exceptions.MappingNotFoundException;
import ftbsc.lll.mapper.tools.data.ClassData;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * A default implementation of {@link IMapper} meant to
 * recycle as much code as possible.
 */
public abstract class AbstractMapper implements IMapper {

   /**
    * A {@link Map} tying each plain class name to its class data.
    */
   protected final Map<String, ClassData> mappings = new HashMap<>();

   /**
    * A {@link Map} tying each obfuscated name to its class data.
    */
   protected final Map<String, ClassData> mappingsInverted = new HashMap<>();

   /**
    * Populates the {@link IMapper} given the lines, ignoring errors depending on the
    * given ignoreErrors flag.
    * @param lines the lines to read
    * @param ignoreErrors try to ignore errors and keep going
    * @throws MalformedMappingsException if an error is encountered and ignoreErrors is false
    */
   @Override
   public void populate(List<String> lines, boolean ignoreErrors) throws MalformedMappingsException {
      this.processLines(lines, ignoreErrors);
      this.mappings.forEach((name, data) -> {
         ClassData reverse = data.generateReverseMappings(this);
         this.mappingsInverted.put(data.nameMapped, reverse);
      });
   }

   /**
    * Reads the given lines of text and attempts to interpret them as
    * mappings of the given type.
    * @param lines the lines to read
    * @param ignoreErrors try to ignore errors and keep going
    * @throws MalformedMappingsException if an error is encountered and ignoreErrors is false
    */
   protected abstract void processLines(List<String> lines, boolean ignoreErrors) throws MalformedMappingsException;

   /**
    * Completely resets the mapper, clearing it of all existing mappings.
    */
   @Override
   public void reset() {
      this.mappings.clear();
      this.mappingsInverted.clear();
   }

   /**
    * Gets a name of a class from the given {@link Map}.
    * @param name the name
    * @param mappings the {@link Map} to pull data from
    * @return the mapped name
    * @throws MappingNotFoundException if no mapping is found
    */
   private static String mapClass(String name, Map<String, ClassData> mappings) {
      ClassData data = mappings.get(name.replace('.', '/'));
      if(data == null)
         throw new MappingNotFoundException("class", name);
      else return data.nameMapped;
   }

   /**
    * Gets the obfuscated name of the class.
    * @param name the plain internal name of the desired class
    * @return the obfuscated name of the class
    * @throws MappingNotFoundException if no mapping is found
    */
   @Override
   public String obfuscateClass(String name)  {
      return mapClass(name, this.mappings);
   }

   /**
    * Gets the plain name of the class.
    * @param nameObf the obfuscated internal name of the desired class
    * @return the plain name of the class
    * @throws MappingNotFoundException if no mapping is found
    */
   @Override
   public String deobfuscateClass(String nameObf) throws MappingNotFoundException {
      return mapClass(nameObf, this.mappingsInverted);
   }

   /**
    * Gets the name of a member from the given {@link Map}.
    * @param parentName the parent class
    * @param mappings the {@link Map} to pull data from
    * @param memberName the field or method name
    * @param methodDescriptor the method descriptor, may be null or partial
    * @return the mapped member name
    * @throws MappingNotFoundException if no mapping is found
    */
   private static String mapMember(String parentName, Map<String, ClassData> mappings,
                                                   String memberName, String methodDescriptor) {
      ClassData data = mappings.get(parentName.replace('.', '/'));
      if(data == null)
         throw new MappingNotFoundException("class", parentName);

      if(methodDescriptor == null)
         return data.mapField(memberName).name;
      else return data.mapMethod(memberName, methodDescriptor).signature.name;
   }

   /**
    * Gets the obfuscated name of a class member (field or method).
    * @param parentName the unobfuscated internal name of the parent class
    * @param memberName the field or method name
    * @param methodDescriptor the optional descriptor of the member, may be null or partial
    * @return the obfuscated name of the given member
    * @throws MappingNotFoundException if no mapping is found
    */
   @Override
   public String obfuscateMember(String parentName, String memberName, String methodDescriptor) {
      return mapMember(parentName, this.mappings, memberName, methodDescriptor);
   }

   /**
    * Gets the plain name of a class member (field or method).
    * @param parentName       the obfuscated internal name of the parent class
    * @param memberName       the obfuscated field name or method signature
    * @param methodDescriptor the obfuscated descriptor of the member (only for methods)
    * @return the plain name of the given member
    * @throws MappingNotFoundException if no mapping is found
    */
   @Override
   public String deobfuscateMember(String parentName, String memberName, String methodDescriptor) throws MappingNotFoundException {
      return mapMember(parentName, this.mappingsInverted, memberName, methodDescriptor);
   }
}