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

com.google.protobuf.nano.FieldArray Maven / Gradle / Ivy

Go to download

Protocol Buffers are a way of encoding structured data in an efficient yet extensible format.

There is a newer version: 3.2.0rc2
Show newest version
// Protocol Buffers - Google's data interchange format
// Copyright 2014 Google Inc.  All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//     * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//     * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

package com.google.protobuf.nano;


/**
 * A custom version of {@code android.util.SparseArray} with the minimal API
 * for storing {@link FieldData} objects.
 *
 * 

This class is an internal implementation detail of nano and should not * be called directly by clients. * * Based on {@code android.support.v4.util.SpareArrayCompat}. */ public final class FieldArray implements Cloneable { private static final FieldData DELETED = new FieldData(); private boolean mGarbage = false; private int[] mFieldNumbers; private FieldData[] mData; private int mSize; /** * Creates a new FieldArray containing no fields. */ FieldArray() { this(10); } /** * Creates a new FieldArray containing no mappings that will not * require any additional memory allocation to store the specified * number of mappings. */ FieldArray(int initialCapacity) { initialCapacity = idealIntArraySize(initialCapacity); mFieldNumbers = new int[initialCapacity]; mData = new FieldData[initialCapacity]; mSize = 0; } /** * Gets the FieldData mapped from the specified fieldNumber, or null * if no such mapping has been made. */ FieldData get(int fieldNumber) { int i = binarySearch(fieldNumber); if (i < 0 || mData[i] == DELETED) { return null; } else { return mData[i]; } } /** * Removes the data from the specified fieldNumber, if there was any. */ void remove(int fieldNumber) { int i = binarySearch(fieldNumber); if (i >= 0 && mData[i] != DELETED) { mData[i] = DELETED; mGarbage = true; } } private void gc() { int n = mSize; int o = 0; int[] keys = mFieldNumbers; FieldData[] values = mData; for (int i = 0; i < n; i++) { FieldData val = values[i]; if (val != DELETED) { if (i != o) { keys[o] = keys[i]; values[o] = val; values[i] = null; } o++; } } mGarbage = false; mSize = o; } /** * Adds a mapping from the specified fieldNumber to the specified data, * replacing the previous mapping if there was one. */ void put(int fieldNumber, FieldData data) { int i = binarySearch(fieldNumber); if (i >= 0) { mData[i] = data; } else { i = ~i; if (i < mSize && mData[i] == DELETED) { mFieldNumbers[i] = fieldNumber; mData[i] = data; return; } if (mGarbage && mSize >= mFieldNumbers.length) { gc(); // Search again because indices may have changed. i = ~ binarySearch(fieldNumber); } if (mSize >= mFieldNumbers.length) { int n = idealIntArraySize(mSize + 1); int[] nkeys = new int[n]; FieldData[] nvalues = new FieldData[n]; System.arraycopy(mFieldNumbers, 0, nkeys, 0, mFieldNumbers.length); System.arraycopy(mData, 0, nvalues, 0, mData.length); mFieldNumbers = nkeys; mData = nvalues; } if (mSize - i != 0) { System.arraycopy(mFieldNumbers, i, mFieldNumbers, i + 1, mSize - i); System.arraycopy(mData, i, mData, i + 1, mSize - i); } mFieldNumbers[i] = fieldNumber; mData[i] = data; mSize++; } } /** * Returns the number of key-value mappings that this FieldArray * currently stores. */ int size() { if (mGarbage) { gc(); } return mSize; } public boolean isEmpty() { return size() == 0; } /** * Given an index in the range 0...size()-1, returns * the value from the indexth key-value mapping that this * FieldArray stores. */ FieldData dataAt(int index) { if (mGarbage) { gc(); } return mData[index]; } @Override public boolean equals(Object o) { if (o == this) { return true; } if (!(o instanceof FieldArray)) { return false; } FieldArray other = (FieldArray) o; if (size() != other.size()) { // size() will call gc() if necessary. return false; } return arrayEquals(mFieldNumbers, other.mFieldNumbers, mSize) && arrayEquals(mData, other.mData, mSize); } @Override public int hashCode() { if (mGarbage) { gc(); } int result = 17; for (int i = 0; i < mSize; i++) { result = 31 * result + mFieldNumbers[i]; result = 31 * result + mData[i].hashCode(); } return result; } private int idealIntArraySize(int need) { return idealByteArraySize(need * 4) / 4; } private int idealByteArraySize(int need) { for (int i = 4; i < 32; i++) if (need <= (1 << i) - 12) return (1 << i) - 12; return need; } private int binarySearch(int value) { int lo = 0; int hi = mSize - 1; while (lo <= hi) { int mid = (lo + hi) >>> 1; int midVal = mFieldNumbers[mid]; if (midVal < value) { lo = mid + 1; } else if (midVal > value) { hi = mid - 1; } else { return mid; // value found } } return ~lo; // value not present } private boolean arrayEquals(int[] a, int[] b, int size) { for (int i = 0; i < size; i++) { if (a[i] != b[i]) { return false; } } return true; } private boolean arrayEquals(FieldData[] a, FieldData[] b, int size) { for (int i = 0; i < size; i++) { if (!a[i].equals(b[i])) { return false; } } return true; } @Override public final FieldArray clone() { // Trigger GC so we compact and don't copy DELETED elements. int size = size(); FieldArray clone = new FieldArray(size); System.arraycopy(mFieldNumbers, 0, clone.mFieldNumbers, 0, size); for (int i = 0; i < size; i++) { if (mData[i] != null) { clone.mData[i] = mData[i].clone(); } } clone.mSize = size; return clone; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy