descriptor_database.cc 18 KB

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