Line data Source code
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 <iostream>
36 : #include <stack>
37 : #include <google/protobuf/stubs/hash.h>
38 :
39 : #include <google/protobuf/message.h>
40 :
41 : #include <google/protobuf/stubs/common.h>
42 : #include <google/protobuf/stubs/once.h>
43 : #include <google/protobuf/io/coded_stream.h>
44 : #include <google/protobuf/io/zero_copy_stream_impl.h>
45 : #include <google/protobuf/descriptor.pb.h>
46 : #include <google/protobuf/descriptor.h>
47 : #include <google/protobuf/generated_message_util.h>
48 : #include <google/protobuf/reflection_ops.h>
49 : #include <google/protobuf/wire_format.h>
50 : #include <google/protobuf/stubs/strutil.h>
51 : #include <google/protobuf/stubs/map_util.h>
52 : #include <google/protobuf/stubs/stl_util.h>
53 :
54 : namespace google {
55 : namespace protobuf {
56 :
57 : using internal::WireFormat;
58 : using internal::ReflectionOps;
59 :
60 582 : Message::~Message() {}
61 :
62 0 : void Message::MergeFrom(const Message& from) {
63 0 : const Descriptor* descriptor = GetDescriptor();
64 0 : GOOGLE_CHECK_EQ(from.GetDescriptor(), descriptor)
65 : << ": Tried to merge from a message with a different type. "
66 0 : "to: " << descriptor->full_name() << ", "
67 0 : "from:" << from.GetDescriptor()->full_name();
68 0 : ReflectionOps::Merge(from, this);
69 0 : }
70 :
71 0 : void Message::CheckTypeAndMergeFrom(const MessageLite& other) {
72 0 : MergeFrom(*down_cast<const Message*>(&other));
73 0 : }
74 :
75 0 : void Message::CopyFrom(const Message& from) {
76 0 : const Descriptor* descriptor = GetDescriptor();
77 0 : GOOGLE_CHECK_EQ(from.GetDescriptor(), descriptor)
78 : << ": Tried to copy from a message with a different type. "
79 0 : "to: " << descriptor->full_name() << ", "
80 0 : "from:" << from.GetDescriptor()->full_name();
81 0 : ReflectionOps::Copy(from, this);
82 0 : }
83 :
84 0 : string Message::GetTypeName() const {
85 0 : return GetDescriptor()->full_name();
86 : }
87 :
88 0 : void Message::Clear() {
89 0 : ReflectionOps::Clear(this);
90 0 : }
91 :
92 0 : bool Message::IsInitialized() const {
93 0 : return ReflectionOps::IsInitialized(*this);
94 : }
95 :
96 0 : void Message::FindInitializationErrors(vector<string>* errors) const {
97 0 : return ReflectionOps::FindInitializationErrors(*this, "", errors);
98 : }
99 :
100 0 : string Message::InitializationErrorString() const {
101 0 : vector<string> errors;
102 0 : FindInitializationErrors(&errors);
103 0 : return Join(errors, ", ");
104 : }
105 :
106 0 : void Message::CheckInitialized() const {
107 0 : GOOGLE_CHECK(IsInitialized())
108 0 : << "Message of type \"" << GetDescriptor()->full_name()
109 0 : << "\" is missing required fields: " << InitializationErrorString();
110 0 : }
111 :
112 0 : void Message::DiscardUnknownFields() {
113 0 : return ReflectionOps::DiscardUnknownFields(this);
114 : }
115 :
116 0 : bool Message::MergePartialFromCodedStream(io::CodedInputStream* input) {
117 0 : return WireFormat::ParseAndMergePartial(input, this);
118 : }
119 :
120 0 : bool Message::ParseFromFileDescriptor(int file_descriptor) {
121 0 : io::FileInputStream input(file_descriptor);
122 0 : return ParseFromZeroCopyStream(&input) && input.GetErrno() == 0;
123 : }
124 :
125 0 : bool Message::ParsePartialFromFileDescriptor(int file_descriptor) {
126 0 : io::FileInputStream input(file_descriptor);
127 0 : return ParsePartialFromZeroCopyStream(&input) && input.GetErrno() == 0;
128 : }
129 :
130 0 : bool Message::ParseFromIstream(istream* input) {
131 0 : io::IstreamInputStream zero_copy_input(input);
132 0 : return ParseFromZeroCopyStream(&zero_copy_input) && input->eof();
133 : }
134 :
135 0 : bool Message::ParsePartialFromIstream(istream* input) {
136 0 : io::IstreamInputStream zero_copy_input(input);
137 0 : return ParsePartialFromZeroCopyStream(&zero_copy_input) && input->eof();
138 : }
139 :
140 :
141 0 : void Message::SerializeWithCachedSizes(
142 : io::CodedOutputStream* output) const {
143 0 : WireFormat::SerializeWithCachedSizes(*this, GetCachedSize(), output);
144 0 : }
145 :
146 0 : int Message::ByteSize() const {
147 0 : int size = WireFormat::ByteSize(*this);
148 0 : SetCachedSize(size);
149 0 : return size;
150 : }
151 :
152 0 : void Message::SetCachedSize(int /* size */) const {
153 0 : GOOGLE_LOG(FATAL) << "Message class \"" << GetDescriptor()->full_name()
154 : << "\" implements neither SetCachedSize() nor ByteSize(). "
155 0 : "Must implement one or the other.";
156 0 : }
157 :
158 0 : int Message::SpaceUsed() const {
159 0 : return GetReflection()->SpaceUsed(*this);
160 : }
161 :
162 0 : bool Message::SerializeToFileDescriptor(int file_descriptor) const {
163 0 : io::FileOutputStream output(file_descriptor);
164 0 : return SerializeToZeroCopyStream(&output);
165 : }
166 :
167 0 : bool Message::SerializePartialToFileDescriptor(int file_descriptor) const {
168 0 : io::FileOutputStream output(file_descriptor);
169 0 : return SerializePartialToZeroCopyStream(&output);
170 : }
171 :
172 0 : bool Message::SerializeToOstream(ostream* output) const {
173 : {
174 0 : io::OstreamOutputStream zero_copy_output(output);
175 0 : if (!SerializeToZeroCopyStream(&zero_copy_output)) return false;
176 : }
177 0 : return output->good();
178 : }
179 :
180 0 : bool Message::SerializePartialToOstream(ostream* output) const {
181 0 : io::OstreamOutputStream zero_copy_output(output);
182 0 : return SerializePartialToZeroCopyStream(&zero_copy_output);
183 : }
184 :
185 :
186 : // =============================================================================
187 : // Reflection and associated Template Specializations
188 :
189 0 : Reflection::~Reflection() {}
190 :
191 : #define HANDLE_TYPE(TYPE, CPPTYPE, CTYPE) \
192 : template<> \
193 : const RepeatedField<TYPE>& Reflection::GetRepeatedField<TYPE>( \
194 : const Message& message, const FieldDescriptor* field) const { \
195 : return *static_cast<RepeatedField<TYPE>* >( \
196 : MutableRawRepeatedField(const_cast<Message*>(&message), \
197 : field, CPPTYPE, CTYPE, NULL)); \
198 : } \
199 : \
200 : template<> \
201 : RepeatedField<TYPE>* Reflection::MutableRepeatedField<TYPE>( \
202 : Message* message, const FieldDescriptor* field) const { \
203 : return static_cast<RepeatedField<TYPE>* >( \
204 : MutableRawRepeatedField(message, field, CPPTYPE, CTYPE, NULL)); \
205 : }
206 :
207 0 : HANDLE_TYPE(int32, FieldDescriptor::CPPTYPE_INT32, -1);
208 0 : HANDLE_TYPE(int64, FieldDescriptor::CPPTYPE_INT64, -1);
209 0 : HANDLE_TYPE(uint32, FieldDescriptor::CPPTYPE_UINT32, -1);
210 0 : HANDLE_TYPE(uint64, FieldDescriptor::CPPTYPE_UINT64, -1);
211 0 : HANDLE_TYPE(float, FieldDescriptor::CPPTYPE_FLOAT, -1);
212 0 : HANDLE_TYPE(double, FieldDescriptor::CPPTYPE_DOUBLE, -1);
213 0 : HANDLE_TYPE(bool, FieldDescriptor::CPPTYPE_BOOL, -1);
214 :
215 :
216 : #undef HANDLE_TYPE
217 :
218 0 : void* Reflection::MutableRawRepeatedString(
219 : Message* message, const FieldDescriptor* field, bool is_string) const {
220 : return MutableRawRepeatedField(message, field,
221 0 : FieldDescriptor::CPPTYPE_STRING, FieldOptions::STRING, NULL);
222 : }
223 :
224 :
225 : // =============================================================================
226 : // MessageFactory
227 :
228 0 : MessageFactory::~MessageFactory() {}
229 :
230 : namespace {
231 :
232 : class GeneratedMessageFactory : public MessageFactory {
233 : public:
234 : GeneratedMessageFactory();
235 : ~GeneratedMessageFactory();
236 :
237 : static GeneratedMessageFactory* singleton();
238 :
239 : typedef void RegistrationFunc(const string&);
240 : void RegisterFile(const char* file, RegistrationFunc* registration_func);
241 : void RegisterType(const Descriptor* descriptor, const Message* prototype);
242 :
243 : // implements MessageFactory ---------------------------------------
244 : const Message* GetPrototype(const Descriptor* type);
245 :
246 : private:
247 : // Only written at static init time, so does not require locking.
248 : hash_map<const char*, RegistrationFunc*,
249 : hash<const char*>, streq> file_map_;
250 :
251 : // Initialized lazily, so requires locking.
252 : Mutex mutex_;
253 : hash_map<const Descriptor*, const Message*> type_map_;
254 : };
255 :
256 : GeneratedMessageFactory* generated_message_factory_ = NULL;
257 : GOOGLE_PROTOBUF_DECLARE_ONCE(generated_message_factory_once_init_);
258 :
259 0 : void ShutdownGeneratedMessageFactory() {
260 0 : delete generated_message_factory_;
261 0 : }
262 :
263 3 : void InitGeneratedMessageFactory() {
264 3 : generated_message_factory_ = new GeneratedMessageFactory;
265 3 : internal::OnShutdown(&ShutdownGeneratedMessageFactory);
266 3 : }
267 :
268 3 : GeneratedMessageFactory::GeneratedMessageFactory() {}
269 0 : GeneratedMessageFactory::~GeneratedMessageFactory() {}
270 :
271 6 : GeneratedMessageFactory* GeneratedMessageFactory::singleton() {
272 : ::google::protobuf::GoogleOnceInit(&generated_message_factory_once_init_,
273 6 : &InitGeneratedMessageFactory);
274 6 : return generated_message_factory_;
275 : }
276 :
277 6 : void GeneratedMessageFactory::RegisterFile(
278 : const char* file, RegistrationFunc* registration_func) {
279 6 : if (!InsertIfNotPresent(&file_map_, file, registration_func)) {
280 0 : GOOGLE_LOG(FATAL) << "File is already registered: " << file;
281 : }
282 6 : }
283 :
284 0 : void GeneratedMessageFactory::RegisterType(const Descriptor* descriptor,
285 : const Message* prototype) {
286 0 : GOOGLE_DCHECK_EQ(descriptor->file()->pool(), DescriptorPool::generated_pool())
287 : << "Tried to register a non-generated type with the generated "
288 0 : "type registry.";
289 :
290 : // This should only be called as a result of calling a file registration
291 : // function during GetPrototype(), in which case we already have locked
292 : // the mutex.
293 0 : mutex_.AssertHeld();
294 0 : if (!InsertIfNotPresent(&type_map_, descriptor, prototype)) {
295 0 : GOOGLE_LOG(DFATAL) << "Type is already registered: " << descriptor->full_name();
296 : }
297 0 : }
298 :
299 :
300 0 : const Message* GeneratedMessageFactory::GetPrototype(const Descriptor* type) {
301 : {
302 0 : ReaderMutexLock lock(&mutex_);
303 0 : const Message* result = FindPtrOrNull(type_map_, type);
304 0 : if (result != NULL) return result;
305 : }
306 :
307 : // If the type is not in the generated pool, then we can't possibly handle
308 : // it.
309 0 : if (type->file()->pool() != DescriptorPool::generated_pool()) return NULL;
310 :
311 : // Apparently the file hasn't been registered yet. Let's do that now.
312 : RegistrationFunc* registration_func =
313 0 : FindPtrOrNull(file_map_, type->file()->name().c_str());
314 0 : if (registration_func == NULL) {
315 0 : GOOGLE_LOG(DFATAL) << "File appears to be in generated pool but wasn't "
316 0 : "registered: " << type->file()->name();
317 0 : return NULL;
318 : }
319 :
320 0 : WriterMutexLock lock(&mutex_);
321 :
322 : // Check if another thread preempted us.
323 0 : const Message* result = FindPtrOrNull(type_map_, type);
324 0 : if (result == NULL) {
325 : // Nope. OK, register everything.
326 0 : registration_func(type->file()->name());
327 : // Should be here now.
328 0 : result = FindPtrOrNull(type_map_, type);
329 : }
330 :
331 0 : if (result == NULL) {
332 0 : GOOGLE_LOG(DFATAL) << "Type appears to be in generated pool but wasn't "
333 0 : << "registered: " << type->full_name();
334 : }
335 :
336 0 : return result;
337 : }
338 :
339 : } // namespace
340 :
341 0 : MessageFactory* MessageFactory::generated_factory() {
342 0 : return GeneratedMessageFactory::singleton();
343 : }
344 :
345 6 : void MessageFactory::InternalRegisterGeneratedFile(
346 : const char* filename, void (*register_messages)(const string&)) {
347 6 : GeneratedMessageFactory::singleton()->RegisterFile(filename,
348 6 : register_messages);
349 6 : }
350 :
351 0 : void MessageFactory::InternalRegisterGeneratedMessage(
352 : const Descriptor* descriptor, const Message* prototype) {
353 0 : GeneratedMessageFactory::singleton()->RegisterType(descriptor, prototype);
354 0 : }
355 :
356 :
357 : } // namespace protobuf
358 9 : } // namespace google
|