1cbd87b904e15c63d06f25b03b0eadf003780ec6cBen Gruver/*
2cbd87b904e15c63d06f25b03b0eadf003780ec6cBen Gruver * Copyright 2014, Google Inc.
3cbd87b904e15c63d06f25b03b0eadf003780ec6cBen Gruver * All rights reserved.
4cbd87b904e15c63d06f25b03b0eadf003780ec6cBen Gruver *
5cbd87b904e15c63d06f25b03b0eadf003780ec6cBen Gruver * Redistribution and use in source and binary forms, with or without
6cbd87b904e15c63d06f25b03b0eadf003780ec6cBen Gruver * modification, are permitted provided that the following conditions are
7cbd87b904e15c63d06f25b03b0eadf003780ec6cBen Gruver * met:
8cbd87b904e15c63d06f25b03b0eadf003780ec6cBen Gruver *
9cbd87b904e15c63d06f25b03b0eadf003780ec6cBen Gruver *     * Redistributions of source code must retain the above copyright
10cbd87b904e15c63d06f25b03b0eadf003780ec6cBen Gruver * notice, this list of conditions and the following disclaimer.
11cbd87b904e15c63d06f25b03b0eadf003780ec6cBen Gruver *     * Redistributions in binary form must reproduce the above
12cbd87b904e15c63d06f25b03b0eadf003780ec6cBen Gruver * copyright notice, this list of conditions and the following disclaimer
13cbd87b904e15c63d06f25b03b0eadf003780ec6cBen Gruver * in the documentation and/or other materials provided with the
14cbd87b904e15c63d06f25b03b0eadf003780ec6cBen Gruver * distribution.
15cbd87b904e15c63d06f25b03b0eadf003780ec6cBen Gruver *     * Neither the name of Google Inc. nor the names of its
16cbd87b904e15c63d06f25b03b0eadf003780ec6cBen Gruver * contributors may be used to endorse or promote products derived from
17cbd87b904e15c63d06f25b03b0eadf003780ec6cBen Gruver * this software without specific prior written permission.
18cbd87b904e15c63d06f25b03b0eadf003780ec6cBen Gruver *
19cbd87b904e15c63d06f25b03b0eadf003780ec6cBen Gruver * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20cbd87b904e15c63d06f25b03b0eadf003780ec6cBen Gruver * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21cbd87b904e15c63d06f25b03b0eadf003780ec6cBen Gruver * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22cbd87b904e15c63d06f25b03b0eadf003780ec6cBen Gruver * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23cbd87b904e15c63d06f25b03b0eadf003780ec6cBen Gruver * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24cbd87b904e15c63d06f25b03b0eadf003780ec6cBen Gruver * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25cbd87b904e15c63d06f25b03b0eadf003780ec6cBen Gruver * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26cbd87b904e15c63d06f25b03b0eadf003780ec6cBen Gruver * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27cbd87b904e15c63d06f25b03b0eadf003780ec6cBen Gruver * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28cbd87b904e15c63d06f25b03b0eadf003780ec6cBen Gruver * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29cbd87b904e15c63d06f25b03b0eadf003780ec6cBen Gruver * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30cbd87b904e15c63d06f25b03b0eadf003780ec6cBen Gruver */
31cbd87b904e15c63d06f25b03b0eadf003780ec6cBen Gruver
32cbd87b904e15c63d06f25b03b0eadf003780ec6cBen Gruverpackage org.jf.smalidea.dexlib.instruction;
33cbd87b904e15c63d06f25b03b0eadf003780ec6cBen Gruver
340dd228064d9e7f617bfea1e805bab59525cf7097Ben Gruverimport com.google.common.base.Function;
350dd228064d9e7f617bfea1e805bab59525cf7097Ben Gruverimport com.google.common.collect.Lists;
360dd228064d9e7f617bfea1e805bab59525cf7097Ben Gruverimport org.jf.dexlib2.Opcode;
37cbd87b904e15c63d06f25b03b0eadf003780ec6cBen Gruverimport org.jf.dexlib2.iface.instruction.SwitchElement;
38cbd87b904e15c63d06f25b03b0eadf003780ec6cBen Gruverimport org.jf.dexlib2.iface.instruction.formats.SparseSwitchPayload;
390dd228064d9e7f617bfea1e805bab59525cf7097Ben Gruverimport org.jf.smalidea.psi.impl.*;
400dd228064d9e7f617bfea1e805bab59525cf7097Ben Gruverimport org.jf.smalidea.util.InstructionUtils;
41cbd87b904e15c63d06f25b03b0eadf003780ec6cBen Gruver
42cbd87b904e15c63d06f25b03b0eadf003780ec6cBen Gruverimport javax.annotation.Nonnull;
43cbd87b904e15c63d06f25b03b0eadf003780ec6cBen Gruverimport java.util.List;
44cbd87b904e15c63d06f25b03b0eadf003780ec6cBen Gruver
45cbd87b904e15c63d06f25b03b0eadf003780ec6cBen Gruverpublic class SmalideaSparseSwitchPayload extends SmalideaInstruction implements SparseSwitchPayload {
46cbd87b904e15c63d06f25b03b0eadf003780ec6cBen Gruver    public SmalideaSparseSwitchPayload(@Nonnull SmaliInstruction instruction) {
47cbd87b904e15c63d06f25b03b0eadf003780ec6cBen Gruver        super(instruction);
48cbd87b904e15c63d06f25b03b0eadf003780ec6cBen Gruver    }
49cbd87b904e15c63d06f25b03b0eadf003780ec6cBen Gruver
50cbd87b904e15c63d06f25b03b0eadf003780ec6cBen Gruver    @Nonnull @Override public List<? extends SwitchElement> getSwitchElements() {
510dd228064d9e7f617bfea1e805bab59525cf7097Ben Gruver        List<SmaliSparseSwitchElement> elements = psiInstruction.getSparseSwitchElements();
520dd228064d9e7f617bfea1e805bab59525cf7097Ben Gruver
530dd228064d9e7f617bfea1e805bab59525cf7097Ben Gruver        SmaliMethod smaliMethod = psiInstruction.getParentMethod();
540dd228064d9e7f617bfea1e805bab59525cf7097Ben Gruver        SmaliInstruction sparseSwitchInstruction = InstructionUtils.findFirstInstructionWithTarget(
550dd228064d9e7f617bfea1e805bab59525cf7097Ben Gruver                smaliMethod, Opcode.SPARSE_SWITCH, psiInstruction.getOffset());
560dd228064d9e7f617bfea1e805bab59525cf7097Ben Gruver        final int baseOffset;
570dd228064d9e7f617bfea1e805bab59525cf7097Ben Gruver
580dd228064d9e7f617bfea1e805bab59525cf7097Ben Gruver        if (sparseSwitchInstruction == null) {
590dd228064d9e7f617bfea1e805bab59525cf7097Ben Gruver            baseOffset = 0;
600dd228064d9e7f617bfea1e805bab59525cf7097Ben Gruver        } else {
610dd228064d9e7f617bfea1e805bab59525cf7097Ben Gruver            baseOffset = sparseSwitchInstruction.getOffset();
620dd228064d9e7f617bfea1e805bab59525cf7097Ben Gruver        }
630dd228064d9e7f617bfea1e805bab59525cf7097Ben Gruver
640dd228064d9e7f617bfea1e805bab59525cf7097Ben Gruver        return Lists.transform(elements, new Function<SmaliSparseSwitchElement, SwitchElement>() {
650dd228064d9e7f617bfea1e805bab59525cf7097Ben Gruver            @Override public SwitchElement apply(final SmaliSparseSwitchElement element) {
660dd228064d9e7f617bfea1e805bab59525cf7097Ben Gruver                return new SwitchElement() {
670dd228064d9e7f617bfea1e805bab59525cf7097Ben Gruver                    @Override public int getKey() {
680dd228064d9e7f617bfea1e805bab59525cf7097Ben Gruver                        return (int)element.getKey().getIntegralValue();
690dd228064d9e7f617bfea1e805bab59525cf7097Ben Gruver                    }
700dd228064d9e7f617bfea1e805bab59525cf7097Ben Gruver
710dd228064d9e7f617bfea1e805bab59525cf7097Ben Gruver                    @Override public int getOffset() {
720dd228064d9e7f617bfea1e805bab59525cf7097Ben Gruver                        SmaliLabelReference labelReference = element.getTarget();
730dd228064d9e7f617bfea1e805bab59525cf7097Ben Gruver                        if (labelReference == null) {
740dd228064d9e7f617bfea1e805bab59525cf7097Ben Gruver                            return 0;
750dd228064d9e7f617bfea1e805bab59525cf7097Ben Gruver                        }
760dd228064d9e7f617bfea1e805bab59525cf7097Ben Gruver
770dd228064d9e7f617bfea1e805bab59525cf7097Ben Gruver                        SmaliLabel label = labelReference.resolve();
780dd228064d9e7f617bfea1e805bab59525cf7097Ben Gruver                        if (label == null) {
790dd228064d9e7f617bfea1e805bab59525cf7097Ben Gruver                            return 0;
800dd228064d9e7f617bfea1e805bab59525cf7097Ben Gruver                        }
810dd228064d9e7f617bfea1e805bab59525cf7097Ben Gruver
820dd228064d9e7f617bfea1e805bab59525cf7097Ben Gruver                        return label.getOffset() - baseOffset;
830dd228064d9e7f617bfea1e805bab59525cf7097Ben Gruver                    }
840dd228064d9e7f617bfea1e805bab59525cf7097Ben Gruver                };
850dd228064d9e7f617bfea1e805bab59525cf7097Ben Gruver            }
860dd228064d9e7f617bfea1e805bab59525cf7097Ben Gruver        });
870dd228064d9e7f617bfea1e805bab59525cf7097Ben Gruver    }
880dd228064d9e7f617bfea1e805bab59525cf7097Ben Gruver
890dd228064d9e7f617bfea1e805bab59525cf7097Ben Gruver    @Override public int getCodeUnits() {
900a2debe4e6eb54a440ec5acbec4e42956da33c29Ben Gruver        return psiInstruction.getInstructionSize()/2;
91cbd87b904e15c63d06f25b03b0eadf003780ec6cBen Gruver    }
92cbd87b904e15c63d06f25b03b0eadf003780ec6cBen Gruver}
93