/thirdparty/breakpad/third_party/protobuf/protobuf/src/google/protobuf/descriptor_database.cc

http://github.com/tomahawk-player/tomahawk · C++ · 541 lines · 387 code · 76 blank · 78 comment · 82 complexity · f34afbac968fa816c2b63f95a810998b MD5 · raw file

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