/*
* Copyright 2016 MiLaboratory.com
*
* 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.milaboratory.util;
import gnu.trove.map.hash.TCharIntHashMap;
public final class ParseUtil {
private ParseUtil() {
}
public static String[] splitWithBrackets(String string, char splitChar, String brackets) {
return splitWithBrackets(string, splitChar, new BracketsInfo(brackets));
}
public static String[] splitWithBrackets(String string, char splitChar, BracketsInfo brackets) {
IntArrayList splitPoints = new IntArrayList();
splitPoints.push(-1);
BracketsProcessor bracketsProcessor = brackets.createBracketsProcessor();
for (int i = 0; i < string.length(); ++i) {
char c = string.charAt(i);
if (!bracketsProcessor.process(c)) {
if (c == splitChar && bracketsProcessor.getDepth() == 0)
splitPoints.push(i);
}
}
bracketsProcessor.finish();
splitPoints.push(string.length());
int size = splitPoints.size() - 1;
String[] result = new String[size];
for (int i = 0; i < size; ++i)
result[i] = string.substring(splitPoints.get(i) + 1, splitPoints.get(i + 1));
return result;
}
public static final class BracketsInfo {
private final TCharIntHashMap bracketsMap = new TCharIntHashMap();
public BracketsInfo(String brackets) {
if (brackets.length() % 2 != 0)
throw new IllegalArgumentException();
for (int i = brackets.length() / 2 - 1; i >= 0; --i) {
bracketsMap.put(brackets.charAt(i * 2), i + 1);
bracketsMap.put(brackets.charAt(i * 2 + 1), -i - 1);
}
}
BracketsProcessor createBracketsProcessor() {
return new BracketsProcessor(bracketsMap);
}
}
private static final class BracketsProcessor {
private final TCharIntHashMap bracketsMap;
IntArrayList types = new IntArrayList();
private BracketsProcessor(TCharIntHashMap bracketsMap) {
this.bracketsMap = bracketsMap;
}
public boolean process(char c) {
int v = bracketsMap.get(c);
if (v == 0)
return false;
else {
if (v < 0) {
if (types.size() == 0)
throw new ParserException("Closing bracket '" + c + "' before any opening bracket.");
if (types.pop() != -v)
throw new ParserException("Unbalanced bracket '" + c + "'.");
return true;
} else {
types.push(v);
return true;
}
}
}
public void finish() {
if (getDepth() != 0)
throw new ParserException("Unbalanced brackets.");
}
public int getDepth() {
return types.size();
}
}
}