1/*
2 * Copyright (C) 2006 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.internal.telephony;
18
19/**
20 * {@hide}
21 */
22public class ATResponseParser
23{
24    /*************************** Instance Variables **************************/
25
26    private String mLine;
27    private int mNext = 0;
28    private int mTokStart, mTokEnd;
29
30    /***************************** Class Methods *****************************/
31
32    public
33    ATResponseParser (String line)
34    {
35        mLine = line;
36    }
37
38    public boolean
39    nextBoolean()
40    {
41        // "\s*(\d)(,|$)"
42        // \d is '0' or '1'
43
44        nextTok();
45
46        if (mTokEnd - mTokStart > 1) {
47            throw new ATParseEx();
48        }
49        char c = mLine.charAt(mTokStart);
50
51        if (c == '0') return false;
52        if (c ==  '1') return true;
53        throw new ATParseEx();
54    }
55
56
57    /** positive int only */
58    public int
59    nextInt()
60    {
61        // "\s*(\d+)(,|$)"
62        int ret = 0;
63
64        nextTok();
65
66        for (int i = mTokStart ; i < mTokEnd ; i++) {
67            char c = mLine.charAt(i);
68
69            // Yes, ASCII decimal digits only
70            if (c < '0' || c > '9') {
71                throw new ATParseEx();
72            }
73
74            ret *= 10;
75            ret += c - '0';
76        }
77
78        return ret;
79    }
80
81    public String
82    nextString()
83    {
84        nextTok();
85
86        return mLine.substring(mTokStart, mTokEnd);
87    }
88
89    public boolean
90    hasMore()
91    {
92        return mNext < mLine.length();
93    }
94
95    private void
96    nextTok()
97    {
98        int len = mLine.length();
99
100        if (mNext == 0) {
101            skipPrefix();
102        }
103
104        if (mNext >= len) {
105            throw new ATParseEx();
106        }
107
108        try {
109            // \s*("([^"]*)"|(.*)\s*)(,|$)
110
111            char c = mLine.charAt(mNext++);
112            boolean hasQuote = false;
113
114            c = skipWhiteSpace(c);
115
116            if (c == '"') {
117                if (mNext >= len) {
118                    throw new ATParseEx();
119                }
120                c = mLine.charAt(mNext++);
121                mTokStart = mNext - 1;
122                while (c != '"' && mNext < len) {
123                    c = mLine.charAt(mNext++);
124                }
125                if (c != '"') {
126                    throw new ATParseEx();
127                }
128                mTokEnd = mNext - 1;
129                if (mNext < len && mLine.charAt(mNext++) != ',') {
130                    throw new ATParseEx();
131                }
132            } else {
133                mTokStart = mNext - 1;
134                mTokEnd = mTokStart;
135                while (c != ',') {
136                    if (!Character.isWhitespace(c)) {
137                        mTokEnd = mNext;
138                    }
139                    if (mNext == len) {
140                        break;
141                    }
142                    c = mLine.charAt(mNext++);
143                }
144            }
145        } catch (StringIndexOutOfBoundsException ex) {
146            throw new ATParseEx();
147        }
148    }
149
150
151    /** Throws ATParseEx if whitespace extends to the end of string */
152    private char
153    skipWhiteSpace (char c)
154    {
155        int len;
156        len = mLine.length();
157        while (mNext < len && Character.isWhitespace(c)) {
158            c = mLine.charAt(mNext++);
159        }
160
161        if (Character.isWhitespace(c)) {
162            throw new ATParseEx();
163        }
164        return c;
165    }
166
167
168    private void
169    skipPrefix()
170    {
171        // consume "^[^:]:"
172
173        mNext = 0;
174        int s = mLine.length();
175        while (mNext < s){
176            char c = mLine.charAt(mNext++);
177
178            if (c == ':') {
179                return;
180            }
181        }
182
183        throw new ATParseEx("missing prefix");
184    }
185
186}
187