10d857b9028f2702ce439e13feccde8182d40e1e5Siva Velusamypackage com.android.test.hierarchyviewer;
20d857b9028f2702ce439e13feccde8182d40e1e5Siva Velusamy
30d857b9028f2702ce439e13feccde8182d40e1e5Siva Velusamyimport java.nio.ByteBuffer;
40d857b9028f2702ce439e13feccde8182d40e1e5Siva Velusamyimport java.nio.charset.Charset;
50d857b9028f2702ce439e13feccde8182d40e1e5Siva Velusamyimport java.util.HashMap;
60d857b9028f2702ce439e13feccde8182d40e1e5Siva Velusamyimport java.util.Map;
70d857b9028f2702ce439e13feccde8182d40e1e5Siva Velusamy
80d857b9028f2702ce439e13feccde8182d40e1e5Siva Velusamypublic class Decoder {
90d857b9028f2702ce439e13feccde8182d40e1e5Siva Velusamy    // Prefixes for simple primitives. These match the JNI definitions.
100d857b9028f2702ce439e13feccde8182d40e1e5Siva Velusamy    public static final byte SIG_BOOLEAN = 'Z';
110d857b9028f2702ce439e13feccde8182d40e1e5Siva Velusamy    public static final byte SIG_BYTE = 'B';
120d857b9028f2702ce439e13feccde8182d40e1e5Siva Velusamy    public static final byte SIG_SHORT = 'S';
130d857b9028f2702ce439e13feccde8182d40e1e5Siva Velusamy    public static final byte SIG_INT = 'I';
140d857b9028f2702ce439e13feccde8182d40e1e5Siva Velusamy    public static final byte SIG_LONG = 'J';
150d857b9028f2702ce439e13feccde8182d40e1e5Siva Velusamy    public static final byte SIG_FLOAT = 'F';
160d857b9028f2702ce439e13feccde8182d40e1e5Siva Velusamy    public static final byte SIG_DOUBLE = 'D';
170d857b9028f2702ce439e13feccde8182d40e1e5Siva Velusamy
180d857b9028f2702ce439e13feccde8182d40e1e5Siva Velusamy    // Prefixes for some commonly used objects
190d857b9028f2702ce439e13feccde8182d40e1e5Siva Velusamy    public static final byte SIG_STRING = 'R';
200d857b9028f2702ce439e13feccde8182d40e1e5Siva Velusamy
210d857b9028f2702ce439e13feccde8182d40e1e5Siva Velusamy    public static final byte SIG_MAP = 'M'; // a map with an short key
220d857b9028f2702ce439e13feccde8182d40e1e5Siva Velusamy    public static final short SIG_END_MAP = 0;
230d857b9028f2702ce439e13feccde8182d40e1e5Siva Velusamy
240d857b9028f2702ce439e13feccde8182d40e1e5Siva Velusamy    private final ByteBuffer mBuf;
250d857b9028f2702ce439e13feccde8182d40e1e5Siva Velusamy
260d857b9028f2702ce439e13feccde8182d40e1e5Siva Velusamy    public Decoder(byte[] buf) {
270d857b9028f2702ce439e13feccde8182d40e1e5Siva Velusamy        this(ByteBuffer.wrap(buf));
280d857b9028f2702ce439e13feccde8182d40e1e5Siva Velusamy    }
290d857b9028f2702ce439e13feccde8182d40e1e5Siva Velusamy
300d857b9028f2702ce439e13feccde8182d40e1e5Siva Velusamy    public Decoder(ByteBuffer buf) {
310d857b9028f2702ce439e13feccde8182d40e1e5Siva Velusamy        mBuf = buf;
320d857b9028f2702ce439e13feccde8182d40e1e5Siva Velusamy    }
330d857b9028f2702ce439e13feccde8182d40e1e5Siva Velusamy
340d857b9028f2702ce439e13feccde8182d40e1e5Siva Velusamy    public boolean hasRemaining() {
350d857b9028f2702ce439e13feccde8182d40e1e5Siva Velusamy        return mBuf.hasRemaining();
360d857b9028f2702ce439e13feccde8182d40e1e5Siva Velusamy    }
370d857b9028f2702ce439e13feccde8182d40e1e5Siva Velusamy
380d857b9028f2702ce439e13feccde8182d40e1e5Siva Velusamy    public Object readObject() {
390d857b9028f2702ce439e13feccde8182d40e1e5Siva Velusamy        byte sig = mBuf.get();
400d857b9028f2702ce439e13feccde8182d40e1e5Siva Velusamy
410d857b9028f2702ce439e13feccde8182d40e1e5Siva Velusamy        switch (sig) {
420d857b9028f2702ce439e13feccde8182d40e1e5Siva Velusamy            case SIG_BOOLEAN:
430d857b9028f2702ce439e13feccde8182d40e1e5Siva Velusamy                return mBuf.get() == 0 ? Boolean.FALSE : Boolean.TRUE;
440d857b9028f2702ce439e13feccde8182d40e1e5Siva Velusamy            case SIG_BYTE:
450d857b9028f2702ce439e13feccde8182d40e1e5Siva Velusamy                return mBuf.get();
460d857b9028f2702ce439e13feccde8182d40e1e5Siva Velusamy            case SIG_SHORT:
470d857b9028f2702ce439e13feccde8182d40e1e5Siva Velusamy                return mBuf.getShort();
480d857b9028f2702ce439e13feccde8182d40e1e5Siva Velusamy            case SIG_INT:
490d857b9028f2702ce439e13feccde8182d40e1e5Siva Velusamy                return mBuf.getInt();
500d857b9028f2702ce439e13feccde8182d40e1e5Siva Velusamy            case SIG_LONG:
510d857b9028f2702ce439e13feccde8182d40e1e5Siva Velusamy                return mBuf.getLong();
520d857b9028f2702ce439e13feccde8182d40e1e5Siva Velusamy            case SIG_FLOAT:
530d857b9028f2702ce439e13feccde8182d40e1e5Siva Velusamy                return mBuf.getFloat();
540d857b9028f2702ce439e13feccde8182d40e1e5Siva Velusamy            case SIG_DOUBLE:
550d857b9028f2702ce439e13feccde8182d40e1e5Siva Velusamy                return mBuf.getDouble();
560d857b9028f2702ce439e13feccde8182d40e1e5Siva Velusamy            case SIG_STRING:
570d857b9028f2702ce439e13feccde8182d40e1e5Siva Velusamy                return readString();
580d857b9028f2702ce439e13feccde8182d40e1e5Siva Velusamy            case SIG_MAP:
590d857b9028f2702ce439e13feccde8182d40e1e5Siva Velusamy                return readMap();
600d857b9028f2702ce439e13feccde8182d40e1e5Siva Velusamy            default:
610d857b9028f2702ce439e13feccde8182d40e1e5Siva Velusamy                throw new DecoderException(sig, mBuf.position() - 1);
620d857b9028f2702ce439e13feccde8182d40e1e5Siva Velusamy        }
630d857b9028f2702ce439e13feccde8182d40e1e5Siva Velusamy    }
640d857b9028f2702ce439e13feccde8182d40e1e5Siva Velusamy
650d857b9028f2702ce439e13feccde8182d40e1e5Siva Velusamy    private String readString() {
660d857b9028f2702ce439e13feccde8182d40e1e5Siva Velusamy        short len = mBuf.getShort();
670d857b9028f2702ce439e13feccde8182d40e1e5Siva Velusamy        byte[] b = new byte[len];
680d857b9028f2702ce439e13feccde8182d40e1e5Siva Velusamy        mBuf.get(b, 0, len);
690d857b9028f2702ce439e13feccde8182d40e1e5Siva Velusamy        return new String(b, Charset.forName("utf-8"));
700d857b9028f2702ce439e13feccde8182d40e1e5Siva Velusamy    }
710d857b9028f2702ce439e13feccde8182d40e1e5Siva Velusamy
720d857b9028f2702ce439e13feccde8182d40e1e5Siva Velusamy    private Map<Short, Object> readMap() {
730d857b9028f2702ce439e13feccde8182d40e1e5Siva Velusamy        Map<Short, Object> m = new HashMap<Short, Object>();
740d857b9028f2702ce439e13feccde8182d40e1e5Siva Velusamy
750d857b9028f2702ce439e13feccde8182d40e1e5Siva Velusamy        while (true) {
760d857b9028f2702ce439e13feccde8182d40e1e5Siva Velusamy            Object o = readObject();
770d857b9028f2702ce439e13feccde8182d40e1e5Siva Velusamy            if (!(o instanceof Short)) {
780d857b9028f2702ce439e13feccde8182d40e1e5Siva Velusamy                throw new DecoderException("Expected short key, got " + o.getClass());
790d857b9028f2702ce439e13feccde8182d40e1e5Siva Velusamy            }
800d857b9028f2702ce439e13feccde8182d40e1e5Siva Velusamy
810d857b9028f2702ce439e13feccde8182d40e1e5Siva Velusamy            Short key = (Short)o;
820d857b9028f2702ce439e13feccde8182d40e1e5Siva Velusamy            if (key == SIG_END_MAP) {
830d857b9028f2702ce439e13feccde8182d40e1e5Siva Velusamy                break;
840d857b9028f2702ce439e13feccde8182d40e1e5Siva Velusamy            }
850d857b9028f2702ce439e13feccde8182d40e1e5Siva Velusamy
860d857b9028f2702ce439e13feccde8182d40e1e5Siva Velusamy            m.put(key, readObject());
870d857b9028f2702ce439e13feccde8182d40e1e5Siva Velusamy        }
880d857b9028f2702ce439e13feccde8182d40e1e5Siva Velusamy
890d857b9028f2702ce439e13feccde8182d40e1e5Siva Velusamy        return m;
900d857b9028f2702ce439e13feccde8182d40e1e5Siva Velusamy    }
910d857b9028f2702ce439e13feccde8182d40e1e5Siva Velusamy
920d857b9028f2702ce439e13feccde8182d40e1e5Siva Velusamy    public static class DecoderException extends RuntimeException {
930d857b9028f2702ce439e13feccde8182d40e1e5Siva Velusamy        public DecoderException(byte seen, int pos) {
940d857b9028f2702ce439e13feccde8182d40e1e5Siva Velusamy            super(String.format("Unexpected byte %c seen at position %d", (char)seen, pos));
950d857b9028f2702ce439e13feccde8182d40e1e5Siva Velusamy        }
960d857b9028f2702ce439e13feccde8182d40e1e5Siva Velusamy
970d857b9028f2702ce439e13feccde8182d40e1e5Siva Velusamy        public DecoderException(String msg) {
980d857b9028f2702ce439e13feccde8182d40e1e5Siva Velusamy            super(msg);
990d857b9028f2702ce439e13feccde8182d40e1e5Siva Velusamy        }
1000d857b9028f2702ce439e13feccde8182d40e1e5Siva Velusamy    }
1010d857b9028f2702ce439e13feccde8182d40e1e5Siva Velusamy}
102