diff options
author | kenton@google.com <kenton@google.com@630680e5-0e50-0410-840e-4b1c322b438d> | 2008-11-21 00:06:27 +0000 |
---|---|---|
committer | kenton@google.com <kenton@google.com@630680e5-0e50-0410-840e-4b1c322b438d> | 2008-11-21 00:06:27 +0000 |
commit | 26bd9eee6ee6d116e1cc0dedeb660cd69d7aac45 (patch) | |
tree | d35cca89e0da44f136090a554ff9abc93a794fa8 /java/src/main | |
parent | a2a32c20434807e9966e3f48375f9419134d1b55 (diff) | |
download | protobuf-26bd9eee6ee6d116e1cc0dedeb660cd69d7aac45.tar.gz protobuf-26bd9eee6ee6d116e1cc0dedeb660cd69d7aac45.tar.bz2 protobuf-26bd9eee6ee6d116e1cc0dedeb660cd69d7aac45.zip |
Integrate changes from internal code.
protoc
* Enum values may now have custom options, using syntax similar to field
options.
* Fixed bug where .proto files which use custom options but don't actually
define them (i.e. they import another .proto file defining the options)
had to explicitly import descriptor.proto.
* Adjacent string literals in .proto files will now be concatenated, like in
C.
C++
* Generated message classes now have a Swap() method which efficiently swaps
the contents of two objects.
* All message classes now have a SpaceUsed() method which returns an estimate
of the number of bytes of allocated memory currently owned by the object.
This is particularly useful when you are reusing a single message object
to improve performance but want to make sure it doesn't bloat up too large.
* New method Message::SerializeAsString() returns a string containing the
serialized data. May be more convenient than calling
SerializeToString(string*).
* In debug mode, log error messages when string-type fields are found to
contain bytes that are not valid UTF-8.
* Fixed bug where a message with multiple extension ranges couldn't parse
extensions.
* Fixed bug where MergeFrom(const Message&) didn't do anything if invoked on
a message that contained no fields (but possibly contained extensions).
* Fixed ShortDebugString() to not be O(n^2). Durr.
* Fixed crash in TextFormat parsing if the first token in the input caused a
tokenization error.
Java
* New overload of mergeFrom() which parses a slice of a byte array instead
of the whole thing.
* New method ByteString.asReadOnlyByteBuffer() does what it sounds like.
* Improved performance of isInitialized() when optimizing for code size.
Python
* Corrected ListFields() signature in Message base class to match what
subclasses actually implement.
* Some minor refactoring.
Diffstat (limited to 'java/src/main')
5 files changed, 88 insertions, 7 deletions
diff --git a/java/src/main/java/com/google/protobuf/AbstractMessage.java b/java/src/main/java/com/google/protobuf/AbstractMessage.java index 51c6e783..2f61859d 100644 --- a/java/src/main/java/com/google/protobuf/AbstractMessage.java +++ b/java/src/main/java/com/google/protobuf/AbstractMessage.java @@ -77,6 +77,7 @@ public abstract class AbstractMessage implements Message { return true; } + @Override public final String toString() { return TextFormat.printToString(this); } @@ -199,6 +200,7 @@ public abstract class AbstractMessage implements Message { public static abstract class Builder<BuilderType extends Builder> implements Message.Builder { // The compiler produces an error if this is not declared explicitly. + @Override public abstract BuilderType clone(); public BuilderType clear() { @@ -307,8 +309,13 @@ public abstract class AbstractMessage implements Message { public BuilderType mergeFrom(byte[] data) throws InvalidProtocolBufferException { + return mergeFrom(data, 0, data.length); + } + + public BuilderType mergeFrom(byte[] data, int off, int len) + throws InvalidProtocolBufferException { try { - CodedInputStream input = CodedInputStream.newInstance(data); + CodedInputStream input = CodedInputStream.newInstance(data, off, len); mergeFrom(input); input.checkLastTagWas(0); return (BuilderType) this; @@ -322,10 +329,18 @@ public abstract class AbstractMessage implements Message { } public BuilderType mergeFrom( - byte[] data, ExtensionRegistry extensionRegistry) + byte[] data, + ExtensionRegistry extensionRegistry) + throws InvalidProtocolBufferException { + return mergeFrom(data, 0, data.length, extensionRegistry); + } + + public BuilderType mergeFrom( + byte[] data, int off, int len, + ExtensionRegistry extensionRegistry) throws InvalidProtocolBufferException { try { - CodedInputStream input = CodedInputStream.newInstance(data); + CodedInputStream input = CodedInputStream.newInstance(data, off, len); mergeFrom(input, extensionRegistry); input.checkLastTagWas(0); return (BuilderType) this; diff --git a/java/src/main/java/com/google/protobuf/ByteString.java b/java/src/main/java/com/google/protobuf/ByteString.java index 9814dfc1..f376e7a1 100644 --- a/java/src/main/java/com/google/protobuf/ByteString.java +++ b/java/src/main/java/com/google/protobuf/ByteString.java @@ -35,6 +35,7 @@ import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.FilterOutputStream; import java.io.UnsupportedEncodingException; +import java.nio.ByteBuffer; /** * Immutable array of bytes. @@ -154,6 +155,15 @@ public final class ByteString { } /** + * Constructs a new read-only {@code java.nio.ByteBuffer} with the + * same backing byte array. + */ + public ByteBuffer asReadOnlyByteBuffer() { + ByteBuffer byteBuffer = ByteBuffer.wrap(this.bytes); + return byteBuffer.asReadOnlyBuffer(); + } + + /** * Constructs a new {@code String} by decoding the bytes using the * specified charset. */ diff --git a/java/src/main/java/com/google/protobuf/CodedInputStream.java b/java/src/main/java/com/google/protobuf/CodedInputStream.java index c956ed2b..caef068b 100644 --- a/java/src/main/java/com/google/protobuf/CodedInputStream.java +++ b/java/src/main/java/com/google/protobuf/CodedInputStream.java @@ -59,7 +59,14 @@ public final class CodedInputStream { * Create a new CodedInputStream wrapping the given byte array. */ public static CodedInputStream newInstance(byte[] buf) { - return new CodedInputStream(buf); + return newInstance(buf, 0, buf.length); + } + + /** + * Create a new CodedInputStream wrapping the given byte array slice. + */ + public static CodedInputStream newInstance(byte[] buf, int off, int len) { + return new CodedInputStream(buf, off, len); } // ----------------------------------------------------------------- @@ -454,7 +461,7 @@ public final class CodedInputStream { private byte[] buffer; private int bufferSize; private int bufferSizeAfterLimit = 0; - private int bufferPos = 0; + private int bufferPos; private InputStream input; private int lastTag = 0; @@ -479,15 +486,17 @@ public final class CodedInputStream { private static final int DEFAULT_SIZE_LIMIT = 64 << 20; // 64MB private static final int BUFFER_SIZE = 4096; - private CodedInputStream(byte[] buffer) { + private CodedInputStream(byte[] buffer, int off, int len) { this.buffer = buffer; - this.bufferSize = buffer.length; + this.bufferSize = off + len; + this.bufferPos = off; this.input = null; } private CodedInputStream(InputStream input) { this.buffer = new byte[BUFFER_SIZE]; this.bufferSize = 0; + this.bufferPos = 0; this.input = input; } diff --git a/java/src/main/java/com/google/protobuf/GeneratedMessage.java b/java/src/main/java/com/google/protobuf/GeneratedMessage.java index bc231a15..b1be8b14 100644 --- a/java/src/main/java/com/google/protobuf/GeneratedMessage.java +++ b/java/src/main/java/com/google/protobuf/GeneratedMessage.java @@ -87,6 +87,33 @@ public abstract class GeneratedMessage extends AbstractMessage { } return result; } + + public boolean isInitialized() { + for (FieldDescriptor field : getDescriptorForType().getFields()) { + // Check that all required fields are present. + if (field.isRequired()) { + if (!hasField(field)) { + return false; + } + } + // Check that embedded messages are initialized. + if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) { + if (field.isRepeated()) { + for (Message element : (List<Message>) getField(field)) { + if (!element.isInitialized()) { + return false; + } + } + } else { + if (hasField(field) && !((Message) getField(field)).isInitialized()) { + return false; + } + } + } + } + + return true; + } public Map<FieldDescriptor, Object> getAllFields() { return Collections.unmodifiableMap(getAllFieldsMutable()); @@ -370,6 +397,10 @@ public abstract class GeneratedMessage extends AbstractMessage { protected boolean extensionsAreInitialized() { return extensions.isInitialized(); } + + public boolean isInitialized() { + return super.isInitialized() && extensionsAreInitialized(); + } /** * Used by subclasses to serialize extensions. Extension ranges may be diff --git a/java/src/main/java/com/google/protobuf/Message.java b/java/src/main/java/com/google/protobuf/Message.java index add5dab6..9635387a 100644 --- a/java/src/main/java/com/google/protobuf/Message.java +++ b/java/src/main/java/com/google/protobuf/Message.java @@ -400,6 +400,13 @@ public interface Message { /** * Parse {@code data} as a message of this type and merge it with the * message being built. This is just a small wrapper around + * {@link #mergeFrom(CodedInputStream)}. + */ + public Builder mergeFrom(byte[] data, int off, int len) throws InvalidProtocolBufferException; + + /** + * Parse {@code data} as a message of this type and merge it with the + * message being built. This is just a small wrapper around * {@link #mergeFrom(CodedInputStream,ExtensionRegistry)}. */ Builder mergeFrom(byte[] data, @@ -407,6 +414,15 @@ public interface Message { throws InvalidProtocolBufferException; /** + * Parse {@code data} as a message of this type and merge it with the + * message being built. This is just a small wrapper around + * {@link #mergeFrom(CodedInputStream,ExtensionRegistry)}. + */ + Builder mergeFrom(byte[] data, int off, int len, + ExtensionRegistry extensionRegistry) + throws InvalidProtocolBufferException; + + /** * Parse a message of this type from {@code input} and merge it with the * message being built. This is just a small wrapper around * {@link #mergeFrom(CodedInputStream)}. Note that this method always |