Methods Summary |
---|
public void | addBool(int tag, boolean value)Appends the given (repeated) tag with the given boolean value.
insertBool(tag, getCount(tag), value);
|
public void | addBytes(int tag, byte[] value)Appends the given (repeated) tag with the given byte[] value.
insertBytes(tag, getCount(tag), value);
|
public void | addDouble(int tag, double value)Appends the given (repeated) tag with the given double value.
insertDouble(tag, getCount(tag), value);
|
public void | addFloat(int tag, float value)Appends the given (repeated) tag with the given float value.
insertFloat(tag, getCount(tag), value);
|
public void | addInt(int tag, int value)Appends the given (repeated) tag with the given int value.
insertInt(tag, getCount(tag), value);
|
public void | addLong(int tag, long value)Appends the given (repeated) tag with the given long value.
insertLong(tag, getCount(tag), value);
|
public com.google.common.io.protocol.ProtoBuf | addNewProtoBuf(int tag)Adds a new protobuf for the specified tag, setting the child protobuf's
type correctly for the tag.
ProtoBuf child = newProtoBufForTag(tag);
addProtoBuf(tag, child);
return child;
|
public void | addProtoBuf(int tag, com.google.common.io.protocol.ProtoBuf value)Appends the given (repeated) tag with the given group or message value.
insertProtoBuf(tag, getCount(tag), value);
|
public void | addString(int tag, java.lang.String value)Appends the given (repeated) tag with the given String value.
insertString(tag, getCount(tag), value);
|
private void | assertTypeMatch(int tag, java.lang.Object object)
int tagType = getType(tag);
if (tagType == ProtoBufType.TYPE_UNDEFINED && msgType == null) {
return;
}
if (object instanceof Boolean) {
if (tagType == ProtoBufType.TYPE_BOOL
|| tagType == WIRETYPE_VARINT) {
return;
}
} else if (object instanceof Long) {
switch(tagType){
case WIRETYPE_FIXED32:
case WIRETYPE_FIXED64:
case WIRETYPE_VARINT:
case ProtoBufType.TYPE_BOOL:
case ProtoBufType.TYPE_ENUM:
case ProtoBufType.TYPE_FIXED32:
case ProtoBufType.TYPE_FIXED64:
case ProtoBufType.TYPE_INT32:
case ProtoBufType.TYPE_INT64:
case ProtoBufType.TYPE_SFIXED32:
case ProtoBufType.TYPE_SFIXED64:
case ProtoBufType.TYPE_UINT32:
case ProtoBufType.TYPE_UINT64:
case ProtoBufType.TYPE_SINT32:
case ProtoBufType.TYPE_SINT64:
case ProtoBufType.TYPE_FLOAT:
case ProtoBufType.TYPE_DOUBLE:
return;
}
} else if (object instanceof byte[]){
switch (tagType){
case WIRETYPE_LENGTH_DELIMITED:
case ProtoBufType.TYPE_DATA:
case ProtoBufType.TYPE_MESSAGE:
case ProtoBufType.TYPE_TEXT:
case ProtoBufType.TYPE_BYTES:
case ProtoBufType.TYPE_STRING:
return;
}
} else if (object instanceof ProtoBuf) {
switch (tagType){
case WIRETYPE_LENGTH_DELIMITED:
case WIRETYPE_START_GROUP:
case ProtoBufType.TYPE_DATA:
case ProtoBufType.TYPE_GROUP:
case ProtoBufType.TYPE_MESSAGE:
if (msgType == null || msgType.getData(tag) == null ||
((ProtoBuf) object).msgType == null ||
((ProtoBuf) object).msgType == msgType.getData(tag)) {
return;
}
}
} else if (object instanceof String){
switch (tagType){
case WIRETYPE_LENGTH_DELIMITED:
case ProtoBufType.TYPE_DATA:
case ProtoBufType.TYPE_TEXT:
case ProtoBufType.TYPE_STRING:
return;
}
}
throw new IllegalArgumentException(MSG_MISMATCH + " type:" + msgType +
" tag:" + tag);
|
public void | clear()Clears all data stored in this ProtoBuf.
values.setSize(0);
wireTypes.setLength(0);
|
private java.lang.Object | convert(java.lang.Object obj, int tagType)Converts the object if a better suited class exists for the given .proto
type. If the formats are not compatible, an exception is thrown.
switch (tagType) {
case ProtoBufType.TYPE_UNDEFINED:
return obj;
case ProtoBufType.TYPE_BOOL:
if (obj instanceof Boolean) {
return obj;
}
switch ((int) ((Long) obj).longValue()) {
case 0:
return FALSE;
case 1:
return TRUE;
default:
throw new IllegalArgumentException(MSG_MISMATCH);
}
case ProtoBufType.TYPE_FIXED32:
case ProtoBufType.TYPE_FIXED64:
case ProtoBufType.TYPE_INT32:
case ProtoBufType.TYPE_INT64:
case ProtoBufType.TYPE_SFIXED32:
case ProtoBufType.TYPE_SFIXED64:
case ProtoBufType.TYPE_SINT32:
case ProtoBufType.TYPE_SINT64:
if (obj instanceof Boolean) {
return SMALL_NUMBERS[((Boolean) obj).booleanValue() ? 1 : 0];
}
return obj;
case ProtoBufType.TYPE_DATA:
case ProtoBufType.TYPE_BYTES:
if (obj instanceof String) {
return encodeUtf8((String) obj);
} else if (obj instanceof ProtoBuf) {
ByteArrayOutputStream buf = new ByteArrayOutputStream();
try {
((ProtoBuf) obj).outputTo(buf);
return buf.toByteArray();
} catch (IOException e) {
throw new RuntimeException(e.toString());
}
}
return obj;
case ProtoBufType.TYPE_TEXT:
case ProtoBufType.TYPE_STRING:
if (obj instanceof byte[]) {
byte[] data = (byte[]) obj;
return decodeUtf8(data, 0, data.length, true);
}
return obj;
case ProtoBufType.TYPE_GROUP:
case ProtoBufType.TYPE_MESSAGE:
if (obj instanceof byte[]) {
try {
return new ProtoBuf(null).parse((byte[]) obj);
} catch (IOException e) {
throw new RuntimeException(e.toString());
}
}
return obj;
default:
// default includes FLOAT and DOUBLE
throw new RuntimeException(MSG_UNSUPPORTED);
}
|
public com.google.common.io.protocol.ProtoBuf | createGroup(int tag)Creates a new instance of the group with the given tag.
return new ProtoBuf((ProtoBufType) getType().getData(tag));
|
static java.lang.String | decodeUtf8(byte[] data, int start, int end, boolean tolerant)Decodes an array of UTF-8 bytes to a Java string (UTF-16). The tolerant
flag determines what to do in case of illegal or unsupported sequences.
StringBuffer sb = new StringBuffer(end - start);
int pos = start;
while (pos < end){
int b = data[pos++] & 0x0ff;
if (b <= 0x7f){
sb.append((char) b);
} else if (b >= 0xf5){ // byte sequence too long
if (!tolerant){
throw new IllegalArgumentException("Invalid UTF8");
}
sb.append((char) b);
} else {
int border = 0xe0;
int count = 1;
int minCode = 128;
int mask = 0x01f;
while (b >= border){
border = (border >> 1) | 0x80;
minCode = minCode << (count == 1 ? 4 : 5);
count++;
mask = mask >> 1;
}
int code = b & mask;
for (int i = 0; i < count; i++){
code = code << 6;
if (pos >= end){
if (!tolerant){
throw new IllegalArgumentException("Invalid UTF8");
}
// otherwise, assume zeroes
} else {
if (!tolerant && (data[pos] & 0xc0) != 0x80){
throw new IllegalArgumentException("Invalid UTF8");
}
code |= (data[pos++] & 0x3f); // six bit
}
}
// illegal code or surrogate code
if (!tolerant && code < minCode || (code >= 0xd800 && code <= 0xdfff)){
throw new IllegalArgumentException("Invalid UTF8");
}
if (code <= 0x0ffff){
sb.append((char) code);
} else { // surrogate UTF16
code -= 0x10000;
sb.append((char) (0xd800 | (code >> 10))); // high 10 bit
sb.append((char) (0xdc00 | (code & 0x3ff))); // low 10 bit
}
}
}
return sb.toString();
|
static byte[] | encodeUtf8(java.lang.String s)Returns a byte array containing the given string, encoded as UTF-8. The
returned byte array contains at least s.length() bytes and at most
4 * s.length() bytes. UTF-16 surrogates are transcoded to UTF-8.
int len = encodeUtf8(s, null, 0);
byte[] result = new byte[len];
encodeUtf8(s, result, 0);
return result;
|
static int | encodeUtf8(java.lang.String s, byte[] buf, int pos)Encodes the given string to UTF-8 in the given buffer or calculates
the space needed if the buffer is null.
int len = s.length();
for (int i = 0; i < len; i++){
int code = s.charAt(i);
// surrogate 0xd800 .. 0xdfff?
if (code >= 0x0d800 && code <= 0x0dfff && i + 1 < len){
int codeLo = s.charAt(i + 1);
// 0xfc00 is the surrogate id mask (first six bit of 16 set)
// 0x03ff is the surrogate data mask (remaining 10 bit)
// check if actually a surrogate pair (d800 ^ dc00 == 0400)
if (((codeLo & 0xfc00) ^ (code & 0x0fc00)) == 0x0400){
i += 1;
int codeHi;
if ((codeLo & 0xfc00) == 0x0d800){
codeHi = codeLo;
codeLo = code;
} else {
codeHi = code;
}
code = (((codeHi & 0x3ff) << 10) | (codeLo & 0x3ff)) + 0x10000;
}
}
if (code <= 0x007f) {
if (buf != null){
buf[pos] = (byte) code;
}
pos += 1;
} else if (code <= 0x07FF) {
// non-ASCII <= 0x7FF
if (buf != null){
buf[pos] = (byte) (0xc0 | (code >> 6));
buf[pos + 1] = (byte) (0x80 | (code & 0x3F));
}
pos += 2;
} else if (code <= 0xFFFF){
// 0x7FF < code <= 0xFFFF
if (buf != null){
buf[pos] = (byte) ((0xe0 | (code >> 12)));
buf[pos + 1] = (byte) ((0x80 | ((code >> 6) & 0x3F)));
buf[pos + 2] = (byte) ((0x80 | (code & 0x3F)));
}
pos += 3;
} else {
if (buf != null){
buf[pos] = (byte) ((0xf0 | (code >> 18)));
buf[pos + 1] = (byte) ((0x80 | ((code >> 12) & 0x3F)));
buf[pos + 2] = (byte) ((0x80 | ((code >> 6) & 0x3F)));
buf[pos + 3] = (byte) ((0x80 | (code & 0x3F)));
}
pos += 4;
}
}
return pos;
|
public boolean | getBool(int tag)Returns the boolean value for the given tag.
return ((Boolean) getObject(tag, ProtoBufType.TYPE_BOOL))
.booleanValue();
|
public boolean | getBool(int tag, int index)Returns the boolean value for the given repeated tag at the given index.
return ((Boolean) getObject(tag, index, ProtoBufType.TYPE_BOOL))
.booleanValue();
|
public byte[] | getBytes(int tag)Returns the given string tag as byte array.
return (byte[]) getObject(tag, ProtoBufType.TYPE_DATA);
|
public byte[] | getBytes(int tag, int index)Returns the given repeated string tag at the given index as byte array.
return (byte[]) getObject(tag, index, ProtoBufType.TYPE_DATA);
|
public int | getCount(int tag)Returns the number of repeated and optional (0..1) values for a given tag.
Note: Default values are not counted (and in general not considered in
access methods for repeated tags), but considered for has(tag).
if (tag >= values.size()){
return 0;
}
Object o = values.elementAt(tag);
if (o == null){
return 0;
}
return (o instanceof Vector) ? ((Vector) o).size() : 1;
|
public int | getDataSize()Returns the number of bytes needed to store this protocol buffer
int size = 0;
for (int tag = 0; tag <= maxTag(); tag++) {
for (int i = 0; i < getCount(tag); i++) {
size += getDataSize(tag, i);
}
}
return size;
|
private int | getDataSize(int tag, int i)Returns the size of the given value
int tagSize = getVarIntSize(tag << 3);
switch(getWireType(tag)){
case WIRETYPE_FIXED32:
return tagSize + 4;
case WIRETYPE_FIXED64:
return tagSize + 8;
case WIRETYPE_VARINT:
long value = getLong(tag, i);
if (isZigZagEncodedType(tag)) {
value = zigZagEncode(value);
}
return tagSize + getVarIntSize(value);
case WIRETYPE_START_GROUP:
// take end group into account....
return tagSize + getProtoBuf(tag, i).getDataSize() + tagSize;
}
// take the object as stored
Object o = getObject(tag, i, ProtoBufType.TYPE_UNDEFINED);
int contentSize;
if (o instanceof byte[]){
contentSize = ((byte[]) o).length;
} else if (o instanceof String) {
contentSize = encodeUtf8((String) o, null, 0);
} else {
contentSize = ((ProtoBuf) o).getDataSize();
}
return tagSize + getVarIntSize(contentSize) + contentSize;
|
private java.lang.Object | getDefault(int tag)Returns the default value for the given tag.
switch(getType(tag)){
case ProtoBufType.TYPE_UNDEFINED:
case ProtoBufType.TYPE_GROUP:
case ProtoBufType.TYPE_MESSAGE:
return null;
default:
return msgType.getData(tag);
}
|
public double | getDouble(int tag)Returns the double value for the given tag.
return Double.longBitsToDouble(getLong(tag));
|
public double | getDouble(int tag, int index)Returns the double value for the given repeated tag at the given index.
return Double.longBitsToDouble(getLong(tag, index));
|
public float | getFloat(int tag)Returns the float value for the given tag.
return Float.intBitsToFloat(getInt(tag));
|
public float | getFloat(int tag, int index)Returns the float value for the given repeated tag at the given index.
return Float.intBitsToFloat(getInt(tag, index));
|
public int | getInt(int tag)Returns the integer value for the given tag.
return (int) ((Long) getObject(tag, ProtoBufType.TYPE_INT32)).longValue();
|
public int | getInt(int tag, int index)Returns the integer value for the given repeated tag at the given index.
return (int) ((Long) getObject(tag, index,
ProtoBufType.TYPE_INT32)).longValue();
|
public long | getLong(int tag)Returns the long value for the given tag.
return ((Long) getObject(tag, ProtoBufType.TYPE_INT64)).longValue();
|
public long | getLong(int tag, int index)Returns the long value for the given repeated tag at the given index.
return ((Long) getObject(tag, index, ProtoBufType.TYPE_INT64)).longValue();
|
private java.lang.Object | getObject(int tag, int desiredType)Returns the indicated value converted to the given type.
int count = getCount(tag);
if (count == 0){
return getDefault(tag);
}
if (count > 1){
throw new IllegalArgumentException();
}
return getObject(tag, 0, desiredType);
|
private java.lang.Object | getObject(int tag, int index, int desiredType)Returns the indicated value converted to the given type.
if (index >= getCount(tag)) {
throw new ArrayIndexOutOfBoundsException();
}
Object o = values.elementAt(tag);
Vector v = null;
if (o instanceof Vector) {
v = (Vector) o;
o = v.elementAt(index);
}
Object o2 = convert(o, desiredType);
if (o2 != o && o != null) {
if (v == null){
setObject(tag, o2);
} else {
v.setElementAt(o2, index);
}
}
return o2;
|
public com.google.common.io.protocol.ProtoBuf | getProtoBuf(int tag)Returns the group or nested message for the given tag.
return (ProtoBuf) getObject(tag, ProtoBufType.TYPE_GROUP);
|
public com.google.common.io.protocol.ProtoBuf | getProtoBuf(int tag, int index)Returns the group or nested message for the given repeated tag at the given
index.
return (ProtoBuf) getObject(tag, index, ProtoBufType.TYPE_GROUP);
|
public java.lang.String | getString(int tag)Returns the string value for a given tag converted to a Java String
assuming UTF-8 encoding.
return (String) getObject(tag, ProtoBufType.TYPE_TEXT);
|
public java.lang.String | getString(int tag, int index)Returns the string value for a given repeated tag at the given index
converted to a Java String assuming UTF-8 encoding.
return (String) getObject(tag, index, ProtoBufType.TYPE_TEXT);
|
public ProtoBufType | getType()Returns the type definition of this protocol buffer or group -- if set.
return msgType;
|
public int | getType(int tag)Returns the tag type of the given tag (one of the ProtoBufType.TYPE_XXX
constants). If no ProtoBufType is set, the wire type is returned. If no
wire type is available, the wire type is determined by looking at the
tag value (making sure the wire type is consistent for all values). If
no value is set, TYPE_UNDEFINED is returned.
int tagType = ProtoBufType.TYPE_UNDEFINED;
if (msgType != null){
tagType = msgType.getType(tag);
}
if (tagType == ProtoBufType.TYPE_UNDEFINED && tag < wireTypes.length()) {
tagType = wireTypes.charAt(tag);
}
if (tagType == ProtoBufType.TYPE_UNDEFINED && getCount(tag) > 0) {
Object o = getObject(tag, 0, ProtoBufType.TYPE_UNDEFINED);
tagType = (o instanceof Long) || (o instanceof Boolean)
? WIRETYPE_VARINT : WIRETYPE_LENGTH_DELIMITED;
}
return tagType;
|
private static int | getVarIntSize(long i)Returns the number of bytes needed to encode the given value using
WIRETYPE_VARINT
if (i < 0) {
return 10;
}
int size = 1;
while (i >= 128) {
size++;
i >>= 7;
}
return size;
|
private final int | getWireType(int tag)Returns the wire type for the given tag. Calls getType() internally,
so a wire type should be found for all non-empty tags, even if no
message type is set and the tag was not previously read.
int tagType = getType(tag);
switch (tagType) {
case WIRETYPE_VARINT:
case WIRETYPE_FIXED32:
case WIRETYPE_FIXED64:
case WIRETYPE_LENGTH_DELIMITED:
case WIRETYPE_START_GROUP:
case ProtoBufType.TYPE_UNDEFINED:
return tagType;
case ProtoBufType.TYPE_BOOL:
case ProtoBufType.TYPE_INT32:
case ProtoBufType.TYPE_INT64:
case ProtoBufType.TYPE_UINT32:
case ProtoBufType.TYPE_UINT64:
case ProtoBufType.TYPE_SINT32:
case ProtoBufType.TYPE_SINT64:
case ProtoBufType.TYPE_ENUM:
return WIRETYPE_VARINT;
case ProtoBufType.TYPE_DATA:
case ProtoBufType.TYPE_MESSAGE:
case ProtoBufType.TYPE_TEXT:
case ProtoBufType.TYPE_BYTES:
case ProtoBufType.TYPE_STRING:
return WIRETYPE_LENGTH_DELIMITED;
case ProtoBufType.TYPE_DOUBLE:
case ProtoBufType.TYPE_FIXED64:
case ProtoBufType.TYPE_SFIXED64:
return WIRETYPE_FIXED64;
case ProtoBufType.TYPE_FLOAT:
case ProtoBufType.TYPE_FIXED32:
case ProtoBufType.TYPE_SFIXED32:
return WIRETYPE_FIXED32;
case ProtoBufType.TYPE_GROUP:
return WIRETYPE_START_GROUP;
default:
throw new RuntimeException(MSG_UNSUPPORTED + ':" + msgType + '/" +
tag + '/" + tagType);
}
|
public boolean | has(int tag)Convenience method for determining whether a tag has a value. Note: in
contrast to getCount(tag) > 0, this method takes the default value
into account.
return getCount(tag) > 0 || getDefault(tag) != null;
|
public void | insertBool(int tag, int index, boolean value)Inserts the given boolean value for the given tag at the given index.
insertObject(tag, index, value ? TRUE : FALSE);
|
public void | insertBytes(int tag, int index, byte[] value)Inserts the given byte array value for the given tag at the given index.
insertObject(tag, index, value);
|
public void | insertDouble(int tag, int index, double value)Inserts the given double value for the given tag at the given index.
insertLong(tag, index, Double.doubleToLongBits(value));
|
public void | insertFloat(int tag, int index, float value)Inserts the given float value for the given tag at the given index.
insertInt(tag, index, Float.floatToIntBits(value));
|
public void | insertInt(int tag, int index, int value)Inserts the given int value for the given tag at the given index.
insertLong(tag, index, value);
|
public void | insertLong(int tag, int index, long value)Inserts the given long value for the given tag at the given index.
insertObject(tag, index, value >= 0 && value < SMALL_NUMBERS.length
? SMALL_NUMBERS[(int) value] : new Long(value));
|
private void | insertObject(int tag, int index, java.lang.Object o)Inserts a value.
assertTypeMatch(tag, o);
int count = getCount(tag);
if (count == 0) {
setObject(tag, o);
} else {
Object curr = values.elementAt(tag);
Vector v;
if (curr instanceof Vector) {
v = (Vector) curr;
} else {
v = new Vector();
v.addElement(curr);
values.setElementAt(v, tag);
}
v.insertElementAt(o, index);
}
|
public void | insertProtoBuf(int tag, int index, com.google.common.io.protocol.ProtoBuf pb)Inserts the given group or message for the given tag at the given index.
insertObject(tag, index, pb);
|
public void | insertString(int tag, int index, java.lang.String value)Inserts the given string value for the given tag at the given index.
insertObject(tag, index, value);
|
private boolean | isZigZagEncodedType(int tag)Returns true if the given tag has a signed type that should be ZigZag-
encoded on the wire.
ZigZag encoding turns a signed number into
a non-negative number by mapping negative input numbers to positive odd
numbers in the output space, and positive input numbers to positive even
numbers in the output space. This is useful because the wire format
for protocol buffers requires a large number of bytes to encode
negative integers, while positive integers take up a smaller number
of bytes proportional to their magnitude.
int declaredType = getType(tag);
return declaredType == ProtoBufType.TYPE_SINT32 ||
declaredType == ProtoBufType.TYPE_SINT64;
|
public int | maxTag()Returns the largest tag id used in this message (to simplify testing).
return values.size() - 1;
|
public com.google.common.io.protocol.ProtoBuf | newProtoBufForTag(int tag)Creates and returns a new protobuf for the specified tag, setting the new
protobuf's type correctly for the tag.
return new ProtoBuf((ProtoBufType) msgType.getData(tag));
|
public void | outputTo(java.io.OutputStream os)Writes this and nested protocol buffers to the given output stream.
for (int tag = 0; tag <= maxTag(); tag++) {
int size = getCount(tag);
int wireType = getWireType(tag);
// ignore default values
for (int i = 0; i < size; i++) {
writeVarInt(os, (tag << 3) | wireType);
switch (wireType) {
case WIRETYPE_FIXED32:
case WIRETYPE_FIXED64:
long v = ((Long) getObject(tag, i, ProtoBufType.TYPE_INT64))
.longValue();
int cnt = (wireType == WIRETYPE_FIXED32) ? 4 : 8;
for (int b = 0; b < cnt; b++) {
os.write((int) (v & 0x0ff));
v >>= 8;
}
break;
case WIRETYPE_VARINT:
v = ((Long) getObject(tag, i, ProtoBufType.TYPE_INT64)).longValue();
if (isZigZagEncodedType(tag)) {
v = zigZagEncode(v);
}
writeVarInt(os, v);
break;
case WIRETYPE_LENGTH_DELIMITED:
Object o = getObject(tag, i,
getType(tag) == ProtoBufType.TYPE_MESSAGE
? ProtoBufType.TYPE_UNDEFINED
: ProtoBufType.TYPE_DATA);
if (o instanceof byte[]){
byte[] data = (byte[]) o;
writeVarInt(os, data.length);
os.write(data);
} else {
ProtoBuf msg = (ProtoBuf) o;
writeVarInt(os, msg.getDataSize());
msg.outputTo(os);
}
break;
case WIRETYPE_START_GROUP:
((ProtoBuf) getObject(tag, i, ProtoBufType.TYPE_GROUP))
.outputTo(os);
writeVarInt(os, (tag << 3) | WIRETYPE_END_GROUP);
break;
default:
throw new IllegalArgumentException();
}
}
}
|
public com.google.common.io.protocol.ProtoBuf | parse(byte[] data)Reads the contents of this ProtocolMessage from the given byte array.
Currently, this is a shortcut for parse(new ByteArrayInputStream(data)).
However, this may change in future versions for efficiency reasons.
parse(new ByteArrayInputStream(data), data.length);
return this;
|
public com.google.common.io.protocol.ProtoBuf | parse(java.io.InputStream is)Reads the contents of this ProtocolMessage from the given stream.
parse(is, Integer.MAX_VALUE);
return this;
|
public int | parse(java.io.InputStream is, int available)Reads the contents of this ProtocolMessage from the given stream, consuming
at most the given number of bytes.
clear();
while (available > 0) {
long tagAndType = readVarInt(is, true /* permits EOF */);
if (tagAndType == -1){
break;
}
available -= getVarIntSize(tagAndType);
int wireType = ((int) tagAndType) & 0x07;
if (wireType == WIRETYPE_END_GROUP) {
break;
}
int tag = (int) (tagAndType >>> 3);
while (wireTypes.length() <= tag){
wireTypes.append((char) ProtoBufType.TYPE_UNDEFINED);
}
wireTypes.setCharAt(tag, (char) wireType);
// first step: decode tag value
Object value;
switch (wireType) {
case WIRETYPE_VARINT:
long v = readVarInt(is, false);
available -= getVarIntSize(v);
if (isZigZagEncodedType(tag)) {
v = zigZagDecode(v);
}
value = (v >= 0 && v < SMALL_NUMBERS.length) ?
SMALL_NUMBERS[(int) v] : new Long(v);
break;
// also used for fixed values
case WIRETYPE_FIXED32:
case WIRETYPE_FIXED64:
v = 0;
int shift = 0;
int count = (wireType == WIRETYPE_FIXED32) ? 4 : 8;
available -= count;
while (count-- > 0) {
long l = is.read();
v |= l << shift;
shift += 8;
}
value = (v >= 0 && v < SMALL_NUMBERS.length)
? SMALL_NUMBERS[(int) v]
: new Long(v);
break;
case WIRETYPE_LENGTH_DELIMITED:
int total = (int) readVarInt(is, false);
available -= getVarIntSize(total);
available -= total;
if (getType(tag) == ProtoBufType.TYPE_MESSAGE) {
ProtoBuf msg = new ProtoBuf((ProtoBufType) msgType.getData(tag));
msg.parse(is, total);
value = msg;
} else {
byte[] data = new byte[total];
int pos = 0;
while (pos < total) {
count = is.read(data, pos, total - pos);
if (count <= 0) {
throw new IOException(MSG_EOF);
}
pos += count;
}
value = data;
}
break;
case WIRETYPE_START_GROUP:
ProtoBuf group = new ProtoBuf(msgType == null
? null
: ((ProtoBufType) msgType.getData(tag)));
available = group.parse(is, available);
value = group;
break;
default:
throw new RuntimeException(MSG_UNSUPPORTED + wireType);
}
insertObject(tag, getCount(tag), value);
}
if (available < 0){
throw new IOException();
}
return available;
|
static long | readVarInt(java.io.InputStream is, boolean permitEOF)Reads a variable-size integer (up to 10 bytes for 64 bit) from the
given input stream.
long result = 0;
int shift = 0;
// max 10 byte wire format for 64 bit integer (7 bit data per byte)
for (int i = 0; i < VARINT_MAX_BYTES; i++) {
int in = is.read();
if (in == -1) {
if (i == 0 && permitEOF) {
return -1;
} else {
throw new IOException("EOF");
}
}
result |= ((long) (in & 0x07f)) << shift;
if ((in & 0x80) == 0){
break; // get out early
}
shift += 7;
}
return result;
|
public void | remove(int tag, int index)Removes the tag value at the given index.
int count = getCount(tag);
if (index >= count){
throw new ArrayIndexOutOfBoundsException();
}
if (count == 1){
values.setElementAt(null, tag);
} else {
Vector v = (Vector) values.elementAt(tag);
v.removeElementAt(index);
}
|
public void | setBool(int tag, boolean value)Sets the given tag to the given boolean value.
setObject(tag, value ? TRUE : FALSE);
|
public void | setBytes(int tag, byte[] value)Sets the given tag to the given data bytes.
setObject(tag, value);
|
public void | setDouble(int tag, double value)Sets the given tag to the given double value.
setLong(tag, Double.doubleToLongBits(value));
|
public void | setFloat(int tag, float value)Sets the given tag to the given float value.
setInt(tag, Float.floatToIntBits(value));
|
public void | setInt(int tag, int value)Sets the given tag to the given integer value.
setLong(tag, value);
|
public void | setLong(int tag, long value)Sets the given tag to the given long value.
setObject(tag, value >= 0 && value < SMALL_NUMBERS.length
? SMALL_NUMBERS[(int) value] : new Long(value));
|
public com.google.common.io.protocol.ProtoBuf | setNewProtoBuf(int tag)Sets a new protobuf for the specified tag, setting the child protobuf's
type correctly for the tag.
ProtoBuf child = newProtoBufForTag(tag);
setProtoBuf(tag, child);
return child;
|
private void | setObject(int tag, java.lang.Object o)Internal helper method to set a (single) value. Overwrites all existing
values.
if (values.size() <= tag) {
values.setSize(tag + 1);
}
if (o != null) {
assertTypeMatch(tag, o);
}
values.setElementAt(o, tag);
|
public void | setProtoBuf(int tag, com.google.common.io.protocol.ProtoBuf pb)Sets the given tag to the given Group or nested Message.
setObject(tag, pb);
|
public void | setString(int tag, java.lang.String value)Sets the given tag to the given String value.
setObject(tag, value);
|
void | setType(ProtoBufType type)Sets the type definition of this protocol buffer. Used internally in
ProtoBufUtil for incremental reading.
if (values.size() != 0 ||
(msgType != null && type != null && type != msgType)) {
throw new IllegalArgumentException();
}
this.msgType = type;
|
public byte[] | toByteArray()Writes this and nested protocol buffers to a byte array.
ByteArrayOutputStream baos = new ByteArrayOutputStream();
outputTo(baos);
return baos.toByteArray();
|
static void | writeVarInt(java.io.OutputStream os, long value)Write a variable-size integer to the given output stream.
for (int i = 0; i < VARINT_MAX_BYTES; i++) {
int toWrite = (int) (value & 0x7f);
value >>>= 7;
if (value == 0) {
os.write(toWrite);
break;
} else {
os.write(toWrite | 0x080);
}
}
|
private static long | zigZagDecode(long v)Converts a non-negative ZigZag-encoded number back into a signed number.
v = (v >>> 1) ^ -(v & 1);
return v;
|
private static long | zigZagEncode(long v)Converts a signed number into a non-negative ZigZag-encoded number.
v = ((v << 1) ^ -(v >>> 63));
return v;
|