/** * 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; }
/** * 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; }