1 25 package org.archive.util; 26 27 import java.io.Serializable ; 28 import java.util.logging.Logger ; 29 30 import org.archive.util.fingerprint.LongFPSet; 31 32 46 public abstract class AbstractLongFPSet implements LongFPSet, Serializable { 47 private static Logger logger = 48 Logger.getLogger("org.archive.util.AbstractLongFPSet"); 49 50 54 protected static byte EMPTY = -1; 55 56 57 protected int capacityPowerOfTwo; 58 59 61 protected float loadFactor; 62 63 64 protected long count; 65 66 70 public AbstractLongFPSet() { 71 super(); 72 } 73 74 83 public AbstractLongFPSet(final int capacityPowerOfTwo, float loadFactor) { 84 this.capacityPowerOfTwo = capacityPowerOfTwo; 85 this.loadFactor = loadFactor; 86 this.count = 0; 87 } 88 89 94 public boolean contains(long val) { 95 long i = indexFor(val); 96 if (slotHasData(i)) { 97 noteAccess(i); 98 return true; 99 } 100 return false; 101 } 102 103 109 protected abstract int getSlotState(long i); 110 111 116 private void noteAccess(long index) { 117 } 120 121 126 public long count() { 127 return count; 128 } 129 130 135 public boolean add(long val) { 136 logger.finest("Adding " + val); 137 long i = indexFor(val); 138 if (slotHasData(i)) { 139 return false; 141 } 142 144 if ((count + 1) > (loadFactor * (1 << capacityPowerOfTwo))) { 146 makeSpace(); 147 i = indexFor(val); 149 assert i < 0 : "slot should be empty"; 150 } 151 152 i = asDataSlot(i); setAt(i, val); 154 count++; 155 noteAccess(i); 156 return true; 157 } 158 159 165 protected abstract void makeSpace(); 166 167 173 protected abstract void setAt(long i, long l); 174 175 181 protected abstract long getAt(long i); 182 183 196 private long indexFor(long val) { 197 long candidateIndex = startIndexFor(val); 198 while (true) { 199 if (getSlotState(candidateIndex) < 0) { 200 return asEmptySlot(candidateIndex); 202 } 203 if (getAt(candidateIndex) == val) { 204 return candidateIndex; 206 } 207 candidateIndex++; 208 if (candidateIndex == 1 << capacityPowerOfTwo) { 209 candidateIndex = 0; } 211 } 212 } 213 214 222 private long startIndexFor(long val) { 223 return (val >>> (64 - capacityPowerOfTwo)); 224 } 225 226 public boolean remove(long l) { 227 long i = indexFor(l); 228 if (!slotHasData(i)) { 229 return false; 231 } 232 removeAt(i); 233 return true; 234 } 235 236 242 protected void removeAt(long index) { 243 count--; 244 clearAt(index); 245 long probeIndex = index + 1; 246 while (true) { 247 if (probeIndex == 1 << capacityPowerOfTwo) { 248 probeIndex = 0; } 250 if (getSlotState(probeIndex) < 0) { 251 break; 253 } 254 long val = getAt(probeIndex); 255 long newIndex = indexFor(val); 256 if (newIndex != probeIndex) { 257 newIndex = asDataSlot(newIndex); relocate(val, probeIndex, newIndex); 260 } 261 probeIndex++; 262 } 263 } 264 265 protected abstract void clearAt(long index); 266 267 protected abstract void relocate(long value, long fromIndex, long toIndex); 268 269 275 public boolean quickContains(long fp) { 276 return false; 277 } 278 279 286 private long asDataSlot(final long index) { 287 if (slotHasData(index)) { return index; 289 } 290 return - (index + 1); 291 } 292 293 299 private long asEmptySlot(final long index) { 300 if (!slotHasData(index)) { return index; 302 } 303 return -index - 1; 304 } 305 306 312 private boolean slotHasData(final long index) { 313 return index >= 0; 314 } 315 } | Popular Tags |