| /* | |
| * | |
| * Copyright 2015 gRPC authors. | |
| * | |
| * Licensed under the Apache License, Version 2.0 (the "License"); | |
| * you may not use this file except in compliance with the License. | |
| * You may obtain a copy of the License at | |
| * | |
| * http://www.apache.org/licenses/LICENSE-2.0 | |
| * | |
| * Unless required by applicable law or agreed to in writing, software | |
| * distributed under the License is distributed on an "AS IS" BASIS, | |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
| * See the License for the specific language governing permissions and | |
| * limitations under the License. | |
| * | |
| */ | |
| #ifndef GRPC_INTERNAL_COMPILER_PYTHON_GENERATOR_HELPERS_H | |
| #define GRPC_INTERNAL_COMPILER_PYTHON_GENERATOR_HELPERS_H | |
| #include <cstring> | |
| #include <fstream> | |
| #include <iostream> | |
| #include <vector> | |
| #include "src/compiler/config.h" | |
| #include "src/compiler/generator_helpers.h" | |
| #include "src/compiler/python_generator.h" | |
| #include "src/compiler/python_private_generator.h" | |
| using grpc::protobuf::Descriptor; | |
| using grpc::protobuf::FileDescriptor; | |
| using grpc::protobuf::MethodDescriptor; | |
| using grpc::protobuf::ServiceDescriptor; | |
| using grpc::protobuf::compiler::GeneratorContext; | |
| using grpc::protobuf::io::CodedOutputStream; | |
| using grpc::protobuf::io::Printer; | |
| using grpc::protobuf::io::StringOutputStream; | |
| using grpc::protobuf::io::ZeroCopyOutputStream; | |
| using grpc_generator::StringReplace; | |
| using grpc_generator::StripProto; | |
| using std::vector; | |
| namespace grpc_python_generator { | |
| namespace { | |
| typedef vector<const Descriptor*> DescriptorVector; | |
| typedef vector<std::string> StringVector; | |
| static std::string StripModulePrefixes( | |
| const std::string& raw_module_name, | |
| const std::vector<std::string>& prefixes_to_filter) { | |
| for (const auto& prefix : prefixes_to_filter) { | |
| if (raw_module_name.rfind(prefix, 0) == 0) { | |
| return raw_module_name.substr(prefix.size(), | |
| raw_module_name.size() - prefix.size()); | |
| } | |
| } | |
| return raw_module_name; | |
| } | |
| // TODO(https://github.com/protocolbuffers/protobuf/issues/888): | |
| // Export `ModuleName` from protobuf's | |
| // `src/google/protobuf/compiler/python/python_generator.cc` file. | |
| std::string ModuleName(const std::string& filename, | |
| const std::string& import_prefix, | |
| const std::vector<std::string>& prefixes_to_filter) { | |
| std::string basename = StripProto(filename); | |
| basename = StringReplace(basename, "-", "_"); | |
| basename = StringReplace(basename, "/", "."); | |
| return StripModulePrefixes(import_prefix + basename + "_pb2", | |
| prefixes_to_filter); | |
| } | |
| // TODO(https://github.com/protocolbuffers/protobuf/issues/888): | |
| // Export `ModuleAlias` from protobuf's | |
| // `src/google/protobuf/compiler/python/python_generator.cc` file. | |
| std::string ModuleAlias(const std::string& filename, | |
| const std::string& import_prefix, | |
| const std::vector<std::string>& prefixes_to_filter) { | |
| std::string module_name = | |
| ModuleName(filename, import_prefix, prefixes_to_filter); | |
| // We can't have dots in the module name, so we replace each with _dot_. | |
| // But that could lead to a collision between a.b and a_dot_b, so we also | |
| // duplicate each underscore. | |
| module_name = StringReplace(module_name, "_", "__"); | |
| module_name = StringReplace(module_name, ".", "_dot_"); | |
| return module_name; | |
| } | |
| bool GetModuleAndMessagePath( | |
| const Descriptor* type, std::string* out, std::string generator_file_name, | |
| bool generate_in_pb2_grpc, std::string& import_prefix, | |
| const std::vector<std::string>& prefixes_to_filter) { | |
| const Descriptor* path_elem_type = type; | |
| DescriptorVector message_path; | |
| do { | |
| message_path.push_back(path_elem_type); | |
| path_elem_type = path_elem_type->containing_type(); | |
| } while (path_elem_type); // implicit nullptr comparison; don't be explicit | |
| std::string file_name = type->file()->name(); | |
| static const int proto_suffix_length = strlen(".proto"); | |
| if (!(file_name.size() > static_cast<size_t>(proto_suffix_length) && | |
| file_name.find_last_of(".proto") == file_name.size() - 1)) { | |
| return false; | |
| } | |
| std::string module; | |
| if (generator_file_name != file_name || generate_in_pb2_grpc) { | |
| module = ModuleAlias(file_name, import_prefix, prefixes_to_filter) + "."; | |
| } else { | |
| module = ""; | |
| } | |
| std::string message_type; | |
| for (DescriptorVector::reverse_iterator path_iter = message_path.rbegin(); | |
| path_iter != message_path.rend(); ++path_iter) { | |
| message_type += (*path_iter)->name() + "."; | |
| } | |
| // no pop_back prior to C++11 | |
| message_type.resize(message_type.size() - 1); | |
| *out = module + message_type; | |
| return true; | |
| } | |
| template <typename DescriptorType> | |
| StringVector get_all_comments(const DescriptorType* descriptor) { | |
| StringVector comments; | |
| grpc_generator::GetComment( | |
| descriptor, grpc_generator::COMMENTTYPE_LEADING_DETACHED, &comments); | |
| grpc_generator::GetComment(descriptor, grpc_generator::COMMENTTYPE_LEADING, | |
| &comments); | |
| grpc_generator::GetComment(descriptor, grpc_generator::COMMENTTYPE_TRAILING, | |
| &comments); | |
| return comments; | |
| } | |
| inline void Split(const std::string& s, char delim, | |
| std::vector<std::string>* append_to) { | |
| if (s.empty()) { | |
| // splitting an empty string logically produces a single-element list | |
| append_to->emplace_back(); | |
| } else { | |
| auto current = s.begin(); | |
| while (current < s.end()) { | |
| const auto next = std::find(current, s.end(), delim); | |
| append_to->emplace_back(current, next); | |
| current = next; | |
| if (current != s.end()) { | |
| // it was the delimiter - need to be at the start of the next entry | |
| ++current; | |
| } | |
| } | |
| } | |
| } | |
| } // namespace | |
| } // namespace grpc_python_generator | |
| #endif // GRPC_INTERNAL_COMPILER_PYTHON_GENERATOR_HELPERS_H |