InflatingBitSet.java

  1. /*
  2.  * Copyright (C) 2012, Google Inc. and others
  3.  *
  4.  * This program and the accompanying materials are made available under the
  5.  * terms of the Eclipse Distribution License v. 1.0 which is available at
  6.  * https://www.eclipse.org/org/documents/edl-v10.php.
  7.  *
  8.  * SPDX-License-Identifier: BSD-3-Clause
  9.  */

  10. package org.eclipse.jgit.internal.storage.file;

  11. import com.googlecode.javaewah.EWAHCompressedBitmap;
  12. import com.googlecode.javaewah.IntIterator;

  13. /**
  14.  * A wrapper around the EWAHCompressedBitmap optimized for the contains
  15.  * operation.
  16.  */
  17. final class InflatingBitSet {
  18.     private static final long[] EMPTY = new long[0];

  19.     private final EWAHCompressedBitmap bitmap;

  20.     private IntIterator iterator;

  21.     private long[] inflated;

  22.     private int nextPosition = -1;

  23.     private final int sizeInBits;

  24.     InflatingBitSet(EWAHCompressedBitmap bitmap) {
  25.         this(bitmap, EMPTY);
  26.     }

  27.     private InflatingBitSet(EWAHCompressedBitmap orBitmap, long[] inflated) {
  28.         this.bitmap = orBitmap;
  29.         this.inflated = inflated;
  30.         this.sizeInBits = bitmap.sizeInBits();
  31.     }

  32.     final boolean maybeContains(int position) {
  33.         if (get(position))
  34.             return true;
  35.         return nextPosition <= position && position < sizeInBits;
  36.     }

  37.     final boolean contains(int position) {
  38.         if (get(position))
  39.             return true;
  40.         if (position <= nextPosition || position >= sizeInBits)
  41.             return position == nextPosition;

  42.         if (iterator == null) {
  43.             iterator = bitmap.intIterator();
  44.             if (iterator.hasNext())
  45.                 nextPosition = iterator.next();
  46.             else
  47.                 return false;
  48.         } else if (!iterator.hasNext())
  49.             return false;

  50.         int positionBlock = block(position);
  51.         if (positionBlock >= inflated.length) {
  52.             long[] tmp = new long[block(sizeInBits) + 1];
  53.             System.arraycopy(inflated, 0, tmp, 0, inflated.length);
  54.             inflated = tmp;
  55.         }

  56.         int block = block(nextPosition);
  57.         long word = mask(nextPosition);
  58.         int end = Math.max(nextPosition, position) | 63;
  59.         while (iterator.hasNext()) {
  60.             nextPosition = iterator.next();
  61.             if (end < nextPosition)
  62.                 break;

  63.             int b = block(nextPosition);
  64.             long m = mask(nextPosition);
  65.             if (block == b) {
  66.                 word |= m;
  67.             } else {
  68.                 inflated[block] = word;
  69.                 block = b;
  70.                 word = m;
  71.             }
  72.         }
  73.         inflated[block] = word;
  74.         return block == positionBlock && (word & mask(position)) != 0;
  75.     }

  76.     private final boolean get(int position) {
  77.         int b = block(position);
  78.         return b < inflated.length && (inflated[b] & mask(position)) != 0;
  79.     }

  80.     private static final int block(int position) {
  81.         return position >> 6;
  82.     }

  83.     private static final long mask(int position) {
  84.         return 1L << position;
  85.     }

  86.     private final boolean isEmpty() {
  87.         return sizeInBits == 0;
  88.     }

  89.     final InflatingBitSet or(EWAHCompressedBitmap other) {
  90.         if (other.sizeInBits() == 0)
  91.             return this;
  92.         return new InflatingBitSet(bitmap.or(other), inflated);
  93.     }

  94.     final InflatingBitSet andNot(EWAHCompressedBitmap other) {
  95.         if (isEmpty())
  96.             return this;
  97.         return new InflatingBitSet(bitmap.andNot(other));
  98.     }

  99.     final InflatingBitSet xor(EWAHCompressedBitmap other) {
  100.         if (isEmpty()) {
  101.             if (other.sizeInBits() == 0)
  102.                 return this;
  103.             return new InflatingBitSet(other);
  104.         }
  105.         return new InflatingBitSet(bitmap.xor(other));
  106.     }

  107.     final EWAHCompressedBitmap getBitmap() {
  108.         return bitmap;
  109.     }
  110. }