Thrift: Slight tweaks to local reflection.
Summary:
Local reflection typespecs for structs now have a dummy T_STOP field at the end
so we don't have to check the size on every iteration.
They also contain information about which fields are optional.
Also put a static pointer to the reflection in each structure.
Reviewed By: mcslee
Test Plan: test/DenseLinkingTest.thrift
Revert Plan: ok
git-svn-id: https://svn.apache.org/repos/asf/incubator/thrift/trunk@665246 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 10127fc..4a6befd 100644
--- a/compiler/cpp/src/generate/t_cpp_generator.cc
+++ b/compiler/cpp/src/generate/t_cpp_generator.cc
@@ -445,6 +445,13 @@
endl <<
indent() << "virtual ~" << tstruct->get_name() << "() throw() {}" << endl << endl;
+ // Pointer to this structure's reflection local typespec.
+ if (gen_dense_) {
+ indent(out) <<
+ "static facebook::thrift::reflection::local::TypeSpec* local_reflection;" <<
+ endl << endl;
+ }
+
// Declare all fields
for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
indent(out) <<
@@ -610,22 +617,32 @@
generate_local_reflection(out, ((t_map*)ttype)->get_key_type(), is_definition);
generate_local_reflection(out, ((t_map*)ttype)->get_val_type(), is_definition);
} else if (ttype->is_struct() || ttype->is_xception()) {
+ // Hacky hacky. For efficiency and convenience, we need a dummy "T_STOP"
+ // type at the end of our typespec array. Unfortunately, there is no
+ // T_STOP type, so we use the global void type, and special case it when
+ // generating its typespec.
+
const vector<t_field*>& members = ((t_struct*)ttype)->get_members();
vector<t_field*>::const_iterator m_iter;
for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
generate_local_reflection(out, (**m_iter).get_type(), is_definition);
}
+ generate_local_reflection(out, g_type_void, is_definition);
- // For definitions of structures, do the arrays of tags and field specs also.
+ // For definitions of structures, do the arrays of metas and field specs also.
if (is_definition) {
- indent(out) << "int16_t " << local_reflection_name("ftags", ttype) <<"[] = {" << endl;
+ out <<
+ indent() << "facebook::thrift::reflection::local::FieldMeta" << endl <<
+ indent() << local_reflection_name("metas", ttype) <<"[] = {" << endl;
indent_up();
- indent(out);
for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
- out << (*m_iter)->get_key() << ", ";
+ indent(out) << "{ " << (*m_iter)->get_key() << ", " <<
+ (((*m_iter)->get_req() == t_field::OPTIONAL) ? "true" : "false") <<
+ " }," << endl;
}
+ // Zero for the T_STOP marker.
+ indent(out) << "{ 0, false }" << endl << "};" << endl;
indent_down();
- out << endl << "};" << endl;
out <<
indent() << "facebook::thrift::reflection::local::TypeSpec*" << endl <<
@@ -635,6 +652,8 @@
indent(out) << "&" <<
local_reflection_name("typespec", (*m_iter)->get_type()) << "," << endl;
}
+ indent(out) << "&" <<
+ local_reflection_name("typespec", g_type_void) << "," << endl;
indent_down();
indent(out) << "};" << endl;
}
@@ -654,12 +673,16 @@
indent_up();
- indent(out) << type_to_enum(ttype);
+ if (ttype->is_void()) {
+ indent(out) << "facebook::thrift::protocol::T_STOP";
+ } else {
+ indent(out) << type_to_enum(ttype);
+ }
if (ttype->is_struct()) {
out << "," << endl <<
indent() << ((t_struct*)ttype)->get_members().size() << "," << endl <<
- indent() << local_reflection_name("ftags", ttype) << "," << endl <<
+ indent() << local_reflection_name("metas", ttype) << "," << endl <<
indent() << local_reflection_name("specs", ttype);
} else if (ttype->is_list()) {
out << "," << endl <<
@@ -678,6 +701,16 @@
out << ");" << endl << endl;
indent_down();
+
+ // If this is a struct and we are in the implementaion file,
+ // also set the class's static pointer to its reflection.
+ if (ttype->is_struct() && is_definition) {
+ indent(out) <<
+ "facebook::thrift::reflection::local::TypeSpec* " <<
+ ttype->get_name() << "::local_reflection = " << endl <<
+ indent() << " &" << local_reflection_name("typespec", ttype) << ";" <<
+ endl << endl;
+ }
}
/**
diff --git a/compiler/cpp/src/main.cc b/compiler/cpp/src/main.cc
index e0ff21f..4362029 100644
--- a/compiler/cpp/src/main.cc
+++ b/compiler/cpp/src/main.cc
@@ -533,6 +533,8 @@
st->generate_fingerprint();
}
+ g_type_void->generate_fingerprint();
+
// If you want to generate fingerprints for implicit structures, start here.
/*
const vector<t_service*>& services = program->get_services();