Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
swim.collections.STreeLeaf Maven / Gradle / Ivy
Go to download
Immutable, structure sharing collections, including hash array mapped tries, finger tries, B-trees, and S-trees (sequence trees)
// Copyright 2015-2019 SWIM.AI inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package swim.collections;
import java.util.AbstractMap;
import java.util.Map;
import swim.util.Cursor;
final class STreeLeaf extends STreePage {
final Map.Entry[] slots;
STreeLeaf(Map.Entry[] slots) {
this.slots = slots;
}
@Override
public boolean isEmpty() {
return this.slots.length == 0;
}
@Override
public int size() {
return this.slots.length;
}
@Override
public int arity() {
return this.slots.length;
}
@Override
public boolean contains(Object value) {
final Map.Entry[] slots = this.slots;
for (int i = 0, n = slots.length; i < n; i += 1) {
if (value.equals(slots[i])) {
return true;
}
}
return false;
}
@Override
public int indexOf(Object value) {
final Map.Entry[] slots = this.slots;
for (int i = 0, n = slots.length; i < n; i += 1) {
if (value.equals(slots[i])) {
return i;
}
}
return -1;
}
@Override
public int lastIndexOf(Object value) {
final Map.Entry[] slots = this.slots;
for (int i = slots.length - 1; i >= 0; i -= 1) {
if (value.equals(slots[i])) {
return i;
}
}
return -1;
}
@Override
public T get(int index) {
final Map.Entry slot = this.slots[index];
if (slot != null) {
return slot.getValue();
} else {
return null;
}
}
@Override
public Map.Entry getEntry(int index) {
return this.slots[index];
}
@Override
public STreeLeaf updated(int index, T newValue, STreeContext tree) {
if (index < 0 || index >= this.slots.length) {
throw new IndexOutOfBoundsException(Integer.toString(index));
}
return updatedSlot(index, newValue);
}
@SuppressWarnings("unchecked")
private STreeLeaf updatedSlot(int index, T newValue) {
final Map.Entry[] oldSlots = this.slots;
final Map.Entry oldSlot = oldSlots[index];
if (newValue != oldSlot.getValue()) {
final int n = oldSlots.length;
final Map.Entry[] newSlots = (Map.Entry[]) new Map.Entry, ?>[n];
System.arraycopy(oldSlots, 0, newSlots, 0, n);
newSlots[index] = new AbstractMap.SimpleImmutableEntry(oldSlot.getKey(), newValue);
return new STreeLeaf(newSlots);
} else {
return this;
}
}
@Override
public STreeLeaf inserted(int index, T newValue, Object id, STreeContext tree) {
if (index < 0 || index > this.slots.length) {
throw new IndexOutOfBoundsException(Integer.toString(index));
}
return insertedSlot(index, newValue, id, tree);
}
@SuppressWarnings("unchecked")
private STreeLeaf insertedSlot(int index, T newValue, Object id, STreeContext tree) {
if (id == null) {
id = tree.identify(newValue);
}
final Map.Entry[] oldSlots = this.slots;
final int n = oldSlots.length + 1;
final Map.Entry[] newSlots = (Map.Entry[]) new Map.Entry, ?>[n];
System.arraycopy(oldSlots, 0, newSlots, 0, index);
newSlots[index] = new AbstractMap.SimpleImmutableEntry(id, newValue);
System.arraycopy(oldSlots, index, newSlots, index + 1, n - (index + 1));
return new STreeLeaf(newSlots);
}
@Override
public STreeLeaf removed(int index, STreeContext tree) {
if (index < 0 || index >= this.slots.length) {
throw new IndexOutOfBoundsException(Integer.toString(index));
}
if (this.slots.length > 1) {
return removedSlot(index);
} else {
return STreeLeaf.empty();
}
}
@SuppressWarnings("unchecked")
private STreeLeaf removedSlot(int index) {
final Map.Entry[] oldSlots = this.slots;
final int n = oldSlots.length - 1;
final Map.Entry[] newSlots = (Map.Entry[]) new Map.Entry, ?>[n];
System.arraycopy(oldSlots, 0, newSlots, 0, index);
System.arraycopy(oldSlots, index + 1, newSlots, index, n - index);
return new STreeLeaf(newSlots);
}
@Override
public STreeLeaf removed(Object object, STreeContext tree) {
final int index = indexOf(object);
if (index >= 0) {
if (this.slots.length > 1) {
return removedSlot(index);
} else {
return STreeLeaf.empty();
}
} else {
return this;
}
}
@SuppressWarnings("unchecked")
@Override
public STreeLeaf drop(int lower, STreeContext tree) {
if (lower > 0) {
final Map.Entry[] oldSlots = this.slots;
final int k = oldSlots.length;
if (lower < k) {
final int n = k - lower;
final Map.Entry[] newSlots = (Map.Entry[]) new Map.Entry, ?>[n];
System.arraycopy(oldSlots, lower, newSlots, 0, n);
return new STreeLeaf(newSlots);
} else {
return STreeLeaf.empty();
}
} else {
return this;
}
}
@SuppressWarnings("unchecked")
@Override
public STreeLeaf take(int upper, STreeContext tree) {
final Map.Entry[] oldSlots = this.slots;
if (upper < oldSlots.length) {
if (upper > 0) {
final Map.Entry[] newSlots = (Map.Entry[]) new Map.Entry, ?>[upper];
System.arraycopy(oldSlots, 0, newSlots, 0, upper);
return new STreeLeaf(newSlots);
} else {
return STreeLeaf.empty();
}
} else {
return this;
}
}
@Override
public STreePage balanced(STreeContext tree) {
final int n = this.slots.length;
if (n > 1 && tree.pageShouldSplit(this)) {
final int x = n >>> 1;
return split(x);
} else {
return this;
}
}
@SuppressWarnings("unchecked")
@Override
public STreeNode split(int x) {
final STreePage[] newPages = (STreePage[]) new STreePage>[2];
final STreeLeaf newLeftPage = splitLeft(x);
final STreeLeaf newRightPage = splitRight(x);
newPages[0] = newLeftPage;
newPages[1] = newRightPage;
final int[] newKnots = new int[1];
newKnots[0] = x;
return new STreeNode(newPages, newKnots, this.slots.length);
}
@SuppressWarnings("unchecked")
@Override
public STreeLeaf splitLeft(int x) {
final Map.Entry[] oldSlots = this.slots;
final Map.Entry[] newSlots = (Map.Entry[]) new Map.Entry, ?>[x];
System.arraycopy(oldSlots, 0, newSlots, 0, x);
return new STreeLeaf(newSlots);
}
@SuppressWarnings("unchecked")
@Override
public STreeLeaf splitRight(int x) {
final Map.Entry[] oldSlots = this.slots;
final int y = oldSlots.length - x;
final Map.Entry[] newSlots = (Map.Entry[]) new Map.Entry, ?>[y];
System.arraycopy(oldSlots, x, newSlots, 0, y);
return new STreeLeaf(newSlots);
}
@Override
public void copyToArray(Object[] array, int offset) {
final Map.Entry[] slots = this.slots;
for (int i = 0, n = slots.length; i < n; i += 1) {
array[offset + i] = slots[i].getValue();
}
}
@Override
public Cursor> entryIterator() {
return Cursor.array(this.slots);
}
@Override
public Cursor> reverseEntryIterator() {
return Cursor.array(this.slots, this.slots.length);
}
private static STreeLeaf empty;
@SuppressWarnings("unchecked")
public static STreeLeaf empty() {
if (empty == null) {
empty = new STreeLeaf((Map.Entry[]) new Map.Entry, ?>[0]);
}
return (STreeLeaf) empty;
}
}