Skip to content

Instantly share code, notes, and snippets.

@fpotter
Created August 11, 2010 18:48
Show Gist options
  • Save fpotter/519511 to your computer and use it in GitHub Desktop.
Save fpotter/519511 to your computer and use it in GitHub Desktop.
Patch to make Thrift (rev 684377) output J2ME compatible Java
Index: compiler/cpp/src/generate/t_java_generator.cc
===================================================================
--- compiler/cpp/src/generate/t_java_generator.cc (revision 687530)
+++ compiler/cpp/src/generate/t_java_generator.cc (working copy)
@@ -41,7 +41,21 @@
iter = parsed_options.find("hashcode");
gen_hash_code_ = (iter != parsed_options.end());
- out_dir_base_ = (bean_style_ ? "gen-javabean" : "gen-java");
+ iter = parsed_options.find("j2me");
+ j2me_style_ = (iter != parsed_options.end());
+
+ if (bean_style_)
+ {
+ out_dir_base_ = "gen-javabean";
+ }
+ else if (j2me_style_)
+ {
+ out_dir_base_ = "gen-j2me";
+ }
+ else
+ {
+ out_dir_base_ = "gen-java";
+ }
}
@@ -183,8 +197,8 @@
bool bean_style_;
bool nocamel_style_;
+ bool j2me_style_;
bool gen_hash_code_;
-
};
@@ -233,19 +247,32 @@
* @return List of imports for Java types that are used in here
*/
string t_java_generator::java_type_imports() {
+
string hash_builder;
if (gen_hash_code_) {
hash_builder = "import org.apache.commons.lang.builder.HashCodeBuilder;\n";
}
+ string collections;
+
+ if (j2me_style_) {
+ collections = string() +
+ "import java.util.Vector;\n" +
+ "import java.util.Hashtable;\n";
+ } else {
+ collections = string() +
+ "import java.util.List;\n" +
+ "import java.util.ArrayList;\n" +
+ "import java.util.Map;\n" +
+ "import java.util.HashMap;\n" +
+ "import java.util.Set;\n" +
+ "import java.util.HashSet;\n";
+ }
+
+
return
string() +
- "import java.util.List;\n" +
- "import java.util.ArrayList;\n" +
- "import java.util.Map;\n" +
- "import java.util.HashMap;\n" +
- "import java.util.Set;\n" +
- "import java.util.HashSet;\n" +
+ collections +
hash_builder +
"import com.facebook.thrift.*;\n\n";
}
@@ -567,7 +594,11 @@
if (is_exception) {
out << "extends Exception ";
}
- out << "implements TBase, java.io.Serializable ";
+ out << "implements TBase ";
+
+ if (!j2me_style_) {
+ out << ", java.io.Serializable ";
+ }
scope_up(out);
@@ -587,8 +618,17 @@
if (members.size() > 0) {
out <<
endl <<
- indent() << "public final Isset __isset = new Isset();" << endl <<
- indent() << "public static final class Isset implements java.io.Serializable {" << endl;
+ indent() << "public final Isset __isset = new Isset();" << endl;
+
+ out <<
+ indent() << "public static final class Isset";
+
+ if (!j2me_style_) {
+ out << " implements java.io.Serializable";
+ }
+
+ out << " {" << endl;
+
indent_up();
for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
indent(out) <<
@@ -723,7 +763,31 @@
indent() << " return false;" << endl;
if (t->is_base_type() && ((t_base_type*)t)->is_binary()) {
- unequal = "!java.util.Arrays.equals(this." + name + ", that." + name + ")";
+
+ // There's no Arrays.equals on CLDC
+ if (j2me_style_) {
+ // test the length first so we give ourselves a chance to shortcircuit the comparison loop
+ out <<
+ indent() << "boolean arraysAreEqual = (this." + name + ".length == that." + name + ".length);" << endl <<
+ indent() << "if (arraysAreEqual)" << endl;
+ scope_up(out);
+ out <<
+ indent() << "for (int i = 0; i < this." + name + ".length; i++)" << endl;
+ scope_up(out);
+ out <<
+ indent() << "if (this." + name + "[i] != that." + name + "[i])" << endl;
+ scope_up(out);
+ out <<
+ indent() << "arraysAreEqual = false;" << endl <<
+ indent() << "break;" << endl;
+ scope_down(out);
+ scope_down(out);
+ scope_down(out);
+
+ unequal = "!arraysAreEqual";
+ } else {
+ unequal = "!java.util.Arrays.equals(this." + name + ", that." + name + ")";
+ }
} else if (can_be_null) {
unequal = "!this." + name + ".equals(that." + name + ")";
} else {
@@ -1158,8 +1222,11 @@
indent() << "public String toString() {" << endl;
indent_up();
+ // Prefer to use StringBuilder on J2SE platforms, as it doesn't have synchronization overhead
+ string className = j2me_style_ ? "StringBuffer" : "StringBuilder";
+
out <<
- indent() << "StringBuilder sb = new StringBuilder(\"" << tstruct->get_name() << "(\");" << endl;
+ indent() << className + " sb = new " + className + "(\"" << tstruct->get_name() << "(\");" << endl;
const vector<t_field*>& fields = tstruct->get_members();
vector<t_field*>::const_iterator f_iter;
@@ -1516,8 +1583,13 @@
indent() << "private Iface iface_;" << endl;
if (extends.empty()) {
- f_service_ <<
- indent() << "protected final HashMap<String,ProcessFunction> processMap_ = new HashMap<String,ProcessFunction>();" << endl;
+ if (j2me_style_) {
+ f_service_ <<
+ indent() << "protected final Hashtable processMap_ = new Hashtable();" << endl;
+ } else {
+ f_service_ <<
+ indent() << "protected final HashMap<String,ProcessFunction> processMap_ = new HashMap<String,ProcessFunction>();" << endl;
+ }
}
f_service_ << endl;
@@ -1533,7 +1605,7 @@
// TODO(mcslee): validate message, was the seqid etc. legit?
f_service_ <<
- indent() << "ProcessFunction fn = processMap_.get(msg.name);" << endl <<
+ indent() << "ProcessFunction fn = (ProcessFunction) processMap_.get(msg.name);" << endl <<
indent() << "if (fn == null) {" << endl <<
indent() << " TProtocolUtil.skip(iprot, TType.STRUCT);" << endl <<
indent() << " iprot.readMessageEnd();" << endl <<
@@ -1917,8 +1989,11 @@
generate_deserialize_field(out, &felem);
+ // CLDC only supports addElement
+ string addMethod = j2me_style_ ? "addElement" : "add";
+
indent(out) <<
- prefix << ".add(" << elem << ");" << endl;
+ prefix << "." + addMethod + "(" << elem << ");" << endl;
}
@@ -2043,6 +2118,7 @@
}
string iter = tmp("_iter");
+
if (ttype->is_map()) {
indent(out) <<
"for (" <<
@@ -2056,11 +2132,18 @@
" : " <<
prefix << ")";
} else if (ttype->is_list()) {
- indent(out) <<
- "for (" <<
- type_name(((t_list*)ttype)->get_elem_type()) << " " << iter <<
- " : " <<
- prefix << ")";
+ if (j2me_style_) {
+ indent(out) <<
+ "final int count = " + prefix + ".size();" << endl;
+ indent(out) <<
+ "for (int i = 0; i < count; i++) ";
+ } else {
+ indent(out) <<
+ "for (" <<
+ type_name(((t_list*)ttype)->get_elem_type()) << " " << iter <<
+ " : " <<
+ prefix << ")";
+ }
}
scope_up(out);
@@ -2070,6 +2153,9 @@
} else if (ttype->is_set()) {
generate_serialize_set_element(out, (t_set*)ttype, iter);
} else if (ttype->is_list()) {
+ if (j2me_style_) {
+ indent(out) << type_name(((t_list*)ttype)->get_elem_type()) << " " << iter << " = (" + type_name(((t_list*)ttype)->get_elem_type()) + ")" + prefix + ".elementAt(i);" << endl;
+ }
generate_serialize_list_element(out, (t_list*)ttype, iter);
}
@@ -2139,31 +2225,43 @@
} else if (ttype->is_enum()) {
return (in_container ? "Integer" : "int");
} else if (ttype->is_map()) {
- t_map* tmap = (t_map*) ttype;
- if (in_init) {
- prefix = "HashMap";
- } else {
- prefix = "Map";
- }
- return prefix + "<" +
- type_name(tmap->get_key_type(), true) + "," +
- type_name(tmap->get_val_type(), true) + ">";
+ if (j2me_style_) {
+ return "Hashtable";
+ } else {
+ t_map* tmap = (t_map*) ttype;
+ if (in_init) {
+ prefix = "HashMap";
+ } else {
+ prefix = "Map";
+ }
+ return prefix + "<" +
+ type_name(tmap->get_key_type(), true) + "," +
+ type_name(tmap->get_val_type(), true) + ">";
+ }
} else if (ttype->is_set()) {
- t_set* tset = (t_set*) ttype;
- if (in_init) {
- prefix = "HashSet<";
- } else {
- prefix = "Set<";
- }
- return prefix + type_name(tset->get_elem_type(), true) + ">";
+ if (j2me_style_) {
+ return "Set";
+ } else {
+ t_set* tset = (t_set*) ttype;
+ if (in_init) {
+ prefix = "HashSet<";
+ } else {
+ prefix = "Set<";
+ }
+ return prefix + type_name(tset->get_elem_type(), true) + ">";
+ }
} else if (ttype->is_list()) {
- t_list* tlist = (t_list*) ttype;
- if (in_init) {
- prefix = "ArrayList<";
- } else {
- prefix = "List<";
- }
- return prefix + type_name(tlist->get_elem_type(), true) + ">";
+ if (j2me_style_) {
+ return "Vector";
+ } else {
+ t_list* tlist = (t_list*) ttype;
+ if (in_init) {
+ prefix = "ArrayList<";
+ } else {
+ prefix = "List<";
+ }
+ return prefix + type_name(tlist->get_elem_type(), true) + ">";
+ }
}
// Check for namespacing
@@ -2364,6 +2462,7 @@
THRIFT_REGISTER_GENERATOR(java, "Java",
" beans: Generate bean-style output files.\n"
+" j2me: Generate J2ME compliant output files.\n"
" nocamel: Do not use CamelCase field accessors with beans.\n"
" hashcode: Generate quality hashCode methods.\n"
);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment