203 lines
5.2 KiB
Java
203 lines
5.2 KiB
Java
/*
|
|
* Copyright (C) 2012 The Android Open Source Project
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
package com.android.imap2;
|
|
|
|
public class Parser {
|
|
String str;
|
|
int pos;
|
|
int len;
|
|
static final String white = "\r\n \t";
|
|
|
|
public Parser (String _str) {
|
|
str = _str;
|
|
pos = 0;
|
|
len = str.length();
|
|
}
|
|
|
|
public Parser (String _str, int start) {
|
|
str = _str;
|
|
pos = start;
|
|
len = str.length();
|
|
}
|
|
|
|
public void skipWhite () {
|
|
while ((pos < len) && white.indexOf(str.charAt(pos)) >= 0)
|
|
pos++;
|
|
}
|
|
|
|
public String parseAtom () {
|
|
skipWhite();
|
|
int start = pos;
|
|
while ((pos < len) && white.indexOf(str.charAt(pos)) < 0)
|
|
pos++;
|
|
if (pos > start)
|
|
return str.substring(start, pos);
|
|
return null;
|
|
}
|
|
|
|
public char nextChar () {
|
|
if (pos >= len)
|
|
return 0;
|
|
else
|
|
return str.charAt(pos++);
|
|
}
|
|
|
|
public char peekChar () {
|
|
if (pos >= len)
|
|
return 0;
|
|
else
|
|
return str.charAt(pos);
|
|
}
|
|
|
|
public String parseString () {
|
|
return parseString(false);
|
|
}
|
|
|
|
public String parseStringOrAtom () {
|
|
return parseString(true);
|
|
}
|
|
|
|
public String parseString (boolean orAtom) {
|
|
skipWhite();
|
|
char c = nextChar();
|
|
if (c != '\"') {
|
|
if (c == '{') {
|
|
int cnt = parseInteger();
|
|
c = nextChar();
|
|
if (c != '}')
|
|
return null;
|
|
int start = pos + 2;
|
|
int end = start + cnt;
|
|
String s = str.substring(start, end);
|
|
pos = end;
|
|
return s;
|
|
} else if (orAtom) {
|
|
backChar();
|
|
return parseAtom();
|
|
} else if (c == 'n' || c == 'N') {
|
|
parseAtom();
|
|
return null;
|
|
} else
|
|
return null;
|
|
}
|
|
int start = pos;
|
|
boolean quote = false;
|
|
while (true) {
|
|
c = nextChar();
|
|
if (c == 0)
|
|
return null;
|
|
else if (quote)
|
|
quote = false;
|
|
else if (c == '\\')
|
|
quote = true;
|
|
else if (c == '\"')
|
|
break;
|
|
}
|
|
return str.substring(start, pos - 1);
|
|
}
|
|
|
|
public void backChar () {
|
|
if (pos > 0)
|
|
pos--;
|
|
}
|
|
|
|
public String parseListOrNil () {
|
|
String list = parseList();
|
|
if (list == null) {
|
|
parseAtom();
|
|
list = "";
|
|
}
|
|
return list;
|
|
}
|
|
|
|
public String parseList () {
|
|
skipWhite();
|
|
if (nextChar() != '(') {
|
|
backChar();
|
|
return null;
|
|
}
|
|
int start = pos;
|
|
int level = 0;
|
|
boolean quote = false;
|
|
boolean string = false;
|
|
while (true) {
|
|
char c = nextChar();
|
|
if (c == 0)
|
|
return null;
|
|
else if (quote)
|
|
quote = false;
|
|
else if (c == '\\' && string)
|
|
quote = true;
|
|
else if (c == '\"')
|
|
string = !string;
|
|
else if (c == '(' && !string)
|
|
level++;
|
|
else if (c == ')' && !string) {
|
|
if (level-- == 0)
|
|
break;
|
|
}
|
|
}
|
|
return str.substring(start, pos - 1);
|
|
}
|
|
|
|
public Integer parseInteger () {
|
|
skipWhite();
|
|
int start = pos;
|
|
while (pos < len) {
|
|
char c = str.charAt(pos);
|
|
if (c >= '0' && c <= '9')
|
|
pos++;
|
|
else
|
|
break;
|
|
}
|
|
if (pos > start) {
|
|
try {
|
|
Integer i = Integer.parseInt(str.substring(start, pos));
|
|
return i;
|
|
} catch (NumberFormatException e) {
|
|
return -1;
|
|
}
|
|
} else
|
|
return -1;
|
|
}
|
|
|
|
public int[] gatherInts () {
|
|
int[] list = new int[128];
|
|
int size = 128;
|
|
int offs = 0;
|
|
while (true) {
|
|
// TODO Slow; handle this inline rather than calling the method
|
|
Integer i = parseInteger();
|
|
if (i >= 0) {
|
|
if (offs == size) {
|
|
// Double the size of the array as necessary
|
|
size <<= 1;
|
|
int[] tmp = new int[size];
|
|
System.arraycopy(list, 0, tmp, 0, offs);
|
|
list = tmp;
|
|
}
|
|
list[offs++] = i;
|
|
}
|
|
else
|
|
break;
|
|
}
|
|
int[] res = new int[offs];
|
|
System.arraycopy(list, 0, res, 0, offs);
|
|
return res;
|
|
}
|
|
}
|