Chromium Code Reviews| Index: components/tracing/tools/proto_zero_plugin/proto_zero_generator.cc |
| diff --git a/components/tracing/tools/proto_zero_plugin/proto_zero_generator.cc b/components/tracing/tools/proto_zero_plugin/proto_zero_generator.cc |
| index 2165673b362eeefc3bbb110ca2e0be0fa6aac01c..055cbe759dda51227492034c18fdb1919a2dbb44 100644 |
| --- a/components/tracing/tools/proto_zero_plugin/proto_zero_generator.cc |
| +++ b/components/tracing/tools/proto_zero_plugin/proto_zero_generator.cc |
| @@ -26,6 +26,7 @@ using google::protobuf::compiler::GeneratorContext; |
| using google::protobuf::io::Printer; |
| using google::protobuf::io::ZeroCopyOutputStream; |
| +using google::protobuf::LowerString; |
| using google::protobuf::Split; |
| using google::protobuf::StripPrefixString; |
| using google::protobuf::StripString; |
| @@ -38,6 +39,93 @@ inline std::string ProtoStubName(const FileDescriptor* proto) { |
| return StripSuffixString(proto->name(), ".proto") + ".pbzero"; |
| } |
| +enum CharCase { |
| + UPPER, |
| + LOWER, |
| + DIGIT, |
| + SYMBOL, |
| + UNDEFINED, |
| +}; |
| + |
| +inline CharCase GetCaseOfChar(char x) { |
| + if ('A' <= x && x <= 'Z') |
| + return CharCase::UPPER; |
|
Primiano Tucci (use gerrit)
2016/08/05 08:52:05
I think here you are reinventing cctype's isupper(
kraynov
2016/08/05 11:05:53
Acknowledged.
|
| + else if ('a' <= x && x <= 'z') |
| + return CharCase::LOWER; |
| + else if ('0' <= x && x <= '9') |
| + return CharCase::DIGIT; |
| + else |
| + return CharCase::SYMBOL; |
| +} |
| + |
| +std::string ExtractWord(const std::string& source, size_t* offset) { |
| + std::string word; |
| + CharCase start_case = CharCase::UNDEFINED; |
| + CharCase end_case = CharCase::UNDEFINED; |
| + |
| + while (*offset < source.size()) { |
| + char current = source.at(*offset); |
| + CharCase current_case = GetCaseOfChar(current); |
| + |
| + // Skip underscores. |
| + if (current_case == CharCase::SYMBOL) { |
| + while (current_case == CharCase::SYMBOL) { |
| + (*offset)++; |
| + if (*offset == source.size()) |
| + return word; |
| + current = source.at(*offset); |
| + current_case = GetCaseOfChar(current); |
| + } |
| + if (!word.empty()) |
| + return word; |
| + } |
| + // Current case must be UPPER, LOWER or DIGIT below this line. |
| + |
| + // Detect word's case. |
| + if (word.empty()) { |
| + start_case = current_case; |
| + if (start_case == CharCase::LOWER || start_case == CharCase::DIGIT) { |
| + end_case = start_case; |
| + } |
| + } else if (end_case == CharCase::UNDEFINED) { |
| + // Must be a second character in this condition. |
| + // Word starting with upper letter has two options (e.g. FOO or Bar). |
| + end_case = current_case; |
| + } |
| + |
| + // Finish the word if case changes. |
| + if (current_case != end_case && end_case != CharCase::UNDEFINED) { |
| + if (end_case == CharCase::UPPER && current_case == CharCase::LOWER) { |
| + // Rollback one character. |
| + // E.g. [URL]Encoder, not [URLE]ncoder. |
| + (*offset)--; |
| + word.erase(word.size() - 1, 1); |
| + } |
| + return word; |
| + } |
| + |
| + word.push_back(current); |
| + (*offset)++; |
| + } |
| + return word; |
| +} |
| + |
| +std::string NameToCamelCase(const std::string& name) { |
| + std::string camel; |
| + size_t offset = 0; |
| + while (offset < name.size()) { |
| + // Offset is mutable by ExtractWord function. |
| + std::string word = ExtractWord(name, &offset); |
| + if (word.empty()) |
| + continue; |
| + LowerString(&word); |
| + if (GetCaseOfChar(word.at(0)) == LOWER) |
| + word.at(0) -= ('a' - 'A'); |
| + camel += word; |
| + } |
| + return camel; |
| +} |
| + |
| class GeneratorJob { |
| public: |
| GeneratorJob(const FileDescriptor *file, |
| @@ -463,7 +551,27 @@ class GeneratorJob { |
| } |
| } |
| - // Fields descriptors. |
| + // Field numbers. |
| + if (message->field_count() > 0) { |
| + stub_h_->Print("enum : int32_t {\n"); |
| + stub_h_->Indent(); |
| + |
| + for (int i = 0; i < message->field_count(); ++i) { |
| + const FieldDescriptor* field = message->field(i); |
| + std::string name = NameToCamelCase(field->name()); |
|
Primiano Tucci (use gerrit)
2016/08/05 08:52:05
can you not just use field->camelcase_name()
kraynov
2016/08/05 11:05:53
Acknowledged.
|
| + if (name.empty()) |
| + Abort("Empty field name in camel case notation."); |
| + |
| + stub_h_->Print( |
| + "k$name$FieldNumber = $id$,\n", |
| + "name", name, |
| + "id", std::to_string(field->number())); |
| + } |
| + stub_h_->Outdent(); |
| + stub_h_->Print("};\n"); |
| + } |
| + |
| + // Field descriptors. |
| for (int i = 0; i < message->field_count(); ++i) { |
| const FieldDescriptor* field = message->field(i); |
| if (field->is_packed()) { |