summaryrefslogtreecommitdiff
path: root/compiler/cpp/src
diff options
context:
space:
mode:
authorkedzie <mark.kedzierski@gmail.com>2014-08-12 13:26:24 -0500
committerRoger Meier <roger@apache.org>2014-08-23 22:27:45 +0200
commitf9b8f5e64137248ea2a1b95312916491d23ab94a (patch)
tree1d2d8864d0c340399c33c16066b1d4bbffe2d2de /compiler/cpp/src
parent5d6378f61e2bed18e316f8f6d48de419a5848b12 (diff)
downloadthrift-f9b8f5e64137248ea2a1b95312916491d23ab94a.tar.gz
THRIFT-2670 Android parcelable generator
-add 'android' option to java compiler which will generate Parcelable structures for Android -cleaned up warnings
Diffstat (limited to 'compiler/cpp/src')
-rw-r--r--compiler/cpp/src/generate/t_java_generator.cc228
1 files changed, 228 insertions, 0 deletions
diff --git a/compiler/cpp/src/generate/t_java_generator.cc b/compiler/cpp/src/generate/t_java_generator.cc
index 4c755acf3..3a556a5a7 100644
--- a/compiler/cpp/src/generate/t_java_generator.cc
+++ b/compiler/cpp/src/generate/t_java_generator.cc
@@ -60,6 +60,9 @@ public:
iter = parsed_options.find("beans");
bean_style_ = (iter != parsed_options.end());
+ iter = parsed_options.find("android");
+ android_style_ = (iter != parsed_options.end());
+
iter = parsed_options.find("private-members");
private_members_ = (iter != parsed_options.end());
@@ -117,6 +120,7 @@ public:
void generate_java_struct(t_struct* tstruct, bool is_exception);
void generate_java_struct_definition(std::ofstream& out, t_struct* tstruct, bool is_xception=false, bool in_class=false, bool is_result=false);
+ void generate_java_struct_parcelable(std::ofstream& out, t_struct* tstruct);
void generate_java_struct_equality(std::ofstream& out, t_struct* tstruct);
void generate_java_struct_compare_to(std::ofstream& out, t_struct* tstruct);
void generate_java_struct_reader(std::ofstream& out, t_struct* tstruct);
@@ -303,6 +307,7 @@ public:
std::string package_dir_;
bool bean_style_;
+ bool android_style_;
bool private_members_;
bool nocamel_style_;
bool fullcamel_style_;
@@ -1288,6 +1293,10 @@ void t_java_generator::generate_java_struct_definition(ofstream &out,
}
out << "implements org.apache.thrift.TBase<" << tstruct->get_name() << ", " << tstruct->get_name() << "._Fields>, java.io.Serializable, Cloneable, Comparable<" << tstruct->get_name() << ">";
+ if (android_style_) {
+ out << ", android.os.Parcelable";
+ }
+
out << " ";
scope_up(out);
@@ -1320,6 +1329,10 @@ void t_java_generator::generate_java_struct_definition(ofstream &out,
out << endl;
+ if(android_style_) {
+ generate_java_struct_parcelable(out, tstruct);
+ }
+
generate_field_name_constants(out, tstruct);
// isset data
@@ -1477,6 +1490,8 @@ void t_java_generator::generate_java_struct_definition(ofstream &out,
indent(out) << " return new " << tstruct->get_name() << "(this);" << endl;
indent(out) << "}" << endl << endl;
+
+
generate_java_struct_clear(out, tstruct);
generate_java_bean_boilerplate(out, tstruct);
@@ -1507,6 +1522,218 @@ void t_java_generator::generate_java_struct_definition(ofstream &out,
}
/**
+ * generates parcelable interface implementation
+ */
+void t_java_generator::generate_java_struct_parcelable(ofstream& out,
+ t_struct* tstruct) {
+ string tname = tstruct->get_name();
+
+ const vector<t_field*>& members = tstruct->get_members();
+ vector<t_field*>::const_iterator m_iter;
+
+ out << indent() << "@Override" << endl <<
+ indent() << "public void writeToParcel(android.os.Parcel out, int flags) {" << endl;
+ indent_up();
+ string bitsetPrimitiveType = "";
+ switch(needs_isset(tstruct, &bitsetPrimitiveType)) {
+ case ISSET_NONE:
+ break;
+ case ISSET_PRIMITIVE:
+ indent(out) << "//primitive bitfield of type: " << bitsetPrimitiveType << endl;
+ if(bitsetPrimitiveType=="byte") {
+ indent(out) << "out.writeByte(__isset_bitfield);" << endl;
+ } else if(bitsetPrimitiveType=="short") {
+ indent(out) << "out.writeInt(new Short(__isset_bitfield).intValue());" << endl;
+ } else if(bitsetPrimitiveType=="int") {
+ indent(out) << "out.writeInt(__isset_bitfield);" << endl;
+ } else if(bitsetPrimitiveType=="long") {
+ indent(out) << "out.writeLong(__isset_bitfield);" << endl;
+ }
+ out << endl;
+ break;
+ case ISSET_BITSET:
+ indent(out) << "//BitSet" << endl;
+ indent(out) << "out.writeSerializable(__isset_bit_vector);" << endl;
+ out << endl;
+ break;
+ }
+ for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
+ t_type* t = get_true_type((*m_iter)->get_type());
+ string name = (*m_iter)->get_name();
+
+ if(t->is_struct()) {
+ indent(out) << "out.writeParcelable(" << name << ", flags);" << endl;
+ } else if(type_name(t)=="float") {
+ indent(out) << "out.writeFloat(" << name << ");" << endl;
+ } else if(t->is_enum()) {
+ indent(out) << "out.writeInt(" << name << ".getValue());" << endl;
+ } else if(t->is_list()) {
+ if(((t_list*)t)->get_elem_type()->get_true_type()->is_struct()) {
+ indent(out) << "out.writeTypedList(" << name << ");" << endl;
+ }else {
+ indent(out) << "out.writeList(" << name << ");" << endl;
+ }
+ } else if(t->is_map()) {
+ indent(out) << "out.writeMap(" << name << ");" << endl;
+ } else if(t->is_base_type()) {
+ if (((t_base_type*)t)->is_binary()) {
+ indent(out) << "out.writeInt(" << name << "!=null ? 1 : 0);" << endl;
+ indent(out) << "if(" << name << " != null) { " << endl;
+ indent_up();
+ indent(out) << "out.writeByteArray(" << name << ".array(), "
+ << name << ".position() + " << name << ".arrayOffset(), "
+ << name << ".limit() - " << name << ".position() );" << endl;
+ scope_down(out);
+ } else {
+ switch(((t_base_type*)t)->get_base()) {
+ case t_base_type::TYPE_I16:
+ indent(out) << "out.writeInt(new Short(" << name << ").intValue());" << endl;
+ break;
+ case t_base_type::TYPE_I32:
+ indent(out) << "out.writeInt(" << name << ");" << endl;
+ break;
+ case t_base_type::TYPE_I64:
+ indent(out) << "out.writeLong(" << name << ");" << endl;
+ break;
+ case t_base_type::TYPE_BOOL:
+ indent(out) << "out.writeInt(" << name << " ? 1 : 0);" << endl;
+ break;
+ case t_base_type::TYPE_BYTE:
+ indent(out) << "out.writeByte(" << name << ");" << endl;
+ break;
+ case t_base_type::TYPE_DOUBLE:
+ indent(out) << "out.writeDouble(" << name << ");" << endl;
+ break;
+ case t_base_type::TYPE_STRING:
+ indent(out) << "out.writeString(" << name << ");" << endl;
+ break;
+ case t_base_type::TYPE_VOID:
+ break;
+ }
+ }
+ }
+ }
+ scope_down(out);
+ out << endl;
+
+ out << indent() << "@Override" << endl <<
+ indent() << "public int describeContents() {" << endl;
+ indent_up();
+ out <<
+ indent() << "return 0;" << endl;
+ scope_down(out);
+ out << endl;
+
+ indent(out) << "public " << tname << "(android.os.Parcel in) {" << endl;
+ indent_up();
+ //read in the required bitfield
+ switch(needs_isset(tstruct, &bitsetPrimitiveType)) {
+ case ISSET_NONE:
+ break;
+ case ISSET_PRIMITIVE:
+ indent(out) << "//primitive bitfield of type: " << bitsetPrimitiveType << endl;
+ if(bitsetPrimitiveType=="byte") {
+ indent(out) << "__isset_bitfield = in.readByte();" << endl;
+ } else if(bitsetPrimitiveType=="short") {
+ indent(out) << "__isset_bitfield = (short) in.readInt();" << endl;
+ } else if(bitsetPrimitiveType=="int") {
+ indent(out) << "__isset_bitfield = in.readInt();" << endl;
+ } else if(bitsetPrimitiveType=="long") {
+ indent(out) << "__isset_bitfield = in.readLong();" << endl;
+ }
+ out << endl;
+ break;
+ case ISSET_BITSET:
+ indent(out) << "//BitSet" << endl;
+ indent(out) << "__isset_bit_vector = (BitSet) in.readSerializable();" << endl;
+ out << endl;
+ break;
+ }
+ //read all the fields
+ for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
+ t_type* t = get_true_type((*m_iter)->get_type());
+ string name = (*m_iter)->get_name();
+ string prefix = "this." + name;
+
+ if(t->is_struct()) {
+ indent(out) << prefix << "= in.readParcelable(" << tname << ".class.getClassLoader());" << endl;
+ } else if(t->is_enum()) {
+ indent(out) << prefix << " = " << type_name(t) << ".findByValue(in.readInt());" << endl;
+ } else if(t->is_list()) {
+ t_list* list = (t_list*)t;
+ indent(out) << prefix << " = new " << type_name(t, false, true) << "();" << endl;
+ if(list->get_elem_type()->get_true_type()->is_struct()) {
+ indent(out) << "in.readTypedList(" << prefix << ", " << type_name(list->get_elem_type()) << ".CREATOR);" << endl;
+ } else {
+ indent(out) << "in.readList(" << prefix << ", " << tname << ".class.getClassLoader());" << endl;
+ }
+ } else if(t->is_map()) {
+ indent(out) << prefix << " = new " << type_name(t, false, true) << "();" << endl;
+ indent(out) << " in.readMap(" << prefix << ", " << tname << ".class.getClassLoader());" << endl;
+ } else if(type_name(t)=="float") {
+ indent(out) << prefix << " = in.readFloat();" << endl;
+ } else if(t->is_base_type()) {
+ t_base_type* bt = (t_base_type*)t;
+ if (bt->is_binary()) {
+ indent(out) << "if(in.readInt()==1) {" << endl;
+ indent_up();
+ indent(out) << prefix << " = ByteBuffer.wrap(in.createByteArray());" << endl;
+ scope_down(out);
+ } else {
+ switch(bt->get_base()) {
+ case t_base_type::TYPE_I16:
+ indent(out) << prefix << " = (short) in.readInt();" << endl;
+ break;
+ case t_base_type::TYPE_I32:
+ indent(out) << prefix << " = in.readInt();" << endl;
+ break;
+ case t_base_type::TYPE_I64:
+ indent(out) << prefix << " = in.readLong();" << endl;
+ break;
+ case t_base_type::TYPE_BOOL:
+ indent(out) << prefix << " = (in.readInt()==1);" << endl;
+ break;
+ case t_base_type::TYPE_BYTE:
+ indent(out) << prefix << " = in.readByte();" << endl;
+ break;
+ case t_base_type::TYPE_DOUBLE:
+ indent(out) << prefix << " = in.readDouble();" << endl;
+ break;
+ case t_base_type::TYPE_STRING:
+ indent(out) << prefix << "= in.readString();" << endl;
+ break;
+ case t_base_type::TYPE_VOID:
+ break;
+ }
+ }
+ }
+ }
+
+ scope_down(out);
+ out << endl;
+
+ indent(out) << "public static final android.os.Parcelable.Creator<" << tname << "> CREATOR = new android.os.Parcelable.Creator<" << tname << ">() {" << endl;
+ indent_up();
+
+ indent(out) << "@Override" << endl <<
+ indent() << "public " << tname << "[] newArray(int size) {" << endl;
+ indent_up();
+ indent(out) << "return new " << tname << "[size];" << endl;
+ scope_down(out);
+ out << endl;
+
+ indent(out) << "@Override" << endl <<
+ indent() << "public " << tname << " createFromParcel(android.os.Parcel in) {" << endl;
+ indent_up();
+ indent(out) << "return new " << tname << "(in);" << endl;
+ scope_down(out);
+
+ indent_down();
+ indent(out) << "};" << endl;
+ out << endl;
+}
+
+/**
* Generates equals methods and a hashCode method for a structure.
*
* @param tstruct The struct definition
@@ -4576,6 +4803,7 @@ THRIFT_REGISTER_GENERATOR(java, "Java",
" private-members: Members will be private, but setter methods will return 'this' like usual.\n"
" nocamel: Do not use CamelCase field accessors with beans.\n"
" fullcamel: Convert underscored_accessor_or_service_names to camelCase.\n"
+" android: Generated structures are Parcelable.\n"
" android_legacy: Do not use java.io.IOException(throwable) (available for Android 2.3 and above).\n"
" java5: Generate Java 1.5 compliant code (includes android_legacy flag).\n"
" reuse-objects: Data objects will not be allocated, but existing instances will be used (read and write).\n"