Default values and nullification for thrift code

Summary: All things are null now, unless you specify a default value!

Reviewed By: marc


git-svn-id: https://svn.apache.org/repos/asf/incubator/thrift/trunk@664963 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Mark Slee 2007-02-01 05:26:18 +00:00
parent 29cbeb6235
commit 7ff3245bfa
13 changed files with 286 additions and 246 deletions

View File

@ -373,29 +373,53 @@ void t_cpp_generator::generate_struct_definition(ofstream& out,
vector<t_field*>::const_iterator m_iter;
const vector<t_field*>& members = tstruct->get_members();
// Default constructor
bool init_ctor = false;
if (!pointers) {
// Default constructor
indent(out) <<
tstruct->get_name() << "()";
bool init_ctor = false;
for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
t_type* t = (*m_iter)->get_type();
while (t->is_typedef()) {
t = ((t_typedef*)t)->get_type();
}
if (t->is_base_type() &&
((t_base_type*)t)->get_base() != t_base_type::TYPE_STRING) {
if (t->is_base_type() || t->is_enum()) {
string dval;
if (t->is_enum()) {
dval += "(" + t->get_name() + ")";
}
dval += t->is_string() ? "\"\"" : "0";
t_const_value* cv = (*m_iter)->get_value();
if (cv != NULL) {
dval = render_const_value(out, (*m_iter)->get_name(), t, cv);
}
if (!init_ctor) {
init_ctor = true;
indent(out) <<
tstruct->get_name() << "() : ";
out << (*m_iter)->get_name() << "(0)";
out << " : ";
out << (*m_iter)->get_name() << "(" << dval << ")";
} else {
out << ", " << (*m_iter)->get_name() << "(0)";
out << ", " << (*m_iter)->get_name() << "(" << dval << ")";
}
}
}
}
if (init_ctor) {
out << " {} " << endl;
out << " {" << endl;
indent_up();
for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
t_type* t = (*m_iter)->get_type();
while (t->is_typedef()) {
t = ((t_typedef*)t)->get_type();
}
if (!t->is_base_type()) {
t_const_value* cv = (*m_iter)->get_value();
if (cv != NULL) {
print_const_value(out, (*m_iter)->get_name(), t, cv);
}
}
}
indent_down();
indent(out) << "} " << endl;
}
out <<
@ -1696,6 +1720,7 @@ void t_cpp_generator::generate_deserialize_container(ofstream& out,
string etype = tmp("_etype");
indent(out) <<
prefix << ".clear();" << endl <<
"uint32_t " << size << ";" << endl;
// Declare variables, read header

View File

@ -146,23 +146,25 @@ void t_java_generator::generate_consts(std::vector<t_const*> consts) {
* is NOT performed in this function as it is always run beforehand using the
* validate_types method in main.cc
*/
void t_java_generator::print_const_value(ofstream& out, string name, t_type* type, t_const_value* value, bool in_static) {
void t_java_generator::print_const_value(std::ofstream& out, string name, t_type* type, t_const_value* value, bool in_static, bool defval) {
indent(out);
if (!defval) {
out <<
(in_static ? "" : "public static final ") <<
type_name(type) << " ";
}
if (type->is_base_type()) {
string v2 = render_const_value(out, name, type, value);
indent(out) << "public static final " << type_name(type) << " " << name << " = " << v2 << ";" << endl <<
endl;
out << name << " = " << v2 << ";" << endl << endl;
} else if (type->is_enum()) {
indent(out) << "public static final int " << name << " = " << value->get_integer() << ";" << endl <<
endl;
out << name << " = " << value->get_integer() << ";" << endl << endl;
} else if (type->is_struct() || type->is_xception()) {
const vector<t_field*>& fields = ((t_struct*)type)->get_members();
vector<t_field*>::const_iterator f_iter;
const map<t_const_value*, t_const_value*>& val = value->get_map();
map<t_const_value*, t_const_value*>::const_iterator v_iter;
indent(out) <<
(in_static ? "" : "public static final ") <<
type_name(type) << " " << name <<
" = new " << type_name(type) << "();" << endl;
out << name << " = new " << type_name(type) << "();" << endl;
if (!in_static) {
indent(out) << "static {" << endl;
indent_up();
@ -187,9 +189,7 @@ void t_java_generator::print_const_value(ofstream& out, string name, t_type* typ
}
out << endl;
} else if (type->is_map()) {
indent(out) <<
(in_static ? "" : "public static final ") <<
type_name(type, true, true) << " " << name << " = new " << type_name(type, true, true) << "();" << endl;
out << name << " = new " << type_name(type, true, true) << "();" << endl;
if (!in_static) {
indent(out) << "static {" << endl;
indent_up();
@ -209,9 +209,7 @@ void t_java_generator::print_const_value(ofstream& out, string name, t_type* typ
}
out << endl;
} else if (type->is_list() || type->is_set()) {
indent(out) <<
(in_static ? "" : "public static final ") <<
type_name(type) << " " << name << " = new " << type_name(type) << "();" << endl;
out << name << " = new " << type_name(type) << "();" << endl;
if (!in_static) {
indent(out) << "static {" << endl;
indent_up();
@ -348,7 +346,7 @@ void t_java_generator::generate_java_struct_definition(ofstream &out,
vector<t_field*>::const_iterator m_iter;
for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
indent(out) <<
"public " << declare_field(*m_iter, true) << endl;
"public " << declare_field(*m_iter, false) << endl;
}
// Inner Isset class
@ -368,6 +366,22 @@ void t_java_generator::generate_java_struct_definition(ofstream &out,
endl;
}
// Default constructor
indent(out) <<
"public " << tstruct->get_name() << "() {" << endl;
indent_up();
for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
t_type* t = (*m_iter)->get_type();
while (t->is_typedef()) {
t = ((t_typedef*)t)->get_type();
}
if (!t->is_base_type() && (*m_iter)->get_value() != NULL) {
print_const_value(out, "this." + (*m_iter)->get_name(), t, (*m_iter)->get_value(), true, true);
}
}
indent_down();
indent(out) << "}" << endl << endl;
generate_java_struct_reader(out, tstruct);
if (is_result) {
generate_java_struct_result_writer(out, tstruct);
@ -1202,6 +1216,8 @@ void t_java_generator::generate_deserialize_container(ofstream& out,
obj = tmp("_list");
}
indent(out) << prefix << " = new " << type_name(ttype, false, true) << "(); // from me" << endl;
// Declare variables, read header
if (ttype->is_map()) {
out <<
@ -1214,7 +1230,6 @@ void t_java_generator::generate_deserialize_container(ofstream& out,
indent() << "TList " << obj << " = iprot.readListBegin();" << endl;
}
// For loop iterates over elements
string i = tmp("_i");
indent(out) <<
@ -1259,9 +1274,9 @@ void t_java_generator::generate_deserialize_map_element(ofstream& out,
t_field fval(tmap->get_val_type(), val);
indent(out) <<
declare_field(&fkey, true) << endl;
declare_field(&fkey) << endl;
indent(out) <<
declare_field(&fval, true) << endl;
declare_field(&fval) << endl;
generate_deserialize_field(out, &fkey);
generate_deserialize_field(out, &fval);
@ -1597,13 +1612,15 @@ string t_java_generator::declare_field(t_field* tfield, bool init) {
while (ttype->is_typedef()) {
ttype = ((t_typedef*)ttype)->get_type();
}
if (ttype->is_base_type()) {
if (ttype->is_base_type() && tfield->get_value() != NULL) {
ofstream dummy;
result += " = " + render_const_value(dummy, tfield->get_name(), ttype, tfield->get_value());
} else if (ttype->is_base_type()) {
t_base_type::t_base tbase = ((t_base_type*)ttype)->get_base();
switch (tbase) {
case t_base_type::TYPE_VOID:
throw "NO T_VOID CONSTRUCT";
case t_base_type::TYPE_STRING:
// result += " = \"\"";
result += " = null";
break;
case t_base_type::TYPE_BOOL:
@ -1625,7 +1642,7 @@ string t_java_generator::declare_field(t_field* tfield, bool init) {
} else if (ttype->is_container()) {
result += " = new " + type_name(ttype, false, true) + "()";
} else {
result += " = null";
result += " = new " + type_name(ttype, false, true) + "()";;
}
}
return result + ";";

View File

@ -40,7 +40,7 @@ class t_java_generator : public t_oop_generator {
void generate_xception(t_struct* txception);
void generate_service (t_service* tservice);
void print_const_value(std::ofstream& out, std::string name, t_type* type, t_const_value* value, bool in_static);
void print_const_value(std::ofstream& out, std::string name, t_type* type, t_const_value* value, bool in_static, bool defval=false);
std::string render_const_value(std::ofstream& out, std::string name, t_type* type, t_const_value* value);
/**
@ -138,7 +138,7 @@ class t_java_generator : public t_oop_generator {
ttype->is_container() ||
ttype->is_struct() ||
ttype->is_xception() ||
(ttype->is_base_type() && (((t_base_type*)ttype)->get_base() == t_base_type::TYPE_STRING));
ttype->is_string();
}

View File

@ -123,7 +123,7 @@ void t_php_generator::generate_const(t_const* tconst) {
t_const_value* value = tconst->get_value();
f_consts_ << "$GLOBALS['" << program_name_ << "_CONSTANTS']['" << name << "'] = ";
print_const_value(type, value);
f_consts_ << render_const_value(type, value);
f_consts_ << ";" << endl << endl;
}
@ -132,36 +132,40 @@ void t_php_generator::generate_const(t_const* tconst) {
* is NOT performed in this function as it is always run beforehand using the
* validate_types method in main.cc
*/
void t_php_generator::print_const_value(t_type* type, t_const_value* value) {
string t_php_generator::render_const_value(t_type* type, t_const_value* value) {
std::ostringstream out;
while (type->is_typedef()) {
type = ((t_typedef*)type)->get_type();
}
if (type->is_base_type()) {
t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
switch (tbase) {
case t_base_type::TYPE_STRING:
f_consts_ << "'" << value->get_string() << "'";
out << "'" << value->get_string() << "'";
break;
case t_base_type::TYPE_BOOL:
f_consts_ << (value->get_integer() > 0 ? "true" : "false");
out << (value->get_integer() > 0 ? "true" : "false");
break;
case t_base_type::TYPE_BYTE:
case t_base_type::TYPE_I16:
case t_base_type::TYPE_I32:
case t_base_type::TYPE_I64:
f_consts_ << value->get_integer();
out << value->get_integer();
break;
case t_base_type::TYPE_DOUBLE:
if (value->get_type() == t_const_value::CV_INTEGER) {
f_consts_ << value->get_integer();
out << value->get_integer();
} else {
f_consts_ << value->get_double();
out << value->get_double();
}
break;
default:
throw "compiler error: no const of base type " + tbase;
}
} else if (type->is_enum()) {
indent(f_consts_) << value->get_integer();
indent(out) << value->get_integer();
} else if (type->is_struct() || type->is_xception()) {
f_consts_ << "new " << php_namespace(type->get_program()) << type->get_name() << "(array(" << endl;
out << "new " << php_namespace(type->get_program()) << type->get_name() << "(array(" << endl;
indent_up();
const vector<t_field*>& fields = ((t_struct*)type)->get_members();
vector<t_field*>::const_iterator f_iter;
@ -177,30 +181,30 @@ void t_php_generator::print_const_value(t_type* type, t_const_value* value) {
if (field_type == NULL) {
throw "type error: " + type->get_name() + " has no field " + v_iter->first->get_string();
}
f_consts_ << indent();
print_const_value(g_type_string, v_iter->first);
f_consts_ << " => ";
print_const_value(field_type, v_iter->second);
f_consts_ << endl;
out << indent();
out << render_const_value(g_type_string, v_iter->first);
out << " => ";
out << render_const_value(field_type, v_iter->second);
out << endl;
}
indent_down();
indent(f_consts_) << "))";
indent(out) << "))";
} else if (type->is_map()) {
t_type* ktype = ((t_map*)type)->get_key_type();
t_type* vtype = ((t_map*)type)->get_val_type();
f_consts_ << "array(" << endl;
out << "array(" << endl;
indent_up();
const map<t_const_value*, t_const_value*>& val = value->get_map();
map<t_const_value*, t_const_value*>::const_iterator v_iter;
for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
f_consts_ << indent();
print_const_value(ktype, v_iter->first);
f_consts_ << " => ";
print_const_value(vtype, v_iter->second);
f_consts_ << "," << endl;
out << indent();
out << render_const_value(ktype, v_iter->first);
out << " => ";
out << render_const_value(vtype, v_iter->second);
out << "," << endl;
}
indent_down();
indent(f_consts_) << ")";
indent(out) << ")";
} else if (type->is_list() || type->is_set()) {
t_type* etype;
if (type->is_list()) {
@ -208,21 +212,22 @@ void t_php_generator::print_const_value(t_type* type, t_const_value* value) {
} else {
etype = ((t_set*)type)->get_elem_type();
}
f_consts_ << "array(" << endl;
out << "array(" << endl;
indent_up();
const vector<t_const_value*>& val = value->get_list();
vector<t_const_value*>::const_iterator v_iter;
for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
f_consts_ << indent();
print_const_value(etype, *v_iter);
out << indent();
out << render_const_value(etype, *v_iter);
if (type->is_set()) {
f_consts_ << " => true";
out << " => true";
}
f_consts_ << "," << endl;
out << "," << endl;
}
indent_down();
indent(f_consts_) << ")";
indent(out) << ")";
}
return out.str();
}
/**
@ -273,8 +278,16 @@ void t_php_generator::generate_php_struct_definition(ofstream& out,
indent_up();
for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
string dval = "null";
t_type* t = (*m_iter)->get_type();
while (t->is_typedef()) {
t = ((t_typedef*)t)->get_type();
}
if ((*m_iter)->get_value() != NULL && !(t->is_struct() || t->is_xception())) {
dval = render_const_value((*m_iter)->get_type(), (*m_iter)->get_value());
}
indent(out) <<
"public $" << (*m_iter)->get_name() << " = null;" << endl;
"public $" << (*m_iter)->get_name() << " = " << dval << ";" << endl;
}
out << endl;
@ -284,6 +297,17 @@ void t_php_generator::generate_php_struct_definition(ofstream& out,
out <<
indent() << "public function __construct($vals=null) {" << endl;
indent_up();
for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
t_type* t = (*m_iter)->get_type();
while (t->is_typedef()) {
t = ((t_typedef*)t)->get_type();
}
if ((*m_iter)->get_value() != NULL && (t->is_struct() || t->is_xception())) {
indent(out) << "$this->" << (*m_iter)->get_name() << " = " << render_const_value(t, (*m_iter)->get_value()) << ";" << endl;
}
}
out <<
indent() << "if (is_array($vals)) {" << endl;
indent_up();
@ -821,7 +845,7 @@ void t_php_generator::generate_service_rest(t_service* tservice) {
"class " << service_name_ << "Rest" << extends_if << " {" << endl;
indent_up();
f_service_ <<
indent() << "var $impl_;" << endl <<
indent() << "private $impl_;" << endl <<
endl <<
indent() << "public function __construct($impl) {" << endl <<
indent() << " $this->impl_ = $impl;" << endl <<

View File

@ -43,7 +43,7 @@ class t_php_generator : public t_oop_generator {
void generate_xception (t_struct* txception);
void generate_service (t_service* tservice);
void print_const_value (t_type* type, t_const_value* value);
std::string render_const_value(t_type* type, t_const_value* value);
/**
* Structs!

View File

@ -123,8 +123,7 @@ void t_py_generator::generate_const(t_const* tconst) {
string name = tconst->get_name();
t_const_value* value = tconst->get_value();
indent(f_consts_) << name << " = ";
print_const_value(type, value);
indent(f_consts_) << name << " = " << render_const_value(type, value);
f_consts_ << endl << endl;
}
@ -133,36 +132,38 @@ void t_py_generator::generate_const(t_const* tconst) {
* is NOT performed in this function as it is always run beforehand using the
* validate_types method in main.cc
*/
void t_py_generator::print_const_value(t_type* type, t_const_value* value) {
string t_py_generator::render_const_value(t_type* type, t_const_value* value) {
std::ostringstream out;
if (type->is_base_type()) {
t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
switch (tbase) {
case t_base_type::TYPE_STRING:
f_consts_ << "'" << value->get_string() << "'";
out << "'" << value->get_string() << "'";
break;
case t_base_type::TYPE_BOOL:
f_consts_ << (value->get_integer() > 0 ? "True" : "False");
out << (value->get_integer() > 0 ? "True" : "False");
break;
case t_base_type::TYPE_BYTE:
case t_base_type::TYPE_I16:
case t_base_type::TYPE_I32:
case t_base_type::TYPE_I64:
f_consts_ << value->get_integer();
out << value->get_integer();
break;
case t_base_type::TYPE_DOUBLE:
if (value->get_type() == t_const_value::CV_INTEGER) {
f_consts_ << value->get_integer();
out << value->get_integer();
} else {
f_consts_ << value->get_double();
out << value->get_double();
}
break;
default:
throw "compiler error: no const of base type " + tbase;
}
} else if (type->is_enum()) {
indent(f_consts_) << value->get_integer();
indent(out) << value->get_integer();
} else if (type->is_struct() || type->is_xception()) {
f_consts_ << type->get_name() << "({" << endl;
out << type->get_name() << "({" << endl;
indent_up();
const vector<t_field*>& fields = ((t_struct*)type)->get_members();
vector<t_field*>::const_iterator f_iter;
@ -178,30 +179,30 @@ void t_py_generator::print_const_value(t_type* type, t_const_value* value) {
if (field_type == NULL) {
throw "type error: " + type->get_name() + " has no field " + v_iter->first->get_string();
}
f_consts_ << indent();
print_const_value(g_type_string, v_iter->first);
f_consts_ << " : ";
print_const_value(field_type, v_iter->second);
f_consts_ << "," << endl;
out << indent();
out << render_const_value(g_type_string, v_iter->first);
out << " : ";
out << render_const_value(field_type, v_iter->second);
out << "," << endl;
}
indent_down();
indent(f_consts_) << "})";
indent(out) << "})";
} else if (type->is_map()) {
t_type* ktype = ((t_map*)type)->get_key_type();
t_type* vtype = ((t_map*)type)->get_val_type();
f_consts_ << "{" << endl;
out << "{" << endl;
indent_up();
const map<t_const_value*, t_const_value*>& val = value->get_map();
map<t_const_value*, t_const_value*>::const_iterator v_iter;
for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
f_consts_ << indent();
print_const_value(ktype, v_iter->first);
f_consts_ << " : ";
print_const_value(vtype, v_iter->second);
f_consts_ << "," << endl;
out << indent();
out << render_const_value(ktype, v_iter->first);
out << " : ";
out << render_const_value(vtype, v_iter->second);
out << "," << endl;
}
indent_down();
indent(f_consts_) << "}";
indent(out) << "}";
} else if (type->is_list() || type->is_set()) {
t_type* etype;
if (type->is_list()) {
@ -210,23 +211,25 @@ void t_py_generator::print_const_value(t_type* type, t_const_value* value) {
etype = ((t_set*)type)->get_elem_type();
}
if (type->is_set()) {
f_consts_ << "set(";
out << "set(";
}
f_consts_ << "[" << endl;
out << "[" << endl;
indent_up();
const vector<t_const_value*>& val = value->get_list();
vector<t_const_value*>::const_iterator v_iter;
for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
f_consts_ << indent();
print_const_value(etype, *v_iter);
f_consts_ << "," << endl;
out << indent();
out << render_const_value(etype, *v_iter);
out << "," << endl;
}
indent_down();
indent(f_consts_) << "]";
indent(out) << "]";
if (type->is_set()) {
f_consts_ << ")";
out << ")";
}
}
return out.str();
}
/**
@ -288,14 +291,9 @@ void t_py_generator::generate_py_struct_definition(ofstream& out,
"pass" <<endl;
} else {
for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
if (is_result) {
indent(out) <<
"self." << (*m_iter)->get_name() << " = None" << endl;
} else {
// This fills in default values, as opposed to nulls
indent(out) <<
declare_field(*m_iter, true) << endl;
}
// This fills in default values, as opposed to nulls
indent(out) <<
declare_field(*m_iter) << endl;
}
indent(out) <<
@ -1393,51 +1391,16 @@ void t_py_generator::generate_serialize_list_element(ofstream &out,
*
* @param ttype The type
*/
string t_py_generator::declare_field(t_field* tfield, bool init, bool obj) {
string t_py_generator::declare_field(t_field* tfield) {
string result = "self." + tfield->get_name();
if (init) {
t_type* type = tfield->get_type();
while (type->is_typedef()) {
type = ((t_typedef*)type)->get_type();
}
if (type->is_base_type()) {
t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
switch (tbase) {
case t_base_type::TYPE_VOID:
break;
case t_base_type::TYPE_STRING:
result += " = ''";
break;
case t_base_type::TYPE_BOOL:
result += " = False";
break;
case t_base_type::TYPE_BYTE:
case t_base_type::TYPE_I16:
case t_base_type::TYPE_I32:
case t_base_type::TYPE_I64:
result += " = 0";
break;
case t_base_type::TYPE_DOUBLE:
result += " = 0.0";
break;
default:
throw "compiler error: no PHP initializer for base type " + tbase;
}
} else if (type->is_enum()) {
result += " = 0";
} else if (type->is_container()) {
if (type->is_map()) {
result += " = {}";
} else {
result += " = []";
}
} else if (type->is_struct() || type->is_xception()) {
if (obj) {
result += " = " + type_name((t_struct*)type) + "()";
} else {
result += " = None";
}
}
t_type* type = tfield->get_type();
while (type->is_typedef()) {
type = ((t_typedef*)type)->get_type();
}
if (tfield->get_value() != NULL) {
result += " = " + render_const_value(type, tfield->get_value());
} else {
result += " = None";
}
return result;
}

View File

@ -38,7 +38,7 @@ class t_py_generator : public t_oop_generator {
void generate_xception (t_struct* txception);
void generate_service (t_service* tservice);
void print_const_value (t_type* type, t_const_value* value);
std::string render_const_value(t_type* type, t_const_value* value);
/**
* Struct generation code
@ -122,7 +122,7 @@ class t_py_generator : public t_oop_generator {
std::string py_autogen_comment();
std::string py_imports();
std::string render_includes();
std::string declare_field(t_field* tfield, bool init=false, bool obj=false);
std::string declare_field(t_field* tfield);
std::string type_name(t_type* ttype);
std::string function_signature(t_function* tfunction, std::string prefix="");
std::string argument_list(t_struct* tstruct);

View File

@ -132,8 +132,7 @@ void t_rb_generator::generate_const(t_const* tconst) {
name[0] = toupper(name[0]);
indent(f_consts_) << name << " = ";
print_const_value(type, value);
indent(f_consts_) << name << " = " << render_const_value(type, value);
f_consts_ << endl << endl;
}
@ -142,36 +141,37 @@ void t_rb_generator::generate_const(t_const* tconst) {
* is NOT performed in this function as it is always run beforehand using the
* validate_types method in main.cc
*/
void t_rb_generator::print_const_value(t_type* type, t_const_value* value) {
string t_rb_generator::render_const_value(t_type* type, t_const_value* value) {
std::ostringstream out;
if (type->is_base_type()) {
t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
switch (tbase) {
case t_base_type::TYPE_STRING:
f_consts_ << "'" << value->get_string() << "'";
out << "'" << value->get_string() << "'";
break;
case t_base_type::TYPE_BOOL:
f_consts_ << (value->get_integer() > 0 ? "true" : "false");
out << (value->get_integer() > 0 ? "true" : "false");
break;
case t_base_type::TYPE_BYTE:
case t_base_type::TYPE_I16:
case t_base_type::TYPE_I32:
case t_base_type::TYPE_I64:
f_consts_ << value->get_integer();
out << value->get_integer();
break;
case t_base_type::TYPE_DOUBLE:
if (value->get_type() == t_const_value::CV_INTEGER) {
f_consts_ << value->get_integer();
out << value->get_integer();
} else {
f_consts_ << value->get_double();
out << value->get_double();
}
break;
default:
throw "compiler error: no const of base type " + tbase;
}
} else if (type->is_enum()) {
indent(f_consts_) << value->get_integer();
indent(out) << value->get_integer();
} else if (type->is_struct() || type->is_xception()) {
f_consts_ << type->get_name() << "({" << endl;
out << type->get_name() << "({" << endl;
indent_up();
const vector<t_field*>& fields = ((t_struct*)type)->get_members();
vector<t_field*>::const_iterator f_iter;
@ -187,30 +187,30 @@ void t_rb_generator::print_const_value(t_type* type, t_const_value* value) {
if (field_type == NULL) {
throw "type error: " + type->get_name() + " has no field " + v_iter->first->get_string();
}
f_consts_ << indent();
print_const_value(g_type_string, v_iter->first);
f_consts_ << " => ";
print_const_value(field_type, v_iter->second);
f_consts_ << "," << endl;
out << indent();
out << render_const_value(g_type_string, v_iter->first);
out << " => ";
out << render_const_value(field_type, v_iter->second);
out << "," << endl;
}
indent_down();
indent(f_consts_) << "})";
indent(out) << "})";
} else if (type->is_map()) {
t_type* ktype = ((t_map*)type)->get_key_type();
t_type* vtype = ((t_map*)type)->get_val_type();
f_consts_ << "{" << endl;
out << "{" << endl;
indent_up();
const map<t_const_value*, t_const_value*>& val = value->get_map();
map<t_const_value*, t_const_value*>::const_iterator v_iter;
for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
f_consts_ << indent();
print_const_value(ktype, v_iter->first);
f_consts_ << " =>x ";
print_const_value(vtype, v_iter->second);
f_consts_ << "," << endl;
out << indent();
out << render_const_value(ktype, v_iter->first);
out << " => ";
out << render_const_value(vtype, v_iter->second);
out << "," << endl;
}
indent_down();
indent(f_consts_) << "}";
indent(out) << "}";
} else if (type->is_list() || type->is_set()) {
t_type* etype;
if (type->is_list()) {
@ -219,28 +219,29 @@ void t_rb_generator::print_const_value(t_type* type, t_const_value* value) {
etype = ((t_set*)type)->get_elem_type();
}
if (type->is_set()) {
f_consts_ << "{";
out << "{";
} else {
f_consts_ << "[" << endl;
out << "[" << endl;
}
indent_up();
const vector<t_const_value*>& val = value->get_list();
vector<t_const_value*>::const_iterator v_iter;
for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
f_consts_ << indent();
print_const_value(etype, *v_iter);
out << indent();
out << render_const_value(etype, *v_iter);
if (type->is_set()) {
f_consts_ << " => true";
out << " => true";
}
f_consts_ << "," << endl;
out << "," << endl;
}
indent_down();
if (type->is_set()) {
indent(f_consts_) << "}";
indent(out) << "}";
} else {
indent(f_consts_) << "]";
indent(out) << "]";
}
}
return out.str();
}
/**
@ -323,6 +324,11 @@ void t_rb_generator::generate_rb_struct_definition(ofstream& out,
indent_up();
if (members.size() > 0) {
for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
if ((*m_iter)->get_value() != NULL) {
indent(out) << declare_field(*m_iter) << endl;
}
}
indent(out) <<
"if (d != nil)" << endl;
indent_up();
@ -1435,51 +1441,16 @@ void t_rb_generator::generate_serialize_list_element(ofstream &out,
*
* @param ttype The type
*/
string t_rb_generator::declare_field(t_field* tfield, bool init, bool obj) {
string t_rb_generator::declare_field(t_field* tfield) {
string result = "@" + tfield->get_name();
if (init) {
t_type* type = tfield->get_type();
while (type->is_typedef()) {
type = ((t_typedef*)type)->get_type();
}
if (type->is_base_type()) {
t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
switch (tbase) {
case t_base_type::TYPE_VOID:
break;
case t_base_type::TYPE_STRING:
result += " = ''";
break;
case t_base_type::TYPE_BOOL:
result += " = false";
break;
case t_base_type::TYPE_BYTE:
case t_base_type::TYPE_I16:
case t_base_type::TYPE_I32:
case t_base_type::TYPE_I64:
result += " = 0";
break;
case t_base_type::TYPE_DOUBLE:
result += " = 0.0";
break;
default:
throw "compiler error: no PHP initializer for base type " + tbase;
}
} else if (type->is_enum()) {
result += " = 0";
} else if (type->is_container()) {
if (type->is_map() || type->is_set()) {
result += " = {}";
} else {
result += " = []";
}
} else if (type->is_struct() || type->is_xception()) {
if (obj) {
result += " = " + type_name((t_struct*)type) + "()";
} else {
result += " = nil";
}
}
t_type* type = tfield->get_type();
while (type->is_typedef()) {
type = ((t_typedef*)type)->get_type();
}
if (tfield->get_value() != NULL) {
result += " = " + render_const_value(type, tfield->get_value());
} else {
result += " = nil";
}
return result;
}

View File

@ -38,7 +38,7 @@ class t_rb_generator : public t_oop_generator {
void generate_xception (t_struct* txception);
void generate_service (t_service* tservice);
void print_const_value (t_type* type, t_const_value* value);
std::string render_const_value(t_type* type, t_const_value* value);
/**
* Struct generation code
@ -122,7 +122,7 @@ class t_rb_generator : public t_oop_generator {
std::string rb_autogen_comment();
std::string rb_imports();
std::string render_includes();
std::string declare_field(t_field* tfield, bool init=false, bool obj=false);
std::string declare_field(t_field* tfield);
std::string type_name(t_type* ttype);
std::string function_signature(t_function* tfunction, std::string prefix="");
std::string argument_list(t_struct* tstruct);

View File

@ -414,6 +414,13 @@ void validate_const_type(t_const* c) {
validate_const_rec(c->get_name(), c->get_type(), c->get_value());
}
/**
* Check the type of a default value assigned to a field.
*/
void validate_field_value(t_field* field, t_const_value* cv) {
validate_const_rec(field->get_name(), field->get_type(), cv);
}
/**
* Parses a program
*/

View File

@ -3,6 +3,7 @@
#include <string>
#include "parse/t_const.h"
#include "parse/t_field.h"
/**
* Defined in the flex library
@ -37,6 +38,11 @@ void failure(const char* fmt, ...);
*/
void validate_const_type(t_const* c);
/**
* Check constant types
*/
void validate_field_value(t_field* field, t_const_value* cv);
/**
* Converts a string filename into a thrift program name
*/

View File

@ -15,12 +15,14 @@ class t_field {
type_(type),
name_(name),
key_(0),
value_(NULL),
xsd_optional_(false) {}
t_field(t_type* type, std::string name, int32_t key) :
type_(type),
name_(name),
key_(key),
value_(NULL),
xsd_optional_(false) {}
~t_field() {}
@ -45,10 +47,19 @@ class t_field {
return xsd_optional_;
}
void set_value(t_const_value* value) {
value_ = value;
}
t_const_value* get_value() {
return value_;
}
private:
t_type* type_;
std::string name_;
int32_t key_;
t_const_value* value_;
bool xsd_optional_;

View File

@ -123,7 +123,9 @@ int y_field_val = -1;
%type<ttype> DefinitionType
%type<tfield> Field
%type<iconst> FieldIdentifier
%type<ttype> FieldType
%type<tconstv> FieldValue
%type<tstruct> FieldList
%type<tenum> Enum
@ -575,32 +577,46 @@ FieldList:
}
Field:
tok_int_constant ':' FieldType tok_identifier XsdOptional CommaOrSemicolonOptional
FieldIdentifier FieldType tok_identifier FieldValue XsdOptional CommaOrSemicolonOptional
{
pdebug("tok_int_constant : Field -> FieldType tok_identifier");
if ($1 <= 0) {
pwarning(1, "Nonpositive value (%d) not allowed as a field key for '%s'.\n", $1, $4);
$1 = y_field_val--;
if ($1 < 0) {
pwarning(2, "No field key specified for %s, resulting protocol may have conflicts or not be backwards compatible!\n", $3);
}
$$ = new t_field($2, $3, $1);
if ($4 != NULL) {
validate_field_value($$, $4);
$$->set_value($4);
}
$$ = new t_field($3, $4, $1);
$$->set_xsd_optional($5);
}
| FieldType tok_identifier XsdOptional CommaOrSemicolonOptional
FieldIdentifier:
tok_int_constant ':'
{
pdebug("Field -> FieldType tok_identifier");
pwarning(2, "No field key specified for '%s', resulting protocol may have conflicts or not be backwards compatible!\n", $2);
$$ = new t_field($1, $2, y_field_val--);
$$->set_xsd_optional($3);
}
| FieldType tok_identifier '=' tok_int_constant CommaOrSemicolonOptional
{
pwarning(1, "Trailing = id notation is deprecated. Use 'Id: Type Name' notation instead");
pdebug("Field -> FieldType tok_identifier = tok_int_constant");
if ($4 <= 0) {
pwarning(1, "Nonpositive value (%d) not allowed as a field key for '%s'.\n", $4, $2);
$4 = y_field_val--;
if ($1 <= 0) {
pwarning(1, "Nonpositive value (%d) not allowed as a field key.\n", $1);
$1 = y_field_val--;
}
$$ = new t_field($1, $2, $4);
$$ = $1;
}
|
{
$$ = y_field_val--;
}
FieldValue:
'=' ConstValue
{
if (g_parse_mode == PROGRAM) {
$$ = $2;
} else {
$$ = NULL;
}
}
|
{
$$ = NULL;
}
DefinitionType: