42 #include <unordered_map>
43 #include <unordered_set>
71 #undef PACKAGE // autoheader #defines this. :(
74 #include <google/protobuf/port_def.inc>
111 #define CONSTRUCTOR(TYPE, TYPE_CONSTANT, FIELD) \
112 inline explicit Symbol(const TYPE* value) { \
113 type = TYPE_CONSTANT; \
114 this->FIELD = value; \
154 static_cast<CppType
>(0),
237 #if !defined(_MSC_VER) || _MSC_VER >= 1900
247 return (
ch >=
'a' &&
ch <=
'z') ? (
ch -
'a' +
'A') :
ch;
251 return (
ch >=
'A' &&
ch <=
'Z') ? (
ch -
'A' +
'a') :
ch;
255 bool capitalize_next = !lower_first;
257 result.reserve(
input.size());
259 for (
int i = 0;
i <
input.size();
i++) {
261 capitalize_next =
true;
262 }
else if (capitalize_next) {
264 capitalize_next =
false;
266 result.push_back(
input[
i]);
271 if (lower_first && !result.empty()) {
272 result[0] =
ToLower(result[0]);
279 bool capitalize_next =
false;
281 result.reserve(
input.size());
283 for (
int i = 0;
i <
input.size();
i++) {
285 capitalize_next =
true;
286 }
else if (capitalize_next) {
288 capitalize_next =
false;
290 result.push_back(
input[
i]);
298 bool next_upper =
true;
300 result.reserve(
input.size());
302 for (
int i = 0;
i <
input.size();
i++) {
319 class PrefixRemover {
323 for (
int i = 0;
i <
prefix.size();
i++) {
346 for (
i = 0, j = 0;
i <
str.size() && j <
prefix_.size();
i++) {
363 while (
i <
str.size() &&
str[
i] ==
'_') {
368 if (
i ==
str.size()) {
373 str.remove_prefix(
i);
393 typedef std::pair<const void*, const char*> PointerStringPair;
395 struct PointerStringPairEqual {
396 inline bool operator()(
const PointerStringPair&
a,
397 const PointerStringPair&
b)
const {
398 return a.first ==
b.first && strcmp(
a.second,
b.second) == 0;
402 typedef std::pair<const Descriptor*, int> DescriptorIntPair;
403 typedef std::pair<const EnumDescriptor*, int> EnumIntPair;
405 #define HASH_MAP std::unordered_map
406 #define HASH_SET std::unordered_set
407 #define HASH_FXN hash
409 template <
typename PairType>
410 struct PointerIntegerPairHash {
411 size_t operator()(
const PairType&
p)
const {
412 static const size_t prime1 = 16777499;
413 static const size_t prime2 = 16777619;
414 return reinterpret_cast<size_t>(
p.first) * prime1 ^
415 static_cast<size_t>(
p.second) * prime2;
420 static const size_t bucket_size = 4;
421 static const size_t min_buckets = 8;
423 inline bool operator()(
const PairType&
a,
const PairType&
b)
const {
424 return a.first <
b.first || (
a.first ==
b.first &&
a.second <
b.second);
428 struct PointerStringPairHash {
429 size_t operator()(
const PointerStringPair&
p)
const {
430 static const size_t prime = 16777619;
431 hash<const char*> cstring_hash;
432 return reinterpret_cast<size_t>(
p.first) * prime ^
433 static_cast<size_t>(cstring_hash(
p.second));
438 static const size_t bucket_size = 4;
439 static const size_t min_buckets = 8;
441 inline bool operator()(
const PointerStringPair&
a,
442 const PointerStringPair&
b)
const {
443 if (
a.first <
b.first)
return true;
444 if (
a.first >
b.first)
return false;
445 return strcmp(
a.second,
b.second) < 0;
450 const Symbol kNullSymbol;
452 typedef HASH_MAP<const char*, Symbol, HASH_FXN<const char*>,
streq>
455 typedef HASH_MAP<PointerStringPair, Symbol, PointerStringPairHash,
456 PointerStringPairEqual>
459 typedef HASH_MAP<const char*, const FileDescriptor*, HASH_FXN<const char*>,
464 PointerStringPairHash, PointerStringPairEqual>
468 PointerIntegerPairHash<DescriptorIntPair>,
469 std::equal_to<DescriptorIntPair>>
473 PointerIntegerPairHash<EnumIntPair>,
474 std::equal_to<EnumIntPair>>
475 EnumValuesByNumberMap;
480 typedef std::map<DescriptorIntPair, const FieldDescriptor*>
481 ExtensionsGroupedByDescriptorMap;
482 typedef HASH_MAP<std::string, const SourceCodeInfo_Location*>
485 std::set<std::string>* NewAllowedProto3Extendee() {
486 auto allowed_proto3_extendees =
new std::set<std::string>;
487 const char* kOptionNames[] = {
488 "FileOptions",
"MessageOptions",
"FieldOptions",
"EnumOptions",
489 "EnumValueOptions",
"ServiceOptions",
"MethodOptions",
"OneofOptions"};
494 allowed_proto3_extendees->insert(
std::string(
"google.protobuf.") +
498 allowed_proto3_extendees->insert(
std::string(
"proto") +
"2." +
501 return allowed_proto3_extendees;
509 static auto allowed_proto3_extendees =
511 return allowed_proto3_extendees->find(
name) !=
512 allowed_proto3_extendees->end();
520 class DescriptorPool::Tables {
602 std::vector<const FieldDescriptor*>* out)
const;
622 template <
typename Type>
627 template <
typename Type>
645 template <
typename Type>
654 std::vector<internal::once_flag*>
656 std::vector<FileDescriptorTables*>
728 const void* parent,
const std::string& lowercase_name)
const;
730 const void* parent,
const std::string& camelcase_name)
const;
756 std::pair<const FileDescriptorTables*, const SourceCodeInfo*>*
p);
787 mutable EnumValuesByNumberMap unknown_enum_values_by_number_
801 : known_bad_files_(3),
802 known_bad_symbols_(3),
803 extensions_loaded_from_db_(3),
812 for (
int i = 0;
i < allocations_.size();
i++) {
813 operator delete(allocations_[
i]);
822 : symbols_by_parent_(3),
823 fields_by_lowercase_name_(3),
824 fields_by_lowercase_name_tmp_(new FieldsByNameMap()),
825 fields_by_camelcase_name_(3),
826 fields_by_camelcase_name_tmp_(new FieldsByNameMap()),
827 fields_by_number_(3),
828 enum_values_by_number_(3),
829 unknown_enum_values_by_number_(3),
830 locations_by_path_(3) {}
835 static auto file_descriptor_tables =
837 return *file_descriptor_tables;
846 checkpoints_.pop_back();
847 if (checkpoints_.empty()) {
850 symbols_after_checkpoint_.clear();
851 files_after_checkpoint_.clear();
852 extensions_after_checkpoint_.clear();
860 for (
int i =
checkpoint.pending_symbols_before_checkpoint;
861 i < symbols_after_checkpoint_.size();
i++) {
862 symbols_by_name_.erase(symbols_after_checkpoint_[
i]);
864 for (
int i =
checkpoint.pending_files_before_checkpoint;
865 i < files_after_checkpoint_.size();
i++) {
866 files_by_name_.erase(files_after_checkpoint_[
i]);
868 for (
int i =
checkpoint.pending_extensions_before_checkpoint;
869 i < extensions_after_checkpoint_.size();
i++) {
870 extensions_.erase(extensions_after_checkpoint_[
i]);
873 symbols_after_checkpoint_.resize(
874 checkpoint.pending_symbols_before_checkpoint);
875 files_after_checkpoint_.resize(
checkpoint.pending_files_before_checkpoint);
876 extensions_after_checkpoint_.resize(
877 checkpoint.pending_extensions_before_checkpoint);
880 strings_.begin() +
checkpoint.strings_before_checkpoint, strings_.end());
882 messages_.begin() +
checkpoint.messages_before_checkpoint,
885 once_dynamics_.begin() +
checkpoint.once_dynamics_before_checkpoint,
886 once_dynamics_.end());
888 file_tables_.begin() +
checkpoint.file_tables_before_checkpoint,
890 for (
int i =
checkpoint.allocations_before_checkpoint;
891 i < allocations_.size();
i++) {
892 operator delete(allocations_[
i]);
895 strings_.resize(
checkpoint.strings_before_checkpoint);
896 messages_.resize(
checkpoint.messages_before_checkpoint);
897 once_dynamics_.resize(
checkpoint.once_dynamics_before_checkpoint);
898 file_tables_.resize(
checkpoint.file_tables_before_checkpoint);
899 allocations_.resize(
checkpoint.allocations_before_checkpoint);
900 checkpoints_.pop_back();
907 if (result ==
nullptr) {
917 symbols_by_parent_, PointerStringPair(parent,
name.c_str()));
918 if (result ==
nullptr) {
928 Symbol result = FindNestedSymbol(parent,
name);
929 if (result.
type !=
type)
return kNullSymbol;
936 if (
pool->fallback_database_ !=
nullptr) {
937 known_bad_symbols_.clear();
938 known_bad_files_.clear();
942 if (result.
IsNull() &&
pool->underlay_ !=
nullptr) {
944 result =
pool->underlay_->tables_->FindByNameHelper(
pool->underlay_,
name);
949 if (
pool->TryFindSymbolInFallbackDatabase(
name)) {
950 result = FindSymbol(
name);
969 if (
field->is_extension()) {
970 if (
field->extension_scope() ==
nullptr) {
971 return field->file();
973 return field->extension_scope();
976 return field->containing_type();
986 for (FieldsByNumberMap::const_iterator
it = fields_by_number_.begin();
987 it != fields_by_number_.end();
it++) {
988 PointerStringPair lowercase_key(FindParentForFieldsByMap(
it->second),
989 it->second->lowercase_name().c_str());
996 const void* parent,
const std::string& lowercase_name)
const {
998 fields_by_lowercase_name_once_,
1001 PointerStringPair(parent, lowercase_name.c_str()));
1010 for (FieldsByNumberMap::const_iterator
it = fields_by_number_.begin();
1011 it != fields_by_number_.end();
it++) {
1012 PointerStringPair camelcase_key(FindParentForFieldsByMap(
it->second),
1013 it->second->camelcase_name().c_str());
1020 const void* parent,
const std::string& camelcase_name)
const {
1022 fields_by_camelcase_name_once_,
1025 PointerStringPair(parent, camelcase_name.c_str()));
1031 std::make_pair(parent,
number));
1040 enum_values_by_number_, std::make_pair(parent,
number));
1041 if (
desc !=
nullptr) {
1049 unknown_enum_values_by_number_, std::make_pair(parent,
number));
1050 if (
desc !=
nullptr) {
1059 unknown_enum_values_by_number_, std::make_pair(parent,
number));
1060 if (
desc !=
nullptr) {
1070 DescriptorPool::Tables* tables =
const_cast<DescriptorPool::Tables*
>(
1073 result->
name_ = tables->AllocateString(enum_value_name);
1075 tables->AllocateString(parent->
full_name() +
"." + enum_value_name);
1077 result->
type_ = parent;
1080 std::make_pair(parent,
number), result);
1092 std::vector<const FieldDescriptor*>* out)
const {
1093 ExtensionsGroupedByDescriptorMap::const_iterator
it =
1094 extensions_.lower_bound(std::make_pair(extendee, 0));
1095 for (;
it != extensions_.end() &&
it->first.first == extendee; ++
it) {
1096 out->push_back(
it->second);
1105 symbols_after_checkpoint_.push_back(full_name.c_str());
1115 PointerStringPair by_parent_key(parent,
name.c_str());
1121 files_after_checkpoint_.push_back(file->
name().c_str());
1130 fields_by_lowercase_name_tmp_ =
nullptr;
1131 fields_by_camelcase_name_tmp_ =
nullptr;
1136 const void* parent = FindParentForFieldsByMap(
field);
1145 PointerStringPair lowercase_key(parent,
field->lowercase_name().c_str());
1147 lowercase_key,
field)) {
1149 &fields_by_lowercase_name_, lowercase_key,
1150 FindPtrOrNull(*fields_by_lowercase_name_tmp_, lowercase_key));
1153 PointerStringPair camelcase_key(parent,
field->camelcase_name().c_str());
1155 camelcase_key,
field)) {
1157 &fields_by_camelcase_name_, camelcase_key,
1158 FindPtrOrNull(*fields_by_camelcase_name_tmp_, camelcase_key));
1163 DescriptorIntPair
key(
field->containing_type(),
field->number());
1174 DescriptorIntPair
key(
field->containing_type(),
field->number());
1176 extensions_after_checkpoint_.push_back(
key);
1185 template <
typename Type>
1187 return reinterpret_cast<Type*
>(AllocateBytes(
sizeof(
Type)));
1190 template <
typename Type>
1192 return reinterpret_cast<Type*
>(AllocateBytes(
sizeof(
Type) *
count));
1197 strings_.push_back(result);
1203 strings_.push_back(result);
1209 once_dynamics_.push_back(result);
1213 template <
typename Type>
1216 messages_.push_back(result);
1222 file_tables_.push_back(result);
1231 if (
size == 0)
return nullptr;
1233 void* result =
operator new(
size);
1234 allocations_.push_back(result);
1239 std::pair<const FileDescriptorTables*, const SourceCodeInfo*>*
p) {
1240 for (
int i = 0,
len =
p->second->location_size();
i <
len; ++
i) {
1242 p->first->locations_by_path_[
Join(loc->
path(),
",")] = loc;
1248 std::pair<const FileDescriptorTables*, const SourceCodeInfo*>
p(
1249 std::make_pair(
this, info));
1275 fallback_database_(fallback_database),
1276 default_error_collector_(error_collector),
1279 enforce_dependencies_(
true),
1280 lazily_build_dependencies_(
false),
1281 allow_unknown_(
false),
1282 enforce_weak_(
false),
1283 disallow_enforce_utf8_(
false) {}
1287 fallback_database_(nullptr),
1288 default_error_collector_(nullptr),
1289 underlay_(underlay),
1291 enforce_dependencies_(
true),
1292 lazily_build_dependencies_(
false),
1293 allow_unknown_(
false),
1294 enforce_weak_(
false),
1295 disallow_enforce_utf8_(
false) {}
1318 return tables_->FindFile(filename) !=
nullptr;
1327 static auto generated_database =
1329 return generated_database;
1356 const void* encoded_file_descriptor,
int size) {
1393 tables_->known_bad_symbols_.clear();
1394 tables_->known_bad_files_.clear();
1397 if (result !=
nullptr)
return result;
1400 if (result !=
nullptr)
return result;
1404 if (result !=
nullptr)
return result;
1413 tables_->known_bad_symbols_.clear();
1414 tables_->known_bad_files_.clear();
1421 if (file_result !=
nullptr)
return file_result;
1424 result =
tables_->FindSymbol(symbol_name);
1496 if (result !=
nullptr) {
1502 tables_->known_bad_symbols_.clear();
1503 tables_->known_bad_files_.clear();
1506 if (result !=
nullptr) {
1511 if (result !=
nullptr)
return result;
1515 if (result !=
nullptr) {
1532 if (
type !=
nullptr) {
1534 const int type_extension_count =
type->extension_count();
1535 for (
int i = 0;
i < type_extension_count;
i++) {
1537 if (
extension->containing_type() == extendee &&
1551 std::vector<const FieldDescriptor*>* out)
const {
1554 tables_->known_bad_symbols_.clear();
1555 tables_->known_bad_files_.clear();
1561 tables_->extensions_loaded_from_db_.count(extendee) == 0) {
1562 std::vector<int> numbers;
1565 for (
int i = 0;
i < numbers.size(); ++
i) {
1571 tables_->extensions_loaded_from_db_.insert(extendee);
1575 tables_->FindAllExtensions(extendee, out);
1814 const Descriptor::ExtensionRange*
1838 const EnumDescriptor::ReservedRange*
1854 if (fallback_database_ ==
nullptr)
return false;
1856 if (tables_->known_bad_files_.count(
name) > 0)
return false;
1859 if (!fallback_database_->FindFileByName(
name, &file_proto) ||
1860 BuildFileFromDatabase(file_proto) ==
nullptr) {
1861 tables_->known_bad_files_.insert(
name);
1870 std::string::size_type dot_pos =
prefix.find_last_of(
'.');
1871 if (dot_pos == std::string::npos) {
1882 if (underlay_ !=
nullptr) {
1884 return underlay_->IsSubSymbolOfBuiltType(
name);
1891 if (fallback_database_ ==
nullptr)
return false;
1893 if (tables_->known_bad_symbols_.count(
name) > 0)
return false;
1912 IsSubSymbolOfBuiltType(
name)
1915 || !fallback_database_->FindFileContainingSymbol(
name, &file_proto)
1920 || tables_->FindFile(file_proto.
name()) !=
nullptr
1923 || BuildFileFromDatabase(file_proto) ==
nullptr) {
1924 tables_->known_bad_symbols_.insert(
name);
1933 if (fallback_database_ ==
nullptr)
return false;
1936 if (!fallback_database_->FindFileContainingExtension(
1941 if (tables_->FindFile(file_proto.
name()) !=
nullptr) {
1948 if (BuildFileFromDatabase(file_proto) ==
nullptr) {
1958 return message_type_->options().map_entry();
1962 bool quote_string_type)
const {
1963 GOOGLE_CHECK(has_default_value()) <<
"No default value";
1966 return StrCat(default_value_int32());
1969 return StrCat(default_value_int64());
1971 case CPPTYPE_UINT32:
1972 return StrCat(default_value_uint32());
1974 case CPPTYPE_UINT64:
1975 return StrCat(default_value_uint64());
1980 case CPPTYPE_DOUBLE:
1984 return default_value_bool() ?
"true" :
"false";
1986 case CPPTYPE_STRING:
1987 if (quote_string_type) {
1988 return "\"" +
CEscape(default_value_string()) +
"\"";
1990 if (
type() == TYPE_BYTES) {
1991 return CEscape(default_value_string());
1993 return default_value_string();
1998 return default_value_enum()->name();
2000 case CPPTYPE_MESSAGE:
2001 GOOGLE_LOG(DFATAL) <<
"Messages can't have default values!";
2004 GOOGLE_LOG(
FATAL) <<
"Can't get here: failed to get default value as string";
2016 for (
int i = 0;
i < dependency_count();
i++) {
2020 for (
int i = 0;
i < public_dependency_count();
i++) {
2024 for (
int i = 0;
i < weak_dependency_count();
i++) {
2028 for (
int i = 0;
i < message_type_count();
i++) {
2034 for (
int i = 0;
i < service_count();
i++) {
2049 GOOGLE_LOG(
ERROR) <<
"Cannot copy json_name to a proto of a different size.";
2052 for (
int i = 0;
i < message_type_count();
i++) {
2061 if (source_code_info_ &&
2106 GOOGLE_LOG(
ERROR) <<
"Cannot copy json_name to a proto of a different size.";
2123 if (has_json_name_) {
2130 implicit_cast<int>(
label())));
2132 implicit_cast<int>(
type())));
2134 if (is_extension()) {
2141 if (
cpp_type() == CPPTYPE_MESSAGE) {
2152 }
else if (
cpp_type() == CPPTYPE_ENUM) {
2159 if (has_default_value()) {
2163 if (containing_oneof() !=
nullptr && !is_extension()) {
2186 for (
int i = 0;
i < value_count();
i++) {
2215 for (
int i = 0;
i < method_count();
i++) {
2241 if (client_streaming_) {
2244 if (server_streaming_) {
2253 bool RetrieveOptionsAssumingRightPool(
2255 std::vector<std::string>* option_entries) {
2256 option_entries->clear();
2258 std::vector<const FieldDescriptor*>
fields;
2260 for (
int i = 0;
i <
fields.size();
i++) {
2262 bool repeated =
false;
2263 if (
fields[
i]->is_repeated()) {
2267 for (
int j = 0; j <
count; j++) {
2271 TextFormat::Printer printer;
2272 printer.SetInitialIndentLevel(
depth + 1);
2273 printer.PrintFieldValueToString(
options,
fields[
i], repeated ? j : -1,
2275 fieldval.append(
"{\n");
2276 fieldval.append(tmp);
2277 fieldval.append(
depth * 2,
' ');
2278 fieldval.append(
"}");
2281 repeated ? j : -1, &fieldval);
2284 if (
fields[
i]->is_extension()) {
2289 option_entries->push_back(
name +
" = " + fieldval);
2292 return !option_entries->empty();
2296 bool RetrieveOptions(
int depth,
const Message&
options,
2298 std::vector<std::string>* option_entries) {
2304 return RetrieveOptionsAssumingRightPool(
depth,
options, option_entries);
2308 if (option_descriptor ==
nullptr) {
2311 return RetrieveOptionsAssumingRightPool(
depth,
options, option_entries);
2313 DynamicMessageFactory factory;
2314 std::unique_ptr<Message> dynamic_options(
2315 factory.GetPrototype(option_descriptor)->New());
2316 if (dynamic_options->ParseFromString(
options.SerializeAsString())) {
2317 return RetrieveOptionsAssumingRightPool(
depth, *dynamic_options,
2322 return RetrieveOptionsAssumingRightPool(
depth,
options, option_entries);
2329 bool FormatBracketedOptions(
int depth,
const Message&
options,
2331 std::vector<std::string> all_options;
2335 return !all_options.empty();
2339 bool FormatLineOptions(
int depth,
const Message&
options,
2342 std::vector<std::string> all_options;
2344 for (
int i = 0;
i < all_options.size();
i++) {
2349 return !all_options.empty();
2352 class SourceLocationCommentPrinter {
2354 template <
typename DescType>
2356 const DebugStringOptions&
options)
2364 const std::vector<int>&
path,
2366 const DebugStringOptions&
options)
2376 for (
int i = 0;
i <
source_loc_.leading_detached_comments.size(); ++
i) {
2397 std::vector<std::string> lines =
Split(stripped_comment,
"\n");
2399 for (
int i = 0;
i < lines.size(); ++
i) {
2425 std::vector<int>
path;
2427 SourceLocationCommentPrinter syntax_comment(
this,
path,
"",
2428 debug_string_options);
2429 syntax_comment.AddPreComment(&contents);
2431 SyntaxName(syntax()));
2432 syntax_comment.AddPostComment(&contents);
2435 SourceLocationCommentPrinter comment_printer(
this,
"", debug_string_options);
2436 comment_printer.AddPreComment(&contents);
2438 std::set<int> public_dependencies;
2439 std::set<int> weak_dependencies;
2440 public_dependencies.insert(public_dependencies_,
2441 public_dependencies_ + public_dependency_count_);
2442 weak_dependencies.insert(weak_dependencies_,
2443 weak_dependencies_ + weak_dependency_count_);
2445 for (
int i = 0;
i < dependency_count();
i++) {
2446 if (public_dependencies.count(
i) > 0) {
2448 dependency(
i)->
name());
2449 }
else if (weak_dependencies.count(
i) > 0) {
2451 dependency(
i)->
name());
2454 dependency(
i)->
name());
2459 std::vector<int>
path;
2461 SourceLocationCommentPrinter package_comment(
this,
path,
"",
2462 debug_string_options);
2463 package_comment.AddPreComment(&contents);
2465 package_comment.AddPostComment(&contents);
2468 if (FormatLineOptions(0,
options(),
pool(), &contents)) {
2469 contents.append(
"\n");
2474 contents.append(
"\n");
2479 std::set<const Descriptor*> groups;
2486 for (
int i = 0;
i < message_type_count();
i++) {
2488 message_type(
i)->DebugString(0, &contents, debug_string_options,
2490 contents.append(
"\n");
2494 for (
int i = 0;
i < service_count();
i++) {
2495 service(
i)->DebugString(&contents, debug_string_options);
2496 contents.append(
"\n");
2502 if (
i > 0) contents.append(
"}\n\n");
2508 debug_string_options);
2512 comment_printer.AddPostComment(&contents);
2531 bool include_opening_clause)
const {
2539 SourceLocationCommentPrinter comment_printer(
this,
prefix,
2540 debug_string_options);
2541 comment_printer.AddPreComment(contents);
2543 if (include_opening_clause) {
2546 contents->append(
" {\n");
2553 std::set<const Descriptor*> groups;
2577 debug_string_options);
2581 debug_string_options);
2601 debug_string_options);
2617 contents->replace(contents->size() - 2, 2,
";\n");
2626 contents->replace(contents->size() - 2, 2,
";\n");
2630 comment_printer.AddPostComment(contents);
2642 if (is_extension()) {
2648 if (is_extension()) {
2649 contents.append(
"}\n");
2662 return kTypeToName[
type()];
2682 bool print_label =
true;
2686 if (is_optional() && (print_label_flag == OMIT_LABEL ||
2688 print_label =
false;
2689 }
else if (is_map()) {
2690 print_label =
false;
2695 label.push_back(
' ');
2698 SourceLocationCommentPrinter comment_printer(
this,
prefix,
2699 debug_string_options);
2700 comment_printer.AddPreComment(contents);
2706 bool bracketed =
false;
2707 if (has_default_value()) {
2710 DefaultValueAsString(
true));
2712 if (has_json_name_) {
2715 contents->append(
"[");
2717 contents->append(
", ");
2719 contents->append(
"json_name = \"");
2720 contents->append(
CEscape(json_name()));
2721 contents->append(
"\"");
2726 &formatted_options)) {
2727 contents->append(bracketed ?
", " :
" [");
2729 contents->append(formatted_options);
2733 contents->append(
"]");
2736 if (
type() == TYPE_GROUP) {
2738 contents->append(
" { ... };\n");
2744 contents->append(
";\n");
2747 comment_printer.AddPostComment(contents);
2767 SourceLocationCommentPrinter comment_printer(
this,
prefix,
2768 debug_string_options);
2769 comment_printer.AddPreComment(contents);
2776 contents->append(
" ... }\n");
2778 contents->append(
"\n");
2781 debug_string_options);
2785 comment_printer.AddPostComment(contents);
2806 SourceLocationCommentPrinter comment_printer(
this,
prefix,
2807 debug_string_options);
2808 comment_printer.AddPreComment(contents);
2814 for (
int i = 0;
i < value_count();
i++) {
2815 value(
i)->DebugString(
depth, contents, debug_string_options);
2829 contents->replace(contents->size() - 2, 2,
";\n");
2838 contents->replace(contents->size() - 2, 2,
";\n");
2843 comment_printer.AddPostComment(contents);
2863 SourceLocationCommentPrinter comment_printer(
this,
prefix,
2864 debug_string_options);
2865 comment_printer.AddPreComment(contents);
2871 &formatted_options)) {
2874 contents->append(
";\n");
2876 comment_printer.AddPostComment(contents);
2894 SourceLocationCommentPrinter comment_printer(
this,
"",
2895 debug_string_options);
2896 comment_printer.AddPreComment(contents);
2902 for (
int i = 0;
i < method_count();
i++) {
2906 contents->append(
"}\n");
2908 comment_printer.AddPostComment(contents);
2929 SourceLocationCommentPrinter comment_printer(
this,
prefix,
2930 debug_string_options);
2931 comment_printer.AddPreComment(contents);
2934 contents,
"$0rpc $1($4.$2) returns ($5.$3)",
prefix,
name(),
2936 client_streaming() ?
"stream " :
"", server_streaming() ?
"stream " :
"");
2940 &formatted_options)) {
2944 contents->append(
";\n");
2947 comment_printer.AddPostComment(contents);
2956 if (source_code_info_) {
2958 tables_->GetSourceLocation(
path, source_code_info_)) {
2960 if (span.
size() == 3 || span.
size() == 4) {
2969 loc->leading_detached_comments().begin(),
2970 loc->leading_detached_comments().end());
2979 std::vector<int>
path;
2984 if (!is_packable())
return false;
2993 std::vector<int>
path;
2999 std::vector<int>
path;
3005 std::vector<int>
path;
3011 std::vector<int>
path;
3017 std::vector<int>
path;
3019 return service()->file()->GetSourceLocation(
path, out_location);
3023 std::vector<int>
path;
3030 std::vector<int>
path;
3032 return type()->file()->GetSourceLocation(
path, out_location);
3047 if (is_extension()) {
3048 if (extension_scope() ==
nullptr) {
3052 extension_scope()->GetLocationPath(
output);
3092 service()->GetLocationPath(
output);
3106 struct OptionsToInterpret {
3108 const std::vector<int>&
path,
const Message* orig_opt,
3127 DescriptorPool::ErrorCollector* error_collector);
3184 void AddNotDefinedError(
3211 bool build_it =
true);
3216 bool build_it =
true);
3236 ResolveMode resolve_mode = LOOKUP_ALL,
3237 bool build_it =
true);
3243 ResolveMode resolve_mode = LOOKUP_ALL,
3244 bool build_it =
true);
3267 template <
typename Type>
3276 template <
class DescriptorT>
3277 void AllocateOptions(
const typename DescriptorT::OptionsType& orig_options,
3278 DescriptorT*
descriptor,
int options_field_tag);
3280 void AllocateOptions(
const FileOptions& orig_options,
3284 template <
class DescriptorT>
3285 void AllocateOptionsImpl(
3287 const typename DescriptorT::OptionsType& orig_options,
3288 DescriptorT*
descriptor,
const std::vector<int>& options_path);
3305 BuildFieldOrExtension(proto, parent, result,
false);
3309 BuildFieldOrExtension(proto, parent, result,
true);
3313 Descriptor::ExtensionRange* result);
3316 Descriptor::ReservedRange* result);
3319 EnumDescriptor::ReservedRange* result);
3346 void CrossLinkExtensionRange(Descriptor::ExtensionRange*
range,
3358 void InterpretOptions();
3373 bool InterpretOptions(OptionsToInterpret* options_to_interpret);
3389 const std::vector<int>& src_path,
3390 const std::vector<int>& options_path);
3401 bool ExamineIfOptionIsSet(
3402 std::vector<const FieldDescriptor*>::const_iterator
3403 intermediate_fields_iter,
3404 std::vector<const FieldDescriptor*>::const_iterator
3405 intermediate_fields_end,
3435 builder_->AddError(options_to_interpret_->element_name,
3436 *uninterpreted_option_,
location, msg);
3494 return pool->allow_unknown_;
3497 return pool->enforce_weak_;
3503 if (
pool->mutex_ !=
nullptr) {
3504 pool->mutex_->AssertHeld();
3552 <<
"Cannot call BuildFile on a DescriptorPool that uses a "
3553 "DescriptorDatabase. You must instead find a way to get your file "
3554 "into the underlying database.";
3556 tables_->known_bad_symbols_.clear();
3557 tables_->known_bad_files_.clear();
3564 <<
"Cannot call BuildFile on a DescriptorPool that uses a "
3565 "DescriptorDatabase. You must instead find a way to get your file "
3566 "into the underlying database.";
3568 tables_->known_bad_symbols_.clear();
3569 tables_->known_bad_files_.clear();
3577 if (tables_->known_bad_files_.count(proto.
name()) > 0) {
3583 if (result ==
nullptr) {
3584 tables_->known_bad_files_.insert(proto.
name());
3591 DescriptorPool::ErrorCollector* error_collector)
3596 possible_undeclared_dependency_(nullptr),
3597 undefine_resolved_name_(
"") {}
3631 "\"" + undefined_symbol +
"\" is not defined.");
3636 "\" seems to be defined in \"" +
3641 "\". To use it here, please "
3642 "add the necessary import.");
3646 "\"" + undefined_symbol +
"\" is resolved to \"" +
3648 "\", which is not defined. "
3649 "The innermost scope is searched first in name resolution. "
3650 "Consider using a leading '.'(i.e., \"." +
3651 undefined_symbol +
"\") to start from the outermost scope.");
3671 (file->
package().size() == package_name.size() ||
3672 file->
package()[package_name.size()] ==
'.');
3676 if (file ==
nullptr || !
dependencies_.insert(file).second)
return;
3689 if (result.
IsNull() &&
pool->underlay_ !=
nullptr) {
3702 if (build_it &&
pool->TryFindSymbolInFallbackDatabase(
name)) {
3703 result =
pool->tables_->FindSymbol(
name);
3718 if (result.
IsNull())
return result;
3742 for (std::set<const FileDescriptor*>::const_iterator
it =
3761 if (!
name.empty() &&
name[0] ==
'.') {
3777 std::string::size_type name_dot_pos =
name.find_first_of(
'.');
3779 if (name_dot_pos == std::string::npos) {
3780 first_part_of_name =
name;
3782 first_part_of_name =
name.substr(0, name_dot_pos);
3789 std::string::size_type dot_pos = scope_to_try.find_last_of(
'.');
3790 if (dot_pos == std::string::npos) {
3793 scope_to_try.erase(dot_pos);
3797 std::string::size_type old_size = scope_to_try.size();
3798 scope_to_try.append(1,
'.');
3799 scope_to_try.append(first_part_of_name);
3802 if (first_part_of_name.size() <
name.size()) {
3806 scope_to_try.append(
name, first_part_of_name.size(),
3807 name.size() - first_part_of_name.size());
3826 scope_to_try.erase(old_size);
3845 bool last_was_period =
false;
3847 for (
int i = 0;
i <
name.size();
i++) {
3852 last_was_period =
false;
3853 }
else if (
name[
i] ==
'.') {
3854 if (last_was_period)
return false;
3855 last_was_period =
true;
3861 return !
name.empty() && !last_was_period;
3881 if (
name[0] ==
'.') {
3883 placeholder_full_name =
tables_->AllocateString(
name.substr(1));
3885 placeholder_full_name =
tables_->AllocateString(
name);
3888 std::string::size_type dotpos = placeholder_full_name->find_last_of(
'.');
3889 if (dotpos != std::string::npos) {
3890 placeholder_package =
3891 tables_->AllocateString(placeholder_full_name->substr(0, dotpos));
3893 tables_->AllocateString(placeholder_full_name->substr(dotpos + 1));
3896 placeholder_name = placeholder_full_name;
3901 *placeholder_full_name +
".placeholder.proto");
3902 placeholder_file->
package_ = placeholder_package;
3909 memset(
static_cast<void*
>(placeholder_enum), 0,
sizeof(*placeholder_enum));
3911 placeholder_enum->full_name_ = placeholder_full_name;
3912 placeholder_enum->name_ = placeholder_name;
3913 placeholder_enum->file_ = placeholder_file;
3915 placeholder_enum->is_placeholder_ =
true;
3916 placeholder_enum->is_unqualified_placeholder_ = (
name[0] !=
'.');
3919 placeholder_enum->value_count_ = 1;
3923 memset(
static_cast<void*
>(placeholder_value), 0,
3924 sizeof(*placeholder_value));
3926 placeholder_value->name_ =
tables_->AllocateString(
"PLACEHOLDER_VALUE");
3928 placeholder_value->full_name_ =
3929 placeholder_package->empty()
3930 ? placeholder_value->name_
3931 :
tables_->AllocateString(*placeholder_package +
3932 ".PLACEHOLDER_VALUE");
3934 placeholder_value->number_ = 0;
3935 placeholder_value->type_ = placeholder_enum;
3938 return Symbol(placeholder_enum);
3944 memset(
static_cast<void*
>(placeholder_message), 0,
3945 sizeof(*placeholder_message));
3947 placeholder_message->full_name_ = placeholder_full_name;
3948 placeholder_message->name_ = placeholder_name;
3949 placeholder_message->file_ = placeholder_file;
3951 placeholder_message->is_placeholder_ =
true;
3952 placeholder_message->is_unqualified_placeholder_ = (
name[0] !=
'.');
3955 placeholder_message->extension_range_count_ = 1;
3956 placeholder_message->extension_ranges_ =
3957 tables_->AllocateArray<Descriptor::ExtensionRange>(1);
3958 placeholder_message->extension_ranges_->start = 1;
3960 placeholder_message->extension_ranges_->end =
3964 return Symbol(placeholder_message);
3980 memset(
static_cast<void*
>(placeholder), 0,
sizeof(*placeholder));
3984 placeholder->
pool_ =
this;
4001 if (parent ==
nullptr) parent =
file_;
4003 if (
tables_->AddSymbol(full_name, symbol)) {
4009 <<
"\" not previously defined in "
4010 "symbols_by_name_, but was defined in "
4011 "symbols_by_parent_; this shouldn't be possible.";
4018 if (other_file ==
file_) {
4019 std::string::size_type dot_pos = full_name.find_last_of(
'.');
4020 if (dot_pos == std::string::npos) {
4022 "\"" + full_name +
"\" is already defined.");
4025 "\"" + full_name.substr(dot_pos + 1) +
4026 "\" is already defined in \"" +
4027 full_name.substr(0, dot_pos) +
"\".");
4032 "\"" + full_name +
"\" is already defined in file \"" +
4033 other_file->
name() +
"\".");
4044 std::string::size_type dot_pos =
name.find_last_of(
'.');
4045 if (dot_pos == std::string::npos) {
4062 "\" is already defined (as something other than "
4063 "a package) in file \"" +
4076 for (
int i = 0;
i <
name.size();
i++) {
4082 "\"" +
name +
"\" is not a valid identifier.");
4092 template <
class DescriptorT>
4094 const typename DescriptorT::OptionsType& orig_options,
4095 DescriptorT*
descriptor,
int options_field_tag) {
4096 std::vector<int> options_path;
4098 options_path.push_back(options_field_tag);
4106 std::vector<int> options_path;
4113 template <
class DescriptorT>
4116 const typename DescriptorT::OptionsType& orig_options,
4117 DescriptorT*
descriptor,
const std::vector<int>& options_path) {
4122 typename DescriptorT::OptionsType*
const dummy =
nullptr;
4125 if (!orig_options.IsInitialized()) {
4128 "Uninterpreted option is missing name or value.");
4136 options->ParseFromString(orig_options.SerializeAsString());
4146 if (
options->uninterpreted_option_size() > 0) {
4154 #define BUILD_ARRAY(INPUT, OUTPUT, NAME, METHOD, PARENT) \
4155 OUTPUT->NAME##_count_ = INPUT.NAME##_size(); \
4156 AllocateArray(INPUT.NAME##_size(), &OUTPUT->NAME##s_); \
4157 for (int i = 0; i < INPUT.NAME##_size(); i++) { \
4158 METHOD(INPUT.NAME(i), PARENT, OUTPUT->NAME##s_ + i); \
4163 std::string error_message(
"File recursively imports itself: ");
4164 for (
int i = from_here;
i <
tables_->pending_files_.size();
i++) {
4165 error_message.append(
tables_->pending_files_[
i]);
4166 error_message.append(
" -> ");
4168 error_message.append(proto.
name());
4170 if (from_here < tables_->pending_files_.size() - 1) {
4193 "\" was not found or had errors.";
4202 existing_file->
CopyTo(&existing_proto);
4206 proto.has_syntax()) {
4211 return existing_proto.SerializeAsString() == proto.SerializeAsString();
4224 if (existing_file !=
nullptr) {
4228 return existing_file;
4243 for (
int i = 0;
i <
tables_->pending_files_.size();
i++) {
4265 tables_->pending_files_.pop_back();
4276 tables_->ClearLastCheckpoint();
4279 tables_->RollbackToLastCheckpoint();
4306 "Missing field: FileDescriptorProto.name.");
4311 if (proto.
syntax().empty() || proto.
syntax() ==
"proto2") {
4313 }
else if (proto.
syntax() ==
"proto3") {
4318 "Unrecognized syntax: " + proto.
syntax());
4322 if (proto.has_package()) {
4334 if (!
tables_->AddFile(result)) {
4336 "A file with this name is already in the pool.");
4341 if (!result->
package().empty()) {
4346 std::set<std::string> seen_dependencies;
4363 std::set<int> weak_deps;
4368 if (!seen_dependencies.insert(proto.
dependency(
i)).second) {
4377 if (dependency == result) {
4384 if (dependency ==
nullptr) {
4413 int public_dependency_count = 0;
4430 "Invalid public dependency index.");
4447 int weak_dependency_count = 0;
4456 "Invalid weak dependency index.");
4468 if (!proto.has_options()) {
4484 for (std::vector<OptionsToInterpret>::iterator iter =
4490 if (info !=
nullptr) {
4527 if (scope.empty()) {
4528 full_name =
tables_->AllocateString(proto_name);
4530 full_name =
tables_->AllocateEmptyString();
4531 *full_name =
StrCat(scope,
".", proto_name);
4565 for (
int i = 0;
i < reserved_name_count; ++
i) {
4571 if (!proto.has_options()) {
4589 "already-defined range $2 to $3.",
4591 range1.
start(), range1.
end() - 1));
4596 HASH_SET<std::string> reserved_name_set;
4599 if (reserved_name_set.find(
name) == reserved_name_set.end()) {
4600 reserved_name_set.insert(
name);
4604 "Field name \"$0\" is reserved multiple times.",
name));
4617 "Extension range $0 to $1 includes field \"$2\" ($3).",
4630 if (reserved_name_set.find(
field->name()) != reserved_name_set.end()) {
4643 const Descriptor::ReservedRange* range2 = result->
reserved_range(j);
4644 if (range1->end > range2->start && range2->end > range1->start) {
4648 "reserved range $2 to $3.",
4649 range1->start, range1->end - 1,
4650 range2->start, range2->end - 1));
4654 const Descriptor::ExtensionRange* range2 = result->
extension_range(j);
4655 if (range1->end > range2->start && range2->end > range1->start) {
4659 "already-defined range $2 to $3.",
4660 range2->start, range2->end - 1,
4661 range1->start, range1->end - 1));
4670 bool is_extension) {
4687 if (lowercase_name == proto.
name()) {
4700 if (proto.has_json_name()) {
4711 implicit_cast<int>(proto.
type()));
4713 implicit_cast<int>(proto.
label()));
4725 "Message extensions cannot have required fields.");
4739 if (proto.has_default_value() && result->
is_repeated()) {
4742 "Repeated fields can't have default values.");
4746 if (proto.has_default_value()) {
4747 char* end_pos =
nullptr;
4768 std::numeric_limits<float>::infinity();
4771 -std::numeric_limits<float>::infinity();
4774 std::numeric_limits<float>::quiet_NaN();
4783 std::numeric_limits<double>::infinity();
4786 -std::numeric_limits<double>::infinity();
4789 std::numeric_limits<double>::quiet_NaN();
4803 "Boolean default must be true or false.");
4822 "Messages can't have default values.");
4827 if (end_pos !=
nullptr) {
4875 if (result->
number() <= 0) {
4877 "Field numbers must be positive integers.");
4894 "Field numbers $0 through $1 are reserved for the protocol "
4895 "buffer library implementation.",
4901 if (!proto.has_extendee()) {
4904 "FieldDescriptorProto.extendee not set for extension field.");
4911 "FieldDescriptorProto.oneof_index should not be set for "
4918 if (proto.has_extendee()) {
4921 "FieldDescriptorProto.extendee set for non-extension field.");
4932 "out of range for type \"$1\".",
4944 if (!proto.has_options()) {
4957 Descriptor::ExtensionRange* result) {
4958 result->start = proto.
start();
4959 result->end = proto.
end();
4960 if (result->start <= 0) {
4962 "Extension numbers must be positive integers.");
4970 if (result->start >= result->end) {
4972 "Extension range end number must be greater than start number.");
4976 result->options_ =
nullptr;
4978 std::vector<int> options_path;
4985 options_path.push_back(
index);
4988 proto.
options(), result, options_path);
4994 Descriptor::ReservedRange* result) {
4995 result->start = proto.
start();
4996 result->end = proto.
end();
4997 if (result->start <= 0) {
4999 "Reserved numbers must be positive integers.");
5005 const EnumDescriptor* parent, EnumDescriptor::ReservedRange* result) {
5006 result->start = proto.
start();
5007 result->end = proto.
end();
5009 if (result->start > result->end) {
5011 "Reserved range end number must be greater than start number.");
5032 if (!proto.has_options()) {
5070 PrefixRemover remover(result->
name());
5071 std::map<std::string, const EnumValueDescriptor*>
values;
5075 EnumValueToPascalCase(remover.MaybeRemove(
value->name()));
5076 std::pair<std::map<std::string, const EnumValueDescriptor*>::iterator,
bool>
5077 insert_result =
values.insert(std::make_pair(stripped,
value));
5078 bool inserted = insert_result.second;
5086 if (!inserted && insert_result.first->second->name() !=
value->name() &&
5087 insert_result.first->second->number() !=
value->number()) {
5089 "Enum name " +
value->name() +
" has the same name as " +
5090 values[stripped]->name() +
5091 " if you ignore case and strip out the enum name prefix (if any). "
5092 "This is error-prone and can lead to undefined behavior. "
5093 "Please avoid doing this. If you are using allow_alias, please "
5094 "assign the same numeric value to both enums.";
5127 "Enums must contain at least one value.");
5138 for (
int i = 0;
i < reserved_name_count; ++
i) {
5146 if (!proto.has_options()) {
5165 "already-defined range $2 to $3.",
5172 HASH_SET<std::string> reserved_name_set;
5175 if (reserved_name_set.find(
name) == reserved_name_set.end()) {
5176 reserved_name_set.insert(
name);
5180 "Enum value \"$0\" is reserved multiple times.",
name));
5196 if (reserved_name_set.find(
value->name()) != reserved_name_set.end()) {
5210 result->
type_ = parent;
5215 size_t scope_len = parent->
full_name_->size() - parent->
name_->size();
5216 full_name->reserve(scope_len + result->
name_->size());
5217 full_name->append(parent->
full_name_->data(), scope_len);
5218 full_name->append(*result->
name_);
5224 if (!proto.has_options()) {
5234 bool added_to_outer_scope =
5242 bool added_to_inner_scope =
5245 if (added_to_inner_scope && !added_to_outer_scope) {
5256 if (outer_scope.empty()) {
5257 outer_scope =
"the global scope";
5259 outer_scope =
"\"" + outer_scope +
"\"";
5263 "Note that enum values use C++ scoping rules, meaning that "
5264 "enum values are siblings of their type, not children of it. "
5266 result->
name() +
"\" must be unique within " + outer_scope +
5267 ", not just within \"" + parent->
name() +
"\".");
5289 if (!proto.has_options()) {
5317 if (!proto.has_options()) {
5359 if (
message->options_ ==
nullptr) {
5363 for (
int i = 0;
i <
message->nested_type_count();
i++) {
5367 for (
int i = 0;
i <
message->enum_type_count();
i++) {
5371 for (
int i = 0;
i <
message->field_count();
i++) {
5375 for (
int i = 0;
i <
message->extension_count();
i++) {
5379 for (
int i = 0;
i <
message->extension_range_count();
i++) {
5387 for (
int i = 0;
i <
message->field_count();
i++) {
5389 if (oneof_decl !=
nullptr) {
5397 message->field(
i - 1)->containing_oneof() != oneof_decl) {
5401 "Fields in the same oneof must be defined consecutively. "
5402 "\"$0\" cannot be defined before the completion of the "
5403 "\"$1\" oneof definition.",
5408 ++
message->oneof_decls_[oneof_decl->
index()].field_count_;
5413 for (
int i = 0;
i <
message->oneof_decl_count();
i++) {
5419 "Oneof must have at least one field.");
5426 if (oneof_decl->
options_ ==
nullptr) {
5432 for (
int i = 0;
i <
message->field_count();
i++) {
5434 if (oneof_decl !=
nullptr) {
5445 Descriptor::ExtensionRange*
range,
5447 if (
range->options_ ==
nullptr) {
5454 if (
field->options_ ==
nullptr) {
5461 if (proto.has_extendee()) {
5473 "\"" + proto.
extendee() +
"\" is not a message type.");
5478 const Descriptor::ExtensionRange* extension_range =
5479 field->containing_type()->FindExtensionRangeContainingNumber(
5482 if (extension_range ==
nullptr) {
5486 "extension number.",
5487 field->containing_type()->full_name(),
5492 if (
field->containing_oneof() !=
nullptr) {
5498 "Fields of oneofs must themselves have label LABEL_OPTIONAL.");
5502 if (proto.has_type_name()) {
5507 proto.has_default_value();
5525 if (
type.IsNull()) {
5532 if (proto.has_default_value()) {
5533 field->default_value_enum_name_ =
5542 if (
field->is_extension()) {
5552 if (
type.IsNull()) {
5570 "\"" + proto.
type_name() +
"\" is not a type.");
5579 "\"" + proto.
type_name() +
"\" is not a message type.");
5584 if (
field->has_default_value()) {
5587 "Messages can't have default values.");
5593 "\"" + proto.
type_name() +
"\" is not an enum type.");
5596 field->enum_type_ =
type.enum_descriptor;
5598 if (
field->enum_type()->is_placeholder_) {
5601 field->has_default_value_ =
false;
5604 if (
field->has_default_value()) {
5613 "Default value for an enum field must be an identifier.");
5623 field->enum_type()) {
5628 "Enum type \"" +
field->enum_type()->full_name() +
5633 }
else if (
field->enum_type()->value_count() > 0) {
5637 field->default_value_enum_ =
field->enum_type()->value(0);
5641 "Field with primitive type has type_name.");
5647 "Field with message or enum type missing type_name.");
5661 field->containing_type() ==
nullptr
5663 :
field->containing_type()->full_name();
5664 if (
field->is_extension()) {
5668 "in \"$1\" by extension \"$2\".",
5669 field->number(), containing_type_name,
5675 "\"$1\" by field \"$2\".",
5676 field->number(), containing_type_name,
5677 conflicting_field->
name()));
5680 if (
field->is_extension()) {
5685 field->containing_type() ==
nullptr
5687 :
field->containing_type()->full_name();
5689 "Extension number $0 has already been used in \"$1\" by extension "
5690 "\"$2\" defined in $3.",
5691 field->number(), containing_type_name,
5718 if (enum_value->
options_ ==
nullptr) {
5725 if (service->
options_ ==
nullptr) {
5744 if (input_type.
IsNull()) {
5755 "\"" + proto.
input_type() +
"\" is not a message type.");
5764 if (output_type.
IsNull()) {
5775 "\"" + proto.
output_type() +
"\" is not a message type.");
5783 #define VALIDATE_OPTIONS_FROM_ARRAY(descriptor, array_name, type) \
5784 for (int i = 0; i < descriptor->array_name##_count(); ++i) { \
5785 Validate##type##Options(descriptor->array_name##s_ + i, \
5786 proto.array_name(i)); \
5794 return file !=
nullptr &&
5813 "Files that do not use optimize_for = LITE_RUNTIME cannot import "
5814 "files which do use this option. This file is not lite, but it "
5841 for (
int i = 0;
i <
name.size(); ++
i) {
5842 if (
name[
i] !=
'_') {
5844 result.push_back(
name[
i] -
'A' +
'a');
5846 result.push_back(
name[
i]);
5855 for (
int i = 0;
i <
message->nested_type_count(); ++
i) {
5858 for (
int i = 0;
i <
message->enum_type_count(); ++
i) {
5861 for (
int i = 0;
i <
message->field_count(); ++
i) {
5864 for (
int i = 0;
i <
message->extension_count(); ++
i) {
5867 if (
message->extension_range_count() > 0) {
5870 "Extension ranges are not allowed in proto3.");
5872 if (
message->options().message_set_wire_format()) {
5875 "MessageSet is not supported in proto3.");
5881 std::map<std::string, const FieldDescriptor*> name_to_field;
5882 for (
int i = 0;
i <
message->field_count(); ++
i) {
5885 if (name_to_field.find(lowercase_name) != name_to_field.end()) {
5888 "The JSON camel-case name of field \"" +
5889 message->field(
i)->name() +
"\" conflicts with field \"" +
5890 name_to_field[lowercase_name]->name() +
"\". This is not " +
5891 "allowed in proto3.");
5893 name_to_field[lowercase_name] =
message->field(
i);
5900 if (
field->is_extension() &&
5901 !AllowedExtendeeInProto3(
field->containing_type()->full_name())) {
5904 "Extensions in proto3 are only allowed for defining options.");
5906 if (
field->is_required()) {
5908 "Required fields are not allowed in proto3.");
5910 if (
field->has_default_value()) {
5913 "Explicit default values are not allowed in proto3.");
5916 field->enum_type() &&
5921 "Enum type \"" +
field->enum_type()->full_name() +
5922 "\" is not a proto3 enum, but is used in \"" +
5923 field->containing_type()->full_name() +
5924 "\" which is a proto3 message type.");
5928 "Groups are not supported in proto3 syntax.");
5937 "The first enum value must be zero in proto3.");
5948 const int64 max_extension_range =
5949 static_cast<int64>(
message->options().message_set_wire_format()
5952 for (
int i = 0;
i <
message->extension_range_count(); ++
i) {
5953 if (
message->extension_range(
i)->end > max_extension_range + 1) {
5958 max_extension_range));
5970 if (
field->options().lazy()) {
5973 "[lazy = true] can only be specified for submessage fields.");
5978 if (
field->options().packed() && !
field->is_packable()) {
5981 "[packed = true] can only be specified for repeated primitive fields.");
5986 if (
field->containing_type_ !=
nullptr &&
5987 &
field->containing_type()->options() !=
5989 field->containing_type()->options().message_set_wire_format()) {
5990 if (
field->is_extension()) {
5991 if (!
field->is_optional() ||
5995 "Extensions of MessageSets must be optional messages.");
5999 "MessageSets cannot have fields, only extensions.");
6008 "Extensions to non-lite types can only be declared in non-lite "
6009 "files. Note that you cannot extend a non-lite type to contain "
6010 "a lite type, but the reverse is allowed.");
6014 if (
field->is_map()) {
6017 "map_entry should not be set explicitly. Use map<KeyType, "
6018 "ValueType> instead.");
6033 if (
field->is_extension() &&
6034 (
field->has_json_name() &&
6035 field->json_name() != ToJsonName(
field->name()))) {
6038 "option json_name is not allowed on extension fields.");
6047 std::map<int, std::string> used_values;
6050 if (used_values.find(enum_value->
number()) != used_values.end()) {
6053 "\" uses the same enum value as \"" +
6054 used_values[enum_value->
number()] +
6055 "\". If this is intended, set "
6056 "'option allow_alias = true;' to the enum definition.";
6080 "Files with optimize_for = LITE_RUNTIME cannot define services "
6081 "unless you set both options cc_generic_services and "
6082 "java_generic_services to false.");
6098 message->extension_count() != 0 ||
6100 message->extension_range_count() != 0 ||
6101 message->nested_type_count() != 0 ||
message->enum_type_count() != 0 ||
6103 message->field_count() != 2 ||
6107 field->containing_type() !=
message->containing_type()) {
6114 key->name() !=
"key") {
6118 value->number() != 2 ||
value->name() !=
"value") {
6123 switch (
key->type()) {
6126 "Key in map fields cannot be enum types.");
6135 "Key in map fields cannot be float/double, bytes or message types.");
6156 if (
value->enum_type()->value(0)->number() != 0) {
6158 "Enum value in map must define 0 as the first value.");
6167 std::map<std::string, const Descriptor*> seen_types;
6168 for (
int i = 0;
i <
message->nested_type_count(); ++
i) {
6170 std::pair<std::map<std::string, const Descriptor*>::iterator,
bool> result =
6171 seen_types.insert(std::make_pair(nested->
name(), nested));
6172 if (!result.second) {
6173 if (result.first->second->options().map_entry() ||
6177 "Expanded map entry type " + nested->
name() +
6178 " conflicts with an existing nested message type.");
6185 for (
int i = 0;
i <
message->field_count(); ++
i) {
6187 std::map<std::string, const Descriptor*>::iterator iter =
6188 seen_types.find(
field->name());
6189 if (iter != seen_types.end() && iter->second->options().map_entry()) {
6192 "Expanded map entry type " + iter->second->name() +
6193 " conflicts with an existing field.");
6197 for (
int i = 0;
i <
message->enum_type_count(); ++
i) {
6199 std::map<std::string, const Descriptor*>::iterator iter =
6200 seen_types.find(enum_desc->
name());
6201 if (iter != seen_types.end() && iter->second->options().map_entry()) {
6204 "Expanded map entry type " + iter->second->name() +
6205 " conflicts with an existing enum type.");
6209 for (
int i = 0;
i <
message->oneof_decl_count(); ++
i) {
6211 std::map<std::string, const Descriptor*>::iterator iter =
6212 seen_types.find(oneof_desc->
name());
6213 if (iter != seen_types.end() && iter->second->options().map_entry()) {
6216 "Expanded map entry type " + iter->second->name() +
6217 " conflicts with an existing oneof type.");
6230 switch (
field->type()) {
6243 "Illegal jstype for int64, uint64, sint64, fixed64 "
6244 "or sfixed64 field: " +
6251 "jstype is only allowed on int64, uint64, sint64, fixed64 "
6252 "or sfixed64 fields.");
6257 #undef VALIDATE_OPTIONS_FROM_ARRAY
6263 : builder_(builder) {
6270 OptionsToInterpret* options_to_interpret) {
6276 bool failed =
false;
6282 options->GetDescriptor()->FindFieldByName(
"uninterpreted_option");
6284 <<
"No field named \"uninterpreted_option\" in the Options proto.";
6285 options->GetReflection()->ClearField(
options, uninterpreted_options_field);
6287 std::vector<int> src_path = options_to_interpret->element_path;
6288 src_path.push_back(uninterpreted_options_field->
number());
6293 "uninterpreted_option");
6294 GOOGLE_CHECK(original_uninterpreted_options_field !=
nullptr)
6295 <<
"No field named \"uninterpreted_option\" in the Options proto.";
6297 const int num_uninterpreted_options =
6300 for (
int i = 0;
i < num_uninterpreted_options; ++
i) {
6301 src_path.push_back(
i);
6302 uninterpreted_option_ = down_cast<const UninterpretedOption*>(
6305 if (!InterpretSingleOption(
options, src_path,
6306 options_to_interpret->element_path)) {
6311 src_path.pop_back();
6314 uninterpreted_option_ =
nullptr;
6328 std::unique_ptr<Message> unparsed_options(
options->New());
6332 if (!unparsed_options->AppendToString(&
buf) ||
6337 "Some options could not be correctly parsed using the proto "
6338 "descriptors compiled into this binary.\n"
6339 "Unparsed options: " +
6340 unparsed_options->ShortDebugString() +
6342 "Parsing attempt: " +
6353 const std::vector<int>& options_path) {
6355 if (uninterpreted_option_->name_size() == 0) {
6358 return AddNameError(
"Option must have a name.");
6360 if (uninterpreted_option_->name(0).name_part() ==
"uninterpreted_option") {
6361 return AddNameError(
6362 "Option must not use reserved name "
6363 "\"uninterpreted_option\".");
6366 const Descriptor* options_descriptor =
nullptr;
6377 Symbol symbol = builder_->FindSymbolNotEnforcingDeps(
6378 options->GetDescriptor()->full_name());
6385 options_descriptor =
options->GetDescriptor();
6397 std::vector<const FieldDescriptor*> intermediate_fields;
6400 std::vector<int> dest_path = options_path;
6402 for (
int i = 0;
i < uninterpreted_option_->name_size(); ++
i) {
6403 const std::string& name_part = uninterpreted_option_->name(
i).name_part();
6404 if (debug_msg_name.size() > 0) {
6405 debug_msg_name +=
".";
6407 if (uninterpreted_option_->name(
i).is_extension()) {
6408 debug_msg_name +=
"(" + name_part +
")";
6424 debug_msg_name += name_part;
6429 if (
field ==
nullptr) {
6433 AddWithoutInterpreting(*uninterpreted_option_,
options);
6435 }
else if (!(builder_->undefine_resolved_name_).empty()) {
6437 return AddNameError(
6438 "Option \"" + debug_msg_name +
"\" is resolved to \"(" +
6439 builder_->undefine_resolved_name_ +
6440 ")\", which is not defined. The innermost scope is searched first "
6441 "in name resolution. Consider using a leading '.'(i.e., \"(." +
6442 debug_msg_name.substr(1) +
6443 "\") to start from the outermost scope.");
6445 return AddNameError(
6446 "Option \"" + debug_msg_name +
6447 "\" unknown. Ensure that your proto" +
6448 " definition file imports the proto which defines the option.");
6457 AddWithoutInterpreting(*uninterpreted_option_,
options);
6463 return AddNameError(
"Option field \"" + debug_msg_name +
6464 "\" is not a field or extension of message \"" +
6469 dest_path.push_back(
field->number());
6471 if (i < uninterpreted_option_->name_size() - 1) {
6473 return AddNameError(
"Option \"" + debug_msg_name +
6474 "\" is an atomic type, not a message.");
6475 }
else if (
field->is_repeated()) {
6476 return AddNameError(
"Option field \"" + debug_msg_name +
6477 "\" is a repeated message. Repeated message "
6478 "options must be initialized using an "
6479 "aggregate value.");
6482 intermediate_fields.push_back(
field);
6497 if (!
field->is_repeated() &&
6498 !ExamineIfOptionIsSet(
6499 intermediate_fields.begin(), intermediate_fields.end(),
field,
6507 std::unique_ptr<UnknownFieldSet> unknown_fields(
new UnknownFieldSet());
6508 if (!SetOptionValue(
field, unknown_fields.get())) {
6514 for (std::vector<const FieldDescriptor*>::reverse_iterator iter =
6515 intermediate_fields.rbegin();
6516 iter != intermediate_fields.rend(); ++iter) {
6517 std::unique_ptr<UnknownFieldSet> parent_unknown_fields(
6519 switch ((*iter)->type()) {
6522 parent_unknown_fields->AddLengthDelimited((*iter)->number()));
6526 <<
"Unexpected failure while serializing option submessage "
6527 << debug_msg_name <<
"\".";
6532 parent_unknown_fields->AddGroup((*iter)->number())
6533 ->MergeFrom(*unknown_fields);
6542 unknown_fields.reset(parent_unknown_fields.release());
6547 options->GetReflection()->MutableUnknownFields(
options)->MergeFrom(
6551 if (
field->is_repeated()) {
6552 int index = repeated_option_counts_[dest_path]++;
6553 dest_path.push_back(
index);
6555 interpreted_paths_[src_path] = dest_path;
6562 if (interpreted_paths_.empty()) {
6579 bool copying =
false;
6581 std::vector<int> pathv;
6582 bool matched =
false;
6585 loc != locs->
end(); loc++) {
6588 bool loc_matches =
true;
6589 if (loc->path_size() < pathv.size()) {
6590 loc_matches =
false;
6592 for (
int j = 0; j < pathv.size(); j++) {
6593 if (loc->path(j) != pathv[j]) {
6594 loc_matches =
false;
6609 for (
int j = 0; j < loc->path_size(); j++) {
6610 pathv.push_back(loc->path(j));
6613 std::map<std::vector<int>, std::vector<int>>::iterator entry =
6614 interpreted_paths_.find(pathv);
6616 if (entry == interpreted_paths_.end()) {
6619 *new_locs.
Add() = *loc;
6633 *new_locs.
Add() = *
it;
6639 *replacement = *loc;
6641 for (std::vector<int>::iterator rit = entry->second.begin();
6642 rit != entry->second.end(); rit++) {
6656 options->GetDescriptor()->FindFieldByName(
"uninterpreted_option");
6661 ->CopyFrom(uninterpreted_option);
6665 std::vector<const FieldDescriptor*>::const_iterator
6666 intermediate_fields_iter,
6667 std::vector<const FieldDescriptor*>::const_iterator intermediate_fields_end,
6674 if (intermediate_fields_iter == intermediate_fields_end) {
6678 return AddNameError(
"Option \"" + debug_msg_name +
6679 "\" was already set.");
6687 (*intermediate_fields_iter)->number()) {
6697 !ExamineIfOptionIsSet(intermediate_fields_iter + 1,
6698 intermediate_fields_end, innermost_field,
6700 intermediate_unknown_fields)) {
6708 if (!ExamineIfOptionIsSet(intermediate_fields_iter + 1,
6709 intermediate_fields_end, innermost_field,
6710 debug_msg_name, unknown_field->
group())) {
6728 switch (option_field->
cpp_type()) {
6730 if (uninterpreted_option_->has_positive_int_value()) {
6731 if (uninterpreted_option_->positive_int_value() >
6733 return AddValueError(
"Value out of range for int32 option \"" +
6736 SetInt32(option_field->
number(),
6737 uninterpreted_option_->positive_int_value(),
6738 option_field->
type(), unknown_fields);
6740 }
else if (uninterpreted_option_->has_negative_int_value()) {
6741 if (uninterpreted_option_->negative_int_value() <
6743 return AddValueError(
"Value out of range for int32 option \"" +
6746 SetInt32(option_field->
number(),
6747 uninterpreted_option_->negative_int_value(),
6748 option_field->
type(), unknown_fields);
6751 return AddValueError(
"Value must be integer for int32 option \"" +
6757 if (uninterpreted_option_->has_positive_int_value()) {
6758 if (uninterpreted_option_->positive_int_value() >
6760 return AddValueError(
"Value out of range for int64 option \"" +
6763 SetInt64(option_field->
number(),
6764 uninterpreted_option_->positive_int_value(),
6765 option_field->
type(), unknown_fields);
6767 }
else if (uninterpreted_option_->has_negative_int_value()) {
6768 SetInt64(option_field->
number(),
6769 uninterpreted_option_->negative_int_value(),
6770 option_field->
type(), unknown_fields);
6772 return AddValueError(
"Value must be integer for int64 option \"" +
6778 if (uninterpreted_option_->has_positive_int_value()) {
6779 if (uninterpreted_option_->positive_int_value() >
kuint32max) {
6780 return AddValueError(
"Value out of range for uint32 option \"" +
6781 option_field->
name() +
"\".");
6783 SetUInt32(option_field->
number(),
6784 uninterpreted_option_->positive_int_value(),
6785 option_field->
type(), unknown_fields);
6788 return AddValueError(
6789 "Value must be non-negative integer for uint32 "
6796 if (uninterpreted_option_->has_positive_int_value()) {
6797 SetUInt64(option_field->
number(),
6798 uninterpreted_option_->positive_int_value(),
6799 option_field->
type(), unknown_fields);
6801 return AddValueError(
6802 "Value must be non-negative integer for uint64 "
6810 if (uninterpreted_option_->has_double_value()) {
6811 value = uninterpreted_option_->double_value();
6812 }
else if (uninterpreted_option_->has_positive_int_value()) {
6813 value = uninterpreted_option_->positive_int_value();
6814 }
else if (uninterpreted_option_->has_negative_int_value()) {
6815 value = uninterpreted_option_->negative_int_value();
6817 return AddValueError(
"Value must be number for float option \"" +
6827 if (uninterpreted_option_->has_double_value()) {
6828 value = uninterpreted_option_->double_value();
6829 }
else if (uninterpreted_option_->has_positive_int_value()) {
6830 value = uninterpreted_option_->positive_int_value();
6831 }
else if (uninterpreted_option_->has_negative_int_value()) {
6832 value = uninterpreted_option_->negative_int_value();
6834 return AddValueError(
"Value must be number for double option \"" +
6844 if (!uninterpreted_option_->has_identifier_value()) {
6845 return AddValueError(
6846 "Value must be identifier for boolean option "
6850 if (uninterpreted_option_->identifier_value() ==
"true") {
6852 }
else if (uninterpreted_option_->identifier_value() ==
"false") {
6855 return AddValueError(
6856 "Value must be \"true\" or \"false\" for boolean "
6864 if (!uninterpreted_option_->has_identifier_value()) {
6865 return AddValueError(
6866 "Value must be identifier for enum-valued option "
6871 const std::string& value_name = uninterpreted_option_->identifier_value();
6878 fully_qualified_name.resize(fully_qualified_name.size() -
6880 fully_qualified_name += value_name;
6887 builder_->FindSymbolNotEnforcingDeps(fully_qualified_name);
6890 return AddValueError(
6891 "Enum type \"" +
enum_type->full_name() +
6892 "\" has no value named \"" + value_name +
"\" for option \"" +
6894 "\". This appears to be a value from a sibling type.");
6902 enum_value =
enum_type->FindValueByName(value_name);
6905 if (enum_value ==
nullptr) {
6906 return AddValueError(
"Enum type \"" +
6908 "\" has no value named \"" + value_name +
6923 if (!uninterpreted_option_->has_string_value()) {
6924 return AddValueError(
6925 "Value must be quoted string for string option "
6931 uninterpreted_option_->string_value());
6935 if (!SetAggregateOption(option_field, unknown_fields)) {
6959 descriptor->options().message_set_wire_format()) {
6971 extension->message_type() == foreign_type) {
7007 if (!uninterpreted_option_->has_aggregate_value()) {
7008 return AddValueError(
"Option \"" + option_field->
full_name() +
7009 "\" is a message. To set the entire message, use "
7011 option_field->
name() +
7012 " = { <proto text format> }\". "
7013 "To set fields within it, use "
7015 option_field->
name() +
".foo = value\".");
7019 std::unique_ptr<Message> dynamic(dynamic_factory_.GetPrototype(
type)->New());
7021 <<
"Could not create an instance of " << option_field->
DebugString();
7023 AggregateErrorCollector collector;
7027 parser.RecordErrorsTo(&collector);
7028 parser.SetFinder(&finder);
7029 if (!
parser.ParseFromString(uninterpreted_option_->aggregate_value(),
7031 AddValueError(
"Error while parsing option value for \"" +
7032 option_field->
name() +
"\": " + collector.error_);
7036 dynamic->SerializeToString(&serial);
7042 group->ParseFromString(serial);
7135 std::set<std::string> annotation_extensions;
7136 annotation_extensions.insert(
"google.protobuf.MessageOptions");
7137 annotation_extensions.insert(
"google.protobuf.FileOptions");
7138 annotation_extensions.insert(
"google.protobuf.FieldOptions");
7139 annotation_extensions.insert(
"google.protobuf.EnumOptions");
7140 annotation_extensions.insert(
"google.protobuf.EnumValueOptions");
7141 annotation_extensions.insert(
"google.protobuf.EnumValueOptions");
7142 annotation_extensions.insert(
"google.protobuf.ServiceOptions");
7143 annotation_extensions.insert(
"google.protobuf.MethodOptions");
7144 annotation_extensions.insert(
"google.protobuf.StreamOptions");
7145 for (std::set<const FileDescriptor*>::const_iterator
it =
7150 for (
i = 0;
i < (*it)->extension_count(); ++
i) {
7151 if (annotation_extensions.find(
7152 (*it)->extension(
i)->containing_type()->full_name()) !=
7153 annotation_extensions.end()) {
7158 if (
i == (*it)->extension_count()) {
7160 "Import " + (*it)->name() +
" but not used.";
7169 bool expecting_enum)
const {
7171 if (!lookup_name.empty() && lookup_name[0] ==
'.') {
7172 lookup_name = lookup_name.substr(1);
7174 Symbol result =
tables_->FindByNameHelper(
this, lookup_name);
7185 Symbol result = file()->pool()->CrossLinkOnDemandHelper(
7195 if (enum_type_ && !default_value_enum_) {
7196 if (default_value_enum_name_) {
7201 std::string::size_type last_dot =
name.find_last_of(
'.');
7202 if (last_dot != std::string::npos) {
7203 name =
name.substr(0, last_dot) +
"." + *default_value_enum_name_;
7205 name = *default_value_enum_name_;
7207 Symbol result = file()->pool()->CrossLinkOnDemandHelper(
name,
true);
7212 if (!default_value_enum_) {
7216 default_value_enum_ = enum_type_->value(0);
7232 return message_type_;
7246 return default_value_enum_;
7250 const bool is_message_set_extension =
7252 containing_type()->options().message_set_wire_format() &&
7255 return is_message_set_extension ?
message_type()->full_name() : full_name();
7260 for (
int i = 0;
i < dependency_count();
i++) {
7261 if (dependencies_names_[
i]) {
7272 if (dependencies_once_) {
7282 return input_type_.Get();
7286 return output_type_.Get();
7313 void LazyDescriptor::Once() {
7321 void LazyDescriptor::OnceInternal() {