示例#1
0
 /**
  * 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();
   }
 }
示例#2
0
 /**
  * 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);
 }
示例#3
0
 /**
  * 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();
   }
 }
 /**
  * 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();
 }
示例#5
0
 /**
  * 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();
 }
示例#6
0
 @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();
 }
示例#7
0
  /**
   * 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;
  }
示例#8
0
 /**
  * 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);
   }
 }
示例#9
0
 /**
  * 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();
 }
示例#10
0
  /**
   * 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();
  }
示例#11
0
  /**
   * Compares results.
   *
   * @param expected expected result
   * @param returned returned result
   * @throws Exception exception
   */
  private static void compare(final ItemList expected, final ItemList returned) throws Exception {

    // Compare response with expected result
    assertEquals("Different number of results", expected.size(), returned.size());

    final long es = expected.size();
    for (int e = 0; e < es; e++) {
      final Item exp = expected.get(e), ret = returned.get(e);
      if (!new DeepEqual().equal(exp, ret)) {
        final TokenBuilder tb = new TokenBuilder("Result ").addLong(e).add(" differs:\nReturned: ");
        tb.addExt(ret.serialize()).add("\nExpected: ").addExt(exp.serialize());
        fail(tb.toString());
      }
    }
  }
示例#12
0
  /**
   * 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);
  }
示例#13
0
 /**
  * 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);
 }
示例#14
0
 /**
  * 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);
 }
示例#15
0
  /**
   * Performs a test on the specified data.
   *
   * @param data data to be tested
   * @throws IOException I/O exception
   */
  private static void run(final byte[] data) throws IOException {
    final TokenBuilder tb = new TokenBuilder();
    final TextInput ti = new TextInput(new IOContent(data));
    ti.read();
    ti.reset();

    for (int b; (b = ti.read()) != -1; ) tb.add(b);
    try {
      ti.reset();
      assertTrue(
          "Mark should not be supported for data size of " + data.length,
          data.length < IO.BLOCKSIZE);
      tb.reset();
      for (int b; (b = ti.read()) != -1; ) tb.add(b);
      assertSame(data, tb.finish());
    } catch (final IOException ex) {
      assertTrue(
          "Mark could not be reset for data size of " + data.length, data.length >= IO.BLOCKSIZE);
    }
  }
示例#16
0
 /**
  * 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;
   }
 }
示例#17
0
 /**
  * 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);
   }
 }
示例#18
0
 /**
  * Scans a document encoding.
  *
  * @return encoding
  * @throws IOException I/O exception
  */
 private String encoding() throws IOException {
   if (!consume(ENCOD)) {
     if (fragment) error(TEXTENC);
     return null;
   }
   s();
   check('=');
   s();
   final TokenBuilder enc = new TokenBuilder();
   final int d = qu();
   int ch = nextChar();
   if (letter(ch) && ch != '_') {
     while (letterOrDigit(ch) || ch == '.' || ch == '-') {
       enc.add(ch);
       ch = nextChar();
     }
     prev(1);
   }
   check((char) d);
   if (enc.isEmpty()) error(DECLENCODE, enc);
   final String e = string(enc.finish());
   input.encoding(e);
   return e;
 }
示例#19
0
  /**
   * 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;
  }
示例#20
0
 /**
  * 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();
 }
示例#21
0
  /**
   * Reads and interprets the next token from the input stream.
   *
   * @return true if the document scanning has been completed
   * @throws IOException I/O exception
   */
  boolean more() throws IOException {
    // gets next character from the input stream
    token.reset();
    final int ch = consume();
    if (ch == 0) {
      type = Type.EOF;
      return false;
    }

    // checks the scanner state
    switch (state) {
      case CONTENT:
        scanCONTENT(ch);
        break;
      case TAG:
      case ATT:
        scanTAG(ch);
        break;
      case QUOTE:
        scanATTVALUE(ch);
    }
    return true;
  }
示例#22
0
  /**
   * Converts to HANKAKU characters.
   *
   * @param text Japanese text
   * @return result of conversion(->HANKAKU)
   */
  private static byte[] toHankaku(final byte[] text) {
    if (ascii(text)) return text;

    final int tl = text.length;
    final TokenBuilder tb = new TokenBuilder(tl);
    for (int t = 0; t < tl; t += cl(text, t)) {
      final int c = cp(text, t);
      if (c >= 0xFF10 && c <= 0xFF19 || c >= 0xFF21 && c <= 0xFF3A || c >= 0xFF41 && c <= 0xFF5A) {
        tb.add(c - 0xFEE0);
      } else if (c == 0x3000) { // IDEOGRAPHIC SPACE
        tb.add(0x0020);
      } else if (c == 0xFF01) { // !
        tb.add(0x0021);
      } else if (c == 0xFF02) { // " FULLWIDTH QUOTATION MARK
        tb.add(0x0022);
      } else if (c == 0x201C) { // " LEFT DOUBLE QUOTATION MARK
        tb.add(0x0022);
      } else if (c == 0x201D) { // " RIGHT DOUBLE QUOTATION MARK
        tb.add(0x0022);
      } else if (c == 0xFF03) { // #
        tb.add(0x0023);
      } else if (c == 0xFF04) { // $
        tb.add(0x0024);
      } else if (c == 0xFF05) { // %
        tb.add(0x0025);
      } else if (c == 0xFF06) { // &
        tb.add(0x0026);
      } else if (c == 0xFF07) { // ' FULLWIDTH APOSTROPHE
        tb.add(0x0027);
      } else if (c == 0x2018) { // ' LEFT SINGLE QUOTATION MARK
        tb.add(0x0027);
      } else if (c == 0x2019) { // ' RIGHT SINGLE QUOTATION MARK
        tb.add(0x0027);
      } else if (c == 0xFF08) { // (
        tb.add(0x0028);
      } else if (c == 0xFF09) { // )
        tb.add(0x0029);
      } else if (c == 0xFF0A) { // *
        tb.add(0x002A);
      } else if (c == 0xFF0B) { // +
        tb.add(0x002B);
      } else if (c == 0xFF0C) { // ,
        tb.add(0x002C);
      } else if (c == 0xFF0D) { // -
        tb.add(0x002D);
      } else if (c == 0xFF0E) { // .
        tb.add(0x002E);
      } else if (c == 0xFF0F) { // /
        tb.add(0x002F);
      } else if (c == 0xFF1A) { // :
        tb.add(0x003A);
      } else if (c == 0xFF1B) { // ;
        tb.add(0x003B);
      } else if (c == 0xFF1C) { // <
        tb.add(0x003C);
      } else if (c == 0xFF1D) { // =
        tb.add(0x003D);
      } else if (c == 0xFF1E) { // >
        tb.add(0x003E);
      } else if (c == 0xFF1F) { // ?
        tb.add(0x003F);
      } else if (c == 0xFF20) { // @
        tb.add(0x0040);
      } else if (c == 0xFF3B) { // [
        tb.add(0x005B);
      } else if (c == 0xFFE5) { // \
        tb.add(0x005C);
      } else if (c == 0xFF3D) { // ]
        tb.add(0x005D);
      } else if (c == 0xFF3E) { // ^
        tb.add(0x005E);
      } else if (c == 0xFF3F) { // _
        tb.add(0x005F);
      } else if (c == 0xFF40) { // `
        tb.add(0x0060);
      } else if (c == 0xFF5B) { // {
        tb.add(0x007B);
      } else if (c == 0xFF5C) { // |
        tb.add(0x007C);
      } else if (c == 0xFF5D) { // }
        tb.add(0x007D);
      } else if (c == 0xFF5E) { // ~
        tb.add(0x007E);
      } else {
        tb.add(c);
      }
    }
    return tb.finish();
  }
示例#23
0
  /**
   * Reads the configuration file and initializes the project properties. The file is located in the
   * project home directory.
   *
   * @param prop property file extension
   */
  protected synchronized void read(final String prop) {
    file = new IOFile(HOME + IO.BASEXSUFFIX + prop);

    final StringList read = new StringList();
    final TokenBuilder err = new TokenBuilder();
    if (!file.exists()) {
      err.addExt("Saving properties in \"%\"..." + NL, file);
    } else {
      BufferedReader br = null;
      try {
        br = new BufferedReader(new FileReader(file.file()));
        for (String line; (line = br.readLine()) != null; ) {
          line = line.trim();
          if (line.isEmpty() || line.charAt(0) == '#') continue;
          final int d = line.indexOf('=');
          if (d < 0) {
            err.addExt("%: \"%\" ignored. " + NL, file, line);
            continue;
          }

          final String val = line.substring(d + 1).trim();
          String key = line.substring(0, d).trim();

          // extract numeric value in key
          int num = 0;
          final int ss = key.length();
          for (int s = 0; s < ss; ++s) {
            if (Character.isDigit(key.charAt(s))) {
              num = Integer.parseInt(key.substring(s));
              key = key.substring(0, s);
              break;
            }
          }
          read.add(key);

          final Object entry = props.get(key);
          if (entry == null) {
            err.addExt("%: \"%\" not found. " + NL, file, key);
          } else if (entry instanceof String) {
            props.put(key, val);
          } else if (entry instanceof Integer) {
            props.put(key, Integer.parseInt(val));
          } else if (entry instanceof Boolean) {
            props.put(key, Boolean.parseBoolean(val));
          } else if (entry instanceof String[]) {
            if (num == 0) {
              props.put(key, new String[Integer.parseInt(val)]);
            } else {
              ((String[]) entry)[num - 1] = val;
            }
          } else if (entry instanceof int[]) {
            ((int[]) entry)[num] = Integer.parseInt(val);
          }
        }
      } catch (final Exception ex) {
        err.addExt("% could not be parsed." + NL, file);
        Util.debug(ex);
      } finally {
        if (br != null)
          try {
            br.close();
          } catch (final IOException ex) {
          }
      }
    }

    // check if all mandatory files have been read
    try {
      if (err.isEmpty()) {
        boolean ok = true;
        for (final Field f : getClass().getFields()) {
          final Object obj = f.get(null);
          if (!(obj instanceof Object[])) continue;
          final String key = ((Object[]) obj)[0].toString();
          ok &= read.contains(key);
        }
        if (!ok) err.addExt("Saving properties in \"%\"..." + NL, file);
      }
    } catch (final IllegalAccessException ex) {
      Util.notexpected(ex);
    }

    if (!err.isEmpty()) {
      Util.err(err.toString());
      write();
    }
  }