1// Protocol Buffers - Google's data interchange format 2// Copyright 2008 Google Inc. All rights reserved. 3// https://developers.google.com/protocol-buffers/ 4// 5// Redistribution and use in source and binary forms, with or without 6// modification, are permitted provided that the following conditions are 7// met: 8// 9// * Redistributions of source code must retain the above copyright 10// notice, this list of conditions and the following disclaimer. 11// * Redistributions in binary form must reproduce the above 12// copyright notice, this list of conditions and the following disclaimer 13// in the documentation and/or other materials provided with the 14// distribution. 15// * Neither the name of Google Inc. nor the names of its 16// contributors may be used to endorse or promote products derived from 17// this software without specific prior written permission. 18// 19// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 31// Author: kenton@google.com (Kenton Varda) 32// Based on original Protocol Buffers design by 33// Sanjay Ghemawat, Jeff Dean, and others. 34 35#include <string> 36#include <vector> 37 38#include <google/protobuf/reflection_ops.h> 39#include <google/protobuf/descriptor.h> 40#include <google/protobuf/descriptor.pb.h> 41#include <google/protobuf/unknown_field_set.h> 42#include <google/protobuf/stubs/strutil.h> 43 44namespace google { 45namespace protobuf { 46namespace internal { 47 48void ReflectionOps::Copy(const Message& from, Message* to) { 49 if (&from == to) return; 50 Clear(to); 51 Merge(from, to); 52} 53 54void ReflectionOps::Merge(const Message& from, Message* to) { 55 GOOGLE_CHECK_NE(&from, to); 56 57 const Descriptor* descriptor = from.GetDescriptor(); 58 GOOGLE_CHECK_EQ(to->GetDescriptor(), descriptor) 59 << "Tried to merge messages of different types " 60 << "(merge " << descriptor->full_name() 61 << " to " << to->GetDescriptor()->full_name() << ")"; 62 63 const Reflection* from_reflection = from.GetReflection(); 64 const Reflection* to_reflection = to->GetReflection(); 65 66 vector<const FieldDescriptor*> fields; 67 from_reflection->ListFields(from, &fields); 68 for (int i = 0; i < fields.size(); i++) { 69 const FieldDescriptor* field = fields[i]; 70 71 if (field->is_repeated()) { 72 int count = from_reflection->FieldSize(from, field); 73 for (int j = 0; j < count; j++) { 74 switch (field->cpp_type()) { 75#define HANDLE_TYPE(CPPTYPE, METHOD) \ 76 case FieldDescriptor::CPPTYPE_##CPPTYPE: \ 77 to_reflection->Add##METHOD(to, field, \ 78 from_reflection->GetRepeated##METHOD(from, field, j)); \ 79 break; 80 81 HANDLE_TYPE(INT32 , Int32 ); 82 HANDLE_TYPE(INT64 , Int64 ); 83 HANDLE_TYPE(UINT32, UInt32); 84 HANDLE_TYPE(UINT64, UInt64); 85 HANDLE_TYPE(FLOAT , Float ); 86 HANDLE_TYPE(DOUBLE, Double); 87 HANDLE_TYPE(BOOL , Bool ); 88 HANDLE_TYPE(STRING, String); 89 HANDLE_TYPE(ENUM , Enum ); 90#undef HANDLE_TYPE 91 92 case FieldDescriptor::CPPTYPE_MESSAGE: 93 to_reflection->AddMessage(to, field)->MergeFrom( 94 from_reflection->GetRepeatedMessage(from, field, j)); 95 break; 96 } 97 } 98 } else { 99 switch (field->cpp_type()) { 100#define HANDLE_TYPE(CPPTYPE, METHOD) \ 101 case FieldDescriptor::CPPTYPE_##CPPTYPE: \ 102 to_reflection->Set##METHOD(to, field, \ 103 from_reflection->Get##METHOD(from, field)); \ 104 break; 105 106 HANDLE_TYPE(INT32 , Int32 ); 107 HANDLE_TYPE(INT64 , Int64 ); 108 HANDLE_TYPE(UINT32, UInt32); 109 HANDLE_TYPE(UINT64, UInt64); 110 HANDLE_TYPE(FLOAT , Float ); 111 HANDLE_TYPE(DOUBLE, Double); 112 HANDLE_TYPE(BOOL , Bool ); 113 HANDLE_TYPE(STRING, String); 114 HANDLE_TYPE(ENUM , Enum ); 115#undef HANDLE_TYPE 116 117 case FieldDescriptor::CPPTYPE_MESSAGE: 118 to_reflection->MutableMessage(to, field)->MergeFrom( 119 from_reflection->GetMessage(from, field)); 120 break; 121 } 122 } 123 } 124 125 to_reflection->MutableUnknownFields(to)->MergeFrom( 126 from_reflection->GetUnknownFields(from)); 127} 128 129void ReflectionOps::Clear(Message* message) { 130 const Reflection* reflection = message->GetReflection(); 131 132 vector<const FieldDescriptor*> fields; 133 reflection->ListFields(*message, &fields); 134 for (int i = 0; i < fields.size(); i++) { 135 reflection->ClearField(message, fields[i]); 136 } 137 138 reflection->MutableUnknownFields(message)->Clear(); 139} 140 141bool ReflectionOps::IsInitialized(const Message& message) { 142 const Descriptor* descriptor = message.GetDescriptor(); 143 const Reflection* reflection = message.GetReflection(); 144 145 // Check required fields of this message. 146 for (int i = 0; i < descriptor->field_count(); i++) { 147 if (descriptor->field(i)->is_required()) { 148 if (!reflection->HasField(message, descriptor->field(i))) { 149 return false; 150 } 151 } 152 } 153 154 // Check that sub-messages are initialized. 155 vector<const FieldDescriptor*> fields; 156 reflection->ListFields(message, &fields); 157 for (int i = 0; i < fields.size(); i++) { 158 const FieldDescriptor* field = fields[i]; 159 if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { 160 161 if (field->is_repeated()) { 162 int size = reflection->FieldSize(message, field); 163 164 for (int j = 0; j < size; j++) { 165 if (!reflection->GetRepeatedMessage(message, field, j) 166 .IsInitialized()) { 167 return false; 168 } 169 } 170 } else { 171 if (!reflection->GetMessage(message, field).IsInitialized()) { 172 return false; 173 } 174 } 175 } 176 } 177 178 return true; 179} 180 181void ReflectionOps::DiscardUnknownFields(Message* message) { 182 const Reflection* reflection = message->GetReflection(); 183 184 reflection->MutableUnknownFields(message)->Clear(); 185 186 vector<const FieldDescriptor*> fields; 187 reflection->ListFields(*message, &fields); 188 for (int i = 0; i < fields.size(); i++) { 189 const FieldDescriptor* field = fields[i]; 190 if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { 191 if (field->is_repeated()) { 192 int size = reflection->FieldSize(*message, field); 193 for (int j = 0; j < size; j++) { 194 reflection->MutableRepeatedMessage(message, field, j) 195 ->DiscardUnknownFields(); 196 } 197 } else { 198 reflection->MutableMessage(message, field)->DiscardUnknownFields(); 199 } 200 } 201 } 202} 203 204static string SubMessagePrefix(const string& prefix, 205 const FieldDescriptor* field, 206 int index) { 207 string result(prefix); 208 if (field->is_extension()) { 209 result.append("("); 210 result.append(field->full_name()); 211 result.append(")"); 212 } else { 213 result.append(field->name()); 214 } 215 if (index != -1) { 216 result.append("["); 217 result.append(SimpleItoa(index)); 218 result.append("]"); 219 } 220 result.append("."); 221 return result; 222} 223 224void ReflectionOps::FindInitializationErrors( 225 const Message& message, 226 const string& prefix, 227 vector<string>* errors) { 228 const Descriptor* descriptor = message.GetDescriptor(); 229 const Reflection* reflection = message.GetReflection(); 230 231 // Check required fields of this message. 232 for (int i = 0; i < descriptor->field_count(); i++) { 233 if (descriptor->field(i)->is_required()) { 234 if (!reflection->HasField(message, descriptor->field(i))) { 235 errors->push_back(prefix + descriptor->field(i)->name()); 236 } 237 } 238 } 239 240 // Check sub-messages. 241 vector<const FieldDescriptor*> fields; 242 reflection->ListFields(message, &fields); 243 for (int i = 0; i < fields.size(); i++) { 244 const FieldDescriptor* field = fields[i]; 245 if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { 246 247 if (field->is_repeated()) { 248 int size = reflection->FieldSize(message, field); 249 250 for (int j = 0; j < size; j++) { 251 const Message& sub_message = 252 reflection->GetRepeatedMessage(message, field, j); 253 FindInitializationErrors(sub_message, 254 SubMessagePrefix(prefix, field, j), 255 errors); 256 } 257 } else { 258 const Message& sub_message = reflection->GetMessage(message, field); 259 FindInitializationErrors(sub_message, 260 SubMessagePrefix(prefix, field, -1), 261 errors); 262 } 263 } 264 } 265} 266 267} // namespace internal 268} // namespace protobuf 269} // namespace google 270