in pgjdbc/src/main/java/org/postgresql/util/PGtokenizer.java [64:130]
public int tokenize(String string, char delim) {
tokens.clear();
final Deque<Character> stack = new ArrayDeque<>();
// stack keeps track of the levels we are in the current token.
// if stack.size is > 0 then we don't split a token when delim is matched.
//
// The Geometric datatypes use this, because often a type may have others
// (usually PGpoint) embedded within a token.
//
// Peter 1998 Jan 6 - Added < and > to the nesting rules
int p;
int s;
boolean skipChar = false;
boolean nestedDoubleQuote = false;
char c = (char)0;
for (p = 0, s = 0; p < string.length(); p++) {
c = string.charAt(p);
// increase nesting if an open character is found
if (c == '(' || c == '[' || c == '<' || (!nestedDoubleQuote && !skipChar && c == '"')) {
stack.push(c);
if (c == '"') {
nestedDoubleQuote = true;
skipChar = true;
}
}
// decrease nesting if a close character is found
if (c == ')' || c == ']' || c == '>' || (nestedDoubleQuote && !skipChar && c == '"')) {
if (c == '"') {
while (!stack.isEmpty() && !Character.valueOf('"').equals(stack.peek())) {
stack.pop();
}
nestedDoubleQuote = false;
stack.pop();
} else {
final Character ch = CLOSING_TO_OPENING_CHARACTER.get(c);
if (!stack.isEmpty() && ch != null && ch.equals(stack.peek())) {
stack.pop();
}
}
}
skipChar = c == '\\';
if (stack.isEmpty() && c == delim) {
tokens.add(string.substring(s, p));
s = p + 1; // +1 to skip the delimiter
}
}
// Don't forget the last token ;-)
if (s < string.length()) {
tokens.add(string.substring(s));
}
// check for last token empty
if ( s == string.length() && c == delim) {
tokens.add("");
}
return tokens.size();
}