You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@activemq.apache.org by ch...@apache.org on 2008/11/13 04:56:48 UTC
svn commit: r713629 [1/2] - in /activemq/sandbox/activemq-protobuf:
activemq-protobuf-test/src/test/java/com/google/protobuf/
activemq-protobuf/src/main/java/org/apache/activemq/protobuf/
Author: chirino
Date: Wed Nov 12 19:56:48 2008
New Revision: 713629
URL: http://svn.apache.org/viewvc?rev=713629&view=rev
Log:
Simplified the Coded Input/Output streams.. they now strictly provide encoding methods and delegate to another stream for buffering
Added:
activemq/sandbox/activemq-protobuf/activemq-protobuf/src/main/java/org/apache/activemq/protobuf/ByteArrayInputStream.java
activemq/sandbox/activemq-protobuf/activemq-protobuf/src/main/java/org/apache/activemq/protobuf/ByteArrayOutputStream.java
activemq/sandbox/activemq-protobuf/activemq-protobuf/src/main/java/org/apache/activemq/protobuf/ByteSequence.java
Modified:
activemq/sandbox/activemq-protobuf/activemq-protobuf-test/src/test/java/com/google/protobuf/GeneratedMessageTest.java
activemq/sandbox/activemq-protobuf/activemq-protobuf/src/main/java/org/apache/activemq/protobuf/BaseMessage.java
activemq/sandbox/activemq-protobuf/activemq-protobuf/src/main/java/org/apache/activemq/protobuf/CodedInputStream.java
activemq/sandbox/activemq-protobuf/activemq-protobuf/src/main/java/org/apache/activemq/protobuf/CodedOutputStream.java
activemq/sandbox/activemq-protobuf/activemq-protobuf/src/main/java/org/apache/activemq/protobuf/DeferredDecodeMessage.java
Modified: activemq/sandbox/activemq-protobuf/activemq-protobuf-test/src/test/java/com/google/protobuf/GeneratedMessageTest.java
URL: http://svn.apache.org/viewvc/activemq/sandbox/activemq-protobuf/activemq-protobuf-test/src/test/java/com/google/protobuf/GeneratedMessageTest.java?rev=713629&r1=713628&r2=713629&view=diff
==============================================================================
--- activemq/sandbox/activemq-protobuf/activemq-protobuf-test/src/test/java/com/google/protobuf/GeneratedMessageTest.java (original)
+++ activemq/sandbox/activemq-protobuf/activemq-protobuf-test/src/test/java/com/google/protobuf/GeneratedMessageTest.java Wed Nov 12 19:56:48 2008
@@ -111,6 +111,9 @@
.setNestedEnum(MessageWithNoOuter.NestedEnum.BAZ)
.setForeignEnum(EnumWithNoOuter.BAR)
;
- assertEquals(message.toString(), MessageWithNoOuter.parseUnframed(message.toUnframedByteArray()).toString());
+
+ byte[] data = message.toUnframedByteArray();
+ MessageWithNoOuter newMessage = MessageWithNoOuter.parseUnframed(data);
+ assertEquals(message.toString(), newMessage.toString());
}
}
Modified: activemq/sandbox/activemq-protobuf/activemq-protobuf/src/main/java/org/apache/activemq/protobuf/BaseMessage.java
URL: http://svn.apache.org/viewvc/activemq/sandbox/activemq-protobuf/activemq-protobuf/src/main/java/org/apache/activemq/protobuf/BaseMessage.java?rev=713629&r1=713628&r2=713629&view=diff
==============================================================================
--- activemq/sandbox/activemq-protobuf/activemq-protobuf/src/main/java/org/apache/activemq/protobuf/BaseMessage.java (original)
+++ activemq/sandbox/activemq-protobuf/activemq-protobuf/src/main/java/org/apache/activemq/protobuf/BaseMessage.java Wed Nov 12 19:56:48 2008
@@ -30,327 +30,302 @@
abstract public class BaseMessage<T> implements Message<T> {
- protected int memoizedSerializedSize = -1;
+ protected int memoizedSerializedSize = -1;
- abstract public T clone() throws CloneNotSupportedException;
+ abstract public T clone() throws CloneNotSupportedException;
- public void clear() {
- memoizedSerializedSize = -1;
- }
-
- public boolean isInitialized() {
- return missingFields().isEmpty();
- }
-
- @SuppressWarnings("unchecked")
- public T assertInitialized() throws UninitializedMessageException {
- java.util.ArrayList<String> missingFields = missingFields();
- if (!missingFields.isEmpty()) {
- throw new UninitializedMessageException(missingFields);
- }
- return (T) this;
- }
-
- @SuppressWarnings("unchecked")
- protected T checktInitialized() throws InvalidProtocolBufferException {
- java.util.ArrayList<String> missingFields = missingFields();
- if (!missingFields.isEmpty()) {
- throw new UninitializedMessageException(missingFields)
- .asInvalidProtocolBufferException();
- }
- return (T) this;
- }
-
- public ArrayList<String> missingFields() {
- load();
- return new ArrayList<String>();
- }
-
- protected void loadAndClear() {
- memoizedSerializedSize = -1;
- }
+ public void clear() {
+ memoizedSerializedSize = -1;
+ }
+
+ public boolean isInitialized() {
+ return missingFields().isEmpty();
+ }
+
+ @SuppressWarnings("unchecked")
+ public T assertInitialized() throws UninitializedMessageException {
+ java.util.ArrayList<String> missingFields = missingFields();
+ if (!missingFields.isEmpty()) {
+ throw new UninitializedMessageException(missingFields);
+ }
+ return (T) this;
+ }
+
+ @SuppressWarnings("unchecked")
+ protected T checktInitialized() throws InvalidProtocolBufferException {
+ java.util.ArrayList<String> missingFields = missingFields();
+ if (!missingFields.isEmpty()) {
+ throw new UninitializedMessageException(missingFields).asInvalidProtocolBufferException();
+ }
+ return (T) this;
+ }
+
+ public ArrayList<String> missingFields() {
+ load();
+ return new ArrayList<String>();
+ }
+
+ protected void loadAndClear() {
+ memoizedSerializedSize = -1;
+ }
- protected void load() {
- }
+ protected void load() {
+ }
@SuppressWarnings("unchecked")
- public T mergeFrom(T other) {
- return (T) this;
+ public T mergeFrom(T other) {
+ return (T) this;
+ }
+
+ public void writeUnframed(CodedOutputStream output) throws java.io.IOException {
+ // if (encodedForm == null) {
+ // encodedForm = new byte[serializedSizeUnframed()];
+ // com.google.protobuf.CodedOutputStream original = output;
+ // output =
+ // com.google.protobuf.CodedOutputStream.newInstance(encodedForm);
+ // if (hasField1()) {
+ // output.writeInt32(1, getField1());
+ // }
+ // if (hasField2()) {
+ // output.writeInt64(2, getField2());
+ // }
+ // if (hasField3()) {
+ // writeMessage(output, 3, getField3());
+ // }
+ // output.checkNoSpaceLeft();
+ // output = original;
+ // }
+ // output.writeRawBytes(encodedForm);
+ }
+
+ // /////////////////////////////////////////////////////////////////
+ // Write related helpers.
+ // /////////////////////////////////////////////////////////////////
+
+ public void writeFramed(CodedOutputStream output) throws IOException {
+ output.writeRawVarint32(serializedSizeUnframed());
+ writeUnframed(output);
+ }
+
+ public byte[] toUnframedByteArray() {
+ try {
+ byte[] result = new byte[serializedSizeUnframed()];
+ CodedOutputStream output = CodedOutputStream.newInstance(result);
+ writeUnframed(output);
+ output.checkNoSpaceLeft();
+ return result;
+ } catch (IOException e) {
+ throw new RuntimeException("Serializing to a byte array threw an IOException " + "(should never happen).", e);
+ }
+ }
+
+ public byte[] toFramedByteArray() {
+ try {
+ byte[] result = new byte[serializedSizeFramed()];
+ CodedOutputStream output = CodedOutputStream.newInstance(result);
+ writeFramed(output);
+ output.checkNoSpaceLeft();
+ return result;
+ } catch (IOException e) {
+ throw new RuntimeException("Serializing to a byte array threw an IOException " + "(should never happen).", e);
+ }
+ }
+
+ public void writeFramed(OutputStream output) throws IOException {
+ CodedOutputStream codedOutput = CodedOutputStream.newInstance(output);
+ writeFramed(codedOutput);
+ codedOutput.flush();
+ }
+
+ public void writeUnframed(OutputStream output) throws IOException {
+ CodedOutputStream codedOutput = CodedOutputStream.newInstance(output);
+ writeUnframed(codedOutput);
+ codedOutput.flush();
+ }
+
+ public int serializedSizeFramed() {
+ int t = serializedSizeUnframed();
+ return CodedOutputStream.computeRawVarint32Size(t) + t;
+
+ }
+
+ // /////////////////////////////////////////////////////////////////
+ // Read related helpers.
+ // /////////////////////////////////////////////////////////////////
+
+ public T mergeFramed(CodedInputStream input) throws IOException {
+ int length = input.readRawVarint32();
+ int oldLimit = input.pushLimit(length);
+ T rc = mergeUnframed(input);
+ // input.checkLastTagWas(0);
+ input.popLimit(oldLimit);
+ return rc;
+ }
+
+ public T mergeUnframed(ByteString data) throws InvalidProtocolBufferException {
+ try {
+ CodedInputStream input = data.newCodedInput();
+ mergeUnframed(input);
+ // input.checkLastTagWas(0);
+ return (T) this;
+ } catch (InvalidProtocolBufferException e) {
+ throw e;
+ } catch (IOException e) {
+ throw new RuntimeException("Reading from a ByteString threw an IOException (should " + "never happen).", e);
+ }
+ }
+
+ public T mergeFramed(ByteString data) throws InvalidProtocolBufferException {
+ try {
+ CodedInputStream input = data.newCodedInput();
+ mergeFramed(input);
+ // input.checkLastTagWas(0);
+ return (T) this;
+ } catch (InvalidProtocolBufferException e) {
+ throw e;
+ } catch (IOException e) {
+ throw new RuntimeException("Reading from a ByteString threw an IOException (should " + "never happen).", e);
+ }
+ }
+
+ public T mergeUnframed(byte[] data) throws InvalidProtocolBufferException {
+ try {
+ CodedInputStream input = CodedInputStream.newInstance(data);
+ mergeUnframed(input);
+ // input.checkLastTagWas(0);
+ return (T) this;
+ } catch (InvalidProtocolBufferException e) {
+ throw e;
+ } catch (IOException e) {
+ throw new RuntimeException("Reading from a byte array threw an IOException (should " + "never happen).", e);
+ }
+ }
+
+ public T mergeFramed(byte[] data) throws InvalidProtocolBufferException {
+ try {
+ CodedInputStream input = CodedInputStream.newInstance(data);
+ mergeFramed(input);
+ // input.checkLastTagWas(0);
+ return (T) this;
+ } catch (InvalidProtocolBufferException e) {
+ throw e;
+ } catch (IOException e) {
+ throw new RuntimeException("Reading from a byte array threw an IOException (should " + "never happen).", e);
+ }
+ }
+
+ public T mergeUnframed(InputStream input) throws IOException {
+ CodedInputStream codedInput = CodedInputStream.newInstance(input);
+ mergeUnframed(codedInput);
+ return (T) this;
+ }
+
+ public T mergeFramed(InputStream input) throws IOException {
+ int length = readRawVarint32(input);
+ byte[] data = new byte[length];
+ int pos = 0;
+ while (pos < length) {
+ int r = input.read(data, pos, length - pos);
+ if (r < 0) {
+ throw new InvalidProtocolBufferException("Input stream ended before a full message frame could be read.");
+ }
+ pos += r;
+ }
+ return mergeUnframed(data);
+ }
+
+ // /////////////////////////////////////////////////////////////////
+ // Internal implementation methods.
+ // /////////////////////////////////////////////////////////////////
+ static protected <T> void addAll(Iterable<T> values, Collection<? super T> list) {
+ if (values instanceof Collection) {
+ @SuppressWarnings("unsafe")
+ Collection<T> collection = (Collection<T>) values;
+ list.addAll(collection);
+ } else {
+ for (T value : values) {
+ list.add(value);
+ }
+ }
+ }
+
+ static protected void writeGroup(CodedOutputStream output, int tag, BaseMessage message) throws IOException {
+ output.writeTag(tag, WIRETYPE_START_GROUP);
+ message.writeUnframed(output);
+ output.writeTag(tag, WIRETYPE_END_GROUP);
+ }
+
+ static protected <T extends BaseMessage> T readGroup(CodedInputStream input, int tag, T group) throws IOException {
+ group.mergeUnframed(input);
+ input.checkLastTagWas(makeTag(tag, WIRETYPE_END_GROUP));
+ return group;
+ }
+
+ static protected int computeGroupSize(int tag, BaseMessage message) {
+ return CodedOutputStream.computeTagSize(tag) * 2 + message.serializedSizeUnframed();
+ }
+
+ static protected void writeMessage(CodedOutputStream output, int tag, BaseMessage message) throws IOException {
+ output.writeTag(tag, WIRETYPE_LENGTH_DELIMITED);
+ message.writeFramed(output);
+ }
+
+ static protected int computeMessageSize(int tag, BaseMessage message) {
+ return CodedOutputStream.computeTagSize(tag) + message.serializedSizeFramed();
+ }
+
+ protected List<String> prefix(List<String> missingFields, String prefix) {
+ ArrayList<String> rc = new ArrayList<String>(missingFields.size());
+ for (String v : missingFields) {
+ rc.add(prefix + v);
+ }
+ return rc;
+ }
+
+ /**
+ * Read a raw Varint from the stream. If larger than 32 bits, discard the
+ * upper bits.
+ */
+ static public int readRawVarint32(InputStream is) throws IOException {
+ byte tmp = readRawByte(is);
+ if (tmp >= 0) {
+ return tmp;
+ }
+ int result = tmp & 0x7f;
+ if ((tmp = readRawByte(is)) >= 0) {
+ result |= tmp << 7;
+ } else {
+ result |= (tmp & 0x7f) << 7;
+ if ((tmp = readRawByte(is)) >= 0) {
+ result |= tmp << 14;
+ } else {
+ result |= (tmp & 0x7f) << 14;
+ if ((tmp = readRawByte(is)) >= 0) {
+ result |= tmp << 21;
+ } else {
+ result |= (tmp & 0x7f) << 21;
+ result |= (tmp = readRawByte(is)) << 28;
+ if (tmp < 0) {
+ // Discard upper 32 bits.
+ for (int i = 0; i < 5; i++) {
+ if (readRawByte(is) >= 0)
+ return result;
+ }
+ throw new InvalidProtocolBufferException("CodedInputStream encountered a malformed varint.");
+ }
+ }
+ }
+ }
+ return result;
+ }
+
+ static protected byte readRawByte(InputStream is) throws IOException {
+ int rc = is.read();
+ if (rc == -1) {
+ throw new InvalidProtocolBufferException("While parsing a protocol message, the input ended unexpectedly " + "in the middle of a field. This could mean either than the " + "input has been truncated or that an embedded message "
+ + "misreported its own length.");
+ }
+ return (byte) rc;
}
-
-
- public void writeUnframed(CodedOutputStream output) throws java.io.IOException {
-// if (encodedForm == null) {
-// encodedForm = new byte[serializedSizeUnframed()];
-// com.google.protobuf.CodedOutputStream original = output;
-// output = com.google.protobuf.CodedOutputStream.newInstance(encodedForm);
-// if (hasField1()) {
-// output.writeInt32(1, getField1());
-// }
-// if (hasField2()) {
-// output.writeInt64(2, getField2());
-// }
-// if (hasField3()) {
-// writeMessage(output, 3, getField3());
-// }
-// output.checkNoSpaceLeft();
-// output = original;
-// }
-// output.writeRawBytes(encodedForm);
- }
-
- // /////////////////////////////////////////////////////////////////
- // Write related helpers.
- // /////////////////////////////////////////////////////////////////
-
- public void writeFramed(CodedOutputStream output) throws IOException {
- output.writeRawVarint32(serializedSizeUnframed());
- writeUnframed(output);
- }
-
- public byte[] toUnframedByteArray() {
- try {
- byte[] result = new byte[serializedSizeUnframed()];
- CodedOutputStream output = CodedOutputStream.newInstance(result);
- writeUnframed(output);
- output.checkNoSpaceLeft();
- return result;
- } catch (IOException e) {
- throw new RuntimeException(
- "Serializing to a byte array threw an IOException "
- + "(should never happen).", e);
- }
- }
-
- public byte[] toFramedByteArray() {
- try {
- byte[] result = new byte[serializedSizeFramed()];
- CodedOutputStream output = CodedOutputStream.newInstance(result);
- writeFramed(output);
- output.checkNoSpaceLeft();
- return result;
- } catch (IOException e) {
- throw new RuntimeException(
- "Serializing to a byte array threw an IOException "
- + "(should never happen).", e);
- }
- }
-
- public void writeFramed(OutputStream output) throws IOException {
- CodedOutputStream codedOutput = CodedOutputStream.newInstance(output);
- writeFramed(codedOutput);
- codedOutput.flush();
- }
-
- public void writeUnframed(OutputStream output) throws IOException {
- CodedOutputStream codedOutput = CodedOutputStream.newInstance(output);
- writeUnframed(codedOutput);
- codedOutput.flush();
- }
-
- public int serializedSizeFramed() {
- int t = serializedSizeUnframed();
- return CodedOutputStream.computeRawVarint32Size(t) + t;
-
- }
-
- // /////////////////////////////////////////////////////////////////
- // Read related helpers.
- // /////////////////////////////////////////////////////////////////
-
- public T mergeFramed(CodedInputStream input) throws IOException {
- int length = input.readRawVarint32();
- int oldLimit = input.pushLimit(length);
- T rc = mergeUnframed(input);
- input.checkLastTagWas(0);
- input.popLimit(oldLimit);
- return rc;
- }
-
- public T mergeUnframed(ByteString data)
- throws InvalidProtocolBufferException {
- try {
- CodedInputStream input = data.newCodedInput();
- mergeUnframed(input);
- input.checkLastTagWas(0);
- return (T) this;
- } catch (InvalidProtocolBufferException e) {
- throw e;
- } catch (IOException e) {
- throw new RuntimeException(
- "Reading from a ByteString threw an IOException (should "
- + "never happen).", e);
- }
- }
-
- public T mergeFramed(ByteString data) throws InvalidProtocolBufferException {
- try {
- CodedInputStream input = data.newCodedInput();
- mergeFramed(input);
- input.checkLastTagWas(0);
- return (T) this;
- } catch (InvalidProtocolBufferException e) {
- throw e;
- } catch (IOException e) {
- throw new RuntimeException(
- "Reading from a ByteString threw an IOException (should "
- + "never happen).", e);
- }
- }
-
- public T mergeUnframed(byte[] data) throws InvalidProtocolBufferException {
- try {
- CodedInputStream input = CodedInputStream.newInstance(data);
- mergeUnframed(input);
- input.checkLastTagWas(0);
- return (T) this;
- } catch (InvalidProtocolBufferException e) {
- throw e;
- } catch (IOException e) {
- throw new RuntimeException(
- "Reading from a byte array threw an IOException (should "
- + "never happen).", e);
- }
- }
-
- public T mergeFramed(byte[] data) throws InvalidProtocolBufferException {
- try {
- CodedInputStream input = CodedInputStream.newInstance(data);
- mergeFramed(input);
- input.checkLastTagWas(0);
- return (T) this;
- } catch (InvalidProtocolBufferException e) {
- throw e;
- } catch (IOException e) {
- throw new RuntimeException(
- "Reading from a byte array threw an IOException (should "
- + "never happen).", e);
- }
- }
-
- public T mergeUnframed(InputStream input) throws IOException {
- CodedInputStream codedInput = CodedInputStream.newInstance(input);
- mergeUnframed(codedInput);
- return (T) this;
- }
-
- public T mergeFramed(InputStream input) throws IOException {
- int length = readRawVarint32(input);
- byte[] data = new byte[length];
- int pos = 0;
- while (pos < length) {
- int r = input.read(data, pos, length - pos);
- if (r < 0) {
- throw new InvalidProtocolBufferException(
- "Input stream ended before a full message frame could be read.");
- }
- pos += r;
- }
- return mergeUnframed(data);
- }
-
- // /////////////////////////////////////////////////////////////////
- // Internal implementation methods.
- // /////////////////////////////////////////////////////////////////
- static protected <T> void addAll(Iterable<T> values,
- Collection<? super T> list) {
- if (values instanceof Collection) {
- @SuppressWarnings("unsafe")
- Collection<T> collection = (Collection<T>) values;
- list.addAll(collection);
- } else {
- for (T value : values) {
- list.add(value);
- }
- }
- }
-
- static protected void writeGroup(CodedOutputStream output, int tag,
- BaseMessage message) throws IOException {
- output.writeTag(tag, WIRETYPE_START_GROUP);
- message.writeUnframed(output);
- output.writeTag(tag, WIRETYPE_END_GROUP);
- }
-
- static protected <T extends BaseMessage> T readGroup(
- CodedInputStream input, int tag, T group) throws IOException {
- group.mergeUnframed(input);
- input.checkLastTagWas(makeTag(tag, WIRETYPE_END_GROUP));
- return group;
- }
-
- static protected int computeGroupSize(int tag, BaseMessage message) {
- return CodedOutputStream.computeTagSize(tag) * 2
- + message.serializedSizeUnframed();
- }
-
- static protected void writeMessage(CodedOutputStream output, int tag,
- BaseMessage message) throws IOException {
- output.writeTag(tag, WIRETYPE_LENGTH_DELIMITED);
- message.writeFramed(output);
- }
-
- static protected int computeMessageSize(int tag, BaseMessage message) {
- return CodedOutputStream.computeTagSize(tag)
- + message.serializedSizeFramed();
- }
-
- protected List<String> prefix(List<String> missingFields, String prefix) {
- ArrayList<String> rc = new ArrayList<String>(missingFields.size());
- for (String v : missingFields) {
- rc.add(prefix + v);
- }
- return rc;
- }
-
- /**
- * Read a raw Varint from the stream. If larger than 32 bits, discard the
- * upper bits.
- */
- static public int readRawVarint32(InputStream is) throws IOException {
- byte tmp = readRawByte(is);
- if (tmp >= 0) {
- return tmp;
- }
- int result = tmp & 0x7f;
- if ((tmp = readRawByte(is)) >= 0) {
- result |= tmp << 7;
- } else {
- result |= (tmp & 0x7f) << 7;
- if ((tmp = readRawByte(is)) >= 0) {
- result |= tmp << 14;
- } else {
- result |= (tmp & 0x7f) << 14;
- if ((tmp = readRawByte(is)) >= 0) {
- result |= tmp << 21;
- } else {
- result |= (tmp & 0x7f) << 21;
- result |= (tmp = readRawByte(is)) << 28;
- if (tmp < 0) {
- // Discard upper 32 bits.
- for (int i = 0; i < 5; i++) {
- if (readRawByte(is) >= 0)
- return result;
- }
- throw new InvalidProtocolBufferException(
- "CodedInputStream encountered a malformed varint.");
- }
- }
- }
- }
- return result;
- }
-
- static protected byte readRawByte(InputStream is) throws IOException {
- int rc = is.read();
- if (rc == -1) {
- throw new InvalidProtocolBufferException(
- "While parsing a protocol message, the input ended unexpectedly "
- + "in the middle of a field. This could mean either than the "
- + "input has been truncated or that an embedded message "
- + "misreported its own length.");
- }
- return (byte) rc;
- }
}
Added: activemq/sandbox/activemq-protobuf/activemq-protobuf/src/main/java/org/apache/activemq/protobuf/ByteArrayInputStream.java
URL: http://svn.apache.org/viewvc/activemq/sandbox/activemq-protobuf/activemq-protobuf/src/main/java/org/apache/activemq/protobuf/ByteArrayInputStream.java?rev=713629&view=auto
==============================================================================
--- activemq/sandbox/activemq-protobuf/activemq-protobuf/src/main/java/org/apache/activemq/protobuf/ByteArrayInputStream.java (added)
+++ activemq/sandbox/activemq-protobuf/activemq-protobuf/src/main/java/org/apache/activemq/protobuf/ByteArrayInputStream.java Wed Nov 12 19:56:48 2008
@@ -0,0 +1,100 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.activemq.protobuf;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+/**
+ * Very similar to the java.io.ByteArrayInputStream but this version is not
+ * thread safe.
+ */
+public class ByteArrayInputStream extends InputStream {
+
+ byte buffer[];
+ int limit;
+ int pos;
+ int mark;
+
+ public ByteArrayInputStream(byte data[]) {
+ this(data, 0, data.length);
+ }
+
+ public ByteArrayInputStream(ByteSequence sequence) {
+ this(sequence.getData(), sequence.getOffset(), sequence.getLength());
+ }
+
+ public ByteArrayInputStream(byte data[], int offset, int size) {
+ this.buffer = data;
+ this.mark = offset;
+ this.pos = offset;
+ this.limit = offset + size;
+ }
+
+ public int read() throws IOException {
+ if (pos < limit) {
+ return buffer[pos++] & 0xff;
+ } else {
+ return -1;
+ }
+ }
+
+ public int read(byte[] b) throws IOException {
+ return read(b, 0, b.length);
+ }
+
+ public int read(byte b[], int off, int len) {
+ if (pos < limit) {
+ len = Math.min(len, limit - pos);
+ if (len > 0) {
+ System.arraycopy(buffer, pos, b, off, len);
+ pos += len;
+ }
+ return len;
+ } else {
+ return -1;
+ }
+ }
+
+ public long skip(long len) throws IOException {
+ if (pos < limit) {
+ len = Math.min(len, limit - pos);
+ if (len > 0) {
+ pos += len;
+ }
+ return len;
+ } else {
+ return -1;
+ }
+ }
+
+ public int available() {
+ return limit - pos;
+ }
+
+ public boolean markSupported() {
+ return true;
+ }
+
+ public void mark(int markpos) {
+ mark = pos;
+ }
+
+ public void reset() {
+ pos = mark;
+ }
+}
Added: activemq/sandbox/activemq-protobuf/activemq-protobuf/src/main/java/org/apache/activemq/protobuf/ByteArrayOutputStream.java
URL: http://svn.apache.org/viewvc/activemq/sandbox/activemq-protobuf/activemq-protobuf/src/main/java/org/apache/activemq/protobuf/ByteArrayOutputStream.java?rev=713629&view=auto
==============================================================================
--- activemq/sandbox/activemq-protobuf/activemq-protobuf/src/main/java/org/apache/activemq/protobuf/ByteArrayOutputStream.java (added)
+++ activemq/sandbox/activemq-protobuf/activemq-protobuf/src/main/java/org/apache/activemq/protobuf/ByteArrayOutputStream.java Wed Nov 12 19:56:48 2008
@@ -0,0 +1,86 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.activemq.protobuf;
+
+import java.io.OutputStream;
+
+
+/**
+ * Very similar to the java.io.ByteArrayOutputStream but this version
+ * is not thread safe and the resulting data is returned in a ByteSequence
+ * to avoid an extra byte[] allocation.
+ */
+public class ByteArrayOutputStream extends OutputStream {
+
+ byte buffer[];
+ int size;
+
+ public ByteArrayOutputStream() {
+ this(1028);
+ }
+ public ByteArrayOutputStream(int capacity) {
+ buffer = new byte[capacity];
+ }
+
+ public ByteArrayOutputStream(byte[] buffer) {
+ this.buffer = buffer;
+ }
+
+ public void write(int b) {
+ int newsize = size + 1;
+ checkCapacity(newsize);
+ buffer[size] = (byte) b;
+ size = newsize;
+ }
+
+ public void write(byte b[], int off, int len) {
+ int newsize = size + len;
+ checkCapacity(newsize);
+ System.arraycopy(b, off, buffer, size, len);
+ size = newsize;
+ }
+
+ /**
+ * Ensures the the buffer has at least the minimumCapacity specified.
+ * @param i
+ */
+ private void checkCapacity(int minimumCapacity) {
+ if (minimumCapacity > buffer.length) {
+ byte b[] = new byte[Math.max(buffer.length << 1, minimumCapacity)];
+ System.arraycopy(buffer, 0, b, 0, size);
+ buffer = b;
+ }
+ }
+
+ public void reset() {
+ size = 0;
+ }
+
+ public ByteSequence toByteSequence() {
+ return new ByteSequence(buffer, 0, size);
+ }
+
+ public byte[] toByteArray() {
+ byte rc[] = new byte[size];
+ System.arraycopy(buffer, 0, rc, 0, size);
+ return rc;
+ }
+
+ public int size() {
+ return size;
+ }
+}
Added: activemq/sandbox/activemq-protobuf/activemq-protobuf/src/main/java/org/apache/activemq/protobuf/ByteSequence.java
URL: http://svn.apache.org/viewvc/activemq/sandbox/activemq-protobuf/activemq-protobuf/src/main/java/org/apache/activemq/protobuf/ByteSequence.java?rev=713629&view=auto
==============================================================================
--- activemq/sandbox/activemq-protobuf/activemq-protobuf/src/main/java/org/apache/activemq/protobuf/ByteSequence.java (added)
+++ activemq/sandbox/activemq-protobuf/activemq-protobuf/src/main/java/org/apache/activemq/protobuf/ByteSequence.java Wed Nov 12 19:56:48 2008
@@ -0,0 +1,74 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.activemq.protobuf;
+
+public class ByteSequence {
+
+ public byte[] data;
+ public int offset;
+ public int length;
+
+ public ByteSequence() {
+ }
+
+ public ByteSequence(byte data[]) {
+ this.data = data;
+ this.offset = 0;
+ this.length = data.length;
+ }
+
+ public ByteSequence(byte data[], int offset, int length) {
+ this.data = data;
+ this.offset = offset;
+ this.length = length;
+ }
+
+ public byte[] getData() {
+ return data;
+ }
+
+ public int getLength() {
+ return length;
+ }
+
+ public int getOffset() {
+ return offset;
+ }
+
+ public void setData(byte[] data) {
+ this.data = data;
+ }
+
+ public void setLength(int length) {
+ this.length = length;
+ }
+
+ public void setOffset(int offset) {
+ this.offset = offset;
+ }
+
+ public void compact() {
+ if (length != data.length) {
+ byte t[] = new byte[length];
+ System.arraycopy(data, offset, t, 0, length);
+ data = t;
+ offset = 0;
+ }
+ }
+
+}
Modified: activemq/sandbox/activemq-protobuf/activemq-protobuf/src/main/java/org/apache/activemq/protobuf/CodedInputStream.java
URL: http://svn.apache.org/viewvc/activemq/sandbox/activemq-protobuf/activemq-protobuf/src/main/java/org/apache/activemq/protobuf/CodedInputStream.java?rev=713629&r1=713628&r2=713629&view=diff
==============================================================================
--- activemq/sandbox/activemq-protobuf/activemq-protobuf/src/main/java/org/apache/activemq/protobuf/CodedInputStream.java (original)
+++ activemq/sandbox/activemq-protobuf/activemq-protobuf/src/main/java/org/apache/activemq/protobuf/CodedInputStream.java Wed Nov 12 19:56:48 2008
@@ -16,10 +16,10 @@
package org.apache.activemq.protobuf;
+import java.io.EOFException;
+import java.io.FilterInputStream;
import java.io.IOException;
import java.io.InputStream;
-import java.util.ArrayList;
-import java.util.List;
/**
* Reads and decodes protocol message fields.
@@ -33,23 +33,23 @@
*
* @author kenton@google.com Kenton Varda
*/
-public final class CodedInputStream {
+public final class CodedInputStream extends FilterInputStream {
+
+ private int lastTag = 0;
+ private int limit = Integer.MAX_VALUE;
+ private int pos;
- /**
- * Create a new CodedInputStream wrapping the given InputStream.
- */
- public static CodedInputStream newInstance(InputStream input) {
- return new CodedInputStream(input);
+ public CodedInputStream(InputStream in) {
+ super(in);
}
- /**
- * Create a new CodedInputStream wrapping the given byte array.
- */
- public static CodedInputStream newInstance(byte[] buf) {
- return new CodedInputStream(buf);
+ public static CodedInputStream newInstance(InputStream input) {
+ return new CodedInputStream( input );
}
- // -----------------------------------------------------------------
+ public static CodedInputStream newInstance(byte[] originalForm) {
+ return new CodedInputStream( new ByteArrayInputStream(originalForm) );
+ }
/**
* Attempt to read a field tag, returning zero if we have reached EOF.
@@ -58,17 +58,16 @@
* number.
*/
public int readTag() throws IOException {
- if (bufferPos == bufferSize && !refillBuffer(false)) {
- lastTag = 0;
+ try {
+ lastTag = readRawVarint32();
+ if (lastTag == 0) {
+ // If we actually read zero, that's not a valid tag.
+ throw InvalidProtocolBufferException.invalidTag();
+ }
+ return lastTag;
+ } catch (EOFException e) {
return 0;
}
-
- lastTag = readRawVarint32();
- if (lastTag == 0) {
- // If we actually read zero, that's not a valid tag.
- throw InvalidProtocolBufferException.invalidTag();
- }
- return lastTag;
}
/**
@@ -173,31 +172,13 @@
/** Read a {@code string} field value from the stream. */
public String readString() throws IOException {
int size = readRawVarint32();
- if (size < bufferSize - bufferPos && size > 0) {
- // Fast path: We already have the bytes in a contiguous buffer, so
- // just copy directly from it.
- String result = new String(buffer, bufferPos, size, "UTF-8");
- bufferPos += size;
- return result;
- } else {
- // Slow path: Build a byte array first then copy it.
- return new String(readRawBytes(size), "UTF-8");
- }
+ return new String(readRawBytes(size), "UTF-8");
}
/** Read a {@code bytes} field value from the stream. */
public ByteString readBytes() throws IOException {
int size = readRawVarint32();
- if (size < bufferSize - bufferPos && size > 0) {
- // Fast path: We already have the bytes in a contiguous buffer, so
- // just copy directly from it.
- ByteString result = ByteString.copyFrom(buffer, bufferPos, size);
- bufferPos += size;
- return result;
- } else {
- // Slow path: Build a byte array first then copy it.
- return ByteString.copyFrom(readRawBytes(size));
- }
+ return ByteString.copyFrom(readRawBytes(size));
}
/** Read a {@code uint32} field value from the stream. */
@@ -336,172 +317,7 @@
*/
public static long decodeZigZag64(long n) {
return (n >>> 1) ^ -(n & 1);
- }
-
- // -----------------------------------------------------------------
-
- private byte[] buffer;
- private int bufferSize;
- private int bufferSizeAfterLimit = 0;
- private int bufferPos = 0;
- private InputStream input;
- private int lastTag = 0;
-
- /**
- * The total number of bytes read before the current buffer. The total bytes
- * read up to the current position can be computed as {@code
- * totalBytesRetired + bufferPos}.
- */
- private int totalBytesRetired = 0;
-
- /** The absolute position of the end of the current message. */
- private int currentLimit = Integer.MAX_VALUE;
-
- /** See setRecursionLimit() */
- private int recursionDepth = 0;
- private int recursionLimit = DEFAULT_RECURSION_LIMIT;
-
- /** See setSizeLimit() */
- private int sizeLimit = DEFAULT_SIZE_LIMIT;
-
- private static final int DEFAULT_RECURSION_LIMIT = 64;
- private static final int DEFAULT_SIZE_LIMIT = 64 << 20; // 64MB
- private static final int BUFFER_SIZE = 4096;
-
- private CodedInputStream(byte[] buffer) {
- this.buffer = buffer;
- this.bufferSize = buffer.length;
- this.input = null;
- }
-
- private CodedInputStream(InputStream input) {
- this.buffer = new byte[BUFFER_SIZE];
- this.bufferSize = 0;
- this.input = input;
- }
-
- /**
- * Set the maximum message recursion depth. In order to prevent malicious
- * messages from causing stack overflows, {@code CodedInputStream} limits
- * how deeply messages may be nested. The default limit is 64.
- *
- * @return the old limit.
- */
- public int setRecursionLimit(int limit) {
- if (limit < 0) {
- throw new IllegalArgumentException("Recursion limit cannot be negative: " + limit);
- }
- int oldLimit = recursionLimit;
- recursionLimit = limit;
- return oldLimit;
- }
-
- /**
- * Set the maximum message size. In order to prevent malicious messages from
- * exhausting memory or causing integer overflows, {@code CodedInputStream}
- * limits how large a message may be. The default limit is 64MB. You should
- * set this limit as small as you can without harming your app's
- * functionality. Note that size limits only apply when reading from an
- * {@code InputStream}, not when constructed around a raw byte array (nor
- * with {@link ByteString#newCodedInput}).
- *
- * @return the old limit.
- */
- public int setSizeLimit(int limit) {
- if (limit < 0) {
- throw new IllegalArgumentException("Size limit cannot be negative: " + limit);
- }
- int oldLimit = sizeLimit;
- sizeLimit = limit;
- return oldLimit;
- }
-
- /**
- * Sets {@code currentLimit} to (current position) + {@code byteLimit}. This
- * is called when descending into a length-delimited embedded message.
- *
- * @return the old limit.
- */
- public int pushLimit(int byteLimit) throws InvalidProtocolBufferException {
- if (byteLimit < 0) {
- throw InvalidProtocolBufferException.negativeSize();
- }
- byteLimit += totalBytesRetired + bufferPos;
- int oldLimit = currentLimit;
- if (byteLimit > oldLimit) {
- throw InvalidProtocolBufferException.truncatedMessage();
- }
- currentLimit = byteLimit;
-
- recomputeBufferSizeAfterLimit();
-
- return oldLimit;
- }
-
- private void recomputeBufferSizeAfterLimit() {
- bufferSize += bufferSizeAfterLimit;
- int bufferEnd = totalBytesRetired + bufferSize;
- if (bufferEnd > currentLimit) {
- // Limit is in current buffer.
- bufferSizeAfterLimit = bufferEnd - currentLimit;
- bufferSize -= bufferSizeAfterLimit;
- } else {
- bufferSizeAfterLimit = 0;
- }
- }
-
- /**
- * Discards the current limit, returning to the previous limit.
- *
- * @param oldLimit
- * The old limit, as returned by {@code pushLimit}.
- */
- public void popLimit(int oldLimit) {
- currentLimit = oldLimit;
- recomputeBufferSizeAfterLimit();
- }
-
- /**
- * Called with {@code this.buffer} is empty to read more bytes from the
- * input. If {@code mustSucceed} is true, refillBuffer() gurantees that
- * either there will be at least one byte in the buffer when it returns or
- * it will throw an exception. If {@code mustSucceed} is false,
- * refillBuffer() returns false if no more bytes were available.
- */
- private boolean refillBuffer(boolean mustSucceed) throws IOException {
- if (bufferPos < bufferSize) {
- throw new IllegalStateException("refillBuffer() called when buffer wasn't empty.");
- }
-
- if (totalBytesRetired + bufferSize == currentLimit) {
- // Oops, we hit a limit.
- if (mustSucceed) {
- throw InvalidProtocolBufferException.truncatedMessage();
- } else {
- return false;
- }
- }
-
- totalBytesRetired += bufferSize;
-
- bufferPos = 0;
- bufferSize = (input == null) ? -1 : input.read(buffer);
- if (bufferSize == -1) {
- bufferSize = 0;
- if (mustSucceed) {
- throw InvalidProtocolBufferException.truncatedMessage();
- } else {
- return false;
- }
- } else {
- recomputeBufferSizeAfterLimit();
- int totalBytesRead = totalBytesRetired + bufferSize + bufferSizeAfterLimit;
- if (totalBytesRead > sizeLimit || totalBytesRead < 0) {
- throw InvalidProtocolBufferException.sizeLimitExceeded();
- }
- return true;
- }
- }
+ }
/**
* Read one byte from the input.
@@ -510,10 +326,15 @@
* The end of the stream or the current limit was reached.
*/
public byte readRawByte() throws IOException {
- if (bufferPos == bufferSize) {
- refillBuffer(true);
+ if( pos >= limit ) {
+ throw new EOFException();
+ }
+ int rc = in.read();
+ if( rc < 0 ) {
+ throw new EOFException();
}
- return buffer[bufferPos++];
+ pos++;
+ return (byte)( rc & 0xFF);
}
/**
@@ -523,114 +344,22 @@
* The end of the stream or the current limit was reached.
*/
public byte[] readRawBytes(int size) throws IOException {
- if (size < 0) {
- throw InvalidProtocolBufferException.negativeSize();
+ if( this.pos+size > limit ) {
+ throw new EOFException();
}
-
- if (totalBytesRetired + bufferPos + size > currentLimit) {
- // Read to the end of the stream anyway.
- skipRawBytes(currentLimit - totalBytesRetired - bufferPos);
- // Then fail.
- throw InvalidProtocolBufferException.truncatedMessage();
- }
-
- if (size <= bufferSize - bufferPos) {
- // We have all the bytes we need already.
- byte[] bytes = new byte[size];
- System.arraycopy(buffer, bufferPos, bytes, 0, size);
- bufferPos += size;
- return bytes;
- } else if (size < BUFFER_SIZE) {
- // Reading more bytes than are in the buffer, but not an excessive
- // number
- // of bytes. We can safely allocate the resulting array ahead of
- // time.
-
- // First copy what we have.
- byte[] bytes = new byte[size];
- int pos = bufferSize - bufferPos;
- System.arraycopy(buffer, bufferPos, bytes, 0, pos);
- bufferPos = bufferSize;
-
- // We want to use refillBuffer() and then copy from the buffer into
- // our
- // byte array rather than reading directly into our byte array
- // because
- // the input may be unbuffered.
- refillBuffer(true);
-
- while (size - pos > bufferSize) {
- System.arraycopy(buffer, 0, bytes, pos, bufferSize);
- pos += bufferSize;
- bufferPos = bufferSize;
- refillBuffer(true);
- }
-
- System.arraycopy(buffer, 0, bytes, pos, size - pos);
- bufferPos = size - pos;
-
- return bytes;
- } else {
- // The size is very large. For security reasons, we can't allocate
- // the
- // entire byte array yet. The size comes directly from the input, so
- // a
- // maliciously-crafted message could provide a bogus very large size
- // in
- // order to trick the app into allocating a lot of memory. We avoid
- // this
- // by allocating and reading only a small chunk at a time, so that
- // the
- // malicious message must actually *be* extremely large to cause
- // problems. Meanwhile, we limit the allowed size of a message
- // elsewhere.
-
- // Remember the buffer markers since we'll have to copy the bytes
- // out of
- // it later.
- int originalBufferPos = bufferPos;
- int originalBufferSize = bufferSize;
-
- // Mark the current buffer consumed.
- totalBytesRetired += bufferSize;
- bufferPos = 0;
- bufferSize = 0;
-
- // Read all the rest of the bytes we need.
- int sizeLeft = size - (originalBufferSize - originalBufferPos);
- List<byte[]> chunks = new ArrayList<byte[]>();
-
- while (sizeLeft > 0) {
- byte[] chunk = new byte[Math.min(sizeLeft, BUFFER_SIZE)];
- int pos = 0;
- while (pos < chunk.length) {
- int n = (input == null) ? -1 : input.read(chunk, pos, chunk.length - pos);
- if (n == -1) {
- throw InvalidProtocolBufferException.truncatedMessage();
- }
- totalBytesRetired += n;
- pos += n;
- }
- sizeLeft -= chunk.length;
- chunks.add(chunk);
- }
-
- // OK, got everything. Now concatenate it all into one buffer.
- byte[] bytes = new byte[size];
-
- // Start by copying the leftover bytes from this.buffer.
- int pos = originalBufferSize - originalBufferPos;
- System.arraycopy(buffer, originalBufferPos, bytes, 0, pos);
-
- // And now all the chunks.
- for (byte[] chunk : chunks) {
- System.arraycopy(chunk, 0, bytes, pos, chunk.length);
- pos += chunk.length;
+ byte[] rc = new byte[size];
+ int c;
+ int pos=0;
+
+ while( pos < size ) {
+ c = in.read(rc, pos, size-pos);
+ if( c < 0 ) {
+ throw new EOFException();
}
-
- // Done.
- return bytes;
+ this.pos += c;
+ pos += c;
}
+ return rc;
}
/**
@@ -640,37 +369,21 @@
* The end of the stream or the current limit was reached.
*/
public void skipRawBytes(int size) throws IOException {
- if (size < 0) {
- throw InvalidProtocolBufferException.negativeSize();
+ int pos = 0;
+ while (pos < size) {
+ int n = (int) in.skip(size - pos);
+ pos += n;
}
+ }
- if (totalBytesRetired + bufferPos + size > currentLimit) {
- // Read to the end of the stream anyway.
- skipRawBytes(currentLimit - totalBytesRetired - bufferPos);
- // Then fail.
- throw InvalidProtocolBufferException.truncatedMessage();
- }
+ public int pushLimit(int limit) {
+ int rc = this.limit;
+ this.limit = pos+limit;
+ return rc;
+ }
- if (size < bufferSize - bufferPos) {
- // We have all the bytes we need already.
- bufferPos += size;
- } else {
- // Skipping more bytes than are in the buffer. First skip what we
- // have.
- int pos = bufferSize - bufferPos;
- totalBytesRetired += pos;
- bufferPos = 0;
- bufferSize = 0;
-
- // Then skip directly from the InputStream for the rest.
- while (pos < size) {
- int n = (input == null) ? -1 : (int) input.skip(size - pos);
- if (n <= 0) {
- throw InvalidProtocolBufferException.truncatedMessage();
- }
- pos += n;
- totalBytesRetired += n;
- }
- }
+ public void popLimit(int limit) {
+ this.limit = limit;
}
+
}
Modified: activemq/sandbox/activemq-protobuf/activemq-protobuf/src/main/java/org/apache/activemq/protobuf/CodedOutputStream.java
URL: http://svn.apache.org/viewvc/activemq/sandbox/activemq-protobuf/activemq-protobuf/src/main/java/org/apache/activemq/protobuf/CodedOutputStream.java?rev=713629&r1=713628&r2=713629&view=diff
==============================================================================
--- activemq/sandbox/activemq-protobuf/activemq-protobuf/src/main/java/org/apache/activemq/protobuf/CodedOutputStream.java (original)
+++ activemq/sandbox/activemq-protobuf/activemq-protobuf/src/main/java/org/apache/activemq/protobuf/CodedOutputStream.java Wed Nov 12 19:56:48 2008
@@ -1,4 +1,3 @@
-
//Protocol Buffers - Google's data interchange format
//Copyright 2008 Google Inc.
//http://code.google.com/p/protobuf/
@@ -16,584 +15,453 @@
//limitations under the License.
package org.apache.activemq.protobuf;
+import java.io.FilterOutputStream;
import java.io.IOException;
import java.io.OutputStream;
/**
-* Encodes and writes protocol message fields.
-*
-* <p>This class contains two kinds of methods: methods that write specific
-* protocol message constructs and field types (e.g. {@link #writeTag} and
-* {@link #writeInt32}) and methods that write low-level values (e.g.
-* {@link #writeRawVarint32} and {@link #writeRawBytes}). If you are
-* writing encoded protocol messages, you should use the former methods, but if
-* you are writing some other format of your own design, use the latter.
-*
-* <p>This class is totally unsynchronized.
-*
-* @author kneton@google.com Kenton Varda
-*/
-public final class CodedOutputStream {
-private final byte[] buffer;
-private final int limit;
-private int position;
-
-private final OutputStream output;
-
-/**
-* The buffer size used in {@link #newInstance(java.io.OutputStream)}.
-*/
-public static final int DEFAULT_BUFFER_SIZE = 4096;
-
-private CodedOutputStream(byte[] buffer, int offset, int length) {
- this.output = null;
- this.buffer = buffer;
- this.position = offset;
- this.limit = offset + length;
-}
-
-private CodedOutputStream(OutputStream output, byte[] buffer) {
- this.output = output;
- this.buffer = buffer;
- this.position = 0;
- this.limit = buffer.length;
-}
-
-/**
-* Create a new {@code CodedOutputStream} wrapping the given
-* {@code OutputStream}.
-*/
-public static CodedOutputStream newInstance(OutputStream output) {
- return newInstance(output, DEFAULT_BUFFER_SIZE);
-}
-
-/**
-* Create a new {@code CodedOutputStream} wrapping the given
-* {@code OutputStream} with a given buffer size.
-*/
-public static CodedOutputStream newInstance(OutputStream output,
- int bufferSize) {
- return new CodedOutputStream(output, new byte[bufferSize]);
-}
-
-/**
-* Create a new {@code CodedOutputStream} that writes directly to the given
-* byte array. If more bytes are written than fit in the array,
-* {@link OutOfSpaceException} will be thrown. Writing directly to a flat
-* array is faster than writing to an {@code OutputStream}. See also
-* {@link ByteString#newCodedBuilder}.
-*/
-public static CodedOutputStream newInstance(byte[] flatArray) {
- return newInstance(flatArray, 0, flatArray.length);
-}
-
-/**
-* Create a new {@code CodedOutputStream} that writes directly to the given
-* byte array slice. If more bytes are written than fit in the slice,
-* {@link OutOfSpaceException} will be thrown. Writing directly to a flat
-* array is faster than writing to an {@code OutputStream}. See also
-* {@link ByteString#newCodedBuilder}.
-*/
-public static CodedOutputStream newInstance(byte[] flatArray, int offset,
- int length) {
- return new CodedOutputStream(flatArray, offset, length);
-}
-
-// -----------------------------------------------------------------
-
-/** Write a {@code double} field, including tag, to the stream. */
-public void writeDouble(int fieldNumber, double value) throws IOException {
- writeTag(fieldNumber, WireFormat.WIRETYPE_FIXED64);
- writeRawLittleEndian64(Double.doubleToRawLongBits(value));
-}
-
-/** Write a {@code float} field, including tag, to the stream. */
-public void writeFloat(int fieldNumber, float value) throws IOException {
- writeTag(fieldNumber, WireFormat.WIRETYPE_FIXED32);
- writeRawLittleEndian32(Float.floatToRawIntBits(value));
-}
-
-/** Write a {@code uint64} field, including tag, to the stream. */
-public void writeUInt64(int fieldNumber, long value) throws IOException {
- writeTag(fieldNumber, WireFormat.WIRETYPE_VARINT);
- writeRawVarint64(value);
-}
-
-/** Write an {@code int64} field, including tag, to the stream. */
-public void writeInt64(int fieldNumber, long value) throws IOException {
- writeTag(fieldNumber, WireFormat.WIRETYPE_VARINT);
- writeRawVarint64(value);
-}
-
-/** Write an {@code int32} field, including tag, to the stream. */
-public void writeInt32(int fieldNumber, int value) throws IOException {
- writeTag(fieldNumber, WireFormat.WIRETYPE_VARINT);
- if (value >= 0) {
- writeRawVarint32(value);
- } else {
- // Must sign-extend.
- writeRawVarint64(value);
- }
-}
-
-/** Write a {@code fixed64} field, including tag, to the stream. */
-public void writeFixed64(int fieldNumber, long value) throws IOException {
- writeTag(fieldNumber, WireFormat.WIRETYPE_FIXED64);
- writeRawLittleEndian64(value);
-}
-
-/** Write a {@code fixed32} field, including tag, to the stream. */
-public void writeFixed32(int fieldNumber, int value) throws IOException {
- writeTag(fieldNumber, WireFormat.WIRETYPE_FIXED32);
- writeRawLittleEndian32(value);
-}
-
-/** Write a {@code bool} field, including tag, to the stream. */
-public void writeBool(int fieldNumber, boolean value) throws IOException {
- writeTag(fieldNumber, WireFormat.WIRETYPE_VARINT);
- writeRawByte(value ? 1 : 0);
-}
-
-/** Write a {@code string} field, including tag, to the stream. */
-public void writeString(int fieldNumber, String value) throws IOException {
- writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED);
- // Unfortunately there does not appear to be any way to tell Java to encode
- // UTF-8 directly into our buffer, so we have to let it create its own byte
- // array and then copy.
- byte[] bytes = value.getBytes("UTF-8");
- writeRawVarint32(bytes.length);
- writeRawBytes(bytes);
-}
-
-/** Write a {@code bytes} field, including tag, to the stream. */
-public void writeBytes(int fieldNumber, ByteString value) throws IOException {
- writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED);
- byte[] bytes = value.toByteArray();
- writeRawVarint32(bytes.length);
- writeRawBytes(bytes);
-}
-
-/** Write a {@code uint32} field, including tag, to the stream. */
-public void writeUInt32(int fieldNumber, int value) throws IOException {
- writeTag(fieldNumber, WireFormat.WIRETYPE_VARINT);
- writeRawVarint32(value);
-}
-
-/**
-* Write an enum field, including tag, to the stream. Caller is responsible
-* for converting the enum value to its numeric value.
-*/
-public void writeEnum(int fieldNumber, int value) throws IOException {
- writeTag(fieldNumber, WireFormat.WIRETYPE_VARINT);
- writeRawVarint32(value);
-}
-
-/** Write an {@code sfixed32} field, including tag, to the stream. */
-public void writeSFixed32(int fieldNumber, int value) throws IOException {
- writeTag(fieldNumber, WireFormat.WIRETYPE_FIXED32);
- writeRawLittleEndian32(value);
-}
-
-/** Write an {@code sfixed64} field, including tag, to the stream. */
-public void writeSFixed64(int fieldNumber, long value) throws IOException {
- writeTag(fieldNumber, WireFormat.WIRETYPE_FIXED64);
- writeRawLittleEndian64(value);
-}
-
-/** Write an {@code sint32} field, including tag, to the stream. */
-public void writeSInt32(int fieldNumber, int value) throws IOException {
- writeTag(fieldNumber, WireFormat.WIRETYPE_VARINT);
- writeRawVarint32(encodeZigZag32(value));
-}
-
-/** Write an {@code sint64} field, including tag, to the stream. */
-public void writeSInt64(int fieldNumber, long value) throws IOException {
- writeTag(fieldNumber, WireFormat.WIRETYPE_VARINT);
- writeRawVarint64(encodeZigZag64(value));
-}
-
-// =================================================================
-
-/**
-* Compute the number of bytes that would be needed to encode a
-* {@code double} field, including tag.
-*/
-public static int computeDoubleSize(int fieldNumber, double value) {
- return computeTagSize(fieldNumber) + LITTLE_ENDIAN_64_SIZE;
-}
-
-/**
-* Compute the number of bytes that would be needed to encode a
-* {@code float} field, including tag.
-*/
-public static int computeFloatSize(int fieldNumber, float value) {
- return computeTagSize(fieldNumber) + LITTLE_ENDIAN_32_SIZE;
-}
-
-/**
-* Compute the number of bytes that would be needed to encode a
-* {@code uint64} field, including tag.
-*/
-public static int computeUInt64Size(int fieldNumber, long value) {
- return computeTagSize(fieldNumber) + computeRawVarint64Size(value);
-}
+ * Encodes and writes protocol message fields.
+ *
+ * <p>
+ * This class contains two kinds of methods: methods that write specific
+ * protocol message constructs and field types (e.g. {@link #writeTag} and
+ * {@link #writeInt32}) and methods that write low-level values (e.g.
+ * {@link #writeRawVarint32} and {@link #writeRawBytes}). If you are writing
+ * encoded protocol messages, you should use the former methods, but if you are
+ * writing some other format of your own design, use the latter.
+ *
+ * <p>
+ * This class is totally unsynchronized.
+ *
+ * @author kneton@google.com Kenton Varda
+ */
+public final class CodedOutputStream extends FilterOutputStream {
+
+ public static CodedOutputStream newInstance(byte[] data) {
+ return new CodedOutputStream(new ByteArrayOutputStream(data));
+ }
+
+ public static CodedOutputStream newInstance(OutputStream output) {
+ return new CodedOutputStream(output);
+ }
+
+ public CodedOutputStream(OutputStream os) {
+ super(os);
+ }
+
+
+ // -----------------------------------------------------------------
+
+ /** Write a {@code double} field, including tag, to the stream. */
+ public void writeDouble(int fieldNumber, double value) throws IOException {
+ writeTag(fieldNumber, WireFormat.WIRETYPE_FIXED64);
+ writeRawLittleEndian64(Double.doubleToRawLongBits(value));
+ }
+
+ /** Write a {@code float} field, including tag, to the stream. */
+ public void writeFloat(int fieldNumber, float value) throws IOException {
+ writeTag(fieldNumber, WireFormat.WIRETYPE_FIXED32);
+ writeRawLittleEndian32(Float.floatToRawIntBits(value));
+ }
+
+ /** Write a {@code uint64} field, including tag, to the stream. */
+ public void writeUInt64(int fieldNumber, long value) throws IOException {
+ writeTag(fieldNumber, WireFormat.WIRETYPE_VARINT);
+ writeRawVarint64(value);
+ }
+
+ /** Write an {@code int64} field, including tag, to the stream. */
+ public void writeInt64(int fieldNumber, long value) throws IOException {
+ writeTag(fieldNumber, WireFormat.WIRETYPE_VARINT);
+ writeRawVarint64(value);
+ }
+
+ /** Write an {@code int32} field, including tag, to the stream. */
+ public void writeInt32(int fieldNumber, int value) throws IOException {
+ writeTag(fieldNumber, WireFormat.WIRETYPE_VARINT);
+ if (value >= 0) {
+ writeRawVarint32(value);
+ } else {
+ // Must sign-extend.
+ writeRawVarint64(value);
+ }
+ }
+
+ /** Write a {@code fixed64} field, including tag, to the stream. */
+ public void writeFixed64(int fieldNumber, long value) throws IOException {
+ writeTag(fieldNumber, WireFormat.WIRETYPE_FIXED64);
+ writeRawLittleEndian64(value);
+ }
+
+ /** Write a {@code fixed32} field, including tag, to the stream. */
+ public void writeFixed32(int fieldNumber, int value) throws IOException {
+ writeTag(fieldNumber, WireFormat.WIRETYPE_FIXED32);
+ writeRawLittleEndian32(value);
+ }
+
+ /** Write a {@code bool} field, including tag, to the stream. */
+ public void writeBool(int fieldNumber, boolean value) throws IOException {
+ writeTag(fieldNumber, WireFormat.WIRETYPE_VARINT);
+ writeRawByte(value ? 1 : 0);
+ }
+
+ /** Write a {@code string} field, including tag, to the stream. */
+ public void writeString(int fieldNumber, String value) throws IOException {
+ writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED);
+ // Unfortunately there does not appear to be any way to tell Java to
+ // encode
+ // UTF-8 directly into our buffer, so we have to let it create its own
+ // byte
+ // array and then copy.
+ byte[] bytes = value.getBytes("UTF-8");
+ writeRawVarint32(bytes.length);
+ writeRawBytes(bytes);
+ }
+
+ /** Write a {@code bytes} field, including tag, to the stream. */
+ public void writeBytes(int fieldNumber, ByteString value) throws IOException {
+ writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED);
+ byte[] bytes = value.toByteArray();
+ writeRawVarint32(bytes.length);
+ writeRawBytes(bytes);
+ }
+
+ /** Write a {@code uint32} field, including tag, to the stream. */
+ public void writeUInt32(int fieldNumber, int value) throws IOException {
+ writeTag(fieldNumber, WireFormat.WIRETYPE_VARINT);
+ writeRawVarint32(value);
+ }
+
+ /**
+ * Write an enum field, including tag, to the stream. Caller is responsible
+ * for converting the enum value to its numeric value.
+ */
+ public void writeEnum(int fieldNumber, int value) throws IOException {
+ writeTag(fieldNumber, WireFormat.WIRETYPE_VARINT);
+ writeRawVarint32(value);
+ }
+
+ /** Write an {@code sfixed32} field, including tag, to the stream. */
+ public void writeSFixed32(int fieldNumber, int value) throws IOException {
+ writeTag(fieldNumber, WireFormat.WIRETYPE_FIXED32);
+ writeRawLittleEndian32(value);
+ }
+
+ /** Write an {@code sfixed64} field, including tag, to the stream. */
+ public void writeSFixed64(int fieldNumber, long value) throws IOException {
+ writeTag(fieldNumber, WireFormat.WIRETYPE_FIXED64);
+ writeRawLittleEndian64(value);
+ }
+
+ /** Write an {@code sint32} field, including tag, to the stream. */
+ public void writeSInt32(int fieldNumber, int value) throws IOException {
+ writeTag(fieldNumber, WireFormat.WIRETYPE_VARINT);
+ writeRawVarint32(encodeZigZag32(value));
+ }
+
+ /** Write an {@code sint64} field, including tag, to the stream. */
+ public void writeSInt64(int fieldNumber, long value) throws IOException {
+ writeTag(fieldNumber, WireFormat.WIRETYPE_VARINT);
+ writeRawVarint64(encodeZigZag64(value));
+ }
+
+ // =================================================================
+
+ /**
+ * Compute the number of bytes that would be needed to encode a {@code
+ * double} field, including tag.
+ */
+ public static int computeDoubleSize(int fieldNumber, double value) {
+ return computeTagSize(fieldNumber) + LITTLE_ENDIAN_64_SIZE;
+ }
+
+ /**
+ * Compute the number of bytes that would be needed to encode a {@code
+ * float} field, including tag.
+ */
+ public static int computeFloatSize(int fieldNumber, float value) {
+ return computeTagSize(fieldNumber) + LITTLE_ENDIAN_32_SIZE;
+ }
+
+ /**
+ * Compute the number of bytes that would be needed to encode a {@code
+ * uint64} field, including tag.
+ */
+ public static int computeUInt64Size(int fieldNumber, long value) {
+ return computeTagSize(fieldNumber) + computeRawVarint64Size(value);
+ }
+
+ /**
+ * Compute the number of bytes that would be needed to encode an {@code
+ * int64} field, including tag.
+ */
+ public static int computeInt64Size(int fieldNumber, long value) {
+ return computeTagSize(fieldNumber) + computeRawVarint64Size(value);
+ }
+
+ /**
+ * Compute the number of bytes that would be needed to encode an {@code
+ * int32} field, including tag.
+ */
+ public static int computeInt32Size(int fieldNumber, int value) {
+ if (value >= 0) {
+ return computeTagSize(fieldNumber) + computeRawVarint32Size(value);
+ } else {
+ // Must sign-extend.
+ return computeTagSize(fieldNumber) + 10;
+ }
+ }
+
+ /**
+ * Compute the number of bytes that would be needed to encode a {@code
+ * fixed64} field, including tag.
+ */
+ public static int computeFixed64Size(int fieldNumber, long value) {
+ return computeTagSize(fieldNumber) + LITTLE_ENDIAN_64_SIZE;
+ }
+
+ /**
+ * Compute the number of bytes that would be needed to encode a {@code
+ * fixed32} field, including tag.
+ */
+ public static int computeFixed32Size(int fieldNumber, int value) {
+ return computeTagSize(fieldNumber) + LITTLE_ENDIAN_32_SIZE;
+ }
+
+ /**
+ * Compute the number of bytes that would be needed to encode a {@code bool}
+ * field, including tag.
+ */
+ public static int computeBoolSize(int fieldNumber, boolean value) {
+ return computeTagSize(fieldNumber) + 1;
+ }
+
+ /**
+ * Compute the number of bytes that would be needed to encode a {@code
+ * string} field, including tag.
+ */
+ public static int computeStringSize(int fieldNumber, String value) {
+ try {
+ byte[] bytes = value.getBytes("UTF-8");
+ return computeTagSize(fieldNumber) + computeRawVarint32Size(bytes.length) + bytes.length;
+ } catch (java.io.UnsupportedEncodingException e) {
+ throw new RuntimeException("UTF-8 not supported.", e);
+ }
+ }
+
+ /**
+ * Compute the number of bytes that would be needed to encode a {@code
+ * bytes} field, including tag.
+ */
+ public static int computeBytesSize(int fieldNumber, ByteString value) {
+ return computeTagSize(fieldNumber) + computeRawVarint32Size(value.size()) + value.size();
+ }
+
+ /**
+ * Compute the number of bytes that would be needed to encode a {@code
+ * uint32} field, including tag.
+ */
+ public static int computeUInt32Size(int fieldNumber, int value) {
+ return computeTagSize(fieldNumber) + computeRawVarint32Size(value);
+ }
+
+ /**
+ * Compute the number of bytes that would be needed to encode an enum field,
+ * including tag. Caller is responsible for converting the enum value to its
+ * numeric value.
+ */
+ public static int computeEnumSize(int fieldNumber, int value) {
+ return computeTagSize(fieldNumber) + computeRawVarint32Size(value);
+ }
+
+ /**
+ * Compute the number of bytes that would be needed to encode an {@code
+ * sfixed32} field, including tag.
+ */
+ public static int computeSFixed32Size(int fieldNumber, int value) {
+ return computeTagSize(fieldNumber) + LITTLE_ENDIAN_32_SIZE;
+ }
+
+ /**
+ * Compute the number of bytes that would be needed to encode an {@code
+ * sfixed64} field, including tag.
+ */
+ public static int computeSFixed64Size(int fieldNumber, long value) {
+ return computeTagSize(fieldNumber) + LITTLE_ENDIAN_64_SIZE;
+ }
+
+ /**
+ * Compute the number of bytes that would be needed to encode an {@code
+ * sint32} field, including tag.
+ */
+ public static int computeSInt32Size(int fieldNumber, int value) {
+ return computeTagSize(fieldNumber) + computeRawVarint32Size(encodeZigZag32(value));
+ }
+
+ /**
+ * Compute the number of bytes that would be needed to encode an {@code
+ * sint64} field, including tag.
+ */
+ public static int computeSInt64Size(int fieldNumber, long value) {
+ return computeTagSize(fieldNumber) + computeRawVarint64Size(encodeZigZag64(value));
+ }
+
+ /** Write a single byte. */
+ public void writeRawByte(byte value) throws IOException {
+ out.write(value);
+ }
+
+ /** Write a single byte, represented by an integer value. */
+ public void writeRawByte(int value) throws IOException {
+ writeRawByte((byte) value);
+ }
+
+ /** Write an array of bytes. */
+ public void writeRawBytes(byte[] value) throws IOException {
+ writeRawBytes(value, 0, value.length);
+ }
+
+ /** Write part of an array of bytes. */
+ public void writeRawBytes(byte[] value, int offset, int length) throws IOException {
+ out.write(value, offset, length);
+ }
+
+ /** Encode and write a tag. */
+ public void writeTag(int fieldNumber, int wireType) throws IOException {
+ writeRawVarint32(WireFormat.makeTag(fieldNumber, wireType));
+ }
+
+ /** Compute the number of bytes that would be needed to encode a tag. */
+ public static int computeTagSize(int fieldNumber) {
+ return computeRawVarint32Size(WireFormat.makeTag(fieldNumber, 0));
+ }
+
+ /**
+ * Encode and write a varint. {@code value} is treated as unsigned, so it
+ * won't be sign-extended if negative.
+ */
+ public void writeRawVarint32(int value) throws IOException {
+ while (true) {
+ if ((value & ~0x7F) == 0) {
+ writeRawByte(value);
+ return;
+ } else {
+ writeRawByte((value & 0x7F) | 0x80);
+ value >>>= 7;
+ }
+ }
+ }
+
+ /**
+ * Compute the number of bytes that would be needed to encode a varint.
+ * {@code value} is treated as unsigned, so it won't be sign-extended if
+ * negative.
+ */
+ public static int computeRawVarint32Size(int value) {
+ if ((value & (0xffffffff << 7)) == 0)
+ return 1;
+ if ((value & (0xffffffff << 14)) == 0)
+ return 2;
+ if ((value & (0xffffffff << 21)) == 0)
+ return 3;
+ if ((value & (0xffffffff << 28)) == 0)
+ return 4;
+ return 5;
+ }
+
+ /** Encode and write a varint. */
+ public void writeRawVarint64(long value) throws IOException {
+ while (true) {
+ if ((value & ~0x7FL) == 0) {
+ writeRawByte((int) value);
+ return;
+ } else {
+ writeRawByte(((int) value & 0x7F) | 0x80);
+ value >>>= 7;
+ }
+ }
+ }
+
+ /** Compute the number of bytes that would be needed to encode a varint. */
+ public static int computeRawVarint64Size(long value) {
+ if ((value & (0xffffffffffffffffL << 7)) == 0)
+ return 1;
+ if ((value & (0xffffffffffffffffL << 14)) == 0)
+ return 2;
+ if ((value & (0xffffffffffffffffL << 21)) == 0)
+ return 3;
+ if ((value & (0xffffffffffffffffL << 28)) == 0)
+ return 4;
+ if ((value & (0xffffffffffffffffL << 35)) == 0)
+ return 5;
+ if ((value & (0xffffffffffffffffL << 42)) == 0)
+ return 6;
+ if ((value & (0xffffffffffffffffL << 49)) == 0)
+ return 7;
+ if ((value & (0xffffffffffffffffL << 56)) == 0)
+ return 8;
+ if ((value & (0xffffffffffffffffL << 63)) == 0)
+ return 9;
+ return 10;
+ }
+
+ /** Write a little-endian 32-bit integer. */
+ public void writeRawLittleEndian32(int value) throws IOException {
+ writeRawByte((value) & 0xFF);
+ writeRawByte((value >> 8) & 0xFF);
+ writeRawByte((value >> 16) & 0xFF);
+ writeRawByte((value >> 24) & 0xFF);
+ }
+
+ public static final int LITTLE_ENDIAN_32_SIZE = 4;
+
+ /** Write a little-endian 64-bit integer. */
+ public void writeRawLittleEndian64(long value) throws IOException {
+ writeRawByte((int) (value) & 0xFF);
+ writeRawByte((int) (value >> 8) & 0xFF);
+ writeRawByte((int) (value >> 16) & 0xFF);
+ writeRawByte((int) (value >> 24) & 0xFF);
+ writeRawByte((int) (value >> 32) & 0xFF);
+ writeRawByte((int) (value >> 40) & 0xFF);
+ writeRawByte((int) (value >> 48) & 0xFF);
+ writeRawByte((int) (value >> 56) & 0xFF);
+ }
+
+ public static final int LITTLE_ENDIAN_64_SIZE = 8;
+
+ /**
+ * Encode a ZigZag-encoded 32-bit value. ZigZag encodes signed integers into
+ * values that can be efficiently encoded with varint. (Otherwise, negative
+ * values must be sign-extended to 64 bits to be varint encoded, thus always
+ * taking 10 bytes on the wire.)
+ *
+ * @param n
+ * A signed 32-bit integer.
+ * @return An unsigned 32-bit integer, stored in a signed int because Java
+ * has no explicit unsigned support.
+ */
+ public static int encodeZigZag32(int n) {
+ // Note: the right-shift must be arithmetic
+ return (n << 1) ^ (n >> 31);
+ }
+
+ /**
+ * Encode a ZigZag-encoded 64-bit value. ZigZag encodes signed integers into
+ * values that can be efficiently encoded with varint. (Otherwise, negative
+ * values must be sign-extended to 64 bits to be varint encoded, thus always
+ * taking 10 bytes on the wire.)
+ *
+ * @param n
+ * A signed 64-bit integer.
+ * @return An unsigned 64-bit integer, stored in a signed int because Java
+ * has no explicit unsigned support.
+ */
+ public static long encodeZigZag64(long n) {
+ // Note: the right-shift must be arithmetic
+ return (n << 1) ^ (n >> 63);
+ }
-/**
-* Compute the number of bytes that would be needed to encode an
-* {@code int64} field, including tag.
-*/
-public static int computeInt64Size(int fieldNumber, long value) {
- return computeTagSize(fieldNumber) + computeRawVarint64Size(value);
-}
+ public void checkNoSpaceLeft() {
+ }
-/**
-* Compute the number of bytes that would be needed to encode an
-* {@code int32} field, including tag.
-*/
-public static int computeInt32Size(int fieldNumber, int value) {
- if (value >= 0) {
- return computeTagSize(fieldNumber) + computeRawVarint32Size(value);
- } else {
- // Must sign-extend.
- return computeTagSize(fieldNumber) + 10;
- }
-}
-
-/**
-* Compute the number of bytes that would be needed to encode a
-* {@code fixed64} field, including tag.
-*/
-public static int computeFixed64Size(int fieldNumber, long value) {
- return computeTagSize(fieldNumber) + LITTLE_ENDIAN_64_SIZE;
-}
-
-/**
-* Compute the number of bytes that would be needed to encode a
-* {@code fixed32} field, including tag.
-*/
-public static int computeFixed32Size(int fieldNumber, int value) {
- return computeTagSize(fieldNumber) + LITTLE_ENDIAN_32_SIZE;
-}
-
-/**
-* Compute the number of bytes that would be needed to encode a
-* {@code bool} field, including tag.
-*/
-public static int computeBoolSize(int fieldNumber, boolean value) {
- return computeTagSize(fieldNumber) + 1;
-}
-
-/**
-* Compute the number of bytes that would be needed to encode a
-* {@code string} field, including tag.
-*/
-public static int computeStringSize(int fieldNumber, String value) {
- try {
- byte[] bytes = value.getBytes("UTF-8");
- return computeTagSize(fieldNumber) +
- computeRawVarint32Size(bytes.length) +
- bytes.length;
- } catch (java.io.UnsupportedEncodingException e) {
- throw new RuntimeException("UTF-8 not supported.", e);
- }
-}
-
-/**
-* Compute the number of bytes that would be needed to encode a
-* {@code bytes} field, including tag.
-*/
-public static int computeBytesSize(int fieldNumber, ByteString value) {
- return computeTagSize(fieldNumber) +
- computeRawVarint32Size(value.size()) +
- value.size();
-}
-
-/**
-* Compute the number of bytes that would be needed to encode a
-* {@code uint32} field, including tag.
-*/
-public static int computeUInt32Size(int fieldNumber, int value) {
- return computeTagSize(fieldNumber) + computeRawVarint32Size(value);
-}
-
-/**
-* Compute the number of bytes that would be needed to encode an
-* enum field, including tag. Caller is responsible for converting the
-* enum value to its numeric value.
-*/
-public static int computeEnumSize(int fieldNumber, int value) {
- return computeTagSize(fieldNumber) + computeRawVarint32Size(value);
-}
-
-/**
-* Compute the number of bytes that would be needed to encode an
-* {@code sfixed32} field, including tag.
-*/
-public static int computeSFixed32Size(int fieldNumber, int value) {
- return computeTagSize(fieldNumber) + LITTLE_ENDIAN_32_SIZE;
-}
-
-/**
-* Compute the number of bytes that would be needed to encode an
-* {@code sfixed64} field, including tag.
-*/
-public static int computeSFixed64Size(int fieldNumber, long value) {
- return computeTagSize(fieldNumber) + LITTLE_ENDIAN_64_SIZE;
-}
-
-/**
-* Compute the number of bytes that would be needed to encode an
-* {@code sint32} field, including tag.
-*/
-public static int computeSInt32Size(int fieldNumber, int value) {
- return computeTagSize(fieldNumber) +
- computeRawVarint32Size(encodeZigZag32(value));
-}
-
-/**
-* Compute the number of bytes that would be needed to encode an
-* {@code sint64} field, including tag.
-*/
-public static int computeSInt64Size(int fieldNumber, long value) {
- return computeTagSize(fieldNumber) +
- computeRawVarint64Size(encodeZigZag64(value));
-}
-
-// =================================================================
-
-/**
-* Internal helper that writes the current buffer to the output. The
-* buffer position is reset to its initial value when this returns.
-*/
-private void refreshBuffer() throws IOException {
- if (output == null) {
- // We're writing to a single buffer.
- throw new OutOfSpaceException();
- }
-
- // Since we have an output stream, this is our buffer
- // and buffer offset == 0
- output.write(buffer, 0, position);
- position = 0;
-}
-
-/**
-* Flushes the stream and forces any buffered bytes to be written. This
-* does not flush the underlying OutputStream.
-*/
-public void flush() throws IOException {
- if (output != null) {
- refreshBuffer();
- }
-}
-
-/**
-* If writing to a flat array, return the space left in the array.
-* Otherwise, throws {@code UnsupportedOperationException}.
-*/
-public int spaceLeft() {
- if (output == null) {
- return limit - position;
- } else {
- throw new UnsupportedOperationException(
- "spaceLeft() can only be called on CodedOutputStreams that are " +
- "writing to a flat array.");
- }
-}
-
-/**
-* Verifies that {@link #spaceLeft()} returns zero. It's common to create
-* a byte array that is exactly big enough to hold a message, then write to
-* it with a {@code CodedOutputStream}. Calling {@code checkNoSpaceLeft()}
-* after writing verifies that the message was actually as big as expected,
-* which can help catch bugs.
-*/
-public void checkNoSpaceLeft() {
- if (spaceLeft() != 0) {
- throw new IllegalStateException(
- "Did not write as much data as expected.");
- }
-}
-
-/**
-* If you create a CodedOutputStream around a simple flat array, you must
-* not attempt to write more bytes than the array has space. Otherwise,
-* this exception will be thrown.
-*/
-public static class OutOfSpaceException extends IOException {
- OutOfSpaceException() {
- super("CodedOutputStream was writing to a flat byte array and ran " +
- "out of space.");
- }
-}
-
-/** Write a single byte. */
-public void writeRawByte(byte value) throws IOException {
- if (position == limit) {
- refreshBuffer();
- }
-
- buffer[position++] = value;
-}
-
-/** Write a single byte, represented by an integer value. */
-public void writeRawByte(int value) throws IOException {
- writeRawByte((byte) value);
-}
-
-/** Write an array of bytes. */
-public void writeRawBytes(byte[] value) throws IOException {
- writeRawBytes(value, 0, value.length);
-}
-
-/** Write part of an array of bytes. */
-public void writeRawBytes(byte[] value, int offset, int length)
- throws IOException {
- if (limit - position >= length) {
- // We have room in the current buffer.
- System.arraycopy(value, offset, buffer, position, length);
- position += length;
- } else {
- // Write extends past current buffer. Fill the rest of this buffer and
- // flush.
- int bytesWritten = limit - position;
- System.arraycopy(value, offset, buffer, position, bytesWritten);
- offset += bytesWritten;
- length -= bytesWritten;
- position = limit;
- refreshBuffer();
-
- // Now deal with the rest.
- // Since we have an output stream, this is our buffer
- // and buffer offset == 0
- if (length <= limit) {
- // Fits in new buffer.
- System.arraycopy(value, offset, buffer, 0, length);
- position = length;
- } else {
- // Write is very big. Let's do it all at once.
- output.write(value, offset, length);
- }
- }
-}
-
-/** Encode and write a tag. */
-public void writeTag(int fieldNumber, int wireType) throws IOException {
- writeRawVarint32(WireFormat.makeTag(fieldNumber, wireType));
-}
-
-/** Compute the number of bytes that would be needed to encode a tag. */
-public static int computeTagSize(int fieldNumber) {
- return computeRawVarint32Size(WireFormat.makeTag(fieldNumber, 0));
-}
-
-/**
-* Encode and write a varint. {@code value} is treated as
-* unsigned, so it won't be sign-extended if negative.
-*/
-public void writeRawVarint32(int value) throws IOException {
- while (true) {
- if ((value & ~0x7F) == 0) {
- writeRawByte(value);
- return;
- } else {
- writeRawByte((value & 0x7F) | 0x80);
- value >>>= 7;
- }
- }
-}
-
-/**
-* Compute the number of bytes that would be needed to encode a varint.
-* {@code value} is treated as unsigned, so it won't be sign-extended if
-* negative.
-*/
-public static int computeRawVarint32Size(int value) {
- if ((value & (0xffffffff << 7)) == 0) return 1;
- if ((value & (0xffffffff << 14)) == 0) return 2;
- if ((value & (0xffffffff << 21)) == 0) return 3;
- if ((value & (0xffffffff << 28)) == 0) return 4;
- return 5;
-}
-
-/** Encode and write a varint. */
-public void writeRawVarint64(long value) throws IOException {
- while (true) {
- if ((value & ~0x7FL) == 0) {
- writeRawByte((int)value);
- return;
- } else {
- writeRawByte(((int)value & 0x7F) | 0x80);
- value >>>= 7;
- }
- }
-}
-
-/** Compute the number of bytes that would be needed to encode a varint. */
-public static int computeRawVarint64Size(long value) {
- if ((value & (0xffffffffffffffffL << 7)) == 0) return 1;
- if ((value & (0xffffffffffffffffL << 14)) == 0) return 2;
- if ((value & (0xffffffffffffffffL << 21)) == 0) return 3;
- if ((value & (0xffffffffffffffffL << 28)) == 0) return 4;
- if ((value & (0xffffffffffffffffL << 35)) == 0) return 5;
- if ((value & (0xffffffffffffffffL << 42)) == 0) return 6;
- if ((value & (0xffffffffffffffffL << 49)) == 0) return 7;
- if ((value & (0xffffffffffffffffL << 56)) == 0) return 8;
- if ((value & (0xffffffffffffffffL << 63)) == 0) return 9;
- return 10;
-}
-
-/** Write a little-endian 32-bit integer. */
-public void writeRawLittleEndian32(int value) throws IOException {
- writeRawByte((value ) & 0xFF);
- writeRawByte((value >> 8) & 0xFF);
- writeRawByte((value >> 16) & 0xFF);
- writeRawByte((value >> 24) & 0xFF);
-}
-
-public static final int LITTLE_ENDIAN_32_SIZE = 4;
-
-/** Write a little-endian 64-bit integer. */
-public void writeRawLittleEndian64(long value) throws IOException {
- writeRawByte((int)(value ) & 0xFF);
- writeRawByte((int)(value >> 8) & 0xFF);
- writeRawByte((int)(value >> 16) & 0xFF);
- writeRawByte((int)(value >> 24) & 0xFF);
- writeRawByte((int)(value >> 32) & 0xFF);
- writeRawByte((int)(value >> 40) & 0xFF);
- writeRawByte((int)(value >> 48) & 0xFF);
- writeRawByte((int)(value >> 56) & 0xFF);
-}
-
-public static final int LITTLE_ENDIAN_64_SIZE = 8;
-
-/**
-* Encode a ZigZag-encoded 32-bit value. ZigZag encodes signed integers
-* into values that can be efficiently encoded with varint. (Otherwise,
-* negative values must be sign-extended to 64 bits to be varint encoded,
-* thus always taking 10 bytes on the wire.)
-*
-* @param n A signed 32-bit integer.
-* @return An unsigned 32-bit integer, stored in a signed int because
-* Java has no explicit unsigned support.
-*/
-public static int encodeZigZag32(int n) {
- // Note: the right-shift must be arithmetic
- return (n << 1) ^ (n >> 31);
-}
-
-/**
-* Encode a ZigZag-encoded 64-bit value. ZigZag encodes signed integers
-* into values that can be efficiently encoded with varint. (Otherwise,
-* negative values must be sign-extended to 64 bits to be varint encoded,
-* thus always taking 10 bytes on the wire.)
-*
-* @param n A signed 64-bit integer.
-* @return An unsigned 64-bit integer, stored in a signed int because
-* Java has no explicit unsigned support.
-*/
-public static long encodeZigZag64(long n) {
- // Note: the right-shift must be arithmetic
- return (n << 1) ^ (n >> 63);
-}
}