1 | /* |
2 | * |
3 | * Copyright 2015 gRPC authors. |
4 | * |
5 | * Licensed under the Apache License, Version 2.0 (the "License"); |
6 | * you may not use this file except in compliance with the License. |
7 | * You may obtain a copy of the License at |
8 | * |
9 | * http://www.apache.org/licenses/LICENSE-2.0 |
10 | * |
11 | * Unless required by applicable law or agreed to in writing, software |
12 | * distributed under the License is distributed on an "AS IS" BASIS, |
13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
14 | * See the License for the specific language governing permissions and |
15 | * limitations under the License. |
16 | * |
17 | */ |
18 | |
19 | #ifndef GRPC_INTERNAL_COMPILER_RUBY_GENERATOR_STRING_INL_H |
20 | #define GRPC_INTERNAL_COMPILER_RUBY_GENERATOR_STRING_INL_H |
21 | |
22 | #include "src/compiler/config.h" |
23 | |
24 | #include <algorithm> |
25 | #include <sstream> |
26 | #include <vector> |
27 | |
28 | using std::getline; |
29 | using std::transform; |
30 | |
31 | namespace grpc_ruby_generator { |
32 | |
33 | // Split splits a string using char into elems. |
34 | inline std::vector<grpc::string>& Split(const grpc::string& s, char delim, |
35 | std::vector<grpc::string>* elems) { |
36 | std::stringstream ss(s); |
37 | grpc::string item; |
38 | while (getline(ss, item, delim)) { |
39 | elems->push_back(item); |
40 | } |
41 | return *elems; |
42 | } |
43 | |
44 | // Split splits a string using char, returning the result in a vector. |
45 | inline std::vector<grpc::string> Split(const grpc::string& s, char delim) { |
46 | std::vector<grpc::string> elems; |
47 | Split(s, delim, &elems); |
48 | return elems; |
49 | } |
50 | |
51 | // Replace replaces from with to in s. |
52 | inline grpc::string Replace(grpc::string s, const grpc::string& from, |
53 | const grpc::string& to) { |
54 | size_t start_pos = s.find(from); |
55 | if (start_pos == grpc::string::npos) { |
56 | return s; |
57 | } |
58 | s.replace(start_pos, from.length(), to); |
59 | return s; |
60 | } |
61 | |
62 | // ReplaceAll replaces all instances of search with replace in s. |
63 | inline grpc::string ReplaceAll(grpc::string s, const grpc::string& search, |
64 | const grpc::string& replace) { |
65 | size_t pos = 0; |
66 | while ((pos = s.find(search, pos)) != grpc::string::npos) { |
67 | s.replace(pos, search.length(), replace); |
68 | pos += replace.length(); |
69 | } |
70 | return s; |
71 | } |
72 | |
73 | // ReplacePrefix replaces from with to in s if search is a prefix of s. |
74 | inline bool ReplacePrefix(grpc::string* s, const grpc::string& from, |
75 | const grpc::string& to) { |
76 | size_t start_pos = s->find(from); |
77 | if (start_pos == grpc::string::npos || start_pos != 0) { |
78 | return false; |
79 | } |
80 | s->replace(start_pos, from.length(), to); |
81 | return true; |
82 | } |
83 | |
84 | // Modularize converts a string into a ruby module compatible name |
85 | inline grpc::string Modularize(grpc::string s) { |
86 | if (s.empty()) { |
87 | return s; |
88 | } |
89 | grpc::string new_string = "" ; |
90 | bool was_last_underscore = false; |
91 | new_string.append(1, ::toupper(s[0])); |
92 | for (grpc::string::size_type i = 1; i < s.size(); ++i) { |
93 | if (was_last_underscore && s[i] != '_') { |
94 | new_string.append(1, ::toupper(s[i])); |
95 | } else if (s[i] != '_') { |
96 | new_string.append(1, s[i]); |
97 | } |
98 | was_last_underscore = s[i] == '_'; |
99 | } |
100 | return new_string; |
101 | } |
102 | |
103 | // RubyPackage gets the ruby package in either proto or ruby_package format |
104 | inline grpc::string RubyPackage(const grpc::protobuf::FileDescriptor* file) { |
105 | grpc::string package_name = file->package(); |
106 | if (file->options().has_ruby_package()) { |
107 | package_name = file->options().ruby_package(); |
108 | |
109 | // If :: is in the package convert the Ruby formatted name |
110 | // -> A::B::C |
111 | // to use the dot seperator notation |
112 | // -> A.B.C |
113 | package_name = ReplaceAll(package_name, "::" , "." ); |
114 | } |
115 | return package_name; |
116 | } |
117 | |
118 | // RubyTypeOf updates a proto type to the required ruby equivalent. |
119 | inline grpc::string RubyTypeOf(const grpc::protobuf::Descriptor* descriptor, |
120 | const grpc::string& package) { |
121 | std::string proto_type = descriptor->full_name(); |
122 | if (descriptor->file()->options().has_ruby_package()) { |
123 | proto_type = RubyPackage(descriptor->file()) + "." + descriptor->name(); |
124 | } |
125 | grpc::string res(proto_type); |
126 | ReplacePrefix(&res, package, "" ); // remove the leading package if present |
127 | ReplacePrefix(&res, "." , "" ); // remove the leading . (no package) |
128 | if (res.find('.') == grpc::string::npos) { |
129 | return res; |
130 | } else { |
131 | std::vector<grpc::string> prefixes_and_type = Split(res, '.'); |
132 | res.clear(); |
133 | for (unsigned int i = 0; i < prefixes_and_type.size(); ++i) { |
134 | if (i != 0) { |
135 | res += "::" ; // switch '.' to the ruby module delim |
136 | } |
137 | if (i < prefixes_and_type.size() - 1) { |
138 | res += Modularize(prefixes_and_type[i]); // capitalize pkgs |
139 | } else { |
140 | res += prefixes_and_type[i]; |
141 | } |
142 | } |
143 | return res; |
144 | } |
145 | } |
146 | |
147 | } // namespace grpc_ruby_generator |
148 | |
149 | #endif // GRPC_INTERNAL_COMPILER_RUBY_GENERATOR_STRING_INL_H |
150 | |