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 <google/protobuf/descriptor_database.h>
36 :
37 : #include <set>
38 :
39 : #include <google/protobuf/descriptor.pb.h>
40 : #include <google/protobuf/wire_format_lite_inl.h>
41 : #include <google/protobuf/stubs/strutil.h>
42 : #include <google/protobuf/stubs/stl_util.h>
43 : #include <google/protobuf/stubs/map_util.h>
44 :
45 : namespace google {
46 : namespace protobuf {
47 :
48 0 : DescriptorDatabase::~DescriptorDatabase() {}
49 :
50 : // ===================================================================
51 :
52 : template <typename Value>
53 6 : bool SimpleDescriptorDatabase::DescriptorIndex<Value>::AddFile(
54 : const FileDescriptorProto& file,
55 : Value value) {
56 6 : if (!InsertIfNotPresent(&by_name_, file.name(), value)) {
57 0 : GOOGLE_LOG(ERROR) << "File already exists in database: " << file.name();
58 0 : return false;
59 : }
60 :
61 : // We must be careful here -- calling file.package() if file.has_package() is
62 : // false could access an uninitialized static-storage variable if we are being
63 : // run at startup time.
64 12 : string path = file.has_package() ? file.package() : string();
65 6 : if (!path.empty()) path += '.';
66 :
67 72 : for (int i = 0; i < file.message_type_size(); i++) {
68 66 : if (!AddSymbol(path + file.message_type(i).name(), value)) return false;
69 66 : if (!AddNestedExtensions(file.message_type(i), value)) return false;
70 : }
71 6 : for (int i = 0; i < file.enum_type_size(); i++) {
72 0 : if (!AddSymbol(path + file.enum_type(i).name(), value)) return false;
73 : }
74 6 : for (int i = 0; i < file.extension_size(); i++) {
75 0 : if (!AddSymbol(path + file.extension(i).name(), value)) return false;
76 0 : if (!AddExtension(file.extension(i), value)) return false;
77 : }
78 6 : for (int i = 0; i < file.service_size(); i++) {
79 0 : if (!AddSymbol(path + file.service(i).name(), value)) return false;
80 : }
81 :
82 6 : return true;
83 : }
84 :
85 : template <typename Value>
86 66 : bool SimpleDescriptorDatabase::DescriptorIndex<Value>::AddSymbol(
87 : const string& name, Value value) {
88 : // We need to make sure not to violate our map invariant.
89 :
90 : // If the symbol name is invalid it could break our lookup algorithm (which
91 : // relies on the fact that '.' sorts before all other characters that are
92 : // valid in symbol names).
93 66 : if (!ValidateSymbolName(name)) {
94 0 : GOOGLE_LOG(ERROR) << "Invalid symbol name: " << name;
95 0 : return false;
96 : }
97 :
98 : // Try to look up the symbol to make sure a super-symbol doesn't already
99 : // exist.
100 66 : typename map<string, Value>::iterator iter = FindLastLessOrEqual(name);
101 :
102 66 : if (iter == by_symbol_.end()) {
103 : // Apparently the map is currently empty. Just insert and be done with it.
104 3 : by_symbol_.insert(typename map<string, Value>::value_type(name, value));
105 3 : return true;
106 : }
107 :
108 63 : if (IsSubSymbol(iter->first, name)) {
109 0 : GOOGLE_LOG(ERROR) << "Symbol name \"" << name << "\" conflicts with the existing "
110 0 : "symbol \"" << iter->first << "\".";
111 0 : return false;
112 : }
113 :
114 : // OK, that worked. Now we have to make sure that no symbol in the map is
115 : // a sub-symbol of the one we are inserting. The only symbol which could
116 : // be so is the first symbol that is greater than the new symbol. Since
117 : // |iter| points at the last symbol that is less than or equal, we just have
118 : // to increment it.
119 63 : ++iter;
120 :
121 63 : if (iter != by_symbol_.end() && IsSubSymbol(name, iter->first)) {
122 0 : GOOGLE_LOG(ERROR) << "Symbol name \"" << name << "\" conflicts with the existing "
123 0 : "symbol \"" << iter->first << "\".";
124 0 : return false;
125 : }
126 :
127 : // OK, no conflicts.
128 :
129 : // Insert the new symbol using the iterator as a hint, the new entry will
130 : // appear immediately before the one the iterator is pointing at.
131 63 : by_symbol_.insert(iter, typename map<string, Value>::value_type(name, value));
132 :
133 63 : return true;
134 : }
135 :
136 : template <typename Value>
137 78 : bool SimpleDescriptorDatabase::DescriptorIndex<Value>::AddNestedExtensions(
138 : const DescriptorProto& message_type,
139 : Value value) {
140 90 : for (int i = 0; i < message_type.nested_type_size(); i++) {
141 12 : if (!AddNestedExtensions(message_type.nested_type(i), value)) return false;
142 : }
143 78 : for (int i = 0; i < message_type.extension_size(); i++) {
144 0 : if (!AddExtension(message_type.extension(i), value)) return false;
145 : }
146 78 : return true;
147 : }
148 :
149 : template <typename Value>
150 0 : bool SimpleDescriptorDatabase::DescriptorIndex<Value>::AddExtension(
151 : const FieldDescriptorProto& field,
152 : Value value) {
153 0 : if (!field.extendee().empty() && field.extendee()[0] == '.') {
154 : // The extension is fully-qualified. We can use it as a lookup key in
155 : // the by_symbol_ table.
156 0 : if (!InsertIfNotPresent(&by_extension_,
157 0 : make_pair(field.extendee().substr(1),
158 0 : field.number()),
159 : value)) {
160 0 : GOOGLE_LOG(ERROR) << "Extension conflicts with extension already in database: "
161 0 : "extend " << field.extendee() << " { "
162 0 : << field.name() << " = " << field.number() << " }";
163 0 : return false;
164 : }
165 : } else {
166 : // Not fully-qualified. We can't really do anything here, unfortunately.
167 : // We don't consider this an error, though, because the descriptor is
168 : // valid.
169 : }
170 0 : return true;
171 : }
172 :
173 : template <typename Value>
174 0 : Value SimpleDescriptorDatabase::DescriptorIndex<Value>::FindFile(
175 : const string& filename) {
176 0 : return FindWithDefault(by_name_, filename, Value());
177 : }
178 :
179 : template <typename Value>
180 0 : Value SimpleDescriptorDatabase::DescriptorIndex<Value>::FindSymbol(
181 : const string& name) {
182 0 : typename map<string, Value>::iterator iter = FindLastLessOrEqual(name);
183 :
184 0 : return (iter != by_symbol_.end() && IsSubSymbol(iter->first, name)) ?
185 0 : iter->second : Value();
186 : }
187 :
188 : template <typename Value>
189 0 : Value SimpleDescriptorDatabase::DescriptorIndex<Value>::FindExtension(
190 : const string& containing_type,
191 : int field_number) {
192 0 : return FindWithDefault(by_extension_,
193 : make_pair(containing_type, field_number),
194 0 : Value());
195 : }
196 :
197 : template <typename Value>
198 0 : bool SimpleDescriptorDatabase::DescriptorIndex<Value>::FindAllExtensionNumbers(
199 : const string& containing_type,
200 : vector<int>* output) {
201 : typename map<pair<string, int>, Value >::const_iterator it =
202 0 : by_extension_.lower_bound(make_pair(containing_type, 0));
203 0 : bool success = false;
204 :
205 0 : for (; it != by_extension_.end() && it->first.first == containing_type;
206 : ++it) {
207 0 : output->push_back(it->first.second);
208 0 : success = true;
209 : }
210 :
211 0 : return success;
212 : }
213 :
214 : template <typename Value>
215 : typename map<string, Value>::iterator
216 66 : SimpleDescriptorDatabase::DescriptorIndex<Value>::FindLastLessOrEqual(
217 : const string& name) {
218 : // Find the last key in the map which sorts less than or equal to the
219 : // symbol name. Since upper_bound() returns the *first* key that sorts
220 : // *greater* than the input, we want the element immediately before that.
221 66 : typename map<string, Value>::iterator iter = by_symbol_.upper_bound(name);
222 66 : if (iter != by_symbol_.begin()) --iter;
223 66 : return iter;
224 : }
225 :
226 : template <typename Value>
227 105 : bool SimpleDescriptorDatabase::DescriptorIndex<Value>::IsSubSymbol(
228 : const string& sub_symbol, const string& super_symbol) {
229 210 : return sub_symbol == super_symbol ||
230 105 : (HasPrefixString(super_symbol, sub_symbol) &&
231 105 : super_symbol[sub_symbol.size()] == '.');
232 : }
233 :
234 : template <typename Value>
235 66 : bool SimpleDescriptorDatabase::DescriptorIndex<Value>::ValidateSymbolName(
236 : const string& name) {
237 2223 : for (int i = 0; i < name.size(); i++) {
238 : // I don't trust ctype.h due to locales. :(
239 8340 : if (name[i] != '.' && name[i] != '_' &&
240 6039 : (name[i] < '0' || name[i] > '9') &&
241 8040 : (name[i] < 'A' || name[i] > 'Z') &&
242 3714 : (name[i] < 'a' || name[i] > 'z')) {
243 0 : return false;
244 : }
245 : }
246 66 : return true;
247 : }
248 :
249 : // -------------------------------------------------------------------
250 :
251 0 : SimpleDescriptorDatabase::SimpleDescriptorDatabase() {}
252 0 : SimpleDescriptorDatabase::~SimpleDescriptorDatabase() {
253 0 : STLDeleteElements(&files_to_delete_);
254 0 : }
255 :
256 0 : bool SimpleDescriptorDatabase::Add(const FileDescriptorProto& file) {
257 0 : FileDescriptorProto* new_file = new FileDescriptorProto;
258 0 : new_file->CopyFrom(file);
259 0 : return AddAndOwn(new_file);
260 : }
261 :
262 0 : bool SimpleDescriptorDatabase::AddAndOwn(const FileDescriptorProto* file) {
263 0 : files_to_delete_.push_back(file);
264 0 : return index_.AddFile(*file, file);
265 : }
266 :
267 0 : bool SimpleDescriptorDatabase::FindFileByName(
268 : const string& filename,
269 : FileDescriptorProto* output) {
270 0 : return MaybeCopy(index_.FindFile(filename), output);
271 : }
272 :
273 0 : bool SimpleDescriptorDatabase::FindFileContainingSymbol(
274 : const string& symbol_name,
275 : FileDescriptorProto* output) {
276 0 : return MaybeCopy(index_.FindSymbol(symbol_name), output);
277 : }
278 :
279 0 : bool SimpleDescriptorDatabase::FindFileContainingExtension(
280 : const string& containing_type,
281 : int field_number,
282 : FileDescriptorProto* output) {
283 0 : return MaybeCopy(index_.FindExtension(containing_type, field_number), output);
284 : }
285 :
286 0 : bool SimpleDescriptorDatabase::FindAllExtensionNumbers(
287 : const string& extendee_type,
288 : vector<int>* output) {
289 0 : return index_.FindAllExtensionNumbers(extendee_type, output);
290 : }
291 :
292 :
293 0 : bool SimpleDescriptorDatabase::MaybeCopy(const FileDescriptorProto* file,
294 : FileDescriptorProto* output) {
295 0 : if (file == NULL) return false;
296 0 : output->CopyFrom(*file);
297 0 : return true;
298 : }
299 :
300 : // -------------------------------------------------------------------
301 :
302 3 : EncodedDescriptorDatabase::EncodedDescriptorDatabase() {}
303 0 : EncodedDescriptorDatabase::~EncodedDescriptorDatabase() {
304 0 : for (int i = 0; i < files_to_delete_.size(); i++) {
305 0 : operator delete(files_to_delete_[i]);
306 : }
307 0 : }
308 :
309 6 : bool EncodedDescriptorDatabase::Add(
310 : const void* encoded_file_descriptor, int size) {
311 12 : FileDescriptorProto file;
312 6 : if (file.ParseFromArray(encoded_file_descriptor, size)) {
313 6 : return index_.AddFile(file, make_pair(encoded_file_descriptor, size));
314 : } else {
315 0 : GOOGLE_LOG(ERROR) << "Invalid file descriptor data passed to "
316 0 : "EncodedDescriptorDatabase::Add().";
317 0 : return false;
318 : }
319 : }
320 :
321 0 : bool EncodedDescriptorDatabase::AddCopy(
322 : const void* encoded_file_descriptor, int size) {
323 0 : void* copy = operator new(size);
324 0 : memcpy(copy, encoded_file_descriptor, size);
325 0 : files_to_delete_.push_back(copy);
326 0 : return Add(copy, size);
327 : }
328 :
329 0 : bool EncodedDescriptorDatabase::FindFileByName(
330 : const string& filename,
331 : FileDescriptorProto* output) {
332 0 : return MaybeParse(index_.FindFile(filename), output);
333 : }
334 :
335 0 : bool EncodedDescriptorDatabase::FindFileContainingSymbol(
336 : const string& symbol_name,
337 : FileDescriptorProto* output) {
338 0 : return MaybeParse(index_.FindSymbol(symbol_name), output);
339 : }
340 :
341 0 : bool EncodedDescriptorDatabase::FindNameOfFileContainingSymbol(
342 : const string& symbol_name,
343 : string* output) {
344 0 : pair<const void*, int> encoded_file = index_.FindSymbol(symbol_name);
345 0 : if (encoded_file.first == NULL) return false;
346 :
347 : // Optimization: The name should be the first field in the encoded message.
348 : // Try to just read it directly.
349 0 : io::CodedInputStream input(reinterpret_cast<const uint8*>(encoded_file.first),
350 0 : encoded_file.second);
351 :
352 : const uint32 kNameTag = internal::WireFormatLite::MakeTag(
353 : FileDescriptorProto::kNameFieldNumber,
354 0 : internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED);
355 :
356 0 : if (input.ReadTag() == kNameTag) {
357 : // Success!
358 0 : return internal::WireFormatLite::ReadString(&input, output);
359 : } else {
360 : // Slow path. Parse whole message.
361 0 : FileDescriptorProto file_proto;
362 0 : if (!file_proto.ParseFromArray(encoded_file.first, encoded_file.second)) {
363 0 : return false;
364 : }
365 0 : *output = file_proto.name();
366 0 : return true;
367 : }
368 : }
369 :
370 0 : bool EncodedDescriptorDatabase::FindFileContainingExtension(
371 : const string& containing_type,
372 : int field_number,
373 : FileDescriptorProto* output) {
374 0 : return MaybeParse(index_.FindExtension(containing_type, field_number),
375 0 : output);
376 : }
377 :
378 0 : bool EncodedDescriptorDatabase::FindAllExtensionNumbers(
379 : const string& extendee_type,
380 : vector<int>* output) {
381 0 : return index_.FindAllExtensionNumbers(extendee_type, output);
382 : }
383 :
384 0 : bool EncodedDescriptorDatabase::MaybeParse(
385 : pair<const void*, int> encoded_file,
386 : FileDescriptorProto* output) {
387 0 : if (encoded_file.first == NULL) return false;
388 0 : return output->ParseFromArray(encoded_file.first, encoded_file.second);
389 : }
390 :
391 : // ===================================================================
392 :
393 0 : DescriptorPoolDatabase::DescriptorPoolDatabase(const DescriptorPool& pool)
394 0 : : pool_(pool) {}
395 0 : DescriptorPoolDatabase::~DescriptorPoolDatabase() {}
396 :
397 0 : bool DescriptorPoolDatabase::FindFileByName(
398 : const string& filename,
399 : FileDescriptorProto* output) {
400 0 : const FileDescriptor* file = pool_.FindFileByName(filename);
401 0 : if (file == NULL) return false;
402 0 : output->Clear();
403 0 : file->CopyTo(output);
404 0 : return true;
405 : }
406 :
407 0 : bool DescriptorPoolDatabase::FindFileContainingSymbol(
408 : const string& symbol_name,
409 : FileDescriptorProto* output) {
410 0 : const FileDescriptor* file = pool_.FindFileContainingSymbol(symbol_name);
411 0 : if (file == NULL) return false;
412 0 : output->Clear();
413 0 : file->CopyTo(output);
414 0 : return true;
415 : }
416 :
417 0 : bool DescriptorPoolDatabase::FindFileContainingExtension(
418 : const string& containing_type,
419 : int field_number,
420 : FileDescriptorProto* output) {
421 0 : const Descriptor* extendee = pool_.FindMessageTypeByName(containing_type);
422 0 : if (extendee == NULL) return false;
423 :
424 : const FieldDescriptor* extension =
425 0 : pool_.FindExtensionByNumber(extendee, field_number);
426 0 : if (extension == NULL) return false;
427 :
428 0 : output->Clear();
429 0 : extension->file()->CopyTo(output);
430 0 : return true;
431 : }
432 :
433 0 : bool DescriptorPoolDatabase::FindAllExtensionNumbers(
434 : const string& extendee_type,
435 : vector<int>* output) {
436 0 : const Descriptor* extendee = pool_.FindMessageTypeByName(extendee_type);
437 0 : if (extendee == NULL) return false;
438 :
439 0 : vector<const FieldDescriptor*> extensions;
440 0 : pool_.FindAllExtensions(extendee, &extensions);
441 :
442 0 : for (int i = 0; i < extensions.size(); ++i) {
443 0 : output->push_back(extensions[i]->number());
444 : }
445 :
446 0 : return true;
447 : }
448 :
449 : // ===================================================================
450 :
451 0 : MergedDescriptorDatabase::MergedDescriptorDatabase(
452 : DescriptorDatabase* source1,
453 0 : DescriptorDatabase* source2) {
454 0 : sources_.push_back(source1);
455 0 : sources_.push_back(source2);
456 0 : }
457 0 : MergedDescriptorDatabase::MergedDescriptorDatabase(
458 0 : const vector<DescriptorDatabase*>& sources)
459 0 : : sources_(sources) {}
460 0 : MergedDescriptorDatabase::~MergedDescriptorDatabase() {}
461 :
462 0 : bool MergedDescriptorDatabase::FindFileByName(
463 : const string& filename,
464 : FileDescriptorProto* output) {
465 0 : for (int i = 0; i < sources_.size(); i++) {
466 0 : if (sources_[i]->FindFileByName(filename, output)) {
467 0 : return true;
468 : }
469 : }
470 0 : return false;
471 : }
472 :
473 0 : bool MergedDescriptorDatabase::FindFileContainingSymbol(
474 : const string& symbol_name,
475 : FileDescriptorProto* output) {
476 0 : for (int i = 0; i < sources_.size(); i++) {
477 0 : if (sources_[i]->FindFileContainingSymbol(symbol_name, output)) {
478 : // The symbol was found in source i. However, if one of the previous
479 : // sources defines a file with the same name (which presumably doesn't
480 : // contain the symbol, since it wasn't found in that source), then we
481 : // must hide it from the caller.
482 0 : FileDescriptorProto temp;
483 0 : for (int j = 0; j < i; j++) {
484 0 : if (sources_[j]->FindFileByName(output->name(), &temp)) {
485 : // Found conflicting file in a previous source.
486 0 : return false;
487 : }
488 : }
489 0 : return true;
490 : }
491 : }
492 0 : return false;
493 : }
494 :
495 0 : bool MergedDescriptorDatabase::FindFileContainingExtension(
496 : const string& containing_type,
497 : int field_number,
498 : FileDescriptorProto* output) {
499 0 : for (int i = 0; i < sources_.size(); i++) {
500 0 : if (sources_[i]->FindFileContainingExtension(
501 0 : containing_type, field_number, output)) {
502 : // The symbol was found in source i. However, if one of the previous
503 : // sources defines a file with the same name (which presumably doesn't
504 : // contain the symbol, since it wasn't found in that source), then we
505 : // must hide it from the caller.
506 0 : FileDescriptorProto temp;
507 0 : for (int j = 0; j < i; j++) {
508 0 : if (sources_[j]->FindFileByName(output->name(), &temp)) {
509 : // Found conflicting file in a previous source.
510 0 : return false;
511 : }
512 : }
513 0 : return true;
514 : }
515 : }
516 0 : return false;
517 : }
518 :
519 0 : bool MergedDescriptorDatabase::FindAllExtensionNumbers(
520 : const string& extendee_type,
521 : vector<int>* output) {
522 0 : set<int> merged_results;
523 0 : vector<int> results;
524 0 : bool success = false;
525 :
526 0 : for (int i = 0; i < sources_.size(); i++) {
527 0 : if (sources_[i]->FindAllExtensionNumbers(extendee_type, &results)) {
528 : copy(results.begin(), results.end(),
529 0 : insert_iterator<set<int> >(merged_results, merged_results.begin()));
530 0 : success = true;
531 : }
532 0 : results.clear();
533 : }
534 :
535 : copy(merged_results.begin(), merged_results.end(),
536 0 : insert_iterator<vector<int> >(*output, output->end()));
537 :
538 0 : return success;
539 : }
540 :
541 :
542 : } // namespace protobuf
543 : } // namespace google
|