1062
1103
plugins_[plugin_name] = path;
1105
} else if (name == "--print_free_field_numbers") {
1106
if (mode_ != MODE_COMPILE) {
1107
cerr << "Cannot use " << name << " and use --encode, --decode or print "
1108
<< "other info at the same time." << endl;
1109
return PARSE_ARGUMENT_FAIL;
1111
if (!output_directives_.empty() || !descriptor_set_name_.empty()) {
1112
cerr << "Cannot use " << name
1113
<< " and generate code or descriptors at the same time." << endl;
1114
return PARSE_ARGUMENT_FAIL;
1117
print_mode_ = PRINT_FREE_FIELDS;
1065
1119
// Some other flag. Look it up in the generators list.
1066
1120
const GeneratorInfo* generator_info =
1151
1205
" well as surrounding comments.\n"
1152
1206
" --error_format=FORMAT Set the format in which to print errors.\n"
1153
1207
" FORMAT may be 'gcc' (the default) or 'msvs'\n"
1154
" (Microsoft Visual Studio format)." << endl;
1208
" (Microsoft Visual Studio format).\n"
1209
" --print_free_field_numbers Print the free field numbers of the messages\n"
1210
" defined in the given proto files. Groups share\n"
1211
" the same field number space with the parent \n"
1212
" message. Extension ranges are counted as \n"
1213
" occupied fields numbers." << endl;
1155
1214
if (!plugin_prefix_.empty()) {
1157
1216
" --plugin=EXECUTABLE Specifies a plugin executable to use.\n"
1495
// Utility function for PrintFreeFieldNumbers.
1496
// Stores occupied ranges into the ranges parameter, and next level of sub
1497
// message types into the nested_messages parameter. The FieldRange is left
1498
// inclusive, right exclusive. i.e. [a, b).
1501
// Note that it only stores the nested message type, iff the nested type is
1502
// either a direct child of the given descriptor, or the nested type is a
1503
// decendent of the given descriptor and all the nodes between the
1504
// nested type and the given descriptor are group types. e.g.
1508
// message NestedBar {}
1511
// group NestedBazGroup = 2 {
1513
// message NestedQuz {}
1516
// message NestedBaz {}
1520
// In this case, Bar, Quz and NestedBaz will be added into the nested types.
1521
// Since free field numbers of group types will not be printed, this makes sure
1522
// the nested message types in groups will not be dropped. The nested_messages
1523
// parameter will contain the direct children (when groups are ignored in the
1524
// tree) of the given descriptor for the caller to traverse. The declaration
1525
// order of the nested messages is also preserved.
1526
typedef pair<int, int> FieldRange;
1527
void GatherOccupiedFieldRanges(const Descriptor* descriptor,
1528
set<FieldRange>* ranges,
1529
vector<const Descriptor*>* nested_messages) {
1530
set<const Descriptor*> groups;
1531
for (int i = 0; i < descriptor->field_count(); ++i) {
1532
const FieldDescriptor* fd = descriptor->field(i);
1533
ranges->insert(FieldRange(fd->number(), fd->number() + 1));
1534
if (fd->type() == FieldDescriptor::TYPE_GROUP) {
1535
groups.insert(fd->message_type());
1538
for (int i = 0; i < descriptor->extension_range_count(); ++i) {
1539
ranges->insert(FieldRange(descriptor->extension_range(i)->start,
1540
descriptor->extension_range(i)->end));
1542
// Handle the nested messages/groups in declaration order to make it
1543
// post-order strict.
1544
for (int i = 0; i < descriptor->nested_type_count(); ++i) {
1545
const Descriptor* nested_desc = descriptor->nested_type(i);
1546
if (groups.find(nested_desc) != groups.end()) {
1547
GatherOccupiedFieldRanges(nested_desc, ranges, nested_messages);
1549
nested_messages->push_back(nested_desc);
1554
// Utility function for PrintFreeFieldNumbers.
1555
// Actually prints the formatted free field numbers for given message name and
1557
void FormatFreeFieldNumbers(const string& name,
1558
const set<FieldRange>& ranges) {
1560
StringAppendF(&output, "%-35s free:", name.c_str());
1561
int next_free_number = 1;
1562
for (set<FieldRange>::iterator i = ranges.begin();
1563
i != ranges.end(); ++i) {
1564
// This happens when groups re-use parent field numbers, in which
1565
// case we skip the FieldRange entirely.
1566
if (next_free_number >= i->second) continue;
1568
if (next_free_number < i->first) {
1569
if (next_free_number + 1 == i->first) {
1571
StringAppendF(&output, " %d", next_free_number);
1574
StringAppendF(&output, " %d-%d", next_free_number, i->first - 1);
1577
next_free_number = i->second;
1579
if (next_free_number <= FieldDescriptor::kMaxNumber) {
1580
StringAppendF(&output, " %d-INF", next_free_number);
1582
cout << output << endl;
1587
void CommandLineInterface::PrintFreeFieldNumbers(
1588
const Descriptor* descriptor) {
1589
set<FieldRange> ranges;
1590
vector<const Descriptor*> nested_messages;
1591
GatherOccupiedFieldRanges(descriptor, &ranges, &nested_messages);
1593
for (int i = 0; i < nested_messages.size(); ++i) {
1594
PrintFreeFieldNumbers(nested_messages[i]);
1596
FormatFreeFieldNumbers(descriptor->full_name(), ranges);
1435
1601
} // namespace compiler
1436
1602
} // namespace protobuf