diff options
Diffstat (limited to 'src/google/protobuf/reflection_ops.cc')
-rw-r--r-- | src/google/protobuf/reflection_ops.cc | 51 |
1 files changed, 43 insertions, 8 deletions
diff --git a/src/google/protobuf/reflection_ops.cc b/src/google/protobuf/reflection_ops.cc index bb9c7f8b..3cd50340 100644 --- a/src/google/protobuf/reflection_ops.cc +++ b/src/google/protobuf/reflection_ops.cc @@ -31,13 +31,16 @@ // Author: kenton@google.com (Kenton Varda) // Based on original Protocol Buffers design by // Sanjay Ghemawat, Jeff Dean, and others. +#include <google/protobuf/reflection_ops.h> #include <string> #include <vector> -#include <google/protobuf/reflection_ops.h> -#include <google/protobuf/descriptor.h> +#include <google/protobuf/stubs/logging.h> +#include <google/protobuf/stubs/common.h> #include <google/protobuf/descriptor.pb.h> +#include <google/protobuf/descriptor.h> +#include <google/protobuf/map_field.h> #include <google/protobuf/unknown_field_set.h> #include <google/protobuf/stubs/strutil.h> @@ -45,6 +48,17 @@ namespace google { namespace protobuf { namespace internal { +static const Reflection* GetReflectionOrDie(const Message& m) { + const Reflection* r = m.GetReflection(); + if (r == nullptr) { + const Descriptor* d = m.GetDescriptor(); + const string& mtype = d ? d->name() : "unknown"; + // RawMessage is one known type for which GetReflection() returns nullptr. + GOOGLE_LOG(FATAL) << "Message does not support reflection (type " << mtype << ")."; + } + return r; +} + void ReflectionOps::Copy(const Message& from, Message* to) { if (&from == to) return; Clear(to); @@ -60,8 +74,8 @@ void ReflectionOps::Merge(const Message& from, Message* to) { << "(merge " << descriptor->full_name() << " to " << to->GetDescriptor()->full_name() << ")"; - const Reflection* from_reflection = from.GetReflection(); - const Reflection* to_reflection = to->GetReflection(); + const Reflection* from_reflection = GetReflectionOrDie(from); + const Reflection* to_reflection = GetReflectionOrDie(*to); std::vector<const FieldDescriptor*> fields; from_reflection->ListFields(from, &fields); @@ -127,7 +141,7 @@ void ReflectionOps::Merge(const Message& from, Message* to) { } void ReflectionOps::Clear(Message* message) { - const Reflection* reflection = message->GetReflection(); + const Reflection* reflection = GetReflectionOrDie(*message); std::vector<const FieldDescriptor*> fields; reflection->ListFields(*message, &fields); @@ -140,7 +154,7 @@ void ReflectionOps::Clear(Message* message) { bool ReflectionOps::IsInitialized(const Message& message) { const Descriptor* descriptor = message.GetDescriptor(); - const Reflection* reflection = message.GetReflection(); + const Reflection* reflection = GetReflectionOrDie(message); // Check required fields of this message. for (int i = 0; i < descriptor->field_count(); i++) { @@ -158,6 +172,27 @@ bool ReflectionOps::IsInitialized(const Message& message) { const FieldDescriptor* field = fields[i]; if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { + if (field->is_map()) { + const FieldDescriptor* value_field = field->message_type()->field(1); + if (value_field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { + MapFieldBase* map_field = + reflection->MapData(const_cast<Message*>(&message), field); + if (map_field->IsMapValid()) { + MapIterator iter(const_cast<Message*>(&message), field); + MapIterator end(const_cast<Message*>(&message), field); + for (map_field->MapBegin(&iter), map_field->MapEnd(&end); + iter != end; ++iter) { + if (!iter.GetValueRef().GetMessageValue().IsInitialized()) { + return false; + } + } + continue; + } + } else { + continue; + } + } + if (field->is_repeated()) { int size = reflection->FieldSize(message, field); @@ -179,7 +214,7 @@ bool ReflectionOps::IsInitialized(const Message& message) { } void ReflectionOps::DiscardUnknownFields(Message* message) { - const Reflection* reflection = message->GetReflection(); + const Reflection* reflection = GetReflectionOrDie(*message); reflection->MutableUnknownFields(message)->Clear(); @@ -226,7 +261,7 @@ void ReflectionOps::FindInitializationErrors( const string& prefix, std::vector<string>* errors) { const Descriptor* descriptor = message.GetDescriptor(); - const Reflection* reflection = message.GetReflection(); + const Reflection* reflection = GetReflectionOrDie(message); // Check required fields of this message. for (int i = 0; i < descriptor->field_count(); i++) { |