From: Mark Slee Date: Thu, 12 Oct 2006 02:47:27 +0000 (+0000) Subject: Allow the specification of custom container types in Thrift IDL files X-Git-Tag: 0.2.0~1644 X-Git-Url: https://source.supwisdom.com/gerrit/gitweb?a=commitdiff_plain;h=4f8da1dfb4dc857265506e0c865fe3d9c7cdf771;p=common%2Fthrift.git Allow the specification of custom container types in Thrift IDL files Summary: If you want your map to be a hash_map instead of an stl::map, we now have a directive in Thrift to let you do that. Instead of: map You can do: map[cpp:hash_map] This tells the Thrift compiler to explicitly use whatever type was specified in the brackets when generating C++ code, instead of the implied Thrift type. Reviewed By: aditya git-svn-id: https://svn.apache.org/repos/asf/incubator/thrift/trunk@664828 13f79535-47bb-0310-9956-ffa450edef68 --- diff --git a/compiler/cpp/src/generate/t_cpp_generator.cc b/compiler/cpp/src/generate/t_cpp_generator.cc index 1a2c8aed..46f71c19 100644 --- a/compiler/cpp/src/generate/t_cpp_generator.cc +++ b/compiler/cpp/src/generate/t_cpp_generator.cc @@ -1498,20 +1498,32 @@ string t_cpp_generator::namespace_close(string ns) { string t_cpp_generator::type_name(t_type* ttype) { if (ttype->is_base_type()) { return base_type_name(((t_base_type*)ttype)->get_base()); - } else if (ttype->is_map()) { + } + + // Check for a custom overloaded C++ name + if (ttype->is_container()) { + t_container* tcontainer = (t_container*) ttype; + if (tcontainer->has_cpp_name()) { + return tcontainer->get_cpp_name(); + } + } + // Use std:: types for containers + if (ttype->is_map()) { t_map* tmap = (t_map*) ttype; return "std::map<" + type_name(tmap->get_key_type()) + ", " + type_name(tmap->get_val_type()) + "> "; - } else if (ttype->is_set()) { + } + if (ttype->is_set()) { t_set* tset = (t_set*) ttype; return "std::set<" + type_name(tset->get_elem_type()) + "> "; - } else if (ttype->is_list()) { + } + if (ttype->is_list()) { t_list* tlist = (t_list*) ttype; return "std::vector<" + type_name(tlist->get_elem_type()) + "> "; - } else { - return ttype->get_name(); } + + return ttype->get_name(); } /** diff --git a/compiler/cpp/src/parse/t_container.h b/compiler/cpp/src/parse/t_container.h new file mode 100644 index 00000000..3b9f1327 --- /dev/null +++ b/compiler/cpp/src/parse/t_container.h @@ -0,0 +1,37 @@ +#ifndef T_CONTAINER_H +#define T_CONTAINER_H + +#include "t_type.h" + +class t_container : public t_type { + public: + t_container() : + cpp_name_(), + has_cpp_name_(false) {} + + virtual ~t_container() {} + + void set_cpp_name(std::string cpp_name) { + cpp_name_ = cpp_name; + has_cpp_name_ = true; + } + + bool has_cpp_name() { + return has_cpp_name_; + } + + std::string get_cpp_name() { + return cpp_name_; + } + + bool is_container() const { + return true; + } + + private: + std::string cpp_name_; + bool has_cpp_name_; + +}; + +#endif diff --git a/compiler/cpp/src/parse/t_list.h b/compiler/cpp/src/parse/t_list.h index 5f9b5aa4..bce5c0db 100644 --- a/compiler/cpp/src/parse/t_list.h +++ b/compiler/cpp/src/parse/t_list.h @@ -1,14 +1,14 @@ #ifndef T_LIST_H #define T_LIST_H -#include "t_type.h" +#include "t_container.h" /** * A list is a lightweight container type that just wraps another data type. * * @author Mark Slee */ -class t_list : public t_type { +class t_list : public t_container { public: t_list(t_type* elem_type) : elem_type_(elem_type) {} diff --git a/compiler/cpp/src/parse/t_map.h b/compiler/cpp/src/parse/t_map.h index ff1c5692..fd559326 100644 --- a/compiler/cpp/src/parse/t_map.h +++ b/compiler/cpp/src/parse/t_map.h @@ -1,13 +1,15 @@ #ifndef T_MAP_H #define T_MAP_H +#include "t_container.h" + /** * A map is a lightweight container type that just wraps another two data * types. * * @author Mark Slee */ -class t_map : public t_type { +class t_map : public t_container { public: t_map(t_type* key_type, t_type* val_type) : key_type_(key_type), diff --git a/compiler/cpp/src/parse/t_set.h b/compiler/cpp/src/parse/t_set.h index e39e4202..239868f2 100644 --- a/compiler/cpp/src/parse/t_set.h +++ b/compiler/cpp/src/parse/t_set.h @@ -1,14 +1,14 @@ #ifndef T_SET_H #define T_SET_H -#include "t_type.h" +#include "t_container.h" /** * A set is a lightweight container type that just wraps another data type. * * @author Mark Slee */ -class t_set : public t_type { +class t_set : public t_container { public: t_set(t_type* elem_type) : elem_type_(elem_type) {} diff --git a/compiler/cpp/src/parse/t_type.h b/compiler/cpp/src/parse/t_type.h index 27b85a56..1d0a2ed8 100644 --- a/compiler/cpp/src/parse/t_type.h +++ b/compiler/cpp/src/parse/t_type.h @@ -24,14 +24,11 @@ class t_type { virtual bool is_enum() const { return false; } virtual bool is_struct() const { return false; } virtual bool is_xception() const { return false; } + virtual bool is_container() const { return false; } virtual bool is_list() const { return false; } virtual bool is_set() const { return false; } virtual bool is_map() const { return false; } - bool is_container() const { - return is_map() || is_set() || is_list(); - } - protected: t_type() {} diff --git a/compiler/cpp/src/thrift.l b/compiler/cpp/src/thrift.l index 64a2bf8d..e72565e4 100644 --- a/compiler/cpp/src/thrift.l +++ b/compiler/cpp/src/thrift.l @@ -34,6 +34,7 @@ multicomm ("/*""/"*([^*/]|[^*]"/"|"*"[^/])*"*"*"*/") comment ("//"[^\n]*) unixcomment ("#"[^\n]*) symbol ([\,\{\}\(\)\=<>]) +cpptype ("[cpp:".*"]") %% @@ -64,8 +65,21 @@ symbol ([\,\{\}\(\)\=<>]) "service" { return tok_service; } "enum" { return tok_enum; } -{intconstant} { yylval.iconst = atoi(yytext); return tok_int_constant; } +{intconstant} { + yylval.iconst = atoi(yytext); + return tok_int_constant; +} + +{cpptype} { + yylval.id = strdup(yytext+5); + yylval.id[strlen(yylval.id)-1] = '\0'; + return tok_cpptype; +} + +{identifier} { + yylval.id = strdup(yytext); + return tok_identifier; +} -{identifier} { yylval.id = strdup(yytext); return tok_identifier; } %% diff --git a/compiler/cpp/src/thrift.y b/compiler/cpp/src/thrift.y index 404c80b1..3bf8b539 100644 --- a/compiler/cpp/src/thrift.y +++ b/compiler/cpp/src/thrift.y @@ -44,6 +44,7 @@ int y_field_val = -1; * Strings identifier */ %token tok_identifier +%token tok_cpptype /** * Integer constant value @@ -122,6 +123,7 @@ int y_field_val = -1; %type ThrowsOptional %type AsyncOptional +%type CppTypeOptional %% @@ -449,24 +451,43 @@ ContainerType: } MapType: - tok_map '<' FieldType ',' FieldType '>' + tok_map CppTypeOptional '<' FieldType ',' FieldType '>' { pdebug("MapType -> tok_map "); - $$ = new t_map($3, $5); + $$ = new t_map($4, $6); + if ($2 != NULL) { + ((t_container*)$$)->set_cpp_name(std::string($2)); + } } SetType: - tok_set '<' FieldType '>' + tok_set CppTypeOptional '<' FieldType '>' { pdebug("SetType -> tok_set"); - $$ = new t_set($3); + $$ = new t_set($4); + if ($2 != NULL) { + ((t_container*)$$)->set_cpp_name(std::string($2)); + } } ListType: - tok_list '<' FieldType '>' + tok_list CppTypeOptional '<' FieldType '>' { pdebug("ListType -> tok_list"); - $$ = new t_list($3); + $$ = new t_list($4); + if ($2 != NULL) { + ((t_container*)$$)->set_cpp_name(std::string($2)); + } + } + +CppTypeOptional: + tok_cpptype + { + $$ = $1; + } +| + { + $$ = NULL; } %%