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                return decodeList();
057            case ']':
058                // end decoding list
059                return null;
060            case 'O':
061                // decode object
062                return decodeObjectid();
063            case 'u':
064            case 'e':
065            case 'o':
066                // decode varuint
067                return decodeVaruint();
068            case 'i':
069                // decode varint
070                return decodeVarint();
071            case 'T':
072                // decode boolean true
073                return 1;
074            case 'F':
075                // decode boolean false
076                return 0;
077            default:
078                Log.e(TAG, "Unknown response parm " + kind + " '" + (char) kind + "'");
079                throw new IOException();
080            }
081            // return null;
082    
083        }
084    
085        protected String decodeString() throws IOException
086        {
087            int length = decodeVaruint();
088            if (length > 0) {
089                byte[] bytes = new byte[length];
090                ioTransport.read(length, bytes, true);
091                String s = new String(bytes);
092                return s;
093            }
094            return "";
095        }
096    
097        protected byte[] decodeBinary() throws IOException
098        {
099            int length = decodeVaruint();
100            if (length > 0) {
101                byte[] bytes = new byte[length];
102                ioTransport.read(length, bytes, true);
103                return bytes;
104            }
105            return new byte[0];
106        }
107    
108        protected int decodeVarint() throws IOException
109        {
110    
111            int number = decodeVaruint();
112            if ((1 & number) != 0) {
113                // negative
114                number = (number ^ (~0)) >> 1;
115            }
116            else {
117                // positive
118                number = (number >> 1);
119            }
120    
121            return number;
122        }
123    
124        protected int decodeVaruint() throws IOException
125        {
126            return (decodeOneVaruint(ioTransport));
127        }
128    
129        protected static int decodeOneVaruint(Transport i) throws IOException
130        {
131            int shift = 0;
132            int result = 0;
133            while (true) {
134                int value = i.read() & 0xFF;
135                result = result | ((value & 0x7f) << shift);
136                shift = shift + 7;
137                if ((value & 0x80) == 0)
138                    break;
139            }
140            return result;
141        }
142    
143        protected int decodeObjectid() throws IOException
144        {
145            return (decodeVaruint());
146        }
147    
148        protected boolean decodeBoolean() throws IOException
149        {
150            int v = ioTransport.read();
151            if (v == 'T') {
152                return true;
153            }
154            else if (v == 'F') {
155                return false;
156            }
157            else {
158                Log.e(TAG, "Invalid boolean value " + v + "'" + (char) v + "'");
159                throw new IOException();
160            }
161        }
162    
163        protected ResponseListElement decodeList() throws IOException
164        {
165            ResponseListElement rlist = new ResponseListElement(ioTransport);
166            return rlist;
167        }
168    }