2
// for the ease to check CDATA starting tag3
private static final char[] CDATA_TAG = {'[', 'C', 'D', 'A', 'T', 'A', '['};5
public boolean isValid(String code) {6
// make sure it is possible to have a start tag and an end tag7
if (!code.startsWith("<") || !code.endsWith(">")) {10
Deque<String> stack = new ArrayDeque<>();11
for (int i = 0; i < code.length(); ++i) {12
char ch = code.charAt(i);13
// if it is a special tag15
if (i == code.length() - 1) {18
ch = code.charAt(++i);21
// we should have a start tag to match the end tag22
if (stack.isEmpty()) {26
StringBuilder sb = new StringBuilder();27
// build tag and move i to the > for the next round28
i = buildTag(code, i + 1, sb);29
// if tag is unmatch, return false30
if (!stack.pop().equals(sb.toString())) {33
// if no start tag left and we are not at the end. The rest content is not enclosed. ->35
if (stack.isEmpty() && i < code.length() - 1) {38
} else if (ch == '!') { // is CDATA tag39
// check if CDATA is encoded in a tag40
if (stack.isEmpty()) {43
// check CDATA and move i to the end of ]]> for the next round44
i = validAndMoveCDATA(code, i + 1);45
// the above function return -1 if CDATA is not valid50
// TAG_NAME should not empty54
StringBuilder sb = new StringBuilder();55
i = buildTag(code, i, sb);56
// TAG_NAME should less than 957
if (sb.isEmpty() || sb.length() > 9) {60
stack.push(sb.toString());64
return stack.isEmpty();67
private int buildTag(String code, int start, StringBuilder sb) {69
// we only go to 10 because the max length is 970
for (; i < start + 10 && i < code.length(); ++i) {71
char ch = code.charAt(i);76
// TAG_NAME should be in uppercase only77
if (!Character.isUpperCase(ch)) {78
// clear the string builder for invalid TAG_NAME87
private int validAndMoveCDATA(String code, int start) {88
// the length of [CDATA[]]> is 10 we need at least 10 characters left89
if (code.length() - start < 10) {92
// check the start part94
for (int j = 0; j < CDATA_TAG.length; ++j) {95
char ch = code.charAt(i++);96
if (ch != CDATA_TAG[j]) {100
// keep the last two characters for identifying the end104
for (; i < code.length(); ++i) {105
char ch = code.charAt(i);106
if (ch == '>' && prev1 == ']' && prev0 == ']') {