예제 #1
0
  /**
   * Adds an element to the end of the array.
   *
   * @param elem element to add
   * @return self reference for convenience
   */
  public ArrayBuilder append(final Value elem) {
    if (inRight < Array.MAX_DIGIT) {
      // just insert the element
      vals[(mid + inRight) % CAP] = elem;
      inRight++;
    } else if (tree.isEmpty() && inLeft < Array.MAX_DIGIT) {
      // move the middle to the right
      mid = (mid + 1) % CAP;
      vals[(mid + inRight + CAP - 1) % CAP] = elem;
      inLeft++;
    } else {
      // push leaf node into the tree
      final Value[] leaf = new Value[NODE_SIZE];
      final int start = mid;
      for (int i = 0; i < NODE_SIZE; i++) leaf[i] = vals[(start + i) % CAP];
      tree.append(new LeafNode(leaf));

      // move rest of the nodes to the right
      final int rest = inRight - NODE_SIZE;
      for (int i = 0; i < rest; i++) {
        final int to = (mid + i) % CAP, from = (to + NODE_SIZE) % CAP;
        vals[to] = vals[from];
      }

      // insert the element
      vals[(mid + rest) % CAP] = elem;
      inRight = rest + 1;
    }
    return this;
  }
예제 #2
0
  /**
   * Appends the given array to this builder.
   *
   * @param arr array to append
   * @return self reference for convenience
   */
  public ArrayBuilder append(final Array arr) {
    if (!(arr instanceof BigArray)) {
      for (final Value val : arr.members()) append(val);
      return this;
    }

    final BigArray big = (BigArray) arr;
    final Value[] ls = big.left, rs = big.right;
    final FingerTree<Value, Value> midTree = big.middle;
    if (midTree.isEmpty()) {
      for (final Value l : big.left) append(l);
      for (final Value r : big.right) append(r);
      return this;
    }

    // merge middle digits
    if (tree.isEmpty()) {
      final int k = inLeft + inRight;
      final Value[] temp = new Value[k];
      final int l = (mid - inLeft + CAP) % CAP, m = CAP - l;
      if (k <= m) {
        System.arraycopy(vals, l, temp, 0, k);
      } else {
        System.arraycopy(vals, l, temp, 0, m);
        System.arraycopy(vals, 0, temp, m, k - m);
      }

      inLeft = inRight = 0;
      tree.append(midTree);
      for (int i = ls.length; --i >= 0; ) prepend(ls[i]);
      for (int i = k; --i >= 0; ) prepend(temp[i]);
      for (final Value r : rs) append(r);
      return this;
    }

    final int inMiddle = inRight + big.left.length,
        leaves = (inMiddle + Array.MAX_LEAF - 1) / Array.MAX_LEAF,
        leafSize = (inMiddle + leaves - 1) / leaves;
    for (int i = 0, l = 0; l < leaves; l++) {
      final int inLeaf = Math.min(leafSize, inMiddle - i);
      final Value[] leaf = new Value[inLeaf];
      for (int p = 0; p < inLeaf; p++) {
        leaf[p] = i < inRight ? vals[(mid + i) % CAP] : big.left[i - inRight];
        i++;
      }
      tree.append(new LeafNode(leaf));
    }

    tree.append(big.middle);
    inRight = 0;
    for (final Value r : big.right) append(r);
    return this;
  }
예제 #3
0
 @Override
 public String toString() {
   final StringBuilder sb = new StringBuilder(getClass().getSimpleName()).append('[');
   if (tree.isEmpty()) {
     final int n = inLeft + inRight, first = (mid - inLeft + CAP) % CAP;
     if (n > 0) {
       sb.append(vals[first]);
       for (int i = 1; i < n; i++) sb.append(", ").append(vals[(first + i) % CAP]);
     }
   } else {
     final int first = (mid - inLeft + CAP) % CAP;
     sb.append(vals[first]);
     for (int i = 1; i < inLeft; i++) sb.append(", ").append(vals[(first + i) % CAP]);
     for (final Value val : tree) sb.append(", ").append(val);
     for (int i = 0; i < inRight; i++) sb.append(", ").append(vals[(mid + i) % CAP]);
   }
   return sb.append(']').toString();
 }
예제 #4
0
  /**
   * Creates an {@link Array} containing the elements of this builder.
   *
   * @return resulting array
   */
  public Array freeze() {
    final int n = inLeft + inRight;
    if (n == 0) return Array.empty();

    final int start = (mid - inLeft + CAP) % CAP;
    if (n <= Array.MAX_SMALL) {
      // small int array, fill directly
      final Value[] small = new Value[n];
      for (int i = 0; i < n; i++) small[i] = vals[(start + i) % CAP];
      return new SmallArray(small);
    }

    // deep array
    final int a = tree.isEmpty() ? n / 2 : inLeft, b = n - a;
    final Value[] ls = new Value[a], rs = new Value[b];
    for (int i = 0; i < a; i++) ls[i] = vals[(start + i) % CAP];
    for (int i = a; i < n; i++) rs[i - a] = vals[(start + i) % CAP];
    return new BigArray(ls, tree.freeze(), rs);
  }