final boolean isLegal(int codepoint, boolean escapeLow, int stripCodePoint, boolean isAttribute) {
            if (codepoint == stripCodePoint) {
                return removeCodePoint();
            } else if (codepoint < ' ') {
                if (!escapeLow) {
                    return true;
                }
                switch (codepoint) {
                    case 0x09:
                    case 0x0a:
                    case 0x0d:
                        return true;
                    default:
                        return ctrlEscapeCodePoint(codepoint);
                }
            } else if (codepoint >= 0x20 && codepoint <= 0xd7ff) {
                switch (codepoint) {
                    case '&':
                        return ampCodePoint();
                    case '<':
                        return ltCodePoint();
                    case '>':
                        return gtCodePoint();
                    case '"':
                        return quotCodePoint(isAttribute);
                    default:
                        return true;
                }
            } else if ((codepoint >= 0xe000 && codepoint <= 0xfffd)
                       || (codepoint >= 0x10000 && codepoint <= 0x10ffff)) {
                return true;
            } else {
                return filterCodePoint(codepoint);

            }
        }
The point of this weird class and the jumble of abstract methods is
linking the scan for characters that must be quoted into the quoting
table, and making it actual work to make them go out of sync again.
vespajlib/src/main/java/com/yahoo/text/XML.java