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 }