/***************************************************************************
* Copyright (C) 2009 by Kevin Krammer <kevin.krammer@gmx.at> *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU Library General Public License as *
* published by the Free Software Foundation; either version 2 of the *
* License, or (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU Library General Public *
* License along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
***************************************************************************/
package org.akonadiproject.akonadi;
import java.util.List;
public class ParenthesisParser {
public static int parseParenthesizedList(CharSequence input,
List<CharSequence> result, int start) throws ProtocolException {
result.clear();
int index = start + 1;
while (index < input.length()) {
switch (input.charAt(index)) {
case '(': {
int end = getClosingParenthesis(input, index);
result.add(input.subSequence(index, end + 1));
index = end;
break;
}
case ' ':
case ')':
++index;
break;
default:
index = parseQuotedString(input, result, index);
break;
}
}
return input.length();
}
public static int parseQuotedString(CharSequence input,
List<CharSequence> result, int start) throws ProtocolException {
int subSeqStart = -1;
boolean inQuotes = false;
for (int index = start; index < input.length(); ++index) {
switch (input.charAt(index)) {
case ' ':
if (subSeqStart != -1 && !inQuotes) {
result.add(input.subSequence(subSeqStart, index));
return index + 1;
}
break;
case '\"':
if (index > 0 && input.charAt(index - 1) == '\\') {
if (subSeqStart == -1) {
subSeqStart = index;
}
break;
}
inQuotes = !inQuotes;
if (inQuotes && subSeqStart == -1) {
subSeqStart = index + 1;
}
if (!inQuotes) {
if (subSeqStart == -1)
throw new ProtocolException(
"No string value after index " + start
+ " in input '" + input + "'");
result.add(input.subSequence(subSeqStart, index));
return index + 1;
}
break;
case '(': // fall through
if (!inQuotes) {
if (subSeqStart == -1)
throw new ProtocolException(
"No string value after index " + start
+ " in input '" + input + "'");
CharSequence subSeq = input.subSequence(subSeqStart, index);
System.err.println("subSeq: start=" + subSeqStart
+ ", end=" + index);
result.add(subSeq);
return index;
}
break;
default:
if (subSeqStart == -1) {
subSeqStart = index;
}
break;
}
}
if (subSeqStart == -1)
throw new ProtocolException("No string value after index " + start
+ " in input '" + input + "'");
result.add(input.subSequence(subSeqStart, input.length() - 1));
return input.length();
}
public static int getClosingParenthesis(CharSequence input,
int openingParenthesis) throws ProtocolException {
boolean inQuotes = false;
int level = 1;
for (int index = openingParenthesis + 1; index < input.length(); ++index) {
switch (input.charAt(index)) {
case '\"':
if (index > 0 && input.charAt(index - 1) == '\\')
break;
inQuotes = !inQuotes;
break;
case '(':
if (!inQuotes) {
++level;
}
break;
case ')':
if (!inQuotes) {
--level;
}
if (level == 0)
return index;
break;
}
}
throw new ProtocolException("No closing parenthesis for opening at "
+ openingParenthesis + " in \'" + input + "'");
}
}