Merge "Add android.util.proto package as an @TestApi."
This commit is contained in:
@@ -41027,6 +41027,156 @@ package android.util {
|
||||
|
||||
}
|
||||
|
||||
package android.util.proto {
|
||||
|
||||
public final class EncodedBuffer {
|
||||
ctor public EncodedBuffer();
|
||||
ctor public EncodedBuffer(int);
|
||||
method public void dumpBuffers(java.lang.String);
|
||||
method public static void dumpByteString(java.lang.String, java.lang.String, byte[]);
|
||||
method public void editRawFixed32(int, int);
|
||||
method public byte[] getBytes(int);
|
||||
method public int getChunkCount();
|
||||
method public java.lang.String getDebugString();
|
||||
method public int getRawFixed32At(int);
|
||||
method public static int getRawVarint32Size(int);
|
||||
method public static int getRawVarint64Size(long);
|
||||
method public static int getRawZigZag32Size(int);
|
||||
method public static int getRawZigZag64Size(long);
|
||||
method public int getReadPos();
|
||||
method public int getReadableSize();
|
||||
method public int getWriteBufIndex();
|
||||
method public int getWriteIndex();
|
||||
method public int getWritePos();
|
||||
method public byte readRawByte();
|
||||
method public int readRawFixed32();
|
||||
method public long readRawUnsigned();
|
||||
method public void rewindRead();
|
||||
method public void rewindWriteTo(int);
|
||||
method public void skipRead(int);
|
||||
method public void startEditing();
|
||||
method public void writeFromThisBuffer(int, int);
|
||||
method public void writeRawBuffer(byte[]);
|
||||
method public void writeRawBuffer(byte[], int, int);
|
||||
method public void writeRawByte(byte);
|
||||
method public void writeRawFixed32(int);
|
||||
method public void writeRawFixed64(long);
|
||||
method public void writeRawVarint32(int);
|
||||
method public void writeRawVarint64(long);
|
||||
method public void writeRawZigZag32(int);
|
||||
method public void writeRawZigZag64(long);
|
||||
}
|
||||
|
||||
public final class ProtoOutputStream {
|
||||
ctor public ProtoOutputStream();
|
||||
ctor public ProtoOutputStream(int);
|
||||
method public static int checkFieldId(long, long);
|
||||
method public static int convertObjectIdToOrdinal(int);
|
||||
method public void dump(java.lang.String);
|
||||
method public void endObject(long);
|
||||
method public void endRepeatedObject(long);
|
||||
method public byte[] getBytes();
|
||||
method public static int getDepthFromToken(long);
|
||||
method public static int getObjectIdFromToken(long);
|
||||
method public static boolean getRepeatedFromToken(long);
|
||||
method public static int getSizePosFromToken(long);
|
||||
method public static int getTagSizeFromToken(long);
|
||||
method public static long makeFieldId(int, long);
|
||||
method public static long makeToken(int, boolean, int, int, int);
|
||||
method public long startObject(long);
|
||||
method public long startRepeatedObject(long);
|
||||
method public static java.lang.String token2String(long);
|
||||
method public void writeBool(long, boolean);
|
||||
method public void writeBytes(long, byte[]);
|
||||
method public void writeDouble(long, double);
|
||||
method public void writeEnum(long, int);
|
||||
method public void writeFixed32(long, int);
|
||||
method public void writeFixed64(long, long);
|
||||
method public void writeFloat(long, float);
|
||||
method public void writeInt32(long, int);
|
||||
method public void writeInt64(long, long);
|
||||
method public void writePackedBool(long, boolean[]);
|
||||
method public void writePackedDouble(long, double[]);
|
||||
method public void writePackedEnum(long, int[]);
|
||||
method public void writePackedFixed32(long, int[]);
|
||||
method public void writePackedFixed64(long, long[]);
|
||||
method public void writePackedFloat(long, float[]);
|
||||
method public void writePackedInt32(long, int[]);
|
||||
method public void writePackedInt64(long, long[]);
|
||||
method public void writePackedSFixed32(long, int[]);
|
||||
method public void writePackedSFixed64(long, long[]);
|
||||
method public void writePackedSInt32(long, int[]);
|
||||
method public void writePackedSInt64(long, long[]);
|
||||
method public void writePackedUInt32(long, int[]);
|
||||
method public void writePackedUInt64(long, long[]);
|
||||
method public void writeRepeatedBool(long, boolean);
|
||||
method public void writeRepeatedBytes(long, byte[]);
|
||||
method public void writeRepeatedDouble(long, double);
|
||||
method public void writeRepeatedEnum(long, int);
|
||||
method public void writeRepeatedFixed32(long, int);
|
||||
method public void writeRepeatedFixed64(long, long);
|
||||
method public void writeRepeatedFloat(long, float);
|
||||
method public void writeRepeatedInt32(long, int);
|
||||
method public void writeRepeatedInt64(long, long);
|
||||
method public void writeRepeatedSFixed32(long, int);
|
||||
method public void writeRepeatedSFixed64(long, long);
|
||||
method public void writeRepeatedSInt32(long, int);
|
||||
method public void writeRepeatedSInt64(long, long);
|
||||
method public void writeRepeatedString(long, java.lang.String);
|
||||
method public void writeRepeatedUInt32(long, int);
|
||||
method public void writeRepeatedUInt64(long, long);
|
||||
method public void writeSFixed32(long, int);
|
||||
method public void writeSFixed64(long, long);
|
||||
method public void writeSInt32(long, int);
|
||||
method public void writeSInt64(long, long);
|
||||
method public void writeString(long, java.lang.String);
|
||||
method public void writeTag(int, int);
|
||||
method public void writeUInt32(long, int);
|
||||
method public void writeUInt64(long, long);
|
||||
field public static final long FIELD_COUNT_MASK = 16492674416640L; // 0xf0000000000L
|
||||
field public static final long FIELD_COUNT_PACKED = 5497558138880L; // 0x50000000000L
|
||||
field public static final long FIELD_COUNT_REPEATED = 2199023255552L; // 0x20000000000L
|
||||
field public static final int FIELD_COUNT_SHIFT = 40; // 0x28
|
||||
field public static final long FIELD_COUNT_SINGLE = 1099511627776L; // 0x10000000000L
|
||||
field public static final long FIELD_COUNT_UNKNOWN = 0L; // 0x0L
|
||||
field public static final int FIELD_ID_MASK = -8; // 0xfffffff8
|
||||
field public static final int FIELD_ID_SHIFT = 3; // 0x3
|
||||
field public static final long FIELD_TYPE_BOOL = 55834574848L; // 0xd00000000L
|
||||
field public static final long FIELD_TYPE_BYTES = 64424509440L; // 0xf00000000L
|
||||
field public static final long FIELD_TYPE_DOUBLE = 4294967296L; // 0x100000000L
|
||||
field public static final long FIELD_TYPE_ENUM = 68719476736L; // 0x1000000000L
|
||||
field public static final long FIELD_TYPE_FIXED32 = 38654705664L; // 0x900000000L
|
||||
field public static final long FIELD_TYPE_FIXED64 = 42949672960L; // 0xa00000000L
|
||||
field public static final long FIELD_TYPE_FLOAT = 8589934592L; // 0x200000000L
|
||||
field public static final long FIELD_TYPE_INT32 = 12884901888L; // 0x300000000L
|
||||
field public static final long FIELD_TYPE_INT64 = 17179869184L; // 0x400000000L
|
||||
field public static final long FIELD_TYPE_MASK = 1095216660480L; // 0xff00000000L
|
||||
field public static final long FIELD_TYPE_OBJECT = 73014444032L; // 0x1100000000L
|
||||
field public static final long FIELD_TYPE_SFIXED32 = 47244640256L; // 0xb00000000L
|
||||
field public static final long FIELD_TYPE_SFIXED64 = 51539607552L; // 0xc00000000L
|
||||
field public static final int FIELD_TYPE_SHIFT = 32; // 0x20
|
||||
field public static final long FIELD_TYPE_SINT32 = 30064771072L; // 0x700000000L
|
||||
field public static final long FIELD_TYPE_SINT64 = 34359738368L; // 0x800000000L
|
||||
field public static final long FIELD_TYPE_STRING = 60129542144L; // 0xe00000000L
|
||||
field public static final long FIELD_TYPE_UINT32 = 21474836480L; // 0x500000000L
|
||||
field public static final long FIELD_TYPE_UINT64 = 25769803776L; // 0x600000000L
|
||||
field public static final long FIELD_TYPE_UNKNOWN = 0L; // 0x0L
|
||||
field public static final java.lang.String TAG = "ProtoOutputStream";
|
||||
field public static final int WIRE_TYPE_END_GROUP = 4; // 0x4
|
||||
field public static final int WIRE_TYPE_FIXED32 = 5; // 0x5
|
||||
field public static final int WIRE_TYPE_FIXED64 = 1; // 0x1
|
||||
field public static final int WIRE_TYPE_LENGTH_DELIMITED = 2; // 0x2
|
||||
field public static final int WIRE_TYPE_MASK = 7; // 0x7
|
||||
field public static final int WIRE_TYPE_START_GROUP = 3; // 0x3
|
||||
field public static final int WIRE_TYPE_VARINT = 0; // 0x0
|
||||
}
|
||||
|
||||
public class ProtoParseException extends java.lang.RuntimeException {
|
||||
ctor public ProtoParseException(java.lang.String);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
package android.view {
|
||||
|
||||
public abstract class AbsSavedState implements android.os.Parcelable {
|
||||
|
||||
678
core/java/android/util/proto/EncodedBuffer.java
Normal file
678
core/java/android/util/proto/EncodedBuffer.java
Normal file
@@ -0,0 +1,678 @@
|
||||
/*
|
||||
* Copyright (C) 2012 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package android.util.proto;
|
||||
|
||||
import android.annotation.TestApi;
|
||||
import android.util.Log;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
* A stream of bytes containing a read pointer and a write pointer,
|
||||
* backed by a set of fixed-size buffers. There are write functions for the
|
||||
* primitive types stored by protocol buffers, but none of the logic
|
||||
* for tags, inner objects, or any of that.
|
||||
*
|
||||
* Terminology:
|
||||
* *Pos: Position in the whole data set (as if it were a single buffer).
|
||||
* *Index: Position within a buffer.
|
||||
* *BufIndex: Index of a buffer within the mBuffers list
|
||||
* @hide
|
||||
*/
|
||||
@TestApi
|
||||
public final class EncodedBuffer {
|
||||
private static final String TAG = "EncodedBuffer";
|
||||
|
||||
private final ArrayList<byte[]> mBuffers = new ArrayList<byte[]>();
|
||||
|
||||
private final int mChunkSize;
|
||||
|
||||
/**
|
||||
* The number of buffers in mBuffers. Stored separately to avoid the extra
|
||||
* function call to size() everywhere for bounds checking.
|
||||
*/
|
||||
private int mBufferCount;
|
||||
|
||||
/**
|
||||
* The buffer we are currently writing to.
|
||||
*/
|
||||
private byte[] mWriteBuffer;
|
||||
|
||||
/**
|
||||
* The index into mWriteBuffer that we will write to next.
|
||||
* It may point to the end of the buffer, in which case,
|
||||
* the NEXT write will allocate a new buffer.
|
||||
*/
|
||||
private int mWriteIndex;
|
||||
|
||||
/**
|
||||
* The index of mWriteBuffer in mBuffers.
|
||||
*/
|
||||
private int mWriteBufIndex;
|
||||
|
||||
/**
|
||||
* The buffer we are currently reading from.
|
||||
*/
|
||||
private byte[] mReadBuffer;
|
||||
|
||||
/**
|
||||
* The index of mReadBuffer in mBuffers.
|
||||
*/
|
||||
private int mReadBufIndex;
|
||||
|
||||
/**
|
||||
* The index into mReadBuffer that we will read from next.
|
||||
* It may point to the end of the buffer, in which case,
|
||||
* the NEXT read will advance to the next buffer.
|
||||
*/
|
||||
private int mReadIndex;
|
||||
|
||||
/**
|
||||
* The amount of data in the last buffer.
|
||||
*/
|
||||
private int mReadLimit = -1;
|
||||
|
||||
/**
|
||||
* How much data there is total.
|
||||
*/
|
||||
private int mReadableSize = -1;
|
||||
|
||||
public EncodedBuffer() {
|
||||
this(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct an EncodedBuffer object.
|
||||
*
|
||||
* @param chunkSize The size of the buffers to use. If chunkSize <= 0, a default
|
||||
* size will be used instead.
|
||||
*/
|
||||
public EncodedBuffer(int chunkSize) {
|
||||
if (chunkSize <= 0) {
|
||||
chunkSize = 8 * 1024;
|
||||
}
|
||||
mChunkSize = chunkSize;
|
||||
mWriteBuffer = new byte[mChunkSize];
|
||||
mBuffers.add(mWriteBuffer);
|
||||
mBufferCount = 1;
|
||||
}
|
||||
|
||||
//
|
||||
// Buffer management.
|
||||
//
|
||||
|
||||
/**
|
||||
* Rewind the read and write pointers, and record how much data was last written.
|
||||
*/
|
||||
public void startEditing() {
|
||||
mReadableSize = ((mWriteBufIndex) * mChunkSize) + mWriteIndex;
|
||||
mReadLimit = mWriteIndex;
|
||||
|
||||
mWriteBuffer = mBuffers.get(0);
|
||||
mWriteIndex = 0;
|
||||
mWriteBufIndex = 0;
|
||||
|
||||
mReadBuffer = mWriteBuffer;
|
||||
mReadBufIndex = 0;
|
||||
mReadIndex = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Rewind the read pointer. Don't touch the write pointer.
|
||||
*/
|
||||
public void rewindRead() {
|
||||
mReadBuffer = mBuffers.get(0);
|
||||
mReadBufIndex = 0;
|
||||
mReadIndex = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Only valid after startEditing. Returns -1 before that.
|
||||
*/
|
||||
public int getReadableSize() {
|
||||
return mReadableSize;
|
||||
}
|
||||
|
||||
//
|
||||
// Reading from the read position.
|
||||
//
|
||||
|
||||
/**
|
||||
* Only valid after startEditing.
|
||||
*/
|
||||
public int getReadPos() {
|
||||
return ((mReadBufIndex) * mChunkSize) + mReadIndex;
|
||||
}
|
||||
|
||||
/**
|
||||
* Skip over _amount_ bytes.
|
||||
*/
|
||||
public void skipRead(int amount) {
|
||||
if (amount < 0) {
|
||||
throw new RuntimeException("skipRead with negative amount=" + amount);
|
||||
}
|
||||
if (amount == 0) {
|
||||
return;
|
||||
}
|
||||
if (amount <= mChunkSize - mReadIndex) {
|
||||
mReadIndex += amount;
|
||||
} else {
|
||||
amount -= mChunkSize - mReadIndex;
|
||||
mReadIndex = amount % mChunkSize;
|
||||
if (mReadIndex == 0) {
|
||||
mReadIndex = mChunkSize;
|
||||
mReadBufIndex += (amount / mChunkSize);
|
||||
} else {
|
||||
mReadBufIndex += 1 + (amount / mChunkSize);
|
||||
}
|
||||
mReadBuffer = mBuffers.get(mReadBufIndex);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Read one byte from the stream and advance the read pointer.
|
||||
*
|
||||
* @throws IndexOutOfBoundsException if the read point is past the end of
|
||||
* the buffer or past the read limit previously set by startEditing().
|
||||
*/
|
||||
public byte readRawByte() {
|
||||
if (mReadBufIndex > mBufferCount
|
||||
|| (mReadBufIndex == mBufferCount - 1 && mReadIndex >= mReadLimit)) {
|
||||
throw new IndexOutOfBoundsException("Trying to read too much data"
|
||||
+ " mReadBufIndex=" + mReadBufIndex + " mBufferCount=" + mBufferCount
|
||||
+ " mReadIndex=" + mReadIndex + " mReadLimit=" + mReadLimit);
|
||||
}
|
||||
if (mReadIndex >= mChunkSize) {
|
||||
mReadBufIndex++;
|
||||
mReadBuffer = mBuffers.get(mReadBufIndex);
|
||||
mReadIndex = 0;
|
||||
}
|
||||
return mReadBuffer[mReadIndex++];
|
||||
}
|
||||
|
||||
/**
|
||||
* Read an unsigned varint. The value will be returend in a java signed long.
|
||||
*/
|
||||
public long readRawUnsigned() {
|
||||
int bits = 0;
|
||||
long result = 0;
|
||||
while (true) {
|
||||
final byte b = readRawByte();
|
||||
result |= ((long)(b & 0x7F)) << bits;
|
||||
if ((b & 0x80) == 0) {
|
||||
return result;
|
||||
}
|
||||
bits += 7;
|
||||
if (bits > 64) {
|
||||
throw new ProtoParseException("Varint too long -- " + getDebugString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Read 32 little endian bits from the stream.
|
||||
*/
|
||||
public int readRawFixed32() {
|
||||
return (readRawByte() & 0x0ff)
|
||||
| ((readRawByte() & 0x0ff) << 8)
|
||||
| ((readRawByte() & 0x0ff) << 16)
|
||||
| ((readRawByte() & 0x0ff) << 24);
|
||||
}
|
||||
|
||||
//
|
||||
// Writing at a the end of the stream.
|
||||
//
|
||||
|
||||
/**
|
||||
* Advance to the next write buffer, allocating it if necessary.
|
||||
*
|
||||
* Must be called immediately <b>before</b> the next write, not after a write,
|
||||
* so that a dangling empty buffer is not created. Doing so will interfere
|
||||
* with the expectation that mWriteIndex will point past the end of the buffer
|
||||
* until the next read happens.
|
||||
*/
|
||||
private void nextWriteBuffer() {
|
||||
mWriteBufIndex++;
|
||||
if (mWriteBufIndex >= mBufferCount) {
|
||||
mWriteBuffer = new byte[mChunkSize];
|
||||
mBuffers.add(mWriteBuffer);
|
||||
mBufferCount++;
|
||||
} else {
|
||||
mWriteBuffer = mBuffers.get(mWriteBufIndex);
|
||||
}
|
||||
mWriteIndex = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Write a single byte to the stream.
|
||||
*/
|
||||
public void writeRawByte(byte val) {
|
||||
if (mWriteIndex >= mChunkSize) {
|
||||
nextWriteBuffer();
|
||||
}
|
||||
mWriteBuffer[mWriteIndex++] = val;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return how many bytes a 32 bit unsigned varint will take when written to the stream.
|
||||
*/
|
||||
public static int getRawVarint32Size(int val) {
|
||||
if ((val & (0xffffffff << 7)) == 0) return 1;
|
||||
if ((val & (0xffffffff << 14)) == 0) return 2;
|
||||
if ((val & (0xffffffff << 21)) == 0) return 3;
|
||||
if ((val & (0xffffffff << 28)) == 0) return 4;
|
||||
return 5;
|
||||
}
|
||||
|
||||
/**
|
||||
* Write an unsigned varint to the stream. A signed value would need to take 10 bytes.
|
||||
*
|
||||
* @param val treated as unsigned.
|
||||
*/
|
||||
public void writeRawVarint32(int val) {
|
||||
while (true) {
|
||||
if ((val & ~0x7F) == 0) {
|
||||
writeRawByte((byte)val);
|
||||
return;
|
||||
} else {
|
||||
writeRawByte((byte)((val & 0x7F) | 0x80));
|
||||
val >>>= 7;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return how many bytes a 32 bit signed zig zag value will take when written to the stream.
|
||||
*/
|
||||
public static int getRawZigZag32Size(int val) {
|
||||
return getRawVarint32Size(zigZag32(val));
|
||||
}
|
||||
|
||||
/**
|
||||
* Write a zig-zag encoded value.
|
||||
*
|
||||
* @param val treated as signed
|
||||
*/
|
||||
public void writeRawZigZag32(int val) {
|
||||
writeRawVarint32(zigZag32(val));
|
||||
}
|
||||
|
||||
/**
|
||||
* Return how many bytes a 64 bit varint will take when written to the stream.
|
||||
*/
|
||||
public static int getRawVarint64Size(long val) {
|
||||
if ((val & (0xffffffffffffffffL << 7)) == 0) return 1;
|
||||
if ((val & (0xffffffffffffffffL << 14)) == 0) return 2;
|
||||
if ((val & (0xffffffffffffffffL << 21)) == 0) return 3;
|
||||
if ((val & (0xffffffffffffffffL << 28)) == 0) return 4;
|
||||
if ((val & (0xffffffffffffffffL << 35)) == 0) return 5;
|
||||
if ((val & (0xffffffffffffffffL << 42)) == 0) return 6;
|
||||
if ((val & (0xffffffffffffffffL << 49)) == 0) return 7;
|
||||
if ((val & (0xffffffffffffffffL << 56)) == 0) return 8;
|
||||
if ((val & (0xffffffffffffffffL << 63)) == 0) return 9;
|
||||
return 10;
|
||||
}
|
||||
|
||||
/**
|
||||
* Write a 64 bit varint to the stream.
|
||||
*/
|
||||
public void writeRawVarint64(long val) {
|
||||
while (true) {
|
||||
if ((val & ~0x7FL) == 0) {
|
||||
writeRawByte((byte)val);
|
||||
return;
|
||||
} else {
|
||||
writeRawByte((byte)((val & 0x7F) | 0x80));
|
||||
val >>>= 7;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return how many bytes a signed 64 bit zig zag value will take when written to the stream.
|
||||
*/
|
||||
public static int getRawZigZag64Size(long val) {
|
||||
return getRawVarint64Size(zigZag64(val));
|
||||
}
|
||||
|
||||
/**
|
||||
* Write a 64 bit signed zig zag value to the stream.
|
||||
*/
|
||||
public void writeRawZigZag64(long val) {
|
||||
writeRawVarint64(zigZag64(val));
|
||||
}
|
||||
|
||||
/**
|
||||
* Write 4 little endian bytes to the stream.
|
||||
*/
|
||||
public void writeRawFixed32(int val) {
|
||||
writeRawByte((byte)(val));
|
||||
writeRawByte((byte)(val >> 8));
|
||||
writeRawByte((byte)(val >> 16));
|
||||
writeRawByte((byte)(val >> 24));
|
||||
}
|
||||
|
||||
/**
|
||||
* Write 8 little endian bytes to the stream.
|
||||
*/
|
||||
public void writeRawFixed64(long val) {
|
||||
writeRawByte((byte)(val));
|
||||
writeRawByte((byte)(val >> 8));
|
||||
writeRawByte((byte)(val >> 16));
|
||||
writeRawByte((byte)(val >> 24));
|
||||
writeRawByte((byte)(val >> 32));
|
||||
writeRawByte((byte)(val >> 40));
|
||||
writeRawByte((byte)(val >> 48));
|
||||
writeRawByte((byte)(val >> 56));
|
||||
}
|
||||
|
||||
/**
|
||||
* Write a buffer to the stream. Writes nothing if val is null or zero-length.
|
||||
*/
|
||||
public void writeRawBuffer(byte[] val) {
|
||||
if (val != null && val.length > 0) {
|
||||
writeRawBuffer(val, 0, val.length);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Write part of an array of bytes.
|
||||
*/
|
||||
public void writeRawBuffer(byte[] val, int offset, int length) {
|
||||
if (val == null) {
|
||||
return;
|
||||
}
|
||||
// Write up to the amount left in the first chunk to write.
|
||||
int amt = length < (mChunkSize - mWriteIndex) ? length : (mChunkSize - mWriteIndex);
|
||||
if (amt > 0) {
|
||||
System.arraycopy(val, offset, mWriteBuffer, mWriteIndex, amt);
|
||||
mWriteIndex += amt;
|
||||
length -= amt;
|
||||
offset += amt;
|
||||
}
|
||||
while (length > 0) {
|
||||
// We know we're now at the beginning of a chunk
|
||||
nextWriteBuffer();
|
||||
amt = length < mChunkSize ? length : mChunkSize;
|
||||
System.arraycopy(val, offset, mWriteBuffer, mWriteIndex, amt);
|
||||
mWriteIndex += amt;
|
||||
length -= amt;
|
||||
offset += amt;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Copies data _size_ bytes of data within this buffer from _srcOffset_
|
||||
* to the current write position. Like memmov but handles the chunked buffer.
|
||||
*/
|
||||
public void writeFromThisBuffer(int srcOffset, int size) {
|
||||
if (mReadLimit < 0) {
|
||||
throw new IllegalStateException("writeFromThisBuffer before startEditing");
|
||||
}
|
||||
if (srcOffset < getWritePos()) {
|
||||
throw new IllegalArgumentException("Can only move forward in the buffer --"
|
||||
+ " srcOffset=" + srcOffset + " size=" + size + " " + getDebugString());
|
||||
}
|
||||
if (srcOffset + size > mReadableSize) {
|
||||
throw new IllegalArgumentException("Trying to move more data than there is --"
|
||||
+ " srcOffset=" + srcOffset + " size=" + size + " " + getDebugString());
|
||||
}
|
||||
if (size == 0) {
|
||||
return;
|
||||
}
|
||||
if (srcOffset == ((mWriteBufIndex) * mChunkSize) + mWriteIndex /* write pos */) {
|
||||
// Writing to the same location. Just advance the write pointer. We already
|
||||
// checked that size is in bounds, so we don't need to do any more range
|
||||
// checking.
|
||||
if (size <= mChunkSize - mWriteIndex) {
|
||||
mWriteIndex += size;
|
||||
} else {
|
||||
size -= mChunkSize - mWriteIndex;
|
||||
mWriteIndex = size % mChunkSize;
|
||||
if (mWriteIndex == 0) {
|
||||
// Roll it back so nextWriteBuffer can do its job
|
||||
// on the next call (also makes mBuffers.get() not
|
||||
// fail if we're at the end).
|
||||
mWriteIndex = mChunkSize;
|
||||
mWriteBufIndex += (size / mChunkSize);
|
||||
} else {
|
||||
mWriteBufIndex += 1 + (size / mChunkSize);
|
||||
}
|
||||
mWriteBuffer = mBuffers.get(mWriteBufIndex);
|
||||
}
|
||||
} else {
|
||||
// Loop through the buffer, copying as much as we can each time.
|
||||
// We already bounds checked so we don't need to do it again here,
|
||||
// and nextWriteBuffer will never allocate.
|
||||
int readBufIndex = srcOffset / mChunkSize;
|
||||
byte[] readBuffer = mBuffers.get(readBufIndex);
|
||||
int readIndex = srcOffset % mChunkSize;
|
||||
while (size > 0) {
|
||||
if (mWriteIndex >= mChunkSize) {
|
||||
nextWriteBuffer();
|
||||
}
|
||||
if (readIndex >= mChunkSize) {
|
||||
readBufIndex++;
|
||||
readBuffer = mBuffers.get(readBufIndex);
|
||||
readIndex = 0;
|
||||
}
|
||||
final int spaceInWriteBuffer = mChunkSize - mWriteIndex;
|
||||
final int availableInReadBuffer = mChunkSize - readIndex;
|
||||
final int amt = Math.min(size, Math.min(spaceInWriteBuffer, availableInReadBuffer));
|
||||
System.arraycopy(readBuffer, readIndex, mWriteBuffer, mWriteIndex, amt);
|
||||
mWriteIndex += amt;
|
||||
readIndex += amt;
|
||||
size -= amt;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Writing at a particular location.
|
||||
//
|
||||
|
||||
/**
|
||||
* Returns the index into the virtual array of the write pointer.
|
||||
*/
|
||||
public int getWritePos() {
|
||||
return ((mWriteBufIndex) * mChunkSize) + mWriteIndex;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets the write pointer to a virtual location as returned by getWritePos.
|
||||
*/
|
||||
public void rewindWriteTo(int writePos) {
|
||||
if (writePos > getWritePos()) {
|
||||
throw new RuntimeException("rewindWriteTo only can go backwards" + writePos);
|
||||
}
|
||||
mWriteBufIndex = writePos / mChunkSize;
|
||||
mWriteIndex = writePos % mChunkSize;
|
||||
if (mWriteIndex == 0 && mWriteBufIndex != 0) {
|
||||
// Roll back so nextWriteBuffer can do its job on the next call
|
||||
// but at the first write we're at 0.
|
||||
mWriteIndex = mChunkSize;
|
||||
mWriteBufIndex--;
|
||||
}
|
||||
mWriteBuffer = mBuffers.get(mWriteBufIndex);
|
||||
}
|
||||
|
||||
/**
|
||||
* Read a 32 bit value from the stream.
|
||||
*
|
||||
* Doesn't touch or affect mWritePos.
|
||||
*/
|
||||
public int getRawFixed32At(int pos) {
|
||||
return (0x00ff & (int)mBuffers.get(pos / mChunkSize)[pos % mChunkSize])
|
||||
| ((0x0ff & (int)mBuffers.get((pos+1) / mChunkSize)[(pos+1) % mChunkSize]) << 8)
|
||||
| ((0x0ff & (int)mBuffers.get((pos+2) / mChunkSize)[(pos+2) % mChunkSize]) << 16)
|
||||
| ((0x0ff & (int)mBuffers.get((pos+3) / mChunkSize)[(pos+3) % mChunkSize]) << 24);
|
||||
}
|
||||
|
||||
/**
|
||||
* Overwrite a 32 bit value in the stream.
|
||||
*
|
||||
* Doesn't touch or affect mWritePos.
|
||||
*/
|
||||
public void editRawFixed32(int pos, int val) {
|
||||
mBuffers.get(pos / mChunkSize)[pos % mChunkSize] = (byte)(val);
|
||||
mBuffers.get((pos+1) / mChunkSize)[(pos+1) % mChunkSize] = (byte)(val >> 8);
|
||||
mBuffers.get((pos+2) / mChunkSize)[(pos+2) % mChunkSize] = (byte)(val >> 16);
|
||||
mBuffers.get((pos+3) / mChunkSize)[(pos+3) % mChunkSize] = (byte)(val >> 24);
|
||||
}
|
||||
|
||||
//
|
||||
// Zigging and zagging
|
||||
//
|
||||
|
||||
/**
|
||||
* Zig-zag encode a 32 bit value.
|
||||
*/
|
||||
private static int zigZag32(int val) {
|
||||
return (val << 1) ^ (val >> 31);
|
||||
}
|
||||
|
||||
/**
|
||||
* Zig-zag encode a 64 bit value.
|
||||
*/
|
||||
private static long zigZag64(long val) {
|
||||
return (val << 1) ^ (val >> 63);
|
||||
}
|
||||
|
||||
//
|
||||
// Debugging / testing
|
||||
//
|
||||
// VisibleForTesting
|
||||
|
||||
/**
|
||||
* Get a copy of the first _size_ bytes of data. This is not range
|
||||
* checked, and if the bounds are outside what has been written you will
|
||||
* get garbage and if it is outside the buffers that have been allocated,
|
||||
* you will get an exception.
|
||||
*/
|
||||
public byte[] getBytes(int size) {
|
||||
final byte[] result = new byte[size];
|
||||
|
||||
final int bufCount = size / mChunkSize;
|
||||
int bufIndex;
|
||||
int writeIndex = 0;
|
||||
|
||||
for (bufIndex=0; bufIndex<bufCount; bufIndex++) {
|
||||
System.arraycopy(mBuffers.get(bufIndex), 0, result, writeIndex, mChunkSize);
|
||||
writeIndex += mChunkSize;
|
||||
}
|
||||
|
||||
final int lastSize = size - (bufCount * mChunkSize);
|
||||
if (lastSize > 0) {
|
||||
System.arraycopy(mBuffers.get(bufIndex), 0, result, writeIndex, lastSize);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the number of chunks allocated.
|
||||
*/
|
||||
// VisibleForTesting
|
||||
public int getChunkCount() {
|
||||
return mBuffers.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the write position inside the current write chunk.
|
||||
*/
|
||||
// VisibleForTesting
|
||||
public int getWriteIndex() {
|
||||
return mWriteIndex;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the index of the current write chunk in the list of chunks.
|
||||
*/
|
||||
// VisibleForTesting
|
||||
public int getWriteBufIndex() {
|
||||
return mWriteBufIndex;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return debugging information about this EncodedBuffer object.
|
||||
*/
|
||||
public String getDebugString() {
|
||||
return "EncodedBuffer( mChunkSize=" + mChunkSize + " mBuffers.size=" + mBuffers.size()
|
||||
+ " mBufferCount=" + mBufferCount + " mWriteIndex=" + mWriteIndex
|
||||
+ " mWriteBufIndex=" + mWriteBufIndex + " mReadBufIndex=" + mReadBufIndex
|
||||
+ " mReadIndex=" + mReadIndex + " mReadableSize=" + mReadableSize
|
||||
+ " mReadLimit=" + mReadLimit + " )";
|
||||
}
|
||||
|
||||
/**
|
||||
* Print the internal buffer chunks.
|
||||
*/
|
||||
public void dumpBuffers(String tag) {
|
||||
final int N = mBuffers.size();
|
||||
int start = 0;
|
||||
for (int i=0; i<N; i++) {
|
||||
start += dumpByteString(tag, "{" + i + "} ", start, mBuffers.get(i));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Print the internal buffer chunks.
|
||||
*/
|
||||
public static void dumpByteString(String tag, String prefix, byte[] buf) {
|
||||
dumpByteString(tag, prefix, 0, buf);
|
||||
}
|
||||
|
||||
/**
|
||||
* Print the internal buffer chunks.
|
||||
*/
|
||||
private static int dumpByteString(String tag, String prefix, int start, byte[] buf) {
|
||||
StringBuffer sb = new StringBuffer();
|
||||
final int length = buf.length;
|
||||
final int lineLen = 16;
|
||||
int i;
|
||||
for (i=0; i<length; i++) {
|
||||
if (i % lineLen == 0) {
|
||||
if (i != 0) {
|
||||
Log.d(tag, sb.toString());
|
||||
sb = new StringBuffer();
|
||||
}
|
||||
sb.append(prefix);
|
||||
sb.append('[');
|
||||
sb.append(start + i);
|
||||
sb.append(']');
|
||||
sb.append(' ');
|
||||
} else {
|
||||
sb.append(' ');
|
||||
}
|
||||
byte b = buf[i];
|
||||
byte c = (byte)((b >> 4) & 0x0f);
|
||||
if (c < 10) {
|
||||
sb.append((char)('0' + c));
|
||||
} else {
|
||||
sb.append((char)('a' - 10 + c));
|
||||
}
|
||||
byte d = (byte)(b & 0x0f);
|
||||
if (d < 10) {
|
||||
sb.append((char)('0' + d));
|
||||
} else {
|
||||
sb.append((char)('a' - 10 + d));
|
||||
}
|
||||
}
|
||||
Log.d(tag, sb.toString());
|
||||
return length;
|
||||
}
|
||||
}
|
||||
1599
core/java/android/util/proto/ProtoOutputStream.java
Normal file
1599
core/java/android/util/proto/ProtoOutputStream.java
Normal file
File diff suppressed because it is too large
Load Diff
38
core/java/android/util/proto/ProtoParseException.java
Normal file
38
core/java/android/util/proto/ProtoParseException.java
Normal file
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright (C) 2012 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package android.util.proto;
|
||||
|
||||
import android.annotation.TestApi;
|
||||
|
||||
/**
|
||||
* Thrown when there is an error parsing protobuf data.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
@TestApi
|
||||
public class ProtoParseException extends RuntimeException {
|
||||
|
||||
/**
|
||||
* Construct a ProtoParseException.
|
||||
*
|
||||
* @param msg The message.
|
||||
*/
|
||||
public ProtoParseException(String msg) {
|
||||
super(msg);
|
||||
}
|
||||
}
|
||||
|
||||
5
core/java/android/util/proto/package.html
Normal file
5
core/java/android/util/proto/package.html
Normal file
@@ -0,0 +1,5 @@
|
||||
<body>
|
||||
Provides utility classes to export protocol buffers from the system.
|
||||
|
||||
{@hide}
|
||||
</body>
|
||||
41
tools/streaming_proto/Android.mk
Normal file
41
tools/streaming_proto/Android.mk
Normal file
@@ -0,0 +1,41 @@
|
||||
#
|
||||
# Copyright (C) 2015 The Android Open Source Project
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
LOCAL_PATH:= $(call my-dir)
|
||||
|
||||
# ==========================================================
|
||||
# Build the host executable: protoc-gen-javastream
|
||||
# ==========================================================
|
||||
include $(CLEAR_VARS)
|
||||
LOCAL_MODULE := protoc-gen-javastream
|
||||
LOCAL_SRC_FILES := \
|
||||
Errors.cpp \
|
||||
string_utils.cpp \
|
||||
main.cpp
|
||||
LOCAL_SHARED_LIBRARIES := \
|
||||
libprotoc
|
||||
include $(BUILD_HOST_EXECUTABLE)
|
||||
|
||||
# ==========================================================
|
||||
# Build the java test
|
||||
# ==========================================================
|
||||
include $(CLEAR_VARS)
|
||||
LOCAL_SRC_FILES := \
|
||||
$(call all-java-files-under, test) \
|
||||
$(call all-proto-files-under, test)
|
||||
LOCAL_MODULE := StreamingProtoTest
|
||||
LOCAL_PROTOC_OPTIMIZE_TYPE := stream
|
||||
include $(BUILD_JAVA_LIBRARY)
|
||||
|
||||
87
tools/streaming_proto/Errors.cpp
Normal file
87
tools/streaming_proto/Errors.cpp
Normal file
@@ -0,0 +1,87 @@
|
||||
#include "Errors.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
namespace android {
|
||||
namespace javastream_proto {
|
||||
|
||||
Errors ERRORS;
|
||||
|
||||
const string UNKNOWN_FILE;
|
||||
const int UNKNOWN_LINE = 0;
|
||||
|
||||
Error::Error()
|
||||
{
|
||||
}
|
||||
|
||||
Error::Error(const Error& that)
|
||||
:filename(that.filename),
|
||||
lineno(that.lineno),
|
||||
message(that.message)
|
||||
{
|
||||
}
|
||||
|
||||
Error::Error(const string& f, int l, const char* m)
|
||||
:filename(f),
|
||||
lineno(l),
|
||||
message(m)
|
||||
{
|
||||
}
|
||||
|
||||
Errors::Errors()
|
||||
:m_errors()
|
||||
{
|
||||
}
|
||||
|
||||
Errors::~Errors()
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
Errors::Add(const string& filename, int lineno, const char* format, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
AddImpl(filename, lineno, format, args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
void
|
||||
Errors::AddImpl(const string& filename, int lineno, const char* format, va_list args)
|
||||
{
|
||||
va_list args2;
|
||||
va_copy(args2, args);
|
||||
int message_size = vsnprintf((char*)NULL, 0, format, args2);
|
||||
va_end(args2);
|
||||
|
||||
char* buffer = new char[message_size+1];
|
||||
vsnprintf(buffer, message_size, format, args);
|
||||
Error error(filename, lineno, buffer);
|
||||
delete[] buffer;
|
||||
|
||||
m_errors.push_back(error);
|
||||
}
|
||||
|
||||
void
|
||||
Errors::Print() const
|
||||
{
|
||||
for (vector<Error>::const_iterator it = m_errors.begin(); it != m_errors.end(); it++) {
|
||||
if (it->filename == UNKNOWN_FILE) {
|
||||
fprintf(stderr, "%s", it->message.c_str());
|
||||
} else if (it->lineno == UNKNOWN_LINE) {
|
||||
fprintf(stderr, "%s:%s", it->filename.c_str(), it->message.c_str());
|
||||
} else {
|
||||
fprintf(stderr, "%s:%d:%s", it->filename.c_str(), it->lineno, it->message.c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
Errors::HasErrors() const
|
||||
{
|
||||
return m_errors.size() > 0;
|
||||
}
|
||||
|
||||
} // namespace javastream_proto
|
||||
} // namespace android
|
||||
|
||||
48
tools/streaming_proto/Errors.h
Normal file
48
tools/streaming_proto/Errors.h
Normal file
@@ -0,0 +1,48 @@
|
||||
#include <stdio.h>
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace android {
|
||||
namespace javastream_proto {
|
||||
|
||||
using namespace std;
|
||||
|
||||
struct Error
|
||||
{
|
||||
Error();
|
||||
explicit Error(const Error& that);
|
||||
Error(const string& filename, int lineno, const char* message);
|
||||
|
||||
string filename;
|
||||
int lineno;
|
||||
string message;
|
||||
};
|
||||
|
||||
class Errors
|
||||
{
|
||||
public:
|
||||
Errors();
|
||||
~Errors();
|
||||
|
||||
// Add an error
|
||||
void Add(const string& filename, int lineno, const char* format, ...);
|
||||
|
||||
// Print the errors to stderr if there are any.
|
||||
void Print() const;
|
||||
|
||||
bool HasErrors() const;
|
||||
|
||||
private:
|
||||
// The errors that have been added
|
||||
vector<Error> m_errors;
|
||||
void AddImpl(const string& filename, int lineno, const char* format, va_list ap);
|
||||
};
|
||||
|
||||
extern Errors ERRORS;
|
||||
extern const string UNKNOWN_FILE;
|
||||
extern const int UNKNOWN_LINE;
|
||||
|
||||
|
||||
} // namespace javastream_proto
|
||||
} // namespace android
|
||||
391
tools/streaming_proto/main.cpp
Normal file
391
tools/streaming_proto/main.cpp
Normal file
@@ -0,0 +1,391 @@
|
||||
#include "Errors.h"
|
||||
|
||||
#include "string_utils.h"
|
||||
|
||||
#include "google/protobuf/compiler/plugin.pb.h"
|
||||
#include "google/protobuf/io/zero_copy_stream_impl.h"
|
||||
#include "google/protobuf/text_format.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <iomanip>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <map>
|
||||
|
||||
using namespace android::javastream_proto;
|
||||
using namespace google::protobuf;
|
||||
using namespace google::protobuf::compiler;
|
||||
using namespace google::protobuf::io;
|
||||
using namespace std;
|
||||
|
||||
const int FIELD_TYPE_SHIFT = 32;
|
||||
const uint64_t FIELD_TYPE_DOUBLE = 1L << FIELD_TYPE_SHIFT;
|
||||
const uint64_t FIELD_TYPE_FLOAT = 2L << FIELD_TYPE_SHIFT;
|
||||
const uint64_t FIELD_TYPE_INT32 = 3L << FIELD_TYPE_SHIFT;
|
||||
const uint64_t FIELD_TYPE_INT64 = 4L << FIELD_TYPE_SHIFT;
|
||||
const uint64_t FIELD_TYPE_UINT32 = 5L << FIELD_TYPE_SHIFT;
|
||||
const uint64_t FIELD_TYPE_UINT64 = 6L << FIELD_TYPE_SHIFT;
|
||||
const uint64_t FIELD_TYPE_SINT32 = 7L << FIELD_TYPE_SHIFT;
|
||||
const uint64_t FIELD_TYPE_SINT64 = 8L << FIELD_TYPE_SHIFT;
|
||||
const uint64_t FIELD_TYPE_FIXED32 = 9L << FIELD_TYPE_SHIFT;
|
||||
const uint64_t FIELD_TYPE_FIXED64 = 10L << FIELD_TYPE_SHIFT;
|
||||
const uint64_t FIELD_TYPE_SFIXED32 = 11L << FIELD_TYPE_SHIFT;
|
||||
const uint64_t FIELD_TYPE_SFIXED64 = 12L << FIELD_TYPE_SHIFT;
|
||||
const uint64_t FIELD_TYPE_BOOL = 13L << FIELD_TYPE_SHIFT;
|
||||
const uint64_t FIELD_TYPE_STRING = 14L << FIELD_TYPE_SHIFT;
|
||||
const uint64_t FIELD_TYPE_BYTES = 15L << FIELD_TYPE_SHIFT;
|
||||
const uint64_t FIELD_TYPE_ENUM = 16L << FIELD_TYPE_SHIFT;
|
||||
const uint64_t FIELD_TYPE_OBJECT = 17L << FIELD_TYPE_SHIFT;
|
||||
|
||||
const int FIELD_COUNT_SHIFT = 40;
|
||||
const uint64_t FIELD_COUNT_SINGLE = 1L << FIELD_COUNT_SHIFT;
|
||||
const uint64_t FIELD_COUNT_REPEATED = 2L << FIELD_COUNT_SHIFT;
|
||||
const uint64_t FIELD_COUNT_PACKED = 5L << FIELD_COUNT_SHIFT;
|
||||
|
||||
|
||||
/**
|
||||
* See if this is the file for this request, and not one of the imported ones.
|
||||
*/
|
||||
static bool
|
||||
should_generate_for_file(const CodeGeneratorRequest& request, const string& file)
|
||||
{
|
||||
const int N = request.file_to_generate_size();
|
||||
for (int i=0; i<N; i++) {
|
||||
if (request.file_to_generate(i) == file) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* If the descriptor gives us a class name, use that. Otherwise make one up from
|
||||
* the filename of the .proto file.
|
||||
*/
|
||||
static string
|
||||
make_outer_class_name(const FileDescriptorProto& file_descriptor)
|
||||
{
|
||||
string name = file_descriptor.options().java_outer_classname();
|
||||
if (name.size() == 0) {
|
||||
name = to_camel_case(file_base_name(file_descriptor.name()));
|
||||
if (name.size() == 0) {
|
||||
ERRORS.Add(UNKNOWN_FILE, UNKNOWN_LINE,
|
||||
"Unable to make an outer class name for file: %s",
|
||||
file_descriptor.name().c_str());
|
||||
name = "Unknown";
|
||||
}
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Figure out the package name that we are generating.
|
||||
*/
|
||||
static string
|
||||
make_java_package(const FileDescriptorProto& file_descriptor) {
|
||||
if (file_descriptor.options().has_java_package()) {
|
||||
return file_descriptor.options().java_package();
|
||||
} else {
|
||||
return file_descriptor.package();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Figure out the name of the file we are generating.
|
||||
*/
|
||||
static string
|
||||
make_file_name(const FileDescriptorProto& file_descriptor)
|
||||
{
|
||||
string const package = make_java_package(file_descriptor);
|
||||
string result;
|
||||
if (package.size() > 0) {
|
||||
result = replace_string(package, '.', '/');
|
||||
result += '/';
|
||||
}
|
||||
|
||||
result += make_outer_class_name(file_descriptor);
|
||||
result += ".java";
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static string
|
||||
indent_more(const string& indent)
|
||||
{
|
||||
return indent + " ";
|
||||
}
|
||||
|
||||
/**
|
||||
* Write the constants for an enum.
|
||||
*/
|
||||
static void
|
||||
write_enum(stringstream& text, const EnumDescriptorProto& enu, const string& indent)
|
||||
{
|
||||
const int N = enu.value_size();
|
||||
text << indent << "// enum " << enu.name() << endl;
|
||||
for (int i=0; i<N; i++) {
|
||||
const EnumValueDescriptorProto& value = enu.value(i);
|
||||
text << indent << "public static final int "
|
||||
<< make_constant_name(value.name())
|
||||
<< " = " << value.number() << ";" << endl;
|
||||
}
|
||||
text << endl;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the string name for a field.
|
||||
*/
|
||||
static string
|
||||
get_proto_type(const FieldDescriptorProto& field)
|
||||
{
|
||||
switch (field.type()) {
|
||||
case FieldDescriptorProto::TYPE_DOUBLE:
|
||||
return "double";
|
||||
case FieldDescriptorProto::TYPE_FLOAT:
|
||||
return "float";
|
||||
case FieldDescriptorProto::TYPE_INT64:
|
||||
return "int64";
|
||||
case FieldDescriptorProto::TYPE_UINT64:
|
||||
return "uint64";
|
||||
case FieldDescriptorProto::TYPE_INT32:
|
||||
return "int32";
|
||||
case FieldDescriptorProto::TYPE_FIXED64:
|
||||
return "fixed64";
|
||||
case FieldDescriptorProto::TYPE_FIXED32:
|
||||
return "fixed32";
|
||||
case FieldDescriptorProto::TYPE_BOOL:
|
||||
return "bool";
|
||||
case FieldDescriptorProto::TYPE_STRING:
|
||||
return "string";
|
||||
case FieldDescriptorProto::TYPE_GROUP:
|
||||
return "group<unsupported!>";
|
||||
case FieldDescriptorProto::TYPE_MESSAGE:
|
||||
return field.type_name();
|
||||
case FieldDescriptorProto::TYPE_BYTES:
|
||||
return "bytes";
|
||||
case FieldDescriptorProto::TYPE_UINT32:
|
||||
return "uint32";
|
||||
case FieldDescriptorProto::TYPE_ENUM:
|
||||
return field.type_name();
|
||||
case FieldDescriptorProto::TYPE_SFIXED32:
|
||||
return "sfixed32";
|
||||
case FieldDescriptorProto::TYPE_SFIXED64:
|
||||
return "sfixed64";
|
||||
case FieldDescriptorProto::TYPE_SINT32:
|
||||
return "sint32";
|
||||
case FieldDescriptorProto::TYPE_SINT64:
|
||||
return "sint64";
|
||||
default:
|
||||
// won't happen
|
||||
return "void";
|
||||
}
|
||||
}
|
||||
|
||||
static uint64_t
|
||||
get_field_id(const FieldDescriptorProto& field)
|
||||
{
|
||||
// Number
|
||||
uint64_t result = (uint32_t)field.number();
|
||||
|
||||
// Type
|
||||
switch (field.type()) {
|
||||
case FieldDescriptorProto::TYPE_DOUBLE:
|
||||
result |= FIELD_TYPE_DOUBLE;
|
||||
case FieldDescriptorProto::TYPE_FLOAT:
|
||||
result |= FIELD_TYPE_FLOAT;
|
||||
case FieldDescriptorProto::TYPE_INT64:
|
||||
result |= FIELD_TYPE_INT64;
|
||||
case FieldDescriptorProto::TYPE_UINT64:
|
||||
result |= FIELD_TYPE_UINT64;
|
||||
case FieldDescriptorProto::TYPE_INT32:
|
||||
result |= FIELD_TYPE_INT32;
|
||||
case FieldDescriptorProto::TYPE_FIXED64:
|
||||
result |= FIELD_TYPE_FIXED64;
|
||||
case FieldDescriptorProto::TYPE_FIXED32:
|
||||
result |= FIELD_TYPE_FIXED32;
|
||||
case FieldDescriptorProto::TYPE_BOOL:
|
||||
result |= FIELD_TYPE_BOOL;
|
||||
case FieldDescriptorProto::TYPE_STRING:
|
||||
result |= FIELD_TYPE_STRING;
|
||||
case FieldDescriptorProto::TYPE_MESSAGE:
|
||||
result |= FIELD_TYPE_OBJECT;
|
||||
case FieldDescriptorProto::TYPE_BYTES:
|
||||
result |= FIELD_TYPE_BYTES;
|
||||
case FieldDescriptorProto::TYPE_UINT32:
|
||||
result |= FIELD_TYPE_UINT32;
|
||||
case FieldDescriptorProto::TYPE_ENUM:
|
||||
result |= FIELD_TYPE_ENUM;
|
||||
case FieldDescriptorProto::TYPE_SFIXED32:
|
||||
result |= FIELD_TYPE_SFIXED32;
|
||||
case FieldDescriptorProto::TYPE_SFIXED64:
|
||||
result |= FIELD_TYPE_SFIXED64;
|
||||
case FieldDescriptorProto::TYPE_SINT32:
|
||||
result |= FIELD_TYPE_SINT32;
|
||||
case FieldDescriptorProto::TYPE_SINT64:
|
||||
result |= FIELD_TYPE_SINT64;
|
||||
default:
|
||||
;
|
||||
}
|
||||
|
||||
// Count
|
||||
if (field.options().packed()) {
|
||||
result |= FIELD_COUNT_PACKED;
|
||||
} else if (field.label() == FieldDescriptorProto::LABEL_REPEATED) {
|
||||
result |= FIELD_COUNT_REPEATED;
|
||||
} else {
|
||||
result |= FIELD_COUNT_SINGLE;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Write a field.
|
||||
*/
|
||||
static void
|
||||
write_field(stringstream& text, const FieldDescriptorProto& field, const string& indent)
|
||||
{
|
||||
string optional_comment = field.label() == FieldDescriptorProto::LABEL_OPTIONAL
|
||||
? "optional " : "";
|
||||
string repeated_comment = field.label() == FieldDescriptorProto::LABEL_REPEATED
|
||||
? "repeated " : "";
|
||||
string proto_type = get_proto_type(field);
|
||||
string packed_comment = field.options().packed()
|
||||
? " [packed=true]" : "";
|
||||
text << indent << "// " << optional_comment << repeated_comment << proto_type << ' '
|
||||
<< field.name() << " = " << field.number() << packed_comment << ';' << endl;
|
||||
|
||||
text << indent << "public static final long " << make_constant_name(field.name()) << " = 0x";
|
||||
|
||||
ios::fmtflags fmt(text.flags());
|
||||
text << setfill('0') << setw(16) << hex << get_field_id(field);
|
||||
text.flags(fmt);
|
||||
|
||||
text << "L;" << endl;
|
||||
|
||||
text << endl;
|
||||
}
|
||||
|
||||
/**
|
||||
* Write a Message constants class.
|
||||
*/
|
||||
static void
|
||||
write_message(stringstream& text, const DescriptorProto& message, const string& indent)
|
||||
{
|
||||
int N;
|
||||
const string indented = indent_more(indent);
|
||||
|
||||
text << indent << "// message " << message.name() << endl;
|
||||
text << indent << "public final class " << message.name() << " {" << endl;
|
||||
text << endl;
|
||||
|
||||
// Enums
|
||||
N = message.enum_type_size();
|
||||
for (int i=0; i<N; i++) {
|
||||
write_enum(text, message.enum_type(i), indented);
|
||||
}
|
||||
|
||||
// Nested classes
|
||||
N = message.nested_type_size();
|
||||
for (int i=0; i<N; i++) {
|
||||
write_message(text, message.nested_type(i), indented);
|
||||
}
|
||||
|
||||
// Fields
|
||||
N = message.field_size();
|
||||
for (int i=0; i<N; i++) {
|
||||
write_field(text, message.field(i), indented);
|
||||
}
|
||||
|
||||
text << indent << "}" << endl;
|
||||
text << endl;
|
||||
}
|
||||
|
||||
/**
|
||||
* Write the contents of a file.
|
||||
*/
|
||||
static void
|
||||
write_file(stringstream& text, const FileDescriptorProto& file_descriptor)
|
||||
{
|
||||
string const package_name = make_java_package(file_descriptor);
|
||||
string const outer_class_name = make_outer_class_name(file_descriptor);
|
||||
|
||||
text << "// Generated by protoc-gen-javastream. DO NOT MODIFY." << endl;
|
||||
text << "// source: " << file_descriptor.name() << endl << endl;
|
||||
|
||||
if (package_name.size() > 0) {
|
||||
if (package_name.size() > 0) {
|
||||
text << "package " << package_name << ";" << endl;
|
||||
text << endl;
|
||||
}
|
||||
}
|
||||
|
||||
// This bit of policy is android api rules specific: Raw proto classes
|
||||
// must never be in the API, but they should all be available for testing.
|
||||
text << "/** @hide */" << endl;
|
||||
text << "@android.annotation.TestApi" << endl;
|
||||
|
||||
text << "public final class " << outer_class_name << " {" << endl;
|
||||
text << endl;
|
||||
|
||||
int N;
|
||||
const string indented = indent_more("");
|
||||
|
||||
N = file_descriptor.enum_type_size();
|
||||
for (int i=0; i<N; i++) {
|
||||
write_enum(text, file_descriptor.enum_type(i), indented);
|
||||
}
|
||||
|
||||
N = file_descriptor.message_type_size();
|
||||
for (int i=0; i<N; i++) {
|
||||
write_message(text, file_descriptor.message_type(i), indented);
|
||||
}
|
||||
|
||||
text << "}" << endl;
|
||||
}
|
||||
|
||||
/**
|
||||
* Main.
|
||||
*/
|
||||
int
|
||||
main(int argc, char const*const* argv)
|
||||
{
|
||||
(void)argc;
|
||||
(void)argv;
|
||||
|
||||
GOOGLE_PROTOBUF_VERIFY_VERSION;
|
||||
|
||||
CodeGeneratorRequest request;
|
||||
CodeGeneratorResponse response;
|
||||
|
||||
// Read the request
|
||||
request.ParseFromIstream(&cin);
|
||||
|
||||
// Build the files we need.
|
||||
const int N = request.proto_file_size();
|
||||
for (int i=0; i<N; i++) {
|
||||
const FileDescriptorProto& file_descriptor = request.proto_file(i);
|
||||
if (should_generate_for_file(request, file_descriptor.name())) {
|
||||
// Generate the text
|
||||
stringstream text;
|
||||
write_file(text, file_descriptor);
|
||||
|
||||
// Put the text in the response
|
||||
CodeGeneratorResponse::File* file_response = response.add_file();
|
||||
file_response->set_name(make_file_name(file_descriptor));
|
||||
file_response->set_content(text.str());
|
||||
|
||||
cerr << "writing file: " << file_response->name() << endl;
|
||||
}
|
||||
}
|
||||
|
||||
// If we had errors, don't write the response. Print the errors and exit.
|
||||
if (ERRORS.HasErrors()) {
|
||||
ERRORS.Print();
|
||||
return 1;
|
||||
}
|
||||
|
||||
// If we didn't have errors, write the response and exit happily.
|
||||
response.SerializeToOstream(&cout);
|
||||
return 0;
|
||||
}
|
||||
95
tools/streaming_proto/string_utils.cpp
Normal file
95
tools/streaming_proto/string_utils.cpp
Normal file
@@ -0,0 +1,95 @@
|
||||
|
||||
#include "string_utils.h"
|
||||
#include <iostream>
|
||||
|
||||
namespace android {
|
||||
namespace javastream_proto {
|
||||
|
||||
using namespace std;
|
||||
|
||||
string
|
||||
to_camel_case(const string& str)
|
||||
{
|
||||
string result;
|
||||
const int N = str.size();
|
||||
result.reserve(N);
|
||||
bool capitalize_next = true;
|
||||
for (int i=0; i<N; i++) {
|
||||
char c = str[i];
|
||||
if (c == '_') {
|
||||
capitalize_next = true;
|
||||
} else {
|
||||
if (capitalize_next && c >= 'a' && c <= 'z') {
|
||||
c = 'A' + c - 'a';
|
||||
capitalize_next = false;
|
||||
} else if (c >= 'A' && c <= 'Z') {
|
||||
capitalize_next = false;
|
||||
} else if (c >= '0' && c <= '9') {
|
||||
capitalize_next = true;
|
||||
} else {
|
||||
// All other characters (e.g. non-latin) count as capital.
|
||||
capitalize_next = false;
|
||||
}
|
||||
result += c;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
string
|
||||
make_constant_name(const string& str)
|
||||
{
|
||||
string result;
|
||||
const int N = str.size();
|
||||
bool underscore_next = false;
|
||||
for (int i=0; i<N; i++) {
|
||||
char c = str[i];
|
||||
if (c >= 'A' && c <= 'Z') {
|
||||
if (underscore_next) {
|
||||
result += '_';
|
||||
underscore_next = false;
|
||||
}
|
||||
} else if (c >= 'a' && c <= 'z') {
|
||||
c = 'A' + c - 'a';
|
||||
underscore_next = true;
|
||||
} else if (c == '_') {
|
||||
underscore_next = false;
|
||||
}
|
||||
result += c;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
string
|
||||
file_base_name(const string& str)
|
||||
{
|
||||
size_t start = str.rfind('/');
|
||||
if (start == string::npos) {
|
||||
start = 0;
|
||||
} else {
|
||||
start++;
|
||||
}
|
||||
size_t end = str.find('.', start);
|
||||
if (end == string::npos) {
|
||||
end = str.size();
|
||||
}
|
||||
return str.substr(start, end-start);
|
||||
}
|
||||
|
||||
string
|
||||
replace_string(const string& str, const char replace, const char with)
|
||||
{
|
||||
string result(str);
|
||||
const int N = result.size();
|
||||
for (int i=0; i<N; i++) {
|
||||
if (result[i] == replace) {
|
||||
result[i] = with;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
} // namespace javastream_proto
|
||||
} // namespace android
|
||||
|
||||
|
||||
32
tools/streaming_proto/string_utils.h
Normal file
32
tools/streaming_proto/string_utils.h
Normal file
@@ -0,0 +1,32 @@
|
||||
#include <string>
|
||||
|
||||
namespace android {
|
||||
namespace javastream_proto {
|
||||
|
||||
using namespace std;
|
||||
|
||||
/**
|
||||
* Capitalizes the string, removes underscores and makes the next letter
|
||||
* capitalized, and makes the letter following numbers capitalized.
|
||||
*/
|
||||
string to_camel_case(const string& str);
|
||||
|
||||
/**
|
||||
* Capitalize and insert underscores for CamelCase.
|
||||
*/
|
||||
string make_constant_name(const string& str);
|
||||
|
||||
/**
|
||||
* Returns the part of a file name that isn't a path and isn't a type suffix.
|
||||
*/
|
||||
string file_base_name(const string& str);
|
||||
|
||||
/**
|
||||
* Replace all occurances of 'replace' with 'with'.
|
||||
*/
|
||||
string replace_string(const string& str, const char replace, const char with);
|
||||
|
||||
|
||||
} // namespace javastream_proto
|
||||
} // namespace android
|
||||
|
||||
26
tools/streaming_proto/test/imported.proto
Normal file
26
tools/streaming_proto/test/imported.proto
Normal file
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* Copyright (C) 2016 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
syntax = "proto2";
|
||||
|
||||
package com.android.streaming_proto_test;
|
||||
|
||||
/**
|
||||
* Message that is used from the other file.
|
||||
*/
|
||||
message ImportedMessage {
|
||||
optional int32 data = 1;
|
||||
};
|
||||
@@ -0,0 +1,7 @@
|
||||
package com.android.streaming_proto_test;
|
||||
|
||||
public class Main {
|
||||
public void main(String[] argv) {
|
||||
System.out.println("hello world");
|
||||
}
|
||||
}
|
||||
124
tools/streaming_proto/test/test.proto
Normal file
124
tools/streaming_proto/test/test.proto
Normal file
@@ -0,0 +1,124 @@
|
||||
/*
|
||||
* Copyright (C) 2016 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
syntax = "proto2";
|
||||
|
||||
import "frameworks/base/tools/streaming_proto/test/imported.proto";
|
||||
|
||||
package com.android.streaming_proto_test;
|
||||
|
||||
/**
|
||||
* Enum that outside the scope of any classes.
|
||||
*/
|
||||
enum Outside {
|
||||
OUTSIDE_0 = 0;
|
||||
OUTSIDE_1 = 1;
|
||||
};
|
||||
|
||||
message Sibling {
|
||||
optional int32 int32_field = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Message with all of the field types.
|
||||
*/
|
||||
message All {
|
||||
/**
|
||||
* Enum that is inside the scope of a class.
|
||||
*/
|
||||
enum Inside {
|
||||
option allow_alias = true;
|
||||
INSIDE_0 = 0;
|
||||
INSIDE_1 = 1;
|
||||
INSIDE_1A = 1;
|
||||
};
|
||||
|
||||
/**
|
||||
* Message that is recursive.
|
||||
*/
|
||||
message Nested {
|
||||
optional int32 data = 10001;
|
||||
optional Nested nested = 10002;
|
||||
};
|
||||
|
||||
optional double double_field = 10;
|
||||
repeated double double_field_repeated = 11;
|
||||
repeated double double_field_packed = 12 [packed=true];
|
||||
|
||||
optional float float_field = 20;
|
||||
repeated float float_field_repeated = 21;
|
||||
repeated float float_field_packed = 22 [packed=true];
|
||||
|
||||
optional int32 int32_field = 30;
|
||||
repeated int32 int32_field_repeated = 31;
|
||||
repeated int32 int32_field_packed = 32 [packed=true];
|
||||
|
||||
optional int64 int64_field = 40;
|
||||
repeated int64 int64_field_repeated = 41;
|
||||
repeated int64 int64_field_packed = 42 [packed=true];
|
||||
|
||||
optional uint32 uint32_field = 50;
|
||||
repeated uint32 uint32_field_repeated = 51;
|
||||
repeated uint32 uint32_field_packed = 52 [packed=true];
|
||||
|
||||
optional uint64 uint64_field = 60;
|
||||
repeated uint64 uint64_field_repeated = 61;
|
||||
repeated uint64 uint64_field_packed = 62 [packed=true];
|
||||
|
||||
optional sint32 sint32_field = 70;
|
||||
repeated sint32 sint32_field_repeated = 71;
|
||||
repeated sint32 sint32_field_packed = 72 [packed=true];
|
||||
|
||||
optional sint64 sint64_field = 80;
|
||||
repeated sint64 sint64_field_repeated = 81;
|
||||
repeated sint64 sint64_field_packed = 82 [packed=true];
|
||||
|
||||
optional fixed32 fixed32_field = 90;
|
||||
repeated fixed32 fixed32_field_repeated = 91;
|
||||
repeated fixed32 fixed32_field_packed = 92 [packed=true];
|
||||
|
||||
optional fixed64 fixed64_field = 100;
|
||||
repeated fixed64 fixed64_field_repeated = 101;
|
||||
repeated fixed64 fixed64_field_packed = 102 [packed=true];
|
||||
|
||||
optional sfixed32 sfixed32_field = 110;
|
||||
repeated sfixed32 sfixed32_field_repeated = 111;
|
||||
repeated sfixed32 sfixed32_field_packed = 112 [packed=true];
|
||||
|
||||
optional sfixed64 sfixed64_field = 120;
|
||||
repeated sfixed64 sfixed64_field_repeated = 121;
|
||||
repeated sfixed64 sfixed64_field_packed = 122 [packed=true];
|
||||
|
||||
optional bool bool_field = 130;
|
||||
repeated bool bool_field_repeated = 131;
|
||||
repeated bool bool_field_packed = 132 [packed=true];
|
||||
|
||||
optional string string_field = 140;
|
||||
repeated string string_field_repeated = 141;
|
||||
|
||||
optional bytes bytes_field = 150;
|
||||
repeated bytes bytes_field_repeated = 151;
|
||||
|
||||
optional Outside outside_field = 160;
|
||||
repeated Outside outside_field_repeated = 161;
|
||||
repeated Outside outside_field_packed = 162 [packed=true];
|
||||
|
||||
optional Nested nested_field = 170;
|
||||
repeated Nested nested_field_repeated = 171;
|
||||
|
||||
optional ImportedMessage imported_field = 180;
|
||||
repeated ImportedMessage imported_field_repeated = 181;
|
||||
};
|
||||
Reference in New Issue
Block a user