aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--editors/proto.vim2
-rw-r--r--java/src/main/java/com/google/protobuf/ByteString.java6
-rw-r--r--java/src/main/java/com/google/protobuf/Internal.java22
-rw-r--r--java/src/main/java/com/google/protobuf/TextFormat.java3
-rw-r--r--java/src/test/java/com/google/protobuf/TextFormatTest.java18
-rw-r--r--src/Makefile.am21
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_extension.h2
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_message.cc42
-rw-r--r--src/google/protobuf/compiler/main.cc6
-rw-r--r--src/google/protobuf/compiler/plugin.pb.cc9
-rw-r--r--src/google/protobuf/descriptor.pb.cc63
-rw-r--r--src/google/protobuf/dynamic_message.cc43
-rw-r--r--src/google/protobuf/dynamic_message_unittest.cc47
-rw-r--r--src/google/protobuf/generated_message_reflection.cc34
-rw-r--r--src/google/protobuf/generated_message_reflection.h17
-rw-r--r--src/google/protobuf/map.h13
-rw-r--r--src/google/protobuf/map_field.h7
-rw-r--r--src/google/protobuf/map_field_inl.h9
-rw-r--r--src/google/protobuf/map_test.cc21
-rw-r--r--src/google/protobuf/map_unittest.proto5
-rw-r--r--src/google/protobuf/no_field_presence_test.cc11
-rw-r--r--src/google/protobuf/unknown_field_set.h9
22 files changed, 333 insertions, 77 deletions
diff --git a/editors/proto.vim b/editors/proto.vim
index 7cd1dbf2..23085a28 100644
--- a/editors/proto.vim
+++ b/editors/proto.vim
@@ -54,7 +54,7 @@ syn keyword pbTodo contained TODO FIXME XXX
syn cluster pbCommentGrp contains=pbTodo
syn keyword pbSyntax syntax import option
-syn keyword pbStructure package message group
+syn keyword pbStructure package message group oneof
syn keyword pbRepeat optional required repeated
syn keyword pbDefault default
syn keyword pbExtend extend extensions to max
diff --git a/java/src/main/java/com/google/protobuf/ByteString.java b/java/src/main/java/com/google/protobuf/ByteString.java
index bd9c2b55..cff1ee51 100644
--- a/java/src/main/java/com/google/protobuf/ByteString.java
+++ b/java/src/main/java/com/google/protobuf/ByteString.java
@@ -503,9 +503,9 @@ public abstract class ByteString implements Iterable<Byte>, Serializable {
/**
* Internal (package private) implementation of
- * @link{#copyTo(byte[],int,int,int}.
+ * {@link #copyTo(byte[],int,int,int)}.
* It assumes that all error checking has already been performed and that
- * @code{numberToCopy > 0}.
+ * {@code numberToCopy > 0}.
*/
protected abstract void copyToInternal(byte[] target, int sourceOffset,
int targetOffset, int numberToCopy);
@@ -700,7 +700,7 @@ public abstract class ByteString implements Iterable<Byte>, Serializable {
* The {@link InputStream} returned by this method is guaranteed to be
* completely non-blocking. The method {@link InputStream#available()}
* returns the number of bytes remaining in the stream. The methods
- * {@link InputStream#read(byte[]), {@link InputStream#read(byte[],int,int)}
+ * {@link InputStream#read(byte[])}, {@link InputStream#read(byte[],int,int)}
* and {@link InputStream#skip(long)} will read/skip as many bytes as are
* available.
* <p>
diff --git a/java/src/main/java/com/google/protobuf/Internal.java b/java/src/main/java/com/google/protobuf/Internal.java
index 5ef39418..5a0de6d1 100644
--- a/java/src/main/java/com/google/protobuf/Internal.java
+++ b/java/src/main/java/com/google/protobuf/Internal.java
@@ -236,7 +236,7 @@ public class Internal {
}
/**
- * Helper method for implementing {@link MessageLite#hashCode()} for longs.
+ * Helper method for implementing {@link Message#hashCode()} for longs.
* @see Long#hashCode()
*/
public static int hashLong(long n) {
@@ -244,7 +244,7 @@ public class Internal {
}
/**
- * Helper method for implementing {@link MessageLite#hashCode()} for
+ * Helper method for implementing {@link Message#hashCode()} for
* booleans.
* @see Boolean#hashCode()
*/
@@ -253,7 +253,7 @@ public class Internal {
}
/**
- * Helper method for implementing {@link MessageLite#hashCode()} for enums.
+ * Helper method for implementing {@link Message#hashCode()} for enums.
* <p>
* This is needed because {@link java.lang.Enum#hashCode()} is final, but we
* need to use the field number as the hash code to ensure compatibility
@@ -264,7 +264,7 @@ public class Internal {
}
/**
- * Helper method for implementing {@link MessageLite#hashCode()} for
+ * Helper method for implementing {@link Message#hashCode()} for
* enum lists.
*/
public static int hashEnumList(List<? extends EnumLite> list) {
@@ -276,7 +276,7 @@ public class Internal {
}
/**
- * Helper method for implementing {@link MessageLite#equals()} for bytes field.
+ * Helper method for implementing {@link Message#equals(Object)} for bytes field.
*/
public static boolean equals(List<byte[]> a, List<byte[]> b) {
if (a.size() != b.size()) return false;
@@ -289,7 +289,7 @@ public class Internal {
}
/**
- * Helper method for implementing {@link MessageLite#hashCode()} for bytes field.
+ * Helper method for implementing {@link Message#hashCode()} for bytes field.
*/
public static int hashCode(List<byte[]> list) {
int hash = 1;
@@ -300,7 +300,7 @@ public class Internal {
}
/**
- * Helper method for implementing {@link MessageLite#hashCode()} for bytes field.
+ * Helper method for implementing {@link Message#hashCode()} for bytes field.
*/
public static int hashCode(byte[] bytes) {
// The hash code for a byte array should be the same as the hash code for a
@@ -311,7 +311,7 @@ public class Internal {
}
/**
- * Helper method for implementing {@link MessageLite#equals()} for bytes
+ * Helper method for implementing {@link Message#equals(Object)} for bytes
* field.
*/
public static boolean equalsByteBuffer(ByteBuffer a, ByteBuffer b) {
@@ -324,7 +324,7 @@ public class Internal {
}
/**
- * Helper method for implementing {@link MessageLite#equals()} for bytes
+ * Helper method for implementing {@link Message#equals(Object)} for bytes
* field.
*/
public static boolean equalsByteBuffer(
@@ -341,7 +341,7 @@ public class Internal {
}
/**
- * Helper method for implementing {@link MessageLite#hashCode()} for bytes
+ * Helper method for implementing {@link Message#hashCode()} for bytes
* field.
*/
public static int hashCodeByteBuffer(List<ByteBuffer> list) {
@@ -355,7 +355,7 @@ public class Internal {
private static final int DEFAULT_BUFFER_SIZE = 4096;
/**
- * Helper method for implementing {@link MessageLite#hashCode()} for bytes
+ * Helper method for implementing {@link Message#hashCode()} for bytes
* field.
*/
public static int hashCodeByteBuffer(ByteBuffer bytes) {
diff --git a/java/src/main/java/com/google/protobuf/TextFormat.java b/java/src/main/java/com/google/protobuf/TextFormat.java
index 63e62fc6..4f6756ed 100644
--- a/java/src/main/java/com/google/protobuf/TextFormat.java
+++ b/java/src/main/java/com/google/protobuf/TextFormat.java
@@ -411,7 +411,8 @@ public final class TextFormat {
generator.print("\"");
generator.print(escapeNonAscii ?
escapeText((String) value) :
- escapeDoubleQuotesAndBackslashes((String) value));
+ escapeDoubleQuotesAndBackslashes((String) value)
+ .replace("\n", "\\n"));
generator.print("\"");
break;
diff --git a/java/src/test/java/com/google/protobuf/TextFormatTest.java b/java/src/test/java/com/google/protobuf/TextFormatTest.java
index 82f9582f..eba06ca0 100644
--- a/java/src/test/java/com/google/protobuf/TextFormatTest.java
+++ b/java/src/test/java/com/google/protobuf/TextFormatTest.java
@@ -864,15 +864,15 @@ public class TextFormatTest extends TestCase {
assertEquals(message.getOptionalString(), builder.getOptionalString());
}
- public void testPrintToUnicodeStringWithNewlines() {
+ public void testPrintToUnicodeStringWithNewlines() throws Exception {
// No newlines at start and end
- assertEquals("optional_string: \"test newlines\n\nin\nstring\"\n",
+ assertEquals("optional_string: \"test newlines\\n\\nin\\nstring\"\n",
TextFormat.printToUnicodeString(TestAllTypes.newBuilder()
.setOptionalString("test newlines\n\nin\nstring")
.build()));
// Newlines at start and end
- assertEquals("optional_string: \"\ntest\nnewlines\n\nin\nstring\n\"\n",
+ assertEquals("optional_string: \"\\ntest\\nnewlines\\n\\nin\\nstring\\n\"\n",
TextFormat.printToUnicodeString(TestAllTypes.newBuilder()
.setOptionalString("\ntest\nnewlines\n\nin\nstring\n")
.build()));
@@ -882,14 +882,22 @@ public class TextFormatTest extends TestCase {
TextFormat.printToUnicodeString(TestAllTypes.newBuilder()
.setOptionalString("")
.build()));
- assertEquals("optional_string: \"\n\"\n",
+ assertEquals("optional_string: \"\\n\"\n",
TextFormat.printToUnicodeString(TestAllTypes.newBuilder()
.setOptionalString("\n")
.build()));
- assertEquals("optional_string: \"\n\n\"\n",
+ assertEquals("optional_string: \"\\n\\n\"\n",
TextFormat.printToUnicodeString(TestAllTypes.newBuilder()
.setOptionalString("\n\n")
.build()));
+
+ // Test escaping roundtrip
+ TestAllTypes message = TestAllTypes.newBuilder()
+ .setOptionalString("\ntest\nnewlines\n\nin\nstring\n")
+ .build();
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+ TextFormat.merge(TextFormat.printToUnicodeString(message), builder);
+ assertEquals(message.getOptionalString(), builder.getOptionalString());
}
public void testPrintToUnicodeString_unknown() {
diff --git a/src/Makefile.am b/src/Makefile.am
index 815c9ae9..b88e32ea 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -239,6 +239,27 @@ libprotoc_la_SOURCES = \
google/protobuf/compiler/java/java_string_field.h \
google/protobuf/compiler/java/java_doc_comment.cc \
google/protobuf/compiler/java/java_doc_comment.h \
+ google/protobuf/compiler/javanano/javanano_enum.cc \
+ google/protobuf/compiler/javanano/javanano_enum_field.h \
+ google/protobuf/compiler/javanano/javanano_extension.cc \
+ google/protobuf/compiler/javanano/javanano_field.cc \
+ google/protobuf/compiler/javanano/javanano_file.cc \
+ google/protobuf/compiler/javanano/javanano_generator.cc \
+ google/protobuf/compiler/javanano/javanano_helpers.cc \
+ google/protobuf/compiler/javanano/javanano_message.cc \
+ google/protobuf/compiler/javanano/javanano_message_field.h \
+ google/protobuf/compiler/javanano/javanano_params.h \
+ google/protobuf/compiler/javanano/javanano_primitive_field.h \
+ google/protobuf/compiler/javanano/javanano_enum_field.cc \
+ google/protobuf/compiler/javanano/javanano_enum.h \
+ google/protobuf/compiler/javanano/javanano_extension.h \
+ google/protobuf/compiler/javanano/javanano_field.h \
+ google/protobuf/compiler/javanano/javanano_file.h \
+ google/protobuf/compiler/javanano/javanano_generator.h \
+ google/protobuf/compiler/javanano/javanano_helpers.h \
+ google/protobuf/compiler/javanano/javanano_message_field.cc \
+ google/protobuf/compiler/javanano/javanano_message.h \
+ google/protobuf/compiler/javanano/javanano_primitive_field.cc \
google/protobuf/compiler/python/python_generator.cc
bin_PROGRAMS = protoc
diff --git a/src/google/protobuf/compiler/cpp/cpp_extension.h b/src/google/protobuf/compiler/cpp/cpp_extension.h
index d354c16a..1c1caf1f 100644
--- a/src/google/protobuf/compiler/cpp/cpp_extension.h
+++ b/src/google/protobuf/compiler/cpp/cpp_extension.h
@@ -57,7 +57,7 @@ namespace cpp {
class ExtensionGenerator {
public:
// See generator.cc for the meaning of dllexport_decl.
- explicit ExtensionGenerator(const FieldDescriptor* desycriptor,
+ explicit ExtensionGenerator(const FieldDescriptor* descriptor,
const Options& options);
~ExtensionGenerator();
diff --git a/src/google/protobuf/compiler/cpp/cpp_message.cc b/src/google/protobuf/compiler/cpp/cpp_message.cc
index b42f32b8..212bc3e9 100644
--- a/src/google/protobuf/compiler/cpp/cpp_message.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_message.cc
@@ -561,7 +561,7 @@ GenerateFieldAccessorDefinitions(io::Printer* printer) {
} else {
printer->Print(vars,
"inline bool $classname$::has_$name$() const {\n"
- " return $name$_ != NULL;\n"
+ " return !_is_default_instance_ && $name$_ != NULL;\n"
"}\n");
}
}
@@ -1051,6 +1051,22 @@ GenerateClassDefinition(io::Printer* printer) {
printer->Print(cached_size_decl.c_str());
need_to_emit_cached_size = false;
}
+ } else {
+ // Without field presence, we need another way to disambiguate the default
+ // instance, because the default instance's submessage fields (if any) store
+ // pointers to the default instances of the submessages even when they
+ // aren't present. Alternatives to this approach might be to (i) use a
+ // tagged pointer on all message fields, setting a tag bit for "not really
+ // present, just default instance"; or (ii) comparing |this| against the
+ // return value from GeneratedMessageFactory::GetPrototype() in all
+ // has_$field$() calls. However, both of these options are much more
+ // expensive (in code size and CPU overhead) than just checking a field in
+ // the message. Long-term, the best solution would be to rearchitect the
+ // default instance design not to store pointers to submessage default
+ // instances, and have reflection get those some other way; but that change
+ // would have too much impact on proto2.
+ printer->Print(
+ "bool _is_default_instance_;\n");
}
// Field members:
@@ -1323,11 +1339,21 @@ GenerateDescriptorInitializer(io::Printer* printer, int index) {
if (UseUnknownFieldSet(descriptor_->file())) {
printer->Print(vars,
" GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET("
- "$classname$, _internal_metadata_));\n");
+ "$classname$, _internal_metadata_),\n");
+ } else {
+ printer->Print(vars,
+ " GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET("
+ "$classname$, _arena_),\n");
+ }
+
+ // is_default_instance_ offset.
+ if (HasFieldPresence(descriptor_->file())) {
+ printer->Print(vars,
+ " -1);\n");
} else {
printer->Print(vars,
" GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET("
- "$classname$, _arena_));\n");
+ "$classname$, _is_default_instance_));\n");
}
// Handle nested types.
@@ -1612,6 +1638,11 @@ GenerateSharedConstructorCode(io::Printer* printer) {
"classname", classname_);
printer->Indent();
+ if (!HasFieldPresence(descriptor_->file())) {
+ printer->Print(
+ " _is_default_instance_ = false;\n");
+ }
+
printer->Print(StrCat(
uses_string_ ? "::google::protobuf::internal::GetEmptyString();\n" : "",
"_cached_size_ = 0;\n").c_str());
@@ -1809,6 +1840,11 @@ GenerateStructors(io::Printer* printer) {
"void $classname$::InitAsDefaultInstance() {\n",
"classname", classname_);
+ if (!HasFieldPresence(descriptor_->file())) {
+ printer->Print(
+ " _is_default_instance_ = true;\n");
+ }
+
// The default instance needs all of its embedded message pointers
// cross-linked to other default instances. We can't do this initialization
// in the constructor because some other default instances may not have been
diff --git a/src/google/protobuf/compiler/main.cc b/src/google/protobuf/compiler/main.cc
index 2f5bdaf7..9f2127bb 100644
--- a/src/google/protobuf/compiler/main.cc
+++ b/src/google/protobuf/compiler/main.cc
@@ -34,6 +34,7 @@
#include <google/protobuf/compiler/cpp/cpp_generator.h>
#include <google/protobuf/compiler/python/python_generator.h>
#include <google/protobuf/compiler/java/java_generator.h>
+#include <google/protobuf/compiler/javanano/javanano_generator.h>
int main(int argc, char* argv[]) {
@@ -57,5 +58,10 @@ int main(int argc, char* argv[]) {
cli.RegisterGenerator("--python_out", &py_generator,
"Generate Python source file.");
+ // Java Nano
+ google::protobuf::compiler::javanano::JavaNanoGenerator javanano_generator;
+ cli.RegisterGenerator("--javanano_out", &javanano_generator,
+ "Generate Java Nano source file.");
+
return cli.Run(argc, argv);
}
diff --git a/src/google/protobuf/compiler/plugin.pb.cc b/src/google/protobuf/compiler/plugin.pb.cc
index f33d716c..5118de15 100644
--- a/src/google/protobuf/compiler/plugin.pb.cc
+++ b/src/google/protobuf/compiler/plugin.pb.cc
@@ -56,7 +56,8 @@ void protobuf_AssignDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto() {
-1,
-1,
sizeof(CodeGeneratorRequest),
- GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(CodeGeneratorRequest, _internal_metadata_));
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(CodeGeneratorRequest, _internal_metadata_),
+ -1);
CodeGeneratorResponse_descriptor_ = file->message_type(1);
static const int CodeGeneratorResponse_offsets_[2] = {
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(CodeGeneratorResponse, error_),
@@ -71,7 +72,8 @@ void protobuf_AssignDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto() {
-1,
-1,
sizeof(CodeGeneratorResponse),
- GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(CodeGeneratorResponse, _internal_metadata_));
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(CodeGeneratorResponse, _internal_metadata_),
+ -1);
CodeGeneratorResponse_File_descriptor_ = CodeGeneratorResponse_descriptor_->nested_type(0);
static const int CodeGeneratorResponse_File_offsets_[3] = {
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(CodeGeneratorResponse_File, name_),
@@ -87,7 +89,8 @@ void protobuf_AssignDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto() {
-1,
-1,
sizeof(CodeGeneratorResponse_File),
- GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(CodeGeneratorResponse_File, _internal_metadata_));
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(CodeGeneratorResponse_File, _internal_metadata_),
+ -1);
}
namespace {
diff --git a/src/google/protobuf/descriptor.pb.cc b/src/google/protobuf/descriptor.pb.cc
index df214d44..97121fa9 100644
--- a/src/google/protobuf/descriptor.pb.cc
+++ b/src/google/protobuf/descriptor.pb.cc
@@ -111,7 +111,8 @@ void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto() {
-1,
-1,
sizeof(FileDescriptorSet),
- GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileDescriptorSet, _internal_metadata_));
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileDescriptorSet, _internal_metadata_),
+ -1);
FileDescriptorProto_descriptor_ = file->message_type(1);
static const int FileDescriptorProto_offsets_[12] = {
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileDescriptorProto, name_),
@@ -136,7 +137,8 @@ void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto() {
-1,
-1,
sizeof(FileDescriptorProto),
- GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileDescriptorProto, _internal_metadata_));
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileDescriptorProto, _internal_metadata_),
+ -1);
DescriptorProto_descriptor_ = file->message_type(2);
static const int DescriptorProto_offsets_[8] = {
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(DescriptorProto, name_),
@@ -157,7 +159,8 @@ void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto() {
-1,
-1,
sizeof(DescriptorProto),
- GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(DescriptorProto, _internal_metadata_));
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(DescriptorProto, _internal_metadata_),
+ -1);
DescriptorProto_ExtensionRange_descriptor_ = DescriptorProto_descriptor_->nested_type(0);
static const int DescriptorProto_ExtensionRange_offsets_[2] = {
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(DescriptorProto_ExtensionRange, start_),
@@ -172,7 +175,8 @@ void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto() {
-1,
-1,
sizeof(DescriptorProto_ExtensionRange),
- GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(DescriptorProto_ExtensionRange, _internal_metadata_));
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(DescriptorProto_ExtensionRange, _internal_metadata_),
+ -1);
FieldDescriptorProto_descriptor_ = file->message_type(3);
static const int FieldDescriptorProto_offsets_[9] = {
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FieldDescriptorProto, name_),
@@ -194,7 +198,8 @@ void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto() {
-1,
-1,
sizeof(FieldDescriptorProto),
- GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FieldDescriptorProto, _internal_metadata_));
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FieldDescriptorProto, _internal_metadata_),
+ -1);
FieldDescriptorProto_Type_descriptor_ = FieldDescriptorProto_descriptor_->enum_type(0);
FieldDescriptorProto_Label_descriptor_ = FieldDescriptorProto_descriptor_->enum_type(1);
OneofDescriptorProto_descriptor_ = file->message_type(4);
@@ -210,7 +215,8 @@ void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto() {
-1,
-1,
sizeof(OneofDescriptorProto),
- GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(OneofDescriptorProto, _internal_metadata_));
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(OneofDescriptorProto, _internal_metadata_),
+ -1);
EnumDescriptorProto_descriptor_ = file->message_type(5);
static const int EnumDescriptorProto_offsets_[3] = {
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(EnumDescriptorProto, name_),
@@ -226,7 +232,8 @@ void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto() {
-1,
-1,
sizeof(EnumDescriptorProto),
- GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(EnumDescriptorProto, _internal_metadata_));
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(EnumDescriptorProto, _internal_metadata_),
+ -1);
EnumValueDescriptorProto_descriptor_ = file->message_type(6);
static const int EnumValueDescriptorProto_offsets_[3] = {
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(EnumValueDescriptorProto, name_),
@@ -242,7 +249,8 @@ void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto() {
-1,
-1,
sizeof(EnumValueDescriptorProto),
- GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(EnumValueDescriptorProto, _internal_metadata_));
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(EnumValueDescriptorProto, _internal_metadata_),
+ -1);
ServiceDescriptorProto_descriptor_ = file->message_type(7);
static const int ServiceDescriptorProto_offsets_[3] = {
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(ServiceDescriptorProto, name_),
@@ -258,7 +266,8 @@ void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto() {
-1,
-1,
sizeof(ServiceDescriptorProto),
- GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(ServiceDescriptorProto, _internal_metadata_));
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(ServiceDescriptorProto, _internal_metadata_),
+ -1);
MethodDescriptorProto_descriptor_ = file->message_type(8);
static const int MethodDescriptorProto_offsets_[6] = {
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MethodDescriptorProto, name_),
@@ -277,7 +286,8 @@ void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto() {
-1,
-1,
sizeof(MethodDescriptorProto),
- GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MethodDescriptorProto, _internal_metadata_));
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MethodDescriptorProto, _internal_metadata_),
+ -1);
FileOptions_descriptor_ = file->message_type(9);
static const int FileOptions_offsets_[13] = {
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, java_package_),
@@ -303,7 +313,8 @@ void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto() {
-1,
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, _extensions_),
sizeof(FileOptions),
- GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, _internal_metadata_));
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, _internal_metadata_),
+ -1);
FileOptions_OptimizeMode_descriptor_ = FileOptions_descriptor_->enum_type(0);
MessageOptions_descriptor_ = file->message_type(10);
static const int MessageOptions_offsets_[5] = {
@@ -322,7 +333,8 @@ void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto() {
-1,
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MessageOptions, _extensions_),
sizeof(MessageOptions),
- GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MessageOptions, _internal_metadata_));
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MessageOptions, _internal_metadata_),
+ -1);
FieldOptions_descriptor_ = file->message_type(11);
static const int FieldOptions_offsets_[6] = {
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FieldOptions, ctype_),
@@ -341,7 +353,8 @@ void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto() {
-1,
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FieldOptions, _extensions_),
sizeof(FieldOptions),
- GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FieldOptions, _internal_metadata_));
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FieldOptions, _internal_metadata_),
+ -1);
FieldOptions_CType_descriptor_ = FieldOptions_descriptor_->enum_type(0);
EnumOptions_descriptor_ = file->message_type(12);
static const int EnumOptions_offsets_[3] = {
@@ -358,7 +371,8 @@ void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto() {
-1,
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(EnumOptions, _extensions_),
sizeof(EnumOptions),
- GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(EnumOptions, _internal_metadata_));
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(EnumOptions, _internal_metadata_),
+ -1);
EnumValueOptions_descriptor_ = file->message_type(13);
static const int EnumValueOptions_offsets_[2] = {
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(EnumValueOptions, deprecated_),
@@ -373,7 +387,8 @@ void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto() {
-1,
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(EnumValueOptions, _extensions_),
sizeof(EnumValueOptions),
- GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(EnumValueOptions, _internal_metadata_));
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(EnumValueOptions, _internal_metadata_),
+ -1);
ServiceOptions_descriptor_ = file->message_type(14);
static const int ServiceOptions_offsets_[2] = {
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(ServiceOptions, deprecated_),
@@ -388,7 +403,8 @@ void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto() {
-1,
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(ServiceOptions, _extensions_),
sizeof(ServiceOptions),
- GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(ServiceOptions, _internal_metadata_));
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(ServiceOptions, _internal_metadata_),
+ -1);
MethodOptions_descriptor_ = file->message_type(15);
static const int MethodOptions_offsets_[2] = {
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MethodOptions, deprecated_),
@@ -403,7 +419,8 @@ void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto() {
-1,
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MethodOptions, _extensions_),
sizeof(MethodOptions),
- GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MethodOptions, _internal_metadata_));
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MethodOptions, _internal_metadata_),
+ -1);
UninterpretedOption_descriptor_ = file->message_type(16);
static const int UninterpretedOption_offsets_[7] = {
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(UninterpretedOption, name_),
@@ -423,7 +440,8 @@ void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto() {
-1,
-1,
sizeof(UninterpretedOption),
- GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(UninterpretedOption, _internal_metadata_));
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(UninterpretedOption, _internal_metadata_),
+ -1);
UninterpretedOption_NamePart_descriptor_ = UninterpretedOption_descriptor_->nested_type(0);
static const int UninterpretedOption_NamePart_offsets_[2] = {
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(UninterpretedOption_NamePart, name_part_),
@@ -438,7 +456,8 @@ void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto() {
-1,
-1,
sizeof(UninterpretedOption_NamePart),
- GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(UninterpretedOption_NamePart, _internal_metadata_));
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(UninterpretedOption_NamePart, _internal_metadata_),
+ -1);
SourceCodeInfo_descriptor_ = file->message_type(17);
static const int SourceCodeInfo_offsets_[1] = {
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(SourceCodeInfo, location_),
@@ -452,7 +471,8 @@ void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto() {
-1,
-1,
sizeof(SourceCodeInfo),
- GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(SourceCodeInfo, _internal_metadata_));
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(SourceCodeInfo, _internal_metadata_),
+ -1);
SourceCodeInfo_Location_descriptor_ = SourceCodeInfo_descriptor_->nested_type(0);
static const int SourceCodeInfo_Location_offsets_[4] = {
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(SourceCodeInfo_Location, path_),
@@ -469,7 +489,8 @@ void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto() {
-1,
-1,
sizeof(SourceCodeInfo_Location),
- GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(SourceCodeInfo_Location, _internal_metadata_));
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(SourceCodeInfo_Location, _internal_metadata_),
+ -1);
}
namespace {
diff --git a/src/google/protobuf/dynamic_message.cc b/src/google/protobuf/dynamic_message.cc
index 565afaab..318ce6f9 100644
--- a/src/google/protobuf/dynamic_message.cc
+++ b/src/google/protobuf/dynamic_message.cc
@@ -218,6 +218,7 @@ class DynamicMessage : public Message {
int oneof_case_offset;
int unknown_fields_offset;
int extensions_offset;
+ int is_default_instance_offset;
// Not owned by the TypeInfo.
DynamicMessageFactory* factory; // The factory that created this object.
@@ -316,6 +317,11 @@ void DynamicMessage::SharedCtor() {
uint32(0);
}
+ if (type_info_->is_default_instance_offset != -1) {
+ *reinterpret_cast<bool*>(
+ OffsetToPointer(type_info_->is_default_instance_offset)) = false;
+ }
+
new(OffsetToPointer(type_info_->unknown_fields_offset)) UnknownFieldSet;
if (type_info_->extensions_offset != -1) {
@@ -532,6 +538,14 @@ void DynamicMessage::CrossLinkPrototypes() {
factory->GetPrototypeNoLock(field->message_type());
}
}
+
+ // Set as the default instance -- this affects field-presence semantics for
+ // proto3.
+ if (type_info_->is_default_instance_offset != -1) {
+ void* is_default_instance_ptr =
+ OffsetToPointer(type_info_->is_default_instance_offset);
+ *reinterpret_cast<bool*>(is_default_instance_ptr) = true;
+ }
}
Message* DynamicMessage::New() const {
@@ -641,11 +655,24 @@ const Message* DynamicMessageFactory::GetPrototypeNoLock(
size = AlignOffset(size);
// Next the has_bits, which is an array of uint32s.
- type_info->has_bits_offset = size;
- int has_bits_array_size =
- DivideRoundingUp(type->field_count(), bitsizeof(uint32));
- size += has_bits_array_size * sizeof(uint32);
- size = AlignOffset(size);
+ if (type->file()->syntax() == FileDescriptor::SYNTAX_PROTO3) {
+ type_info->has_bits_offset = -1;
+ } else {
+ type_info->has_bits_offset = size;
+ int has_bits_array_size =
+ DivideRoundingUp(type->field_count(), bitsizeof(uint32));
+ size += has_bits_array_size * sizeof(uint32);
+ size = AlignOffset(size);
+ }
+
+ // The is_default_instance member, if any.
+ if (type->file()->syntax() == FileDescriptor::SYNTAX_PROTO3) {
+ type_info->is_default_instance_offset = size;
+ size += sizeof(bool);
+ size = AlignOffset(size);
+ } else {
+ type_info->is_default_instance_offset = -1;
+ }
// The oneof_case, if any. It is an array of uint32s.
if (type->oneof_decl_count() > 0) {
@@ -731,7 +758,8 @@ const Message* DynamicMessageFactory::GetPrototypeNoLock(
type_info->pool,
this,
type_info->size,
- -1 /* arena_offset */));
+ -1 /* arena_offset */,
+ type_info->is_default_instance_offset));
} else {
type_info->reflection.reset(
new GeneratedMessageReflection(
@@ -744,7 +772,8 @@ const Message* DynamicMessageFactory::GetPrototypeNoLock(
type_info->pool,
this,
type_info->size,
- -1 /* arena_offset */));
+ -1 /* arena_offset */,
+ type_info->is_default_instance_offset));
}
// Cross link prototypes.
prototype->CrossLinkPrototypes();
diff --git a/src/google/protobuf/dynamic_message_unittest.cc b/src/google/protobuf/dynamic_message_unittest.cc
index 6353ecbf..522a092a 100644
--- a/src/google/protobuf/dynamic_message_unittest.cc
+++ b/src/google/protobuf/dynamic_message_unittest.cc
@@ -46,6 +46,7 @@
#include <google/protobuf/descriptor.pb.h>
#include <google/protobuf/test_util.h>
#include <google/protobuf/unittest.pb.h>
+#include <google/protobuf/unittest_no_field_presence.pb.h>
#include <google/protobuf/testing/googletest.h>
#include <gtest/gtest.h>
@@ -65,6 +66,8 @@ class DynamicMessageTest : public testing::Test {
const Message* packed_prototype_;
const Descriptor* oneof_descriptor_;
const Message* oneof_prototype_;
+ const Descriptor* proto3_descriptor_;
+ const Message* proto3_prototype_;
DynamicMessageTest(): factory_(&pool_) {}
@@ -76,16 +79,20 @@ class DynamicMessageTest : public testing::Test {
FileDescriptorProto unittest_file;
FileDescriptorProto unittest_import_file;
FileDescriptorProto unittest_import_public_file;
+ FileDescriptorProto unittest_no_field_presence_file;
unittest::TestAllTypes::descriptor()->file()->CopyTo(&unittest_file);
unittest_import::ImportMessage::descriptor()->file()->CopyTo(
&unittest_import_file);
unittest_import::PublicImportMessage::descriptor()->file()->CopyTo(
&unittest_import_public_file);
+ proto2_nofieldpresence_unittest::TestAllTypes::descriptor()->
+ file()->CopyTo(&unittest_no_field_presence_file);
ASSERT_TRUE(pool_.BuildFile(unittest_import_public_file) != NULL);
ASSERT_TRUE(pool_.BuildFile(unittest_import_file) != NULL);
ASSERT_TRUE(pool_.BuildFile(unittest_file) != NULL);
+ ASSERT_TRUE(pool_.BuildFile(unittest_no_field_presence_file) != NULL);
descriptor_ = pool_.FindMessageTypeByName("protobuf_unittest.TestAllTypes");
ASSERT_TRUE(descriptor_ != NULL);
@@ -105,6 +112,12 @@ class DynamicMessageTest : public testing::Test {
pool_.FindMessageTypeByName("protobuf_unittest.TestOneof2");
ASSERT_TRUE(oneof_descriptor_ != NULL);
oneof_prototype_ = factory_.GetPrototype(oneof_descriptor_);
+
+ proto3_descriptor_ =
+ pool_.FindMessageTypeByName(
+ "proto2_nofieldpresence_unittest.TestAllTypes");
+ ASSERT_TRUE(proto3_descriptor_ != NULL);
+ proto3_prototype_ = factory_.GetPrototype(proto3_descriptor_);
}
};
@@ -233,6 +246,40 @@ TEST_F(DynamicMessageTest, Arena) {
// Return without freeing: should not leak.
}
+TEST_F(DynamicMessageTest, Proto3) {
+ Message* message = proto3_prototype_->New();
+ const Reflection* refl = message->GetReflection();
+ const Descriptor* desc = message->GetDescriptor();
+
+ // Just test a single primtive and single message field here to make sure we
+ // are getting the no-field-presence semantics elsewhere. DynamicMessage uses
+ // GeneratedMessageReflection under the hood, so the rest should be fine as
+ // long as GMR recognizes that we're using a proto3 message.
+ const FieldDescriptor* optional_int32 =
+ desc->FindFieldByName("optional_int32");
+ const FieldDescriptor* optional_msg =
+ desc->FindFieldByName("optional_nested_message");
+ EXPECT_TRUE(optional_int32 != NULL);
+ EXPECT_TRUE(optional_msg != NULL);
+
+ EXPECT_EQ(false, refl->HasField(*message, optional_int32));
+ refl->SetInt32(message, optional_int32, 42);
+ EXPECT_EQ(true, refl->HasField(*message, optional_int32));
+ refl->SetInt32(message, optional_int32, 0);
+ EXPECT_EQ(false, refl->HasField(*message, optional_int32));
+
+ EXPECT_EQ(false, refl->HasField(*message, optional_msg));
+ refl->MutableMessage(message, optional_msg);
+ EXPECT_EQ(true, refl->HasField(*message, optional_msg));
+ delete refl->ReleaseMessage(message, optional_msg);
+ EXPECT_EQ(false, refl->HasField(*message, optional_msg));
+
+ // Also ensure that the default instance handles field presence properly.
+ EXPECT_EQ(false, refl->HasField(*proto3_prototype_, optional_msg));
+
+ delete message;
+}
+
} // namespace protobuf
} // namespace google
diff --git a/src/google/protobuf/generated_message_reflection.cc b/src/google/protobuf/generated_message_reflection.cc
index a20e362c..b4e98acd 100644
--- a/src/google/protobuf/generated_message_reflection.cc
+++ b/src/google/protobuf/generated_message_reflection.cc
@@ -193,7 +193,8 @@ GeneratedMessageReflection::GeneratedMessageReflection(
const DescriptorPool* descriptor_pool,
MessageFactory* factory,
int object_size,
- int arena_offset)
+ int arena_offset,
+ int is_default_instance_offset)
: descriptor_ (descriptor),
default_instance_ (default_instance),
offsets_ (offsets),
@@ -201,6 +202,7 @@ GeneratedMessageReflection::GeneratedMessageReflection(
unknown_fields_offset_(unknown_fields_offset),
extensions_offset_(extensions_offset),
arena_offset_ (arena_offset),
+ is_default_instance_offset_(is_default_instance_offset),
object_size_ (object_size),
descriptor_pool_ ((descriptor_pool == NULL) ?
DescriptorPool::generated_pool() :
@@ -220,7 +222,8 @@ GeneratedMessageReflection::GeneratedMessageReflection(
const DescriptorPool* descriptor_pool,
MessageFactory* factory,
int object_size,
- int arena_offset)
+ int arena_offset,
+ int is_default_instance_offset)
: descriptor_ (descriptor),
default_instance_ (default_instance),
default_oneof_instance_ (default_oneof_instance),
@@ -230,6 +233,7 @@ GeneratedMessageReflection::GeneratedMessageReflection(
unknown_fields_offset_(unknown_fields_offset),
extensions_offset_(extensions_offset),
arena_offset_ (arena_offset),
+ is_default_instance_offset_(is_default_instance_offset),
object_size_ (object_size),
descriptor_pool_ ((descriptor_pool == NULL) ?
DescriptorPool::generated_pool() :
@@ -1829,6 +1833,17 @@ GeneratedMessageReflection::MutableInternalMetadataWithArena(
return reinterpret_cast<InternalMetadataWithArena*>(ptr);
}
+inline bool
+GeneratedMessageReflection::GetIsDefaultInstance(
+ const Message& message) const {
+ if (is_default_instance_offset_ == kHasNoDefaultInstanceField) {
+ return false;
+ }
+ const void* ptr = reinterpret_cast<const uint8*>(&message) +
+ is_default_instance_offset_;
+ return *reinterpret_cast<const bool*>(ptr);
+}
+
// Simple accessors for manipulating has_bits_.
inline bool GeneratedMessageReflection::HasBit(
const Message& message, const FieldDescriptor* field) const {
@@ -1836,7 +1851,8 @@ inline bool GeneratedMessageReflection::HasBit(
// proto3: no has-bits. All fields present except messages, which are
// present only if their message-field pointer is non-NULL.
if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
- return GetRaw<const Message*>(message, field) != NULL;
+ return !GetIsDefaultInstance(message) &&
+ GetRaw<const Message*>(message, field) != NULL;
} else {
// Non-message field (and non-oneof, since that was handled in HasField()
// before calling us), and singular (again, checked in HasField). So, this
@@ -2082,7 +2098,8 @@ GeneratedMessageReflection::NewGeneratedMessageReflection(
const void* default_oneof_instance,
int oneof_case_offset,
int object_size,
- int arena_offset) {
+ int arena_offset,
+ int is_default_instance_offset) {
return new GeneratedMessageReflection(descriptor,
default_instance,
offsets,
@@ -2094,7 +2111,8 @@ GeneratedMessageReflection::NewGeneratedMessageReflection(
DescriptorPool::generated_pool(),
MessageFactory::generated_factory(),
object_size,
- arena_offset);
+ arena_offset,
+ is_default_instance_offset);
}
GeneratedMessageReflection*
@@ -2106,7 +2124,8 @@ GeneratedMessageReflection::NewGeneratedMessageReflection(
int unknown_fields_offset,
int extensions_offset,
int object_size,
- int arena_offset) {
+ int arena_offset,
+ int is_default_instance_offset) {
return new GeneratedMessageReflection(descriptor,
default_instance,
offsets,
@@ -2116,7 +2135,8 @@ GeneratedMessageReflection::NewGeneratedMessageReflection(
DescriptorPool::generated_pool(),
MessageFactory::generated_factory(),
object_size,
- arena_offset);
+ arena_offset,
+ is_default_instance_offset);
}
} // namespace internal
diff --git a/src/google/protobuf/generated_message_reflection.h b/src/google/protobuf/generated_message_reflection.h
index 306809da..4dddf6c7 100644
--- a/src/google/protobuf/generated_message_reflection.h
+++ b/src/google/protobuf/generated_message_reflection.h
@@ -136,7 +136,8 @@ class LIBPROTOBUF_EXPORT GeneratedMessageReflection : public Reflection {
const DescriptorPool* pool,
MessageFactory* factory,
int object_size,
- int arena_offset);
+ int arena_offset,
+ int is_default_instance_offset = -1);
// Similar with the construction above. Call this construction if the
// message has oneof definition.
@@ -173,7 +174,8 @@ class LIBPROTOBUF_EXPORT GeneratedMessageReflection : public Reflection {
const DescriptorPool* pool,
MessageFactory* factory,
int object_size,
- int arena_offset);
+ int arena_offset,
+ int is_default_instance_offset = -1);
~GeneratedMessageReflection();
// Shorter-to-call helpers for the above two constructions that work if the
@@ -190,7 +192,8 @@ class LIBPROTOBUF_EXPORT GeneratedMessageReflection : public Reflection {
const void* default_oneof_instance,
int oneof_case_offset,
int object_size,
- int arena_offset);
+ int arena_offset,
+ int is_default_instance_offset = -1);
static GeneratedMessageReflection* NewGeneratedMessageReflection(
const Descriptor* descriptor,
@@ -200,7 +203,8 @@ class LIBPROTOBUF_EXPORT GeneratedMessageReflection : public Reflection {
int unknown_fields_offset,
int extensions_offset,
int object_size,
- int arena_offset);
+ int arena_offset,
+ int is_default_instance_offset = -1);
// implements Reflection -------------------------------------------
@@ -414,8 +418,11 @@ class LIBPROTOBUF_EXPORT GeneratedMessageReflection : public Reflection {
int unknown_fields_offset_;
int extensions_offset_;
int arena_offset_;
+ int is_default_instance_offset_;
int object_size_;
+ static const int kHasNoDefaultInstanceField = -1;
+
const DescriptorPool* descriptor_pool_;
MessageFactory* message_factory_;
@@ -446,6 +453,8 @@ class LIBPROTOBUF_EXPORT GeneratedMessageReflection : public Reflection {
inline internal::InternalMetadataWithArena*
MutableInternalMetadataWithArena(Message* message) const;
+ inline bool GetIsDefaultInstance(const Message& message) const;
+
inline bool HasBit(const Message& message,
const FieldDescriptor* field) const;
inline void SetBit(Message* message,
diff --git a/src/google/protobuf/map.h b/src/google/protobuf/map.h
index e55a6d43..f6ae3e52 100644
--- a/src/google/protobuf/map.h
+++ b/src/google/protobuf/map.h
@@ -56,7 +56,7 @@ class MapField;
template <typename Key, typename T>
class MapPair {
public:
- typedef Key first_type;
+ typedef const Key first_type;
typedef T second_type;
MapPair(const Key& other_first, const T& other_second)
@@ -67,14 +67,13 @@ class MapPair {
MapPair(const MapPair& other)
: first(other.first), second(other.second) {}
- MapPair& operator=(const MapPair& other) {
- first = other.first;
- second = other.second;
- return *this;
- }
-
~MapPair() {}
+ // Implicitly convertible to std::pair.
+ operator std::pair<const Key, T>() const {
+ return std::pair<const Key, T>(first, second);
+ }
+
const Key first;
T second;
diff --git a/src/google/protobuf/map_field.h b/src/google/protobuf/map_field.h
index 4ceaf4a0..0fad1351 100644
--- a/src/google/protobuf/map_field.h
+++ b/src/google/protobuf/map_field.h
@@ -213,6 +213,13 @@ class LIBPROTOBUF_EXPORT MapField : public MapFieldBase {
mutable const EntryType* default_entry_;
};
+// True if IsInitialized() is true for value field in all elements of t. T is
+// expected to be message. It's useful to have this helper here to keep the
+// protobuf compiler from ever having to emit loops in IsInitialized() methods.
+// We want the C++ compiler to inline this or not as it sees fit.
+template <typename Key, typename T>
+bool AllAreInitialized(const Map<Key, T>& t);
+
} // namespace internal
} // namespace protobuf
diff --git a/src/google/protobuf/map_field_inl.h b/src/google/protobuf/map_field_inl.h
index 6f17df95..79302e48 100644
--- a/src/google/protobuf/map_field_inl.h
+++ b/src/google/protobuf/map_field_inl.h
@@ -262,6 +262,15 @@ void MapField<Key, T, KeyProto, ValueProto,
}
}
+template <typename Key, typename T>
+bool AllAreInitialized(const Map<Key, T>& t) {
+ for (typename Map<Key, T>::const_iterator it = t.begin(); it != t.end();
+ ++it) {
+ if (!it->second.IsInitialized()) return false;
+ }
+ return true;
+}
+
} // namespace internal
} // namespace protobuf
diff --git a/src/google/protobuf/map_test.cc b/src/google/protobuf/map_test.cc
index f9544efb..c680ccb2 100644
--- a/src/google/protobuf/map_test.cc
+++ b/src/google/protobuf/map_test.cc
@@ -544,6 +544,13 @@ TEST_F(MapImplTest, EqualRange) {
EXPECT_TRUE(const_map_.end() == const_range.second);
}
+TEST_F(MapImplTest, ConvertToStdMap) {
+ map_[100] = 101;
+ std::map<int32, int32> std_map(map_.begin(), map_.end());
+ EXPECT_EQ(1, std_map.size());
+ EXPECT_EQ(101, std_map[100]);
+}
+
// Map Field Reflection Test ========================================
static int Func(int i, int j) {
@@ -1740,6 +1747,20 @@ TEST(GeneratedMapFieldTest, MessageLiteMap) {
EXPECT_EQ(1, to.map_field().at(1));
}
+TEST(GeneratedMapFieldTest, IsInitialized) {
+ unittest::TestRequiredMessageMap map_message;
+
+ // Add an uninitialized message.
+ (*map_message.mutable_map_field())[0];
+ EXPECT_FALSE(map_message.IsInitialized());
+
+ // Initialize uninitialized message
+ (*map_message.mutable_map_field())[0].set_a(0);
+ (*map_message.mutable_map_field())[0].set_b(0);
+ (*map_message.mutable_map_field())[0].set_c(0);
+ EXPECT_TRUE(map_message.IsInitialized());
+}
+
// Generated Message Reflection Test ================================
TEST(GeneratedMapFieldReflectionTest, SpaceUsed) {
diff --git a/src/google/protobuf/map_unittest.proto b/src/google/protobuf/map_unittest.proto
index 54bc4486..9232d58f 100644
--- a/src/google/protobuf/map_unittest.proto
+++ b/src/google/protobuf/map_unittest.proto
@@ -75,3 +75,8 @@ enum MapEnum {
MAP_ENUM_BAR = 1;
MAP_ENUM_BAZ = 2;
}
+
+// Test embeded message with required fields
+message TestRequiredMessageMap {
+ map<int32, TestRequired> map_field = 1;
+}
diff --git a/src/google/protobuf/no_field_presence_test.cc b/src/google/protobuf/no_field_presence_test.cc
index f248327c..4b7b31d9 100644
--- a/src/google/protobuf/no_field_presence_test.cc
+++ b/src/google/protobuf/no_field_presence_test.cc
@@ -269,6 +269,10 @@ TEST(NoFieldPresenceTest, MessageFieldPresenceTest) {
EXPECT_EQ(true, message.has_optional_lazy_message());
message.clear_optional_lazy_message();
EXPECT_EQ(false, message.has_optional_lazy_message());
+
+ // Test field presence of a message field on the default instance.
+ EXPECT_EQ(false, proto2_nofieldpresence_unittest::TestAllTypes::
+ default_instance().has_optional_nested_message());
}
TEST(NoFieldPresenceTest, ReflectionHasFieldTest) {
@@ -287,6 +291,13 @@ TEST(NoFieldPresenceTest, ReflectionHasFieldTest) {
EXPECT_EQ(false, r->HasField(message, field));
}
+ // Test field presence of a message field on the default instance.
+ const google::protobuf::FieldDescriptor* msg_field =
+ desc->FindFieldByName("optional_nested_message");
+ EXPECT_EQ(false, r->HasField(
+ proto2_nofieldpresence_unittest::TestAllTypes::
+ default_instance(), msg_field));
+
// Fill all fields, expect everything to report true (check oneofs below).
FillValues(&message);
for (int i = 0; i < desc->field_count(); i++) {
diff --git a/src/google/protobuf/unknown_field_set.h b/src/google/protobuf/unknown_field_set.h
index 6f7a9fdb..e8c0a13c 100644
--- a/src/google/protobuf/unknown_field_set.h
+++ b/src/google/protobuf/unknown_field_set.h
@@ -224,13 +224,16 @@ class LIBPROTOBUF_EXPORT UnknownField {
uint32 number_;
uint32 type_;
+
+ union LengthDelimited {
+ string* string_value_;
+ };
+
union {
uint64 varint_;
uint32 fixed32_;
uint64 fixed64_;
- mutable union {
- string* string_value_;
- } length_delimited_;
+ mutable union LengthDelimited length_delimited_;
UnknownFieldSet* group_;
};
};