blob: 905ed354049b24c654c11fbc33515c26026bb1e8 [file] [log] [blame]
Yi Jin0473f88b2017-10-09 11:21:40 -07001#include "Errors.h"
Yi Jinf9ed04b2017-10-20 16:17:58 -07002#include "stream_proto_utils.h"
Yi Jin0473f88b2017-10-09 11:21:40 -07003#include "string_utils.h"
4
Yi Jin0473f88b2017-10-09 11:21:40 -07005#include <iomanip>
6#include <iostream>
7#include <sstream>
8
9using namespace android::stream_proto;
Yi Jin0473f88b2017-10-09 11:21:40 -070010using namespace google::protobuf::io;
11using namespace std;
12
Yi Jinf68e7472017-12-18 15:55:19 -080013const bool GENERATE_MAPPING = true;
14
Yi Jin0473f88b2017-10-09 11:21:40 -070015static string
16make_filename(const FileDescriptorProto& file_descriptor)
17{
18 return file_descriptor.name() + ".h";
19}
20
Yi Jin0473f88b2017-10-09 11:21:40 -070021static void
22write_enum(stringstream& text, const EnumDescriptorProto& enu, const string& indent)
23{
24 const int N = enu.value_size();
25 text << indent << "// enum " << enu.name() << endl;
26 for (int i=0; i<N; i++) {
27 const EnumValueDescriptorProto& value = enu.value(i);
Yi Jin0dfa7522017-11-06 17:43:47 -080028 text << indent << "const int "
Yi Jin0473f88b2017-10-09 11:21:40 -070029 << make_constant_name(value.name())
30 << " = " << value.number() << ";" << endl;
31 }
Yi Jine2f7f792017-11-01 17:08:27 -070032
Yi Jinf68e7472017-12-18 15:55:19 -080033 if (GENERATE_MAPPING) {
Yi Jine2f7f792017-11-01 17:08:27 -070034 string name = make_constant_name(enu.name());
35 string prefix = name + "_";
Mike Maa47ad722020-01-28 22:04:20 -080036 text << indent << "static const int _ENUM_" << name << "_COUNT = " << N << ";" << endl;
37 text << indent << "static const char* _ENUM_" << name << "_NAMES[" << N << "] = {" << endl;
Yi Jine2f7f792017-11-01 17:08:27 -070038 for (int i=0; i<N; i++) {
39 text << indent << INDENT << "\"" << stripPrefix(enu.value(i).name(), prefix) << "\"," << endl;
40 }
41 text << indent << "};" << endl;
Mike Maa47ad722020-01-28 22:04:20 -080042 text << indent << "static const int _ENUM_" << name << "_VALUES[" << N << "] = {" << endl;
Yi Jine2f7f792017-11-01 17:08:27 -070043 for (int i=0; i<N; i++) {
44 text << indent << INDENT << make_constant_name(enu.value(i).name()) << "," << endl;
45 }
46 text << indent << "};" << endl;
47 }
48
Yi Jin0473f88b2017-10-09 11:21:40 -070049 text << endl;
50}
51
Yi Jin0473f88b2017-10-09 11:21:40 -070052static void
53write_field(stringstream& text, const FieldDescriptorProto& field, const string& indent)
54{
55 string optional_comment = field.label() == FieldDescriptorProto::LABEL_OPTIONAL
56 ? "optional " : "";
57 string repeated_comment = field.label() == FieldDescriptorProto::LABEL_REPEATED
58 ? "repeated " : "";
59 string proto_type = get_proto_type(field);
60 string packed_comment = field.options().packed()
61 ? " [packed=true]" : "";
62 text << indent << "// " << optional_comment << repeated_comment << proto_type << ' '
63 << field.name() << " = " << field.number() << packed_comment << ';' << endl;
64
65 text << indent << "const uint64_t " << make_constant_name(field.name()) << " = 0x";
66
67 ios::fmtflags fmt(text.flags());
68 text << setfill('0') << setw(16) << hex << get_field_id(field);
69 text.flags(fmt);
70
71 text << "LL;" << endl;
72
73 text << endl;
74}
75
76static void
Yi Jinf68e7472017-12-18 15:55:19 -080077write_message(stringstream& text, const DescriptorProto& message, const string& indent)
Yi Jin0473f88b2017-10-09 11:21:40 -070078{
79 int N;
80 const string indented = indent + INDENT;
81
82 text << indent << "// message " << message.name() << endl;
Yi Jin04625ad2017-10-17 18:29:33 -070083 text << indent << "namespace " << message.name() << " {" << endl;
Yi Jin0473f88b2017-10-09 11:21:40 -070084
85 // Enums
86 N = message.enum_type_size();
87 for (int i=0; i<N; i++) {
88 write_enum(text, message.enum_type(i), indented);
89 }
90
91 // Nested classes
92 N = message.nested_type_size();
93 for (int i=0; i<N; i++) {
Yi Jinf68e7472017-12-18 15:55:19 -080094 write_message(text, message.nested_type(i), indented);
Yi Jin0473f88b2017-10-09 11:21:40 -070095 }
96
97 // Fields
98 N = message.field_size();
99 for (int i=0; i<N; i++) {
100 write_field(text, message.field(i), indented);
101 }
102
Yi Jinf68e7472017-12-18 15:55:19 -0800103 if (GENERATE_MAPPING) {
Yi Jin04625ad2017-10-17 18:29:33 -0700104 N = message.field_size();
Mike Maa47ad722020-01-28 22:04:20 -0800105 text << indented << "static const int _FIELD_COUNT = " << N << ";" << endl;
106 text << indented << "static const char* _FIELD_NAMES[" << N << "] = {" << endl;
Yi Jin04625ad2017-10-17 18:29:33 -0700107 for (int i=0; i<N; i++) {
108 text << indented << INDENT << "\"" << message.field(i).name() << "\"," << endl;
109 }
110 text << indented << "};" << endl;
Mike Maa47ad722020-01-28 22:04:20 -0800111 text << indented << "static const uint64_t _FIELD_IDS[" << N << "] = {" << endl;
Yi Jin04625ad2017-10-17 18:29:33 -0700112 for (int i=0; i<N; i++) {
113 text << indented << INDENT << make_constant_name(message.field(i).name()) << "," << endl;
114 }
115 text << indented << "};" << endl << endl;
116 }
117
118 text << indent << "} //" << message.name() << endl;
Yi Jin0473f88b2017-10-09 11:21:40 -0700119 text << endl;
120}
121
Ethan Lee58e60db2023-07-14 21:56:33 +0000122static void write_header_file(const string& request_parameter, CodeGeneratorResponse* response,
123 const FileDescriptorProto& file_descriptor) {
Yi Jin0473f88b2017-10-09 11:21:40 -0700124 stringstream text;
125
126 text << "// Generated by protoc-gen-cppstream. DO NOT MODIFY." << endl;
127 text << "// source: " << file_descriptor.name() << endl << endl;
128
129 string header = "ANDROID_" + replace_string(file_descriptor.name(), '/', '_');
130 header = replace_string(header, '.', '_') + "_stream_h";
131 header = make_constant_name(header);
132
133 text << "#ifndef " << header << endl;
134 text << "#define " << header << endl;
135 text << endl;
136
137 vector<string> namespaces = split(file_descriptor.package(), '.');
138 for (vector<string>::iterator it = namespaces.begin(); it != namespaces.end(); it++) {
139 text << "namespace " << *it << " {" << endl;
140 }
141 text << endl;
142
143 size_t N;
144 N = file_descriptor.enum_type_size();
145 for (size_t i=0; i<N; i++) {
146 write_enum(text, file_descriptor.enum_type(i), "");
147 }
148
149 N = file_descriptor.message_type_size();
150 for (size_t i=0; i<N; i++) {
Yi Jinf68e7472017-12-18 15:55:19 -0800151 write_message(text, file_descriptor.message_type(i), "");
Yi Jin0473f88b2017-10-09 11:21:40 -0700152 }
153
Mike Maa47ad722020-01-28 22:04:20 -0800154 for (vector<string>::reverse_iterator it = namespaces.rbegin(); it != namespaces.rend(); it++) {
Yi Jin0473f88b2017-10-09 11:21:40 -0700155 text << "} // " << *it << endl;
156 }
157
158 text << endl;
159 text << "#endif // " << header << endl;
160
Ethan Lee58e60db2023-07-14 21:56:33 +0000161 if (request_parameter.find("experimental_allow_proto3_optional") != string::npos) {
162 response->set_supported_features(CodeGeneratorResponse::FEATURE_PROTO3_OPTIONAL);
163 }
Yi Jin0473f88b2017-10-09 11:21:40 -0700164 CodeGeneratorResponse::File* file_response = response->add_file();
165 file_response->set_name(make_filename(file_descriptor));
166 file_response->set_content(text.str());
167}
168
169int main(int argc, char const *argv[])
170{
171 (void)argc;
172 (void)argv;
173
174 GOOGLE_PROTOBUF_VERIFY_VERSION;
175
176 CodeGeneratorRequest request;
177 CodeGeneratorResponse response;
178
179 // Read the request
180 request.ParseFromIstream(&cin);
181
182 // Build the files we need.
183 const int N = request.proto_file_size();
184 for (int i=0; i<N; i++) {
185 const FileDescriptorProto& file_descriptor = request.proto_file(i);
186 if (should_generate_for_file(request, file_descriptor.name())) {
Ethan Lee58e60db2023-07-14 21:56:33 +0000187 write_header_file(request.parameter(), &response, file_descriptor);
Yi Jin0473f88b2017-10-09 11:21:40 -0700188 }
189 }
190
191 // If we had errors, don't write the response. Print the errors and exit.
192 if (ERRORS.HasErrors()) {
193 ERRORS.Print();
194 return 1;
195 }
196
197 // If we didn't have errors, write the response and exit happily.
198 response.SerializeToOstream(&cout);
199
200 /* code */
201 return 0;
Yi Jin04625ad2017-10-17 18:29:33 -0700202}