示例#1
0
  /**
   * Algorithm of Tarjan for computing the strongly connected components of a graph.
   *
   * @param v current node
   * @throws QueryException if a variable directly calls itself
   */
  private void tarjan(final int v) throws QueryException {
    final int ixv = 2 * v, llv = ixv + 1, idx = next++;
    while (list.size() <= llv) list.add(-1);
    list.set(ixv, idx);
    list.set(llv, idx);

    stack.push(v);

    for (final int w : adjacentTo(v)) {
      final int ixw = 2 * w, llw = ixw + 1;
      if (list.size() <= ixw || list.get(ixw) < 0) {
        // Successor w has not yet been visited; recurse on it
        tarjan(w);
        list.set(llv, Math.min(list.get(llv), list.get(llw)));
      } else if (stack.contains(w)) {
        // Successor w is in stack S and hence in the current SCC
        list.set(llv, Math.min(list.get(llv), list.get(ixw)));
      }
    }

    // If v is a root node, pop the stack and generate an SCC
    if (list.get(llv) == list.get(ixv)) {
      int w;
      Scope[] out = null;
      do {
        w = stack.pop();
        final Scope scp = scopes.get(w);
        out = out == null ? new Scope[] {scp} : Array.add(out, scp);
      } while (w != v);
      result.add(out);
    }
  }
示例#2
0
  @Override
  public DiskData build() throws IOException {
    meta.assign(parser);
    meta.dirty = true;

    // calculate optimized output buffer sizes to reduce disk fragmentation
    final Runtime rt = Runtime.getRuntime();
    final long max = Math.min(1 << 22, rt.maxMemory() - rt.freeMemory() >> 2);
    int bs = (int) Math.min(meta.filesize, max);
    bs = Math.max(IO.BLOCKSIZE, bs - bs % IO.BLOCKSIZE);

    // drop old database (if available) and create new one
    DropDB.drop(dbname, sopts);
    sopts.dbpath(dbname).md();

    elemNames = new Names(meta);
    attrNames = new Names(meta);
    try {
      tout = new DataOutput(new TableOutput(meta, DATATBL));
      xout = new DataOutput(meta.dbfile(DATATXT), bs);
      vout = new DataOutput(meta.dbfile(DATAATV), bs);
      sout = new DataOutput(meta.dbfile(DATATMP), bs);

      final Performance perf = Prop.debug ? new Performance() : null;
      Util.debug(tit() + DOTS);
      parse();
      if (Prop.debug) Util.errln(" " + perf + " (" + Performance.getMemory() + ')');

    } catch (final IOException ex) {
      try {
        close();
      } catch (final IOException ignored) {
      }
      throw ex;
    }
    close();

    // copy temporary values into database table
    try (final DataInput in = new DataInput(meta.dbfile(DATATMP))) {
      final TableAccess ta = new TableDiskAccess(meta, true);
      for (; spos < ssize; ++spos) ta.write4(in.readNum(), 8, in.readNum());
      ta.close();
    }
    meta.dbfile(DATATMP).delete();

    // return database instance
    return new DiskData(meta, elemNames, attrNames, path, ns);
  }
示例#3
0
  /**
   * Adds an element entry to the internal update buffer.
   *
   * @param dist parent distance
   * @param name tag name index
   * @param asize number of attributes
   * @param size node size
   * @param uri namespace uri reference
   * @param ne namespace flag
   */
  public final void elem(
      final int dist,
      final int name,
      final int asize,
      final int size,
      final int uri,
      final boolean ne) {

    // build and insert new entry
    final int i = newID();
    final int n = ne ? 1 << 7 : 0;
    s(Math.min(IO.MAXATTS, asize) << 3 | ELEM);
    s(n | (byte) (name >> 8));
    s(name);
    s(uri);
    s(dist >> 24);
    s(dist >> 16);
    s(dist >> 8);
    s(dist);
    s(size >> 24);
    s(size >> 16);
    s(size >> 8);
    s(size);
    s(i >> 24);
    s(i >> 16);
    s(i >> 8);
    s(i);
  }
示例#4
0
  /**
   * Adds an attribute entry to the internal update buffer.
   *
   * @param pre pre value
   * @param dist parent distance
   * @param name attribute name
   * @param value attribute value
   * @param uri namespace uri reference
   * @param ne namespace flag
   */
  public final void attr(
      final int pre,
      final int dist,
      final int name,
      final byte[] value,
      final int uri,
      final boolean ne) {

    // add attribute to text storage
    final int i = newID();
    final long v = index(pre, i, value, ATTR);
    final int n = ne ? 1 << 7 : 0;
    s(Math.min(IO.MAXATTS, dist) << 3 | ATTR);
    s(n | (byte) (name >> 8));
    s(name);
    s(v >> 32);
    s(v >> 24);
    s(v >> 16);
    s(v >> 8);
    s(v);
    s(0);
    s(0);
    s(0);
    s(uri);
    s(i >> 24);
    s(i >> 16);
    s(i >> 8);
    s(i);
  }
示例#5
0
  @Override
  public void keyTyped(final KeyEvent e) {
    if (undo == null || control(e) || DELNEXT.is(e) || DELPREV.is(e) || ESCAPE.is(e)) return;

    text.pos(text.cursor());
    // string to be added
    String ch = String.valueOf(e.getKeyChar());

    // remember if marked text is to be deleted
    boolean del = true;
    final byte[] txt = text.text();
    if (TAB.is(e)) {
      if (text.marked()) {
        // check if lines are to be indented
        final int s = Math.min(text.pos(), text.start());
        final int l = Math.max(text.pos(), text.start()) - 1;
        for (int p = s; p <= l && p < txt.length; p++) del &= txt[p] != '\n';
        if (!del) {
          text.indent(s, l, e.isShiftDown());
          ch = null;
        }
      } else {
        boolean c = true;
        for (int p = text.pos() - 1; p >= 0 && c; p--) {
          final byte b = txt[p];
          c = ws(b);
          if (b == '\n') break;
        }
        if (c) ch = "  ";
      }
    }

    // delete marked text
    if (text.marked() && del) text.delete();

    if (ENTER.is(e)) {
      // adopt indentation from previous line
      final StringBuilder sb = new StringBuilder(1).append(e.getKeyChar());
      int s = 0;
      for (int p = text.pos() - 1; p >= 0; p--) {
        final byte b = txt[p];
        if (b == '\n') break;
        if (b == '\t') {
          s += 2;
        } else if (b == ' ') {
          s++;
        } else {
          s = 0;
        }
      }
      for (int p = 0; p < s; p++) sb.append(' ');
      ch = sb.toString();
    }

    if (ch != null) text.add(ch);
    text.setCaret();
    rend.calc();
    showCursor(2);
    e.consume();
  }
示例#6
0
  @Override
  public void keyTyped(final KeyEvent e) {
    if (!hist.active()
        || control(e)
        || DELNEXT.is(e)
        || DELPREV.is(e)
        || ESCAPE.is(e)
        || CUT2.is(e)) return;

    final int caret = editor.pos();

    // remember if marked text is to be deleted
    final StringBuilder sb = new StringBuilder(1).append(e.getKeyChar());
    final boolean indent = TAB.is(e) && editor.indent(sb, e.isShiftDown());

    // delete marked text
    final boolean selected = editor.selected() && !indent;
    if (selected) editor.delete();

    final int move = ENTER.is(e) ? editor.enter(sb) : editor.add(sb, selected);

    // refresh history and adjust cursor position
    hist.store(editor.text(), caret, editor.pos());
    if (move != 0) editor.pos(Math.min(editor.size(), caret + move));

    // adjust text height
    scrollCode.invokeLater(true);
    e.consume();
  }
示例#7
0
  @Override
  public Value value(final QueryContext qc) throws QueryException {
    final FItem getKey = checkArity(exprs[1], 1, qc);
    final long k = Math.min(toLong(exprs[2], qc), Integer.MAX_VALUE);
    if (k < 1) return Empty.SEQ;

    final Iter iter = exprs[0].iter(qc);
    final MinHeap<Item, Item> heap =
        new MinHeap<>(
            new Comparator<Item>() {
              @Override
              public int compare(final Item it1, final Item it2) {
                try {
                  return OpV.LT.eval(it1, it2, sc.collation, sc, info) ? -1 : 1;
                } catch (final QueryException qe) {
                  throw new QueryRTException(qe);
                }
              }
            });

    try {
      for (Item it; (it = iter.next()) != null; ) {
        heap.insert(checkNoEmpty(getKey.invokeItem(qc, info, it)), it);
        if (heap.size() > k) heap.removeMin();
      }
    } catch (final QueryRTException ex) {
      throw ex.getCause();
    }

    final ValueBuilder vb = new ValueBuilder();
    while (!heap.isEmpty()) vb.addFront(heap.removeMin());
    return vb.value();
  }
示例#8
0
 /**
  * Fill the current buffer with bytes from the specified array from the specified offset.
  *
  * @param s source array
  * @param o offset from the beginning of the array
  * @return number of written bytes
  */
 private int write(final byte[] s, final int o) {
   final Buffer bf = bm.current();
   final int len = Math.min(IO.BLOCKSIZE, s.length - o);
   System.arraycopy(s, o, bf.data, 0, len);
   bf.dirty = true;
   return len;
 }
示例#9
0
 /**
  * Finds line and column for the specified query parser.
  *
  * @param parser parser
  */
 void pos(final InputParser parser) {
   markedCol = parser.mark;
   if (info != null) return;
   // check if line/column information has already been added
   parser.pos = Math.min(parser.mark, parser.length);
   info = new InputInfo(parser);
 }
示例#10
0
文件: FTIndex.java 项目: fpapai/basex
  /**
   * Performs a wildcard search for the specified token.
   *
   * @param token token to look for
   * @return iterator
   */
  private synchronized IndexIterator wc(final byte[] token) {
    final FTIndexIterator it = FTIndexIterator.FTEMPTY;
    final FTWildcard wc = new FTWildcard(token);
    if (!wc.parse()) return it;

    final IntList pr = new IntList();
    final IntList ps = new IntList();
    final byte[] pref = wc.prefix();
    final int pl = pref.length, tl = tp.length;
    final int l = Math.min(tl - 1, wc.max());
    for (int ti = pl; ti <= l; ti++) {
      int i = tp[ti];
      if (i == -1) continue;
      int c = ti + 1;
      int e = -1;
      while (c < tl && e == -1) e = tp[c++];
      i = find(pref, i, e, ti);

      while (i < e) {
        final byte[] t = inY.readBytes(i, ti);
        if (!startsWith(t, pref)) break;
        if (wc.match(t)) {
          inZ.cursor(pointer(i, ti));
          final int s = size(i, ti);
          for (int d = 0; d < s; d++) {
            pr.add(inZ.readNum());
            ps.add(inZ.readNum());
          }
        }
        i += ti + ENTRY;
      }
    }
    return iter(new FTCache(pr, ps), token);
  }
示例#11
0
  /**
   * Returns a pre value.
   *
   * @param id unique node id
   * @return pre value or -1 if id was not found
   */
  final int preold(final int id) {
    // find pre value in table
    for (int p = Math.max(0, id); p < meta.size; ++p) if (id == id(p)) return p;
    final int ps = Math.min(meta.size, id);
    for (int p = 0; p < ps; ++p) if (id == id(p)) return p;

    // id not found
    return -1;
  }
示例#12
0
文件: ADate.java 项目: jefferya/basex
  /**
   * Adds/subtracts the specified yearMonth duration.
   *
   * @param dur duration
   * @param plus plus/minus flag
   * @param ii input info
   * @throws QueryException query exception
   */
  final void calc(final YMDur dur, final boolean plus, final InputInfo ii) throws QueryException {
    final long m = plus ? dur.mon : -dur.mon;
    final long mn = mon + m;
    mon = (byte) mod(mn, 12);
    yea += div(mn, 12);
    day = (byte) Math.min(dpm(yea, mon) - 1, day);

    if (yea <= MIN_YEAR || yea > MAX_YEAR) throw YEARRANGE_X.get(ii, yea);
  }
示例#13
0
  @Override
  public final void mouseDragged(final MouseEvent e) {
    if (!SwingUtilities.isLeftMouseButton(e)) return;

    // selection mode
    select(e.getPoint(), false);
    final int y = Math.max(20, Math.min(e.getY(), getHeight() - 20));
    if (y != e.getY()) scroll.pos(scroll.pos() + e.getY() - y);
  }
示例#14
0
 /**
  * Draws a visualization tooltip.
  *
  * @param g graphics reference
  * @param tt tooltip label
  * @param x horizontal position
  * @param y vertical position
  * @param w width
  * @param c color color depth
  */
 public static void drawTooltip(
     final Graphics g, final String tt, final int x, final int y, final int w, final int c) {
   final int tw = width(g, tt);
   final int th = g.getFontMetrics().getHeight();
   final int xx = Math.min(w - tw - 8, x);
   g.setColor(color(c));
   g.fillRect(xx - 1, y - th, tw + 4, th);
   g.setColor(BACK);
   g.drawString(tt, xx, y - 4);
 }
示例#15
0
文件: FTIndex.java 项目: fpapai/basex
  /**
   * Performs a fuzzy search for the specified token with a maximum number of errors.
   *
   * @param token token to look for
   * @param k number of errors allowed
   * @return iterator
   */
  private synchronized IndexIterator fuzzy(final byte[] token, final int k) {
    FTIndexIterator it = FTIndexIterator.FTEMPTY;
    final int tokl = token.length, tl = tp.length;
    final int e = Math.min(tl - 1, tokl + k);
    int s = Math.max(1, tokl - k) - 1;

    while (++s <= e) {
      int p = tp[s];
      if (p == -1) continue;
      int t = s + 1, r = -1;
      while (t < tl && r == -1) r = tp[t++];
      while (p < r) {
        if (ls.similar(inY.readBytes(p, s), token, k)) {
          it = FTIndexIterator.union(iter(pointer(p, s), size(p, s), inZ, token), it);
        }
        p += s + ENTRY;
      }
    }
    return it;
  }
示例#16
0
  /**
   * Inserts a data instance at the specified pre value. Note that the specified data instance must
   * differ from this instance.
   *
   * @param ipre value at which to insert new data
   * @param ipar parent pre value of node
   * @param clip data clip
   */
  public final void insert(final int ipre, final int ipar, final DataClip clip) {
    meta.update();

    // update value and document indexes
    if (meta.updindex) indexBegin();
    resources.insert(ipre, clip);

    final int dsize = clip.size();
    final int buf = Math.min(dsize, IO.BLOCKSIZE >> IO.NODEPOWER);
    // resize buffer to cache more entries
    buffer(buf);

    // find all namespaces in scope to avoid duplicate declarations
    final TokenMap nsScope = nspaces.scope(ipar, this);

    // loop through all entries
    final IntList preStack = new IntList();
    final NSNode nsRoot = nspaces.current();
    final HashSet<NSNode> newNodes = new HashSet<NSNode>();
    final IntList flagPres = new IntList();

    // indicates if database only contains a dummy node
    final Data data = clip.data;
    int c = 0;
    for (int dpre = clip.start; dpre < clip.end; ++dpre, ++c) {
      if (c != 0 && c % buf == 0) insert(ipre + c - buf);

      final int pre = ipre + c;
      final int dkind = data.kind(dpre);
      final int dpar = data.parent(dpre, dkind);
      // ipar < 0 if document nodes on top level are added
      final int dis = dpar >= 0 ? dpre - dpar : ipar >= 0 ? pre - ipar : 0;
      final int par = dis == 0 ? -1 : pre - dis;

      if (c == 0) nspaces.root(par, this);

      while (!preStack.isEmpty() && preStack.peek() > par) nspaces.close(preStack.pop());

      switch (dkind) {
        case DOC:
          // add document
          nspaces.prepare();
          final int s = data.size(dpre, dkind);
          doc(pre, s, data.text(dpre, true));
          meta.ndocs++;
          preStack.push(pre);
          break;
        case ELEM:
          // add element
          nspaces.prepare();
          boolean ne = false;
          if (data.nsFlag(dpre)) {
            final Atts at = data.ns(dpre);
            for (int a = 0; a < at.size(); ++a) {
              // see if prefix has been declared/ is part of current ns scope
              final byte[] old = nsScope.get(at.name(a));
              if (old == null || !eq(old, at.value(a))) {
                // we have to keep track of all new NSNodes that are added
                // to the Namespace structure, as their pre values must not
                // be updated. I.e. if an NSNode N with pre value 3 existed
                // prior to inserting and two new nodes are inserted at
                // location pre == 3 we have to make sure N and only N gets
                // updated.
                newNodes.add(nspaces.add(at.name(a), at.value(a), pre));
                ne = true;
              }
            }
          }
          byte[] nm = data.name(dpre, dkind);
          elem(
              dis,
              tagindex.index(nm, null, false),
              data.attSize(dpre, dkind),
              data.size(dpre, dkind),
              nspaces.uri(nm, true),
              ne);
          preStack.push(pre);
          break;
        case TEXT:
        case COMM:
        case PI:
          // add text
          text(pre, dis, data.text(dpre, true), dkind);
          break;
        case ATTR:
          // add attribute
          nm = data.name(dpre, dkind);
          // check if prefix already in nsScope or not
          final byte[] attPref = prefix(nm);
          // check if prefix of attribute has already been declared, otherwise
          // add declaration to parent node
          if (data.nsFlag(dpre) && nsScope.get(attPref) == null) {
            nspaces.add(
                par,
                preStack.isEmpty() ? -1 : preStack.peek(),
                attPref,
                data.nspaces.uri(data.uri(dpre, dkind)),
                this);
            // save pre value to set ns flag later for this node. can't be done
            // here as direct table access would interfere with the buffer
            flagPres.add(par);
          }
          attr(
              pre,
              dis,
              atnindex.index(nm, null, false),
              data.text(dpre, false),
              nspaces.uri(nm, false),
              false);
          break;
      }
    }
    // finalize and update namespace structure
    while (!preStack.isEmpty()) nspaces.close(preStack.pop());
    nspaces.root(nsRoot);

    if (bp != 0) insert(ipre + c - 1 - (c - 1) % buf);
    // reset buffer to old size
    buffer(1);

    // set ns flags
    for (int f = 0; f < flagPres.size(); f++) {
      final int fl = flagPres.get(f);
      table.write2(fl, 1, name(fl) | 1 << 15);
    }

    // increase size of ancestors
    int p = ipar;
    while (p >= 0) {
      final int k = kind(p);
      size(p, k, size(p, k) + dsize);
      p = parent(p, k);
    }

    if (meta.updindex) {
      // add the entries to the ID -> PRE mapping:
      idmap.insert(ipre, id(ipre), dsize);
      indexEnd();
    }

    if (!cache) updateDist(ipre + dsize, dsize);

    // propagate PRE value shifts to namespaces
    if (ipar != -1) nspaces.insert(ipre, dsize, newNodes);
  }
示例#17
0
 @Override
 void calcSize(final long[] minMax) {
   minMax[0] = Math.min(minMax[0], 1);
 }