// Protocol Buffers - Google's data interchange format // Copyright 2008 Google Inc. All rights reserved. // https://developers.google.com/protocol-buffers/ // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // Author: kenton@google.com (Kenton Varda) // Based on original Protocol Buffers design by // Sanjay Ghemawat, Jeff Dean, and others. #include #include #include #include #include #include #include #include #include #include // Must be included last. #include 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 std::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); Merge(from, to); } void ReflectionOps::Merge(const Message& from, Message* to) { GOOGLE_CHECK_NE(&from, to); const Descriptor* descriptor = from.GetDescriptor(); GOOGLE_CHECK_EQ(to->GetDescriptor(), descriptor) << "Tried to merge messages of different types " << "(merge " << descriptor->full_name() << " to " << to->GetDescriptor()->full_name() << ")"; const Reflection* from_reflection = GetReflectionOrDie(from); const Reflection* to_reflection = GetReflectionOrDie(*to); bool is_from_generated = (from_reflection->GetMessageFactory() == google::protobuf::MessageFactory::generated_factory()); bool is_to_generated = (to_reflection->GetMessageFactory() == google::protobuf::MessageFactory::generated_factory()); std::vector fields; from_reflection->ListFieldsOmitStripped(from, &fields); for (const FieldDescriptor* field : fields) { if (field->is_repeated()) { // Use map reflection if both are in map status and have the // same map type to avoid sync with repeated field. // Note: As from and to messages have the same descriptor, the // map field types are the same if they are both generated // messages or both dynamic messages. if (is_from_generated == is_to_generated && field->is_map()) { const MapFieldBase* from_field = from_reflection->GetMapData(from, field); MapFieldBase* to_field = to_reflection->MutableMapData(to, field); if (to_field->IsMapValid() && from_field->IsMapValid()) { to_field->MergeFrom(*from_field); continue; } } int count = from_reflection->FieldSize(from, field); for (int j = 0; j < count; j++) { switch (field->cpp_type()) { #define HANDLE_TYPE(CPPTYPE, METHOD) \ case FieldDescriptor::CPPTYPE_##CPPTYPE: \ to_reflection->Add##METHOD( \ to, field, from_reflection->GetRepeated##METHOD(from, field, j)); \ break; HANDLE_TYPE(INT32, Int32); HANDLE_TYPE(INT64, Int64); HANDLE_TYPE(UINT32, UInt32); HANDLE_TYPE(UINT64, UInt64); HANDLE_TYPE(FLOAT, Float); HANDLE_TYPE(DOUBLE, Double); HANDLE_TYPE(BOOL, Bool); HANDLE_TYPE(STRING, String); HANDLE_TYPE(ENUM, Enum); #undef HANDLE_TYPE case FieldDescriptor::CPPTYPE_MESSAGE: const Message& from_child = from_reflection->GetRepeatedMessage(from, field, j); if (from_reflection == to_reflection) { to_reflection ->AddMessage(to, field, from_child.GetReflection()->GetMessageFactory()) ->MergeFrom(from_child); } else { to_reflection->AddMessage(to, field)->MergeFrom(from_child); } break; } } } else { switch (field->cpp_type()) { #define HANDLE_TYPE(CPPTYPE, METHOD) \ case FieldDescriptor::CPPTYPE_##CPPTYPE: \ to_reflection->Set##METHOD(to, field, \ from_reflection->Get##METHOD(from, field)); \ break; HANDLE_TYPE(INT32, Int32); HANDLE_TYPE(INT64, Int64); HANDLE_TYPE(UINT32, UInt32); HANDLE_TYPE(UINT64, UInt64); HANDLE_TYPE(FLOAT, Float); HANDLE_TYPE(DOUBLE, Double); HANDLE_TYPE(BOOL, Bool); HANDLE_TYPE(STRING, String); HANDLE_TYPE(ENUM, Enum); #undef HANDLE_TYPE case FieldDescriptor::CPPTYPE_MESSAGE: const Message& from_child = from_reflection->GetMessage(from, field); if (from_reflection == to_reflection) { to_reflection ->MutableMessage( to, field, from_child.GetReflection()->GetMessageFactory()) ->MergeFrom(from_child); } else { to_reflection->MutableMessage(to, field)->MergeFrom(from_child); } break; } } } if (!from_reflection->GetUnknownFields(from).empty()) { to_reflection->MutableUnknownFields(to)->MergeFrom( from_reflection->GetUnknownFields(from)); } } void ReflectionOps::Clear(Message* message) { const Reflection* reflection = GetReflectionOrDie(*message); std::vector fields; reflection->ListFieldsOmitStripped(*message, &fields); for (const FieldDescriptor* field : fields) { reflection->ClearField(message, field); } if (reflection->GetInternalMetadata(*message).have_unknown_fields()) { reflection->MutableUnknownFields(message)->Clear(); } } bool ReflectionOps::IsInitialized(const Message& message, bool check_fields, bool check_descendants) { const Descriptor* descriptor = message.GetDescriptor(); const Reflection* reflection = GetReflectionOrDie(message); if (const int field_count = descriptor->field_count()) { const FieldDescriptor* begin = descriptor->field(0); const FieldDescriptor* end = begin + field_count; GOOGLE_DCHECK_EQ(descriptor->field(field_count - 1), end - 1); if (check_fields) { // Check required fields of this message. for (const FieldDescriptor* field = begin; field != end; ++field) { if (field->is_required() && !reflection->HasField(message, field)) { return false; } } } if (check_descendants) { for (const FieldDescriptor* field = begin; field != end; ++field) { if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { const Descriptor* message_type = field->message_type(); if (PROTOBUF_PREDICT_FALSE(message_type->options().map_entry())) { if (message_type->field(1)->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { const MapFieldBase* map_field = reflection->GetMapData(message, field); if (map_field->IsMapValid()) { MapIterator it(const_cast(&message), field); MapIterator end_map(const_cast(&message), field); for (map_field->MapBegin(&it), map_field->MapEnd(&end_map); it != end_map; ++it) { if (!it.GetValueRef().GetMessageValue().IsInitialized()) { return false; } } } } } else if (field->is_repeated()) { const int size = reflection->FieldSize(message, field); for (int j = 0; j < size; j++) { if (!reflection->GetRepeatedMessage(message, field, j) .IsInitialized()) { return false; } } } else if (reflection->HasField(message, field)) { if (!reflection->GetMessage(message, field).IsInitialized()) { return false; } } } } } } if (check_descendants && reflection->HasExtensionSet(message) && !reflection->GetExtensionSet(message).IsInitialized()) { return false; } return true; } bool ReflectionOps::IsInitialized(const Message& message) { const Descriptor* descriptor = message.GetDescriptor(); const Reflection* reflection = GetReflectionOrDie(message); // Check required fields of this message. { const int field_count = descriptor->field_count(); for (int i = 0; i < field_count; i++) { if (descriptor->field(i)->is_required()) { if (!reflection->HasField(message, descriptor->field(i))) { return false; } } } } // Check that sub-messages are initialized. std::vector fields; // Should be safe to skip stripped fields because required fields are not // stripped. reflection->ListFieldsOmitStripped(message, &fields); for (const FieldDescriptor* field : fields) { 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) { const MapFieldBase* map_field = reflection->GetMapData(message, field); if (map_field->IsMapValid()) { MapIterator iter(const_cast(&message), field); MapIterator end(const_cast(&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); for (int j = 0; j < size; j++) { if (!reflection->GetRepeatedMessage(message, field, j) .IsInitialized()) { return false; } } } else { if (!reflection->GetMessage(message, field).IsInitialized()) { return false; } } } } return true; } static bool IsMapValueMessageTyped(const FieldDescriptor* map_field) { return map_field->message_type()->field(1)->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE; } void ReflectionOps::DiscardUnknownFields(Message* message) { const Reflection* reflection = GetReflectionOrDie(*message); reflection->MutableUnknownFields(message)->Clear(); // Walk through the fields of this message and DiscardUnknownFields on any // messages present. std::vector fields; reflection->ListFields(*message, &fields); for (const FieldDescriptor* field : fields) { // Skip over non-message fields. if (field->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE) { continue; } // Discard the unknown fields in maps that contain message values. if (field->is_map() && IsMapValueMessageTyped(field)) { const MapFieldBase* map_field = reflection->MutableMapData(message, field); if (map_field->IsMapValid()) { MapIterator iter(message, field); MapIterator end(message, field); for (map_field->MapBegin(&iter), map_field->MapEnd(&end); iter != end; ++iter) { iter.MutableValueRef()->MutableMessageValue()->DiscardUnknownFields(); } } // Discard every unknown field inside messages in a repeated field. } else if (field->is_repeated()) { int size = reflection->FieldSize(*message, field); for (int j = 0; j < size; j++) { reflection->MutableRepeatedMessage(message, field, j) ->DiscardUnknownFields(); } // Discard the unknown fields inside an optional message. } else { reflection->MutableMessage(message, field)->DiscardUnknownFields(); } } } static std::string SubMessagePrefix(const std::string& prefix, const FieldDescriptor* field, int index) { std::string result(prefix); if (field->is_extension()) { result.append("("); result.append(field->full_name()); result.append(")"); } else { result.append(field->name()); } if (index != -1) { result.append("["); result.append(StrCat(index)); result.append("]"); } result.append("."); return result; } void ReflectionOps::FindInitializationErrors(const Message& message, const std::string& prefix, std::vector* errors) { const Descriptor* descriptor = message.GetDescriptor(); const Reflection* reflection = GetReflectionOrDie(message); // Check required fields of this message. { const int field_count = descriptor->field_count(); for (int i = 0; i < field_count; i++) { if (descriptor->field(i)->is_required()) { if (!reflection->HasField(message, descriptor->field(i))) { errors->push_back(prefix + descriptor->field(i)->name()); } } } } // Check sub-messages. std::vector fields; reflection->ListFieldsOmitStripped(message, &fields); for (const FieldDescriptor* field : fields) { if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { if (field->is_repeated()) { int size = reflection->FieldSize(message, field); for (int j = 0; j < size; j++) { const Message& sub_message = reflection->GetRepeatedMessage(message, field, j); FindInitializationErrors(sub_message, SubMessagePrefix(prefix, field, j), errors); } } else { const Message& sub_message = reflection->GetMessage(message, field); FindInitializationErrors(sub_message, SubMessagePrefix(prefix, field, -1), errors); } } } } void GenericSwap(Message* lhs, Message* rhs) { #ifndef PROTOBUF_FORCE_COPY_IN_SWAP GOOGLE_DCHECK(Arena::InternalGetOwningArena(lhs) != Arena::InternalGetOwningArena(rhs)); GOOGLE_DCHECK(Arena::InternalGetOwningArena(lhs) != nullptr || Arena::InternalGetOwningArena(rhs) != nullptr); #endif // !PROTOBUF_FORCE_COPY_IN_SWAP // At least one of these must have an arena, so make `rhs` point to it. Arena* arena = Arena::InternalGetOwningArena(rhs); if (arena == nullptr) { std::swap(lhs, rhs); arena = Arena::InternalGetOwningArena(rhs); } // Improve efficiency by placing the temporary on an arena so that messages // are copied twice rather than three times. Message* tmp = rhs->New(arena); tmp->CheckTypeAndMergeFrom(*lhs); lhs->Clear(); lhs->CheckTypeAndMergeFrom(*rhs); #ifdef PROTOBUF_FORCE_COPY_IN_SWAP rhs->Clear(); rhs->CheckTypeAndMergeFrom(*tmp); if (arena == nullptr) delete tmp; #else // PROTOBUF_FORCE_COPY_IN_SWAP rhs->GetReflection()->Swap(tmp, rhs); #endif // !PROTOBUF_FORCE_COPY_IN_SWAP } } // namespace internal } // namespace protobuf } // namespace google #include