parent
56095026cc
commit
5db217305f
227 changed files with 25713 additions and 3789 deletions
@ -0,0 +1,136 @@ |
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 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; |
||||
|
||||
import com.google.protobuf.Internal.ProtobufList; |
||||
|
||||
import java.util.AbstractList; |
||||
import java.util.Collection; |
||||
|
||||
/** |
||||
* An abstract implementation of {@link ProtobufList} which manages mutability semantics. All mutate |
||||
* methods are check if the list is mutable before proceeding. Subclasses must invoke |
||||
* {@link #ensureIsMutable()} manually when overriding those methods. |
||||
*/ |
||||
abstract class AbstractProtobufList<E> extends AbstractList<E> implements ProtobufList<E> { |
||||
|
||||
/** |
||||
* Whether or not this list is modifiable. |
||||
*/ |
||||
private boolean isMutable; |
||||
|
||||
/** |
||||
* Constructs a mutable list by default. |
||||
*/ |
||||
AbstractProtobufList() { |
||||
isMutable = true; |
||||
} |
||||
|
||||
@Override |
||||
public boolean add(E e) { |
||||
ensureIsMutable(); |
||||
return super.add(e); |
||||
} |
||||
|
||||
@Override |
||||
public void add(int index, E element) { |
||||
ensureIsMutable(); |
||||
super.add(index, element); |
||||
} |
||||
|
||||
@Override |
||||
public boolean addAll(Collection<? extends E> c) { |
||||
ensureIsMutable(); |
||||
return super.addAll(c); |
||||
} |
||||
|
||||
@Override |
||||
public boolean addAll(int index, Collection<? extends E> c) { |
||||
ensureIsMutable(); |
||||
return super.addAll(index, c); |
||||
} |
||||
|
||||
@Override |
||||
public void clear() { |
||||
ensureIsMutable(); |
||||
super.clear(); |
||||
} |
||||
|
||||
@Override |
||||
public boolean isModifiable() { |
||||
return isMutable; |
||||
} |
||||
|
||||
@Override |
||||
public final void makeImmutable() { |
||||
isMutable = false; |
||||
} |
||||
|
||||
@Override |
||||
public E remove(int index) { |
||||
ensureIsMutable(); |
||||
return super.remove(index); |
||||
} |
||||
|
||||
@Override |
||||
public boolean remove(Object o) { |
||||
ensureIsMutable(); |
||||
return super.remove(o); |
||||
} |
||||
|
||||
@Override |
||||
public boolean removeAll(Collection<?> c) { |
||||
ensureIsMutable(); |
||||
return super.removeAll(c); |
||||
} |
||||
|
||||
@Override |
||||
public boolean retainAll(Collection<?> c) { |
||||
ensureIsMutable(); |
||||
return super.retainAll(c); |
||||
} |
||||
|
||||
@Override |
||||
public E set(int index, E element) { |
||||
ensureIsMutable(); |
||||
return super.set(index, element); |
||||
} |
||||
|
||||
/** |
||||
* Throws an {@link UnsupportedOperationException} if the list is immutable. Subclasses are |
||||
* responsible for invoking this method on mutate operations. |
||||
*/ |
||||
protected void ensureIsMutable() { |
||||
if (!isMutable) { |
||||
throw new UnsupportedOperationException(); |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,244 @@ |
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 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; |
||||
|
||||
import com.google.protobuf.Internal.BooleanList; |
||||
|
||||
import java.util.Arrays; |
||||
import java.util.Collection; |
||||
import java.util.List; |
||||
import java.util.RandomAccess; |
||||
|
||||
/** |
||||
* An implementation of {@link BooleanList} on top of a primitive array. |
||||
* |
||||
* @author dweis@google.com (Daniel Weis) |
||||
*/ |
||||
final class BooleanArrayList |
||||
extends AbstractProtobufList<Boolean> implements BooleanList, RandomAccess { |
||||
|
||||
private static final int DEFAULT_CAPACITY = 10; |
||||
|
||||
private static final BooleanArrayList EMPTY_LIST = new BooleanArrayList(); |
||||
static { |
||||
EMPTY_LIST.makeImmutable(); |
||||
} |
||||
|
||||
public static BooleanArrayList emptyList() { |
||||
return EMPTY_LIST; |
||||
} |
||||
|
||||
/** |
||||
* The backing store for the list. |
||||
*/ |
||||
private boolean[] array; |
||||
|
||||
/** |
||||
* The size of the list distinct from the length of the array. That is, it is the number of |
||||
* elements set in the list. |
||||
*/ |
||||
private int size; |
||||
|
||||
/** |
||||
* Constructs a new mutable {@code BooleanArrayList}. |
||||
*/ |
||||
BooleanArrayList() { |
||||
array = new boolean[DEFAULT_CAPACITY]; |
||||
size = 0; |
||||
} |
||||
|
||||
/** |
||||
* Constructs a new mutable {@code BooleanArrayList} containing the same elements as |
||||
* {@code other}. |
||||
*/ |
||||
BooleanArrayList(List<Boolean> other) { |
||||
if (other instanceof BooleanArrayList) { |
||||
BooleanArrayList list = (BooleanArrayList) other; |
||||
array = list.array.clone(); |
||||
size = list.size; |
||||
} else { |
||||
size = other.size(); |
||||
array = new boolean[size]; |
||||
for (int i = 0; i < size; i++) { |
||||
array[i] = other.get(i); |
||||
} |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
public Boolean get(int index) { |
||||
return getBoolean(index); |
||||
} |
||||
|
||||
@Override |
||||
public boolean getBoolean(int index) { |
||||
ensureIndexInRange(index); |
||||
return array[index]; |
||||
} |
||||
|
||||
@Override |
||||
public int size() { |
||||
return size; |
||||
} |
||||
|
||||
@Override |
||||
public Boolean set(int index, Boolean element) { |
||||
return setBoolean(index, element); |
||||
} |
||||
|
||||
@Override |
||||
public boolean setBoolean(int index, boolean element) { |
||||
ensureIsMutable(); |
||||
ensureIndexInRange(index); |
||||
boolean previousValue = array[index]; |
||||
array[index] = element; |
||||
return previousValue; |
||||
} |
||||
|
||||
@Override |
||||
public void add(int index, Boolean element) { |
||||
addBoolean(index, element); |
||||
} |
||||
|
||||
/** |
||||
* Like {@link #add(Boolean)} but more efficient in that it doesn't box the element. |
||||
*/ |
||||
@Override |
||||
public void addBoolean(boolean element) { |
||||
addBoolean(size, element); |
||||
} |
||||
|
||||
/** |
||||
* Like {@link #add(int, Boolean)} but more efficient in that it doesn't box the element. |
||||
*/ |
||||
private void addBoolean(int index, boolean element) { |
||||
ensureIsMutable(); |
||||
if (index < 0 || index > size) { |
||||
throw new IndexOutOfBoundsException(makeOutOfBoundsExceptionMessage(index)); |
||||
} |
||||
|
||||
if (size < array.length) { |
||||
// Shift everything over to make room
|
||||
System.arraycopy(array, index, array, index + 1, size - index); |
||||
} else { |
||||
// Resize to 1.5x the size
|
||||
int length = ((size * 3) / 2) + 1; |
||||
boolean[] newArray = new boolean[length]; |
||||
|
||||
// Copy the first part directly
|
||||
System.arraycopy(array, 0, newArray, 0, index); |
||||
|
||||
// Copy the rest shifted over by one to make room
|
||||
System.arraycopy(array, index, newArray, index + 1, size - index); |
||||
array = newArray; |
||||
} |
||||
|
||||
array[index] = element; |
||||
size++; |
||||
modCount++; |
||||
} |
||||
|
||||
@Override |
||||
public boolean addAll(Collection<? extends Boolean> collection) { |
||||
ensureIsMutable(); |
||||
|
||||
if (collection == null) { |
||||
throw new NullPointerException(); |
||||
} |
||||
|
||||
// We specialize when adding another BooleanArrayList to avoid boxing elements.
|
||||
if (!(collection instanceof BooleanArrayList)) { |
||||
return super.addAll(collection); |
||||
} |
||||
|
||||
BooleanArrayList list = (BooleanArrayList) collection; |
||||
if (list.size == 0) { |
||||
return false; |
||||
} |
||||
|
||||
int overflow = Integer.MAX_VALUE - size; |
||||
if (overflow < list.size) { |
||||
// We can't actually represent a list this large.
|
||||
throw new OutOfMemoryError(); |
||||
} |
||||
|
||||
int newSize = size + list.size; |
||||
if (newSize > array.length) { |
||||
array = Arrays.copyOf(array, newSize); |
||||
} |
||||
|
||||
System.arraycopy(list.array, 0, array, size, list.size); |
||||
size = newSize; |
||||
modCount++; |
||||
return true; |
||||
} |
||||
|
||||
@Override |
||||
public boolean remove(Object o) { |
||||
ensureIsMutable(); |
||||
for (int i = 0; i < size; i++) { |
||||
if (o.equals(array[i])) { |
||||
System.arraycopy(array, i + 1, array, i, size - i); |
||||
size--; |
||||
modCount++; |
||||
return true; |
||||
} |
||||
} |
||||
return false; |
||||
} |
||||
|
||||
@Override |
||||
public Boolean remove(int index) { |
||||
ensureIsMutable(); |
||||
ensureIndexInRange(index); |
||||
boolean value = array[index]; |
||||
System.arraycopy(array, index + 1, array, index, size - index); |
||||
size--; |
||||
modCount++; |
||||
return value; |
||||
} |
||||
|
||||
/** |
||||
* Ensures that the provided {@code index} is within the range of {@code [0, size]}. Throws an |
||||
* {@link IndexOutOfBoundsException} if it is not. |
||||
* |
||||
* @param index the index to verify is in range |
||||
*/ |
||||
private void ensureIndexInRange(int index) { |
||||
if (index < 0 || index >= size) { |
||||
throw new IndexOutOfBoundsException(makeOutOfBoundsExceptionMessage(index)); |
||||
} |
||||
} |
||||
|
||||
private String makeOutOfBoundsExceptionMessage(int index) { |
||||
return "Index:" + index + ", Size:" + size; |
||||
} |
||||
} |
@ -0,0 +1,243 @@ |
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 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; |
||||
|
||||
import com.google.protobuf.Internal.DoubleList; |
||||
|
||||
import java.util.Arrays; |
||||
import java.util.Collection; |
||||
import java.util.List; |
||||
import java.util.RandomAccess; |
||||
|
||||
/** |
||||
* An implementation of {@link DoubleList} on top of a primitive array. |
||||
* |
||||
* @author dweis@google.com (Daniel Weis) |
||||
*/ |
||||
final class DoubleArrayList |
||||
extends AbstractProtobufList<Double> implements DoubleList, RandomAccess { |
||||
|
||||
private static final int DEFAULT_CAPACITY = 10; |
||||
|
||||
private static final DoubleArrayList EMPTY_LIST = new DoubleArrayList(); |
||||
static { |
||||
EMPTY_LIST.makeImmutable(); |
||||
} |
||||
|
||||
public static DoubleArrayList emptyList() { |
||||
return EMPTY_LIST; |
||||
} |
||||
|
||||
/** |
||||
* The backing store for the list. |
||||
*/ |
||||
private double[] array; |
||||
|
||||
/** |
||||
* The size of the list distinct from the length of the array. That is, it is the number of |
||||
* elements set in the list. |
||||
*/ |
||||
private int size; |
||||
|
||||
/** |
||||
* Constructs a new mutable {@code DoubleArrayList}. |
||||
*/ |
||||
DoubleArrayList() { |
||||
array = new double[DEFAULT_CAPACITY]; |
||||
size = 0; |
||||
} |
||||
|
||||
/** |
||||
* Constructs a new mutable {@code DoubleArrayList} containing the same elements as {@code other}. |
||||
*/ |
||||
DoubleArrayList(List<Double> other) { |
||||
if (other instanceof DoubleArrayList) { |
||||
DoubleArrayList list = (DoubleArrayList) other; |
||||
array = list.array.clone(); |
||||
size = list.size; |
||||
} else { |
||||
size = other.size(); |
||||
array = new double[size]; |
||||
for (int i = 0; i < size; i++) { |
||||
array[i] = other.get(i); |
||||
} |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
public Double get(int index) { |
||||
return getDouble(index); |
||||
} |
||||
|
||||
@Override |
||||
public double getDouble(int index) { |
||||
ensureIndexInRange(index); |
||||
return array[index]; |
||||
} |
||||
|
||||
@Override |
||||
public int size() { |
||||
return size; |
||||
} |
||||
|
||||
@Override |
||||
public Double set(int index, Double element) { |
||||
return setDouble(index, element); |
||||
} |
||||
|
||||
@Override |
||||
public double setDouble(int index, double element) { |
||||
ensureIsMutable(); |
||||
ensureIndexInRange(index); |
||||
double previousValue = array[index]; |
||||
array[index] = element; |
||||
return previousValue; |
||||
} |
||||
|
||||
@Override |
||||
public void add(int index, Double element) { |
||||
addDouble(index, element); |
||||
} |
||||
|
||||
/** |
||||
* Like {@link #add(Double)} but more efficient in that it doesn't box the element. |
||||
*/ |
||||
@Override |
||||
public void addDouble(double element) { |
||||
addDouble(size, element); |
||||
} |
||||
|
||||
/** |
||||
* Like {@link #add(int, Double)} but more efficient in that it doesn't box the element. |
||||
*/ |
||||
private void addDouble(int index, double element) { |
||||
ensureIsMutable(); |
||||
if (index < 0 || index > size) { |
||||
throw new IndexOutOfBoundsException(makeOutOfBoundsExceptionMessage(index)); |
||||
} |
||||
|
||||
if (size < array.length) { |
||||
// Shift everything over to make room
|
||||
System.arraycopy(array, index, array, index + 1, size - index); |
||||
} else { |
||||
// Resize to 1.5x the size
|
||||
int length = ((size * 3) / 2) + 1; |
||||
double[] newArray = new double[length]; |
||||
|
||||
// Copy the first part directly
|
||||
System.arraycopy(array, 0, newArray, 0, index); |
||||
|
||||
// Copy the rest shifted over by one to make room
|
||||
System.arraycopy(array, index, newArray, index + 1, size - index); |
||||
array = newArray; |
||||
} |
||||
|
||||
array[index] = element; |
||||
size++; |
||||
modCount++; |
||||
} |
||||
|
||||
@Override |
||||
public boolean addAll(Collection<? extends Double> collection) { |
||||
ensureIsMutable(); |
||||
|
||||
if (collection == null) { |
||||
throw new NullPointerException(); |
||||
} |
||||
|
||||
// We specialize when adding another DoubleArrayList to avoid boxing elements.
|
||||
if (!(collection instanceof DoubleArrayList)) { |
||||
return super.addAll(collection); |
||||
} |
||||
|
||||
DoubleArrayList list = (DoubleArrayList) collection; |
||||
if (list.size == 0) { |
||||
return false; |
||||
} |
||||
|
||||
int overflow = Integer.MAX_VALUE - size; |
||||
if (overflow < list.size) { |
||||
// We can't actually represent a list this large.
|
||||
throw new OutOfMemoryError(); |
||||
} |
||||
|
||||
int newSize = size + list.size; |
||||
if (newSize > array.length) { |
||||
array = Arrays.copyOf(array, newSize); |
||||
} |
||||
|
||||
System.arraycopy(list.array, 0, array, size, list.size); |
||||
size = newSize; |
||||
modCount++; |
||||
return true; |
||||
} |
||||
|
||||
@Override |
||||
public boolean remove(Object o) { |
||||
ensureIsMutable(); |
||||
for (int i = 0; i < size; i++) { |
||||
if (o.equals(array[i])) { |
||||
System.arraycopy(array, i + 1, array, i, size - i); |
||||
size--; |
||||
modCount++; |
||||
return true; |
||||
} |
||||
} |
||||
return false; |
||||
} |
||||
|
||||
@Override |
||||
public Double remove(int index) { |
||||
ensureIsMutable(); |
||||
ensureIndexInRange(index); |
||||
double value = array[index]; |
||||
System.arraycopy(array, index + 1, array, index, size - index); |
||||
size--; |
||||
modCount++; |
||||
return value; |
||||
} |
||||
|
||||
/** |
||||
* Ensures that the provided {@code index} is within the range of {@code [0, size]}. Throws an |
||||
* {@link IndexOutOfBoundsException} if it is not. |
||||
* |
||||
* @param index the index to verify is in range |
||||
*/ |
||||
private void ensureIndexInRange(int index) { |
||||
if (index < 0 || index >= size) { |
||||
throw new IndexOutOfBoundsException(makeOutOfBoundsExceptionMessage(index)); |
||||
} |
||||
} |
||||
|
||||
private String makeOutOfBoundsExceptionMessage(int index) { |
||||
return "Index:" + index + ", Size:" + size; |
||||
} |
||||
} |
@ -0,0 +1,242 @@ |
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 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; |
||||
|
||||
import com.google.protobuf.Internal.FloatList; |
||||
|
||||
import java.util.Arrays; |
||||
import java.util.Collection; |
||||
import java.util.List; |
||||
import java.util.RandomAccess; |
||||
|
||||
/** |
||||
* An implementation of {@link FloatList} on top of a primitive array. |
||||
* |
||||
* @author dweis@google.com (Daniel Weis) |
||||
*/ |
||||
final class FloatArrayList extends AbstractProtobufList<Float> implements FloatList, RandomAccess { |
||||
|
||||
private static final int DEFAULT_CAPACITY = 10; |
||||
|
||||
private static final FloatArrayList EMPTY_LIST = new FloatArrayList(); |
||||
static { |
||||
EMPTY_LIST.makeImmutable(); |
||||
} |
||||
|
||||
public static FloatArrayList emptyList() { |
||||
return EMPTY_LIST; |
||||
} |
||||
|
||||
/** |
||||
* The backing store for the list. |
||||
*/ |
||||
private float[] array; |
||||
|
||||
/** |
||||
* The size of the list distinct from the length of the array. That is, it is the number of |
||||
* elements set in the list. |
||||
*/ |
||||
private int size; |
||||
|
||||
/** |
||||
* Constructs a new mutable {@code FloatArrayList}. |
||||
*/ |
||||
FloatArrayList() { |
||||
array = new float[DEFAULT_CAPACITY]; |
||||
size = 0; |
||||
} |
||||
|
||||
/** |
||||
* Constructs a new mutable {@code FloatArrayList} containing the same elements as {@code other}. |
||||
*/ |
||||
FloatArrayList(List<Float> other) { |
||||
if (other instanceof FloatArrayList) { |
||||
FloatArrayList list = (FloatArrayList) other; |
||||
array = list.array.clone(); |
||||
size = list.size; |
||||
} else { |
||||
size = other.size(); |
||||
array = new float[size]; |
||||
for (int i = 0; i < size; i++) { |
||||
array[i] = other.get(i); |
||||
} |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
public Float get(int index) { |
||||
return getFloat(index); |
||||
} |
||||
|
||||
@Override |
||||
public float getFloat(int index) { |
||||
ensureIndexInRange(index); |
||||
return array[index]; |
||||
} |
||||
|
||||
@Override |
||||
public int size() { |
||||
return size; |
||||
} |
||||
|
||||
@Override |
||||
public Float set(int index, Float element) { |
||||
return setFloat(index, element); |
||||
} |
||||
|
||||
@Override |
||||
public float setFloat(int index, float element) { |
||||
ensureIsMutable(); |
||||
ensureIndexInRange(index); |
||||
float previousValue = array[index]; |
||||
array[index] = element; |
||||
return previousValue; |
||||
} |
||||
|
||||
@Override |
||||
public void add(int index, Float element) { |
||||
addFloat(index, element); |
||||
} |
||||
|
||||
/** |
||||
* Like {@link #add(Float)} but more efficient in that it doesn't box the element. |
||||
*/ |
||||
@Override |
||||
public void addFloat(float element) { |
||||
addFloat(size, element); |
||||
} |
||||
|
||||
/** |
||||
* Like {@link #add(int, Float)} but more efficient in that it doesn't box the element. |
||||
*/ |
||||
private void addFloat(int index, float element) { |
||||
ensureIsMutable(); |
||||
if (index < 0 || index > size) { |
||||
throw new IndexOutOfBoundsException(makeOutOfBoundsExceptionMessage(index)); |
||||
} |
||||
|
||||
if (size < array.length) { |
||||
// Shift everything over to make room
|
||||
System.arraycopy(array, index, array, index + 1, size - index); |
||||
} else { |
||||
// Resize to 1.5x the size
|
||||
int length = ((size * 3) / 2) + 1; |
||||
float[] newArray = new float[length]; |
||||
|
||||
// Copy the first part directly
|
||||
System.arraycopy(array, 0, newArray, 0, index); |
||||
|
||||
// Copy the rest shifted over by one to make room
|
||||
System.arraycopy(array, index, newArray, index + 1, size - index); |
||||
array = newArray; |
||||
} |
||||
|
||||
array[index] = element; |
||||
size++; |
||||
modCount++; |
||||
} |
||||
|
||||
@Override |
||||
public boolean addAll(Collection<? extends Float> collection) { |
||||
ensureIsMutable(); |
||||
|
||||
if (collection == null) { |
||||
throw new NullPointerException(); |
||||
} |
||||
|
||||
// We specialize when adding another FloatArrayList to avoid boxing elements.
|
||||
if (!(collection instanceof FloatArrayList)) { |
||||
return super.addAll(collection); |
||||
} |
||||
|
||||
FloatArrayList list = (FloatArrayList) collection; |
||||
if (list.size == 0) { |
||||
return false; |
||||
} |
||||
|
||||
int overflow = Integer.MAX_VALUE - size; |
||||
if (overflow < list.size) { |
||||
// We can't actually represent a list this large.
|
||||
throw new OutOfMemoryError(); |
||||
} |
||||
|
||||
int newSize = size + list.size; |
||||
if (newSize > array.length) { |
||||
array = Arrays.copyOf(array, newSize); |
||||
} |
||||
|
||||
System.arraycopy(list.array, 0, array, size, list.size); |
||||
size = newSize; |
||||
modCount++; |
||||
return true; |
||||
} |
||||
|
||||
@Override |
||||
public boolean remove(Object o) { |
||||
ensureIsMutable(); |
||||
for (int i = 0; i < size; i++) { |
||||
if (o.equals(array[i])) { |
||||
System.arraycopy(array, i + 1, array, i, size - i); |
||||
size--; |
||||
modCount++; |
||||
return true; |
||||
} |
||||
} |
||||
return false; |
||||
} |
||||
|
||||
@Override |
||||
public Float remove(int index) { |
||||
ensureIsMutable(); |
||||
ensureIndexInRange(index); |
||||
float value = array[index]; |
||||
System.arraycopy(array, index + 1, array, index, size - index); |
||||
size--; |
||||
modCount++; |
||||
return value; |
||||
} |
||||
|
||||
/** |
||||
* Ensures that the provided {@code index} is within the range of {@code [0, size]}. Throws an |
||||
* {@link IndexOutOfBoundsException} if it is not. |
||||
* |
||||
* @param index the index to verify is in range |
||||
*/ |
||||
private void ensureIndexInRange(int index) { |
||||
if (index < 0 || index >= size) { |
||||
throw new IndexOutOfBoundsException(makeOutOfBoundsExceptionMessage(index)); |
||||
} |
||||
} |
||||
|
||||
private String makeOutOfBoundsExceptionMessage(int index) { |
||||
return "Index:" + index + ", Size:" + size; |
||||
} |
||||
} |
@ -0,0 +1,242 @@ |
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 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; |
||||
|
||||
import com.google.protobuf.Internal.IntList; |
||||
|
||||
import java.util.Arrays; |
||||
import java.util.Collection; |
||||
import java.util.List; |
||||
import java.util.RandomAccess; |
||||
|
||||
/** |
||||
* An implementation of {@link IntList} on top of a primitive array. |
||||
* |
||||
* @author dweis@google.com (Daniel Weis) |
||||
*/ |
||||
final class IntArrayList extends AbstractProtobufList<Integer> implements IntList, RandomAccess { |
||||
|
||||
private static final int DEFAULT_CAPACITY = 10; |
||||
|
||||
private static final IntArrayList EMPTY_LIST = new IntArrayList(); |
||||
static { |
||||
EMPTY_LIST.makeImmutable(); |
||||
} |
||||
|
||||
public static IntArrayList emptyList() { |
||||
return EMPTY_LIST; |
||||
} |
||||
|
||||
/** |
||||
* The backing store for the list. |
||||
*/ |
||||
private int[] array; |
||||
|
||||
/** |
||||
* The size of the list distinct from the length of the array. That is, it is the number of |
||||
* elements set in the list. |
||||
*/ |
||||
private int size; |
||||
|
||||
/** |
||||
* Constructs a new mutable {@code IntArrayList}. |
||||
*/ |
||||
IntArrayList() { |
||||
array = new int[DEFAULT_CAPACITY]; |
||||
size = 0; |
||||
} |
||||
|
||||
/** |
||||
* Constructs a new mutable {@code IntArrayList} containing the same elements as {@code other}. |
||||
*/ |
||||
IntArrayList(List<Integer> other) { |
||||
if (other instanceof IntArrayList) { |
||||
IntArrayList list = (IntArrayList) other; |
||||
array = list.array.clone(); |
||||
size = list.size; |
||||
} else { |
||||
size = other.size(); |
||||
array = new int[size]; |
||||
for (int i = 0; i < size; i++) { |
||||
array[i] = other.get(i); |
||||
} |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
public Integer get(int index) { |
||||
return getInt(index); |
||||
} |
||||
|
||||
@Override |
||||
public int getInt(int index) { |
||||
ensureIndexInRange(index); |
||||
return array[index]; |
||||
} |
||||
|
||||
@Override |
||||
public int size() { |
||||
return size; |
||||
} |
||||
|
||||
@Override |
||||
public Integer set(int index, Integer element) { |
||||
return setInt(index, element); |
||||
} |
||||
|
||||
@Override |
||||
public int setInt(int index, int element) { |
||||
ensureIsMutable(); |
||||
ensureIndexInRange(index); |
||||
int previousValue = array[index]; |
||||
array[index] = element; |
||||
return previousValue; |
||||
} |
||||
|
||||
@Override |
||||
public void add(int index, Integer element) { |
||||
addInt(index, element); |
||||
} |
||||
|
||||
/** |
||||
* Like {@link #add(Integer)} but more efficient in that it doesn't box the element. |
||||
*/ |
||||
@Override |
||||
public void addInt(int element) { |
||||
addInt(size, element); |
||||
} |
||||
|
||||
/** |
||||
* Like {@link #add(int, Integer)} but more efficient in that it doesn't box the element. |
||||
*/ |
||||
private void addInt(int index, int element) { |
||||
ensureIsMutable(); |
||||
if (index < 0 || index > size) { |
||||
throw new IndexOutOfBoundsException(makeOutOfBoundsExceptionMessage(index)); |
||||
} |
||||
|
||||
if (size < array.length) { |
||||
// Shift everything over to make room
|
||||
System.arraycopy(array, index, array, index + 1, size - index); |
||||
} else { |
||||
// Resize to 1.5x the size
|
||||
int length = ((size * 3) / 2) + 1; |
||||
int[] newArray = new int[length]; |
||||
|
||||
// Copy the first part directly
|
||||
System.arraycopy(array, 0, newArray, 0, index); |
||||
|
||||
// Copy the rest shifted over by one to make room
|
||||
System.arraycopy(array, index, newArray, index + 1, size - index); |
||||
array = newArray; |
||||
} |
||||
|
||||
array[index] = element; |
||||
size++; |
||||
modCount++; |
||||
} |
||||
|
||||
@Override |
||||
public boolean addAll(Collection<? extends Integer> collection) { |
||||
ensureIsMutable(); |
||||
|
||||
if (collection == null) { |
||||
throw new NullPointerException(); |
||||
} |
||||
|
||||
// We specialize when adding another IntArrayList to avoid boxing elements.
|
||||
if (!(collection instanceof IntArrayList)) { |
||||
return super.addAll(collection); |
||||
} |
||||
|
||||
IntArrayList list = (IntArrayList) collection; |
||||
if (list.size == 0) { |
||||
return false; |
||||
} |
||||
|
||||
int overflow = Integer.MAX_VALUE - size; |
||||
if (overflow < list.size) { |
||||
// We can't actually represent a list this large.
|
||||
throw new OutOfMemoryError(); |
||||
} |
||||
|
||||
int newSize = size + list.size; |
||||
if (newSize > array.length) { |
||||
array = Arrays.copyOf(array, newSize); |
||||
} |
||||
|
||||
System.arraycopy(list.array, 0, array, size, list.size); |
||||
size = newSize; |
||||
modCount++; |
||||
return true; |
||||
} |
||||
|
||||
@Override |
||||
public boolean remove(Object o) { |
||||
ensureIsMutable(); |
||||
for (int i = 0; i < size; i++) { |
||||
if (o.equals(array[i])) { |
||||
System.arraycopy(array, i + 1, array, i, size - i); |
||||
size--; |
||||
modCount++; |
||||
return true; |
||||
} |
||||
} |
||||
return false; |
||||
} |
||||
|
||||
@Override |
||||
public Integer remove(int index) { |
||||
ensureIsMutable(); |
||||
ensureIndexInRange(index); |
||||
int value = array[index]; |
||||
System.arraycopy(array, index + 1, array, index, size - index); |
||||
size--; |
||||
modCount++; |
||||
return value; |
||||
} |
||||
|
||||
/** |
||||
* Ensures that the provided {@code index} is within the range of {@code [0, size]}. Throws an |
||||
* {@link IndexOutOfBoundsException} if it is not. |
||||
* |
||||
* @param index the index to verify is in range |
||||
*/ |
||||
private void ensureIndexInRange(int index) { |
||||
if (index < 0 || index >= size) { |
||||
throw new IndexOutOfBoundsException(makeOutOfBoundsExceptionMessage(index)); |
||||
} |
||||
} |
||||
|
||||
private String makeOutOfBoundsExceptionMessage(int index) { |
||||
return "Index:" + index + ", Size:" + size; |
||||
} |
||||
} |
@ -0,0 +1,242 @@ |
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 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; |
||||
|
||||
import com.google.protobuf.Internal.LongList; |
||||
|
||||
import java.util.Arrays; |
||||
import java.util.Collection; |
||||
import java.util.List; |
||||
import java.util.RandomAccess; |
||||
|
||||
/** |
||||
* An implementation of {@link LongList} on top of a primitive array. |
||||
* |
||||
* @author dweis@google.com (Daniel Weis) |
||||
*/ |
||||
final class LongArrayList extends AbstractProtobufList<Long> implements LongList, RandomAccess { |
||||
|
||||
private static final int DEFAULT_CAPACITY = 10; |
||||
|
||||
private static final LongArrayList EMPTY_LIST = new LongArrayList(); |
||||
static { |
||||
EMPTY_LIST.makeImmutable(); |
||||
} |
||||
|
||||
public static LongArrayList emptyList() { |
||||
return EMPTY_LIST; |
||||
} |
||||
|
||||
/** |
||||
* The backing store for the list. |
||||
*/ |
||||
private long[] array; |
||||
|
||||
/** |
||||
* The size of the list distinct from the length of the array. That is, it is the number of |
||||
* elements set in the list. |
||||
*/ |
||||
private int size; |
||||
|
||||
/** |
||||
* Constructs a new mutable {@code LongArrayList}. |
||||
*/ |
||||
LongArrayList() { |
||||
array = new long[DEFAULT_CAPACITY]; |
||||
size = 0; |
||||
} |
||||
|
||||
/** |
||||
* Constructs a new mutable {@code LongArrayList} containing the same elements as {@code other}. |
||||
*/ |
||||
LongArrayList(List<Long> other) { |
||||
if (other instanceof LongArrayList) { |
||||
LongArrayList list = (LongArrayList) other; |
||||
array = list.array.clone(); |
||||
size = list.size; |
||||
} else { |
||||
size = other.size(); |
||||
array = new long[size]; |
||||
for (int i = 0; i < size; i++) { |
||||
array[i] = other.get(i); |
||||
} |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
public Long get(int index) { |
||||
return getLong(index); |
||||
} |
||||
|
||||
@Override |
||||
public long getLong(int index) { |
||||
ensureIndexInRange(index); |
||||
return array[index]; |
||||
} |
||||
|
||||
@Override |
||||
public int size() { |
||||
return size; |
||||
} |
||||
|
||||
@Override |
||||
public Long set(int index, Long element) { |
||||
return setLong(index, element); |
||||
} |
||||
|
||||
@Override |
||||
public long setLong(int index, long element) { |
||||
ensureIsMutable(); |
||||
ensureIndexInRange(index); |
||||
long previousValue = array[index]; |
||||
array[index] = element; |
||||
return previousValue; |
||||
} |
||||
|
||||
@Override |
||||
public void add(int index, Long element) { |
||||
addLong(index, element); |
||||
} |
||||
|
||||
/** |
||||
* Like {@link #add(Long)} but more efficient in that it doesn't box the element. |
||||
*/ |
||||
@Override |
||||
public void addLong(long element) { |
||||
addLong(size, element); |
||||
} |
||||
|
||||
/** |
||||
* Like {@link #add(int, Long)} but more efficient in that it doesn't box the element. |
||||
*/ |
||||
private void addLong(int index, long element) { |
||||
ensureIsMutable(); |
||||
if (index < 0 || index > size) { |
||||
throw new IndexOutOfBoundsException(makeOutOfBoundsExceptionMessage(index)); |
||||
} |
||||
|
||||
if (size < array.length) { |
||||
// Shift everything over to make room
|
||||
System.arraycopy(array, index, array, index + 1, size - index); |
||||
} else { |
||||
// Resize to 1.5x the size
|
||||
int length = ((size * 3) / 2) + 1; |
||||
long[] newArray = new long[length]; |
||||
|
||||
// Copy the first part directly
|
||||
System.arraycopy(array, 0, newArray, 0, index); |
||||
|
||||
// Copy the rest shifted over by one to make room
|
||||
System.arraycopy(array, index, newArray, index + 1, size - index); |
||||
array = newArray; |
||||
} |
||||
|
||||
array[index] = element; |
||||
size++; |
||||
modCount++; |
||||
} |
||||
|
||||
@Override |
||||
public boolean addAll(Collection<? extends Long> collection) { |
||||
ensureIsMutable(); |
||||
|
||||
if (collection == null) { |
||||
throw new NullPointerException(); |
||||
} |
||||
|
||||
// We specialize when adding another LongArrayList to avoid boxing elements.
|
||||
if (!(collection instanceof LongArrayList)) { |
||||
return super.addAll(collection); |
||||
} |
||||
|
||||
LongArrayList list = (LongArrayList) collection; |
||||
if (list.size == 0) { |
||||
return false; |
||||
} |
||||
|
||||
int overflow = Integer.MAX_VALUE - size; |
||||
if (overflow < list.size) { |
||||
// We can't actually represent a list this large.
|
||||
throw new OutOfMemoryError(); |
||||
} |
||||
|
||||
int newSize = size + list.size; |
||||
if (newSize > array.length) { |
||||
array = Arrays.copyOf(array, newSize); |
||||
} |
||||
|
||||
System.arraycopy(list.array, 0, array, size, list.size); |
||||
size = newSize; |
||||
modCount++; |
||||
return true; |
||||
} |
||||
|
||||
@Override |
||||
public boolean remove(Object o) { |
||||
ensureIsMutable(); |
||||
for (int i = 0; i < size; i++) { |
||||
if (o.equals(array[i])) { |
||||
System.arraycopy(array, i + 1, array, i, size - i); |
||||
size--; |
||||
modCount++; |
||||
return true; |
||||
} |
||||
} |
||||
return false; |
||||
} |
||||
|
||||
@Override |
||||
public Long remove(int index) { |
||||
ensureIsMutable(); |
||||
ensureIndexInRange(index); |
||||
long value = array[index]; |
||||
System.arraycopy(array, index + 1, array, index, size - index); |
||||
size--; |
||||
modCount++; |
||||
return value; |
||||
} |
||||
|
||||
/** |
||||
* Ensures that the provided {@code index} is within the range of {@code [0, size]}. Throws an |
||||
* {@link IndexOutOfBoundsException} if it is not. |
||||
* |
||||
* @param index the index to verify is in range |
||||
*/ |
||||
private void ensureIndexInRange(int index) { |
||||
if (index < 0 || index >= size) { |
||||
throw new IndexOutOfBoundsException(makeOutOfBoundsExceptionMessage(index)); |
||||
} |
||||
} |
||||
|
||||
private String makeOutOfBoundsExceptionMessage(int index) { |
||||
return "Index:" + index + ", Size:" + size; |
||||
} |
||||
} |
@ -0,0 +1,48 @@ |
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 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; |
||||
|
||||
/** |
||||
* Verifies that an object is mutable, throwing if not. |
||||
*/ |
||||
interface MutabilityOracle { |
||||
static final MutabilityOracle IMMUTABLE = new MutabilityOracle() { |
||||
@Override |
||||
public void ensureMutable() { |
||||
throw new UnsupportedOperationException(); |
||||
} |
||||
}; |
||||
|
||||
/** |
||||
* Throws an {@link UnsupportedOperationException} if not mutable. |
||||
*/ |
||||
void ensureMutable(); |
||||
} |
@ -0,0 +1,95 @@ |
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 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; |
||||
|
||||
import com.google.protobuf.Internal.ProtobufList; |
||||
|
||||
import java.util.ArrayList; |
||||
import java.util.List; |
||||
|
||||
/** |
||||
* Implements {@link ProtobufList} for non-primitive and {@link String} types. |
||||
*/ |
||||
class ProtobufArrayList<E> extends AbstractProtobufList<E> { |
||||
|
||||
private static final ProtobufArrayList<Object> EMPTY_LIST = new ProtobufArrayList<Object>(); |
||||
static { |
||||
EMPTY_LIST.makeImmutable(); |
||||
} |
||||
|
||||
@SuppressWarnings("unchecked") // Guaranteed safe by runtime.
|
||||
public static <E> ProtobufArrayList<E> emptyList() { |
||||
return (ProtobufArrayList<E>) EMPTY_LIST; |
||||
} |
||||
|
||||
private final List<E> list; |
||||
|
||||
ProtobufArrayList() { |
||||
list = new ArrayList<E>(); |
||||
} |
||||
|
||||
ProtobufArrayList(List<E> toCopy) { |
||||
list = new ArrayList<E>(toCopy); |
||||
} |
||||
|
||||
@Override |
||||
public void add(int index, E element) { |
||||
ensureIsMutable(); |
||||
list.add(index, element); |
||||
modCount++; |
||||
} |
||||
|
||||
@Override |
||||
public E get(int index) { |
||||
return list.get(index); |
||||
} |
||||
|
||||
@Override |
||||
public E remove(int index) { |
||||
ensureIsMutable(); |
||||
E toReturn = list.remove(index); |
||||
modCount++; |
||||
return toReturn; |
||||
} |
||||
|
||||
@Override |
||||
public E set(int index, E element) { |
||||
ensureIsMutable(); |
||||
E toReturn = list.set(index, element); |
||||
modCount++; |
||||
return toReturn; |
||||
} |
||||
|
||||
@Override |
||||
public int size() { |
||||
return list.size(); |
||||
} |
||||
} |
@ -0,0 +1,473 @@ |
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 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; |
||||
|
||||
import static java.util.Arrays.asList; |
||||
|
||||
import junit.framework.TestCase; |
||||
|
||||
import java.util.Collections; |
||||
import java.util.ConcurrentModificationException; |
||||
import java.util.Iterator; |
||||
|
||||
/** |
||||
* Tests for {@link BooleanArrayList}. |
||||
* |
||||
* @author dweis@google.com (Daniel Weis) |
||||
*/ |
||||
public class BooleanArrayListTest extends TestCase { |
||||
|
||||
private static final BooleanArrayList UNARY_LIST = newImmutableBooleanArrayList(true); |
||||
private static final BooleanArrayList TERTIARY_LIST = |
||||
newImmutableBooleanArrayList(true, true, false); |
||||
|
||||
private BooleanArrayList list; |
||||
|
||||
@Override |
||||
protected void setUp() throws Exception { |
||||
list = new BooleanArrayList(); |
||||
} |
||||
|
||||
public void testEmptyListReturnsSameInstance() { |
||||
assertSame(BooleanArrayList.emptyList(), BooleanArrayList.emptyList()); |
||||
} |
||||
|
||||
public void testEmptyListIsImmutable() { |
||||
assertImmutable(BooleanArrayList.emptyList()); |
||||
} |
||||
|
||||
public void testMakeImmutable() { |
||||
list.addBoolean(true); |
||||
list.addBoolean(false); |
||||
list.addBoolean(true); |
||||
list.addBoolean(true); |
||||
list.makeImmutable(); |
||||
assertImmutable(list); |
||||
} |
||||
|
||||
public void testCopyConstructor() { |
||||
BooleanArrayList copy = new BooleanArrayList(TERTIARY_LIST); |
||||
assertEquals(TERTIARY_LIST, copy); |
||||
|
||||
copy = new BooleanArrayList(BooleanArrayList.emptyList()); |
||||
assertEquals(BooleanArrayList.emptyList(), copy); |
||||
|
||||
copy = new BooleanArrayList(asList(false, false, true)); |
||||
assertEquals(asList(false, false, true), copy); |
||||
|
||||
copy = new BooleanArrayList(Collections.<Boolean>emptyList()); |
||||
assertEquals(BooleanArrayList.emptyList(), copy); |
||||
} |
||||
|
||||
public void testModificationWithIteration() { |
||||
list.addAll(asList(true, false, false, true)); |
||||
Iterator<Boolean> iterator = list.iterator(); |
||||
assertEquals(4, list.size()); |
||||
assertEquals(true, (boolean) list.get(0)); |
||||
assertEquals(true, (boolean) iterator.next()); |
||||
list.set(0, true); |
||||
assertEquals(false, (boolean) iterator.next()); |
||||
|
||||
list.remove(0); |
||||
try { |
||||
iterator.next(); |
||||
fail(); |
||||
} catch (ConcurrentModificationException e) { |
||||
// expected
|
||||
} |
||||
|
||||
iterator = list.iterator(); |
||||
list.add(0, false); |
||||
try { |
||||
iterator.next(); |
||||
fail(); |
||||
} catch (ConcurrentModificationException e) { |
||||
// expected
|
||||
} |
||||
} |
||||
|
||||
public void testGet() { |
||||
assertEquals(true, (boolean) TERTIARY_LIST.get(0)); |
||||
assertEquals(true, (boolean) TERTIARY_LIST.get(1)); |
||||
assertEquals(false, (boolean) TERTIARY_LIST.get(2)); |
||||
|
||||
try { |
||||
TERTIARY_LIST.get(-1); |
||||
fail(); |
||||
} catch (IndexOutOfBoundsException e) { |
||||
// expected
|
||||
} |
||||
|
||||
try { |
||||
TERTIARY_LIST.get(3); |
||||
fail(); |
||||
} catch (IndexOutOfBoundsException e) { |
||||
// expected
|
||||
} |
||||
} |
||||
|
||||
public void testGetInt() { |
||||
assertEquals(true, TERTIARY_LIST.getBoolean(0)); |
||||
assertEquals(true, TERTIARY_LIST.getBoolean(1)); |
||||
assertEquals(false, TERTIARY_LIST.getBoolean(2)); |
||||
|
||||
try { |
||||
TERTIARY_LIST.get(-1); |
||||
fail(); |
||||
} catch (IndexOutOfBoundsException e) { |
||||
// expected
|
||||
} |
||||
|
||||
try { |
||||
TERTIARY_LIST.get(3); |
||||
fail(); |
||||
} catch (IndexOutOfBoundsException e) { |
||||
// expected
|
||||
} |
||||
} |
||||
|
||||
public void testSize() { |
||||
assertEquals(0, BooleanArrayList.emptyList().size()); |
||||
assertEquals(1, UNARY_LIST.size()); |
||||
assertEquals(3, TERTIARY_LIST.size()); |
||||
|
||||
list.addBoolean(true); |
||||
list.addBoolean(false); |
||||
list.addBoolean(false); |
||||
list.addBoolean(false); |
||||
assertEquals(4, list.size()); |
||||
|
||||
list.remove(0); |
||||
assertEquals(3, list.size()); |
||||
|
||||
list.add(true); |
||||
assertEquals(4, list.size()); |
||||
} |
||||
|
||||
public void testSet() { |
||||
list.addBoolean(false); |
||||
list.addBoolean(false); |
||||
|
||||
assertEquals(false, (boolean) list.set(0, true)); |
||||
assertEquals(true, list.getBoolean(0)); |
||||
|
||||
assertEquals(false, (boolean) list.set(1, false)); |
||||
assertEquals(false, list.getBoolean(1)); |
||||
|
||||
try { |
||||
list.set(-1, true); |
||||
fail(); |
||||
} catch (IndexOutOfBoundsException e) { |
||||
// expected
|
||||
} |
||||
|
||||
try { |
||||
list.set(2, false); |
||||
fail(); |
||||
} catch (IndexOutOfBoundsException e) { |
||||
// expected
|
||||
} |
||||
} |
||||
|
||||
public void testSetInt() { |
||||
list.addBoolean(true); |
||||
list.addBoolean(true); |
||||
|
||||
assertEquals(true, list.setBoolean(0, false)); |
||||
assertEquals(false, list.getBoolean(0)); |
||||
|
||||
assertEquals(true, list.setBoolean(1, false)); |
||||
assertEquals(false, list.getBoolean(1)); |
||||
|
||||
try { |
||||
list.setBoolean(-1, false); |
||||
fail(); |
||||
} catch (IndexOutOfBoundsException e) { |
||||
// expected
|
||||
} |
||||
|
||||
try { |
||||
list.setBoolean(2, true); |
||||
fail(); |
||||
} catch (IndexOutOfBoundsException e) { |
||||
// expected
|
||||
} |
||||
} |
||||
|
||||
public void testAdd() { |
||||
assertEquals(0, list.size()); |
||||
|
||||
assertTrue(list.add(true)); |
||||
assertEquals(asList(true), list); |
||||
|
||||
assertTrue(list.add(false)); |
||||
list.add(0, false); |
||||
assertEquals(asList(false, true, false), list); |
||||
|
||||
list.add(0, false); |
||||
list.add(0, true); |
||||
// Force a resize by getting up to 11 elements.
|
||||
for (int i = 0; i < 6; i++) { |
||||
list.add(true); |
||||
} |
||||
assertEquals(asList(true, false, false, true, false, true, true, true, true, true, true), list); |
||||
|
||||
try { |
||||
list.add(-1, false); |
||||
} catch (IndexOutOfBoundsException e) { |
||||
// expected
|
||||
} |
||||
|
||||
try { |
||||
list.add(4, true); |
||||
} catch (IndexOutOfBoundsException e) { |
||||
// expected
|
||||
} |
||||
} |
||||
|
||||
public void testAddInt() { |
||||
assertEquals(0, list.size()); |
||||
|
||||
list.addBoolean(true); |
||||
assertEquals(asList(true), list); |
||||
|
||||
list.addBoolean(false); |
||||
assertEquals(asList(true, false), list); |
||||
} |
||||
|
||||
public void testAddAll() { |
||||
assertEquals(0, list.size()); |
||||
|
||||
assertTrue(list.addAll(Collections.singleton(false))); |
||||
assertEquals(1, list.size()); |
||||
assertEquals(false, (boolean) list.get(0)); |
||||
assertEquals(false, list.getBoolean(0)); |
||||
|
||||
assertTrue(list.addAll(asList(true, false, false, false, true))); |
||||
assertEquals(asList(false, true, false, false, false, true), list); |
||||
|
||||
assertTrue(list.addAll(TERTIARY_LIST)); |
||||
assertEquals(asList(false, true, false, false, false, true, true, true, false), list); |
||||
|
||||
assertFalse(list.addAll(Collections.<Boolean>emptyList())); |
||||
assertFalse(list.addAll(BooleanArrayList.emptyList())); |
||||
} |
||||
|
||||
public void testRemove() { |
||||
list.addAll(TERTIARY_LIST); |
||||
assertEquals(true, (boolean) list.remove(0)); |
||||
assertEquals(asList(true, false), list); |
||||
|
||||
assertTrue(list.remove(Boolean.TRUE)); |
||||
assertEquals(asList(false), list); |
||||
|
||||
assertFalse(list.remove(Boolean.TRUE)); |
||||
assertEquals(asList(false), list); |
||||
|
||||
assertEquals(false, (boolean) list.remove(0)); |
||||
assertEquals(asList(), list); |
||||
|
||||
try { |
||||
list.remove(-1); |
||||
fail(); |
||||
} catch (IndexOutOfBoundsException e) { |
||||
// expected
|
||||
} |
||||
|
||||
try { |
||||
list.remove(0); |
||||
} catch (IndexOutOfBoundsException e) { |
||||
// expected
|
||||
} |
||||
} |
||||
|
||||
private void assertImmutable(BooleanArrayList list) { |
||||
if (list.contains(1)) { |
||||
throw new RuntimeException("Cannot test the immutability of lists that contain 1."); |
||||
} |
||||
|
||||
try { |
||||
list.add(false); |
||||
fail(); |
||||
} catch (UnsupportedOperationException e) { |
||||
// expected
|
||||
} |
||||
|
||||
try { |
||||
list.add(0, true); |
||||
fail(); |
||||
} catch (UnsupportedOperationException e) { |
||||
// expected
|
||||
} |
||||
|
||||
try { |
||||
list.addAll(Collections.<Boolean>emptyList()); |
||||
fail(); |
||||
} catch (UnsupportedOperationException e) { |
||||
// expected
|
||||
} |
||||
|
||||
try { |
||||
list.addAll(Collections.singletonList(false)); |
||||
fail(); |
||||
} catch (UnsupportedOperationException e) { |
||||
// expected
|
||||
} |
||||
|
||||
try { |
||||
list.addAll(new BooleanArrayList()); |
||||
fail(); |
||||
} catch (UnsupportedOperationException e) { |
||||
// expected
|
||||
} |
||||
|
||||
try { |
||||
list.addAll(UNARY_LIST); |
||||
fail(); |
||||
} catch (UnsupportedOperationException e) { |
||||
// expected
|
||||
} |
||||
|
||||
try { |
||||
list.addAll(0, Collections.singleton(true)); |
||||
fail(); |
||||
} catch (UnsupportedOperationException e) { |
||||
// expected
|
||||
} |
||||
|
||||
try { |
||||
list.addAll(0, UNARY_LIST); |
||||
fail(); |
||||
} catch (UnsupportedOperationException e) { |
||||
// expected
|
||||
} |
||||
|
||||
try { |
||||
list.addAll(0, Collections.<Boolean>emptyList()); |
||||
fail(); |
||||
} catch (UnsupportedOperationException e) { |
||||
// expected
|
||||
} |
||||
|
||||
try { |
||||
list.addBoolean(true); |
||||
fail(); |
||||
} catch (UnsupportedOperationException e) { |
||||
// expected
|
||||
} |
||||
|
||||
try { |
||||
list.clear(); |
||||
fail(); |
||||
} catch (UnsupportedOperationException e) { |
||||
// expected
|
||||
} |
||||
|
||||
try { |
||||
list.remove(1); |
||||
fail(); |
||||
} catch (UnsupportedOperationException e) { |
||||
// expected
|
||||
} |
||||
|
||||
try { |
||||
list.remove(new Object()); |
||||
fail(); |
||||
} catch (UnsupportedOperationException e) { |
||||
// expected
|
||||
} |
||||
|
||||
try { |
||||
list.removeAll(Collections.<Boolean>emptyList()); |
||||
fail(); |
||||
} catch (UnsupportedOperationException e) { |
||||
// expected
|
||||
} |
||||
|
||||
try { |
||||
list.removeAll(Collections.singleton(1)); |
||||
fail(); |
||||
} catch (UnsupportedOperationException e) { |
||||
// expected
|
||||
} |
||||
|
||||
try { |
||||
list.removeAll(UNARY_LIST); |
||||
fail(); |
||||
} catch (UnsupportedOperationException e) { |
||||
// expected
|
||||
} |
||||
|
||||
try { |
||||
list.retainAll(Collections.<Boolean>emptyList()); |
||||
fail(); |
||||
} catch (UnsupportedOperationException e) { |
||||
// expected
|
||||
} |
||||
|
||||
try { |
||||
list.retainAll(Collections.singleton(1)); |
||||
fail(); |
||||
} catch (UnsupportedOperationException e) { |
||||
// expected
|
||||
} |
||||
|
||||
try { |
||||
list.retainAll(UNARY_LIST); |
||||
fail(); |
||||
} catch (UnsupportedOperationException e) { |
||||
// expected
|
||||
} |
||||
|
||||
try { |
||||
list.set(0, true); |
||||
fail(); |
||||
} catch (UnsupportedOperationException e) { |
||||
// expected
|
||||
} |
||||
|
||||
try { |
||||
list.setBoolean(0, false); |
||||
fail(); |
||||
} catch (UnsupportedOperationException e) { |
||||
// expected
|
||||
} |
||||
} |
||||
|
||||
private static BooleanArrayList newImmutableBooleanArrayList(boolean... elements) { |
||||
BooleanArrayList list = new BooleanArrayList(); |
||||
for (boolean element : elements) { |
||||
list.addBoolean(element); |
||||
} |
||||
list.makeImmutable(); |
||||
return list; |
||||
} |
||||
} |
@ -0,0 +1,473 @@ |
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 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; |
||||
|
||||
import static java.util.Arrays.asList; |
||||
|
||||
import junit.framework.TestCase; |
||||
|
||||
import java.util.Collections; |
||||
import java.util.ConcurrentModificationException; |
||||
import java.util.Iterator; |
||||
|
||||
/** |
||||
* Tests for {@link DoubleArrayList}. |
||||
* |
||||
* @author dweis@google.com (Daniel Weis) |
||||
*/ |
||||
public class DoubleArrayListTest extends TestCase { |
||||
|
||||
private static final DoubleArrayList UNARY_LIST = newImmutableDoubleArrayList(1); |
||||
private static final DoubleArrayList TERTIARY_LIST = |
||||
newImmutableDoubleArrayList(1, 2, 3); |
||||
|
||||
private DoubleArrayList list; |
||||
|
||||
@Override |
||||
protected void setUp() throws Exception { |
||||
list = new DoubleArrayList(); |
||||
} |
||||
|
||||
public void testEmptyListReturnsSameInstance() { |
||||
assertSame(DoubleArrayList.emptyList(), DoubleArrayList.emptyList()); |
||||
} |
||||
|
||||
public void testEmptyListIsImmutable() { |
||||
assertImmutable(DoubleArrayList.emptyList()); |
||||
} |
||||
|
||||
public void testMakeImmutable() { |
||||
list.addDouble(2); |
||||
list.addDouble(4); |
||||
list.addDouble(6); |
||||
list.addDouble(8); |
||||
list.makeImmutable(); |
||||
assertImmutable(list); |
||||
} |
||||
|
||||
public void testCopyConstructor() { |
||||
DoubleArrayList copy = new DoubleArrayList(TERTIARY_LIST); |
||||
assertEquals(TERTIARY_LIST, copy); |
||||
|
||||
copy = new DoubleArrayList(DoubleArrayList.emptyList()); |
||||
assertEquals(DoubleArrayList.emptyList(), copy); |
||||
|
||||
copy = new DoubleArrayList(asList(1D, 2D, 3D)); |
||||
assertEquals(asList(1D, 2D, 3D), copy); |
||||
|
||||
copy = new DoubleArrayList(Collections.<Double>emptyList()); |
||||
assertEquals(DoubleArrayList.emptyList(), copy); |
||||
} |
||||
|
||||
public void testModificationWithIteration() { |
||||
list.addAll(asList(1D, 2D, 3D, 4D)); |
||||
Iterator<Double> iterator = list.iterator(); |
||||
assertEquals(4, list.size()); |
||||
assertEquals(1D, (double) list.get(0)); |
||||
assertEquals(1D, (double) iterator.next()); |
||||
list.set(0, 1D); |
||||
assertEquals(2D, (double) iterator.next()); |
||||
|
||||
list.remove(0); |
||||
try { |
||||
iterator.next(); |
||||
fail(); |
||||
} catch (ConcurrentModificationException e) { |
||||
// expected
|
||||
} |
||||
|
||||
iterator = list.iterator(); |
||||
list.add(0, 0D); |
||||
try { |
||||
iterator.next(); |
||||
fail(); |
||||
} catch (ConcurrentModificationException e) { |
||||
// expected
|
||||
} |
||||
} |
||||
|
||||
public void testGet() { |
||||
assertEquals(1D, (double) TERTIARY_LIST.get(0)); |
||||
assertEquals(2D, (double) TERTIARY_LIST.get(1)); |
||||
assertEquals(3D, (double) TERTIARY_LIST.get(2)); |
||||
|
||||
try { |
||||
TERTIARY_LIST.get(-1); |
||||
fail(); |
||||
} catch (IndexOutOfBoundsException e) { |
||||
// expected
|
||||
} |
||||
|
||||
try { |
||||
TERTIARY_LIST.get(3); |
||||
fail(); |
||||
} catch (IndexOutOfBoundsException e) { |
||||
// expected
|
||||
} |
||||
} |
||||
|
||||
public void testGetInt() { |
||||
assertEquals(1D, TERTIARY_LIST.getDouble(0)); |
||||
assertEquals(2D, TERTIARY_LIST.getDouble(1)); |
||||
assertEquals(3D, TERTIARY_LIST.getDouble(2)); |
||||
|
||||
try { |
||||
TERTIARY_LIST.get(-1); |
||||
fail(); |
||||
} catch (IndexOutOfBoundsException e) { |
||||
// expected
|
||||
} |
||||
|
||||
try { |
||||
TERTIARY_LIST.get(3); |
||||
fail(); |
||||
} catch (IndexOutOfBoundsException e) { |
||||
// expected
|
||||
} |
||||
} |
||||
|
||||
public void testSize() { |
||||
assertEquals(0, DoubleArrayList.emptyList().size()); |
||||
assertEquals(1, UNARY_LIST.size()); |
||||
assertEquals(3, TERTIARY_LIST.size()); |
||||
|
||||
list.addDouble(2); |
||||
list.addDouble(4); |
||||
list.addDouble(6); |
||||
list.addDouble(8); |
||||
assertEquals(4, list.size()); |
||||
|
||||
list.remove(0); |
||||
assertEquals(3, list.size()); |
||||
|
||||
list.add(16D); |
||||
assertEquals(4, list.size()); |
||||
} |
||||
|
||||
public void testSet() { |
||||
list.addDouble(2); |
||||
list.addDouble(4); |
||||
|
||||
assertEquals(2D, (double) list.set(0, 0D)); |
||||
assertEquals(0D, list.getDouble(0)); |
||||
|
||||
assertEquals(4D, (double) list.set(1, 0D)); |
||||
assertEquals(0D, list.getDouble(1)); |
||||
|
||||
try { |
||||
list.set(-1, 0D); |
||||
fail(); |
||||
} catch (IndexOutOfBoundsException e) { |
||||
// expected
|
||||
} |
||||
|
||||
try { |
||||
list.set(2, 0D); |
||||
fail(); |
||||
} catch (IndexOutOfBoundsException e) { |
||||
// expected
|
||||
} |
||||
} |
||||
|
||||
public void testSetInt() { |
||||
list.addDouble(2); |
||||
list.addDouble(4); |
||||
|
||||
assertEquals(2D, list.setDouble(0, 0)); |
||||
assertEquals(0D, list.getDouble(0)); |
||||
|
||||
assertEquals(4D, list.setDouble(1, 0)); |
||||
assertEquals(0D, list.getDouble(1)); |
||||
|
||||
try { |
||||
list.setDouble(-1, 0); |
||||
fail(); |
||||
} catch (IndexOutOfBoundsException e) { |
||||
// expected
|
||||
} |
||||
|
||||
try { |
||||
list.setDouble(2, 0); |
||||
fail(); |
||||
} catch (IndexOutOfBoundsException e) { |
||||
// expected
|
||||
} |
||||
} |
||||
|
||||
public void testAdd() { |
||||
assertEquals(0, list.size()); |
||||
|
||||
assertTrue(list.add(2D)); |
||||
assertEquals(asList(2D), list); |
||||
|
||||
assertTrue(list.add(3D)); |
||||
list.add(0, 4D); |
||||
assertEquals(asList(4D, 2D, 3D), list); |
||||
|
||||
list.add(0, 1D); |
||||
list.add(0, 0D); |
||||
// Force a resize by getting up to 11 elements.
|
||||
for (int i = 0; i < 6; i++) { |
||||
list.add(Double.valueOf(5 + i)); |
||||
} |
||||
assertEquals(asList(0D, 1D, 4D, 2D, 3D, 5D, 6D, 7D, 8D, 9D, 10D), list); |
||||
|
||||
try { |
||||
list.add(-1, 5D); |
||||
} catch (IndexOutOfBoundsException e) { |
||||
// expected
|
||||
} |
||||
|
||||
try { |
||||
list.add(4, 5D); |
||||
} catch (IndexOutOfBoundsException e) { |
||||
// expected
|
||||
} |
||||
} |
||||
|
||||
public void testAddInt() { |
||||
assertEquals(0, list.size()); |
||||
|
||||
list.addDouble(2); |
||||
assertEquals(asList(2D), list); |
||||
|
||||
list.addDouble(3); |
||||
assertEquals(asList(2D, 3D), list); |
||||
} |
||||
|
||||
public void testAddAll() { |
||||
assertEquals(0, list.size()); |
||||
|
||||
assertTrue(list.addAll(Collections.singleton(1D))); |
||||
assertEquals(1, list.size()); |
||||
assertEquals(1D, (double) list.get(0)); |
||||
assertEquals(1D, list.getDouble(0)); |
||||
|
||||
assertTrue(list.addAll(asList(2D, 3D, 4D, 5D, 6D))); |
||||
assertEquals(asList(1D, 2D, 3D, 4D, 5D, 6D), list); |
||||
|
||||
assertTrue(list.addAll(TERTIARY_LIST)); |
||||
assertEquals(asList(1D, 2D, 3D, 4D, 5D, 6D, 1D, 2D, 3D), list); |
||||
|
||||
assertFalse(list.addAll(Collections.<Double>emptyList())); |
||||
assertFalse(list.addAll(DoubleArrayList.emptyList())); |
||||
} |
||||
|
||||
public void testRemove() { |
||||
list.addAll(TERTIARY_LIST); |
||||
assertEquals(1D, (double) list.remove(0)); |
||||
assertEquals(asList(2D, 3D), list); |
||||
|
||||
assertTrue(list.remove(Double.valueOf(3))); |
||||
assertEquals(asList(2D), list); |
||||
|
||||
assertFalse(list.remove(Double.valueOf(3))); |
||||
assertEquals(asList(2D), list); |
||||
|
||||
assertEquals(2D, (double) list.remove(0)); |
||||
assertEquals(asList(), list); |
||||
|
||||
try { |
||||
list.remove(-1); |
||||
fail(); |
||||
} catch (IndexOutOfBoundsException e) { |
||||
// expected
|
||||
} |
||||
|
||||
try { |
||||
list.remove(0); |
||||
} catch (IndexOutOfBoundsException e) { |
||||
// expected
|
||||
} |
||||
} |
||||
|
||||
private void assertImmutable(DoubleArrayList list) { |
||||
if (list.contains(1)) { |
||||
throw new RuntimeException("Cannot test the immutability of lists that contain 1."); |
||||
} |
||||
|
||||
try { |
||||
list.add(1D); |
||||
fail(); |
||||
} catch (UnsupportedOperationException e) { |
||||
// expected
|
||||
} |
||||
|
||||
try { |
||||
list.add(0, 1D); |
||||
fail(); |
||||
} catch (UnsupportedOperationException e) { |
||||
// expected
|
||||
} |
||||
|
||||
try { |
||||
list.addAll(Collections.<Double>emptyList()); |
||||
fail(); |
||||
} catch (UnsupportedOperationException e) { |
||||
// expected
|
||||
} |
||||
|
||||
try { |
||||
list.addAll(Collections.singletonList(1D)); |
||||
fail(); |
||||
} catch (UnsupportedOperationException e) { |
||||
// expected
|
||||
} |
||||
|
||||
try { |
||||
list.addAll(new DoubleArrayList()); |
||||
fail(); |
||||
} catch (UnsupportedOperationException e) { |
||||
// expected
|
||||
} |
||||
|
||||
try { |
||||
list.addAll(UNARY_LIST); |
||||
fail(); |
||||
} catch (UnsupportedOperationException e) { |
||||
// expected
|
||||
} |
||||
|
||||
try { |
||||
list.addAll(0, Collections.singleton(1D)); |
||||
fail(); |
||||
} catch (UnsupportedOperationException e) { |
||||
// expected
|
||||
} |
||||
|
||||
try { |
||||
list.addAll(0, UNARY_LIST); |
||||
fail(); |
||||
} catch (UnsupportedOperationException e) { |
||||
// expected
|
||||
} |
||||
|
||||
try { |
||||
list.addAll(0, Collections.<Double>emptyList()); |
||||
fail(); |
||||
} catch (UnsupportedOperationException e) { |
||||
// expected
|
||||
} |
||||
|
||||
try { |
||||
list.addDouble(0); |
||||
fail(); |
||||
} catch (UnsupportedOperationException e) { |
||||
// expected
|
||||
} |
||||
|
||||
try { |
||||
list.clear(); |
||||
fail(); |
||||
} catch (UnsupportedOperationException e) { |
||||
// expected
|
||||
} |
||||
|
||||
try { |
||||
list.remove(1); |
||||
fail(); |
||||
} catch (UnsupportedOperationException e) { |
||||
// expected
|
||||
} |
||||
|
||||
try { |
||||
list.remove(new Object()); |
||||
fail(); |
||||
} catch (UnsupportedOperationException e) { |
||||
// expected
|
||||
} |
||||
|
||||
try { |
||||
list.removeAll(Collections.<Double>emptyList()); |
||||
fail(); |
||||
} catch (UnsupportedOperationException e) { |
||||
// expected
|
||||
} |
||||
|
||||
try { |
||||
list.removeAll(Collections.singleton(1)); |
||||
fail(); |
||||
} catch (UnsupportedOperationException e) { |
||||
// expected
|
||||
} |
||||
|
||||
try { |
||||
list.removeAll(UNARY_LIST); |
||||
fail(); |
||||
} catch (UnsupportedOperationException e) { |
||||
// expected
|
||||
} |
||||
|
||||
try { |
||||
list.retainAll(Collections.<Double>emptyList()); |
||||
fail(); |
||||
} catch (UnsupportedOperationException e) { |
||||
// expected
|
||||
} |
||||
|
||||
try { |
||||
list.retainAll(Collections.singleton(1)); |
||||
fail(); |
||||
} catch (UnsupportedOperationException e) { |
||||
// expected
|
||||
} |
||||
|
||||
try { |
||||
list.retainAll(UNARY_LIST); |
||||
fail(); |
||||
} catch (UnsupportedOperationException e) { |
||||
// expected
|
||||
} |
||||
|
||||
try { |
||||
list.set(0, 0D); |
||||
fail(); |
||||
} catch (UnsupportedOperationException e) { |
||||
// expected
|
||||
} |
||||
|
||||
try { |
||||
list.setDouble(0, 0); |
||||
fail(); |
||||
} catch (UnsupportedOperationException e) { |
||||
// expected
|
||||
} |
||||
} |
||||
|
||||
private static DoubleArrayList newImmutableDoubleArrayList(double... elements) { |
||||
DoubleArrayList list = new DoubleArrayList(); |
||||
for (double element : elements) { |
||||
list.addDouble(element); |
||||
} |
||||
list.makeImmutable(); |
||||
return list; |
||||
} |
||||
} |
@ -0,0 +1,473 @@ |
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 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; |
||||
|
||||
import static java.util.Arrays.asList; |
||||
|
||||
import junit.framework.TestCase; |
||||
|
||||
import java.util.Collections; |
||||
import java.util.ConcurrentModificationException; |
||||
import java.util.Iterator; |
||||
|
||||
/** |
||||
* Tests for {@link FloatArrayList}. |
||||
* |
||||
* @author dweis@google.com (Daniel Weis) |
||||
*/ |
||||
public class FloatArrayListTest extends TestCase { |
||||
|
||||
private static final FloatArrayList UNARY_LIST = newImmutableFloatArrayList(1); |
||||
private static final FloatArrayList TERTIARY_LIST = |
||||
newImmutableFloatArrayList(1, 2, 3); |
||||
|
||||
private FloatArrayList list; |
||||
|
||||
@Override |
||||
protected void setUp() throws Exception { |
||||
list = new FloatArrayList(); |
||||
} |
||||
|
||||
public void testEmptyListReturnsSameInstance() { |
||||
assertSame(FloatArrayList.emptyList(), FloatArrayList.emptyList()); |
||||
} |
||||
|
||||
public void testEmptyListIsImmutable() { |
||||
assertImmutable(FloatArrayList.emptyList()); |
||||
} |
||||
|
||||
public void testMakeImmutable() { |
||||
list.addFloat(2); |
||||
list.addFloat(4); |
||||
list.addFloat(6); |
||||
list.addFloat(8); |
||||
list.makeImmutable(); |
||||
assertImmutable(list); |
||||
} |
||||
|
||||
public void testCopyConstructor() { |
||||
FloatArrayList copy = new FloatArrayList(TERTIARY_LIST); |
||||
assertEquals(TERTIARY_LIST, copy); |
||||
|
||||
copy = new FloatArrayList(FloatArrayList.emptyList()); |
||||
assertEquals(FloatArrayList.emptyList(), copy); |
||||
|
||||
copy = new FloatArrayList(asList(1F, 2F, 3F)); |
||||
assertEquals(asList(1F, 2F, 3F), copy); |
||||
|
||||
copy = new FloatArrayList(Collections.<Float>emptyList()); |
||||
assertEquals(FloatArrayList.emptyList(), copy); |
||||
} |
||||
|
||||
public void testModificationWithIteration() { |
||||
list.addAll(asList(1F, 2F, 3F, 4F)); |
||||
Iterator<Float> iterator = list.iterator(); |
||||
assertEquals(4, list.size()); |
||||
assertEquals(1F, (float) list.get(0)); |
||||
assertEquals(1F, (float) iterator.next()); |
||||
list.set(0, 1F); |
||||
assertEquals(2F, (float) iterator.next()); |
||||
|
||||
list.remove(0); |
||||
try { |
||||
iterator.next(); |
||||
fail(); |
||||
} catch (ConcurrentModificationException e) { |
||||
// expected
|
||||
} |
||||
|
||||
iterator = list.iterator(); |
||||
list.add(0, 0F); |
||||
try { |
||||
iterator.next(); |
||||
fail(); |
||||
} catch (ConcurrentModificationException e) { |
||||
// expected
|
||||
} |
||||
} |
||||
|
||||
public void testGet() { |
||||
assertEquals(1F, (float) TERTIARY_LIST.get(0)); |
||||
assertEquals(2F, (float) TERTIARY_LIST.get(1)); |
||||
assertEquals(3F, (float) TERTIARY_LIST.get(2)); |
||||
|
||||
try { |
||||
TERTIARY_LIST.get(-1); |
||||
fail(); |
||||
} catch (IndexOutOfBoundsException e) { |
||||
// expected
|
||||
} |
||||
|
||||
try { |
||||
TERTIARY_LIST.get(3); |
||||
fail(); |
||||
} catch (IndexOutOfBoundsException e) { |
||||
// expected
|
||||
} |
||||
} |
||||
|
||||
public void testGetFloat() { |
||||
assertEquals(1F, TERTIARY_LIST.getFloat(0)); |
||||
assertEquals(2F, TERTIARY_LIST.getFloat(1)); |
||||
assertEquals(3F, TERTIARY_LIST.getFloat(2)); |
||||
|
||||
try { |
||||
TERTIARY_LIST.get(-1); |
||||
fail(); |
||||
} catch (IndexOutOfBoundsException e) { |
||||
// expected
|
||||
} |
||||
|
||||
try { |
||||
TERTIARY_LIST.get(3); |
||||
fail(); |
||||
} catch (IndexOutOfBoundsException e) { |
||||
// expected
|
||||
} |
||||
} |
||||
|
||||
public void testSize() { |
||||
assertEquals(0, FloatArrayList.emptyList().size()); |
||||
assertEquals(1, UNARY_LIST.size()); |
||||
assertEquals(3, TERTIARY_LIST.size()); |
||||
|
||||
list.addFloat(2); |
||||
list.addFloat(4); |
||||
list.addFloat(6); |
||||
list.addFloat(8); |
||||
assertEquals(4, list.size()); |
||||
|
||||
list.remove(0); |
||||
assertEquals(3, list.size()); |
||||
|
||||
list.add(16F); |
||||
assertEquals(4, list.size()); |
||||
} |
||||
|
||||
public void testSet() { |
||||
list.addFloat(2); |
||||
list.addFloat(4); |
||||
|
||||
assertEquals(2F, (float) list.set(0, 0F)); |
||||
assertEquals(0F, list.getFloat(0)); |
||||
|
||||
assertEquals(4F, (float) list.set(1, 0F)); |
||||
assertEquals(0F, list.getFloat(1)); |
||||
|
||||
try { |
||||
list.set(-1, 0F); |
||||
fail(); |
||||
} catch (IndexOutOfBoundsException e) { |
||||
// expected
|
||||
} |
||||
|
||||
try { |
||||
list.set(2, 0F); |
||||
fail(); |
||||
} catch (IndexOutOfBoundsException e) { |
||||
// expected
|
||||
} |
||||
} |
||||
|
||||
public void testSetFloat() { |
||||
list.addFloat(2); |
||||
list.addFloat(4); |
||||
|
||||
assertEquals(2F, list.setFloat(0, 0)); |
||||
assertEquals(0F, list.getFloat(0)); |
||||
|
||||
assertEquals(4F, list.setFloat(1, 0)); |
||||
assertEquals(0F, list.getFloat(1)); |
||||
|
||||
try { |
||||
list.setFloat(-1, 0); |
||||
fail(); |
||||
} catch (IndexOutOfBoundsException e) { |
||||
// expected
|
||||
} |
||||
|
||||
try { |
||||
list.setFloat(2, 0); |
||||
fail(); |
||||
} catch (IndexOutOfBoundsException e) { |
||||
// expected
|
||||
} |
||||
} |
||||
|
||||
public void testAdd() { |
||||
assertEquals(0, list.size()); |
||||
|
||||
assertTrue(list.add(2F)); |
||||
assertEquals(asList(2F), list); |
||||
|
||||
assertTrue(list.add(3F)); |
||||
list.add(0, 4F); |
||||
assertEquals(asList(4F, 2F, 3F), list); |
||||
|
||||
list.add(0, 1F); |
||||
list.add(0, 0F); |
||||
// Force a resize by getting up to 11 elements.
|
||||
for (int i = 0; i < 6; i++) { |
||||
list.add(Float.valueOf(5 + i)); |
||||
} |
||||
assertEquals(asList(0F, 1F, 4F, 2F, 3F, 5F, 6F, 7F, 8F, 9F, 10F), list); |
||||
|
||||
try { |
||||
list.add(-1, 5F); |
||||
} catch (IndexOutOfBoundsException e) { |
||||
// expected
|
||||
} |
||||
|
||||
try { |
||||
list.add(4, 5F); |
||||
} catch (IndexOutOfBoundsException e) { |
||||
// expected
|
||||
} |
||||
} |
||||
|
||||
public void testAddFloat() { |
||||
assertEquals(0, list.size()); |
||||
|
||||
list.addFloat(2); |
||||
assertEquals(asList(2F), list); |
||||
|
||||
list.addFloat(3); |
||||
assertEquals(asList(2F, 3F), list); |
||||
} |
||||
|
||||
public void testAddAll() { |
||||
assertEquals(0, list.size()); |
||||
|
||||
assertTrue(list.addAll(Collections.singleton(1F))); |
||||
assertEquals(1, list.size()); |
||||
assertEquals(1F, (float) list.get(0)); |
||||
assertEquals(1F, list.getFloat(0)); |
||||
|
||||
assertTrue(list.addAll(asList(2F, 3F, 4F, 5F, 6F))); |
||||
assertEquals(asList(1F, 2F, 3F, 4F, 5F, 6F), list); |
||||
|
||||
assertTrue(list.addAll(TERTIARY_LIST)); |
||||
assertEquals(asList(1F, 2F, 3F, 4F, 5F, 6F, 1F, 2F, 3F), list); |
||||
|
||||
assertFalse(list.addAll(Collections.<Float>emptyList())); |
||||
assertFalse(list.addAll(FloatArrayList.emptyList())); |
||||
} |
||||
|
||||
public void testRemove() { |
||||
list.addAll(TERTIARY_LIST); |
||||
assertEquals(1F, (float) list.remove(0)); |
||||
assertEquals(asList(2F, 3F), list); |
||||
|
||||
assertTrue(list.remove(Float.valueOf(3))); |
||||
assertEquals(asList(2F), list); |
||||
|
||||
assertFalse(list.remove(Float.valueOf(3))); |
||||
assertEquals(asList(2F), list); |
||||
|
||||
assertEquals(2F, (float) list.remove(0)); |
||||
assertEquals(asList(), list); |
||||
|
||||
try { |
||||
list.remove(-1); |
||||
fail(); |
||||
} catch (IndexOutOfBoundsException e) { |
||||
// expected
|
||||
} |
||||
|
||||
try { |
||||
list.remove(0); |
||||
} catch (IndexOutOfBoundsException e) { |
||||
// expected
|
||||
} |
||||
} |
||||
|
||||
private void assertImmutable(FloatArrayList list) { |
||||
if (list.contains(1)) { |
||||
throw new RuntimeException("Cannot test the immutability of lists that contain 1."); |
||||
} |
||||
|
||||
try { |
||||
list.add(1F); |
||||
fail(); |
||||
} catch (UnsupportedOperationException e) { |
||||
// expected
|
||||
} |
||||
|
||||
try { |
||||
list.add(0, 1F); |
||||
fail(); |
||||
} catch (UnsupportedOperationException e) { |
||||
// expected
|
||||
} |
||||
|
||||
try { |
||||
list.addAll(Collections.<Float>emptyList()); |
||||
fail(); |
||||
} catch (UnsupportedOperationException e) { |
||||
// expected
|
||||
} |
||||
|
||||
try { |
||||
list.addAll(Collections.singletonList(1F)); |
||||
fail(); |
||||
} catch (UnsupportedOperationException e) { |
||||
// expected
|
||||
} |
||||
|
||||
try { |
||||
list.addAll(new FloatArrayList()); |
||||
fail(); |
||||
} catch (UnsupportedOperationException e) { |
||||
// expected
|
||||
} |
||||
|
||||
try { |
||||
list.addAll(UNARY_LIST); |
||||
fail(); |
||||
} catch (UnsupportedOperationException e) { |
||||
// expected
|
||||
} |
||||
|
||||
try { |
||||
list.addAll(0, Collections.singleton(1F)); |
||||
fail(); |
||||
} catch (UnsupportedOperationException e) { |
||||
// expected
|
||||
} |
||||
|
||||
try { |
||||
list.addAll(0, UNARY_LIST); |
||||
fail(); |
||||
} catch (UnsupportedOperationException e) { |
||||
// expected
|
||||
} |
||||
|
||||
try { |
||||
list.addAll(0, Collections.<Float>emptyList()); |
||||
fail(); |
||||
} catch (UnsupportedOperationException e) { |
||||
// expected
|
||||
} |
||||
|
||||
try { |
||||
list.addFloat(0); |
||||
fail(); |
||||
} catch (UnsupportedOperationException e) { |
||||
// expected
|
||||
} |
||||
|
||||
try { |
||||
list.clear(); |
||||
fail(); |
||||
} catch (UnsupportedOperationException e) { |
||||
// expected
|
||||
} |
||||
|
||||
try { |
||||
list.remove(1); |
||||
fail(); |
||||
} catch (UnsupportedOperationException e) { |
||||
// expected
|
||||
} |
||||
|
||||
try { |
||||
list.remove(new Object()); |
||||
fail(); |
||||
} catch (UnsupportedOperationException e) { |
||||
// expected
|
||||
} |
||||
|
||||
try { |
||||
list.removeAll(Collections.<Float>emptyList()); |
||||
fail(); |
||||
} catch (UnsupportedOperationException e) { |
||||
// expected
|
||||
} |
||||
|
||||
try { |
||||
list.removeAll(Collections.singleton(1)); |
||||
fail(); |
||||
} catch (UnsupportedOperationException e) { |
||||
// expected
|
||||
} |
||||
|
||||
try { |
||||
list.removeAll(UNARY_LIST); |
||||
fail(); |
||||
} catch (UnsupportedOperationException e) { |
||||
// expected
|
||||
} |
||||
|
||||
try { |
||||
list.retainAll(Collections.<Float>emptyList()); |
||||
fail(); |
||||
} catch (UnsupportedOperationException e) { |
||||
// expected
|
||||
} |
||||
|
||||
try { |
||||
list.retainAll(Collections.singleton(1)); |
||||
fail(); |
||||
} catch (UnsupportedOperationException e) { |
||||
// expected
|
||||
} |
||||
|
||||
try { |
||||
list.retainAll(UNARY_LIST); |
||||
fail(); |
||||
} catch (UnsupportedOperationException e) { |
||||
// expected
|
||||
} |
||||
|
||||
try { |
||||
list.set(0, 0F); |
||||
fail(); |
||||
} catch (UnsupportedOperationException e) { |
||||
// expected
|
||||
} |
||||
|
||||
try { |
||||
list.setFloat(0, 0); |
||||
fail(); |
||||
} catch (UnsupportedOperationException e) { |
||||
// expected
|
||||
} |
||||
} |
||||
|
||||
private static FloatArrayList newImmutableFloatArrayList(int... elements) { |
||||
FloatArrayList list = new FloatArrayList(); |
||||
for (int element : elements) { |
||||
list.addFloat(element); |
||||
} |
||||
list.makeImmutable(); |
||||
return list; |
||||
} |
||||
} |
@ -0,0 +1,473 @@ |
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 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; |
||||
|
||||
import static java.util.Arrays.asList; |
||||
|
||||
import junit.framework.TestCase; |
||||
|
||||
import java.util.Collections; |
||||
import java.util.ConcurrentModificationException; |
||||
import java.util.Iterator; |
||||
|
||||
/** |
||||
* Tests for {@link IntArrayList}. |
||||
* |
||||
* @author dweis@google.com (Daniel Weis) |
||||
*/ |
||||
public class IntArrayListTest extends TestCase { |
||||
|
||||
private static final IntArrayList UNARY_LIST = newImmutableIntArrayList(1); |
||||
private static final IntArrayList TERTIARY_LIST = |
||||
newImmutableIntArrayList(1, 2, 3); |
||||
|
||||
private IntArrayList list; |
||||
|
||||
@Override |
||||
protected void setUp() throws Exception { |
||||
list = new IntArrayList(); |
||||
} |
||||
|
||||
public void testEmptyListReturnsSameInstance() { |
||||
assertSame(IntArrayList.emptyList(), IntArrayList.emptyList()); |
||||
} |
||||
|
||||
public void testEmptyListIsImmutable() { |
||||
assertImmutable(IntArrayList.emptyList()); |
||||
} |
||||
|
||||
public void testMakeImmutable() { |
||||
list.addInt(2); |
||||
list.addInt(4); |
||||
list.addInt(6); |
||||
list.addInt(8); |
||||
list.makeImmutable(); |
||||
assertImmutable(list); |
||||
} |
||||
|
||||
public void testCopyConstructor() { |
||||
IntArrayList copy = new IntArrayList(TERTIARY_LIST); |
||||
assertEquals(TERTIARY_LIST, copy); |
||||
|
||||
copy = new IntArrayList(IntArrayList.emptyList()); |
||||
assertEquals(IntArrayList.emptyList(), copy); |
||||
|
||||
copy = new IntArrayList(asList(1, 2, 3)); |
||||
assertEquals(asList(1, 2, 3), copy); |
||||
|
||||
copy = new IntArrayList(Collections.<Integer>emptyList()); |
||||
assertEquals(IntArrayList.emptyList(), copy); |
||||
} |
||||
|
||||
public void testModificationWithIteration() { |
||||
list.addAll(asList(1, 2, 3, 4)); |
||||
Iterator<Integer> iterator = list.iterator(); |
||||
assertEquals(4, list.size()); |
||||
assertEquals(1, (int) list.get(0)); |
||||
assertEquals(1, (int) iterator.next()); |
||||
list.set(0, 1); |
||||
assertEquals(2, (int) iterator.next()); |
||||
|
||||
list.remove(0); |
||||
try { |
||||
iterator.next(); |
||||
fail(); |
||||
} catch (ConcurrentModificationException e) { |
||||
// expected
|
||||
} |
||||
|
||||
iterator = list.iterator(); |
||||
list.add(0, 0); |
||||
try { |
||||
iterator.next(); |
||||
fail(); |
||||
} catch (ConcurrentModificationException e) { |
||||
// expected
|
||||
} |
||||
} |
||||
|
||||
public void testGet() { |
||||
assertEquals(1, (int) TERTIARY_LIST.get(0)); |
||||
assertEquals(2, (int) TERTIARY_LIST.get(1)); |
||||
assertEquals(3, (int) TERTIARY_LIST.get(2)); |
||||
|
||||
try { |
||||
TERTIARY_LIST.get(-1); |
||||
fail(); |
||||
} catch (IndexOutOfBoundsException e) { |
||||
// expected
|
||||
} |
||||
|
||||
try { |
||||
TERTIARY_LIST.get(3); |
||||
fail(); |
||||
} catch (IndexOutOfBoundsException e) { |
||||
// expected
|
||||
} |
||||
} |
||||
|
||||
public void testGetInt() { |
||||
assertEquals(1, TERTIARY_LIST.getInt(0)); |
||||
assertEquals(2, TERTIARY_LIST.getInt(1)); |
||||
assertEquals(3, TERTIARY_LIST.getInt(2)); |
||||
|
||||
try { |
||||
TERTIARY_LIST.get(-1); |
||||
fail(); |
||||
} catch (IndexOutOfBoundsException e) { |
||||
// expected
|
||||
} |
||||
|
||||
try { |
||||
TERTIARY_LIST.get(3); |
||||
fail(); |
||||
} catch (IndexOutOfBoundsException e) { |
||||
// expected
|
||||
} |
||||
} |
||||
|
||||
public void testSize() { |
||||
assertEquals(0, IntArrayList.emptyList().size()); |
||||
assertEquals(1, UNARY_LIST.size()); |
||||
assertEquals(3, TERTIARY_LIST.size()); |
||||
|
||||
list.addInt(2); |
||||
list.addInt(4); |
||||
list.addInt(6); |
||||
list.addInt(8); |
||||
assertEquals(4, list.size()); |
||||
|
||||
list.remove(0); |
||||
assertEquals(3, list.size()); |
||||
|
||||
list.add(16); |
||||
assertEquals(4, list.size()); |
||||
} |
||||
|
||||
public void testSet() { |
||||
list.addInt(2); |
||||
list.addInt(4); |
||||
|
||||
assertEquals(2, (int) list.set(0, 0)); |
||||
assertEquals(0, list.getInt(0)); |
||||
|
||||
assertEquals(4, (int) list.set(1, 0)); |
||||
assertEquals(0, list.getInt(1)); |
||||
|
||||
try { |
||||
list.set(-1, 0); |
||||
fail(); |
||||
} catch (IndexOutOfBoundsException e) { |
||||
// expected
|
||||
} |
||||
|
||||
try { |
||||
list.set(2, 0); |
||||
fail(); |
||||
} catch (IndexOutOfBoundsException e) { |
||||
// expected
|
||||
} |
||||
} |
||||
|
||||
public void testSetInt() { |
||||
list.addInt(2); |
||||
list.addInt(4); |
||||
|
||||
assertEquals(2, list.setInt(0, 0)); |
||||
assertEquals(0, list.getInt(0)); |
||||
|
||||
assertEquals(4, list.setInt(1, 0)); |
||||
assertEquals(0, list.getInt(1)); |
||||
|
||||
try { |
||||
list.setInt(-1, 0); |
||||
fail(); |
||||
} catch (IndexOutOfBoundsException e) { |
||||
// expected
|
||||
} |
||||
|
||||
try { |
||||
list.setInt(2, 0); |
||||
fail(); |
||||
} catch (IndexOutOfBoundsException e) { |
||||
// expected
|
||||
} |
||||
} |
||||
|
||||
public void testAdd() { |
||||
assertEquals(0, list.size()); |
||||
|
||||
assertTrue(list.add(2)); |
||||
assertEquals(asList(2), list); |
||||
|
||||
assertTrue(list.add(3)); |
||||
list.add(0, 4); |
||||
assertEquals(asList(4, 2, 3), list); |
||||
|
||||
list.add(0, 1); |
||||
list.add(0, 0); |
||||
// Force a resize by getting up to 11 elements.
|
||||
for (int i = 0; i < 6; i++) { |
||||
list.add(5 + i); |
||||
} |
||||
assertEquals(asList(0, 1, 4, 2, 3, 5, 6, 7, 8, 9, 10), list); |
||||
|
||||
try { |
||||
list.add(-1, 5); |
||||
} catch (IndexOutOfBoundsException e) { |
||||
// expected
|
||||
} |
||||
|
||||
try { |
||||
list.add(4, 5); |
||||
} catch (IndexOutOfBoundsException e) { |
||||
// expected
|
||||
} |
||||
} |
||||
|
||||
public void testAddInt() { |
||||
assertEquals(0, list.size()); |
||||
|
||||
list.addInt(2); |
||||
assertEquals(asList(2), list); |
||||
|
||||
list.addInt(3); |
||||
assertEquals(asList(2, 3), list); |
||||
} |
||||
|
||||
public void testAddAll() { |
||||
assertEquals(0, list.size()); |
||||
|
||||
assertTrue(list.addAll(Collections.singleton(1))); |
||||
assertEquals(1, list.size()); |
||||
assertEquals(1, (int) list.get(0)); |
||||
assertEquals(1, list.getInt(0)); |
||||
|
||||
assertTrue(list.addAll(asList(2, 3, 4, 5, 6))); |
||||
assertEquals(asList(1, 2, 3, 4, 5, 6), list); |
||||
|
||||
assertTrue(list.addAll(TERTIARY_LIST)); |
||||
assertEquals(asList(1, 2, 3, 4, 5, 6, 1, 2, 3), list); |
||||
|
||||
assertFalse(list.addAll(Collections.<Integer>emptyList())); |
||||
assertFalse(list.addAll(IntArrayList.emptyList())); |
||||
} |
||||
|
||||
public void testRemove() { |
||||
list.addAll(TERTIARY_LIST); |
||||
assertEquals(1, (int) list.remove(0)); |
||||
assertEquals(asList(2, 3), list); |
||||
|
||||
assertTrue(list.remove(Integer.valueOf(3))); |
||||
assertEquals(asList(2), list); |
||||
|
||||
assertFalse(list.remove(Integer.valueOf(3))); |
||||
assertEquals(asList(2), list); |
||||
|
||||
assertEquals(2, (int) list.remove(0)); |
||||
assertEquals(asList(), list); |
||||
|
||||
try { |
||||
list.remove(-1); |
||||
fail(); |
||||
} catch (IndexOutOfBoundsException e) { |
||||
// expected
|
||||
} |
||||
|
||||
try { |
||||
list.remove(0); |
||||
} catch (IndexOutOfBoundsException e) { |
||||
// expected
|
||||
} |
||||
} |
||||
|
||||
private void assertImmutable(IntArrayList list) { |
||||
if (list.contains(1)) { |
||||
throw new RuntimeException("Cannot test the immutability of lists that contain 1."); |
||||
} |
||||
|
||||
try { |
||||
list.add(1); |
||||
fail(); |
||||
} catch (UnsupportedOperationException e) { |
||||
// expected
|
||||
} |
||||
|
||||
try { |
||||
list.add(0, 1); |
||||
fail(); |
||||
} catch (UnsupportedOperationException e) { |
||||
// expected
|
||||
} |
||||
|
||||
try { |
||||
list.addAll(Collections.<Integer>emptyList()); |
||||
fail(); |
||||
} catch (UnsupportedOperationException e) { |
||||
// expected
|
||||
} |
||||
|
||||
try { |
||||
list.addAll(Collections.singletonList(1)); |
||||
fail(); |
||||
} catch (UnsupportedOperationException e) { |
||||
// expected
|
||||
} |
||||
|
||||
try { |
||||
list.addAll(new IntArrayList()); |
||||
fail(); |
||||
} catch (UnsupportedOperationException e) { |
||||
// expected
|
||||
} |
||||
|
||||
try { |
||||
list.addAll(UNARY_LIST); |
||||
fail(); |
||||
} catch (UnsupportedOperationException e) { |
||||
// expected
|
||||
} |
||||
|
||||
try { |
||||
list.addAll(0, Collections.singleton(1)); |
||||
fail(); |
||||
} catch (UnsupportedOperationException e) { |
||||
// expected
|
||||
} |
||||
|
||||
try { |
||||
list.addAll(0, UNARY_LIST); |
||||
fail(); |
||||
} catch (UnsupportedOperationException e) { |
||||
// expected
|
||||
} |
||||
|
||||
try { |
||||
list.addAll(0, Collections.<Integer>emptyList()); |
||||
fail(); |
||||
} catch (UnsupportedOperationException e) { |
||||
// expected
|
||||
} |
||||
|
||||
try { |
||||
list.addInt(0); |
||||
fail(); |
||||
} catch (UnsupportedOperationException e) { |
||||
// expected
|
||||
} |
||||
|
||||
try { |
||||
list.clear(); |
||||
fail(); |
||||
} catch (UnsupportedOperationException e) { |
||||
// expected
|
||||
} |
||||
|
||||
try { |
||||
list.remove(1); |
||||
fail(); |
||||
} catch (UnsupportedOperationException e) { |
||||
// expected
|
||||
} |
||||
|
||||
try { |
||||
list.remove(new Object()); |
||||
fail(); |
||||
} catch (UnsupportedOperationException e) { |
||||
// expected
|
||||
} |
||||
|
||||
try { |
||||
list.removeAll(Collections.<Integer>emptyList()); |
||||
fail(); |
||||
} catch (UnsupportedOperationException e) { |
||||
// expected
|
||||
} |
||||
|
||||
try { |
||||
list.removeAll(Collections.singleton(1)); |
||||
fail(); |
||||
} catch (UnsupportedOperationException e) { |
||||
// expected
|
||||
} |
||||
|
||||
try { |
||||
list.removeAll(UNARY_LIST); |
||||
fail(); |
||||
} catch (UnsupportedOperationException e) { |
||||
// expected
|
||||
} |
||||
|
||||
try { |
||||
list.retainAll(Collections.<Integer>emptyList()); |
||||
fail(); |
||||
} catch (UnsupportedOperationException e) { |
||||
// expected
|
||||
} |
||||
|
||||
try { |
||||
list.retainAll(Collections.singleton(1)); |
||||
fail(); |
||||
} catch (UnsupportedOperationException e) { |
||||
// expected
|
||||
} |
||||
|
||||
try { |
||||
list.retainAll(UNARY_LIST); |
||||
fail(); |
||||
} catch (UnsupportedOperationException e) { |
||||
// expected
|
||||
} |
||||
|
||||
try { |
||||
list.set(0, 0); |
||||
fail(); |
||||
} catch (UnsupportedOperationException e) { |
||||
// expected
|
||||
} |
||||
|
||||
try { |
||||
list.setInt(0, 0); |
||||
fail(); |
||||
} catch (UnsupportedOperationException e) { |
||||
// expected
|
||||
} |
||||
} |
||||
|
||||
private static IntArrayList newImmutableIntArrayList(int... elements) { |
||||
IntArrayList list = new IntArrayList(); |
||||
for (int element : elements) { |
||||
list.addInt(element); |
||||
} |
||||
list.makeImmutable(); |
||||
return list; |
||||
} |
||||
} |
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,473 @@ |
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 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; |
||||
|
||||
import static java.util.Arrays.asList; |
||||
|
||||
import junit.framework.TestCase; |
||||
|
||||
import java.util.Collections; |
||||
import java.util.ConcurrentModificationException; |
||||
import java.util.Iterator; |
||||
|
||||
/** |
||||
* Tests for {@link LongArrayList}. |
||||
* |
||||
* @author dweis@google.com (Daniel Weis) |
||||
*/ |
||||
public class LongArrayListTest extends TestCase { |
||||
|
||||
private static final LongArrayList UNARY_LIST = newImmutableLongArrayList(1); |
||||
private static final LongArrayList TERTIARY_LIST = |
||||
newImmutableLongArrayList(1, 2, 3); |
||||
|
||||
private LongArrayList list; |
||||
|
||||
@Override |
||||
protected void setUp() throws Exception { |
||||
list = new LongArrayList(); |
||||
} |
||||
|
||||
public void testEmptyListReturnsSameInstance() { |
||||
assertSame(LongArrayList.emptyList(), LongArrayList.emptyList()); |
||||
} |
||||
|
||||
public void testEmptyListIsImmutable() { |
||||
assertImmutable(LongArrayList.emptyList()); |
||||
} |
||||
|
||||
public void testMakeImmutable() { |
||||
list.addLong(2); |
||||
list.addLong(4); |
||||
list.addLong(6); |
||||
list.addLong(8); |
||||
list.makeImmutable(); |
||||
assertImmutable(list); |
||||
} |
||||
|
||||
public void testCopyConstructor() { |
||||
LongArrayList copy = new LongArrayList(TERTIARY_LIST); |
||||
assertEquals(TERTIARY_LIST, copy); |
||||
|
||||
copy = new LongArrayList(LongArrayList.emptyList()); |
||||
assertEquals(LongArrayList.emptyList(), copy); |
||||
|
||||
copy = new LongArrayList(asList(1L, 2L, 3L)); |
||||
assertEquals(asList(1L, 2L, 3L), copy); |
||||
|
||||
copy = new LongArrayList(Collections.<Long>emptyList()); |
||||
assertEquals(LongArrayList.emptyList(), copy); |
||||
} |
||||
|
||||
public void testModificationWithIteration() { |
||||
list.addAll(asList(1L, 2L, 3L, 4L)); |
||||
Iterator<Long> iterator = list.iterator(); |
||||
assertEquals(4, list.size()); |
||||
assertEquals(1, (long) list.get(0)); |
||||
assertEquals(1, (long) iterator.next()); |
||||
list.set(0, 1L); |
||||
assertEquals(2, (long) iterator.next()); |
||||
|
||||
list.remove(0); |
||||
try { |
||||
iterator.next(); |
||||
fail(); |
||||
} catch (ConcurrentModificationException e) { |
||||
// expected
|
||||
} |
||||
|
||||
iterator = list.iterator(); |
||||
list.add(0, 0L); |
||||
try { |
||||
iterator.next(); |
||||
fail(); |
||||
} catch (ConcurrentModificationException e) { |
||||
// expected
|
||||
} |
||||
} |
||||
|
||||
public void testGet() { |
||||
assertEquals(1, (long) TERTIARY_LIST.get(0)); |
||||
assertEquals(2, (long) TERTIARY_LIST.get(1)); |
||||
assertEquals(3, (long) TERTIARY_LIST.get(2)); |
||||
|
||||
try { |
||||
TERTIARY_LIST.get(-1); |
||||
fail(); |
||||
} catch (IndexOutOfBoundsException e) { |
||||
// expected
|
||||
} |
||||
|
||||
try { |
||||
TERTIARY_LIST.get(3); |
||||
fail(); |
||||
} catch (IndexOutOfBoundsException e) { |
||||
// expected
|
||||
} |
||||
} |
||||
|
||||
public void testGetLong() { |
||||
assertEquals(1, TERTIARY_LIST.getLong(0)); |
||||
assertEquals(2, TERTIARY_LIST.getLong(1)); |
||||
assertEquals(3, TERTIARY_LIST.getLong(2)); |
||||
|
||||
try { |
||||
TERTIARY_LIST.get(-1); |
||||
fail(); |
||||
} catch (IndexOutOfBoundsException e) { |
||||
// expected
|
||||
} |
||||
|
||||
try { |
||||
TERTIARY_LIST.get(3); |
||||
fail(); |
||||
} catch (IndexOutOfBoundsException e) { |
||||
// expected
|
||||
} |
||||
} |
||||
|
||||
public void testSize() { |
||||
assertEquals(0, LongArrayList.emptyList().size()); |
||||
assertEquals(1, UNARY_LIST.size()); |
||||
assertEquals(3, TERTIARY_LIST.size()); |
||||
|
||||
list.addLong(2); |
||||
list.addLong(4); |
||||
list.addLong(6); |
||||
list.addLong(8); |
||||
assertEquals(4, list.size()); |
||||
|
||||
list.remove(0); |
||||
assertEquals(3, list.size()); |
||||
|
||||
list.add(16L); |
||||
assertEquals(4, list.size()); |
||||
} |
||||
|
||||
public void testSet() { |
||||
list.addLong(2); |
||||
list.addLong(4); |
||||
|
||||
assertEquals(2, (long) list.set(0, 0L)); |
||||
assertEquals(0, list.getLong(0)); |
||||
|
||||
assertEquals(4, (long) list.set(1, 0L)); |
||||
assertEquals(0, list.getLong(1)); |
||||
|
||||
try { |
||||
list.set(-1, 0L); |
||||
fail(); |
||||
} catch (IndexOutOfBoundsException e) { |
||||
// expected
|
||||
} |
||||
|
||||
try { |
||||
list.set(2, 0L); |
||||
fail(); |
||||
} catch (IndexOutOfBoundsException e) { |
||||
// expected
|
||||
} |
||||
} |
||||
|
||||
public void testSetLong() { |
||||
list.addLong(2); |
||||
list.addLong(4); |
||||
|
||||
assertEquals(2, list.setLong(0, 0)); |
||||
assertEquals(0, list.getLong(0)); |
||||
|
||||
assertEquals(4, list.setLong(1, 0)); |
||||
assertEquals(0, list.getLong(1)); |
||||
|
||||
try { |
||||
list.setLong(-1, 0); |
||||
fail(); |
||||
} catch (IndexOutOfBoundsException e) { |
||||
// expected
|
||||
} |
||||
|
||||
try { |
||||
list.setLong(2, 0); |
||||
fail(); |
||||
} catch (IndexOutOfBoundsException e) { |
||||
// expected
|
||||
} |
||||
} |
||||
|
||||
public void testAdd() { |
||||
assertEquals(0, list.size()); |
||||
|
||||
assertTrue(list.add(2L)); |
||||
assertEquals(asList(2L), list); |
||||
|
||||
assertTrue(list.add(3L)); |
||||
list.add(0, 4L); |
||||
assertEquals(asList(4L, 2L, 3L), list); |
||||
|
||||
list.add(0, 1L); |
||||
list.add(0, 0L); |
||||
// Force a resize by getting up to 11 elements.
|
||||
for (int i = 0; i < 6; i++) { |
||||
list.add(Long.valueOf(5 + i)); |
||||
} |
||||
assertEquals(asList(0L, 1L, 4L, 2L, 3L, 5L, 6L, 7L, 8L, 9L, 10L), list); |
||||
|
||||
try { |
||||
list.add(-1, 5L); |
||||
} catch (IndexOutOfBoundsException e) { |
||||
// expected
|
||||
} |
||||
|
||||
try { |
||||
list.add(4, 5L); |
||||
} catch (IndexOutOfBoundsException e) { |
||||
// expected
|
||||
} |
||||
} |
||||
|
||||
public void testAddLong() { |
||||
assertEquals(0, list.size()); |
||||
|
||||
list.addLong(2); |
||||
assertEquals(asList(2L), list); |
||||
|
||||
list.addLong(3); |
||||
assertEquals(asList(2L, 3L), list); |
||||
} |
||||
|
||||
public void testAddAll() { |
||||
assertEquals(0, list.size()); |
||||
|
||||
assertTrue(list.addAll(Collections.singleton(1L))); |
||||
assertEquals(1, list.size()); |
||||
assertEquals(1, (long) list.get(0)); |
||||
assertEquals(1, list.getLong(0)); |
||||
|
||||
assertTrue(list.addAll(asList(2L, 3L, 4L, 5L, 6L))); |
||||
assertEquals(asList(1L, 2L, 3L, 4L, 5L, 6L), list); |
||||
|
||||
assertTrue(list.addAll(TERTIARY_LIST)); |
||||
assertEquals(asList(1L, 2L, 3L, 4L, 5L, 6L, 1L, 2L, 3L), list); |
||||
|
||||
assertFalse(list.addAll(Collections.<Long>emptyList())); |
||||
assertFalse(list.addAll(LongArrayList.emptyList())); |
||||
} |
||||
|
||||
public void testRemove() { |
||||
list.addAll(TERTIARY_LIST); |
||||
assertEquals(1, (long) list.remove(0)); |
||||
assertEquals(asList(2L, 3L), list); |
||||
|
||||
assertTrue(list.remove(3L)); |
||||
assertEquals(asList(2L), list); |
||||
|
||||
assertFalse(list.remove(3L)); |
||||
assertEquals(asList(2L), list); |
||||
|
||||
assertEquals(2, (long) list.remove(0)); |
||||
assertEquals(asList(), list); |
||||
|
||||
try { |
||||
list.remove(-1); |
||||
fail(); |
||||
} catch (IndexOutOfBoundsException e) { |
||||
// expected
|
||||
} |
||||
|
||||
try { |
||||
list.remove(0); |
||||
} catch (IndexOutOfBoundsException e) { |
||||
// expected
|
||||
} |
||||
} |
||||
|
||||
private void assertImmutable(LongArrayList list) { |
||||
if (list.contains(1)) { |
||||
throw new RuntimeException("Cannot test the immutability of lists that contain 1."); |
||||
} |
||||
|
||||
try { |
||||
list.add(1L); |
||||
fail(); |
||||
} catch (UnsupportedOperationException e) { |
||||
// expected
|
||||
} |
||||
|
||||
try { |
||||
list.add(0, 1L); |
||||
fail(); |
||||
} catch (UnsupportedOperationException e) { |
||||
// expected
|
||||
} |
||||
|
||||
try { |
||||
list.addAll(Collections.<Long>emptyList()); |
||||
fail(); |
||||
} catch (UnsupportedOperationException e) { |
||||
// expected
|
||||
} |
||||
|
||||
try { |
||||
list.addAll(Collections.singletonList(1L)); |
||||
fail(); |
||||
} catch (UnsupportedOperationException e) { |
||||
// expected
|
||||
} |
||||
|
||||
try { |
||||
list.addAll(new LongArrayList()); |
||||
fail(); |
||||
} catch (UnsupportedOperationException e) { |
||||
// expected
|
||||
} |
||||
|
||||
try { |
||||
list.addAll(UNARY_LIST); |
||||
fail(); |
||||
} catch (UnsupportedOperationException e) { |
||||
// expected
|
||||
} |
||||
|
||||
try { |
||||
list.addAll(0, Collections.singleton(1L)); |
||||
fail(); |
||||
} catch (UnsupportedOperationException e) { |
||||
// expected
|
||||
} |
||||
|
||||
try { |
||||
list.addAll(0, UNARY_LIST); |
||||
fail(); |
||||
} catch (UnsupportedOperationException e) { |
||||
// expected
|
||||
} |
||||
|
||||
try { |
||||
list.addAll(0, Collections.<Long>emptyList()); |
||||
fail(); |
||||
} catch (UnsupportedOperationException e) { |
||||
// expected
|
||||
} |
||||
|
||||
try { |
||||
list.addLong(0); |
||||
fail(); |
||||
} catch (UnsupportedOperationException e) { |
||||
// expected
|
||||
} |
||||
|
||||
try { |
||||
list.clear(); |
||||
fail(); |
||||
} catch (UnsupportedOperationException e) { |
||||
// expected
|
||||
} |
||||
|
||||
try { |
||||
list.remove(1); |
||||
fail(); |
||||
} catch (UnsupportedOperationException e) { |
||||
// expected
|
||||
} |
||||
|
||||
try { |
||||
list.remove(new Object()); |
||||
fail(); |
||||
} catch (UnsupportedOperationException e) { |
||||
// expected
|
||||
} |
||||
|
||||
try { |
||||
list.removeAll(Collections.<Long>emptyList()); |
||||
fail(); |
||||
} catch (UnsupportedOperationException e) { |
||||
// expected
|
||||
} |
||||
|
||||
try { |
||||
list.removeAll(Collections.singleton(1)); |
||||
fail(); |
||||
} catch (UnsupportedOperationException e) { |
||||
// expected
|
||||
} |
||||
|
||||
try { |
||||
list.removeAll(UNARY_LIST); |
||||
fail(); |
||||
} catch (UnsupportedOperationException e) { |
||||
// expected
|
||||
} |
||||
|
||||
try { |
||||
list.retainAll(Collections.<Long>emptyList()); |
||||
fail(); |
||||
} catch (UnsupportedOperationException e) { |
||||
// expected
|
||||
} |
||||
|
||||
try { |
||||
list.retainAll(Collections.singleton(1)); |
||||
fail(); |
||||
} catch (UnsupportedOperationException e) { |
||||
// expected
|
||||
} |
||||
|
||||
try { |
||||
list.retainAll(UNARY_LIST); |
||||
fail(); |
||||
} catch (UnsupportedOperationException e) { |
||||
// expected
|
||||
} |
||||
|
||||
try { |
||||
list.set(0, 0L); |
||||
fail(); |
||||
} catch (UnsupportedOperationException e) { |
||||
// expected
|
||||
} |
||||
|
||||
try { |
||||
list.setLong(0, 0); |
||||
fail(); |
||||
} catch (UnsupportedOperationException e) { |
||||
// expected
|
||||
} |
||||
} |
||||
|
||||
private static LongArrayList newImmutableLongArrayList(long... elements) { |
||||
LongArrayList list = new LongArrayList(); |
||||
for (long element : elements) { |
||||
list.addLong(element); |
||||
} |
||||
list.makeImmutable(); |
||||
return list; |
||||
} |
||||
} |
@ -0,0 +1,303 @@ |
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 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; |
||||
|
||||
import static java.util.Arrays.asList; |
||||
|
||||
import junit.framework.TestCase; |
||||
|
||||
import java.util.Collections; |
||||
import java.util.ConcurrentModificationException; |
||||
import java.util.Iterator; |
||||
import java.util.List; |
||||
|
||||
/** |
||||
* Tests for {@link ProtobufArrayList}. |
||||
*/ |
||||
public class ProtobufArrayListTest extends TestCase { |
||||
|
||||
private static final ProtobufArrayList<Integer> UNARY_LIST = newImmutableProtoArrayList(1); |
||||
private static final ProtobufArrayList<Integer> TERTIARY_LIST = |
||||
newImmutableProtoArrayList(1, 2, 3); |
||||
|
||||
private ProtobufArrayList<Integer> list; |
||||
|
||||
@Override |
||||
protected void setUp() throws Exception { |
||||
list = new ProtobufArrayList<Integer>(); |
||||
} |
||||
|
||||
public void testEmptyListReturnsSameInstance() { |
||||
assertSame(ProtobufArrayList.emptyList(), ProtobufArrayList.emptyList()); |
||||
} |
||||
|
||||
public void testEmptyListIsImmutable() { |
||||
assertImmutable(ProtobufArrayList.<Integer>emptyList()); |
||||
} |
||||
|
||||
public void testCopyConstructor() { |
||||
ProtobufArrayList<Integer> copy = new ProtobufArrayList<Integer>(TERTIARY_LIST); |
||||
assertEquals(TERTIARY_LIST, copy); |
||||
|
||||
copy = new ProtobufArrayList<Integer>(IntArrayList.emptyList()); |
||||
assertEquals(ProtobufArrayList.emptyList(), copy); |
||||
|
||||
copy = new ProtobufArrayList<Integer>(asList(1, 2, 3)); |
||||
assertEquals(asList(1, 2, 3), copy); |
||||
|
||||
copy = new ProtobufArrayList<Integer>(Collections.<Integer>emptyList()); |
||||
assertEquals(ProtobufArrayList.emptyList(), copy); |
||||
} |
||||
|
||||
public void testModificationWithIteration() { |
||||
list.addAll(asList(1, 2, 3, 4)); |
||||
Iterator<Integer> iterator = list.iterator(); |
||||
assertEquals(4, list.size()); |
||||
assertEquals(1, (int) list.get(0)); |
||||
assertEquals(1, (int) iterator.next()); |
||||
|
||||
list.remove(0); |
||||
try { |
||||
iterator.next(); |
||||
fail(); |
||||
} catch (ConcurrentModificationException e) { |
||||
// expected
|
||||
} |
||||
|
||||
iterator = list.iterator(); |
||||
list.set(0, 1); |
||||
try { |
||||
iterator.next(); |
||||
fail(); |
||||
} catch (ConcurrentModificationException e) { |
||||
// expected
|
||||
} |
||||
|
||||
iterator = list.iterator(); |
||||
list.add(0, 0); |
||||
try { |
||||
iterator.next(); |
||||
fail(); |
||||
} catch (ConcurrentModificationException e) { |
||||
// expected
|
||||
} |
||||
} |
||||
|
||||
public void testMakeImmutable() { |
||||
list.add(2); |
||||
list.add(4); |
||||
list.add(6); |
||||
list.add(8); |
||||
list.makeImmutable(); |
||||
assertImmutable(list); |
||||
} |
||||
|
||||
public void testRemove() { |
||||
list.add(2); |
||||
list.add(4); |
||||
list.add(6); |
||||
|
||||
list.remove(1); |
||||
assertEquals(asList(2, 6), list); |
||||
|
||||
list.remove(1); |
||||
assertEquals(asList(2), list); |
||||
|
||||
list.remove(0); |
||||
assertEquals(asList(), list); |
||||
} |
||||
|
||||
public void testGet() { |
||||
list.add(2); |
||||
list.add(6); |
||||
|
||||
assertEquals(2, (int) list.get(0)); |
||||
assertEquals(6, (int) list.get(1)); |
||||
} |
||||
|
||||
public void testSet() { |
||||
list.add(2); |
||||
list.add(6); |
||||
|
||||
list.set(0, 1); |
||||
assertEquals(1, (int) list.get(0)); |
||||
list.set(1, 2); |
||||
assertEquals(2, (int) list.get(1)); |
||||
} |
||||
|
||||
private void assertImmutable(List<Integer> list) { |
||||
if (list.contains(1)) { |
||||
throw new RuntimeException("Cannot test the immutability of lists that contain 1."); |
||||
} |
||||
|
||||
try { |
||||
list.add(1); |
||||
fail(); |
||||
} catch (UnsupportedOperationException e) { |
||||
// expected
|
||||
} |
||||
|
||||
try { |
||||
list.add(0, 1); |
||||
fail(); |
||||
} catch (UnsupportedOperationException e) { |
||||
// expected
|
||||
} |
||||
|
||||
try { |
||||
list.addAll(Collections.<Integer>emptyList()); |
||||
fail(); |
||||
} catch (UnsupportedOperationException e) { |
||||
// expected
|
||||
} |
||||
|
||||
try { |
||||
list.addAll(Collections.singletonList(1)); |
||||
fail(); |
||||
} catch (UnsupportedOperationException e) { |
||||
// expected
|
||||
} |
||||
|
||||
try { |
||||
list.addAll(new ProtobufArrayList<Integer>()); |
||||
fail(); |
||||
} catch (UnsupportedOperationException e) { |
||||
// expected
|
||||
} |
||||
|
||||
try { |
||||
list.addAll(UNARY_LIST); |
||||
fail(); |
||||
} catch (UnsupportedOperationException e) { |
||||
// expected
|
||||
} |
||||
|
||||
try { |
||||
list.addAll(0, Collections.singleton(1)); |
||||
fail(); |
||||
} catch (UnsupportedOperationException e) { |
||||
// expected
|
||||
} |
||||
|
||||
try { |
||||
list.addAll(0, UNARY_LIST); |
||||
fail(); |
||||
} catch (UnsupportedOperationException e) { |
||||
// expected
|
||||
} |
||||
|
||||
try { |
||||
list.addAll(0, Collections.<Integer>emptyList()); |
||||
fail(); |
||||
} catch (UnsupportedOperationException e) { |
||||
// expected
|
||||
} |
||||
|
||||
try { |
||||
list.clear(); |
||||
fail(); |
||||
} catch (UnsupportedOperationException e) { |
||||
// expected
|
||||
} |
||||
|
||||
try { |
||||
list.remove(1); |
||||
fail(); |
||||
} catch (UnsupportedOperationException e) { |
||||
// expected
|
||||
} |
||||
|
||||
try { |
||||
list.remove(new Object()); |
||||
fail(); |
||||
} catch (UnsupportedOperationException e) { |
||||
// expected
|
||||
} |
||||
|
||||
try { |
||||
list.removeAll(Collections.<Double>emptyList()); |
||||
fail(); |
||||
} catch (UnsupportedOperationException e) { |
||||
// expected
|
||||
} |
||||
|
||||
try { |
||||
list.removeAll(Collections.singleton(1)); |
||||
fail(); |
||||
} catch (UnsupportedOperationException e) { |
||||
// expected
|
||||
} |
||||
|
||||
try { |
||||
list.removeAll(UNARY_LIST); |
||||
fail(); |
||||
} catch (UnsupportedOperationException e) { |
||||
// expected
|
||||
} |
||||
|
||||
try { |
||||
list.retainAll(Collections.<Double>emptyList()); |
||||
fail(); |
||||
} catch (UnsupportedOperationException e) { |
||||
// expected
|
||||
} |
||||
|
||||
try { |
||||
list.retainAll(Collections.singleton(1)); |
||||
fail(); |
||||
} catch (UnsupportedOperationException e) { |
||||
// expected
|
||||
} |
||||
|
||||
try { |
||||
list.retainAll(UNARY_LIST); |
||||
fail(); |
||||
} catch (UnsupportedOperationException e) { |
||||
// expected
|
||||
} |
||||
|
||||
try { |
||||
list.set(0, 0); |
||||
fail(); |
||||
} catch (UnsupportedOperationException e) { |
||||
// expected
|
||||
} |
||||
} |
||||
|
||||
private static ProtobufArrayList<Integer> newImmutableProtoArrayList(int... elements) { |
||||
ProtobufArrayList<Integer> list = new ProtobufArrayList<Integer>(); |
||||
for (int element : elements) { |
||||
list.add(element); |
||||
} |
||||
list.makeImmutable(); |
||||
return list; |
||||
} |
||||
} |
@ -0,0 +1,61 @@ |
||||
// Protocol Buffers - Google's data interchange format |
||||
// Copyright 2008 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. |
||||
|
||||
// Regression test for a map initilaization order bug. The bug only manifests |
||||
// when: |
||||
// 1. A message contains map fields and is also extendable. |
||||
// 2. There is a file-level extension defined in the same file referencing |
||||
// the above message as the extension type. |
||||
// 3. The program executes in the following order: |
||||
// a. getDescriptor() is called on another message in the same file. |
||||
// b. use protobuf reflection to access the map field. |
||||
// The symptom is a NullPointerException being thrown. |
||||
syntax = "proto2"; |
||||
|
||||
package map_test; |
||||
|
||||
option java_package = "map_test"; |
||||
option java_outer_classname = "MapInitializationOrderTest"; |
||||
option java_multiple_files = true; |
||||
|
||||
// Mirrors the structure of |
||||
// javatests/com/google/cloud/common/logging/logging_test.proto. |
||||
|
||||
message Message1 { |
||||
map<string, bool> map_field = 1; |
||||
extensions 1000 to max; |
||||
} |
||||
|
||||
extend Message1 { |
||||
optional Message1 recursive_extension = 1001; |
||||
} |
||||
|
||||
message RedactAllTypes { |
||||
} |
@ -0,0 +1,540 @@ |
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 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.
|
||||
|
||||
// Author: haberman@google.com (Josh Haberman)
|
||||
|
||||
#include <google/protobuf/pyext/message_map_container.h> |
||||
|
||||
#include <google/protobuf/stubs/common.h> |
||||
#include <google/protobuf/message.h> |
||||
#include <google/protobuf/pyext/message.h> |
||||
#include <google/protobuf/pyext/scoped_pyobject_ptr.h> |
||||
|
||||
namespace google { |
||||
namespace protobuf { |
||||
namespace python { |
||||
|
||||
struct MessageMapIterator { |
||||
PyObject_HEAD; |
||||
|
||||
// This dict contains the full contents of what we want to iterate over.
|
||||
// There's no way to avoid building this, because the list representation
|
||||
// (which is canonical) can contain duplicate keys. So at the very least we
|
||||
// need a set that lets us skip duplicate keys. And at the point that we're
|
||||
// doing that, we might as well just build the actual dict we're iterating
|
||||
// over and use dict's built-in iterator.
|
||||
PyObject* dict; |
||||
|
||||
// An iterator on dict.
|
||||
PyObject* iter; |
||||
|
||||
// A pointer back to the container, so we can notice changes to the version.
|
||||
MessageMapContainer* container; |
||||
|
||||
// The version of the map when we took the iterator to it.
|
||||
//
|
||||
// We store this so that if the map is modified during iteration we can throw
|
||||
// an error.
|
||||
uint64 version; |
||||
}; |
||||
|
||||
static MessageMapIterator* GetIter(PyObject* obj) { |
||||
return reinterpret_cast<MessageMapIterator*>(obj); |
||||
} |
||||
|
||||
namespace message_map_container { |
||||
|
||||
static MessageMapContainer* GetMap(PyObject* obj) { |
||||
return reinterpret_cast<MessageMapContainer*>(obj); |
||||
} |
||||
|
||||
// The private constructor of MessageMapContainer objects.
|
||||
PyObject* NewContainer(CMessage* parent, |
||||
const google::protobuf::FieldDescriptor* parent_field_descriptor, |
||||
PyObject* concrete_class) { |
||||
if (!CheckFieldBelongsToMessage(parent_field_descriptor, parent->message)) { |
||||
return NULL; |
||||
} |
||||
|
||||
PyObject* obj = PyType_GenericAlloc(&MessageMapContainer_Type, 0); |
||||
if (obj == NULL) { |
||||
return PyErr_Format(PyExc_RuntimeError, |
||||
"Could not allocate new container."); |
||||
} |
||||
|
||||
MessageMapContainer* self = GetMap(obj); |
||||
|
||||
self->message = parent->message; |
||||
self->parent = parent; |
||||
self->parent_field_descriptor = parent_field_descriptor; |
||||
self->owner = parent->owner; |
||||
self->version = 0; |
||||
|
||||
self->key_field_descriptor = |
||||
parent_field_descriptor->message_type()->FindFieldByName("key"); |
||||
self->value_field_descriptor = |
||||
parent_field_descriptor->message_type()->FindFieldByName("value"); |
||||
|
||||
self->message_dict = PyDict_New(); |
||||
if (self->message_dict == NULL) { |
||||
return PyErr_Format(PyExc_RuntimeError, |
||||
"Could not allocate message dict."); |
||||
} |
||||
|
||||
Py_INCREF(concrete_class); |
||||
self->subclass_init = concrete_class; |
||||
|
||||
if (self->key_field_descriptor == NULL || |
||||
self->value_field_descriptor == NULL) { |
||||
Py_DECREF(obj); |
||||
return PyErr_Format(PyExc_KeyError, |
||||
"Map entry descriptor did not have key/value fields"); |
||||
} |
||||
|
||||
return obj; |
||||
} |
||||
|
||||
// Initializes the underlying Message object of "to" so it becomes a new parent
|
||||
// repeated scalar, and copies all the values from "from" to it. A child scalar
|
||||
// container can be released by passing it as both from and to (e.g. making it
|
||||
// the recipient of the new parent message and copying the values from itself).
|
||||
static int InitializeAndCopyToParentContainer( |
||||
MessageMapContainer* from, |
||||
MessageMapContainer* to) { |
||||
// For now we require from == to, re-evaluate if we want to support deep copy
|
||||
// as in repeated_composite_container.cc.
|
||||
GOOGLE_DCHECK(from == to); |
||||
Message* old_message = from->message; |
||||
Message* new_message = old_message->New(); |
||||
to->parent = NULL; |
||||
to->parent_field_descriptor = from->parent_field_descriptor; |
||||
to->message = new_message; |
||||
to->owner.reset(new_message); |
||||
|
||||
vector<const FieldDescriptor*> fields; |
||||
fields.push_back(from->parent_field_descriptor); |
||||
old_message->GetReflection()->SwapFields(old_message, new_message, fields); |
||||
return 0; |
||||
} |
||||
|
||||
static PyObject* GetCMessage(MessageMapContainer* self, Message* entry) { |
||||
// Get or create the CMessage object corresponding to this message.
|
||||
Message* message = entry->GetReflection()->MutableMessage( |
||||
entry, self->value_field_descriptor); |
||||
ScopedPyObjectPtr key(PyLong_FromVoidPtr(message)); |
||||
PyObject* ret = PyDict_GetItem(self->message_dict, key); |
||||
|
||||
if (ret == NULL) { |
||||
CMessage* cmsg = cmessage::NewEmptyMessage(self->subclass_init, |
||||
message->GetDescriptor()); |
||||
ret = reinterpret_cast<PyObject*>(cmsg); |
||||
|
||||
if (cmsg == NULL) { |
||||
return NULL; |
||||
} |
||||
cmsg->owner = self->owner; |
||||
cmsg->message = message; |
||||
cmsg->parent = self->parent; |
||||
|
||||
if (PyDict_SetItem(self->message_dict, key, ret) < 0) { |
||||
Py_DECREF(ret); |
||||
return NULL; |
||||
} |
||||
} else { |
||||
Py_INCREF(ret); |
||||
} |
||||
|
||||
return ret; |
||||
} |
||||
|
||||
int Release(MessageMapContainer* self) { |
||||
InitializeAndCopyToParentContainer(self, self); |
||||
return 0; |
||||
} |
||||
|
||||
void SetOwner(MessageMapContainer* self, |
||||
const shared_ptr<Message>& new_owner) { |
||||
self->owner = new_owner; |
||||
} |
||||
|
||||
Py_ssize_t Length(PyObject* _self) { |
||||
MessageMapContainer* self = GetMap(_self); |
||||
google::protobuf::Message* message = self->message; |
||||
return message->GetReflection()->FieldSize(*message, |
||||
self->parent_field_descriptor); |
||||
} |
||||
|
||||
int MapKeyMatches(MessageMapContainer* self, const Message* entry, |
||||
PyObject* key) { |
||||
// TODO(haberman): do we need more strict type checking?
|
||||
ScopedPyObjectPtr entry_key( |
||||
cmessage::InternalGetScalar(entry, self->key_field_descriptor)); |
||||
int ret = PyObject_RichCompareBool(key, entry_key, Py_EQ); |
||||
return ret; |
||||
} |
||||
|
||||
int SetItem(PyObject *_self, PyObject *key, PyObject *v) { |
||||
if (v) { |
||||
PyErr_Format(PyExc_ValueError, |
||||
"Direct assignment of submessage not allowed"); |
||||
return -1; |
||||
} |
||||
|
||||
// Now we know that this is a delete, not a set.
|
||||
|
||||
MessageMapContainer* self = GetMap(_self); |
||||
cmessage::AssureWritable(self->parent); |
||||
|
||||
Message* message = self->message; |
||||
const Reflection* reflection = message->GetReflection(); |
||||
size_t size = |
||||
reflection->FieldSize(*message, self->parent_field_descriptor); |
||||
|
||||
// Right now the Reflection API doesn't support map lookup, so we implement it
|
||||
// via linear search. We need to search from the end because the underlying
|
||||
// representation can have duplicates if a user calls MergeFrom(); the last
|
||||
// one needs to win.
|
||||
//
|
||||
// TODO(haberman): add lookup API to Reflection API.
|
||||
bool found = false; |
||||
for (int i = size - 1; i >= 0; i--) { |
||||
Message* entry = reflection->MutableRepeatedMessage( |
||||
message, self->parent_field_descriptor, i); |
||||
int matches = MapKeyMatches(self, entry, key); |
||||
if (matches < 0) return -1; |
||||
if (matches) { |
||||
found = true; |
||||
if (i != size - 1) { |
||||
reflection->SwapElements(message, self->parent_field_descriptor, i, |
||||
size - 1); |
||||
} |
||||
reflection->RemoveLast(message, self->parent_field_descriptor); |
||||
|
||||
// Can't exit now, the repeated field representation of maps allows
|
||||
// duplicate keys, and we have to be sure to remove all of them.
|
||||
} |
||||
} |
||||
|
||||
if (!found) { |
||||
PyErr_Format(PyExc_KeyError, "Key not present in map"); |
||||
return -1; |
||||
} |
||||
|
||||
self->version++; |
||||
|
||||
return 0; |
||||
} |
||||
|
||||
PyObject* GetIterator(PyObject *_self) { |
||||
MessageMapContainer* self = GetMap(_self); |
||||
|
||||
ScopedPyObjectPtr obj(PyType_GenericAlloc(&MessageMapIterator_Type, 0)); |
||||
if (obj == NULL) { |
||||
return PyErr_Format(PyExc_KeyError, "Could not allocate iterator"); |
||||
} |
||||
|
||||
MessageMapIterator* iter = GetIter(obj); |
||||
|
||||
Py_INCREF(self); |
||||
iter->container = self; |
||||
iter->version = self->version; |
||||
iter->dict = PyDict_New(); |
||||
if (iter->dict == NULL) { |
||||
return PyErr_Format(PyExc_RuntimeError, |
||||
"Could not allocate dict for iterator."); |
||||
} |
||||
|
||||
// Build the entire map into a dict right now. Start from the beginning so
|
||||
// that later entries win in the case of duplicates.
|
||||
Message* message = self->message; |
||||
const Reflection* reflection = message->GetReflection(); |
||||
|
||||
// Right now the Reflection API doesn't support map lookup, so we implement it
|
||||
// via linear search. We need to search from the end because the underlying
|
||||
// representation can have duplicates if a user calls MergeFrom(); the last
|
||||
// one needs to win.
|
||||
//
|
||||
// TODO(haberman): add lookup API to Reflection API.
|
||||
size_t size = |
||||
reflection->FieldSize(*message, self->parent_field_descriptor); |
||||
for (int i = size - 1; i >= 0; i--) { |
||||
Message* entry = reflection->MutableRepeatedMessage( |
||||
message, self->parent_field_descriptor, i); |
||||
ScopedPyObjectPtr key( |
||||
cmessage::InternalGetScalar(entry, self->key_field_descriptor)); |
||||
if (PyDict_SetItem(iter->dict, key.get(), GetCMessage(self, entry)) < 0) { |
||||
return PyErr_Format(PyExc_RuntimeError, |
||||
"SetItem failed in iterator construction."); |
||||
} |
||||
} |
||||
|
||||
iter->iter = PyObject_GetIter(iter->dict); |
||||
|
||||
return obj.release(); |
||||
} |
||||
|
||||
PyObject* GetItem(PyObject* _self, PyObject* key) { |
||||
MessageMapContainer* self = GetMap(_self); |
||||
cmessage::AssureWritable(self->parent); |
||||
Message* message = self->message; |
||||
const Reflection* reflection = message->GetReflection(); |
||||
|
||||
// Right now the Reflection API doesn't support map lookup, so we implement it
|
||||
// via linear search. We need to search from the end because the underlying
|
||||
// representation can have duplicates if a user calls MergeFrom(); the last
|
||||
// one needs to win.
|
||||
//
|
||||
// TODO(haberman): add lookup API to Reflection API.
|
||||
size_t size = |
||||
reflection->FieldSize(*message, self->parent_field_descriptor); |
||||
for (int i = size - 1; i >= 0; i--) { |
||||
Message* entry = reflection->MutableRepeatedMessage( |
||||
message, self->parent_field_descriptor, i); |
||||
int matches = MapKeyMatches(self, entry, key); |
||||
if (matches < 0) return NULL; |
||||
if (matches) { |
||||
return GetCMessage(self, entry); |
||||
} |
||||
} |
||||
|
||||
// Key is not already present; insert a new entry.
|
||||
Message* entry = |
||||
reflection->AddMessage(message, self->parent_field_descriptor); |
||||
|
||||
self->version++; |
||||
|
||||
if (cmessage::InternalSetNonOneofScalar(entry, self->key_field_descriptor, |
||||
key) < 0) { |
||||
reflection->RemoveLast(message, self->parent_field_descriptor); |
||||
return NULL; |
||||
} |
||||
|
||||
return GetCMessage(self, entry); |
||||
} |
||||
|
||||
PyObject* Contains(PyObject* _self, PyObject* key) { |
||||
MessageMapContainer* self = GetMap(_self); |
||||
Message* message = self->message; |
||||
const Reflection* reflection = message->GetReflection(); |
||||
|
||||
// Right now the Reflection API doesn't support map lookup, so we implement it
|
||||
// via linear search.
|
||||
//
|
||||
// TODO(haberman): add lookup API to Reflection API.
|
||||
size_t size = |
||||
reflection->FieldSize(*message, self->parent_field_descriptor); |
||||
for (int i = 0; i < size; i++) { |
||||
Message* entry = reflection->MutableRepeatedMessage( |
||||
message, self->parent_field_descriptor, i); |
||||
int matches = MapKeyMatches(self, entry, key); |
||||
if (matches < 0) return NULL; |
||||
if (matches) { |
||||
Py_RETURN_TRUE; |
||||
} |
||||
} |
||||
|
||||
Py_RETURN_FALSE; |
||||
} |
||||
|
||||
PyObject* Clear(PyObject* _self) { |
||||
MessageMapContainer* self = GetMap(_self); |
||||
cmessage::AssureWritable(self->parent); |
||||
Message* message = self->message; |
||||
const Reflection* reflection = message->GetReflection(); |
||||
|
||||
self->version++; |
||||
reflection->ClearField(message, self->parent_field_descriptor); |
||||
|
||||
Py_RETURN_NONE; |
||||
} |
||||
|
||||
PyObject* Get(PyObject* self, PyObject* args) { |
||||
PyObject* key; |
||||
PyObject* default_value = NULL; |
||||
if (PyArg_ParseTuple(args, "O|O", &key, &default_value) < 0) { |
||||
return NULL; |
||||
} |
||||
|
||||
ScopedPyObjectPtr is_present(Contains(self, key)); |
||||
if (is_present.get() == NULL) { |
||||
return NULL; |
||||
} |
||||
|
||||
if (PyObject_IsTrue(is_present.get())) { |
||||
return GetItem(self, key); |
||||
} else { |
||||
if (default_value != NULL) { |
||||
Py_INCREF(default_value); |
||||
return default_value; |
||||
} else { |
||||
Py_RETURN_NONE; |
||||
} |
||||
} |
||||
} |
||||
|
||||
static PyMappingMethods MpMethods = { |
||||
Length, // mp_length
|
||||
GetItem, // mp_subscript
|
||||
SetItem, // mp_ass_subscript
|
||||
}; |
||||
|
||||
static void Dealloc(PyObject* _self) { |
||||
MessageMapContainer* self = GetMap(_self); |
||||
self->owner.reset(); |
||||
Py_DECREF(self->message_dict); |
||||
Py_TYPE(_self)->tp_free(_self); |
||||
} |
||||
|
||||
static PyMethodDef Methods[] = { |
||||
{ "__contains__", (PyCFunction)Contains, METH_O, |
||||
"Tests whether the map contains this element."}, |
||||
{ "clear", (PyCFunction)Clear, METH_NOARGS, |
||||
"Removes all elements from the map."}, |
||||
{ "get", Get, METH_VARARGS, |
||||
"Gets the value for the given key if present, or otherwise a default" }, |
||||
{ "get_or_create", GetItem, METH_O, |
||||
"Alias for getitem, useful to make explicit that the map is mutated." }, |
||||
/*
|
||||
{ "__deepcopy__", (PyCFunction)DeepCopy, METH_VARARGS, |
||||
"Makes a deep copy of the class." }, |
||||
{ "__reduce__", (PyCFunction)Reduce, METH_NOARGS, |
||||
"Outputs picklable representation of the repeated field." }, |
||||
*/ |
||||
{NULL, NULL}, |
||||
}; |
||||
|
||||
} // namespace message_map_container
|
||||
|
||||
namespace message_map_iterator { |
||||
|
||||
static void Dealloc(PyObject* _self) { |
||||
MessageMapIterator* self = GetIter(_self); |
||||
Py_DECREF(self->dict); |
||||
Py_DECREF(self->iter); |
||||
Py_DECREF(self->container); |
||||
Py_TYPE(_self)->tp_free(_self); |
||||
} |
||||
|
||||
PyObject* IterNext(PyObject* _self) { |
||||
MessageMapIterator* self = GetIter(_self); |
||||
|
||||
// This won't catch mutations to the map performed by MergeFrom(); no easy way
|
||||
// to address that.
|
||||
if (self->version != self->container->version) { |
||||
return PyErr_Format(PyExc_RuntimeError, |
||||
"Map modified during iteration."); |
||||
} |
||||
|
||||
return PyIter_Next(self->iter); |
||||
} |
||||
|
||||
} // namespace message_map_iterator
|
||||
|
||||
PyTypeObject MessageMapContainer_Type = { |
||||
PyVarObject_HEAD_INIT(&PyType_Type, 0) |
||||
FULL_MODULE_NAME ".MessageMapContainer", // tp_name
|
||||
sizeof(MessageMapContainer), // tp_basicsize
|
||||
0, // tp_itemsize
|
||||
message_map_container::Dealloc, // tp_dealloc
|
||||
0, // tp_print
|
||||
0, // tp_getattr
|
||||
0, // tp_setattr
|
||||
0, // tp_compare
|
||||
0, // tp_repr
|
||||
0, // tp_as_number
|
||||
0, // tp_as_sequence
|
||||
&message_map_container::MpMethods, // tp_as_mapping
|
||||
0, // tp_hash
|
||||
0, // tp_call
|
||||
0, // tp_str
|
||||
0, // tp_getattro
|
||||
0, // tp_setattro
|
||||
0, // tp_as_buffer
|
||||
Py_TPFLAGS_DEFAULT, // tp_flags
|
||||
"A map container for message", // tp_doc
|
||||
0, // tp_traverse
|
||||
0, // tp_clear
|
||||
0, // tp_richcompare
|
||||
0, // tp_weaklistoffset
|
||||
message_map_container::GetIterator, // tp_iter
|
||||
0, // tp_iternext
|
||||
message_map_container::Methods, // tp_methods
|
||||
0, // tp_members
|
||||
0, // tp_getset
|
||||
0, // tp_base
|
||||
0, // tp_dict
|
||||
0, // tp_descr_get
|
||||
0, // tp_descr_set
|
||||
0, // tp_dictoffset
|
||||
0, // tp_init
|
||||
}; |
||||
|
||||
PyTypeObject MessageMapIterator_Type = { |
||||
PyVarObject_HEAD_INIT(&PyType_Type, 0) |
||||
FULL_MODULE_NAME ".MessageMapIterator", // tp_name
|
||||
sizeof(MessageMapIterator), // tp_basicsize
|
||||
0, // tp_itemsize
|
||||
message_map_iterator::Dealloc, // tp_dealloc
|
||||
0, // tp_print
|
||||
0, // tp_getattr
|
||||
0, // tp_setattr
|
||||
0, // tp_compare
|
||||
0, // tp_repr
|
||||
0, // tp_as_number
|
||||
0, // tp_as_sequence
|
||||
0, // tp_as_mapping
|
||||
0, // tp_hash
|
||||
0, // tp_call
|
||||
0, // tp_str
|
||||
0, // tp_getattro
|
||||
0, // tp_setattro
|
||||
0, // tp_as_buffer
|
||||
Py_TPFLAGS_DEFAULT, // tp_flags
|
||||
"A scalar map iterator", // tp_doc
|
||||
0, // tp_traverse
|
||||
0, // tp_clear
|
||||
0, // tp_richcompare
|
||||
0, // tp_weaklistoffset
|
||||
PyObject_SelfIter, // tp_iter
|
||||
message_map_iterator::IterNext, // tp_iternext
|
||||
0, // tp_methods
|
||||
0, // tp_members
|
||||
0, // tp_getset
|
||||
0, // tp_base
|
||||
0, // tp_dict
|
||||
0, // tp_descr_get
|
||||
0, // tp_descr_set
|
||||
0, // tp_dictoffset
|
||||
0, // tp_init
|
||||
}; |
||||
|
||||
} // namespace python
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
@ -0,0 +1,117 @@ |
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 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.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_PYTHON_CPP_MESSAGE_MAP_CONTAINER_H__ |
||||
#define GOOGLE_PROTOBUF_PYTHON_CPP_MESSAGE_MAP_CONTAINER_H__ |
||||
|
||||
#include <Python.h> |
||||
|
||||
#include <memory> |
||||
#ifndef _SHARED_PTR_H |
||||
#include <google/protobuf/stubs/shared_ptr.h> |
||||
#endif |
||||
|
||||
#include <google/protobuf/descriptor.h> |
||||
|
||||
namespace google { |
||||
namespace protobuf { |
||||
|
||||
class Message; |
||||
|
||||
using internal::shared_ptr; |
||||
|
||||
namespace python { |
||||
|
||||
struct CMessage; |
||||
|
||||
struct MessageMapContainer { |
||||
PyObject_HEAD; |
||||
|
||||
// This is the top-level C++ Message object that owns the whole
|
||||
// proto tree. Every Python MessageMapContainer holds a
|
||||
// reference to it in order to keep it alive as long as there's a
|
||||
// Python object that references any part of the tree.
|
||||
shared_ptr<Message> owner; |
||||
|
||||
// Pointer to the C++ Message that contains this container. The
|
||||
// MessageMapContainer does not own this pointer.
|
||||
Message* message; |
||||
|
||||
// Weak reference to a parent CMessage object (i.e. may be NULL.)
|
||||
//
|
||||
// Used to make sure all ancestors are also mutable when first
|
||||
// modifying the container.
|
||||
CMessage* parent; |
||||
|
||||
// Pointer to the parent's descriptor that describes this
|
||||
// field. Used together with the parent's message when making a
|
||||
// default message instance mutable.
|
||||
// The pointer is owned by the global DescriptorPool.
|
||||
const FieldDescriptor* parent_field_descriptor; |
||||
const FieldDescriptor* key_field_descriptor; |
||||
const FieldDescriptor* value_field_descriptor; |
||||
|
||||
// A callable that is used to create new child messages.
|
||||
PyObject* subclass_init; |
||||
|
||||
// A dict mapping Message* -> CMessage.
|
||||
PyObject* message_dict; |
||||
|
||||
// We bump this whenever we perform a mutation, to invalidate existing
|
||||
// iterators.
|
||||
uint64 version; |
||||
}; |
||||
|
||||
extern PyTypeObject MessageMapContainer_Type; |
||||
extern PyTypeObject MessageMapIterator_Type; |
||||
|
||||
namespace message_map_container { |
||||
|
||||
// Builds a MessageMapContainer object, from a parent message and a
|
||||
// field descriptor.
|
||||
extern PyObject* NewContainer(CMessage* parent, |
||||
const FieldDescriptor* parent_field_descriptor, |
||||
PyObject* concrete_class); |
||||
|
||||
// Releases the messages in the container to a new message.
|
||||
//
|
||||
// Returns 0 on success, -1 on failure.
|
||||
int Release(MessageMapContainer* self); |
||||
|
||||
// Set the owner field of self and any children of self.
|
||||
void SetOwner(MessageMapContainer* self, |
||||
const shared_ptr<Message>& new_owner); |
||||
|
||||
} // namespace message_map_container
|
||||
} // namespace python
|
||||
} // namespace protobuf
|
||||
|
||||
} // namespace google
|
||||
#endif // GOOGLE_PROTOBUF_PYTHON_CPP_MESSAGE_MAP_CONTAINER_H__
|
@ -0,0 +1,514 @@ |
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 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.
|
||||
|
||||
// Author: haberman@google.com (Josh Haberman)
|
||||
|
||||
#include <google/protobuf/pyext/scalar_map_container.h> |
||||
|
||||
#include <google/protobuf/stubs/common.h> |
||||
#include <google/protobuf/message.h> |
||||
#include <google/protobuf/pyext/message.h> |
||||
#include <google/protobuf/pyext/scoped_pyobject_ptr.h> |
||||
|
||||
namespace google { |
||||
namespace protobuf { |
||||
namespace python { |
||||
|
||||
struct ScalarMapIterator { |
||||
PyObject_HEAD; |
||||
|
||||
// This dict contains the full contents of what we want to iterate over.
|
||||
// There's no way to avoid building this, because the list representation
|
||||
// (which is canonical) can contain duplicate keys. So at the very least we
|
||||
// need a set that lets us skip duplicate keys. And at the point that we're
|
||||
// doing that, we might as well just build the actual dict we're iterating
|
||||
// over and use dict's built-in iterator.
|
||||
PyObject* dict; |
||||
|
||||
// An iterator on dict.
|
||||
PyObject* iter; |
||||
|
||||
// A pointer back to the container, so we can notice changes to the version.
|
||||
ScalarMapContainer* container; |
||||
|
||||
// The version of the map when we took the iterator to it.
|
||||
//
|
||||
// We store this so that if the map is modified during iteration we can throw
|
||||
// an error.
|
||||
uint64 version; |
||||
}; |
||||
|
||||
static ScalarMapIterator* GetIter(PyObject* obj) { |
||||
return reinterpret_cast<ScalarMapIterator*>(obj); |
||||
} |
||||
|
||||
namespace scalar_map_container { |
||||
|
||||
static ScalarMapContainer* GetMap(PyObject* obj) { |
||||
return reinterpret_cast<ScalarMapContainer*>(obj); |
||||
} |
||||
|
||||
// The private constructor of ScalarMapContainer objects.
|
||||
PyObject *NewContainer( |
||||
CMessage* parent, const google::protobuf::FieldDescriptor* parent_field_descriptor) { |
||||
if (!CheckFieldBelongsToMessage(parent_field_descriptor, parent->message)) { |
||||
return NULL; |
||||
} |
||||
|
||||
ScopedPyObjectPtr obj(PyType_GenericAlloc(&ScalarMapContainer_Type, 0)); |
||||
if (obj.get() == NULL) { |
||||
return PyErr_Format(PyExc_RuntimeError, |
||||
"Could not allocate new container."); |
||||
} |
||||
|
||||
ScalarMapContainer* self = GetMap(obj); |
||||
|
||||
self->message = parent->message; |
||||
self->parent = parent; |
||||
self->parent_field_descriptor = parent_field_descriptor; |
||||
self->owner = parent->owner; |
||||
self->version = 0; |
||||
|
||||
self->key_field_descriptor = |
||||
parent_field_descriptor->message_type()->FindFieldByName("key"); |
||||
self->value_field_descriptor = |
||||
parent_field_descriptor->message_type()->FindFieldByName("value"); |
||||
|
||||
if (self->key_field_descriptor == NULL || |
||||
self->value_field_descriptor == NULL) { |
||||
return PyErr_Format(PyExc_KeyError, |
||||
"Map entry descriptor did not have key/value fields"); |
||||
} |
||||
|
||||
return obj.release(); |
||||
} |
||||
|
||||
// Initializes the underlying Message object of "to" so it becomes a new parent
|
||||
// repeated scalar, and copies all the values from "from" to it. A child scalar
|
||||
// container can be released by passing it as both from and to (e.g. making it
|
||||
// the recipient of the new parent message and copying the values from itself).
|
||||
static int InitializeAndCopyToParentContainer( |
||||
ScalarMapContainer* from, |
||||
ScalarMapContainer* to) { |
||||
// For now we require from == to, re-evaluate if we want to support deep copy
|
||||
// as in repeated_scalar_container.cc.
|
||||
GOOGLE_DCHECK(from == to); |
||||
Message* old_message = from->message; |
||||
Message* new_message = old_message->New(); |
||||
to->parent = NULL; |
||||
to->parent_field_descriptor = from->parent_field_descriptor; |
||||
to->message = new_message; |
||||
to->owner.reset(new_message); |
||||
|
||||
vector<const FieldDescriptor*> fields; |
||||
fields.push_back(from->parent_field_descriptor); |
||||
old_message->GetReflection()->SwapFields(old_message, new_message, fields); |
||||
return 0; |
||||
} |
||||
|
||||
int Release(ScalarMapContainer* self) { |
||||
return InitializeAndCopyToParentContainer(self, self); |
||||
} |
||||
|
||||
void SetOwner(ScalarMapContainer* self, |
||||
const shared_ptr<Message>& new_owner) { |
||||
self->owner = new_owner; |
||||
} |
||||
|
||||
Py_ssize_t Length(PyObject* _self) { |
||||
ScalarMapContainer* self = GetMap(_self); |
||||
google::protobuf::Message* message = self->message; |
||||
return message->GetReflection()->FieldSize(*message, |
||||
self->parent_field_descriptor); |
||||
} |
||||
|
||||
int MapKeyMatches(ScalarMapContainer* self, const Message* entry, |
||||
PyObject* key) { |
||||
// TODO(haberman): do we need more strict type checking?
|
||||
ScopedPyObjectPtr entry_key( |
||||
cmessage::InternalGetScalar(entry, self->key_field_descriptor)); |
||||
int ret = PyObject_RichCompareBool(key, entry_key, Py_EQ); |
||||
return ret; |
||||
} |
||||
|
||||
PyObject* GetItem(PyObject* _self, PyObject* key) { |
||||
ScalarMapContainer* self = GetMap(_self); |
||||
|
||||
Message* message = self->message; |
||||
const Reflection* reflection = message->GetReflection(); |
||||
|
||||
// Right now the Reflection API doesn't support map lookup, so we implement it
|
||||
// via linear search.
|
||||
//
|
||||
// TODO(haberman): add lookup API to Reflection API.
|
||||
size_t size = reflection->FieldSize(*message, self->parent_field_descriptor); |
||||
for (int i = size - 1; i >= 0; i--) { |
||||
const Message& entry = reflection->GetRepeatedMessage( |
||||
*message, self->parent_field_descriptor, i); |
||||
int matches = MapKeyMatches(self, &entry, key); |
||||
if (matches < 0) return NULL; |
||||
if (matches) { |
||||
return cmessage::InternalGetScalar(&entry, self->value_field_descriptor); |
||||
} |
||||
} |
||||
|
||||
// Need to add a new entry.
|
||||
Message* entry = |
||||
reflection->AddMessage(message, self->parent_field_descriptor); |
||||
PyObject* ret = NULL; |
||||
|
||||
if (cmessage::InternalSetNonOneofScalar(entry, self->key_field_descriptor, |
||||
key) >= 0) { |
||||
ret = cmessage::InternalGetScalar(entry, self->value_field_descriptor); |
||||
} |
||||
|
||||
self->version++; |
||||
|
||||
// If there was a type error above, it set the Python exception.
|
||||
return ret; |
||||
} |
||||
|
||||
int SetItem(PyObject *_self, PyObject *key, PyObject *v) { |
||||
ScalarMapContainer* self = GetMap(_self); |
||||
cmessage::AssureWritable(self->parent); |
||||
|
||||
Message* message = self->message; |
||||
const Reflection* reflection = message->GetReflection(); |
||||
size_t size = |
||||
reflection->FieldSize(*message, self->parent_field_descriptor); |
||||
self->version++; |
||||
|
||||
if (v) { |
||||
// Set item.
|
||||
//
|
||||
// Right now the Reflection API doesn't support map lookup, so we implement
|
||||
// it via linear search.
|
||||
//
|
||||
// TODO(haberman): add lookup API to Reflection API.
|
||||
for (int i = size - 1; i >= 0; i--) { |
||||
Message* entry = reflection->MutableRepeatedMessage( |
||||
message, self->parent_field_descriptor, i); |
||||
int matches = MapKeyMatches(self, entry, key); |
||||
if (matches < 0) return -1; |
||||
if (matches) { |
||||
return cmessage::InternalSetNonOneofScalar( |
||||
entry, self->value_field_descriptor, v); |
||||
} |
||||
} |
||||
|
||||
// Key is not already present; insert a new entry.
|
||||
Message* entry = |
||||
reflection->AddMessage(message, self->parent_field_descriptor); |
||||
|
||||
if (cmessage::InternalSetNonOneofScalar(entry, self->key_field_descriptor, |
||||
key) < 0 || |
||||
cmessage::InternalSetNonOneofScalar(entry, self->value_field_descriptor, |
||||
v) < 0) { |
||||
reflection->RemoveLast(message, self->parent_field_descriptor); |
||||
return -1; |
||||
} |
||||
|
||||
return 0; |
||||
} else { |
||||
bool found = false; |
||||
for (int i = size - 1; i >= 0; i--) { |
||||
Message* entry = reflection->MutableRepeatedMessage( |
||||
message, self->parent_field_descriptor, i); |
||||
int matches = MapKeyMatches(self, entry, key); |
||||
if (matches < 0) return -1; |
||||
if (matches) { |
||||
found = true; |
||||
if (i != size - 1) { |
||||
reflection->SwapElements(message, self->parent_field_descriptor, i, |
||||
size - 1); |
||||
} |
||||
reflection->RemoveLast(message, self->parent_field_descriptor); |
||||
|
||||
// Can't exit now, the repeated field representation of maps allows
|
||||
// duplicate keys, and we have to be sure to remove all of them.
|
||||
} |
||||
} |
||||
|
||||
if (found) { |
||||
return 0; |
||||
} else { |
||||
PyErr_Format(PyExc_KeyError, "Key not present in map"); |
||||
return -1; |
||||
} |
||||
} |
||||
} |
||||
|
||||
PyObject* GetIterator(PyObject *_self) { |
||||
ScalarMapContainer* self = GetMap(_self); |
||||
|
||||
ScopedPyObjectPtr obj(PyType_GenericAlloc(&ScalarMapIterator_Type, 0)); |
||||
if (obj == NULL) { |
||||
return PyErr_Format(PyExc_KeyError, "Could not allocate iterator"); |
||||
} |
||||
|
||||
ScalarMapIterator* iter = GetIter(obj.get()); |
||||
|
||||
Py_INCREF(self); |
||||
iter->container = self; |
||||
iter->version = self->version; |
||||
iter->dict = PyDict_New(); |
||||
if (iter->dict == NULL) { |
||||
return PyErr_Format(PyExc_RuntimeError, |
||||
"Could not allocate dict for iterator."); |
||||
} |
||||
|
||||
// Build the entire map into a dict right now. Start from the beginning so
|
||||
// that later entries win in the case of duplicates.
|
||||
Message* message = self->message; |
||||
const Reflection* reflection = message->GetReflection(); |
||||
|
||||
// Right now the Reflection API doesn't support map lookup, so we implement it
|
||||
// via linear search. We need to search from the end because the underlying
|
||||
// representation can have duplicates if a user calls MergeFrom(); the last
|
||||
// one needs to win.
|
||||
//
|
||||
// TODO(haberman): add lookup API to Reflection API.
|
||||
size_t size = |
||||
reflection->FieldSize(*message, self->parent_field_descriptor); |
||||
for (int i = 0; i < size; i++) { |
||||
Message* entry = reflection->MutableRepeatedMessage( |
||||
message, self->parent_field_descriptor, i); |
||||
ScopedPyObjectPtr key( |
||||
cmessage::InternalGetScalar(entry, self->key_field_descriptor)); |
||||
ScopedPyObjectPtr val( |
||||
cmessage::InternalGetScalar(entry, self->value_field_descriptor)); |
||||
if (PyDict_SetItem(iter->dict, key.get(), val.get()) < 0) { |
||||
return PyErr_Format(PyExc_RuntimeError, |
||||
"SetItem failed in iterator construction."); |
||||
} |
||||
} |
||||
|
||||
|
||||
iter->iter = PyObject_GetIter(iter->dict); |
||||
|
||||
|
||||
return obj.release(); |
||||
} |
||||
|
||||
PyObject* Clear(PyObject* _self) { |
||||
ScalarMapContainer* self = GetMap(_self); |
||||
cmessage::AssureWritable(self->parent); |
||||
Message* message = self->message; |
||||
const Reflection* reflection = message->GetReflection(); |
||||
|
||||
reflection->ClearField(message, self->parent_field_descriptor); |
||||
|
||||
Py_RETURN_NONE; |
||||
} |
||||
|
||||
PyObject* Contains(PyObject* _self, PyObject* key) { |
||||
ScalarMapContainer* self = GetMap(_self); |
||||
|
||||
Message* message = self->message; |
||||
const Reflection* reflection = message->GetReflection(); |
||||
|
||||
// Right now the Reflection API doesn't support map lookup, so we implement it
|
||||
// via linear search.
|
||||
//
|
||||
// TODO(haberman): add lookup API to Reflection API.
|
||||
size_t size = reflection->FieldSize(*message, self->parent_field_descriptor); |
||||
for (int i = size - 1; i >= 0; i--) { |
||||
const Message& entry = reflection->GetRepeatedMessage( |
||||
*message, self->parent_field_descriptor, i); |
||||
int matches = MapKeyMatches(self, &entry, key); |
||||
if (matches < 0) return NULL; |
||||
if (matches) { |
||||
Py_RETURN_TRUE; |
||||
} |
||||
} |
||||
|
||||
Py_RETURN_FALSE; |
||||
} |
||||
|
||||
PyObject* Get(PyObject* self, PyObject* args) { |
||||
PyObject* key; |
||||
PyObject* default_value = NULL; |
||||
if (PyArg_ParseTuple(args, "O|O", &key, &default_value) < 0) { |
||||
return NULL; |
||||
} |
||||
|
||||
ScopedPyObjectPtr is_present(Contains(self, key)); |
||||
if (is_present.get() == NULL) { |
||||
return NULL; |
||||
} |
||||
|
||||
if (PyObject_IsTrue(is_present.get())) { |
||||
return GetItem(self, key); |
||||
} else { |
||||
if (default_value != NULL) { |
||||
Py_INCREF(default_value); |
||||
return default_value; |
||||
} else { |
||||
Py_RETURN_NONE; |
||||
} |
||||
} |
||||
} |
||||
|
||||
static PyMappingMethods MpMethods = { |
||||
Length, // mp_length
|
||||
GetItem, // mp_subscript
|
||||
SetItem, // mp_ass_subscript
|
||||
}; |
||||
|
||||
static void Dealloc(PyObject* _self) { |
||||
ScalarMapContainer* self = GetMap(_self); |
||||
self->owner.reset(); |
||||
Py_TYPE(_self)->tp_free(_self); |
||||
} |
||||
|
||||
static PyMethodDef Methods[] = { |
||||
{ "__contains__", Contains, METH_O, |
||||
"Tests whether a key is a member of the map." }, |
||||
{ "clear", (PyCFunction)Clear, METH_NOARGS, |
||||
"Removes all elements from the map." }, |
||||
{ "get", Get, METH_VARARGS, |
||||
"Gets the value for the given key if present, or otherwise a default" }, |
||||
/*
|
||||
{ "__deepcopy__", (PyCFunction)DeepCopy, METH_VARARGS, |
||||
"Makes a deep copy of the class." }, |
||||
{ "__reduce__", (PyCFunction)Reduce, METH_NOARGS, |
||||
"Outputs picklable representation of the repeated field." }, |
||||
*/ |
||||
{NULL, NULL}, |
||||
}; |
||||
|
||||
} // namespace scalar_map_container
|
||||
|
||||
namespace scalar_map_iterator { |
||||
|
||||
static void Dealloc(PyObject* _self) { |
||||
ScalarMapIterator* self = GetIter(_self); |
||||
Py_DECREF(self->dict); |
||||
Py_DECREF(self->iter); |
||||
Py_DECREF(self->container); |
||||
Py_TYPE(_self)->tp_free(_self); |
||||
} |
||||
|
||||
PyObject* IterNext(PyObject* _self) { |
||||
ScalarMapIterator* self = GetIter(_self); |
||||
|
||||
// This won't catch mutations to the map performed by MergeFrom(); no easy way
|
||||
// to address that.
|
||||
if (self->version != self->container->version) { |
||||
return PyErr_Format(PyExc_RuntimeError, |
||||
"Map modified during iteration."); |
||||
} |
||||
|
||||
return PyIter_Next(self->iter); |
||||
} |
||||
|
||||
} // namespace scalar_map_iterator
|
||||
|
||||
PyTypeObject ScalarMapContainer_Type = { |
||||
PyVarObject_HEAD_INIT(&PyType_Type, 0) |
||||
FULL_MODULE_NAME ".ScalarMapContainer", // tp_name
|
||||
sizeof(ScalarMapContainer), // tp_basicsize
|
||||
0, // tp_itemsize
|
||||
scalar_map_container::Dealloc, // tp_dealloc
|
||||
0, // tp_print
|
||||
0, // tp_getattr
|
||||
0, // tp_setattr
|
||||
0, // tp_compare
|
||||
0, // tp_repr
|
||||
0, // tp_as_number
|
||||
0, // tp_as_sequence
|
||||
&scalar_map_container::MpMethods, // tp_as_mapping
|
||||
0, // tp_hash
|
||||
0, // tp_call
|
||||
0, // tp_str
|
||||
0, // tp_getattro
|
||||
0, // tp_setattro
|
||||
0, // tp_as_buffer
|
||||
Py_TPFLAGS_DEFAULT, // tp_flags
|
||||
"A scalar map container", // tp_doc
|
||||
0, // tp_traverse
|
||||
0, // tp_clear
|
||||
0, // tp_richcompare
|
||||
0, // tp_weaklistoffset
|
||||
scalar_map_container::GetIterator, // tp_iter
|
||||
0, // tp_iternext
|
||||
scalar_map_container::Methods, // tp_methods
|
||||
0, // tp_members
|
||||
0, // tp_getset
|
||||
0, // tp_base
|
||||
0, // tp_dict
|
||||
0, // tp_descr_get
|
||||
0, // tp_descr_set
|
||||
0, // tp_dictoffset
|
||||
0, // tp_init
|
||||
}; |
||||
|
||||
PyTypeObject ScalarMapIterator_Type = { |
||||
PyVarObject_HEAD_INIT(&PyType_Type, 0) |
||||
FULL_MODULE_NAME ".ScalarMapIterator", // tp_name
|
||||
sizeof(ScalarMapIterator), // tp_basicsize
|
||||
0, // tp_itemsize
|
||||
scalar_map_iterator::Dealloc, // tp_dealloc
|
||||
0, // tp_print
|
||||
0, // tp_getattr
|
||||
0, // tp_setattr
|
||||
0, // tp_compare
|
||||
0, // tp_repr
|
||||
0, // tp_as_number
|
||||
0, // tp_as_sequence
|
||||
0, // tp_as_mapping
|
||||
0, // tp_hash
|
||||
0, // tp_call
|
||||
0, // tp_str
|
||||
0, // tp_getattro
|
||||
0, // tp_setattro
|
||||
0, // tp_as_buffer
|
||||
Py_TPFLAGS_DEFAULT, // tp_flags
|
||||
"A scalar map iterator", // tp_doc
|
||||
0, // tp_traverse
|
||||
0, // tp_clear
|
||||
0, // tp_richcompare
|
||||
0, // tp_weaklistoffset
|
||||
PyObject_SelfIter, // tp_iter
|
||||
scalar_map_iterator::IterNext, // tp_iternext
|
||||
0, // tp_methods
|
||||
0, // tp_members
|
||||
0, // tp_getset
|
||||
0, // tp_base
|
||||
0, // tp_dict
|
||||
0, // tp_descr_get
|
||||
0, // tp_descr_set
|
||||
0, // tp_dictoffset
|
||||
0, // tp_init
|
||||
}; |
||||
|
||||
} // namespace python
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
@ -0,0 +1,110 @@ |
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 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.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_PYTHON_CPP_SCALAR_MAP_CONTAINER_H__ |
||||
#define GOOGLE_PROTOBUF_PYTHON_CPP_SCALAR_MAP_CONTAINER_H__ |
||||
|
||||
#include <Python.h> |
||||
|
||||
#include <memory> |
||||
#ifndef _SHARED_PTR_H |
||||
#include <google/protobuf/stubs/shared_ptr.h> |
||||
#endif |
||||
|
||||
#include <google/protobuf/descriptor.h> |
||||
|
||||
namespace google { |
||||
namespace protobuf { |
||||
|
||||
class Message; |
||||
|
||||
using internal::shared_ptr; |
||||
|
||||
namespace python { |
||||
|
||||
struct CMessage; |
||||
|
||||
struct ScalarMapContainer { |
||||
PyObject_HEAD; |
||||
|
||||
// This is the top-level C++ Message object that owns the whole
|
||||
// proto tree. Every Python ScalarMapContainer holds a
|
||||
// reference to it in order to keep it alive as long as there's a
|
||||
// Python object that references any part of the tree.
|
||||
shared_ptr<Message> owner; |
||||
|
||||
// Pointer to the C++ Message that contains this container. The
|
||||
// ScalarMapContainer does not own this pointer.
|
||||
Message* message; |
||||
|
||||
// Weak reference to a parent CMessage object (i.e. may be NULL.)
|
||||
//
|
||||
// Used to make sure all ancestors are also mutable when first
|
||||
// modifying the container.
|
||||
CMessage* parent; |
||||
|
||||
// Pointer to the parent's descriptor that describes this
|
||||
// field. Used together with the parent's message when making a
|
||||
// default message instance mutable.
|
||||
// The pointer is owned by the global DescriptorPool.
|
||||
const FieldDescriptor* parent_field_descriptor; |
||||
const FieldDescriptor* key_field_descriptor; |
||||
const FieldDescriptor* value_field_descriptor; |
||||
|
||||
// We bump this whenever we perform a mutation, to invalidate existing
|
||||
// iterators.
|
||||
uint64 version; |
||||
}; |
||||
|
||||
extern PyTypeObject ScalarMapContainer_Type; |
||||
extern PyTypeObject ScalarMapIterator_Type; |
||||
|
||||
namespace scalar_map_container { |
||||
|
||||
// Builds a ScalarMapContainer object, from a parent message and a
|
||||
// field descriptor.
|
||||
extern PyObject *NewContainer( |
||||
CMessage* parent, const FieldDescriptor* parent_field_descriptor); |
||||
|
||||
// Releases the messages in the container to a new message.
|
||||
//
|
||||
// Returns 0 on success, -1 on failure.
|
||||
int Release(ScalarMapContainer* self); |
||||
|
||||
// Set the owner field of self and any children of self.
|
||||
void SetOwner(ScalarMapContainer* self, |
||||
const shared_ptr<Message>& new_owner); |
||||
|
||||
} // namespace scalar_map_container
|
||||
} // namespace python
|
||||
} // namespace protobuf
|
||||
|
||||
} // namespace google
|
||||
#endif // GOOGLE_PROTOBUF_PYTHON_CPP_SCALAR_MAP_CONTAINER_H__
|
@ -0,0 +1,100 @@ |
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 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.
|
||||
|
||||
#include <google/protobuf/any.h> |
||||
|
||||
namespace google { |
||||
namespace protobuf { |
||||
namespace internal { |
||||
|
||||
namespace { |
||||
string GetTypeUrl(const Descriptor* message) { |
||||
return string(kTypeGoogleApisComPrefix) + message->full_name(); |
||||
} |
||||
|
||||
} // namespace
|
||||
|
||||
const char kAnyFullTypeName[] = "google.protobuf.Any"; |
||||
const char kTypeGoogleApisComPrefix[] = "type.googleapis.com/"; |
||||
|
||||
AnyMetadata::AnyMetadata(UrlType* type_url, ValueType* value) |
||||
: type_url_(type_url), value_(value) { |
||||
} |
||||
|
||||
void AnyMetadata::PackFrom(const Message& message) { |
||||
type_url_->SetNoArena(&::google::protobuf::internal::GetEmptyString(), |
||||
GetTypeUrl(message.GetDescriptor())); |
||||
message.SerializeToString(value_->MutableNoArena( |
||||
&::google::protobuf::internal::GetEmptyStringAlreadyInited())); |
||||
} |
||||
|
||||
bool AnyMetadata::UnpackTo(Message* message) const { |
||||
if (!InternalIs(message->GetDescriptor())) { |
||||
return false; |
||||
} |
||||
return message->ParseFromString( |
||||
value_->GetNoArena(&::google::protobuf::internal::GetEmptyString())); |
||||
} |
||||
|
||||
bool AnyMetadata::InternalIs(const Descriptor* descriptor) const { |
||||
return type_url_->GetNoArena( |
||||
&::google::protobuf::internal::GetEmptyString()) == |
||||
GetTypeUrl(descriptor); |
||||
} |
||||
|
||||
bool ParseAnyTypeUrl(const string& type_url, string* full_type_name) { |
||||
const int prefix_len = strlen(kTypeGoogleApisComPrefix); |
||||
if (strncmp(type_url.c_str(), kTypeGoogleApisComPrefix, prefix_len) == 0) { |
||||
full_type_name->assign(type_url.data() + prefix_len, |
||||
type_url.size() - prefix_len); |
||||
return true; |
||||
} |
||||
return true; |
||||
} |
||||
|
||||
|
||||
bool GetAnyFieldDescriptors(const Message& message, |
||||
const FieldDescriptor** type_url_field, |
||||
const FieldDescriptor** value_field) { |
||||
const Descriptor* descriptor = message.GetDescriptor(); |
||||
if (descriptor->full_name() != kAnyFullTypeName) { |
||||
return false; |
||||
} |
||||
*type_url_field = descriptor->FindFieldByNumber(1); |
||||
*value_field = descriptor->FindFieldByNumber(2); |
||||
return (*type_url_field != NULL && |
||||
(*type_url_field)->type() == FieldDescriptor::TYPE_STRING && |
||||
*value_field != NULL && |
||||
(*value_field)->type() == FieldDescriptor::TYPE_BYTES); |
||||
} |
||||
|
||||
} // namespace internal
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
@ -0,0 +1,90 @@ |
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 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.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_ANY_H__ |
||||
#define GOOGLE_PROTOBUF_ANY_H__ |
||||
|
||||
#include <string> |
||||
|
||||
#include <google/protobuf/stubs/common.h> |
||||
#include <google/protobuf/arenastring.h> |
||||
#include <google/protobuf/descriptor.h> |
||||
#include <google/protobuf/message.h> |
||||
|
||||
namespace google { |
||||
namespace protobuf { |
||||
namespace internal { |
||||
|
||||
// Helper class used to implement google::protobuf::Any.
|
||||
class AnyMetadata { |
||||
typedef ArenaStringPtr UrlType; |
||||
typedef ArenaStringPtr ValueType; |
||||
public: |
||||
// AnyMetadata does not take ownership of "type_url" and "value".
|
||||
AnyMetadata(UrlType* type_url, ValueType* value); |
||||
|
||||
void PackFrom(const Message& message); |
||||
|
||||
bool UnpackTo(Message* message) const; |
||||
|
||||
template<typename T> |
||||
bool Is() const { |
||||
return InternalIs(T::default_instance().GetDescriptor()); |
||||
} |
||||
|
||||
private: |
||||
bool InternalIs(const Descriptor* message) const; |
||||
|
||||
UrlType* type_url_; |
||||
ValueType* value_; |
||||
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(AnyMetadata); |
||||
}; |
||||
|
||||
extern const char kAnyFullTypeName[]; // "google.protobuf.Any".
|
||||
extern const char kTypeGoogleApisComPrefix[]; // "type.googleapis.com/".
|
||||
|
||||
// Get the proto type name from Any::type_url value. For example, passing
|
||||
// "type.googleapis.com/rpc.QueryOrigin" will return "rpc.QueryOrigin" in
|
||||
// *full_type_name. Returns false if type_url does not start with
|
||||
// "type.googleapis.com".
|
||||
bool ParseAnyTypeUrl(const string& type_url, string* full_type_name); |
||||
|
||||
// See if message is of type google.protobuf.Any, if so, return the descriptors
|
||||
// for "type_url" and "value" fields.
|
||||
bool GetAnyFieldDescriptors(const Message& message, |
||||
const FieldDescriptor** type_url_field, |
||||
const FieldDescriptor** value_field); |
||||
|
||||
} // namespace internal
|
||||
} // namespace protobuf
|
||||
|
||||
} // namespace google
|
||||
#endif // GOOGLE_PROTOBUF_ANY_H__
|
@ -0,0 +1,89 @@ |
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 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.
|
||||
|
||||
#include <google/protobuf/any_test.pb.h> |
||||
#include <gtest/gtest.h> |
||||
|
||||
namespace google { |
||||
namespace protobuf { |
||||
namespace { |
||||
|
||||
TEST(AnyTest, TestPackAndUnpack) { |
||||
protobuf_unittest::TestAny submessage; |
||||
submessage.set_int32_value(12345); |
||||
protobuf_unittest::TestAny message; |
||||
message.mutable_any_value()->PackFrom(submessage); |
||||
|
||||
string data = message.SerializeAsString(); |
||||
|
||||
ASSERT_TRUE(message.ParseFromString(data)); |
||||
EXPECT_TRUE(message.has_any_value()); |
||||
ASSERT_TRUE(message.any_value().UnpackTo(&submessage)); |
||||
EXPECT_EQ(12345, submessage.int32_value()); |
||||
} |
||||
|
||||
TEST(AnyTest, TestPackAndUnpackAny) { |
||||
// We can pack a Any message inside another Any message.
|
||||
protobuf_unittest::TestAny submessage; |
||||
submessage.set_int32_value(12345); |
||||
google::protobuf::Any any; |
||||
any.PackFrom(submessage); |
||||
protobuf_unittest::TestAny message; |
||||
message.mutable_any_value()->PackFrom(any); |
||||
|
||||
string data = message.SerializeAsString(); |
||||
|
||||
ASSERT_TRUE(message.ParseFromString(data)); |
||||
EXPECT_TRUE(message.has_any_value()); |
||||
ASSERT_TRUE(message.any_value().UnpackTo(&any)); |
||||
ASSERT_TRUE(any.UnpackTo(&submessage)); |
||||
EXPECT_EQ(12345, submessage.int32_value()); |
||||
} |
||||
|
||||
TEST(AnyTest, TestIs) { |
||||
protobuf_unittest::TestAny submessage; |
||||
submessage.set_int32_value(12345); |
||||
google::protobuf::Any any; |
||||
any.PackFrom(submessage); |
||||
ASSERT_TRUE(any.ParseFromString(any.SerializeAsString())); |
||||
EXPECT_TRUE(any.Is<protobuf_unittest::TestAny>()); |
||||
EXPECT_FALSE(any.Is<google::protobuf::Any>()); |
||||
|
||||
protobuf_unittest::TestAny message; |
||||
message.mutable_any_value()->PackFrom(any); |
||||
ASSERT_TRUE(message.ParseFromString(message.SerializeAsString())); |
||||
EXPECT_FALSE(message.any_value().Is<protobuf_unittest::TestAny>()); |
||||
EXPECT_TRUE(message.any_value().Is<google::protobuf::Any>()); |
||||
} |
||||
|
||||
} // namespace
|
||||
} // namespace protobuf
|
||||
|
||||
} // namespace google
|
@ -0,0 +1,41 @@ |
||||
// Protocol Buffers - Google's data interchange format |
||||
// Copyright 2008 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. |
||||
|
||||
syntax = "proto3"; |
||||
|
||||
package protobuf_unittest; |
||||
|
||||
import "google/protobuf/any.proto"; |
||||
|
||||
message TestAny { |
||||
int32 int32_value = 1; |
||||
google.protobuf.Any any_value = 2; |
||||
repeated google.protobuf.Any repeated_any_value = 3; |
||||
} |
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue