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    }