@Override public String toString() { final TokenBuilder tb = new TokenBuilder().add(var.toString()).add(' ').add(ASSIGN); tb.add(' ').add(expr.toString()); if (coll != null) tb.add(' ').add(COLLATION).add(" \"").add(coll.uri()).add('"'); return tb.toString(); }
/** * Scans an entity value. [9] * * @param p pe reference flag * @return value * @throws IOException I/O exception */ private byte[] entityValue(final boolean p) throws IOException { final int qu = consume(); if (qu != '\'' && qu != '"') { prev(1); return null; } TokenBuilder tok = new TokenBuilder(); int ch; while ((ch = nextChar()) != qu) { if (ch == '&') tok.add(ref(false)); else if (ch == '%') { if (!p) error(INVPE); tok.add(peRef()); } else { tok.add(ch); } } final XMLInput tmp = input; input = new XMLInput(new IOContent(tok.finish())); tok = new TokenBuilder(); while ((ch = consume()) != 0) { if (ch == '&') tok.add(ref(false)); else tok.add(ch); } input = tmp; return tok.finish(); }
/** * Joins the path. * * @param s segment to start with * @return joined path */ private String join(final int s) { final TokenBuilder tb = new TokenBuilder(); for (int p = s; p < segments.length; p++) { if (!tb.isEmpty()) tb.add('/'); tb.add(segments[p]); } return tb.toString(); }
@Override public String toString() { final TokenBuilder tb = new TokenBuilder(Util.className(this)).add('['); for (int i = 1; i < size; i++) { tb.add(Integer.toString(keys[i])).add(": ").addExt(get(keys[i])); if (i < size - 1) tb.add(",\n\t"); } return tb.add(']').toString(); }
/** * Returns the database path (i.e., all path entries except for the first). * * @return path depth */ public String dbpath() { final TokenBuilder tb = new TokenBuilder(); final int ps = segments.length; for (int p = 1; p < ps; p++) { if (!tb.isEmpty()) tb.add('/'); tb.add(segments[p]); } return tb.toString(); }
@Override public final synchronized String toString() { final TokenBuilder tb = new TokenBuilder(); for (final Entry<String, Object> e : props.entrySet()) { if (!tb.isEmpty()) tb.add(','); tb.add(e.getKey()).add('=').addExt(e.getValue()); } return tb.toString(); }
@Override public String toString() { final int es = expr.length; final TokenBuilder tb = new TokenBuilder(expr[es - 1].toString()).add('('); for (int e = 0; e < es - 1; e++) { tb.add(expr[e].toString()); if (e < es - 2) tb.add(", "); } return tb.add(')').toString(); }
/** * Adds the time zone to the specified token builder. * * @param tb token builder */ void zone(final TokenBuilder tb) { if (tz == Short.MAX_VALUE) return; if (tz == 0) { tb.add('Z'); } else { tb.add(tz > 0 ? '+' : '-'); prefix(tb, Math.abs(tz) / 60, 2); tb.add(':'); prefix(tb, Math.abs(tz) % 60, 2); } }
/** * Scans CDATA. * * @throws IOException I/O exception */ private void cDATA() throws IOException { int ch; while (true) { while ((ch = nextChar()) != ']') token.add(ch); if (consume(']')) { if (consume('>')) return; prev(1); } token.add(ch); } }
@Override public String getMessage() { final TokenBuilder tb = new TokenBuilder(); if (info != null) tb.add(STOPPED_AT).add(info.toString()).add(COL).add(NL); final byte[] code = name.local(); if (code.length != 0) tb.add('[').add(name.prefixId(QueryText.ERROR_URI)).add("] "); tb.add(getLocalizedMessage()); if (!stack.isEmpty()) { tb.add(NL).add(NL).add(STACK_TRACE).add(COL); for (final InputInfo ii : stack) tb.add(NL).add(LI).add(ii.toString()); } return tb.toString(); }
/** * Scans a reference. [67] * * @param f dissolve entities * @return entity * @throws IOException I/O exception */ private byte[] ref(final boolean f) throws IOException { // scans numeric entities if (consume('#')) { // [66] final TokenBuilder ent = new TokenBuilder(); int b = 10; int ch = nextChar(); ent.add(ch); if (ch == 'x') { b = 16; ent.add(ch = nextChar()); } int n = 0; do { final boolean m = ch >= '0' && ch <= '9'; final boolean h = b == 16 && (ch >= 'a' && ch <= 'f' || ch >= 'A' && ch <= 'F'); if (!m && !h) { completeRef(ent); return QUESTION; } n *= b; n += ch & 15; if (!m) n += 9; ent.add(ch = nextChar()); } while (ch != ';'); if (!valid(n)) return QUESTION; ent.reset(); ent.add(n); return ent.finish(); } // scans predefined entities [68] final byte[] name = name(false); if (!consume(';')) return QUESTION; if (!f) return concat(AMPER, name, SEMI); byte[] en = ents.get(name); if (en == null) { // unknown entity: try HTML entities (lazy initialization) if (HTMLENTS.size() == 0) { for (int s = 0; s < HTMLENTITIES.length; s += 2) { HTMLENTS.add(token(HTMLENTITIES[s]), token(HTMLENTITIES[s + 1])); } } en = HTMLENTS.get(name); } return en == null ? QUESTION : en; }
@Override public byte[] info(final MainOptions options) { final TokenBuilder tb = new TokenBuilder(); tb.add(LI_STRUCTURE).add(HASH).add(NL); tb.add(LI_NAMES).add(data.meta.names(type)).add(NL); final IndexStats stats = new IndexStats(options.get(MainOptions.MAXSTAT)); final int s = values.size(); for (int p = 1; p <= s; p++) { final int oc = lenList.get(p); if (oc > 0 && stats.adding(oc)) stats.add(values.key(p), oc); } stats.print(tb); return tb.finish(); }
/** * Returns an atomized content for any node kind. The atomized value can be an attribute value or * XML content. * * @param pre pre value * @return atomized value */ public final byte[] atom(final int pre) { switch (kind(pre)) { case TEXT: case COMM: return text(pre, true); case ATTR: return text(pre, false); case PI: byte[] txt = text(pre, true); final int i = indexOf(txt, ' '); return i == -1 ? EMPTY : substring(txt, i + 1); default: // create atomized text node TokenBuilder tb = null; byte[] t = EMPTY; int p = pre; final int s = p + size(p, kind(p)); while (p != s) { final int k = kind(p); if (k == TEXT) { txt = text(p, true); if (t == EMPTY) { t = txt; } else { if (tb == null) tb = new TokenBuilder(t); tb.add(txt); } } p += attSize(p, k); } return tb == null ? t : tb.finish(); } }
/** * Adds some characters to the entity. * * @param ent token builder * @throws IOException I/O exception */ private void completeRef(final TokenBuilder ent) throws IOException { int ch = consume(); while (ent.size() < 10 && ch >= ' ' && ch != ';') { ent.add(ch); ch = consume(); } }
/** * Scans a processing instruction. * * @throws IOException I/O exception */ private void pi() throws IOException { final byte[] tok = name(true); if (eq(lc(tok), XML)) error(PIRES); token.add(tok); int ch = nextChar(); if (ch != '?' && !ws(ch)) error(PITEXT); do { while (ch != '?') { token.add(ch); ch = nextChar(); } if ((ch = consume()) == '>') return; token.add('?'); } while (true); }
/** * Consumes an Nmtoken. [7] * * @throws IOException I/O exception */ private void nmtoken() throws IOException { final TokenBuilder name = new TokenBuilder(); int c; while (isChar(c = nextChar())) name.add(c); prev(1); if (name.isEmpty()) error(INVNAME); }
/** * Scans an attribute value. [10] * * @param ch current character * @throws IOException I/O exception */ private void attValue(final int ch) throws IOException { boolean wrong = false; int c = ch; do { if (c == 0) error(ATTCLOSE, (char) c); wrong |= c == '\'' || c == '"'; if (c == '<') error(wrong ? ATTCLOSE : ATTCHAR, (char) c); if (c == 0x0A) c = ' '; if (c == '&') { // verify... final byte[] r = ref(true); if (r.length == 1) token.add(r); else if (!input.add(r, false)) error(RECENT); } else { token.add(c); } } while ((c = consume()) != quote); }
/** * Replaces the specified character and returns the result token. * * @param token token to be checked * @param search the character to be replaced * @param replace the new character * @return resulting token */ public static byte[] replace(final byte[] token, final int search, final int replace) { final TokenBuilder tb = new TokenBuilder(token.length); final int tl = token.length; for (int i = 0; i < tl; i += cl(token, i)) { final int c = cp(token, i); tb.add(c == search ? replace : c); } return tb.finish(); }
/** * Scans an external ID. * * @param f full flag * @param r root flag * @return id * @throws IOException I/O exception */ private byte[] externalID(final boolean f, final boolean r) throws IOException { byte[] cont = null; final boolean pub = consume(PUBLIC); if (pub || consume(SYSTEM)) { checkS(); if (pub) { pubidLit(); if (f) checkS(); } final int qu = consume(); // [11] if (qu == '\'' || qu == '"') { int ch; final TokenBuilder tok = new TokenBuilder(); while ((ch = nextChar()) != qu) tok.add(ch); if (!f) return null; final String name = string(tok.finish()); if (!dtd && r) return cont; final XMLInput tin = input; try { final IO file = input.io().merge(name); cont = file.read(); } catch (final IOException ex) { Util.debug(ex); // skip unknown DTDs/entities cont = new byte[] {'?'}; } input = new XMLInput(new IOContent(cont, name)); if (consume(XDECL)) { check(XML); s(); if (version()) checkS(); s(); if (encoding() == null) error(TEXTENC); ch = nextChar(); if (s(ch)) ch = nextChar(); if (ch != '?') error(WRONGCHAR, '?', ch); ch = nextChar(); if (ch != '>') error(WRONGCHAR, '>', ch); cont = Arrays.copyOfRange(cont, input.pos(), cont.length); } s(); if (r) { extSubsetDecl(); if (!consume((char) 0)) error(INVEND); } input = tin; } else { if (f) error(SCANQUOTE, (char) qu); prev(1); } } return cont; }
/** * Scans a comment. * * @throws IOException I/O exception */ private void comment() throws IOException { do { final int ch = nextChar(); if (ch == '-' && consume('-')) { check('>'); return; } token.add(ch); } while (true); }
/** * Scans XML text. * * @param ch current character * @throws IOException I/O exception */ private void content(final int ch) throws IOException { type = Type.TEXT; boolean f = true; int c = ch; while (c != 0) { if (c != '<') { if (c == '&') { // scan entity final byte[] r = ref(true); if (r.length == 1) token.add(r); else if (!input.add(r, false)) error(RECENT); } else { if (c == ']') { // ']]>' not allowed in content if (consume() == ']') { if (consume() == '>') error(CONTCDATA); prev(1); } prev(1); } // add character to cached content token.add(c); } } else { if (!f && !isCDATA()) { text = false; prev(1); if (chop) token.trim(); return; } cDATA(); } c = consume(); f = false; } // end of file if (!fragment) { if (!ws(token.finish())) error(AFTERROOT); type = Type.EOF; } }
/** * Deletes the specified character from the token. * * @param token token * @param ch character to be removed * @return resulting token */ public static byte[] delete(final byte[] token, final int ch) { // skip step if specified ascii character is not contained if (ch < 0x80 && !contains(token, ch)) return token; // remove character final TokenBuilder tb = new TokenBuilder(token.length); final int tl = token.length; for (int i = 0; i < tl; i += cl(token, i)) { final int c = cp(token, i); if (c != ch) tb.add(c); } return tb.finish(); }
/** * Consumes an XML name. [5] * * @param f force parsing * @return name * @throws IOException I/O exception */ private byte[] name(final boolean f) throws IOException { final TokenBuilder name = new TokenBuilder(); int c = consume(); if (!isStartChar(c)) { if (f) error(INVNAME); prev(1); return null; } do name.add(c); while (isChar(c = nextChar())); prev(1); return name.finish(); }
/** * Converts a string to a UTF8 byte array. * * @param string string to be converted * @return byte array */ private static byte[] utf8(final String string) { final char[] arr = string.toCharArray(); final int al = arr.length; final TokenBuilder tb = new TokenBuilder(al << 1); for (int c = 0; c < al; ++c) { final char ch = arr[c]; tb.add( Character.isHighSurrogate(ch) && c < al - 1 && Character.isLowSurrogate(arr[c + 1]) ? Character.toCodePoint(ch, arr[++c]) : ch); } return tb.finish(); }
/** * Scans an XML tag. * * @param ch current character * @throws IOException I/O exception */ private void scanTAG(final int ch) throws IOException { int c = ch; // scan tag end... if (c == '>') { type = Type.R_BR; state = State.CONTENT; } else if (c == '=') { // scan equal sign... type = Type.EQ; } else if (c == '\'' || c == '"') { // scan quote... type = Type.QUOTE; state = State.QUOTE; quote = c; } else if (c == '/') { // scan empty tag end... type = Type.CLOSE_R_BR; if ((c = nextChar()) == '>') { state = State.CONTENT; } else { token.add(c); error(CLOSING); } } else if (s(c)) { // scan whitespace... type = Type.WS; } else if (isStartChar(c)) { // scan tag name... type = state == State.ATT ? Type.ATTNAME : Type.ELEMNAME; do token.add(c); while (isChar(c = nextChar())); prev(1); state = State.ATT; } else { // undefined character... error(CHARACTER, (char) c); } }
/** * Returns an information string for an unexpected exception. * * @param ex exception * @return dummy object */ public static String bug(final Throwable ex) { final TokenBuilder tb = new TokenBuilder(BUGINFO); tb.add(NL).add("Contact: ").add(MAIL); tb.add(NL).add("Version: ").add(TITLE); tb.add(NL).add("Java: ").add(System.getProperty("java.vendor")); tb.add(", ").add(System.getProperty("java.version")); tb.add(NL).add("OS: ").add(System.getProperty("os.name")); tb.add(", ").add(System.getProperty("os.arch")); tb.add(NL).add("Stack Trace: "); for (final String e : toArray(ex)) tb.add(NL).add(e); return tb.toString(); }
/** * Converts the path to a string array, containing the single segments. * * @param path path, or {@code null} * @return path depth */ public static String[] toSegments(final String path) { final StringList sl = new StringList(); if (path != null) { final TokenBuilder tb = new TokenBuilder(); for (int s = 0; s < path.length(); s++) { final char ch = path.charAt(s); if (ch == '/') { if (tb.isEmpty()) continue; sl.add(tb.toString()); tb.reset(); } else { tb.add(ch); } } if (!tb.isEmpty()) sl.add(tb.toString()); } return sl.toArray(); }
/** * Splits a token around matches of the given separator. * * @param token token to be split * @param sep separation character * @return array */ public static byte[][] split(final byte[] token, final int sep) { final int l = token.length; final byte[][] split = new byte[l][]; int s = 0; final TokenBuilder tb = new TokenBuilder(); for (int i = 0; i < l; i += cl(token, i)) { final int c = cp(token, i); if (c == sep) { if (!tb.isEmpty()) { split[s++] = tb.finish(); tb.reset(); } } else { tb.add(c); } } if (!tb.isEmpty()) split[s++] = tb.finish(); return Array.copyOf(split, s); }
@Override protected byte[] stem(final byte[] word) { int ln = 0; final int wl = word.length; final char[] s = new char[wl]; for (int i = 0; i < wl; i += Token.cl(word, i)) { s[ln++] = (char) Token.cp(word, i); } if (ln < 4) return word; final int olen = ln; // "short rules": if it hits one of these, it skips the "long list" int l = rule0(s, ln); l = rule1(s, l); l = rule2(s, l); l = rule3(s, l); l = rule4(s, l); l = rule5(s, l); l = rule6(s, l); l = rule7(s, l); l = rule8(s, l); l = rule9(s, l); l = rule10(s, l); l = rule11(s, l); l = rule12(s, l); l = rule13(s, l); l = rule14(s, l); l = rule15(s, l); l = rule16(s, l); l = rule17(s, l); l = rule18(s, l); l = rule19(s, l); l = rule20(s, l); if (l == olen) l = rule21(s, l); // "long list" l = rule22(s, l); final TokenBuilder tb = new TokenBuilder(l << 1); for (int i = 0; i < l; i++) tb.add(s[i]); return tb.finish(); }
/** * Returns a string representation of the index structure. * * @param all include database contents in the representation. During updates, database lookups * must be avoided, as the data structures will be inconsistent. * @return string */ public String toString(final boolean all) { final TokenBuilder tb = new TokenBuilder(); tb.addExt(type).add(" INDEX, '").add(data.meta.name).add("':\n"); final int s = lenList.size(); for (int m = 1; m < s; m++) { final int len = lenList.get(m); if (len == 0) continue; final int[] ids = idsList.get(m); tb.add(" ").addInt(m); if (all) tb.add(", key: \"").add(data.text(data.pre(ids[0]), type == IndexType.TEXT)).add('"'); tb.add(", ids"); if (all) tb.add("/pres"); tb.add(": "); for (int n = 0; n < len; n++) { if (n != 0) tb.add(","); tb.addInt(ids[n]); if (all) tb.add('/').addInt(data.pre(ids[n])); } tb.add("\n"); } return tb.toString(); }