    001    /**
    002     * Copyright (C) 2010, Skype Limited
    003     *
    004     * All intellectual property rights, including but not limited to copyrights,
    005     * trademarks and patents, as well as know how and trade secrets contained in,
    006     * relating to, or arising from the internet telephony software of
    007     * Skype Limited (including its affiliates, "Skype"), including without
    008     * limitation this source code, Skype API and related material of such
    009     * software proprietary to Skype and/or its licensors ("IP Rights") are and
    010     * shall remain the exclusive property of Skype and/or its licensors.
    011     * The recipient hereby acknowledges and agrees that any unauthorized use of
    012     * the IP Rights is a violation of intellectual property laws.
    013     *
    014     * Skype reserves all rights and may take legal action against infringers of
    015     * IP Rights.
    016     *
    017     * The recipient agrees not to remove, obscure, make illegible or alter any
    018     * notices or indications of the IP Rights and/or Skype's rights and
    019     * ownership thereof.
    020     */
    021
    022    package com.skype.ipc;
    023
    024    import java.io.IOException;
    025
    026    import com.skype.util.Log;
    027
    028    public abstract class AbstractDecoder
    029    {
    030        private static final String TAG        = "AbstractDecoder";
    031        public static final int     NULL_VALUE = -1;
    032        protected Transport         ioTransport;
    033
    034        AbstractDecoder(Transport in) // ,EventCallback.eType type)
    035        {
    036            ioTransport = in;
    037        }
    038
    039        protected Object decodeOneOfKind(int kind) throws IOException
    040        {
    041            switch (kind) {
    042            case 'z':
    043                // no more parms
    044                Log.d(TAG, "No more params");
    045                return null;
    046            case 'S':
    047            case 'X':
    048            case 'f':
    049                // decode string
    050                return decodeString();
    051            case 'B':
    052                // decode binary
    053                return decodeBinary();
    054            case '[':
    055                // decode list
    056                Log.d(TAG, "Parm is list. Starting list decoding...");
    057                return decodeList();
    058            case ']':
    059                // end decoding list
    060                Log.d(TAG, "Ending list decoding");
    061                return null;
    062            case 'O':
    063                // decode object
    064                return decodeObjectid();
    065            case 'u':
    066            case 'e':
    067            case 'o':
    068                // decode varuint
    069                return decodeVaruint();
    070            case 'i':
    071                // decode varint
    072                return decodeVarint();
    073            case 'T':
    074                // decode boolean true
    075                return 1;
    076            case 'F':
    077                // decode boolean false
    078                return 0;
    079            default:
    080                Log.e(TAG, "Unknown response parm " + kind + " '" + (char) kind + "'");
    081                throw new IOException();
    082            }
    083            // return null;
    084
    085        }
    086
    087        protected String decodeString() throws IOException
    088        {
    089            int length = decodeVaruint();
    090            if (length > 0) {
    091                byte[] bytes = new byte[length];
    092                ioTransport.read(length, bytes, true);
    093                String s = new String(bytes);
    094                return s;
    095            }
    096            return "";
    097        }
    098
    099        protected byte[] decodeBinary() throws IOException
    100        {
    101            int length = decodeVaruint();
    102            if (length > 0) {
    103                byte[] bytes = new byte[length];
    104                ioTransport.read(length, bytes, true);
    105                return bytes;
    106            }
    107            return new byte[0];
    108        }
    109
    110        protected int decodeVarint() throws IOException
    111        {
    112
    113            int number = decodeVaruint();
    114            if ((1 & number) != 0) {
    115                // negative
    116                number = (number ^ (~0)) >> 1;
    117            }
    118            else {
    119                // positive
    120                number = (number >> 1);
    121            }
    122
    123            return number;
    124        }
    125
    126        protected int decodeVaruint() throws IOException
    127        {
    128            return (decodeOneVaruint(ioTransport));
    129        }
    130
    131        protected static int decodeOneVaruint(Transport i) throws IOException
    132        {
    133            Log.d(TAG,"Going to decode Varuint");
    134            int shift = 0;
    135            int result = 0;
    136            while (true) {
    137                int value = i.read() & 0xFF;
    138                result = result | ((value & 0x7f) << shift);
    139                shift = shift + 7;
    140                Log.d(TAG, "processing byte " + value + ", result=" + result + ",shift=" + shift);
    141                if ((value & 0x80) == 0)
    142                    break;
    143            }
    144            return result;
    145        }
    146
    147        protected int decodeObjectid() throws IOException
    148        {
    149            return (decodeVaruint());
    150        }
    151
    152        protected boolean decodeBoolean() throws IOException
    153        {
    154            int v = ioTransport.read();
    155            if (v == 'T') {
    156                return true;
    157            }
    158            else if (v == 'F') {
    159                return false;
    160            }
    161            else {
    162                Log.e(TAG, "Invalid boolean value " + v + "'" + (char) v + "'");
    163                throw new IOException();
    164            }
    165        }
    166
    167        protected ResponseListElement decodeList() throws IOException
    168        {
    169            ResponseListElement rlist = new ResponseListElement(ioTransport);
    170            return rlist;
    171        }
    172    }