From 1c2fb6ba88a889016992448e778a02b9a3dede8b Mon Sep 17 00:00:00 2001 From: "Jurgen J. Vinju" Date: Mon, 8 Jan 2024 18:47:47 +0100 Subject: [PATCH 01/11] added CF annotations --- .../collections/ShareableValuesHashSet.java | 18 +++++++++++++----- .../vallang/util/ShareableHashSet.java | 6 ++++++ 2 files changed, 19 insertions(+), 5 deletions(-) diff --git a/src/main/java/io/usethesource/vallang/impl/util/collections/ShareableValuesHashSet.java b/src/main/java/io/usethesource/vallang/impl/util/collections/ShareableValuesHashSet.java index 77bff52d9..6372b4440 100644 --- a/src/main/java/io/usethesource/vallang/impl/util/collections/ShareableValuesHashSet.java +++ b/src/main/java/io/usethesource/vallang/impl/util/collections/ShareableValuesHashSet.java @@ -15,6 +15,8 @@ import java.util.NoSuchElementException; import java.util.Set; +import org.checkerframework.checker.initialization.qual.UnknownInitialization; +import org.checkerframework.checker.nullness.qual.EnsuresNonNullIf; import org.checkerframework.checker.nullness.qual.Nullable; import io.usethesource.vallang.IValue; @@ -454,9 +456,9 @@ public String toString(){ } private static class SetIterator implements Iterator{ - private final Entry[] data; + private final Entry@Nullable[] data; - private Entry current; + private @Nullable Entry current; private int index; public SetIterator(Entry[] entries){ @@ -469,7 +471,7 @@ public SetIterator(Entry[] entries){ locateNext(); } - private void locateNext(){ + private void locateNext(@UnknownInitialization SetIterator this) { Entry next = current.next; if(next != null){ current = next; @@ -489,12 +491,17 @@ private void locateNext(){ index = 0; } + @EnsuresNonNullIf(expression="this.current", result=true) + @Override public boolean hasNext(){ return (current != null); } + @Override public IValue next(){ - if(!hasNext()) throw new NoSuchElementException("There are no more elements in this iteration"); + if (!hasNext()) { + throw new NoSuchElementException("There are no more elements in this iteration"); + } IValue value = current.value; locateNext(); @@ -502,7 +509,8 @@ public IValue next(){ return value; } - public void remove(){ + @Override + public void remove() { throw new UnsupportedOperationException("This iterator doesn't support removal."); } } diff --git a/src/main/java/io/usethesource/vallang/util/ShareableHashSet.java b/src/main/java/io/usethesource/vallang/util/ShareableHashSet.java index 9d9e23db9..6b314f022 100644 --- a/src/main/java/io/usethesource/vallang/util/ShareableHashSet.java +++ b/src/main/java/io/usethesource/vallang/util/ShareableHashSet.java @@ -15,6 +15,7 @@ import java.util.NoSuchElementException; import java.util.Set; +import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; /** @@ -162,8 +163,13 @@ private void ensureCapacity(){ * The value to insert. * @return Returns true if this set didn't contain the given value yet; false if it did. */ + @Override public boolean add(V value){ ensureCapacity(); + + if (value == null) { + throw new NullPointerException(); + } int hash = value.hashCode(); int position = hash & hashMask; From 49e1725b055fe937643215e81d2738c3d71cea85 Mon Sep 17 00:00:00 2001 From: "Jurgen J. Vinju" Date: Mon, 8 Jan 2024 19:45:30 +0100 Subject: [PATCH 02/11] handled complex semi-initialized method call --- .../collections/ShareableValuesHashSet.java | 34 ++++++++++--------- 1 file changed, 18 insertions(+), 16 deletions(-) diff --git a/src/main/java/io/usethesource/vallang/impl/util/collections/ShareableValuesHashSet.java b/src/main/java/io/usethesource/vallang/impl/util/collections/ShareableValuesHashSet.java index 6372b4440..394e2f8f9 100644 --- a/src/main/java/io/usethesource/vallang/impl/util/collections/ShareableValuesHashSet.java +++ b/src/main/java/io/usethesource/vallang/impl/util/collections/ShareableValuesHashSet.java @@ -17,6 +17,7 @@ import org.checkerframework.checker.initialization.qual.UnknownInitialization; import org.checkerframework.checker.nullness.qual.EnsuresNonNullIf; +import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; import io.usethesource.vallang.IValue; @@ -456,44 +457,45 @@ public String toString(){ } private static class SetIterator implements Iterator{ - private final Entry@Nullable[] data; + private final @Nullable Entry[] data; private @Nullable Entry current; private int index; - public SetIterator(Entry[] entries){ + public SetIterator(Entry[] entries) { super(); data = entries; index = data.length - 1; current = new Entry<>(0, null, data[index]); - locateNext(); + locateNext(data, current); } - private void locateNext(@UnknownInitialization SetIterator this) { - Entry next = current.next; - if(next != null){ - current = next; + private void locateNext(@UnknownInitialization SetIterator this, @Nullable Entry[] data, Entry nonNullCurrent) { + Entry next = nonNullCurrent.next; + + if (next != null) { + this.current = next; return; } - for(int i = index - 1; i >= 0 ; i--){ - Entry entry = data[i]; - if(entry != null){ - current = entry; - index = i; + for (int i = this.index - 1; i >= 0 ; i--) { + @Nullable Entry entry = data[i]; + if (entry != null) { + this.current = entry; + this.index = i; return; } } - current = null; - index = 0; + this.current = null; + this.index = 0; } @EnsuresNonNullIf(expression="this.current", result=true) @Override - public boolean hasNext(){ + public boolean hasNext(@UnknownInitialization SetIterator this) { return (current != null); } @@ -504,7 +506,7 @@ public IValue next(){ } IValue value = current.value; - locateNext(); + locateNext(data, current); return value; } From f89ace2909130ecab1478f57235a70c3536ce3cf Mon Sep 17 00:00:00 2001 From: "Jurgen J. Vinju" Date: Mon, 8 Jan 2024 20:22:52 +0100 Subject: [PATCH 03/11] another few steps --- .../collections/ShareableValuesHashSet.java | 54 ++++++++----------- 1 file changed, 23 insertions(+), 31 deletions(-) diff --git a/src/main/java/io/usethesource/vallang/impl/util/collections/ShareableValuesHashSet.java b/src/main/java/io/usethesource/vallang/impl/util/collections/ShareableValuesHashSet.java index 394e2f8f9..e4dc88676 100644 --- a/src/main/java/io/usethesource/vallang/impl/util/collections/ShareableValuesHashSet.java +++ b/src/main/java/io/usethesource/vallang/impl/util/collections/ShareableValuesHashSet.java @@ -305,35 +305,27 @@ public boolean removeAll(Collection collection){ return changed; } + @Override public Object[] toArray(){ - Object[] values = new Object[load]; - - Iterator valuesIterator = iterator(); - int i = 0; - while(valuesIterator.hasNext()){ - values[i++] = valuesIterator.next(); - } - - return values; - } + throw new UnsupportedOperationException(); - @SuppressWarnings("unchecked") - public T[] toArray(T[] array){ - if(array.length < load) return (T[]) toArray(); + // Object[] values = new Object[load]; - Iterator valuesIterator = iterator(); - int i = 0; - while(valuesIterator.hasNext()){ - array[i++] = (T) valuesIterator.next(); - } + // Iterator valuesIterator = iterator(); + // int i = 0; + // while(valuesIterator.hasNext()){ + // values[i++] = valuesIterator.next(); + // } - for(; i < load; i++){ - array[i] = null; - } - - return array; + // return values; } + + @Override + public @Nullable T[] toArray(T[] array) { + throw new UnsupportedOperationException(); + } + @Override public String toString(){ StringBuilder buffer = new StringBuilder(); @@ -434,9 +426,9 @@ private static class Entry{ public final int hash; public final V value; - public final Entry next; + public final @Nullable Entry next; - public Entry(int hash, V value, Entry next){ + public Entry(int hash, V value, @Nullable Entry next){ super(); this.hash = hash; @@ -459,7 +451,7 @@ public String toString(){ private static class SetIterator implements Iterator{ private final @Nullable Entry[] data; - private @Nullable Entry current; + private @Nullable Entry<@Nullable IValue> current; private int index; public SetIterator(Entry[] entries) { @@ -468,12 +460,12 @@ public SetIterator(Entry[] entries) { data = entries; index = data.length - 1; - current = new Entry<>(0, null, data[index]); - locateNext(data, current); + current = null; + locateNext(data); } - private void locateNext(@UnknownInitialization SetIterator this, @Nullable Entry[] data, Entry nonNullCurrent) { - Entry next = nonNullCurrent.next; + private void locateNext(@UnknownInitialization SetIterator this, @Nullable Entry[] data) { + Entry next = current != null ? current.next : null; if (next != null) { this.current = next; @@ -506,7 +498,7 @@ public IValue next(){ } IValue value = current.value; - locateNext(data, current); + locateNext(data); return value; } From 53abc661405d2683b8dac18f240da9e562717172 Mon Sep 17 00:00:00 2001 From: "Jurgen J. Vinju" Date: Mon, 8 Jan 2024 20:41:47 +0100 Subject: [PATCH 04/11] fixed s... error --- .../impl/util/collections/ShareableValuesHashSet.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/io/usethesource/vallang/impl/util/collections/ShareableValuesHashSet.java b/src/main/java/io/usethesource/vallang/impl/util/collections/ShareableValuesHashSet.java index e4dc88676..11439b987 100644 --- a/src/main/java/io/usethesource/vallang/impl/util/collections/ShareableValuesHashSet.java +++ b/src/main/java/io/usethesource/vallang/impl/util/collections/ShareableValuesHashSet.java @@ -422,7 +422,7 @@ public boolean equals(@Nullable Object o){ return false; } - private static class Entry{ + private static class Entry{ public final int hash; public final V value; @@ -451,7 +451,7 @@ public String toString(){ private static class SetIterator implements Iterator{ private final @Nullable Entry[] data; - private @Nullable Entry<@Nullable IValue> current; + private @Nullable Entry current; private int index; public SetIterator(Entry[] entries) { @@ -497,7 +497,7 @@ public IValue next(){ throw new NoSuchElementException("There are no more elements in this iteration"); } - IValue value = current.value; + @NonNull IValue value = current.value; locateNext(data); return value; From cce23a70abfee6bdf3b5945958b4850b4633d582 Mon Sep 17 00:00:00 2001 From: "Jurgen J. Vinju" Date: Mon, 8 Jan 2024 21:07:03 +0100 Subject: [PATCH 05/11] removed implements Set from ShareableValuesHashSet and also the unused methods that came with that interface. simplifies annotations enormously --- .../PersistentHashIndexedBinaryRelation.java | 19 ++- .../collections/ShareableValuesHashSet.java | 122 +----------------- .../vallang/util/ShareableHashSet.java | 1 - 3 files changed, 12 insertions(+), 130 deletions(-) diff --git a/src/main/java/io/usethesource/vallang/impl/persistent/PersistentHashIndexedBinaryRelation.java b/src/main/java/io/usethesource/vallang/impl/persistent/PersistentHashIndexedBinaryRelation.java index 399656704..86d7a0c02 100644 --- a/src/main/java/io/usethesource/vallang/impl/persistent/PersistentHashIndexedBinaryRelation.java +++ b/src/main/java/io/usethesource/vallang/impl/persistent/PersistentHashIndexedBinaryRelation.java @@ -17,7 +17,6 @@ import java.util.Arrays; import java.util.HashMap; -import java.util.HashSet; import java.util.Iterator; import java.util.Map; import java.util.Objects; @@ -557,7 +556,7 @@ public ISet closure() { @Override public ISet closureStar() { // calculate - java.util.Set closureDelta = computeClosureDelta(); + ShareableValuesHashSet closureDelta = computeClosureDelta(); IWriter resultWriter = writer(); resultWriter.insertAll(this); @@ -570,13 +569,13 @@ public ISet closureStar() { return resultWriter.done(); } - private java.util.Set computeClosureDelta() { + private ShareableValuesHashSet computeClosureDelta() { IValueFactory vf = ValueFactory.getInstance(); RotatingQueue iLeftKeys = new RotatingQueue<>(); RotatingQueue> iLefts = new RotatingQueue<>(); Map> interestingLeftSides = new HashMap<>(); - Map> potentialRightSides = new HashMap<>(); + Map potentialRightSides = new HashMap<>(); // Index for (IValue val : this) { @@ -584,7 +583,7 @@ private java.util.Set computeClosureDelta() { IValue key = tuple.get(0); IValue value = tuple.get(1); RotatingQueue leftValues = interestingLeftSides.get(key); - java.util.Set rightValues; + ShareableValuesHashSet rightValues; if (leftValues != null) { rightValues = potentialRightSides.get(key); @@ -610,9 +609,9 @@ private java.util.Set computeClosureDelta() { int nextSize = 0; // Compute - final java.util.Set newTuples = new ShareableValuesHashSet(); + final ShareableValuesHashSet newTuples = new ShareableValuesHashSet(); do { - Map> rightSides = potentialRightSides; + Map rightSides = potentialRightSides; potentialRightSides = new HashMap<>(); for (; size > 0; size--) { @@ -625,7 +624,7 @@ private java.util.Set computeClosureDelta() { IValue rightKey; while ((rightKey = leftValues.get()) != null) { - java.util.Set rightValues = rightSides.get(rightKey); + ShareableValuesHashSet rightValues = rightSides.get(rightKey); if (rightValues != null) { Iterator rightValuesIterator = rightValues.iterator(); while (rightValuesIterator.hasNext()) { @@ -640,9 +639,9 @@ private java.util.Set computeClosureDelta() { } interestingLeftValues.put(rightValue); - java.util.Set potentialRightValues = potentialRightSides.get(rightKey); + ShareableValuesHashSet potentialRightValues = potentialRightSides.get(rightKey); if (potentialRightValues == null) { - potentialRightValues = new HashSet<>(); + potentialRightValues = new ShareableValuesHashSet(); potentialRightSides.put(rightKey, potentialRightValues); } potentialRightValues.add(rightValue); diff --git a/src/main/java/io/usethesource/vallang/impl/util/collections/ShareableValuesHashSet.java b/src/main/java/io/usethesource/vallang/impl/util/collections/ShareableValuesHashSet.java index 11439b987..7525a263b 100644 --- a/src/main/java/io/usethesource/vallang/impl/util/collections/ShareableValuesHashSet.java +++ b/src/main/java/io/usethesource/vallang/impl/util/collections/ShareableValuesHashSet.java @@ -7,28 +7,26 @@ * * Contributors: * Arnold Lankamp - interfaces and implementation +* Jurgen Vinju - CF annotation, maintenance and removal of unused methods *******************************************************************************/ package io.usethesource.vallang.impl.util.collections; import java.util.Collection; import java.util.Iterator; import java.util.NoSuchElementException; -import java.util.Set; - import org.checkerframework.checker.initialization.qual.UnknownInitialization; import org.checkerframework.checker.nullness.qual.EnsuresNonNullIf; import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; import io.usethesource.vallang.IValue; -import io.usethesource.vallang.impl.persistent.ValueFactory; /** * A specialized version of the ShareableSet, specifically meant for storing values. * * @author Arnold Lankamp */ -public final class ShareableValuesHashSet implements Set, Iterable{ +public final class ShareableValuesHashSet implements Iterable{ private final static int INITIAL_LOG_SIZE = 4; private int modSize; @@ -138,10 +136,6 @@ private void ensureCapacity(){ } } - public boolean addTuple(IValue... fields) { - return add(ValueFactory.getInstance().tuple(fields)); - } - public boolean add(IValue value){ ensureCapacity(); @@ -185,31 +179,7 @@ public boolean contains(Object object){ return false; } - - public boolean containsMatch(Object object){ - IValue value = (IValue) object; - - int hash = value.hashCode(); - int position = hash & hashMask; - - Entry entry = data[position]; - while(entry != null){ - if(hash == entry.hash && value.match(entry.value)) { - return true; - } - - entry = entry.next; - } - - for (Entry e : data) { - if (e != null && value.match(e.value)) { - return true; - } - } - - return false; - } - + public boolean remove(Object object){ IValue value = (IValue) object; @@ -267,63 +237,6 @@ public boolean addAll(Collection collection){ return changed; } - - public boolean containsAll(Collection collection){ - Iterator collectionIterator = collection.iterator(); - while(collectionIterator.hasNext()){ - if(!contains(collectionIterator.next())) return false; - } - - return true; - } - - public boolean retainAll(Collection collection){ - boolean changed = false; - - Iterator valuesIterator = iterator(); - while(valuesIterator.hasNext()){ - IValue value = valuesIterator.next(); - if(!collection.contains(value)){ - remove(value); - - changed = true; - } - } - - return changed; - } - - public boolean removeAll(Collection collection){ - boolean changed = false; - - Iterator collectionIterator = collection.iterator(); - while(collectionIterator.hasNext()){ - Object value = collectionIterator.next(); - changed |= remove(value); - } - - return changed; - } - - @Override - public Object[] toArray(){ - throw new UnsupportedOperationException(); - - // Object[] values = new Object[load]; - - // Iterator valuesIterator = iterator(); - // int i = 0; - // while(valuesIterator.hasNext()){ - // values[i++] = valuesIterator.next(); - // } - - // return values; - } - - @Override - public @Nullable T[] toArray(T[] array) { - throw new UnsupportedOperationException(); - } @Override public String toString(){ @@ -356,35 +269,6 @@ public int hashCode(){ return currentHashCode; } - public boolean isEqual(ShareableValuesHashSet other){ - if(other == null) return false; - - if(other.currentHashCode != currentHashCode) return false; - if(other.size() != size()) return false; - - if(isEmpty()) return true; // No need to check if the sets are empty. - - Iterator otherIterator = other.iterator(); - while(otherIterator.hasNext()){ - if(!contains(otherIterator.next())) return false; - } - return true; - } - - public boolean match(ShareableValuesHashSet other){ - if(other == null) return false; - - if(other.size() != size()) return false; - - if(isEmpty()) return true; // No need to check if the sets are empty. - - Iterator otherIterator = other.iterator(); - while(otherIterator.hasNext()){ - if(!containsMatch(otherIterator.next())) return false; - } - return true; - } - private boolean containsTruelyEqual(IValue value){ int hash = value.hashCode(); int position = hash & hashMask; diff --git a/src/main/java/io/usethesource/vallang/util/ShareableHashSet.java b/src/main/java/io/usethesource/vallang/util/ShareableHashSet.java index 6b314f022..c6e9ee47e 100644 --- a/src/main/java/io/usethesource/vallang/util/ShareableHashSet.java +++ b/src/main/java/io/usethesource/vallang/util/ShareableHashSet.java @@ -15,7 +15,6 @@ import java.util.NoSuchElementException; import java.util.Set; -import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; /** From bc66f2cbf4658ec1131b13849240fa5eb2a489c5 Mon Sep 17 00:00:00 2001 From: "Jurgen J. Vinju" Date: Mon, 8 Jan 2024 21:22:18 +0100 Subject: [PATCH 06/11] improved difficult loop in remove to help cf --- .../util/collections/ShareableValuesHashSet.java | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/src/main/java/io/usethesource/vallang/impl/util/collections/ShareableValuesHashSet.java b/src/main/java/io/usethesource/vallang/impl/util/collections/ShareableValuesHashSet.java index 7525a263b..4161b94b0 100644 --- a/src/main/java/io/usethesource/vallang/impl/util/collections/ShareableValuesHashSet.java +++ b/src/main/java/io/usethesource/vallang/impl/util/collections/ShareableValuesHashSet.java @@ -32,7 +32,7 @@ public final class ShareableValuesHashSet implements Iterable{ private int modSize; private int hashMask; - private Entry[] data; + private @Nullable Entry[] data; private int threshold; @@ -187,15 +187,16 @@ public boolean remove(Object object){ int position = hash & hashMask; Entry currentStartEntry = data[position]; - if(currentStartEntry != null){ + + if (currentStartEntry != null) { Entry entry = currentStartEntry; - do{ - if(hash == entry.hash && entry.value.equals(value)){ + do { + if (hash == entry.hash && entry.value.equals(value)) { Entry e = data[position]; data[position] = entry.next; // Reconstruct the other entries (if necessary). - while(e != entry){ + while (e != entry && e != null) { data[position] = new Entry<>(e.hash, e.value, data[position]); e = e.next; @@ -209,7 +210,7 @@ public boolean remove(Object object){ } entry = entry.next; - }while(entry != null); + } while(entry != null); } return false; @@ -338,7 +339,7 @@ private static class SetIterator implements Iterator{ private @Nullable Entry current; private int index; - public SetIterator(Entry[] entries) { + public SetIterator(@Nullable Entry[] entries) { super(); data = entries; From a9084726da3ee2d1a82c6528550d367fb8ecbce9 Mon Sep 17 00:00:00 2001 From: "Jurgen J. Vinju" Date: Mon, 8 Jan 2024 21:24:34 +0100 Subject: [PATCH 07/11] added superfluous null-check to help CF in loop --- .../impl/util/collections/ShareableValuesHashSet.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/main/java/io/usethesource/vallang/impl/util/collections/ShareableValuesHashSet.java b/src/main/java/io/usethesource/vallang/impl/util/collections/ShareableValuesHashSet.java index 4161b94b0..4a7b3843d 100644 --- a/src/main/java/io/usethesource/vallang/impl/util/collections/ShareableValuesHashSet.java +++ b/src/main/java/io/usethesource/vallang/impl/util/collections/ShareableValuesHashSet.java @@ -95,18 +95,18 @@ private void rehash(){ threshold = tableSize; Entry[] oldData = data; - for(int i = oldData.length - 1; i >= 0; i--){ + for (int i = oldData.length - 1; i >= 0; i--) { Entry entry = oldData[i]; - if(entry != null){ + if (entry != null) { // Determine the last unchanged entry chain. Entry lastUnchangedEntryChain = entry; int newLastUnchangedEntryChainIndex = entry.hash & hashMask; Entry e = entry.next; - while(e != null){ + while (e != null) { int newIndex = e.hash & hashMask; - if(newIndex != newLastUnchangedEntryChainIndex){ + if (newIndex != newLastUnchangedEntryChainIndex) { lastUnchangedEntryChain = e; newLastUnchangedEntryChainIndex = newIndex; } @@ -117,7 +117,7 @@ private void rehash(){ newData[newLastUnchangedEntryChainIndex] = lastUnchangedEntryChain; // Reconstruct the other entries (if necessary). - while(entry != lastUnchangedEntryChain){ + while (entry != lastUnchangedEntryChain && entry != null) { int hash = entry.hash; int position = hash & hashMask; newData[position] = new Entry<>(hash, entry.value, newData[position]); From 81a635daa1829256e6633ccd44bebbc1442821c9 Mon Sep 17 00:00:00 2001 From: "Jurgen J. Vinju" Date: Mon, 8 Jan 2024 21:26:58 +0100 Subject: [PATCH 08/11] last annotation in ShareableValuesHashSet; on to the ShareableHashSet --- .../vallang/impl/util/collections/ShareableValuesHashSet.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/io/usethesource/vallang/impl/util/collections/ShareableValuesHashSet.java b/src/main/java/io/usethesource/vallang/impl/util/collections/ShareableValuesHashSet.java index 4a7b3843d..92996a275 100644 --- a/src/main/java/io/usethesource/vallang/impl/util/collections/ShareableValuesHashSet.java +++ b/src/main/java/io/usethesource/vallang/impl/util/collections/ShareableValuesHashSet.java @@ -94,7 +94,7 @@ private void rehash(){ threshold = tableSize; - Entry[] oldData = data; + @Nullable Entry[] oldData = data; for (int i = oldData.length - 1; i >= 0; i--) { Entry entry = oldData[i]; From a6a6425799930653b3b310c019227252e4d5b4e0 Mon Sep 17 00:00:00 2001 From: "Jurgen J. Vinju" Date: Mon, 8 Jan 2024 21:49:40 +0100 Subject: [PATCH 09/11] removed unused class --- .../vallang/util/ShareableHashSet.java | 629 ------------------ 1 file changed, 629 deletions(-) delete mode 100644 src/main/java/io/usethesource/vallang/util/ShareableHashSet.java diff --git a/src/main/java/io/usethesource/vallang/util/ShareableHashSet.java b/src/main/java/io/usethesource/vallang/util/ShareableHashSet.java deleted file mode 100644 index c6e9ee47e..000000000 --- a/src/main/java/io/usethesource/vallang/util/ShareableHashSet.java +++ /dev/null @@ -1,629 +0,0 @@ -/******************************************************************************* -* Copyright (c) 2009 Centrum Wiskunde en Informatica (CWI) -* All rights reserved. This program and the accompanying materials -* are made available under the terms of the Eclipse Public License v1.0 -* which accompanies this distribution, and is available at -* http://www.eclipse.org/legal/epl-v10.html -* -* Contributors: -* Arnold Lankamp - interfaces and implementation -*******************************************************************************/ -package io.usethesource.vallang.util; - -import java.util.Collection; -import java.util.Iterator; -import java.util.NoSuchElementException; -import java.util.Set; - -import org.checkerframework.checker.nullness.qual.Nullable; - -/** - * This set implementation is shareable and can be easily cloned - * (simple arraycopy of the entries array). - * - * @author Arnold Lankamp - * - * @param - * The value type. - */ -public final class ShareableHashSet implements Set, Iterable{ - private final static int INITIAL_LOG_SIZE = 4; - - private int modSize; - private int hashMask; - - private Entry[] data; - - private int threshold; - - private int load; - - private int currentHashCode; - - /** - * Default constructor. - */ - @SuppressWarnings("unchecked") - public ShareableHashSet(){ - super(); - - modSize = INITIAL_LOG_SIZE; - int tableSize = 1 << modSize; - hashMask = tableSize - 1; - data = (Entry[]) new Entry[tableSize]; - - threshold = tableSize; - - load = 0; - - currentHashCode = 0; - } - - /** - * Copy constructor. - * - * @param sharedHashSet - * The set to copy. - */ - public ShareableHashSet(ShareableHashSet sharedHashSet){ - super(); - - modSize = sharedHashSet.modSize; - int tableSize = 1 << modSize; - hashMask = tableSize - 1; - data = sharedHashSet.data.clone(); - - threshold = tableSize; - - load = sharedHashSet.load; - - currentHashCode = sharedHashSet.currentHashCode; - } - - /** - * Removes all the entries from this set. - */ - @SuppressWarnings("unchecked") - public void clear(){ - modSize = INITIAL_LOG_SIZE; - int tableSize = 1 << modSize; - hashMask = tableSize - 1; - data = (Entry[]) new Entry[tableSize]; - - threshold = tableSize; - - load = 0; - - currentHashCode = 0; - } - - /** - * Rehashes this set. - */ - private void rehash(){ - modSize++; - int tableSize = 1 << modSize; - hashMask = tableSize - 1; - @SuppressWarnings("unchecked") - Entry[] newData = (Entry[]) new Entry[tableSize]; - - threshold = tableSize; - - Entry[] oldData = data; - for(int i = oldData.length - 1; i >= 0; i--){ - Entry entry = oldData[i]; - - if(entry != null){ - // Determine the last unchanged entry chain. - Entry lastUnchangedEntryChain = entry; - int newLastUnchangedEntryChainIndex = entry.hash & hashMask; - - Entry e = entry.next; - while(e != null){ - int newIndex = e.hash & hashMask; - if(newIndex != newLastUnchangedEntryChainIndex){ - lastUnchangedEntryChain = e; - newLastUnchangedEntryChainIndex = newIndex; - } - - e = e.next; - } - - newData[newLastUnchangedEntryChainIndex] = lastUnchangedEntryChain; - - // Reconstruct the other entries (if necessary). - while(entry != lastUnchangedEntryChain){ - int hash = entry.hash; - int position = hash & hashMask; - newData[position] = new Entry<>(hash, entry.value, newData[position]); - - entry = entry.next; - } - } - } - - data = newData; - } - - /** - * Makes sure the size of the entry array and the load of the set stay in proper relation to - * eachother. - */ - private void ensureCapacity(){ - if(load > threshold){ - rehash(); - } - } - - /** - * Inserts the given value into this set. - * - * @param value - * The value to insert. - * @return Returns true if this set didn't contain the given value yet; false if it did. - */ - @Override - public boolean add(V value){ - ensureCapacity(); - - if (value == null) { - throw new NullPointerException(); - } - - int hash = value.hashCode(); - int position = hash & hashMask; - - Entry currentStartEntry = data[position]; - // Check if the value is already in here. - if(currentStartEntry != null){ - Entry entry = currentStartEntry; - do{ - if(hash == entry.hash && entry.value.equals(value)){ - return false; // Return false if it's already present. - } - - entry = entry.next; - }while(entry != null); - } - - data[position] = new Entry<>(hash, value, currentStartEntry); // Insert the new entry. - - load++; - - currentHashCode ^= hash; // Update the current hashcode of this map. - - return true; - } - - /** - * Checks if this set contains the given value. - * - * @param value - * The value to check for. - * @return True if this set contains the given value; false otherwise. - */ - public boolean contains(Object value){ - int hash = value.hashCode(); - int position = hash & hashMask; - - Entry entry = data[position]; - while(entry != null){ - if(hash == entry.hash && value.equals(entry.value)) return true; - - entry = entry.next; - } - - return false; - } - - /** - * Removes the given object from this set (if present.) - * - * @param value - * The value to remove. - * @return True if this set contained the given object; false otherwise. - */ - public boolean remove(Object value){ - int hash = value.hashCode(); - int position = hash & hashMask; - - Entry currentStartEntry = data[position]; - if(currentStartEntry != null){ - Entry entry = currentStartEntry; - do{ - if(hash == entry.hash && entry.value.equals(value)){ - Entry e = data[position]; - - data[position] = entry.next; - // Reconstruct the other entries (if necessary). - while(e != entry){ - data[position] = new Entry<>(e.hash, e.value, data[position]); - - e = e.next; - } - - load--; - - currentHashCode ^= hash; // Update the current hashcode of this set. - - return true; - } - - entry = entry.next; - }while(entry != null); - } - - return false; - } - - /** - * Returns the number of values this set currently contains. - * - * @return The number of values this set currently contains. - */ - public int size(){ - return load; - } - - /** - * Checks whether or not this set is empty. - * - * @return True is this set is empty; false otherwise. - */ - public boolean isEmpty(){ - return (load == 0); - } - - /** - * Constructs an iterator for this set. - * - * @return An iterator for this set. - * - * @see java.lang.Iterable#iterator() - */ - public Iterator iterator(){ - return new SetIterator<>(data); - } - - /** - * Adds all the elements from the given collection to this set. - * - * @param collection - * The collection that contains the elements to add. - * @return True if this set changed; false if it didn't. - */ - public boolean addAll(Collection collection){ - boolean changed = false; - - Iterator collectionIterator = collection.iterator(); - while(collectionIterator.hasNext()){ - changed |= add(collectionIterator.next()); - } - - return changed; - } - - /** - * Checks if the collection contains all the elements in the given collection. - * - * @param collection - * The collection that contains the elements to check for. - * @return True if this set contains all the elements in the given collections; false if it - * didn't. - */ - public boolean containsAll(Collection collection){ - Iterator collectionIterator = collection.iterator(); - while(collectionIterator.hasNext()){ - if(!contains(collectionIterator.next())) return false; - } - - return true; - } - - /** - * Removes all the elements from this set which are not present in the given collection. - * - * @param collection - * The collection that contains the elements which need to be retained. - * @return True if this set changed; false if it didn't. - */ - public boolean retainAll(Collection collection){ - boolean changed = false; - - Iterator valuesIterator = iterator(); - while(valuesIterator.hasNext()){ - V value = valuesIterator.next(); - if(!collection.contains(value)){ - remove(value); - - changed = true; - } - } - - return changed; - } - - /** - * Removes all the elements in the given collection from this set. - * - * @param collection - * The collection that contains the elements to remove from this set. - * @return True if this set change; false if it didn't. - */ - public boolean removeAll(Collection collection){ - boolean changed = false; - - Iterator collectionIterator = collection.iterator(); - while(collectionIterator.hasNext()){ - Object value = collectionIterator.next(); - changed |= remove(value); - } - - return changed; - } - - /** - * Returns all the elements from this set in an array. - * - * @return All the elements from this set in an array. - */ - public Object[] toArray(){ - Object[] values = new Object[load]; - - Iterator valuesIterator = iterator(); - int i = 0; - while(valuesIterator.hasNext()){ - values[i++] = valuesIterator.next(); - } - - return values; - } - - - /** - * Returns all the elements from this set in an array. - * - * @param array - * The array to use; in case it isn't large enough a new one will be allocated. - * @return All the elements from this set in an array. - */ - @SuppressWarnings("unchecked") - public T[] toArray(T[] array){ - if(array.length < load) return (T[]) toArray(); - - Iterator valuesIterator = iterator(); - int i = 0; - while(valuesIterator.hasNext()){ - array[i++] = (T) valuesIterator.next(); - } - - for(; i < load; i++){ - array[i] = null; - } - - return array; - } - - /** - * Prints the internal representation of this set to a string. - * - * @see java.lang.Object#toString() - */ - public String toString(){ - StringBuilder buffer = new StringBuilder(); - - buffer.append('{'); - for(int i = 0; i < data.length; i++){ - buffer.append('['); - Entry e = data[i]; - if(e != null){ - buffer.append(e); - - e = e.next; - - while(e != null){ - buffer.append(','); - buffer.append(e); - - e = e.next; - } - } - buffer.append(']'); - } - buffer.append('}'); - - return buffer.toString(); - } - - /** - * Returns the current hash code of this set. - * - * @return The current hash code of this set. - * - * @see java.lang.Object#hashCode() - */ - public int hashCode(){ - return currentHashCode; - } - - /** - * Check whether or not the current content of this set is equal to that of the given object / set. - * - * @return True if the content of this set is equal to the given object / set. - * - * @see java.lang.Object#equals(Object) - */ - @Override - public boolean equals(@Nullable Object o){ - if (o == null) { - return false; - } - - if (o.getClass() == getClass()){ - ShareableHashSet other = (ShareableHashSet) o; - - if (other.currentHashCode != currentHashCode) { - return false; - } - if (other.size() != size()) { - return false; - } - - if (isEmpty()) { - return true; // No need to check if the sets are empty. - } - - Iterator otherIterator = other.iterator(); - while (otherIterator.hasNext()){ - if (!contains(otherIterator.next())) { - return false; - } - } - return true; - } - - return false; - } - - /** - * Entry, used for containing values and constructing buckets. - * - * @author Arnold Lankamp - * - * @param - * The value type. - */ - private static class Entry{ - public final int hash; - public final V value; - - public final Entry next; - - /** - * Constructor. - * - * @param hash - * The hash code of the value - * @param value - * The value - * @param next - * A reference to the next entry in the bucket (if any). - */ - public Entry(int hash, V value, Entry next){ - super(); - - this.hash = hash; - this.value = value; - - this.next = next; - } - - /** - * Prints the internal representation of this entry to a string. - * - * @see java.lang.Object#toString() - */ - public String toString(){ - StringBuilder buffer = new StringBuilder(); - - buffer.append('<'); - buffer.append(value); - buffer.append('>'); - - return buffer.toString(); - } - } - - /** - * Iterator for this set. - * - * @author Arnold Lankamp - * - * @param - * The value type. - */ - private static class SetIterator implements Iterator{ - private final Entry[] data; - - private Entry current; - private int index; - - /** - * Constructor. - * - * @param entries - * The entries to iterator over. - */ - public SetIterator(Entry[] entries){ - super(); - - data = entries; - - index = data.length - 1; - current = new Entry<>(0, null, data[index]); - locateNext(); - } - - /** - * Locates the next value in the set. - */ - private void locateNext(){ - Entry next = current.next; - if(next != null){ - current = next; - return; - } - - for(int i = index - 1; i >= 0 ; i--){ - Entry entry = data[i]; - if(entry != null){ - current = entry; - index = i; - return; - } - } - - current = null; - index = 0; - } - - /** - * Checks if there are more elements in this iteration. - * - * @see java.util.Iterator#hasNext() - */ - public boolean hasNext(){ - return (current != null); - } - - /** - * Returns the next element in this iteration. - * - * @return The next element in this iteration. - * @throws NoSuchElementException - * Thrown if there are no more elements in this iteration when calling this - * method. - * - * @see java.util.Iterator#next() - */ - public V next(){ - if(!hasNext()) throw new NoSuchElementException("There are no more elements in this iteration"); - - V value = current.value; - locateNext(); - - return value; - } - - /** - * Removal is not supported by this iterator. - * - * @throws java.lang.UnsupportedOperationException - * - * @see java.util.Iterator#remove() - */ - public void remove(){ - throw new UnsupportedOperationException("This iterator doesn't support removal."); - } - } -} From d1ced7012a760c584eb303381b63b1bea440d904 Mon Sep 17 00:00:00 2001 From: "Jurgen J. Vinju" Date: Mon, 8 Jan 2024 21:57:09 +0100 Subject: [PATCH 10/11] loving git bisect; fixed bug just introduced --- .../vallang/impl/util/collections/ShareableValuesHashSet.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/io/usethesource/vallang/impl/util/collections/ShareableValuesHashSet.java b/src/main/java/io/usethesource/vallang/impl/util/collections/ShareableValuesHashSet.java index 92996a275..7585b67ea 100644 --- a/src/main/java/io/usethesource/vallang/impl/util/collections/ShareableValuesHashSet.java +++ b/src/main/java/io/usethesource/vallang/impl/util/collections/ShareableValuesHashSet.java @@ -345,7 +345,7 @@ public SetIterator(@Nullable Entry[] entries) { data = entries; index = data.length - 1; - current = null; + current = new Entry<>(0, null, data[index]); locateNext(data); } From ac77a7e3608c5f894fba9eea111451640a327d54 Mon Sep 17 00:00:00 2001 From: "Jurgen J. Vinju" Date: Mon, 8 Jan 2024 22:02:34 +0100 Subject: [PATCH 11/11] added dummy value to acquiesque the checker framework --- .../vallang/impl/util/collections/ShareableValuesHashSet.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/io/usethesource/vallang/impl/util/collections/ShareableValuesHashSet.java b/src/main/java/io/usethesource/vallang/impl/util/collections/ShareableValuesHashSet.java index 7585b67ea..faa749837 100644 --- a/src/main/java/io/usethesource/vallang/impl/util/collections/ShareableValuesHashSet.java +++ b/src/main/java/io/usethesource/vallang/impl/util/collections/ShareableValuesHashSet.java @@ -20,6 +20,7 @@ import org.checkerframework.checker.nullness.qual.Nullable; import io.usethesource.vallang.IValue; +import io.usethesource.vallang.impl.persistent.ValueFactory; /** * A specialized version of the ShareableSet, specifically meant for storing values. @@ -345,7 +346,7 @@ public SetIterator(@Nullable Entry[] entries) { data = entries; index = data.length - 1; - current = new Entry<>(0, null, data[index]); + current = new Entry<>(0, ValueFactory.getInstance().bool(true) /* dummy */, data[index]); locateNext(data); }