// supports 8 different character classes sclass JSONSpecialIntegral { int minLevel = 1, maxLevel = 8; byte[] input; int[] bracketLevel; // diff +1 for opening bracket, diff -1 for closing bracket int[] bracketCount; // diff +1 for any bracket byte[] quotesBitSet; // is character within string? (byte[] = faster replacement for BitSet) *() {} *(byte[] *input) {} void analyze(S input) { this.input = toUtf8(input); // XXX probably wrong analyze(); } void analyze(byte[] input) { this.input = input; analyze(); } void analyze { byte[] input = this.input; int n = input.length; bracketLevel = new int[n]; bracketCount = new int[n]; quotesBitSet = byteArrayBitSet_new(n); int bracketLvl = 0, bracketCnt = 0; bool inQuotes; for i to n: { byte b = input[i]; if (isOpener(b)) { if (!inQuotes) { ++bracketLvl; ++bracketCnt; } } else if (isCloser(b)) { if (!inQuotes) { --bracketLvl; ++bracketCnt; } } else if (inQuotes && b == '\'') { bracketLevel[i] = bracketLvl; bracketCount[i] = bracketCnt; setBit(quotesBitSet, i, inQuotes); i++; } else if (b == '"') { inQuotes = !inQuotes; } ifdef JSONSpecialIntegral_debug printVars(+i, +b, c := (char) b, +bracketLvl, +bracketCnt, +inQuotes); endifdef bracketLevel[i] = bracketLvl; bracketCount[i] = bracketCnt; setBit(quotesBitSet, i, inQuotes); } } int bracketLevel(int idx) { if (idx < 0) ret 0; ret bracketLevel[min(bracketLevel.length-1, idx)]; } int bracketCount(int idx) { if (idx < 0) ret 0; ret bracketCount[min(bracketLevel.length-1, idx)]; } bool inQuoteBit(int idx) { ret getBit(quotesBitSet, idx); } bool isOpener(byte b) { ret b == (byte) '{' || b == (byte) '['; } bool isCloser(byte b) { ret b == (byte) '}' || b == (byte) ']'; } S stats() { ret renderVars( inputLength := l(input), sizeFactor := formatDouble((elementSize(bracketLevel)+elementSize(bracketCount)+1/8.0), 2); } int n() { ret input.length; } }