You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@thrift.apache.org by je...@apache.org on 2015/10/14 00:02:51 UTC

thrift git commit: Fix for misc. codegen issues with THRIFT-2905 Client: Cocoa Patch: Kevin Wooten

Repository: thrift
Updated Branches:
  refs/heads/master 2d3eff5d3 -> 673c44bc1


Fix for misc. codegen issues with THRIFT-2905
Client: Cocoa
Patch: Kevin Wooten <ke...@wooten.com>

This closes #652


Project: http://git-wip-us.apache.org/repos/asf/thrift/repo
Commit: http://git-wip-us.apache.org/repos/asf/thrift/commit/673c44bc
Tree: http://git-wip-us.apache.org/repos/asf/thrift/tree/673c44bc
Diff: http://git-wip-us.apache.org/repos/asf/thrift/diff/673c44bc

Branch: refs/heads/master
Commit: 673c44bc11250cf5ed891d7855e915de5ed70ed8
Parents: 2d3eff5
Author: Jens Geyer <je...@apache.org>
Authored: Tue Oct 13 23:58:50 2015 +0200
Committer: Jens Geyer <je...@apache.org>
Committed: Tue Oct 13 23:58:50 2015 +0200

----------------------------------------------------------------------
 compiler/cpp/src/generate/t_cocoa_generator.cc | 310 ++++++++++++--------
 1 file changed, 180 insertions(+), 130 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/thrift/blob/673c44bc/compiler/cpp/src/generate/t_cocoa_generator.cc
----------------------------------------------------------------------
diff --git a/compiler/cpp/src/generate/t_cocoa_generator.cc b/compiler/cpp/src/generate/t_cocoa_generator.cc
index f8924bb..5319ba9 100644
--- a/compiler/cpp/src/generate/t_cocoa_generator.cc
+++ b/compiler/cpp/src/generate/t_cocoa_generator.cc
@@ -29,6 +29,7 @@
 #include "platform.h"
 
 using std::map;
+using std::ostream;
 using std::ofstream;
 using std::ostringstream;
 using std::string;
@@ -91,16 +92,15 @@ public:
   void generate_xception(t_struct* txception);
   void generate_service(t_service* tservice);
 
-  void print_const_value(std::ofstream& out,
-                         std::string name,
+  void print_const_value(ostream& out,
+                         string name,
                          t_type* type,
                          t_const_value* value,
-                         bool defval = false,
-                         bool is_property = false);
-  std::string render_const_value(ofstream& out,
+                         bool defval = false);
+  std::string render_const_value(ostream& out,
                                  t_type* type,
                                  t_const_value* value,
-                                 bool containerize_it = false);
+                                 bool box_it = false);
 
   void generate_cocoa_struct(t_struct* tstruct, bool is_exception);
   void generate_cocoa_struct_interface(std::ofstream& out,
@@ -213,6 +213,7 @@ public:
   std::string cocoa_imports();
   std::string cocoa_thrift_imports();
   std::string type_name(t_type* ttype, bool class_ref = false, bool needs_mutable = false);
+  std::string element_type_name(t_type* ttype);
   std::string base_type_name(t_base_type* tbase);
   std::string declare_property(t_field* tfield);
   std::string declare_property_isset(t_field* tfield);
@@ -226,9 +227,8 @@ public:
   std::string format_string_for_type(t_type* type);
   std::string format_cast_for_type(t_type* type);
   std::string call_field_setter(t_field* tfield, std::string fieldName);
-  std::string containerize(t_type* ttype, std::string fieldName);
-  std::string decontainerize(t_field* tfield, std::string fieldName);
-  std::string decontainerize(t_type* ttype, std::string fieldName);
+  std::string box(t_type *ttype, std::string field_name);
+  std::string unbox(t_type* ttype, std::string field_name);
   std::string getter_name(string field_name);
   std::string setter_name(string field_name);
 
@@ -442,7 +442,7 @@ void t_cocoa_generator::generate_consts(std::vector<t_const*> consts) {
   // Public constants for base types & strings
   vector<t_const*>::iterator c_iter;
   for (c_iter = consts.begin(); c_iter != consts.end(); ++c_iter) {
-    t_type* type = (*c_iter)->get_type();
+    t_type* type = (*c_iter)->get_type()->get_true_type();
     if (!type->is_container() && !type->is_struct()) {
       const_interface << "FOUNDATION_EXPORT " << type_name(type) << " "
                       << cocoa_prefix_ << capitalize((*c_iter)->get_name()) << ";" << endl;
@@ -456,6 +456,8 @@ void t_cocoa_generator::generate_consts(std::vector<t_const*> consts) {
   string constants_class_name = cocoa_prefix_ + capitalize(program_name_) + "Constants";
 
   if (needs_class) {
+    
+    const_interface << endl;
 
     const_interface << "@interface " << constants_class_name << " : NSObject ";
     scope_up(const_interface);
@@ -464,14 +466,14 @@ void t_cocoa_generator::generate_consts(std::vector<t_const*> consts) {
     // getter method for each constant defined.
     for (c_iter = consts.begin(); c_iter != consts.end(); ++c_iter) {
       string name = (*c_iter)->get_name();
-      t_type* type = (*c_iter)->get_type();
+      t_type* type = (*c_iter)->get_type()->get_true_type();
       if (type->is_container() || type->is_struct()) {
         t_type* type = (*c_iter)->get_type();
-        const_interface << "+ (" << type_name(type) << ") " << name << ";" << endl;
+        const_interface << endl << "+ (" << type_name(type) << ") " << name << ";" << endl;
       }
     }
 
-    const_interface << "@end";
+    const_interface << endl << "@end";
   }
 
   // this gets spit into the header file in ::close_generator
@@ -485,7 +487,8 @@ void t_cocoa_generator::generate_consts(std::vector<t_const*> consts) {
     string name = (*c_iter)->get_name();
     t_type* type = (*c_iter)->get_type();
     f_impl_ << type_name(type) << " " << cocoa_prefix_ << name;
-    if (!type->is_container() && !type->is_struct()) {
+    t_type* ttype = type->get_true_type();
+    if (!ttype->is_container() && !ttype->is_struct()) {
       f_impl_ << " = " << render_const_value(f_impl_, type, (*c_iter)->get_value());
     }
     f_impl_ << ";" << endl;
@@ -493,19 +496,21 @@ void t_cocoa_generator::generate_consts(std::vector<t_const*> consts) {
   f_impl_ << endl;
 
   if (needs_class) {
-    f_impl_ << "@implementation " << constants_class_name << endl;
+
+    f_impl_ << "@implementation " << constants_class_name << endl << endl;
 
     // initialize complex constants when the class is loaded
     f_impl_ << "+ (void) initialize ";
     scope_up(f_impl_);
 
     for (c_iter = consts.begin(); c_iter != consts.end(); ++c_iter) {
-      if ((*c_iter)->get_type()->is_container() || (*c_iter)->get_type()->is_struct()) {
+      t_type* ttype = (*c_iter)->get_type()->get_true_type();
+      if (ttype->is_container() || ttype->is_struct()) {
+        f_impl_ << endl;
         print_const_value(f_impl_,
                           cocoa_prefix_ + (*c_iter)->get_name(),
                           (*c_iter)->get_type(),
                           (*c_iter)->get_value(),
-                          false,
                           false);
         f_impl_ << ";" << endl;
       }
@@ -515,9 +520,9 @@ void t_cocoa_generator::generate_consts(std::vector<t_const*> consts) {
     // getter method for each constant
     for (c_iter = consts.begin(); c_iter != consts.end(); ++c_iter) {
       string name = (*c_iter)->get_name();
-      t_type* type = (*c_iter)->get_type();
+      t_type* type = (*c_iter)->get_type()->get_true_type();
       if (type->is_container() || type->is_struct()) {
-        f_impl_ << "+ (" << type_name(type) << ") " << name;
+        f_impl_ << endl << "+ (" << type_name(type) << ") " << name << " ";
         scope_up(f_impl_);
         indent(f_impl_) << "return " << cocoa_prefix_ << name << ";" << endl;
         scope_down(f_impl_);
@@ -932,8 +937,7 @@ void t_cocoa_generator::generate_cocoa_struct_implementation(ofstream& out,
                             "self." + (*m_iter)->get_name(),
                             t,
                             (*m_iter)->get_value(),
-                            false,
-                            true);
+                            false);
         }
       }
     }
@@ -2107,7 +2111,7 @@ void t_cocoa_generator::generate_cocoa_service_server_implementation(ofstream& o
     out << ": __thriftError];" << endl;
     out << indent() << "if (!serviceResult) return NO;" << endl;
     if (!(*f_iter)->get_returntype()->is_void()) {
-      out << indent() << "[result setSuccess: " << decontainerize((*f_iter)->get_returntype(), "serviceResult") << "];" << endl;
+      out << indent() << "[result setSuccess: " << unbox((*f_iter)->get_returntype(), "serviceResult") << "];" << endl;
     }
     
     // write out the result if not oneway
@@ -2270,35 +2274,63 @@ void t_cocoa_generator::generate_deserialize_container(ofstream& out,
  * suitable for putting into a container, if necessary.  Basically,
  * wrap scaler primitives in NSNumber objects.
  */
-string t_cocoa_generator::containerize(t_type* ttype, string fieldName) {
-  // FIXME - optimize here to avoid autorelease pool?
+string t_cocoa_generator::box(t_type* ttype, string field_name) {
+
   ttype = get_true_type(ttype);
   if (ttype->is_enum()) {
-    return "[NSNumber numberWithInt: " + fieldName + "]";
+    return "@(" + field_name + ")";
   } 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 "can't containerize void";
-    case t_base_type::TYPE_BOOL:
-      return "[NSNumber numberWithBool: " + fieldName + "]";
-    case t_base_type::TYPE_BYTE:
-      return "[NSNumber numberWithChar: " + fieldName + "]";
-    case t_base_type::TYPE_I16:
-      return "[NSNumber numberWithShort: " + fieldName + "]";
-    case t_base_type::TYPE_I32:
-      return "[NSNumber numberWithLong: " + fieldName + "]";
-    case t_base_type::TYPE_I64:
-      return "[NSNumber numberWithLongLong: " + fieldName + "]";
-    case t_base_type::TYPE_DOUBLE:
-      return "[NSNumber numberWithDouble: " + fieldName + "]";
-    default:
-      break;
+      case t_base_type::TYPE_VOID:
+        throw "can't box void";
+      case t_base_type::TYPE_BOOL:
+      case t_base_type::TYPE_BYTE:
+      case t_base_type::TYPE_I16:
+      case t_base_type::TYPE_I32:
+      case t_base_type::TYPE_I64:
+      case t_base_type::TYPE_DOUBLE:
+        return "@(" + field_name + ")";
+      default:
+        break;
     }
   }
 
   // do nothing
-  return fieldName;
+  return field_name;
+}
+
+/**
+ * Extracts the actual value from a boxed value
+ */
+string t_cocoa_generator::unbox(t_type* ttype, string field_name) {
+  ttype = get_true_type(ttype);
+  if (ttype->is_enum()) {
+    return "[" + field_name + " intValue]";
+  } 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 "can't unbox void";
+      case t_base_type::TYPE_BOOL:
+        return "[" + field_name + " boolValue]";
+      case t_base_type::TYPE_BYTE:
+        return "((SInt8)[" + field_name + " charValue])";
+      case t_base_type::TYPE_I16:
+        return "((SInt16)[" + field_name + " shortValue])";
+      case t_base_type::TYPE_I32:
+        return "((SInt32)[" + field_name + " longValue])";
+      case t_base_type::TYPE_I64:
+        return "((SInt64)[" + field_name + " longLongValue])";
+      case t_base_type::TYPE_DOUBLE:
+        return "[" + field_name + " doubleValue]";
+      default:
+        break;
+    }
+  }
+  
+  // do nothing
+  return field_name;
 }
 
 /**
@@ -2317,8 +2349,8 @@ void t_cocoa_generator::generate_deserialize_map_element(ofstream& out,
   generate_deserialize_field(out, &fkey, key);
   generate_deserialize_field(out, &fval, val);
 
-  indent(out) << "[" << fieldName << " setObject: " << containerize(valType, val)
-              << " forKey: " << containerize(keyType, key) << "];" << endl;
+  indent(out) << "[" << fieldName << " setObject: " << box(valType, val)
+              << " forKey: " << box(keyType, key) << "];" << endl;
 }
 
 /**
@@ -2333,7 +2365,7 @@ void t_cocoa_generator::generate_deserialize_set_element(ofstream& out,
 
   generate_deserialize_field(out, &felem, elem);
 
-  indent(out) << "[" << fieldName << " addObject: " << containerize(type, elem) << "];" << endl;
+  indent(out) << "[" << fieldName << " addObject: " << box(type, elem) << "];" << endl;
 }
 
 /**
@@ -2348,7 +2380,7 @@ void t_cocoa_generator::generate_deserialize_list_element(ofstream& out,
 
   generate_deserialize_field(out, &felem, elem);
 
-  indent(out) << "[" << fieldName << " addObject: " << containerize(type, elem) << "];" << endl;
+  indent(out) << "[" << fieldName << " addObject: " << box(type, elem) << "];" << endl;
 }
 
 /**
@@ -2501,44 +2533,6 @@ void t_cocoa_generator::generate_serialize_container(ofstream& out,
 }
 
 /**
- * Given a field variable name, wrap it in code that converts it to a
- * primitive type, if necessary.
- */
-string t_cocoa_generator::decontainerize(t_field* tfield, string fieldName) {
-  return decontainerize(tfield->get_type(), fieldName);
-}
-
-string t_cocoa_generator::decontainerize(t_type* ttype, string fieldName) {
-  ttype = get_true_type(ttype);
-  if (ttype->is_enum()) {
-    return "[" + fieldName + " intValue]";
-  } 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 "can't decontainerize void";
-      case t_base_type::TYPE_BOOL:
-        return "[" + fieldName + " boolValue]";
-      case t_base_type::TYPE_BYTE:
-        return "((SInt8)[" + fieldName + " charValue])";
-      case t_base_type::TYPE_I16:
-        return "((SInt16)[" + fieldName + " shortValue])";
-      case t_base_type::TYPE_I32:
-        return "((SInt32)[" + fieldName + " longValue])";
-      case t_base_type::TYPE_I64:
-        return "((SInt64)[" + fieldName + " longLongValue])";
-      case t_base_type::TYPE_DOUBLE:
-        return "[" + fieldName + " doubleValue]";
-      default:
-        break;
-    }
-  }
-  
-  // do nothing
-  return fieldName;
-}
-
-/**
  * Serializes the members of a map.
  */
 void t_cocoa_generator::generate_serialize_map_element(ofstream& out,
@@ -2546,9 +2540,9 @@ void t_cocoa_generator::generate_serialize_map_element(ofstream& out,
                                                        string key,
                                                        string mapName) {
   t_field kfield(tmap->get_key_type(), key);
-  generate_serialize_field(out, &kfield, decontainerize(&kfield, key));
+  generate_serialize_field(out, &kfield, unbox(kfield.get_type(), key));
   t_field vfield(tmap->get_val_type(), "[" + mapName + " objectForKey: " + key + "]");
-  generate_serialize_field(out, &vfield, decontainerize(&vfield, vfield.get_name()));
+  generate_serialize_field(out, &vfield, unbox(vfield.get_type(), vfield.get_name()));
 }
 
 /**
@@ -2558,7 +2552,7 @@ void t_cocoa_generator::generate_serialize_set_element(ofstream& out,
                                                        t_set* tset,
                                                        string elementName) {
   t_field efield(tset->get_elem_type(), elementName);
-  generate_serialize_field(out, &efield, decontainerize(&efield, elementName));
+  generate_serialize_field(out, &efield, unbox(efield.get_type(), elementName));
 }
 
 /**
@@ -2569,7 +2563,7 @@ void t_cocoa_generator::generate_serialize_list_element(ofstream& out,
                                                         string index,
                                                         string listName) {
   t_field efield(tlist->get_elem_type(), "[" + listName + " objectAtIndex: " + index + "]");
-  generate_serialize_field(out, &efield, decontainerize(&efield, efield.get_name()));
+  generate_serialize_field(out, &efield, unbox(efield.get_type(), efield.get_name()));
 }
 
 /**
@@ -2594,15 +2588,15 @@ string t_cocoa_generator::type_name(t_type* ttype, bool class_ref, bool needs_mu
   } else if (ttype->is_map()) {
     t_map *map = (t_map *)ttype;
     result = needs_mutable ? "NSMutableDictionary" : "NSDictionary";
-    result += "<" + type_name(map->get_key_type()) + ", " + type_name(map->get_val_type()) + ">";
+    result += "<" + element_type_name(map->get_key_type()) + ", " + element_type_name(map->get_val_type()) + ">";
   } else if (ttype->is_set()) {
     t_set *set = (t_set *)ttype;
     result = needs_mutable ? "NSMutableSet" : "NSSet";
-    result += "<" + type_name(set->get_elem_type()) + ">";
+    result += "<" + element_type_name(set->get_elem_type()) + ">";
   } else if (ttype->is_list()) {
     t_list *list = (t_list *)ttype;
     result = needs_mutable ? "NSMutableArray" : "NSArray";
-    result += "<" + type_name(list->get_elem_type()) + ">";
+    result += "<" + element_type_name(list->get_elem_type()) + ">";
   } else {
     // Check for prefix
     t_program* program = ttype->get_program();
@@ -2620,6 +2614,51 @@ string t_cocoa_generator::type_name(t_type* ttype, bool class_ref, bool needs_mu
 }
 
 /**
+ * Returns an Objective-C type name for container types
+ * 
+ * @param ttype the type
+ */
+string t_cocoa_generator::element_type_name(t_type* etype) {
+  
+  t_type* ttype = etype->get_true_type();
+  
+  if (etype->is_typedef() && type_can_be_null(ttype)) {
+    return type_name(etype);
+  }
+  
+  string result;
+  if (ttype->is_base_type()) {
+    t_base_type* tbase = (t_base_type*)ttype;
+    switch (tbase->get_base()) {
+    case t_base_type::TYPE_STRING:
+      if (tbase->is_binary()) {
+        result = "NSData *";
+      }
+      else {
+        result = "NSString *";
+      }
+      break;
+    default:
+      result = "NSNumber *";
+      break;
+    }
+  } else if (ttype->is_map()) {
+    t_map *map = (t_map *)ttype;
+    result = "NSDictionary<" + element_type_name(map->get_key_type()) + ", " + element_type_name(map->get_val_type()) + ">";
+  } else if (ttype->is_set()) {
+    t_set *set = (t_set *)ttype;
+    result = "NSSet<" + element_type_name(set->get_elem_type()) + ">";
+  } else if (ttype->is_list()) {
+    t_list *list = (t_list *)ttype;
+    result = "NSArray<" + element_type_name(list->get_elem_type()) + ">";
+  } else if (ttype->is_struct() || ttype->is_xception()) {
+    result = cocoa_prefix_ + ttype->get_name() + " *";
+  }
+  
+  return result;
+}
+
+/**
  * Returns the Objective-C type that corresponds to the thrift type.
  *
  * @param tbase The base type
@@ -2658,36 +2697,34 @@ string t_cocoa_generator::base_type_name(t_base_type* type) {
  * is NOT performed in this function as it is always run beforehand using the
  * validate_types method in main.cc
  */
-void t_cocoa_generator::print_const_value(std::ofstream& out,
-                                          std::string name,
+void t_cocoa_generator::print_const_value(ostream& out,
+                                          string name,
                                           t_type* type,
                                           t_const_value* value,
-                                          bool defval,
-                                          bool is_property) {
+                                          bool defval) {
   type = get_true_type(type);
 
-  indent(out);
   if (type->is_base_type()) {
     string v2 = render_const_value(out, type, value);
+    indent(out);
     if (defval)
       out << type_name(type) << " ";
     out << name << " = " << v2 << ";" << endl << endl;
   } else if (type->is_enum()) {
+    indent(out);
     if (defval)
       out << type_name(type) << " ";
     out << name << " = " << render_const_value(out, type, value) << ";" << endl << endl;
   } else if (type->is_struct() || type->is_xception()) {
+    indent(out);
     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;
     if (defval)
       out << type_name(type) << " ";
-    if (defval || is_property)
-      out << name << " = [" << type_name(type, true) << " new];"
-          << endl;
-    else
-      out << name << " = [" << type_name(type, true) << " new];" << endl;
+    out << name << " = [" << type_name(type, true) << " new];"
+        << endl;
     for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
       t_type* field_type = NULL;
       for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
@@ -2702,55 +2739,68 @@ void t_cocoa_generator::print_const_value(std::ofstream& out,
       std::string cap_name = capitalize(v_iter->first->get_string());
       indent(out) << "[" << name << " set" << cap_name << ":" << val << "];" << endl;
     }
-    out << endl;
   } else if (type->is_map()) {
+    ostringstream mapout;
+    indent(mapout);
     t_type* ktype = ((t_map*)type)->get_key_type();
     t_type* vtype = ((t_map*)type)->get_val_type();
     const map<t_const_value*, t_const_value*>& val = value->get_map();
     map<t_const_value*, t_const_value*>::const_iterator v_iter;
     if (defval)
-      out << "NSMutableDictionary *"
-          << name << " = [[NSMutableDictionary alloc] initWithCapacity:" << val.size() << "]; "
-          << endl;
-    for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
-      string key = render_const_value(out, ktype, v_iter->first, true);
-      string val = render_const_value(out, vtype, v_iter->second, true);
-      indent(out) << "[" << name << " setObject:" << val << " forKey:" << key << "];" << endl;
+      mapout << type_name(type) << " ";
+    mapout << name << " = @{";
+    for (v_iter = val.begin(); v_iter != val.end();) {
+      mapout << render_const_value(out, ktype, v_iter->first, true) << ": "
+          << render_const_value(out, vtype, v_iter->second, true);
+      if (++v_iter != val.end()) {
+        mapout << ", ";
+      }
     }
-    out << endl;
+    mapout << "}";
+    out << mapout.str();
   } else if (type->is_list()) {
+    ostringstream listout;
+    indent(listout);
     t_type* etype = ((t_list*)type)->get_elem_type();
     const vector<t_const_value*>& val = value->get_list();
     vector<t_const_value*>::const_iterator v_iter;
     if (defval)
-      out << "NSMutableArray *"
-          << name << " = [[NSMutableArray alloc] initWithCapacity:" << val.size() << "];" << endl;
-    for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
-      string val = render_const_value(out, etype, *v_iter, true);
-      indent(out) << "[" << name << " addObject:" << val << "];" << endl;
+      listout << type_name(type) << " ";
+    listout << name << " = @[";
+    for (v_iter = val.begin(); v_iter != val.end();) {
+      listout << render_const_value(out, etype, *v_iter, true);
+      if (++v_iter != val.end()) {
+        listout << ", ";
+      }
     }
-    out << endl;
+    listout << "]";
+    out << listout.str();
   } else if (type->is_set()) {
+    ostringstream setout;
+    indent(setout);
     t_type* etype = ((t_set*)type)->get_elem_type();
     const vector<t_const_value*>& val = value->get_list();
     vector<t_const_value*>::const_iterator v_iter;
     if (defval)
-      out << "NSMutableSet *"
-          << name << " = [[NSMutableSet alloc] initWithCapacity:" << val.size() << "];" << endl;
-    for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
-      string val = render_const_value(out, etype, *v_iter, true);
-      indent(out) << "[" << name << " addObject:" << val << "];" << endl;
+      setout << type_name(type) << " ";
+    setout << name << " = NSSet setWithArray:@[";
+    for (v_iter = val.begin(); v_iter != val.end();) {
+      setout << render_const_value(out, etype, *v_iter, true);
+      if (++v_iter != val.end()) {
+        setout << ", ";
+      }
     }
-    out << endl;
+    setout << "]]";
+    out << setout.str();
   } else {
     throw "compiler error: no const of type " + type->get_name();
   }
 }
 
-string t_cocoa_generator::render_const_value(ofstream& out,
+string t_cocoa_generator::render_const_value(ostream& out,
                                              t_type* type,
                                              t_const_value* value,
-                                             bool containerize_it) {
+                                             bool box_it) {
   type = get_true_type(type);
   std::ostringstream render;
 
@@ -2787,12 +2837,12 @@ string t_cocoa_generator::render_const_value(ofstream& out,
     render << value->get_integer();
   } else {
     string t = tmp("tmp");
-    print_const_value(out, t, type, value, true, false);
+    print_const_value(out, t, type, value, true);
     render << t;
   }
 
-  if (containerize_it) {
-    return containerize(type, render.str());
+  if (box_it) {
+    return box(type, render.str());
   }
   return render.str();
 }
@@ -2805,7 +2855,7 @@ ORIGINAL
 string t_cocoa_generator::render_const_value(string name,
                                              t_type* type,
                                              t_const_value* value,
-                                             bool containerize_it) {
+                                             bool box_it) {
   type = get_true_type(type);
   std::ostringstream render;
 
@@ -2929,8 +2979,8 @@ string t_cocoa_generator::render_const_value(string name,
     throw "don't know how to render constant for type: " + type->get_name();
   }
 
-  if (containerize_it) {
-    return containerize(type, render.str());
+  if (box_it) {
+    return box(type, render.str());
   }
 
   return render.str();