All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.squareup.okhttp.internal.BitArray Maven / Gradle / Ivy

There is a newer version: 2.7.5
Show newest version
/*
 * Copyright 2014 Square 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 com.squareup.okhttp.internal;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import static java.lang.String.format;

/** A simple bitset which supports left shifting. */
public interface BitArray {

  void clear();

  void set(int index);

  void toggle(int index);

  boolean get(int index);

  void shiftLeft(int count);

  /** Bit set that only supports settings bits 0 - 63. */
  public final class FixedCapacity implements BitArray {
    long data = 0x0000000000000000L;

    @Override public void clear() {
      data = 0x0000000000000000L;
    }

    @Override public void set(int index) {
      data |= (1L << checkInput(index));
    }

    @Override public void toggle(int index) {
      data ^= (1L << checkInput(index));
    }

    @Override public boolean get(int index) {
      return ((data >> checkInput(index)) & 1L) == 1;
    }

    @Override public void shiftLeft(int count) {
      data = data << checkInput(count);
    }

    @Override public String toString() {
      return Long.toBinaryString(data);
    }

    public BitArray toVariableCapacity() {
      return new VariableCapacity(this);
    }

    private static int checkInput(int index) {
      if (index < 0 || index > 63) {
        throw new IllegalArgumentException(format("input must be between 0 and 63: %s", index));
      }
      return index;
    }
  }

  /** Bit set that grows as needed. */
  public final class VariableCapacity implements BitArray {

    long[] data;

    // Start offset which allows for cheap shifting. Data is always kept on 64-bit bounds but we
    // offset the outward facing index to support shifts without having to move the underlying bits.
    private int start; // Valid values are [0..63]

    public VariableCapacity() {
      data = new long[1];
    }

    private VariableCapacity(FixedCapacity small) {
      data = new long[] {small.data, 0};
    }

    private void growToSize(int size) {
      long[] newData = new long[size];
      if (data != null) {
        System.arraycopy(data, 0, newData, 0, data.length);
      }
      data = newData;
    }

    private int offsetOf(int index) {
      index += start;
      int offset = index / 64;
      if (offset > data.length - 1) {
        growToSize(offset + 1);
      }
      return offset;
    }

    private int shiftOf(int index) {
      return (index + start) % 64;
    }

    @Override public void clear() {
      Arrays.fill(data, 0);
    }

    @Override public void set(int index) {
      checkInput(index);
      int offset = offsetOf(index);
      data[offset] |= 1L << shiftOf(index);
    }

    @Override public void toggle(int index) {
      checkInput(index);
      int offset = offsetOf(index);
      data[offset] ^= 1L << shiftOf(index);
    }

    @Override public boolean get(int index) {
      checkInput(index);
      int offset = offsetOf(index);
      return (data[offset] & (1L << shiftOf(index))) != 0;
    }

    @Override public void shiftLeft(int count) {
      start -= checkInput(count);
      if (start < 0) {
        int arrayShift = (start / -64) + 1;
        long[] newData = new long[data.length + arrayShift];
        System.arraycopy(data, 0, newData, arrayShift, data.length);
        data = newData;
        start = 64 + (start % 64);
      }
    }

    @Override public String toString() {
      StringBuilder builder = new StringBuilder("{");
      List ints = toIntegerList();
      for (int i = 0, count = ints.size(); i < count; i++) {
        if (i > 0) {
          builder.append(',');
        }
        builder.append(ints.get(i));
      }
      return builder.append('}').toString();
    }

    List toIntegerList() {
      List ints = new ArrayList();
      for (int i = 0, count = data.length * 64 - start; i < count; i++) {
        if (get(i)) {
          ints.add(i);
        }
      }
      return ints;
    }

    private static int checkInput(int index) {
      if (index < 0) {
        throw new IllegalArgumentException(format("input must be a positive number: %s", index));
      }
      return index;
    }
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy