blob: 67a3e785dd501d3ada8cb804a50ac951bd2c44c3 [file] [log] [blame]
David Reissea2cba82009-03-30 21:35:00 +00001/*
2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing,
13 * software distributed under the License is distributed on an
14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 * KIND, either express or implied. See the License for the
16 * specific language governing permissions and limitations
17 * under the License.
18 */
Mark Sleee9ce01c2007-05-16 02:29:53 +000019
Mark Slee31985722006-05-24 21:45:31 +000020#include "t_generator.h"
21using namespace std;
22
23/**
24 * Top level program generation function. Calls the generator subclass methods
25 * for preparing file streams etc. then iterates over all the parts of the
26 * program to perform the correct actions.
27 *
28 * @param program The thrift program to compile into C++ source
29 */
Mark Sleef0712dc2006-10-25 19:03:57 +000030void t_generator::generate_program() {
Mark Slee31985722006-05-24 21:45:31 +000031 // Initialize the generator
Mark Sleef0712dc2006-10-25 19:03:57 +000032 init_generator();
Mark Slee31985722006-05-24 21:45:31 +000033
Mark Slee31985722006-05-24 21:45:31 +000034 // Generate enums
Mark Sleef0712dc2006-10-25 19:03:57 +000035 vector<t_enum*> enums = program_->get_enums();
Mark Slee31985722006-05-24 21:45:31 +000036 vector<t_enum*>::iterator en_iter;
37 for (en_iter = enums.begin(); en_iter != enums.end(); ++en_iter) {
38 generate_enum(*en_iter);
39 }
40
Mark Sleea340e0d2007-01-16 23:00:31 +000041 // Generate typedefs
42 vector<t_typedef*> typedefs = program_->get_typedefs();
43 vector<t_typedef*>::iterator td_iter;
44 for (td_iter = typedefs.begin(); td_iter != typedefs.end(); ++td_iter) {
45 generate_typedef(*td_iter);
46 }
47
Bryan Duxburyab3666e2009-09-01 23:03:47 +000048 // Generate structs, exceptions, and unions in declared order
Mark Slee1c4ced72008-01-14 23:04:43 +000049 vector<t_struct*> objects = program_->get_objects();
50 vector<t_struct*>::iterator o_iter;
51 for (o_iter = objects.begin(); o_iter != objects.end(); ++o_iter) {
52 if ((*o_iter)->is_xception()) {
53 generate_xception(*o_iter);
54 } else {
55 generate_struct(*o_iter);
56 }
Mark Slee9cb7c612006-09-01 22:17:45 +000057 }
58
Jake Farrella6c031a2011-11-21 13:52:51 +000059 // Generate constants
60 vector<t_const*> consts = program_->get_consts();
61 generate_consts(consts);
62
Mark Slee31985722006-05-24 21:45:31 +000063 // Generate services
Mark Sleef0712dc2006-10-25 19:03:57 +000064 vector<t_service*> services = program_->get_services();
Mark Slee31985722006-05-24 21:45:31 +000065 vector<t_service*>::iterator sv_iter;
66 for (sv_iter = services.begin(); sv_iter != services.end(); ++sv_iter) {
Mark Sleee8540632006-05-30 09:24:40 +000067 service_name_ = get_service_name(*sv_iter);
Mark Slee31985722006-05-24 21:45:31 +000068 generate_service(*sv_iter);
69 }
70
71 // Close the generator
Mark Sleef0712dc2006-10-25 19:03:57 +000072 close_generator();
Mark Slee31985722006-05-24 21:45:31 +000073}
Mark Sleeaa7671d2006-11-29 03:19:31 +000074
David Reiss82e6fc02009-03-26 23:32:36 +000075string t_generator::escape_string(const string &in) const {
76 string result = "";
77 for (string::const_iterator it = in.begin(); it < in.end(); it++) {
78 std::map<char, std::string>::const_iterator res = escape_.find(*it);
79 if (res != escape_.end()) {
80 result.append(res->second);
81 } else {
82 result.push_back(*it);
83 }
84 }
85 return result;
86}
87
Mark Sleeaa7671d2006-11-29 03:19:31 +000088void t_generator::generate_consts(vector<t_const*> consts) {
89 vector<t_const*>::iterator c_iter;
90 for (c_iter = consts.begin(); c_iter != consts.end(); ++c_iter) {
91 generate_const(*c_iter);
92 }
93}
David Reissbd0db882008-02-27 01:54:51 +000094
David Reiss39aa00d2009-03-26 08:40:18 +000095void t_generator::generate_docstring_comment(ofstream& out,
96 const string& comment_start,
97 const string& line_prefix,
98 const string& contents,
99 const string& comment_end) {
100 if (comment_start != "") indent(out) << comment_start;
101 stringstream docs(contents, ios_base::in);
102 while (!docs.eof()) {
103 char line[1024];
104 docs.getline(line, 1024);
Bryan Duxbury1316ed92010-09-02 14:20:01 +0000105
106 // Just prnt a newline when the line & prefix are empty.
107 if (strlen(line) == 0 && line_prefix == "" && !docs.eof()) {
108 out << std::endl;
109 } else if (strlen(line) > 0 || !docs.eof()) { // skip the empty last line
David Reiss39aa00d2009-03-26 08:40:18 +0000110 indent(out) << line_prefix << line << std::endl;
111 }
112 }
113 if (comment_end != "") indent(out) << comment_end;
114}
115
David Reissbd0db882008-02-27 01:54:51 +0000116
117void t_generator_registry::register_generator(t_generator_factory* factory) {
118 gen_map_t& the_map = get_generator_map();
119 if (the_map.find(factory->get_short_name()) != the_map.end()) {
120 failure("Duplicate generators for language \"%s\"!\n", factory->get_short_name().c_str());
121 }
122 the_map[factory->get_short_name()] = factory;
123}
124
125t_generator* t_generator_registry::get_generator(t_program* program,
126 const string& options) {
127 string::size_type colon = options.find(':');
128 string language = options.substr(0, colon);
129
130 map<string, string> parsed_options;
131 if (colon != string::npos) {
132 string::size_type pos = colon+1;
133 while (pos != string::npos && pos < options.size()) {
134 string::size_type next_pos = options.find(',', pos);
135 string option = options.substr(pos, next_pos-pos);
136 pos = ((next_pos == string::npos) ? next_pos : next_pos+1);
137
138 string::size_type separator = option.find('=');
139 string key, value;
140 if (separator == string::npos) {
141 key = option;
142 value = "";
143 } else {
144 key = option.substr(0, separator);
145 value = option.substr(separator+1);
146 }
147
148 parsed_options[key] = value;
149 }
150 }
151
152 gen_map_t& the_map = get_generator_map();
153 gen_map_t::iterator iter = the_map.find(language);
154
155 if (iter == the_map.end()) {
156 return NULL;
157 }
158
159 return iter->second->get_generator(program, parsed_options, options);
160}
161
162t_generator_registry::gen_map_t& t_generator_registry::get_generator_map() {
163 // http://www.parashift.com/c++-faq-lite/ctors.html#faq-10.12
164 static gen_map_t* the_map = new gen_map_t();
165 return *the_map;
166}
167
168t_generator_factory::t_generator_factory(
169 const std::string& short_name,
170 const std::string& long_name,
171 const std::string& documentation)
172 : short_name_(short_name)
173 , long_name_(long_name)
174 , documentation_(documentation)
175{
176 t_generator_registry::register_generator(this);
177}