diff options
Diffstat (limited to 'src/com/google/common/io/protocol/ProtoBuf.java')
-rw-r--r-- | src/com/google/common/io/protocol/ProtoBuf.java | 143 |
1 files changed, 114 insertions, 29 deletions
diff --git a/src/com/google/common/io/protocol/ProtoBuf.java b/src/com/google/common/io/protocol/ProtoBuf.java index f2af32fa..8ebd1b9a 100644 --- a/src/com/google/common/io/protocol/ProtoBuf.java +++ b/src/com/google/common/io/protocol/ProtoBuf.java @@ -32,8 +32,8 @@ import java.util.*; * but only the simple methods take default values into account. The reason for * this behavior is that default values cannot be removed -- they would reappear * after a serialization cycle. If a tag has repeated values, setXXX(tag, value) - * will overwrite all of them and getXXX(tag) will throw an exception. - * + * will overwrite all of them and getXXX(tag) will throw an exception. + * */ public class ProtoBuf { @@ -46,12 +46,12 @@ public class ProtoBuf { private static final String MSG_UNSUPPORTED = "Unsupp.Type"; // names copied from //net/proto2/internal/wire_format.cc - private static final int WIRETYPE_END_GROUP = 4; - private static final int WIRETYPE_FIXED32 = 5; - private static final int WIRETYPE_FIXED64 = 1; - private static final int WIRETYPE_LENGTH_DELIMITED = 2; - private static final int WIRETYPE_START_GROUP = 3; - private static final int WIRETYPE_VARINT = 0; + static final int WIRETYPE_END_GROUP = 4; + static final int WIRETYPE_FIXED32 = 5; + static final int WIRETYPE_FIXED64 = 1; + static final int WIRETYPE_LENGTH_DELIMITED = 2; + static final int WIRETYPE_START_GROUP = 3; + static final int WIRETYPE_VARINT = 0; /** Maximum number of bytes for VARINT wire format (64 bit, 7 bit/byte) */ private static final int VARINT_MAX_BYTES = 10; @@ -62,7 +62,7 @@ public class ProtoBuf { new Long(10), new Long(11), new Long(12), new Long(13), new Long(14), new Long(15)}; - private final ProtoBufType msgType; + private ProtoBufType msgType; private final Vector values = new Vector(); /** @@ -124,6 +124,20 @@ public class ProtoBuf { } /** + * Appends the given (repeated) tag with the given float value. + */ + public void addFloat(int tag, float value) { + insertFloat(tag, getCount(tag), value); + } + + /** + * Appends the given (repeated) tag with the given double value. + */ + public void addDouble(int tag, double value) { + insertDouble(tag, getCount(tag), value); + } + + /** * Appends the given (repeated) tag with the given group or message value. */ public void addProtoBuf(int tag, ProtoBuf value){ @@ -196,6 +210,34 @@ public class ProtoBuf { return ((Long) getObject(tag, index, ProtoBufType.TYPE_INT64)).longValue(); } + /** + * Returns the float value for the given tag. + */ + public float getFloat(int tag) { + return Float.intBitsToFloat(getInt(tag)); + } + + /** + * Returns the float value for the given repeated tag at the given index. + */ + public float getFloat(int tag, int index) { + return Float.intBitsToFloat(getInt(tag, index)); + } + + /** + * Returns the double value for the given tag. + */ + public double getDouble(int tag) { + return Double.longBitsToDouble(getLong(tag)); + } + + /** + * Returns the double value for the given repeated tag at the given index. + */ + public double getDouble(int tag, int index) { + return Double.longBitsToDouble(getLong(tag, index)); + } + /** * Returns the group or nested message for the given tag. */ @@ -235,6 +277,20 @@ public class ProtoBuf { } /** + * Sets the type definition of this protocol buffer. Used internally in + * ProtoBufUtil for incremental reading. + * + * @param type the new type + */ + void setType(ProtoBufType type) { + if (values.size() != 0 || + (msgType != null && type != null && type != msgType)) { + throw new IllegalArgumentException(); + } + this.msgType = type; + } + + /** * 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. @@ -652,6 +708,20 @@ public class ProtoBuf { ? SMALL_NUMBERS[(int) value] : new Long(value)); } + /** + * Sets the given tag to the given double value. + */ + public void setDouble(int tag, double value) { + setLong(tag, Double.doubleToLongBits(value)); + } + + /** + * Sets the given tag to the given float value. + */ + public void setFloat(int tag, float value) { + setInt(tag, Float.floatToIntBits(value)); + } + /** * Sets the given tag to the given Group or nested Message. */ @@ -695,6 +765,20 @@ public class ProtoBuf { ? SMALL_NUMBERS[(int) value] : new Long(value)); } + /** + * Inserts the given float value for the given tag at the given index. + */ + public void insertFloat(int tag, int index, float value) { + insertInt(tag, index, Float.floatToIntBits(value)); + } + + /** + * Inserts the given double value for the given tag at the given index. + */ + public void insertDouble(int tag, int index, double value) { + insertLong(tag, index, Double.doubleToLongBits(value)); + } + /** * Inserts the given group or message for the given tag at the given index. */ @@ -739,6 +823,8 @@ public class ProtoBuf { 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[]){ @@ -748,7 +834,6 @@ public class ProtoBuf { case ProtoBufType.TYPE_MESSAGE: case ProtoBufType.TYPE_TEXT: case ProtoBufType.TYPE_BYTES: - case ProtoBufType.TYPE_STRING: return; } } else if (object instanceof ProtoBuf) { @@ -1079,21 +1164,21 @@ public class ProtoBuf { /** * Encodes the given string to UTF-8 in the given buffer or calculates * the space needed if the buffer is null. - * + * * @param s the string to be UTF-8 encoded * @param buf byte array to write to - * @return new buffer position after writing (which equals the required size + * @return new buffer position after writing (which equals the required size * if pos is 0) */ static int encodeUtf8(String s, byte[] buf, int pos){ 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) @@ -1138,35 +1223,35 @@ public class ProtoBuf { buf[pos + 2] = (byte) ((0x80 | ((code >> 6) & 0x3F))); buf[pos + 3] = (byte) ((0x80 | (code & 0x3F))); } - pos += 4; + pos += 4; } } - + return pos; } /** - * 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. - * - * @param data input byte array containing UTF-8 data + * 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. + * + * @param data input byte array containing UTF-8 data * @param start decoding start position in byte array * @param end decoding end position in byte array - * @param tolerant if true, an IllegalArgumentException is thrown for illegal + * @param tolerant if true, an IllegalArgumentException is thrown for illegal * UTF-8 codes * @return the string containing the UTF-8 decoding result */ - static String decodeUtf8(byte[] data, int start, int end, + static String decodeUtf8(byte[] data, int start, int end, boolean tolerant){ - + 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 + } else if (b >= 0xf5){ // byte sequence too long if (!tolerant){ throw new IllegalArgumentException("Invalid UTF8"); } @@ -1174,16 +1259,16 @@ public class ProtoBuf { } else { int border = 0xe0; int count = 1; - int minCode = 128; + int minCode = 128; int mask = 0x01f; while (b >= border){ border = (border >> 1) | 0x80; - minCode = minCode << (count == 1 ? 4 : 5); + 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){ @@ -1198,7 +1283,7 @@ public class ProtoBuf { code |= (data[pos++] & 0x3f); // six bit } } - + // illegal code or surrogate code if (!tolerant && code < minCode || (code >= 0xd800 && code <= 0xdfff)){ throw new IllegalArgumentException("Invalid UTF8"); |