Browse Source

Restoring authorship annotation for <e-sidorov@yandex-team.ru>. Commit 2 of 2.

e-sidorov 3 years ago
parent
commit
ce2ad6f6a6

+ 464 - 464
contrib/restricted/thrift/compiler/thrift/audit/t_audit.cpp

@@ -1,464 +1,464 @@
- 
-#include <cassert> 
-#include <stdlib.h> 
-#include <stdio.h> 
-#include <stdarg.h> 
-#include <time.h> 
-#include <string> 
-#include <algorithm> 
-#include <sys/types.h> 
-#include <sys/stat.h> 
-#include <errno.h> 
-#include <limits.h> 
- 
-// Careful: must include globals first for extern definitions 
-#include "thrift/globals.h" 
- 
-#include "thrift/parse/t_program.h" 
-#include "thrift/parse/t_scope.h" 
-#include "thrift/parse/t_const.h" 
-#include "thrift/parse/t_field.h" 
- 
-#include "thrift/version.h" 
- 
-#include "thrift/audit/t_audit.h" 
- 
-extern int g_warn; 
-extern std::string g_curpath; 
-extern bool g_return_failure; 
- 
-void thrift_audit_warning(int level, const char* fmt, ...) { 
-   if (g_warn < level) { 
-      return; 
-   } 
-   va_list args; 
-   printf("[Thrift Audit Warning:%s] ", g_curpath.c_str()); 
-   va_start(args, fmt); 
-   vprintf(fmt, args); 
-   va_end(args); 
-   printf("\n"); 
-} 
- 
-void thrift_audit_failure(const char* fmt, ...) { 
-  va_list args; 
-  fprintf(stderr, "[Thrift Audit Failure:%s] ", g_curpath.c_str()); 
-  va_start(args, fmt); 
-  vfprintf(stderr, fmt, args); 
-  va_end(args); 
-  fprintf(stderr, "\n"); 
-  g_return_failure = true; 
-} 
- 
-void compare_namespace(t_program* newProgram, t_program* oldProgram) 
-{ 
-   const std::map<std::string, std::string>& newNamespaceMap = newProgram->get_all_namespaces(); 
-   const std::map<std::string, std::string>& oldNamespaceMap = oldProgram->get_all_namespaces(); 
- 
-   for(std::map<std::string, std::string>::const_iterator oldNamespaceMapIt = oldNamespaceMap.begin(); 
-         oldNamespaceMapIt != oldNamespaceMap.end(); 
-         oldNamespaceMapIt++) 
-   { 
-      std::map<std::string, std::string>::const_iterator newNamespaceMapIt = newNamespaceMap.find(oldNamespaceMapIt->first); 
-      if(newNamespaceMapIt == newNamespaceMap.end()) 
-      { 
-         thrift_audit_warning(1, "Language %s not found in new thrift file\n", (oldNamespaceMapIt->first).c_str()); 
-      } 
-      else if((newNamespaceMapIt->second) != oldNamespaceMapIt->second) 
-      { 
-         thrift_audit_warning(1, "Namespace %s changed in new thrift file\n", (oldNamespaceMapIt->second).c_str()); 
-      } 
-   } 
-} 
- 
-void compare_enum_values(t_enum* newEnum,t_enum* oldEnum) 
-{ 
-   const std::vector<t_enum_value*>& oldEnumValues = oldEnum->get_constants(); 
-   for(std::vector<t_enum_value*>::const_iterator oldEnumValuesIt = oldEnumValues.begin(); 
-         oldEnumValuesIt != oldEnumValues.end(); 
-         oldEnumValuesIt++) 
-   { 
-      int enumValue = (*oldEnumValuesIt)->get_value(); 
-      t_enum_value* newEnumValue = newEnum->get_constant_by_value(enumValue); 
-      if(newEnumValue != NULL) 
-      { 
-         std::string enumName = (*oldEnumValuesIt)->get_name(); 
-         if(enumName != newEnumValue->get_name()) 
-         { 
-            thrift_audit_warning(1, "Name of the value %d changed in enum %s\n", enumValue, oldEnum->get_name().c_str()); 
-         } 
-      } 
-      else 
-      { 
-         thrift_audit_failure("Enum value %d missing in %s\n", enumValue, oldEnum->get_name().c_str()); 
-      } 
- 
-   } 
-} 
- 
-void compare_enums(const std::vector<t_enum*>& newEnumList, const std::vector<t_enum*>& oldEnumList) 
-{ 
-   std::map<std::string,t_enum*> newEnumMap; 
-   std::vector<t_enum*>::const_iterator newEnumIt; 
-   for(newEnumIt = newEnumList.begin(); newEnumIt != newEnumList.end(); newEnumIt++) 
-   { 
-      newEnumMap[(*newEnumIt)->get_name()] = *newEnumIt; 
-   } 
-   std::vector<t_enum*>::const_iterator oldEnumIt; 
-   for(oldEnumIt = oldEnumList.begin(); oldEnumIt != oldEnumList.end(); oldEnumIt++) 
-   { 
-      std::map<std::string,t_enum*>::iterator newEnumMapIt; 
-      newEnumMapIt = newEnumMap.find((*oldEnumIt)->get_name()); 
- 
-      if(newEnumMapIt == newEnumMap.end()) 
-      { 
-         thrift_audit_warning(1, "Enum %s not found in new thrift file\n",(*oldEnumIt)->get_name().c_str()); 
-      } 
-      else 
-      { 
-         compare_enum_values(newEnumMapIt->second, *oldEnumIt); 
-      } 
-   } 
-} 
- 
-//This function returns 'true' if the two arguements are of same types. 
-//Returns false if they are of different type 
-bool compare_type(t_type* newType, t_type* oldType) 
-{ 
-   //Comparing names of two types will work when the newType and oldType are basic types or structs or enums. 
-   //However, when they are containers, get_name() returns empty for which we have to compare the type of 
-   //their elements as well. 
-   if((newType->get_name()).empty() && (oldType->get_name()).empty()) 
-   { 
- 
-      if(newType->is_list() && oldType->is_list()) 
-      { 
-         t_type* newElementType = ((t_list*)newType)->get_elem_type(); 
-         t_type* oldElementType = ((t_list*)oldType)->get_elem_type(); 
-         return compare_type(newElementType, oldElementType); 
-      } 
-      else if(newType->is_map() && oldType->is_map()) 
-      { 
-         t_type* newKeyType = ((t_map*)newType)->get_key_type(); 
-         t_type* oldKeyType = ((t_map*)oldType)->get_key_type(); 
- 
-         t_type* newValType = ((t_map*)newType)->get_val_type(); 
-         t_type* oldValType = ((t_map*)oldType)->get_val_type(); 
- 
-         return (compare_type(newKeyType, oldKeyType) && compare_type(newValType, oldValType)); 
-      } 
-      else if(newType->is_set() && oldType->is_set()) 
-      { 
-         t_type* newElementType = ((t_set*)newType)->get_elem_type(); 
-         t_type* oldElementType = ((t_set*)oldType)->get_elem_type(); 
-         return compare_type(newElementType, oldElementType); 
-      } 
-      else 
-      { 
-         return false; 
-      } 
-   } 
-   else if(newType->get_name() == oldType->get_name()) 
-   { 
-      return true; 
-   } 
-   else 
-   { 
-      return false; 
-   } 
-} 
- 
-bool compare_pair(std::pair<t_const_value*, t_const_value*> newMapPair, std::pair<t_const_value*, t_const_value*> oldMapPair) 
-{ 
-   return compare_defaults(newMapPair.first, oldMapPair.first) && compare_defaults(newMapPair.second, oldMapPair.second); 
-} 
- 
-// This function returns 'true' if the default values are same. Returns false if they are different. 
-bool compare_defaults(t_const_value* newStructDefault, t_const_value* oldStructDefault) 
-{ 
-   if(newStructDefault == NULL && oldStructDefault == NULL) return true; 
-   else if(newStructDefault == NULL && oldStructDefault != NULL) return false; 
-   else if (newStructDefault != NULL && oldStructDefault == NULL) return false; 
- 
-   if(newStructDefault->get_type() != oldStructDefault->get_type()) 
-   { 
-      return false; 
-   } 
- 
-   switch(newStructDefault->get_type()) 
-   { 
-      case t_const_value::CV_INTEGER: 
-         return (newStructDefault->get_integer() == oldStructDefault->get_integer()); 
-      case t_const_value::CV_DOUBLE: 
-         return (newStructDefault->get_double() == oldStructDefault->get_double()); 
-      case t_const_value::CV_STRING: 
-         return (newStructDefault->get_string() == oldStructDefault->get_string()); 
-      case t_const_value::CV_LIST: 
-         { 
-            const std::vector<t_const_value*>& oldDefaultList = oldStructDefault->get_list(); 
-            const std::vector<t_const_value*>& newDefaultList = newStructDefault->get_list(); 
-            bool defaultValuesCompare = (oldDefaultList.size() == newDefaultList.size()); 
- 
-            return defaultValuesCompare && std::equal(newDefaultList.begin(), newDefaultList.end(), oldDefaultList.begin(), compare_defaults); 
-         } 
-      case t_const_value::CV_MAP: 
-         { 
-            const std::map<t_const_value*, t_const_value*, t_const_value::value_compare> newMap = newStructDefault->get_map(); 
-            const std::map<t_const_value*, t_const_value*, t_const_value::value_compare> oldMap = oldStructDefault->get_map(); 
- 
-            bool defaultValuesCompare = (oldMap.size() == newMap.size()); 
- 
-            return defaultValuesCompare && std::equal(newMap.begin(), newMap.end(), oldMap.begin(), compare_pair); 
-         } 
-      case t_const_value::CV_IDENTIFIER: 
-         return (newStructDefault->get_identifier() == oldStructDefault->get_identifier()); 
-      default: 
-         return false; 
-   } 
- 
-} 
- 
-void compare_struct_field(t_field* newField, t_field* oldField, std::string oldStructName) 
-{ 
-   t_type* newFieldType = newField->get_type(); 
-   t_type* oldFieldType = oldField->get_type(); 
-   if(!compare_type(newFieldType, oldFieldType)) 
-   { 
-      thrift_audit_failure("Struct Field Type Changed for Id = %d in %s \n", newField->get_key(), oldStructName.c_str()); 
-   } 
- 
-   // A Struct member can be optional if it is mentioned explicitly, or if it is assigned with default values. 
-   bool newStructFieldOptional = (newField->get_req() != t_field::T_REQUIRED); 
-   bool oldStructFieldOptional = (oldField->get_req() != t_field::T_REQUIRED); 
- 
-   if(newStructFieldOptional != oldStructFieldOptional) 
-   { 
-      thrift_audit_failure("Struct Field Requiredness Changed for Id = %d in %s \n", newField->get_key(), oldStructName.c_str()); 
-   } 
-   if(newStructFieldOptional || oldStructFieldOptional) 
-   { 
-      if(!compare_defaults(newField->get_value(), oldField->get_value())) 
-      { 
-         thrift_audit_warning(1, "Default value changed for Id = %d in %s \n", newField->get_key(), oldStructName.c_str()); 
-      } 
-   } 
- 
-   std::string fieldName = newField->get_name(); 
-   if(fieldName != oldField->get_name()) 
-   { 
-      thrift_audit_warning(1, "Struct field name changed for Id = %d in %s\n", newField->get_key(), oldStructName.c_str()); 
-   } 
- 
-} 
- 
-void compare_single_struct(t_struct* newStruct, t_struct* oldStruct, const std::string& oldStructName = std::string()) 
-{ 
-   std::string structName = oldStructName.empty() ? oldStruct->get_name() : oldStructName; 
-   const std::vector<t_field*>& oldStructMembersInIdOrder = oldStruct->get_sorted_members(); 
-   const std::vector<t_field*>& newStructMembersInIdOrder = newStruct->get_sorted_members(); 
-   std::vector<t_field*>::const_iterator oldStructMemberIt = oldStructMembersInIdOrder.begin(); 
-   std::vector<t_field*>::const_iterator newStructMemberIt = newStructMembersInIdOrder.begin(); 
- 
-   // Since we have the struct members in their ID order, comparing their IDs can be done by traversing the two member 
-   // lists together. 
-   while(!(oldStructMemberIt == oldStructMembersInIdOrder.end() && newStructMemberIt == newStructMembersInIdOrder.end())) 
-   { 
-      if(newStructMemberIt == newStructMembersInIdOrder.end() && oldStructMemberIt != oldStructMembersInIdOrder.end()) 
-      { 
-         // A field ID has been removed from the end. 
-         thrift_audit_failure("Struct Field removed for Id = %d in %s \n", (*oldStructMemberIt)->get_key(), structName.c_str()); 
-         oldStructMemberIt++; 
-      } 
-      else if(newStructMemberIt != newStructMembersInIdOrder.end() && oldStructMemberIt == oldStructMembersInIdOrder.end()) 
-      { 
-         //New field ID has been added to the end. 
-         if((*newStructMemberIt)->get_req() == t_field::T_REQUIRED) 
-         { 
-            thrift_audit_failure("Required Struct Field Added for Id = %d in %s \n", (*newStructMemberIt)->get_key(), structName.c_str()); 
-         } 
-         newStructMemberIt++; 
-      } 
-      else if((*newStructMemberIt)->get_key() == (*oldStructMemberIt)->get_key()) 
-      { 
-         //Field ID found in both structs. Compare field types, default values. 
-         compare_struct_field(*newStructMemberIt, *oldStructMemberIt, structName); 
- 
-         newStructMemberIt++; 
-         oldStructMemberIt++; 
-      } 
-      else if((*newStructMemberIt)->get_key() < (*oldStructMemberIt)->get_key()) 
-      { 
-         //New Field Id is inserted in between 
-         //Adding fields to struct is fine, but adding them in the middle is suspicious. Error!! 
-         thrift_audit_failure("Struct field is added in the middle with Id = %d in %s\n",  (*newStructMemberIt)->get_key(),  structName.c_str()); 
-         newStructMemberIt++; 
-      } 
-      else if((*newStructMemberIt)->get_key() > (*oldStructMemberIt)->get_key()) 
-      { 
-         //A field is deleted in newStruct. 
-         thrift_audit_failure("Struct Field removed for Id = %d in %s \n",  (*oldStructMemberIt)->get_key(), structName.c_str()); 
-         oldStructMemberIt++; 
-      } 
- 
-   } 
-} 
- 
-void compare_structs(const std::vector<t_struct*>& newStructList, const std::vector<t_struct*>& oldStructList) 
-{ 
-   std::map<std::string,t_struct*> newStructMap; 
-   std::vector<t_struct*>::const_iterator newStructListIt; 
-   for(newStructListIt = newStructList.begin(); newStructListIt != newStructList.end(); newStructListIt++) 
-   { 
-      newStructMap[(*newStructListIt)->get_name()] = *newStructListIt; 
-   } 
- 
-   std::vector<t_struct*>::const_iterator oldStructListIt; 
-   for(oldStructListIt = oldStructList.begin(); oldStructListIt != oldStructList.end(); oldStructListIt++) 
-   { 
-      std::map<std::string, t_struct*>::iterator newStructMapIt; 
-      newStructMapIt = newStructMap.find((*oldStructListIt)->get_name()); 
-      if(newStructMapIt == newStructMap.end()) 
-      { 
-         thrift_audit_failure("Struct %s not found in new thrift file\n", (*oldStructListIt)->get_name().c_str()); 
-      } 
-      else 
-      { 
-         compare_single_struct(newStructMapIt->second, *oldStructListIt); 
-      } 
-   } 
- 
-} 
- 
-void compare_single_function(t_function* newFunction, t_function* oldFunction) 
-{ 
-   t_type* newFunctionReturnType = newFunction->get_returntype(); 
- 
-   if(newFunction->is_oneway() != oldFunction->is_oneway()) 
-   { 
-      thrift_audit_failure("Oneway attribute changed for function %s\n",oldFunction->get_name().c_str()); 
-   } 
-   if(!compare_type(newFunctionReturnType, oldFunction->get_returntype())) 
-   { 
-      thrift_audit_failure("Return type changed for function %s\n",oldFunction->get_name().c_str()); 
-   } 
- 
-   //Compare function arguments. 
-   compare_single_struct(newFunction->get_arglist(), oldFunction->get_arglist()); 
-   std::string exceptionName = oldFunction->get_name(); 
-   exceptionName += "_exception"; 
-   compare_single_struct(newFunction->get_xceptions(), oldFunction->get_xceptions(), exceptionName); 
-} 
- 
-void compare_functions(const std::vector<t_function*>& newFunctionList, const std::vector<t_function*>& oldFunctionList) 
-{ 
-   std::map<std::string, t_function*> newFunctionMap; 
-   std::map<std::string, t_function*>::iterator newFunctionMapIt; 
-   for(std::vector<t_function*>::const_iterator newFunctionIt = newFunctionList.begin(); 
-         newFunctionIt != newFunctionList.end(); 
-         newFunctionIt++) 
-   { 
-      newFunctionMap[(*newFunctionIt)->get_name()] = *newFunctionIt; 
-   } 
- 
-   for(std::vector<t_function*>::const_iterator oldFunctionIt = oldFunctionList.begin(); 
-         oldFunctionIt != oldFunctionList.end(); 
-         oldFunctionIt++) 
-   { 
-      newFunctionMapIt = newFunctionMap.find((*oldFunctionIt)->get_name()); 
-      if(newFunctionMapIt == newFunctionMap.end()) 
-      { 
-         thrift_audit_failure("New Thrift File has missing function %s\n",(*oldFunctionIt)->get_name().c_str()); 
-         continue; 
-      } 
-      else 
-      { 
-         //Function is found in both thrift files. Compare return type and argument list 
-         compare_single_function(newFunctionMapIt->second, *oldFunctionIt); 
-      } 
-   } 
- 
-} 
- 
-void compare_services(const std::vector<t_service*>& newServices, const std::vector<t_service*>& oldServices) 
-{ 
-   std::vector<t_service*>::const_iterator oldServiceIt; 
- 
-   std::map<std::string, t_service*> newServiceMap; 
-   for(std::vector<t_service*>::const_iterator newServiceIt = newServices.begin(); 
-         newServiceIt != newServices.end(); 
-         newServiceIt++) 
-   { 
-      newServiceMap[(*newServiceIt)->get_name()] = *newServiceIt; 
-   } 
- 
- 
-   for(oldServiceIt = oldServices.begin(); oldServiceIt != oldServices.end(); oldServiceIt++) 
-   { 
-      const std::string oldServiceName = (*oldServiceIt)->get_name(); 
-      std::map<std::string, t_service*>::iterator newServiceMapIt = newServiceMap.find(oldServiceName); 
- 
-      if(newServiceMapIt == newServiceMap.end()) 
-      { 
-         thrift_audit_failure("New Thrift file is missing a service %s\n", oldServiceName.c_str()); 
-      } 
-      else 
-      { 
-         t_service* oldServiceExtends = (*oldServiceIt)->get_extends(); 
-         t_service* newServiceExtends = (newServiceMapIt->second)->get_extends(); 
- 
-         if(oldServiceExtends == NULL) 
-         { 
-            // It is fine to add extends. So if service in older thrift did not have any extends, we are fine. 
-            // DO Nothing 
-         } 
-         else if(oldServiceExtends != NULL && newServiceExtends == NULL) 
-         { 
-            thrift_audit_failure("Change in Service inheritance for %s\n", oldServiceName.c_str()); 
-         } 
-         else 
-         { 
-            std::string oldExtendsName = oldServiceExtends->get_name(); 
-            std::string newExtendsName = newServiceExtends->get_name(); 
- 
-            if( newExtendsName != oldExtendsName) 
-            { 
-               thrift_audit_failure("Change in Service inheritance for %s\n", oldServiceName.c_str()); 
-            } 
-         } 
- 
-         compare_functions((newServiceMapIt->second)->get_functions(), (*oldServiceIt)->get_functions()); 
-      } 
- 
-   } 
- 
-} 
- 
-void compare_consts(const std::vector<t_const*>& newConst, const std::vector<t_const*>& oldConst) 
-{ 
-   std::vector<t_const*>::const_iterator newConstIt; 
-   std::vector<t_const*>::const_iterator oldConstIt; 
- 
-   std::map<std::string, t_const*> newConstMap; 
- 
-   for(newConstIt = newConst.begin(); newConstIt != newConst.end(); newConstIt++) 
-   { 
-      newConstMap[(*newConstIt)->get_name()] = *newConstIt; 
-   } 
- 
-   std::map<std::string, t_const*>::const_iterator newConstMapIt; 
-   for(oldConstIt = oldConst.begin(); oldConstIt != oldConst.end(); oldConstIt++) 
-   { 
-      newConstMapIt = newConstMap.find((*oldConstIt)->get_name()); 
-      if(newConstMapIt == newConstMap.end()) 
-      { 
-         thrift_audit_warning(1, "Constants Missing %s \n", ((*oldConstIt)->get_name()).c_str()); 
-      } 
-      else if(!compare_type((newConstMapIt->second)->get_type(), (*oldConstIt)->get_type())) 
-      { 
-         thrift_audit_warning(1, "Constant %s is of different type \n", ((*oldConstIt)->get_name()).c_str()); 
-      } 
-      else if(!compare_defaults((newConstMapIt->second)->get_value(), (*oldConstIt)->get_value())) 
-      { 
-         thrift_audit_warning(1, "Constant %s has different value\n", ((*oldConstIt)->get_name()).c_str()); 
-      } 
-   } 
-} 
+
+#include <cassert>
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <time.h>
+#include <string>
+#include <algorithm>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <limits.h>
+
+// Careful: must include globals first for extern definitions
+#include "thrift/globals.h"
+
+#include "thrift/parse/t_program.h"
+#include "thrift/parse/t_scope.h"
+#include "thrift/parse/t_const.h"
+#include "thrift/parse/t_field.h"
+
+#include "thrift/version.h"
+
+#include "thrift/audit/t_audit.h"
+
+extern int g_warn;
+extern std::string g_curpath;
+extern bool g_return_failure;
+
+void thrift_audit_warning(int level, const char* fmt, ...) {
+   if (g_warn < level) {
+      return;
+   }
+   va_list args;
+   printf("[Thrift Audit Warning:%s] ", g_curpath.c_str());
+   va_start(args, fmt);
+   vprintf(fmt, args);
+   va_end(args);
+   printf("\n");
+}
+
+void thrift_audit_failure(const char* fmt, ...) {
+  va_list args;
+  fprintf(stderr, "[Thrift Audit Failure:%s] ", g_curpath.c_str());
+  va_start(args, fmt);
+  vfprintf(stderr, fmt, args);
+  va_end(args);
+  fprintf(stderr, "\n");
+  g_return_failure = true;
+}
+
+void compare_namespace(t_program* newProgram, t_program* oldProgram)
+{
+   const std::map<std::string, std::string>& newNamespaceMap = newProgram->get_all_namespaces();
+   const std::map<std::string, std::string>& oldNamespaceMap = oldProgram->get_all_namespaces();
+
+   for(std::map<std::string, std::string>::const_iterator oldNamespaceMapIt = oldNamespaceMap.begin();
+         oldNamespaceMapIt != oldNamespaceMap.end();
+         oldNamespaceMapIt++)
+   {
+      std::map<std::string, std::string>::const_iterator newNamespaceMapIt = newNamespaceMap.find(oldNamespaceMapIt->first);
+      if(newNamespaceMapIt == newNamespaceMap.end())
+      {
+         thrift_audit_warning(1, "Language %s not found in new thrift file\n", (oldNamespaceMapIt->first).c_str());
+      }
+      else if((newNamespaceMapIt->second) != oldNamespaceMapIt->second)
+      {
+         thrift_audit_warning(1, "Namespace %s changed in new thrift file\n", (oldNamespaceMapIt->second).c_str());
+      }
+   }
+}
+
+void compare_enum_values(t_enum* newEnum,t_enum* oldEnum)
+{
+   const std::vector<t_enum_value*>& oldEnumValues = oldEnum->get_constants();
+   for(std::vector<t_enum_value*>::const_iterator oldEnumValuesIt = oldEnumValues.begin();
+         oldEnumValuesIt != oldEnumValues.end();
+         oldEnumValuesIt++)
+   {
+      int enumValue = (*oldEnumValuesIt)->get_value();
+      t_enum_value* newEnumValue = newEnum->get_constant_by_value(enumValue);
+      if(newEnumValue != NULL)
+      {
+         std::string enumName = (*oldEnumValuesIt)->get_name();
+         if(enumName != newEnumValue->get_name())
+         {
+            thrift_audit_warning(1, "Name of the value %d changed in enum %s\n", enumValue, oldEnum->get_name().c_str());
+         }
+      }
+      else
+      {
+         thrift_audit_failure("Enum value %d missing in %s\n", enumValue, oldEnum->get_name().c_str());
+      }
+
+   }
+}
+
+void compare_enums(const std::vector<t_enum*>& newEnumList, const std::vector<t_enum*>& oldEnumList)
+{
+   std::map<std::string,t_enum*> newEnumMap;
+   std::vector<t_enum*>::const_iterator newEnumIt;
+   for(newEnumIt = newEnumList.begin(); newEnumIt != newEnumList.end(); newEnumIt++)
+   {
+      newEnumMap[(*newEnumIt)->get_name()] = *newEnumIt;
+   }
+   std::vector<t_enum*>::const_iterator oldEnumIt;
+   for(oldEnumIt = oldEnumList.begin(); oldEnumIt != oldEnumList.end(); oldEnumIt++)
+   {
+      std::map<std::string,t_enum*>::iterator newEnumMapIt;
+      newEnumMapIt = newEnumMap.find((*oldEnumIt)->get_name());
+
+      if(newEnumMapIt == newEnumMap.end())
+      {
+         thrift_audit_warning(1, "Enum %s not found in new thrift file\n",(*oldEnumIt)->get_name().c_str());
+      }
+      else
+      {
+         compare_enum_values(newEnumMapIt->second, *oldEnumIt);
+      }
+   }
+}
+
+//This function returns 'true' if the two arguements are of same types.
+//Returns false if they are of different type
+bool compare_type(t_type* newType, t_type* oldType)
+{
+   //Comparing names of two types will work when the newType and oldType are basic types or structs or enums.
+   //However, when they are containers, get_name() returns empty for which we have to compare the type of
+   //their elements as well.
+   if((newType->get_name()).empty() && (oldType->get_name()).empty())
+   {
+
+      if(newType->is_list() && oldType->is_list())
+      {
+         t_type* newElementType = ((t_list*)newType)->get_elem_type();
+         t_type* oldElementType = ((t_list*)oldType)->get_elem_type();
+         return compare_type(newElementType, oldElementType);
+      }
+      else if(newType->is_map() && oldType->is_map())
+      {
+         t_type* newKeyType = ((t_map*)newType)->get_key_type();
+         t_type* oldKeyType = ((t_map*)oldType)->get_key_type();
+
+         t_type* newValType = ((t_map*)newType)->get_val_type();
+         t_type* oldValType = ((t_map*)oldType)->get_val_type();
+
+         return (compare_type(newKeyType, oldKeyType) && compare_type(newValType, oldValType));
+      }
+      else if(newType->is_set() && oldType->is_set())
+      {
+         t_type* newElementType = ((t_set*)newType)->get_elem_type();
+         t_type* oldElementType = ((t_set*)oldType)->get_elem_type();
+         return compare_type(newElementType, oldElementType);
+      }
+      else
+      {
+         return false;
+      }
+   }
+   else if(newType->get_name() == oldType->get_name())
+   {
+      return true;
+   }
+   else
+   {
+      return false;
+   }
+}
+
+bool compare_pair(std::pair<t_const_value*, t_const_value*> newMapPair, std::pair<t_const_value*, t_const_value*> oldMapPair)
+{
+   return compare_defaults(newMapPair.first, oldMapPair.first) && compare_defaults(newMapPair.second, oldMapPair.second);
+}
+
+// This function returns 'true' if the default values are same. Returns false if they are different.
+bool compare_defaults(t_const_value* newStructDefault, t_const_value* oldStructDefault)
+{
+   if(newStructDefault == NULL && oldStructDefault == NULL) return true;
+   else if(newStructDefault == NULL && oldStructDefault != NULL) return false;
+   else if (newStructDefault != NULL && oldStructDefault == NULL) return false;
+
+   if(newStructDefault->get_type() != oldStructDefault->get_type())
+   {
+      return false;
+   }
+
+   switch(newStructDefault->get_type())
+   {
+      case t_const_value::CV_INTEGER:
+         return (newStructDefault->get_integer() == oldStructDefault->get_integer());
+      case t_const_value::CV_DOUBLE:
+         return (newStructDefault->get_double() == oldStructDefault->get_double());
+      case t_const_value::CV_STRING:
+         return (newStructDefault->get_string() == oldStructDefault->get_string());
+      case t_const_value::CV_LIST:
+         {
+            const std::vector<t_const_value*>& oldDefaultList = oldStructDefault->get_list();
+            const std::vector<t_const_value*>& newDefaultList = newStructDefault->get_list();
+            bool defaultValuesCompare = (oldDefaultList.size() == newDefaultList.size());
+
+            return defaultValuesCompare && std::equal(newDefaultList.begin(), newDefaultList.end(), oldDefaultList.begin(), compare_defaults);
+         }
+      case t_const_value::CV_MAP:
+         {
+            const std::map<t_const_value*, t_const_value*, t_const_value::value_compare> newMap = newStructDefault->get_map();
+            const std::map<t_const_value*, t_const_value*, t_const_value::value_compare> oldMap = oldStructDefault->get_map();
+
+            bool defaultValuesCompare = (oldMap.size() == newMap.size());
+
+            return defaultValuesCompare && std::equal(newMap.begin(), newMap.end(), oldMap.begin(), compare_pair);
+         }
+      case t_const_value::CV_IDENTIFIER:
+         return (newStructDefault->get_identifier() == oldStructDefault->get_identifier());
+      default:
+         return false;
+   }
+
+}
+
+void compare_struct_field(t_field* newField, t_field* oldField, std::string oldStructName)
+{
+   t_type* newFieldType = newField->get_type();
+   t_type* oldFieldType = oldField->get_type();
+   if(!compare_type(newFieldType, oldFieldType))
+   {
+      thrift_audit_failure("Struct Field Type Changed for Id = %d in %s \n", newField->get_key(), oldStructName.c_str());
+   }
+
+   // A Struct member can be optional if it is mentioned explicitly, or if it is assigned with default values.
+   bool newStructFieldOptional = (newField->get_req() != t_field::T_REQUIRED);
+   bool oldStructFieldOptional = (oldField->get_req() != t_field::T_REQUIRED);
+
+   if(newStructFieldOptional != oldStructFieldOptional)
+   {
+      thrift_audit_failure("Struct Field Requiredness Changed for Id = %d in %s \n", newField->get_key(), oldStructName.c_str());
+   }
+   if(newStructFieldOptional || oldStructFieldOptional)
+   {
+      if(!compare_defaults(newField->get_value(), oldField->get_value()))
+      {
+         thrift_audit_warning(1, "Default value changed for Id = %d in %s \n", newField->get_key(), oldStructName.c_str());
+      }
+   }
+
+   std::string fieldName = newField->get_name();
+   if(fieldName != oldField->get_name())
+   {
+      thrift_audit_warning(1, "Struct field name changed for Id = %d in %s\n", newField->get_key(), oldStructName.c_str());
+   }
+
+}
+
+void compare_single_struct(t_struct* newStruct, t_struct* oldStruct, const std::string& oldStructName = std::string())
+{
+   std::string structName = oldStructName.empty() ? oldStruct->get_name() : oldStructName;
+   const std::vector<t_field*>& oldStructMembersInIdOrder = oldStruct->get_sorted_members();
+   const std::vector<t_field*>& newStructMembersInIdOrder = newStruct->get_sorted_members();
+   std::vector<t_field*>::const_iterator oldStructMemberIt = oldStructMembersInIdOrder.begin();
+   std::vector<t_field*>::const_iterator newStructMemberIt = newStructMembersInIdOrder.begin();
+
+   // Since we have the struct members in their ID order, comparing their IDs can be done by traversing the two member
+   // lists together.
+   while(!(oldStructMemberIt == oldStructMembersInIdOrder.end() && newStructMemberIt == newStructMembersInIdOrder.end()))
+   {
+      if(newStructMemberIt == newStructMembersInIdOrder.end() && oldStructMemberIt != oldStructMembersInIdOrder.end())
+      {
+         // A field ID has been removed from the end.
+         thrift_audit_failure("Struct Field removed for Id = %d in %s \n", (*oldStructMemberIt)->get_key(), structName.c_str());
+         oldStructMemberIt++;
+      }
+      else if(newStructMemberIt != newStructMembersInIdOrder.end() && oldStructMemberIt == oldStructMembersInIdOrder.end())
+      {
+         //New field ID has been added to the end.
+         if((*newStructMemberIt)->get_req() == t_field::T_REQUIRED)
+         {
+            thrift_audit_failure("Required Struct Field Added for Id = %d in %s \n", (*newStructMemberIt)->get_key(), structName.c_str());
+         }
+         newStructMemberIt++;
+      }
+      else if((*newStructMemberIt)->get_key() == (*oldStructMemberIt)->get_key())
+      {
+         //Field ID found in both structs. Compare field types, default values.
+         compare_struct_field(*newStructMemberIt, *oldStructMemberIt, structName);
+
+         newStructMemberIt++;
+         oldStructMemberIt++;
+      }
+      else if((*newStructMemberIt)->get_key() < (*oldStructMemberIt)->get_key())
+      {
+         //New Field Id is inserted in between
+         //Adding fields to struct is fine, but adding them in the middle is suspicious. Error!!
+         thrift_audit_failure("Struct field is added in the middle with Id = %d in %s\n",  (*newStructMemberIt)->get_key(),  structName.c_str());
+         newStructMemberIt++;
+      }
+      else if((*newStructMemberIt)->get_key() > (*oldStructMemberIt)->get_key())
+      {
+         //A field is deleted in newStruct.
+         thrift_audit_failure("Struct Field removed for Id = %d in %s \n",  (*oldStructMemberIt)->get_key(), structName.c_str());
+         oldStructMemberIt++;
+      }
+
+   }
+}
+
+void compare_structs(const std::vector<t_struct*>& newStructList, const std::vector<t_struct*>& oldStructList)
+{
+   std::map<std::string,t_struct*> newStructMap;
+   std::vector<t_struct*>::const_iterator newStructListIt;
+   for(newStructListIt = newStructList.begin(); newStructListIt != newStructList.end(); newStructListIt++)
+   {
+      newStructMap[(*newStructListIt)->get_name()] = *newStructListIt;
+   }
+
+   std::vector<t_struct*>::const_iterator oldStructListIt;
+   for(oldStructListIt = oldStructList.begin(); oldStructListIt != oldStructList.end(); oldStructListIt++)
+   {
+      std::map<std::string, t_struct*>::iterator newStructMapIt;
+      newStructMapIt = newStructMap.find((*oldStructListIt)->get_name());
+      if(newStructMapIt == newStructMap.end())
+      {
+         thrift_audit_failure("Struct %s not found in new thrift file\n", (*oldStructListIt)->get_name().c_str());
+      }
+      else
+      {
+         compare_single_struct(newStructMapIt->second, *oldStructListIt);
+      }
+   }
+
+}
+
+void compare_single_function(t_function* newFunction, t_function* oldFunction)
+{
+   t_type* newFunctionReturnType = newFunction->get_returntype();
+
+   if(newFunction->is_oneway() != oldFunction->is_oneway())
+   {
+      thrift_audit_failure("Oneway attribute changed for function %s\n",oldFunction->get_name().c_str());
+   }
+   if(!compare_type(newFunctionReturnType, oldFunction->get_returntype()))
+   {
+      thrift_audit_failure("Return type changed for function %s\n",oldFunction->get_name().c_str());
+   }
+
+   //Compare function arguments.
+   compare_single_struct(newFunction->get_arglist(), oldFunction->get_arglist());
+   std::string exceptionName = oldFunction->get_name();
+   exceptionName += "_exception";
+   compare_single_struct(newFunction->get_xceptions(), oldFunction->get_xceptions(), exceptionName);
+}
+
+void compare_functions(const std::vector<t_function*>& newFunctionList, const std::vector<t_function*>& oldFunctionList)
+{
+   std::map<std::string, t_function*> newFunctionMap;
+   std::map<std::string, t_function*>::iterator newFunctionMapIt;
+   for(std::vector<t_function*>::const_iterator newFunctionIt = newFunctionList.begin();
+         newFunctionIt != newFunctionList.end();
+         newFunctionIt++)
+   {
+      newFunctionMap[(*newFunctionIt)->get_name()] = *newFunctionIt;
+   }
+
+   for(std::vector<t_function*>::const_iterator oldFunctionIt = oldFunctionList.begin();
+         oldFunctionIt != oldFunctionList.end();
+         oldFunctionIt++)
+   {
+      newFunctionMapIt = newFunctionMap.find((*oldFunctionIt)->get_name());
+      if(newFunctionMapIt == newFunctionMap.end())
+      {
+         thrift_audit_failure("New Thrift File has missing function %s\n",(*oldFunctionIt)->get_name().c_str());
+         continue;
+      }
+      else
+      {
+         //Function is found in both thrift files. Compare return type and argument list
+         compare_single_function(newFunctionMapIt->second, *oldFunctionIt);
+      }
+   }
+
+}
+
+void compare_services(const std::vector<t_service*>& newServices, const std::vector<t_service*>& oldServices)
+{
+   std::vector<t_service*>::const_iterator oldServiceIt;
+
+   std::map<std::string, t_service*> newServiceMap;
+   for(std::vector<t_service*>::const_iterator newServiceIt = newServices.begin();
+         newServiceIt != newServices.end();
+         newServiceIt++)
+   {
+      newServiceMap[(*newServiceIt)->get_name()] = *newServiceIt;
+   }
+
+
+   for(oldServiceIt = oldServices.begin(); oldServiceIt != oldServices.end(); oldServiceIt++)
+   {
+      const std::string oldServiceName = (*oldServiceIt)->get_name();
+      std::map<std::string, t_service*>::iterator newServiceMapIt = newServiceMap.find(oldServiceName);
+
+      if(newServiceMapIt == newServiceMap.end())
+      {
+         thrift_audit_failure("New Thrift file is missing a service %s\n", oldServiceName.c_str());
+      }
+      else
+      {
+         t_service* oldServiceExtends = (*oldServiceIt)->get_extends();
+         t_service* newServiceExtends = (newServiceMapIt->second)->get_extends();
+
+         if(oldServiceExtends == NULL)
+         {
+            // It is fine to add extends. So if service in older thrift did not have any extends, we are fine.
+            // DO Nothing
+         }
+         else if(oldServiceExtends != NULL && newServiceExtends == NULL)
+         {
+            thrift_audit_failure("Change in Service inheritance for %s\n", oldServiceName.c_str());
+         }
+         else
+         {
+            std::string oldExtendsName = oldServiceExtends->get_name();
+            std::string newExtendsName = newServiceExtends->get_name();
+
+            if( newExtendsName != oldExtendsName)
+            {
+               thrift_audit_failure("Change in Service inheritance for %s\n", oldServiceName.c_str());
+            }
+         }
+
+         compare_functions((newServiceMapIt->second)->get_functions(), (*oldServiceIt)->get_functions());
+      }
+
+   }
+
+}
+
+void compare_consts(const std::vector<t_const*>& newConst, const std::vector<t_const*>& oldConst)
+{
+   std::vector<t_const*>::const_iterator newConstIt;
+   std::vector<t_const*>::const_iterator oldConstIt;
+
+   std::map<std::string, t_const*> newConstMap;
+
+   for(newConstIt = newConst.begin(); newConstIt != newConst.end(); newConstIt++)
+   {
+      newConstMap[(*newConstIt)->get_name()] = *newConstIt;
+   }
+
+   std::map<std::string, t_const*>::const_iterator newConstMapIt;
+   for(oldConstIt = oldConst.begin(); oldConstIt != oldConst.end(); oldConstIt++)
+   {
+      newConstMapIt = newConstMap.find((*oldConstIt)->get_name());
+      if(newConstMapIt == newConstMap.end())
+      {
+         thrift_audit_warning(1, "Constants Missing %s \n", ((*oldConstIt)->get_name()).c_str());
+      }
+      else if(!compare_type((newConstMapIt->second)->get_type(), (*oldConstIt)->get_type()))
+      {
+         thrift_audit_warning(1, "Constant %s is of different type \n", ((*oldConstIt)->get_name()).c_str());
+      }
+      else if(!compare_defaults((newConstMapIt->second)->get_value(), (*oldConstIt)->get_value()))
+      {
+         thrift_audit_warning(1, "Constant %s has different value\n", ((*oldConstIt)->get_name()).c_str());
+      }
+   }
+}

+ 14 - 14
contrib/restricted/thrift/compiler/thrift/audit/t_audit.h

@@ -1,14 +1,14 @@
-#ifndef T_AUDIT_H 
-#define T_AUDIT_H 
- 
-void compare_namespace(t_program* newProgram, t_program* oldProgram); 
-void compare_enums(const std::vector<t_enum*>& newEnumList, 
-                   const std::vector<t_enum*>& oldEnumList); 
-bool compare_defaults(t_const_value* newStructDefault, t_const_value* oldStructDefault); 
-void compare_structs(const std::vector<t_struct*>& newStructList, 
-                     const std::vector<t_struct*>& oldStructList); 
-void compare_services(const std::vector<t_service*>& newServices, 
-                      const std::vector<t_service*>& oldServices); 
-void compare_consts(const std::vector<t_const*>& newConst, const std::vector<t_const*>& oldConst); 
- 
-#endif 
+#ifndef T_AUDIT_H
+#define T_AUDIT_H
+
+void compare_namespace(t_program* newProgram, t_program* oldProgram);
+void compare_enums(const std::vector<t_enum*>& newEnumList,
+                   const std::vector<t_enum*>& oldEnumList);
+bool compare_defaults(t_const_value* newStructDefault, t_const_value* oldStructDefault);
+void compare_structs(const std::vector<t_struct*>& newStructList,
+                     const std::vector<t_struct*>& oldStructList);
+void compare_services(const std::vector<t_service*>& newServices,
+                      const std::vector<t_service*>& oldServices);
+void compare_consts(const std::vector<t_const*>& newConst, const std::vector<t_const*>& oldConst);
+
+#endif

+ 69 - 69
contrib/restricted/thrift/compiler/thrift/common.cc

@@ -1,69 +1,69 @@
-/* 
- * Licensed to the Apache Software Foundation (ASF) under one 
- * or more contributor license agreements. See the NOTICE file 
- * distributed with this work for additional information 
- * regarding copyright ownership. The ASF licenses this file 
- * to you under the Apache License, Version 2.0 (the 
- * "License"); you may not use this file except in compliance 
- * with the License. You may obtain a copy of the License at 
- * 
- *   http://www.apache.org/licenses/LICENSE-2.0 
- * 
- * Unless required by applicable law or agreed to in writing, 
- * software distributed under the License is distributed on an 
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 
- * KIND, either express or implied. See the License for the 
- * specific language governing permissions and limitations 
- * under the License. 
- */ 
- 
-#include "thrift/common.h" 
-#include "thrift/parse/t_base_type.h" 
- 
-t_type* g_type_void; 
-t_type* g_type_string; 
-t_type* g_type_binary; 
-t_type* g_type_slist; 
-t_type* g_type_bool; 
-t_type* g_type_i8; 
-t_type* g_type_i16; 
-t_type* g_type_i32; 
-t_type* g_type_i64; 
-t_type* g_type_double; 
- 
-void initGlobals() { 
-  g_type_void = new t_base_type("void", t_base_type::TYPE_VOID); 
-  g_type_string = new t_base_type("string", t_base_type::TYPE_STRING); 
-  g_type_binary = new t_base_type("string", t_base_type::TYPE_STRING); 
-  ((t_base_type*)g_type_binary)->set_binary(true); 
-  g_type_slist = new t_base_type("string", t_base_type::TYPE_STRING); 
-  ((t_base_type*)g_type_slist)->set_string_list(true); 
-  g_type_bool = new t_base_type("bool", t_base_type::TYPE_BOOL); 
-  g_type_i8 = new t_base_type("i8", t_base_type::TYPE_I8); 
-  g_type_i16 = new t_base_type("i16", t_base_type::TYPE_I16); 
-  g_type_i32 = new t_base_type("i32", t_base_type::TYPE_I32); 
-  g_type_i64 = new t_base_type("i64", t_base_type::TYPE_I64); 
-  g_type_double = new t_base_type("double", t_base_type::TYPE_DOUBLE); 
-} 
- 
-void clearGlobals() { 
-  delete g_type_void; 
-  delete g_type_string; 
-  delete g_type_bool; 
-  delete g_type_i8; 
-  delete g_type_i16; 
-  delete g_type_i32; 
-  delete g_type_i64; 
-  delete g_type_double; 
-} 
- 
-/** 
- * Those are not really needed for plugins but causes link errors without 
- */ 
- 
-/** 
- * The location of the last parsed doctext comment. 
- */ 
-int g_doctext_lineno; 
-int g_program_doctext_lineno = 0; 
-PROGDOCTEXT_STATUS g_program_doctext_status = INVALID; 
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#include "thrift/common.h"
+#include "thrift/parse/t_base_type.h"
+
+t_type* g_type_void;
+t_type* g_type_string;
+t_type* g_type_binary;
+t_type* g_type_slist;
+t_type* g_type_bool;
+t_type* g_type_i8;
+t_type* g_type_i16;
+t_type* g_type_i32;
+t_type* g_type_i64;
+t_type* g_type_double;
+
+void initGlobals() {
+  g_type_void = new t_base_type("void", t_base_type::TYPE_VOID);
+  g_type_string = new t_base_type("string", t_base_type::TYPE_STRING);
+  g_type_binary = new t_base_type("string", t_base_type::TYPE_STRING);
+  ((t_base_type*)g_type_binary)->set_binary(true);
+  g_type_slist = new t_base_type("string", t_base_type::TYPE_STRING);
+  ((t_base_type*)g_type_slist)->set_string_list(true);
+  g_type_bool = new t_base_type("bool", t_base_type::TYPE_BOOL);
+  g_type_i8 = new t_base_type("i8", t_base_type::TYPE_I8);
+  g_type_i16 = new t_base_type("i16", t_base_type::TYPE_I16);
+  g_type_i32 = new t_base_type("i32", t_base_type::TYPE_I32);
+  g_type_i64 = new t_base_type("i64", t_base_type::TYPE_I64);
+  g_type_double = new t_base_type("double", t_base_type::TYPE_DOUBLE);
+}
+
+void clearGlobals() {
+  delete g_type_void;
+  delete g_type_string;
+  delete g_type_bool;
+  delete g_type_i8;
+  delete g_type_i16;
+  delete g_type_i32;
+  delete g_type_i64;
+  delete g_type_double;
+}
+
+/**
+ * Those are not really needed for plugins but causes link errors without
+ */
+
+/**
+ * The location of the last parsed doctext comment.
+ */
+int g_doctext_lineno;
+int g_program_doctext_lineno = 0;
+PROGDOCTEXT_STATUS g_program_doctext_status = INVALID;

+ 43 - 43
contrib/restricted/thrift/compiler/thrift/common.h

@@ -1,43 +1,43 @@
-/* 
- * Licensed to the Apache Software Foundation (ASF) under one 
- * or more contributor license agreements. See the NOTICE file 
- * distributed with this work for additional information 
- * regarding copyright ownership. The ASF licenses this file 
- * to you under the Apache License, Version 2.0 (the 
- * "License"); you may not use this file except in compliance 
- * with the License. You may obtain a copy of the License at 
- * 
- *   http://www.apache.org/licenses/LICENSE-2.0 
- * 
- * Unless required by applicable law or agreed to in writing, 
- * software distributed under the License is distributed on an 
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 
- * KIND, either express or implied. See the License for the 
- * specific language governing permissions and limitations 
- * under the License. 
- */ 
- 
-#ifndef T_COMMON_H 
-#define T_COMMON_H 
- 
-#include "thrift/parse/t_type.h" 
- 
-/** 
- * Global types for the parser to be able to reference 
- */ 
- 
-extern t_type* g_type_void; 
-extern t_type* g_type_string; 
-extern t_type* g_type_binary; 
-extern t_type* g_type_slist; 
-extern t_type* g_type_bool; 
-extern t_type* g_type_i8; 
-extern t_type* g_type_i16; 
-extern t_type* g_type_i32; 
-extern t_type* g_type_i64; 
-extern t_type* g_type_double; 
- 
-void initGlobals(); 
-void clearGlobals(); 
- 
-#endif 
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#ifndef T_COMMON_H
+#define T_COMMON_H
+
+#include "thrift/parse/t_type.h"
+
+/**
+ * Global types for the parser to be able to reference
+ */
+
+extern t_type* g_type_void;
+extern t_type* g_type_string;
+extern t_type* g_type_binary;
+extern t_type* g_type_slist;
+extern t_type* g_type_bool;
+extern t_type* g_type_i8;
+extern t_type* g_type_i16;
+extern t_type* g_type_i32;
+extern t_type* g_type_i64;
+extern t_type* g_type_double;
+
+void initGlobals();
+void clearGlobals();
+
+#endif

+ 2594 - 2594
contrib/restricted/thrift/compiler/thrift/generate/t_as3_generator.cc

@@ -1,2594 +1,2594 @@
-/* 
- * Licensed to the Apache Software Foundation (ASF) under one 
- * or more contributor license agreements. See the NOTICE file 
- * distributed with this work for additional information 
- * regarding copyright ownership. The ASF licenses this file 
- * to you under the Apache License, Version 2.0 (the 
- * "License"); you may not use this file except in compliance 
- * with the License. You may obtain a copy of the License at 
- * 
- *   http://www.apache.org/licenses/LICENSE-2.0 
- * 
- * Unless required by applicable law or agreed to in writing, 
- * software distributed under the License is distributed on an 
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 
- * KIND, either express or implied. See the License for the 
- * specific language governing permissions and limitations 
- * under the License. 
- */ 
- 
-#include <sstream> 
-#include <string> 
-#include <fstream> 
-#include <iostream> 
-#include <vector> 
-#include <cctype> 
- 
-#include <sys/stat.h> 
-#include <stdexcept> 
- 
-#include "thrift/platform.h" 
-#include "thrift/generate/t_oop_generator.h" 
- 
-using std::map; 
-using std::ostream; 
-using std::ostringstream; 
-using std::string; 
-using std::stringstream; 
-using std::vector; 
- 
-static const string endl = "\n"; // avoid ostream << std::endl flushes 
- 
-/** 
- * AS3 code generator. 
- * 
- */ 
-class t_as3_generator : public t_oop_generator { 
-public: 
-  t_as3_generator(t_program* program, 
-                  const std::map<std::string, std::string>& parsed_options, 
-                  const std::string& option_string) 
-    : t_oop_generator(program) { 
-    (void)option_string; 
-    std::map<std::string, std::string>::const_iterator iter; 
- 
-    bindable_ = false; 
-    for( iter = parsed_options.begin(); iter != parsed_options.end(); ++iter) { 
-      if( iter->first.compare("bindable") == 0) { 
-        bindable_ = true; 
-      } else { 
-        throw "unknown option as3:" + iter->first; 
-      } 
-    } 
- 
-    out_dir_base_ = "gen-as3"; 
-  } 
- 
-  /** 
-   * Init and close methods 
-   */ 
- 
-  void init_generator(); 
-  void close_generator(); 
- 
-  void generate_consts(std::vector<t_const*> consts); 
- 
-  /** 
-   * Program-level generation functions 
-   */ 
- 
-  void generate_typedef(t_typedef* ttypedef); 
-  void generate_enum(t_enum* tenum); 
-  void generate_struct(t_struct* tstruct); 
-  void generate_xception(t_struct* txception); 
-  void generate_service(t_service* tservice); 
- 
-  void print_const_value(std::ostream& out, 
-                         std::string name, 
-                         t_type* type, 
-                         t_const_value* value, 
-                         bool in_static, 
-                         bool defval = false); 
-  std::string render_const_value(ostream& out, 
-                                 std::string name, 
-                                 t_type* type, 
-                                 t_const_value* value); 
- 
-  /** 
-   * Service-level generation functions 
-   */ 
- 
-  void generate_as3_struct(t_struct* tstruct, bool is_exception); 
- 
-  void generate_as3_struct_definition(std::ostream& out, 
-                                      t_struct* tstruct, 
-                                      bool is_xception = false, 
-                                      bool in_class = false, 
-                                      bool is_result = false); 
-  // removed -- equality,compare_to 
-  void generate_as3_struct_reader(std::ostream& out, t_struct* tstruct); 
-  void generate_as3_validator(std::ostream& out, t_struct* tstruct); 
-  void generate_as3_struct_result_writer(std::ostream& out, t_struct* tstruct); 
-  void generate_as3_struct_writer(std::ostream& out, t_struct* tstruct); 
-  void generate_as3_struct_tostring(std::ostream& out, t_struct* tstruct, bool bindable); 
-  void generate_as3_meta_data_map(std::ostream& out, t_struct* tstruct); 
-  void generate_field_value_meta_data(std::ostream& out, t_type* type); 
-  std::string get_as3_type_string(t_type* type); 
-  void generate_reflection_setters(std::ostringstream& out, 
-                                   t_type* type, 
-                                   std::string field_name, 
-                                   std::string cap_name); 
-  void generate_reflection_getters(std::ostringstream& out, 
-                                   t_type* type, 
-                                   std::string field_name, 
-                                   std::string cap_name); 
-  void generate_generic_field_getters_setters(std::ostream& out, t_struct* tstruct); 
-  void generate_generic_isset_method(std::ostream& out, t_struct* tstruct); 
-  void generate_as3_bean_boilerplate(std::ostream& out, t_struct* tstruct, bool bindable); 
- 
-  void generate_function_helpers(t_function* tfunction); 
-  std::string get_cap_name(std::string name); 
-  std::string generate_isset_check(t_field* field); 
-  std::string generate_isset_check(std::string field); 
-  void generate_isset_set(ostream& out, t_field* field); 
-  // removed std::string isset_field_id(t_field* field); 
- 
-  void generate_service_interface(t_service* tservice); 
-  void generate_service_helpers(t_service* tservice); 
-  void generate_service_client(t_service* tservice); 
-  void generate_service_server(t_service* tservice); 
-  void generate_process_function(t_service* tservice, t_function* tfunction); 
- 
-  /** 
-   * Serialization constructs 
-   */ 
- 
-  void generate_deserialize_field(std::ostream& out, t_field* tfield, std::string prefix = ""); 
- 
-  void generate_deserialize_struct(std::ostream& out, t_struct* tstruct, std::string prefix = ""); 
- 
-  void generate_deserialize_container(std::ostream& out, t_type* ttype, std::string prefix = ""); 
- 
-  void generate_deserialize_set_element(std::ostream& out, t_set* tset, std::string prefix = ""); 
- 
-  void generate_deserialize_map_element(std::ostream& out, t_map* tmap, std::string prefix = ""); 
- 
-  void generate_deserialize_list_element(std::ostream& out, 
-                                         t_list* tlist, 
-                                         std::string prefix = ""); 
- 
-  void generate_serialize_field(std::ostream& out, t_field* tfield, std::string prefix = ""); 
- 
-  void generate_serialize_struct(std::ostream& out, t_struct* tstruct, std::string prefix = ""); 
- 
-  void generate_serialize_container(std::ostream& out, t_type* ttype, std::string prefix = ""); 
- 
-  void generate_serialize_map_element(std::ostream& out, 
-                                      t_map* tmap, 
-                                      std::string iter, 
-                                      std::string map); 
- 
-  void generate_serialize_set_element(std::ostream& out, t_set* tmap, std::string iter); 
- 
-  void generate_serialize_list_element(std::ostream& out, t_list* tlist, std::string iter); 
- 
-  void generate_as3_doc(std::ostream& out, t_doc* tdoc); 
- 
-  void generate_as3_doc(std::ostream& out, t_function* tdoc); 
- 
-  /** 
-   * Helper rendering functions 
-   */ 
- 
-  std::string as3_package(); 
-  std::string as3_type_imports(); 
-  std::string as3_thrift_imports(); 
-  std::string as3_thrift_gen_imports(t_struct* tstruct, string& imports); 
-  std::string as3_thrift_gen_imports(t_service* tservice); 
-  std::string type_name(t_type* ttype, bool in_container = false, bool in_init = false); 
-  std::string base_type_name(t_base_type* tbase, bool in_container = false); 
-  std::string declare_field(t_field* tfield, bool init = false); 
-  std::string function_signature(t_function* tfunction, std::string prefix = ""); 
-  std::string argument_list(t_struct* tstruct); 
-  std::string type_to_enum(t_type* ttype); 
-  std::string get_enum_class_name(t_type* type); 
- 
-  bool type_can_be_null(t_type* ttype) { 
-    ttype = get_true_type(ttype); 
- 
-    return ttype->is_container() || ttype->is_struct() || ttype->is_xception() 
-           || ttype->is_string(); 
-  } 
- 
-  std::string constant_name(std::string name); 
- 
-private: 
-  /** 
-   * File streams 
-   */ 
- 
-  std::string package_name_; 
-  ofstream_with_content_based_conditional_update f_service_; 
-  std::string package_dir_; 
- 
-  bool bindable_; 
-}; 
- 
-/** 
- * Prepares for file generation by opening up the necessary file output 
- * streams. 
- * 
- * @param tprogram The program to generate 
- */ 
-void t_as3_generator::init_generator() { 
-  // Make output directory 
-  MKDIR(get_out_dir().c_str()); 
-  package_name_ = program_->get_namespace("as3"); 
- 
-  string dir = package_name_; 
-  string subdir = get_out_dir(); 
-  string::size_type loc; 
-  while ((loc = dir.find(".")) != string::npos) { 
-    subdir = subdir + "/" + dir.substr(0, loc); 
-    MKDIR(subdir.c_str()); 
-    dir = dir.substr(loc + 1); 
-  } 
-  if (dir.size() > 0) { 
-    subdir = subdir + "/" + dir; 
-    MKDIR(subdir.c_str()); 
-  } 
- 
-  package_dir_ = subdir; 
-} 
- 
-/** 
- * Packages the generated file 
- * 
- * @return String of the package, i.e. "package org.apache.thriftdemo;" 
- */ 
-string t_as3_generator::as3_package() { 
-  if (!package_name_.empty()) { 
-    return string("package ") + package_name_ + " "; 
-  } 
-  return "package "; 
-} 
- 
-/** 
- * Prints standard as3 imports 
- * 
- * @return List of imports for As3 types that are used in here 
- */ 
-string t_as3_generator::as3_type_imports() { 
-  return string() + "import org.apache.thrift.Set;\n" + "import flash.utils.ByteArray;\n" 
-         + "import flash.utils.Dictionary;\n\n"; 
-} 
- 
-/** 
- * Prints standard as3 imports 
- * 
- * @return List of imports necessary for thrift 
- */ 
-string t_as3_generator::as3_thrift_imports() { 
-  return string() + "import org.apache.thrift.*;\n" + "import org.apache.thrift.meta_data.*;\n" 
-         + "import org.apache.thrift.protocol.*;\n\n"; 
-} 
- 
-/** 
- * Prints imports needed for a given type 
- * 
- * @return List of imports necessary for a given t_struct 
- */ 
-string t_as3_generator::as3_thrift_gen_imports(t_struct* tstruct, string& imports) { 
- 
-  const vector<t_field*>& members = tstruct->get_members(); 
-  vector<t_field*>::const_iterator m_iter; 
- 
-  // For each type check if it is from a differnet namespace 
-  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { 
-    t_program* program = (*m_iter)->get_type()->get_program(); 
-    if (program != NULL && program != program_) { 
-      string package = program->get_namespace("as3"); 
-      if (!package.empty()) { 
-        if (imports.find(package + "." + (*m_iter)->get_type()->get_name()) == string::npos) { 
-          imports.append("import " + package + "." + (*m_iter)->get_type()->get_name() + ";\n"); 
-        } 
-      } 
-    } 
-  } 
-  return imports; 
-} 
- 
-/** 
- * Prints imports needed for a given type 
- * 
- * @return List of imports necessary for a given t_service 
- */ 
-string t_as3_generator::as3_thrift_gen_imports(t_service* tservice) { 
-  string imports; 
-  const vector<t_function*>& functions = tservice->get_functions(); 
-  vector<t_function*>::const_iterator f_iter; 
- 
-  // For each type check if it is from a differnet namespace 
-  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) { 
-    t_program* program = (*f_iter)->get_returntype()->get_program(); 
-    if (program != NULL && program != program_) { 
-      string package = program->get_namespace("as3"); 
-      if (!package.empty()) { 
-        if (imports.find(package + "." + (*f_iter)->get_returntype()->get_name()) == string::npos) { 
-          imports.append("import " + package + "." + (*f_iter)->get_returntype()->get_name() 
-                         + ";\n"); 
-        } 
-      } 
-    } 
- 
-    as3_thrift_gen_imports((*f_iter)->get_arglist(), imports); 
-    as3_thrift_gen_imports((*f_iter)->get_xceptions(), imports); 
-  } 
- 
-  return imports; 
-} 
- 
-/** 
- * Nothing in As3 
- */ 
-void t_as3_generator::close_generator() { 
-} 
- 
-/** 
- * Generates a typedef. This is not done in As3, since it does 
- * not support arbitrary name replacements, and it'd be a wacky waste 
- * of overhead to make wrapper classes. 
- * 
- * @param ttypedef The type definition 
- */ 
-void t_as3_generator::generate_typedef(t_typedef* ttypedef) { 
-  (void)ttypedef; 
-} 
- 
-/** 
- * Enums are a class with a set of static constants. 
- * 
- * @param tenum The enumeration 
- */ 
-void t_as3_generator::generate_enum(t_enum* tenum) { 
-  // Make output file 
-  string f_enum_name = package_dir_ + "/" + (tenum->get_name()) + ".as"; 
-  ofstream_with_content_based_conditional_update f_enum; 
-  f_enum.open(f_enum_name); 
- 
-  // Comment and package it 
-  f_enum << autogen_comment() << as3_package() << endl; 
- 
-  scope_up(f_enum); 
-  // Add as3 imports 
-  f_enum << string() + "import org.apache.thrift.Set;" << endl << "import flash.utils.Dictionary;" 
-         << endl; 
- 
-  indent(f_enum) << "public class " << tenum->get_name() << " "; 
-  scope_up(f_enum); 
- 
-  vector<t_enum_value*> constants = tenum->get_constants(); 
-  vector<t_enum_value*>::iterator c_iter; 
-  for (c_iter = constants.begin(); c_iter != constants.end(); ++c_iter) { 
-    int value = (*c_iter)->get_value(); 
-    indent(f_enum) << "public static const " << (*c_iter)->get_name() << ":int = " << value << ";" 
-                   << endl; 
-  } 
- 
-  // Create a static Set with all valid values for this enum 
-  f_enum << endl; 
- 
-  indent(f_enum) << "public static const VALID_VALUES:Set = new Set("; 
-  indent_up(); 
-  bool firstValue = true; 
-  for (c_iter = constants.begin(); c_iter != constants.end(); ++c_iter) { 
-    // populate set 
-    f_enum << (firstValue ? "" : ", ") << (*c_iter)->get_name(); 
-    firstValue = false; 
-  } 
-  indent_down(); 
-  f_enum << ");" << endl; 
- 
-  indent(f_enum) << "public static const VALUES_TO_NAMES:Dictionary = new Dictionary();" << endl; 
- 
-  scope_up(f_enum); 
-  for (c_iter = constants.begin(); c_iter != constants.end(); ++c_iter) { 
-    indent(f_enum) << "VALUES_TO_NAMES[" << (*c_iter)->get_name() << "] = \"" 
-                   << (*c_iter)->get_name() << "\";" << endl; 
-  } 
-  f_enum << endl; 
- 
-  scope_down(f_enum); 
- 
-  scope_down(f_enum); // end class 
- 
-  scope_down(f_enum); // end package 
- 
-  f_enum.close(); 
-} 
- 
-/** 
- * Generates a class that holds all the constants. 
- */ 
-void t_as3_generator::generate_consts(std::vector<t_const*> consts) { 
-  if (consts.empty()) { 
-    return; 
-  } 
- 
-  string f_consts_name = package_dir_ + "/" + program_name_ + "Constants.as"; 
-  ofstream_with_content_based_conditional_update f_consts; 
-  f_consts.open(f_consts_name); 
- 
-  // Print header 
-  f_consts << autogen_comment() << as3_package(); 
- 
-  scope_up(f_consts); 
-  f_consts << endl; 
- 
-  f_consts << as3_type_imports(); 
- 
-  indent(f_consts) << "public class " << program_name_ << "Constants {" << endl << endl; 
-  indent_up(); 
-  vector<t_const*>::iterator c_iter; 
-  for (c_iter = consts.begin(); c_iter != consts.end(); ++c_iter) { 
-    print_const_value(f_consts, 
-                      (*c_iter)->get_name(), 
-                      (*c_iter)->get_type(), 
-                      (*c_iter)->get_value(), 
-                      false); 
-  } 
-  indent_down(); 
-  indent(f_consts) << "}" << endl; 
-  scope_down(f_consts); 
-  f_consts.close(); 
-} 
- 
-void t_as3_generator::print_const_value(std::ostream& out, 
-                                        string name, 
-                                        t_type* type, 
-                                        t_const_value* value, 
-                                        bool in_static, 
-                                        bool defval) { 
-  type = get_true_type(type); 
- 
-  indent(out); 
-  if (!defval) { 
-    out << (in_static ? "var " : "public static const "); 
-  } 
-  if (type->is_base_type()) { 
-    string v2 = render_const_value(out, name, type, value); 
-    out << name; 
-    if (!defval) { 
-      out << ":" << type_name(type); 
-    } 
-    out << " = " << v2 << ";" << endl << endl; 
-  } else if (type->is_enum()) { 
-    out << name; 
-    if (!defval) { 
-      out << ":" << type_name(type); 
-    } 
-    out << " = " << 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*, t_const_value::value_compare>& val = value->get_map(); 
-    map<t_const_value*, t_const_value*, t_const_value::value_compare>::const_iterator v_iter; 
-    out << name << ":" << type_name(type) << " = new " << type_name(type, false, true) << "();" 
-        << endl; 
-    if (!in_static) { 
-      indent(out) << "{" << endl; 
-      indent_up(); 
-      indent(out) << "new function():void {" << endl; 
-      indent_up(); 
-    } 
-    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) { 
-        if ((*f_iter)->get_name() == v_iter->first->get_string()) { 
-          field_type = (*f_iter)->get_type(); 
-        } 
-      } 
-      if (field_type == NULL) { 
-        throw "type error: " + type->get_name() + " has no field " + v_iter->first->get_string(); 
-      } 
-      string val = render_const_value(out, name, field_type, v_iter->second); 
-      indent(out) << name << "."; 
-      out << v_iter->first->get_string() << " = " << val << ";" << endl; 
-    } 
-    if (!in_static) { 
-      indent_down(); 
-      indent(out) << "}();" << endl; 
-      indent_down(); 
-      indent(out) << "}" << endl; 
-    } 
-    out << endl; 
-  } else if (type->is_map()) { 
-    out << name; 
-    if (!defval) { 
-      out << ":" << type_name(type); 
-    } 
-    out << " = new " << type_name(type, false, true) << "();" << endl; 
-    if (!in_static) { 
-      indent(out) << "{" << endl; 
-      indent_up(); 
-      indent(out) << "new function():void {" << endl; 
-      indent_up(); 
-    } 
-    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*, t_const_value::value_compare>& val = value->get_map(); 
-    map<t_const_value*, t_const_value*, t_const_value::value_compare>::const_iterator v_iter; 
-    for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) { 
-      string key = render_const_value(out, name, ktype, v_iter->first); 
-      string val = render_const_value(out, name, vtype, v_iter->second); 
-      indent(out) << name << "[" << key << "] = " << val << ";" << endl; 
-    } 
-    if (!in_static) { 
-      indent_down(); 
-      indent(out) << "}();" << endl; 
-      indent_down(); 
-      indent(out) << "}" << endl; 
-    } 
-    out << endl; 
-  } else if (type->is_list() || type->is_set()) { 
-    out << name; 
-    if (!defval) { 
-      out << ":" << type_name(type); 
-    } 
-    out << " = new " << type_name(type, false, true) << "();" << endl; 
-    if (!in_static) { 
-      indent(out) << "{" << endl; 
-      indent_up(); 
-      indent(out) << "new function():void {" << endl; 
-      indent_up(); 
-    } 
-    t_type* etype; 
-    if (type->is_list()) { 
-      etype = ((t_list*)type)->get_elem_type(); 
-    } else { 
-      etype = ((t_set*)type)->get_elem_type(); 
-    } 
-    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) { 
-      string val = render_const_value(out, name, etype, *v_iter); 
-      indent(out) << name << "." << (type->is_list() ? "push" : "add") << "(" << val << ");" 
-                  << endl; 
-    } 
-    if (!in_static) { 
-      indent_down(); 
-      indent(out) << "}();" << endl; 
-      indent_down(); 
-      indent(out) << "}" << endl; 
-    } 
-    out << endl; 
-  } else { 
-    throw "compiler error: no const of type " + type->get_name(); 
-  } 
-} 
- 
-string t_as3_generator::render_const_value(ostream& out, 
-                                           string name, 
-                                           t_type* type, 
-                                           t_const_value* value) { 
-  (void)name; 
-  type = get_true_type(type); 
-  std::ostringstream render; 
- 
-  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: 
-      render << '"' << get_escaped_string(value) << '"'; 
-      break; 
-    case t_base_type::TYPE_BOOL: 
-      render << ((value->get_integer() > 0) ? "true" : "false"); 
-      break; 
-    case t_base_type::TYPE_I8: 
-      render << "(byte)" << value->get_integer(); 
-      break; 
-    case t_base_type::TYPE_I16: 
-      render << "(short)" << value->get_integer(); 
-      break; 
-    case t_base_type::TYPE_I32: 
-      render << value->get_integer(); 
-      break; 
-    case t_base_type::TYPE_I64: 
-      render << value->get_integer() << "L"; 
-      break; 
-    case t_base_type::TYPE_DOUBLE: 
-      if (value->get_type() == t_const_value::CV_INTEGER) { 
-        render << "(double)" << value->get_integer(); 
-      } else { 
-        render << value->get_double(); 
-      } 
-      break; 
-    default: 
-      throw "compiler error: no const of base type " + t_base_type::t_base_name(tbase); 
-    } 
-  } else if (type->is_enum()) { 
-    render << value->get_integer(); 
-  } else { 
-    string t = tmp("tmp"); 
-    print_const_value(out, t, type, value, true); 
-    render << t; 
-  } 
- 
-  return render.str(); 
-} 
- 
-/** 
- * Generates a struct definition for a thrift data type. This is a class 
- * with data members, read(), write(), and an inner Isset class. 
- * 
- * @param tstruct The struct definition 
- */ 
-void t_as3_generator::generate_struct(t_struct* tstruct) { 
-  generate_as3_struct(tstruct, false); 
-} 
- 
-/** 
- * Exceptions are structs, but they inherit from Exception 
- * 
- * @param tstruct The struct definition 
- */ 
-void t_as3_generator::generate_xception(t_struct* txception) { 
-  generate_as3_struct(txception, true); 
-} 
- 
-/** 
- * As3 struct definition. 
- * 
- * @param tstruct The struct definition 
- */ 
-void t_as3_generator::generate_as3_struct(t_struct* tstruct, bool is_exception) { 
-  // Make output file 
-  string f_struct_name = package_dir_ + "/" + (tstruct->get_name()) + ".as"; 
-  ofstream_with_content_based_conditional_update f_struct; 
-  f_struct.open(f_struct_name.c_str()); 
- 
-  f_struct << autogen_comment() << as3_package(); 
- 
-  scope_up(f_struct); 
-  f_struct << endl; 
- 
-  string imports; 
- 
-  f_struct << as3_type_imports() << as3_thrift_imports() << as3_thrift_gen_imports(tstruct, imports) 
-           << endl; 
- 
-  if (bindable_ && !is_exception) { 
-    f_struct << "import flash.events.Event;" << endl << "import flash.events.EventDispatcher;" 
-             << endl << "import mx.events.PropertyChangeEvent;" << endl; 
-  } 
- 
-  generate_as3_struct_definition(f_struct, tstruct, is_exception); 
- 
-  scope_down(f_struct); // end of package 
-  f_struct.close(); 
-} 
- 
-/** 
- * As3 struct definition. This has various parameters, as it could be 
- * generated standalone or inside another class as a helper. If it 
- * is a helper than it is a static class. 
- * 
- * @param tstruct      The struct definition 
- * @param is_exception Is this an exception? 
- * @param in_class     If inside a class, needs to be static class 
- * @param is_result    If this is a result it needs a different writer 
- */ 
-void t_as3_generator::generate_as3_struct_definition(ostream& out, 
-                                                     t_struct* tstruct, 
-                                                     bool is_exception, 
-                                                     bool in_class, 
-                                                     bool is_result) { 
-  generate_as3_doc(out, tstruct); 
- 
-  bool is_final = (tstruct->annotations_.find("final") != tstruct->annotations_.end()); 
-  bool bindable = !is_exception && !in_class && bindable_; 
- 
-  indent(out) << (in_class ? "" : "public ") << (is_final ? "final " : "") << "class " 
-              << tstruct->get_name() << " "; 
- 
-  if (is_exception) { 
-    out << "extends Error "; 
-  } else if (bindable) { 
-    out << "extends EventDispatcher "; 
-  } 
-  out << "implements TBase "; 
- 
-  scope_up(out); 
- 
-  indent(out) << "private static const STRUCT_DESC:TStruct = new TStruct(\"" << tstruct->get_name() 
-              << "\");" << endl; 
- 
-  // Members are public for -as3, private for -as3bean 
-  const vector<t_field*>& members = tstruct->get_members(); 
-  vector<t_field*>::const_iterator m_iter; 
- 
-  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { 
-    indent(out) << "private static const " << constant_name((*m_iter)->get_name()) 
-                << "_FIELD_DESC:TField = new TField(\"" << (*m_iter)->get_name() << "\", " 
-                << type_to_enum((*m_iter)->get_type()) << ", " << (*m_iter)->get_key() << ");" 
-                << endl; 
-  } 
- 
-  out << endl; 
- 
-  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { 
-    generate_as3_doc(out, *m_iter); 
-    indent(out) << "private var _" << (*m_iter)->get_name() + ":" + type_name((*m_iter)->get_type()) 
-                << ";" << endl; 
- 
-    indent(out) << "public static const " << upcase_string((*m_iter)->get_name()) 
-                << ":int = " << (*m_iter)->get_key() << ";" << endl; 
-  } 
- 
-  out << endl; 
- 
-  // Inner Isset class 
-  if (members.size() > 0) { 
-    for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { 
-      if (!type_can_be_null((*m_iter)->get_type())) { 
-        indent(out) << "private var __isset_" << (*m_iter)->get_name() << ":Boolean = false;" 
-                    << endl; 
-      } 
-    } 
-  } 
- 
-  out << endl; 
- 
-  generate_as3_meta_data_map(out, tstruct); 
- 
-  // Static initializer to populate global class to struct metadata map 
-  indent(out) << "{" << endl; 
-  indent_up(); 
-  indent(out) << "FieldMetaData.addStructMetaDataMap(" << type_name(tstruct) << ", metaDataMap);" 
-              << endl; 
-  indent_down(); 
-  indent(out) << "}" << endl << endl; 
- 
-  // Default constructor 
-  indent(out) << "public function " << tstruct->get_name() << "() {" << endl; 
-  indent_up(); 
-  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { 
-    if ((*m_iter)->get_value() != NULL) { 
-      indent(out) << "this._" << (*m_iter)->get_name() << " = " 
-                  << (*m_iter)->get_value()->get_integer() << ";" << endl; 
-    } 
-  } 
-  indent_down(); 
-  indent(out) << "}" << endl << endl; 
- 
-  generate_as3_bean_boilerplate(out, tstruct, bindable); 
-  generate_generic_field_getters_setters(out, tstruct); 
-  generate_generic_isset_method(out, tstruct); 
- 
-  generate_as3_struct_reader(out, tstruct); 
-  if (is_result) { 
-    generate_as3_struct_result_writer(out, tstruct); 
-  } else { 
-    generate_as3_struct_writer(out, tstruct); 
-  } 
-  generate_as3_struct_tostring(out, tstruct, bindable); 
-  generate_as3_validator(out, tstruct); 
-  scope_down(out); 
-  out << endl; 
-} 
- 
-/** 
- * Generates a function to read all the fields of the struct. 
- * 
- * @param tstruct The struct definition 
- */ 
-void t_as3_generator::generate_as3_struct_reader(ostream& out, t_struct* tstruct) { 
-  out << indent() << "public function read(iprot:TProtocol):void {" << endl; 
-  indent_up(); 
- 
-  const vector<t_field*>& fields = tstruct->get_members(); 
-  vector<t_field*>::const_iterator f_iter; 
- 
-  // Declare stack tmp variables and read struct header 
-  out << indent() << "var field:TField;" << endl << indent() << "iprot.readStructBegin();" << endl; 
- 
-  // Loop over reading in fields 
-  indent(out) << "while (true)" << endl; 
-  scope_up(out); 
- 
-  // Read beginning field marker 
-  indent(out) << "field = iprot.readFieldBegin();" << endl; 
- 
-  // Check for field STOP marker and break 
-  indent(out) << "if (field.type == TType.STOP) { " << endl; 
-  indent_up(); 
-  indent(out) << "break;" << endl; 
-  indent_down(); 
-  indent(out) << "}" << endl; 
- 
-  // Switch statement on the field we are reading 
-  indent(out) << "switch (field.id)" << endl; 
- 
-  scope_up(out); 
- 
-  // Generate deserialization code for known cases 
-  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { 
-    indent(out) << "case " << upcase_string((*f_iter)->get_name()) << ":" << endl; 
-    indent_up(); 
-    indent(out) << "if (field.type == " << type_to_enum((*f_iter)->get_type()) << ") {" << endl; 
-    indent_up(); 
- 
-    generate_deserialize_field(out, *f_iter, "this."); 
-    generate_isset_set(out, *f_iter); 
-    indent_down(); 
-    out << indent() << "} else { " << endl << indent() << "  TProtocolUtil.skip(iprot, field.type);" 
-        << endl << indent() << "}" << endl << indent() << "break;" << endl; 
-    indent_down(); 
-  } 
- 
-  // In the default case we skip the field 
-  out << indent() << "default:" << endl << indent() << "  TProtocolUtil.skip(iprot, field.type);" 
-      << endl << indent() << "  break;" << endl; 
- 
-  scope_down(out); 
- 
-  // Read field end marker 
-  indent(out) << "iprot.readFieldEnd();" << endl; 
- 
-  scope_down(out); 
- 
-  out << indent() << "iprot.readStructEnd();" << endl << endl; 
- 
-  // in non-beans style, check for required fields of primitive type 
-  // (which can be checked here but not in the general validate method) 
-  out << endl << indent() << "// check for required fields of primitive type, which can't be " 
-                             "checked in the validate method" << endl; 
-  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { 
-    if ((*f_iter)->get_req() == t_field::T_REQUIRED && !type_can_be_null((*f_iter)->get_type())) { 
-      out << indent() << "if (!__isset_" << (*f_iter)->get_name() << ") {" << endl << indent() 
-          << "  throw new TProtocolError(TProtocolError.UNKNOWN, \"Required field '" 
-          << (*f_iter)->get_name() 
-          << "' was not found in serialized data! Struct: \" + toString());" << endl << indent() 
-          << "}" << endl; 
-    } 
-  } 
- 
-  // performs various checks (e.g. check that all required fields are set) 
-  indent(out) << "validate();" << endl; 
- 
-  indent_down(); 
-  out << indent() << "}" << endl << endl; 
-} 
- 
-// generates as3 method to perform various checks 
-// (e.g. check that all required fields are set) 
-void t_as3_generator::generate_as3_validator(ostream& out, t_struct* tstruct) { 
-  indent(out) << "public function validate():void {" << endl; 
-  indent_up(); 
- 
-  const vector<t_field*>& fields = tstruct->get_members(); 
-  vector<t_field*>::const_iterator f_iter; 
- 
-  out << indent() << "// check for required fields" << endl; 
-  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { 
-    if ((*f_iter)->get_req() == t_field::T_REQUIRED) { 
-      if (type_can_be_null((*f_iter)->get_type())) { 
-        indent(out) << "if (" << (*f_iter)->get_name() << " == null) {" << endl; 
-        indent(out) << "  throw new TProtocolError(TProtocolError.UNKNOWN, \"Required field '" 
-                    << (*f_iter)->get_name() << "' was not present! Struct: \" + toString());" 
-                    << endl; 
-        indent(out) << "}" << endl; 
-      } else { 
-        indent(out) << "// alas, we cannot check '" << (*f_iter)->get_name() 
-                    << "' because it's a primitive and you chose the non-beans generator." << endl; 
-      } 
-    } 
-  } 
- 
-  // check that fields of type enum have valid values 
-  out << indent() << "// check that fields of type enum have valid values" << endl; 
-  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { 
-    t_field* field = (*f_iter); 
-    t_type* type = field->get_type(); 
-    // if field is an enum, check that its value is valid 
-    if (type->is_enum()) { 
-      indent(out) << "if (" << generate_isset_check(field) << " && !" << get_enum_class_name(type) 
-                  << ".VALID_VALUES.contains(" << field->get_name() << ")){" << endl; 
-      indent_up(); 
-      indent(out) << "throw new TProtocolError(TProtocolError.UNKNOWN, \"The field '" 
-                  << field->get_name() << "' has been assigned the invalid value \" + " 
-                  << field->get_name() << ");" << endl; 
-      indent_down(); 
-      indent(out) << "}" << endl; 
-    } 
-  } 
- 
-  indent_down(); 
-  indent(out) << "}" << endl << endl; 
-} 
- 
-/** 
- * Generates a function to write all the fields of the struct 
- * 
- * @param tstruct The struct definition 
- */ 
-void t_as3_generator::generate_as3_struct_writer(ostream& out, t_struct* tstruct) { 
-  out << indent() << "public function write(oprot:TProtocol):void {" << endl; 
-  indent_up(); 
- 
-  string name = tstruct->get_name(); 
-  const vector<t_field*>& fields = tstruct->get_sorted_members(); 
-  vector<t_field*>::const_iterator f_iter; 
- 
-  // performs various checks (e.g. check that all required fields are set) 
-  indent(out) << "validate();" << endl << endl; 
- 
-  indent(out) << "oprot.writeStructBegin(STRUCT_DESC);" << endl; 
- 
-  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { 
-    bool could_be_unset = (*f_iter)->get_req() == t_field::T_OPTIONAL; 
-    if (could_be_unset) { 
-      indent(out) << "if (" << generate_isset_check(*f_iter) << ") {" << endl; 
-      indent_up(); 
-    } 
-    bool null_allowed = type_can_be_null((*f_iter)->get_type()); 
-    if (null_allowed) { 
-      out << indent() << "if (this." << (*f_iter)->get_name() << " != null) {" << endl; 
-      indent_up(); 
-    } 
- 
-    indent(out) << "oprot.writeFieldBegin(" << constant_name((*f_iter)->get_name()) 
-                << "_FIELD_DESC);" << endl; 
- 
-    // Write field contents 
-    generate_serialize_field(out, *f_iter, "this."); 
- 
-    // Write field closer 
-    indent(out) << "oprot.writeFieldEnd();" << endl; 
- 
-    if (null_allowed) { 
-      indent_down(); 
-      indent(out) << "}" << endl; 
-    } 
-    if (could_be_unset) { 
-      indent_down(); 
-      indent(out) << "}" << endl; 
-    } 
-  } 
-  // Write the struct map 
-  out << indent() << "oprot.writeFieldStop();" << endl << indent() << "oprot.writeStructEnd();" 
-      << endl; 
- 
-  indent_down(); 
-  out << indent() << "}" << endl << endl; 
-} 
- 
-/** 
- * Generates a function to write all the fields of the struct, 
- * which is a function result. These fields are only written 
- * if they are set in the Isset array, and only one of them 
- * can be set at a time. 
- * 
- * @param tstruct The struct definition 
- */ 
-void t_as3_generator::generate_as3_struct_result_writer(ostream& out, t_struct* tstruct) { 
-  out << indent() << "public function write(oprot:TProtocol):void {" << endl; 
-  indent_up(); 
- 
-  string name = tstruct->get_name(); 
-  const vector<t_field*>& fields = tstruct->get_sorted_members(); 
-  vector<t_field*>::const_iterator f_iter; 
- 
-  indent(out) << "oprot.writeStructBegin(STRUCT_DESC);" << endl; 
- 
-  bool first = true; 
-  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { 
-    if (first) { 
-      first = false; 
-      out << endl << indent() << "if "; 
-    } else { 
-      out << " else if "; 
-    } 
- 
-    out << "(this." << generate_isset_check(*f_iter) << ") {" << endl; 
- 
-    indent_up(); 
- 
-    indent(out) << "oprot.writeFieldBegin(" << constant_name((*f_iter)->get_name()) 
-                << "_FIELD_DESC);" << endl; 
- 
-    // Write field contents 
-    generate_serialize_field(out, *f_iter, "this."); 
- 
-    // Write field closer 
-    indent(out) << "oprot.writeFieldEnd();" << endl; 
- 
-    indent_down(); 
-    indent(out) << "}"; 
-  } 
-  // Write the struct map 
-  out << endl << indent() << "oprot.writeFieldStop();" << endl << indent() 
-      << "oprot.writeStructEnd();" << endl; 
- 
-  indent_down(); 
-  out << indent() << "}" << endl << endl; 
-} 
- 
-void t_as3_generator::generate_reflection_getters(ostringstream& out, 
-                                                  t_type* type, 
-                                                  string field_name, 
-                                                  string cap_name) { 
-  (void)type; 
-  (void)cap_name; 
-  indent(out) << "case " << upcase_string(field_name) << ":" << endl; 
-  indent_up(); 
-  indent(out) << "return this." << field_name << ";" << endl; 
-  indent_down(); 
-} 
- 
-void t_as3_generator::generate_reflection_setters(ostringstream& out, 
-                                                  t_type* type, 
-                                                  string field_name, 
-                                                  string cap_name) { 
-  (void)type; 
-  (void)cap_name; 
-  indent(out) << "case " << upcase_string(field_name) << ":" << endl; 
-  indent_up(); 
-  indent(out) << "if (value == null) {" << endl; 
-  indent(out) << "  unset" << get_cap_name(field_name) << "();" << endl; 
-  indent(out) << "} else {" << endl; 
-  indent(out) << "  this." << field_name << " = value;" << endl; 
-  indent(out) << "}" << endl; 
-  indent(out) << "break;" << endl << endl; 
- 
-  indent_down(); 
-} 
- 
-void t_as3_generator::generate_generic_field_getters_setters(std::ostream& out, 
-                                                             t_struct* tstruct) { 
- 
-  std::ostringstream getter_stream; 
-  std::ostringstream setter_stream; 
- 
-  // build up the bodies of both the getter and setter at once 
-  const vector<t_field*>& fields = tstruct->get_members(); 
-  vector<t_field*>::const_iterator f_iter; 
-  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { 
-    t_field* field = *f_iter; 
-    t_type* type = get_true_type(field->get_type()); 
-    std::string field_name = field->get_name(); 
-    std::string cap_name = get_cap_name(field_name); 
- 
-    indent_up(); 
-    generate_reflection_setters(setter_stream, type, field_name, cap_name); 
-    generate_reflection_getters(getter_stream, type, field_name, cap_name); 
-    indent_down(); 
-  } 
- 
-  // create the setter 
-  indent(out) << "public function setFieldValue(fieldID:int, value:*):void {" << endl; 
-  indent_up(); 
- 
-  indent(out) << "switch (fieldID) {" << endl; 
- 
-  out << setter_stream.str(); 
- 
-  indent(out) << "default:" << endl; 
-  indent(out) << "  throw new ArgumentError(\"Field \" + fieldID + \" doesn't exist!\");" << endl; 
- 
-  indent(out) << "}" << endl; 
- 
-  indent_down(); 
-  indent(out) << "}" << endl << endl; 
- 
-  // create the getter 
-  indent(out) << "public function getFieldValue(fieldID:int):* {" << endl; 
-  indent_up(); 
- 
-  indent(out) << "switch (fieldID) {" << endl; 
- 
-  out << getter_stream.str(); 
- 
-  indent(out) << "default:" << endl; 
-  indent(out) << "  throw new ArgumentError(\"Field \" + fieldID + \" doesn't exist!\");" << endl; 
- 
-  indent(out) << "}" << endl; 
- 
-  indent_down(); 
- 
-  indent(out) << "}" << endl << endl; 
-} 
- 
-// Creates a generic isSet method that takes the field number as argument 
-void t_as3_generator::generate_generic_isset_method(std::ostream& out, t_struct* tstruct) { 
-  const vector<t_field*>& fields = tstruct->get_members(); 
-  vector<t_field*>::const_iterator f_iter; 
- 
-  // create the isSet method 
-  indent(out) << "// Returns true if field corresponding to fieldID is set (has been assigned a " 
-                 "value) and false otherwise" << endl; 
-  indent(out) << "public function isSet(fieldID:int):Boolean {" << endl; 
-  indent_up(); 
-  indent(out) << "switch (fieldID) {" << endl; 
- 
-  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { 
-    t_field* field = *f_iter; 
-    indent(out) << "case " << upcase_string(field->get_name()) << ":" << endl; 
-    indent_up(); 
-    indent(out) << "return " << generate_isset_check(field) << ";" << endl; 
-    indent_down(); 
-  } 
- 
-  indent(out) << "default:" << endl; 
-  indent(out) << "  throw new ArgumentError(\"Field \" + fieldID + \" doesn't exist!\");" << endl; 
- 
-  indent(out) << "}" << endl; 
- 
-  indent_down(); 
-  indent(out) << "}" << endl << endl; 
-} 
- 
-/** 
- * Generates a set of As3 Bean boilerplate functions (setters, getters, etc.) 
- * for the given struct. 
- * 
- * @param tstruct The struct definition 
- */ 
-void t_as3_generator::generate_as3_bean_boilerplate(ostream& out, 
-                                                    t_struct* tstruct, 
-                                                    bool bindable) { 
-  const vector<t_field*>& fields = tstruct->get_members(); 
-  vector<t_field*>::const_iterator f_iter; 
-  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { 
-    t_field* field = *f_iter; 
-    t_type* type = get_true_type(field->get_type()); 
-    std::string field_name = field->get_name(); 
-    std::string cap_name = get_cap_name(field_name); 
- 
-    // Simple getter 
-    generate_as3_doc(out, field); 
-    indent(out) << "public function get " << field_name << "():" << type_name(type) << " {" << endl; 
-    indent_up(); 
-    indent(out) << "return this._" << field_name << ";" << endl; 
-    indent_down(); 
-    indent(out) << "}" << endl << endl; 
- 
-    // Simple setter 
-    generate_as3_doc(out, field); 
-    std::string propName = tmp("thriftPropertyChange"); 
-    if (bindable) { 
-      indent(out) << "[Bindable(event=\"" << propName << "\")]" << endl; 
-    } 
-    indent(out) << "public function set " << field_name << "(" << field_name << ":" 
-                << type_name(type) << "):void {" << endl; 
-    indent_up(); 
-    indent(out) << "this._" << field_name << " = " << field_name << ";" << endl; 
-    generate_isset_set(out, field); 
- 
-    if (bindable) { 
-      // We have to use a custom event rather than the default, because if you use the default, 
-      // the setter only gets called if the value has changed - this means calling 
-      // foo.setIntValue(0) 
-      // will not cause foo.isIntValueSet() to return true since the value of foo._intValue wasn't 
-      // changed 
-      // so the setter was never called. 
-      indent(out) << "dispatchEvent(new Event(\"" << propName << "\"));" << endl; 
- 
-      // However, if you just use a custom event, then collections won't be able to detect when 
-      // elements 
-      // in the collections have changed since they listed for PropertyChangeEvents.  So, we 
-      // dispatch both. 
-      indent(out) << "dispatchEvent(new PropertyChangeEvent(PropertyChangeEvent.PROPERTY_CHANGE));" 
-                  << endl; 
-    } 
-    indent_down(); 
-    indent(out) << "}" << endl << endl; 
- 
-    // Unsetter 
-    indent(out) << "public function unset" << cap_name << "():void {" << endl; 
-    indent_up(); 
-    if (type_can_be_null(type)) { 
-      indent(out) << "this." << field_name << " = null;" << endl; 
-    } else { 
-      indent(out) << "this.__isset_" << field_name << " = false;" << endl; 
-    } 
-    indent_down(); 
-    indent(out) << "}" << endl << endl; 
- 
-    // isSet method 
-    indent(out) << "// Returns true if field " << field_name 
-                << " is set (has been assigned a value) and false otherwise" << endl; 
-    indent(out) << "public function is" << get_cap_name("set") << cap_name << "():Boolean {" 
-                << endl; 
-    indent_up(); 
-    if (type_can_be_null(type)) { 
-      indent(out) << "return this." << field_name << " != null;" << endl; 
-    } else { 
-      indent(out) << "return this.__isset_" << field_name << ";" << endl; 
-    } 
-    indent_down(); 
-    indent(out) << "}" << endl << endl; 
-  } 
-} 
- 
-/** 
- * Generates a toString() method for the given struct 
- * 
- * @param tstruct The struct definition 
- */ 
-void t_as3_generator::generate_as3_struct_tostring(ostream& out, 
-                                                   t_struct* tstruct, 
-                                                   bool bindable) { 
-  // If it's bindable, it extends EventDispatcher so toString is an override. 
-  out << indent() << "public " << (bindable ? "override " : "") << "function toString():String {" 
-      << endl; 
-  indent_up(); 
- 
-  out << indent() << "var ret:String = new String(\"" << tstruct->get_name() << "(\");" << endl; 
-  out << indent() << "var first:Boolean = true;" << endl << endl; 
- 
-  const vector<t_field*>& fields = tstruct->get_members(); 
-  vector<t_field*>::const_iterator f_iter; 
-  bool first = true; 
-  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { 
-    bool could_be_unset = (*f_iter)->get_req() == t_field::T_OPTIONAL; 
-    if (could_be_unset) { 
-      indent(out) << "if (" << generate_isset_check(*f_iter) << ") {" << endl; 
-      indent_up(); 
-    } 
- 
-    t_field* field = (*f_iter); 
- 
-    if (!first) { 
-      indent(out) << "if (!first) ret +=  \", \";" << endl; 
-    } 
-    indent(out) << "ret += \"" << (*f_iter)->get_name() << ":\";" << endl; 
-    bool can_be_null = type_can_be_null(field->get_type()); 
-    if (can_be_null) { 
-      indent(out) << "if (this." << (*f_iter)->get_name() << " == null) {" << endl; 
-      indent(out) << "  ret += \"null\";" << endl; 
-      indent(out) << "} else {" << endl; 
-      indent_up(); 
-    } 
- 
-    if (field->get_type()->is_binary()) { 
-      indent(out) << "  ret += \"BINARY\";" << endl; 
-    } else if (field->get_type()->is_enum()) { 
-      indent(out) << "var " << field->get_name() 
-                  << "_name:String = " << get_enum_class_name(field->get_type()) 
-                  << ".VALUES_TO_NAMES[this." << (*f_iter)->get_name() << "];" << endl; 
-      indent(out) << "if (" << field->get_name() << "_name != null) {" << endl; 
-      indent(out) << "  ret += " << field->get_name() << "_name;" << endl; 
-      indent(out) << "  ret += \" (\";" << endl; 
-      indent(out) << "}" << endl; 
-      indent(out) << "ret += this." << field->get_name() << ";" << endl; 
-      indent(out) << "if (" << field->get_name() << "_name != null) {" << endl; 
-      indent(out) << "  ret += \")\";" << endl; 
-      indent(out) << "}" << endl; 
-    } else { 
-      indent(out) << "ret += this." << (*f_iter)->get_name() << ";" << endl; 
-    } 
- 
-    if (can_be_null) { 
-      indent_down(); 
-      indent(out) << "}" << endl; 
-    } 
-    indent(out) << "first = false;" << endl; 
- 
-    if (could_be_unset) { 
-      indent_down(); 
-      indent(out) << "}" << endl; 
-    } 
-    first = false; 
-  } 
-  out << indent() << "ret += \")\";" << endl << indent() << "return ret;" << endl; 
- 
-  indent_down(); 
-  indent(out) << "}" << endl << endl; 
-} 
- 
-/** 
- * Generates a static map with meta data to store information such as fieldID to 
- * fieldName mapping 
- * 
- * @param tstruct The struct definition 
- */ 
-void t_as3_generator::generate_as3_meta_data_map(ostream& out, t_struct* tstruct) { 
-  const vector<t_field*>& fields = tstruct->get_members(); 
-  vector<t_field*>::const_iterator f_iter; 
- 
-  // Static Map with fieldID -> FieldMetaData mappings 
-  indent(out) << "public static const metaDataMap:Dictionary = new Dictionary();" << endl; 
- 
-  if (fields.size() > 0) { 
-    // Populate map 
-    scope_up(out); 
-    for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { 
-      t_field* field = *f_iter; 
-      std::string field_name = field->get_name(); 
-      indent(out) << "metaDataMap[" << upcase_string(field_name) << "] = new FieldMetaData(\"" 
-                  << field_name << "\", "; 
- 
-      // Set field requirement type (required, optional, etc.) 
-      if (field->get_req() == t_field::T_REQUIRED) { 
-        out << "TFieldRequirementType.REQUIRED, "; 
-      } else if (field->get_req() == t_field::T_OPTIONAL) { 
-        out << "TFieldRequirementType.OPTIONAL, "; 
-      } else { 
-        out << "TFieldRequirementType.DEFAULT, "; 
-      } 
- 
-      // Create value meta data 
-      generate_field_value_meta_data(out, field->get_type()); 
-      out << ");" << endl; 
-    } 
-    scope_down(out); 
-  } 
-} 
- 
-/** 
- * Returns a string with the as3 representation of the given thrift type 
- * (e.g. for the type struct it returns "TType.STRUCT") 
- */ 
-std::string t_as3_generator::get_as3_type_string(t_type* type) { 
-  if (type->is_list()) { 
-    return "TType.LIST"; 
-  } else if (type->is_map()) { 
-    return "TType.MAP"; 
-  } else if (type->is_set()) { 
-    return "TType.SET"; 
-  } else if (type->is_struct() || type->is_xception()) { 
-    return "TType.STRUCT"; 
-  } else if (type->is_enum()) { 
-    return "TType.I32"; 
-  } else if (type->is_typedef()) { 
-    return get_as3_type_string(((t_typedef*)type)->get_type()); 
-  } else if (type->is_base_type()) { 
-    switch (((t_base_type*)type)->get_base()) { 
-    case t_base_type::TYPE_VOID: 
-      return "TType.VOID"; 
-      break; 
-    case t_base_type::TYPE_STRING: 
-      return "TType.STRING"; 
-      break; 
-    case t_base_type::TYPE_BOOL: 
-      return "TType.BOOL"; 
-      break; 
-    case t_base_type::TYPE_I8: 
-      return "TType.BYTE"; 
-      break; 
-    case t_base_type::TYPE_I16: 
-      return "TType.I16"; 
-      break; 
-    case t_base_type::TYPE_I32: 
-      return "TType.I32"; 
-      break; 
-    case t_base_type::TYPE_I64: 
-      return "TType.I64"; 
-      break; 
-    case t_base_type::TYPE_DOUBLE: 
-      return "TType.DOUBLE"; 
-      break; 
-    default: 
-      throw std::runtime_error("Unknown thrift type \"" + type->get_name() 
-                               + "\" passed to t_as3_generator::get_as3_type_string!"); 
-      break; // This should never happen! 
-    } 
-  } else { 
-    throw std::runtime_error( 
-        "Unknown thrift type \"" + type->get_name() 
-        + "\" passed to t_as3_generator::get_as3_type_string!"); // This should never happen! 
-  } 
-} 
- 
-void t_as3_generator::generate_field_value_meta_data(std::ostream& out, t_type* type) { 
-  out << endl; 
-  indent_up(); 
-  indent_up(); 
-  if (type->is_struct() || type->is_xception()) { 
-    indent(out) << "new StructMetaData(TType.STRUCT, " << type_name(type); 
-  } else if (type->is_container()) { 
-    if (type->is_list()) { 
-      indent(out) << "new ListMetaData(TType.LIST, "; 
-      t_type* elem_type = ((t_list*)type)->get_elem_type(); 
-      generate_field_value_meta_data(out, elem_type); 
-    } else if (type->is_set()) { 
-      indent(out) << "new SetMetaData(TType.SET, "; 
-      t_type* elem_type = ((t_list*)type)->get_elem_type(); 
-      generate_field_value_meta_data(out, elem_type); 
-    } else { // map 
-      indent(out) << "new MapMetaData(TType.MAP, "; 
-      t_type* key_type = ((t_map*)type)->get_key_type(); 
-      t_type* val_type = ((t_map*)type)->get_val_type(); 
-      generate_field_value_meta_data(out, key_type); 
-      out << ", "; 
-      generate_field_value_meta_data(out, val_type); 
-    } 
-  } else { 
-    indent(out) << "new FieldValueMetaData(" << get_as3_type_string(type); 
-  } 
-  out << ")"; 
-  indent_down(); 
-  indent_down(); 
-} 
- 
-/** 
- * Generates a thrift service. In C++, this comprises an entirely separate 
- * header and source file. The header file defines the methods and includes 
- * the data types defined in the main header file, and the implementation 
- * file contains implementations of the basic printer and default interfaces. 
- * 
- * @param tservice The service definition 
- */ 
-void t_as3_generator::generate_service(t_service* tservice) { 
-  // Make interface file 
-  string f_service_name = package_dir_ + "/" + service_name_ + ".as"; 
-  f_service_.open(f_service_name.c_str()); 
- 
-  f_service_ << autogen_comment() << as3_package(); 
- 
-  scope_up(f_service_); 
- 
-  f_service_ << endl << as3_type_imports() << as3_thrift_imports() 
-             << as3_thrift_gen_imports(tservice); 
- 
-  if (tservice->get_extends() != NULL) { 
-    t_type* parent = tservice->get_extends(); 
-    string parent_namespace = parent->get_program()->get_namespace("as3"); 
-    if (!parent_namespace.empty() && parent_namespace != package_name_) { 
-      f_service_ << "import " << type_name(parent) << ";" << endl; 
-    } 
-  } 
- 
-  f_service_ << endl; 
- 
-  generate_service_interface(tservice); 
- 
-  scope_down(f_service_); 
-  f_service_.close(); 
- 
-  // Now make the implementation/client file 
-  f_service_name = package_dir_ + "/" + service_name_ + "Impl.as"; 
-  f_service_.open(f_service_name.c_str()); 
- 
-  f_service_ << autogen_comment() << as3_package(); 
- 
-  scope_up(f_service_); 
- 
-  f_service_ << endl << as3_type_imports() << as3_thrift_imports() 
-             << as3_thrift_gen_imports(tservice); 
- 
-  if (tservice->get_extends() != NULL) { 
-    t_type* parent = tservice->get_extends(); 
-    string parent_namespace = parent->get_program()->get_namespace("as3"); 
-    if (!parent_namespace.empty() && parent_namespace != package_name_) { 
-      f_service_ << "import " << type_name(parent) << "Impl;" << endl; 
-    } 
-  } 
- 
-  f_service_ << endl; 
- 
-  generate_service_client(tservice); 
-  scope_down(f_service_); 
- 
-  f_service_ << as3_type_imports(); 
-  f_service_ << as3_thrift_imports(); 
-  f_service_ << as3_thrift_gen_imports(tservice); 
-  if (!package_name_.empty()) { 
-    f_service_ << "import " << package_name_ << ".*;" << endl; 
-  } 
- 
-  generate_service_helpers(tservice); 
- 
-  f_service_.close(); 
- 
-  // Now make the processor/server file 
-  f_service_name = package_dir_ + "/" + service_name_ + "Processor.as"; 
-  f_service_.open(f_service_name.c_str()); 
- 
-  f_service_ << autogen_comment() << as3_package(); 
- 
-  scope_up(f_service_); 
- 
-  f_service_ << endl << as3_type_imports() << as3_thrift_imports() 
-             << as3_thrift_gen_imports(tservice) << endl; 
- 
-  generate_service_server(tservice); 
-  scope_down(f_service_); 
- 
-  f_service_ << as3_type_imports(); 
-  f_service_ << as3_thrift_imports(); 
-  f_service_ << as3_thrift_gen_imports(tservice) << endl; 
-  if (!package_name_.empty()) { 
-    f_service_ << "import " << package_name_ << ".*;" << endl; 
-  } 
- 
-  generate_service_helpers(tservice); 
- 
-  f_service_.close(); 
-} 
- 
-/** 
- * Generates a service interface definition. 
- * 
- * @param tservice The service to generate a header definition for 
- */ 
-void t_as3_generator::generate_service_interface(t_service* tservice) { 
-  string extends_iface = ""; 
-  if (tservice->get_extends() != NULL) { 
-    extends_iface = " extends " + tservice->get_extends()->get_name(); 
-  } 
- 
-  generate_as3_doc(f_service_, tservice); 
-  f_service_ << indent() << "public interface " << service_name_ << extends_iface << " {" << endl 
-             << endl; 
-  indent_up(); 
-  vector<t_function*> functions = tservice->get_functions(); 
-  vector<t_function*>::iterator f_iter; 
-  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) { 
-    generate_as3_doc(f_service_, *f_iter); 
-    if (!(*f_iter)->is_oneway()) { 
-      if ((*f_iter)->get_returntype()->is_void()) { 
-        indent(f_service_) << "//function onError(Error):void;" << endl; 
-        indent(f_service_) << "//function onSuccess():void;" << endl; 
-      } else { 
-        indent(f_service_) << "//function onError(Error):void;" << endl; 
-        indent(f_service_) << "//function onSuccess(" << type_name((*f_iter)->get_returntype()) 
-                           << "):void;" << endl; 
-      } 
-    } 
-    indent(f_service_) << function_signature(*f_iter) << ";" << endl << endl; 
-  } 
-  indent_down(); 
-  f_service_ << indent() << "}" << endl << endl; 
-} 
- 
-/** 
- * Generates structs for all the service args and return types 
- * 
- * @param tservice The service 
- */ 
-void t_as3_generator::generate_service_helpers(t_service* tservice) { 
-  vector<t_function*> functions = tservice->get_functions(); 
-  vector<t_function*>::iterator f_iter; 
-  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) { 
-    t_struct* ts = (*f_iter)->get_arglist(); 
-    generate_as3_struct_definition(f_service_, ts, false, true); 
-    generate_function_helpers(*f_iter); 
-  } 
-} 
- 
-/** 
- * Generates a service client definition. 
- * 
- * @param tservice The service to generate a server for. 
- */ 
-void t_as3_generator::generate_service_client(t_service* tservice) { 
-  string extends = ""; 
-  string extends_client = ""; 
-  if (tservice->get_extends() != NULL) { 
-    extends = tservice->get_extends()->get_name(); 
-    extends_client = " extends " + extends + "Impl"; 
-  } 
- 
-  indent(f_service_) << "public class " << service_name_ << "Impl" << extends_client 
-                     << " implements " << service_name_ << " {" << endl; 
-  indent_up(); 
- 
-  indent(f_service_) << "public function " << service_name_ << "Impl" 
-                     << "(iprot:TProtocol, oprot:TProtocol=null)" << endl; 
-  scope_up(f_service_); 
-  if (extends.empty()) { 
-    f_service_ << indent() << "iprot_ = iprot;" << endl; 
-    f_service_ << indent() << "if (oprot == null) {" << endl; 
-    indent_up(); 
-    f_service_ << indent() << "oprot_ = iprot;" << endl; 
-    indent_down(); 
-    f_service_ << indent() << "} else {" << endl; 
-    indent_up(); 
-    f_service_ << indent() << "oprot_ = oprot;" << endl; 
-    indent_down(); 
-    f_service_ << indent() << "}"; 
-  } else { 
-    f_service_ << indent() << "super(iprot, oprot);" << endl; 
-  } 
-  scope_down(f_service_); 
-  f_service_ << endl; 
- 
-  if (extends.empty()) { 
-    f_service_ << indent() << "protected var iprot_:TProtocol;" << endl << indent() 
-               << "protected var oprot_:TProtocol;" << endl << endl << indent() 
-               << "protected var seqid_:int;" << endl << endl; 
- 
-    indent(f_service_) << "public function getInputProtocol():TProtocol" << endl; 
-    scope_up(f_service_); 
-    indent(f_service_) << "return this.iprot_;" << endl; 
-    scope_down(f_service_); 
-    f_service_ << endl; 
- 
-    indent(f_service_) << "public function getOutputProtocol():TProtocol" << endl; 
-    scope_up(f_service_); 
-    indent(f_service_) << "return this.oprot_;" << endl; 
-    scope_down(f_service_); 
-    f_service_ << endl; 
-  } 
- 
-  // Generate client method implementations 
-  vector<t_function*> functions = tservice->get_functions(); 
-  vector<t_function*>::const_iterator f_iter; 
-  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) { 
-    string funname = (*f_iter)->get_name(); 
- 
-    // Open function 
-    if (!(*f_iter)->is_oneway()) { 
-      if ((*f_iter)->get_returntype()->is_void()) { 
-        indent(f_service_) << "//function onError(Error):void;" << endl; 
-        indent(f_service_) << "//function onSuccess():void;" << endl; 
-      } else { 
-        indent(f_service_) << "//function onError(Error):void;" << endl; 
-        indent(f_service_) << "//function onSuccess(" << type_name((*f_iter)->get_returntype()) 
-                           << "):void;" << endl; 
-      } 
-    } 
-    indent(f_service_) << "public " << function_signature(*f_iter) << endl; 
-    scope_up(f_service_); 
- 
-    // Get the struct of function call params 
-    t_struct* arg_struct = (*f_iter)->get_arglist(); 
- 
-    string argsname = (*f_iter)->get_name() + "_args"; 
-    vector<t_field*>::const_iterator fld_iter; 
-    const vector<t_field*>& fields = arg_struct->get_members(); 
- 
-    // Serialize the request 
-    f_service_ << indent() << "oprot_.writeMessageBegin(new TMessage(\"" << funname << "\", " 
-               << ((*f_iter)->is_oneway() ? "TMessageType.ONEWAY" : "TMessageType.CALL") 
-               << ", seqid_));" << endl << indent() << "var args:" << argsname << " = new " 
-               << argsname << "();" << endl; 
- 
-    for (fld_iter = fields.begin(); fld_iter != fields.end(); ++fld_iter) { 
-      f_service_ << indent() << "args." << (*fld_iter)->get_name() << " = " 
-                 << (*fld_iter)->get_name() << ";" << endl; 
-    } 
- 
-    f_service_ << indent() << "args.write(oprot_);" << endl << indent() 
-               << "oprot_.writeMessageEnd();" << endl; 
- 
-    if ((*f_iter)->is_oneway()) { 
-      f_service_ << indent() << "oprot_.getTransport().flush();" << endl; 
-    } else { 
-      f_service_ << indent() << "oprot_.getTransport().flush(function(error:Error):void {" << endl; 
-      indent_up(); 
-      f_service_ << indent() << "try {" << endl; 
-      indent_up(); 
-      string resultname = (*f_iter)->get_name() + "_result"; 
-      f_service_ << indent() << "if (error != null) {" << endl << indent() 
-                 << "  if (onError != null) onError(error);" << endl << indent() << "  return;" 
-                 << endl << indent() << "}" << endl << indent() 
-                 << "var msg:TMessage = iprot_.readMessageBegin();" << endl << indent() 
-                 << "if (msg.type == TMessageType.EXCEPTION) {" << endl << indent() 
-                 << "  var x:TApplicationError = TApplicationError.read(iprot_);" << endl 
-                 << indent() << "  iprot_.readMessageEnd();" << endl << indent() 
-                 << "  if (onError != null) onError(x);" << endl << indent() << "  return;" << endl 
-                 << indent() << "}" << endl << indent() << "var result :" << resultname << " = new " 
-                 << resultname << "();" << endl << indent() << "result.read(iprot_);" << endl 
-                 << indent() << "iprot_.readMessageEnd();" << endl; 
- 
-      // Careful, only return _result if not a void function 
-      if (!(*f_iter)->get_returntype()->is_void()) { 
-        f_service_ << indent() << "if (result." << generate_isset_check("success") << ") {" << endl 
-                   << indent() << "  if (onSuccess != null) onSuccess(result.success);" << endl 
-                   << indent() << "  return;" << endl << indent() << "}" << endl; 
-      } 
- 
-      t_struct* xs = (*f_iter)->get_xceptions(); 
-      const std::vector<t_field*>& xceptions = xs->get_members(); 
-      vector<t_field*>::const_iterator x_iter; 
-      for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) { 
-        f_service_ << indent() << "if (result." << (*x_iter)->get_name() << " != null) {" << endl 
-                   << indent() << "  if (onError != null) onError(result." << (*x_iter)->get_name() 
-                   << ");" << endl << indent() << "  return;" << endl << indent() << "}" << endl; 
-      } 
- 
-      // If you get here it's an exception, unless a void function 
-      if ((*f_iter)->get_returntype()->is_void()) { 
-        f_service_ << indent() << "if (onSuccess != null) onSuccess();" << endl << indent() 
-                   << "return;" << endl; 
-      } else { 
- 
-        f_service_ << indent() << "if (onError != null) onError(new " 
-                                  "TApplicationError(TApplicationError.MISSING_RESULT, \"" 
-                   << (*f_iter)->get_name() << " failed: unknown result\"));" << endl; 
-      } 
-      indent_down(); 
-      f_service_ << indent() << "} catch (e:TError) {" << endl << indent() 
-                 << "  if (onError != null) onError(e);" << endl << indent() << "}" << endl; 
- 
-      indent_down(); 
-      indent(f_service_) << "});" << endl; 
-    } 
-    // Close function 
-    scope_down(f_service_); 
-    f_service_ << endl; 
-  } 
- 
-  indent_down(); 
-  indent(f_service_) << "}" << endl; 
-} 
- 
-/** 
- * Generates a service server definition. 
- * 
- * @param tservice The service to generate a server for. 
- */ 
-void t_as3_generator::generate_service_server(t_service* tservice) { 
-  // Generate the dispatch methods 
-  vector<t_function*> functions = tservice->get_functions(); 
-  vector<t_function*>::iterator f_iter; 
- 
-  // Extends stuff 
-  string extends = ""; 
-  string extends_processor = ""; 
-  if (tservice->get_extends() != NULL) { 
-    extends = type_name(tservice->get_extends()); 
-    extends_processor = " extends " + extends + "Processor"; 
-  } 
- 
-  // Generate the header portion 
-  indent(f_service_) << "public class " << service_name_ << "Processor" << extends_processor 
-                     << " implements TProcessor {" << endl; 
-  indent_up(); 
- 
-  indent(f_service_) << "public function " << service_name_ << "Processor(iface:" << service_name_ 
-                     << ")" << endl; 
-  scope_up(f_service_); 
-  if (!extends.empty()) { 
-    f_service_ << indent() << "super(iface);" << endl; 
-  } 
-  f_service_ << indent() << "iface_ = iface;" << endl; 
- 
-  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) { 
-    f_service_ << indent() << "PROCESS_MAP[\"" << (*f_iter)->get_name() 
-               << "\"] = " << (*f_iter)->get_name() << "();" << endl; 
-  } 
- 
-  scope_down(f_service_); 
-  f_service_ << endl; 
- 
-  f_service_ << indent() << "private var iface_:" << service_name_ << ";" << endl; 
- 
-  if (extends.empty()) { 
-    f_service_ << indent() << "protected const PROCESS_MAP:Dictionary = new Dictionary();" << endl; 
-  } 
- 
-  f_service_ << endl; 
- 
-  // Generate the server implementation 
-  string override = ""; 
-  if (tservice->get_extends() != NULL) { 
-    override = "override "; 
-  } 
-  indent(f_service_) << override 
-                     << "public function process(iprot:TProtocol, oprot:TProtocol):Boolean" << endl; 
-  scope_up(f_service_); 
- 
-  f_service_ << indent() << "var msg:TMessage = iprot.readMessageBegin();" << endl; 
- 
-  // TODO(mcslee): validate message, was the seqid etc. legit? 
-  // AS- If all method is oneway: 
-  // do you have an oprot? 
-  // do you you need nullcheck? 
-  f_service_ 
-      << indent() << "var fn:Function = PROCESS_MAP[msg.name];" << endl << indent() 
-      << "if (fn == null) {" << endl << indent() << "  TProtocolUtil.skip(iprot, TType.STRUCT);" 
-      << endl << indent() << "  iprot.readMessageEnd();" << endl << indent() 
-      << "  var x:TApplicationError = new TApplicationError(TApplicationError.UNKNOWN_METHOD, " 
-         "\"Invalid method name: '\"+msg.name+\"'\");" << endl << indent() 
-      << "  oprot.writeMessageBegin(new TMessage(msg.name, TMessageType.EXCEPTION, msg.seqid));" 
-      << endl << indent() << "  x.write(oprot);" << endl << indent() << "  oprot.writeMessageEnd();" 
-      << endl << indent() << "  oprot.getTransport().flush();" << endl << indent() 
-      << "  return true;" << endl << indent() << "}" << endl << indent() 
-      << "fn.call(this,msg.seqid, iprot, oprot);" << endl; 
- 
-  f_service_ << indent() << "return true;" << endl; 
- 
-  scope_down(f_service_); 
-  f_service_ << endl; 
- 
-  // Generate the process subfunctions 
-  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) { 
-    generate_process_function(tservice, *f_iter); 
-  } 
- 
-  indent_down(); 
-  indent(f_service_) << "}" << endl << endl; 
-} 
- 
-/** 
- * Generates a struct and helpers for a function. 
- * 
- * @param tfunction The function 
- */ 
-void t_as3_generator::generate_function_helpers(t_function* tfunction) { 
-  if (tfunction->is_oneway()) { 
-    return; 
-  } 
- 
-  t_struct result(program_, tfunction->get_name() + "_result"); 
-  t_field success(tfunction->get_returntype(), "success", 0); 
-  if (!tfunction->get_returntype()->is_void()) { 
-    result.append(&success); 
-  } 
- 
-  t_struct* xs = tfunction->get_xceptions(); 
-  const vector<t_field*>& fields = xs->get_members(); 
-  vector<t_field*>::const_iterator f_iter; 
-  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { 
-    result.append(*f_iter); 
-  } 
- 
-  generate_as3_struct_definition(f_service_, &result, false, true, true); 
-} 
- 
-/** 
- * Generates a process function definition. 
- * 
- * @param tfunction The function to write a dispatcher for 
- */ 
-void t_as3_generator::generate_process_function(t_service* tservice, t_function* tfunction) { 
-  (void)tservice; 
-  // Open class 
-  indent(f_service_) << "private function " << tfunction->get_name() << "():Function {" << endl; 
-  indent_up(); 
- 
-  // Open function 
-  indent(f_service_) << "return function(seqid:int, iprot:TProtocol, oprot:TProtocol):void" << endl; 
-  scope_up(f_service_); 
- 
-  string argsname = tfunction->get_name() + "_args"; 
-  string resultname = tfunction->get_name() + "_result"; 
- 
-  f_service_ << indent() << "var args:" << argsname << " = new " << argsname << "();" << endl 
-             << indent() << "args.read(iprot);" << endl << indent() << "iprot.readMessageEnd();" 
-             << endl; 
- 
-  t_struct* xs = tfunction->get_xceptions(); 
-  const std::vector<t_field*>& xceptions = xs->get_members(); 
-  vector<t_field*>::const_iterator x_iter; 
- 
-  // Declare result for non oneway function 
-  if (!tfunction->is_oneway()) { 
-    f_service_ << indent() << "var result:" << resultname << " = new " << resultname << "();" 
-               << endl; 
-  } 
- 
-  // Try block for a function with exceptions 
-  if (xceptions.size() > 0) { 
-    f_service_ << indent() << "try {" << endl; 
-    indent_up(); 
-  } 
- 
-  // Generate the function call 
-  t_struct* arg_struct = tfunction->get_arglist(); 
-  const std::vector<t_field*>& fields = arg_struct->get_members(); 
-  vector<t_field*>::const_iterator f_iter; 
- 
-  f_service_ << indent(); 
-  if (tfunction->is_oneway()) { 
-    f_service_ << "iface_." << tfunction->get_name() << "("; 
-    bool first = true; 
-    for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { 
-      if (first) { 
-        first = false; 
-      } else { 
-        f_service_ << ", "; 
-      } 
-      f_service_ << "args." << (*f_iter)->get_name(); 
-    } 
-    f_service_ << ");" << endl; 
-  } else { 
-    f_service_ << "// sorry this operation is not supported yet" << endl; 
-    f_service_ << indent() << "throw new Error(\"This is not yet supported\");" << endl; 
-  } 
- 
-  // Set isset on success field 
-  if (!tfunction->is_oneway() && !tfunction->get_returntype()->is_void() 
-      && !type_can_be_null(tfunction->get_returntype())) { 
-    f_service_ << indent() << "result.set" << get_cap_name("success") << get_cap_name("isSet") 
-               << "(true);" << endl; 
-  } 
- 
-  if (!tfunction->is_oneway() && xceptions.size() > 0) { 
-    indent_down(); 
-    f_service_ << indent() << "}"; 
-    for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) { 
-      f_service_ << " catch (" << (*x_iter)->get_name() << ":" 
-                 << type_name((*x_iter)->get_type(), false, false) << ") {" << endl; 
-      if (!tfunction->is_oneway()) { 
-        indent_up(); 
-        f_service_ << indent() << "result." << (*x_iter)->get_name() << " = " 
-                   << (*x_iter)->get_name() << ";" << endl; 
-        indent_down(); 
-        f_service_ << indent() << "}"; 
-      } else { 
-        f_service_ << "}"; 
-      } 
-    } 
-    f_service_ << " catch (th:Error) {" << endl; 
-    indent_up(); 
-    f_service_ << indent() << "trace(\"Internal error processing " << tfunction->get_name() 
-               << "\", th);" << endl << indent() 
-               << "var x:TApplicationError = new " 
-                  "TApplicationError(TApplicationError.INTERNAL_ERROR, \"Internal error processing " 
-               << tfunction->get_name() << "\");" << endl << indent() 
-               << "oprot.writeMessageBegin(new TMessage(\"" << tfunction->get_name() 
-               << "\", TMessageType.EXCEPTION, seqid));" << endl << indent() << "x.write(oprot);" 
-               << endl << indent() << "oprot.writeMessageEnd();" << endl << indent() 
-               << "oprot.getTransport().flush();" << endl << indent() << "return;" << endl; 
-    indent_down(); 
-    f_service_ << indent() << "}" << endl; 
-  } 
- 
-  // Shortcut out here for oneway functions 
-  if (tfunction->is_oneway()) { 
-    f_service_ << indent() << "return;" << endl; 
-    scope_down(f_service_); 
- 
-    // Close class 
-    indent_down(); 
-    f_service_ << indent() << "}" << endl << endl; 
-    return; 
-  } 
- 
-  f_service_ << indent() << "oprot.writeMessageBegin(new TMessage(\"" << tfunction->get_name() 
-             << "\", TMessageType.REPLY, seqid));" << endl << indent() << "result.write(oprot);" 
-             << endl << indent() << "oprot.writeMessageEnd();" << endl << indent() 
-             << "oprot.getTransport().flush();" << endl; 
- 
-  // Close function 
-  scope_down(f_service_); 
-  f_service_ << endl; 
- 
-  // Close class 
-  indent_down(); 
-  f_service_ << indent() << "}" << endl << endl; 
-} 
- 
-/** 
- * Deserializes a field of any type. 
- * 
- * @param tfield The field 
- * @param prefix The variable name or container for this field 
- */ 
-void t_as3_generator::generate_deserialize_field(ostream& out, t_field* tfield, string prefix) { 
-  t_type* type = get_true_type(tfield->get_type()); 
- 
-  if (type->is_void()) { 
-    throw "CANNOT GENERATE DESERIALIZE CODE FOR void TYPE: " + prefix + tfield->get_name(); 
-  } 
- 
-  string name = prefix + tfield->get_name(); 
- 
-  if (type->is_struct() || type->is_xception()) { 
-    generate_deserialize_struct(out, (t_struct*)type, name); 
-  } else if (type->is_container()) { 
-    generate_deserialize_container(out, type, name); 
-  } else if (type->is_base_type() || type->is_enum()) { 
- 
-    indent(out) << name << " = iprot."; 
- 
-    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: 
-        throw "compiler error: cannot serialize void field in a struct: " + name; 
-        break; 
-      case t_base_type::TYPE_STRING: 
-        if (type->is_binary()) { 
-          out << "readBinary();"; 
-        } else { 
-          out << "readString();"; 
-        } 
-        break; 
-      case t_base_type::TYPE_BOOL: 
-        out << "readBool();"; 
-        break; 
-      case t_base_type::TYPE_I8: 
-        out << "readByte();"; 
-        break; 
-      case t_base_type::TYPE_I16: 
-        out << "readI16();"; 
-        break; 
-      case t_base_type::TYPE_I32: 
-        out << "readI32();"; 
-        break; 
-      case t_base_type::TYPE_I64: 
-        out << "readI64();"; 
-        break; 
-      case t_base_type::TYPE_DOUBLE: 
-        out << "readDouble();"; 
-        break; 
-      default: 
-        throw "compiler error: no As3 name for base type " + t_base_type::t_base_name(tbase); 
-      } 
-    } else if (type->is_enum()) { 
-      out << "readI32();"; 
-    } 
-    out << endl; 
-  } else { 
-    printf("DO NOT KNOW HOW TO DESERIALIZE FIELD '%s' TYPE '%s'\n", 
-           tfield->get_name().c_str(), 
-           type_name(type).c_str()); 
-  } 
-} 
- 
-/** 
- * Generates an unserializer for a struct, invokes read() 
- */ 
-void t_as3_generator::generate_deserialize_struct(ostream& out, t_struct* tstruct, string prefix) { 
-  out << indent() << prefix << " = new " << type_name(tstruct) << "();" << endl << indent() 
-      << prefix << ".read(iprot);" << endl; 
-} 
- 
-/** 
- * Deserializes a container by reading its size and then iterating 
- */ 
-void t_as3_generator::generate_deserialize_container(ostream& out, t_type* ttype, string prefix) { 
-  scope_up(out); 
- 
-  string obj; 
- 
-  if (ttype->is_map()) { 
-    obj = tmp("_map"); 
-  } else if (ttype->is_set()) { 
-    obj = tmp("_set"); 
-  } else if (ttype->is_list()) { 
-    obj = tmp("_list"); 
-  } 
- 
-  // Declare variables, read header 
-  if (ttype->is_map()) { 
-    indent(out) << "var " << obj << ":TMap = iprot.readMapBegin();" << endl; 
-  } else if (ttype->is_set()) { 
-    indent(out) << "var " << obj << ":TSet = iprot.readSetBegin();" << endl; 
-  } else if (ttype->is_list()) { 
-    indent(out) << "var " << obj << ":TList = iprot.readListBegin();" << endl; 
-  } 
- 
-  indent(out) << prefix << " = new " << type_name(ttype, false, true) 
-              // size the collection correctly 
-              << "(" 
-              << ");" << endl; 
- 
-  // For loop iterates over elements 
-  string i = tmp("_i"); 
-  indent(out) << "for (var " << i << ":int = 0; " << i << " < " << obj << ".size" 
-              << "; " 
-              << "++" << i << ")" << endl; 
- 
-  scope_up(out); 
- 
-  if (ttype->is_map()) { 
-    generate_deserialize_map_element(out, (t_map*)ttype, prefix); 
-  } else if (ttype->is_set()) { 
-    generate_deserialize_set_element(out, (t_set*)ttype, prefix); 
-  } else if (ttype->is_list()) { 
-    generate_deserialize_list_element(out, (t_list*)ttype, prefix); 
-  } 
- 
-  scope_down(out); 
- 
-  // Read container end 
-  if (ttype->is_map()) { 
-    indent(out) << "iprot.readMapEnd();" << endl; 
-  } else if (ttype->is_set()) { 
-    indent(out) << "iprot.readSetEnd();" << endl; 
-  } else if (ttype->is_list()) { 
-    indent(out) << "iprot.readListEnd();" << endl; 
-  } 
- 
-  scope_down(out); 
-} 
- 
-/** 
- * Generates code to deserialize a map 
- */ 
-void t_as3_generator::generate_deserialize_map_element(ostream& out, t_map* tmap, string prefix) { 
-  string key = tmp("_key"); 
-  string val = tmp("_val"); 
-  t_field fkey(tmap->get_key_type(), key); 
-  t_field fval(tmap->get_val_type(), val); 
- 
-  indent(out) << declare_field(&fkey) << endl; 
-  indent(out) << declare_field(&fval) << endl; 
- 
-  generate_deserialize_field(out, &fkey); 
-  generate_deserialize_field(out, &fval); 
- 
-  indent(out) << prefix << "[" << key << "] = " << val << ";" << endl; 
-} 
- 
-/** 
- * Deserializes a set element 
- */ 
-void t_as3_generator::generate_deserialize_set_element(ostream& out, t_set* tset, string prefix) { 
-  string elem = tmp("_elem"); 
-  t_field felem(tset->get_elem_type(), elem); 
- 
-  indent(out) << declare_field(&felem) << endl; 
- 
-  generate_deserialize_field(out, &felem); 
- 
-  indent(out) << prefix << ".add(" << elem << ");" << endl; 
-} 
- 
-/** 
- * Deserializes a list element 
- */ 
-void t_as3_generator::generate_deserialize_list_element(ostream& out, 
-                                                        t_list* tlist, 
-                                                        string prefix) { 
-  string elem = tmp("_elem"); 
-  t_field felem(tlist->get_elem_type(), elem); 
- 
-  indent(out) << declare_field(&felem) << endl; 
- 
-  generate_deserialize_field(out, &felem); 
- 
-  indent(out) << prefix << ".push(" << elem << ");" << endl; 
-} 
- 
-/** 
- * Serializes a field of any type. 
- * 
- * @param tfield The field to serialize 
- * @param prefix Name to prepend to field name 
- */ 
-void t_as3_generator::generate_serialize_field(ostream& out, t_field* tfield, string prefix) { 
-  t_type* type = get_true_type(tfield->get_type()); 
- 
-  // Do nothing for void types 
-  if (type->is_void()) { 
-    throw "CANNOT GENERATE SERIALIZE CODE FOR void TYPE: " + prefix + tfield->get_name(); 
-  } 
- 
-  if (type->is_struct() || type->is_xception()) { 
-    generate_serialize_struct(out, (t_struct*)type, prefix + tfield->get_name()); 
-  } else if (type->is_container()) { 
-    generate_serialize_container(out, type, prefix + tfield->get_name()); 
-  } else if (type->is_base_type() || type->is_enum()) { 
- 
-    string name = prefix + tfield->get_name(); 
-    indent(out) << "oprot."; 
- 
-    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: 
-        throw "compiler error: cannot serialize void field in a struct: " + name; 
-        break; 
-      case t_base_type::TYPE_STRING: 
-        if (type->is_binary()) { 
-          out << "writeBinary(" << name << ");"; 
-        } else { 
-          out << "writeString(" << name << ");"; 
-        } 
-        break; 
-      case t_base_type::TYPE_BOOL: 
-        out << "writeBool(" << name << ");"; 
-        break; 
-      case t_base_type::TYPE_I8: 
-        out << "writeByte(" << name << ");"; 
-        break; 
-      case t_base_type::TYPE_I16: 
-        out << "writeI16(" << name << ");"; 
-        break; 
-      case t_base_type::TYPE_I32: 
-        out << "writeI32(" << name << ");"; 
-        break; 
-      case t_base_type::TYPE_I64: 
-        out << "writeI64(" << name << ");"; 
-        break; 
-      case t_base_type::TYPE_DOUBLE: 
-        out << "writeDouble(" << name << ");"; 
-        break; 
-      default: 
-        throw "compiler error: no As3 name for base type " + t_base_type::t_base_name(tbase); 
-      } 
-    } else if (type->is_enum()) { 
-      out << "writeI32(" << name << ");"; 
-    } 
-    out << endl; 
-  } else { 
-    printf("DO NOT KNOW HOW TO SERIALIZE FIELD '%s%s' TYPE '%s'\n", 
-           prefix.c_str(), 
-           tfield->get_name().c_str(), 
-           type_name(type).c_str()); 
-  } 
-} 
- 
-/** 
- * Serializes all the members of a struct. 
- * 
- * @param tstruct The struct to serialize 
- * @param prefix  String prefix to attach to all fields 
- */ 
-void t_as3_generator::generate_serialize_struct(ostream& out, t_struct* tstruct, string prefix) { 
-  (void)tstruct; 
-  out << indent() << prefix << ".write(oprot);" << endl; 
-} 
- 
-/** 
- * Serializes a container by writing its size then the elements. 
- * 
- * @param ttype  The type of container 
- * @param prefix String prefix for fields 
- */ 
-void t_as3_generator::generate_serialize_container(ostream& out, t_type* ttype, string prefix) { 
-  scope_up(out); 
- 
-  if (ttype->is_map()) { 
-    string iter = tmp("_key"); 
-    string counter = tmp("_sizeCounter"); 
-    indent(out) << "var " << counter << ":int = 0;" << endl; 
-    indent(out) << "for (var " << iter << ":* in " << prefix << ") {" << endl; 
-    indent(out) << "  " << counter << +"++;" << endl; 
-    indent(out) << "}" << endl; 
- 
-    indent(out) << "oprot.writeMapBegin(new TMap(" << type_to_enum(((t_map*)ttype)->get_key_type()) 
-                << ", " << type_to_enum(((t_map*)ttype)->get_val_type()) << ", " << counter << "));" 
-                << endl; 
-  } else if (ttype->is_set()) { 
-    indent(out) << "oprot.writeSetBegin(new TSet(" << type_to_enum(((t_set*)ttype)->get_elem_type()) 
-                << ", " << prefix << ".size));" << endl; 
-  } else if (ttype->is_list()) { 
-    indent(out) << "oprot.writeListBegin(new TList(" 
-                << type_to_enum(((t_list*)ttype)->get_elem_type()) << ", " << prefix << ".length));" 
-                << endl; 
-  } 
- 
-  string iter = tmp("elem"); 
-  if (ttype->is_map()) { 
-    indent(out) << "for (var " << iter << ":* in " << prefix << ")"; 
-  } else if (ttype->is_set()) { 
-    indent(out) << "for each (var " << iter << ":* in " << prefix << ".toArray())"; 
-  } else if (ttype->is_list()) { 
-    indent(out) << "for each (var " << iter << ":* in " << prefix << ")"; 
-  } 
- 
-  scope_up(out); 
- 
-  if (ttype->is_map()) { 
-    generate_serialize_map_element(out, (t_map*)ttype, iter, prefix); 
-  } else if (ttype->is_set()) { 
-    generate_serialize_set_element(out, (t_set*)ttype, iter); 
-  } else if (ttype->is_list()) { 
-    generate_serialize_list_element(out, (t_list*)ttype, iter); 
-  } 
- 
-  scope_down(out); 
- 
-  if (ttype->is_map()) { 
-    indent(out) << "oprot.writeMapEnd();" << endl; 
-  } else if (ttype->is_set()) { 
-    indent(out) << "oprot.writeSetEnd();" << endl; 
-  } else if (ttype->is_list()) { 
-    indent(out) << "oprot.writeListEnd();" << endl; 
-  } 
- 
-  scope_down(out); 
-} 
- 
-/** 
- * Serializes the members of a map. 
- */ 
-void t_as3_generator::generate_serialize_map_element(ostream& out, 
-                                                     t_map* tmap, 
-                                                     string iter, 
-                                                     string map) { 
-  t_field kfield(tmap->get_key_type(), iter); 
-  generate_serialize_field(out, &kfield, ""); 
-  t_field vfield(tmap->get_val_type(), map + "[" + iter + "]"); 
-  generate_serialize_field(out, &vfield, ""); 
-} 
- 
-/** 
- * Serializes the members of a set. 
- */ 
-void t_as3_generator::generate_serialize_set_element(ostream& out, t_set* tset, string iter) { 
-  t_field efield(tset->get_elem_type(), iter); 
-  generate_serialize_field(out, &efield, ""); 
-} 
- 
-/** 
- * Serializes the members of a list. 
- */ 
-void t_as3_generator::generate_serialize_list_element(ostream& out, t_list* tlist, string iter) { 
-  t_field efield(tlist->get_elem_type(), iter); 
-  generate_serialize_field(out, &efield, ""); 
-} 
- 
-/** 
- * Returns a As3 type name 
- * 
- * @param ttype The type 
- * @param container Is the type going inside a container? 
- * @return As3 type name, i.e. HashMap<Key,Value> 
- */ 
-string t_as3_generator::type_name(t_type* ttype, bool in_container, bool in_init) { 
-  (void)in_init; 
-  // In As3 typedefs are just resolved to their real type 
-  ttype = get_true_type(ttype); 
-  string prefix; 
- 
-  if (ttype->is_base_type()) { 
-    return base_type_name((t_base_type*)ttype, in_container); 
-  } else if (ttype->is_enum()) { 
-    return "int"; 
-  } else if (ttype->is_map()) { 
-    return "Dictionary"; 
-  } else if (ttype->is_set()) { 
-    return "Set"; 
-  } else if (ttype->is_list()) { 
-    return "Array"; 
-  } 
- 
-  // Check for namespacing 
-  t_program* program = ttype->get_program(); 
-  if (program != NULL && program != program_) { 
-    string package = program->get_namespace("as3"); 
-    if (!package.empty()) { 
-      return package + "." + ttype->get_name(); 
-    } 
-  } 
- 
-  return ttype->get_name(); 
-} 
- 
-/** 
- * Returns the AS3 type that corresponds to the thrift type. 
- * 
- * @param tbase The base type 
- * @param container Is it going in a As3 container? 
- */ 
-string t_as3_generator::base_type_name(t_base_type* type, bool in_container) { 
-  (void)in_container; 
-  t_base_type::t_base tbase = type->get_base(); 
- 
-  switch (tbase) { 
-  case t_base_type::TYPE_VOID: 
-    return "void"; 
-  case t_base_type::TYPE_STRING: 
-    if (type->is_binary()) { 
-      return "ByteArray"; 
-    } else { 
-      return "String"; 
-    } 
-  case t_base_type::TYPE_BOOL: 
-    return "Boolean"; 
-  case t_base_type::TYPE_I8: 
-  case t_base_type::TYPE_I16: 
-  case t_base_type::TYPE_I32: 
-    return "int"; 
-  case t_base_type::TYPE_I64: 
-    throw "i64 is not yet supported in as3"; 
-  case t_base_type::TYPE_DOUBLE: 
-    return "Number"; 
-  default: 
-    throw "compiler error: no As3 name for base type " + t_base_type::t_base_name(tbase); 
-  } 
-} 
- 
-/** 
- * Declares a field, which may include initialization as necessary. 
- * 
- * @param ttype The type 
- */ 
-string t_as3_generator::declare_field(t_field* tfield, bool init) { 
-  // TODO(mcslee): do we ever need to initialize the field? 
-  string result = "var " + tfield->get_name() + ":" + type_name(tfield->get_type()); 
-  if (init) { 
-    t_type* ttype = get_true_type(tfield->get_type()); 
-    if (ttype->is_base_type() && tfield->get_value() != NULL) { 
-      std::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 += " = null"; 
-        break; 
-      case t_base_type::TYPE_BOOL: 
-        result += " = false"; 
-        break; 
-      case t_base_type::TYPE_I8: 
-      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 += " = (double)0"; 
-        break; 
-      } 
- 
-    } else if (ttype->is_enum()) { 
-      result += " = 0"; 
-    } else if (ttype->is_container()) { 
-      result += " = new " + type_name(ttype, false, true) + "()"; 
-    } else { 
-      result += " = new " + type_name(ttype, false, true) + "()"; 
-      ; 
-    } 
-  } 
-  return result + ";"; 
-} 
- 
-/** 
- * Renders a function signature of the form 'type name(args)' 
- * 
- * @param tfunction Function definition 
- * @return String of rendered function definition 
- */ 
-string t_as3_generator::function_signature(t_function* tfunction, string prefix) { 
-  std::string arguments = argument_list(tfunction->get_arglist()); 
-  if (!tfunction->is_oneway()) { 
-    if (arguments != "") { 
-      arguments += ", "; 
-    } 
-    arguments += "onError:Function, onSuccess:Function"; 
-  } 
- 
-  std::string result = "function " + prefix + tfunction->get_name() + "(" + arguments + "):void"; 
-  return result; 
-} 
- 
-/** 
- * Renders a comma separated field list, with type names 
- */ 
-string t_as3_generator::argument_list(t_struct* tstruct) { 
-  string result = ""; 
- 
-  const vector<t_field*>& fields = tstruct->get_members(); 
-  vector<t_field*>::const_iterator f_iter; 
-  bool first = true; 
-  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { 
-    if (first) { 
-      first = false; 
-    } else { 
-      result += ", "; 
-    } 
-    result += (*f_iter)->get_name() + ":" + type_name((*f_iter)->get_type()); 
-  } 
-  return result; 
-} 
- 
-/** 
- * Converts the parse type to a C++ enum string for the given type. 
- */ 
-string t_as3_generator::type_to_enum(t_type* type) { 
-  type = get_true_type(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: 
-      throw "NO T_VOID CONSTRUCT"; 
-    case t_base_type::TYPE_STRING: 
-      return "TType.STRING"; 
-    case t_base_type::TYPE_BOOL: 
-      return "TType.BOOL"; 
-    case t_base_type::TYPE_I8: 
-      return "TType.BYTE"; 
-    case t_base_type::TYPE_I16: 
-      return "TType.I16"; 
-    case t_base_type::TYPE_I32: 
-      return "TType.I32"; 
-    case t_base_type::TYPE_I64: 
-      return "TType.I64"; 
-    case t_base_type::TYPE_DOUBLE: 
-      return "TType.DOUBLE"; 
-    } 
-  } else if (type->is_enum()) { 
-    return "TType.I32"; 
-  } else if (type->is_struct() || type->is_xception()) { 
-    return "TType.STRUCT"; 
-  } else if (type->is_map()) { 
-    return "TType.MAP"; 
-  } else if (type->is_set()) { 
-    return "TType.SET"; 
-  } else if (type->is_list()) { 
-    return "TType.LIST"; 
-  } 
- 
-  throw "INVALID TYPE IN type_to_enum: " + type->get_name(); 
-} 
- 
-/** 
- * Applies the correct style to a string based on the value of nocamel_style_ 
- */ 
-std::string t_as3_generator::get_cap_name(std::string name) { 
-  name[0] = toupper(name[0]); 
-  return name; 
-} 
- 
-string t_as3_generator::constant_name(string name) { 
-  string constant_name; 
- 
-  bool is_first = true; 
-  bool was_previous_char_upper = false; 
-  for (string::iterator iter = name.begin(); iter != name.end(); ++iter) { 
-    string::value_type character = (*iter); 
- 
-    bool is_upper = isupper(character); 
- 
-    if (is_upper && !is_first && !was_previous_char_upper) { 
-      constant_name += '_'; 
-    } 
-    constant_name += toupper(character); 
- 
-    is_first = false; 
-    was_previous_char_upper = is_upper; 
-  } 
- 
-  return constant_name; 
-} 
- 
-/** 
- * Emits a As3Doc comment if the provided object has a doc in Thrift 
- */ 
-void t_as3_generator::generate_as3_doc(ostream& out, t_doc* tdoc) { 
-  if (tdoc->has_doc()) { 
-    generate_docstring_comment(out, "/**\n", " * ", tdoc->get_doc(), " */\n"); 
-  } 
-} 
- 
-/** 
- * Emits a As3Doc comment if the provided function object has a doc in Thrift 
- */ 
-void t_as3_generator::generate_as3_doc(ostream& out, t_function* tfunction) { 
-  if (tfunction->has_doc()) { 
-    stringstream ss; 
-    ss << tfunction->get_doc(); 
-    const vector<t_field*>& fields = tfunction->get_arglist()->get_members(); 
-    vector<t_field*>::const_iterator p_iter; 
-    for (p_iter = fields.begin(); p_iter != fields.end(); ++p_iter) { 
-      t_field* p = *p_iter; 
-      ss << "\n@param " << p->get_name(); 
-      if (p->has_doc()) { 
-        ss << " " << p->get_doc(); 
-      } 
-    } 
-    generate_docstring_comment(out, "/**\n", " * ", ss.str(), " */\n"); 
-  } 
-} 
- 
-std::string t_as3_generator::generate_isset_check(t_field* field) { 
-  return generate_isset_check(field->get_name()); 
-} 
- 
-std::string t_as3_generator::generate_isset_check(std::string field_name) { 
-  return "is" + get_cap_name("set") + get_cap_name(field_name) + "()"; 
-} 
- 
-void t_as3_generator::generate_isset_set(ostream& out, t_field* field) { 
-  if (!type_can_be_null(field->get_type())) { 
-    indent(out) << "this.__isset_" << field->get_name() << " = true;" << endl; 
-  } 
-} 
- 
-std::string t_as3_generator::get_enum_class_name(t_type* type) { 
-  string package = ""; 
-  t_program* program = type->get_program(); 
-  if (program != NULL && program != program_) { 
-    package = program->get_namespace("as3") + "."; 
-  } 
-  return package + type->get_name(); 
-} 
- 
-THRIFT_REGISTER_GENERATOR( 
-    as3, 
-    "AS3", 
-    "    bindable:        Add [bindable] metadata to all the struct classes.\n") 
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#include <sstream>
+#include <string>
+#include <fstream>
+#include <iostream>
+#include <vector>
+#include <cctype>
+
+#include <sys/stat.h>
+#include <stdexcept>
+
+#include "thrift/platform.h"
+#include "thrift/generate/t_oop_generator.h"
+
+using std::map;
+using std::ostream;
+using std::ostringstream;
+using std::string;
+using std::stringstream;
+using std::vector;
+
+static const string endl = "\n"; // avoid ostream << std::endl flushes
+
+/**
+ * AS3 code generator.
+ *
+ */
+class t_as3_generator : public t_oop_generator {
+public:
+  t_as3_generator(t_program* program,
+                  const std::map<std::string, std::string>& parsed_options,
+                  const std::string& option_string)
+    : t_oop_generator(program) {
+    (void)option_string;
+    std::map<std::string, std::string>::const_iterator iter;
+
+    bindable_ = false;
+    for( iter = parsed_options.begin(); iter != parsed_options.end(); ++iter) {
+      if( iter->first.compare("bindable") == 0) {
+        bindable_ = true;
+      } else {
+        throw "unknown option as3:" + iter->first;
+      }
+    }
+
+    out_dir_base_ = "gen-as3";
+  }
+
+  /**
+   * Init and close methods
+   */
+
+  void init_generator();
+  void close_generator();
+
+  void generate_consts(std::vector<t_const*> consts);
+
+  /**
+   * Program-level generation functions
+   */
+
+  void generate_typedef(t_typedef* ttypedef);
+  void generate_enum(t_enum* tenum);
+  void generate_struct(t_struct* tstruct);
+  void generate_xception(t_struct* txception);
+  void generate_service(t_service* tservice);
+
+  void print_const_value(std::ostream& out,
+                         std::string name,
+                         t_type* type,
+                         t_const_value* value,
+                         bool in_static,
+                         bool defval = false);
+  std::string render_const_value(ostream& out,
+                                 std::string name,
+                                 t_type* type,
+                                 t_const_value* value);
+
+  /**
+   * Service-level generation functions
+   */
+
+  void generate_as3_struct(t_struct* tstruct, bool is_exception);
+
+  void generate_as3_struct_definition(std::ostream& out,
+                                      t_struct* tstruct,
+                                      bool is_xception = false,
+                                      bool in_class = false,
+                                      bool is_result = false);
+  // removed -- equality,compare_to
+  void generate_as3_struct_reader(std::ostream& out, t_struct* tstruct);
+  void generate_as3_validator(std::ostream& out, t_struct* tstruct);
+  void generate_as3_struct_result_writer(std::ostream& out, t_struct* tstruct);
+  void generate_as3_struct_writer(std::ostream& out, t_struct* tstruct);
+  void generate_as3_struct_tostring(std::ostream& out, t_struct* tstruct, bool bindable);
+  void generate_as3_meta_data_map(std::ostream& out, t_struct* tstruct);
+  void generate_field_value_meta_data(std::ostream& out, t_type* type);
+  std::string get_as3_type_string(t_type* type);
+  void generate_reflection_setters(std::ostringstream& out,
+                                   t_type* type,
+                                   std::string field_name,
+                                   std::string cap_name);
+  void generate_reflection_getters(std::ostringstream& out,
+                                   t_type* type,
+                                   std::string field_name,
+                                   std::string cap_name);
+  void generate_generic_field_getters_setters(std::ostream& out, t_struct* tstruct);
+  void generate_generic_isset_method(std::ostream& out, t_struct* tstruct);
+  void generate_as3_bean_boilerplate(std::ostream& out, t_struct* tstruct, bool bindable);
+
+  void generate_function_helpers(t_function* tfunction);
+  std::string get_cap_name(std::string name);
+  std::string generate_isset_check(t_field* field);
+  std::string generate_isset_check(std::string field);
+  void generate_isset_set(ostream& out, t_field* field);
+  // removed std::string isset_field_id(t_field* field);
+
+  void generate_service_interface(t_service* tservice);
+  void generate_service_helpers(t_service* tservice);
+  void generate_service_client(t_service* tservice);
+  void generate_service_server(t_service* tservice);
+  void generate_process_function(t_service* tservice, t_function* tfunction);
+
+  /**
+   * Serialization constructs
+   */
+
+  void generate_deserialize_field(std::ostream& out, t_field* tfield, std::string prefix = "");
+
+  void generate_deserialize_struct(std::ostream& out, t_struct* tstruct, std::string prefix = "");
+
+  void generate_deserialize_container(std::ostream& out, t_type* ttype, std::string prefix = "");
+
+  void generate_deserialize_set_element(std::ostream& out, t_set* tset, std::string prefix = "");
+
+  void generate_deserialize_map_element(std::ostream& out, t_map* tmap, std::string prefix = "");
+
+  void generate_deserialize_list_element(std::ostream& out,
+                                         t_list* tlist,
+                                         std::string prefix = "");
+
+  void generate_serialize_field(std::ostream& out, t_field* tfield, std::string prefix = "");
+
+  void generate_serialize_struct(std::ostream& out, t_struct* tstruct, std::string prefix = "");
+
+  void generate_serialize_container(std::ostream& out, t_type* ttype, std::string prefix = "");
+
+  void generate_serialize_map_element(std::ostream& out,
+                                      t_map* tmap,
+                                      std::string iter,
+                                      std::string map);
+
+  void generate_serialize_set_element(std::ostream& out, t_set* tmap, std::string iter);
+
+  void generate_serialize_list_element(std::ostream& out, t_list* tlist, std::string iter);
+
+  void generate_as3_doc(std::ostream& out, t_doc* tdoc);
+
+  void generate_as3_doc(std::ostream& out, t_function* tdoc);
+
+  /**
+   * Helper rendering functions
+   */
+
+  std::string as3_package();
+  std::string as3_type_imports();
+  std::string as3_thrift_imports();
+  std::string as3_thrift_gen_imports(t_struct* tstruct, string& imports);
+  std::string as3_thrift_gen_imports(t_service* tservice);
+  std::string type_name(t_type* ttype, bool in_container = false, bool in_init = false);
+  std::string base_type_name(t_base_type* tbase, bool in_container = false);
+  std::string declare_field(t_field* tfield, bool init = false);
+  std::string function_signature(t_function* tfunction, std::string prefix = "");
+  std::string argument_list(t_struct* tstruct);
+  std::string type_to_enum(t_type* ttype);
+  std::string get_enum_class_name(t_type* type);
+
+  bool type_can_be_null(t_type* ttype) {
+    ttype = get_true_type(ttype);
+
+    return ttype->is_container() || ttype->is_struct() || ttype->is_xception()
+           || ttype->is_string();
+  }
+
+  std::string constant_name(std::string name);
+
+private:
+  /**
+   * File streams
+   */
+
+  std::string package_name_;
+  ofstream_with_content_based_conditional_update f_service_;
+  std::string package_dir_;
+
+  bool bindable_;
+};
+
+/**
+ * Prepares for file generation by opening up the necessary file output
+ * streams.
+ *
+ * @param tprogram The program to generate
+ */
+void t_as3_generator::init_generator() {
+  // Make output directory
+  MKDIR(get_out_dir().c_str());
+  package_name_ = program_->get_namespace("as3");
+
+  string dir = package_name_;
+  string subdir = get_out_dir();
+  string::size_type loc;
+  while ((loc = dir.find(".")) != string::npos) {
+    subdir = subdir + "/" + dir.substr(0, loc);
+    MKDIR(subdir.c_str());
+    dir = dir.substr(loc + 1);
+  }
+  if (dir.size() > 0) {
+    subdir = subdir + "/" + dir;
+    MKDIR(subdir.c_str());
+  }
+
+  package_dir_ = subdir;
+}
+
+/**
+ * Packages the generated file
+ *
+ * @return String of the package, i.e. "package org.apache.thriftdemo;"
+ */
+string t_as3_generator::as3_package() {
+  if (!package_name_.empty()) {
+    return string("package ") + package_name_ + " ";
+  }
+  return "package ";
+}
+
+/**
+ * Prints standard as3 imports
+ *
+ * @return List of imports for As3 types that are used in here
+ */
+string t_as3_generator::as3_type_imports() {
+  return string() + "import org.apache.thrift.Set;\n" + "import flash.utils.ByteArray;\n"
+         + "import flash.utils.Dictionary;\n\n";
+}
+
+/**
+ * Prints standard as3 imports
+ *
+ * @return List of imports necessary for thrift
+ */
+string t_as3_generator::as3_thrift_imports() {
+  return string() + "import org.apache.thrift.*;\n" + "import org.apache.thrift.meta_data.*;\n"
+         + "import org.apache.thrift.protocol.*;\n\n";
+}
+
+/**
+ * Prints imports needed for a given type
+ *
+ * @return List of imports necessary for a given t_struct
+ */
+string t_as3_generator::as3_thrift_gen_imports(t_struct* tstruct, string& imports) {
+
+  const vector<t_field*>& members = tstruct->get_members();
+  vector<t_field*>::const_iterator m_iter;
+
+  // For each type check if it is from a differnet namespace
+  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
+    t_program* program = (*m_iter)->get_type()->get_program();
+    if (program != NULL && program != program_) {
+      string package = program->get_namespace("as3");
+      if (!package.empty()) {
+        if (imports.find(package + "." + (*m_iter)->get_type()->get_name()) == string::npos) {
+          imports.append("import " + package + "." + (*m_iter)->get_type()->get_name() + ";\n");
+        }
+      }
+    }
+  }
+  return imports;
+}
+
+/**
+ * Prints imports needed for a given type
+ *
+ * @return List of imports necessary for a given t_service
+ */
+string t_as3_generator::as3_thrift_gen_imports(t_service* tservice) {
+  string imports;
+  const vector<t_function*>& functions = tservice->get_functions();
+  vector<t_function*>::const_iterator f_iter;
+
+  // For each type check if it is from a differnet namespace
+  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
+    t_program* program = (*f_iter)->get_returntype()->get_program();
+    if (program != NULL && program != program_) {
+      string package = program->get_namespace("as3");
+      if (!package.empty()) {
+        if (imports.find(package + "." + (*f_iter)->get_returntype()->get_name()) == string::npos) {
+          imports.append("import " + package + "." + (*f_iter)->get_returntype()->get_name()
+                         + ";\n");
+        }
+      }
+    }
+
+    as3_thrift_gen_imports((*f_iter)->get_arglist(), imports);
+    as3_thrift_gen_imports((*f_iter)->get_xceptions(), imports);
+  }
+
+  return imports;
+}
+
+/**
+ * Nothing in As3
+ */
+void t_as3_generator::close_generator() {
+}
+
+/**
+ * Generates a typedef. This is not done in As3, since it does
+ * not support arbitrary name replacements, and it'd be a wacky waste
+ * of overhead to make wrapper classes.
+ *
+ * @param ttypedef The type definition
+ */
+void t_as3_generator::generate_typedef(t_typedef* ttypedef) {
+  (void)ttypedef;
+}
+
+/**
+ * Enums are a class with a set of static constants.
+ *
+ * @param tenum The enumeration
+ */
+void t_as3_generator::generate_enum(t_enum* tenum) {
+  // Make output file
+  string f_enum_name = package_dir_ + "/" + (tenum->get_name()) + ".as";
+  ofstream_with_content_based_conditional_update f_enum;
+  f_enum.open(f_enum_name);
+
+  // Comment and package it
+  f_enum << autogen_comment() << as3_package() << endl;
+
+  scope_up(f_enum);
+  // Add as3 imports
+  f_enum << string() + "import org.apache.thrift.Set;" << endl << "import flash.utils.Dictionary;"
+         << endl;
+
+  indent(f_enum) << "public class " << tenum->get_name() << " ";
+  scope_up(f_enum);
+
+  vector<t_enum_value*> constants = tenum->get_constants();
+  vector<t_enum_value*>::iterator c_iter;
+  for (c_iter = constants.begin(); c_iter != constants.end(); ++c_iter) {
+    int value = (*c_iter)->get_value();
+    indent(f_enum) << "public static const " << (*c_iter)->get_name() << ":int = " << value << ";"
+                   << endl;
+  }
+
+  // Create a static Set with all valid values for this enum
+  f_enum << endl;
+
+  indent(f_enum) << "public static const VALID_VALUES:Set = new Set(";
+  indent_up();
+  bool firstValue = true;
+  for (c_iter = constants.begin(); c_iter != constants.end(); ++c_iter) {
+    // populate set
+    f_enum << (firstValue ? "" : ", ") << (*c_iter)->get_name();
+    firstValue = false;
+  }
+  indent_down();
+  f_enum << ");" << endl;
+
+  indent(f_enum) << "public static const VALUES_TO_NAMES:Dictionary = new Dictionary();" << endl;
+
+  scope_up(f_enum);
+  for (c_iter = constants.begin(); c_iter != constants.end(); ++c_iter) {
+    indent(f_enum) << "VALUES_TO_NAMES[" << (*c_iter)->get_name() << "] = \""
+                   << (*c_iter)->get_name() << "\";" << endl;
+  }
+  f_enum << endl;
+
+  scope_down(f_enum);
+
+  scope_down(f_enum); // end class
+
+  scope_down(f_enum); // end package
+
+  f_enum.close();
+}
+
+/**
+ * Generates a class that holds all the constants.
+ */
+void t_as3_generator::generate_consts(std::vector<t_const*> consts) {
+  if (consts.empty()) {
+    return;
+  }
+
+  string f_consts_name = package_dir_ + "/" + program_name_ + "Constants.as";
+  ofstream_with_content_based_conditional_update f_consts;
+  f_consts.open(f_consts_name);
+
+  // Print header
+  f_consts << autogen_comment() << as3_package();
+
+  scope_up(f_consts);
+  f_consts << endl;
+
+  f_consts << as3_type_imports();
+
+  indent(f_consts) << "public class " << program_name_ << "Constants {" << endl << endl;
+  indent_up();
+  vector<t_const*>::iterator c_iter;
+  for (c_iter = consts.begin(); c_iter != consts.end(); ++c_iter) {
+    print_const_value(f_consts,
+                      (*c_iter)->get_name(),
+                      (*c_iter)->get_type(),
+                      (*c_iter)->get_value(),
+                      false);
+  }
+  indent_down();
+  indent(f_consts) << "}" << endl;
+  scope_down(f_consts);
+  f_consts.close();
+}
+
+void t_as3_generator::print_const_value(std::ostream& out,
+                                        string name,
+                                        t_type* type,
+                                        t_const_value* value,
+                                        bool in_static,
+                                        bool defval) {
+  type = get_true_type(type);
+
+  indent(out);
+  if (!defval) {
+    out << (in_static ? "var " : "public static const ");
+  }
+  if (type->is_base_type()) {
+    string v2 = render_const_value(out, name, type, value);
+    out << name;
+    if (!defval) {
+      out << ":" << type_name(type);
+    }
+    out << " = " << v2 << ";" << endl << endl;
+  } else if (type->is_enum()) {
+    out << name;
+    if (!defval) {
+      out << ":" << type_name(type);
+    }
+    out << " = " << 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*, t_const_value::value_compare>& val = value->get_map();
+    map<t_const_value*, t_const_value*, t_const_value::value_compare>::const_iterator v_iter;
+    out << name << ":" << type_name(type) << " = new " << type_name(type, false, true) << "();"
+        << endl;
+    if (!in_static) {
+      indent(out) << "{" << endl;
+      indent_up();
+      indent(out) << "new function():void {" << endl;
+      indent_up();
+    }
+    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) {
+        if ((*f_iter)->get_name() == v_iter->first->get_string()) {
+          field_type = (*f_iter)->get_type();
+        }
+      }
+      if (field_type == NULL) {
+        throw "type error: " + type->get_name() + " has no field " + v_iter->first->get_string();
+      }
+      string val = render_const_value(out, name, field_type, v_iter->second);
+      indent(out) << name << ".";
+      out << v_iter->first->get_string() << " = " << val << ";" << endl;
+    }
+    if (!in_static) {
+      indent_down();
+      indent(out) << "}();" << endl;
+      indent_down();
+      indent(out) << "}" << endl;
+    }
+    out << endl;
+  } else if (type->is_map()) {
+    out << name;
+    if (!defval) {
+      out << ":" << type_name(type);
+    }
+    out << " = new " << type_name(type, false, true) << "();" << endl;
+    if (!in_static) {
+      indent(out) << "{" << endl;
+      indent_up();
+      indent(out) << "new function():void {" << endl;
+      indent_up();
+    }
+    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*, t_const_value::value_compare>& val = value->get_map();
+    map<t_const_value*, t_const_value*, t_const_value::value_compare>::const_iterator v_iter;
+    for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
+      string key = render_const_value(out, name, ktype, v_iter->first);
+      string val = render_const_value(out, name, vtype, v_iter->second);
+      indent(out) << name << "[" << key << "] = " << val << ";" << endl;
+    }
+    if (!in_static) {
+      indent_down();
+      indent(out) << "}();" << endl;
+      indent_down();
+      indent(out) << "}" << endl;
+    }
+    out << endl;
+  } else if (type->is_list() || type->is_set()) {
+    out << name;
+    if (!defval) {
+      out << ":" << type_name(type);
+    }
+    out << " = new " << type_name(type, false, true) << "();" << endl;
+    if (!in_static) {
+      indent(out) << "{" << endl;
+      indent_up();
+      indent(out) << "new function():void {" << endl;
+      indent_up();
+    }
+    t_type* etype;
+    if (type->is_list()) {
+      etype = ((t_list*)type)->get_elem_type();
+    } else {
+      etype = ((t_set*)type)->get_elem_type();
+    }
+    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) {
+      string val = render_const_value(out, name, etype, *v_iter);
+      indent(out) << name << "." << (type->is_list() ? "push" : "add") << "(" << val << ");"
+                  << endl;
+    }
+    if (!in_static) {
+      indent_down();
+      indent(out) << "}();" << endl;
+      indent_down();
+      indent(out) << "}" << endl;
+    }
+    out << endl;
+  } else {
+    throw "compiler error: no const of type " + type->get_name();
+  }
+}
+
+string t_as3_generator::render_const_value(ostream& out,
+                                           string name,
+                                           t_type* type,
+                                           t_const_value* value) {
+  (void)name;
+  type = get_true_type(type);
+  std::ostringstream render;
+
+  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:
+      render << '"' << get_escaped_string(value) << '"';
+      break;
+    case t_base_type::TYPE_BOOL:
+      render << ((value->get_integer() > 0) ? "true" : "false");
+      break;
+    case t_base_type::TYPE_I8:
+      render << "(byte)" << value->get_integer();
+      break;
+    case t_base_type::TYPE_I16:
+      render << "(short)" << value->get_integer();
+      break;
+    case t_base_type::TYPE_I32:
+      render << value->get_integer();
+      break;
+    case t_base_type::TYPE_I64:
+      render << value->get_integer() << "L";
+      break;
+    case t_base_type::TYPE_DOUBLE:
+      if (value->get_type() == t_const_value::CV_INTEGER) {
+        render << "(double)" << value->get_integer();
+      } else {
+        render << value->get_double();
+      }
+      break;
+    default:
+      throw "compiler error: no const of base type " + t_base_type::t_base_name(tbase);
+    }
+  } else if (type->is_enum()) {
+    render << value->get_integer();
+  } else {
+    string t = tmp("tmp");
+    print_const_value(out, t, type, value, true);
+    render << t;
+  }
+
+  return render.str();
+}
+
+/**
+ * Generates a struct definition for a thrift data type. This is a class
+ * with data members, read(), write(), and an inner Isset class.
+ *
+ * @param tstruct The struct definition
+ */
+void t_as3_generator::generate_struct(t_struct* tstruct) {
+  generate_as3_struct(tstruct, false);
+}
+
+/**
+ * Exceptions are structs, but they inherit from Exception
+ *
+ * @param tstruct The struct definition
+ */
+void t_as3_generator::generate_xception(t_struct* txception) {
+  generate_as3_struct(txception, true);
+}
+
+/**
+ * As3 struct definition.
+ *
+ * @param tstruct The struct definition
+ */
+void t_as3_generator::generate_as3_struct(t_struct* tstruct, bool is_exception) {
+  // Make output file
+  string f_struct_name = package_dir_ + "/" + (tstruct->get_name()) + ".as";
+  ofstream_with_content_based_conditional_update f_struct;
+  f_struct.open(f_struct_name.c_str());
+
+  f_struct << autogen_comment() << as3_package();
+
+  scope_up(f_struct);
+  f_struct << endl;
+
+  string imports;
+
+  f_struct << as3_type_imports() << as3_thrift_imports() << as3_thrift_gen_imports(tstruct, imports)
+           << endl;
+
+  if (bindable_ && !is_exception) {
+    f_struct << "import flash.events.Event;" << endl << "import flash.events.EventDispatcher;"
+             << endl << "import mx.events.PropertyChangeEvent;" << endl;
+  }
+
+  generate_as3_struct_definition(f_struct, tstruct, is_exception);
+
+  scope_down(f_struct); // end of package
+  f_struct.close();
+}
+
+/**
+ * As3 struct definition. This has various parameters, as it could be
+ * generated standalone or inside another class as a helper. If it
+ * is a helper than it is a static class.
+ *
+ * @param tstruct      The struct definition
+ * @param is_exception Is this an exception?
+ * @param in_class     If inside a class, needs to be static class
+ * @param is_result    If this is a result it needs a different writer
+ */
+void t_as3_generator::generate_as3_struct_definition(ostream& out,
+                                                     t_struct* tstruct,
+                                                     bool is_exception,
+                                                     bool in_class,
+                                                     bool is_result) {
+  generate_as3_doc(out, tstruct);
+
+  bool is_final = (tstruct->annotations_.find("final") != tstruct->annotations_.end());
+  bool bindable = !is_exception && !in_class && bindable_;
+
+  indent(out) << (in_class ? "" : "public ") << (is_final ? "final " : "") << "class "
+              << tstruct->get_name() << " ";
+
+  if (is_exception) {
+    out << "extends Error ";
+  } else if (bindable) {
+    out << "extends EventDispatcher ";
+  }
+  out << "implements TBase ";
+
+  scope_up(out);
+
+  indent(out) << "private static const STRUCT_DESC:TStruct = new TStruct(\"" << tstruct->get_name()
+              << "\");" << endl;
+
+  // Members are public for -as3, private for -as3bean
+  const vector<t_field*>& members = tstruct->get_members();
+  vector<t_field*>::const_iterator m_iter;
+
+  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
+    indent(out) << "private static const " << constant_name((*m_iter)->get_name())
+                << "_FIELD_DESC:TField = new TField(\"" << (*m_iter)->get_name() << "\", "
+                << type_to_enum((*m_iter)->get_type()) << ", " << (*m_iter)->get_key() << ");"
+                << endl;
+  }
+
+  out << endl;
+
+  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
+    generate_as3_doc(out, *m_iter);
+    indent(out) << "private var _" << (*m_iter)->get_name() + ":" + type_name((*m_iter)->get_type())
+                << ";" << endl;
+
+    indent(out) << "public static const " << upcase_string((*m_iter)->get_name())
+                << ":int = " << (*m_iter)->get_key() << ";" << endl;
+  }
+
+  out << endl;
+
+  // Inner Isset class
+  if (members.size() > 0) {
+    for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
+      if (!type_can_be_null((*m_iter)->get_type())) {
+        indent(out) << "private var __isset_" << (*m_iter)->get_name() << ":Boolean = false;"
+                    << endl;
+      }
+    }
+  }
+
+  out << endl;
+
+  generate_as3_meta_data_map(out, tstruct);
+
+  // Static initializer to populate global class to struct metadata map
+  indent(out) << "{" << endl;
+  indent_up();
+  indent(out) << "FieldMetaData.addStructMetaDataMap(" << type_name(tstruct) << ", metaDataMap);"
+              << endl;
+  indent_down();
+  indent(out) << "}" << endl << endl;
+
+  // Default constructor
+  indent(out) << "public function " << tstruct->get_name() << "() {" << endl;
+  indent_up();
+  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
+    if ((*m_iter)->get_value() != NULL) {
+      indent(out) << "this._" << (*m_iter)->get_name() << " = "
+                  << (*m_iter)->get_value()->get_integer() << ";" << endl;
+    }
+  }
+  indent_down();
+  indent(out) << "}" << endl << endl;
+
+  generate_as3_bean_boilerplate(out, tstruct, bindable);
+  generate_generic_field_getters_setters(out, tstruct);
+  generate_generic_isset_method(out, tstruct);
+
+  generate_as3_struct_reader(out, tstruct);
+  if (is_result) {
+    generate_as3_struct_result_writer(out, tstruct);
+  } else {
+    generate_as3_struct_writer(out, tstruct);
+  }
+  generate_as3_struct_tostring(out, tstruct, bindable);
+  generate_as3_validator(out, tstruct);
+  scope_down(out);
+  out << endl;
+}
+
+/**
+ * Generates a function to read all the fields of the struct.
+ *
+ * @param tstruct The struct definition
+ */
+void t_as3_generator::generate_as3_struct_reader(ostream& out, t_struct* tstruct) {
+  out << indent() << "public function read(iprot:TProtocol):void {" << endl;
+  indent_up();
+
+  const vector<t_field*>& fields = tstruct->get_members();
+  vector<t_field*>::const_iterator f_iter;
+
+  // Declare stack tmp variables and read struct header
+  out << indent() << "var field:TField;" << endl << indent() << "iprot.readStructBegin();" << endl;
+
+  // Loop over reading in fields
+  indent(out) << "while (true)" << endl;
+  scope_up(out);
+
+  // Read beginning field marker
+  indent(out) << "field = iprot.readFieldBegin();" << endl;
+
+  // Check for field STOP marker and break
+  indent(out) << "if (field.type == TType.STOP) { " << endl;
+  indent_up();
+  indent(out) << "break;" << endl;
+  indent_down();
+  indent(out) << "}" << endl;
+
+  // Switch statement on the field we are reading
+  indent(out) << "switch (field.id)" << endl;
+
+  scope_up(out);
+
+  // Generate deserialization code for known cases
+  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+    indent(out) << "case " << upcase_string((*f_iter)->get_name()) << ":" << endl;
+    indent_up();
+    indent(out) << "if (field.type == " << type_to_enum((*f_iter)->get_type()) << ") {" << endl;
+    indent_up();
+
+    generate_deserialize_field(out, *f_iter, "this.");
+    generate_isset_set(out, *f_iter);
+    indent_down();
+    out << indent() << "} else { " << endl << indent() << "  TProtocolUtil.skip(iprot, field.type);"
+        << endl << indent() << "}" << endl << indent() << "break;" << endl;
+    indent_down();
+  }
+
+  // In the default case we skip the field
+  out << indent() << "default:" << endl << indent() << "  TProtocolUtil.skip(iprot, field.type);"
+      << endl << indent() << "  break;" << endl;
+
+  scope_down(out);
+
+  // Read field end marker
+  indent(out) << "iprot.readFieldEnd();" << endl;
+
+  scope_down(out);
+
+  out << indent() << "iprot.readStructEnd();" << endl << endl;
+
+  // in non-beans style, check for required fields of primitive type
+  // (which can be checked here but not in the general validate method)
+  out << endl << indent() << "// check for required fields of primitive type, which can't be "
+                             "checked in the validate method" << endl;
+  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+    if ((*f_iter)->get_req() == t_field::T_REQUIRED && !type_can_be_null((*f_iter)->get_type())) {
+      out << indent() << "if (!__isset_" << (*f_iter)->get_name() << ") {" << endl << indent()
+          << "  throw new TProtocolError(TProtocolError.UNKNOWN, \"Required field '"
+          << (*f_iter)->get_name()
+          << "' was not found in serialized data! Struct: \" + toString());" << endl << indent()
+          << "}" << endl;
+    }
+  }
+
+  // performs various checks (e.g. check that all required fields are set)
+  indent(out) << "validate();" << endl;
+
+  indent_down();
+  out << indent() << "}" << endl << endl;
+}
+
+// generates as3 method to perform various checks
+// (e.g. check that all required fields are set)
+void t_as3_generator::generate_as3_validator(ostream& out, t_struct* tstruct) {
+  indent(out) << "public function validate():void {" << endl;
+  indent_up();
+
+  const vector<t_field*>& fields = tstruct->get_members();
+  vector<t_field*>::const_iterator f_iter;
+
+  out << indent() << "// check for required fields" << endl;
+  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+    if ((*f_iter)->get_req() == t_field::T_REQUIRED) {
+      if (type_can_be_null((*f_iter)->get_type())) {
+        indent(out) << "if (" << (*f_iter)->get_name() << " == null) {" << endl;
+        indent(out) << "  throw new TProtocolError(TProtocolError.UNKNOWN, \"Required field '"
+                    << (*f_iter)->get_name() << "' was not present! Struct: \" + toString());"
+                    << endl;
+        indent(out) << "}" << endl;
+      } else {
+        indent(out) << "// alas, we cannot check '" << (*f_iter)->get_name()
+                    << "' because it's a primitive and you chose the non-beans generator." << endl;
+      }
+    }
+  }
+
+  // check that fields of type enum have valid values
+  out << indent() << "// check that fields of type enum have valid values" << endl;
+  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+    t_field* field = (*f_iter);
+    t_type* type = field->get_type();
+    // if field is an enum, check that its value is valid
+    if (type->is_enum()) {
+      indent(out) << "if (" << generate_isset_check(field) << " && !" << get_enum_class_name(type)
+                  << ".VALID_VALUES.contains(" << field->get_name() << ")){" << endl;
+      indent_up();
+      indent(out) << "throw new TProtocolError(TProtocolError.UNKNOWN, \"The field '"
+                  << field->get_name() << "' has been assigned the invalid value \" + "
+                  << field->get_name() << ");" << endl;
+      indent_down();
+      indent(out) << "}" << endl;
+    }
+  }
+
+  indent_down();
+  indent(out) << "}" << endl << endl;
+}
+
+/**
+ * Generates a function to write all the fields of the struct
+ *
+ * @param tstruct The struct definition
+ */
+void t_as3_generator::generate_as3_struct_writer(ostream& out, t_struct* tstruct) {
+  out << indent() << "public function write(oprot:TProtocol):void {" << endl;
+  indent_up();
+
+  string name = tstruct->get_name();
+  const vector<t_field*>& fields = tstruct->get_sorted_members();
+  vector<t_field*>::const_iterator f_iter;
+
+  // performs various checks (e.g. check that all required fields are set)
+  indent(out) << "validate();" << endl << endl;
+
+  indent(out) << "oprot.writeStructBegin(STRUCT_DESC);" << endl;
+
+  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+    bool could_be_unset = (*f_iter)->get_req() == t_field::T_OPTIONAL;
+    if (could_be_unset) {
+      indent(out) << "if (" << generate_isset_check(*f_iter) << ") {" << endl;
+      indent_up();
+    }
+    bool null_allowed = type_can_be_null((*f_iter)->get_type());
+    if (null_allowed) {
+      out << indent() << "if (this." << (*f_iter)->get_name() << " != null) {" << endl;
+      indent_up();
+    }
+
+    indent(out) << "oprot.writeFieldBegin(" << constant_name((*f_iter)->get_name())
+                << "_FIELD_DESC);" << endl;
+
+    // Write field contents
+    generate_serialize_field(out, *f_iter, "this.");
+
+    // Write field closer
+    indent(out) << "oprot.writeFieldEnd();" << endl;
+
+    if (null_allowed) {
+      indent_down();
+      indent(out) << "}" << endl;
+    }
+    if (could_be_unset) {
+      indent_down();
+      indent(out) << "}" << endl;
+    }
+  }
+  // Write the struct map
+  out << indent() << "oprot.writeFieldStop();" << endl << indent() << "oprot.writeStructEnd();"
+      << endl;
+
+  indent_down();
+  out << indent() << "}" << endl << endl;
+}
+
+/**
+ * Generates a function to write all the fields of the struct,
+ * which is a function result. These fields are only written
+ * if they are set in the Isset array, and only one of them
+ * can be set at a time.
+ *
+ * @param tstruct The struct definition
+ */
+void t_as3_generator::generate_as3_struct_result_writer(ostream& out, t_struct* tstruct) {
+  out << indent() << "public function write(oprot:TProtocol):void {" << endl;
+  indent_up();
+
+  string name = tstruct->get_name();
+  const vector<t_field*>& fields = tstruct->get_sorted_members();
+  vector<t_field*>::const_iterator f_iter;
+
+  indent(out) << "oprot.writeStructBegin(STRUCT_DESC);" << endl;
+
+  bool first = true;
+  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+    if (first) {
+      first = false;
+      out << endl << indent() << "if ";
+    } else {
+      out << " else if ";
+    }
+
+    out << "(this." << generate_isset_check(*f_iter) << ") {" << endl;
+
+    indent_up();
+
+    indent(out) << "oprot.writeFieldBegin(" << constant_name((*f_iter)->get_name())
+                << "_FIELD_DESC);" << endl;
+
+    // Write field contents
+    generate_serialize_field(out, *f_iter, "this.");
+
+    // Write field closer
+    indent(out) << "oprot.writeFieldEnd();" << endl;
+
+    indent_down();
+    indent(out) << "}";
+  }
+  // Write the struct map
+  out << endl << indent() << "oprot.writeFieldStop();" << endl << indent()
+      << "oprot.writeStructEnd();" << endl;
+
+  indent_down();
+  out << indent() << "}" << endl << endl;
+}
+
+void t_as3_generator::generate_reflection_getters(ostringstream& out,
+                                                  t_type* type,
+                                                  string field_name,
+                                                  string cap_name) {
+  (void)type;
+  (void)cap_name;
+  indent(out) << "case " << upcase_string(field_name) << ":" << endl;
+  indent_up();
+  indent(out) << "return this." << field_name << ";" << endl;
+  indent_down();
+}
+
+void t_as3_generator::generate_reflection_setters(ostringstream& out,
+                                                  t_type* type,
+                                                  string field_name,
+                                                  string cap_name) {
+  (void)type;
+  (void)cap_name;
+  indent(out) << "case " << upcase_string(field_name) << ":" << endl;
+  indent_up();
+  indent(out) << "if (value == null) {" << endl;
+  indent(out) << "  unset" << get_cap_name(field_name) << "();" << endl;
+  indent(out) << "} else {" << endl;
+  indent(out) << "  this." << field_name << " = value;" << endl;
+  indent(out) << "}" << endl;
+  indent(out) << "break;" << endl << endl;
+
+  indent_down();
+}
+
+void t_as3_generator::generate_generic_field_getters_setters(std::ostream& out,
+                                                             t_struct* tstruct) {
+
+  std::ostringstream getter_stream;
+  std::ostringstream setter_stream;
+
+  // build up the bodies of both the getter and setter at once
+  const vector<t_field*>& fields = tstruct->get_members();
+  vector<t_field*>::const_iterator f_iter;
+  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+    t_field* field = *f_iter;
+    t_type* type = get_true_type(field->get_type());
+    std::string field_name = field->get_name();
+    std::string cap_name = get_cap_name(field_name);
+
+    indent_up();
+    generate_reflection_setters(setter_stream, type, field_name, cap_name);
+    generate_reflection_getters(getter_stream, type, field_name, cap_name);
+    indent_down();
+  }
+
+  // create the setter
+  indent(out) << "public function setFieldValue(fieldID:int, value:*):void {" << endl;
+  indent_up();
+
+  indent(out) << "switch (fieldID) {" << endl;
+
+  out << setter_stream.str();
+
+  indent(out) << "default:" << endl;
+  indent(out) << "  throw new ArgumentError(\"Field \" + fieldID + \" doesn't exist!\");" << endl;
+
+  indent(out) << "}" << endl;
+
+  indent_down();
+  indent(out) << "}" << endl << endl;
+
+  // create the getter
+  indent(out) << "public function getFieldValue(fieldID:int):* {" << endl;
+  indent_up();
+
+  indent(out) << "switch (fieldID) {" << endl;
+
+  out << getter_stream.str();
+
+  indent(out) << "default:" << endl;
+  indent(out) << "  throw new ArgumentError(\"Field \" + fieldID + \" doesn't exist!\");" << endl;
+
+  indent(out) << "}" << endl;
+
+  indent_down();
+
+  indent(out) << "}" << endl << endl;
+}
+
+// Creates a generic isSet method that takes the field number as argument
+void t_as3_generator::generate_generic_isset_method(std::ostream& out, t_struct* tstruct) {
+  const vector<t_field*>& fields = tstruct->get_members();
+  vector<t_field*>::const_iterator f_iter;
+
+  // create the isSet method
+  indent(out) << "// Returns true if field corresponding to fieldID is set (has been assigned a "
+                 "value) and false otherwise" << endl;
+  indent(out) << "public function isSet(fieldID:int):Boolean {" << endl;
+  indent_up();
+  indent(out) << "switch (fieldID) {" << endl;
+
+  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+    t_field* field = *f_iter;
+    indent(out) << "case " << upcase_string(field->get_name()) << ":" << endl;
+    indent_up();
+    indent(out) << "return " << generate_isset_check(field) << ";" << endl;
+    indent_down();
+  }
+
+  indent(out) << "default:" << endl;
+  indent(out) << "  throw new ArgumentError(\"Field \" + fieldID + \" doesn't exist!\");" << endl;
+
+  indent(out) << "}" << endl;
+
+  indent_down();
+  indent(out) << "}" << endl << endl;
+}
+
+/**
+ * Generates a set of As3 Bean boilerplate functions (setters, getters, etc.)
+ * for the given struct.
+ *
+ * @param tstruct The struct definition
+ */
+void t_as3_generator::generate_as3_bean_boilerplate(ostream& out,
+                                                    t_struct* tstruct,
+                                                    bool bindable) {
+  const vector<t_field*>& fields = tstruct->get_members();
+  vector<t_field*>::const_iterator f_iter;
+  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+    t_field* field = *f_iter;
+    t_type* type = get_true_type(field->get_type());
+    std::string field_name = field->get_name();
+    std::string cap_name = get_cap_name(field_name);
+
+    // Simple getter
+    generate_as3_doc(out, field);
+    indent(out) << "public function get " << field_name << "():" << type_name(type) << " {" << endl;
+    indent_up();
+    indent(out) << "return this._" << field_name << ";" << endl;
+    indent_down();
+    indent(out) << "}" << endl << endl;
+
+    // Simple setter
+    generate_as3_doc(out, field);
+    std::string propName = tmp("thriftPropertyChange");
+    if (bindable) {
+      indent(out) << "[Bindable(event=\"" << propName << "\")]" << endl;
+    }
+    indent(out) << "public function set " << field_name << "(" << field_name << ":"
+                << type_name(type) << "):void {" << endl;
+    indent_up();
+    indent(out) << "this._" << field_name << " = " << field_name << ";" << endl;
+    generate_isset_set(out, field);
+
+    if (bindable) {
+      // We have to use a custom event rather than the default, because if you use the default,
+      // the setter only gets called if the value has changed - this means calling
+      // foo.setIntValue(0)
+      // will not cause foo.isIntValueSet() to return true since the value of foo._intValue wasn't
+      // changed
+      // so the setter was never called.
+      indent(out) << "dispatchEvent(new Event(\"" << propName << "\"));" << endl;
+
+      // However, if you just use a custom event, then collections won't be able to detect when
+      // elements
+      // in the collections have changed since they listed for PropertyChangeEvents.  So, we
+      // dispatch both.
+      indent(out) << "dispatchEvent(new PropertyChangeEvent(PropertyChangeEvent.PROPERTY_CHANGE));"
+                  << endl;
+    }
+    indent_down();
+    indent(out) << "}" << endl << endl;
+
+    // Unsetter
+    indent(out) << "public function unset" << cap_name << "():void {" << endl;
+    indent_up();
+    if (type_can_be_null(type)) {
+      indent(out) << "this." << field_name << " = null;" << endl;
+    } else {
+      indent(out) << "this.__isset_" << field_name << " = false;" << endl;
+    }
+    indent_down();
+    indent(out) << "}" << endl << endl;
+
+    // isSet method
+    indent(out) << "// Returns true if field " << field_name
+                << " is set (has been assigned a value) and false otherwise" << endl;
+    indent(out) << "public function is" << get_cap_name("set") << cap_name << "():Boolean {"
+                << endl;
+    indent_up();
+    if (type_can_be_null(type)) {
+      indent(out) << "return this." << field_name << " != null;" << endl;
+    } else {
+      indent(out) << "return this.__isset_" << field_name << ";" << endl;
+    }
+    indent_down();
+    indent(out) << "}" << endl << endl;
+  }
+}
+
+/**
+ * Generates a toString() method for the given struct
+ *
+ * @param tstruct The struct definition
+ */
+void t_as3_generator::generate_as3_struct_tostring(ostream& out,
+                                                   t_struct* tstruct,
+                                                   bool bindable) {
+  // If it's bindable, it extends EventDispatcher so toString is an override.
+  out << indent() << "public " << (bindable ? "override " : "") << "function toString():String {"
+      << endl;
+  indent_up();
+
+  out << indent() << "var ret:String = new String(\"" << tstruct->get_name() << "(\");" << endl;
+  out << indent() << "var first:Boolean = true;" << endl << endl;
+
+  const vector<t_field*>& fields = tstruct->get_members();
+  vector<t_field*>::const_iterator f_iter;
+  bool first = true;
+  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+    bool could_be_unset = (*f_iter)->get_req() == t_field::T_OPTIONAL;
+    if (could_be_unset) {
+      indent(out) << "if (" << generate_isset_check(*f_iter) << ") {" << endl;
+      indent_up();
+    }
+
+    t_field* field = (*f_iter);
+
+    if (!first) {
+      indent(out) << "if (!first) ret +=  \", \";" << endl;
+    }
+    indent(out) << "ret += \"" << (*f_iter)->get_name() << ":\";" << endl;
+    bool can_be_null = type_can_be_null(field->get_type());
+    if (can_be_null) {
+      indent(out) << "if (this." << (*f_iter)->get_name() << " == null) {" << endl;
+      indent(out) << "  ret += \"null\";" << endl;
+      indent(out) << "} else {" << endl;
+      indent_up();
+    }
+
+    if (field->get_type()->is_binary()) {
+      indent(out) << "  ret += \"BINARY\";" << endl;
+    } else if (field->get_type()->is_enum()) {
+      indent(out) << "var " << field->get_name()
+                  << "_name:String = " << get_enum_class_name(field->get_type())
+                  << ".VALUES_TO_NAMES[this." << (*f_iter)->get_name() << "];" << endl;
+      indent(out) << "if (" << field->get_name() << "_name != null) {" << endl;
+      indent(out) << "  ret += " << field->get_name() << "_name;" << endl;
+      indent(out) << "  ret += \" (\";" << endl;
+      indent(out) << "}" << endl;
+      indent(out) << "ret += this." << field->get_name() << ";" << endl;
+      indent(out) << "if (" << field->get_name() << "_name != null) {" << endl;
+      indent(out) << "  ret += \")\";" << endl;
+      indent(out) << "}" << endl;
+    } else {
+      indent(out) << "ret += this." << (*f_iter)->get_name() << ";" << endl;
+    }
+
+    if (can_be_null) {
+      indent_down();
+      indent(out) << "}" << endl;
+    }
+    indent(out) << "first = false;" << endl;
+
+    if (could_be_unset) {
+      indent_down();
+      indent(out) << "}" << endl;
+    }
+    first = false;
+  }
+  out << indent() << "ret += \")\";" << endl << indent() << "return ret;" << endl;
+
+  indent_down();
+  indent(out) << "}" << endl << endl;
+}
+
+/**
+ * Generates a static map with meta data to store information such as fieldID to
+ * fieldName mapping
+ *
+ * @param tstruct The struct definition
+ */
+void t_as3_generator::generate_as3_meta_data_map(ostream& out, t_struct* tstruct) {
+  const vector<t_field*>& fields = tstruct->get_members();
+  vector<t_field*>::const_iterator f_iter;
+
+  // Static Map with fieldID -> FieldMetaData mappings
+  indent(out) << "public static const metaDataMap:Dictionary = new Dictionary();" << endl;
+
+  if (fields.size() > 0) {
+    // Populate map
+    scope_up(out);
+    for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+      t_field* field = *f_iter;
+      std::string field_name = field->get_name();
+      indent(out) << "metaDataMap[" << upcase_string(field_name) << "] = new FieldMetaData(\""
+                  << field_name << "\", ";
+
+      // Set field requirement type (required, optional, etc.)
+      if (field->get_req() == t_field::T_REQUIRED) {
+        out << "TFieldRequirementType.REQUIRED, ";
+      } else if (field->get_req() == t_field::T_OPTIONAL) {
+        out << "TFieldRequirementType.OPTIONAL, ";
+      } else {
+        out << "TFieldRequirementType.DEFAULT, ";
+      }
+
+      // Create value meta data
+      generate_field_value_meta_data(out, field->get_type());
+      out << ");" << endl;
+    }
+    scope_down(out);
+  }
+}
+
+/**
+ * Returns a string with the as3 representation of the given thrift type
+ * (e.g. for the type struct it returns "TType.STRUCT")
+ */
+std::string t_as3_generator::get_as3_type_string(t_type* type) {
+  if (type->is_list()) {
+    return "TType.LIST";
+  } else if (type->is_map()) {
+    return "TType.MAP";
+  } else if (type->is_set()) {
+    return "TType.SET";
+  } else if (type->is_struct() || type->is_xception()) {
+    return "TType.STRUCT";
+  } else if (type->is_enum()) {
+    return "TType.I32";
+  } else if (type->is_typedef()) {
+    return get_as3_type_string(((t_typedef*)type)->get_type());
+  } else if (type->is_base_type()) {
+    switch (((t_base_type*)type)->get_base()) {
+    case t_base_type::TYPE_VOID:
+      return "TType.VOID";
+      break;
+    case t_base_type::TYPE_STRING:
+      return "TType.STRING";
+      break;
+    case t_base_type::TYPE_BOOL:
+      return "TType.BOOL";
+      break;
+    case t_base_type::TYPE_I8:
+      return "TType.BYTE";
+      break;
+    case t_base_type::TYPE_I16:
+      return "TType.I16";
+      break;
+    case t_base_type::TYPE_I32:
+      return "TType.I32";
+      break;
+    case t_base_type::TYPE_I64:
+      return "TType.I64";
+      break;
+    case t_base_type::TYPE_DOUBLE:
+      return "TType.DOUBLE";
+      break;
+    default:
+      throw std::runtime_error("Unknown thrift type \"" + type->get_name()
+                               + "\" passed to t_as3_generator::get_as3_type_string!");
+      break; // This should never happen!
+    }
+  } else {
+    throw std::runtime_error(
+        "Unknown thrift type \"" + type->get_name()
+        + "\" passed to t_as3_generator::get_as3_type_string!"); // This should never happen!
+  }
+}
+
+void t_as3_generator::generate_field_value_meta_data(std::ostream& out, t_type* type) {
+  out << endl;
+  indent_up();
+  indent_up();
+  if (type->is_struct() || type->is_xception()) {
+    indent(out) << "new StructMetaData(TType.STRUCT, " << type_name(type);
+  } else if (type->is_container()) {
+    if (type->is_list()) {
+      indent(out) << "new ListMetaData(TType.LIST, ";
+      t_type* elem_type = ((t_list*)type)->get_elem_type();
+      generate_field_value_meta_data(out, elem_type);
+    } else if (type->is_set()) {
+      indent(out) << "new SetMetaData(TType.SET, ";
+      t_type* elem_type = ((t_list*)type)->get_elem_type();
+      generate_field_value_meta_data(out, elem_type);
+    } else { // map
+      indent(out) << "new MapMetaData(TType.MAP, ";
+      t_type* key_type = ((t_map*)type)->get_key_type();
+      t_type* val_type = ((t_map*)type)->get_val_type();
+      generate_field_value_meta_data(out, key_type);
+      out << ", ";
+      generate_field_value_meta_data(out, val_type);
+    }
+  } else {
+    indent(out) << "new FieldValueMetaData(" << get_as3_type_string(type);
+  }
+  out << ")";
+  indent_down();
+  indent_down();
+}
+
+/**
+ * Generates a thrift service. In C++, this comprises an entirely separate
+ * header and source file. The header file defines the methods and includes
+ * the data types defined in the main header file, and the implementation
+ * file contains implementations of the basic printer and default interfaces.
+ *
+ * @param tservice The service definition
+ */
+void t_as3_generator::generate_service(t_service* tservice) {
+  // Make interface file
+  string f_service_name = package_dir_ + "/" + service_name_ + ".as";
+  f_service_.open(f_service_name.c_str());
+
+  f_service_ << autogen_comment() << as3_package();
+
+  scope_up(f_service_);
+
+  f_service_ << endl << as3_type_imports() << as3_thrift_imports()
+             << as3_thrift_gen_imports(tservice);
+
+  if (tservice->get_extends() != NULL) {
+    t_type* parent = tservice->get_extends();
+    string parent_namespace = parent->get_program()->get_namespace("as3");
+    if (!parent_namespace.empty() && parent_namespace != package_name_) {
+      f_service_ << "import " << type_name(parent) << ";" << endl;
+    }
+  }
+
+  f_service_ << endl;
+
+  generate_service_interface(tservice);
+
+  scope_down(f_service_);
+  f_service_.close();
+
+  // Now make the implementation/client file
+  f_service_name = package_dir_ + "/" + service_name_ + "Impl.as";
+  f_service_.open(f_service_name.c_str());
+
+  f_service_ << autogen_comment() << as3_package();
+
+  scope_up(f_service_);
+
+  f_service_ << endl << as3_type_imports() << as3_thrift_imports()
+             << as3_thrift_gen_imports(tservice);
+
+  if (tservice->get_extends() != NULL) {
+    t_type* parent = tservice->get_extends();
+    string parent_namespace = parent->get_program()->get_namespace("as3");
+    if (!parent_namespace.empty() && parent_namespace != package_name_) {
+      f_service_ << "import " << type_name(parent) << "Impl;" << endl;
+    }
+  }
+
+  f_service_ << endl;
+
+  generate_service_client(tservice);
+  scope_down(f_service_);
+
+  f_service_ << as3_type_imports();
+  f_service_ << as3_thrift_imports();
+  f_service_ << as3_thrift_gen_imports(tservice);
+  if (!package_name_.empty()) {
+    f_service_ << "import " << package_name_ << ".*;" << endl;
+  }
+
+  generate_service_helpers(tservice);
+
+  f_service_.close();
+
+  // Now make the processor/server file
+  f_service_name = package_dir_ + "/" + service_name_ + "Processor.as";
+  f_service_.open(f_service_name.c_str());
+
+  f_service_ << autogen_comment() << as3_package();
+
+  scope_up(f_service_);
+
+  f_service_ << endl << as3_type_imports() << as3_thrift_imports()
+             << as3_thrift_gen_imports(tservice) << endl;
+
+  generate_service_server(tservice);
+  scope_down(f_service_);
+
+  f_service_ << as3_type_imports();
+  f_service_ << as3_thrift_imports();
+  f_service_ << as3_thrift_gen_imports(tservice) << endl;
+  if (!package_name_.empty()) {
+    f_service_ << "import " << package_name_ << ".*;" << endl;
+  }
+
+  generate_service_helpers(tservice);
+
+  f_service_.close();
+}
+
+/**
+ * Generates a service interface definition.
+ *
+ * @param tservice The service to generate a header definition for
+ */
+void t_as3_generator::generate_service_interface(t_service* tservice) {
+  string extends_iface = "";
+  if (tservice->get_extends() != NULL) {
+    extends_iface = " extends " + tservice->get_extends()->get_name();
+  }
+
+  generate_as3_doc(f_service_, tservice);
+  f_service_ << indent() << "public interface " << service_name_ << extends_iface << " {" << endl
+             << endl;
+  indent_up();
+  vector<t_function*> functions = tservice->get_functions();
+  vector<t_function*>::iterator f_iter;
+  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
+    generate_as3_doc(f_service_, *f_iter);
+    if (!(*f_iter)->is_oneway()) {
+      if ((*f_iter)->get_returntype()->is_void()) {
+        indent(f_service_) << "//function onError(Error):void;" << endl;
+        indent(f_service_) << "//function onSuccess():void;" << endl;
+      } else {
+        indent(f_service_) << "//function onError(Error):void;" << endl;
+        indent(f_service_) << "//function onSuccess(" << type_name((*f_iter)->get_returntype())
+                           << "):void;" << endl;
+      }
+    }
+    indent(f_service_) << function_signature(*f_iter) << ";" << endl << endl;
+  }
+  indent_down();
+  f_service_ << indent() << "}" << endl << endl;
+}
+
+/**
+ * Generates structs for all the service args and return types
+ *
+ * @param tservice The service
+ */
+void t_as3_generator::generate_service_helpers(t_service* tservice) {
+  vector<t_function*> functions = tservice->get_functions();
+  vector<t_function*>::iterator f_iter;
+  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
+    t_struct* ts = (*f_iter)->get_arglist();
+    generate_as3_struct_definition(f_service_, ts, false, true);
+    generate_function_helpers(*f_iter);
+  }
+}
+
+/**
+ * Generates a service client definition.
+ *
+ * @param tservice The service to generate a server for.
+ */
+void t_as3_generator::generate_service_client(t_service* tservice) {
+  string extends = "";
+  string extends_client = "";
+  if (tservice->get_extends() != NULL) {
+    extends = tservice->get_extends()->get_name();
+    extends_client = " extends " + extends + "Impl";
+  }
+
+  indent(f_service_) << "public class " << service_name_ << "Impl" << extends_client
+                     << " implements " << service_name_ << " {" << endl;
+  indent_up();
+
+  indent(f_service_) << "public function " << service_name_ << "Impl"
+                     << "(iprot:TProtocol, oprot:TProtocol=null)" << endl;
+  scope_up(f_service_);
+  if (extends.empty()) {
+    f_service_ << indent() << "iprot_ = iprot;" << endl;
+    f_service_ << indent() << "if (oprot == null) {" << endl;
+    indent_up();
+    f_service_ << indent() << "oprot_ = iprot;" << endl;
+    indent_down();
+    f_service_ << indent() << "} else {" << endl;
+    indent_up();
+    f_service_ << indent() << "oprot_ = oprot;" << endl;
+    indent_down();
+    f_service_ << indent() << "}";
+  } else {
+    f_service_ << indent() << "super(iprot, oprot);" << endl;
+  }
+  scope_down(f_service_);
+  f_service_ << endl;
+
+  if (extends.empty()) {
+    f_service_ << indent() << "protected var iprot_:TProtocol;" << endl << indent()
+               << "protected var oprot_:TProtocol;" << endl << endl << indent()
+               << "protected var seqid_:int;" << endl << endl;
+
+    indent(f_service_) << "public function getInputProtocol():TProtocol" << endl;
+    scope_up(f_service_);
+    indent(f_service_) << "return this.iprot_;" << endl;
+    scope_down(f_service_);
+    f_service_ << endl;
+
+    indent(f_service_) << "public function getOutputProtocol():TProtocol" << endl;
+    scope_up(f_service_);
+    indent(f_service_) << "return this.oprot_;" << endl;
+    scope_down(f_service_);
+    f_service_ << endl;
+  }
+
+  // Generate client method implementations
+  vector<t_function*> functions = tservice->get_functions();
+  vector<t_function*>::const_iterator f_iter;
+  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
+    string funname = (*f_iter)->get_name();
+
+    // Open function
+    if (!(*f_iter)->is_oneway()) {
+      if ((*f_iter)->get_returntype()->is_void()) {
+        indent(f_service_) << "//function onError(Error):void;" << endl;
+        indent(f_service_) << "//function onSuccess():void;" << endl;
+      } else {
+        indent(f_service_) << "//function onError(Error):void;" << endl;
+        indent(f_service_) << "//function onSuccess(" << type_name((*f_iter)->get_returntype())
+                           << "):void;" << endl;
+      }
+    }
+    indent(f_service_) << "public " << function_signature(*f_iter) << endl;
+    scope_up(f_service_);
+
+    // Get the struct of function call params
+    t_struct* arg_struct = (*f_iter)->get_arglist();
+
+    string argsname = (*f_iter)->get_name() + "_args";
+    vector<t_field*>::const_iterator fld_iter;
+    const vector<t_field*>& fields = arg_struct->get_members();
+
+    // Serialize the request
+    f_service_ << indent() << "oprot_.writeMessageBegin(new TMessage(\"" << funname << "\", "
+               << ((*f_iter)->is_oneway() ? "TMessageType.ONEWAY" : "TMessageType.CALL")
+               << ", seqid_));" << endl << indent() << "var args:" << argsname << " = new "
+               << argsname << "();" << endl;
+
+    for (fld_iter = fields.begin(); fld_iter != fields.end(); ++fld_iter) {
+      f_service_ << indent() << "args." << (*fld_iter)->get_name() << " = "
+                 << (*fld_iter)->get_name() << ";" << endl;
+    }
+
+    f_service_ << indent() << "args.write(oprot_);" << endl << indent()
+               << "oprot_.writeMessageEnd();" << endl;
+
+    if ((*f_iter)->is_oneway()) {
+      f_service_ << indent() << "oprot_.getTransport().flush();" << endl;
+    } else {
+      f_service_ << indent() << "oprot_.getTransport().flush(function(error:Error):void {" << endl;
+      indent_up();
+      f_service_ << indent() << "try {" << endl;
+      indent_up();
+      string resultname = (*f_iter)->get_name() + "_result";
+      f_service_ << indent() << "if (error != null) {" << endl << indent()
+                 << "  if (onError != null) onError(error);" << endl << indent() << "  return;"
+                 << endl << indent() << "}" << endl << indent()
+                 << "var msg:TMessage = iprot_.readMessageBegin();" << endl << indent()
+                 << "if (msg.type == TMessageType.EXCEPTION) {" << endl << indent()
+                 << "  var x:TApplicationError = TApplicationError.read(iprot_);" << endl
+                 << indent() << "  iprot_.readMessageEnd();" << endl << indent()
+                 << "  if (onError != null) onError(x);" << endl << indent() << "  return;" << endl
+                 << indent() << "}" << endl << indent() << "var result :" << resultname << " = new "
+                 << resultname << "();" << endl << indent() << "result.read(iprot_);" << endl
+                 << indent() << "iprot_.readMessageEnd();" << endl;
+
+      // Careful, only return _result if not a void function
+      if (!(*f_iter)->get_returntype()->is_void()) {
+        f_service_ << indent() << "if (result." << generate_isset_check("success") << ") {" << endl
+                   << indent() << "  if (onSuccess != null) onSuccess(result.success);" << endl
+                   << indent() << "  return;" << endl << indent() << "}" << endl;
+      }
+
+      t_struct* xs = (*f_iter)->get_xceptions();
+      const std::vector<t_field*>& xceptions = xs->get_members();
+      vector<t_field*>::const_iterator x_iter;
+      for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) {
+        f_service_ << indent() << "if (result." << (*x_iter)->get_name() << " != null) {" << endl
+                   << indent() << "  if (onError != null) onError(result." << (*x_iter)->get_name()
+                   << ");" << endl << indent() << "  return;" << endl << indent() << "}" << endl;
+      }
+
+      // If you get here it's an exception, unless a void function
+      if ((*f_iter)->get_returntype()->is_void()) {
+        f_service_ << indent() << "if (onSuccess != null) onSuccess();" << endl << indent()
+                   << "return;" << endl;
+      } else {
+
+        f_service_ << indent() << "if (onError != null) onError(new "
+                                  "TApplicationError(TApplicationError.MISSING_RESULT, \""
+                   << (*f_iter)->get_name() << " failed: unknown result\"));" << endl;
+      }
+      indent_down();
+      f_service_ << indent() << "} catch (e:TError) {" << endl << indent()
+                 << "  if (onError != null) onError(e);" << endl << indent() << "}" << endl;
+
+      indent_down();
+      indent(f_service_) << "});" << endl;
+    }
+    // Close function
+    scope_down(f_service_);
+    f_service_ << endl;
+  }
+
+  indent_down();
+  indent(f_service_) << "}" << endl;
+}
+
+/**
+ * Generates a service server definition.
+ *
+ * @param tservice The service to generate a server for.
+ */
+void t_as3_generator::generate_service_server(t_service* tservice) {
+  // Generate the dispatch methods
+  vector<t_function*> functions = tservice->get_functions();
+  vector<t_function*>::iterator f_iter;
+
+  // Extends stuff
+  string extends = "";
+  string extends_processor = "";
+  if (tservice->get_extends() != NULL) {
+    extends = type_name(tservice->get_extends());
+    extends_processor = " extends " + extends + "Processor";
+  }
+
+  // Generate the header portion
+  indent(f_service_) << "public class " << service_name_ << "Processor" << extends_processor
+                     << " implements TProcessor {" << endl;
+  indent_up();
+
+  indent(f_service_) << "public function " << service_name_ << "Processor(iface:" << service_name_
+                     << ")" << endl;
+  scope_up(f_service_);
+  if (!extends.empty()) {
+    f_service_ << indent() << "super(iface);" << endl;
+  }
+  f_service_ << indent() << "iface_ = iface;" << endl;
+
+  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
+    f_service_ << indent() << "PROCESS_MAP[\"" << (*f_iter)->get_name()
+               << "\"] = " << (*f_iter)->get_name() << "();" << endl;
+  }
+
+  scope_down(f_service_);
+  f_service_ << endl;
+
+  f_service_ << indent() << "private var iface_:" << service_name_ << ";" << endl;
+
+  if (extends.empty()) {
+    f_service_ << indent() << "protected const PROCESS_MAP:Dictionary = new Dictionary();" << endl;
+  }
+
+  f_service_ << endl;
+
+  // Generate the server implementation
+  string override = "";
+  if (tservice->get_extends() != NULL) {
+    override = "override ";
+  }
+  indent(f_service_) << override
+                     << "public function process(iprot:TProtocol, oprot:TProtocol):Boolean" << endl;
+  scope_up(f_service_);
+
+  f_service_ << indent() << "var msg:TMessage = iprot.readMessageBegin();" << endl;
+
+  // TODO(mcslee): validate message, was the seqid etc. legit?
+  // AS- If all method is oneway:
+  // do you have an oprot?
+  // do you you need nullcheck?
+  f_service_
+      << indent() << "var fn:Function = PROCESS_MAP[msg.name];" << endl << indent()
+      << "if (fn == null) {" << endl << indent() << "  TProtocolUtil.skip(iprot, TType.STRUCT);"
+      << endl << indent() << "  iprot.readMessageEnd();" << endl << indent()
+      << "  var x:TApplicationError = new TApplicationError(TApplicationError.UNKNOWN_METHOD, "
+         "\"Invalid method name: '\"+msg.name+\"'\");" << endl << indent()
+      << "  oprot.writeMessageBegin(new TMessage(msg.name, TMessageType.EXCEPTION, msg.seqid));"
+      << endl << indent() << "  x.write(oprot);" << endl << indent() << "  oprot.writeMessageEnd();"
+      << endl << indent() << "  oprot.getTransport().flush();" << endl << indent()
+      << "  return true;" << endl << indent() << "}" << endl << indent()
+      << "fn.call(this,msg.seqid, iprot, oprot);" << endl;
+
+  f_service_ << indent() << "return true;" << endl;
+
+  scope_down(f_service_);
+  f_service_ << endl;
+
+  // Generate the process subfunctions
+  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
+    generate_process_function(tservice, *f_iter);
+  }
+
+  indent_down();
+  indent(f_service_) << "}" << endl << endl;
+}
+
+/**
+ * Generates a struct and helpers for a function.
+ *
+ * @param tfunction The function
+ */
+void t_as3_generator::generate_function_helpers(t_function* tfunction) {
+  if (tfunction->is_oneway()) {
+    return;
+  }
+
+  t_struct result(program_, tfunction->get_name() + "_result");
+  t_field success(tfunction->get_returntype(), "success", 0);
+  if (!tfunction->get_returntype()->is_void()) {
+    result.append(&success);
+  }
+
+  t_struct* xs = tfunction->get_xceptions();
+  const vector<t_field*>& fields = xs->get_members();
+  vector<t_field*>::const_iterator f_iter;
+  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+    result.append(*f_iter);
+  }
+
+  generate_as3_struct_definition(f_service_, &result, false, true, true);
+}
+
+/**
+ * Generates a process function definition.
+ *
+ * @param tfunction The function to write a dispatcher for
+ */
+void t_as3_generator::generate_process_function(t_service* tservice, t_function* tfunction) {
+  (void)tservice;
+  // Open class
+  indent(f_service_) << "private function " << tfunction->get_name() << "():Function {" << endl;
+  indent_up();
+
+  // Open function
+  indent(f_service_) << "return function(seqid:int, iprot:TProtocol, oprot:TProtocol):void" << endl;
+  scope_up(f_service_);
+
+  string argsname = tfunction->get_name() + "_args";
+  string resultname = tfunction->get_name() + "_result";
+
+  f_service_ << indent() << "var args:" << argsname << " = new " << argsname << "();" << endl
+             << indent() << "args.read(iprot);" << endl << indent() << "iprot.readMessageEnd();"
+             << endl;
+
+  t_struct* xs = tfunction->get_xceptions();
+  const std::vector<t_field*>& xceptions = xs->get_members();
+  vector<t_field*>::const_iterator x_iter;
+
+  // Declare result for non oneway function
+  if (!tfunction->is_oneway()) {
+    f_service_ << indent() << "var result:" << resultname << " = new " << resultname << "();"
+               << endl;
+  }
+
+  // Try block for a function with exceptions
+  if (xceptions.size() > 0) {
+    f_service_ << indent() << "try {" << endl;
+    indent_up();
+  }
+
+  // Generate the function call
+  t_struct* arg_struct = tfunction->get_arglist();
+  const std::vector<t_field*>& fields = arg_struct->get_members();
+  vector<t_field*>::const_iterator f_iter;
+
+  f_service_ << indent();
+  if (tfunction->is_oneway()) {
+    f_service_ << "iface_." << tfunction->get_name() << "(";
+    bool first = true;
+    for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+      if (first) {
+        first = false;
+      } else {
+        f_service_ << ", ";
+      }
+      f_service_ << "args." << (*f_iter)->get_name();
+    }
+    f_service_ << ");" << endl;
+  } else {
+    f_service_ << "// sorry this operation is not supported yet" << endl;
+    f_service_ << indent() << "throw new Error(\"This is not yet supported\");" << endl;
+  }
+
+  // Set isset on success field
+  if (!tfunction->is_oneway() && !tfunction->get_returntype()->is_void()
+      && !type_can_be_null(tfunction->get_returntype())) {
+    f_service_ << indent() << "result.set" << get_cap_name("success") << get_cap_name("isSet")
+               << "(true);" << endl;
+  }
+
+  if (!tfunction->is_oneway() && xceptions.size() > 0) {
+    indent_down();
+    f_service_ << indent() << "}";
+    for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) {
+      f_service_ << " catch (" << (*x_iter)->get_name() << ":"
+                 << type_name((*x_iter)->get_type(), false, false) << ") {" << endl;
+      if (!tfunction->is_oneway()) {
+        indent_up();
+        f_service_ << indent() << "result." << (*x_iter)->get_name() << " = "
+                   << (*x_iter)->get_name() << ";" << endl;
+        indent_down();
+        f_service_ << indent() << "}";
+      } else {
+        f_service_ << "}";
+      }
+    }
+    f_service_ << " catch (th:Error) {" << endl;
+    indent_up();
+    f_service_ << indent() << "trace(\"Internal error processing " << tfunction->get_name()
+               << "\", th);" << endl << indent()
+               << "var x:TApplicationError = new "
+                  "TApplicationError(TApplicationError.INTERNAL_ERROR, \"Internal error processing "
+               << tfunction->get_name() << "\");" << endl << indent()
+               << "oprot.writeMessageBegin(new TMessage(\"" << tfunction->get_name()
+               << "\", TMessageType.EXCEPTION, seqid));" << endl << indent() << "x.write(oprot);"
+               << endl << indent() << "oprot.writeMessageEnd();" << endl << indent()
+               << "oprot.getTransport().flush();" << endl << indent() << "return;" << endl;
+    indent_down();
+    f_service_ << indent() << "}" << endl;
+  }
+
+  // Shortcut out here for oneway functions
+  if (tfunction->is_oneway()) {
+    f_service_ << indent() << "return;" << endl;
+    scope_down(f_service_);
+
+    // Close class
+    indent_down();
+    f_service_ << indent() << "}" << endl << endl;
+    return;
+  }
+
+  f_service_ << indent() << "oprot.writeMessageBegin(new TMessage(\"" << tfunction->get_name()
+             << "\", TMessageType.REPLY, seqid));" << endl << indent() << "result.write(oprot);"
+             << endl << indent() << "oprot.writeMessageEnd();" << endl << indent()
+             << "oprot.getTransport().flush();" << endl;
+
+  // Close function
+  scope_down(f_service_);
+  f_service_ << endl;
+
+  // Close class
+  indent_down();
+  f_service_ << indent() << "}" << endl << endl;
+}
+
+/**
+ * Deserializes a field of any type.
+ *
+ * @param tfield The field
+ * @param prefix The variable name or container for this field
+ */
+void t_as3_generator::generate_deserialize_field(ostream& out, t_field* tfield, string prefix) {
+  t_type* type = get_true_type(tfield->get_type());
+
+  if (type->is_void()) {
+    throw "CANNOT GENERATE DESERIALIZE CODE FOR void TYPE: " + prefix + tfield->get_name();
+  }
+
+  string name = prefix + tfield->get_name();
+
+  if (type->is_struct() || type->is_xception()) {
+    generate_deserialize_struct(out, (t_struct*)type, name);
+  } else if (type->is_container()) {
+    generate_deserialize_container(out, type, name);
+  } else if (type->is_base_type() || type->is_enum()) {
+
+    indent(out) << name << " = iprot.";
+
+    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:
+        throw "compiler error: cannot serialize void field in a struct: " + name;
+        break;
+      case t_base_type::TYPE_STRING:
+        if (type->is_binary()) {
+          out << "readBinary();";
+        } else {
+          out << "readString();";
+        }
+        break;
+      case t_base_type::TYPE_BOOL:
+        out << "readBool();";
+        break;
+      case t_base_type::TYPE_I8:
+        out << "readByte();";
+        break;
+      case t_base_type::TYPE_I16:
+        out << "readI16();";
+        break;
+      case t_base_type::TYPE_I32:
+        out << "readI32();";
+        break;
+      case t_base_type::TYPE_I64:
+        out << "readI64();";
+        break;
+      case t_base_type::TYPE_DOUBLE:
+        out << "readDouble();";
+        break;
+      default:
+        throw "compiler error: no As3 name for base type " + t_base_type::t_base_name(tbase);
+      }
+    } else if (type->is_enum()) {
+      out << "readI32();";
+    }
+    out << endl;
+  } else {
+    printf("DO NOT KNOW HOW TO DESERIALIZE FIELD '%s' TYPE '%s'\n",
+           tfield->get_name().c_str(),
+           type_name(type).c_str());
+  }
+}
+
+/**
+ * Generates an unserializer for a struct, invokes read()
+ */
+void t_as3_generator::generate_deserialize_struct(ostream& out, t_struct* tstruct, string prefix) {
+  out << indent() << prefix << " = new " << type_name(tstruct) << "();" << endl << indent()
+      << prefix << ".read(iprot);" << endl;
+}
+
+/**
+ * Deserializes a container by reading its size and then iterating
+ */
+void t_as3_generator::generate_deserialize_container(ostream& out, t_type* ttype, string prefix) {
+  scope_up(out);
+
+  string obj;
+
+  if (ttype->is_map()) {
+    obj = tmp("_map");
+  } else if (ttype->is_set()) {
+    obj = tmp("_set");
+  } else if (ttype->is_list()) {
+    obj = tmp("_list");
+  }
+
+  // Declare variables, read header
+  if (ttype->is_map()) {
+    indent(out) << "var " << obj << ":TMap = iprot.readMapBegin();" << endl;
+  } else if (ttype->is_set()) {
+    indent(out) << "var " << obj << ":TSet = iprot.readSetBegin();" << endl;
+  } else if (ttype->is_list()) {
+    indent(out) << "var " << obj << ":TList = iprot.readListBegin();" << endl;
+  }
+
+  indent(out) << prefix << " = new " << type_name(ttype, false, true)
+              // size the collection correctly
+              << "("
+              << ");" << endl;
+
+  // For loop iterates over elements
+  string i = tmp("_i");
+  indent(out) << "for (var " << i << ":int = 0; " << i << " < " << obj << ".size"
+              << "; "
+              << "++" << i << ")" << endl;
+
+  scope_up(out);
+
+  if (ttype->is_map()) {
+    generate_deserialize_map_element(out, (t_map*)ttype, prefix);
+  } else if (ttype->is_set()) {
+    generate_deserialize_set_element(out, (t_set*)ttype, prefix);
+  } else if (ttype->is_list()) {
+    generate_deserialize_list_element(out, (t_list*)ttype, prefix);
+  }
+
+  scope_down(out);
+
+  // Read container end
+  if (ttype->is_map()) {
+    indent(out) << "iprot.readMapEnd();" << endl;
+  } else if (ttype->is_set()) {
+    indent(out) << "iprot.readSetEnd();" << endl;
+  } else if (ttype->is_list()) {
+    indent(out) << "iprot.readListEnd();" << endl;
+  }
+
+  scope_down(out);
+}
+
+/**
+ * Generates code to deserialize a map
+ */
+void t_as3_generator::generate_deserialize_map_element(ostream& out, t_map* tmap, string prefix) {
+  string key = tmp("_key");
+  string val = tmp("_val");
+  t_field fkey(tmap->get_key_type(), key);
+  t_field fval(tmap->get_val_type(), val);
+
+  indent(out) << declare_field(&fkey) << endl;
+  indent(out) << declare_field(&fval) << endl;
+
+  generate_deserialize_field(out, &fkey);
+  generate_deserialize_field(out, &fval);
+
+  indent(out) << prefix << "[" << key << "] = " << val << ";" << endl;
+}
+
+/**
+ * Deserializes a set element
+ */
+void t_as3_generator::generate_deserialize_set_element(ostream& out, t_set* tset, string prefix) {
+  string elem = tmp("_elem");
+  t_field felem(tset->get_elem_type(), elem);
+
+  indent(out) << declare_field(&felem) << endl;
+
+  generate_deserialize_field(out, &felem);
+
+  indent(out) << prefix << ".add(" << elem << ");" << endl;
+}
+
+/**
+ * Deserializes a list element
+ */
+void t_as3_generator::generate_deserialize_list_element(ostream& out,
+                                                        t_list* tlist,
+                                                        string prefix) {
+  string elem = tmp("_elem");
+  t_field felem(tlist->get_elem_type(), elem);
+
+  indent(out) << declare_field(&felem) << endl;
+
+  generate_deserialize_field(out, &felem);
+
+  indent(out) << prefix << ".push(" << elem << ");" << endl;
+}
+
+/**
+ * Serializes a field of any type.
+ *
+ * @param tfield The field to serialize
+ * @param prefix Name to prepend to field name
+ */
+void t_as3_generator::generate_serialize_field(ostream& out, t_field* tfield, string prefix) {
+  t_type* type = get_true_type(tfield->get_type());
+
+  // Do nothing for void types
+  if (type->is_void()) {
+    throw "CANNOT GENERATE SERIALIZE CODE FOR void TYPE: " + prefix + tfield->get_name();
+  }
+
+  if (type->is_struct() || type->is_xception()) {
+    generate_serialize_struct(out, (t_struct*)type, prefix + tfield->get_name());
+  } else if (type->is_container()) {
+    generate_serialize_container(out, type, prefix + tfield->get_name());
+  } else if (type->is_base_type() || type->is_enum()) {
+
+    string name = prefix + tfield->get_name();
+    indent(out) << "oprot.";
+
+    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:
+        throw "compiler error: cannot serialize void field in a struct: " + name;
+        break;
+      case t_base_type::TYPE_STRING:
+        if (type->is_binary()) {
+          out << "writeBinary(" << name << ");";
+        } else {
+          out << "writeString(" << name << ");";
+        }
+        break;
+      case t_base_type::TYPE_BOOL:
+        out << "writeBool(" << name << ");";
+        break;
+      case t_base_type::TYPE_I8:
+        out << "writeByte(" << name << ");";
+        break;
+      case t_base_type::TYPE_I16:
+        out << "writeI16(" << name << ");";
+        break;
+      case t_base_type::TYPE_I32:
+        out << "writeI32(" << name << ");";
+        break;
+      case t_base_type::TYPE_I64:
+        out << "writeI64(" << name << ");";
+        break;
+      case t_base_type::TYPE_DOUBLE:
+        out << "writeDouble(" << name << ");";
+        break;
+      default:
+        throw "compiler error: no As3 name for base type " + t_base_type::t_base_name(tbase);
+      }
+    } else if (type->is_enum()) {
+      out << "writeI32(" << name << ");";
+    }
+    out << endl;
+  } else {
+    printf("DO NOT KNOW HOW TO SERIALIZE FIELD '%s%s' TYPE '%s'\n",
+           prefix.c_str(),
+           tfield->get_name().c_str(),
+           type_name(type).c_str());
+  }
+}
+
+/**
+ * Serializes all the members of a struct.
+ *
+ * @param tstruct The struct to serialize
+ * @param prefix  String prefix to attach to all fields
+ */
+void t_as3_generator::generate_serialize_struct(ostream& out, t_struct* tstruct, string prefix) {
+  (void)tstruct;
+  out << indent() << prefix << ".write(oprot);" << endl;
+}
+
+/**
+ * Serializes a container by writing its size then the elements.
+ *
+ * @param ttype  The type of container
+ * @param prefix String prefix for fields
+ */
+void t_as3_generator::generate_serialize_container(ostream& out, t_type* ttype, string prefix) {
+  scope_up(out);
+
+  if (ttype->is_map()) {
+    string iter = tmp("_key");
+    string counter = tmp("_sizeCounter");
+    indent(out) << "var " << counter << ":int = 0;" << endl;
+    indent(out) << "for (var " << iter << ":* in " << prefix << ") {" << endl;
+    indent(out) << "  " << counter << +"++;" << endl;
+    indent(out) << "}" << endl;
+
+    indent(out) << "oprot.writeMapBegin(new TMap(" << type_to_enum(((t_map*)ttype)->get_key_type())
+                << ", " << type_to_enum(((t_map*)ttype)->get_val_type()) << ", " << counter << "));"
+                << endl;
+  } else if (ttype->is_set()) {
+    indent(out) << "oprot.writeSetBegin(new TSet(" << type_to_enum(((t_set*)ttype)->get_elem_type())
+                << ", " << prefix << ".size));" << endl;
+  } else if (ttype->is_list()) {
+    indent(out) << "oprot.writeListBegin(new TList("
+                << type_to_enum(((t_list*)ttype)->get_elem_type()) << ", " << prefix << ".length));"
+                << endl;
+  }
+
+  string iter = tmp("elem");
+  if (ttype->is_map()) {
+    indent(out) << "for (var " << iter << ":* in " << prefix << ")";
+  } else if (ttype->is_set()) {
+    indent(out) << "for each (var " << iter << ":* in " << prefix << ".toArray())";
+  } else if (ttype->is_list()) {
+    indent(out) << "for each (var " << iter << ":* in " << prefix << ")";
+  }
+
+  scope_up(out);
+
+  if (ttype->is_map()) {
+    generate_serialize_map_element(out, (t_map*)ttype, iter, prefix);
+  } else if (ttype->is_set()) {
+    generate_serialize_set_element(out, (t_set*)ttype, iter);
+  } else if (ttype->is_list()) {
+    generate_serialize_list_element(out, (t_list*)ttype, iter);
+  }
+
+  scope_down(out);
+
+  if (ttype->is_map()) {
+    indent(out) << "oprot.writeMapEnd();" << endl;
+  } else if (ttype->is_set()) {
+    indent(out) << "oprot.writeSetEnd();" << endl;
+  } else if (ttype->is_list()) {
+    indent(out) << "oprot.writeListEnd();" << endl;
+  }
+
+  scope_down(out);
+}
+
+/**
+ * Serializes the members of a map.
+ */
+void t_as3_generator::generate_serialize_map_element(ostream& out,
+                                                     t_map* tmap,
+                                                     string iter,
+                                                     string map) {
+  t_field kfield(tmap->get_key_type(), iter);
+  generate_serialize_field(out, &kfield, "");
+  t_field vfield(tmap->get_val_type(), map + "[" + iter + "]");
+  generate_serialize_field(out, &vfield, "");
+}
+
+/**
+ * Serializes the members of a set.
+ */
+void t_as3_generator::generate_serialize_set_element(ostream& out, t_set* tset, string iter) {
+  t_field efield(tset->get_elem_type(), iter);
+  generate_serialize_field(out, &efield, "");
+}
+
+/**
+ * Serializes the members of a list.
+ */
+void t_as3_generator::generate_serialize_list_element(ostream& out, t_list* tlist, string iter) {
+  t_field efield(tlist->get_elem_type(), iter);
+  generate_serialize_field(out, &efield, "");
+}
+
+/**
+ * Returns a As3 type name
+ *
+ * @param ttype The type
+ * @param container Is the type going inside a container?
+ * @return As3 type name, i.e. HashMap<Key,Value>
+ */
+string t_as3_generator::type_name(t_type* ttype, bool in_container, bool in_init) {
+  (void)in_init;
+  // In As3 typedefs are just resolved to their real type
+  ttype = get_true_type(ttype);
+  string prefix;
+
+  if (ttype->is_base_type()) {
+    return base_type_name((t_base_type*)ttype, in_container);
+  } else if (ttype->is_enum()) {
+    return "int";
+  } else if (ttype->is_map()) {
+    return "Dictionary";
+  } else if (ttype->is_set()) {
+    return "Set";
+  } else if (ttype->is_list()) {
+    return "Array";
+  }
+
+  // Check for namespacing
+  t_program* program = ttype->get_program();
+  if (program != NULL && program != program_) {
+    string package = program->get_namespace("as3");
+    if (!package.empty()) {
+      return package + "." + ttype->get_name();
+    }
+  }
+
+  return ttype->get_name();
+}
+
+/**
+ * Returns the AS3 type that corresponds to the thrift type.
+ *
+ * @param tbase The base type
+ * @param container Is it going in a As3 container?
+ */
+string t_as3_generator::base_type_name(t_base_type* type, bool in_container) {
+  (void)in_container;
+  t_base_type::t_base tbase = type->get_base();
+
+  switch (tbase) {
+  case t_base_type::TYPE_VOID:
+    return "void";
+  case t_base_type::TYPE_STRING:
+    if (type->is_binary()) {
+      return "ByteArray";
+    } else {
+      return "String";
+    }
+  case t_base_type::TYPE_BOOL:
+    return "Boolean";
+  case t_base_type::TYPE_I8:
+  case t_base_type::TYPE_I16:
+  case t_base_type::TYPE_I32:
+    return "int";
+  case t_base_type::TYPE_I64:
+    throw "i64 is not yet supported in as3";
+  case t_base_type::TYPE_DOUBLE:
+    return "Number";
+  default:
+    throw "compiler error: no As3 name for base type " + t_base_type::t_base_name(tbase);
+  }
+}
+
+/**
+ * Declares a field, which may include initialization as necessary.
+ *
+ * @param ttype The type
+ */
+string t_as3_generator::declare_field(t_field* tfield, bool init) {
+  // TODO(mcslee): do we ever need to initialize the field?
+  string result = "var " + tfield->get_name() + ":" + type_name(tfield->get_type());
+  if (init) {
+    t_type* ttype = get_true_type(tfield->get_type());
+    if (ttype->is_base_type() && tfield->get_value() != NULL) {
+      std::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 += " = null";
+        break;
+      case t_base_type::TYPE_BOOL:
+        result += " = false";
+        break;
+      case t_base_type::TYPE_I8:
+      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 += " = (double)0";
+        break;
+      }
+
+    } else if (ttype->is_enum()) {
+      result += " = 0";
+    } else if (ttype->is_container()) {
+      result += " = new " + type_name(ttype, false, true) + "()";
+    } else {
+      result += " = new " + type_name(ttype, false, true) + "()";
+      ;
+    }
+  }
+  return result + ";";
+}
+
+/**
+ * Renders a function signature of the form 'type name(args)'
+ *
+ * @param tfunction Function definition
+ * @return String of rendered function definition
+ */
+string t_as3_generator::function_signature(t_function* tfunction, string prefix) {
+  std::string arguments = argument_list(tfunction->get_arglist());
+  if (!tfunction->is_oneway()) {
+    if (arguments != "") {
+      arguments += ", ";
+    }
+    arguments += "onError:Function, onSuccess:Function";
+  }
+
+  std::string result = "function " + prefix + tfunction->get_name() + "(" + arguments + "):void";
+  return result;
+}
+
+/**
+ * Renders a comma separated field list, with type names
+ */
+string t_as3_generator::argument_list(t_struct* tstruct) {
+  string result = "";
+
+  const vector<t_field*>& fields = tstruct->get_members();
+  vector<t_field*>::const_iterator f_iter;
+  bool first = true;
+  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+    if (first) {
+      first = false;
+    } else {
+      result += ", ";
+    }
+    result += (*f_iter)->get_name() + ":" + type_name((*f_iter)->get_type());
+  }
+  return result;
+}
+
+/**
+ * Converts the parse type to a C++ enum string for the given type.
+ */
+string t_as3_generator::type_to_enum(t_type* type) {
+  type = get_true_type(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:
+      throw "NO T_VOID CONSTRUCT";
+    case t_base_type::TYPE_STRING:
+      return "TType.STRING";
+    case t_base_type::TYPE_BOOL:
+      return "TType.BOOL";
+    case t_base_type::TYPE_I8:
+      return "TType.BYTE";
+    case t_base_type::TYPE_I16:
+      return "TType.I16";
+    case t_base_type::TYPE_I32:
+      return "TType.I32";
+    case t_base_type::TYPE_I64:
+      return "TType.I64";
+    case t_base_type::TYPE_DOUBLE:
+      return "TType.DOUBLE";
+    }
+  } else if (type->is_enum()) {
+    return "TType.I32";
+  } else if (type->is_struct() || type->is_xception()) {
+    return "TType.STRUCT";
+  } else if (type->is_map()) {
+    return "TType.MAP";
+  } else if (type->is_set()) {
+    return "TType.SET";
+  } else if (type->is_list()) {
+    return "TType.LIST";
+  }
+
+  throw "INVALID TYPE IN type_to_enum: " + type->get_name();
+}
+
+/**
+ * Applies the correct style to a string based on the value of nocamel_style_
+ */
+std::string t_as3_generator::get_cap_name(std::string name) {
+  name[0] = toupper(name[0]);
+  return name;
+}
+
+string t_as3_generator::constant_name(string name) {
+  string constant_name;
+
+  bool is_first = true;
+  bool was_previous_char_upper = false;
+  for (string::iterator iter = name.begin(); iter != name.end(); ++iter) {
+    string::value_type character = (*iter);
+
+    bool is_upper = isupper(character);
+
+    if (is_upper && !is_first && !was_previous_char_upper) {
+      constant_name += '_';
+    }
+    constant_name += toupper(character);
+
+    is_first = false;
+    was_previous_char_upper = is_upper;
+  }
+
+  return constant_name;
+}
+
+/**
+ * Emits a As3Doc comment if the provided object has a doc in Thrift
+ */
+void t_as3_generator::generate_as3_doc(ostream& out, t_doc* tdoc) {
+  if (tdoc->has_doc()) {
+    generate_docstring_comment(out, "/**\n", " * ", tdoc->get_doc(), " */\n");
+  }
+}
+
+/**
+ * Emits a As3Doc comment if the provided function object has a doc in Thrift
+ */
+void t_as3_generator::generate_as3_doc(ostream& out, t_function* tfunction) {
+  if (tfunction->has_doc()) {
+    stringstream ss;
+    ss << tfunction->get_doc();
+    const vector<t_field*>& fields = tfunction->get_arglist()->get_members();
+    vector<t_field*>::const_iterator p_iter;
+    for (p_iter = fields.begin(); p_iter != fields.end(); ++p_iter) {
+      t_field* p = *p_iter;
+      ss << "\n@param " << p->get_name();
+      if (p->has_doc()) {
+        ss << " " << p->get_doc();
+      }
+    }
+    generate_docstring_comment(out, "/**\n", " * ", ss.str(), " */\n");
+  }
+}
+
+std::string t_as3_generator::generate_isset_check(t_field* field) {
+  return generate_isset_check(field->get_name());
+}
+
+std::string t_as3_generator::generate_isset_check(std::string field_name) {
+  return "is" + get_cap_name("set") + get_cap_name(field_name) + "()";
+}
+
+void t_as3_generator::generate_isset_set(ostream& out, t_field* field) {
+  if (!type_can_be_null(field->get_type())) {
+    indent(out) << "this.__isset_" << field->get_name() << " = true;" << endl;
+  }
+}
+
+std::string t_as3_generator::get_enum_class_name(t_type* type) {
+  string package = "";
+  t_program* program = type->get_program();
+  if (program != NULL && program != program_) {
+    package = program->get_namespace("as3") + ".";
+  }
+  return package + type->get_name();
+}
+
+THRIFT_REGISTER_GENERATOR(
+    as3,
+    "AS3",
+    "    bindable:        Add [bindable] metadata to all the struct classes.\n")

+ 4562 - 4562
contrib/restricted/thrift/compiler/thrift/generate/t_c_glib_generator.cc

@@ -1,4562 +1,4562 @@
-/* 
- * Licensed to the Apache Software Foundation (ASF) under one 
- * or more contributor license agreements. See the NOTICE file 
- * distributed with this work for additional information 
- * regarding copyright ownership. The ASF licenses this file 
- * to you under the Apache License, Version 2.0 (the 
- * "License"); you may not use this file except in compliance 
- * with the License. You may obtain a copy of the License at 
- * 
- *   http://www.apache.org/licenses/LICENSE-2.0 
- * 
- * Unless required by applicable law or agreed to in writing, 
- * software distributed under the License is distributed on an 
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 
- * KIND, either express or implied. See the License for the 
- * specific language governing permissions and limitations 
- * under the License. 
- * 
- * Contains some contributions under the Thrift Software License. 
- * Please see doc/old-thrift-license.txt in the Thrift distribution for 
- * details. 
- */ 
- 
-#include <fstream> 
-#include <iostream> 
-#include <stdexcept> 
-#include <string> 
-#include <vector> 
- 
-#include <ctype.h> 
- 
-#include "thrift/platform.h" 
-#include "thrift/generate/t_oop_generator.h" 
- 
-using std::map; 
-using std::ostream; 
-using std::ostringstream; 
-using std::string; 
-using std::stringstream; 
-using std::vector; 
- 
-static const string endl = "\n"; // avoid ostream << std::endl flushes 
- 
-/* forward declarations */ 
-string initial_caps_to_underscores(string name); 
-string underscores_to_initial_caps(string name); 
-string to_upper_case(string name); 
-string to_lower_case(string name); 
- 
-/** 
- * C code generator, using glib for C typing. 
- */ 
-class t_c_glib_generator : public t_oop_generator { 
-public: 
-  /* constructor */ 
-  t_c_glib_generator(t_program* program, 
-                     const map<string, string>& parsed_options, 
-                     const string& option_string) 
-    : t_oop_generator(program) { 
-    (void)option_string; 
-    std::map<std::string, std::string>::const_iterator iter; 
- 
-    /* set the output directory */ 
-    this->out_dir_base_ = "gen-c_glib"; 
- 
-    /* no options yet */ 
-    for( iter = parsed_options.begin(); iter != parsed_options.end(); ++iter) { 
-      throw "unknown option c_glib:" + iter->first; 
-    } 
- 
-    /* set the namespace */ 
-    this->nspace = program_->get_namespace("c_glib"); 
- 
-    if (this->nspace.empty()) { 
-      this->nspace = ""; 
-      this->nspace_u = ""; 
-      this->nspace_uc = ""; 
-      this->nspace_lc = ""; 
-    } else { 
-      /* replace dots with underscores */ 
-      char* tmp = strdup(this->nspace.c_str()); 
-      for (unsigned int i = 0; i < strlen(tmp); i++) { 
-        if (tmp[i] == '.') { 
-          tmp[i] = '_'; 
-        } 
-      } 
-      this->nspace = string(tmp, strlen(tmp)); 
-      free(tmp); 
- 
-      /* clean up the namespace for C. 
-       * An input of 'namespace foo' should result in: 
-       *  - nspace = foo       - for thrift objects and typedefs 
-       *  - nspace_u = Foo     - for internal GObject prefixes 
-       *  - nspace_uc = FOO_   - for macro prefixes 
-       *  - nspace_lc = foo_   - for filename and method prefixes 
-       * The underscores are there since uc and lc strings are used as file and 
-       * variable prefixes. 
-       */ 
-      this->nspace_u = initial_caps_to_underscores(this->nspace); 
-      this->nspace_uc = to_upper_case(this->nspace_u) + "_"; 
-      this->nspace_lc = to_lower_case(this->nspace_u) + "_"; 
-    } 
-  } 
- 
-  /* initialization and destruction */ 
-  void init_generator(); 
-  void close_generator(); 
- 
-  /* generation functions */ 
-  void generate_typedef(t_typedef* ttypedef); 
-  void generate_enum(t_enum* tenum); 
-  void generate_consts(vector<t_const*> consts); 
-  void generate_struct(t_struct* tstruct); 
-  void generate_service(t_service* tservice); 
-  void generate_xception(t_struct* tstruct); 
- 
-private: 
-  /* file streams */ 
-  ofstream_with_content_based_conditional_update f_types_; 
-  ofstream_with_content_based_conditional_update f_types_impl_; 
-  ofstream_with_content_based_conditional_update f_header_; 
-  ofstream_with_content_based_conditional_update f_service_; 
- 
-  /* namespace variables */ 
-  string nspace; 
-  string nspace_u; 
-  string nspace_uc; 
-  string nspace_lc; 
- 
-  /* helper functions */ 
-  bool is_complex_type(t_type* ttype); 
-  bool is_numeric(t_type* ttype); 
-  string type_name(t_type* ttype, bool in_typedef = false, bool is_const = false); 
-  string property_type_name(t_type* ttype, bool in_typedef = false, bool is_const = false); 
-  string base_type_name(t_type* type); 
-  string type_to_enum(t_type* type); 
-  string constant_literal(t_type* type, t_const_value* value); 
-  string constant_value(string name, t_type* type, t_const_value* value); 
-  string constant_value_with_storage(string name, t_type* type, t_const_value* value); 
-  string function_signature(t_function* tfunction); 
-  string argument_list(t_struct* tstruct); 
-  string xception_list(t_struct* tstruct); 
-  string declare_field(t_field* tfield, 
-                       bool init = false, 
-                       bool pointer = false, 
-                       bool constant = false, 
-                       bool reference = false); 
-  void declare_local_variable(ostream& out, t_type* ttype, string& base_name, bool for_hash_table); 
-  void declore_local_variable_for_write(ostream& out, t_type* ttype, string& base_name); 
- 
-  /* generation functions */ 
-  void generate_const_initializer(string name, 
-                                  t_type* type, 
-                                  t_const_value* value, 
-                                  bool top_level = false); 
-  void generate_service_helpers(t_service* tservice); 
-  void generate_service_client(t_service* tservice); 
-  void generate_service_handler(t_service* tservice); 
-  void generate_service_processor(t_service* tservice); 
-  void generate_service_server(t_service* tservice); 
-  void generate_object(t_struct* tstruct); 
-  void generate_struct_writer(ostream& out, 
-                              t_struct* tstruct, 
-                              string this_name, 
-                              string this_get = "", 
-                              bool is_function = true); 
-  void generate_struct_reader(ostream& out, 
-                              t_struct* tstruct, 
-                              string this_name, 
-                              string this_get = "", 
-                              bool is_function = true); 
- 
-  void generate_serialize_field(ostream& out, 
-                                t_field* tfield, 
-                                string prefix, 
-                                string suffix, 
-                                int error_ret); 
-  void generate_serialize_struct(ostream& out, t_struct* tstruct, string prefix, int error_ret); 
-  void generate_serialize_container(ostream& out, t_type* ttype, string prefix, int error_ret); 
-  void generate_serialize_map_element(ostream& out, 
-                                      t_map* tmap, 
-                                      string key, 
-                                      string value, 
-                                      int error_ret); 
-  void generate_serialize_set_element(ostream& out, t_set* tset, string element, int error_ret); 
-  void generate_serialize_list_element(ostream& out, 
-                                       t_list* tlist, 
-                                       string list, 
-                                       string index, 
-                                       int error_ret); 
- 
-  void generate_deserialize_field(ostream& out, 
-                                  t_field* tfield, 
-                                  string prefix, 
-                                  string suffix, 
-                                  int error_ret, 
-                                  bool allocate = true); 
-  void generate_deserialize_struct(ostream& out, 
-                                   t_struct* tstruct, 
-                                   string prefix, 
-                                   int error_ret, 
-                                   bool allocate = true); 
-  void generate_deserialize_container(ostream& out, t_type* ttype, string prefix, int error_ret); 
-  void generate_deserialize_map_element(ostream& out, t_map* tmap, string prefix, int error_ret); 
-  void generate_deserialize_set_element(ostream& out, t_set* tset, string prefix, int error_ret); 
-  void generate_deserialize_list_element(ostream& out, 
-                                         t_list* tlist, 
-                                         string prefix, 
-                                         string index, 
-                                         int error_ret); 
- 
-  string generate_new_hash_from_type(t_type* key, t_type* value); 
-  string generate_new_array_from_type(t_type* ttype); 
- 
-  string generate_free_func_from_type(t_type* ttype); 
-  string generate_hash_func_from_type(t_type* ttype); 
-  string generate_cmp_func_from_type(t_type* ttype); 
-}; 
- 
-/** 
- * Prepare for file generation by opening up the necessary file 
- * output streams. 
- */ 
-void t_c_glib_generator::init_generator() { 
-  /* create output directory */ 
-  MKDIR(get_out_dir().c_str()); 
- 
-  string program_name_u = initial_caps_to_underscores(program_name_); 
-  string program_name_uc = to_upper_case(program_name_u); 
-  string program_name_lc = to_lower_case(program_name_u); 
- 
-  /* create output files */ 
-  string f_types_name = get_out_dir() + this->nspace_lc + program_name_lc + "_types.h"; 
-  f_types_.open(f_types_name.c_str()); 
-  string f_types_impl_name = get_out_dir() + this->nspace_lc + program_name_lc + "_types.c"; 
-  f_types_impl_.open(f_types_impl_name.c_str()); 
- 
-  /* add thrift boilerplate headers */ 
-  f_types_ << autogen_comment(); 
-  f_types_impl_ << autogen_comment(); 
- 
-  /* include inclusion guard */ 
-  f_types_ << "#ifndef " << this->nspace_uc << program_name_uc << "_TYPES_H" << endl << "#define " 
-           << this->nspace_uc << program_name_uc << "_TYPES_H" << endl << endl; 
- 
-  /* include base types */ 
-  f_types_ << "/* base includes */" << endl << "#include <glib-object.h>" << endl 
-           << "#include <thrift/c_glib/thrift_struct.h>" << endl 
-           << "#include <thrift/c_glib/protocol/thrift_protocol.h>" << endl; 
- 
-  /* include other thrift includes */ 
-  const vector<t_program*>& includes = program_->get_includes(); 
-  for (size_t i = 0; i < includes.size(); ++i) { 
-    f_types_ << "/* other thrift includes */" << endl << "#include \"" << this->nspace_lc 
-             << initial_caps_to_underscores(includes[i]->get_name()) << "_types.h\"" << endl; 
-  } 
-  f_types_ << endl; 
- 
-  /* include custom headers */ 
-  const vector<string>& c_includes = program_->get_c_includes(); 
-  f_types_ << "/* custom thrift includes */" << endl; 
-  for (size_t i = 0; i < c_includes.size(); ++i) { 
-    if (c_includes[i][0] == '<') { 
-      f_types_ << "#include " << c_includes[i] << endl; 
-    } else { 
-      f_types_ << "#include \"" << c_includes[i] << "\"" << endl; 
-    } 
-  } 
-  f_types_ << endl; 
- 
-  /* include math.h (for "INFINITY") in the implementation file, in case we 
-     encounter a struct with a member of type double */ 
-  f_types_impl_ << endl << "#include <math.h>" << endl; 
- 
-  // include the types file 
-  f_types_impl_ << endl << "#include \"" << this->nspace_lc << program_name_u << "_types.h\"" 
-                << endl << "#include <thrift/c_glib/thrift.h>" << endl << endl; 
- 
-  f_types_ << "/* begin types */" << endl << endl; 
-} 
- 
-/** 
- *  Finish up generation and close all file streams. 
- */ 
-void t_c_glib_generator::close_generator() { 
-  string program_name_uc = to_upper_case(initial_caps_to_underscores(program_name_)); 
- 
-  /* end the header inclusion guard */ 
-  f_types_ << "#endif /* " << this->nspace_uc << program_name_uc << "_TYPES_H */" << endl; 
- 
-  /* close output file */ 
-  f_types_.close(); 
-  f_types_impl_.close(); 
-} 
- 
-/** 
- * Generates a Thrift typedef in C code.  For example: 
- * 
- * Thrift: 
- * typedef map<i32,i32> SomeMap 
- * 
- * C: 
- * typedef GHashTable * ThriftSomeMap; 
- */ 
-void t_c_glib_generator::generate_typedef(t_typedef* ttypedef) { 
-  f_types_ << indent() << "typedef " << type_name(ttypedef->get_type(), true) << " " << this->nspace 
-           << ttypedef->get_symbolic() << ";" << endl << endl; 
-} 
- 
-/** 
- * Generates a C enumeration.  For example: 
- * 
- * Thrift: 
- * enum MyEnum { 
- *   ONE = 1, 
- *   TWO 
- * } 
- * 
- * C: 
- * enum _ThriftMyEnum { 
- *   THRIFT_MY_ENUM_ONE = 1, 
- *   THRIFT_MY_ENUM_TWO 
- * }; 
- * typedef enum _ThriftMyEnum ThriftMyEnum; 
- */ 
-void t_c_glib_generator::generate_enum(t_enum* tenum) { 
-  string name = tenum->get_name(); 
-  string name_uc = to_upper_case(initial_caps_to_underscores(name)); 
- 
-  f_types_ << indent() << "enum _" << this->nspace << name << " {" << endl; 
- 
-  indent_up(); 
- 
-  vector<t_enum_value*> constants = tenum->get_constants(); 
-  vector<t_enum_value*>::iterator c_iter; 
-  bool first = true; 
- 
-  /* output each of the enumeration elements */ 
-  for (c_iter = constants.begin(); c_iter != constants.end(); ++c_iter) { 
-    if (first) { 
-      first = false; 
-    } else { 
-      f_types_ << "," << endl; 
-    } 
- 
-    f_types_ << indent() << this->nspace_uc << name_uc << "_" << (*c_iter)->get_name(); 
-    f_types_ << " = " << (*c_iter)->get_value(); 
-  } 
- 
-  indent_down(); 
-  f_types_ << endl << "};" << endl << "typedef enum _" << this->nspace << name << " " 
-           << this->nspace << name << ";" << endl << endl; 
- 
-  f_types_ << "/* return the name of the constant */" << endl; 
-  f_types_ << "const char *" << endl; 
-  f_types_ << "toString_" << name << "(int value); " << endl << endl; 
-  ; 
-  f_types_impl_ << "/* return the name of the constant */" << endl; 
-  f_types_impl_ << "const char *" << endl; 
-  f_types_impl_ << "toString_" << name << "(int value) " << endl; 
-  f_types_impl_ << "{" << endl; 
-  f_types_impl_ << "  static __thread char buf[16] = {0};" << endl; 
-  f_types_impl_ << "  switch(value) {" << endl; 
-  std::set<int> done; 
-  for (c_iter = constants.begin(); c_iter != constants.end(); ++c_iter) { 
-    int value = (*c_iter)->get_value(); 
-    // Skipping duplicate value 
-    if (done.find(value) == done.end()) { 
-      done.insert(value); 
-      f_types_impl_ << "  case " << this->nspace_uc << name_uc << "_" << (*c_iter)->get_name() 
-                    << ":" 
-                    << "return \"" << this->nspace_uc << name_uc << "_" << (*c_iter)->get_name() 
-                    << "\";" << endl; 
-    } 
-  } 
-  f_types_impl_ << "  default: g_snprintf(buf, 16, \"%d\", value); return buf;" << endl; 
-  f_types_impl_ << "  }" << endl; 
-  f_types_impl_ << "}" << endl << endl; 
-} 
- 
-/** 
- * Generates Thrift constants in C code. 
- */ 
-void t_c_glib_generator::generate_consts(vector<t_const*> consts) { 
-  f_types_ << "/* constants */" << endl; 
-  f_types_impl_ << "/* constants */" << endl; 
- 
-  vector<t_const*>::iterator c_iter; 
-  for (c_iter = consts.begin(); c_iter != consts.end(); ++c_iter) { 
-    string name = (*c_iter)->get_name(); 
-    string name_uc = to_upper_case(name); 
-    string name_lc = to_lower_case(name); 
-    t_type* type = (*c_iter)->get_type(); 
-    t_const_value* value = (*c_iter)->get_value(); 
- 
-    if (is_complex_type(type)) { 
-      f_types_ << type_name(type) << indent() << this->nspace_lc << name_lc 
-               << "_constant();" << endl; 
-    } 
- 
-    f_types_ << indent() << "#define " << this->nspace_uc << name_uc << " " 
-             << constant_value(name_lc, type, value) << endl; 
- 
-    generate_const_initializer(name_lc, type, value, true); 
-  } 
- 
-  f_types_ << endl; 
-  f_types_impl_ << endl; 
-} 
- 
-/** 
- * Generate Thrift structs in C code, as GObjects.  Example: 
- * 
- * Thrift: 
- * struct Bonk 
- * { 
- *   1: string message, 
- *   2: i32 type 
- * } 
- * 
- * C GObject instance header: 
- * struct _ThriftBonk 
- * { 
- *   GObject parent; 
- * 
- *   gchar * message; 
- *   gint32 type; 
- * }; 
- * typedef struct _ThriftBonk ThriftBonk 
- * // ... additional GObject boilerplate ... 
- */ 
-void t_c_glib_generator::generate_struct(t_struct* tstruct) { 
-  f_types_ << "/* struct " << tstruct->get_name() << " */" << endl; 
-  generate_object(tstruct); 
-} 
- 
-/** 
- * Generate C code to represent Thrift services.  Creates a new GObject 
- * which can be used to access the service. 
- */ 
-void t_c_glib_generator::generate_service(t_service* tservice) { 
-  string svcname_u = initial_caps_to_underscores(tservice->get_name()); 
-  string svcname_uc = this->nspace_uc + to_upper_case(svcname_u); 
-  string filename = this->nspace_lc + to_lower_case(svcname_u); 
- 
-  // make output files 
-  string f_header_name = get_out_dir() + filename + ".h"; 
-  f_header_.open(f_header_name.c_str()); 
- 
-  string program_name_u = initial_caps_to_underscores(program_name_); 
-  string program_name_lc = to_lower_case(program_name_u); 
- 
-  // add header file boilerplate 
-  f_header_ << autogen_comment(); 
- 
-  // add an inclusion guard 
-  f_header_ << "#ifndef " << svcname_uc << "_H" << endl << "#define " << svcname_uc << "_H" << endl 
-            << endl; 
- 
-  // add standard includes 
-  f_header_ << "#include <thrift/c_glib/processor/thrift_dispatch_processor.h>" << endl << endl; 
-  f_header_ << "#include \"" << this->nspace_lc << program_name_lc << "_types.h\"" << endl; 
- 
-  // if we are inheriting from another service, include its header 
-  t_service* extends_service = tservice->get_extends(); 
-  if (extends_service != NULL) { 
-    f_header_ << "#include \"" << this->nspace_lc 
-              << to_lower_case(initial_caps_to_underscores(extends_service->get_name())) << ".h\"" 
-              << endl; 
-  } 
-  f_header_ << endl; 
- 
-  // create the service implementation 
-  string f_service_name = get_out_dir() + filename + ".c"; 
-  f_service_.open(f_service_name.c_str()); 
- 
-  // add the boilerplace header 
-  f_service_ << autogen_comment(); 
- 
-  // include the headers 
-  f_service_ << "#include <string.h>" << endl << "#include <thrift/c_glib/thrift.h>" << endl 
-             << "#include <thrift/c_glib/thrift_application_exception.h>" << endl << "#include \"" 
-             << filename << ".h\"" << endl << endl; 
- 
-  // generate the service-helper classes 
-  generate_service_helpers(tservice); 
- 
-  // generate the client objects 
-  generate_service_client(tservice); 
- 
-  // generate the server objects 
-  generate_service_server(tservice); 
- 
-  // end the header inclusion guard 
-  f_header_ << "#endif /* " << svcname_uc << "_H */" << endl; 
- 
-  // close the files 
-  f_service_.close(); 
-  f_header_.close(); 
-} 
- 
-/** 
- * 
- */ 
-void t_c_glib_generator::generate_xception(t_struct* tstruct) { 
-  string name = tstruct->get_name(); 
-  string name_u = initial_caps_to_underscores(name); 
-  string name_lc = to_lower_case(name_u); 
-  string name_uc = to_upper_case(name_u); 
- 
-  generate_object(tstruct); 
- 
-  f_types_ << "/* exception */" << endl 
-           << "typedef enum" << endl 
-           << "{" << endl; 
-  indent_up(); 
-  f_types_ << indent() << this->nspace_uc << name_uc << "_ERROR_CODE" << endl; 
-  indent_down(); 
-  f_types_ << "} " << this->nspace << name << "Error;" << endl 
-           << endl 
-           << "GQuark " << this->nspace_lc << name_lc 
-           << "_error_quark (void);" << endl 
-           << "#define " << this->nspace_uc << name_uc << "_ERROR (" 
-           << this->nspace_lc << name_lc << "_error_quark())" << endl 
-           << endl 
-           << endl; 
- 
-  f_types_impl_ << "/* define the GError domain for exceptions */" << endl << "#define " 
-                << this->nspace_uc << name_uc << "_ERROR_DOMAIN \"" << this->nspace_lc << name_lc 
-                << "_error_quark\"" << endl << "GQuark" << endl << this->nspace_lc << name_lc 
-                << "_error_quark (void)" << endl << "{" << endl 
-                << "  return g_quark_from_static_string (" << this->nspace_uc << name_uc 
-                << "_ERROR_DOMAIN);" << endl << "}" << endl << endl; 
-} 
- 
-/******************** 
- * HELPER FUNCTIONS * 
- ********************/ 
- 
-/** 
- * Returns true if ttype is not a primitive. 
- */ 
-bool t_c_glib_generator::is_complex_type(t_type* ttype) { 
-  ttype = get_true_type(ttype); 
- 
-  return ttype->is_container() || ttype->is_struct() || ttype->is_xception(); 
-} 
- 
-bool t_c_glib_generator::is_numeric(t_type* ttype) { 
-  return ttype->is_enum() || (ttype->is_base_type() && !ttype->is_string()); 
-} 
- 
-/** 
- * Maps a Thrift t_type to a C type. 
- */ 
-string t_c_glib_generator::type_name(t_type* ttype, bool in_typedef, bool is_const) { 
-  if (ttype->is_base_type()) { 
-    string bname = base_type_name(ttype); 
- 
-    if (is_const) { 
-      return "const " + bname; 
-    } else { 
-      return bname; 
-    } 
-  } 
- 
-  if (ttype->is_container()) { 
-    string cname; 
- 
-    t_container* tcontainer = (t_container*)ttype; 
-    if (tcontainer->has_cpp_name()) { 
-      cname = tcontainer->get_cpp_name(); 
-    } else if (ttype->is_map()) { 
-      cname = "GHashTable"; 
-    } else if (ttype->is_set()) { 
-      // since a set requires unique elements, use a GHashTable, and 
-      // populate the keys and values with the same data, using keys for 
-      // the actual writes and reads. 
-      // TODO: discuss whether or not to implement TSet, THashSet or GHashSet 
-      cname = "GHashTable"; 
-    } else if (ttype->is_list()) { 
-      t_type* etype = ((t_list*)ttype)->get_elem_type(); 
-      if (etype->is_void()) { 
-        throw std::runtime_error("compiler error: list element type cannot be void"); 
-      } 
-      // TODO: investigate other implementations besides GPtrArray 
-      cname = is_numeric(etype) ? "GArray" : "GPtrArray"; 
-    } 
- 
-    /* Omit the dereference operator if we are aliasing this type within a 
-       typedef, to allow the type to be used more naturally in client code; 
-       otherwise, include it */ 
-    if (!in_typedef) { 
-      cname += " *"; 
-    } 
- 
-    if (is_const) { 
-      return "const " + cname; 
-    } else { 
-      return cname; 
-    } 
-  } 
- 
-  // check for a namespace 
-  string pname = this->nspace + ttype->get_name(); 
- 
-  if (is_complex_type(ttype)) { 
-    pname += " *"; 
-  } 
- 
-  if (is_const) { 
-    return "const " + pname; 
-  } else { 
-    return pname; 
-  } 
-} 
- 
-/** 
- * Maps a Thrift primitive to the type needed to hold its value when used as an 
- * object property. 
- * 
- * This method is needed because all integer properties of width less than 64 
- * bits map to the same type, gint, as opposed to their width-specific type 
- * (gint8, gint16 or gint32). 
- */ 
-string t_c_glib_generator::property_type_name(t_type* ttype, bool in_typedef, bool is_const) { 
-  string result; 
- 
-  if (ttype->is_base_type()) { 
-    switch (((t_base_type*)ttype)->get_base()) { 
-    case t_base_type::TYPE_I8: 
-    case t_base_type::TYPE_I16: 
-    case t_base_type::TYPE_I32: 
-      if (is_const) { 
-        result = "const gint"; 
-      } else { 
-        result = "gint"; 
-      } 
-      break; 
- 
-    default: 
-      result = type_name(ttype, in_typedef, is_const); 
-    } 
-  } else { 
-    result = type_name(ttype, in_typedef, is_const); 
-  } 
- 
-  return result; 
-} 
- 
-/** 
- * Maps a Thrift primitive to a C primitive. 
- */ 
-string t_c_glib_generator::base_type_name(t_type* type) { 
-  if (type->is_enum()) { 
-    return type_name(type); 
-  } 
-  if (!type->is_base_type()) { 
-    throw std::invalid_argument("Only base types are suppported."); 
-  } 
-  t_base_type* base_type = reinterpret_cast<t_base_type*>(type); 
-  t_base_type::t_base tbase = base_type->get_base(); 
-  switch (tbase) { 
-  case t_base_type::TYPE_VOID: 
-    return "void"; 
-  case t_base_type::TYPE_STRING: 
-    if (base_type->is_binary()) { 
-      return "GByteArray *"; 
-    } else { 
-      return "gchar *"; 
-    } 
-  case t_base_type::TYPE_BOOL: 
-    return "gboolean"; 
-  case t_base_type::TYPE_I8: 
-    return "gint8"; 
-  case t_base_type::TYPE_I16: 
-    return "gint16"; 
-  case t_base_type::TYPE_I32: 
-    return "gint32"; 
-  case t_base_type::TYPE_I64: 
-    return "gint64"; 
-  case t_base_type::TYPE_DOUBLE: 
-    return "gdouble"; 
-  default: 
-    throw std::logic_error("compiler error: no C base type name for base type " 
-                           + t_base_type::t_base_name(tbase)); 
-  } 
-} 
- 
-/** 
- * Returns a member of the ThriftType C enumeration in thrift_protocol.h 
- * for a Thrift type. 
- */ 
-string t_c_glib_generator::type_to_enum(t_type* type) { 
-  type = get_true_type(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: 
-      throw "NO T_VOID CONSTRUCT"; 
-    case t_base_type::TYPE_STRING: 
-      return "T_STRING"; 
-    case t_base_type::TYPE_BOOL: 
-      return "T_BOOL"; 
-    case t_base_type::TYPE_I8: 
-      return "T_BYTE"; 
-    case t_base_type::TYPE_I16: 
-      return "T_I16"; 
-    case t_base_type::TYPE_I32: 
-      return "T_I32"; 
-    case t_base_type::TYPE_I64: 
-      return "T_I64"; 
-    case t_base_type::TYPE_DOUBLE: 
-      return "T_DOUBLE"; 
-    } 
-  } else if (type->is_enum()) { 
-    return "T_I32"; 
-  } else if (type->is_struct()) { 
-    return "T_STRUCT"; 
-  } else if (type->is_xception()) { 
-    return "T_STRUCT"; 
-  } else if (type->is_map()) { 
-    return "T_MAP"; 
-  } else if (type->is_set()) { 
-    return "T_SET"; 
-  } else if (type->is_list()) { 
-    return "T_LIST"; 
-  } 
- 
-  throw "INVALID TYPE IN type_to_enum: " + type->get_name(); 
-} 
- 
-/** 
- * Returns a Thrift constant formatted as a literal for inclusion in C code. 
- */ 
-string t_c_glib_generator::constant_literal(t_type* type, t_const_value* value) { 
-  ostringstream render; 
- 
-  if (type->is_base_type()) { 
-    /* primitives */ 
-    t_base_type::t_base tbase = ((t_base_type*)type)->get_base(); 
- 
-    switch (tbase) { 
-    case t_base_type::TYPE_STRING: 
-      render << "\"" + value->get_string() + "\""; 
-      break; 
-    case t_base_type::TYPE_BOOL: 
-      render << ((value->get_integer() != 0) ? "TRUE" : "FALSE"); 
-      break; 
-    case t_base_type::TYPE_I8: 
-    case t_base_type::TYPE_I16: 
-    case t_base_type::TYPE_I32: 
-    case t_base_type::TYPE_I64: 
-      render << value->get_integer(); 
-      break; 
-    case t_base_type::TYPE_DOUBLE: 
-      render << value->get_double(); 
-      break; 
-    default: 
-      throw "compiler error: no const of base type " + t_base_type::t_base_name(tbase); 
-    } 
-  } else { 
-    t_const_value::t_const_value_type value_type = value->get_type(); 
- 
-    switch (value_type) { 
-    case t_const_value::CV_IDENTIFIER: 
-      render << value->get_integer(); 
-      break; 
-    case t_const_value::CV_LIST: 
-      render << "{ "; 
-      { 
-        t_type* elem_type = ((t_list*)type)->get_elem_type(); 
-        const vector<t_const_value*>& list = value->get_list(); 
-        vector<t_const_value*>::const_iterator list_iter; 
- 
-        if (list.size() > 0) { 
-          list_iter = list.begin(); 
-          render << constant_literal(elem_type, *list_iter); 
- 
-          while (++list_iter != list.end()) { 
-            render << ", " << constant_literal(elem_type, *list_iter); 
-          } 
-        } 
-      } 
-      render << " }"; 
-      break; 
-    case t_const_value::CV_MAP: 
-    default: 
-      render << "NULL /* not supported */"; 
-    } 
-  } 
- 
-  return render.str(); 
-} 
- 
-/** 
- * Returns C code that represents a Thrift constant. 
- */ 
-string t_c_glib_generator::constant_value(string name, t_type* type, t_const_value* value) { 
-  ostringstream render; 
- 
-  if (type->is_base_type()) { 
-    /* primitives */ 
-    t_base_type::t_base tbase = ((t_base_type*)type)->get_base(); 
-    switch (tbase) { 
-    case t_base_type::TYPE_STRING: 
-      render << "g_strdup (\"" + value->get_string() + "\")"; 
-      break; 
-    case t_base_type::TYPE_BOOL: 
-      render << ((value->get_integer() != 0) ? 1 : 0); 
-      break; 
-    case t_base_type::TYPE_I8: 
-    case t_base_type::TYPE_I16: 
-    case t_base_type::TYPE_I32: 
-      render << value->get_integer(); 
-      break; 
-    case t_base_type::TYPE_I64: 
-      render << "G_GINT64_CONSTANT (" << value->get_integer() << ")"; 
-      break; 
-    case t_base_type::TYPE_DOUBLE: 
-      if (value->get_type() == t_const_value::CV_INTEGER) { 
-        render << value->get_integer(); 
-      } else { 
-        render << value->get_double(); 
-      } 
-      break; 
-    default: 
-      throw "compiler error: no const of base type " + t_base_type::t_base_name(tbase); 
-    } 
-  } else if (type->is_enum()) { 
-    render << "(" << type_name(type) << ")" << value->get_integer(); 
-  } else if (is_complex_type(type)) { 
-    render << "(" << this->nspace_lc << to_lower_case(name) << "_constant())"; 
-  } else { 
-    render << "NULL /* not supported */"; 
-  } 
- 
-  return render.str(); 
-} 
- 
-/** 
- * Renders a function signature of the form 'type name(args)' 
- * 
- * @param tfunction Function definition 
- * @return String of rendered function definition 
- */ 
-string t_c_glib_generator::function_signature(t_function* tfunction) { 
-  t_type* ttype = tfunction->get_returntype(); 
-  t_struct* arglist = tfunction->get_arglist(); 
-  t_struct* xlist = tfunction->get_xceptions(); 
-  string fname = initial_caps_to_underscores(tfunction->get_name()); 
- 
-  bool has_return = !ttype->is_void(); 
-  bool has_args = arglist->get_members().size() == 0; 
-  bool has_xceptions = xlist->get_members().size() == 0; 
-  return "gboolean " + this->nspace_lc + fname + " (" + this->nspace + service_name_ + "If * iface" 
-         + (has_return ? ", " + type_name(ttype) + "* _return" : "") 
-         + (has_args ? "" : (", " + argument_list(arglist))) 
-         + (has_xceptions ? "" : (", " + xception_list(xlist))) + ", GError ** error)"; 
-} 
- 
-/** 
- * Renders a field list 
- * 
- * @param tstruct The struct definition 
- * @return Comma sepearated list of all field names in that struct 
- */ 
-string t_c_glib_generator::argument_list(t_struct* tstruct) { 
-  string result = ""; 
- 
-  const vector<t_field*>& fields = tstruct->get_members(); 
-  vector<t_field*>::const_iterator f_iter; 
-  bool first = true; 
-  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { 
-    if (first) { 
-      first = false; 
-    } else { 
-      result += ", "; 
-    } 
-    result += type_name((*f_iter)->get_type(), false, true) + " " + (*f_iter)->get_name(); 
-  } 
-  return result; 
-} 
- 
-/** 
- * Renders mutable exception lists 
- * 
- * @param tstruct The struct definition 
- * @return Comma sepearated list of all field names in that struct 
- */ 
-string t_c_glib_generator::xception_list(t_struct* tstruct) { 
-  string result = ""; 
- 
-  const vector<t_field*>& fields = tstruct->get_members(); 
-  vector<t_field*>::const_iterator f_iter; 
-  bool first = true; 
-  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { 
-    if (first) { 
-      first = false; 
-    } else { 
-      result += ", "; 
-    } 
-    result += type_name((*f_iter)->get_type(), false, false) + "* " + (*f_iter)->get_name(); 
-  } 
-  return result; 
-} 
- 
-/** 
- * Declares a field, including any necessary initialization. 
- */ 
-string t_c_glib_generator::declare_field(t_field* tfield, 
-                                         bool init, 
-                                         bool pointer, 
-                                         bool constant, 
-                                         bool reference) { 
-  string result = ""; 
-  if (constant) { 
-    result += "const "; 
-  } 
-  result += type_name(tfield->get_type()); 
-  if (pointer) { 
-    result += "*"; 
-  } 
-  if (reference) { 
-    result += "*"; 
-  } 
-  result += " " + tfield->get_name(); 
-  if (init) { 
-    t_type* type = get_true_type(tfield->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_BOOL: 
-      case t_base_type::TYPE_I8: 
-      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 += " = (gdouble) 0"; 
-        break; 
-      case t_base_type::TYPE_STRING: 
-        result += " = NULL"; 
-        break; 
-      default: 
-        throw "compiler error: no C intializer for base type " + t_base_type::t_base_name(tbase); 
-      } 
-    } else if (type->is_enum()) { 
-      result += " = (" + type_name(type) + ") 0"; 
-    } else if (type->is_struct() || type->is_container()) { 
-      result += " = NULL"; 
-    } 
-  } 
- 
-  if (!reference) { 
-    result += ";"; 
-  } 
- 
-  return result; 
-} 
- 
-string t_c_glib_generator::constant_value_with_storage(string fname, 
-                                                       t_type* etype, 
-                                                       t_const_value* value) { 
-  ostringstream render; 
-  if (is_numeric(etype)) { 
-    render << "    " << type_name(etype) << " *" << fname << " = " 
-           << "g_new (" << base_type_name(etype) << ", 1);" << endl 
-           << "    *" << fname << " = " << constant_value(fname, (t_type*)etype, value) << ";" 
-           << endl; 
-  } else { 
-    render << "    " << type_name(etype) << " " << fname << " = " 
-           << constant_value(fname, (t_type*)etype, value) << ";" << endl; 
-  } 
-  return render.str(); 
-} 
- 
-/** 
- * Generates C code that initializes complex constants. 
- */ 
-void t_c_glib_generator::generate_const_initializer(string name, 
-                                                    t_type* type, 
-                                                    t_const_value* value, 
-                                                    bool top_level) { 
-  string name_u = initial_caps_to_underscores(name); 
-  string name_lc = to_lower_case(name_u); 
-  string type_u = initial_caps_to_underscores(type->get_name()); 
-  string type_uc = to_upper_case(type_u); 
-  string maybe_static = top_level ? "" : "static "; 
- 
-  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*, t_const_value::value_compare>& val = value->get_map(); 
-    map<t_const_value*, t_const_value*, t_const_value::value_compare>::const_iterator v_iter; 
-    ostringstream initializers; 
- 
-    // initialize any constants that may be referenced by this initializer 
-    for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) { 
-      t_type* field_type = NULL; 
-      string field_name = ""; 
- 
-      for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { 
-        if ((*f_iter)->get_name() == v_iter->first->get_string()) { 
-          field_type = (*f_iter)->get_type(); 
-          field_name = (*f_iter)->get_name(); 
-          break; 
-        } 
-      } 
-      if (field_type == NULL) { 
-        throw "type error: " + type->get_name() + " has no field " 
-          + v_iter->first->get_string(); 
-      } 
-      field_name = tmp(field_name); 
- 
-      generate_const_initializer(name + "_constant_" + field_name, 
-                                 field_type, 
-                                 v_iter->second); 
-      initializers << "    constant->" << v_iter->first->get_string() << " = " 
-                   << constant_value(name + "_constant_" + field_name, 
-                                     field_type, 
-                                     v_iter->second) << ";" << endl 
-                   << "    constant->__isset_" << v_iter->first->get_string() 
-                   << " = TRUE;" << endl; 
-    } 
- 
-    // implement the initializer 
-    f_types_impl_ << maybe_static << this->nspace << type->get_name() << " *" 
-                  << endl 
-                  << this->nspace_lc << name_lc << "_constant (void)" << endl; 
-    scope_up(f_types_impl_); 
-    f_types_impl_ << indent() << "static " << this->nspace << type->get_name() 
-                  << " *constant = NULL;" << endl 
-                  << indent() << "if (constant == NULL)" << endl; 
-    scope_up(f_types_impl_); 
-    f_types_impl_ << indent() << "constant = g_object_new (" << this->nspace_uc 
-                  << "TYPE_" << type_uc << ", NULL);" << endl 
-                  << initializers.str(); 
-    scope_down(f_types_impl_); 
- 
-    for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) { 
-      t_type* field_type = NULL; 
-      string field_name = ""; 
- 
-      for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { 
-        if ((*f_iter)->get_name() == v_iter->first->get_string()) { 
-          field_type = (*f_iter)->get_type(); 
-          field_name = (*f_iter)->get_name(); 
-          break; 
-        } 
-      } 
-      if (field_type == NULL) { 
-        throw "type error: " + type->get_name() + " has no field " 
-          + v_iter->first->get_string(); 
-      } 
-      field_name = tmp(field_name); 
-    } 
- 
-    f_types_impl_ << indent() << "return constant;" << endl; 
-    scope_down(f_types_impl_); 
-    f_types_impl_ << endl; 
-  } else if (type->is_list()) { 
-    string list_type = "GPtrArray *"; 
-    string free_func 
-        = generate_free_func_from_type(reinterpret_cast<t_list*>(type)->get_elem_type()); 
-    string list_initializer = "g_ptr_array_new_with_free_func (" + free_func + ");"; 
-    string list_appender = "g_ptr_array_add"; 
-    bool list_variable = false; 
- 
-    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; 
-    ostringstream initializers; 
-    ostringstream appenders; 
- 
-    list_initializer = generate_new_array_from_type(etype); 
-    if (etype->is_base_type()) { 
-      t_base_type::t_base tbase = ((t_base_type*)etype)->get_base(); 
-      switch (tbase) { 
-      case t_base_type::TYPE_VOID: 
-        throw "compiler error: cannot determine array type"; 
-      case t_base_type::TYPE_BOOL: 
-      case t_base_type::TYPE_I8: 
-      case t_base_type::TYPE_I16: 
-      case t_base_type::TYPE_I32: 
-      case t_base_type::TYPE_I64: 
-      case t_base_type::TYPE_DOUBLE: 
-        list_type = "GArray *"; 
-        list_appender = "g_array_append_val"; 
-        list_variable = true; 
-        break; 
-      case t_base_type::TYPE_STRING: 
-        break; 
-      default: 
-        throw "compiler error: no array info for type"; 
-      } 
-    } else if (etype->is_enum()) { 
-      list_type = "GArray *"; 
-      list_appender = "g_array_append_val"; 
-      list_variable = true; 
-    } 
- 
-    for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) { 
-      string fname = tmp(name); 
- 
-      generate_const_initializer(fname, etype, (*v_iter)); 
-      if (list_variable) { 
-        initializers << "    " << type_name(etype) << " " << fname << " = " 
-                     << constant_value(fname, (t_type*)etype, (*v_iter)) << ";" 
-                     << endl; 
-        appenders << "    " << list_appender << "(constant, " << fname << ");" 
-                  << endl; 
-      } else { 
-        appenders << "    " << list_appender << "(constant, " 
-                  << constant_value(fname, (t_type*)etype, (*v_iter)) << ");" 
-                  << endl; 
-      } 
-    } 
- 
-    f_types_impl_ << maybe_static << list_type << endl 
-                  << this->nspace_lc << name_lc << "_constant (void)" << endl; 
-    scope_up(f_types_impl_); 
-    f_types_impl_ << indent() << "static " << list_type << " constant = NULL;" 
-                  << endl 
-                  << indent() << "if (constant == NULL)" << endl; 
-    scope_up(f_types_impl_); 
-    if (!initializers.str().empty()) { 
-      f_types_impl_ << initializers.str() 
-                    << endl; 
-    } 
-    f_types_impl_ << indent() << "constant = " << list_initializer << endl 
-                  << appenders.str(); 
-    scope_down(f_types_impl_); 
-    f_types_impl_ << indent() << "return constant;" << endl; 
-    scope_down(f_types_impl_); 
-    f_types_impl_ << endl; 
-  } else if (type->is_set()) { 
-    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; 
-    ostringstream initializers; 
-    ostringstream appenders; 
- 
-    for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) { 
-      string fname = tmp(name); 
-      string ptr = is_numeric(etype) ? "*" : ""; 
-      generate_const_initializer(fname, etype, (*v_iter)); 
-      initializers << constant_value_with_storage(fname, (t_type*)etype, *v_iter); 
-      appenders << "    g_hash_table_insert (constant, " << fname << ", 0);" << endl; 
-    } 
- 
-    f_types_impl_ << maybe_static << "GHashTable *" << endl 
-                  << this->nspace_lc << name_lc << "_constant (void)" << endl; 
-    scope_up(f_types_impl_); 
-    f_types_impl_ << indent() << "static GHashTable *constant = NULL;" << endl 
-                  << indent() << "if (constant == NULL)" << endl; 
-    scope_up(f_types_impl_); 
-    f_types_impl_ << initializers.str() << endl 
-                  << indent() << "constant = " << generate_new_hash_from_type(etype, NULL) << endl 
-                  << appenders.str(); 
-    scope_down(f_types_impl_); 
-    f_types_impl_ << indent() << "return constant;" << endl; 
-    scope_down(f_types_impl_); 
-    f_types_impl_ << endl; 
-  } else if (type->is_map()) { 
-    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*, t_const_value::value_compare>& val = value->get_map(); 
-    map<t_const_value*, t_const_value*, t_const_value::value_compare>::const_iterator v_iter; 
-    ostringstream initializers; 
-    ostringstream appenders; 
- 
-    for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) { 
-      string fname = tmp(name); 
-      string kname = fname + "key"; 
-      string vname = fname + "val"; 
-      generate_const_initializer(kname, ktype, v_iter->first); 
-      generate_const_initializer(vname, vtype, v_iter->second); 
- 
-      initializers << constant_value_with_storage(kname, (t_type*)ktype, v_iter->first); 
-      initializers << constant_value_with_storage(vname, (t_type*)vtype, v_iter->second); 
-      appenders << "    g_hash_table_insert (constant, " << kname << ", " << vname << ");" << endl; 
-    } 
- 
-    f_types_impl_ << maybe_static << "GHashTable *" << endl 
-                  << this->nspace_lc << name_lc << "_constant (void)" << endl; 
-    scope_up(f_types_impl_); 
-    f_types_impl_ << indent() << "static GHashTable *constant = NULL;" << endl 
-                  << indent() << "if (constant == NULL)" << endl; 
-    scope_up(f_types_impl_); 
-    f_types_impl_ << initializers.str() << endl 
-                  << indent() << "constant = " << generate_new_hash_from_type(ktype, vtype) << endl 
-                  << appenders.str(); 
-    scope_down(f_types_impl_); 
-    f_types_impl_ << indent() << "return constant;" << endl; 
-    scope_down(f_types_impl_); 
-    f_types_impl_ << endl; 
-  } 
-} 
- 
-/** 
- * Generates helper classes for a service, consisting of a ThriftStruct subclass 
- * for the arguments to and the result from each method. 
- * 
- * @param tservice The service for which to generate helper classes 
- */ 
-void t_c_glib_generator::generate_service_helpers(t_service* tservice) { 
-  vector<t_function*> functions = tservice->get_functions(); 
-  vector<t_function*>::iterator function_iter; 
- 
-  // Iterate through the service's methods 
-  for (function_iter = functions.begin(); function_iter != functions.end(); ++function_iter) { 
-    string function_name = (*function_iter)->get_name(); 
-    t_struct* arg_list = (*function_iter)->get_arglist(); 
-    string arg_list_name_orig = arg_list->get_name(); 
- 
-    // Generate the arguments class 
-    arg_list->set_name(tservice->get_name() + underscores_to_initial_caps(function_name) + "Args"); 
-    generate_struct(arg_list); 
- 
-    arg_list->set_name(arg_list_name_orig); 
- 
-    // Generate the result class 
-    if (!(*function_iter)->is_oneway()) { 
-      t_struct result(program_, 
-                      tservice->get_name() + underscores_to_initial_caps(function_name) + "Result"); 
-      t_field success((*function_iter)->get_returntype(), "success", 0); 
-      success.set_req(t_field::T_OPTIONAL); 
-      if (!(*function_iter)->get_returntype()->is_void()) { 
-        result.append(&success); 
-      } 
- 
-      t_struct* xs = (*function_iter)->get_xceptions(); 
-      const vector<t_field*>& fields = xs->get_members(); 
-      vector<t_field*>::const_iterator field_iter; 
-      for (field_iter = fields.begin(); field_iter != fields.end(); ++field_iter) { 
-        (*field_iter)->set_req(t_field::T_OPTIONAL); 
-        result.append(*field_iter); 
-      } 
- 
-      generate_struct(&result); 
-    } 
-  } 
-} 
- 
-/** 
- * Generates C code that represents a Thrift service client. 
- */ 
-void t_c_glib_generator::generate_service_client(t_service* tservice) { 
-  /* get some C friendly service names */ 
-  string service_name_lc = to_lower_case(initial_caps_to_underscores(service_name_)); 
-  string service_name_uc = to_upper_case(service_name_lc); 
- 
-  string parent_service_name; 
-  string parent_service_name_lc; 
-  string parent_service_name_uc; 
- 
-  string parent_class_name = "GObject"; 
-  string parent_type_name = "G_TYPE_OBJECT"; 
- 
-  // The service this service extends, or NULL if it extends no 
-  // service 
-  t_service* extends_service = tservice->get_extends(); 
-  if (extends_service) { 
-    // The name of the parent service 
-    parent_service_name = extends_service->get_name(); 
-    parent_service_name_lc = to_lower_case(initial_caps_to_underscores(parent_service_name)); 
-    parent_service_name_uc = to_upper_case(parent_service_name_lc); 
- 
-    // The names of the client class' parent class and type 
-    parent_class_name = this->nspace + parent_service_name + "Client"; 
-    parent_type_name = this->nspace_uc + "TYPE_" + parent_service_name_uc + "_CLIENT"; 
-  } 
- 
-  // The base service (the topmost in the "extends" hierarchy), on 
-  // whose client class the "input_protocol" and "output_protocol" 
-  // properties are defined 
-  t_service* base_service = tservice; 
-  while (base_service->get_extends()) { 
-    base_service = base_service->get_extends(); 
-  } 
- 
-  string base_service_name = base_service->get_name(); 
-  string base_service_name_lc = to_lower_case(initial_caps_to_underscores(base_service_name)); 
-  string base_service_name_uc = to_upper_case(base_service_name_lc); 
- 
-  // Generate the client interface dummy object in the header. 
-  f_header_ << "/* " << service_name_ << " service interface */" << endl << "typedef struct _" 
-            << this->nspace << service_name_ << "If " << this->nspace << service_name_ << "If; " 
-            << " /* dummy object */" << endl << endl; 
- 
-  // Generate the client interface object in the header. 
-  f_header_ << "struct _" << this->nspace << service_name_ << "IfInterface" << endl << "{" << endl 
-            << "  GTypeInterface parent;" << endl << endl; 
- 
-  /* write out the functions for this interface */ 
-  indent_up(); 
-  vector<t_function*> functions = tservice->get_functions(); 
-  vector<t_function*>::const_iterator f_iter; 
-  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) { 
-    /* make the function name C friendly */ 
-    string funname = initial_caps_to_underscores((*f_iter)->get_name()); 
-    t_type* ttype = (*f_iter)->get_returntype(); 
-    t_struct* arglist = (*f_iter)->get_arglist(); 
-    t_struct* xlist = (*f_iter)->get_xceptions(); 
-    bool has_return = !ttype->is_void(); 
-    bool has_args = arglist->get_members().size() == 0; 
-    bool has_xceptions = xlist->get_members().size() == 0; 
- 
-    string params = "(" + this->nspace + service_name_ + "If *iface" 
-                    + (has_return ? ", " + type_name(ttype) + "* _return" : "") 
-                    + (has_args ? "" : (", " + argument_list(arglist))) 
-                    + (has_xceptions ? "" : (", " + xception_list(xlist))) + ", GError **error)"; 
- 
-    indent(f_header_) << "gboolean (*" << funname << ") " << params << ";" << endl; 
-  } 
-  indent_down(); 
- 
-  f_header_ << "};" << endl << "typedef struct _" << this->nspace << service_name_ << "IfInterface " 
-            << this->nspace << service_name_ << "IfInterface;" << endl << endl; 
- 
-  // generate all the interface boilerplate 
-  f_header_ << "GType " << this->nspace_lc << service_name_lc << "_if_get_type (void);" << endl 
-            << "#define " << this->nspace_uc << "TYPE_" << service_name_uc << "_IF " 
-            << "(" << this->nspace_lc << service_name_lc << "_if_get_type())" << endl << "#define " 
-            << this->nspace_uc << service_name_uc << "_IF(obj) " 
-            << "(G_TYPE_CHECK_INSTANCE_CAST ((obj), " << this->nspace_uc << "TYPE_" 
-            << service_name_uc << "_IF, " << this->nspace << service_name_ << "If))" << endl 
-            << "#define " << this->nspace_uc << "IS_" << service_name_uc << "_IF(obj) " 
-            << "(G_TYPE_CHECK_INSTANCE_TYPE ((obj), " << this->nspace_uc << "TYPE_" 
-            << service_name_uc << "_IF))" << endl << "#define " << this->nspace_uc 
-            << service_name_uc << "_IF_GET_INTERFACE(inst) (G_TYPE_INSTANCE_GET_INTERFACE ((inst), " 
-            << this->nspace_uc << "TYPE_" << service_name_uc << "_IF, " << this->nspace 
-            << service_name_ << "IfInterface))" << endl << endl; 
- 
-  // write out all the interface function prototypes 
-  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) { 
-    /* make the function name C friendly */ 
-    string funname = initial_caps_to_underscores((*f_iter)->get_name()); 
-    t_type* ttype = (*f_iter)->get_returntype(); 
-    t_struct* arglist = (*f_iter)->get_arglist(); 
-    t_struct* xlist = (*f_iter)->get_xceptions(); 
-    bool has_return = !ttype->is_void(); 
-    bool has_args = arglist->get_members().size() == 0; 
-    bool has_xceptions = xlist->get_members().size() == 0; 
- 
-    string params = "(" + this->nspace + service_name_ + "If *iface" 
-                    + (has_return ? ", " + type_name(ttype) + "* _return" : "") 
-                    + (has_args ? "" : (", " + argument_list(arglist))) 
-                    + (has_xceptions ? "" : (", " + xception_list(xlist))) + ", GError **error)"; 
- 
-    f_header_ << "gboolean " << this->nspace_lc << service_name_lc << "_if_" << funname << " " 
-              << params << ";" << endl; 
-  } 
-  f_header_ << endl; 
- 
-  // Generate the client object instance definition in the header. 
-  f_header_ << "/* " << service_name_ << " service client */" << endl << "struct _" << this->nspace 
-            << service_name_ << "Client" << endl << "{" << endl << "  " << parent_class_name 
-            << " parent;" << endl; 
-  if (!extends_service) { 
-    // Define "input_protocol" and "output_protocol" properties only 
-    // for base services; child service-client classes will inherit 
-    // these 
-    f_header_ << endl << "  ThriftProtocol *input_protocol;" << endl 
-              << "  ThriftProtocol *output_protocol;" << endl; 
-  } 
-  f_header_ << "};" << endl << "typedef struct _" << this->nspace << service_name_ << "Client " 
-            << this->nspace << service_name_ << "Client;" << endl << endl; 
- 
-  // Generate the class definition in the header. 
-  f_header_ << "struct _" << this->nspace << service_name_ << "ClientClass" << endl << "{" << endl 
-            << "  " << parent_class_name << "Class parent;" << endl << "};" << endl 
-            << "typedef struct _" << this->nspace << service_name_ << "ClientClass " << this->nspace 
-            << service_name_ << "ClientClass;" << endl << endl; 
- 
-  // Create all the GObject boilerplate 
-  f_header_ << "GType " << this->nspace_lc << service_name_lc << "_client_get_type (void);" << endl 
-            << "#define " << this->nspace_uc << "TYPE_" << service_name_uc << "_CLIENT " 
-            << "(" << this->nspace_lc << service_name_lc << "_client_get_type())" << endl 
-            << "#define " << this->nspace_uc << service_name_uc << "_CLIENT(obj) " 
-            << "(G_TYPE_CHECK_INSTANCE_CAST ((obj), " << this->nspace_uc << "TYPE_" 
-            << service_name_uc << "_CLIENT, " << this->nspace << service_name_ << "Client))" << endl 
-            << "#define " << this->nspace_uc << service_name_uc << "_CLIENT_CLASS(c) " 
-            << "(G_TYPE_CHECK_CLASS_CAST ((c), " << this->nspace_uc << "TYPE_" << service_name_uc 
-            << "_CLIENT, " << this->nspace << service_name_ << "ClientClass))" << endl << "#define " 
-            << this->nspace_uc << service_name_uc << "_IS_CLIENT(obj) " 
-            << "(G_TYPE_CHECK_INSTANCE_TYPE ((obj), " << this->nspace_uc << "TYPE_" 
-            << service_name_uc << "_CLIENT))" << endl << "#define " << this->nspace_uc 
-            << service_name_uc << "_IS_CLIENT_CLASS(c) " 
-            << "(G_TYPE_CHECK_CLASS_TYPE ((c), " << this->nspace_uc << "TYPE_" << service_name_uc 
-            << "_CLIENT))" << endl << "#define " << this->nspace_uc << service_name_uc 
-            << "_CLIENT_GET_CLASS(obj) " 
-            << "(G_TYPE_INSTANCE_GET_CLASS ((obj), " << this->nspace_uc << "TYPE_" 
-            << service_name_uc << "_CLIENT, " << this->nspace << service_name_ << "ClientClass))" 
-            << endl << endl; 
- 
-  /* write out the function prototypes */ 
-  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) { 
-    /* make the function name C friendly */ 
-    string funname = to_lower_case(initial_caps_to_underscores((*f_iter)->get_name())); 
- 
-    t_function service_function((*f_iter)->get_returntype(), 
-                                service_name_lc + string("_client_") + funname, 
-                                (*f_iter)->get_arglist(), 
-                                (*f_iter)->get_xceptions()); 
-    indent(f_header_) << function_signature(&service_function) << ";" << endl; 
- 
-    t_function send_function(g_type_void, 
-                             service_name_lc + string("_client_send_") + funname, 
-                             (*f_iter)->get_arglist()); 
-    indent(f_header_) << function_signature(&send_function) << ";" << endl; 
- 
-    // implement recv if not a oneway service 
-    if (!(*f_iter)->is_oneway()) { 
-      t_struct noargs(program_); 
-      t_function recv_function((*f_iter)->get_returntype(), 
-                               service_name_lc + string("_client_recv_") + funname, 
-                               &noargs, 
-                               (*f_iter)->get_xceptions()); 
-      indent(f_header_) << function_signature(&recv_function) << ";" << endl; 
-    } 
-  } 
- 
-  /* write out the get/set function prototypes */ 
-  f_header_ << "void " + service_name_lc + "_client_set_property (GObject *object, guint " 
-                                           "property_id, const GValue *value, GParamSpec *pspec);" 
-            << endl; 
-  f_header_ << "void " + service_name_lc + "_client_get_property (GObject *object, guint " 
-                                           "property_id, GValue *value, GParamSpec *pspec);" 
-            << endl; 
- 
-  f_header_ << endl; 
-  // end of header code 
- 
-  // Generate interface method implementations 
-  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) { 
-    /* make the function name C friendly */ 
-    string funname = initial_caps_to_underscores((*f_iter)->get_name()); 
-    t_type* ttype = (*f_iter)->get_returntype(); 
-    t_struct* arglist = (*f_iter)->get_arglist(); 
-    t_struct* xlist = (*f_iter)->get_xceptions(); 
-    bool has_return = !ttype->is_void(); 
-    bool has_args = arglist->get_members().size() == 0; 
-    bool has_xceptions = xlist->get_members().size() == 0; 
- 
-    string params = "(" + this->nspace + service_name_ + "If *iface" 
-                    + (has_return ? ", " + type_name(ttype) + "* _return" : "") 
-                    + (has_args ? "" : (", " + argument_list(arglist))) 
-                    + (has_xceptions ? "" : (", " + xception_list(xlist))) + ", GError **error)"; 
- 
-    string params_without_type = string("iface, ") + (has_return ? "_return, " : ""); 
- 
-    const vector<t_field*>& fields = arglist->get_members(); 
-    vector<t_field*>::const_iterator f_iter_field; 
-    for (f_iter_field = fields.begin(); f_iter_field != fields.end(); ++f_iter_field) { 
-      params_without_type += (*f_iter_field)->get_name(); 
-      params_without_type += ", "; 
-    } 
- 
-    const vector<t_field*>& xceptions = xlist->get_members(); 
-    vector<t_field*>::const_iterator x_iter; 
-    for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) { 
-      params_without_type += (*x_iter)->get_name(); 
-      params_without_type += ", "; 
-    } 
- 
-    f_service_ << "gboolean" << endl << this->nspace_lc << service_name_lc << "_if_" << funname 
-               << " " << params << endl << "{" << endl << "  return " << this->nspace_uc 
-               << service_name_uc << "_IF_GET_INTERFACE (iface)->" << funname << " (" 
-               << params_without_type << "error);" << endl << "}" << endl << endl; 
-  } 
- 
-  // Generate interface boilerplate 
-  f_service_ << "GType" << endl << this->nspace_lc << service_name_lc << "_if_get_type (void)" 
-             << endl << "{" << endl << "  static GType type = 0;" << endl << "  if (type == 0)" 
-             << endl << "  {" << endl << "    static const GTypeInfo type_info =" << endl << "    {" 
-             << endl << "      sizeof (" << this->nspace << service_name_ << "IfInterface)," << endl 
-             << "      NULL,  /* base_init */" << endl << "      NULL,  /* base_finalize */" << endl 
-             << "      NULL,  /* class_init */" << endl << "      NULL,  /* class_finalize */" 
-             << endl << "      NULL,  /* class_data */" << endl 
-             << "      0,     /* instance_size */" << endl << "      0,     /* n_preallocs */" 
-             << endl << "      NULL,  /* instance_init */" << endl 
-             << "      NULL   /* value_table */" << endl << "    };" << endl 
-             << "    type = g_type_register_static (G_TYPE_INTERFACE," << endl 
-             << "                                   \"" << this->nspace << service_name_ << "If\"," 
-             << endl << "                                   &type_info, 0);" << endl << "  }" 
-             << endl << "  return type;" << endl << "}" << endl << endl; 
- 
-  // Generate client boilerplate 
-  f_service_ << "static void " << endl << this->nspace_lc << service_name_lc 
-             << "_if_interface_init (" << this->nspace << service_name_ << "IfInterface *iface);" 
-             << endl << endl << "G_DEFINE_TYPE_WITH_CODE (" << this->nspace << service_name_ 
-             << "Client, " << this->nspace_lc << service_name_lc << "_client," << endl 
-             << "                         " << parent_type_name << ", " << endl 
-             << "                         G_IMPLEMENT_INTERFACE (" << this->nspace_uc << "TYPE_" 
-             << service_name_uc << "_IF," << endl 
-             << "                                                " << this->nspace_lc 
-             << service_name_lc << "_if_interface_init))" << endl << endl; 
- 
-  // Generate property-related code only for base services---child 
-  // service-client classes have only properties inherited from their 
-  // parent class 
-  if (!extends_service) { 
-    // Generate client properties 
-    f_service_ << "enum _" << this->nspace << service_name_ << "ClientProperties" << endl << "{" 
-               << endl << "  PROP_0," << endl << "  PROP_" << this->nspace_uc << service_name_uc 
-               << "_CLIENT_INPUT_PROTOCOL," << endl << "  PROP_" << this->nspace_uc 
-               << service_name_uc << "_CLIENT_OUTPUT_PROTOCOL" << endl << "};" << endl << endl; 
- 
-    // generate property setter 
-    f_service_ << "void" << endl << this->nspace_lc << service_name_lc << "_client_set_property (" 
-               << "GObject *object, guint property_id, const GValue *value, " 
-               << "GParamSpec *pspec)" << endl << "{" << endl << "  " << this->nspace 
-               << service_name_ << "Client *client = " << this->nspace_uc << service_name_uc 
-               << "_CLIENT (object);" << endl << endl << "  THRIFT_UNUSED_VAR (pspec);" << endl 
-               << endl << "  switch (property_id)" << endl << "  {" << endl << "    case PROP_" 
-               << this->nspace_uc << service_name_uc << "_CLIENT_INPUT_PROTOCOL:" << endl 
-               << "      client->input_protocol = g_value_get_object (value);" << endl 
-               << "      break;" << endl << "    case PROP_" << this->nspace_uc << service_name_uc 
-               << "_CLIENT_OUTPUT_PROTOCOL:" << endl 
-               << "      client->output_protocol = g_value_get_object (value);" << endl 
-               << "      break;" << endl << "  }" << endl << "}" << endl << endl; 
- 
-    // generate property getter 
-    f_service_ << "void" << endl << this->nspace_lc << service_name_lc << "_client_get_property (" 
-               << "GObject *object, guint property_id, GValue *value, " 
-               << "GParamSpec *pspec)" << endl << "{" << endl << "  " << this->nspace 
-               << service_name_ << "Client *client = " << this->nspace_uc << service_name_uc 
-               << "_CLIENT (object);" << endl << endl << "  THRIFT_UNUSED_VAR (pspec);" << endl 
-               << endl << "  switch (property_id)" << endl << "  {" << endl << "    case PROP_" 
-               << this->nspace_uc << service_name_uc << "_CLIENT_INPUT_PROTOCOL:" << endl 
-               << "      g_value_set_object (value, client->input_protocol);" << endl 
-               << "      break;" << endl << "    case PROP_" << this->nspace_uc << service_name_uc 
-               << "_CLIENT_OUTPUT_PROTOCOL:" << endl 
-               << "      g_value_set_object (value, client->output_protocol);" << endl 
-               << "      break;" << endl << "  }" << endl << "}" << endl << endl; 
-  } 
- 
-  // Generate client method implementations 
-  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) { 
-    string name = (*f_iter)->get_name(); 
-    string funname = initial_caps_to_underscores(name); 
- 
-    // Get the struct of function call params and exceptions 
-    t_struct* arg_struct = (*f_iter)->get_arglist(); 
- 
-    // Function for sending 
-    t_function send_function(g_type_void, 
-                             service_name_lc + string("_client_send_") + funname, 
-                             (*f_iter)->get_arglist()); 
- 
-    // Open the send function 
-    indent(f_service_) << function_signature(&send_function) << endl; 
-    scope_up(f_service_); 
- 
-    string reqType = (*f_iter)->is_oneway() ? "T_ONEWAY" : "T_CALL"; 
- 
-    // Serialize the request 
-    f_service_ << indent() << "gint32 cseqid = 0;" << endl << indent() 
-               << "ThriftProtocol * protocol = " << this->nspace_uc << base_service_name_uc 
-               << "_CLIENT (iface)->output_protocol;" << endl << endl << indent() 
-               << "if (thrift_protocol_write_message_begin (protocol, \"" << name << "\", " 
-               << reqType << ", cseqid, error) < 0)" << endl << indent() << "  return FALSE;" 
-               << endl << endl; 
- 
-    generate_struct_writer(f_service_, arg_struct, "", "", false); 
- 
-    f_service_ << indent() << "if (thrift_protocol_write_message_end (protocol, error) < 0)" << endl 
-               << indent() << "  return FALSE;" << endl << indent() 
-               << "if (!thrift_transport_flush (protocol->transport, error))" << endl << indent() 
-               << "  return FALSE;" << endl << indent() 
-               << "if (!thrift_transport_write_end (protocol->transport, error))" << endl 
-               << indent() << "  return FALSE;" << endl << endl << indent() << "return TRUE;" 
-               << endl; 
- 
-    scope_down(f_service_); 
-    f_service_ << endl; 
- 
-    // Generate recv function only if not an async function 
-    if (!(*f_iter)->is_oneway()) { 
-      t_struct noargs(program_); 
-      t_function recv_function((*f_iter)->get_returntype(), 
-                               service_name_lc + string("_client_recv_") + funname, 
-                               &noargs, 
-                               (*f_iter)->get_xceptions()); 
-      // Open function 
-      indent(f_service_) << function_signature(&recv_function) << endl; 
-      scope_up(f_service_); 
- 
-      f_service_ << indent() << "gint32 rseqid;" << endl 
-                 << indent() << "gchar * fname = NULL;" << endl 
-                 << indent() << "ThriftMessageType mtype;" << endl 
-                 << indent() << "ThriftProtocol * protocol = " 
-                 << this->nspace_uc << base_service_name_uc 
-                 << "_CLIENT (iface)->input_protocol;" << endl 
-                 << indent() << "ThriftApplicationException *xception;" << endl 
-                 << endl 
-                 << indent() << "if (thrift_protocol_read_message_begin " 
-                    "(protocol, &fname, &mtype, &rseqid, error) < 0) {" << endl; 
-      indent_up(); 
-      f_service_ << indent() << "if (fname) g_free (fname);" << endl 
-                 << indent() << "return FALSE;" << endl; 
-      indent_down(); 
-      f_service_ << indent() << "}" << endl 
-                 << endl 
-                 << indent() << "if (mtype == T_EXCEPTION) {" << endl; 
-      indent_up(); 
-      f_service_ << indent() << "if (fname) g_free (fname);" << endl 
-                 << indent() << "xception = g_object_new " 
-                    "(THRIFT_TYPE_APPLICATION_EXCEPTION, NULL);" << endl 
-                 << indent() << "thrift_struct_read (THRIFT_STRUCT (xception), " 
-                    "protocol, NULL);" << endl 
-                 << indent() << "thrift_protocol_read_message_end " 
-                    "(protocol, NULL);" << endl 
-                 << indent() << "thrift_transport_read_end " 
-                    "(protocol->transport, NULL);" << endl 
-                 << indent() << "g_set_error (error, " 
-                    "THRIFT_APPLICATION_EXCEPTION_ERROR,xception->type, " 
-                    "\"application error: %s\", xception->message);" << endl 
-                 << indent() << "g_object_unref (xception);" << endl 
-                 << indent() << "return FALSE;" << endl; 
-      indent_down(); 
-      f_service_ << indent() << "} else if (mtype != T_REPLY) {" << endl; 
-      indent_up(); 
-      f_service_ << indent() << "if (fname) g_free (fname);" << endl 
-                 << indent() << "thrift_protocol_skip (protocol, T_STRUCT, " 
-                    "NULL);" << endl 
-                 << indent() << "thrift_protocol_read_message_end (protocol, " 
-                    "NULL);" << endl 
-                 << indent() << "thrift_transport_read_end (" 
-                    "protocol->transport, NULL);" << endl 
-                 << indent() << "g_set_error (error, " 
-                    "THRIFT_APPLICATION_EXCEPTION_ERROR, " 
-                    "THRIFT_APPLICATION_EXCEPTION_ERROR_INVALID_MESSAGE_TYPE, " 
-                    "\"invalid message type %d, expected T_REPLY\", mtype);" 
-                 << endl 
-                 << indent() << "return FALSE;" << endl; 
-      indent_down(); 
-      f_service_ << indent() << "} else if (strncmp (fname, \"" << name 
-                 << "\", " << name.length() << ") != 0) {" << endl; 
-      indent_up(); 
-      f_service_ << indent() << "thrift_protocol_skip (protocol, T_STRUCT, " 
-                    "NULL);" << endl 
-                 << indent() << "thrift_protocol_read_message_end (protocol," 
-                    "error);" << endl 
-                 << indent() << "thrift_transport_read_end (" 
-                    "protocol->transport, error);" << endl 
-                 << indent() << "g_set_error (error, " 
-                    "THRIFT_APPLICATION_EXCEPTION_ERROR, " 
-                    "THRIFT_APPLICATION_EXCEPTION_ERROR_WRONG_METHOD_NAME, " 
-                    "\"wrong method name %s, expected " << name 
-                    << "\", fname);" << endl 
-                 << indent() << "if (fname) g_free (fname);" << endl 
-                 << indent() << "return FALSE;" << endl; 
-      indent_down(); 
-      f_service_ << indent() << "}" << endl 
-                 << indent() << "if (fname) g_free (fname);" << endl 
-                 << endl; 
- 
-      t_struct* xs = (*f_iter)->get_xceptions(); 
-      const std::vector<t_field*>& xceptions = xs->get_members(); 
-      vector<t_field*>::const_iterator x_iter; 
- 
-      { 
-        t_struct result(program_, tservice->get_name() + "_" + (*f_iter)->get_name() + "_result"); 
-        t_field success((*f_iter)->get_returntype(), "*_return", 0); 
-        if (!(*f_iter)->get_returntype()->is_void()) { 
-          result.append(&success); 
-        } 
- 
-        // add readers for exceptions, dereferencing the pointer. 
-        for (x_iter = xceptions.begin(); x_iter != xceptions.end(); x_iter++) { 
-          t_field* xception = new t_field((*x_iter)->get_type(), 
-                                          "*" + (*x_iter)->get_name(), 
-                                          (*x_iter)->get_key()); 
-          result.append(xception); 
-        } 
- 
-        generate_struct_reader(f_service_, &result, "", "", false); 
-      } 
- 
-      f_service_ << indent() << "if (thrift_protocol_read_message_end (protocol, error) < 0)" 
-                 << endl << indent() << "  return FALSE;" << endl << endl << indent() 
-                 << "if (!thrift_transport_read_end (protocol->transport, error))" << endl 
-                 << indent() << "  return FALSE;" << endl << endl; 
- 
-      // copy over any throw exceptions and return failure 
-      for (x_iter = xceptions.begin(); x_iter != xceptions.end(); x_iter++) { 
-        f_service_ << indent() << "if (*" << (*x_iter)->get_name() << " != NULL)" << endl 
-                   << indent() << "{" << endl << indent() << "    g_set_error (error, " 
-                   << this->nspace_uc 
-                   << to_upper_case(initial_caps_to_underscores((*x_iter)->get_type()->get_name())) 
-                   << "_ERROR, " << this->nspace_uc 
-                   << to_upper_case(initial_caps_to_underscores((*x_iter)->get_type()->get_name())) 
-                   << "_ERROR_CODE, \"" << (*x_iter)->get_type()->get_name() << "\");" << endl 
-                   << indent() << "    return FALSE;" << endl << indent() << "}" << endl; 
-      } 
-      // Close function 
-      indent(f_service_) << "return TRUE;" << endl; 
-      scope_down(f_service_); 
-      f_service_ << endl; 
-    } 
- 
-    // Open function 
-    t_function service_function((*f_iter)->get_returntype(), 
-                                service_name_lc + string("_client_") + funname, 
-                                (*f_iter)->get_arglist(), 
-                                (*f_iter)->get_xceptions()); 
-    indent(f_service_) << function_signature(&service_function) << endl; 
-    scope_up(f_service_); 
- 
-    // wrap each function 
-    f_service_ << indent() << "if (!" << this->nspace_lc << service_name_lc << "_client_send_" 
-               << funname << " (iface"; 
- 
-    // Declare the function arguments 
-    const vector<t_field*>& fields = arg_struct->get_members(); 
-    vector<t_field*>::const_iterator fld_iter; 
-    for (fld_iter = fields.begin(); fld_iter != fields.end(); ++fld_iter) { 
-      f_service_ << ", " << (*fld_iter)->get_name(); 
-    } 
-    f_service_ << ", error))" << endl << indent() << "  return FALSE;" << endl; 
- 
-    // if not oneway, implement recv 
-    if (!(*f_iter)->is_oneway()) { 
-      string ret = (*f_iter)->get_returntype()->is_void() ? "" : "_return, "; 
- 
-      const vector<t_field*>& xceptions = (*f_iter)->get_xceptions()->get_members(); 
-      vector<t_field*>::const_iterator x_iter; 
-      for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) { 
-        ret += (*x_iter)->get_name(); 
-        ret += ", "; 
-      } 
- 
-      f_service_ << indent() << "if (!" << this->nspace_lc << service_name_lc << "_client_recv_" 
-                 << funname << " (iface, " << ret << "error))" << endl << indent() 
-                 << "  return FALSE;" << endl; 
-    } 
- 
-    // return TRUE which means all functions were called OK 
-    indent(f_service_) << "return TRUE;" << endl; 
-    scope_down(f_service_); 
-    f_service_ << endl; 
-  } 
- 
-  // create the interface initializer 
-  f_service_ << "static void" << endl 
-             << this->nspace_lc << service_name_lc << "_if_interface_init (" 
-             << this->nspace << service_name_ << "IfInterface *iface)" << endl; 
-  scope_up(f_service_); 
-  if (functions.size() > 0) { 
-    for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) { 
-      /* make the function name C friendly */ 
-      string funname = initial_caps_to_underscores((*f_iter)->get_name()); 
- 
-      f_service_ << indent() << "iface->" << funname << " = " << this->nspace_lc 
-                 << service_name_lc << "_client_" << funname << ";" << endl; 
-    } 
-  } 
-  else { 
-    f_service_ << indent() << "THRIFT_UNUSED_VAR (iface);" << endl; 
-  } 
-  scope_down(f_service_); 
-  f_service_ << endl; 
- 
-  // create the client instance initializer 
-  f_service_ << "static void" << endl 
-             << this->nspace_lc << service_name_lc << "_client_init (" 
-             << this->nspace << service_name_ << "Client *client)" << endl; 
-  scope_up(f_service_); 
-  if (!extends_service) { 
-    f_service_ << indent() << "client->input_protocol = NULL;" << endl 
-               << indent() << "client->output_protocol = NULL;" << endl; 
-  } 
-  else { 
-    f_service_ << indent() << "THRIFT_UNUSED_VAR (client);" << endl; 
-  } 
-  scope_down(f_service_); 
-  f_service_ << endl; 
- 
-  // create the client class initializer 
-  f_service_ << "static void" << endl << this->nspace_lc << service_name_lc 
-             << "_client_class_init (" << this->nspace << service_name_ << "ClientClass *cls)" 
-             << endl << "{" << endl; 
-  if (!extends_service) { 
-    f_service_ << "  GObjectClass *gobject_class = G_OBJECT_CLASS (cls);" << endl 
-               << "  GParamSpec *param_spec;" << endl << endl 
-               << "  gobject_class->set_property = " << this->nspace_lc << service_name_lc 
-               << "_client_set_property;" << endl 
-               << "  gobject_class->get_property = " << this->nspace_lc << service_name_lc 
-               << "_client_get_property;" << endl << endl 
-               << "  param_spec = g_param_spec_object (\"input_protocol\"," << endl 
-               << "                                    \"input protocol (construct)\"," << endl 
-               << "                                    \"Set the client input protocol\"," << endl 
-               << "                                    THRIFT_TYPE_PROTOCOL," << endl 
-               << "                                    G_PARAM_READWRITE);" << endl 
-               << "  g_object_class_install_property (gobject_class," << endl 
-               << "                                   PROP_" << this->nspace_uc << service_name_uc 
-               << "_CLIENT_INPUT_PROTOCOL, param_spec);" << endl << endl 
-               << "  param_spec = g_param_spec_object (\"output_protocol\"," << endl 
-               << "                                    \"output protocol (construct)\"," << endl 
-               << "                                    \"Set the client output protocol\"," << endl 
-               << "                                    THRIFT_TYPE_PROTOCOL," << endl 
-               << "                                    G_PARAM_READWRITE);" << endl 
-               << "  g_object_class_install_property (gobject_class," << endl 
-               << "                                   PROP_" << this->nspace_uc << service_name_uc 
-               << "_CLIENT_OUTPUT_PROTOCOL, param_spec);" << endl; 
-  } 
-  else { 
-    f_service_ << "  THRIFT_UNUSED_VAR (cls);" << endl; 
-  } 
-  f_service_ << "}" << endl << endl; 
-} 
- 
-/** 
- * Generates C code that represents a Thrift service handler. 
- * 
- * @param tservice The service for which to generate a handler. 
- */ 
-void t_c_glib_generator::generate_service_handler(t_service* tservice) { 
-  vector<t_function*> functions = tservice->get_functions(); 
-  vector<t_function*>::const_iterator function_iter; 
- 
-  string service_name_lc = to_lower_case(initial_caps_to_underscores(service_name_)); 
-  string service_name_uc = to_upper_case(service_name_lc); 
- 
-  string class_name = this->nspace + service_name_ + "Handler"; 
-  string class_name_lc = to_lower_case(initial_caps_to_underscores(class_name)); 
-  string class_name_uc = to_upper_case(class_name_lc); 
- 
-  string parent_class_name; 
-  string parent_type_name; 
- 
-  string args_indent; 
- 
-  // The service this service extends, or NULL if it extends no service 
-  t_service* extends_service = tservice->get_extends(); 
- 
-  // Determine the name of our parent service (if any) and the handler class' 
-  // parent class name and type 
-  if (extends_service) { 
-    string parent_service_name = extends_service->get_name(); 
-    string parent_service_name_lc = to_lower_case(initial_caps_to_underscores(parent_service_name)); 
-    string parent_service_name_uc = to_upper_case(parent_service_name_lc); 
- 
-    parent_class_name = this->nspace + parent_service_name + "Handler"; 
-    parent_type_name = this->nspace_uc + "TYPE_" + parent_service_name_uc + "_HANDLER"; 
-  } else { 
-    parent_class_name = "GObject"; 
-    parent_type_name = "G_TYPE_OBJECT"; 
-  } 
- 
-  // Generate the handler class' definition in the header file 
- 
-  // Generate the handler instance definition 
-  f_header_ << "/* " << service_name_ << " handler (abstract base class) */" << endl << "struct _" 
-            << class_name << endl << "{" << endl; 
-  indent_up(); 
-  f_header_ << indent() << parent_class_name << " parent;" << endl; 
-  indent_down(); 
-  f_header_ << "};" << endl << "typedef struct _" << class_name << " " << class_name << ";" << endl 
-            << endl; 
- 
-  // Generate the handler class definition, including its class members 
-  // (methods) 
-  f_header_ << "struct _" << class_name << "Class" << endl << "{" << endl; 
-  indent_up(); 
-  f_header_ << indent() << parent_class_name << "Class parent;" << endl << endl; 
- 
-  for (function_iter = functions.begin(); function_iter != functions.end(); ++function_iter) { 
-    string method_name = initial_caps_to_underscores((*function_iter)->get_name()); 
-    t_type* return_type = (*function_iter)->get_returntype(); 
-    t_struct* arg_list = (*function_iter)->get_arglist(); 
-    t_struct* x_list = (*function_iter)->get_xceptions(); 
-    bool has_return = !return_type->is_void(); 
-    bool has_args = arg_list->get_members().size() == 0; 
-    bool has_xceptions = x_list->get_members().size() == 0; 
- 
-    string params = "(" + this->nspace + service_name_ + "If *iface" 
-                    + (has_return ? ", " + type_name(return_type) + "* _return" : "") 
-                    + (has_args ? "" : (", " + argument_list(arg_list))) 
-                    + (has_xceptions ? "" : (", " + xception_list(x_list))) + ", GError **error)"; 
- 
-    indent(f_header_) << "gboolean (*" << method_name << ") " << params << ";" << endl; 
-  } 
-  indent_down(); 
- 
-  f_header_ << "};" << endl << "typedef struct _" << class_name << "Class " << class_name 
-            << "Class;" << endl << endl; 
- 
-  // Generate the remaining header boilerplate 
-  f_header_ << "GType " << class_name_lc << "_get_type (void);" << endl << "#define " 
-            << this->nspace_uc << "TYPE_" << service_name_uc << "_HANDLER " 
-            << "(" << class_name_lc << "_get_type())" << endl << "#define " << class_name_uc 
-            << "(obj) " 
-            << "(G_TYPE_CHECK_INSTANCE_CAST ((obj), " << this->nspace_uc << "TYPE_" 
-            << service_name_uc << "_HANDLER, " << class_name << "))" << endl << "#define " 
-            << this->nspace_uc << "IS_" << service_name_uc << "_HANDLER(obj) " 
-            << "(G_TYPE_CHECK_INSTANCE_TYPE ((obj), " << this->nspace_uc << "TYPE_" 
-            << service_name_uc << "_HANDLER))" << endl << "#define " << class_name_uc 
-            << "_CLASS(c) (G_TYPE_CHECK_CLASS_CAST ((c), " << this->nspace_uc << "TYPE_" 
-            << service_name_uc << "_HANDLER, " << class_name << "Class))" << endl << "#define " 
-            << this->nspace_uc << "IS_" << service_name_uc << "_HANDLER_CLASS(c) " 
-            << "(G_TYPE_CHECK_CLASS_TYPE ((c), " << this->nspace_uc << "TYPE_" << service_name_uc 
-            << "_HANDLER))" << endl << "#define " << this->nspace_uc << service_name_uc 
-            << "_HANDLER_GET_CLASS(obj) " 
-            << "(G_TYPE_INSTANCE_GET_CLASS ((obj), " << this->nspace_uc << "TYPE_" 
-            << service_name_uc << "_HANDLER, " << class_name << "Class))" << endl << endl; 
- 
-  // Generate the handler class' method definitions 
-  for (function_iter = functions.begin(); function_iter != functions.end(); ++function_iter) { 
-    string method_name = initial_caps_to_underscores((*function_iter)->get_name()); 
-    t_type* return_type = (*function_iter)->get_returntype(); 
-    t_struct* arg_list = (*function_iter)->get_arglist(); 
-    t_struct* x_list = (*function_iter)->get_xceptions(); 
-    bool has_return = !return_type->is_void(); 
-    bool has_args = arg_list->get_members().size() == 0; 
-    bool has_xceptions = x_list->get_members().size() == 0; 
- 
-    string params = "(" + this->nspace + service_name_ + "If *iface" 
-                    + (has_return ? ", " + type_name(return_type) + "* _return" : "") 
-                    + (has_args ? "" : (", " + argument_list(arg_list))) 
-                    + (has_xceptions ? "" : (", " + xception_list(x_list))) + ", GError **error)"; 
- 
-    f_header_ << "gboolean " << class_name_lc << "_" << method_name << " " << params << ";" << endl; 
-  } 
-  f_header_ << endl; 
- 
-  // Generate the handler's implementation in the implementation file 
- 
-  // Generate the implementation boilerplate 
-  f_service_ << "static void" << endl << class_name_lc << "_" << service_name_lc 
-             << "_if_interface_init (" << this->nspace << service_name_ << "IfInterface *iface);" 
-             << endl << endl; 
- 
-  args_indent = string(25, ' '); 
-  f_service_ << "G_DEFINE_TYPE_WITH_CODE (" << class_name << ", " << endl << args_indent 
-             << class_name_lc << "," << endl << args_indent << parent_type_name << "," << endl 
-             << args_indent << "G_IMPLEMENT_INTERFACE (" << this->nspace_uc << "TYPE_" 
-             << service_name_uc << "_IF," << endl; 
-  args_indent += string(23, ' '); 
-  f_service_ << args_indent << class_name_lc << "_" << service_name_lc << "_if_interface_init))" 
-             << endl << endl; 
- 
-  // Generate the handler method implementations 
-  for (function_iter = functions.begin(); function_iter != functions.end(); ++function_iter) { 
-    string function_name = (*function_iter)->get_name(); 
-    string method_name = initial_caps_to_underscores(function_name); 
-    t_type* return_type = (*function_iter)->get_returntype(); 
-    t_struct* arg_list = (*function_iter)->get_arglist(); 
-    t_struct* x_list = (*function_iter)->get_xceptions(); 
- 
-    const vector<t_field*>& args = arg_list->get_members(); 
-    const vector<t_field*>& xceptions = x_list->get_members(); 
- 
-    vector<t_field*>::const_iterator field_iter; 
- 
-    t_function implementing_function(return_type, 
-                                     service_name_lc + "_handler_" + method_name, 
-                                     arg_list, 
-                                     x_list, 
-                                     (*function_iter)->is_oneway()); 
- 
-    indent(f_service_) << function_signature(&implementing_function) << endl; 
-    scope_up(f_service_); 
-    f_service_ << indent() << "g_return_val_if_fail (" << this->nspace_uc << "IS_" 
-               << service_name_uc << "_HANDLER (iface), FALSE);" << endl << endl << indent() 
-               << "return " << class_name_uc << "_GET_CLASS (iface)" 
-               << "->" << method_name << " (iface, "; 
- 
-    if (!return_type->is_void()) { 
-      f_service_ << "_return, "; 
-    } 
-    for (field_iter = args.begin(); field_iter != args.end(); ++field_iter) { 
-      f_service_ << (*field_iter)->get_name() << ", "; 
-    } 
-    for (field_iter = xceptions.begin(); field_iter != xceptions.end(); ++field_iter) { 
-      f_service_ << (*field_iter)->get_name() << ", "; 
-    } 
-    f_service_ << "error);" << endl; 
-    scope_down(f_service_); 
-    f_service_ << endl; 
-  } 
- 
-  // Generate the handler interface initializer 
-  f_service_ << "static void" << endl << class_name_lc << "_" << service_name_lc 
-             << "_if_interface_init (" << this->nspace << service_name_ << "IfInterface *iface)" 
-             << endl; 
-  scope_up(f_service_); 
-  if (functions.size() > 0) { 
-    for (function_iter = functions.begin(); function_iter != functions.end(); ++function_iter) { 
-      string method_name = initial_caps_to_underscores((*function_iter)->get_name()); 
- 
-      f_service_ << indent() << "iface->" << method_name << " = " << class_name_lc << "_" 
-                 << method_name << ";" << endl; 
-    } 
-  } 
-  else { 
-    f_service_ << "THRIFT_UNUSED_VAR (iface);" << endl; 
-  } 
-  scope_down(f_service_); 
-  f_service_ << endl; 
- 
-  // Generate the handler instance initializer 
-  f_service_ << "static void" << endl << class_name_lc << "_init (" << class_name << " *self)" 
-             << endl; 
-  scope_up(f_service_); 
-  f_service_ << indent() << "THRIFT_UNUSED_VAR (self);" << endl; 
-  scope_down(f_service_); 
-  f_service_ << endl; 
- 
-  // Generate the handler class initializer 
-  f_service_ << "static void" << endl 
-             << class_name_lc << "_class_init (" << class_name << "Class *cls)" 
-             << endl; 
-  scope_up(f_service_); 
-  if (functions.size() > 0) { 
-    for (function_iter = functions.begin(); 
-         function_iter != functions.end(); 
-         ++function_iter) { 
-      string function_name = (*function_iter)->get_name(); 
-      string method_name = initial_caps_to_underscores(function_name); 
- 
-      // All methods are pure virtual and must be implemented by subclasses 
-      f_service_ << indent() << "cls->" << method_name << " = NULL;" << endl; 
-    } 
-  } 
-  else { 
-    f_service_ << indent() << "THRIFT_UNUSED_VAR (cls);" << endl; 
-  } 
-  scope_down(f_service_); 
-  f_service_ << endl; 
-} 
- 
-/** 
- * Generates C code that represents a Thrift service processor. 
- * 
- * @param tservice The service for which to generate a processor 
- */ 
-void t_c_glib_generator::generate_service_processor(t_service* tservice) { 
-  vector<t_function*> functions = tservice->get_functions(); 
-  vector<t_function*>::const_iterator function_iter; 
- 
-  string service_name_lc = to_lower_case(initial_caps_to_underscores(service_name_)); 
-  string service_name_uc = to_upper_case(service_name_lc); 
- 
-  string class_name = this->nspace + service_name_ + "Processor"; 
-  string class_name_lc = to_lower_case(initial_caps_to_underscores(class_name)); 
-  string class_name_uc = to_upper_case(class_name_lc); 
- 
-  string parent_class_name; 
-  string parent_type_name; 
- 
-  string handler_class_name = this->nspace + service_name_ + "Handler"; 
-  string handler_class_name_lc = initial_caps_to_underscores(handler_class_name); 
- 
-  string process_function_type_name = class_name + "ProcessFunction"; 
-  string process_function_def_type_name = 
-    class_name_lc + "_process_function_def"; 
- 
-  string function_name; 
-  string args_indent; 
- 
-  // The service this service extends, or NULL if it extends no service 
-  t_service* extends_service = tservice->get_extends(); 
- 
-  // Determine the name of our parent service (if any) and the 
-  // processor class' parent class name and type 
-  if (extends_service) { 
-    string parent_service_name = extends_service->get_name(); 
-    string parent_service_name_lc = to_lower_case(initial_caps_to_underscores(parent_service_name)); 
-    string parent_service_name_uc = to_upper_case(parent_service_name_lc); 
- 
-    parent_class_name = this->nspace + parent_service_name + "Processor"; 
-    parent_type_name = this->nspace_uc + "TYPE_" + parent_service_name_uc + "_PROCESSOR"; 
-  } else { 
-    parent_class_name = "ThriftDispatchProcessor"; 
-    parent_type_name = "THRIFT_TYPE_DISPATCH_PROCESSOR"; 
-  } 
- 
-  // Generate the processor class' definition in the header file 
- 
-  // Generate the processor instance definition 
-  f_header_ << "/* " << service_name_ << " processor */" << endl << "struct _" << class_name << endl 
-            << "{" << endl; 
-  indent_up(); 
-  f_header_ << indent() << parent_class_name << " parent;" << endl << endl << indent() 
-            << "/* protected */" << endl << indent() 
-            << this->nspace + service_name_ + "Handler *handler;" << endl << indent() 
-            << "GHashTable *process_map;" << endl; 
-  indent_down(); 
-  f_header_ << "};" << endl << "typedef struct _" << class_name << " " << class_name << ";" << endl 
-            << endl; 
- 
-  // Generate the processor class definition 
-  f_header_ << "struct _" << class_name << "Class" << endl << "{" << endl; 
-  indent_up(); 
-  f_header_ << indent() << parent_class_name << "Class parent;" << endl << endl << indent() 
-            << "/* protected */" << endl << indent() 
-            << "gboolean (*dispatch_call) (ThriftDispatchProcessor *processor," << endl; 
-  args_indent = indent() + string(27, ' '); 
-  f_header_ << args_indent << "ThriftProtocol *in," << endl << args_indent << "ThriftProtocol *out," 
-            << endl << args_indent << "gchar *fname," << endl << args_indent << "gint32 seqid," 
-            << endl << args_indent << "GError **error);" << endl; 
-  indent_down(); 
-  f_header_ << "};" << endl << "typedef struct _" << class_name << "Class " << class_name 
-            << "Class;" << endl << endl; 
- 
-  // Generate the remaining header boilerplate 
-  f_header_ << "GType " << class_name_lc << "_get_type (void);" << endl << "#define " 
-            << this->nspace_uc << "TYPE_" << service_name_uc << "_PROCESSOR " 
-            << "(" << class_name_lc << "_get_type())" << endl << "#define " << class_name_uc 
-            << "(obj) " 
-            << "(G_TYPE_CHECK_INSTANCE_CAST ((obj), " << this->nspace_uc << "TYPE_" 
-            << service_name_uc << "_PROCESSOR, " << class_name << "))" << endl << "#define " 
-            << this->nspace_uc << "IS_" << service_name_uc << "_PROCESSOR(obj) " 
-            << "(G_TYPE_CHECK_INSTANCE_TYPE ((obj), " << this->nspace_uc << "TYPE_" 
-            << service_name_uc << "_PROCESSOR))" << endl << "#define " << class_name_uc 
-            << "_CLASS(c) (G_TYPE_CHECK_CLASS_CAST ((c), " << this->nspace_uc << "TYPE_" 
-            << service_name_uc << "_PROCESSOR, " << class_name << "Class))" << endl << "#define " 
-            << this->nspace_uc << "IS_" << service_name_uc << "_PROCESSOR_CLASS(c) " 
-            << "(G_TYPE_CHECK_CLASS_TYPE ((c), " << this->nspace_uc << "TYPE_" << service_name_uc 
-            << "_PROCESSOR))" << endl << "#define " << this->nspace_uc << service_name_uc 
-            << "_PROCESSOR_GET_CLASS(obj) " 
-            << "(G_TYPE_INSTANCE_GET_CLASS ((obj), " << this->nspace_uc << "TYPE_" 
-            << service_name_uc << "_PROCESSOR, " << class_name << "Class))" << endl << endl; 
- 
-  // Generate the processor's implementation in the implementation file 
- 
-  // Generate the processor's properties enum 
-  f_service_ << "enum _" << class_name << "Properties" << endl << "{" << endl; 
-  indent_up(); 
-  f_service_ << indent() << "PROP_" << class_name_uc << "_0," << endl << indent() << "PROP_" 
-             << class_name_uc << "_HANDLER" << endl; 
-  indent_down(); 
-  f_service_ << "};" << endl << endl; 
- 
-  // Generate the implementation boilerplate 
-  args_indent = string(15, ' '); 
-  f_service_ << "G_DEFINE_TYPE (" << class_name << "," << endl << args_indent << class_name_lc 
-             << "," << endl << args_indent << parent_type_name << ")" << endl << endl; 
- 
-  // Generate the processor's processing-function type 
-  args_indent = string(process_function_type_name.length() + 23, ' '); 
-  f_service_ << "typedef gboolean (* " << process_function_type_name << ") (" 
-             << class_name << " *, " << endl 
-             << args_indent << "gint32," << endl 
-             << args_indent << "ThriftProtocol *," << endl 
-             << args_indent << "ThriftProtocol *," << endl 
-             << args_indent << "GError **);" << endl 
-             << endl; 
- 
-  // Generate the processor's processing-function-definition type 
-  f_service_ << "typedef struct" << endl 
-             << "{" << endl; 
-  indent_up(); 
-  f_service_ << indent() << "gchar *name;" << endl 
-             << indent() << process_function_type_name << " function;" << endl; 
-  indent_down(); 
-  f_service_ << "} " << process_function_def_type_name << ";" << endl 
-             << endl; 
- 
-  // Generate forward declarations of the processor's processing functions so we 
-  // can refer to them in the processing-function-definition struct below and 
-  // keep all of the processor's declarations in one place 
-  for (function_iter = functions.begin(); 
-       function_iter != functions.end(); 
-       ++function_iter) { 
-    function_name = class_name_lc + "_process_" 
-      + initial_caps_to_underscores((*function_iter)->get_name()); 
- 
-    args_indent = string(function_name.length() + 2, ' '); 
-    f_service_ << "static gboolean" << endl 
-               << function_name << " (" 
-               << class_name << " *," << endl 
-               << args_indent << "gint32," << endl 
-               << args_indent << "ThriftProtocol *," << endl 
-               << args_indent << "ThriftProtocol *," << endl 
-               << args_indent << "GError **);" << endl; 
-  } 
-  f_service_ << endl; 
- 
-  // Generate the processor's processing-function definitions, if the service 
-  // defines any methods 
-  if (functions.size() > 0) { 
-    f_service_ << indent() << "static " << process_function_def_type_name 
-               << endl 
-               << indent() << class_name_lc << "_process_function_defs[" 
-               << functions.size() << "] = {" << endl; 
-    indent_up(); 
-    for (function_iter = functions.begin(); 
-         function_iter != functions.end(); 
-         ++function_iter) { 
-      string service_function_name = (*function_iter)->get_name(); 
-      string process_function_name = class_name_lc + "_process_" 
-        + initial_caps_to_underscores(service_function_name); 
- 
-      f_service_ << indent() << "{" << endl; 
-      indent_up(); 
-      f_service_ << indent() << "\"" << service_function_name << "\"," << endl 
-                 << indent() << process_function_name << endl; 
-      indent_down(); 
-      f_service_ << indent() << "}" 
-                 << (function_iter == --functions.end() ? "" : ",") << endl; 
-    } 
-    indent_down(); 
-    f_service_ << indent() << "};" << endl 
-               << endl; 
-  } 
- 
-  // Generate the processor's processing functions 
-  for (function_iter = functions.begin(); function_iter != functions.end(); ++function_iter) { 
-    string service_function_name = (*function_iter)->get_name(); 
-    string service_function_name_ic = underscores_to_initial_caps(service_function_name); 
-    string service_function_name_lc = initial_caps_to_underscores(service_function_name); 
-    string service_function_name_uc = to_upper_case(service_function_name_lc); 
- 
-    t_type* return_type = (*function_iter)->get_returntype(); 
-    bool has_return_value = !return_type->is_void(); 
- 
-    t_struct* arg_list = (*function_iter)->get_arglist(); 
-    const vector<t_field*>& args = arg_list->get_members(); 
-    vector<t_field*>::const_iterator arg_iter; 
- 
-    const vector<t_field*>& xceptions = (*function_iter)->get_xceptions()->get_members(); 
-    vector<t_field*>::const_iterator xception_iter; 
- 
-    string args_class_name = this->nspace + service_name_ + service_function_name_ic + "Args"; 
-    string args_class_type = this->nspace_uc + "TYPE_" + service_name_uc + "_" 
-                             + service_function_name_uc + "_ARGS"; 
- 
-    string result_class_name = this->nspace + service_name_ + service_function_name_ic + "Result"; 
-    string result_class_type = this->nspace_uc + "TYPE_" + service_name_uc + "_" 
-                               + service_function_name_uc + "_RESULT"; 
- 
-    string handler_function_name = handler_class_name_lc + "_" + service_function_name_lc; 
- 
-    function_name = class_name_lc + "_process_" 
-                    + initial_caps_to_underscores(service_function_name); 
- 
-    args_indent = string(function_name.length() + 2, ' '); 
-    f_service_ << "static gboolean" << endl << function_name << " (" << class_name << " *self," 
-               << endl << args_indent << "gint32 sequence_id," << endl << args_indent 
-               << "ThriftProtocol *input_protocol," << endl << args_indent 
-               << "ThriftProtocol *output_protocol," << endl << args_indent << "GError **error)" 
-               << endl; 
-    scope_up(f_service_); 
-    f_service_ << indent() << "gboolean result = TRUE;" << endl 
-               << indent() << "ThriftTransport * transport;" << endl 
-               << indent() << "ThriftApplicationException *xception;" << endl 
-               << indent() << args_class_name + " * args =" << endl; 
-    indent_up(); 
-    f_service_ << indent() << "g_object_new (" << args_class_type << ", NULL);" << endl << endl; 
-    indent_down(); 
-    if ((*function_iter)->is_oneway()) { 
-      f_service_ << indent() << "THRIFT_UNUSED_VAR (sequence_id);" << endl << indent() 
-                 << "THRIFT_UNUSED_VAR (output_protocol);" << endl << endl; 
-    } 
-    f_service_ << indent() << "g_object_get (input_protocol, \"transport\", " 
-               << "&transport, NULL);" << endl << endl; 
- 
-    // Read the method's arguments from the caller 
-    f_service_ << indent() << "if ((thrift_struct_read (THRIFT_STRUCT (args), " 
-               << "input_protocol, error) != -1) &&" << endl << indent() 
-               << "    (thrift_protocol_read_message_end (input_protocol, " 
-               << "error) != -1) &&" << endl << indent() 
-               << "    (thrift_transport_read_end (transport, error) != FALSE))" << endl; 
-    scope_up(f_service_); 
- 
-    for (arg_iter = args.begin(); arg_iter != args.end(); ++arg_iter) { 
-      f_service_ << indent() << property_type_name((*arg_iter)->get_type()) << " " 
-                 << (*arg_iter)->get_name() << ";" << endl; 
-    } 
-    for (xception_iter = xceptions.begin(); xception_iter != xceptions.end(); ++xception_iter) { 
-      f_service_ << indent() << type_name((*xception_iter)->get_type()) << " " 
-                 << initial_caps_to_underscores((*xception_iter)->get_name()) << " = NULL;" << endl; 
-    } 
-    if (has_return_value) { 
-      f_service_ << indent() << property_type_name(return_type) << " return_value;" << endl; 
-    } 
-    if (!(*function_iter)->is_oneway()) { 
-      f_service_ << indent() << result_class_name << " * result_struct;" << endl; 
-    } 
-    f_service_ << endl; 
- 
-    if (args.size() > 0) { 
-      f_service_ << indent() << "g_object_get (args," << endl; 
-      args_indent = indent() + string(14, ' '); 
-      for (arg_iter = args.begin(); arg_iter != args.end(); ++arg_iter) { 
-        string arg_name = (*arg_iter)->get_name(); 
- 
-        f_service_ << args_indent << "\"" << arg_name << "\", &" << arg_name << "," << endl; 
-      } 
-      f_service_ << args_indent << "NULL);" << endl << endl; 
-    } 
- 
-    if (!(*function_iter)->is_oneway()) { 
-      f_service_ << indent() << "g_object_unref (transport);" << endl << indent() 
-                 << "g_object_get (output_protocol, \"transport\", " 
-                 << "&transport, NULL);" << endl << endl << indent() 
-                 << "result_struct = g_object_new (" << result_class_type << ", NULL);" << endl; 
-      if (has_return_value) { 
-        f_service_ << indent() << "g_object_get (result_struct, " 
-                                  "\"success\", &return_value, NULL);" << endl; 
-      } 
-      f_service_ << endl; 
-    } 
- 
-    // Pass the arguments to the corresponding method in the handler 
-    f_service_ << indent() << "if (" << handler_function_name << " (" << this->nspace_uc 
-               << service_name_uc << "_IF (self->handler)," << endl; 
-    args_indent = indent() + string(handler_function_name.length() + 6, ' '); 
-    if (has_return_value) { 
-      string return_type_name = type_name(return_type); 
- 
-      f_service_ << args_indent; 
- 
-      // Cast return_value if it was declared as a type other than the return 
-      // value's actual type---this is true for integer values 32 bits or fewer 
-      // in width, for which GLib requires a plain gint type be used when 
-      // storing or retrieving as an object property 
-      if (return_type_name != property_type_name(return_type)) { 
-        if (return_type_name[return_type_name.length() - 1] != '*') { 
-          return_type_name += ' '; 
-        } 
-        return_type_name += '*'; 
- 
-        f_service_ << "(" << return_type_name << ")"; 
-      } 
- 
-      f_service_ << "&return_value," << endl; 
-    } 
-    for (arg_iter = args.begin(); arg_iter != args.end(); ++arg_iter) { 
-      f_service_ << args_indent << (*arg_iter)->get_name() << "," << endl; 
-    } 
-    for (xception_iter = xceptions.begin(); xception_iter != xceptions.end(); ++xception_iter) { 
-      f_service_ << args_indent << "&" << initial_caps_to_underscores((*xception_iter)->get_name()) 
-                 << "," << endl; 
-    } 
-    f_service_ << args_indent << "error) == TRUE)" << endl; 
-    scope_up(f_service_); 
- 
-    // The handler reported success; return the result, if any, to the caller 
-    if (!(*function_iter)->is_oneway()) { 
-      if (has_return_value) { 
-        f_service_ << indent() << "g_object_set (result_struct, \"success\", "; 
-        if (type_name(return_type) != property_type_name(return_type)) { 
-          // Roundtrip cast to fix the position of sign bit. 
-          f_service_ << "(" << property_type_name(return_type) << ")" 
-                     << "(" << type_name(return_type) << ")"; 
-        } 
-        f_service_ << "return_value, " 
-                   << "NULL);" << endl; 
- 
-        // Deallocate (or unref) return_value 
-        return_type = get_true_type(return_type); 
-        if (return_type->is_base_type()) { 
-          t_base_type* base_type = ((t_base_type*)return_type); 
- 
-          if (base_type->get_base() == t_base_type::TYPE_STRING) { 
-            f_service_ << indent() << "if (return_value != NULL)" << endl; 
-            indent_up(); 
-            if (base_type->is_binary()) { 
-              f_service_ << indent() << "g_byte_array_unref (return_value);" << endl; 
-            } else { 
-              f_service_ << indent() << "g_free (return_value);" << endl; 
-            } 
-            indent_down(); 
-          } 
-        } else if (return_type->is_container()) { 
-          f_service_ << indent() << "if (return_value != NULL)" << endl; 
-          indent_up(); 
- 
-          if (return_type->is_list()) { 
-            t_type* elem_type = ((t_list*)return_type)->get_elem_type(); 
- 
-            f_service_ << indent(); 
-            if (is_numeric(elem_type)) { 
-              f_service_ << "g_array_unref"; 
-            } else { 
-              f_service_ << "g_ptr_array_unref"; 
-            } 
-            f_service_ << " (return_value);" << endl; 
-          } else if (return_type->is_map() || return_type->is_set()) { 
-            f_service_ << indent() << "g_hash_table_unref (return_value);" << endl; 
-          } 
- 
-          indent_down(); 
-        } else if (return_type->is_struct()) { 
-          f_service_ << indent() << "if (return_value != NULL)" << endl; 
-          indent_up(); 
-          f_service_ << indent() << "g_object_unref (return_value);" << endl; 
-          indent_down(); 
-        } 
- 
-        f_service_ << endl; 
-      } 
-      f_service_ << indent() << "result =" << endl; 
-      indent_up(); 
-      f_service_ << indent() << "((thrift_protocol_write_message_begin (output_protocol," << endl; 
-      args_indent = indent() + string(39, ' '); 
-      f_service_ << args_indent << "\"" << service_function_name << "\"," << endl << args_indent 
-                 << "T_REPLY," << endl << args_indent << "sequence_id," << endl << args_indent 
-                 << "error) != -1) &&" << endl << indent() 
-                 << " (thrift_struct_write (THRIFT_STRUCT (result_struct)," << endl; 
-      args_indent = indent() + string(23, ' '); 
-      f_service_ << args_indent << "output_protocol," << endl << args_indent << "error) != -1));" 
-                 << endl; 
-      indent_down(); 
-    } 
-    scope_down(f_service_); 
-    f_service_ << indent() << "else" << endl; 
-    scope_up(f_service_); 
- 
-    // The handler reported failure; check to see if an application-defined 
-    // exception was raised and if so, return it to the caller 
-    f_service_ << indent(); 
-    if (xceptions.size() > 0) { 
-      for (xception_iter = xceptions.begin(); xception_iter != xceptions.end(); ++xception_iter) { 
-        f_service_ << "if (" << initial_caps_to_underscores((*xception_iter)->get_name()) 
-                   << " != NULL)" << endl; 
-        scope_up(f_service_); 
-        f_service_ << indent() << "g_object_set (result_struct," << endl; 
-        args_indent = indent() + string(14, ' '); 
-        f_service_ << args_indent << "\"" << (*xception_iter)->get_name() << "\", " 
-                   << (*xception_iter)->get_name() << "," << endl << args_indent << "NULL);" << endl 
-                   << endl; 
-        f_service_ << indent() << "result =" << endl; 
-        indent_up(); 
-        f_service_ << indent() << "((thrift_protocol_write_message_begin (output_protocol," << endl; 
-        args_indent = indent() + string(39, ' '); 
-        f_service_ << args_indent << "\"" << service_function_name << "\"," << endl << args_indent 
-                   << "T_REPLY," << endl << args_indent << "sequence_id," << endl << args_indent 
-                   << "error) != -1) &&" << endl << indent() 
-                   << " (thrift_struct_write (THRIFT_STRUCT (result_struct)," << endl; 
-        args_indent = indent() + string(23, ' '); 
-        f_service_ << args_indent << "output_protocol," << endl << args_indent << "error) != -1));" 
-                   << endl; 
-        indent_down(); 
-        scope_down(f_service_); 
-        f_service_ << indent() << "else" << endl; 
-      } 
- 
-      scope_up(f_service_); 
-      f_service_ << indent(); 
-    } 
- 
-    // If the handler reported failure but raised no application-defined 
-    // exception, return a Thrift application exception with the information 
-    // returned via GLib's own error-reporting mechanism 
-    f_service_ << "if (*error == NULL)" << endl; 
-    indent_up(); 
-    f_service_ << indent() << "g_warning (\"" << service_name_ << "." 
-               << (*function_iter)->get_name() << " implementation returned FALSE \"" << endl 
-               << indent() << string(11, ' ') << "\"but did not set an error\");" << endl << endl; 
-    indent_down(); 
-    f_service_ << indent() << "xception =" << endl; 
-    indent_up(); 
-    f_service_ << indent() << "g_object_new (THRIFT_TYPE_APPLICATION_EXCEPTION," << endl; 
-    args_indent = indent() + string(14, ' '); 
-    f_service_ << args_indent << "\"type\",    *error != NULL ? (*error)->code :" << endl 
-               << args_indent << string(11, ' ') << "THRIFT_APPLICATION_EXCEPTION_ERROR_UNKNOWN," 
-               << endl << args_indent << "\"message\", *error != NULL ? (*error)->message : NULL," 
-               << endl << args_indent << "NULL);" << endl; 
-    indent_down(); 
-    f_service_ << indent() << "g_clear_error (error);" << endl << endl << indent() 
-               << "result =" << endl; 
-    indent_up(); 
-    f_service_ << indent() << "((thrift_protocol_write_message_begin (output_protocol," << endl; 
-    args_indent = indent() + string(39, ' '); 
-    f_service_ << args_indent << "\"" << service_function_name << "\"," << endl << args_indent 
-               << "T_EXCEPTION," << endl << args_indent << "sequence_id," << endl << args_indent 
-               << "error) != -1) &&" << endl << indent() 
-               << " (thrift_struct_write (THRIFT_STRUCT (xception)," << endl; 
-    args_indent = indent() + string(23, ' '); 
-    f_service_ << args_indent << "output_protocol," << endl << args_indent << "error) != -1));" 
-               << endl; 
-    indent_down(); 
-    f_service_ << endl << indent() << "g_object_unref (xception);" << endl; 
- 
-    if (xceptions.size() > 0) { 
-      scope_down(f_service_); 
-    } 
-    scope_down(f_service_); 
-    f_service_ << endl; 
- 
-    // Dellocate or unref retrieved argument values as necessary 
-    for (arg_iter = args.begin(); arg_iter != args.end(); ++arg_iter) { 
-      string arg_name = (*arg_iter)->get_name(); 
-      t_type* arg_type = get_true_type((*arg_iter)->get_type()); 
- 
-      if (arg_type->is_base_type()) { 
-        t_base_type* base_type = ((t_base_type*)arg_type); 
- 
-        if (base_type->get_base() == t_base_type::TYPE_STRING) { 
-          f_service_ << indent() << "if (" << arg_name << " != NULL)" << endl; 
-          indent_up(); 
-          if (base_type->is_binary()) { 
-            f_service_ << indent() << "g_byte_array_unref (" << arg_name << ");" << endl; 
-          } else { 
-            f_service_ << indent() << "g_free (" << arg_name << ");" << endl; 
-          } 
-          indent_down(); 
-        } 
-      } else if (arg_type->is_container()) { 
-        f_service_ << indent() << "if (" << arg_name << " != NULL)" << endl; 
-        indent_up(); 
- 
-        if (arg_type->is_list()) { 
-          t_type* elem_type = ((t_list*)arg_type)->get_elem_type(); 
- 
-          f_service_ << indent(); 
-          if (is_numeric(elem_type)) { 
-            f_service_ << "g_array_unref"; 
-          } else { 
-            f_service_ << "g_ptr_array_unref"; 
-          } 
-          f_service_ << " (" << arg_name << ");" << endl; 
-        } else if (arg_type->is_map() || arg_type->is_set()) { 
-          f_service_ << indent() << "g_hash_table_unref (" << arg_name << ");" << endl; 
-        } 
- 
-        indent_down(); 
-      } else if (arg_type->is_struct()) { 
-        f_service_ << indent() << "if (" << arg_name << " != NULL)" << endl; 
-        indent_up(); 
-        f_service_ << indent() << "g_object_unref (" << arg_name << ");" << endl; 
-        indent_down(); 
-      } 
-    } 
- 
-    if (!(*function_iter)->is_oneway()) { 
-      f_service_ << indent() << "g_object_unref (result_struct);" << endl << endl << indent() 
-                 << "if (result == TRUE)" << endl; 
-      indent_up(); 
-      f_service_ << indent() << "result =" << endl; 
-      indent_up(); 
-      f_service_ << indent() << "((thrift_protocol_write_message_end " 
-                 << "(output_protocol, error) != -1) &&" << endl << indent() 
-                 << " (thrift_transport_write_end (transport, error) " 
-                 << "!= FALSE) &&" << endl << indent() 
-                 << " (thrift_transport_flush (transport, error) " 
-                 << "!= FALSE));" << endl; 
-      indent_down(); 
-      indent_down(); 
-    } 
-    scope_down(f_service_); 
-    f_service_ << indent() << "else" << endl; 
-    indent_up(); 
-    f_service_ << indent() << "result = FALSE;" << endl; 
-    indent_down(); 
- 
-    f_service_ << endl << indent() << "g_object_unref (transport);" << endl << indent() 
-               << "g_object_unref (args);" << endl << endl << indent() << "return result;" << endl; 
-    scope_down(f_service_); 
- 
-    f_service_ << endl; 
-  } 
- 
-  // Generate the processor's dispatch_call implementation 
-  function_name = class_name_lc + "_dispatch_call"; 
-  args_indent = indent() + string(function_name.length() + 2, ' '); 
-  f_service_ << "static gboolean" << endl << function_name 
-             << " (ThriftDispatchProcessor *dispatch_processor," << endl << args_indent 
-             << "ThriftProtocol *input_protocol," << endl << args_indent 
-             << "ThriftProtocol *output_protocol," << endl << args_indent << "gchar *method_name," 
-             << endl << args_indent << "gint32 sequence_id," << endl << args_indent 
-             << "GError **error)" << endl; 
-  scope_up(f_service_); 
-  f_service_ << indent() << class_name_lc << "_process_function_def *" 
-             << "process_function_def;" << endl; 
-  f_service_ << indent() << "gboolean dispatch_result = FALSE;" << endl << endl << indent() 
-             << class_name << " *self = " << class_name_uc << " (dispatch_processor);" << endl; 
-  f_service_ << indent() << parent_class_name << "Class " 
-                                                 "*parent_class =" << endl; 
-  indent_up(); 
-  f_service_ << indent() << "g_type_class_peek_parent (" << class_name_uc << "_GET_CLASS (self));" 
-             << endl; 
-  indent_down(); 
-  f_service_ << endl 
-             << indent() << "process_function_def = " 
-             << "g_hash_table_lookup (self->process_map, method_name);" << endl 
-             << indent() << "if (process_function_def != NULL)" << endl; 
-  scope_up(f_service_); 
-  args_indent = indent() + string(53, ' '); 
-  f_service_ << indent() << "g_free (method_name);" << endl 
-             << indent() << "dispatch_result = " 
-             << "(*process_function_def->function) (self," << endl 
-             << args_indent << "sequence_id," << endl 
-             << args_indent << "input_protocol," << endl 
-             << args_indent << "output_protocol," << endl 
-             << args_indent << "error);" << endl; 
-  scope_down(f_service_); 
-  f_service_ << indent() << "else" << endl; 
-  scope_up(f_service_); 
- 
-  // Method name not recognized; chain up to our parent processor---note the 
-  // top-most implementation of this method, in ThriftDispatchProcessor itself, 
-  // will return an application exception to the caller if no class in the 
-  // hierarchy recognizes the method name 
-  f_service_ << indent() << "dispatch_result = parent_class->dispatch_call " 
-                            "(dispatch_processor," << endl; 
-  args_indent = indent() + string(47, ' '); 
-  f_service_ << args_indent << "input_protocol," << endl << args_indent << "output_protocol," 
-             << endl << args_indent << "method_name," << endl << args_indent << "sequence_id," 
-             << endl << args_indent << "error);" << endl; 
-  scope_down(f_service_); 
-  f_service_ << endl << indent() << "return dispatch_result;" << endl; 
-  scope_down(f_service_); 
-  f_service_ << endl; 
- 
-  // Generate the processor's property setter 
-  function_name = class_name_lc + "_set_property"; 
-  args_indent = string(function_name.length() + 2, ' '); 
-  f_service_ << "static void" << endl << function_name << " (GObject *object," << endl 
-             << args_indent << "guint property_id," << endl << args_indent << "const GValue *value," 
-             << endl << args_indent << "GParamSpec *pspec)" << endl; 
-  scope_up(f_service_); 
-  f_service_ << indent() << class_name << " *self = " << class_name_uc << " (object);" << endl 
-             << endl << indent() << "switch (property_id)" << endl; 
-  scope_up(f_service_); 
-  f_service_ << indent() << "case PROP_" << class_name_uc << "_HANDLER:" << endl; 
-  indent_up(); 
-  f_service_ << indent() << "if (self->handler != NULL)" << endl; 
-  indent_up(); 
-  f_service_ << indent() << "g_object_unref (self->handler);" << endl; 
-  indent_down(); 
-  f_service_ << indent() << "self->handler = g_value_get_object (value);" << endl << indent() 
-             << "g_object_ref (self->handler);" << endl; 
-  if (extends_service) { 
-    // Chain up to set the handler in every superclass as well 
-    f_service_ << endl << indent() << "G_OBJECT_CLASS (" << class_name_lc << "_parent_class)->" 
-               << endl; 
-    indent_up(); 
-    f_service_ << indent() << "set_property (object, property_id, value, pspec);" << endl; 
-    indent_down(); 
-  } 
-  f_service_ << indent() << "break;" << endl; 
-  indent_down(); 
-  f_service_ << indent() << "default:" << endl; 
-  indent_up(); 
-  f_service_ << indent() << "G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);" 
-             << endl << indent() << "break;" << endl; 
-  indent_down(); 
-  scope_down(f_service_); 
-  scope_down(f_service_); 
-  f_service_ << endl; 
- 
-  // Generate processor's property getter 
-  function_name = class_name_lc + "_get_property"; 
-  args_indent = string(function_name.length() + 2, ' '); 
-  f_service_ << "static void" << endl << function_name << " (GObject *object," << endl 
-             << args_indent << "guint property_id," << endl << args_indent << "GValue *value," 
-             << endl << args_indent << "GParamSpec *pspec)" << endl; 
-  scope_up(f_service_); 
-  f_service_ << indent() << class_name << " *self = " << class_name_uc << " (object);" << endl 
-             << endl << indent() << "switch (property_id)" << endl; 
-  scope_up(f_service_); 
-  f_service_ << indent() << "case PROP_" << class_name_uc << "_HANDLER:" << endl; 
-  indent_up(); 
-  f_service_ << indent() << "g_value_set_object (value, self->handler);" << endl << indent() 
-             << "break;" << endl; 
-  indent_down(); 
-  f_service_ << indent() << "default:" << endl; 
-  indent_up(); 
-  f_service_ << indent() << "G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);" 
-             << endl << indent() << "break;" << endl; 
-  indent_down(); 
-  scope_down(f_service_); 
-  scope_down(f_service_); 
-  f_service_ << endl; 
- 
-  // Generator the processor's dispose function 
-  f_service_ << "static void" << endl << class_name_lc << "_dispose (GObject *gobject)" << endl; 
-  scope_up(f_service_); 
-  f_service_ << indent() << class_name << " *self = " << class_name_uc << " (gobject);" << endl 
-             << endl << indent() << "if (self->handler != NULL)" << endl; 
-  scope_up(f_service_); 
-  f_service_ << indent() << "g_object_unref (self->handler);" << endl << indent() 
-             << "self->handler = NULL;" << endl; 
-  scope_down(f_service_); 
-  f_service_ << endl << indent() << "G_OBJECT_CLASS (" << class_name_lc << "_parent_class)" 
-                                                                           "->dispose (gobject);" 
-             << endl; 
-  scope_down(f_service_); 
-  f_service_ << endl; 
- 
-  // Generate processor finalize function 
-  f_service_ << "static void" << endl << class_name_lc << "_finalize (GObject *gobject)" << endl; 
-  scope_up(f_service_); 
-  f_service_ << indent() << this->nspace << service_name_ << "Processor *self = " << this->nspace_uc 
-             << service_name_uc << "_PROCESSOR (gobject);" << endl << endl << indent() 
-             << "thrift_safe_hash_table_destroy (self->process_map);" << endl << endl << indent() 
-             << "G_OBJECT_CLASS (" << class_name_lc << "_parent_class)" 
-                                                       "->finalize (gobject);" << endl; 
-  scope_down(f_service_); 
-  f_service_ << endl; 
- 
-  // Generate processor instance initializer 
-  f_service_ << "static void" << endl << class_name_lc << "_init (" << class_name << " *self)" 
-             << endl; 
-  scope_up(f_service_); 
-  if (functions.size() > 0) { 
-    f_service_ << indent() << "guint index;" << endl 
-               << endl; 
-  } 
-  f_service_ << indent() << "self->handler = NULL;" << endl << indent() 
-             << "self->process_map = " 
-                "g_hash_table_new (g_str_hash, g_str_equal);" << endl; 
-  if (functions.size() > 0) { 
-    args_indent = string(21, ' '); 
-    f_service_ << endl 
-               << indent() << "for (index = 0; index < " 
-               << functions.size() << "; index += 1)" << endl; 
-    indent_up(); 
-    f_service_ << indent() << "g_hash_table_insert (self->process_map," << endl 
-               << indent() << args_indent 
-               << class_name_lc << "_process_function_defs[index].name," << endl 
-               << indent() << args_indent 
-               << "&" << class_name_lc << "_process_function_defs[index]" << ");" 
-               << endl; 
-    indent_down(); 
-  } 
-  scope_down(f_service_); 
-  f_service_ << endl; 
- 
-  // Generate processor class initializer 
-  f_service_ << "static void" << endl << class_name_lc << "_class_init (" << class_name 
-             << "Class *cls)" << endl; 
-  scope_up(f_service_); 
-  f_service_ << indent() << "GObjectClass *gobject_class = G_OBJECT_CLASS (cls);" << endl 
-             << indent() << "ThriftDispatchProcessorClass *dispatch_processor_class =" << endl; 
-  indent_up(); 
-  f_service_ << indent() << "THRIFT_DISPATCH_PROCESSOR_CLASS (cls);" << endl; 
-  indent_down(); 
-  f_service_ << indent() << "GParamSpec *param_spec;" << endl << endl << indent() 
-             << "gobject_class->dispose = " << class_name_lc << "_dispose;" << endl << indent() 
-             << "gobject_class->finalize = " << class_name_lc << "_finalize;" << endl << indent() 
-             << "gobject_class->set_property = " << class_name_lc << "_set_property;" << endl 
-             << indent() << "gobject_class->get_property = " << class_name_lc << "_get_property;" 
-             << endl << endl << indent() 
-             << "dispatch_processor_class->dispatch_call = " << class_name_lc << "_dispatch_call;" 
-             << endl << indent() << "cls->dispatch_call = " << class_name_lc << "_dispatch_call;" 
-             << endl << endl << indent() << "param_spec = g_param_spec_object (\"handler\"," 
-             << endl; 
-  args_indent = indent() + string(34, ' '); 
-  f_service_ << args_indent << "\"Service handler implementation\"," << endl << args_indent 
-             << "\"The service handler implementation \"" << endl << args_indent 
-             << "\"to which method calls are dispatched.\"," << endl << args_indent 
-             << this->nspace_uc + "TYPE_" + service_name_uc + "_HANDLER," << endl << args_indent 
-             << "G_PARAM_READWRITE);" << endl; 
-  f_service_ << indent() << "g_object_class_install_property (gobject_class," << endl; 
-  args_indent = indent() + string(33, ' '); 
-  f_service_ << args_indent << "PROP_" << class_name_uc << "_HANDLER," << endl << args_indent 
-             << "param_spec);" << endl; 
-  scope_down(f_service_); 
-} 
- 
-/** 
- * Generates C code that represents a Thrift service server. 
- */ 
-void t_c_glib_generator::generate_service_server(t_service* tservice) { 
-  (void)tservice; 
-  // Generate the service's handler class 
-  generate_service_handler(tservice); 
- 
-  // Generate the service's processor class 
-  generate_service_processor(tservice); 
-} 
- 
-/** 
- * Generates C code to represent a THrift structure as a GObject. 
- */ 
-void t_c_glib_generator::generate_object(t_struct* tstruct) { 
-  string name = tstruct->get_name(); 
-  string name_u = initial_caps_to_underscores(name); 
-  string name_uc = to_upper_case(name_u); 
- 
-  string class_name = this->nspace + name; 
-  string class_name_lc = to_lower_case(initial_caps_to_underscores(class_name)); 
-  string class_name_uc = to_upper_case(class_name_lc); 
- 
-  string function_name; 
-  string args_indent; 
- 
-  // write the instance definition 
-  f_types_ << "struct _" << this->nspace << name << endl << "{ " << endl 
-           << "  ThriftStruct parent; " << endl << endl << "  /* public */" << endl; 
- 
-  // for each field, add a member variable 
-  vector<t_field*>::const_iterator m_iter; 
-  const vector<t_field*>& members = tstruct->get_members(); 
-  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { 
-    t_type* t = get_true_type((*m_iter)->get_type()); 
-    f_types_ << "  " << type_name(t) << " " << (*m_iter)->get_name() << ";" << endl; 
-    if ((*m_iter)->get_req() != t_field::T_REQUIRED) { 
-      f_types_ << "  gboolean __isset_" << (*m_iter)->get_name() << ";" << endl; 
-    } 
-  } 
- 
-  // close the structure definition and create a typedef 
-  f_types_ << "};" << endl << "typedef struct _" << this->nspace << name << " " << this->nspace 
-           << name << ";" << endl << endl; 
- 
-  // write the class definition 
-  f_types_ << "struct _" << this->nspace << name << "Class" << endl << "{" << endl 
-           << "  ThriftStructClass parent;" << endl << "};" << endl << "typedef struct _" 
-           << this->nspace << name << "Class " << this->nspace << name << "Class;" << endl << endl; 
- 
-  // write the standard GObject boilerplate 
-  f_types_ << "GType " << this->nspace_lc << name_u << "_get_type (void);" << endl << "#define " 
-           << this->nspace_uc << "TYPE_" << name_uc << " (" << this->nspace_lc << name_u 
-           << "_get_type())" << endl << "#define " << this->nspace_uc << name_uc 
-           << "(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), " << this->nspace_uc << "TYPE_" << name_uc 
-           << ", " << this->nspace << name << "))" << endl << "#define " << this->nspace_uc 
-           << name_uc << "_CLASS(c) (G_TYPE_CHECK_CLASS_CAST ((c), " << this->nspace_uc << "_TYPE_" 
-           << name_uc << ", " << this->nspace << name << "Class))" << endl << "#define " 
-           << this->nspace_uc << "IS_" << name_uc << "(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), " 
-           << this->nspace_uc << "TYPE_" << name_uc << "))" << endl << "#define " << this->nspace_uc 
-           << "IS_" << name_uc << "_CLASS(c) (G_TYPE_CHECK_CLASS_TYPE ((c), " << this->nspace_uc 
-           << "TYPE_" << name_uc << "))" << endl << "#define " << this->nspace_uc << name_uc 
-           << "_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), " << this->nspace_uc << "TYPE_" 
-           << name_uc << ", " << this->nspace << name << "Class))" << endl << endl; 
- 
-  // start writing the object implementation .c file 
- 
-  // generate properties enum 
-  if (members.size() > 0) { 
-    f_types_impl_ << "enum _" << class_name << "Properties" << endl << "{" << endl; 
-    indent_up(); 
-    f_types_impl_ << indent() << "PROP_" << class_name_uc << "_0"; 
-    for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { 
-      string member_name_uc 
-          = to_upper_case(to_lower_case(initial_caps_to_underscores((*m_iter)->get_name()))); 
- 
-      f_types_impl_ << "," << endl << indent() << "PROP_" << class_name_uc << "_" << member_name_uc; 
-    } 
-    f_types_impl_ << endl; 
-    indent_down(); 
-    f_types_impl_ << "};" << endl << endl; 
-  } 
- 
-  // generate struct I/O methods 
-  string this_get = this->nspace + name + " * this_object = " + this->nspace_uc + name_uc 
-                    + "(object);"; 
-  generate_struct_reader(f_types_impl_, tstruct, "this_object->", this_get); 
-  generate_struct_writer(f_types_impl_, tstruct, "this_object->", this_get); 
- 
-  // generate property setter and getter 
-  if (members.size() > 0) { 
-    // generate property setter 
-    function_name = class_name_lc + "_set_property"; 
-    args_indent = string(function_name.length() + 2, ' '); 
-    f_types_impl_ << "static void" << endl << function_name << " (GObject *object," << endl 
-                  << args_indent << "guint property_id," << endl << args_indent 
-                  << "const GValue *value," << endl << args_indent << "GParamSpec *pspec)" << endl; 
-    scope_up(f_types_impl_); 
-    f_types_impl_ << indent() << class_name << " *self = " << class_name_uc << " (object);" << endl 
-                  << endl << indent() << "switch (property_id)" << endl; 
-    scope_up(f_types_impl_); 
-    for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { 
-      t_field* member = (*m_iter); 
-      string member_name = member->get_name(); 
-      string member_name_uc 
-          = to_upper_case(to_lower_case(initial_caps_to_underscores(member_name))); 
-      t_type* member_type = get_true_type(member->get_type()); 
- 
-      string property_identifier = "PROP_" + class_name_uc + "_" + member_name_uc; 
- 
-      f_types_impl_ << indent() << "case " << property_identifier + ":" << endl; 
-      indent_up(); 
- 
-      if (member_type->is_base_type()) { 
-        t_base_type* base_type = ((t_base_type*)member_type); 
-        string assign_function_name; 
- 
-        if (base_type->get_base() == t_base_type::TYPE_STRING) { 
-          string release_function_name; 
- 
-          f_types_impl_ << indent() << "if (self->" << member_name << " != NULL)" << endl; 
-          indent_up(); 
- 
-          if (base_type->is_binary()) { 
-            release_function_name = "g_byte_array_unref"; 
-            assign_function_name = "g_value_dup_boxed"; 
-          } else { 
-            release_function_name = "g_free"; 
-            assign_function_name = "g_value_dup_string"; 
-          } 
- 
-          f_types_impl_ << indent() << release_function_name << " (self->" << member_name << ");" 
-                        << endl; 
-          indent_down(); 
-        } else { 
-          switch (base_type->get_base()) { 
-          case t_base_type::TYPE_BOOL: 
-            assign_function_name = "g_value_get_boolean"; 
-            break; 
- 
-          case t_base_type::TYPE_I8: 
-          case t_base_type::TYPE_I16: 
-          case t_base_type::TYPE_I32: 
-            assign_function_name = "g_value_get_int"; 
-            break; 
- 
-          case t_base_type::TYPE_I64: 
-            assign_function_name = "g_value_get_int64"; 
-            break; 
- 
-          case t_base_type::TYPE_DOUBLE: 
-            assign_function_name = "g_value_get_double"; 
-            break; 
- 
-          default: 
-            throw "compiler error: " 
-                  "unrecognized base type \"" + base_type->get_name() + "\" " 
-                                                                        "for struct member \"" 
-                + member_name + "\""; 
-            break; 
-          } 
-        } 
- 
-        f_types_impl_ << indent() << "self->" << member_name << " = " << assign_function_name 
-                      << " (value);" << endl; 
-      } else if (member_type->is_enum()) { 
-        f_types_impl_ << indent() << "self->" << member_name << " = g_value_get_int (value);" 
-                      << endl; 
-      } else if (member_type->is_container()) { 
-        string release_function_name; 
-        string assign_function_name; 
- 
-        if (member_type->is_list()) { 
-          t_type* elem_type = ((t_list*)member_type)->get_elem_type(); 
- 
-          // Lists of base types other than strings are represented as GArrays; 
-          // all others as GPtrArrays 
-          if (is_numeric(elem_type)) { 
-            release_function_name = "g_array_unref"; 
-          } else { 
-            release_function_name = "g_ptr_array_unref"; 
-          } 
- 
-          assign_function_name = "g_value_dup_boxed"; 
-        } else if (member_type->is_set() || member_type->is_map()) { 
-          release_function_name = "g_hash_table_unref"; 
-          assign_function_name = "g_value_dup_boxed"; 
-        } 
- 
-        f_types_impl_ << indent() << "if (self->" << member_name << " != NULL)" << endl; 
-        indent_up(); 
-        f_types_impl_ << indent() << release_function_name << " (self->" << member_name << ");" 
-                      << endl; 
-        indent_down(); 
-        f_types_impl_ << indent() << "self->" << member_name << " = " << assign_function_name 
-                      << " (value);" << endl; 
-      } else if (member_type->is_struct() || member_type->is_xception()) { 
-        f_types_impl_ << indent() << "if (self->" << member_name << " != NULL)" << endl; 
-        indent_up(); 
-        f_types_impl_ << indent() << "g_object_unref (self->" << member_name << ");" << endl; 
-        indent_down(); 
-        f_types_impl_ << indent() << "self->" << member_name << " = g_value_dup_object (value);" 
-                      << endl; 
-      } 
- 
-      if (member->get_req() != t_field::T_REQUIRED) { 
-        f_types_impl_ << indent() << "self->__isset_" << member_name << " = TRUE;" << endl; 
-      } 
- 
-      f_types_impl_ << indent() << "break;" << endl << endl; 
-      indent_down(); 
-    } 
-    f_types_impl_ << indent() << "default:" << endl; 
-    indent_up(); 
-    f_types_impl_ << indent() << "G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);" 
-                  << endl << indent() << "break;" << endl; 
-    indent_down(); 
-    scope_down(f_types_impl_); 
-    scope_down(f_types_impl_); 
-    f_types_impl_ << endl; 
- 
-    // generate property getter 
-    function_name = class_name_lc + "_get_property"; 
-    args_indent = string(function_name.length() + 2, ' '); 
-    f_types_impl_ << "static void" << endl << function_name << " (GObject *object," << endl 
-                  << args_indent << "guint property_id," << endl << args_indent << "GValue *value," 
-                  << endl << args_indent << "GParamSpec *pspec)" << endl; 
-    scope_up(f_types_impl_); 
-    f_types_impl_ << indent() << class_name << " *self = " << class_name_uc << " (object);" << endl 
-                  << endl << indent() << "switch (property_id)" << endl; 
-    scope_up(f_types_impl_); 
-    for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { 
-      t_field* member = (*m_iter); 
-      string member_name = (*m_iter)->get_name(); 
-      string member_name_uc 
-          = to_upper_case(to_lower_case(initial_caps_to_underscores(member_name))); 
-      t_type* member_type = get_true_type(member->get_type()); 
- 
-      string property_identifier = "PROP_" + class_name_uc + "_" + member_name_uc; 
- 
-      string setter_function_name; 
- 
-      if (member_type->is_base_type()) { 
-        t_base_type* base_type = ((t_base_type*)member_type); 
- 
-        switch (base_type->get_base()) { 
-        case t_base_type::TYPE_BOOL: 
-          setter_function_name = "g_value_set_boolean"; 
-          break; 
- 
-        case t_base_type::TYPE_I8: 
-        case t_base_type::TYPE_I16: 
-        case t_base_type::TYPE_I32: 
-          setter_function_name = "g_value_set_int"; 
-          break; 
- 
-        case t_base_type::TYPE_I64: 
-          setter_function_name = "g_value_set_int64"; 
-          break; 
- 
-        case t_base_type::TYPE_DOUBLE: 
-          setter_function_name = "g_value_set_double"; 
-          break; 
- 
-        case t_base_type::TYPE_STRING: 
-          if (base_type->is_binary()) { 
-            setter_function_name = "g_value_set_boxed"; 
-          } else { 
-            setter_function_name = "g_value_set_string"; 
-          } 
-          break; 
- 
-        default: 
-          throw "compiler error: " 
-                "unrecognized base type \"" + base_type->get_name() + "\" " 
-                                                                      "for struct member \"" 
-              + member_name + "\""; 
-          break; 
-        } 
-      } else if (member_type->is_enum()) { 
-        setter_function_name = "g_value_set_int"; 
-      } else if (member_type->is_struct() || member_type->is_xception()) { 
-        setter_function_name = "g_value_set_object"; 
-      } else if (member_type->is_container()) { 
-        setter_function_name = "g_value_set_boxed"; 
-      } else { 
-        throw "compiler error: " 
-              "unrecognized type for struct member \"" + member_name + "\""; 
-      } 
- 
-      f_types_impl_ << indent() << "case " << property_identifier + ":" << endl; 
-      indent_up(); 
-      f_types_impl_ << indent() << setter_function_name << " (value, self->" << member_name << ");" 
-                    << endl << indent() << "break;" << endl << endl; 
-      indent_down(); 
-    } 
-    f_types_impl_ << indent() << "default:" << endl; 
-    indent_up(); 
-    f_types_impl_ << indent() << "G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);" 
-                  << endl << indent() << "break;" << endl; 
-    indent_down(); 
-    scope_down(f_types_impl_); 
-    scope_down(f_types_impl_); 
-    f_types_impl_ << endl; 
-  } 
- 
-  // generate the instance init function 
- 
-  f_types_impl_ << "static void " << endl << this->nspace_lc << name_u << "_instance_init (" 
-                << this->nspace << name << " * object)" << endl << "{" << endl; 
-  indent_up(); 
- 
-  // generate default-value structures for container-type members 
-  bool constant_declaration_output = false; 
-  bool string_list_constant_output = false; 
-  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { 
-    t_field* member = *m_iter; 
-    t_const_value* member_value = member->get_value(); 
- 
-    if (member_value != NULL) { 
-      string member_name = member->get_name(); 
-      t_type* member_type = get_true_type(member->get_type()); 
- 
-      if (member_type->is_list()) { 
-        const vector<t_const_value*>& list = member_value->get_list(); 
-        t_type* elem_type = ((t_list*)member_type)->get_elem_type(); 
- 
-        // Generate an array with the list literal 
-        indent(f_types_impl_) << "static " << type_name(elem_type, false, true) << " __default_" 
-                              << member_name << "[" << list.size() << "] = " << endl; 
-        indent_up(); 
-        f_types_impl_ << indent() << constant_literal(member_type, member_value) << ";" << endl; 
-        indent_down(); 
- 
-        constant_declaration_output = true; 
- 
-        // If we are generating values for a pointer array (i.e. a list of 
-        // strings), set a flag so we know to also declare an index variable to 
-        // use in pre-populating the array 
-        if (elem_type->is_string()) { 
-          string_list_constant_output = true; 
-        } 
-      } 
- 
-      // TODO: Handle container types other than list 
-    } 
-  } 
-  if (constant_declaration_output) { 
-    if (string_list_constant_output) { 
-      indent(f_types_impl_) << "unsigned int list_index;" << endl; 
-    } 
- 
-    f_types_impl_ << endl; 
-  } 
- 
-  // satisfy compilers with -Wall turned on 
-  indent(f_types_impl_) << "/* satisfy -Wall */" << endl << indent() 
-                        << "THRIFT_UNUSED_VAR (object);" << endl; 
- 
-  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { 
-    t_type* t = get_true_type((*m_iter)->get_type()); 
-    if (t->is_base_type()) { 
-      string dval = " = "; 
-      if (t->is_enum()) { 
-        dval += "(" + type_name(t) + ")"; 
-      } 
-      t_const_value* cv = (*m_iter)->get_value(); 
-      if (cv != NULL) { 
-        dval += constant_value("", t, cv); 
-      } else { 
-        dval += t->is_string() ? "NULL" : "0"; 
-      } 
-      indent(f_types_impl_) << "object->" << (*m_iter)->get_name() << dval << ";" << endl; 
-    } else if (t->is_struct()) { 
-      string name = (*m_iter)->get_name(); 
-      string type_name_uc 
-          = to_upper_case(initial_caps_to_underscores((*m_iter)->get_type()->get_name())); 
-      indent(f_types_impl_) << "object->" << name << " = g_object_new (" << this->nspace_uc 
-                            << "TYPE_" << type_name_uc << ", NULL);" << endl; 
-    } else if (t->is_xception()) { 
-      string name = (*m_iter)->get_name(); 
-      indent(f_types_impl_) << "object->" << name << " = NULL;" << endl; 
-    } else if (t->is_container()) { 
-      string name = (*m_iter)->get_name(); 
-      string init_function; 
-      t_type* etype = NULL; 
- 
-      if (t->is_map()) { 
-        t_type* key = ((t_map*)t)->get_key_type(); 
-        t_type* value = ((t_map*)t)->get_val_type(); 
-        init_function = generate_new_hash_from_type(key, value); 
-      } else if (t->is_set()) { 
-        etype = ((t_set*)t)->get_elem_type(); 
-        init_function = generate_new_hash_from_type(etype, NULL); 
-      } else if (t->is_list()) { 
-        etype = ((t_list*)t)->get_elem_type(); 
-        init_function = generate_new_array_from_type(etype); 
-      } 
- 
-      indent(f_types_impl_) << "object->" << name << " = " << init_function << endl; 
- 
-      // Pre-populate the container with the specified default values, if any 
-      if ((*m_iter)->get_value()) { 
-        t_const_value* member_value = (*m_iter)->get_value(); 
- 
-        if (t->is_list()) { 
-          const vector<t_const_value*>& list = member_value->get_list(); 
- 
-          if (is_numeric(etype)) { 
-            indent(f_types_impl_) << 
-              "g_array_append_vals (object->" << name << ", &__default_" << 
-              name << ", " << list.size() << ");" << endl; 
-          } 
-          else { 
-            indent(f_types_impl_) << 
-              "for (list_index = 0; list_index < " << list.size() << "; " << 
-              "list_index += 1)" << endl; 
-            indent_up(); 
-            indent(f_types_impl_) << 
-              "g_ptr_array_add (object->" << name << "," << endl << 
-              indent() << string(17, ' ') << "g_strdup (__default_" << 
-              name << "[list_index]));" << endl; 
-            indent_down(); 
-          } 
-        } 
- 
-        // TODO: Handle container types other than list 
-      } 
-    } 
- 
-    /* if not required, initialize the __isset variable */ 
-    if ((*m_iter)->get_req() != t_field::T_REQUIRED) { 
-      indent(f_types_impl_) << "object->__isset_" << (*m_iter)->get_name() << " = FALSE;" << endl; 
-    } 
-  } 
- 
-  indent_down(); 
-  f_types_impl_ << "}" << endl << endl; 
- 
-  /* create the destructor */ 
-  f_types_impl_ << "static void " << endl << this->nspace_lc << name_u 
-                << "_finalize (GObject *object)" << endl << "{" << endl; 
-  indent_up(); 
- 
-  f_types_impl_ << indent() << this->nspace << name << " *tobject = " << this->nspace_uc << name_uc 
-                << " (object);" << endl << endl; 
- 
-  f_types_impl_ << indent() << "/* satisfy -Wall in case we don't use tobject */" << endl 
-                << indent() << "THRIFT_UNUSED_VAR (tobject);" << endl; 
- 
-  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { 
-    t_type* t = get_true_type((*m_iter)->get_type()); 
-    if (t->is_container()) { 
-      string name = (*m_iter)->get_name(); 
-      if (t->is_map() || t->is_set()) { 
-        f_types_impl_ << indent() << "if (tobject->" << name << " != NULL)" << endl; 
-        f_types_impl_ << indent() << "{" << endl; 
-        indent_up(); 
-        f_types_impl_ << indent() << "g_hash_table_destroy (tobject->" << name << ");" << endl; 
-        f_types_impl_ << indent() << "tobject->" << name << " = NULL;" << endl; 
-        indent_down(); 
-        f_types_impl_ << indent() << "}" << endl; 
-      } else if (t->is_list()) { 
-        t_type* etype = ((t_list*)t)->get_elem_type(); 
-        string destructor_function = "g_ptr_array_unref"; 
- 
-        if (etype->is_base_type()) { 
-          t_base_type::t_base tbase = ((t_base_type*)etype)->get_base(); 
-          switch (tbase) { 
-          case t_base_type::TYPE_VOID: 
-            throw "compiler error: cannot determine array type"; 
-          case t_base_type::TYPE_BOOL: 
-          case t_base_type::TYPE_I8: 
-          case t_base_type::TYPE_I16: 
-          case t_base_type::TYPE_I32: 
-          case t_base_type::TYPE_I64: 
-          case t_base_type::TYPE_DOUBLE: 
-            destructor_function = "g_array_unref"; 
-            break; 
-          case t_base_type::TYPE_STRING: 
-            break; 
-          default: 
-            throw "compiler error: no array info for type"; 
-          } 
-        } else if (etype->is_enum()) { 
-          destructor_function = "g_array_unref"; 
-        } 
- 
-        f_types_impl_ << indent() << "if (tobject->" << name << " != NULL)" << endl; 
-        f_types_impl_ << indent() << "{" << endl; 
-        indent_up(); 
-        f_types_impl_ << indent() << destructor_function << " (tobject->" << name << ");" << endl; 
-        f_types_impl_ << indent() << "tobject->" << name << " = NULL;" << endl; 
-        indent_down(); 
-        f_types_impl_ << indent() << "}" << endl; 
-      } 
-    } else if (t->is_struct() || t->is_xception()) { 
-      string name = (*m_iter)->get_name(); 
-      // TODO: g_clear_object needs glib >= 2.28 
-      // f_types_impl_ << indent() << "g_clear_object (&(tobject->" << name << "));" << endl; 
-      // does g_object_unref the trick? 
-      f_types_impl_ << indent() << "if (tobject->" << name << " != NULL)" << endl; 
-      f_types_impl_ << indent() << "{" << endl; 
-      indent_up(); 
-      f_types_impl_ << indent() << "g_object_unref(tobject->" << name << ");" << endl; 
-      f_types_impl_ << indent() << "tobject->" << name << " = NULL;" << endl; 
-      indent_down(); 
-      f_types_impl_ << indent() << "}" << endl; 
-    } else if (t->is_string()) { 
-      string name = (*m_iter)->get_name(); 
-      f_types_impl_ << indent() << "if (tobject->" << name << " != NULL)" << endl; 
-      f_types_impl_ << indent() << "{" << endl; 
-      indent_up(); 
-      f_types_impl_ << indent() << generate_free_func_from_type(t) << "(tobject->" << name << ");" 
-                    << endl; 
-      f_types_impl_ << indent() << "tobject->" << name << " = NULL;" << endl; 
-      indent_down(); 
-      f_types_impl_ << indent() << "}" << endl; 
-    } 
-  } 
- 
-  indent_down(); 
-  f_types_impl_ << "}" << endl << endl; 
- 
-  // generate the class init function 
- 
-  f_types_impl_ << "static void" << endl << class_name_lc << "_class_init (" << class_name 
-                << "Class * cls)" << endl; 
-  scope_up(f_types_impl_); 
- 
-  f_types_impl_ << indent() << "GObjectClass *gobject_class = G_OBJECT_CLASS (cls);" << endl 
-                << indent() << "ThriftStructClass *struct_class = " 
-                << "THRIFT_STRUCT_CLASS (cls);" << endl << endl << indent() 
-                << "struct_class->read = " << class_name_lc << "_read;" << endl << indent() 
-                << "struct_class->write = " << class_name_lc << "_write;" << endl << endl 
-                << indent() << "gobject_class->finalize = " << class_name_lc << "_finalize;" 
-                << endl; 
-  if (members.size() > 0) { 
-    f_types_impl_ << indent() << "gobject_class->get_property = " << class_name_lc 
-                  << "_get_property;" << endl << indent() 
-                  << "gobject_class->set_property = " << class_name_lc << "_set_property;" << endl; 
- 
-    // install a property for each member 
-    for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { 
-      t_field* member = (*m_iter); 
-      string member_name = member->get_name(); 
-      string member_name_uc 
-          = to_upper_case(to_lower_case(initial_caps_to_underscores(member_name))); 
-      t_type* member_type = get_true_type(member->get_type()); 
-      t_const_value* member_value = member->get_value(); 
- 
-      string property_identifier = "PROP_" + class_name_uc + "_" + member_name_uc; 
- 
-      f_types_impl_ << endl << indent() << "g_object_class_install_property" << endl; 
-      indent_up(); 
-      args_indent = indent() + ' '; 
-      f_types_impl_ << indent() << "(gobject_class," << endl << args_indent << property_identifier 
-                    << "," << endl << args_indent; 
- 
-      if (member_type->is_base_type()) { 
-        t_base_type::t_base base_type = ((t_base_type*)member_type)->get_base(); 
- 
-        if (base_type == t_base_type::TYPE_STRING) { 
-          if (((t_base_type*)member_type)->is_binary()) { 
-            args_indent += string(20, ' '); 
-            f_types_impl_ << "g_param_spec_boxed (\"" << member_name << "\"," << endl << args_indent 
-                          << "NULL," << endl << args_indent << "NULL," << endl << args_indent 
-                          << "G_TYPE_BYTE_ARRAY," << endl << args_indent << "G_PARAM_READWRITE));" 
-                          << endl; 
-          } else { 
-            args_indent += string(21, ' '); 
-            f_types_impl_ << "g_param_spec_string (\"" << member_name << "\"," << endl 
-                          << args_indent << "NULL," << endl << args_indent << "NULL," << endl 
-                          << args_indent 
-                          << ((member_value != NULL) ? "\"" + member_value->get_string() + "\"" 
-                                                     : "NULL") << "," << endl << args_indent 
-                          << "G_PARAM_READWRITE));" << endl; 
-          } 
-        } else if (base_type == t_base_type::TYPE_BOOL) { 
-          args_indent += string(22, ' '); 
-          f_types_impl_ << "g_param_spec_boolean (\"" << member_name << "\"," << endl << args_indent 
-                        << "NULL," << endl << args_indent << "NULL," << endl << args_indent 
-                        << (((member_value != NULL) && (member_value->get_integer() != 0)) 
-                                ? "TRUE" 
-                                : "FALSE") << "," << endl << args_indent << "G_PARAM_READWRITE));" 
-                        << endl; 
-        } else if ((base_type == t_base_type::TYPE_I8) || (base_type == t_base_type::TYPE_I16) 
-                   || (base_type == t_base_type::TYPE_I32) || (base_type == t_base_type::TYPE_I64) 
-                   || (base_type == t_base_type::TYPE_DOUBLE)) { 
-          string param_spec_function_name = "g_param_spec_int"; 
-          string min_value; 
-          string max_value; 
-          ostringstream default_value; 
- 
-          switch (base_type) { 
-          case t_base_type::TYPE_I8: 
-            min_value = "G_MININT8"; 
-            max_value = "G_MAXINT8"; 
-            break; 
- 
-          case t_base_type::TYPE_I16: 
-            min_value = "G_MININT16"; 
-            max_value = "G_MAXINT16"; 
-            break; 
- 
-          case t_base_type::TYPE_I32: 
-            min_value = "G_MININT32"; 
-            max_value = "G_MAXINT32"; 
-            break; 
- 
-          case t_base_type::TYPE_I64: 
-            param_spec_function_name = "g_param_spec_int64"; 
-            min_value = "G_MININT64"; 
-            max_value = "G_MAXINT64"; 
-            break; 
- 
-          case t_base_type::TYPE_DOUBLE: 
-            param_spec_function_name = "g_param_spec_double"; 
-            min_value = "-INFINITY"; 
-            max_value = "INFINITY"; 
-            break; 
- 
-          default: 
-            throw "compiler error: " 
-                  "unrecognized base type \"" + member_type->get_name() + "\" " 
-                                                                          "for struct member \"" 
-                + member_name + "\""; 
-            break; 
-          } 
- 
-          if (member_value != NULL) { 
-            default_value << (base_type == t_base_type::TYPE_DOUBLE ? member_value->get_double() 
-                                                                    : member_value->get_integer()); 
-          } else { 
-            default_value << "0"; 
-          } 
- 
-          args_indent += string(param_spec_function_name.length() + 2, ' '); 
-          f_types_impl_ << param_spec_function_name << " (\"" << member_name << "\"," << endl 
-                        << args_indent << "NULL," << endl << args_indent << "NULL," << endl 
-                        << args_indent << min_value << "," << endl << args_indent << max_value 
-                        << "," << endl << args_indent << default_value.str() << "," << endl 
-                        << args_indent << "G_PARAM_READWRITE));" << endl; 
-        } 
- 
-        indent_down(); 
-      } else if (member_type->is_enum()) { 
-        t_enum_value* enum_min_value = ((t_enum*)member_type)->get_min_value(); 
-        t_enum_value* enum_max_value = ((t_enum*)member_type)->get_max_value(); 
-        int min_value = (enum_min_value != NULL) ? enum_min_value->get_value() : 0; 
-        int max_value = (enum_max_value != NULL) ? enum_max_value->get_value() : 0; 
- 
-        args_indent += string(18, ' '); 
-        f_types_impl_ << "g_param_spec_int (\"" << member_name << "\"," << endl << args_indent 
-                      << "NULL," << endl << args_indent << "NULL," << endl << args_indent 
-                      << min_value << "," << endl << args_indent << max_value << "," << endl 
-                      << args_indent << min_value << "," << endl << args_indent 
-                      << "G_PARAM_READWRITE));" << endl; 
-        indent_down(); 
-      } else if (member_type->is_struct() || member_type->is_xception()) { 
-        string param_type = this->nspace_uc + "TYPE_" 
-                            + to_upper_case(initial_caps_to_underscores(member_type->get_name())); 
- 
-        args_indent += string(20, ' '); 
-        f_types_impl_ << "g_param_spec_object (\"" << member_name << "\"," << endl << args_indent 
-                      << "NULL," << endl << args_indent << "NULL," << endl << args_indent 
-                      << param_type << "," << endl << args_indent << "G_PARAM_READWRITE));" << endl; 
-        indent_down(); 
-      } else if (member_type->is_list()) { 
-        t_type* elem_type = ((t_list*)member_type)->get_elem_type(); 
-        string param_type; 
- 
-        if (elem_type->is_base_type() && !elem_type->is_string()) { 
-          param_type = "G_TYPE_ARRAY"; 
-        } else { 
-          param_type = "G_TYPE_PTR_ARRAY"; 
-        } 
- 
-        args_indent += string(20, ' '); 
-        f_types_impl_ << "g_param_spec_boxed (\"" << member_name << "\"," << endl << args_indent 
-                      << "NULL," << endl << args_indent << "NULL," << endl << args_indent 
-                      << param_type << "," << endl << args_indent << "G_PARAM_READWRITE));" << endl; 
-        indent_down(); 
-      } else if (member_type->is_set() || member_type->is_map()) { 
-        args_indent += string(20, ' '); 
-        f_types_impl_ << "g_param_spec_boxed (\"" << member_name << "\"," << endl << args_indent 
-                      << "NULL," << endl << args_indent << "NULL," << endl << args_indent 
-                      << "G_TYPE_HASH_TABLE," << endl << args_indent << "G_PARAM_READWRITE));" 
-                      << endl; 
-        indent_down(); 
-      } 
-    } 
-  } 
-  scope_down(f_types_impl_); 
-  f_types_impl_ << endl; 
- 
-  f_types_impl_ << "GType" << endl << this->nspace_lc << name_u << "_get_type (void)" << endl << "{" 
-                << endl << "  static GType type = 0;" << endl << endl << "  if (type == 0) " << endl 
-                << "  {" << endl << "    static const GTypeInfo type_info = " << endl << "    {" 
-                << endl << "      sizeof (" << this->nspace << name << "Class)," << endl 
-                << "      NULL, /* base_init */" << endl << "      NULL, /* base_finalize */" 
-                << endl << "      (GClassInitFunc) " << this->nspace_lc << name_u << "_class_init," 
-                << endl << "      NULL, /* class_finalize */" << endl 
-                << "      NULL, /* class_data */" << endl << "      sizeof (" << this->nspace 
-                << name << ")," << endl << "      0, /* n_preallocs */" << endl 
-                << "      (GInstanceInitFunc) " << this->nspace_lc << name_u << "_instance_init," 
-                << endl << "      NULL, /* value_table */" << endl << "    };" << endl << endl 
-                << "    type = g_type_register_static (THRIFT_TYPE_STRUCT, " << endl 
-                << "                                   \"" << this->nspace << name << "Type\"," 
-                << endl << "                                   &type_info, 0);" << endl << "  }" 
-                << endl << endl << "  return type;" << endl << "}" << endl << endl; 
-} 
- 
-/** 
- * Generates functions to write Thrift structures to a stream. 
- */ 
-void t_c_glib_generator::generate_struct_writer(ostream& out, 
-                                                t_struct* tstruct, 
-                                                string this_name, 
-                                                string this_get, 
-                                                bool is_function) { 
-  string name = tstruct->get_name(); 
-  string name_u = initial_caps_to_underscores(name); 
-  string name_uc = to_upper_case(name_u); 
- 
-  const vector<t_field*>& fields = tstruct->get_members(); 
-  vector<t_field*>::const_iterator f_iter; 
-  int error_ret = 0; 
- 
-  if (is_function) { 
-    error_ret = -1; 
-    indent(out) << "static gint32" << endl << this->nspace_lc << name_u 
-                << "_write (ThriftStruct *object, ThriftProtocol *protocol, GError **error)" 
-                << endl; 
-  } 
-  indent(out) << "{" << endl; 
-  indent_up(); 
- 
-  out << indent() << "gint32 ret;" << endl << indent() << "gint32 xfer = 0;" << endl << endl; 
- 
-  indent(out) << this_get << endl; 
-  // satisfy -Wall in the case of an empty struct 
-  if (!this_get.empty()) { 
-    indent(out) << "THRIFT_UNUSED_VAR (this_object);" << endl; 
-  } 
- 
-  out << indent() << "if ((ret = thrift_protocol_write_struct_begin (protocol, \"" << name 
-      << "\", error)) < 0)" << endl << indent() << "  return " << error_ret << ";" << endl 
-      << indent() << "xfer += ret;" << endl; 
- 
-  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { 
-    if ((*f_iter)->get_req() == t_field::T_OPTIONAL) { 
-      indent(out) << "if (this_object->__isset_" << (*f_iter)->get_name() << " == TRUE) {" << endl; 
-      indent_up(); 
-    } 
- 
-    out << indent() << "if ((ret = thrift_protocol_write_field_begin (protocol, " 
-        << "\"" << (*f_iter)->get_name() << "\", " << type_to_enum((*f_iter)->get_type()) << ", " 
-        << (*f_iter)->get_key() << ", error)) < 0)" << endl << indent() << "  return " << error_ret 
-        << ";" << endl << indent() << "xfer += ret;" << endl; 
-    generate_serialize_field(out, *f_iter, this_name, "", error_ret); 
-    out << indent() << "if ((ret = thrift_protocol_write_field_end (protocol, error)) < 0)" << endl 
-        << indent() << "  return " << error_ret << ";" << endl << indent() << "xfer += ret;" 
-        << endl; 
- 
-    if ((*f_iter)->get_req() == t_field::T_OPTIONAL) { 
-      indent_down(); 
-      indent(out) << "}" << endl; 
-    } 
-  } 
- 
-  // write the struct map 
-  out << indent() << "if ((ret = thrift_protocol_write_field_stop (protocol, error)) < 0)" << endl 
-      << indent() << "  return " << error_ret << ";" << endl << indent() << "xfer += ret;" << endl 
-      << indent() << "if ((ret = thrift_protocol_write_struct_end (protocol, error)) < 0)" << endl 
-      << indent() << "  return " << error_ret << ";" << endl << indent() << "xfer += ret;" << endl 
-      << endl; 
- 
-  if (is_function) { 
-    indent(out) << "return xfer;" << endl; 
-  } 
- 
-  indent_down(); 
-  indent(out) << "}" << endl << endl; 
-} 
- 
-/** 
- * Generates code to read Thrift structures from a stream. 
- */ 
-void t_c_glib_generator::generate_struct_reader(ostream& out, 
-                                                t_struct* tstruct, 
-                                                string this_name, 
-                                                string this_get, 
-                                                bool is_function) { 
-  string name = tstruct->get_name(); 
-  string name_u = initial_caps_to_underscores(name); 
-  string name_uc = to_upper_case(name_u); 
-  int error_ret = 0; 
-  const vector<t_field*>& fields = tstruct->get_members(); 
-  vector<t_field*>::const_iterator f_iter; 
- 
-  if (is_function) { 
-    error_ret = -1; 
-    indent(out) << "/* reads a " << name_u << " object */" << endl << "static gint32" << endl 
-                << this->nspace_lc << name_u 
-                << "_read (ThriftStruct *object, ThriftProtocol *protocol, GError **error)" << endl; 
-  } 
- 
-  indent(out) << "{" << endl; 
-  indent_up(); 
- 
-  // declare stack temp variables 
-  out << indent() << "gint32 ret;" << endl << indent() << "gint32 xfer = 0;" << endl << indent() 
-      << "gchar *name = NULL;" << endl << indent() << "ThriftType ftype;" << endl << indent() 
-      << "gint16 fid;" << endl << indent() << "guint32 len = 0;" << endl << indent() 
-      << "gpointer data = NULL;" << endl << indent() << this_get << endl; 
- 
-  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { 
-    if ((*f_iter)->get_req() == t_field::T_REQUIRED) { 
-      indent(out) << "gboolean isset_" << (*f_iter)->get_name() << " = FALSE;" << endl; 
-    } 
-  } 
- 
-  out << endl; 
- 
-  // satisfy -Wall in case we don't use some variables 
-  out << indent() << "/* satisfy -Wall in case these aren't used */" << endl << indent() 
-      << "THRIFT_UNUSED_VAR (len);" << endl << indent() << "THRIFT_UNUSED_VAR (data);" << endl; 
- 
-  if (!this_get.empty()) { 
-    out << indent() << "THRIFT_UNUSED_VAR (this_object);" << endl; 
-  } 
-  out << endl; 
- 
-  // read the beginning of the structure marker 
-  out << indent() << "/* read the struct begin marker */" << endl << indent() 
-      << "if ((ret = thrift_protocol_read_struct_begin (protocol, &name, error)) < 0)" << endl 
-      << indent() << "{" << endl << indent() << "  if (name) g_free (name);" << endl << indent() 
-      << "  return " << error_ret << ";" << endl << indent() << "}" << endl << indent() 
-      << "xfer += ret;" << endl << indent() << "if (name) g_free (name);" << endl << indent() 
-      << "name = NULL;" << endl << endl; 
- 
-  // read the struct fields 
-  out << indent() << "/* read the struct fields */" << endl << indent() << "while (1)" << endl; 
-  scope_up(out); 
- 
-  // read beginning field marker 
-  out << indent() << "/* read the beginning of a field */" << endl << indent() 
-      << "if ((ret = thrift_protocol_read_field_begin (protocol, &name, &ftype, &fid, error)) < 0)" 
-      << endl << indent() << "{" << endl << indent() << "  if (name) g_free (name);" << endl 
-      << indent() << "  return " << error_ret << ";" << endl << indent() << "}" << endl << indent() 
-      << "xfer += ret;" << endl << indent() << "if (name) g_free (name);" << endl << indent() 
-      << "name = NULL;" << endl << endl; 
- 
-  // check for field STOP marker 
-  out << indent() << "/* break if we get a STOP field */" << endl << indent() 
-      << "if (ftype == T_STOP)" << endl << indent() << "{" << endl << indent() << "  break;" << endl 
-      << indent() << "}" << endl << endl; 
- 
-  // switch depending on the field type 
-  indent(out) << "switch (fid)" << endl; 
- 
-  // start switch 
-  scope_up(out); 
- 
-  // generate deserialization code for known types 
-  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { 
-    indent(out) << "case " << (*f_iter)->get_key() << ":" << endl; 
-    indent_up(); 
-    indent(out) << "if (ftype == " << type_to_enum((*f_iter)->get_type()) << ")" << endl; 
-    indent(out) << "{" << endl; 
- 
-    indent_up(); 
-    // generate deserialize field 
-    generate_deserialize_field(out, *f_iter, this_name, "", error_ret, false); 
-    indent_down(); 
- 
-    out << indent() << "} else {" << endl << indent() 
-        << "  if ((ret = thrift_protocol_skip (protocol, ftype, error)) < 0)" << endl << indent() 
-        << "    return " << error_ret << ";" << endl << indent() << "  xfer += ret;" << endl 
-        << indent() << "}" << endl << indent() << "break;" << endl; 
-    indent_down(); 
-  } 
- 
-  // create the default case 
-  out << indent() << "default:" << endl << indent() 
-      << "  if ((ret = thrift_protocol_skip (protocol, ftype, error)) < 0)" << endl << indent() 
-      << "    return " << error_ret << ";" << endl << indent() << "  xfer += ret;" << endl 
-      << indent() << "  break;" << endl; 
- 
-  // end switch 
-  scope_down(out); 
- 
-  // read field end marker 
-  out << indent() << "if ((ret = thrift_protocol_read_field_end (protocol, error)) < 0)" << endl 
-      << indent() << "  return " << error_ret << ";" << endl << indent() << "xfer += ret;" << endl; 
- 
-  // end while loop 
-  scope_down(out); 
-  out << endl; 
- 
-  // read the end of the structure 
-  out << indent() << "if ((ret = thrift_protocol_read_struct_end (protocol, error)) < 0)" << endl 
-      << indent() << "  return " << error_ret << ";" << endl << indent() << "xfer += ret;" << endl 
-      << endl; 
- 
-  // if a required field is missing, throw an error 
-  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { 
-    if ((*f_iter)->get_req() == t_field::T_REQUIRED) { 
-      out << indent() << "if (!isset_" << (*f_iter)->get_name() << ")" << endl << indent() << "{" 
-          << endl << indent() << "  g_set_error (error, THRIFT_PROTOCOL_ERROR," << endl << indent() 
-          << "               THRIFT_PROTOCOL_ERROR_INVALID_DATA," << endl << indent() 
-          << "               \"missing field\");" << endl << indent() << "  return -1;" << endl 
-          << indent() << "}" << endl << endl; 
-    } 
-  } 
- 
-  if (is_function) { 
-    indent(out) << "return xfer;" << endl; 
-  } 
- 
-  // end the function/structure 
-  indent_down(); 
-  indent(out) << "}" << endl << endl; 
-} 
- 
-void t_c_glib_generator::generate_serialize_field(ostream& out, 
-                                                  t_field* tfield, 
-                                                  string prefix, 
-                                                  string suffix, 
-                                                  int error_ret) { 
-  t_type* type = get_true_type(tfield->get_type()); 
-  string name = prefix + tfield->get_name() + suffix; 
- 
-  if (type->is_void()) { 
-    throw "CANNOT GENERATE SERIALIZE CODE FOR void TYPE: " + name; 
-  } 
- 
-  if (type->is_struct() || type->is_xception()) { 
-    generate_serialize_struct(out, (t_struct*)type, name, error_ret); 
-  } else if (type->is_container()) { 
-    generate_serialize_container(out, type, name, error_ret); 
-  } else if (type->is_base_type() || type->is_enum()) { 
-    indent(out) << "if ((ret = thrift_protocol_write_"; 
- 
-    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: 
-        throw "compiler error: cannot serialize void field in a struct: " + name; 
-        break; 
-      case t_base_type::TYPE_BOOL: 
-        out << "bool (protocol, " << name; 
-        break; 
-      case t_base_type::TYPE_I8: 
-        out << "byte (protocol, " << name; 
-        break; 
-      case t_base_type::TYPE_I16: 
-        out << "i16 (protocol, " << name; 
-        break; 
-      case t_base_type::TYPE_I32: 
-        out << "i32 (protocol, " << name; 
-        break; 
-      case t_base_type::TYPE_I64: 
-        out << "i64 (protocol, " << name; 
-        break; 
-      case t_base_type::TYPE_DOUBLE: 
-        out << "double (protocol, " << name; 
-        break; 
-      case t_base_type::TYPE_STRING: 
-        if (type->is_binary()) { 
-          out << "binary (protocol, " << name << " ? ((GByteArray *) " << name << ")->data : NULL, " 
-              << name << " ? ((GByteArray *) " << name << ")->len : 0"; 
-        } else { 
-          out << "string (protocol, " << name; 
-        } 
-        break; 
-      default: 
-        throw "compiler error: no C writer for base type " + t_base_type::t_base_name(tbase) + name; 
-      } 
-    } else { 
-      out << "i32 (protocol, (gint32) " << name; 
-    } 
-    out << ", error)) < 0)" << endl 
-        << indent() << "  return " << error_ret << ";" << endl 
-        << indent() << "xfer += ret;" << endl << endl; 
-  } else { 
-    throw std::logic_error("DO NOT KNOW HOW TO SERIALIZE FIELD '" + name + "' TYPE '" 
-                           + type_name(type)); 
-  } 
-} 
- 
-void t_c_glib_generator::generate_serialize_struct(ostream& out, 
-                                                   t_struct* tstruct, 
-                                                   string prefix, 
-                                                   int error_ret) { 
-  (void)tstruct; 
-  out << indent() << "if ((ret = thrift_struct_write (THRIFT_STRUCT (" << prefix 
-      << "), protocol, error)) < 0)" << endl << indent() << "  return " << error_ret << ";" << endl 
-      << indent() << "xfer += ret;" << endl << endl; 
-} 
- 
-void t_c_glib_generator::generate_serialize_container(ostream& out, 
-                                                      t_type* ttype, 
-                                                      string prefix, 
-                                                      int error_ret) { 
-  scope_up(out); 
- 
-  if (ttype->is_map()) { 
-    t_type* tkey = ((t_map*)ttype)->get_key_type(); 
-    t_type* tval = ((t_map*)ttype)->get_val_type(); 
-    string tkey_name = type_name(tkey); 
-    string tval_name = type_name(tval); 
-    string tkey_ptr; 
-    string tval_ptr; 
-    string keyname = tmp("key"); 
-    string valname = tmp("val"); 
- 
-    declore_local_variable_for_write(out, tkey, keyname); 
-    declore_local_variable_for_write(out, tval, valname); 
- 
-    /* If either the key or value type is a typedef, find its underlying type so 
-       we can correctly determine how to generate a pointer to it */ 
-    tkey = get_true_type(tkey); 
-    tval = get_true_type(tval); 
- 
-    tkey_ptr = tkey->is_string() || !tkey->is_base_type() ? "" : "*"; 
-    tval_ptr = tval->is_string() || !tval->is_base_type() ? "" : "*"; 
- 
-    /* 
-     * Some ugliness here.  To maximize backwards compatibility, we 
-     * avoid using GHashTableIter and instead get a GList of all keys, 
-     * then copy it into a array on the stack, and free it. 
-     * This is because we may exit early before we get a chance to free the 
-     * GList. 
-     */ 
-    out << indent() << "GList *key_list = NULL, *iter = NULL;" << endl 
-        << indent() << tkey_name << tkey_ptr << "* keys;" << endl 
-        << indent() << "int i = 0, key_count;" << endl 
-        << endl 
-        << indent() << "if ((ret = thrift_protocol_write_map_begin (protocol, " 
-        << type_to_enum(tkey) << ", " << type_to_enum(tval) << ", " << prefix << " ? " 
-        << "(gint32) g_hash_table_size ((GHashTable *) " << prefix << ") : 0" 
-        << ", error)) < 0)" << endl; 
-    indent_up(); 
-    out << indent() << "return " << error_ret << ";" << endl; 
-    indent_down(); 
-    out << indent() << "xfer += ret;" << endl 
-        << indent() << "if (" << prefix << ")" << endl 
-        << indent() << "  g_hash_table_foreach ((GHashTable *) " << prefix 
-        << ", thrift_hash_table_get_keys, &key_list);" << endl 
-        << indent() << "key_count = g_list_length (key_list);" << endl 
-        << indent() << "keys = g_newa (" << tkey_name << tkey_ptr 
-        << ", key_count);" << endl 
-        << indent() << "for (iter = g_list_first (key_list); iter; " 
-           "iter = iter->next)" << endl; 
-    indent_up(); 
-    out << indent() << "keys[i++] = (" << tkey_name << tkey_ptr 
-        << ") iter->data;" << endl; 
-    indent_down(); 
-    out << indent() << "g_list_free (key_list);" << endl 
-        << endl 
-        << indent() << "for (i = 0; i < key_count; ++i)" << endl; 
-    scope_up(out); 
-    out << indent() << keyname << " = keys[i];" << endl 
-        << indent() << valname << " = (" << tval_name << tval_ptr 
-        << ") g_hash_table_lookup (((GHashTable *) " << prefix 
-        << "), (gpointer) " << keyname << ");" << endl 
-        << endl; 
-    generate_serialize_map_element(out, 
-                                   (t_map*)ttype, 
-                                   tkey_ptr + " " + keyname, 
-                                   tval_ptr + " " + valname, 
-                                   error_ret); 
-    scope_down(out); 
-    out << indent() << "if ((ret = thrift_protocol_write_map_end (protocol, " 
-           "error)) < 0)" << endl; 
-    indent_up(); 
-    out << indent() << "return " << error_ret << ";" << endl; 
-    indent_down(); 
-    out << indent() << "xfer += ret;" << endl; 
-  } else if (ttype->is_set()) { 
-    t_type* telem = ((t_set*)ttype)->get_elem_type(); 
-    string telem_name = type_name(telem); 
-    string telem_ptr = telem->is_string() || !telem->is_base_type() ? "" : "*"; 
-    out << indent() << "GList *key_list = NULL, *iter = NULL;" << endl 
-        << indent() << telem_name << telem_ptr << "* keys;" << endl 
-        << indent() << "int i = 0, key_count;" << endl 
-        << indent() << telem_name << telem_ptr << " elem;" << endl 
-        << indent() << "gpointer value;" << endl 
-        << indent() << "THRIFT_UNUSED_VAR (value);" << endl 
-        << endl 
-        << indent() << "if ((ret = thrift_protocol_write_set_begin (protocol, " 
-        << type_to_enum(telem) << ", " << prefix << " ? " 
-        << "(gint32) g_hash_table_size ((GHashTable *) " << prefix << ") : 0" 
-        << ", error)) < 0)" << endl; 
-    indent_up(); 
-    out << indent() << "return " << error_ret << ";" << endl; 
-    indent_down(); 
-    out << indent() << "xfer += ret;" << endl 
-        << indent() << "if (" << prefix << ")" << endl 
-        << indent() << "  g_hash_table_foreach ((GHashTable *) " << prefix 
-        << ", thrift_hash_table_get_keys, &key_list);" << endl 
-        << indent() << "key_count = g_list_length (key_list);" << endl 
-        << indent() << "keys = g_newa (" << telem_name << telem_ptr 
-        << ", key_count);" << endl 
-        << indent() << "for (iter = g_list_first (key_list); iter; " 
-           "iter = iter->next)" << endl; 
-    indent_up(); 
-    out << indent() << "keys[i++] = (" << telem_name << telem_ptr 
-        << ") iter->data;" << endl; 
-    indent_down(); 
-    out << indent() << "g_list_free (key_list);" << endl 
-        << endl 
-        << indent() << "for (i = 0; i < key_count; ++i)" << endl; 
-    scope_up(out); 
-    out << indent() << "elem = keys[i];" << endl 
-        << indent() << "value = (gpointer) g_hash_table_lookup " 
-           "(((GHashTable *) " << prefix << "), (gpointer) elem);" << endl 
-        << endl; 
-    generate_serialize_set_element(out, 
-                                   (t_set*)ttype, 
-                                   telem_ptr + "elem", 
-                                   error_ret); 
-    scope_down(out); 
-    out << indent() << "if ((ret = thrift_protocol_write_set_end (protocol, " 
-           "error)) < 0)" << endl; 
-    indent_up(); 
-    out << indent() << "return " << error_ret << ";" << endl; 
-    indent_down(); 
-    out << indent() << "xfer += ret;" << endl; 
-  } else if (ttype->is_list()) { 
-    string length = "(" + prefix + " ? " + prefix + "->len : 0)"; 
-    string i = tmp("i"); 
-    out << indent() << "guint " << i << ";" << endl 
-        << endl 
-        << indent() << "if ((ret = thrift_protocol_write_list_begin (protocol, " 
-        << type_to_enum(((t_list*)ttype)->get_elem_type()) << ", (gint32) " 
-        << length << ", error)) < 0)" << endl; 
-    indent_up(); 
-    out << indent() << "return " << error_ret << ";" << endl; 
-    indent_down(); 
-    out << indent() << "xfer += ret;" << endl 
-        << indent() << "for (" << i << " = 0; " << i << " < " << length << "; " 
-        << i << "++)" << endl; 
-    scope_up(out); 
-    generate_serialize_list_element(out, (t_list*)ttype, prefix, i, error_ret); 
-    scope_down(out); 
-    out << indent() << "if ((ret = thrift_protocol_write_list_end (protocol, " 
-           "error)) < 0)" << endl; 
-    indent_up(); 
-    out << indent() << "return " << error_ret << ";" << endl; 
-    indent_down(); 
-    out << indent() << "xfer += ret;" << endl; 
-  } 
- 
-  scope_down(out); 
-} 
- 
-void t_c_glib_generator::generate_serialize_map_element(ostream& out, 
-                                                        t_map* tmap, 
-                                                        string key, 
-                                                        string value, 
-                                                        int error_ret) { 
-  t_field kfield(tmap->get_key_type(), key); 
-  generate_serialize_field(out, &kfield, "", "", error_ret); 
- 
-  t_field vfield(tmap->get_val_type(), value); 
-  generate_serialize_field(out, &vfield, "", "", error_ret); 
-} 
- 
-void t_c_glib_generator::generate_serialize_set_element(ostream& out, 
-                                                        t_set* tset, 
-                                                        string element, 
-                                                        int error_ret) { 
-  t_field efield(tset->get_elem_type(), element); 
-  generate_serialize_field(out, &efield, "", "", error_ret); 
-} 
- 
-void t_c_glib_generator::generate_serialize_list_element(ostream& out, 
-                                                         t_list* tlist, 
-                                                         string list, 
-                                                         string index, 
-                                                         int error_ret) { 
-  t_type* ttype = get_true_type(tlist->get_elem_type()); 
- 
-  // cast to non-const 
-  string cast = ""; 
-  string name = "g_ptr_array_index ((GPtrArray *) " + list + ", " + index + ")"; 
- 
-  if (ttype->is_void()) { 
-    throw std::runtime_error("compiler error: list element type cannot be void"); 
-  } else if (is_numeric(ttype)) { 
-    name = "g_array_index (" + list + ", " + base_type_name(ttype) + ", " + index + ")"; 
-  } else if (ttype->is_string()) { 
-    cast = "(gchar*)"; 
-  } else if (ttype->is_map() || ttype->is_set()) { 
-    cast = "(GHashTable*)"; 
-  } else if (ttype->is_list()) { 
-    t_type* etype = ((t_list*)ttype)->get_elem_type(); 
-    if (etype->is_void()) { 
-      throw std::runtime_error("compiler error: list element type cannot be void"); 
-    } 
-    cast = is_numeric(etype) ? "(GArray*)" : "(GPtrArray*)"; 
-  } 
- 
-  t_field efield(ttype, "(" + cast + name + ")"); 
-  generate_serialize_field(out, &efield, "", "", error_ret); 
-} 
- 
-/* deserializes a field of any type. */ 
-void t_c_glib_generator::generate_deserialize_field(ostream& out, 
-                                                    t_field* tfield, 
-                                                    string prefix, 
-                                                    string suffix, 
-                                                    int error_ret, 
-                                                    bool allocate) { 
-  t_type* type = get_true_type(tfield->get_type()); 
- 
-  if (type->is_void()) { 
-    throw std::runtime_error("CANNOT GENERATE DESERIALIZE CODE FOR void TYPE: " + prefix 
-                             + tfield->get_name()); 
-  } 
- 
-  string name = prefix + tfield->get_name() + suffix; 
- 
-  if (type->is_struct() || type->is_xception()) { 
-    generate_deserialize_struct(out, (t_struct*)type, name, error_ret, allocate); 
-  } else if (type->is_container()) { 
-    generate_deserialize_container(out, type, name, error_ret); 
-  } else if (type->is_base_type()) { 
-    t_base_type::t_base tbase = ((t_base_type*)type)->get_base(); 
-    if (tbase == t_base_type::TYPE_STRING) { 
-      indent(out) << "if (" << name << " != NULL)" << endl << indent() << "{" << endl; 
-      indent_up(); 
-      indent(out) << "g_free(" << name << ");" << endl << indent() << name << " = NULL;" << endl; 
-      indent_down(); 
-      indent(out) << "}" << endl << endl; 
-    } 
-    indent(out) << "if ((ret = thrift_protocol_read_"; 
- 
-    switch (tbase) { 
-    case t_base_type::TYPE_VOID: 
-      throw "compiler error: cannot serialize void field in a struct: " + name; 
-      break; 
-    case t_base_type::TYPE_STRING: 
-      if (type->is_binary()) { 
-        out << "binary (protocol, &data, &len"; 
-      } else { 
-        out << "string (protocol, &" << name; 
-      } 
-      break; 
-    case t_base_type::TYPE_BOOL: 
-      out << "bool (protocol, &" << name; 
-      break; 
-    case t_base_type::TYPE_I8: 
-      out << "byte (protocol, &" << name; 
-      break; 
-    case t_base_type::TYPE_I16: 
-      out << "i16 (protocol, &" << name; 
-      break; 
-    case t_base_type::TYPE_I32: 
-      out << "i32 (protocol, &" << name; 
-      break; 
-    case t_base_type::TYPE_I64: 
-      out << "i64 (protocol, &" << name; 
-      break; 
-    case t_base_type::TYPE_DOUBLE: 
-      out << "double (protocol, &" << name; 
-      break; 
-    default: 
-      throw "compiler error: no C reader for base type " + t_base_type::t_base_name(tbase) + name; 
-    } 
-    out << ", error)) < 0)" << endl; 
-    out << indent() << "  return " << error_ret << ";" << endl << indent() << "xfer += ret;" 
-        << endl; 
- 
-    // load the byte array with the data 
-    if (tbase == t_base_type::TYPE_STRING && type->is_binary()) { 
-      indent(out) << name << " = g_byte_array_new();" << endl; 
-      indent(out) << "g_byte_array_append (" << name << ", (guint8 *) data, (guint) len);" << endl; 
-      indent(out) << "g_free (data);" << endl; 
-    } 
-  } else if (type->is_enum()) { 
-    string t = tmp("ecast"); 
-    out << indent() << "gint32 " << t << ";" << endl << indent() 
-        << "if ((ret = thrift_protocol_read_i32 (protocol, &" << t << ", error)) < 0)" << endl 
-        << indent() << "  return " << error_ret << ";" << endl << indent() << "xfer += ret;" << endl 
-        << indent() << name << " = (" << type_name(type) << ")" << t << ";" << endl; 
-  } else { 
-    throw std::logic_error("DO NOT KNOW HOW TO SERIALIZE FIELD '" + tfield->get_name() + "' TYPE '" 
-                           + type_name(type)); 
-  } 
- 
-  // if the type is not required and this is a thrift struct (no prefix), 
-  // set the isset variable.  if the type is required, then set the 
-  // local variable indicating the value was set, so that we can do    // validation later. 
-  if (prefix != "" && tfield->get_req() != t_field::T_REQUIRED) { 
-    indent(out) << prefix << "__isset_" << tfield->get_name() << suffix << " = TRUE;" << endl; 
-  } else if (prefix != "" && tfield->get_req() == t_field::T_REQUIRED) { 
-    indent(out) << "isset_" << tfield->get_name() << " = TRUE;" << endl; 
-  } 
-} 
- 
-void t_c_glib_generator::generate_deserialize_struct(ostream& out, 
-                                                     t_struct* tstruct, 
-                                                     string prefix, 
-                                                     int error_ret, 
-                                                     bool allocate) { 
-  string name_uc = to_upper_case(initial_caps_to_underscores(tstruct->get_name())); 
-  if (tstruct->is_xception()) { 
-    out << indent() << "/* This struct is an exception */" << endl; 
-    allocate = true; 
-  } 
- 
-  if (allocate) { 
-    out << indent() << "if ( " << prefix << " != NULL)" << endl << indent() << "{" << endl; 
-    indent_up(); 
-    out << indent() << "g_object_unref (" << prefix << ");" << endl; 
-    indent_down(); 
-    out << indent() << "}" << endl << indent() << prefix << " = g_object_new (" << this->nspace_uc 
-        << "TYPE_" << name_uc << ", NULL);" << endl; 
-  } 
-  out << indent() << "if ((ret = thrift_struct_read (THRIFT_STRUCT (" << prefix 
-      << "), protocol, error)) < 0)" << endl << indent() << "{" << endl; 
-  indent_up(); 
-  if (allocate) { 
-    indent(out) << "g_object_unref (" << prefix << ");" << endl; 
-    if (tstruct->is_xception()) { 
-      indent(out) << prefix << " = NULL;" << endl; 
-    } 
-  } 
-  out << indent() << "return " << error_ret << ";" << endl; 
-  indent_down(); 
-  out << indent() << "}" << endl << indent() << "xfer += ret;" << endl; 
-} 
- 
-void t_c_glib_generator::generate_deserialize_container(ostream& out, 
-                                                        t_type* ttype, 
-                                                        string prefix, 
-                                                        int error_ret) { 
-  scope_up(out); 
- 
-  if (ttype->is_map()) { 
-    out << indent() << "guint32 size;" << endl 
-        << indent() << "guint32 i;" << endl 
-        << indent() << "ThriftType key_type;" << endl 
-        << indent() << "ThriftType value_type;" << endl 
-        << endl 
-        << indent() << "/* read the map begin marker */" << endl 
-        << indent() << "if ((ret = thrift_protocol_read_map_begin (protocol, " 
-           "&key_type, &value_type, &size, error)) < 0)" << endl; 
-    indent_up(); 
-    out << indent() << "return " << error_ret << ";" << endl; 
-    indent_down(); 
-    out << indent() << "xfer += ret;" << endl 
-        << endl; 
- 
-    // iterate over map elements 
-    out << indent() << "/* iterate through each of the map's fields */" << endl 
-        << indent() << "for (i = 0; i < size; i++)" << endl; 
-    scope_up(out); 
-    generate_deserialize_map_element(out, (t_map*)ttype, prefix, error_ret); 
-    scope_down(out); 
-    out << endl; 
- 
-    // read map end 
-    out << indent() << "/* read the map end marker */" << endl 
-        << indent() << "if ((ret = thrift_protocol_read_map_end (protocol, " 
-           "error)) < 0)" << endl; 
-    indent_up(); 
-    out << indent() << "return " << error_ret << ";" << endl; 
-    indent_down(); 
-    out << indent() << "xfer += ret;" << endl; 
-  } else if (ttype->is_set()) { 
-    out << indent() << "guint32 size;" << endl 
-        << indent() << "guint32 i;" << endl 
-        << indent() << "ThriftType element_type;" << endl 
-        << endl 
-        << indent() << "if ((ret = thrift_protocol_read_set_begin (protocol, " 
-           "&element_type, &size, error)) < 0)" << endl; 
-    indent_up(); 
-    out << indent() << "return " << error_ret << ";" << endl; 
-    indent_down(); 
-    out << indent() << "xfer += ret;" << endl 
-        << endl; 
- 
-    // iterate over the elements 
-    out << indent() << "/* iterate through the set elements */" << endl 
-        << indent() << "for (i = 0; i < size; ++i)" << endl; 
-    scope_up(out); 
-    generate_deserialize_set_element(out, (t_set*)ttype, prefix, error_ret); 
-    scope_down(out); 
- 
-    // read set end 
-    out << indent() << "if ((ret = thrift_protocol_read_set_end (protocol, " 
-           "error)) < 0)" << endl; 
-    indent_up(); 
-    out << indent() << "return " << error_ret << ";" << endl; 
-    indent_down(); 
-    out << indent() << "xfer += ret;" << endl 
-        << endl; 
-  } else if (ttype->is_list()) { 
-    out << indent() << "guint32 size;" << endl 
-        << indent() << "guint32 i;" << endl 
-        << indent() << "ThriftType element_type;" << endl 
-        << endl 
-        << indent() << "if ((ret = thrift_protocol_read_list_begin (protocol, " 
-           "&element_type,&size, error)) < 0)" << endl; 
-    indent_up(); 
-    out << indent() << "return " << error_ret << ";" << endl; 
-    indent_down(); 
-    out << indent() << "xfer += ret;" << endl 
-        << endl; 
- 
-    // iterate over the elements 
-    out << indent() << "/* iterate through list elements */" << endl 
-        << indent() << "for (i = 0; i < size; i++)" << endl; 
-    scope_up(out); 
-    generate_deserialize_list_element(out, 
-                                      (t_list*)ttype, 
-                                      prefix, 
-                                      "i", 
-                                      error_ret); 
-    scope_down(out); 
- 
-    // read list end 
-    out << indent() << "if ((ret = thrift_protocol_read_list_end (protocol, " 
-           "error)) < 0)" << endl; 
-    indent_up(); 
-    out << indent() << "return " << error_ret << ";" << endl; 
-    indent_down(); 
-    out << indent() << "xfer += ret;" << endl; 
-  } 
- 
-  scope_down(out); 
-} 
- 
-void t_c_glib_generator::declare_local_variable(ostream& out, t_type* ttype, string& name, bool for_hash_table) { 
-  string tname = type_name(ttype); 
- 
-  /* If the given type is a typedef, find its underlying type so we 
-     can correctly determine how to generate a pointer to it */ 
-  ttype = get_true_type(ttype); 
-  string ptr = !is_numeric(ttype) ? "" : "*"; 
- 
-  if (ttype->is_map()) { 
-    t_map* tmap = (t_map*)ttype; 
-    out << indent() << tname << ptr << " " << name << " = " 
-        << generate_new_hash_from_type(tmap->get_key_type(), tmap->get_val_type()) << endl; 
-  } else if (ttype->is_list()) { 
-    t_list* tlist = (t_list*)ttype; 
-    out << indent() << tname << ptr << " " << name << " = " 
-        << generate_new_array_from_type(tlist->get_elem_type()) << endl; 
-  } else if (for_hash_table && ttype->is_enum()) { 
-    out << indent() << tname << " " << name << ";" << endl; 
-  } else { 
-    out << indent() << tname << ptr << " " << name 
-        << (ptr != "" ? " = g_new (" + tname + ", 1)" : " = NULL") << ";" << endl; 
-  } 
-} 
- 
-void t_c_glib_generator::declore_local_variable_for_write(ostream& out, 
-                                                          t_type* ttype, 
-                                                          string& name) { 
-  string tname = type_name(ttype); 
-  ttype = get_true_type(ttype); 
-  string ptr = ttype->is_string() || !ttype->is_base_type() ? " " : "* "; 
-  string init_val = ttype->is_enum() ? "" : " = NULL"; 
-  out << indent() << tname << ptr << name << init_val << ";" << endl; 
-} 
- 
-void t_c_glib_generator::generate_deserialize_map_element(ostream& out, 
-                                                          t_map* tmap, 
-                                                          string prefix, 
-                                                          int error_ret) { 
-  t_type* tkey = tmap->get_key_type(); 
-  t_type* tval = tmap->get_val_type(); 
-  string keyname = tmp("key"); 
-  string valname = tmp("val"); 
- 
-  declare_local_variable(out, tkey, keyname, true); 
-  declare_local_variable(out, tval, valname, true); 
- 
-  /* If either the key or value type is a typedef, find its underlying 
-     type so we can correctly determine how to generate a pointer to 
-     it */ 
-  tkey = get_true_type(tkey); 
-  tval = get_true_type(tval); 
- 
-  string tkey_ptr = tkey->is_string() || !tkey->is_base_type() ? "" : "*"; 
-  string tval_ptr = tval->is_string() || !tval->is_base_type() ? "" : "*"; 
- 
-  // deserialize the fields of the map element 
-  t_field fkey(tkey, tkey_ptr + keyname); 
-  generate_deserialize_field(out, &fkey, "", "", error_ret); 
-  t_field fval(tval, tval_ptr + valname); 
-  generate_deserialize_field(out, &fval, "", "", error_ret); 
- 
-  indent(out) << "if (" << prefix << " && " << keyname << ")" << endl; 
-  indent_up(); 
-  indent(out) << "g_hash_table_insert ((GHashTable *)" << prefix << ", (gpointer) " << keyname 
-              << ", (gpointer) " << valname << ");" << endl; 
-  indent_down(); 
-} 
- 
-void t_c_glib_generator::generate_deserialize_set_element(ostream& out, 
-                                                          t_set* tset, 
-                                                          string prefix, 
-                                                          int error_ret) { 
-  t_type* telem = tset->get_elem_type(); 
-  string elem = tmp("_elem"); 
-  string telem_ptr = telem->is_string() || !telem->is_base_type() ? "" : "*"; 
- 
-  declare_local_variable(out, telem, elem, true); 
- 
-  t_field felem(telem, telem_ptr + elem); 
-  generate_deserialize_field(out, &felem, "", "", error_ret); 
- 
-  indent(out) << "if (" << prefix << " && " << elem << ")" << endl; 
-  indent_up(); 
-  indent(out) << "g_hash_table_insert ((GHashTable *) " << prefix << ", (gpointer) " << elem 
-              << ", (gpointer) " << elem << ");" << endl; 
-  indent_down(); 
-} 
- 
-void t_c_glib_generator::generate_deserialize_list_element(ostream& out, 
-                                                           t_list* tlist, 
-                                                           string prefix, 
-                                                           string index, 
-                                                           int error_ret) { 
-  (void)index; 
-  t_type* ttype = get_true_type(tlist->get_elem_type()); 
-  string elem = tmp("_elem"); 
-  string telem_ptr = !is_numeric(ttype) ? "" : "*"; 
- 
-  declare_local_variable(out, ttype, elem, false); 
- 
-  t_field felem(ttype, telem_ptr + elem); 
-  generate_deserialize_field(out, &felem, "", "", error_ret); 
- 
-  if (ttype->is_void()) { 
-    throw std::runtime_error("compiler error: list element type cannot be void"); 
-  } else if (is_numeric(ttype)) { 
-    indent(out) << "g_array_append_vals (" << prefix << ", " << elem << ", 1);" << endl; 
-  } else { 
-    indent(out) << "g_ptr_array_add (" << prefix << ", " << elem << ");" << endl; 
-  } 
-} 
- 
-string t_c_glib_generator::generate_free_func_from_type(t_type* ttype) { 
-  if (ttype == NULL) 
-    return "NULL"; 
- 
-  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 "compiler error: cannot determine hash type"; 
-      break; 
-    case t_base_type::TYPE_BOOL: 
-    case t_base_type::TYPE_I8: 
-    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 "g_free"; 
-    case t_base_type::TYPE_STRING: 
-      if (((t_base_type*)ttype)->is_binary()) { 
-        return "thrift_string_free"; 
-      } 
-      return "g_free"; 
-    default: 
-      throw "compiler error: no hash table info for type"; 
-    } 
-  } else if (ttype->is_enum()) { 
-    return "NULL"; 
-  } else if (ttype->is_map() || ttype->is_set()) { 
-    return "(GDestroyNotify) thrift_safe_hash_table_destroy"; 
-  } else if (ttype->is_struct()) { 
-    return "g_object_unref"; 
-  } else if (ttype->is_list()) { 
-    t_type* etype = ((t_list*)ttype)->get_elem_type(); 
-    if (etype->is_base_type()) { 
-      t_base_type::t_base tbase = ((t_base_type*)etype)->get_base(); 
-      switch (tbase) { 
-      case t_base_type::TYPE_VOID: 
-        throw "compiler error: cannot determine array type"; 
-        break; 
-      case t_base_type::TYPE_BOOL: 
-      case t_base_type::TYPE_I8: 
-      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 "(GDestroyNotify) g_array_unref"; 
-      case t_base_type::TYPE_STRING: 
-        return "(GDestroyNotify) g_ptr_array_unref"; 
-      default: 
-        throw "compiler error: no array info for type"; 
-      } 
-    } else if (etype->is_container() || etype->is_struct()) { 
-      return "(GDestroyNotify) g_ptr_array_unref"; 
-      ; 
-    } else if (etype->is_enum()) { 
-      return "(GDestroyNotify) g_array_unref"; 
-    } 
-    printf("Type not expected inside the array: %s\n", etype->get_name().c_str()); 
-    throw "Type not expected inside array"; 
-  } else if (ttype->is_typedef()) { 
-    return generate_free_func_from_type(((t_typedef*)ttype)->get_type()); 
-  } 
-  printf("Type not expected: %s\n", ttype->get_name().c_str()); 
-  throw "Type not expected"; 
-} 
- 
-string t_c_glib_generator::generate_hash_func_from_type(t_type* ttype) { 
-  if (ttype == NULL) 
-    return "NULL"; 
- 
-  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 "compiler error: cannot determine hash type"; 
-      break; 
-    case t_base_type::TYPE_BOOL: 
-      return "thrift_boolean_hash"; 
-    case t_base_type::TYPE_I8: 
-      return "thrift_int8_hash"; 
-    case t_base_type::TYPE_I16: 
-      return "thrift_int16_hash"; 
-    case t_base_type::TYPE_I32: 
-      return "g_int_hash"; 
-    case t_base_type::TYPE_I64: 
-      return "g_int64_hash"; 
-    case t_base_type::TYPE_DOUBLE: 
-      return "g_double_hash"; 
-    case t_base_type::TYPE_STRING: 
-      return "g_str_hash"; 
-    default: 
-      throw "compiler error: no hash table info for type"; 
-    } 
-  } else if (ttype->is_enum()) { 
-    return "g_direct_hash"; 
-  } else if (ttype->is_container() || ttype->is_struct()) { 
-    return "g_direct_hash"; 
-  } else if (ttype->is_typedef()) { 
-    return generate_hash_func_from_type(((t_typedef*)ttype)->get_type()); 
-  } 
-  printf("Type not expected: %s\n", ttype->get_name().c_str()); 
-  throw "Type not expected"; 
-} 
- 
-string t_c_glib_generator::generate_cmp_func_from_type(t_type* ttype) { 
-  if (ttype == NULL) 
-    return "NULL"; 
- 
-  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 "compiler error: cannot determine hash type"; 
-      break; 
-    case t_base_type::TYPE_BOOL: 
-      return "thrift_boolean_equal"; 
-    case t_base_type::TYPE_I8: 
-      return "thrift_int8_equal"; 
-    case t_base_type::TYPE_I16: 
-      return "thrift_int16_equal"; 
-    case t_base_type::TYPE_I32: 
-      return "g_int_equal"; 
-    case t_base_type::TYPE_I64: 
-      return "g_int64_equal"; 
-    case t_base_type::TYPE_DOUBLE: 
-      return "g_double_equal"; 
-    case t_base_type::TYPE_STRING: 
-      return "g_str_equal"; 
-    default: 
-      throw "compiler error: no hash table info for type"; 
-    } 
-  } else if (ttype->is_enum()) { 
-    return "g_direct_equal"; 
-  } else if (ttype->is_container() || ttype->is_struct()) { 
-    return "g_direct_equal"; 
-  } else if (ttype->is_typedef()) { 
-    return generate_cmp_func_from_type(((t_typedef*)ttype)->get_type()); 
-  } 
-  printf("Type not expected: %s\n", ttype->get_name().c_str()); 
-  throw "Type not expected"; 
-} 
- 
-string t_c_glib_generator::generate_new_hash_from_type(t_type* key, t_type* value) { 
-  string hash_func = generate_hash_func_from_type(key); 
-  string cmp_func = generate_cmp_func_from_type(key); 
-  string key_free_func = generate_free_func_from_type(key); 
-  string value_free_func = generate_free_func_from_type(value); 
- 
-  return "g_hash_table_new_full (" + hash_func + ", " + cmp_func + ", " + key_free_func + ", " 
-         + value_free_func + ");"; 
-} 
- 
-string t_c_glib_generator::generate_new_array_from_type(t_type* ttype) { 
-  if (ttype->is_void()) { 
-    throw std::runtime_error("compiler error: cannot determine array type"); 
-  } else if (is_numeric(ttype)) { 
-    return "g_array_new (0, 1, sizeof (" + base_type_name(ttype) + "));"; 
-  } else { 
-    string free_func = generate_free_func_from_type(ttype); 
-    return "g_ptr_array_new_with_free_func (" + free_func + ");"; 
-  } 
-} 
- 
-/*************************************** 
- * UTILITY FUNCTIONS                   * 
- ***************************************/ 
- 
-/** 
- * Upper case a string.  Wraps boost's string utility. 
- */ 
-string to_upper_case(string name) { 
-  string s(name); 
-  std::transform(s.begin(), s.end(), s.begin(), ::toupper); 
-  return s; 
-  //  return boost::to_upper_copy (name); 
-} 
- 
-/** 
- * Lower case a string.  Wraps boost's string utility. 
- */ 
-string to_lower_case(string name) { 
-  string s(name); 
-  std::transform(s.begin(), s.end(), s.begin(), ::tolower); 
-  return s; 
-  //  return boost::to_lower_copy (name); 
-} 
- 
-/** 
- * Makes a string friendly to C code standards by lowercasing and adding 
- * underscores, with the exception of the first character.  For example: 
- * 
- * Input: "ZomgCamelCase" 
- * Output: "zomg_camel_case" 
- */ 
-string initial_caps_to_underscores(string name) { 
-  string ret; 
-  const char* tmp = name.c_str(); 
-  int pos = 0; 
- 
-  /* the first character isn't underscored if uppercase, just lowercased */ 
-  ret += tolower(tmp[pos]); 
-  pos++; 
-  for (unsigned int i = pos; i < name.length(); i++) { 
-    char lc = tolower(tmp[i]); 
-    if (lc != tmp[i]) { 
-      ret += '_'; 
-    } 
-    ret += lc; 
-  } 
- 
-  return ret; 
-} 
- 
-/** 
- * Performs the reverse operation of initial_caps_to_underscores: The first 
- * character of the string is made uppercase, along with each character that 
- * follows an underscore (which is removed). Useful for converting Thrift 
- * service-method names into GObject-style class names. 
- * 
- * Input: "zomg_camel_case" 
- * Output: "ZomgCamelCase" 
- */ 
-string underscores_to_initial_caps(string name) { 
-  string ret; 
-  const char* tmp = name.c_str(); 
-  bool uppercase_next = true; 
- 
-  for (unsigned int i = 0; i < name.length(); i++) { 
-    char c = tmp[i]; 
-    if (c == '_') { 
-      uppercase_next = true; 
-    } else { 
-      if (uppercase_next) { 
-        ret += toupper(c); 
-        uppercase_next = false; 
-      } else { 
-        ret += c; 
-      } 
-    } 
-  } 
- 
-  return ret; 
-} 
- 
-/* register this generator with the main program */ 
-THRIFT_REGISTER_GENERATOR(c_glib, "C, using GLib", "") 
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ * Contains some contributions under the Thrift Software License.
+ * Please see doc/old-thrift-license.txt in the Thrift distribution for
+ * details.
+ */
+
+#include <fstream>
+#include <iostream>
+#include <stdexcept>
+#include <string>
+#include <vector>
+
+#include <ctype.h>
+
+#include "thrift/platform.h"
+#include "thrift/generate/t_oop_generator.h"
+
+using std::map;
+using std::ostream;
+using std::ostringstream;
+using std::string;
+using std::stringstream;
+using std::vector;
+
+static const string endl = "\n"; // avoid ostream << std::endl flushes
+
+/* forward declarations */
+string initial_caps_to_underscores(string name);
+string underscores_to_initial_caps(string name);
+string to_upper_case(string name);
+string to_lower_case(string name);
+
+/**
+ * C code generator, using glib for C typing.
+ */
+class t_c_glib_generator : public t_oop_generator {
+public:
+  /* constructor */
+  t_c_glib_generator(t_program* program,
+                     const map<string, string>& parsed_options,
+                     const string& option_string)
+    : t_oop_generator(program) {
+    (void)option_string;
+    std::map<std::string, std::string>::const_iterator iter;
+
+    /* set the output directory */
+    this->out_dir_base_ = "gen-c_glib";
+
+    /* no options yet */
+    for( iter = parsed_options.begin(); iter != parsed_options.end(); ++iter) {
+      throw "unknown option c_glib:" + iter->first;
+    }
+
+    /* set the namespace */
+    this->nspace = program_->get_namespace("c_glib");
+
+    if (this->nspace.empty()) {
+      this->nspace = "";
+      this->nspace_u = "";
+      this->nspace_uc = "";
+      this->nspace_lc = "";
+    } else {
+      /* replace dots with underscores */
+      char* tmp = strdup(this->nspace.c_str());
+      for (unsigned int i = 0; i < strlen(tmp); i++) {
+        if (tmp[i] == '.') {
+          tmp[i] = '_';
+        }
+      }
+      this->nspace = string(tmp, strlen(tmp));
+      free(tmp);
+
+      /* clean up the namespace for C.
+       * An input of 'namespace foo' should result in:
+       *  - nspace = foo       - for thrift objects and typedefs
+       *  - nspace_u = Foo     - for internal GObject prefixes
+       *  - nspace_uc = FOO_   - for macro prefixes
+       *  - nspace_lc = foo_   - for filename and method prefixes
+       * The underscores are there since uc and lc strings are used as file and
+       * variable prefixes.
+       */
+      this->nspace_u = initial_caps_to_underscores(this->nspace);
+      this->nspace_uc = to_upper_case(this->nspace_u) + "_";
+      this->nspace_lc = to_lower_case(this->nspace_u) + "_";
+    }
+  }
+
+  /* initialization and destruction */
+  void init_generator();
+  void close_generator();
+
+  /* generation functions */
+  void generate_typedef(t_typedef* ttypedef);
+  void generate_enum(t_enum* tenum);
+  void generate_consts(vector<t_const*> consts);
+  void generate_struct(t_struct* tstruct);
+  void generate_service(t_service* tservice);
+  void generate_xception(t_struct* tstruct);
+
+private:
+  /* file streams */
+  ofstream_with_content_based_conditional_update f_types_;
+  ofstream_with_content_based_conditional_update f_types_impl_;
+  ofstream_with_content_based_conditional_update f_header_;
+  ofstream_with_content_based_conditional_update f_service_;
+
+  /* namespace variables */
+  string nspace;
+  string nspace_u;
+  string nspace_uc;
+  string nspace_lc;
+
+  /* helper functions */
+  bool is_complex_type(t_type* ttype);
+  bool is_numeric(t_type* ttype);
+  string type_name(t_type* ttype, bool in_typedef = false, bool is_const = false);
+  string property_type_name(t_type* ttype, bool in_typedef = false, bool is_const = false);
+  string base_type_name(t_type* type);
+  string type_to_enum(t_type* type);
+  string constant_literal(t_type* type, t_const_value* value);
+  string constant_value(string name, t_type* type, t_const_value* value);
+  string constant_value_with_storage(string name, t_type* type, t_const_value* value);
+  string function_signature(t_function* tfunction);
+  string argument_list(t_struct* tstruct);
+  string xception_list(t_struct* tstruct);
+  string declare_field(t_field* tfield,
+                       bool init = false,
+                       bool pointer = false,
+                       bool constant = false,
+                       bool reference = false);
+  void declare_local_variable(ostream& out, t_type* ttype, string& base_name, bool for_hash_table);
+  void declore_local_variable_for_write(ostream& out, t_type* ttype, string& base_name);
+
+  /* generation functions */
+  void generate_const_initializer(string name,
+                                  t_type* type,
+                                  t_const_value* value,
+                                  bool top_level = false);
+  void generate_service_helpers(t_service* tservice);
+  void generate_service_client(t_service* tservice);
+  void generate_service_handler(t_service* tservice);
+  void generate_service_processor(t_service* tservice);
+  void generate_service_server(t_service* tservice);
+  void generate_object(t_struct* tstruct);
+  void generate_struct_writer(ostream& out,
+                              t_struct* tstruct,
+                              string this_name,
+                              string this_get = "",
+                              bool is_function = true);
+  void generate_struct_reader(ostream& out,
+                              t_struct* tstruct,
+                              string this_name,
+                              string this_get = "",
+                              bool is_function = true);
+
+  void generate_serialize_field(ostream& out,
+                                t_field* tfield,
+                                string prefix,
+                                string suffix,
+                                int error_ret);
+  void generate_serialize_struct(ostream& out, t_struct* tstruct, string prefix, int error_ret);
+  void generate_serialize_container(ostream& out, t_type* ttype, string prefix, int error_ret);
+  void generate_serialize_map_element(ostream& out,
+                                      t_map* tmap,
+                                      string key,
+                                      string value,
+                                      int error_ret);
+  void generate_serialize_set_element(ostream& out, t_set* tset, string element, int error_ret);
+  void generate_serialize_list_element(ostream& out,
+                                       t_list* tlist,
+                                       string list,
+                                       string index,
+                                       int error_ret);
+
+  void generate_deserialize_field(ostream& out,
+                                  t_field* tfield,
+                                  string prefix,
+                                  string suffix,
+                                  int error_ret,
+                                  bool allocate = true);
+  void generate_deserialize_struct(ostream& out,
+                                   t_struct* tstruct,
+                                   string prefix,
+                                   int error_ret,
+                                   bool allocate = true);
+  void generate_deserialize_container(ostream& out, t_type* ttype, string prefix, int error_ret);
+  void generate_deserialize_map_element(ostream& out, t_map* tmap, string prefix, int error_ret);
+  void generate_deserialize_set_element(ostream& out, t_set* tset, string prefix, int error_ret);
+  void generate_deserialize_list_element(ostream& out,
+                                         t_list* tlist,
+                                         string prefix,
+                                         string index,
+                                         int error_ret);
+
+  string generate_new_hash_from_type(t_type* key, t_type* value);
+  string generate_new_array_from_type(t_type* ttype);
+
+  string generate_free_func_from_type(t_type* ttype);
+  string generate_hash_func_from_type(t_type* ttype);
+  string generate_cmp_func_from_type(t_type* ttype);
+};
+
+/**
+ * Prepare for file generation by opening up the necessary file
+ * output streams.
+ */
+void t_c_glib_generator::init_generator() {
+  /* create output directory */
+  MKDIR(get_out_dir().c_str());
+
+  string program_name_u = initial_caps_to_underscores(program_name_);
+  string program_name_uc = to_upper_case(program_name_u);
+  string program_name_lc = to_lower_case(program_name_u);
+
+  /* create output files */
+  string f_types_name = get_out_dir() + this->nspace_lc + program_name_lc + "_types.h";
+  f_types_.open(f_types_name.c_str());
+  string f_types_impl_name = get_out_dir() + this->nspace_lc + program_name_lc + "_types.c";
+  f_types_impl_.open(f_types_impl_name.c_str());
+
+  /* add thrift boilerplate headers */
+  f_types_ << autogen_comment();
+  f_types_impl_ << autogen_comment();
+
+  /* include inclusion guard */
+  f_types_ << "#ifndef " << this->nspace_uc << program_name_uc << "_TYPES_H" << endl << "#define "
+           << this->nspace_uc << program_name_uc << "_TYPES_H" << endl << endl;
+
+  /* include base types */
+  f_types_ << "/* base includes */" << endl << "#include <glib-object.h>" << endl
+           << "#include <thrift/c_glib/thrift_struct.h>" << endl
+           << "#include <thrift/c_glib/protocol/thrift_protocol.h>" << endl;
+
+  /* include other thrift includes */
+  const vector<t_program*>& includes = program_->get_includes();
+  for (size_t i = 0; i < includes.size(); ++i) {
+    f_types_ << "/* other thrift includes */" << endl << "#include \"" << this->nspace_lc
+             << initial_caps_to_underscores(includes[i]->get_name()) << "_types.h\"" << endl;
+  }
+  f_types_ << endl;
+
+  /* include custom headers */
+  const vector<string>& c_includes = program_->get_c_includes();
+  f_types_ << "/* custom thrift includes */" << endl;
+  for (size_t i = 0; i < c_includes.size(); ++i) {
+    if (c_includes[i][0] == '<') {
+      f_types_ << "#include " << c_includes[i] << endl;
+    } else {
+      f_types_ << "#include \"" << c_includes[i] << "\"" << endl;
+    }
+  }
+  f_types_ << endl;
+
+  /* include math.h (for "INFINITY") in the implementation file, in case we
+     encounter a struct with a member of type double */
+  f_types_impl_ << endl << "#include <math.h>" << endl;
+
+  // include the types file
+  f_types_impl_ << endl << "#include \"" << this->nspace_lc << program_name_u << "_types.h\""
+                << endl << "#include <thrift/c_glib/thrift.h>" << endl << endl;
+
+  f_types_ << "/* begin types */" << endl << endl;
+}
+
+/**
+ *  Finish up generation and close all file streams.
+ */
+void t_c_glib_generator::close_generator() {
+  string program_name_uc = to_upper_case(initial_caps_to_underscores(program_name_));
+
+  /* end the header inclusion guard */
+  f_types_ << "#endif /* " << this->nspace_uc << program_name_uc << "_TYPES_H */" << endl;
+
+  /* close output file */
+  f_types_.close();
+  f_types_impl_.close();
+}
+
+/**
+ * Generates a Thrift typedef in C code.  For example:
+ *
+ * Thrift:
+ * typedef map<i32,i32> SomeMap
+ *
+ * C:
+ * typedef GHashTable * ThriftSomeMap;
+ */
+void t_c_glib_generator::generate_typedef(t_typedef* ttypedef) {
+  f_types_ << indent() << "typedef " << type_name(ttypedef->get_type(), true) << " " << this->nspace
+           << ttypedef->get_symbolic() << ";" << endl << endl;
+}
+
+/**
+ * Generates a C enumeration.  For example:
+ *
+ * Thrift:
+ * enum MyEnum {
+ *   ONE = 1,
+ *   TWO
+ * }
+ *
+ * C:
+ * enum _ThriftMyEnum {
+ *   THRIFT_MY_ENUM_ONE = 1,
+ *   THRIFT_MY_ENUM_TWO
+ * };
+ * typedef enum _ThriftMyEnum ThriftMyEnum;
+ */
+void t_c_glib_generator::generate_enum(t_enum* tenum) {
+  string name = tenum->get_name();
+  string name_uc = to_upper_case(initial_caps_to_underscores(name));
+
+  f_types_ << indent() << "enum _" << this->nspace << name << " {" << endl;
+
+  indent_up();
+
+  vector<t_enum_value*> constants = tenum->get_constants();
+  vector<t_enum_value*>::iterator c_iter;
+  bool first = true;
+
+  /* output each of the enumeration elements */
+  for (c_iter = constants.begin(); c_iter != constants.end(); ++c_iter) {
+    if (first) {
+      first = false;
+    } else {
+      f_types_ << "," << endl;
+    }
+
+    f_types_ << indent() << this->nspace_uc << name_uc << "_" << (*c_iter)->get_name();
+    f_types_ << " = " << (*c_iter)->get_value();
+  }
+
+  indent_down();
+  f_types_ << endl << "};" << endl << "typedef enum _" << this->nspace << name << " "
+           << this->nspace << name << ";" << endl << endl;
+
+  f_types_ << "/* return the name of the constant */" << endl;
+  f_types_ << "const char *" << endl;
+  f_types_ << "toString_" << name << "(int value); " << endl << endl;
+  ;
+  f_types_impl_ << "/* return the name of the constant */" << endl;
+  f_types_impl_ << "const char *" << endl;
+  f_types_impl_ << "toString_" << name << "(int value) " << endl;
+  f_types_impl_ << "{" << endl;
+  f_types_impl_ << "  static __thread char buf[16] = {0};" << endl;
+  f_types_impl_ << "  switch(value) {" << endl;
+  std::set<int> done;
+  for (c_iter = constants.begin(); c_iter != constants.end(); ++c_iter) {
+    int value = (*c_iter)->get_value();
+    // Skipping duplicate value
+    if (done.find(value) == done.end()) {
+      done.insert(value);
+      f_types_impl_ << "  case " << this->nspace_uc << name_uc << "_" << (*c_iter)->get_name()
+                    << ":"
+                    << "return \"" << this->nspace_uc << name_uc << "_" << (*c_iter)->get_name()
+                    << "\";" << endl;
+    }
+  }
+  f_types_impl_ << "  default: g_snprintf(buf, 16, \"%d\", value); return buf;" << endl;
+  f_types_impl_ << "  }" << endl;
+  f_types_impl_ << "}" << endl << endl;
+}
+
+/**
+ * Generates Thrift constants in C code.
+ */
+void t_c_glib_generator::generate_consts(vector<t_const*> consts) {
+  f_types_ << "/* constants */" << endl;
+  f_types_impl_ << "/* constants */" << endl;
+
+  vector<t_const*>::iterator c_iter;
+  for (c_iter = consts.begin(); c_iter != consts.end(); ++c_iter) {
+    string name = (*c_iter)->get_name();
+    string name_uc = to_upper_case(name);
+    string name_lc = to_lower_case(name);
+    t_type* type = (*c_iter)->get_type();
+    t_const_value* value = (*c_iter)->get_value();
+
+    if (is_complex_type(type)) {
+      f_types_ << type_name(type) << indent() << this->nspace_lc << name_lc
+               << "_constant();" << endl;
+    }
+
+    f_types_ << indent() << "#define " << this->nspace_uc << name_uc << " "
+             << constant_value(name_lc, type, value) << endl;
+
+    generate_const_initializer(name_lc, type, value, true);
+  }
+
+  f_types_ << endl;
+  f_types_impl_ << endl;
+}
+
+/**
+ * Generate Thrift structs in C code, as GObjects.  Example:
+ *
+ * Thrift:
+ * struct Bonk
+ * {
+ *   1: string message,
+ *   2: i32 type
+ * }
+ *
+ * C GObject instance header:
+ * struct _ThriftBonk
+ * {
+ *   GObject parent;
+ *
+ *   gchar * message;
+ *   gint32 type;
+ * };
+ * typedef struct _ThriftBonk ThriftBonk
+ * // ... additional GObject boilerplate ...
+ */
+void t_c_glib_generator::generate_struct(t_struct* tstruct) {
+  f_types_ << "/* struct " << tstruct->get_name() << " */" << endl;
+  generate_object(tstruct);
+}
+
+/**
+ * Generate C code to represent Thrift services.  Creates a new GObject
+ * which can be used to access the service.
+ */
+void t_c_glib_generator::generate_service(t_service* tservice) {
+  string svcname_u = initial_caps_to_underscores(tservice->get_name());
+  string svcname_uc = this->nspace_uc + to_upper_case(svcname_u);
+  string filename = this->nspace_lc + to_lower_case(svcname_u);
+
+  // make output files
+  string f_header_name = get_out_dir() + filename + ".h";
+  f_header_.open(f_header_name.c_str());
+
+  string program_name_u = initial_caps_to_underscores(program_name_);
+  string program_name_lc = to_lower_case(program_name_u);
+
+  // add header file boilerplate
+  f_header_ << autogen_comment();
+
+  // add an inclusion guard
+  f_header_ << "#ifndef " << svcname_uc << "_H" << endl << "#define " << svcname_uc << "_H" << endl
+            << endl;
+
+  // add standard includes
+  f_header_ << "#include <thrift/c_glib/processor/thrift_dispatch_processor.h>" << endl << endl;
+  f_header_ << "#include \"" << this->nspace_lc << program_name_lc << "_types.h\"" << endl;
+
+  // if we are inheriting from another service, include its header
+  t_service* extends_service = tservice->get_extends();
+  if (extends_service != NULL) {
+    f_header_ << "#include \"" << this->nspace_lc
+              << to_lower_case(initial_caps_to_underscores(extends_service->get_name())) << ".h\""
+              << endl;
+  }
+  f_header_ << endl;
+
+  // create the service implementation
+  string f_service_name = get_out_dir() + filename + ".c";
+  f_service_.open(f_service_name.c_str());
+
+  // add the boilerplace header
+  f_service_ << autogen_comment();
+
+  // include the headers
+  f_service_ << "#include <string.h>" << endl << "#include <thrift/c_glib/thrift.h>" << endl
+             << "#include <thrift/c_glib/thrift_application_exception.h>" << endl << "#include \""
+             << filename << ".h\"" << endl << endl;
+
+  // generate the service-helper classes
+  generate_service_helpers(tservice);
+
+  // generate the client objects
+  generate_service_client(tservice);
+
+  // generate the server objects
+  generate_service_server(tservice);
+
+  // end the header inclusion guard
+  f_header_ << "#endif /* " << svcname_uc << "_H */" << endl;
+
+  // close the files
+  f_service_.close();
+  f_header_.close();
+}
+
+/**
+ *
+ */
+void t_c_glib_generator::generate_xception(t_struct* tstruct) {
+  string name = tstruct->get_name();
+  string name_u = initial_caps_to_underscores(name);
+  string name_lc = to_lower_case(name_u);
+  string name_uc = to_upper_case(name_u);
+
+  generate_object(tstruct);
+
+  f_types_ << "/* exception */" << endl
+           << "typedef enum" << endl
+           << "{" << endl;
+  indent_up();
+  f_types_ << indent() << this->nspace_uc << name_uc << "_ERROR_CODE" << endl;
+  indent_down();
+  f_types_ << "} " << this->nspace << name << "Error;" << endl
+           << endl
+           << "GQuark " << this->nspace_lc << name_lc
+           << "_error_quark (void);" << endl
+           << "#define " << this->nspace_uc << name_uc << "_ERROR ("
+           << this->nspace_lc << name_lc << "_error_quark())" << endl
+           << endl
+           << endl;
+
+  f_types_impl_ << "/* define the GError domain for exceptions */" << endl << "#define "
+                << this->nspace_uc << name_uc << "_ERROR_DOMAIN \"" << this->nspace_lc << name_lc
+                << "_error_quark\"" << endl << "GQuark" << endl << this->nspace_lc << name_lc
+                << "_error_quark (void)" << endl << "{" << endl
+                << "  return g_quark_from_static_string (" << this->nspace_uc << name_uc
+                << "_ERROR_DOMAIN);" << endl << "}" << endl << endl;
+}
+
+/********************
+ * HELPER FUNCTIONS *
+ ********************/
+
+/**
+ * Returns true if ttype is not a primitive.
+ */
+bool t_c_glib_generator::is_complex_type(t_type* ttype) {
+  ttype = get_true_type(ttype);
+
+  return ttype->is_container() || ttype->is_struct() || ttype->is_xception();
+}
+
+bool t_c_glib_generator::is_numeric(t_type* ttype) {
+  return ttype->is_enum() || (ttype->is_base_type() && !ttype->is_string());
+}
+
+/**
+ * Maps a Thrift t_type to a C type.
+ */
+string t_c_glib_generator::type_name(t_type* ttype, bool in_typedef, bool is_const) {
+  if (ttype->is_base_type()) {
+    string bname = base_type_name(ttype);
+
+    if (is_const) {
+      return "const " + bname;
+    } else {
+      return bname;
+    }
+  }
+
+  if (ttype->is_container()) {
+    string cname;
+
+    t_container* tcontainer = (t_container*)ttype;
+    if (tcontainer->has_cpp_name()) {
+      cname = tcontainer->get_cpp_name();
+    } else if (ttype->is_map()) {
+      cname = "GHashTable";
+    } else if (ttype->is_set()) {
+      // since a set requires unique elements, use a GHashTable, and
+      // populate the keys and values with the same data, using keys for
+      // the actual writes and reads.
+      // TODO: discuss whether or not to implement TSet, THashSet or GHashSet
+      cname = "GHashTable";
+    } else if (ttype->is_list()) {
+      t_type* etype = ((t_list*)ttype)->get_elem_type();
+      if (etype->is_void()) {
+        throw std::runtime_error("compiler error: list element type cannot be void");
+      }
+      // TODO: investigate other implementations besides GPtrArray
+      cname = is_numeric(etype) ? "GArray" : "GPtrArray";
+    }
+
+    /* Omit the dereference operator if we are aliasing this type within a
+       typedef, to allow the type to be used more naturally in client code;
+       otherwise, include it */
+    if (!in_typedef) {
+      cname += " *";
+    }
+
+    if (is_const) {
+      return "const " + cname;
+    } else {
+      return cname;
+    }
+  }
+
+  // check for a namespace
+  string pname = this->nspace + ttype->get_name();
+
+  if (is_complex_type(ttype)) {
+    pname += " *";
+  }
+
+  if (is_const) {
+    return "const " + pname;
+  } else {
+    return pname;
+  }
+}
+
+/**
+ * Maps a Thrift primitive to the type needed to hold its value when used as an
+ * object property.
+ *
+ * This method is needed because all integer properties of width less than 64
+ * bits map to the same type, gint, as opposed to their width-specific type
+ * (gint8, gint16 or gint32).
+ */
+string t_c_glib_generator::property_type_name(t_type* ttype, bool in_typedef, bool is_const) {
+  string result;
+
+  if (ttype->is_base_type()) {
+    switch (((t_base_type*)ttype)->get_base()) {
+    case t_base_type::TYPE_I8:
+    case t_base_type::TYPE_I16:
+    case t_base_type::TYPE_I32:
+      if (is_const) {
+        result = "const gint";
+      } else {
+        result = "gint";
+      }
+      break;
+
+    default:
+      result = type_name(ttype, in_typedef, is_const);
+    }
+  } else {
+    result = type_name(ttype, in_typedef, is_const);
+  }
+
+  return result;
+}
+
+/**
+ * Maps a Thrift primitive to a C primitive.
+ */
+string t_c_glib_generator::base_type_name(t_type* type) {
+  if (type->is_enum()) {
+    return type_name(type);
+  }
+  if (!type->is_base_type()) {
+    throw std::invalid_argument("Only base types are suppported.");
+  }
+  t_base_type* base_type = reinterpret_cast<t_base_type*>(type);
+  t_base_type::t_base tbase = base_type->get_base();
+  switch (tbase) {
+  case t_base_type::TYPE_VOID:
+    return "void";
+  case t_base_type::TYPE_STRING:
+    if (base_type->is_binary()) {
+      return "GByteArray *";
+    } else {
+      return "gchar *";
+    }
+  case t_base_type::TYPE_BOOL:
+    return "gboolean";
+  case t_base_type::TYPE_I8:
+    return "gint8";
+  case t_base_type::TYPE_I16:
+    return "gint16";
+  case t_base_type::TYPE_I32:
+    return "gint32";
+  case t_base_type::TYPE_I64:
+    return "gint64";
+  case t_base_type::TYPE_DOUBLE:
+    return "gdouble";
+  default:
+    throw std::logic_error("compiler error: no C base type name for base type "
+                           + t_base_type::t_base_name(tbase));
+  }
+}
+
+/**
+ * Returns a member of the ThriftType C enumeration in thrift_protocol.h
+ * for a Thrift type.
+ */
+string t_c_glib_generator::type_to_enum(t_type* type) {
+  type = get_true_type(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:
+      throw "NO T_VOID CONSTRUCT";
+    case t_base_type::TYPE_STRING:
+      return "T_STRING";
+    case t_base_type::TYPE_BOOL:
+      return "T_BOOL";
+    case t_base_type::TYPE_I8:
+      return "T_BYTE";
+    case t_base_type::TYPE_I16:
+      return "T_I16";
+    case t_base_type::TYPE_I32:
+      return "T_I32";
+    case t_base_type::TYPE_I64:
+      return "T_I64";
+    case t_base_type::TYPE_DOUBLE:
+      return "T_DOUBLE";
+    }
+  } else if (type->is_enum()) {
+    return "T_I32";
+  } else if (type->is_struct()) {
+    return "T_STRUCT";
+  } else if (type->is_xception()) {
+    return "T_STRUCT";
+  } else if (type->is_map()) {
+    return "T_MAP";
+  } else if (type->is_set()) {
+    return "T_SET";
+  } else if (type->is_list()) {
+    return "T_LIST";
+  }
+
+  throw "INVALID TYPE IN type_to_enum: " + type->get_name();
+}
+
+/**
+ * Returns a Thrift constant formatted as a literal for inclusion in C code.
+ */
+string t_c_glib_generator::constant_literal(t_type* type, t_const_value* value) {
+  ostringstream render;
+
+  if (type->is_base_type()) {
+    /* primitives */
+    t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
+
+    switch (tbase) {
+    case t_base_type::TYPE_STRING:
+      render << "\"" + value->get_string() + "\"";
+      break;
+    case t_base_type::TYPE_BOOL:
+      render << ((value->get_integer() != 0) ? "TRUE" : "FALSE");
+      break;
+    case t_base_type::TYPE_I8:
+    case t_base_type::TYPE_I16:
+    case t_base_type::TYPE_I32:
+    case t_base_type::TYPE_I64:
+      render << value->get_integer();
+      break;
+    case t_base_type::TYPE_DOUBLE:
+      render << value->get_double();
+      break;
+    default:
+      throw "compiler error: no const of base type " + t_base_type::t_base_name(tbase);
+    }
+  } else {
+    t_const_value::t_const_value_type value_type = value->get_type();
+
+    switch (value_type) {
+    case t_const_value::CV_IDENTIFIER:
+      render << value->get_integer();
+      break;
+    case t_const_value::CV_LIST:
+      render << "{ ";
+      {
+        t_type* elem_type = ((t_list*)type)->get_elem_type();
+        const vector<t_const_value*>& list = value->get_list();
+        vector<t_const_value*>::const_iterator list_iter;
+
+        if (list.size() > 0) {
+          list_iter = list.begin();
+          render << constant_literal(elem_type, *list_iter);
+
+          while (++list_iter != list.end()) {
+            render << ", " << constant_literal(elem_type, *list_iter);
+          }
+        }
+      }
+      render << " }";
+      break;
+    case t_const_value::CV_MAP:
+    default:
+      render << "NULL /* not supported */";
+    }
+  }
+
+  return render.str();
+}
+
+/**
+ * Returns C code that represents a Thrift constant.
+ */
+string t_c_glib_generator::constant_value(string name, t_type* type, t_const_value* value) {
+  ostringstream render;
+
+  if (type->is_base_type()) {
+    /* primitives */
+    t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
+    switch (tbase) {
+    case t_base_type::TYPE_STRING:
+      render << "g_strdup (\"" + value->get_string() + "\")";
+      break;
+    case t_base_type::TYPE_BOOL:
+      render << ((value->get_integer() != 0) ? 1 : 0);
+      break;
+    case t_base_type::TYPE_I8:
+    case t_base_type::TYPE_I16:
+    case t_base_type::TYPE_I32:
+      render << value->get_integer();
+      break;
+    case t_base_type::TYPE_I64:
+      render << "G_GINT64_CONSTANT (" << value->get_integer() << ")";
+      break;
+    case t_base_type::TYPE_DOUBLE:
+      if (value->get_type() == t_const_value::CV_INTEGER) {
+        render << value->get_integer();
+      } else {
+        render << value->get_double();
+      }
+      break;
+    default:
+      throw "compiler error: no const of base type " + t_base_type::t_base_name(tbase);
+    }
+  } else if (type->is_enum()) {
+    render << "(" << type_name(type) << ")" << value->get_integer();
+  } else if (is_complex_type(type)) {
+    render << "(" << this->nspace_lc << to_lower_case(name) << "_constant())";
+  } else {
+    render << "NULL /* not supported */";
+  }
+
+  return render.str();
+}
+
+/**
+ * Renders a function signature of the form 'type name(args)'
+ *
+ * @param tfunction Function definition
+ * @return String of rendered function definition
+ */
+string t_c_glib_generator::function_signature(t_function* tfunction) {
+  t_type* ttype = tfunction->get_returntype();
+  t_struct* arglist = tfunction->get_arglist();
+  t_struct* xlist = tfunction->get_xceptions();
+  string fname = initial_caps_to_underscores(tfunction->get_name());
+
+  bool has_return = !ttype->is_void();
+  bool has_args = arglist->get_members().size() == 0;
+  bool has_xceptions = xlist->get_members().size() == 0;
+  return "gboolean " + this->nspace_lc + fname + " (" + this->nspace + service_name_ + "If * iface"
+         + (has_return ? ", " + type_name(ttype) + "* _return" : "")
+         + (has_args ? "" : (", " + argument_list(arglist)))
+         + (has_xceptions ? "" : (", " + xception_list(xlist))) + ", GError ** error)";
+}
+
+/**
+ * Renders a field list
+ *
+ * @param tstruct The struct definition
+ * @return Comma sepearated list of all field names in that struct
+ */
+string t_c_glib_generator::argument_list(t_struct* tstruct) {
+  string result = "";
+
+  const vector<t_field*>& fields = tstruct->get_members();
+  vector<t_field*>::const_iterator f_iter;
+  bool first = true;
+  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+    if (first) {
+      first = false;
+    } else {
+      result += ", ";
+    }
+    result += type_name((*f_iter)->get_type(), false, true) + " " + (*f_iter)->get_name();
+  }
+  return result;
+}
+
+/**
+ * Renders mutable exception lists
+ *
+ * @param tstruct The struct definition
+ * @return Comma sepearated list of all field names in that struct
+ */
+string t_c_glib_generator::xception_list(t_struct* tstruct) {
+  string result = "";
+
+  const vector<t_field*>& fields = tstruct->get_members();
+  vector<t_field*>::const_iterator f_iter;
+  bool first = true;
+  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+    if (first) {
+      first = false;
+    } else {
+      result += ", ";
+    }
+    result += type_name((*f_iter)->get_type(), false, false) + "* " + (*f_iter)->get_name();
+  }
+  return result;
+}
+
+/**
+ * Declares a field, including any necessary initialization.
+ */
+string t_c_glib_generator::declare_field(t_field* tfield,
+                                         bool init,
+                                         bool pointer,
+                                         bool constant,
+                                         bool reference) {
+  string result = "";
+  if (constant) {
+    result += "const ";
+  }
+  result += type_name(tfield->get_type());
+  if (pointer) {
+    result += "*";
+  }
+  if (reference) {
+    result += "*";
+  }
+  result += " " + tfield->get_name();
+  if (init) {
+    t_type* type = get_true_type(tfield->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_BOOL:
+      case t_base_type::TYPE_I8:
+      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 += " = (gdouble) 0";
+        break;
+      case t_base_type::TYPE_STRING:
+        result += " = NULL";
+        break;
+      default:
+        throw "compiler error: no C intializer for base type " + t_base_type::t_base_name(tbase);
+      }
+    } else if (type->is_enum()) {
+      result += " = (" + type_name(type) + ") 0";
+    } else if (type->is_struct() || type->is_container()) {
+      result += " = NULL";
+    }
+  }
+
+  if (!reference) {
+    result += ";";
+  }
+
+  return result;
+}
+
+string t_c_glib_generator::constant_value_with_storage(string fname,
+                                                       t_type* etype,
+                                                       t_const_value* value) {
+  ostringstream render;
+  if (is_numeric(etype)) {
+    render << "    " << type_name(etype) << " *" << fname << " = "
+           << "g_new (" << base_type_name(etype) << ", 1);" << endl
+           << "    *" << fname << " = " << constant_value(fname, (t_type*)etype, value) << ";"
+           << endl;
+  } else {
+    render << "    " << type_name(etype) << " " << fname << " = "
+           << constant_value(fname, (t_type*)etype, value) << ";" << endl;
+  }
+  return render.str();
+}
+
+/**
+ * Generates C code that initializes complex constants.
+ */
+void t_c_glib_generator::generate_const_initializer(string name,
+                                                    t_type* type,
+                                                    t_const_value* value,
+                                                    bool top_level) {
+  string name_u = initial_caps_to_underscores(name);
+  string name_lc = to_lower_case(name_u);
+  string type_u = initial_caps_to_underscores(type->get_name());
+  string type_uc = to_upper_case(type_u);
+  string maybe_static = top_level ? "" : "static ";
+
+  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*, t_const_value::value_compare>& val = value->get_map();
+    map<t_const_value*, t_const_value*, t_const_value::value_compare>::const_iterator v_iter;
+    ostringstream initializers;
+
+    // initialize any constants that may be referenced by this initializer
+    for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
+      t_type* field_type = NULL;
+      string field_name = "";
+
+      for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+        if ((*f_iter)->get_name() == v_iter->first->get_string()) {
+          field_type = (*f_iter)->get_type();
+          field_name = (*f_iter)->get_name();
+          break;
+        }
+      }
+      if (field_type == NULL) {
+        throw "type error: " + type->get_name() + " has no field "
+          + v_iter->first->get_string();
+      }
+      field_name = tmp(field_name);
+
+      generate_const_initializer(name + "_constant_" + field_name,
+                                 field_type,
+                                 v_iter->second);
+      initializers << "    constant->" << v_iter->first->get_string() << " = "
+                   << constant_value(name + "_constant_" + field_name,
+                                     field_type,
+                                     v_iter->second) << ";" << endl
+                   << "    constant->__isset_" << v_iter->first->get_string()
+                   << " = TRUE;" << endl;
+    }
+
+    // implement the initializer
+    f_types_impl_ << maybe_static << this->nspace << type->get_name() << " *"
+                  << endl
+                  << this->nspace_lc << name_lc << "_constant (void)" << endl;
+    scope_up(f_types_impl_);
+    f_types_impl_ << indent() << "static " << this->nspace << type->get_name()
+                  << " *constant = NULL;" << endl
+                  << indent() << "if (constant == NULL)" << endl;
+    scope_up(f_types_impl_);
+    f_types_impl_ << indent() << "constant = g_object_new (" << this->nspace_uc
+                  << "TYPE_" << type_uc << ", NULL);" << endl
+                  << initializers.str();
+    scope_down(f_types_impl_);
+
+    for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
+      t_type* field_type = NULL;
+      string field_name = "";
+
+      for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+        if ((*f_iter)->get_name() == v_iter->first->get_string()) {
+          field_type = (*f_iter)->get_type();
+          field_name = (*f_iter)->get_name();
+          break;
+        }
+      }
+      if (field_type == NULL) {
+        throw "type error: " + type->get_name() + " has no field "
+          + v_iter->first->get_string();
+      }
+      field_name = tmp(field_name);
+    }
+
+    f_types_impl_ << indent() << "return constant;" << endl;
+    scope_down(f_types_impl_);
+    f_types_impl_ << endl;
+  } else if (type->is_list()) {
+    string list_type = "GPtrArray *";
+    string free_func
+        = generate_free_func_from_type(reinterpret_cast<t_list*>(type)->get_elem_type());
+    string list_initializer = "g_ptr_array_new_with_free_func (" + free_func + ");";
+    string list_appender = "g_ptr_array_add";
+    bool list_variable = false;
+
+    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;
+    ostringstream initializers;
+    ostringstream appenders;
+
+    list_initializer = generate_new_array_from_type(etype);
+    if (etype->is_base_type()) {
+      t_base_type::t_base tbase = ((t_base_type*)etype)->get_base();
+      switch (tbase) {
+      case t_base_type::TYPE_VOID:
+        throw "compiler error: cannot determine array type";
+      case t_base_type::TYPE_BOOL:
+      case t_base_type::TYPE_I8:
+      case t_base_type::TYPE_I16:
+      case t_base_type::TYPE_I32:
+      case t_base_type::TYPE_I64:
+      case t_base_type::TYPE_DOUBLE:
+        list_type = "GArray *";
+        list_appender = "g_array_append_val";
+        list_variable = true;
+        break;
+      case t_base_type::TYPE_STRING:
+        break;
+      default:
+        throw "compiler error: no array info for type";
+      }
+    } else if (etype->is_enum()) {
+      list_type = "GArray *";
+      list_appender = "g_array_append_val";
+      list_variable = true;
+    }
+
+    for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
+      string fname = tmp(name);
+
+      generate_const_initializer(fname, etype, (*v_iter));
+      if (list_variable) {
+        initializers << "    " << type_name(etype) << " " << fname << " = "
+                     << constant_value(fname, (t_type*)etype, (*v_iter)) << ";"
+                     << endl;
+        appenders << "    " << list_appender << "(constant, " << fname << ");"
+                  << endl;
+      } else {
+        appenders << "    " << list_appender << "(constant, "
+                  << constant_value(fname, (t_type*)etype, (*v_iter)) << ");"
+                  << endl;
+      }
+    }
+
+    f_types_impl_ << maybe_static << list_type << endl
+                  << this->nspace_lc << name_lc << "_constant (void)" << endl;
+    scope_up(f_types_impl_);
+    f_types_impl_ << indent() << "static " << list_type << " constant = NULL;"
+                  << endl
+                  << indent() << "if (constant == NULL)" << endl;
+    scope_up(f_types_impl_);
+    if (!initializers.str().empty()) {
+      f_types_impl_ << initializers.str()
+                    << endl;
+    }
+    f_types_impl_ << indent() << "constant = " << list_initializer << endl
+                  << appenders.str();
+    scope_down(f_types_impl_);
+    f_types_impl_ << indent() << "return constant;" << endl;
+    scope_down(f_types_impl_);
+    f_types_impl_ << endl;
+  } else if (type->is_set()) {
+    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;
+    ostringstream initializers;
+    ostringstream appenders;
+
+    for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
+      string fname = tmp(name);
+      string ptr = is_numeric(etype) ? "*" : "";
+      generate_const_initializer(fname, etype, (*v_iter));
+      initializers << constant_value_with_storage(fname, (t_type*)etype, *v_iter);
+      appenders << "    g_hash_table_insert (constant, " << fname << ", 0);" << endl;
+    }
+
+    f_types_impl_ << maybe_static << "GHashTable *" << endl
+                  << this->nspace_lc << name_lc << "_constant (void)" << endl;
+    scope_up(f_types_impl_);
+    f_types_impl_ << indent() << "static GHashTable *constant = NULL;" << endl
+                  << indent() << "if (constant == NULL)" << endl;
+    scope_up(f_types_impl_);
+    f_types_impl_ << initializers.str() << endl
+                  << indent() << "constant = " << generate_new_hash_from_type(etype, NULL) << endl
+                  << appenders.str();
+    scope_down(f_types_impl_);
+    f_types_impl_ << indent() << "return constant;" << endl;
+    scope_down(f_types_impl_);
+    f_types_impl_ << endl;
+  } else if (type->is_map()) {
+    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*, t_const_value::value_compare>& val = value->get_map();
+    map<t_const_value*, t_const_value*, t_const_value::value_compare>::const_iterator v_iter;
+    ostringstream initializers;
+    ostringstream appenders;
+
+    for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
+      string fname = tmp(name);
+      string kname = fname + "key";
+      string vname = fname + "val";
+      generate_const_initializer(kname, ktype, v_iter->first);
+      generate_const_initializer(vname, vtype, v_iter->second);
+
+      initializers << constant_value_with_storage(kname, (t_type*)ktype, v_iter->first);
+      initializers << constant_value_with_storage(vname, (t_type*)vtype, v_iter->second);
+      appenders << "    g_hash_table_insert (constant, " << kname << ", " << vname << ");" << endl;
+    }
+
+    f_types_impl_ << maybe_static << "GHashTable *" << endl
+                  << this->nspace_lc << name_lc << "_constant (void)" << endl;
+    scope_up(f_types_impl_);
+    f_types_impl_ << indent() << "static GHashTable *constant = NULL;" << endl
+                  << indent() << "if (constant == NULL)" << endl;
+    scope_up(f_types_impl_);
+    f_types_impl_ << initializers.str() << endl
+                  << indent() << "constant = " << generate_new_hash_from_type(ktype, vtype) << endl
+                  << appenders.str();
+    scope_down(f_types_impl_);
+    f_types_impl_ << indent() << "return constant;" << endl;
+    scope_down(f_types_impl_);
+    f_types_impl_ << endl;
+  }
+}
+
+/**
+ * Generates helper classes for a service, consisting of a ThriftStruct subclass
+ * for the arguments to and the result from each method.
+ *
+ * @param tservice The service for which to generate helper classes
+ */
+void t_c_glib_generator::generate_service_helpers(t_service* tservice) {
+  vector<t_function*> functions = tservice->get_functions();
+  vector<t_function*>::iterator function_iter;
+
+  // Iterate through the service's methods
+  for (function_iter = functions.begin(); function_iter != functions.end(); ++function_iter) {
+    string function_name = (*function_iter)->get_name();
+    t_struct* arg_list = (*function_iter)->get_arglist();
+    string arg_list_name_orig = arg_list->get_name();
+
+    // Generate the arguments class
+    arg_list->set_name(tservice->get_name() + underscores_to_initial_caps(function_name) + "Args");
+    generate_struct(arg_list);
+
+    arg_list->set_name(arg_list_name_orig);
+
+    // Generate the result class
+    if (!(*function_iter)->is_oneway()) {
+      t_struct result(program_,
+                      tservice->get_name() + underscores_to_initial_caps(function_name) + "Result");
+      t_field success((*function_iter)->get_returntype(), "success", 0);
+      success.set_req(t_field::T_OPTIONAL);
+      if (!(*function_iter)->get_returntype()->is_void()) {
+        result.append(&success);
+      }
+
+      t_struct* xs = (*function_iter)->get_xceptions();
+      const vector<t_field*>& fields = xs->get_members();
+      vector<t_field*>::const_iterator field_iter;
+      for (field_iter = fields.begin(); field_iter != fields.end(); ++field_iter) {
+        (*field_iter)->set_req(t_field::T_OPTIONAL);
+        result.append(*field_iter);
+      }
+
+      generate_struct(&result);
+    }
+  }
+}
+
+/**
+ * Generates C code that represents a Thrift service client.
+ */
+void t_c_glib_generator::generate_service_client(t_service* tservice) {
+  /* get some C friendly service names */
+  string service_name_lc = to_lower_case(initial_caps_to_underscores(service_name_));
+  string service_name_uc = to_upper_case(service_name_lc);
+
+  string parent_service_name;
+  string parent_service_name_lc;
+  string parent_service_name_uc;
+
+  string parent_class_name = "GObject";
+  string parent_type_name = "G_TYPE_OBJECT";
+
+  // The service this service extends, or NULL if it extends no
+  // service
+  t_service* extends_service = tservice->get_extends();
+  if (extends_service) {
+    // The name of the parent service
+    parent_service_name = extends_service->get_name();
+    parent_service_name_lc = to_lower_case(initial_caps_to_underscores(parent_service_name));
+    parent_service_name_uc = to_upper_case(parent_service_name_lc);
+
+    // The names of the client class' parent class and type
+    parent_class_name = this->nspace + parent_service_name + "Client";
+    parent_type_name = this->nspace_uc + "TYPE_" + parent_service_name_uc + "_CLIENT";
+  }
+
+  // The base service (the topmost in the "extends" hierarchy), on
+  // whose client class the "input_protocol" and "output_protocol"
+  // properties are defined
+  t_service* base_service = tservice;
+  while (base_service->get_extends()) {
+    base_service = base_service->get_extends();
+  }
+
+  string base_service_name = base_service->get_name();
+  string base_service_name_lc = to_lower_case(initial_caps_to_underscores(base_service_name));
+  string base_service_name_uc = to_upper_case(base_service_name_lc);
+
+  // Generate the client interface dummy object in the header.
+  f_header_ << "/* " << service_name_ << " service interface */" << endl << "typedef struct _"
+            << this->nspace << service_name_ << "If " << this->nspace << service_name_ << "If; "
+            << " /* dummy object */" << endl << endl;
+
+  // Generate the client interface object in the header.
+  f_header_ << "struct _" << this->nspace << service_name_ << "IfInterface" << endl << "{" << endl
+            << "  GTypeInterface parent;" << endl << endl;
+
+  /* write out the functions for this interface */
+  indent_up();
+  vector<t_function*> functions = tservice->get_functions();
+  vector<t_function*>::const_iterator f_iter;
+  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
+    /* make the function name C friendly */
+    string funname = initial_caps_to_underscores((*f_iter)->get_name());
+    t_type* ttype = (*f_iter)->get_returntype();
+    t_struct* arglist = (*f_iter)->get_arglist();
+    t_struct* xlist = (*f_iter)->get_xceptions();
+    bool has_return = !ttype->is_void();
+    bool has_args = arglist->get_members().size() == 0;
+    bool has_xceptions = xlist->get_members().size() == 0;
+
+    string params = "(" + this->nspace + service_name_ + "If *iface"
+                    + (has_return ? ", " + type_name(ttype) + "* _return" : "")
+                    + (has_args ? "" : (", " + argument_list(arglist)))
+                    + (has_xceptions ? "" : (", " + xception_list(xlist))) + ", GError **error)";
+
+    indent(f_header_) << "gboolean (*" << funname << ") " << params << ";" << endl;
+  }
+  indent_down();
+
+  f_header_ << "};" << endl << "typedef struct _" << this->nspace << service_name_ << "IfInterface "
+            << this->nspace << service_name_ << "IfInterface;" << endl << endl;
+
+  // generate all the interface boilerplate
+  f_header_ << "GType " << this->nspace_lc << service_name_lc << "_if_get_type (void);" << endl
+            << "#define " << this->nspace_uc << "TYPE_" << service_name_uc << "_IF "
+            << "(" << this->nspace_lc << service_name_lc << "_if_get_type())" << endl << "#define "
+            << this->nspace_uc << service_name_uc << "_IF(obj) "
+            << "(G_TYPE_CHECK_INSTANCE_CAST ((obj), " << this->nspace_uc << "TYPE_"
+            << service_name_uc << "_IF, " << this->nspace << service_name_ << "If))" << endl
+            << "#define " << this->nspace_uc << "IS_" << service_name_uc << "_IF(obj) "
+            << "(G_TYPE_CHECK_INSTANCE_TYPE ((obj), " << this->nspace_uc << "TYPE_"
+            << service_name_uc << "_IF))" << endl << "#define " << this->nspace_uc
+            << service_name_uc << "_IF_GET_INTERFACE(inst) (G_TYPE_INSTANCE_GET_INTERFACE ((inst), "
+            << this->nspace_uc << "TYPE_" << service_name_uc << "_IF, " << this->nspace
+            << service_name_ << "IfInterface))" << endl << endl;
+
+  // write out all the interface function prototypes
+  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
+    /* make the function name C friendly */
+    string funname = initial_caps_to_underscores((*f_iter)->get_name());
+    t_type* ttype = (*f_iter)->get_returntype();
+    t_struct* arglist = (*f_iter)->get_arglist();
+    t_struct* xlist = (*f_iter)->get_xceptions();
+    bool has_return = !ttype->is_void();
+    bool has_args = arglist->get_members().size() == 0;
+    bool has_xceptions = xlist->get_members().size() == 0;
+
+    string params = "(" + this->nspace + service_name_ + "If *iface"
+                    + (has_return ? ", " + type_name(ttype) + "* _return" : "")
+                    + (has_args ? "" : (", " + argument_list(arglist)))
+                    + (has_xceptions ? "" : (", " + xception_list(xlist))) + ", GError **error)";
+
+    f_header_ << "gboolean " << this->nspace_lc << service_name_lc << "_if_" << funname << " "
+              << params << ";" << endl;
+  }
+  f_header_ << endl;
+
+  // Generate the client object instance definition in the header.
+  f_header_ << "/* " << service_name_ << " service client */" << endl << "struct _" << this->nspace
+            << service_name_ << "Client" << endl << "{" << endl << "  " << parent_class_name
+            << " parent;" << endl;
+  if (!extends_service) {
+    // Define "input_protocol" and "output_protocol" properties only
+    // for base services; child service-client classes will inherit
+    // these
+    f_header_ << endl << "  ThriftProtocol *input_protocol;" << endl
+              << "  ThriftProtocol *output_protocol;" << endl;
+  }
+  f_header_ << "};" << endl << "typedef struct _" << this->nspace << service_name_ << "Client "
+            << this->nspace << service_name_ << "Client;" << endl << endl;
+
+  // Generate the class definition in the header.
+  f_header_ << "struct _" << this->nspace << service_name_ << "ClientClass" << endl << "{" << endl
+            << "  " << parent_class_name << "Class parent;" << endl << "};" << endl
+            << "typedef struct _" << this->nspace << service_name_ << "ClientClass " << this->nspace
+            << service_name_ << "ClientClass;" << endl << endl;
+
+  // Create all the GObject boilerplate
+  f_header_ << "GType " << this->nspace_lc << service_name_lc << "_client_get_type (void);" << endl
+            << "#define " << this->nspace_uc << "TYPE_" << service_name_uc << "_CLIENT "
+            << "(" << this->nspace_lc << service_name_lc << "_client_get_type())" << endl
+            << "#define " << this->nspace_uc << service_name_uc << "_CLIENT(obj) "
+            << "(G_TYPE_CHECK_INSTANCE_CAST ((obj), " << this->nspace_uc << "TYPE_"
+            << service_name_uc << "_CLIENT, " << this->nspace << service_name_ << "Client))" << endl
+            << "#define " << this->nspace_uc << service_name_uc << "_CLIENT_CLASS(c) "
+            << "(G_TYPE_CHECK_CLASS_CAST ((c), " << this->nspace_uc << "TYPE_" << service_name_uc
+            << "_CLIENT, " << this->nspace << service_name_ << "ClientClass))" << endl << "#define "
+            << this->nspace_uc << service_name_uc << "_IS_CLIENT(obj) "
+            << "(G_TYPE_CHECK_INSTANCE_TYPE ((obj), " << this->nspace_uc << "TYPE_"
+            << service_name_uc << "_CLIENT))" << endl << "#define " << this->nspace_uc
+            << service_name_uc << "_IS_CLIENT_CLASS(c) "
+            << "(G_TYPE_CHECK_CLASS_TYPE ((c), " << this->nspace_uc << "TYPE_" << service_name_uc
+            << "_CLIENT))" << endl << "#define " << this->nspace_uc << service_name_uc
+            << "_CLIENT_GET_CLASS(obj) "
+            << "(G_TYPE_INSTANCE_GET_CLASS ((obj), " << this->nspace_uc << "TYPE_"
+            << service_name_uc << "_CLIENT, " << this->nspace << service_name_ << "ClientClass))"
+            << endl << endl;
+
+  /* write out the function prototypes */
+  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
+    /* make the function name C friendly */
+    string funname = to_lower_case(initial_caps_to_underscores((*f_iter)->get_name()));
+
+    t_function service_function((*f_iter)->get_returntype(),
+                                service_name_lc + string("_client_") + funname,
+                                (*f_iter)->get_arglist(),
+                                (*f_iter)->get_xceptions());
+    indent(f_header_) << function_signature(&service_function) << ";" << endl;
+
+    t_function send_function(g_type_void,
+                             service_name_lc + string("_client_send_") + funname,
+                             (*f_iter)->get_arglist());
+    indent(f_header_) << function_signature(&send_function) << ";" << endl;
+
+    // implement recv if not a oneway service
+    if (!(*f_iter)->is_oneway()) {
+      t_struct noargs(program_);
+      t_function recv_function((*f_iter)->get_returntype(),
+                               service_name_lc + string("_client_recv_") + funname,
+                               &noargs,
+                               (*f_iter)->get_xceptions());
+      indent(f_header_) << function_signature(&recv_function) << ";" << endl;
+    }
+  }
+
+  /* write out the get/set function prototypes */
+  f_header_ << "void " + service_name_lc + "_client_set_property (GObject *object, guint "
+                                           "property_id, const GValue *value, GParamSpec *pspec);"
+            << endl;
+  f_header_ << "void " + service_name_lc + "_client_get_property (GObject *object, guint "
+                                           "property_id, GValue *value, GParamSpec *pspec);"
+            << endl;
+
+  f_header_ << endl;
+  // end of header code
+
+  // Generate interface method implementations
+  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
+    /* make the function name C friendly */
+    string funname = initial_caps_to_underscores((*f_iter)->get_name());
+    t_type* ttype = (*f_iter)->get_returntype();
+    t_struct* arglist = (*f_iter)->get_arglist();
+    t_struct* xlist = (*f_iter)->get_xceptions();
+    bool has_return = !ttype->is_void();
+    bool has_args = arglist->get_members().size() == 0;
+    bool has_xceptions = xlist->get_members().size() == 0;
+
+    string params = "(" + this->nspace + service_name_ + "If *iface"
+                    + (has_return ? ", " + type_name(ttype) + "* _return" : "")
+                    + (has_args ? "" : (", " + argument_list(arglist)))
+                    + (has_xceptions ? "" : (", " + xception_list(xlist))) + ", GError **error)";
+
+    string params_without_type = string("iface, ") + (has_return ? "_return, " : "");
+
+    const vector<t_field*>& fields = arglist->get_members();
+    vector<t_field*>::const_iterator f_iter_field;
+    for (f_iter_field = fields.begin(); f_iter_field != fields.end(); ++f_iter_field) {
+      params_without_type += (*f_iter_field)->get_name();
+      params_without_type += ", ";
+    }
+
+    const vector<t_field*>& xceptions = xlist->get_members();
+    vector<t_field*>::const_iterator x_iter;
+    for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) {
+      params_without_type += (*x_iter)->get_name();
+      params_without_type += ", ";
+    }
+
+    f_service_ << "gboolean" << endl << this->nspace_lc << service_name_lc << "_if_" << funname
+               << " " << params << endl << "{" << endl << "  return " << this->nspace_uc
+               << service_name_uc << "_IF_GET_INTERFACE (iface)->" << funname << " ("
+               << params_without_type << "error);" << endl << "}" << endl << endl;
+  }
+
+  // Generate interface boilerplate
+  f_service_ << "GType" << endl << this->nspace_lc << service_name_lc << "_if_get_type (void)"
+             << endl << "{" << endl << "  static GType type = 0;" << endl << "  if (type == 0)"
+             << endl << "  {" << endl << "    static const GTypeInfo type_info =" << endl << "    {"
+             << endl << "      sizeof (" << this->nspace << service_name_ << "IfInterface)," << endl
+             << "      NULL,  /* base_init */" << endl << "      NULL,  /* base_finalize */" << endl
+             << "      NULL,  /* class_init */" << endl << "      NULL,  /* class_finalize */"
+             << endl << "      NULL,  /* class_data */" << endl
+             << "      0,     /* instance_size */" << endl << "      0,     /* n_preallocs */"
+             << endl << "      NULL,  /* instance_init */" << endl
+             << "      NULL   /* value_table */" << endl << "    };" << endl
+             << "    type = g_type_register_static (G_TYPE_INTERFACE," << endl
+             << "                                   \"" << this->nspace << service_name_ << "If\","
+             << endl << "                                   &type_info, 0);" << endl << "  }"
+             << endl << "  return type;" << endl << "}" << endl << endl;
+
+  // Generate client boilerplate
+  f_service_ << "static void " << endl << this->nspace_lc << service_name_lc
+             << "_if_interface_init (" << this->nspace << service_name_ << "IfInterface *iface);"
+             << endl << endl << "G_DEFINE_TYPE_WITH_CODE (" << this->nspace << service_name_
+             << "Client, " << this->nspace_lc << service_name_lc << "_client," << endl
+             << "                         " << parent_type_name << ", " << endl
+             << "                         G_IMPLEMENT_INTERFACE (" << this->nspace_uc << "TYPE_"
+             << service_name_uc << "_IF," << endl
+             << "                                                " << this->nspace_lc
+             << service_name_lc << "_if_interface_init))" << endl << endl;
+
+  // Generate property-related code only for base services---child
+  // service-client classes have only properties inherited from their
+  // parent class
+  if (!extends_service) {
+    // Generate client properties
+    f_service_ << "enum _" << this->nspace << service_name_ << "ClientProperties" << endl << "{"
+               << endl << "  PROP_0," << endl << "  PROP_" << this->nspace_uc << service_name_uc
+               << "_CLIENT_INPUT_PROTOCOL," << endl << "  PROP_" << this->nspace_uc
+               << service_name_uc << "_CLIENT_OUTPUT_PROTOCOL" << endl << "};" << endl << endl;
+
+    // generate property setter
+    f_service_ << "void" << endl << this->nspace_lc << service_name_lc << "_client_set_property ("
+               << "GObject *object, guint property_id, const GValue *value, "
+               << "GParamSpec *pspec)" << endl << "{" << endl << "  " << this->nspace
+               << service_name_ << "Client *client = " << this->nspace_uc << service_name_uc
+               << "_CLIENT (object);" << endl << endl << "  THRIFT_UNUSED_VAR (pspec);" << endl
+               << endl << "  switch (property_id)" << endl << "  {" << endl << "    case PROP_"
+               << this->nspace_uc << service_name_uc << "_CLIENT_INPUT_PROTOCOL:" << endl
+               << "      client->input_protocol = g_value_get_object (value);" << endl
+               << "      break;" << endl << "    case PROP_" << this->nspace_uc << service_name_uc
+               << "_CLIENT_OUTPUT_PROTOCOL:" << endl
+               << "      client->output_protocol = g_value_get_object (value);" << endl
+               << "      break;" << endl << "  }" << endl << "}" << endl << endl;
+
+    // generate property getter
+    f_service_ << "void" << endl << this->nspace_lc << service_name_lc << "_client_get_property ("
+               << "GObject *object, guint property_id, GValue *value, "
+               << "GParamSpec *pspec)" << endl << "{" << endl << "  " << this->nspace
+               << service_name_ << "Client *client = " << this->nspace_uc << service_name_uc
+               << "_CLIENT (object);" << endl << endl << "  THRIFT_UNUSED_VAR (pspec);" << endl
+               << endl << "  switch (property_id)" << endl << "  {" << endl << "    case PROP_"
+               << this->nspace_uc << service_name_uc << "_CLIENT_INPUT_PROTOCOL:" << endl
+               << "      g_value_set_object (value, client->input_protocol);" << endl
+               << "      break;" << endl << "    case PROP_" << this->nspace_uc << service_name_uc
+               << "_CLIENT_OUTPUT_PROTOCOL:" << endl
+               << "      g_value_set_object (value, client->output_protocol);" << endl
+               << "      break;" << endl << "  }" << endl << "}" << endl << endl;
+  }
+
+  // Generate client method implementations
+  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
+    string name = (*f_iter)->get_name();
+    string funname = initial_caps_to_underscores(name);
+
+    // Get the struct of function call params and exceptions
+    t_struct* arg_struct = (*f_iter)->get_arglist();
+
+    // Function for sending
+    t_function send_function(g_type_void,
+                             service_name_lc + string("_client_send_") + funname,
+                             (*f_iter)->get_arglist());
+
+    // Open the send function
+    indent(f_service_) << function_signature(&send_function) << endl;
+    scope_up(f_service_);
+
+    string reqType = (*f_iter)->is_oneway() ? "T_ONEWAY" : "T_CALL";
+
+    // Serialize the request
+    f_service_ << indent() << "gint32 cseqid = 0;" << endl << indent()
+               << "ThriftProtocol * protocol = " << this->nspace_uc << base_service_name_uc
+               << "_CLIENT (iface)->output_protocol;" << endl << endl << indent()
+               << "if (thrift_protocol_write_message_begin (protocol, \"" << name << "\", "
+               << reqType << ", cseqid, error) < 0)" << endl << indent() << "  return FALSE;"
+               << endl << endl;
+
+    generate_struct_writer(f_service_, arg_struct, "", "", false);
+
+    f_service_ << indent() << "if (thrift_protocol_write_message_end (protocol, error) < 0)" << endl
+               << indent() << "  return FALSE;" << endl << indent()
+               << "if (!thrift_transport_flush (protocol->transport, error))" << endl << indent()
+               << "  return FALSE;" << endl << indent()
+               << "if (!thrift_transport_write_end (protocol->transport, error))" << endl
+               << indent() << "  return FALSE;" << endl << endl << indent() << "return TRUE;"
+               << endl;
+
+    scope_down(f_service_);
+    f_service_ << endl;
+
+    // Generate recv function only if not an async function
+    if (!(*f_iter)->is_oneway()) {
+      t_struct noargs(program_);
+      t_function recv_function((*f_iter)->get_returntype(),
+                               service_name_lc + string("_client_recv_") + funname,
+                               &noargs,
+                               (*f_iter)->get_xceptions());
+      // Open function
+      indent(f_service_) << function_signature(&recv_function) << endl;
+      scope_up(f_service_);
+
+      f_service_ << indent() << "gint32 rseqid;" << endl
+                 << indent() << "gchar * fname = NULL;" << endl
+                 << indent() << "ThriftMessageType mtype;" << endl
+                 << indent() << "ThriftProtocol * protocol = "
+                 << this->nspace_uc << base_service_name_uc
+                 << "_CLIENT (iface)->input_protocol;" << endl
+                 << indent() << "ThriftApplicationException *xception;" << endl
+                 << endl
+                 << indent() << "if (thrift_protocol_read_message_begin "
+                    "(protocol, &fname, &mtype, &rseqid, error) < 0) {" << endl;
+      indent_up();
+      f_service_ << indent() << "if (fname) g_free (fname);" << endl
+                 << indent() << "return FALSE;" << endl;
+      indent_down();
+      f_service_ << indent() << "}" << endl
+                 << endl
+                 << indent() << "if (mtype == T_EXCEPTION) {" << endl;
+      indent_up();
+      f_service_ << indent() << "if (fname) g_free (fname);" << endl
+                 << indent() << "xception = g_object_new "
+                    "(THRIFT_TYPE_APPLICATION_EXCEPTION, NULL);" << endl
+                 << indent() << "thrift_struct_read (THRIFT_STRUCT (xception), "
+                    "protocol, NULL);" << endl
+                 << indent() << "thrift_protocol_read_message_end "
+                    "(protocol, NULL);" << endl
+                 << indent() << "thrift_transport_read_end "
+                    "(protocol->transport, NULL);" << endl
+                 << indent() << "g_set_error (error, "
+                    "THRIFT_APPLICATION_EXCEPTION_ERROR,xception->type, "
+                    "\"application error: %s\", xception->message);" << endl
+                 << indent() << "g_object_unref (xception);" << endl
+                 << indent() << "return FALSE;" << endl;
+      indent_down();
+      f_service_ << indent() << "} else if (mtype != T_REPLY) {" << endl;
+      indent_up();
+      f_service_ << indent() << "if (fname) g_free (fname);" << endl
+                 << indent() << "thrift_protocol_skip (protocol, T_STRUCT, "
+                    "NULL);" << endl
+                 << indent() << "thrift_protocol_read_message_end (protocol, "
+                    "NULL);" << endl
+                 << indent() << "thrift_transport_read_end ("
+                    "protocol->transport, NULL);" << endl
+                 << indent() << "g_set_error (error, "
+                    "THRIFT_APPLICATION_EXCEPTION_ERROR, "
+                    "THRIFT_APPLICATION_EXCEPTION_ERROR_INVALID_MESSAGE_TYPE, "
+                    "\"invalid message type %d, expected T_REPLY\", mtype);"
+                 << endl
+                 << indent() << "return FALSE;" << endl;
+      indent_down();
+      f_service_ << indent() << "} else if (strncmp (fname, \"" << name
+                 << "\", " << name.length() << ") != 0) {" << endl;
+      indent_up();
+      f_service_ << indent() << "thrift_protocol_skip (protocol, T_STRUCT, "
+                    "NULL);" << endl
+                 << indent() << "thrift_protocol_read_message_end (protocol,"
+                    "error);" << endl
+                 << indent() << "thrift_transport_read_end ("
+                    "protocol->transport, error);" << endl
+                 << indent() << "g_set_error (error, "
+                    "THRIFT_APPLICATION_EXCEPTION_ERROR, "
+                    "THRIFT_APPLICATION_EXCEPTION_ERROR_WRONG_METHOD_NAME, "
+                    "\"wrong method name %s, expected " << name
+                    << "\", fname);" << endl
+                 << indent() << "if (fname) g_free (fname);" << endl
+                 << indent() << "return FALSE;" << endl;
+      indent_down();
+      f_service_ << indent() << "}" << endl
+                 << indent() << "if (fname) g_free (fname);" << endl
+                 << endl;
+
+      t_struct* xs = (*f_iter)->get_xceptions();
+      const std::vector<t_field*>& xceptions = xs->get_members();
+      vector<t_field*>::const_iterator x_iter;
+
+      {
+        t_struct result(program_, tservice->get_name() + "_" + (*f_iter)->get_name() + "_result");
+        t_field success((*f_iter)->get_returntype(), "*_return", 0);
+        if (!(*f_iter)->get_returntype()->is_void()) {
+          result.append(&success);
+        }
+
+        // add readers for exceptions, dereferencing the pointer.
+        for (x_iter = xceptions.begin(); x_iter != xceptions.end(); x_iter++) {
+          t_field* xception = new t_field((*x_iter)->get_type(),
+                                          "*" + (*x_iter)->get_name(),
+                                          (*x_iter)->get_key());
+          result.append(xception);
+        }
+
+        generate_struct_reader(f_service_, &result, "", "", false);
+      }
+
+      f_service_ << indent() << "if (thrift_protocol_read_message_end (protocol, error) < 0)"
+                 << endl << indent() << "  return FALSE;" << endl << endl << indent()
+                 << "if (!thrift_transport_read_end (protocol->transport, error))" << endl
+                 << indent() << "  return FALSE;" << endl << endl;
+
+      // copy over any throw exceptions and return failure
+      for (x_iter = xceptions.begin(); x_iter != xceptions.end(); x_iter++) {
+        f_service_ << indent() << "if (*" << (*x_iter)->get_name() << " != NULL)" << endl
+                   << indent() << "{" << endl << indent() << "    g_set_error (error, "
+                   << this->nspace_uc
+                   << to_upper_case(initial_caps_to_underscores((*x_iter)->get_type()->get_name()))
+                   << "_ERROR, " << this->nspace_uc
+                   << to_upper_case(initial_caps_to_underscores((*x_iter)->get_type()->get_name()))
+                   << "_ERROR_CODE, \"" << (*x_iter)->get_type()->get_name() << "\");" << endl
+                   << indent() << "    return FALSE;" << endl << indent() << "}" << endl;
+      }
+      // Close function
+      indent(f_service_) << "return TRUE;" << endl;
+      scope_down(f_service_);
+      f_service_ << endl;
+    }
+
+    // Open function
+    t_function service_function((*f_iter)->get_returntype(),
+                                service_name_lc + string("_client_") + funname,
+                                (*f_iter)->get_arglist(),
+                                (*f_iter)->get_xceptions());
+    indent(f_service_) << function_signature(&service_function) << endl;
+    scope_up(f_service_);
+
+    // wrap each function
+    f_service_ << indent() << "if (!" << this->nspace_lc << service_name_lc << "_client_send_"
+               << funname << " (iface";
+
+    // Declare the function arguments
+    const vector<t_field*>& fields = arg_struct->get_members();
+    vector<t_field*>::const_iterator fld_iter;
+    for (fld_iter = fields.begin(); fld_iter != fields.end(); ++fld_iter) {
+      f_service_ << ", " << (*fld_iter)->get_name();
+    }
+    f_service_ << ", error))" << endl << indent() << "  return FALSE;" << endl;
+
+    // if not oneway, implement recv
+    if (!(*f_iter)->is_oneway()) {
+      string ret = (*f_iter)->get_returntype()->is_void() ? "" : "_return, ";
+
+      const vector<t_field*>& xceptions = (*f_iter)->get_xceptions()->get_members();
+      vector<t_field*>::const_iterator x_iter;
+      for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) {
+        ret += (*x_iter)->get_name();
+        ret += ", ";
+      }
+
+      f_service_ << indent() << "if (!" << this->nspace_lc << service_name_lc << "_client_recv_"
+                 << funname << " (iface, " << ret << "error))" << endl << indent()
+                 << "  return FALSE;" << endl;
+    }
+
+    // return TRUE which means all functions were called OK
+    indent(f_service_) << "return TRUE;" << endl;
+    scope_down(f_service_);
+    f_service_ << endl;
+  }
+
+  // create the interface initializer
+  f_service_ << "static void" << endl
+             << this->nspace_lc << service_name_lc << "_if_interface_init ("
+             << this->nspace << service_name_ << "IfInterface *iface)" << endl;
+  scope_up(f_service_);
+  if (functions.size() > 0) {
+    for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
+      /* make the function name C friendly */
+      string funname = initial_caps_to_underscores((*f_iter)->get_name());
+
+      f_service_ << indent() << "iface->" << funname << " = " << this->nspace_lc
+                 << service_name_lc << "_client_" << funname << ";" << endl;
+    }
+  }
+  else {
+    f_service_ << indent() << "THRIFT_UNUSED_VAR (iface);" << endl;
+  }
+  scope_down(f_service_);
+  f_service_ << endl;
+
+  // create the client instance initializer
+  f_service_ << "static void" << endl
+             << this->nspace_lc << service_name_lc << "_client_init ("
+             << this->nspace << service_name_ << "Client *client)" << endl;
+  scope_up(f_service_);
+  if (!extends_service) {
+    f_service_ << indent() << "client->input_protocol = NULL;" << endl
+               << indent() << "client->output_protocol = NULL;" << endl;
+  }
+  else {
+    f_service_ << indent() << "THRIFT_UNUSED_VAR (client);" << endl;
+  }
+  scope_down(f_service_);
+  f_service_ << endl;
+
+  // create the client class initializer
+  f_service_ << "static void" << endl << this->nspace_lc << service_name_lc
+             << "_client_class_init (" << this->nspace << service_name_ << "ClientClass *cls)"
+             << endl << "{" << endl;
+  if (!extends_service) {
+    f_service_ << "  GObjectClass *gobject_class = G_OBJECT_CLASS (cls);" << endl
+               << "  GParamSpec *param_spec;" << endl << endl
+               << "  gobject_class->set_property = " << this->nspace_lc << service_name_lc
+               << "_client_set_property;" << endl
+               << "  gobject_class->get_property = " << this->nspace_lc << service_name_lc
+               << "_client_get_property;" << endl << endl
+               << "  param_spec = g_param_spec_object (\"input_protocol\"," << endl
+               << "                                    \"input protocol (construct)\"," << endl
+               << "                                    \"Set the client input protocol\"," << endl
+               << "                                    THRIFT_TYPE_PROTOCOL," << endl
+               << "                                    G_PARAM_READWRITE);" << endl
+               << "  g_object_class_install_property (gobject_class," << endl
+               << "                                   PROP_" << this->nspace_uc << service_name_uc
+               << "_CLIENT_INPUT_PROTOCOL, param_spec);" << endl << endl
+               << "  param_spec = g_param_spec_object (\"output_protocol\"," << endl
+               << "                                    \"output protocol (construct)\"," << endl
+               << "                                    \"Set the client output protocol\"," << endl
+               << "                                    THRIFT_TYPE_PROTOCOL," << endl
+               << "                                    G_PARAM_READWRITE);" << endl
+               << "  g_object_class_install_property (gobject_class," << endl
+               << "                                   PROP_" << this->nspace_uc << service_name_uc
+               << "_CLIENT_OUTPUT_PROTOCOL, param_spec);" << endl;
+  }
+  else {
+    f_service_ << "  THRIFT_UNUSED_VAR (cls);" << endl;
+  }
+  f_service_ << "}" << endl << endl;
+}
+
+/**
+ * Generates C code that represents a Thrift service handler.
+ *
+ * @param tservice The service for which to generate a handler.
+ */
+void t_c_glib_generator::generate_service_handler(t_service* tservice) {
+  vector<t_function*> functions = tservice->get_functions();
+  vector<t_function*>::const_iterator function_iter;
+
+  string service_name_lc = to_lower_case(initial_caps_to_underscores(service_name_));
+  string service_name_uc = to_upper_case(service_name_lc);
+
+  string class_name = this->nspace + service_name_ + "Handler";
+  string class_name_lc = to_lower_case(initial_caps_to_underscores(class_name));
+  string class_name_uc = to_upper_case(class_name_lc);
+
+  string parent_class_name;
+  string parent_type_name;
+
+  string args_indent;
+
+  // The service this service extends, or NULL if it extends no service
+  t_service* extends_service = tservice->get_extends();
+
+  // Determine the name of our parent service (if any) and the handler class'
+  // parent class name and type
+  if (extends_service) {
+    string parent_service_name = extends_service->get_name();
+    string parent_service_name_lc = to_lower_case(initial_caps_to_underscores(parent_service_name));
+    string parent_service_name_uc = to_upper_case(parent_service_name_lc);
+
+    parent_class_name = this->nspace + parent_service_name + "Handler";
+    parent_type_name = this->nspace_uc + "TYPE_" + parent_service_name_uc + "_HANDLER";
+  } else {
+    parent_class_name = "GObject";
+    parent_type_name = "G_TYPE_OBJECT";
+  }
+
+  // Generate the handler class' definition in the header file
+
+  // Generate the handler instance definition
+  f_header_ << "/* " << service_name_ << " handler (abstract base class) */" << endl << "struct _"
+            << class_name << endl << "{" << endl;
+  indent_up();
+  f_header_ << indent() << parent_class_name << " parent;" << endl;
+  indent_down();
+  f_header_ << "};" << endl << "typedef struct _" << class_name << " " << class_name << ";" << endl
+            << endl;
+
+  // Generate the handler class definition, including its class members
+  // (methods)
+  f_header_ << "struct _" << class_name << "Class" << endl << "{" << endl;
+  indent_up();
+  f_header_ << indent() << parent_class_name << "Class parent;" << endl << endl;
+
+  for (function_iter = functions.begin(); function_iter != functions.end(); ++function_iter) {
+    string method_name = initial_caps_to_underscores((*function_iter)->get_name());
+    t_type* return_type = (*function_iter)->get_returntype();
+    t_struct* arg_list = (*function_iter)->get_arglist();
+    t_struct* x_list = (*function_iter)->get_xceptions();
+    bool has_return = !return_type->is_void();
+    bool has_args = arg_list->get_members().size() == 0;
+    bool has_xceptions = x_list->get_members().size() == 0;
+
+    string params = "(" + this->nspace + service_name_ + "If *iface"
+                    + (has_return ? ", " + type_name(return_type) + "* _return" : "")
+                    + (has_args ? "" : (", " + argument_list(arg_list)))
+                    + (has_xceptions ? "" : (", " + xception_list(x_list))) + ", GError **error)";
+
+    indent(f_header_) << "gboolean (*" << method_name << ") " << params << ";" << endl;
+  }
+  indent_down();
+
+  f_header_ << "};" << endl << "typedef struct _" << class_name << "Class " << class_name
+            << "Class;" << endl << endl;
+
+  // Generate the remaining header boilerplate
+  f_header_ << "GType " << class_name_lc << "_get_type (void);" << endl << "#define "
+            << this->nspace_uc << "TYPE_" << service_name_uc << "_HANDLER "
+            << "(" << class_name_lc << "_get_type())" << endl << "#define " << class_name_uc
+            << "(obj) "
+            << "(G_TYPE_CHECK_INSTANCE_CAST ((obj), " << this->nspace_uc << "TYPE_"
+            << service_name_uc << "_HANDLER, " << class_name << "))" << endl << "#define "
+            << this->nspace_uc << "IS_" << service_name_uc << "_HANDLER(obj) "
+            << "(G_TYPE_CHECK_INSTANCE_TYPE ((obj), " << this->nspace_uc << "TYPE_"
+            << service_name_uc << "_HANDLER))" << endl << "#define " << class_name_uc
+            << "_CLASS(c) (G_TYPE_CHECK_CLASS_CAST ((c), " << this->nspace_uc << "TYPE_"
+            << service_name_uc << "_HANDLER, " << class_name << "Class))" << endl << "#define "
+            << this->nspace_uc << "IS_" << service_name_uc << "_HANDLER_CLASS(c) "
+            << "(G_TYPE_CHECK_CLASS_TYPE ((c), " << this->nspace_uc << "TYPE_" << service_name_uc
+            << "_HANDLER))" << endl << "#define " << this->nspace_uc << service_name_uc
+            << "_HANDLER_GET_CLASS(obj) "
+            << "(G_TYPE_INSTANCE_GET_CLASS ((obj), " << this->nspace_uc << "TYPE_"
+            << service_name_uc << "_HANDLER, " << class_name << "Class))" << endl << endl;
+
+  // Generate the handler class' method definitions
+  for (function_iter = functions.begin(); function_iter != functions.end(); ++function_iter) {
+    string method_name = initial_caps_to_underscores((*function_iter)->get_name());
+    t_type* return_type = (*function_iter)->get_returntype();
+    t_struct* arg_list = (*function_iter)->get_arglist();
+    t_struct* x_list = (*function_iter)->get_xceptions();
+    bool has_return = !return_type->is_void();
+    bool has_args = arg_list->get_members().size() == 0;
+    bool has_xceptions = x_list->get_members().size() == 0;
+
+    string params = "(" + this->nspace + service_name_ + "If *iface"
+                    + (has_return ? ", " + type_name(return_type) + "* _return" : "")
+                    + (has_args ? "" : (", " + argument_list(arg_list)))
+                    + (has_xceptions ? "" : (", " + xception_list(x_list))) + ", GError **error)";
+
+    f_header_ << "gboolean " << class_name_lc << "_" << method_name << " " << params << ";" << endl;
+  }
+  f_header_ << endl;
+
+  // Generate the handler's implementation in the implementation file
+
+  // Generate the implementation boilerplate
+  f_service_ << "static void" << endl << class_name_lc << "_" << service_name_lc
+             << "_if_interface_init (" << this->nspace << service_name_ << "IfInterface *iface);"
+             << endl << endl;
+
+  args_indent = string(25, ' ');
+  f_service_ << "G_DEFINE_TYPE_WITH_CODE (" << class_name << ", " << endl << args_indent
+             << class_name_lc << "," << endl << args_indent << parent_type_name << "," << endl
+             << args_indent << "G_IMPLEMENT_INTERFACE (" << this->nspace_uc << "TYPE_"
+             << service_name_uc << "_IF," << endl;
+  args_indent += string(23, ' ');
+  f_service_ << args_indent << class_name_lc << "_" << service_name_lc << "_if_interface_init))"
+             << endl << endl;
+
+  // Generate the handler method implementations
+  for (function_iter = functions.begin(); function_iter != functions.end(); ++function_iter) {
+    string function_name = (*function_iter)->get_name();
+    string method_name = initial_caps_to_underscores(function_name);
+    t_type* return_type = (*function_iter)->get_returntype();
+    t_struct* arg_list = (*function_iter)->get_arglist();
+    t_struct* x_list = (*function_iter)->get_xceptions();
+
+    const vector<t_field*>& args = arg_list->get_members();
+    const vector<t_field*>& xceptions = x_list->get_members();
+
+    vector<t_field*>::const_iterator field_iter;
+
+    t_function implementing_function(return_type,
+                                     service_name_lc + "_handler_" + method_name,
+                                     arg_list,
+                                     x_list,
+                                     (*function_iter)->is_oneway());
+
+    indent(f_service_) << function_signature(&implementing_function) << endl;
+    scope_up(f_service_);
+    f_service_ << indent() << "g_return_val_if_fail (" << this->nspace_uc << "IS_"
+               << service_name_uc << "_HANDLER (iface), FALSE);" << endl << endl << indent()
+               << "return " << class_name_uc << "_GET_CLASS (iface)"
+               << "->" << method_name << " (iface, ";
+
+    if (!return_type->is_void()) {
+      f_service_ << "_return, ";
+    }
+    for (field_iter = args.begin(); field_iter != args.end(); ++field_iter) {
+      f_service_ << (*field_iter)->get_name() << ", ";
+    }
+    for (field_iter = xceptions.begin(); field_iter != xceptions.end(); ++field_iter) {
+      f_service_ << (*field_iter)->get_name() << ", ";
+    }
+    f_service_ << "error);" << endl;
+    scope_down(f_service_);
+    f_service_ << endl;
+  }
+
+  // Generate the handler interface initializer
+  f_service_ << "static void" << endl << class_name_lc << "_" << service_name_lc
+             << "_if_interface_init (" << this->nspace << service_name_ << "IfInterface *iface)"
+             << endl;
+  scope_up(f_service_);
+  if (functions.size() > 0) {
+    for (function_iter = functions.begin(); function_iter != functions.end(); ++function_iter) {
+      string method_name = initial_caps_to_underscores((*function_iter)->get_name());
+
+      f_service_ << indent() << "iface->" << method_name << " = " << class_name_lc << "_"
+                 << method_name << ";" << endl;
+    }
+  }
+  else {
+    f_service_ << "THRIFT_UNUSED_VAR (iface);" << endl;
+  }
+  scope_down(f_service_);
+  f_service_ << endl;
+
+  // Generate the handler instance initializer
+  f_service_ << "static void" << endl << class_name_lc << "_init (" << class_name << " *self)"
+             << endl;
+  scope_up(f_service_);
+  f_service_ << indent() << "THRIFT_UNUSED_VAR (self);" << endl;
+  scope_down(f_service_);
+  f_service_ << endl;
+
+  // Generate the handler class initializer
+  f_service_ << "static void" << endl
+             << class_name_lc << "_class_init (" << class_name << "Class *cls)"
+             << endl;
+  scope_up(f_service_);
+  if (functions.size() > 0) {
+    for (function_iter = functions.begin();
+         function_iter != functions.end();
+         ++function_iter) {
+      string function_name = (*function_iter)->get_name();
+      string method_name = initial_caps_to_underscores(function_name);
+
+      // All methods are pure virtual and must be implemented by subclasses
+      f_service_ << indent() << "cls->" << method_name << " = NULL;" << endl;
+    }
+  }
+  else {
+    f_service_ << indent() << "THRIFT_UNUSED_VAR (cls);" << endl;
+  }
+  scope_down(f_service_);
+  f_service_ << endl;
+}
+
+/**
+ * Generates C code that represents a Thrift service processor.
+ *
+ * @param tservice The service for which to generate a processor
+ */
+void t_c_glib_generator::generate_service_processor(t_service* tservice) {
+  vector<t_function*> functions = tservice->get_functions();
+  vector<t_function*>::const_iterator function_iter;
+
+  string service_name_lc = to_lower_case(initial_caps_to_underscores(service_name_));
+  string service_name_uc = to_upper_case(service_name_lc);
+
+  string class_name = this->nspace + service_name_ + "Processor";
+  string class_name_lc = to_lower_case(initial_caps_to_underscores(class_name));
+  string class_name_uc = to_upper_case(class_name_lc);
+
+  string parent_class_name;
+  string parent_type_name;
+
+  string handler_class_name = this->nspace + service_name_ + "Handler";
+  string handler_class_name_lc = initial_caps_to_underscores(handler_class_name);
+
+  string process_function_type_name = class_name + "ProcessFunction";
+  string process_function_def_type_name =
+    class_name_lc + "_process_function_def";
+
+  string function_name;
+  string args_indent;
+
+  // The service this service extends, or NULL if it extends no service
+  t_service* extends_service = tservice->get_extends();
+
+  // Determine the name of our parent service (if any) and the
+  // processor class' parent class name and type
+  if (extends_service) {
+    string parent_service_name = extends_service->get_name();
+    string parent_service_name_lc = to_lower_case(initial_caps_to_underscores(parent_service_name));
+    string parent_service_name_uc = to_upper_case(parent_service_name_lc);
+
+    parent_class_name = this->nspace + parent_service_name + "Processor";
+    parent_type_name = this->nspace_uc + "TYPE_" + parent_service_name_uc + "_PROCESSOR";
+  } else {
+    parent_class_name = "ThriftDispatchProcessor";
+    parent_type_name = "THRIFT_TYPE_DISPATCH_PROCESSOR";
+  }
+
+  // Generate the processor class' definition in the header file
+
+  // Generate the processor instance definition
+  f_header_ << "/* " << service_name_ << " processor */" << endl << "struct _" << class_name << endl
+            << "{" << endl;
+  indent_up();
+  f_header_ << indent() << parent_class_name << " parent;" << endl << endl << indent()
+            << "/* protected */" << endl << indent()
+            << this->nspace + service_name_ + "Handler *handler;" << endl << indent()
+            << "GHashTable *process_map;" << endl;
+  indent_down();
+  f_header_ << "};" << endl << "typedef struct _" << class_name << " " << class_name << ";" << endl
+            << endl;
+
+  // Generate the processor class definition
+  f_header_ << "struct _" << class_name << "Class" << endl << "{" << endl;
+  indent_up();
+  f_header_ << indent() << parent_class_name << "Class parent;" << endl << endl << indent()
+            << "/* protected */" << endl << indent()
+            << "gboolean (*dispatch_call) (ThriftDispatchProcessor *processor," << endl;
+  args_indent = indent() + string(27, ' ');
+  f_header_ << args_indent << "ThriftProtocol *in," << endl << args_indent << "ThriftProtocol *out,"
+            << endl << args_indent << "gchar *fname," << endl << args_indent << "gint32 seqid,"
+            << endl << args_indent << "GError **error);" << endl;
+  indent_down();
+  f_header_ << "};" << endl << "typedef struct _" << class_name << "Class " << class_name
+            << "Class;" << endl << endl;
+
+  // Generate the remaining header boilerplate
+  f_header_ << "GType " << class_name_lc << "_get_type (void);" << endl << "#define "
+            << this->nspace_uc << "TYPE_" << service_name_uc << "_PROCESSOR "
+            << "(" << class_name_lc << "_get_type())" << endl << "#define " << class_name_uc
+            << "(obj) "
+            << "(G_TYPE_CHECK_INSTANCE_CAST ((obj), " << this->nspace_uc << "TYPE_"
+            << service_name_uc << "_PROCESSOR, " << class_name << "))" << endl << "#define "
+            << this->nspace_uc << "IS_" << service_name_uc << "_PROCESSOR(obj) "
+            << "(G_TYPE_CHECK_INSTANCE_TYPE ((obj), " << this->nspace_uc << "TYPE_"
+            << service_name_uc << "_PROCESSOR))" << endl << "#define " << class_name_uc
+            << "_CLASS(c) (G_TYPE_CHECK_CLASS_CAST ((c), " << this->nspace_uc << "TYPE_"
+            << service_name_uc << "_PROCESSOR, " << class_name << "Class))" << endl << "#define "
+            << this->nspace_uc << "IS_" << service_name_uc << "_PROCESSOR_CLASS(c) "
+            << "(G_TYPE_CHECK_CLASS_TYPE ((c), " << this->nspace_uc << "TYPE_" << service_name_uc
+            << "_PROCESSOR))" << endl << "#define " << this->nspace_uc << service_name_uc
+            << "_PROCESSOR_GET_CLASS(obj) "
+            << "(G_TYPE_INSTANCE_GET_CLASS ((obj), " << this->nspace_uc << "TYPE_"
+            << service_name_uc << "_PROCESSOR, " << class_name << "Class))" << endl << endl;
+
+  // Generate the processor's implementation in the implementation file
+
+  // Generate the processor's properties enum
+  f_service_ << "enum _" << class_name << "Properties" << endl << "{" << endl;
+  indent_up();
+  f_service_ << indent() << "PROP_" << class_name_uc << "_0," << endl << indent() << "PROP_"
+             << class_name_uc << "_HANDLER" << endl;
+  indent_down();
+  f_service_ << "};" << endl << endl;
+
+  // Generate the implementation boilerplate
+  args_indent = string(15, ' ');
+  f_service_ << "G_DEFINE_TYPE (" << class_name << "," << endl << args_indent << class_name_lc
+             << "," << endl << args_indent << parent_type_name << ")" << endl << endl;
+
+  // Generate the processor's processing-function type
+  args_indent = string(process_function_type_name.length() + 23, ' ');
+  f_service_ << "typedef gboolean (* " << process_function_type_name << ") ("
+             << class_name << " *, " << endl
+             << args_indent << "gint32," << endl
+             << args_indent << "ThriftProtocol *," << endl
+             << args_indent << "ThriftProtocol *," << endl
+             << args_indent << "GError **);" << endl
+             << endl;
+
+  // Generate the processor's processing-function-definition type
+  f_service_ << "typedef struct" << endl
+             << "{" << endl;
+  indent_up();
+  f_service_ << indent() << "gchar *name;" << endl
+             << indent() << process_function_type_name << " function;" << endl;
+  indent_down();
+  f_service_ << "} " << process_function_def_type_name << ";" << endl
+             << endl;
+
+  // Generate forward declarations of the processor's processing functions so we
+  // can refer to them in the processing-function-definition struct below and
+  // keep all of the processor's declarations in one place
+  for (function_iter = functions.begin();
+       function_iter != functions.end();
+       ++function_iter) {
+    function_name = class_name_lc + "_process_"
+      + initial_caps_to_underscores((*function_iter)->get_name());
+
+    args_indent = string(function_name.length() + 2, ' ');
+    f_service_ << "static gboolean" << endl
+               << function_name << " ("
+               << class_name << " *," << endl
+               << args_indent << "gint32," << endl
+               << args_indent << "ThriftProtocol *," << endl
+               << args_indent << "ThriftProtocol *," << endl
+               << args_indent << "GError **);" << endl;
+  }
+  f_service_ << endl;
+
+  // Generate the processor's processing-function definitions, if the service
+  // defines any methods
+  if (functions.size() > 0) {
+    f_service_ << indent() << "static " << process_function_def_type_name
+               << endl
+               << indent() << class_name_lc << "_process_function_defs["
+               << functions.size() << "] = {" << endl;
+    indent_up();
+    for (function_iter = functions.begin();
+         function_iter != functions.end();
+         ++function_iter) {
+      string service_function_name = (*function_iter)->get_name();
+      string process_function_name = class_name_lc + "_process_"
+        + initial_caps_to_underscores(service_function_name);
+
+      f_service_ << indent() << "{" << endl;
+      indent_up();
+      f_service_ << indent() << "\"" << service_function_name << "\"," << endl
+                 << indent() << process_function_name << endl;
+      indent_down();
+      f_service_ << indent() << "}"
+                 << (function_iter == --functions.end() ? "" : ",") << endl;
+    }
+    indent_down();
+    f_service_ << indent() << "};" << endl
+               << endl;
+  }
+
+  // Generate the processor's processing functions
+  for (function_iter = functions.begin(); function_iter != functions.end(); ++function_iter) {
+    string service_function_name = (*function_iter)->get_name();
+    string service_function_name_ic = underscores_to_initial_caps(service_function_name);
+    string service_function_name_lc = initial_caps_to_underscores(service_function_name);
+    string service_function_name_uc = to_upper_case(service_function_name_lc);
+
+    t_type* return_type = (*function_iter)->get_returntype();
+    bool has_return_value = !return_type->is_void();
+
+    t_struct* arg_list = (*function_iter)->get_arglist();
+    const vector<t_field*>& args = arg_list->get_members();
+    vector<t_field*>::const_iterator arg_iter;
+
+    const vector<t_field*>& xceptions = (*function_iter)->get_xceptions()->get_members();
+    vector<t_field*>::const_iterator xception_iter;
+
+    string args_class_name = this->nspace + service_name_ + service_function_name_ic + "Args";
+    string args_class_type = this->nspace_uc + "TYPE_" + service_name_uc + "_"
+                             + service_function_name_uc + "_ARGS";
+
+    string result_class_name = this->nspace + service_name_ + service_function_name_ic + "Result";
+    string result_class_type = this->nspace_uc + "TYPE_" + service_name_uc + "_"
+                               + service_function_name_uc + "_RESULT";
+
+    string handler_function_name = handler_class_name_lc + "_" + service_function_name_lc;
+
+    function_name = class_name_lc + "_process_"
+                    + initial_caps_to_underscores(service_function_name);
+
+    args_indent = string(function_name.length() + 2, ' ');
+    f_service_ << "static gboolean" << endl << function_name << " (" << class_name << " *self,"
+               << endl << args_indent << "gint32 sequence_id," << endl << args_indent
+               << "ThriftProtocol *input_protocol," << endl << args_indent
+               << "ThriftProtocol *output_protocol," << endl << args_indent << "GError **error)"
+               << endl;
+    scope_up(f_service_);
+    f_service_ << indent() << "gboolean result = TRUE;" << endl
+               << indent() << "ThriftTransport * transport;" << endl
+               << indent() << "ThriftApplicationException *xception;" << endl
+               << indent() << args_class_name + " * args =" << endl;
+    indent_up();
+    f_service_ << indent() << "g_object_new (" << args_class_type << ", NULL);" << endl << endl;
+    indent_down();
+    if ((*function_iter)->is_oneway()) {
+      f_service_ << indent() << "THRIFT_UNUSED_VAR (sequence_id);" << endl << indent()
+                 << "THRIFT_UNUSED_VAR (output_protocol);" << endl << endl;
+    }
+    f_service_ << indent() << "g_object_get (input_protocol, \"transport\", "
+               << "&transport, NULL);" << endl << endl;
+
+    // Read the method's arguments from the caller
+    f_service_ << indent() << "if ((thrift_struct_read (THRIFT_STRUCT (args), "
+               << "input_protocol, error) != -1) &&" << endl << indent()
+               << "    (thrift_protocol_read_message_end (input_protocol, "
+               << "error) != -1) &&" << endl << indent()
+               << "    (thrift_transport_read_end (transport, error) != FALSE))" << endl;
+    scope_up(f_service_);
+
+    for (arg_iter = args.begin(); arg_iter != args.end(); ++arg_iter) {
+      f_service_ << indent() << property_type_name((*arg_iter)->get_type()) << " "
+                 << (*arg_iter)->get_name() << ";" << endl;
+    }
+    for (xception_iter = xceptions.begin(); xception_iter != xceptions.end(); ++xception_iter) {
+      f_service_ << indent() << type_name((*xception_iter)->get_type()) << " "
+                 << initial_caps_to_underscores((*xception_iter)->get_name()) << " = NULL;" << endl;
+    }
+    if (has_return_value) {
+      f_service_ << indent() << property_type_name(return_type) << " return_value;" << endl;
+    }
+    if (!(*function_iter)->is_oneway()) {
+      f_service_ << indent() << result_class_name << " * result_struct;" << endl;
+    }
+    f_service_ << endl;
+
+    if (args.size() > 0) {
+      f_service_ << indent() << "g_object_get (args," << endl;
+      args_indent = indent() + string(14, ' ');
+      for (arg_iter = args.begin(); arg_iter != args.end(); ++arg_iter) {
+        string arg_name = (*arg_iter)->get_name();
+
+        f_service_ << args_indent << "\"" << arg_name << "\", &" << arg_name << "," << endl;
+      }
+      f_service_ << args_indent << "NULL);" << endl << endl;
+    }
+
+    if (!(*function_iter)->is_oneway()) {
+      f_service_ << indent() << "g_object_unref (transport);" << endl << indent()
+                 << "g_object_get (output_protocol, \"transport\", "
+                 << "&transport, NULL);" << endl << endl << indent()
+                 << "result_struct = g_object_new (" << result_class_type << ", NULL);" << endl;
+      if (has_return_value) {
+        f_service_ << indent() << "g_object_get (result_struct, "
+                                  "\"success\", &return_value, NULL);" << endl;
+      }
+      f_service_ << endl;
+    }
+
+    // Pass the arguments to the corresponding method in the handler
+    f_service_ << indent() << "if (" << handler_function_name << " (" << this->nspace_uc
+               << service_name_uc << "_IF (self->handler)," << endl;
+    args_indent = indent() + string(handler_function_name.length() + 6, ' ');
+    if (has_return_value) {
+      string return_type_name = type_name(return_type);
+
+      f_service_ << args_indent;
+
+      // Cast return_value if it was declared as a type other than the return
+      // value's actual type---this is true for integer values 32 bits or fewer
+      // in width, for which GLib requires a plain gint type be used when
+      // storing or retrieving as an object property
+      if (return_type_name != property_type_name(return_type)) {
+        if (return_type_name[return_type_name.length() - 1] != '*') {
+          return_type_name += ' ';
+        }
+        return_type_name += '*';
+
+        f_service_ << "(" << return_type_name << ")";
+      }
+
+      f_service_ << "&return_value," << endl;
+    }
+    for (arg_iter = args.begin(); arg_iter != args.end(); ++arg_iter) {
+      f_service_ << args_indent << (*arg_iter)->get_name() << "," << endl;
+    }
+    for (xception_iter = xceptions.begin(); xception_iter != xceptions.end(); ++xception_iter) {
+      f_service_ << args_indent << "&" << initial_caps_to_underscores((*xception_iter)->get_name())
+                 << "," << endl;
+    }
+    f_service_ << args_indent << "error) == TRUE)" << endl;
+    scope_up(f_service_);
+
+    // The handler reported success; return the result, if any, to the caller
+    if (!(*function_iter)->is_oneway()) {
+      if (has_return_value) {
+        f_service_ << indent() << "g_object_set (result_struct, \"success\", ";
+        if (type_name(return_type) != property_type_name(return_type)) {
+          // Roundtrip cast to fix the position of sign bit.
+          f_service_ << "(" << property_type_name(return_type) << ")"
+                     << "(" << type_name(return_type) << ")";
+        }
+        f_service_ << "return_value, "
+                   << "NULL);" << endl;
+
+        // Deallocate (or unref) return_value
+        return_type = get_true_type(return_type);
+        if (return_type->is_base_type()) {
+          t_base_type* base_type = ((t_base_type*)return_type);
+
+          if (base_type->get_base() == t_base_type::TYPE_STRING) {
+            f_service_ << indent() << "if (return_value != NULL)" << endl;
+            indent_up();
+            if (base_type->is_binary()) {
+              f_service_ << indent() << "g_byte_array_unref (return_value);" << endl;
+            } else {
+              f_service_ << indent() << "g_free (return_value);" << endl;
+            }
+            indent_down();
+          }
+        } else if (return_type->is_container()) {
+          f_service_ << indent() << "if (return_value != NULL)" << endl;
+          indent_up();
+
+          if (return_type->is_list()) {
+            t_type* elem_type = ((t_list*)return_type)->get_elem_type();
+
+            f_service_ << indent();
+            if (is_numeric(elem_type)) {
+              f_service_ << "g_array_unref";
+            } else {
+              f_service_ << "g_ptr_array_unref";
+            }
+            f_service_ << " (return_value);" << endl;
+          } else if (return_type->is_map() || return_type->is_set()) {
+            f_service_ << indent() << "g_hash_table_unref (return_value);" << endl;
+          }
+
+          indent_down();
+        } else if (return_type->is_struct()) {
+          f_service_ << indent() << "if (return_value != NULL)" << endl;
+          indent_up();
+          f_service_ << indent() << "g_object_unref (return_value);" << endl;
+          indent_down();
+        }
+
+        f_service_ << endl;
+      }
+      f_service_ << indent() << "result =" << endl;
+      indent_up();
+      f_service_ << indent() << "((thrift_protocol_write_message_begin (output_protocol," << endl;
+      args_indent = indent() + string(39, ' ');
+      f_service_ << args_indent << "\"" << service_function_name << "\"," << endl << args_indent
+                 << "T_REPLY," << endl << args_indent << "sequence_id," << endl << args_indent
+                 << "error) != -1) &&" << endl << indent()
+                 << " (thrift_struct_write (THRIFT_STRUCT (result_struct)," << endl;
+      args_indent = indent() + string(23, ' ');
+      f_service_ << args_indent << "output_protocol," << endl << args_indent << "error) != -1));"
+                 << endl;
+      indent_down();
+    }
+    scope_down(f_service_);
+    f_service_ << indent() << "else" << endl;
+    scope_up(f_service_);
+
+    // The handler reported failure; check to see if an application-defined
+    // exception was raised and if so, return it to the caller
+    f_service_ << indent();
+    if (xceptions.size() > 0) {
+      for (xception_iter = xceptions.begin(); xception_iter != xceptions.end(); ++xception_iter) {
+        f_service_ << "if (" << initial_caps_to_underscores((*xception_iter)->get_name())
+                   << " != NULL)" << endl;
+        scope_up(f_service_);
+        f_service_ << indent() << "g_object_set (result_struct," << endl;
+        args_indent = indent() + string(14, ' ');
+        f_service_ << args_indent << "\"" << (*xception_iter)->get_name() << "\", "
+                   << (*xception_iter)->get_name() << "," << endl << args_indent << "NULL);" << endl
+                   << endl;
+        f_service_ << indent() << "result =" << endl;
+        indent_up();
+        f_service_ << indent() << "((thrift_protocol_write_message_begin (output_protocol," << endl;
+        args_indent = indent() + string(39, ' ');
+        f_service_ << args_indent << "\"" << service_function_name << "\"," << endl << args_indent
+                   << "T_REPLY," << endl << args_indent << "sequence_id," << endl << args_indent
+                   << "error) != -1) &&" << endl << indent()
+                   << " (thrift_struct_write (THRIFT_STRUCT (result_struct)," << endl;
+        args_indent = indent() + string(23, ' ');
+        f_service_ << args_indent << "output_protocol," << endl << args_indent << "error) != -1));"
+                   << endl;
+        indent_down();
+        scope_down(f_service_);
+        f_service_ << indent() << "else" << endl;
+      }
+
+      scope_up(f_service_);
+      f_service_ << indent();
+    }
+
+    // If the handler reported failure but raised no application-defined
+    // exception, return a Thrift application exception with the information
+    // returned via GLib's own error-reporting mechanism
+    f_service_ << "if (*error == NULL)" << endl;
+    indent_up();
+    f_service_ << indent() << "g_warning (\"" << service_name_ << "."
+               << (*function_iter)->get_name() << " implementation returned FALSE \"" << endl
+               << indent() << string(11, ' ') << "\"but did not set an error\");" << endl << endl;
+    indent_down();
+    f_service_ << indent() << "xception =" << endl;
+    indent_up();
+    f_service_ << indent() << "g_object_new (THRIFT_TYPE_APPLICATION_EXCEPTION," << endl;
+    args_indent = indent() + string(14, ' ');
+    f_service_ << args_indent << "\"type\",    *error != NULL ? (*error)->code :" << endl
+               << args_indent << string(11, ' ') << "THRIFT_APPLICATION_EXCEPTION_ERROR_UNKNOWN,"
+               << endl << args_indent << "\"message\", *error != NULL ? (*error)->message : NULL,"
+               << endl << args_indent << "NULL);" << endl;
+    indent_down();
+    f_service_ << indent() << "g_clear_error (error);" << endl << endl << indent()
+               << "result =" << endl;
+    indent_up();
+    f_service_ << indent() << "((thrift_protocol_write_message_begin (output_protocol," << endl;
+    args_indent = indent() + string(39, ' ');
+    f_service_ << args_indent << "\"" << service_function_name << "\"," << endl << args_indent
+               << "T_EXCEPTION," << endl << args_indent << "sequence_id," << endl << args_indent
+               << "error) != -1) &&" << endl << indent()
+               << " (thrift_struct_write (THRIFT_STRUCT (xception)," << endl;
+    args_indent = indent() + string(23, ' ');
+    f_service_ << args_indent << "output_protocol," << endl << args_indent << "error) != -1));"
+               << endl;
+    indent_down();
+    f_service_ << endl << indent() << "g_object_unref (xception);" << endl;
+
+    if (xceptions.size() > 0) {
+      scope_down(f_service_);
+    }
+    scope_down(f_service_);
+    f_service_ << endl;
+
+    // Dellocate or unref retrieved argument values as necessary
+    for (arg_iter = args.begin(); arg_iter != args.end(); ++arg_iter) {
+      string arg_name = (*arg_iter)->get_name();
+      t_type* arg_type = get_true_type((*arg_iter)->get_type());
+
+      if (arg_type->is_base_type()) {
+        t_base_type* base_type = ((t_base_type*)arg_type);
+
+        if (base_type->get_base() == t_base_type::TYPE_STRING) {
+          f_service_ << indent() << "if (" << arg_name << " != NULL)" << endl;
+          indent_up();
+          if (base_type->is_binary()) {
+            f_service_ << indent() << "g_byte_array_unref (" << arg_name << ");" << endl;
+          } else {
+            f_service_ << indent() << "g_free (" << arg_name << ");" << endl;
+          }
+          indent_down();
+        }
+      } else if (arg_type->is_container()) {
+        f_service_ << indent() << "if (" << arg_name << " != NULL)" << endl;
+        indent_up();
+
+        if (arg_type->is_list()) {
+          t_type* elem_type = ((t_list*)arg_type)->get_elem_type();
+
+          f_service_ << indent();
+          if (is_numeric(elem_type)) {
+            f_service_ << "g_array_unref";
+          } else {
+            f_service_ << "g_ptr_array_unref";
+          }
+          f_service_ << " (" << arg_name << ");" << endl;
+        } else if (arg_type->is_map() || arg_type->is_set()) {
+          f_service_ << indent() << "g_hash_table_unref (" << arg_name << ");" << endl;
+        }
+
+        indent_down();
+      } else if (arg_type->is_struct()) {
+        f_service_ << indent() << "if (" << arg_name << " != NULL)" << endl;
+        indent_up();
+        f_service_ << indent() << "g_object_unref (" << arg_name << ");" << endl;
+        indent_down();
+      }
+    }
+
+    if (!(*function_iter)->is_oneway()) {
+      f_service_ << indent() << "g_object_unref (result_struct);" << endl << endl << indent()
+                 << "if (result == TRUE)" << endl;
+      indent_up();
+      f_service_ << indent() << "result =" << endl;
+      indent_up();
+      f_service_ << indent() << "((thrift_protocol_write_message_end "
+                 << "(output_protocol, error) != -1) &&" << endl << indent()
+                 << " (thrift_transport_write_end (transport, error) "
+                 << "!= FALSE) &&" << endl << indent()
+                 << " (thrift_transport_flush (transport, error) "
+                 << "!= FALSE));" << endl;
+      indent_down();
+      indent_down();
+    }
+    scope_down(f_service_);
+    f_service_ << indent() << "else" << endl;
+    indent_up();
+    f_service_ << indent() << "result = FALSE;" << endl;
+    indent_down();
+
+    f_service_ << endl << indent() << "g_object_unref (transport);" << endl << indent()
+               << "g_object_unref (args);" << endl << endl << indent() << "return result;" << endl;
+    scope_down(f_service_);
+
+    f_service_ << endl;
+  }
+
+  // Generate the processor's dispatch_call implementation
+  function_name = class_name_lc + "_dispatch_call";
+  args_indent = indent() + string(function_name.length() + 2, ' ');
+  f_service_ << "static gboolean" << endl << function_name
+             << " (ThriftDispatchProcessor *dispatch_processor," << endl << args_indent
+             << "ThriftProtocol *input_protocol," << endl << args_indent
+             << "ThriftProtocol *output_protocol," << endl << args_indent << "gchar *method_name,"
+             << endl << args_indent << "gint32 sequence_id," << endl << args_indent
+             << "GError **error)" << endl;
+  scope_up(f_service_);
+  f_service_ << indent() << class_name_lc << "_process_function_def *"
+             << "process_function_def;" << endl;
+  f_service_ << indent() << "gboolean dispatch_result = FALSE;" << endl << endl << indent()
+             << class_name << " *self = " << class_name_uc << " (dispatch_processor);" << endl;
+  f_service_ << indent() << parent_class_name << "Class "
+                                                 "*parent_class =" << endl;
+  indent_up();
+  f_service_ << indent() << "g_type_class_peek_parent (" << class_name_uc << "_GET_CLASS (self));"
+             << endl;
+  indent_down();
+  f_service_ << endl
+             << indent() << "process_function_def = "
+             << "g_hash_table_lookup (self->process_map, method_name);" << endl
+             << indent() << "if (process_function_def != NULL)" << endl;
+  scope_up(f_service_);
+  args_indent = indent() + string(53, ' ');
+  f_service_ << indent() << "g_free (method_name);" << endl
+             << indent() << "dispatch_result = "
+             << "(*process_function_def->function) (self," << endl
+             << args_indent << "sequence_id," << endl
+             << args_indent << "input_protocol," << endl
+             << args_indent << "output_protocol," << endl
+             << args_indent << "error);" << endl;
+  scope_down(f_service_);
+  f_service_ << indent() << "else" << endl;
+  scope_up(f_service_);
+
+  // Method name not recognized; chain up to our parent processor---note the
+  // top-most implementation of this method, in ThriftDispatchProcessor itself,
+  // will return an application exception to the caller if no class in the
+  // hierarchy recognizes the method name
+  f_service_ << indent() << "dispatch_result = parent_class->dispatch_call "
+                            "(dispatch_processor," << endl;
+  args_indent = indent() + string(47, ' ');
+  f_service_ << args_indent << "input_protocol," << endl << args_indent << "output_protocol,"
+             << endl << args_indent << "method_name," << endl << args_indent << "sequence_id,"
+             << endl << args_indent << "error);" << endl;
+  scope_down(f_service_);
+  f_service_ << endl << indent() << "return dispatch_result;" << endl;
+  scope_down(f_service_);
+  f_service_ << endl;
+
+  // Generate the processor's property setter
+  function_name = class_name_lc + "_set_property";
+  args_indent = string(function_name.length() + 2, ' ');
+  f_service_ << "static void" << endl << function_name << " (GObject *object," << endl
+             << args_indent << "guint property_id," << endl << args_indent << "const GValue *value,"
+             << endl << args_indent << "GParamSpec *pspec)" << endl;
+  scope_up(f_service_);
+  f_service_ << indent() << class_name << " *self = " << class_name_uc << " (object);" << endl
+             << endl << indent() << "switch (property_id)" << endl;
+  scope_up(f_service_);
+  f_service_ << indent() << "case PROP_" << class_name_uc << "_HANDLER:" << endl;
+  indent_up();
+  f_service_ << indent() << "if (self->handler != NULL)" << endl;
+  indent_up();
+  f_service_ << indent() << "g_object_unref (self->handler);" << endl;
+  indent_down();
+  f_service_ << indent() << "self->handler = g_value_get_object (value);" << endl << indent()
+             << "g_object_ref (self->handler);" << endl;
+  if (extends_service) {
+    // Chain up to set the handler in every superclass as well
+    f_service_ << endl << indent() << "G_OBJECT_CLASS (" << class_name_lc << "_parent_class)->"
+               << endl;
+    indent_up();
+    f_service_ << indent() << "set_property (object, property_id, value, pspec);" << endl;
+    indent_down();
+  }
+  f_service_ << indent() << "break;" << endl;
+  indent_down();
+  f_service_ << indent() << "default:" << endl;
+  indent_up();
+  f_service_ << indent() << "G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);"
+             << endl << indent() << "break;" << endl;
+  indent_down();
+  scope_down(f_service_);
+  scope_down(f_service_);
+  f_service_ << endl;
+
+  // Generate processor's property getter
+  function_name = class_name_lc + "_get_property";
+  args_indent = string(function_name.length() + 2, ' ');
+  f_service_ << "static void" << endl << function_name << " (GObject *object," << endl
+             << args_indent << "guint property_id," << endl << args_indent << "GValue *value,"
+             << endl << args_indent << "GParamSpec *pspec)" << endl;
+  scope_up(f_service_);
+  f_service_ << indent() << class_name << " *self = " << class_name_uc << " (object);" << endl
+             << endl << indent() << "switch (property_id)" << endl;
+  scope_up(f_service_);
+  f_service_ << indent() << "case PROP_" << class_name_uc << "_HANDLER:" << endl;
+  indent_up();
+  f_service_ << indent() << "g_value_set_object (value, self->handler);" << endl << indent()
+             << "break;" << endl;
+  indent_down();
+  f_service_ << indent() << "default:" << endl;
+  indent_up();
+  f_service_ << indent() << "G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);"
+             << endl << indent() << "break;" << endl;
+  indent_down();
+  scope_down(f_service_);
+  scope_down(f_service_);
+  f_service_ << endl;
+
+  // Generator the processor's dispose function
+  f_service_ << "static void" << endl << class_name_lc << "_dispose (GObject *gobject)" << endl;
+  scope_up(f_service_);
+  f_service_ << indent() << class_name << " *self = " << class_name_uc << " (gobject);" << endl
+             << endl << indent() << "if (self->handler != NULL)" << endl;
+  scope_up(f_service_);
+  f_service_ << indent() << "g_object_unref (self->handler);" << endl << indent()
+             << "self->handler = NULL;" << endl;
+  scope_down(f_service_);
+  f_service_ << endl << indent() << "G_OBJECT_CLASS (" << class_name_lc << "_parent_class)"
+                                                                           "->dispose (gobject);"
+             << endl;
+  scope_down(f_service_);
+  f_service_ << endl;
+
+  // Generate processor finalize function
+  f_service_ << "static void" << endl << class_name_lc << "_finalize (GObject *gobject)" << endl;
+  scope_up(f_service_);
+  f_service_ << indent() << this->nspace << service_name_ << "Processor *self = " << this->nspace_uc
+             << service_name_uc << "_PROCESSOR (gobject);" << endl << endl << indent()
+             << "thrift_safe_hash_table_destroy (self->process_map);" << endl << endl << indent()
+             << "G_OBJECT_CLASS (" << class_name_lc << "_parent_class)"
+                                                       "->finalize (gobject);" << endl;
+  scope_down(f_service_);
+  f_service_ << endl;
+
+  // Generate processor instance initializer
+  f_service_ << "static void" << endl << class_name_lc << "_init (" << class_name << " *self)"
+             << endl;
+  scope_up(f_service_);
+  if (functions.size() > 0) {
+    f_service_ << indent() << "guint index;" << endl
+               << endl;
+  }
+  f_service_ << indent() << "self->handler = NULL;" << endl << indent()
+             << "self->process_map = "
+                "g_hash_table_new (g_str_hash, g_str_equal);" << endl;
+  if (functions.size() > 0) {
+    args_indent = string(21, ' ');
+    f_service_ << endl
+               << indent() << "for (index = 0; index < "
+               << functions.size() << "; index += 1)" << endl;
+    indent_up();
+    f_service_ << indent() << "g_hash_table_insert (self->process_map," << endl
+               << indent() << args_indent
+               << class_name_lc << "_process_function_defs[index].name," << endl
+               << indent() << args_indent
+               << "&" << class_name_lc << "_process_function_defs[index]" << ");"
+               << endl;
+    indent_down();
+  }
+  scope_down(f_service_);
+  f_service_ << endl;
+
+  // Generate processor class initializer
+  f_service_ << "static void" << endl << class_name_lc << "_class_init (" << class_name
+             << "Class *cls)" << endl;
+  scope_up(f_service_);
+  f_service_ << indent() << "GObjectClass *gobject_class = G_OBJECT_CLASS (cls);" << endl
+             << indent() << "ThriftDispatchProcessorClass *dispatch_processor_class =" << endl;
+  indent_up();
+  f_service_ << indent() << "THRIFT_DISPATCH_PROCESSOR_CLASS (cls);" << endl;
+  indent_down();
+  f_service_ << indent() << "GParamSpec *param_spec;" << endl << endl << indent()
+             << "gobject_class->dispose = " << class_name_lc << "_dispose;" << endl << indent()
+             << "gobject_class->finalize = " << class_name_lc << "_finalize;" << endl << indent()
+             << "gobject_class->set_property = " << class_name_lc << "_set_property;" << endl
+             << indent() << "gobject_class->get_property = " << class_name_lc << "_get_property;"
+             << endl << endl << indent()
+             << "dispatch_processor_class->dispatch_call = " << class_name_lc << "_dispatch_call;"
+             << endl << indent() << "cls->dispatch_call = " << class_name_lc << "_dispatch_call;"
+             << endl << endl << indent() << "param_spec = g_param_spec_object (\"handler\","
+             << endl;
+  args_indent = indent() + string(34, ' ');
+  f_service_ << args_indent << "\"Service handler implementation\"," << endl << args_indent
+             << "\"The service handler implementation \"" << endl << args_indent
+             << "\"to which method calls are dispatched.\"," << endl << args_indent
+             << this->nspace_uc + "TYPE_" + service_name_uc + "_HANDLER," << endl << args_indent
+             << "G_PARAM_READWRITE);" << endl;
+  f_service_ << indent() << "g_object_class_install_property (gobject_class," << endl;
+  args_indent = indent() + string(33, ' ');
+  f_service_ << args_indent << "PROP_" << class_name_uc << "_HANDLER," << endl << args_indent
+             << "param_spec);" << endl;
+  scope_down(f_service_);
+}
+
+/**
+ * Generates C code that represents a Thrift service server.
+ */
+void t_c_glib_generator::generate_service_server(t_service* tservice) {
+  (void)tservice;
+  // Generate the service's handler class
+  generate_service_handler(tservice);
+
+  // Generate the service's processor class
+  generate_service_processor(tservice);
+}
+
+/**
+ * Generates C code to represent a THrift structure as a GObject.
+ */
+void t_c_glib_generator::generate_object(t_struct* tstruct) {
+  string name = tstruct->get_name();
+  string name_u = initial_caps_to_underscores(name);
+  string name_uc = to_upper_case(name_u);
+
+  string class_name = this->nspace + name;
+  string class_name_lc = to_lower_case(initial_caps_to_underscores(class_name));
+  string class_name_uc = to_upper_case(class_name_lc);
+
+  string function_name;
+  string args_indent;
+
+  // write the instance definition
+  f_types_ << "struct _" << this->nspace << name << endl << "{ " << endl
+           << "  ThriftStruct parent; " << endl << endl << "  /* public */" << endl;
+
+  // for each field, add a member variable
+  vector<t_field*>::const_iterator m_iter;
+  const vector<t_field*>& members = tstruct->get_members();
+  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
+    t_type* t = get_true_type((*m_iter)->get_type());
+    f_types_ << "  " << type_name(t) << " " << (*m_iter)->get_name() << ";" << endl;
+    if ((*m_iter)->get_req() != t_field::T_REQUIRED) {
+      f_types_ << "  gboolean __isset_" << (*m_iter)->get_name() << ";" << endl;
+    }
+  }
+
+  // close the structure definition and create a typedef
+  f_types_ << "};" << endl << "typedef struct _" << this->nspace << name << " " << this->nspace
+           << name << ";" << endl << endl;
+
+  // write the class definition
+  f_types_ << "struct _" << this->nspace << name << "Class" << endl << "{" << endl
+           << "  ThriftStructClass parent;" << endl << "};" << endl << "typedef struct _"
+           << this->nspace << name << "Class " << this->nspace << name << "Class;" << endl << endl;
+
+  // write the standard GObject boilerplate
+  f_types_ << "GType " << this->nspace_lc << name_u << "_get_type (void);" << endl << "#define "
+           << this->nspace_uc << "TYPE_" << name_uc << " (" << this->nspace_lc << name_u
+           << "_get_type())" << endl << "#define " << this->nspace_uc << name_uc
+           << "(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), " << this->nspace_uc << "TYPE_" << name_uc
+           << ", " << this->nspace << name << "))" << endl << "#define " << this->nspace_uc
+           << name_uc << "_CLASS(c) (G_TYPE_CHECK_CLASS_CAST ((c), " << this->nspace_uc << "_TYPE_"
+           << name_uc << ", " << this->nspace << name << "Class))" << endl << "#define "
+           << this->nspace_uc << "IS_" << name_uc << "(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), "
+           << this->nspace_uc << "TYPE_" << name_uc << "))" << endl << "#define " << this->nspace_uc
+           << "IS_" << name_uc << "_CLASS(c) (G_TYPE_CHECK_CLASS_TYPE ((c), " << this->nspace_uc
+           << "TYPE_" << name_uc << "))" << endl << "#define " << this->nspace_uc << name_uc
+           << "_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), " << this->nspace_uc << "TYPE_"
+           << name_uc << ", " << this->nspace << name << "Class))" << endl << endl;
+
+  // start writing the object implementation .c file
+
+  // generate properties enum
+  if (members.size() > 0) {
+    f_types_impl_ << "enum _" << class_name << "Properties" << endl << "{" << endl;
+    indent_up();
+    f_types_impl_ << indent() << "PROP_" << class_name_uc << "_0";
+    for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
+      string member_name_uc
+          = to_upper_case(to_lower_case(initial_caps_to_underscores((*m_iter)->get_name())));
+
+      f_types_impl_ << "," << endl << indent() << "PROP_" << class_name_uc << "_" << member_name_uc;
+    }
+    f_types_impl_ << endl;
+    indent_down();
+    f_types_impl_ << "};" << endl << endl;
+  }
+
+  // generate struct I/O methods
+  string this_get = this->nspace + name + " * this_object = " + this->nspace_uc + name_uc
+                    + "(object);";
+  generate_struct_reader(f_types_impl_, tstruct, "this_object->", this_get);
+  generate_struct_writer(f_types_impl_, tstruct, "this_object->", this_get);
+
+  // generate property setter and getter
+  if (members.size() > 0) {
+    // generate property setter
+    function_name = class_name_lc + "_set_property";
+    args_indent = string(function_name.length() + 2, ' ');
+    f_types_impl_ << "static void" << endl << function_name << " (GObject *object," << endl
+                  << args_indent << "guint property_id," << endl << args_indent
+                  << "const GValue *value," << endl << args_indent << "GParamSpec *pspec)" << endl;
+    scope_up(f_types_impl_);
+    f_types_impl_ << indent() << class_name << " *self = " << class_name_uc << " (object);" << endl
+                  << endl << indent() << "switch (property_id)" << endl;
+    scope_up(f_types_impl_);
+    for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
+      t_field* member = (*m_iter);
+      string member_name = member->get_name();
+      string member_name_uc
+          = to_upper_case(to_lower_case(initial_caps_to_underscores(member_name)));
+      t_type* member_type = get_true_type(member->get_type());
+
+      string property_identifier = "PROP_" + class_name_uc + "_" + member_name_uc;
+
+      f_types_impl_ << indent() << "case " << property_identifier + ":" << endl;
+      indent_up();
+
+      if (member_type->is_base_type()) {
+        t_base_type* base_type = ((t_base_type*)member_type);
+        string assign_function_name;
+
+        if (base_type->get_base() == t_base_type::TYPE_STRING) {
+          string release_function_name;
+
+          f_types_impl_ << indent() << "if (self->" << member_name << " != NULL)" << endl;
+          indent_up();
+
+          if (base_type->is_binary()) {
+            release_function_name = "g_byte_array_unref";
+            assign_function_name = "g_value_dup_boxed";
+          } else {
+            release_function_name = "g_free";
+            assign_function_name = "g_value_dup_string";
+          }
+
+          f_types_impl_ << indent() << release_function_name << " (self->" << member_name << ");"
+                        << endl;
+          indent_down();
+        } else {
+          switch (base_type->get_base()) {
+          case t_base_type::TYPE_BOOL:
+            assign_function_name = "g_value_get_boolean";
+            break;
+
+          case t_base_type::TYPE_I8:
+          case t_base_type::TYPE_I16:
+          case t_base_type::TYPE_I32:
+            assign_function_name = "g_value_get_int";
+            break;
+
+          case t_base_type::TYPE_I64:
+            assign_function_name = "g_value_get_int64";
+            break;
+
+          case t_base_type::TYPE_DOUBLE:
+            assign_function_name = "g_value_get_double";
+            break;
+
+          default:
+            throw "compiler error: "
+                  "unrecognized base type \"" + base_type->get_name() + "\" "
+                                                                        "for struct member \""
+                + member_name + "\"";
+            break;
+          }
+        }
+
+        f_types_impl_ << indent() << "self->" << member_name << " = " << assign_function_name
+                      << " (value);" << endl;
+      } else if (member_type->is_enum()) {
+        f_types_impl_ << indent() << "self->" << member_name << " = g_value_get_int (value);"
+                      << endl;
+      } else if (member_type->is_container()) {
+        string release_function_name;
+        string assign_function_name;
+
+        if (member_type->is_list()) {
+          t_type* elem_type = ((t_list*)member_type)->get_elem_type();
+
+          // Lists of base types other than strings are represented as GArrays;
+          // all others as GPtrArrays
+          if (is_numeric(elem_type)) {
+            release_function_name = "g_array_unref";
+          } else {
+            release_function_name = "g_ptr_array_unref";
+          }
+
+          assign_function_name = "g_value_dup_boxed";
+        } else if (member_type->is_set() || member_type->is_map()) {
+          release_function_name = "g_hash_table_unref";
+          assign_function_name = "g_value_dup_boxed";
+        }
+
+        f_types_impl_ << indent() << "if (self->" << member_name << " != NULL)" << endl;
+        indent_up();
+        f_types_impl_ << indent() << release_function_name << " (self->" << member_name << ");"
+                      << endl;
+        indent_down();
+        f_types_impl_ << indent() << "self->" << member_name << " = " << assign_function_name
+                      << " (value);" << endl;
+      } else if (member_type->is_struct() || member_type->is_xception()) {
+        f_types_impl_ << indent() << "if (self->" << member_name << " != NULL)" << endl;
+        indent_up();
+        f_types_impl_ << indent() << "g_object_unref (self->" << member_name << ");" << endl;
+        indent_down();
+        f_types_impl_ << indent() << "self->" << member_name << " = g_value_dup_object (value);"
+                      << endl;
+      }
+
+      if (member->get_req() != t_field::T_REQUIRED) {
+        f_types_impl_ << indent() << "self->__isset_" << member_name << " = TRUE;" << endl;
+      }
+
+      f_types_impl_ << indent() << "break;" << endl << endl;
+      indent_down();
+    }
+    f_types_impl_ << indent() << "default:" << endl;
+    indent_up();
+    f_types_impl_ << indent() << "G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);"
+                  << endl << indent() << "break;" << endl;
+    indent_down();
+    scope_down(f_types_impl_);
+    scope_down(f_types_impl_);
+    f_types_impl_ << endl;
+
+    // generate property getter
+    function_name = class_name_lc + "_get_property";
+    args_indent = string(function_name.length() + 2, ' ');
+    f_types_impl_ << "static void" << endl << function_name << " (GObject *object," << endl
+                  << args_indent << "guint property_id," << endl << args_indent << "GValue *value,"
+                  << endl << args_indent << "GParamSpec *pspec)" << endl;
+    scope_up(f_types_impl_);
+    f_types_impl_ << indent() << class_name << " *self = " << class_name_uc << " (object);" << endl
+                  << endl << indent() << "switch (property_id)" << endl;
+    scope_up(f_types_impl_);
+    for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
+      t_field* member = (*m_iter);
+      string member_name = (*m_iter)->get_name();
+      string member_name_uc
+          = to_upper_case(to_lower_case(initial_caps_to_underscores(member_name)));
+      t_type* member_type = get_true_type(member->get_type());
+
+      string property_identifier = "PROP_" + class_name_uc + "_" + member_name_uc;
+
+      string setter_function_name;
+
+      if (member_type->is_base_type()) {
+        t_base_type* base_type = ((t_base_type*)member_type);
+
+        switch (base_type->get_base()) {
+        case t_base_type::TYPE_BOOL:
+          setter_function_name = "g_value_set_boolean";
+          break;
+
+        case t_base_type::TYPE_I8:
+        case t_base_type::TYPE_I16:
+        case t_base_type::TYPE_I32:
+          setter_function_name = "g_value_set_int";
+          break;
+
+        case t_base_type::TYPE_I64:
+          setter_function_name = "g_value_set_int64";
+          break;
+
+        case t_base_type::TYPE_DOUBLE:
+          setter_function_name = "g_value_set_double";
+          break;
+
+        case t_base_type::TYPE_STRING:
+          if (base_type->is_binary()) {
+            setter_function_name = "g_value_set_boxed";
+          } else {
+            setter_function_name = "g_value_set_string";
+          }
+          break;
+
+        default:
+          throw "compiler error: "
+                "unrecognized base type \"" + base_type->get_name() + "\" "
+                                                                      "for struct member \""
+              + member_name + "\"";
+          break;
+        }
+      } else if (member_type->is_enum()) {
+        setter_function_name = "g_value_set_int";
+      } else if (member_type->is_struct() || member_type->is_xception()) {
+        setter_function_name = "g_value_set_object";
+      } else if (member_type->is_container()) {
+        setter_function_name = "g_value_set_boxed";
+      } else {
+        throw "compiler error: "
+              "unrecognized type for struct member \"" + member_name + "\"";
+      }
+
+      f_types_impl_ << indent() << "case " << property_identifier + ":" << endl;
+      indent_up();
+      f_types_impl_ << indent() << setter_function_name << " (value, self->" << member_name << ");"
+                    << endl << indent() << "break;" << endl << endl;
+      indent_down();
+    }
+    f_types_impl_ << indent() << "default:" << endl;
+    indent_up();
+    f_types_impl_ << indent() << "G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);"
+                  << endl << indent() << "break;" << endl;
+    indent_down();
+    scope_down(f_types_impl_);
+    scope_down(f_types_impl_);
+    f_types_impl_ << endl;
+  }
+
+  // generate the instance init function
+
+  f_types_impl_ << "static void " << endl << this->nspace_lc << name_u << "_instance_init ("
+                << this->nspace << name << " * object)" << endl << "{" << endl;
+  indent_up();
+
+  // generate default-value structures for container-type members
+  bool constant_declaration_output = false;
+  bool string_list_constant_output = false;
+  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
+    t_field* member = *m_iter;
+    t_const_value* member_value = member->get_value();
+
+    if (member_value != NULL) {
+      string member_name = member->get_name();
+      t_type* member_type = get_true_type(member->get_type());
+
+      if (member_type->is_list()) {
+        const vector<t_const_value*>& list = member_value->get_list();
+        t_type* elem_type = ((t_list*)member_type)->get_elem_type();
+
+        // Generate an array with the list literal
+        indent(f_types_impl_) << "static " << type_name(elem_type, false, true) << " __default_"
+                              << member_name << "[" << list.size() << "] = " << endl;
+        indent_up();
+        f_types_impl_ << indent() << constant_literal(member_type, member_value) << ";" << endl;
+        indent_down();
+
+        constant_declaration_output = true;
+
+        // If we are generating values for a pointer array (i.e. a list of
+        // strings), set a flag so we know to also declare an index variable to
+        // use in pre-populating the array
+        if (elem_type->is_string()) {
+          string_list_constant_output = true;
+        }
+      }
+
+      // TODO: Handle container types other than list
+    }
+  }
+  if (constant_declaration_output) {
+    if (string_list_constant_output) {
+      indent(f_types_impl_) << "unsigned int list_index;" << endl;
+    }
+
+    f_types_impl_ << endl;
+  }
+
+  // satisfy compilers with -Wall turned on
+  indent(f_types_impl_) << "/* satisfy -Wall */" << endl << indent()
+                        << "THRIFT_UNUSED_VAR (object);" << endl;
+
+  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
+    t_type* t = get_true_type((*m_iter)->get_type());
+    if (t->is_base_type()) {
+      string dval = " = ";
+      if (t->is_enum()) {
+        dval += "(" + type_name(t) + ")";
+      }
+      t_const_value* cv = (*m_iter)->get_value();
+      if (cv != NULL) {
+        dval += constant_value("", t, cv);
+      } else {
+        dval += t->is_string() ? "NULL" : "0";
+      }
+      indent(f_types_impl_) << "object->" << (*m_iter)->get_name() << dval << ";" << endl;
+    } else if (t->is_struct()) {
+      string name = (*m_iter)->get_name();
+      string type_name_uc
+          = to_upper_case(initial_caps_to_underscores((*m_iter)->get_type()->get_name()));
+      indent(f_types_impl_) << "object->" << name << " = g_object_new (" << this->nspace_uc
+                            << "TYPE_" << type_name_uc << ", NULL);" << endl;
+    } else if (t->is_xception()) {
+      string name = (*m_iter)->get_name();
+      indent(f_types_impl_) << "object->" << name << " = NULL;" << endl;
+    } else if (t->is_container()) {
+      string name = (*m_iter)->get_name();
+      string init_function;
+      t_type* etype = NULL;
+
+      if (t->is_map()) {
+        t_type* key = ((t_map*)t)->get_key_type();
+        t_type* value = ((t_map*)t)->get_val_type();
+        init_function = generate_new_hash_from_type(key, value);
+      } else if (t->is_set()) {
+        etype = ((t_set*)t)->get_elem_type();
+        init_function = generate_new_hash_from_type(etype, NULL);
+      } else if (t->is_list()) {
+        etype = ((t_list*)t)->get_elem_type();
+        init_function = generate_new_array_from_type(etype);
+      }
+
+      indent(f_types_impl_) << "object->" << name << " = " << init_function << endl;
+
+      // Pre-populate the container with the specified default values, if any
+      if ((*m_iter)->get_value()) {
+        t_const_value* member_value = (*m_iter)->get_value();
+
+        if (t->is_list()) {
+          const vector<t_const_value*>& list = member_value->get_list();
+
+          if (is_numeric(etype)) {
+            indent(f_types_impl_) <<
+              "g_array_append_vals (object->" << name << ", &__default_" <<
+              name << ", " << list.size() << ");" << endl;
+          }
+          else {
+            indent(f_types_impl_) <<
+              "for (list_index = 0; list_index < " << list.size() << "; " <<
+              "list_index += 1)" << endl;
+            indent_up();
+            indent(f_types_impl_) <<
+              "g_ptr_array_add (object->" << name << "," << endl <<
+              indent() << string(17, ' ') << "g_strdup (__default_" <<
+              name << "[list_index]));" << endl;
+            indent_down();
+          }
+        }
+
+        // TODO: Handle container types other than list
+      }
+    }
+
+    /* if not required, initialize the __isset variable */
+    if ((*m_iter)->get_req() != t_field::T_REQUIRED) {
+      indent(f_types_impl_) << "object->__isset_" << (*m_iter)->get_name() << " = FALSE;" << endl;
+    }
+  }
+
+  indent_down();
+  f_types_impl_ << "}" << endl << endl;
+
+  /* create the destructor */
+  f_types_impl_ << "static void " << endl << this->nspace_lc << name_u
+                << "_finalize (GObject *object)" << endl << "{" << endl;
+  indent_up();
+
+  f_types_impl_ << indent() << this->nspace << name << " *tobject = " << this->nspace_uc << name_uc
+                << " (object);" << endl << endl;
+
+  f_types_impl_ << indent() << "/* satisfy -Wall in case we don't use tobject */" << endl
+                << indent() << "THRIFT_UNUSED_VAR (tobject);" << endl;
+
+  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
+    t_type* t = get_true_type((*m_iter)->get_type());
+    if (t->is_container()) {
+      string name = (*m_iter)->get_name();
+      if (t->is_map() || t->is_set()) {
+        f_types_impl_ << indent() << "if (tobject->" << name << " != NULL)" << endl;
+        f_types_impl_ << indent() << "{" << endl;
+        indent_up();
+        f_types_impl_ << indent() << "g_hash_table_destroy (tobject->" << name << ");" << endl;
+        f_types_impl_ << indent() << "tobject->" << name << " = NULL;" << endl;
+        indent_down();
+        f_types_impl_ << indent() << "}" << endl;
+      } else if (t->is_list()) {
+        t_type* etype = ((t_list*)t)->get_elem_type();
+        string destructor_function = "g_ptr_array_unref";
+
+        if (etype->is_base_type()) {
+          t_base_type::t_base tbase = ((t_base_type*)etype)->get_base();
+          switch (tbase) {
+          case t_base_type::TYPE_VOID:
+            throw "compiler error: cannot determine array type";
+          case t_base_type::TYPE_BOOL:
+          case t_base_type::TYPE_I8:
+          case t_base_type::TYPE_I16:
+          case t_base_type::TYPE_I32:
+          case t_base_type::TYPE_I64:
+          case t_base_type::TYPE_DOUBLE:
+            destructor_function = "g_array_unref";
+            break;
+          case t_base_type::TYPE_STRING:
+            break;
+          default:
+            throw "compiler error: no array info for type";
+          }
+        } else if (etype->is_enum()) {
+          destructor_function = "g_array_unref";
+        }
+
+        f_types_impl_ << indent() << "if (tobject->" << name << " != NULL)" << endl;
+        f_types_impl_ << indent() << "{" << endl;
+        indent_up();
+        f_types_impl_ << indent() << destructor_function << " (tobject->" << name << ");" << endl;
+        f_types_impl_ << indent() << "tobject->" << name << " = NULL;" << endl;
+        indent_down();
+        f_types_impl_ << indent() << "}" << endl;
+      }
+    } else if (t->is_struct() || t->is_xception()) {
+      string name = (*m_iter)->get_name();
+      // TODO: g_clear_object needs glib >= 2.28
+      // f_types_impl_ << indent() << "g_clear_object (&(tobject->" << name << "));" << endl;
+      // does g_object_unref the trick?
+      f_types_impl_ << indent() << "if (tobject->" << name << " != NULL)" << endl;
+      f_types_impl_ << indent() << "{" << endl;
+      indent_up();
+      f_types_impl_ << indent() << "g_object_unref(tobject->" << name << ");" << endl;
+      f_types_impl_ << indent() << "tobject->" << name << " = NULL;" << endl;
+      indent_down();
+      f_types_impl_ << indent() << "}" << endl;
+    } else if (t->is_string()) {
+      string name = (*m_iter)->get_name();
+      f_types_impl_ << indent() << "if (tobject->" << name << " != NULL)" << endl;
+      f_types_impl_ << indent() << "{" << endl;
+      indent_up();
+      f_types_impl_ << indent() << generate_free_func_from_type(t) << "(tobject->" << name << ");"
+                    << endl;
+      f_types_impl_ << indent() << "tobject->" << name << " = NULL;" << endl;
+      indent_down();
+      f_types_impl_ << indent() << "}" << endl;
+    }
+  }
+
+  indent_down();
+  f_types_impl_ << "}" << endl << endl;
+
+  // generate the class init function
+
+  f_types_impl_ << "static void" << endl << class_name_lc << "_class_init (" << class_name
+                << "Class * cls)" << endl;
+  scope_up(f_types_impl_);
+
+  f_types_impl_ << indent() << "GObjectClass *gobject_class = G_OBJECT_CLASS (cls);" << endl
+                << indent() << "ThriftStructClass *struct_class = "
+                << "THRIFT_STRUCT_CLASS (cls);" << endl << endl << indent()
+                << "struct_class->read = " << class_name_lc << "_read;" << endl << indent()
+                << "struct_class->write = " << class_name_lc << "_write;" << endl << endl
+                << indent() << "gobject_class->finalize = " << class_name_lc << "_finalize;"
+                << endl;
+  if (members.size() > 0) {
+    f_types_impl_ << indent() << "gobject_class->get_property = " << class_name_lc
+                  << "_get_property;" << endl << indent()
+                  << "gobject_class->set_property = " << class_name_lc << "_set_property;" << endl;
+
+    // install a property for each member
+    for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
+      t_field* member = (*m_iter);
+      string member_name = member->get_name();
+      string member_name_uc
+          = to_upper_case(to_lower_case(initial_caps_to_underscores(member_name)));
+      t_type* member_type = get_true_type(member->get_type());
+      t_const_value* member_value = member->get_value();
+
+      string property_identifier = "PROP_" + class_name_uc + "_" + member_name_uc;
+
+      f_types_impl_ << endl << indent() << "g_object_class_install_property" << endl;
+      indent_up();
+      args_indent = indent() + ' ';
+      f_types_impl_ << indent() << "(gobject_class," << endl << args_indent << property_identifier
+                    << "," << endl << args_indent;
+
+      if (member_type->is_base_type()) {
+        t_base_type::t_base base_type = ((t_base_type*)member_type)->get_base();
+
+        if (base_type == t_base_type::TYPE_STRING) {
+          if (((t_base_type*)member_type)->is_binary()) {
+            args_indent += string(20, ' ');
+            f_types_impl_ << "g_param_spec_boxed (\"" << member_name << "\"," << endl << args_indent
+                          << "NULL," << endl << args_indent << "NULL," << endl << args_indent
+                          << "G_TYPE_BYTE_ARRAY," << endl << args_indent << "G_PARAM_READWRITE));"
+                          << endl;
+          } else {
+            args_indent += string(21, ' ');
+            f_types_impl_ << "g_param_spec_string (\"" << member_name << "\"," << endl
+                          << args_indent << "NULL," << endl << args_indent << "NULL," << endl
+                          << args_indent
+                          << ((member_value != NULL) ? "\"" + member_value->get_string() + "\""
+                                                     : "NULL") << "," << endl << args_indent
+                          << "G_PARAM_READWRITE));" << endl;
+          }
+        } else if (base_type == t_base_type::TYPE_BOOL) {
+          args_indent += string(22, ' ');
+          f_types_impl_ << "g_param_spec_boolean (\"" << member_name << "\"," << endl << args_indent
+                        << "NULL," << endl << args_indent << "NULL," << endl << args_indent
+                        << (((member_value != NULL) && (member_value->get_integer() != 0))
+                                ? "TRUE"
+                                : "FALSE") << "," << endl << args_indent << "G_PARAM_READWRITE));"
+                        << endl;
+        } else if ((base_type == t_base_type::TYPE_I8) || (base_type == t_base_type::TYPE_I16)
+                   || (base_type == t_base_type::TYPE_I32) || (base_type == t_base_type::TYPE_I64)
+                   || (base_type == t_base_type::TYPE_DOUBLE)) {
+          string param_spec_function_name = "g_param_spec_int";
+          string min_value;
+          string max_value;
+          ostringstream default_value;
+
+          switch (base_type) {
+          case t_base_type::TYPE_I8:
+            min_value = "G_MININT8";
+            max_value = "G_MAXINT8";
+            break;
+
+          case t_base_type::TYPE_I16:
+            min_value = "G_MININT16";
+            max_value = "G_MAXINT16";
+            break;
+
+          case t_base_type::TYPE_I32:
+            min_value = "G_MININT32";
+            max_value = "G_MAXINT32";
+            break;
+
+          case t_base_type::TYPE_I64:
+            param_spec_function_name = "g_param_spec_int64";
+            min_value = "G_MININT64";
+            max_value = "G_MAXINT64";
+            break;
+
+          case t_base_type::TYPE_DOUBLE:
+            param_spec_function_name = "g_param_spec_double";
+            min_value = "-INFINITY";
+            max_value = "INFINITY";
+            break;
+
+          default:
+            throw "compiler error: "
+                  "unrecognized base type \"" + member_type->get_name() + "\" "
+                                                                          "for struct member \""
+                + member_name + "\"";
+            break;
+          }
+
+          if (member_value != NULL) {
+            default_value << (base_type == t_base_type::TYPE_DOUBLE ? member_value->get_double()
+                                                                    : member_value->get_integer());
+          } else {
+            default_value << "0";
+          }
+
+          args_indent += string(param_spec_function_name.length() + 2, ' ');
+          f_types_impl_ << param_spec_function_name << " (\"" << member_name << "\"," << endl
+                        << args_indent << "NULL," << endl << args_indent << "NULL," << endl
+                        << args_indent << min_value << "," << endl << args_indent << max_value
+                        << "," << endl << args_indent << default_value.str() << "," << endl
+                        << args_indent << "G_PARAM_READWRITE));" << endl;
+        }
+
+        indent_down();
+      } else if (member_type->is_enum()) {
+        t_enum_value* enum_min_value = ((t_enum*)member_type)->get_min_value();
+        t_enum_value* enum_max_value = ((t_enum*)member_type)->get_max_value();
+        int min_value = (enum_min_value != NULL) ? enum_min_value->get_value() : 0;
+        int max_value = (enum_max_value != NULL) ? enum_max_value->get_value() : 0;
+
+        args_indent += string(18, ' ');
+        f_types_impl_ << "g_param_spec_int (\"" << member_name << "\"," << endl << args_indent
+                      << "NULL," << endl << args_indent << "NULL," << endl << args_indent
+                      << min_value << "," << endl << args_indent << max_value << "," << endl
+                      << args_indent << min_value << "," << endl << args_indent
+                      << "G_PARAM_READWRITE));" << endl;
+        indent_down();
+      } else if (member_type->is_struct() || member_type->is_xception()) {
+        string param_type = this->nspace_uc + "TYPE_"
+                            + to_upper_case(initial_caps_to_underscores(member_type->get_name()));
+
+        args_indent += string(20, ' ');
+        f_types_impl_ << "g_param_spec_object (\"" << member_name << "\"," << endl << args_indent
+                      << "NULL," << endl << args_indent << "NULL," << endl << args_indent
+                      << param_type << "," << endl << args_indent << "G_PARAM_READWRITE));" << endl;
+        indent_down();
+      } else if (member_type->is_list()) {
+        t_type* elem_type = ((t_list*)member_type)->get_elem_type();
+        string param_type;
+
+        if (elem_type->is_base_type() && !elem_type->is_string()) {
+          param_type = "G_TYPE_ARRAY";
+        } else {
+          param_type = "G_TYPE_PTR_ARRAY";
+        }
+
+        args_indent += string(20, ' ');
+        f_types_impl_ << "g_param_spec_boxed (\"" << member_name << "\"," << endl << args_indent
+                      << "NULL," << endl << args_indent << "NULL," << endl << args_indent
+                      << param_type << "," << endl << args_indent << "G_PARAM_READWRITE));" << endl;
+        indent_down();
+      } else if (member_type->is_set() || member_type->is_map()) {
+        args_indent += string(20, ' ');
+        f_types_impl_ << "g_param_spec_boxed (\"" << member_name << "\"," << endl << args_indent
+                      << "NULL," << endl << args_indent << "NULL," << endl << args_indent
+                      << "G_TYPE_HASH_TABLE," << endl << args_indent << "G_PARAM_READWRITE));"
+                      << endl;
+        indent_down();
+      }
+    }
+  }
+  scope_down(f_types_impl_);
+  f_types_impl_ << endl;
+
+  f_types_impl_ << "GType" << endl << this->nspace_lc << name_u << "_get_type (void)" << endl << "{"
+                << endl << "  static GType type = 0;" << endl << endl << "  if (type == 0) " << endl
+                << "  {" << endl << "    static const GTypeInfo type_info = " << endl << "    {"
+                << endl << "      sizeof (" << this->nspace << name << "Class)," << endl
+                << "      NULL, /* base_init */" << endl << "      NULL, /* base_finalize */"
+                << endl << "      (GClassInitFunc) " << this->nspace_lc << name_u << "_class_init,"
+                << endl << "      NULL, /* class_finalize */" << endl
+                << "      NULL, /* class_data */" << endl << "      sizeof (" << this->nspace
+                << name << ")," << endl << "      0, /* n_preallocs */" << endl
+                << "      (GInstanceInitFunc) " << this->nspace_lc << name_u << "_instance_init,"
+                << endl << "      NULL, /* value_table */" << endl << "    };" << endl << endl
+                << "    type = g_type_register_static (THRIFT_TYPE_STRUCT, " << endl
+                << "                                   \"" << this->nspace << name << "Type\","
+                << endl << "                                   &type_info, 0);" << endl << "  }"
+                << endl << endl << "  return type;" << endl << "}" << endl << endl;
+}
+
+/**
+ * Generates functions to write Thrift structures to a stream.
+ */
+void t_c_glib_generator::generate_struct_writer(ostream& out,
+                                                t_struct* tstruct,
+                                                string this_name,
+                                                string this_get,
+                                                bool is_function) {
+  string name = tstruct->get_name();
+  string name_u = initial_caps_to_underscores(name);
+  string name_uc = to_upper_case(name_u);
+
+  const vector<t_field*>& fields = tstruct->get_members();
+  vector<t_field*>::const_iterator f_iter;
+  int error_ret = 0;
+
+  if (is_function) {
+    error_ret = -1;
+    indent(out) << "static gint32" << endl << this->nspace_lc << name_u
+                << "_write (ThriftStruct *object, ThriftProtocol *protocol, GError **error)"
+                << endl;
+  }
+  indent(out) << "{" << endl;
+  indent_up();
+
+  out << indent() << "gint32 ret;" << endl << indent() << "gint32 xfer = 0;" << endl << endl;
+
+  indent(out) << this_get << endl;
+  // satisfy -Wall in the case of an empty struct
+  if (!this_get.empty()) {
+    indent(out) << "THRIFT_UNUSED_VAR (this_object);" << endl;
+  }
+
+  out << indent() << "if ((ret = thrift_protocol_write_struct_begin (protocol, \"" << name
+      << "\", error)) < 0)" << endl << indent() << "  return " << error_ret << ";" << endl
+      << indent() << "xfer += ret;" << endl;
+
+  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+    if ((*f_iter)->get_req() == t_field::T_OPTIONAL) {
+      indent(out) << "if (this_object->__isset_" << (*f_iter)->get_name() << " == TRUE) {" << endl;
+      indent_up();
+    }
+
+    out << indent() << "if ((ret = thrift_protocol_write_field_begin (protocol, "
+        << "\"" << (*f_iter)->get_name() << "\", " << type_to_enum((*f_iter)->get_type()) << ", "
+        << (*f_iter)->get_key() << ", error)) < 0)" << endl << indent() << "  return " << error_ret
+        << ";" << endl << indent() << "xfer += ret;" << endl;
+    generate_serialize_field(out, *f_iter, this_name, "", error_ret);
+    out << indent() << "if ((ret = thrift_protocol_write_field_end (protocol, error)) < 0)" << endl
+        << indent() << "  return " << error_ret << ";" << endl << indent() << "xfer += ret;"
+        << endl;
+
+    if ((*f_iter)->get_req() == t_field::T_OPTIONAL) {
+      indent_down();
+      indent(out) << "}" << endl;
+    }
+  }
+
+  // write the struct map
+  out << indent() << "if ((ret = thrift_protocol_write_field_stop (protocol, error)) < 0)" << endl
+      << indent() << "  return " << error_ret << ";" << endl << indent() << "xfer += ret;" << endl
+      << indent() << "if ((ret = thrift_protocol_write_struct_end (protocol, error)) < 0)" << endl
+      << indent() << "  return " << error_ret << ";" << endl << indent() << "xfer += ret;" << endl
+      << endl;
+
+  if (is_function) {
+    indent(out) << "return xfer;" << endl;
+  }
+
+  indent_down();
+  indent(out) << "}" << endl << endl;
+}
+
+/**
+ * Generates code to read Thrift structures from a stream.
+ */
+void t_c_glib_generator::generate_struct_reader(ostream& out,
+                                                t_struct* tstruct,
+                                                string this_name,
+                                                string this_get,
+                                                bool is_function) {
+  string name = tstruct->get_name();
+  string name_u = initial_caps_to_underscores(name);
+  string name_uc = to_upper_case(name_u);
+  int error_ret = 0;
+  const vector<t_field*>& fields = tstruct->get_members();
+  vector<t_field*>::const_iterator f_iter;
+
+  if (is_function) {
+    error_ret = -1;
+    indent(out) << "/* reads a " << name_u << " object */" << endl << "static gint32" << endl
+                << this->nspace_lc << name_u
+                << "_read (ThriftStruct *object, ThriftProtocol *protocol, GError **error)" << endl;
+  }
+
+  indent(out) << "{" << endl;
+  indent_up();
+
+  // declare stack temp variables
+  out << indent() << "gint32 ret;" << endl << indent() << "gint32 xfer = 0;" << endl << indent()
+      << "gchar *name = NULL;" << endl << indent() << "ThriftType ftype;" << endl << indent()
+      << "gint16 fid;" << endl << indent() << "guint32 len = 0;" << endl << indent()
+      << "gpointer data = NULL;" << endl << indent() << this_get << endl;
+
+  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+    if ((*f_iter)->get_req() == t_field::T_REQUIRED) {
+      indent(out) << "gboolean isset_" << (*f_iter)->get_name() << " = FALSE;" << endl;
+    }
+  }
+
+  out << endl;
+
+  // satisfy -Wall in case we don't use some variables
+  out << indent() << "/* satisfy -Wall in case these aren't used */" << endl << indent()
+      << "THRIFT_UNUSED_VAR (len);" << endl << indent() << "THRIFT_UNUSED_VAR (data);" << endl;
+
+  if (!this_get.empty()) {
+    out << indent() << "THRIFT_UNUSED_VAR (this_object);" << endl;
+  }
+  out << endl;
+
+  // read the beginning of the structure marker
+  out << indent() << "/* read the struct begin marker */" << endl << indent()
+      << "if ((ret = thrift_protocol_read_struct_begin (protocol, &name, error)) < 0)" << endl
+      << indent() << "{" << endl << indent() << "  if (name) g_free (name);" << endl << indent()
+      << "  return " << error_ret << ";" << endl << indent() << "}" << endl << indent()
+      << "xfer += ret;" << endl << indent() << "if (name) g_free (name);" << endl << indent()
+      << "name = NULL;" << endl << endl;
+
+  // read the struct fields
+  out << indent() << "/* read the struct fields */" << endl << indent() << "while (1)" << endl;
+  scope_up(out);
+
+  // read beginning field marker
+  out << indent() << "/* read the beginning of a field */" << endl << indent()
+      << "if ((ret = thrift_protocol_read_field_begin (protocol, &name, &ftype, &fid, error)) < 0)"
+      << endl << indent() << "{" << endl << indent() << "  if (name) g_free (name);" << endl
+      << indent() << "  return " << error_ret << ";" << endl << indent() << "}" << endl << indent()
+      << "xfer += ret;" << endl << indent() << "if (name) g_free (name);" << endl << indent()
+      << "name = NULL;" << endl << endl;
+
+  // check for field STOP marker
+  out << indent() << "/* break if we get a STOP field */" << endl << indent()
+      << "if (ftype == T_STOP)" << endl << indent() << "{" << endl << indent() << "  break;" << endl
+      << indent() << "}" << endl << endl;
+
+  // switch depending on the field type
+  indent(out) << "switch (fid)" << endl;
+
+  // start switch
+  scope_up(out);
+
+  // generate deserialization code for known types
+  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+    indent(out) << "case " << (*f_iter)->get_key() << ":" << endl;
+    indent_up();
+    indent(out) << "if (ftype == " << type_to_enum((*f_iter)->get_type()) << ")" << endl;
+    indent(out) << "{" << endl;
+
+    indent_up();
+    // generate deserialize field
+    generate_deserialize_field(out, *f_iter, this_name, "", error_ret, false);
+    indent_down();
+
+    out << indent() << "} else {" << endl << indent()
+        << "  if ((ret = thrift_protocol_skip (protocol, ftype, error)) < 0)" << endl << indent()
+        << "    return " << error_ret << ";" << endl << indent() << "  xfer += ret;" << endl
+        << indent() << "}" << endl << indent() << "break;" << endl;
+    indent_down();
+  }
+
+  // create the default case
+  out << indent() << "default:" << endl << indent()
+      << "  if ((ret = thrift_protocol_skip (protocol, ftype, error)) < 0)" << endl << indent()
+      << "    return " << error_ret << ";" << endl << indent() << "  xfer += ret;" << endl
+      << indent() << "  break;" << endl;
+
+  // end switch
+  scope_down(out);
+
+  // read field end marker
+  out << indent() << "if ((ret = thrift_protocol_read_field_end (protocol, error)) < 0)" << endl
+      << indent() << "  return " << error_ret << ";" << endl << indent() << "xfer += ret;" << endl;
+
+  // end while loop
+  scope_down(out);
+  out << endl;
+
+  // read the end of the structure
+  out << indent() << "if ((ret = thrift_protocol_read_struct_end (protocol, error)) < 0)" << endl
+      << indent() << "  return " << error_ret << ";" << endl << indent() << "xfer += ret;" << endl
+      << endl;
+
+  // if a required field is missing, throw an error
+  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+    if ((*f_iter)->get_req() == t_field::T_REQUIRED) {
+      out << indent() << "if (!isset_" << (*f_iter)->get_name() << ")" << endl << indent() << "{"
+          << endl << indent() << "  g_set_error (error, THRIFT_PROTOCOL_ERROR," << endl << indent()
+          << "               THRIFT_PROTOCOL_ERROR_INVALID_DATA," << endl << indent()
+          << "               \"missing field\");" << endl << indent() << "  return -1;" << endl
+          << indent() << "}" << endl << endl;
+    }
+  }
+
+  if (is_function) {
+    indent(out) << "return xfer;" << endl;
+  }
+
+  // end the function/structure
+  indent_down();
+  indent(out) << "}" << endl << endl;
+}
+
+void t_c_glib_generator::generate_serialize_field(ostream& out,
+                                                  t_field* tfield,
+                                                  string prefix,
+                                                  string suffix,
+                                                  int error_ret) {
+  t_type* type = get_true_type(tfield->get_type());
+  string name = prefix + tfield->get_name() + suffix;
+
+  if (type->is_void()) {
+    throw "CANNOT GENERATE SERIALIZE CODE FOR void TYPE: " + name;
+  }
+
+  if (type->is_struct() || type->is_xception()) {
+    generate_serialize_struct(out, (t_struct*)type, name, error_ret);
+  } else if (type->is_container()) {
+    generate_serialize_container(out, type, name, error_ret);
+  } else if (type->is_base_type() || type->is_enum()) {
+    indent(out) << "if ((ret = thrift_protocol_write_";
+
+    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:
+        throw "compiler error: cannot serialize void field in a struct: " + name;
+        break;
+      case t_base_type::TYPE_BOOL:
+        out << "bool (protocol, " << name;
+        break;
+      case t_base_type::TYPE_I8:
+        out << "byte (protocol, " << name;
+        break;
+      case t_base_type::TYPE_I16:
+        out << "i16 (protocol, " << name;
+        break;
+      case t_base_type::TYPE_I32:
+        out << "i32 (protocol, " << name;
+        break;
+      case t_base_type::TYPE_I64:
+        out << "i64 (protocol, " << name;
+        break;
+      case t_base_type::TYPE_DOUBLE:
+        out << "double (protocol, " << name;
+        break;
+      case t_base_type::TYPE_STRING:
+        if (type->is_binary()) {
+          out << "binary (protocol, " << name << " ? ((GByteArray *) " << name << ")->data : NULL, "
+              << name << " ? ((GByteArray *) " << name << ")->len : 0";
+        } else {
+          out << "string (protocol, " << name;
+        }
+        break;
+      default:
+        throw "compiler error: no C writer for base type " + t_base_type::t_base_name(tbase) + name;
+      }
+    } else {
+      out << "i32 (protocol, (gint32) " << name;
+    }
+    out << ", error)) < 0)" << endl
+        << indent() << "  return " << error_ret << ";" << endl
+        << indent() << "xfer += ret;" << endl << endl;
+  } else {
+    throw std::logic_error("DO NOT KNOW HOW TO SERIALIZE FIELD '" + name + "' TYPE '"
+                           + type_name(type));
+  }
+}
+
+void t_c_glib_generator::generate_serialize_struct(ostream& out,
+                                                   t_struct* tstruct,
+                                                   string prefix,
+                                                   int error_ret) {
+  (void)tstruct;
+  out << indent() << "if ((ret = thrift_struct_write (THRIFT_STRUCT (" << prefix
+      << "), protocol, error)) < 0)" << endl << indent() << "  return " << error_ret << ";" << endl
+      << indent() << "xfer += ret;" << endl << endl;
+}
+
+void t_c_glib_generator::generate_serialize_container(ostream& out,
+                                                      t_type* ttype,
+                                                      string prefix,
+                                                      int error_ret) {
+  scope_up(out);
+
+  if (ttype->is_map()) {
+    t_type* tkey = ((t_map*)ttype)->get_key_type();
+    t_type* tval = ((t_map*)ttype)->get_val_type();
+    string tkey_name = type_name(tkey);
+    string tval_name = type_name(tval);
+    string tkey_ptr;
+    string tval_ptr;
+    string keyname = tmp("key");
+    string valname = tmp("val");
+
+    declore_local_variable_for_write(out, tkey, keyname);
+    declore_local_variable_for_write(out, tval, valname);
+
+    /* If either the key or value type is a typedef, find its underlying type so
+       we can correctly determine how to generate a pointer to it */
+    tkey = get_true_type(tkey);
+    tval = get_true_type(tval);
+
+    tkey_ptr = tkey->is_string() || !tkey->is_base_type() ? "" : "*";
+    tval_ptr = tval->is_string() || !tval->is_base_type() ? "" : "*";
+
+    /*
+     * Some ugliness here.  To maximize backwards compatibility, we
+     * avoid using GHashTableIter and instead get a GList of all keys,
+     * then copy it into a array on the stack, and free it.
+     * This is because we may exit early before we get a chance to free the
+     * GList.
+     */
+    out << indent() << "GList *key_list = NULL, *iter = NULL;" << endl
+        << indent() << tkey_name << tkey_ptr << "* keys;" << endl
+        << indent() << "int i = 0, key_count;" << endl
+        << endl
+        << indent() << "if ((ret = thrift_protocol_write_map_begin (protocol, "
+        << type_to_enum(tkey) << ", " << type_to_enum(tval) << ", " << prefix << " ? "
+        << "(gint32) g_hash_table_size ((GHashTable *) " << prefix << ") : 0"
+        << ", error)) < 0)" << endl;
+    indent_up();
+    out << indent() << "return " << error_ret << ";" << endl;
+    indent_down();
+    out << indent() << "xfer += ret;" << endl
+        << indent() << "if (" << prefix << ")" << endl
+        << indent() << "  g_hash_table_foreach ((GHashTable *) " << prefix
+        << ", thrift_hash_table_get_keys, &key_list);" << endl
+        << indent() << "key_count = g_list_length (key_list);" << endl
+        << indent() << "keys = g_newa (" << tkey_name << tkey_ptr
+        << ", key_count);" << endl
+        << indent() << "for (iter = g_list_first (key_list); iter; "
+           "iter = iter->next)" << endl;
+    indent_up();
+    out << indent() << "keys[i++] = (" << tkey_name << tkey_ptr
+        << ") iter->data;" << endl;
+    indent_down();
+    out << indent() << "g_list_free (key_list);" << endl
+        << endl
+        << indent() << "for (i = 0; i < key_count; ++i)" << endl;
+    scope_up(out);
+    out << indent() << keyname << " = keys[i];" << endl
+        << indent() << valname << " = (" << tval_name << tval_ptr
+        << ") g_hash_table_lookup (((GHashTable *) " << prefix
+        << "), (gpointer) " << keyname << ");" << endl
+        << endl;
+    generate_serialize_map_element(out,
+                                   (t_map*)ttype,
+                                   tkey_ptr + " " + keyname,
+                                   tval_ptr + " " + valname,
+                                   error_ret);
+    scope_down(out);
+    out << indent() << "if ((ret = thrift_protocol_write_map_end (protocol, "
+           "error)) < 0)" << endl;
+    indent_up();
+    out << indent() << "return " << error_ret << ";" << endl;
+    indent_down();
+    out << indent() << "xfer += ret;" << endl;
+  } else if (ttype->is_set()) {
+    t_type* telem = ((t_set*)ttype)->get_elem_type();
+    string telem_name = type_name(telem);
+    string telem_ptr = telem->is_string() || !telem->is_base_type() ? "" : "*";
+    out << indent() << "GList *key_list = NULL, *iter = NULL;" << endl
+        << indent() << telem_name << telem_ptr << "* keys;" << endl
+        << indent() << "int i = 0, key_count;" << endl
+        << indent() << telem_name << telem_ptr << " elem;" << endl
+        << indent() << "gpointer value;" << endl
+        << indent() << "THRIFT_UNUSED_VAR (value);" << endl
+        << endl
+        << indent() << "if ((ret = thrift_protocol_write_set_begin (protocol, "
+        << type_to_enum(telem) << ", " << prefix << " ? "
+        << "(gint32) g_hash_table_size ((GHashTable *) " << prefix << ") : 0"
+        << ", error)) < 0)" << endl;
+    indent_up();
+    out << indent() << "return " << error_ret << ";" << endl;
+    indent_down();
+    out << indent() << "xfer += ret;" << endl
+        << indent() << "if (" << prefix << ")" << endl
+        << indent() << "  g_hash_table_foreach ((GHashTable *) " << prefix
+        << ", thrift_hash_table_get_keys, &key_list);" << endl
+        << indent() << "key_count = g_list_length (key_list);" << endl
+        << indent() << "keys = g_newa (" << telem_name << telem_ptr
+        << ", key_count);" << endl
+        << indent() << "for (iter = g_list_first (key_list); iter; "
+           "iter = iter->next)" << endl;
+    indent_up();
+    out << indent() << "keys[i++] = (" << telem_name << telem_ptr
+        << ") iter->data;" << endl;
+    indent_down();
+    out << indent() << "g_list_free (key_list);" << endl
+        << endl
+        << indent() << "for (i = 0; i < key_count; ++i)" << endl;
+    scope_up(out);
+    out << indent() << "elem = keys[i];" << endl
+        << indent() << "value = (gpointer) g_hash_table_lookup "
+           "(((GHashTable *) " << prefix << "), (gpointer) elem);" << endl
+        << endl;
+    generate_serialize_set_element(out,
+                                   (t_set*)ttype,
+                                   telem_ptr + "elem",
+                                   error_ret);
+    scope_down(out);
+    out << indent() << "if ((ret = thrift_protocol_write_set_end (protocol, "
+           "error)) < 0)" << endl;
+    indent_up();
+    out << indent() << "return " << error_ret << ";" << endl;
+    indent_down();
+    out << indent() << "xfer += ret;" << endl;
+  } else if (ttype->is_list()) {
+    string length = "(" + prefix + " ? " + prefix + "->len : 0)";
+    string i = tmp("i");
+    out << indent() << "guint " << i << ";" << endl
+        << endl
+        << indent() << "if ((ret = thrift_protocol_write_list_begin (protocol, "
+        << type_to_enum(((t_list*)ttype)->get_elem_type()) << ", (gint32) "
+        << length << ", error)) < 0)" << endl;
+    indent_up();
+    out << indent() << "return " << error_ret << ";" << endl;
+    indent_down();
+    out << indent() << "xfer += ret;" << endl
+        << indent() << "for (" << i << " = 0; " << i << " < " << length << "; "
+        << i << "++)" << endl;
+    scope_up(out);
+    generate_serialize_list_element(out, (t_list*)ttype, prefix, i, error_ret);
+    scope_down(out);
+    out << indent() << "if ((ret = thrift_protocol_write_list_end (protocol, "
+           "error)) < 0)" << endl;
+    indent_up();
+    out << indent() << "return " << error_ret << ";" << endl;
+    indent_down();
+    out << indent() << "xfer += ret;" << endl;
+  }
+
+  scope_down(out);
+}
+
+void t_c_glib_generator::generate_serialize_map_element(ostream& out,
+                                                        t_map* tmap,
+                                                        string key,
+                                                        string value,
+                                                        int error_ret) {
+  t_field kfield(tmap->get_key_type(), key);
+  generate_serialize_field(out, &kfield, "", "", error_ret);
+
+  t_field vfield(tmap->get_val_type(), value);
+  generate_serialize_field(out, &vfield, "", "", error_ret);
+}
+
+void t_c_glib_generator::generate_serialize_set_element(ostream& out,
+                                                        t_set* tset,
+                                                        string element,
+                                                        int error_ret) {
+  t_field efield(tset->get_elem_type(), element);
+  generate_serialize_field(out, &efield, "", "", error_ret);
+}
+
+void t_c_glib_generator::generate_serialize_list_element(ostream& out,
+                                                         t_list* tlist,
+                                                         string list,
+                                                         string index,
+                                                         int error_ret) {
+  t_type* ttype = get_true_type(tlist->get_elem_type());
+
+  // cast to non-const
+  string cast = "";
+  string name = "g_ptr_array_index ((GPtrArray *) " + list + ", " + index + ")";
+
+  if (ttype->is_void()) {
+    throw std::runtime_error("compiler error: list element type cannot be void");
+  } else if (is_numeric(ttype)) {
+    name = "g_array_index (" + list + ", " + base_type_name(ttype) + ", " + index + ")";
+  } else if (ttype->is_string()) {
+    cast = "(gchar*)";
+  } else if (ttype->is_map() || ttype->is_set()) {
+    cast = "(GHashTable*)";
+  } else if (ttype->is_list()) {
+    t_type* etype = ((t_list*)ttype)->get_elem_type();
+    if (etype->is_void()) {
+      throw std::runtime_error("compiler error: list element type cannot be void");
+    }
+    cast = is_numeric(etype) ? "(GArray*)" : "(GPtrArray*)";
+  }
+
+  t_field efield(ttype, "(" + cast + name + ")");
+  generate_serialize_field(out, &efield, "", "", error_ret);
+}
+
+/* deserializes a field of any type. */
+void t_c_glib_generator::generate_deserialize_field(ostream& out,
+                                                    t_field* tfield,
+                                                    string prefix,
+                                                    string suffix,
+                                                    int error_ret,
+                                                    bool allocate) {
+  t_type* type = get_true_type(tfield->get_type());
+
+  if (type->is_void()) {
+    throw std::runtime_error("CANNOT GENERATE DESERIALIZE CODE FOR void TYPE: " + prefix
+                             + tfield->get_name());
+  }
+
+  string name = prefix + tfield->get_name() + suffix;
+
+  if (type->is_struct() || type->is_xception()) {
+    generate_deserialize_struct(out, (t_struct*)type, name, error_ret, allocate);
+  } else if (type->is_container()) {
+    generate_deserialize_container(out, type, name, error_ret);
+  } else if (type->is_base_type()) {
+    t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
+    if (tbase == t_base_type::TYPE_STRING) {
+      indent(out) << "if (" << name << " != NULL)" << endl << indent() << "{" << endl;
+      indent_up();
+      indent(out) << "g_free(" << name << ");" << endl << indent() << name << " = NULL;" << endl;
+      indent_down();
+      indent(out) << "}" << endl << endl;
+    }
+    indent(out) << "if ((ret = thrift_protocol_read_";
+
+    switch (tbase) {
+    case t_base_type::TYPE_VOID:
+      throw "compiler error: cannot serialize void field in a struct: " + name;
+      break;
+    case t_base_type::TYPE_STRING:
+      if (type->is_binary()) {
+        out << "binary (protocol, &data, &len";
+      } else {
+        out << "string (protocol, &" << name;
+      }
+      break;
+    case t_base_type::TYPE_BOOL:
+      out << "bool (protocol, &" << name;
+      break;
+    case t_base_type::TYPE_I8:
+      out << "byte (protocol, &" << name;
+      break;
+    case t_base_type::TYPE_I16:
+      out << "i16 (protocol, &" << name;
+      break;
+    case t_base_type::TYPE_I32:
+      out << "i32 (protocol, &" << name;
+      break;
+    case t_base_type::TYPE_I64:
+      out << "i64 (protocol, &" << name;
+      break;
+    case t_base_type::TYPE_DOUBLE:
+      out << "double (protocol, &" << name;
+      break;
+    default:
+      throw "compiler error: no C reader for base type " + t_base_type::t_base_name(tbase) + name;
+    }
+    out << ", error)) < 0)" << endl;
+    out << indent() << "  return " << error_ret << ";" << endl << indent() << "xfer += ret;"
+        << endl;
+
+    // load the byte array with the data
+    if (tbase == t_base_type::TYPE_STRING && type->is_binary()) {
+      indent(out) << name << " = g_byte_array_new();" << endl;
+      indent(out) << "g_byte_array_append (" << name << ", (guint8 *) data, (guint) len);" << endl;
+      indent(out) << "g_free (data);" << endl;
+    }
+  } else if (type->is_enum()) {
+    string t = tmp("ecast");
+    out << indent() << "gint32 " << t << ";" << endl << indent()
+        << "if ((ret = thrift_protocol_read_i32 (protocol, &" << t << ", error)) < 0)" << endl
+        << indent() << "  return " << error_ret << ";" << endl << indent() << "xfer += ret;" << endl
+        << indent() << name << " = (" << type_name(type) << ")" << t << ";" << endl;
+  } else {
+    throw std::logic_error("DO NOT KNOW HOW TO SERIALIZE FIELD '" + tfield->get_name() + "' TYPE '"
+                           + type_name(type));
+  }
+
+  // if the type is not required and this is a thrift struct (no prefix),
+  // set the isset variable.  if the type is required, then set the
+  // local variable indicating the value was set, so that we can do    // validation later.
+  if (prefix != "" && tfield->get_req() != t_field::T_REQUIRED) {
+    indent(out) << prefix << "__isset_" << tfield->get_name() << suffix << " = TRUE;" << endl;
+  } else if (prefix != "" && tfield->get_req() == t_field::T_REQUIRED) {
+    indent(out) << "isset_" << tfield->get_name() << " = TRUE;" << endl;
+  }
+}
+
+void t_c_glib_generator::generate_deserialize_struct(ostream& out,
+                                                     t_struct* tstruct,
+                                                     string prefix,
+                                                     int error_ret,
+                                                     bool allocate) {
+  string name_uc = to_upper_case(initial_caps_to_underscores(tstruct->get_name()));
+  if (tstruct->is_xception()) {
+    out << indent() << "/* This struct is an exception */" << endl;
+    allocate = true;
+  }
+
+  if (allocate) {
+    out << indent() << "if ( " << prefix << " != NULL)" << endl << indent() << "{" << endl;
+    indent_up();
+    out << indent() << "g_object_unref (" << prefix << ");" << endl;
+    indent_down();
+    out << indent() << "}" << endl << indent() << prefix << " = g_object_new (" << this->nspace_uc
+        << "TYPE_" << name_uc << ", NULL);" << endl;
+  }
+  out << indent() << "if ((ret = thrift_struct_read (THRIFT_STRUCT (" << prefix
+      << "), protocol, error)) < 0)" << endl << indent() << "{" << endl;
+  indent_up();
+  if (allocate) {
+    indent(out) << "g_object_unref (" << prefix << ");" << endl;
+    if (tstruct->is_xception()) {
+      indent(out) << prefix << " = NULL;" << endl;
+    }
+  }
+  out << indent() << "return " << error_ret << ";" << endl;
+  indent_down();
+  out << indent() << "}" << endl << indent() << "xfer += ret;" << endl;
+}
+
+void t_c_glib_generator::generate_deserialize_container(ostream& out,
+                                                        t_type* ttype,
+                                                        string prefix,
+                                                        int error_ret) {
+  scope_up(out);
+
+  if (ttype->is_map()) {
+    out << indent() << "guint32 size;" << endl
+        << indent() << "guint32 i;" << endl
+        << indent() << "ThriftType key_type;" << endl
+        << indent() << "ThriftType value_type;" << endl
+        << endl
+        << indent() << "/* read the map begin marker */" << endl
+        << indent() << "if ((ret = thrift_protocol_read_map_begin (protocol, "
+           "&key_type, &value_type, &size, error)) < 0)" << endl;
+    indent_up();
+    out << indent() << "return " << error_ret << ";" << endl;
+    indent_down();
+    out << indent() << "xfer += ret;" << endl
+        << endl;
+
+    // iterate over map elements
+    out << indent() << "/* iterate through each of the map's fields */" << endl
+        << indent() << "for (i = 0; i < size; i++)" << endl;
+    scope_up(out);
+    generate_deserialize_map_element(out, (t_map*)ttype, prefix, error_ret);
+    scope_down(out);
+    out << endl;
+
+    // read map end
+    out << indent() << "/* read the map end marker */" << endl
+        << indent() << "if ((ret = thrift_protocol_read_map_end (protocol, "
+           "error)) < 0)" << endl;
+    indent_up();
+    out << indent() << "return " << error_ret << ";" << endl;
+    indent_down();
+    out << indent() << "xfer += ret;" << endl;
+  } else if (ttype->is_set()) {
+    out << indent() << "guint32 size;" << endl
+        << indent() << "guint32 i;" << endl
+        << indent() << "ThriftType element_type;" << endl
+        << endl
+        << indent() << "if ((ret = thrift_protocol_read_set_begin (protocol, "
+           "&element_type, &size, error)) < 0)" << endl;
+    indent_up();
+    out << indent() << "return " << error_ret << ";" << endl;
+    indent_down();
+    out << indent() << "xfer += ret;" << endl
+        << endl;
+
+    // iterate over the elements
+    out << indent() << "/* iterate through the set elements */" << endl
+        << indent() << "for (i = 0; i < size; ++i)" << endl;
+    scope_up(out);
+    generate_deserialize_set_element(out, (t_set*)ttype, prefix, error_ret);
+    scope_down(out);
+
+    // read set end
+    out << indent() << "if ((ret = thrift_protocol_read_set_end (protocol, "
+           "error)) < 0)" << endl;
+    indent_up();
+    out << indent() << "return " << error_ret << ";" << endl;
+    indent_down();
+    out << indent() << "xfer += ret;" << endl
+        << endl;
+  } else if (ttype->is_list()) {
+    out << indent() << "guint32 size;" << endl
+        << indent() << "guint32 i;" << endl
+        << indent() << "ThriftType element_type;" << endl
+        << endl
+        << indent() << "if ((ret = thrift_protocol_read_list_begin (protocol, "
+           "&element_type,&size, error)) < 0)" << endl;
+    indent_up();
+    out << indent() << "return " << error_ret << ";" << endl;
+    indent_down();
+    out << indent() << "xfer += ret;" << endl
+        << endl;
+
+    // iterate over the elements
+    out << indent() << "/* iterate through list elements */" << endl
+        << indent() << "for (i = 0; i < size; i++)" << endl;
+    scope_up(out);
+    generate_deserialize_list_element(out,
+                                      (t_list*)ttype,
+                                      prefix,
+                                      "i",
+                                      error_ret);
+    scope_down(out);
+
+    // read list end
+    out << indent() << "if ((ret = thrift_protocol_read_list_end (protocol, "
+           "error)) < 0)" << endl;
+    indent_up();
+    out << indent() << "return " << error_ret << ";" << endl;
+    indent_down();
+    out << indent() << "xfer += ret;" << endl;
+  }
+
+  scope_down(out);
+}
+
+void t_c_glib_generator::declare_local_variable(ostream& out, t_type* ttype, string& name, bool for_hash_table) {
+  string tname = type_name(ttype);
+
+  /* If the given type is a typedef, find its underlying type so we
+     can correctly determine how to generate a pointer to it */
+  ttype = get_true_type(ttype);
+  string ptr = !is_numeric(ttype) ? "" : "*";
+
+  if (ttype->is_map()) {
+    t_map* tmap = (t_map*)ttype;
+    out << indent() << tname << ptr << " " << name << " = "
+        << generate_new_hash_from_type(tmap->get_key_type(), tmap->get_val_type()) << endl;
+  } else if (ttype->is_list()) {
+    t_list* tlist = (t_list*)ttype;
+    out << indent() << tname << ptr << " " << name << " = "
+        << generate_new_array_from_type(tlist->get_elem_type()) << endl;
+  } else if (for_hash_table && ttype->is_enum()) {
+    out << indent() << tname << " " << name << ";" << endl;
+  } else {
+    out << indent() << tname << ptr << " " << name
+        << (ptr != "" ? " = g_new (" + tname + ", 1)" : " = NULL") << ";" << endl;
+  }
+}
+
+void t_c_glib_generator::declore_local_variable_for_write(ostream& out,
+                                                          t_type* ttype,
+                                                          string& name) {
+  string tname = type_name(ttype);
+  ttype = get_true_type(ttype);
+  string ptr = ttype->is_string() || !ttype->is_base_type() ? " " : "* ";
+  string init_val = ttype->is_enum() ? "" : " = NULL";
+  out << indent() << tname << ptr << name << init_val << ";" << endl;
+}
+
+void t_c_glib_generator::generate_deserialize_map_element(ostream& out,
+                                                          t_map* tmap,
+                                                          string prefix,
+                                                          int error_ret) {
+  t_type* tkey = tmap->get_key_type();
+  t_type* tval = tmap->get_val_type();
+  string keyname = tmp("key");
+  string valname = tmp("val");
+
+  declare_local_variable(out, tkey, keyname, true);
+  declare_local_variable(out, tval, valname, true);
+
+  /* If either the key or value type is a typedef, find its underlying
+     type so we can correctly determine how to generate a pointer to
+     it */
+  tkey = get_true_type(tkey);
+  tval = get_true_type(tval);
+
+  string tkey_ptr = tkey->is_string() || !tkey->is_base_type() ? "" : "*";
+  string tval_ptr = tval->is_string() || !tval->is_base_type() ? "" : "*";
+
+  // deserialize the fields of the map element
+  t_field fkey(tkey, tkey_ptr + keyname);
+  generate_deserialize_field(out, &fkey, "", "", error_ret);
+  t_field fval(tval, tval_ptr + valname);
+  generate_deserialize_field(out, &fval, "", "", error_ret);
+
+  indent(out) << "if (" << prefix << " && " << keyname << ")" << endl;
+  indent_up();
+  indent(out) << "g_hash_table_insert ((GHashTable *)" << prefix << ", (gpointer) " << keyname
+              << ", (gpointer) " << valname << ");" << endl;
+  indent_down();
+}
+
+void t_c_glib_generator::generate_deserialize_set_element(ostream& out,
+                                                          t_set* tset,
+                                                          string prefix,
+                                                          int error_ret) {
+  t_type* telem = tset->get_elem_type();
+  string elem = tmp("_elem");
+  string telem_ptr = telem->is_string() || !telem->is_base_type() ? "" : "*";
+
+  declare_local_variable(out, telem, elem, true);
+
+  t_field felem(telem, telem_ptr + elem);
+  generate_deserialize_field(out, &felem, "", "", error_ret);
+
+  indent(out) << "if (" << prefix << " && " << elem << ")" << endl;
+  indent_up();
+  indent(out) << "g_hash_table_insert ((GHashTable *) " << prefix << ", (gpointer) " << elem
+              << ", (gpointer) " << elem << ");" << endl;
+  indent_down();
+}
+
+void t_c_glib_generator::generate_deserialize_list_element(ostream& out,
+                                                           t_list* tlist,
+                                                           string prefix,
+                                                           string index,
+                                                           int error_ret) {
+  (void)index;
+  t_type* ttype = get_true_type(tlist->get_elem_type());
+  string elem = tmp("_elem");
+  string telem_ptr = !is_numeric(ttype) ? "" : "*";
+
+  declare_local_variable(out, ttype, elem, false);
+
+  t_field felem(ttype, telem_ptr + elem);
+  generate_deserialize_field(out, &felem, "", "", error_ret);
+
+  if (ttype->is_void()) {
+    throw std::runtime_error("compiler error: list element type cannot be void");
+  } else if (is_numeric(ttype)) {
+    indent(out) << "g_array_append_vals (" << prefix << ", " << elem << ", 1);" << endl;
+  } else {
+    indent(out) << "g_ptr_array_add (" << prefix << ", " << elem << ");" << endl;
+  }
+}
+
+string t_c_glib_generator::generate_free_func_from_type(t_type* ttype) {
+  if (ttype == NULL)
+    return "NULL";
+
+  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 "compiler error: cannot determine hash type";
+      break;
+    case t_base_type::TYPE_BOOL:
+    case t_base_type::TYPE_I8:
+    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 "g_free";
+    case t_base_type::TYPE_STRING:
+      if (((t_base_type*)ttype)->is_binary()) {
+        return "thrift_string_free";
+      }
+      return "g_free";
+    default:
+      throw "compiler error: no hash table info for type";
+    }
+  } else if (ttype->is_enum()) {
+    return "NULL";
+  } else if (ttype->is_map() || ttype->is_set()) {
+    return "(GDestroyNotify) thrift_safe_hash_table_destroy";
+  } else if (ttype->is_struct()) {
+    return "g_object_unref";
+  } else if (ttype->is_list()) {
+    t_type* etype = ((t_list*)ttype)->get_elem_type();
+    if (etype->is_base_type()) {
+      t_base_type::t_base tbase = ((t_base_type*)etype)->get_base();
+      switch (tbase) {
+      case t_base_type::TYPE_VOID:
+        throw "compiler error: cannot determine array type";
+        break;
+      case t_base_type::TYPE_BOOL:
+      case t_base_type::TYPE_I8:
+      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 "(GDestroyNotify) g_array_unref";
+      case t_base_type::TYPE_STRING:
+        return "(GDestroyNotify) g_ptr_array_unref";
+      default:
+        throw "compiler error: no array info for type";
+      }
+    } else if (etype->is_container() || etype->is_struct()) {
+      return "(GDestroyNotify) g_ptr_array_unref";
+      ;
+    } else if (etype->is_enum()) {
+      return "(GDestroyNotify) g_array_unref";
+    }
+    printf("Type not expected inside the array: %s\n", etype->get_name().c_str());
+    throw "Type not expected inside array";
+  } else if (ttype->is_typedef()) {
+    return generate_free_func_from_type(((t_typedef*)ttype)->get_type());
+  }
+  printf("Type not expected: %s\n", ttype->get_name().c_str());
+  throw "Type not expected";
+}
+
+string t_c_glib_generator::generate_hash_func_from_type(t_type* ttype) {
+  if (ttype == NULL)
+    return "NULL";
+
+  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 "compiler error: cannot determine hash type";
+      break;
+    case t_base_type::TYPE_BOOL:
+      return "thrift_boolean_hash";
+    case t_base_type::TYPE_I8:
+      return "thrift_int8_hash";
+    case t_base_type::TYPE_I16:
+      return "thrift_int16_hash";
+    case t_base_type::TYPE_I32:
+      return "g_int_hash";
+    case t_base_type::TYPE_I64:
+      return "g_int64_hash";
+    case t_base_type::TYPE_DOUBLE:
+      return "g_double_hash";
+    case t_base_type::TYPE_STRING:
+      return "g_str_hash";
+    default:
+      throw "compiler error: no hash table info for type";
+    }
+  } else if (ttype->is_enum()) {
+    return "g_direct_hash";
+  } else if (ttype->is_container() || ttype->is_struct()) {
+    return "g_direct_hash";
+  } else if (ttype->is_typedef()) {
+    return generate_hash_func_from_type(((t_typedef*)ttype)->get_type());
+  }
+  printf("Type not expected: %s\n", ttype->get_name().c_str());
+  throw "Type not expected";
+}
+
+string t_c_glib_generator::generate_cmp_func_from_type(t_type* ttype) {
+  if (ttype == NULL)
+    return "NULL";
+
+  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 "compiler error: cannot determine hash type";
+      break;
+    case t_base_type::TYPE_BOOL:
+      return "thrift_boolean_equal";
+    case t_base_type::TYPE_I8:
+      return "thrift_int8_equal";
+    case t_base_type::TYPE_I16:
+      return "thrift_int16_equal";
+    case t_base_type::TYPE_I32:
+      return "g_int_equal";
+    case t_base_type::TYPE_I64:
+      return "g_int64_equal";
+    case t_base_type::TYPE_DOUBLE:
+      return "g_double_equal";
+    case t_base_type::TYPE_STRING:
+      return "g_str_equal";
+    default:
+      throw "compiler error: no hash table info for type";
+    }
+  } else if (ttype->is_enum()) {
+    return "g_direct_equal";
+  } else if (ttype->is_container() || ttype->is_struct()) {
+    return "g_direct_equal";
+  } else if (ttype->is_typedef()) {
+    return generate_cmp_func_from_type(((t_typedef*)ttype)->get_type());
+  }
+  printf("Type not expected: %s\n", ttype->get_name().c_str());
+  throw "Type not expected";
+}
+
+string t_c_glib_generator::generate_new_hash_from_type(t_type* key, t_type* value) {
+  string hash_func = generate_hash_func_from_type(key);
+  string cmp_func = generate_cmp_func_from_type(key);
+  string key_free_func = generate_free_func_from_type(key);
+  string value_free_func = generate_free_func_from_type(value);
+
+  return "g_hash_table_new_full (" + hash_func + ", " + cmp_func + ", " + key_free_func + ", "
+         + value_free_func + ");";
+}
+
+string t_c_glib_generator::generate_new_array_from_type(t_type* ttype) {
+  if (ttype->is_void()) {
+    throw std::runtime_error("compiler error: cannot determine array type");
+  } else if (is_numeric(ttype)) {
+    return "g_array_new (0, 1, sizeof (" + base_type_name(ttype) + "));";
+  } else {
+    string free_func = generate_free_func_from_type(ttype);
+    return "g_ptr_array_new_with_free_func (" + free_func + ");";
+  }
+}
+
+/***************************************
+ * UTILITY FUNCTIONS                   *
+ ***************************************/
+
+/**
+ * Upper case a string.  Wraps boost's string utility.
+ */
+string to_upper_case(string name) {
+  string s(name);
+  std::transform(s.begin(), s.end(), s.begin(), ::toupper);
+  return s;
+  //  return boost::to_upper_copy (name);
+}
+
+/**
+ * Lower case a string.  Wraps boost's string utility.
+ */
+string to_lower_case(string name) {
+  string s(name);
+  std::transform(s.begin(), s.end(), s.begin(), ::tolower);
+  return s;
+  //  return boost::to_lower_copy (name);
+}
+
+/**
+ * Makes a string friendly to C code standards by lowercasing and adding
+ * underscores, with the exception of the first character.  For example:
+ *
+ * Input: "ZomgCamelCase"
+ * Output: "zomg_camel_case"
+ */
+string initial_caps_to_underscores(string name) {
+  string ret;
+  const char* tmp = name.c_str();
+  int pos = 0;
+
+  /* the first character isn't underscored if uppercase, just lowercased */
+  ret += tolower(tmp[pos]);
+  pos++;
+  for (unsigned int i = pos; i < name.length(); i++) {
+    char lc = tolower(tmp[i]);
+    if (lc != tmp[i]) {
+      ret += '_';
+    }
+    ret += lc;
+  }
+
+  return ret;
+}
+
+/**
+ * Performs the reverse operation of initial_caps_to_underscores: The first
+ * character of the string is made uppercase, along with each character that
+ * follows an underscore (which is removed). Useful for converting Thrift
+ * service-method names into GObject-style class names.
+ *
+ * Input: "zomg_camel_case"
+ * Output: "ZomgCamelCase"
+ */
+string underscores_to_initial_caps(string name) {
+  string ret;
+  const char* tmp = name.c_str();
+  bool uppercase_next = true;
+
+  for (unsigned int i = 0; i < name.length(); i++) {
+    char c = tmp[i];
+    if (c == '_') {
+      uppercase_next = true;
+    } else {
+      if (uppercase_next) {
+        ret += toupper(c);
+        uppercase_next = false;
+      } else {
+        ret += c;
+      }
+    }
+  }
+
+  return ret;
+}
+
+/* register this generator with the main program */
+THRIFT_REGISTER_GENERATOR(c_glib, "C, using GLib", "")

+ 558 - 558
contrib/restricted/thrift/compiler/thrift/generate/t_cl_generator.cc

@@ -1,558 +1,558 @@
-/* 
- * Copyright (c) 2008- Patrick Collison <patrick@collison.ie> 
- * Copyright (c) 2006- Facebook 
- * 
- * Licensed to the Apache Software Foundation (ASF) under one 
- * or more contributor license agreements. See the NOTICE file 
- * distributed with this work for additional information 
- * regarding copyright ownership. The ASF licenses this file 
- * to you under the Apache License, Version 2.0 (the 
- * "License"); you may not use this file except in compliance 
- * with the License. You may obtain a copy of the License at 
- * 
- *   http://www.apache.org/licenses/LICENSE-2.0 
- * 
- * Unless required by applicable law or agreed to in writing, 
- * software distributed under the License is distributed on an 
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 
- * KIND, either express or implied. See the License for the 
- * specific language governing permissions and limitations 
- * under the License. 
- */ 
- 
-#include <string> 
-#include <fstream> 
-#include <iostream> 
-#include <vector> 
- 
-#include <stdlib.h> 
-#include <boost/tokenizer.hpp> 
-#include <sys/stat.h> 
-#include <sys/types.h> 
-#include <sstream> 
-#include <string> 
-#include <algorithm> 
- 
-#include "thrift/platform.h" 
-#include "t_oop_generator.h" 
-using namespace std; 
- 
- 
-/** 
- * Common Lisp code generator. 
- * 
- * @author Patrick Collison <patrick@collison.ie> 
- */ 
-class t_cl_generator : public t_oop_generator { 
- public: 
-  t_cl_generator( 
-      t_program* program, 
-      const std::map<std::string, std::string>& parsed_options, 
-      const std::string& option_string) 
-    : t_oop_generator(program) 
-  { 
-    no_asd = false; 
-    system_prefix = "thrift-gen-"; 
- 
-    std::map<std::string, std::string>::const_iterator iter; 
- 
-    for(iter = parsed_options.begin(); iter != parsed_options.end(); ++iter) { 
-      if(iter->first.compare("no_asd") == 0) { 
-        no_asd = true; 
-      } else if (iter->first.compare("sys_pref") == 0) { 
-	system_prefix = iter->second; 
-      } else { 
-        throw "unknown option cl:" + iter->first; 
-      } 
-    } 
- 
-    out_dir_base_ = "gen-cl"; 
-    copy_options_ = option_string; 
-  } 
- 
-  void init_generator(); 
-  void close_generator(); 
- 
-  void generate_typedef     (t_typedef*  ttypedef); 
-  void generate_enum        (t_enum*     tenum); 
-  void generate_const       (t_const*    tconst); 
-  void generate_struct      (t_struct*   tstruct); 
-  void generate_xception    (t_struct*   txception); 
-  void generate_service     (t_service*  tservice); 
-  void generate_cl_struct (std::ostream& out, t_struct* tstruct, bool is_exception); 
-  void generate_cl_struct_internal (std::ostream& out, t_struct* tstruct, bool is_exception); 
-  void generate_exception_sig(std::ostream& out, t_function* f); 
-  std::string render_const_value(t_type* type, t_const_value* value); 
- 
-  std::string cl_autogen_comment(); 
-  void asdf_def(std::ostream &out); 
-  void package_def(std::ostream &out); 
-  void package_in(std::ostream &out); 
-  std::string generated_package(); 
-  std::string prefix(std::string name); 
-  std::string package_of(t_program* program); 
-  std::string package(); 
-  std::string render_includes(); 
- 
-  std::string type_name(t_type* ttype); 
-  std::string typespec (t_type *t); 
-  std::string function_signature(t_function* tfunction); 
-  std::string argument_list(t_struct* tstruct); 
- 
-  std::string cl_docstring(std::string raw); 
- 
- private: 
- 
-  int temporary_var; 
-  /** 
-   * Isolate the variable definitions, as they can require structure definitions 
-   */ 
-  ofstream_with_content_based_conditional_update f_asd_; 
-  ofstream_with_content_based_conditional_update f_types_; 
-  ofstream_with_content_based_conditional_update f_vars_; 
- 
-  std::string copy_options_; 
- 
-  bool no_asd; 
-  std::string system_prefix; 
-}; 
- 
- 
-void t_cl_generator::init_generator() { 
-  MKDIR(get_out_dir().c_str()); 
-  string program_dir = get_out_dir() + "/" + program_name_; 
-  MKDIR(program_dir.c_str()); 
- 
-  temporary_var = 0; 
- 
-  string f_types_name = program_dir + "/" + program_name_ + "-types.lisp"; 
-  string f_vars_name = program_dir + "/" + program_name_ + "-vars.lisp"; 
- 
-  f_types_.open(f_types_name.c_str()); 
-  f_types_ << cl_autogen_comment() << endl; 
-  f_vars_.open(f_vars_name.c_str()); 
-  f_vars_ << cl_autogen_comment() << endl; 
- 
-  package_def(f_types_); 
-  package_in(f_types_); 
-  package_in(f_vars_); 
- 
-  if (!no_asd) { 
-    string f_asd_name = program_dir + "/" + system_prefix + program_name_ + ".asd"; 
-    f_asd_.open(f_asd_name.c_str()); 
-    f_asd_ << cl_autogen_comment() << endl; 
-    asdf_def(f_asd_); 
-  } 
-} 
- 
-/** 
- * Renders all the imports necessary for including another Thrift program 
- */ 
-string t_cl_generator::render_includes() { 
-  const vector<t_program*>& includes = program_->get_includes(); 
-  string result = ""; 
-  result += ":depends-on (:thrift"; 
-  for (size_t i = 0; i < includes.size(); ++i) { 
-    result += " :" + system_prefix + underscore(includes[i]->get_name()); 
-  } 
-  result += ")\n"; 
-  return result; 
-} 
- 
-string t_cl_generator::package_of(t_program* program) { 
-  string prefix = program->get_namespace("cl"); 
-  return prefix.empty() ? "thrift-generated" : prefix; 
-} 
- 
-string t_cl_generator::package() { 
-  return package_of(program_); 
-} 
- 
-string t_cl_generator::prefix(string symbol) { 
-  return "\"" + symbol + "\""; 
-} 
- 
-string t_cl_generator::cl_autogen_comment() { 
-  return 
-    std::string(";;; ") + "Autogenerated by Thrift\n" + 
-    ";;; DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING\n" + 
-    ";;; options string: " + copy_options_ + "\n"; 
-} 
- 
-string t_cl_generator::cl_docstring(string raw) { 
-  replace(raw.begin(), raw.end(), '"', '\''); 
-  return raw; 
-} 
- 
- 
-void t_cl_generator::close_generator() { 
-  f_asd_.close(); 
-  f_types_.close(); 
-  f_vars_.close(); 
-} 
- 
-string t_cl_generator::generated_package() { 
-  return program_->get_namespace("cpp"); 
-} 
- 
-void t_cl_generator::asdf_def(std::ostream &out) { 
-  out << "(asdf:defsystem #:" << system_prefix << program_name_ << endl; 
-  indent_up(); 
-  out << indent() << render_includes() 
-      << indent() << ":serial t" << endl 
-      << indent() << ":components (" 
-      << "(:file \"" << program_name_ << "-types\") " 
-      << "(:file \"" << program_name_ << "-vars\")))" << endl; 
-  indent_down(); 
-} 
- 
-/*** 
- * Generate a package definition. Add use references equivalent to the idl file's include statements. 
- */ 
-void t_cl_generator::package_def(std::ostream &out) { 
-  const vector<t_program*>& includes = program_->get_includes(); 
- 
-  out << "(thrift:def-package :" << package(); 
-  if ( includes.size() > 0 ) { 
-    out << " :use ("; 
-    for (size_t i = 0; i < includes.size(); ++i) { 
-      out << " :" << includes[i]->get_name(); 
-    } 
-    out << ")"; 
-  } 
-  out << ")" << endl << endl; 
-} 
- 
-void t_cl_generator::package_in(std::ostream &out) { 
-  out << "(cl:in-package :" << package() << ")" << endl << endl; 
-} 
- 
-/** 
- * Generates a typedef. This is not done in Common Lisp, types are all implicit. 
- * 
- * @param ttypedef The type definition 
- */ 
-void t_cl_generator::generate_typedef(t_typedef* ttypedef) { 
-  (void)ttypedef; 
-} 
- 
-void t_cl_generator::generate_enum(t_enum* tenum) { 
-  f_types_ << "(thrift:def-enum " << prefix(tenum->get_name()) << endl; 
- 
-  vector<t_enum_value*> constants = tenum->get_constants(); 
-  vector<t_enum_value*>::iterator c_iter; 
-  int value = -1; 
- 
-  indent_up(); 
-  f_types_ << indent() << "("; 
-  for (c_iter = constants.begin(); c_iter != constants.end(); ++c_iter) { 
-    value = (*c_iter)->get_value(); 
- 
-    if(c_iter != constants.begin()) f_types_ << endl << indent() << " "; 
- 
-    f_types_ << "(\"" << (*c_iter)->get_name() << "\" . " << value << ")"; 
-  } 
-  indent_down(); 
-  f_types_ << "))" << endl << endl; 
-} 
- 
-/** 
- * Generate a constant value 
- */ 
-void t_cl_generator::generate_const(t_const* tconst) { 
-  t_type* type = tconst->get_type(); 
-  string name = tconst->get_name(); 
-  t_const_value* value = tconst->get_value(); 
- 
-  f_vars_ << "(thrift:def-constant " << prefix(name) << " " << render_const_value(type, value) << ")" 
-          << endl << endl; 
-} 
- 
-/** 
- * Prints the value of a constant with the given type. Note that type checking 
- * is NOT performed in this function as it is always run beforehand using the 
- * validate_types method in main.cc 
- */ 
-string t_cl_generator::render_const_value(t_type* type, t_const_value* value) { 
-  type = get_true_type(type); 
-  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: 
-      out << "\"" << value->get_string() << "\""; 
-      break; 
-    case t_base_type::TYPE_BOOL: 
-      out << (value->get_integer() > 0 ? "t" : "nil"); 
-      break; 
-    case t_base_type::TYPE_I8: 
-    case t_base_type::TYPE_I16: 
-    case t_base_type::TYPE_I32: 
-    case t_base_type::TYPE_I64: 
-      out << value->get_integer(); 
-      break; 
-    case t_base_type::TYPE_DOUBLE: 
-      if (value->get_type() == t_const_value::CV_INTEGER) { 
-        out << value->get_integer(); 
-      } else { 
-        out << value->get_double(); 
-      } 
-      break; 
-    default: 
-      throw "compiler error: no const of base type " + t_base_type::t_base_name(tbase); 
-    } 
-  } else if (type->is_enum()) { 
-    indent(out) << value->get_integer(); 
-  } else if (type->is_struct() || type->is_xception()) { 
-    out << (type->is_struct() ? "(make-instance '" : "(make-exception '") << 
-           lowercase(type->get_name()) << " " << endl; 
-    indent_up(); 
- 
-    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*, t_const_value::value_compare>& val = value->get_map(); 
-    map<t_const_value*, t_const_value*, t_const_value::value_compare>::const_iterator v_iter; 
- 
-    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) { 
-        if ((*f_iter)->get_name() == v_iter->first->get_string()) { 
-          field_type = (*f_iter)->get_type(); 
-        } 
-      } 
-      if (field_type == NULL) { 
-        throw "type error: " + type->get_name() + " has no field " + v_iter->first->get_string(); 
-      } 
- 
-      out << indent() << ":" << v_iter->first->get_string() << " " << 
-        render_const_value(field_type, v_iter->second) << endl; 
-    } 
-    out << indent() << ")"; 
- 
-    indent_down(); 
-  } else if (type->is_map()) { 
-    // emit an hash form with both keys and values to be evaluated 
-    t_type* ktype = ((t_map*)type)->get_key_type(); 
-    t_type* vtype = ((t_map*)type)->get_val_type(); 
-    out << "(thrift:map "; 
-    indent_up(); 
-    const map<t_const_value*, t_const_value*, t_const_value::value_compare>& val = value->get_map(); 
-    map<t_const_value*, t_const_value*, t_const_value::value_compare>::const_iterator v_iter; 
-    for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) { 
-      out << endl << indent() 
-          << "(cl:cons " << render_const_value(ktype, v_iter->first) << " " 
-          << render_const_value(vtype, v_iter->second) << ")"; 
-    } 
-    indent_down(); 
-    out << indent() << ")"; 
-  } else if (type->is_list() || type->is_set()) { 
-    t_type* etype; 
-    if (type->is_list()) { 
-      etype = ((t_list*)type)->get_elem_type(); 
-    } else { 
-      etype = ((t_set*)type)->get_elem_type(); 
-    } 
-    if (type->is_set()) { 
-      out << "(thrift:set" << endl; 
-    } else { 
-      out << "(thrift:list" << endl; 
-    } 
-    indent_up(); 
-    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) { 
-      out << indent() << render_const_value(etype, *v_iter) << endl; 
-    } 
-    out << indent() << ")"; 
-    indent_down(); 
-    indent_down(); 
-  } else { 
-    throw "CANNOT GENERATE CONSTANT FOR TYPE: " + type->get_name(); 
-  } 
-  return out.str(); 
-} 
- 
-void t_cl_generator::generate_struct(t_struct* tstruct) { 
-  generate_cl_struct(f_types_, tstruct, false); 
-} 
- 
-void t_cl_generator::generate_xception(t_struct* txception) { 
-  generate_cl_struct(f_types_, txception, true); 
-} 
- 
-void t_cl_generator::generate_cl_struct_internal(std::ostream& out, t_struct* tstruct, bool is_exception) { 
-  (void)is_exception; 
-  const vector<t_field*>& members = tstruct->get_members(); 
-  vector<t_field*>::const_iterator m_iter; 
- 
-  out << "("; 
- 
-  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { 
-    t_const_value* value = (*m_iter)->get_value(); 
-    t_type* type = (*m_iter)->get_type(); 
- 
-    if (m_iter != members.begin()) { 
-      out << endl << indent() << " "; 
-    } 
-    out << "(" << prefix((*m_iter)->get_name()) << " " << 
-        ( (NULL != value) ? render_const_value(type, value) : "nil" ) << 
-        " :id " << (*m_iter)->get_key(); 
-    if ( type->is_base_type() && "string" == typespec(type) ) 
-      if ( ((t_base_type*)type)->is_binary() ) 
-        out << " :type binary"; 
-      else 
-        out << " :type string"; 
-    else 
-      out << " :type " << typespec(type); 
-    if ( (*m_iter)->get_req() == t_field::T_OPTIONAL ) { 
-      out << " :optional t"; 
-    } 
-    if ( (*m_iter)->has_doc()) { 
-      out << " :documentation \"" << cl_docstring((*m_iter)->get_doc()) << "\""; 
-    } 
-    out <<")"; 
-  } 
- 
-  out << ")"; 
-} 
- 
-void t_cl_generator::generate_cl_struct(std::ostream& out, t_struct* tstruct, bool is_exception = false) { 
-  std::string name = type_name(tstruct); 
-  out << (is_exception ? "(thrift:def-exception " : "(thrift:def-struct ") << 
-      prefix(name) << endl; 
-  indent_up(); 
-  if ( tstruct->has_doc() ) { 
-    out << indent() ; 
-    out << "\"" << cl_docstring(tstruct->get_doc()) << "\"" << endl; 
-  } 
-  out << indent() ; 
-  generate_cl_struct_internal(out, tstruct, is_exception); 
-  indent_down(); 
-  out << ")" << endl << endl; 
-} 
- 
-void t_cl_generator::generate_exception_sig(std::ostream& out, t_function* f) { 
-  generate_cl_struct_internal(out, f->get_xceptions(), true); 
-} 
- 
-void t_cl_generator::generate_service(t_service* tservice) { 
-  string extends_client; 
-  vector<t_function*> functions = tservice->get_functions(); 
-  vector<t_function*>::iterator f_iter; 
- 
-  if (tservice->get_extends() != NULL) { 
-    extends_client = type_name(tservice->get_extends()); 
-  } 
- 
-  extends_client = extends_client.empty() ? "nil" : prefix(extends_client); 
- 
-  f_types_ << "(thrift:def-service " << prefix(service_name_) << " " 
-           << extends_client; 
- 
-  indent_up(); 
- 
-  if ( tservice->has_doc()) { 
-      f_types_ << endl << indent() 
-               << "(:documentation \"" << cl_docstring(tservice->get_doc()) << "\")"; 
-    } 
- 
-  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) { 
-    t_function* function = *f_iter; 
-    string fname = function->get_name(); 
-    string signature = function_signature(function); 
-    t_struct* exceptions = function->get_xceptions(); 
-    const vector<t_field*>& xmembers = exceptions->get_members(); 
- 
-    f_types_ << endl << indent() << "(:method " << prefix(fname); 
-    f_types_ << " (" << signature << " "  << typespec((*f_iter)->get_returntype()) << ")"; 
-    if (xmembers.size() > 0) { 
-      f_types_ << endl << indent() << " :exceptions " ; 
-      generate_exception_sig(f_types_, function); 
-    } 
-    if ( (*f_iter)->is_oneway() ) { 
-      f_types_ << endl << indent() << " :oneway t"; 
-    } 
-    if ( (*f_iter)->has_doc() ) { 
-      f_types_ << endl << indent() << " :documentation \"" 
-               << cl_docstring((*f_iter)->get_doc()) << "\""; 
-  } 
-    f_types_ << ")"; 
-  } 
- 
-  f_types_ << ")" << endl << endl; 
- 
-  indent_down(); 
-} 
- 
-string t_cl_generator::typespec(t_type *t) { 
-  t = get_true_type(t); 
- 
-  if (t -> is_binary()){ 
-    return "binary"; 
-  } else if (t->is_base_type()) { 
-    return type_name(t); 
-  } else if (t->is_map()) { 
-    t_map *m = (t_map*) t; 
-    return "(thrift:map " + typespec(m->get_key_type()) + " " + 
-      typespec(m->get_val_type()) + ")"; 
-  } else if (t->is_struct() || t->is_xception()) { 
-    return "(struct " + prefix(type_name(t)) + ")"; 
-  } else if (t->is_list()) { 
-    return "(thrift:list " + typespec(((t_list*) t)->get_elem_type()) + ")"; 
-  } else if (t->is_set()) { 
-    return "(thrift:set " + typespec(((t_set*) t)->get_elem_type()) + ")"; 
-  } else if (t->is_enum()) { 
-    return "(enum \"" + ((t_enum*) t)->get_name() + "\")"; 
-  } else { 
-    throw "Sorry, I don't know how to generate this: " + type_name(t); 
-  } 
-} 
- 
-string t_cl_generator::function_signature(t_function* tfunction) { 
-  return argument_list(tfunction->get_arglist()); 
-} 
- 
-string t_cl_generator::argument_list(t_struct* tstruct) { 
-  stringstream res; 
-  res << "("; 
- 
-  const vector<t_field*>& fields = tstruct->get_members(); 
-  vector<t_field*>::const_iterator f_iter; 
-  bool first = true; 
-  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { 
-    if (first) { 
-      first = false; 
-    } else { 
-      res << " "; 
-    } 
-    res << "(" + prefix((*f_iter)->get_name()) << " " << 
-      typespec((*f_iter)->get_type()) << " " << 
-      (*f_iter)->get_key() <<  ")"; 
- 
- 
-  } 
-  res << ")"; 
-  return res.str(); 
-} 
- 
-string t_cl_generator::type_name(t_type* ttype) { 
-  string prefix = ""; 
-  t_program* program = ttype->get_program(); 
- 
-  if (program != NULL && program != program_) 
-    prefix = package_of(program) == package() ? "" : package_of(program) + ":"; 
- 
-  string name = ttype->get_name(); 
- 
-  if (ttype->is_struct() || ttype->is_xception()) 
-    name = lowercase(ttype->get_name()); 
- 
-  return prefix + name; 
-} 
- 
-THRIFT_REGISTER_GENERATOR( 
-    cl, 
-    "Common Lisp", 
-    "    no_asd:          Do not define ASDF systems for each generated Thrift program.\n" 
-    "    sys_pref=        The prefix to give ASDF system names. Default: thrift-gen-\n") 
+/*
+ * Copyright (c) 2008- Patrick Collison <patrick@collison.ie>
+ * Copyright (c) 2006- Facebook
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#include <string>
+#include <fstream>
+#include <iostream>
+#include <vector>
+
+#include <stdlib.h>
+#include <boost/tokenizer.hpp>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sstream>
+#include <string>
+#include <algorithm>
+
+#include "thrift/platform.h"
+#include "t_oop_generator.h"
+using namespace std;
+
+
+/**
+ * Common Lisp code generator.
+ *
+ * @author Patrick Collison <patrick@collison.ie>
+ */
+class t_cl_generator : public t_oop_generator {
+ public:
+  t_cl_generator(
+      t_program* program,
+      const std::map<std::string, std::string>& parsed_options,
+      const std::string& option_string)
+    : t_oop_generator(program)
+  {
+    no_asd = false;
+    system_prefix = "thrift-gen-";
+
+    std::map<std::string, std::string>::const_iterator iter;
+
+    for(iter = parsed_options.begin(); iter != parsed_options.end(); ++iter) {
+      if(iter->first.compare("no_asd") == 0) {
+        no_asd = true;
+      } else if (iter->first.compare("sys_pref") == 0) {
+	system_prefix = iter->second;
+      } else {
+        throw "unknown option cl:" + iter->first;
+      }
+    }
+
+    out_dir_base_ = "gen-cl";
+    copy_options_ = option_string;
+  }
+
+  void init_generator();
+  void close_generator();
+
+  void generate_typedef     (t_typedef*  ttypedef);
+  void generate_enum        (t_enum*     tenum);
+  void generate_const       (t_const*    tconst);
+  void generate_struct      (t_struct*   tstruct);
+  void generate_xception    (t_struct*   txception);
+  void generate_service     (t_service*  tservice);
+  void generate_cl_struct (std::ostream& out, t_struct* tstruct, bool is_exception);
+  void generate_cl_struct_internal (std::ostream& out, t_struct* tstruct, bool is_exception);
+  void generate_exception_sig(std::ostream& out, t_function* f);
+  std::string render_const_value(t_type* type, t_const_value* value);
+
+  std::string cl_autogen_comment();
+  void asdf_def(std::ostream &out);
+  void package_def(std::ostream &out);
+  void package_in(std::ostream &out);
+  std::string generated_package();
+  std::string prefix(std::string name);
+  std::string package_of(t_program* program);
+  std::string package();
+  std::string render_includes();
+
+  std::string type_name(t_type* ttype);
+  std::string typespec (t_type *t);
+  std::string function_signature(t_function* tfunction);
+  std::string argument_list(t_struct* tstruct);
+
+  std::string cl_docstring(std::string raw);
+
+ private:
+
+  int temporary_var;
+  /**
+   * Isolate the variable definitions, as they can require structure definitions
+   */
+  ofstream_with_content_based_conditional_update f_asd_;
+  ofstream_with_content_based_conditional_update f_types_;
+  ofstream_with_content_based_conditional_update f_vars_;
+
+  std::string copy_options_;
+
+  bool no_asd;
+  std::string system_prefix;
+};
+
+
+void t_cl_generator::init_generator() {
+  MKDIR(get_out_dir().c_str());
+  string program_dir = get_out_dir() + "/" + program_name_;
+  MKDIR(program_dir.c_str());
+
+  temporary_var = 0;
+
+  string f_types_name = program_dir + "/" + program_name_ + "-types.lisp";
+  string f_vars_name = program_dir + "/" + program_name_ + "-vars.lisp";
+
+  f_types_.open(f_types_name.c_str());
+  f_types_ << cl_autogen_comment() << endl;
+  f_vars_.open(f_vars_name.c_str());
+  f_vars_ << cl_autogen_comment() << endl;
+
+  package_def(f_types_);
+  package_in(f_types_);
+  package_in(f_vars_);
+
+  if (!no_asd) {
+    string f_asd_name = program_dir + "/" + system_prefix + program_name_ + ".asd";
+    f_asd_.open(f_asd_name.c_str());
+    f_asd_ << cl_autogen_comment() << endl;
+    asdf_def(f_asd_);
+  }
+}
+
+/**
+ * Renders all the imports necessary for including another Thrift program
+ */
+string t_cl_generator::render_includes() {
+  const vector<t_program*>& includes = program_->get_includes();
+  string result = "";
+  result += ":depends-on (:thrift";
+  for (size_t i = 0; i < includes.size(); ++i) {
+    result += " :" + system_prefix + underscore(includes[i]->get_name());
+  }
+  result += ")\n";
+  return result;
+}
+
+string t_cl_generator::package_of(t_program* program) {
+  string prefix = program->get_namespace("cl");
+  return prefix.empty() ? "thrift-generated" : prefix;
+}
+
+string t_cl_generator::package() {
+  return package_of(program_);
+}
+
+string t_cl_generator::prefix(string symbol) {
+  return "\"" + symbol + "\"";
+}
+
+string t_cl_generator::cl_autogen_comment() {
+  return
+    std::string(";;; ") + "Autogenerated by Thrift\n" +
+    ";;; DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING\n" +
+    ";;; options string: " + copy_options_ + "\n";
+}
+
+string t_cl_generator::cl_docstring(string raw) {
+  replace(raw.begin(), raw.end(), '"', '\'');
+  return raw;
+}
+
+
+void t_cl_generator::close_generator() {
+  f_asd_.close();
+  f_types_.close();
+  f_vars_.close();
+}
+
+string t_cl_generator::generated_package() {
+  return program_->get_namespace("cpp");
+}
+
+void t_cl_generator::asdf_def(std::ostream &out) {
+  out << "(asdf:defsystem #:" << system_prefix << program_name_ << endl;
+  indent_up();
+  out << indent() << render_includes()
+      << indent() << ":serial t" << endl
+      << indent() << ":components ("
+      << "(:file \"" << program_name_ << "-types\") "
+      << "(:file \"" << program_name_ << "-vars\")))" << endl;
+  indent_down();
+}
+
+/***
+ * Generate a package definition. Add use references equivalent to the idl file's include statements.
+ */
+void t_cl_generator::package_def(std::ostream &out) {
+  const vector<t_program*>& includes = program_->get_includes();
+
+  out << "(thrift:def-package :" << package();
+  if ( includes.size() > 0 ) {
+    out << " :use (";
+    for (size_t i = 0; i < includes.size(); ++i) {
+      out << " :" << includes[i]->get_name();
+    }
+    out << ")";
+  }
+  out << ")" << endl << endl;
+}
+
+void t_cl_generator::package_in(std::ostream &out) {
+  out << "(cl:in-package :" << package() << ")" << endl << endl;
+}
+
+/**
+ * Generates a typedef. This is not done in Common Lisp, types are all implicit.
+ *
+ * @param ttypedef The type definition
+ */
+void t_cl_generator::generate_typedef(t_typedef* ttypedef) {
+  (void)ttypedef;
+}
+
+void t_cl_generator::generate_enum(t_enum* tenum) {
+  f_types_ << "(thrift:def-enum " << prefix(tenum->get_name()) << endl;
+
+  vector<t_enum_value*> constants = tenum->get_constants();
+  vector<t_enum_value*>::iterator c_iter;
+  int value = -1;
+
+  indent_up();
+  f_types_ << indent() << "(";
+  for (c_iter = constants.begin(); c_iter != constants.end(); ++c_iter) {
+    value = (*c_iter)->get_value();
+
+    if(c_iter != constants.begin()) f_types_ << endl << indent() << " ";
+
+    f_types_ << "(\"" << (*c_iter)->get_name() << "\" . " << value << ")";
+  }
+  indent_down();
+  f_types_ << "))" << endl << endl;
+}
+
+/**
+ * Generate a constant value
+ */
+void t_cl_generator::generate_const(t_const* tconst) {
+  t_type* type = tconst->get_type();
+  string name = tconst->get_name();
+  t_const_value* value = tconst->get_value();
+
+  f_vars_ << "(thrift:def-constant " << prefix(name) << " " << render_const_value(type, value) << ")"
+          << endl << endl;
+}
+
+/**
+ * Prints the value of a constant with the given type. Note that type checking
+ * is NOT performed in this function as it is always run beforehand using the
+ * validate_types method in main.cc
+ */
+string t_cl_generator::render_const_value(t_type* type, t_const_value* value) {
+  type = get_true_type(type);
+  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:
+      out << "\"" << value->get_string() << "\"";
+      break;
+    case t_base_type::TYPE_BOOL:
+      out << (value->get_integer() > 0 ? "t" : "nil");
+      break;
+    case t_base_type::TYPE_I8:
+    case t_base_type::TYPE_I16:
+    case t_base_type::TYPE_I32:
+    case t_base_type::TYPE_I64:
+      out << value->get_integer();
+      break;
+    case t_base_type::TYPE_DOUBLE:
+      if (value->get_type() == t_const_value::CV_INTEGER) {
+        out << value->get_integer();
+      } else {
+        out << value->get_double();
+      }
+      break;
+    default:
+      throw "compiler error: no const of base type " + t_base_type::t_base_name(tbase);
+    }
+  } else if (type->is_enum()) {
+    indent(out) << value->get_integer();
+  } else if (type->is_struct() || type->is_xception()) {
+    out << (type->is_struct() ? "(make-instance '" : "(make-exception '") <<
+           lowercase(type->get_name()) << " " << endl;
+    indent_up();
+
+    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*, t_const_value::value_compare>& val = value->get_map();
+    map<t_const_value*, t_const_value*, t_const_value::value_compare>::const_iterator v_iter;
+
+    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) {
+        if ((*f_iter)->get_name() == v_iter->first->get_string()) {
+          field_type = (*f_iter)->get_type();
+        }
+      }
+      if (field_type == NULL) {
+        throw "type error: " + type->get_name() + " has no field " + v_iter->first->get_string();
+      }
+
+      out << indent() << ":" << v_iter->first->get_string() << " " <<
+        render_const_value(field_type, v_iter->second) << endl;
+    }
+    out << indent() << ")";
+
+    indent_down();
+  } else if (type->is_map()) {
+    // emit an hash form with both keys and values to be evaluated
+    t_type* ktype = ((t_map*)type)->get_key_type();
+    t_type* vtype = ((t_map*)type)->get_val_type();
+    out << "(thrift:map ";
+    indent_up();
+    const map<t_const_value*, t_const_value*, t_const_value::value_compare>& val = value->get_map();
+    map<t_const_value*, t_const_value*, t_const_value::value_compare>::const_iterator v_iter;
+    for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
+      out << endl << indent()
+          << "(cl:cons " << render_const_value(ktype, v_iter->first) << " "
+          << render_const_value(vtype, v_iter->second) << ")";
+    }
+    indent_down();
+    out << indent() << ")";
+  } else if (type->is_list() || type->is_set()) {
+    t_type* etype;
+    if (type->is_list()) {
+      etype = ((t_list*)type)->get_elem_type();
+    } else {
+      etype = ((t_set*)type)->get_elem_type();
+    }
+    if (type->is_set()) {
+      out << "(thrift:set" << endl;
+    } else {
+      out << "(thrift:list" << endl;
+    }
+    indent_up();
+    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) {
+      out << indent() << render_const_value(etype, *v_iter) << endl;
+    }
+    out << indent() << ")";
+    indent_down();
+    indent_down();
+  } else {
+    throw "CANNOT GENERATE CONSTANT FOR TYPE: " + type->get_name();
+  }
+  return out.str();
+}
+
+void t_cl_generator::generate_struct(t_struct* tstruct) {
+  generate_cl_struct(f_types_, tstruct, false);
+}
+
+void t_cl_generator::generate_xception(t_struct* txception) {
+  generate_cl_struct(f_types_, txception, true);
+}
+
+void t_cl_generator::generate_cl_struct_internal(std::ostream& out, t_struct* tstruct, bool is_exception) {
+  (void)is_exception;
+  const vector<t_field*>& members = tstruct->get_members();
+  vector<t_field*>::const_iterator m_iter;
+
+  out << "(";
+
+  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
+    t_const_value* value = (*m_iter)->get_value();
+    t_type* type = (*m_iter)->get_type();
+
+    if (m_iter != members.begin()) {
+      out << endl << indent() << " ";
+    }
+    out << "(" << prefix((*m_iter)->get_name()) << " " <<
+        ( (NULL != value) ? render_const_value(type, value) : "nil" ) <<
+        " :id " << (*m_iter)->get_key();
+    if ( type->is_base_type() && "string" == typespec(type) )
+      if ( ((t_base_type*)type)->is_binary() )
+        out << " :type binary";
+      else
+        out << " :type string";
+    else
+      out << " :type " << typespec(type);
+    if ( (*m_iter)->get_req() == t_field::T_OPTIONAL ) {
+      out << " :optional t";
+    }
+    if ( (*m_iter)->has_doc()) {
+      out << " :documentation \"" << cl_docstring((*m_iter)->get_doc()) << "\"";
+    }
+    out <<")";
+  }
+
+  out << ")";
+}
+
+void t_cl_generator::generate_cl_struct(std::ostream& out, t_struct* tstruct, bool is_exception = false) {
+  std::string name = type_name(tstruct);
+  out << (is_exception ? "(thrift:def-exception " : "(thrift:def-struct ") <<
+      prefix(name) << endl;
+  indent_up();
+  if ( tstruct->has_doc() ) {
+    out << indent() ;
+    out << "\"" << cl_docstring(tstruct->get_doc()) << "\"" << endl;
+  }
+  out << indent() ;
+  generate_cl_struct_internal(out, tstruct, is_exception);
+  indent_down();
+  out << ")" << endl << endl;
+}
+
+void t_cl_generator::generate_exception_sig(std::ostream& out, t_function* f) {
+  generate_cl_struct_internal(out, f->get_xceptions(), true);
+}
+
+void t_cl_generator::generate_service(t_service* tservice) {
+  string extends_client;
+  vector<t_function*> functions = tservice->get_functions();
+  vector<t_function*>::iterator f_iter;
+
+  if (tservice->get_extends() != NULL) {
+    extends_client = type_name(tservice->get_extends());
+  }
+
+  extends_client = extends_client.empty() ? "nil" : prefix(extends_client);
+
+  f_types_ << "(thrift:def-service " << prefix(service_name_) << " "
+           << extends_client;
+
+  indent_up();
+
+  if ( tservice->has_doc()) {
+      f_types_ << endl << indent()
+               << "(:documentation \"" << cl_docstring(tservice->get_doc()) << "\")";
+    }
+
+  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
+    t_function* function = *f_iter;
+    string fname = function->get_name();
+    string signature = function_signature(function);
+    t_struct* exceptions = function->get_xceptions();
+    const vector<t_field*>& xmembers = exceptions->get_members();
+
+    f_types_ << endl << indent() << "(:method " << prefix(fname);
+    f_types_ << " (" << signature << " "  << typespec((*f_iter)->get_returntype()) << ")";
+    if (xmembers.size() > 0) {
+      f_types_ << endl << indent() << " :exceptions " ;
+      generate_exception_sig(f_types_, function);
+    }
+    if ( (*f_iter)->is_oneway() ) {
+      f_types_ << endl << indent() << " :oneway t";
+    }
+    if ( (*f_iter)->has_doc() ) {
+      f_types_ << endl << indent() << " :documentation \""
+               << cl_docstring((*f_iter)->get_doc()) << "\"";
+  }
+    f_types_ << ")";
+  }
+
+  f_types_ << ")" << endl << endl;
+
+  indent_down();
+}
+
+string t_cl_generator::typespec(t_type *t) {
+  t = get_true_type(t);
+
+  if (t -> is_binary()){
+    return "binary";
+  } else if (t->is_base_type()) {
+    return type_name(t);
+  } else if (t->is_map()) {
+    t_map *m = (t_map*) t;
+    return "(thrift:map " + typespec(m->get_key_type()) + " " +
+      typespec(m->get_val_type()) + ")";
+  } else if (t->is_struct() || t->is_xception()) {
+    return "(struct " + prefix(type_name(t)) + ")";
+  } else if (t->is_list()) {
+    return "(thrift:list " + typespec(((t_list*) t)->get_elem_type()) + ")";
+  } else if (t->is_set()) {
+    return "(thrift:set " + typespec(((t_set*) t)->get_elem_type()) + ")";
+  } else if (t->is_enum()) {
+    return "(enum \"" + ((t_enum*) t)->get_name() + "\")";
+  } else {
+    throw "Sorry, I don't know how to generate this: " + type_name(t);
+  }
+}
+
+string t_cl_generator::function_signature(t_function* tfunction) {
+  return argument_list(tfunction->get_arglist());
+}
+
+string t_cl_generator::argument_list(t_struct* tstruct) {
+  stringstream res;
+  res << "(";
+
+  const vector<t_field*>& fields = tstruct->get_members();
+  vector<t_field*>::const_iterator f_iter;
+  bool first = true;
+  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+    if (first) {
+      first = false;
+    } else {
+      res << " ";
+    }
+    res << "(" + prefix((*f_iter)->get_name()) << " " <<
+      typespec((*f_iter)->get_type()) << " " <<
+      (*f_iter)->get_key() <<  ")";
+
+
+  }
+  res << ")";
+  return res.str();
+}
+
+string t_cl_generator::type_name(t_type* ttype) {
+  string prefix = "";
+  t_program* program = ttype->get_program();
+
+  if (program != NULL && program != program_)
+    prefix = package_of(program) == package() ? "" : package_of(program) + ":";
+
+  string name = ttype->get_name();
+
+  if (ttype->is_struct() || ttype->is_xception())
+    name = lowercase(ttype->get_name());
+
+  return prefix + name;
+}
+
+THRIFT_REGISTER_GENERATOR(
+    cl,
+    "Common Lisp",
+    "    no_asd:          Do not define ASDF systems for each generated Thrift program.\n"
+    "    sys_pref=        The prefix to give ASDF system names. Default: thrift-gen-\n")

+ 3309 - 3309
contrib/restricted/thrift/compiler/thrift/generate/t_cocoa_generator.cc

@@ -1,3309 +1,3309 @@
-/* 
- * Licensed to the Apache Software Foundation (ASF) under one 
- * or more contributor license agreements. See the NOTICE file 
- * distributed with this work for additional information 
- * regarding copyright ownership. The ASF licenses this file 
- * to you under the Apache License, Version 2.0 (the 
- * "License"); you may not use this file except in compliance 
- * with the License. You may obtain a copy of the License at 
- * 
- *   http://www.apache.org/licenses/LICENSE-2.0 
- * 
- * Unless required by applicable law or agreed to in writing, 
- * software distributed under the License is distributed on an 
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 
- * KIND, either express or implied. See the License for the 
- * specific language governing permissions and limitations 
- * under the License. 
- */ 
- 
-#include <string> 
-#include <fstream> 
-#include <iostream> 
-#include <vector> 
- 
-#include <stdlib.h> 
-#include <sys/stat.h> 
-#include <sstream> 
-#include "thrift/platform.h" 
-#include "thrift/generate/t_oop_generator.h" 
- 
-using std::map; 
-using std::ostream; 
-using std::ofstream; 
-using std::ostringstream; 
-using std::string; 
-using std::stringstream; 
-using std::vector; 
- 
-static const string endl = "\n"; // avoid ostream << std::endl flushes 
- 
-/** 
- * Objective-C code generator. 
- * 
- * mostly copy/pasting/tweaking from mcslee's work. 
- */ 
-class t_cocoa_generator : public t_oop_generator { 
-public: 
-  t_cocoa_generator(t_program* program, 
-                    const std::map<std::string, std::string>& parsed_options, 
-                    const std::string& option_string) 
-    : t_oop_generator(program) { 
-    (void)option_string; 
-    std::map<std::string, std::string>::const_iterator iter; 
- 
-    log_unexpected_ = false; 
-    validate_required_ = false; 
-    async_clients_ = false; 
-    promise_kit_ = false; 
-    debug_descriptions_ = false; 
-    pods_ = false; 
-    for( iter = parsed_options.begin(); iter != parsed_options.end(); ++iter) { 
-      if( iter->first.compare("log_unexpected") == 0) { 
-        log_unexpected_ = true; 
-      } else if( iter->first.compare("validate_required") == 0) { 
-        validate_required_ = true; 
-      } else if( iter->first.compare("async_clients") == 0) { 
-        async_clients_ = true; 
-      } else if( iter->first.compare("promise_kit") == 0) { 
-        promise_kit_ = true; 
-      } else if( iter->first.compare("debug_descriptions") == 0) { 
-        debug_descriptions_ = true; 
-      } else if( iter->first.compare("pods") == 0) { 
-        pods_ = true; 
-      } else { 
-        throw "unknown option cocoa:" + iter->first; 
-      } 
-    } 
- 
-    out_dir_base_ = "gen-cocoa"; 
-  } 
- 
-  /** 
-   * Init and close methods 
-   */ 
- 
-  void init_generator(); 
-  void close_generator(); 
- 
-  void generate_consts(std::vector<t_const*> consts); 
- 
-  /** 
-   * Program-level generation functions 
-   */ 
- 
-  void generate_typedef(t_typedef* ttypedef); 
-  void generate_enum(t_enum* tenum); 
-  void generate_struct(t_struct* tstruct); 
-  void generate_xception(t_struct* txception); 
-  void generate_service(t_service* tservice); 
- 
-  void print_const_value(ostream& out, 
-                         string name, 
-                         t_type* type, 
-                         t_const_value* value, 
-                         bool defval = false); 
-  std::string render_const_value(ostream& out, 
-                                 t_type* type, 
-                                 t_const_value* value, 
-                                 bool box_it = false); 
- 
-  void generate_cocoa_struct(t_struct* tstruct, bool is_exception); 
-  void generate_cocoa_struct_interface(std::ostream& out, 
-                                       t_struct* tstruct, 
-                                       bool is_xception = false); 
-  void generate_cocoa_struct_implementation(std::ostream& out, 
-                                            t_struct* tstruct, 
-                                            bool is_xception = false, 
-                                            bool is_result = false); 
-  void generate_cocoa_struct_initializer_signature(std::ostream& out, t_struct* tstruct); 
-  void generate_cocoa_struct_init_with_coder_method(ostream& out, 
-                                                    t_struct* tstruct, 
-                                                    bool is_exception); 
-  void generate_cocoa_struct_encode_with_coder_method(ostream& out, 
-                                                      t_struct* tstruct, 
-                                                      bool is_exception); 
-  void generate_cocoa_struct_copy_method(ostream& out, 
-                                         t_struct* tstruct, 
-                                         bool is_exception); 
-  void generate_cocoa_struct_hash_method(ostream& out, t_struct* tstruct); 
-  void generate_cocoa_struct_is_equal_method(ostream& out, 
-                                             t_struct* tstruct, 
-                                             bool is_exception); 
-  void generate_cocoa_struct_field_accessor_implementations(std::ostream& out, 
-                                                            t_struct* tstruct, 
-                                                            bool is_exception); 
-  void generate_cocoa_struct_reader(std::ostream& out, t_struct* tstruct); 
-  void generate_cocoa_struct_result_writer(std::ostream& out, t_struct* tstruct); 
-  void generate_cocoa_struct_writer(std::ostream& out, t_struct* tstruct); 
-  void generate_cocoa_struct_validator(std::ostream& out, t_struct* tstruct); 
-  void generate_cocoa_struct_description(std::ostream& out, t_struct* tstruct); 
- 
-  std::string function_result_helper_struct_type(t_service *tservice, t_function* tfunction); 
-  std::string function_args_helper_struct_type(t_service* tservice, t_function* tfunction); 
-  void generate_function_helpers(t_service *tservice, t_function* tfunction); 
- 
-  /** 
-   * Service-level generation functions 
-   */ 
- 
-  void generate_cocoa_service_protocol(std::ostream& out, t_service* tservice); 
-  void generate_cocoa_service_async_protocol(std::ostream& out, t_service* tservice); 
- 
-  void generate_cocoa_service_client_interface(std::ostream& out, t_service* tservice); 
-  void generate_cocoa_service_client_async_interface(std::ostream& out, t_service* tservice); 
- 
-  void generate_cocoa_service_client_send_function_implementation(ostream& out, 
-                                                                  t_service* tservice, 
-                                                                  t_function* tfunction, 
-                                                                  bool needs_protocol); 
-  void generate_cocoa_service_client_send_function_invocation(ostream& out, t_function* tfunction); 
-  void generate_cocoa_service_client_send_async_function_invocation(ostream& out, 
-                                                                    t_function* tfunction, 
-                                                                    string failureBlockName); 
-  void generate_cocoa_service_client_recv_function_implementation(ostream& out, 
-                                                                  t_service* tservice, 
-                                                                  t_function* tfunction, 
-                                                                  bool needs_protocol); 
-  void generate_cocoa_service_client_implementation(std::ostream& out, t_service* tservice); 
-  void generate_cocoa_service_client_async_implementation(std::ostream& out, t_service* tservice); 
- 
-  void generate_cocoa_service_server_interface(std::ostream& out, t_service* tservice); 
-  void generate_cocoa_service_server_implementation(std::ostream& out, t_service* tservice); 
-  void generate_cocoa_service_helpers(t_service* tservice); 
-  void generate_service_client(t_service* tservice); 
-  void generate_service_server(t_service* tservice); 
-  void generate_process_function(t_service* tservice, t_function* tfunction); 
- 
-  /** 
-   * Serialization constructs 
-   */ 
- 
-  void generate_deserialize_field(std::ostream& out, t_field* tfield, std::string fieldName); 
- 
-  void generate_deserialize_struct(std::ostream& out, t_struct* tstruct, std::string prefix = ""); 
- 
-  void generate_deserialize_container(std::ostream& out, t_type* ttype, std::string prefix = ""); 
- 
-  void generate_deserialize_set_element(std::ostream& out, t_set* tset, std::string prefix = ""); 
- 
-  void generate_deserialize_map_element(std::ostream& out, t_map* tmap, std::string prefix = ""); 
- 
-  void generate_deserialize_list_element(std::ostream& out, 
-                                         t_list* tlist, 
-                                         std::string prefix = ""); 
- 
-  void generate_serialize_field(std::ostream& out, t_field* tfield, std::string prefix = ""); 
- 
-  void generate_serialize_struct(std::ostream& out, t_struct* tstruct, std::string fieldName = ""); 
- 
-  void generate_serialize_container(std::ostream& out, t_type* ttype, std::string prefix = ""); 
- 
-  void generate_serialize_map_element(std::ostream& out, 
-                                      t_map* tmap, 
-                                      std::string iter, 
-                                      std::string map); 
- 
-  void generate_serialize_set_element(std::ostream& out, t_set* tmap, std::string iter); 
- 
-  void generate_serialize_list_element(std::ostream& out, 
-                                       t_list* tlist, 
-                                       std::string index, 
-                                       std::string listName); 
- 
-  /** 
-   * Helper rendering functions 
-   */ 
- 
-  std::string cocoa_prefix(); 
-  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); 
-  std::string declare_property_unset(t_field* tfield); 
-  std::string invalid_return_statement(t_function* tfunction); 
-  std::string function_signature(t_function* tfunction, bool include_error); 
-  std::string async_function_signature(t_function* tfunction, bool include_error); 
-  std::string promise_function_signature(t_function* tfunction); 
-  std::string argument_list(t_struct* tstruct, string protocol_name, bool include_error); 
-  std::string type_to_enum(t_type* ttype); 
-  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 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); 
- 
-  bool type_can_be_copy(t_type* ttype) { 
-    ttype = get_true_type(ttype); 
-     
-    return ttype->is_string(); 
-  } 
-   
-  bool type_can_be_null(t_type* ttype) { 
-    ttype = get_true_type(ttype); 
- 
-    return ttype->is_container() || ttype->is_struct() || ttype->is_xception() 
-           || ttype->is_string(); 
-  } 
- 
-private: 
-  std::string cocoa_prefix_; 
-  std::string constants_declarations_; 
-  int error_constant_; 
- 
-  /** 
-   * File streams 
-   */ 
- 
-  ofstream_with_content_based_conditional_update f_header_; 
-  ofstream_with_content_based_conditional_update f_impl_; 
- 
-  bool log_unexpected_; 
-  bool validate_required_; 
-  bool async_clients_; 
-  bool promise_kit_; 
-  bool debug_descriptions_; 
-  bool pods_; 
-}; 
- 
-/** 
- * Prepares for file generation by opening up the necessary file output 
- * streams. 
- */ 
-void t_cocoa_generator::init_generator() { 
-  // Make output directory 
-  MKDIR(get_out_dir().c_str()); 
-  cocoa_prefix_ = program_->get_namespace("cocoa"); 
- 
-  // we have a .h header file... 
-  string f_header_name = cocoa_prefix_ + capitalize(program_name_) + ".h"; 
-  string f_header_fullname = get_out_dir() + f_header_name; 
-  f_header_.open(f_header_fullname.c_str()); 
- 
-  f_header_ << autogen_comment() << endl; 
- 
-  f_header_ << cocoa_imports() << cocoa_thrift_imports(); 
- 
-  // ...and a .m implementation file 
-  string f_impl_name = cocoa_prefix_ + capitalize(program_name_) + ".m"; 
-  string f_impl_fullname = get_out_dir() + f_impl_name; 
-  f_impl_.open(f_impl_fullname.c_str()); 
- 
-  f_impl_ << autogen_comment() << endl; 
- 
-  f_impl_ << cocoa_imports() << cocoa_thrift_imports() << "#import \"" << f_header_name << "\"" 
-          << endl << endl; 
- 
-  error_constant_ = 60000; 
-} 
- 
-/** 
- * Prints standard Cocoa imports 
- * 
- * @return List of imports for Cocoa libraries 
- */ 
-string t_cocoa_generator::cocoa_imports() { 
-  return string() + "#import <Foundation/Foundation.h>\n" + "\n"; 
-} 
- 
-/** 
- * Prints thrift runtime imports 
- * 
- * @return List of imports necessary for thrift runtime 
- */ 
-string t_cocoa_generator::cocoa_thrift_imports() { 
- 
-  vector<string> includes_list; 
-  includes_list.push_back("TProtocol.h"); 
-  includes_list.push_back("TProtocolFactory.h"); 
-  includes_list.push_back("TApplicationError.h"); 
-  includes_list.push_back("TProtocolError.h"); 
-  includes_list.push_back("TProtocolUtil.h"); 
-  includes_list.push_back("TProcessor.h"); 
-  includes_list.push_back("TBase.h"); 
-  includes_list.push_back("TAsyncTransport.h"); 
-  includes_list.push_back("TBaseClient.h"); 
- 
-  std::ostringstream includes; 
- 
-  vector<string>::const_iterator i_iter; 
-  for (i_iter=includes_list.begin(); i_iter!=includes_list.end(); ++i_iter) { 
-    includes << "#import "; 
-    if (pods_) { 
-      includes << "<Thrift/" << *i_iter << ">"; 
-    } else { 
-      includes << "\"" << *i_iter << "\""; 
-    } 
-    includes << endl; 
-  } 
- 
-  includes << endl; 
- 
-  if (promise_kit_) { 
-    includes << "#import "; 
-    if (pods_) { 
-      includes << "<PromiseKit/PromiseKit.h>"; 
-    } else { 
-      includes << "\"PromiseKit.h\""; 
-    } 
-    includes << endl; 
-  } 
- 
-  // Include other Thrift includes 
-  const vector<t_program*>& other_includes = program_->get_includes(); 
-  for (size_t i = 0; i < other_includes.size(); ++i) { 
-    includes << "#import \"" 
-             << other_includes[i]->get_namespace("cocoa") 
-             << capitalize(other_includes[i]->get_name()) 
-             << ".h\"" << endl; 
-  } 
- 
-  includes << endl; 
- 
-  return includes.str(); 
-} 
- 
-/** 
- * Finish up generation. 
- */ 
-void t_cocoa_generator::close_generator() { 
-  // stick our constants declarations at the end of the header file 
-  // since they refer to things we are defining. 
-  f_header_ << constants_declarations_ << endl; 
-} 
- 
-/** 
- * Generates a typedef. This is just a simple 1-liner in objective-c 
- * 
- * @param ttypedef The type definition 
- */ 
-void t_cocoa_generator::generate_typedef(t_typedef* ttypedef) { 
-  if (ttypedef->get_type()->is_map()) { 
-    t_map *map = (t_map *)ttypedef->get_type(); 
-    if (map->get_key_type()->is_struct()) { 
-      f_header_ << indent() << "@class " << type_name(map->get_key_type(), true) << ";" << endl; 
-    } 
-    if (map->get_val_type()->is_struct()) { 
-      f_header_ << indent() << "@class " << type_name(map->get_val_type(), true) << ";" << endl; 
-    } 
-  } 
-  else if (ttypedef->get_type()->is_set()) { 
-    t_set *set = (t_set *)ttypedef->get_type(); 
-    if (set->get_elem_type()->is_struct()) { 
-      f_header_ << indent() << "@class " << type_name(set->get_elem_type(), true) << ";" << endl; 
-    } 
-  } 
-  else if (ttypedef->get_type()->is_list()) { 
-    t_list *list = (t_list *)ttypedef->get_type(); 
-    if (list->get_elem_type()->is_struct()) { 
-      f_header_ << indent() << "@class " << type_name(list->get_elem_type(), true) << ";" << endl; 
-    } 
-  } 
-  f_header_ << indent() << "typedef " << type_name(ttypedef->get_type()) << " " << cocoa_prefix_ 
-            << ttypedef->get_symbolic() << ";" << endl << endl; 
-  if (ttypedef->get_type()->is_container()) { 
-    f_header_ << indent() << "typedef " << type_name(ttypedef->get_type(), false, true) << " " << cocoa_prefix_ 
-              << "Mutable" << ttypedef->get_symbolic() << ";" << endl << endl; 
-  } 
-} 
- 
-/** 
- * Generates code for an enumerated type. In Objective-C, this is 
- * essentially the same as the thrift definition itself, instead using 
- * NS_ENUM keyword in Objective-C.  For namespace purposes, the name of 
- * the enum is prefixed to each element in keeping with Cocoa & Swift 
- * standards. 
- * 
- * @param tenum The enumeration 
- */ 
-void t_cocoa_generator::generate_enum(t_enum* tenum) { 
-  f_header_ << indent() << "typedef NS_ENUM(SInt32, " << cocoa_prefix_ << tenum->get_name() << ") {" << endl; 
-  indent_up(); 
- 
-  vector<t_enum_value*> constants = tenum->get_constants(); 
-  vector<t_enum_value*>::iterator c_iter; 
-  bool first = true; 
-  for (c_iter = constants.begin(); c_iter != constants.end(); ++c_iter) { 
-    if (first) { 
-      first = false; 
-    } else { 
-      f_header_ << "," << endl; 
-    } 
-    f_header_ << indent() << cocoa_prefix_ << tenum->get_name() << (*c_iter)->get_name(); 
-    f_header_ << " = " << (*c_iter)->get_value(); 
-  } 
- 
-  indent_down(); 
-  f_header_ << endl << "};" << endl << endl; 
-} 
- 
-/** 
- * Generates a class that holds all the constants. 
- */ 
-void t_cocoa_generator::generate_consts(std::vector<t_const*> consts) { 
-  std::ostringstream const_interface; 
- 
-  const_interface << "FOUNDATION_EXPORT NSString *" << cocoa_prefix_ << capitalize(program_name_) << "ErrorDomain;" << endl 
-                  << endl; 
- 
- 
-  bool needs_class = false; 
- 
-  // 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()->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; 
-    } 
-    else { 
-      needs_class = true; 
-    } 
-  } 
- 
- 
-  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); 
-    scope_down(const_interface); 
- 
-    // 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()->get_true_type(); 
-      if (type->is_container() || type->is_struct()) { 
-        t_type* type = (*c_iter)->get_type(); 
-        const_interface << endl << "+ (" << type_name(type) << ") " << name << ";" << endl; 
-      } 
-    } 
- 
-    const_interface << endl << "@end"; 
-  } 
- 
-  // this gets spit into the header file in ::close_generator 
-  constants_declarations_ = const_interface.str(); 
- 
-  f_impl_ << "NSString *" << cocoa_prefix_ << capitalize(program_name_) << "ErrorDomain = " 
-          << "@\"" << cocoa_prefix_ << capitalize(program_name_) << "ErrorDomain\";" << endl << endl; 
- 
-  // variables in the .m hold all simple constant values 
-  for (c_iter = consts.begin(); c_iter != consts.end(); ++c_iter) { 
-    string name = (*c_iter)->get_name(); 
-    t_type* type = (*c_iter)->get_type(); 
-    f_impl_ << type_name(type) << " " << cocoa_prefix_ << name; 
-    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; 
-  } 
-  f_impl_ << endl; 
- 
-  if (needs_class) { 
- 
-    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) { 
-      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); 
-        f_impl_ << ";" << endl; 
-      } 
-    } 
-    scope_down(f_impl_); 
- 
-    // 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()->get_true_type(); 
-      if (type->is_container() || type->is_struct()) { 
-        f_impl_ << endl << "+ (" << type_name(type) << ") " << name << " "; 
-        scope_up(f_impl_); 
-        indent(f_impl_) << "return " << cocoa_prefix_ << name << ";" << endl; 
-        scope_down(f_impl_); 
-      } 
-    } 
- 
-    f_impl_ << "@end" << endl << endl; 
-  } 
-} 
- 
-/** 
- * Generates a struct definition for a thrift data type. This is a class 
- * with protected data members, read(), write(), and getters and setters. 
- * 
- * @param tstruct The struct definition 
- */ 
-void t_cocoa_generator::generate_struct(t_struct* tstruct) { 
-  generate_cocoa_struct_interface(f_header_, tstruct, false); 
-  generate_cocoa_struct_implementation(f_impl_, tstruct, false); 
-} 
- 
-/** 
- * Exceptions are structs, but they inherit from NSException 
- * 
- * @param tstruct The struct definition 
- */ 
-void t_cocoa_generator::generate_xception(t_struct* txception) { 
-  generate_cocoa_struct_interface(f_header_, txception, true); 
-  generate_cocoa_struct_implementation(f_impl_, txception, true); 
-} 
- 
-/** 
- * Generate the interface for a struct 
- * 
- * @param tstruct The struct definition 
- */ 
-void t_cocoa_generator::generate_cocoa_struct_interface(ostream& out, 
-                                                        t_struct* tstruct, 
-                                                        bool is_exception) { 
- 
-  if (is_exception) { 
-    out << "enum {" << endl 
-        << "  " << cocoa_prefix_ << capitalize(program_name_) << "Error" << tstruct->get_name() <<  " = -" << error_constant_++ << endl 
-        << "};" << endl 
-        << endl; 
-  } 
- 
-  out << "@interface " << cocoa_prefix_ << tstruct->get_name() << " : "; 
- 
-  if (is_exception) { 
-    out << "NSError "; 
-  } else { 
-    out << "NSObject "; 
-  } 
-  out << "<TBase, NSCoding, NSCopying> " << endl; 
- 
-  out << endl; 
- 
-  // properties 
-  const vector<t_field*>& members = tstruct->get_members(); 
-  if (members.size() > 0) { 
-    vector<t_field*>::const_iterator m_iter; 
-    for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { 
-      out << indent() << declare_property(*m_iter) << endl; 
-      out << indent() << declare_property_isset(*m_iter) << endl; 
-      out << indent() << declare_property_unset(*m_iter) << endl; 
-      out << endl; 
-    } 
-  } 
- 
-  out << endl; 
- 
-  // initializer for all fields 
-  if (!members.empty()) { 
-    generate_cocoa_struct_initializer_signature(out, tstruct); 
-    out << ";" << endl; 
-  } 
-  out << endl; 
- 
-  out << "@end" << endl << endl; 
-} 
- 
-/** 
- * Generate signature for initializer of struct with a parameter for 
- * each field. 
- */ 
-void t_cocoa_generator::generate_cocoa_struct_initializer_signature(ostream& out, 
-                                                                    t_struct* tstruct) { 
-  const vector<t_field*>& members = tstruct->get_members(); 
-  vector<t_field*>::const_iterator m_iter; 
-  indent(out) << "- (instancetype) initWith"; 
-  for (m_iter = members.begin(); m_iter != members.end();) { 
-    if (m_iter == members.begin()) { 
-      out << capitalize((*m_iter)->get_name()); 
-    } else { 
-      out << (*m_iter)->get_name(); 
-    } 
-    out << ": (" << type_name((*m_iter)->get_type()) << ") " << (*m_iter)->get_name(); 
-    ++m_iter; 
-    if (m_iter != members.end()) { 
-      out << " "; 
-    } 
-  } 
-} 
- 
-/** 
- * Generate the initWithCoder method for this struct so it's compatible with 
- * the NSCoding protocol 
- */ 
-void t_cocoa_generator::generate_cocoa_struct_init_with_coder_method(ostream& out, 
-                                                                     t_struct* tstruct, 
-                                                                     bool is_exception) { 
- 
-  indent(out) << "- (instancetype) initWithCoder: (NSCoder *) decoder" << endl; 
-  scope_up(out); 
- 
-  if (is_exception) { 
-    // NSExceptions conform to NSCoding, so we can call super 
-    indent(out) << "self = [super initWithCoder: decoder];" << endl; 
-  } else { 
-    indent(out) << "self = [super init];" << endl; 
-  } 
- 
-  indent(out) << "if (self) "; 
-  scope_up(out); 
- 
-  const vector<t_field*>& members = tstruct->get_members(); 
-  vector<t_field*>::const_iterator m_iter; 
- 
-  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { 
-    t_type* t = get_true_type((*m_iter)->get_type()); 
-    out << indent() << "if ([decoder containsValueForKey: @\"" << (*m_iter)->get_name() << "\"])" 
-        << endl; 
-    scope_up(out); 
-    out << indent() << "_" << (*m_iter)->get_name() << " = "; 
-    if (type_can_be_null(t)) { 
-      out << "[decoder decodeObjectForKey: @\"" << (*m_iter)->get_name() << "\"];" 
-          << endl; 
-    } else if (t->is_enum()) { 
-      out << "[decoder decodeIntForKey: @\"" << (*m_iter)->get_name() << "\"];" << endl; 
-    } else { 
-      t_base_type::t_base tbase = ((t_base_type*)t)->get_base(); 
-      switch (tbase) { 
-      case t_base_type::TYPE_BOOL: 
-        out << "[decoder decodeBoolForKey: @\"" << (*m_iter)->get_name() << "\"];" << endl; 
-        break; 
-      case t_base_type::TYPE_I8: 
-        out << "[decoder decodeIntForKey: @\"" << (*m_iter)->get_name() << "\"];" << endl; 
-        break; 
-      case t_base_type::TYPE_I16: 
-        out << "[decoder decodeIntForKey: @\"" << (*m_iter)->get_name() << "\"];" << endl; 
-        break; 
-      case t_base_type::TYPE_I32: 
-        out << "[decoder decodeInt32ForKey: @\"" << (*m_iter)->get_name() << "\"];" << endl; 
-        break; 
-      case t_base_type::TYPE_I64: 
-        out << "[decoder decodeInt64ForKey: @\"" << (*m_iter)->get_name() << "\"];" << endl; 
-        break; 
-      case t_base_type::TYPE_DOUBLE: 
-        out << "[decoder decodeDoubleForKey: @\"" << (*m_iter)->get_name() << "\"];" << endl; 
-        break; 
-      default: 
-        throw "compiler error: don't know how to decode thrift type: " 
-            + t_base_type::t_base_name(tbase); 
-      } 
-    } 
-    out << indent() << "_" << (*m_iter)->get_name() << "IsSet = YES;" << endl; 
-    scope_down(out); 
-  } 
- 
-  scope_down(out); 
- 
-  out << indent() << "return self;" << endl; 
-  scope_down(out); 
-  out << endl; 
-} 
- 
-/** 
- * Generate the encodeWithCoder method for this struct so it's compatible with 
- * the NSCoding protocol 
- */ 
-void t_cocoa_generator::generate_cocoa_struct_encode_with_coder_method(ostream& out, 
-                                                                       t_struct* tstruct, 
-                                                                       bool is_exception) { 
- 
-  indent(out) << "- (void) encodeWithCoder: (NSCoder *) encoder" << endl; 
-  scope_up(out); 
- 
-  if (is_exception) { 
-    // NSExceptions conform to NSCoding, so we can call super 
-    out << indent() << "[super encodeWithCoder: encoder];" << endl; 
-  } 
- 
-  const vector<t_field*>& members = tstruct->get_members(); 
-  vector<t_field*>::const_iterator m_iter; 
- 
-  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { 
-    t_type* t = get_true_type((*m_iter)->get_type()); 
-    out << indent() << "if (_" << (*m_iter)->get_name() << "IsSet)" << endl; 
-    scope_up(out); 
-    if (type_can_be_null(t)) { 
-      out << indent() << "[encoder encodeObject: _" << (*m_iter)->get_name() << " forKey: @\"" 
-          << (*m_iter)->get_name() << "\"];" << endl; 
-    } else if (t->is_enum()) { 
-      out << indent() << "[encoder encodeInt: _" << (*m_iter)->get_name() << " forKey: @\"" 
-          << (*m_iter)->get_name() << "\"];" << endl; 
-    } else { 
-      t_base_type::t_base tbase = ((t_base_type*)t)->get_base(); 
-      switch (tbase) { 
-      case t_base_type::TYPE_BOOL: 
-        out << indent() << "[encoder encodeBool: _" << (*m_iter)->get_name() << " forKey: @\"" 
-            << (*m_iter)->get_name() << "\"];" << endl; 
-        break; 
-      case t_base_type::TYPE_I8: 
-        out << indent() << "[encoder encodeInt: _" << (*m_iter)->get_name() << " forKey: @\"" 
-            << (*m_iter)->get_name() << "\"];" << endl; 
-        break; 
-      case t_base_type::TYPE_I16: 
-        out << indent() << "[encoder encodeInt: _" << (*m_iter)->get_name() << " forKey: @\"" 
-            << (*m_iter)->get_name() << "\"];" << endl; 
-        break; 
-      case t_base_type::TYPE_I32: 
-        out << indent() << "[encoder encodeInt32: _" << (*m_iter)->get_name() << " forKey: @\"" 
-            << (*m_iter)->get_name() << "\"];" << endl; 
-        break; 
-      case t_base_type::TYPE_I64: 
-        out << indent() << "[encoder encodeInt64: _" << (*m_iter)->get_name() << " forKey: @\"" 
-            << (*m_iter)->get_name() << "\"];" << endl; 
-        break; 
-      case t_base_type::TYPE_DOUBLE: 
-        out << indent() << "[encoder encodeDouble: _" << (*m_iter)->get_name() << " forKey: @\"" 
-            << (*m_iter)->get_name() << "\"];" << endl; 
-        break; 
-      default: 
-        throw "compiler error: don't know how to encode thrift type: " 
-            + t_base_type::t_base_name(tbase); 
-      } 
-    } 
-    scope_down(out); 
-  } 
- 
-  scope_down(out); 
-  out << endl; 
-} 
- 
-/** 
- * Generate the copy method for this struct 
- */ 
-void t_cocoa_generator::generate_cocoa_struct_copy_method(ostream& out, t_struct* tstruct, bool is_exception) { 
-  out << indent() << "- (instancetype) copyWithZone:(NSZone *)zone" << endl; 
-  scope_up(out); 
- 
-  if (is_exception) { 
-    out << indent() << type_name(tstruct) << " val = [" << cocoa_prefix_ << tstruct->get_name() << " errorWithDomain: self.domain code: self.code userInfo: self.userInfo];" << endl; 
-  } else { 
-    out << indent() << type_name(tstruct) << " val = [" << cocoa_prefix_ << tstruct->get_name() << " new];" << endl; 
-  } 
- 
-  const vector<t_field*>& members = tstruct->get_members(); 
-  vector<t_field*>::const_iterator m_iter; 
- 
-  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { 
-    t_type* t = get_true_type((*m_iter)->get_type()); 
-    out << indent() << "if (_" << (*m_iter)->get_name() << "IsSet)" << endl; 
-    scope_up(out); 
-    if (type_can_be_null(t)) { 
-      out << indent() << "val." << (*m_iter)->get_name() << " = [self." << (*m_iter)->get_name() << " copy];"; 
-    } else { 
-      out << indent() << "val." << (*m_iter)->get_name() << " = self." << (*m_iter)->get_name() << ";"; 
-    } 
-    out << endl; 
-    scope_down(out); 
-  } 
- 
-  out << indent() << "return val;" << endl; 
- 
-  scope_down(out); 
-  out << endl; 
-} 
- 
-/** 
- * Generate the hash method for this struct 
- */ 
-void t_cocoa_generator::generate_cocoa_struct_hash_method(ostream& out, t_struct* tstruct) { 
-  indent(out) << "- (NSUInteger) hash" << endl; 
-  scope_up(out); 
-  out << indent() << "NSUInteger hash = 17;" << endl; 
- 
-  const vector<t_field*>& members = tstruct->get_members(); 
-  vector<t_field*>::const_iterator m_iter; 
- 
-  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { 
-    t_type* t = get_true_type((*m_iter)->get_type()); 
-    out << indent() << "hash = (hash * 31) ^ _" << (*m_iter)->get_name() 
-        << "IsSet ? 2654435761 : 0;" << endl; 
-    out << indent() << "if (_" << (*m_iter)->get_name() << "IsSet)" << endl; 
-    scope_up(out); 
-    if (type_can_be_null(t)) { 
-      out << indent() << "hash = (hash * 31) ^ [_" << (*m_iter)->get_name() << " hash];" << endl; 
-    } else { 
-      out << indent() << "hash = (hash * 31) ^ [@(_" << (*m_iter)->get_name() << ") hash];" 
-          << endl; 
-    } 
-    scope_down(out); 
-  } 
- 
-  out << indent() << "return hash;" << endl; 
-  scope_down(out); 
-  out << endl; 
-} 
- 
-/** 
- * Generate the isEqual method for this struct 
- */ 
-void t_cocoa_generator::generate_cocoa_struct_is_equal_method(ostream& out, t_struct* tstruct, bool is_exception) { 
-  indent(out) << "- (BOOL) isEqual: (id) anObject" << endl; 
-  scope_up(out); 
- 
-  indent(out) << "if (self == anObject) {" << endl; 
-  indent_up(); 
-  indent(out) << "return YES;" << endl; 
-  indent_down(); 
-  indent(out) << "}" << endl; 
- 
-  string class_name = cocoa_prefix_ + tstruct->get_name(); 
- 
-  if (is_exception) { 
-    indent(out) << "if (![super isEqual:anObject]) {" << endl; 
-    indent_up(); 
-    indent(out) << "return NO;" << endl; 
-    indent_down(); 
-    indent(out) << "}" << endl << endl; 
-  } 
-  else { 
-    indent(out) << "if (![anObject isKindOfClass:[" << class_name << " class]]) {" << endl; 
-    indent_up(); 
-    indent(out) << "return NO;" << endl; 
-    indent_down(); 
-    indent(out) << "}" << endl; 
-  } 
- 
-  const vector<t_field*>& members = tstruct->get_members(); 
-  vector<t_field*>::const_iterator m_iter; 
- 
-  if (!members.empty()) { 
-    indent(out) << class_name << " *other = (" << class_name << " *)anObject;" << endl; 
- 
-    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 (type_can_be_null(t)) { 
-        out << indent() << "if ((_" << name << "IsSet != other->_" << name << "IsSet) ||" << endl 
-            << indent() << "    " 
-            << "(_" << name << "IsSet && " 
-            << "((_" << name << " || other->_" << name << ") && " 
-            << "![_" << name << " isEqual:other->_" << name << "]))) {" << endl; 
-      } else { 
-        out << indent() << "if ((_" << name << "IsSet != other->_" << name << "IsSet) ||" << endl 
-            << indent() << "    " 
-            << "(_" << name << "IsSet && " 
-            << "(_" << name << " != other->_" << name << "))) {" << endl; 
-      } 
-      indent_up(); 
-      indent(out) << "return NO;" << endl; 
-      indent_down(); 
-      indent(out) << "}" << endl; 
-    } 
-  } 
- 
-  out << indent() << "return YES;" << endl; 
-  scope_down(out); 
-  out << endl; 
-} 
- 
-/** 
- * Generate struct implementation. 
- * 
- * @param tstruct      The struct definition 
- * @param is_exception Is this an exception? 
- * @param is_result    If this is a result it needs a different writer 
- */ 
-void t_cocoa_generator::generate_cocoa_struct_implementation(ostream& out, 
-                                                             t_struct* tstruct, 
-                                                             bool is_exception, 
-                                                             bool is_result) { 
-  indent(out) << "@implementation " << cocoa_prefix_ << tstruct->get_name() << endl << endl; 
- 
-  const vector<t_field*>& members = tstruct->get_members(); 
-  vector<t_field*>::const_iterator m_iter; 
- 
-  // exceptions need to call the designated initializer on NSException 
-  if (is_exception) { 
-    out << indent() << "- (instancetype) init" << endl; 
-    scope_up(out); 
-    out << indent() << "return [super initWithDomain: " << cocoa_prefix_ << capitalize(program_name_) << "ErrorDomain" << endl 
-        << indent() << "                        code: " << cocoa_prefix_ << capitalize(program_name_) << "Error" << tstruct->get_name() << endl 
-        << indent() << "                    userInfo: nil];" << endl; 
-    scope_down(out); 
-    out << endl; 
-  } else { 
-    // struct 
- 
-    // default initializer 
-    // setup instance variables with default values 
-    indent(out) << "- (instancetype) init" << endl; 
-    scope_up(out); 
-    indent(out) << "self = [super init];" << endl; 
-    indent(out) << "if (self)"; 
-    scope_up(out); 
-    if (members.size() > 0) { 
-      for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { 
-        t_type* t = get_true_type((*m_iter)->get_type()); 
-        if ((*m_iter)->get_value() != NULL) { 
-          print_const_value(out, 
-                            "self." + (*m_iter)->get_name(), 
-                            t, 
-                            (*m_iter)->get_value(), 
-                            false); 
-        } 
-      } 
-    } 
-    scope_down(out); 
-    indent(out) << "return self;" << endl; 
-    scope_down(out); 
-    out << endl; 
-  } 
- 
-  // initializer with all fields as params 
-  if (!members.empty()) { 
-    generate_cocoa_struct_initializer_signature(out, tstruct); 
-    out << endl; 
-    scope_up(out); 
-    if (is_exception) { 
-      out << indent() << "self = [self init];" << endl; 
-    } else { 
-      out << indent() << "self = [super init];" << endl; 
-    } 
- 
-    indent(out) << "if (self)"; 
-    scope_up(out); 
-    for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { 
-      out << indent() << "_" << (*m_iter)->get_name() << " = "; 
-      if (get_true_type((*m_iter)->get_type())->is_container()) { 
-        out << "[" << (*m_iter)->get_name() << " mutableCopy];" << endl; 
-      } else { 
-        out << (*m_iter)->get_name() << ";" << endl; 
-      } 
-      out << indent() << "_" << (*m_iter)->get_name() << "IsSet = YES;" << endl; 
-    } 
-    scope_down(out); 
- 
-    out << indent() << "return self;" << endl; 
-    scope_down(out); 
-    out << endl; 
-  } 
- 
-  // initWithCoder for NSCoding 
-  generate_cocoa_struct_init_with_coder_method(out, tstruct, is_exception); 
-  // encodeWithCoder for NSCoding 
-  generate_cocoa_struct_encode_with_coder_method(out, tstruct, is_exception); 
-  // hash and isEqual for NSObject 
-  generate_cocoa_struct_hash_method(out, tstruct); 
-  generate_cocoa_struct_is_equal_method(out, tstruct, is_exception); 
-  // copy for NSObject 
-  generate_cocoa_struct_copy_method(out, tstruct, is_exception); 
- 
-  // the rest of the methods 
-  generate_cocoa_struct_field_accessor_implementations(out, tstruct, is_exception); 
-  generate_cocoa_struct_reader(out, tstruct); 
-  if (is_result) { 
-    generate_cocoa_struct_result_writer(out, tstruct); 
-  } else { 
-    generate_cocoa_struct_writer(out, tstruct); 
-  } 
-  generate_cocoa_struct_validator(out, tstruct); 
-  generate_cocoa_struct_description(out, tstruct); 
- 
-  out << "@end" << endl << endl; 
-} 
- 
-/** 
- * Generates a function to read all the fields of the struct. 
- * 
- * @param tstruct The struct definition 
- */ 
-void t_cocoa_generator::generate_cocoa_struct_reader(ostream& out, t_struct* tstruct) { 
-  out << "- (BOOL) read: (id <TProtocol>) inProtocol error: (NSError *__autoreleasing *)__thriftError" << endl; 
-  scope_up(out); 
- 
-  const vector<t_field*>& fields = tstruct->get_members(); 
-  vector<t_field*>::const_iterator f_iter; 
- 
-  // Declare stack tmp variables 
-  indent(out) << "NSString * fieldName;" << endl; 
-  indent(out) << "SInt32 fieldType;" << endl; 
-  indent(out) << "SInt32 fieldID;" << endl; 
-  out << endl; 
- 
-  indent(out) << "if (![inProtocol readStructBeginReturningName: NULL error: __thriftError]) return NO;" << endl; 
- 
-  // Loop over reading in fields 
-  indent(out) << "while (true)" << endl; 
-  scope_up(out); 
- 
-  // Read beginning field marker 
-  indent(out) 
-      << "if (![inProtocol readFieldBeginReturningName: &fieldName type: &fieldType fieldID: &fieldID error: __thriftError]) return NO;" 
-      << endl; 
- 
-  // Check for field STOP marker and break 
-  indent(out) << "if (fieldType == TTypeSTOP) { " << endl; 
-  indent_up(); 
-  indent(out) << "break;" << endl; 
-  indent_down(); 
-  indent(out) << "}" << endl; 
- 
-  // Switch statement on the field we are reading 
-  indent(out) << "switch (fieldID)" << endl; 
- 
-  scope_up(out); 
- 
-  // Generate deserialization code for known cases 
-  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { 
-    indent(out) << "case " << (*f_iter)->get_key() << ":" << endl; 
-    indent_up(); 
-    indent(out) << "if (fieldType == " << type_to_enum((*f_iter)->get_type()) << ") {" << endl; 
-    indent_up(); 
- 
-    generate_deserialize_field(out, *f_iter, "fieldValue"); 
-    indent(out) << call_field_setter(*f_iter, "fieldValue") << endl; 
- 
-    indent_down(); 
-    out << indent() << "} else { " << endl; 
-    if (log_unexpected_) { 
-      out << indent() << "  NSLog(@\"%s: field ID %i has unexpected type %i.  Skipping.\", " 
-                         "__PRETTY_FUNCTION__, (int)fieldID, (int)fieldType);" << endl; 
-    } 
- 
-    out << indent() << "  if (![TProtocolUtil skipType: fieldType onProtocol: inProtocol error: __thriftError]) return NO;" << endl; 
-    out << indent() << "}" << endl << indent() << "break;" << endl; 
-    indent_down(); 
-  } 
- 
-  // In the default case we skip the field 
-  out << indent() << "default:" << endl; 
-  if (log_unexpected_) { 
-    out << indent() << "  NSLog(@\"%s: unexpected field ID %i with type %i.  Skipping.\", " 
-                       "__PRETTY_FUNCTION__, (int)fieldID, (int)fieldType);" << endl; 
-  } 
- 
-  out << indent() << "  if (![TProtocolUtil skipType: fieldType onProtocol: inProtocol error: __thriftError]) return NO;" << endl; 
- 
-  out << indent() << "  break;" << endl; 
- 
-  scope_down(out); 
- 
-  // Read field end marker 
-  indent(out) << "if (![inProtocol readFieldEnd: __thriftError]) return NO;" << endl; 
- 
-  scope_down(out); 
- 
-  out << indent() << "if (![inProtocol readStructEnd: __thriftError]) return NO;" << endl; 
- 
-  // performs various checks (e.g. check that all required fields are set) 
-  if (validate_required_) { 
-    out << indent() << "if (![self validate: __thriftError]) return NO;" << endl; 
-  } 
- 
-  indent(out) << "return YES;" << endl; 
- 
-  indent_down(); 
-  out << indent() << "}" << endl << endl; 
-} 
- 
-/** 
- * Generates a function to write all the fields of the struct 
- * 
- * @param tstruct The struct definition 
- */ 
-void t_cocoa_generator::generate_cocoa_struct_writer(ostream& out, t_struct* tstruct) { 
-  out << indent() << "- (BOOL) write: (id <TProtocol>) outProtocol error: (NSError *__autoreleasing *)__thriftError {" << endl; 
-  indent_up(); 
- 
-  string name = tstruct->get_name(); 
-  const vector<t_field*>& fields = tstruct->get_members(); 
-  vector<t_field*>::const_iterator f_iter; 
- 
-  out << indent() << "if (![outProtocol writeStructBeginWithName: @\"" << name << "\" error: __thriftError]) return NO;" << endl; 
- 
-  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { 
-    out << indent() << "if (_" << (*f_iter)->get_name() << "IsSet) {" << endl; 
-    indent_up(); 
-    bool null_allowed = type_can_be_null((*f_iter)->get_type()); 
-    if (null_allowed) { 
-      out << indent() << "if (_" << (*f_iter)->get_name() << " != nil) {" << endl; 
-      indent_up(); 
-    } 
- 
-    indent(out) << "if (![outProtocol writeFieldBeginWithName: @\"" << (*f_iter)->get_name() 
-                << "\" type: " << type_to_enum((*f_iter)->get_type()) 
-                << " fieldID: " << (*f_iter)->get_key() << " error: __thriftError]) return NO;" << endl; 
- 
-    // Write field contents 
-    generate_serialize_field(out, *f_iter, "_" + (*f_iter)->get_name()); 
- 
-    // Write field closer 
-    indent(out) << "if (![outProtocol writeFieldEnd: __thriftError]) return NO;" << endl; 
- 
-    if (null_allowed) { 
-      scope_down(out); 
-    } 
-    scope_down(out); 
-  } 
-  // Write the struct map 
-  out << indent() << "if (![outProtocol writeFieldStop: __thriftError]) return NO;" << endl 
-      << indent() << "if (![outProtocol writeStructEnd: __thriftError]) return NO;" << endl; 
- 
-  indent(out) << "return YES;" << endl; 
- 
-  indent_down(); 
-  out << indent() << "}" << endl << endl; 
-} 
- 
-/** 
- * Generates a function to write all the fields of the struct, which 
- * is a function result. These fields are only written if they are 
- * set, and only one of them can be set at a time. 
- * 
- * @param tstruct The struct definition 
- */ 
-void t_cocoa_generator::generate_cocoa_struct_result_writer(ostream& out, t_struct* tstruct) { 
-  out << indent() << "- (BOOL) write: (id <TProtocol>) outProtocol error: (NSError *__autoreleasing *)__thriftError {" << endl; 
-  indent_up(); 
- 
-  string name = tstruct->get_name(); 
-  const vector<t_field*>& fields = tstruct->get_members(); 
-  vector<t_field*>::const_iterator f_iter; 
- 
-  out << indent() << "if (![outProtocol writeStructBeginWithName: @\"" << name << "\" error: __thriftError]) return NO;" << endl; 
- 
-  bool first = true; 
-  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { 
-    if (first) { 
-      first = false; 
-      out << endl << indent() << "if "; 
-    } else { 
-      out << " else if "; 
-    } 
- 
-    out << "(_" << (*f_iter)->get_name() << "IsSet) {" << endl; 
-    indent_up(); 
- 
-    bool null_allowed = type_can_be_null((*f_iter)->get_type()); 
-    if (null_allowed) { 
-      out << indent() << "if (_" << (*f_iter)->get_name() << " != nil) {" << endl; 
-      indent_up(); 
-    } 
- 
-    indent(out) << "if (![outProtocol writeFieldBeginWithName: @\"" << (*f_iter)->get_name() 
-                << "\" type: " << type_to_enum((*f_iter)->get_type()) 
-                << " fieldID: " << (*f_iter)->get_key() << " error: __thriftError]) return NO;" << endl; 
- 
-    // Write field contents 
-    generate_serialize_field(out, *f_iter, "_" + (*f_iter)->get_name()); 
- 
-    // Write field closer 
-    indent(out) << "if (![outProtocol writeFieldEnd: __thriftError]) return NO;" << endl; 
- 
-    if (null_allowed) { 
-      indent_down(); 
-      indent(out) << "}" << endl; 
-    } 
- 
-    indent_down(); 
-    indent(out) << "}"; 
-  } 
-  // Write the struct map 
-  out << endl << indent() << "if (![outProtocol writeFieldStop: __thriftError]) return NO;" 
-      << endl << indent() << "if (![outProtocol writeStructEnd: __thriftError]) return NO;" 
-      << endl; 
- 
-  indent(out) << "return YES;" << endl; 
- 
-  indent_down(); 
-  out << indent() << "}" << endl << endl; 
-} 
- 
-/** 
- * Generates a function to perform various checks 
- * (e.g. check that all required fields are set) 
- * 
- * @param tstruct The struct definition 
- */ 
-void t_cocoa_generator::generate_cocoa_struct_validator(ostream& out, t_struct* tstruct) { 
-  out << indent() << "- (BOOL) validate: (NSError *__autoreleasing *)__thriftError {" << endl; 
-  indent_up(); 
- 
-  const vector<t_field*>& fields = tstruct->get_members(); 
-  vector<t_field*>::const_iterator f_iter; 
- 
-  out << indent() << "// check for required fields" << endl; 
-  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { 
-    t_field* field = (*f_iter); 
-    if ((*f_iter)->get_req() == t_field::T_REQUIRED) { 
-      out << indent() << "if (!_" << field->get_name() << "IsSet) "; 
-      scope_up(out); 
-      indent(out) << "if (__thriftError) "; 
-      scope_up(out); 
-      out << indent() << "*__thriftError = [NSError errorWithDomain: TProtocolErrorDomain" << endl 
-          << indent() << "                                     code: TProtocolErrorUnknown" << endl 
-          << indent() << "                                 userInfo: @{TProtocolErrorExtendedErrorKey: @(TProtocolExtendedErrorMissingRequiredField)," << endl 
-          << indent() << "                                             TProtocolErrorFieldNameKey: @\"" << (*f_iter)->get_name() << "\"}];" << endl; 
-      scope_down(out); 
-      scope_down(out); 
-    } 
-  } 
-  indent(out) << "return YES;" << endl; 
-  indent_down(); 
-  out << indent() << "}" << endl << endl; 
-} 
- 
-/** 
- * Generate property accessor methods for all fields in the struct. 
- * getter, setter, isset getter. 
- * 
- * @param tstruct The struct definition 
- */ 
-void t_cocoa_generator::generate_cocoa_struct_field_accessor_implementations(ostream& out, 
-                                                                             t_struct* tstruct, 
-                                                                             bool is_exception) { 
-  (void)is_exception; 
-  const vector<t_field*>& fields = tstruct->get_members(); 
-  vector<t_field*>::const_iterator f_iter; 
-  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { 
-    t_field* field = *f_iter; 
-    t_type* type = get_true_type(field->get_type()); 
-    std::string field_name = field->get_name(); 
-    std::string cap_name = field_name; 
-    cap_name[0] = toupper(cap_name[0]); 
- 
-    // Simple setter 
-    indent(out) << "- (void) set" << cap_name << ": (" << type_name(type, false, true) << ") " << field_name 
-                << " {" << endl; 
-    indent_up(); 
-    indent(out) << "_" << field_name << " = " << field_name << ";" << endl; 
-    indent(out) << "_" << field_name << "IsSet = YES;" << endl; 
-    indent_down(); 
-    indent(out) << "}" << endl << endl; 
- 
-    // Unsetter - do we need this? 
-    indent(out) << "- (void) unset" << cap_name << " {" << endl; 
-    indent_up(); 
-    if (type_can_be_null(type)) { 
-      indent(out) << "_" << field_name << " = nil;" << endl; 
-    } 
-    indent(out) << "_" << field_name << "IsSet = NO;" << endl; 
-    indent_down(); 
-    indent(out) << "}" << endl << endl; 
-  } 
-} 
- 
-/** 
- * Generates a description method for the given struct 
- * 
- * @param tstruct The struct definition 
- */ 
-void t_cocoa_generator::generate_cocoa_struct_description(ostream& out, t_struct* tstruct) { 
- 
-  // Allow use of debugDescription so the app can add description via a cateogory/extension 
-  if (debug_descriptions_) { 
-    out << indent() << "- (NSString *) debugDescription {" << endl; 
-  } 
-  else { 
-    out << indent() << "- (NSString *) description {" << endl; 
-  } 
-  indent_up(); 
- 
-  out << indent() << "NSMutableString * ms = [NSMutableString stringWithString: @\"" 
-      << cocoa_prefix_ << tstruct->get_name() << "(\"];" << endl; 
- 
-  const vector<t_field*>& fields = tstruct->get_members(); 
-  vector<t_field*>::const_iterator f_iter; 
-  bool first = true; 
-  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { 
-    if (first) { 
-      first = false; 
-      indent(out) << "[ms appendString: @\"" << (*f_iter)->get_name() << ":\"];" << endl; 
-    } else { 
-      indent(out) << "[ms appendString: @\"," << (*f_iter)->get_name() << ":\"];" << endl; 
-    } 
-    t_type* ttype = (*f_iter)->get_type(); 
-    indent(out) << "[ms appendFormat: @\"" << format_string_for_type(ttype) << "\", " 
-                << format_cast_for_type(ttype) << "_" << (*f_iter)->get_name() << "];" << endl; 
-  } 
-  out << indent() << "[ms appendString: @\")\"];" << endl << indent() 
-      << "return [NSString stringWithString: ms];" << endl; 
- 
-  indent_down(); 
-  indent(out) << "}" << endl << endl; 
-} 
- 
-/** 
- * Generates a thrift service.  In Objective-C this consists of a 
- * protocol definition, a client interface and a client implementation. 
- * 
- * @param tservice The service definition 
- */ 
-void t_cocoa_generator::generate_service(t_service* tservice) { 
-  generate_cocoa_service_protocol(f_header_, tservice); 
-  generate_cocoa_service_client_interface(f_header_, tservice); 
-  generate_cocoa_service_server_interface(f_header_, tservice); 
-  generate_cocoa_service_helpers(tservice); 
-  generate_cocoa_service_client_implementation(f_impl_, tservice); 
-  generate_cocoa_service_server_implementation(f_impl_, tservice); 
-  if (async_clients_) { 
-    generate_cocoa_service_async_protocol(f_header_, tservice); 
-    generate_cocoa_service_client_async_interface(f_header_, tservice); 
-    generate_cocoa_service_client_async_implementation(f_impl_, tservice); 
-  } 
-} 
- 
-/** 
- * Generates structs for all the service return types 
- * 
- * @param tservice The service 
- */ 
-void t_cocoa_generator::generate_cocoa_service_helpers(t_service* tservice) { 
-  vector<t_function*> functions = tservice->get_functions(); 
-  vector<t_function*>::iterator f_iter; 
-  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) { 
- 
-    t_struct* ts = (*f_iter)->get_arglist(); 
- 
-    string qname = function_args_helper_struct_type(tservice, *f_iter); 
- 
-    t_struct qname_ts = t_struct(ts->get_program(), qname); 
- 
-    const vector<t_field*>& members = ts->get_members(); 
-    vector<t_field*>::const_iterator m_iter; 
-    for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { 
-      qname_ts.append(*m_iter); 
-    } 
- 
-    generate_cocoa_struct_interface(f_impl_, &qname_ts, false); 
-    generate_cocoa_struct_implementation(f_impl_, &qname_ts, false, false); 
-    generate_function_helpers(tservice, *f_iter); 
-  } 
-} 
- 
-string t_cocoa_generator::function_result_helper_struct_type(t_service *tservice, t_function* tfunction) { 
-  if (tfunction->is_oneway()) { 
-    return tservice->get_name() + "_" + tfunction->get_name(); 
-  } else { 
-    return tservice->get_name() + "_" + tfunction->get_name() + "_result"; 
-  } 
-} 
- 
-string t_cocoa_generator::function_args_helper_struct_type(t_service *tservice, t_function* tfunction) { 
-  return tservice->get_name() + "_" + tfunction->get_name() + "_args"; 
-} 
- 
-/** 
- * Generates a struct and helpers for a function. 
- * 
- * @param tfunction The function 
- */ 
-void t_cocoa_generator::generate_function_helpers(t_service *tservice, t_function* tfunction) { 
-  if (tfunction->is_oneway()) { 
-    return; 
-  } 
- 
-  // create a result struct with a success field of the return type, 
-  // and a field for each type of exception thrown 
-  t_struct result(program_, function_result_helper_struct_type(tservice, tfunction)); 
-  t_field success(tfunction->get_returntype(), "success", 0); 
-  if (!tfunction->get_returntype()->is_void()) { 
-    result.append(&success); 
-  } 
- 
-  t_struct* xs = tfunction->get_xceptions(); 
-  const vector<t_field*>& fields = xs->get_members(); 
-  vector<t_field*>::const_iterator f_iter; 
-  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { 
-    result.append(*f_iter); 
-  } 
- 
-  // generate the result struct 
-  generate_cocoa_struct_interface(f_impl_, &result, false); 
-  generate_cocoa_struct_implementation(f_impl_, &result, false, true); 
-} 
- 
-/** 
- * Generates a service protocol definition. 
- * 
- * @param tservice The service to generate a protocol definition for 
- */ 
-void t_cocoa_generator::generate_cocoa_service_protocol(ostream& out, t_service* tservice) { 
-  out << "@protocol " << cocoa_prefix_ << tservice->get_name() << " <NSObject>" << endl; 
- 
-  vector<t_function*> functions = tservice->get_functions(); 
-  vector<t_function*>::iterator f_iter; 
-  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) { 
-    out << "- " << function_signature(*f_iter, true) << ";" 
-        << "  // throws "; 
-    t_struct* xs = (*f_iter)->get_xceptions(); 
-    const std::vector<t_field*>& xceptions = xs->get_members(); 
-    vector<t_field*>::const_iterator x_iter; 
-    for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) { 
-      out << type_name((*x_iter)->get_type()) + ", "; 
-    } 
-    out << "TException" << endl; 
-  } 
-  out << "@end" << endl << endl; 
-} 
- 
-/** 
- * Generates an asynchronous service protocol definition. 
- * 
- * @param tservice The service to generate a protocol definition for 
- */ 
-void t_cocoa_generator::generate_cocoa_service_async_protocol(ostream& out, t_service* tservice) { 
-  out << "@protocol " << cocoa_prefix_ << tservice->get_name() << "Async" 
-      << " <NSObject>" << endl; 
- 
-  vector<t_function*> functions = tservice->get_functions(); 
-  vector<t_function*>::iterator f_iter; 
-  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) { 
-    out << "- " << async_function_signature(*f_iter, false) << ";" << endl; 
-    if (promise_kit_) { 
-      out << "- " << promise_function_signature(*f_iter) << ";" << endl; 
-    } 
-  } 
-  out << "@end" << endl << endl; 
-} 
- 
-/** 
- * Generates a service client interface definition. 
- * 
- * @param tservice The service to generate a client interface definition for 
- */ 
-void t_cocoa_generator::generate_cocoa_service_client_interface(ostream& out, 
-                                                                t_service* tservice) { 
-  out << "@interface " << cocoa_prefix_ << tservice->get_name() << "Client : TBaseClient <" 
-      << cocoa_prefix_ << tservice->get_name() << "> " << endl; 
- 
-  out << "- (id) initWithProtocol: (id <TProtocol>) protocol;" << endl; 
-  out << "- (id) initWithInProtocol: (id <TProtocol>) inProtocol outProtocol: (id <TProtocol>) " 
-         "outProtocol;" << endl; 
-  out << "@end" << endl << endl; 
-} 
- 
-/** 
- * Generates a service client interface definition. 
- * 
- * @param tservice The service to generate a client interface definition for 
- */ 
-void t_cocoa_generator::generate_cocoa_service_client_async_interface(ostream& out, 
-                                                                      t_service* tservice) { 
-  out << "@interface " << cocoa_prefix_ << tservice->get_name() << "ClientAsync : TBaseClient <" 
-      << cocoa_prefix_ << tservice->get_name() << "Async> " << endl 
-      << endl; 
- 
-  out << "- (id) initWithProtocolFactory: (id <TProtocolFactory>) protocolFactory " 
-      << "transportFactory: (id <TAsyncTransportFactory>) transportFactory;" << endl; 
-  out << "@end" << endl << endl; 
-} 
- 
-/** 
- * Generates a service server interface definition. In other words, the TProcess implementation for 
- *the 
- * service definition. 
- * 
- * @param tservice The service to generate a client interface definition for 
- */ 
-void t_cocoa_generator::generate_cocoa_service_server_interface(ostream& out, 
-                                                                t_service* tservice) { 
-  out << "@interface " << cocoa_prefix_ << tservice->get_name() 
-      << "Processor : NSObject <TProcessor> " << endl; 
- 
-  out << "- (id) initWith" << tservice->get_name() << ": (id <" << cocoa_prefix_ 
-      << tservice->get_name() << ">) service;" << endl; 
-  out << "- (id<" << cocoa_prefix_ << tservice->get_name() << ">) service;" << endl; 
- 
-  out << "@end" << endl << endl; 
-} 
- 
-void t_cocoa_generator::generate_cocoa_service_client_send_function_implementation( 
-    ostream& out, 
-    t_service *tservice, 
-    t_function* tfunction, 
-    bool needs_protocol) { 
-  string funname = tfunction->get_name(); 
- 
-  t_function send_function(g_type_bool, 
-                           string("send_") + tfunction->get_name(), 
-                           tfunction->get_arglist()); 
- 
-  string argsname = function_args_helper_struct_type(tservice, tfunction); 
- 
-  // Open function 
-  indent(out) << "- (BOOL) send_" << tfunction->get_name() << argument_list(tfunction->get_arglist(), needs_protocol ? "outProtocol" : "", true) << endl; 
-  scope_up(out); 
- 
-  // Serialize the request 
-  out << indent() << "if (![outProtocol writeMessageBeginWithName: @\"" << funname << "\"" 
-      << (tfunction->is_oneway() ? " type: TMessageTypeONEWAY" : " type: TMessageTypeCALL") 
-      << " sequenceID: 0 error: __thriftError]) return NO;" << endl; 
- 
-  out << indent() << "if (![outProtocol writeStructBeginWithName: @\"" << argsname 
-                  << "\" error: __thriftError]) return NO;" << endl; 
- 
-  // write out function parameters 
-  t_struct* arg_struct = tfunction->get_arglist(); 
-  const vector<t_field*>& fields = arg_struct->get_members(); 
-  vector<t_field*>::const_iterator fld_iter; 
-  for (fld_iter = fields.begin(); fld_iter != fields.end(); ++fld_iter) { 
-    string fieldName = (*fld_iter)->get_name(); 
-    if (type_can_be_null((*fld_iter)->get_type())) { 
-      out << indent() << "if (" << fieldName << " != nil)"; 
-      scope_up(out); 
-    } 
-    out << indent() << "if (![outProtocol writeFieldBeginWithName: @\"" << fieldName 
-        << "\"" 
-           " type: " << type_to_enum((*fld_iter)->get_type()) 
-        << " fieldID: " << (*fld_iter)->get_key() << " error: __thriftError]) return NO;" << endl; 
- 
-    generate_serialize_field(out, *fld_iter, fieldName); 
- 
-    out << indent() << "if (![outProtocol writeFieldEnd: __thriftError]) return NO;" << endl; 
- 
-    if (type_can_be_null((*fld_iter)->get_type())) { 
-      indent_down(); 
-      out << indent() << "}" << endl; 
-    } 
-  } 
- 
-  out << indent() << "if (![outProtocol writeFieldStop: __thriftError]) return NO;" << endl; 
-  out << indent() << "if (![outProtocol writeStructEnd: __thriftError]) return NO;" << endl; 
-  out << indent() << "if (![outProtocol writeMessageEnd: __thriftError]) return NO;" << endl; 
-  out << indent() << "return YES;" << endl; 
-  scope_down(out); 
-  out << endl; 
-} 
- 
-void t_cocoa_generator::generate_cocoa_service_client_recv_function_implementation( 
-    ostream& out, 
-    t_service* tservice, 
-    t_function* tfunction, 
-    bool needs_protocol) { 
- 
- 
-  // Open function 
-  indent(out) << "- (BOOL) recv_" << tfunction->get_name(); 
-  if (!tfunction->get_returntype()->is_void()) { 
-    out << ": (" << type_name(tfunction->get_returntype(), false, true) << " *) result "; 
-    if (needs_protocol) { 
-      out << "protocol"; 
-    } else { 
-      out << "error"; 
-    } 
-  } 
-  if (needs_protocol) { 
-    out << ": (id<TProtocol>) inProtocol error"; 
-  } 
-  out << ": (NSError *__autoreleasing *)__thriftError" << endl; 
-  scope_up(out); 
- 
-  // TODO(mcslee): Message validation here, was the seqid etc ok? 
- 
-  // check for an exception 
-  out << indent() << "NSError *incomingException = [self checkIncomingMessageException: inProtocol];" << endl 
-      << indent() << "if (incomingException)"; 
-  scope_up(out); 
-  out << indent() << "if (__thriftError)"; 
-  scope_up(out); 
-  out << indent() << "*__thriftError = incomingException;" << endl; 
-  scope_down(out); 
-  out << indent() << "return NO;" << endl; 
-  scope_down(out); 
- 
-  // FIXME - could optimize here to reduce creation of temporary objects. 
-  string resultname = function_result_helper_struct_type(tservice, tfunction); 
-  out << indent() << cocoa_prefix_ << resultname << " * resulter = [" << cocoa_prefix_ << resultname << " new];" << endl; 
-  indent(out) << "if (![resulter read: inProtocol error: __thriftError]) return NO;" << endl; 
-  indent(out) << "if (![inProtocol readMessageEnd: __thriftError]) return NO;" << endl; 
- 
-  // Careful, only return _result if not a void function 
-  if (!tfunction->get_returntype()->is_void()) { 
-    out << indent() << "if (resulter.successIsSet)"; 
-    scope_up(out); 
-    out << indent() << "*result = resulter.success;" << endl; 
-    out << indent() << "return YES;" << endl; 
-    scope_down(out); 
-  } 
- 
-  t_struct* xs = tfunction->get_xceptions(); 
-  const std::vector<t_field*>& xceptions = xs->get_members(); 
-  vector<t_field*>::const_iterator x_iter; 
-  for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) { 
-    out << indent() << "if (resulter." << (*x_iter)->get_name() << "IsSet)"; 
-    scope_up(out); 
-    out << indent() << "if (__thriftError)"; 
-    scope_up(out); 
-    out << indent() << "*__thriftError = [resulter " << (*x_iter)->get_name() << "];" << endl; 
-    scope_down(out); 
-    out << indent() << "return NO;" << endl; 
-    scope_down(out); 
-  } 
- 
-  // If you get here it's an exception, unless a void function 
-  if (tfunction->get_returntype()->is_void()) { 
-    indent(out) << "return YES;" << endl; 
-  } else { 
-    out << indent() << "if (__thriftError)"; 
-    scope_up(out); 
-    out << indent() << "*__thriftError = [NSError errorWithDomain: TApplicationErrorDomain" << endl 
-        << indent() << "                                     code: TApplicationErrorMissingResult" << endl 
-        << indent() << "                                 userInfo: @{TApplicationErrorMethodKey: @\"" 
-        << tfunction->get_name() << "\"}];" << endl; 
-    scope_down(out); 
-    out << indent() << "return NO;" << endl; 
-  } 
- 
-  // Close function 
-  scope_down(out); 
-  out << endl; 
-} 
- 
-/** 
- * Generates an invocation of a given 'send_' function. 
- * 
- * @param tfunction The service to generate an implementation for 
- */ 
-void t_cocoa_generator::generate_cocoa_service_client_send_function_invocation( 
-                                                                               ostream& out, 
-                                                                               t_function* tfunction) { 
- 
-  t_struct* arg_struct = tfunction->get_arglist(); 
-  const vector<t_field*>& fields = arg_struct->get_members(); 
-  vector<t_field*>::const_iterator fld_iter; 
-  out << indent() << "if (![self send_" << tfunction->get_name(); 
-  bool first = true; 
-  for (fld_iter = fields.begin(); fld_iter != fields.end(); ++fld_iter) { 
-    string fieldName = (*fld_iter)->get_name(); 
-    out << " "; 
-    if (first) { 
-      first = false; 
-      out << ": " << fieldName; 
-    } else { 
-      out << fieldName << ": " << fieldName; 
-    } 
-  } 
-  if (!fields.empty()) { 
-    out << " error"; 
-  } 
-  out << ": __thriftError]) " << invalid_return_statement(tfunction) << endl; 
-} 
- 
-/** 
- * Generates an invocation of a given 'send_' function. 
- * 
- * @param tfunction The service to generate an implementation for 
- */ 
-void t_cocoa_generator::generate_cocoa_service_client_send_async_function_invocation( 
-                                                                                     ostream& out, 
-                                                                                     t_function* tfunction, 
-                                                                                     string failureBlockName) { 
- 
-  t_struct* arg_struct = tfunction->get_arglist(); 
-  const vector<t_field*>& fields = arg_struct->get_members(); 
-  vector<t_field*>::const_iterator fld_iter; 
-  out << indent() << "if (![self send_" << tfunction->get_name(); 
-  bool first = true; 
-  for (fld_iter = fields.begin(); fld_iter != fields.end(); ++fld_iter) { 
-    string fieldName = (*fld_iter)->get_name(); 
-    out << " "; 
-    if (first) { 
-      first = false; 
-      out << ": " << fieldName; 
-    } else { 
-      out << fieldName << ": " << fieldName; 
-    } 
-  } 
-  if (!fields.empty()) { 
-    out << " protocol"; 
-  } 
-  out << ": protocol error: &thriftError]) "; 
-  scope_up(out); 
-  out << indent() << failureBlockName << "(thriftError);" << endl 
-      << indent() << "return;" << endl; 
-  scope_down(out); 
-} 
- 
-/** 
- * Generates a service client implementation. 
- * 
- * @param tservice The service to generate an implementation for 
- */ 
-void t_cocoa_generator::generate_cocoa_service_client_implementation(ostream& out, 
-                                                                     t_service* tservice) { 
- 
-  string name = cocoa_prefix_ + tservice->get_name() + "Client"; 
- 
-  out << "@interface " << name << " () "; 
-  scope_up(out); 
-  out << endl; 
-  out << indent() << "id<TProtocol> inProtocol;" << endl; 
-  out << indent() << "id<TProtocol> outProtocol;" << endl; 
-  out << endl; 
-  scope_down(out); 
-  out << endl; 
-  out << "@end" << endl << endl; 
- 
-  out << "@implementation " << name << endl; 
- 
-  // initializers 
-  out << "- (id) initWithProtocol: (id <TProtocol>) protocol" << endl; 
-  scope_up(out); 
-  out << indent() << "return [self initWithInProtocol: protocol outProtocol: protocol];" << endl; 
-  scope_down(out); 
-  out << endl; 
- 
-  out << "- (id) initWithInProtocol: (id <TProtocol>) anInProtocol outProtocol: (id <TProtocol>) " 
-         "anOutProtocol" << endl; 
-  scope_up(out); 
-  out << indent() << "self = [super init];" << endl; 
-  out << indent() << "if (self) "; 
-  scope_up(out); 
-  out << indent() << "inProtocol = anInProtocol;" << endl; 
-  out << indent() << "outProtocol = anOutProtocol;" << endl; 
-  scope_down(out); 
-  out << indent() << "return self;" << endl; 
-  scope_down(out); 
-  out << endl; 
- 
-  // generate client method implementations 
-  vector<t_function*> functions = tservice->get_functions(); 
-  vector<t_function*>::const_iterator f_iter; 
-  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) { 
- 
-    generate_cocoa_service_client_send_function_implementation(out, tservice, *f_iter, false); 
- 
-    if (!(*f_iter)->is_oneway()) { 
-      generate_cocoa_service_client_recv_function_implementation(out, tservice, *f_iter, false); 
-    } 
- 
-    // Open function 
-    indent(out) << "- " << function_signature(*f_iter, true) << endl; 
-    scope_up(out); 
-    generate_cocoa_service_client_send_function_invocation(out, *f_iter); 
- 
-    out << indent() << "if (![[outProtocol transport] flush: __thriftError]) " << invalid_return_statement(*f_iter) << endl; 
-    if (!(*f_iter)->is_oneway()) { 
-      if ((*f_iter)->get_returntype()->is_void()) { 
-        out << indent() << "if (![self recv_" << (*f_iter)->get_name() << ": __thriftError]) return NO;" << endl; 
-        out << indent() << "return YES;" << endl; 
-      } else { 
-        out << indent() << type_name((*f_iter)->get_returntype(), false, true) << " __result;" << endl 
-            << indent() << "if (![self recv_" << (*f_iter)->get_name() << ": &__result error: __thriftError]) " 
-            << invalid_return_statement(*f_iter) << endl; 
-        if (type_can_be_null((*f_iter)->get_returntype())) { 
-          out << indent() << "return __result;" << endl; 
-        } else { 
-          out << indent() << "return @(__result);" << endl; 
-        } 
-      } 
-    } 
-    else { 
-      out << indent() << "return YES;" << endl; 
-    } 
-    scope_down(out); 
-    out << endl; 
-  } 
- 
-  out << "@end" << endl << endl; 
-} 
- 
-/** 
- * Generates a service client implementation for its asynchronous interface. 
- * 
- * @param tservice The service to generate an implementation for 
- */ 
-void t_cocoa_generator::generate_cocoa_service_client_async_implementation(ostream& out, 
-                                                                           t_service* tservice) { 
- 
-  string name = cocoa_prefix_ + tservice->get_name() + "ClientAsync"; 
- 
-  out << "@interface " << name << " () "; 
-  scope_up(out); 
-  out << endl; 
-  out << indent() << "id<TProtocolFactory> protocolFactory;" << endl; 
-  out << indent() << "id<TAsyncTransportFactory> transportFactory;" << endl; 
-  out << endl; 
-  scope_down(out); 
-  out << endl; 
-  out << "@end" << endl << endl; 
- 
- 
-  out << "@implementation " << name << endl 
-      << endl << "- (id) initWithProtocolFactory: (id <TProtocolFactory>) aProtocolFactory " 
-                 "transportFactory: (id <TAsyncTransportFactory>) aTransportFactory;" << endl; 
- 
-  scope_up(out); 
-  out << indent() << "self = [super init];" << endl; 
-  out << indent() << "if (self) {" << endl; 
-  out << indent() << "  protocolFactory = aProtocolFactory;" << endl; 
-  out << indent() << "  transportFactory = aTransportFactory;" << endl; 
-  out << indent() << "}" << endl; 
-  out << indent() << "return self;" << endl; 
-  scope_down(out); 
-  out << endl; 
- 
-  // generate client method implementations 
-  vector<t_function*> functions = tservice->get_functions(); 
-  vector<t_function*>::const_iterator f_iter; 
-  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) { 
- 
-    generate_cocoa_service_client_send_function_implementation(out, tservice, *f_iter, true); 
- 
-    if (!(*f_iter)->is_oneway()) { 
-      generate_cocoa_service_client_recv_function_implementation(out, tservice, *f_iter, true); 
-    } 
- 
-    // Open function 
-    indent(out) << "- " << async_function_signature(*f_iter, false) << endl; 
-    scope_up(out); 
- 
-    out << indent() << "NSError *thriftError;" << endl 
-        << indent() << "id<TAsyncTransport> transport = [transportFactory newTransport];" << endl 
-        << indent() << "id<TProtocol> protocol = [protocolFactory newProtocolOnTransport:transport];" << endl 
-        << endl; 
- 
-    generate_cocoa_service_client_send_async_function_invocation(out, *f_iter, "failureBlock"); 
- 
-    out << indent() << "[transport flushWithCompletion:^{" << endl; 
-    indent_up(); 
- 
-    if (!(*f_iter)->is_oneway()) { 
-      out << indent() << "NSError *thriftError;" << endl; 
- 
-      if (!(*f_iter)->get_returntype()->is_void()) { 
-        out << indent() << type_name((*f_iter)->get_returntype()) << " result;" << endl; 
-      } 
-      out << indent() << "if (![self recv_" << (*f_iter)->get_name(); 
-      if (!(*f_iter)->get_returntype()->is_void()) { 
-        out << ": &result protocol"; 
-      } 
-      out << ": protocol error: &thriftError]) "; 
-      scope_up(out); 
-      out << indent() << "failureBlock(thriftError);" << endl 
-          << indent() << "return;" << endl; 
-      scope_down(out); 
-    } 
- 
-    out << indent() << "responseBlock("; 
-    if (!(*f_iter)->is_oneway() && !(*f_iter)->get_returntype()->is_void()) { 
-      out << "result"; 
-    } 
-    out << ");" << endl; 
- 
-    indent_down(); 
- 
-    out << indent() << "} failure:failureBlock];" << endl; 
- 
-    scope_down(out); 
- 
-    out << endl; 
- 
-    // Promise function 
-    if (promise_kit_) { 
- 
-      indent(out) << "- " << promise_function_signature(*f_iter) << endl; 
-      scope_up(out); 
- 
-      out << indent() << "return [AnyPromise promiseWithResolverBlock:^(PMKResolver resolver) {" << endl; 
-      indent_up(); 
- 
-      out << indent() << "NSError *thriftError;" << endl 
-          << indent() << "id<TAsyncTransport> transport = [transportFactory newTransport];" << endl 
-          << indent() << "id<TProtocol> protocol = [protocolFactory newProtocolOnTransport:transport];" << endl 
-          << endl; 
- 
-      generate_cocoa_service_client_send_async_function_invocation(out, *f_iter, "resolver"); 
- 
-      out << indent() << "[transport flushWithCompletion:^{" << endl; 
-      indent_up(); 
- 
-      if (!(*f_iter)->is_oneway()) { 
-        out << indent() << "NSError *thriftError;" << endl; 
- 
-        if (!(*f_iter)->get_returntype()->is_void()) { 
-          out << indent() << type_name((*f_iter)->get_returntype()) << " result;" << endl; 
-        } 
-        out << indent() << "if (![self recv_" << (*f_iter)->get_name(); 
-        if (!(*f_iter)->get_returntype()->is_void()) { 
-          out << ": &result protocol"; 
-        } 
-        out << ": protocol error: &thriftError]) "; 
-        scope_up(out); 
-        out << indent() << "resolver(thriftError);" << endl 
-            << indent() << "return;" << endl; 
-        scope_down(out); 
-      } 
- 
-      out << indent() << "resolver("; 
-      if ((*f_iter)->is_oneway() || (*f_iter)->get_returntype()->is_void()) { 
-        out << "@YES"; 
-      } else if (type_can_be_null((*f_iter)->get_returntype())) { 
-        out << "result"; 
-      } else { 
-        out << "@(result)"; 
-      } 
-      out << ");" << endl; 
- 
-      indent_down(); 
- 
-      out << indent() << "} failure:^(NSError *error) {" << endl; 
-      indent_up(); 
-      out << indent() << "resolver(error);" << endl; 
-      indent_down(); 
-      out << indent() << "}];" << endl; 
- 
-      indent_down(); 
-      out << indent() << "}];" << endl; 
- 
-      scope_down(out); 
- 
-      out << endl; 
- 
-    } 
- 
-  } 
- 
-  out << "@end" << endl << endl; 
-} 
- 
-/** 
- * Generates a service server implementation.  In other words the actual TProcessor implementation 
- * for the service. 
- * 
- * @param tservice The service to generate an implementation for 
- */ 
-void t_cocoa_generator::generate_cocoa_service_server_implementation(ostream& out, 
-                                                                     t_service* tservice) { 
- 
-  string name = cocoa_prefix_ + tservice->get_name() + "Processor"; 
- 
-  out << "@interface " << name << " () "; 
- 
-  scope_up(out); 
-  out << indent() << "id <" << cocoa_prefix_ << tservice->get_name() << "> service;" << endl; 
-  out << indent() << "NSDictionary * methodMap;" << endl; 
-  scope_down(out); 
- 
-  out << "@end" << endl << endl; 
- 
-  out << "@implementation " << name << endl; 
- 
-  // initializer 
-  out << endl; 
-  out << "- (id) initWith" << tservice->get_name() << ": (id <" << cocoa_prefix_ << tservice->get_name() << ">) aService" << endl; 
-  scope_up(out); 
-  out << indent() << "self = [super init];" << endl; 
-  out << indent() << "if (self) "; 
-  scope_up(out); 
-  out << indent() << "service = aService;" << endl; 
-  out << indent() << "methodMap = [NSMutableDictionary dictionary];" << endl; 
- 
-  // generate method map for routing incoming calls 
-  vector<t_function*> functions = tservice->get_functions(); 
-  vector<t_function*>::const_iterator f_iter; 
-  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) { 
-    string funname = (*f_iter)->get_name(); 
-    scope_up(out); 
-    out << indent() << "SEL s = @selector(process_" << funname << "_withSequenceID:inProtocol:outProtocol:error:);" << endl; 
-    out << indent() << "NSMethodSignature * sig = [self methodSignatureForSelector: s];" << endl; 
-    out << indent() << "NSInvocation * invocation = [NSInvocation invocationWithMethodSignature: sig];" << endl; 
-    out << indent() << "[invocation setSelector: s];" << endl; 
-    out << indent() << "[invocation retainArguments];" << endl; 
-    out << indent() << "[methodMap setValue: invocation forKey: @\"" << funname << "\"];" << endl; 
-    scope_down(out); 
-  } 
-  scope_down(out); 
-  out << indent() << "return self;" << endl; 
-  scope_down(out); 
- 
-  // implementation of the 'service' method which returns the service associated with this 
-  // processor 
-  out << endl; 
-  out << indent() << "- (id<" << cocoa_prefix_ << tservice->get_name() << ">) service" << endl; 
-  out << indent() << "{" << endl; 
-  out << indent() << "  return service;" << endl; 
-  out << indent() << "}" << endl; 
- 
-  // implementation of the TProcess method, which dispatches the incoming call using the method map 
-  out << endl; 
-  out << indent() << "- (BOOL) processOnInputProtocol: (id <TProtocol>) inProtocol" << endl; 
-  out << indent() << "                 outputProtocol: (id <TProtocol>) outProtocol" << endl; 
-  out << indent() << "                          error: (NSError *__autoreleasing *)__thriftError" << endl; 
-  out << indent() << "{" << endl; 
-  out << indent() << "  NSString * messageName;" << endl; 
-  out << indent() << "  SInt32 messageType;" << endl; 
-  out << indent() << "  SInt32 seqID;" << endl; 
-  out << indent() << "  if (![inProtocol readMessageBeginReturningName: &messageName" << endl; 
-  out << indent() << "                                       type: &messageType" << endl; 
-  out << indent() << "                                 sequenceID: &seqID" << endl; 
-  out << indent() << "                                      error: __thriftError]) return NO;" << endl; 
-  out << indent() << "  NSInvocation * invocation = [methodMap valueForKey: messageName];" << endl; 
-  out << indent() << "  if (invocation == nil) {" << endl; 
-  out << indent() << "    if (![TProtocolUtil skipType: TTypeSTRUCT onProtocol: inProtocol error: __thriftError]) return NO;" << endl; 
-  out << indent() << "    if (![inProtocol readMessageEnd: __thriftError]) return NO;" << endl; 
-  out << indent() << "    NSError * x = [NSError errorWithDomain: TApplicationErrorDomain" << endl; 
-  out << indent() << "                                      code: TApplicationErrorUnknownMethod" << endl; 
-  out << indent() << "                                  userInfo: @{TApplicationErrorMethodKey: messageName}];" << endl; 
-  out << indent() << "    if (![outProtocol writeMessageBeginWithName: messageName" << endl; 
-  out << indent() << "                                           type: TMessageTypeEXCEPTION" << endl; 
-  out << indent() << "                                     sequenceID: seqID" << endl; 
-  out << indent() << "                                          error: __thriftError]) return NO;" << endl; 
-  out << indent() << "    if (![x write: outProtocol error: __thriftError]) return NO;" << endl; 
-  out << indent() << "    if (![outProtocol writeMessageEnd: __thriftError]) return NO;" << endl; 
-  out << indent() << "    if (![[outProtocol transport] flush: __thriftError]) return NO;" << endl; 
-  out << indent() << "    return YES;" << endl; 
-  out << indent() << "  }" << endl; 
-  out << indent() << "  // NSInvocation does not conform to NSCopying protocol" << endl; 
-  out << indent() << "  NSInvocation * i = [NSInvocation invocationWithMethodSignature: " 
-                     "[invocation methodSignature]];" << endl; 
-  out << indent() << "  [i setSelector: [invocation selector]];" << endl; 
-  out << indent() << "  [i setArgument: &seqID atIndex: 2];" << endl; 
-  out << indent() << "  [i setArgument: &inProtocol atIndex: 3];" << endl; 
-  out << indent() << "  [i setArgument: &outProtocol atIndex: 4];" << endl; 
-  out << indent() << "  [i setArgument: &__thriftError atIndex: 5];" << endl; 
-  out << indent() << "  [i setTarget: self];" << endl; 
-  out << indent() << "  [i invoke];" << endl; 
-  out << indent() << "  return YES;" << endl; 
-  out << indent() << "}" << endl; 
- 
-  // generate a process_XXXX method for each service function, which reads args, calls the service, 
-  // and writes results 
-  functions = tservice->get_functions(); 
-  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) { 
-    out << endl; 
-    string funname = (*f_iter)->get_name(); 
-    out << indent() << "- (BOOL) process_" << funname 
-        << "_withSequenceID: (SInt32) seqID inProtocol: (id<TProtocol>) inProtocol outProtocol: " 
-           "(id<TProtocol>) outProtocol error:(NSError *__autoreleasing *)__thriftError" << endl; 
-    scope_up(out); 
-    string argstype = cocoa_prefix_ + function_args_helper_struct_type(tservice, *f_iter); 
-    out << indent() << argstype << " * args = [" << argstype << " new];" << endl; 
-    out << indent() << "if (![args read: inProtocol error: __thriftError]) return NO;" << endl; 
-    out << indent() << "if (![inProtocol readMessageEnd: __thriftError]) return NO;" << endl; 
- 
-    // prepare the result if not oneway 
-    if (!(*f_iter)->is_oneway()) { 
-      string resulttype = cocoa_prefix_ + function_result_helper_struct_type(tservice, *f_iter); 
-      out << indent() << resulttype << " * result = [" << resulttype << " new];" << endl; 
-    } 
- 
-    // make the call to the actual service object 
-    out << indent(); 
-    if ((*f_iter)->get_returntype()->is_void()) { 
-      out << "BOOL"; 
-    } else if (type_can_be_null((*f_iter)->get_returntype())) { 
-      out << type_name((*f_iter)->get_returntype(), false, true); 
-    } else { 
-      out << "NSNumber *"; 
-    } 
-    out << " serviceResult = "; 
-    if ((*f_iter)->get_returntype()->get_true_type()->is_container()) { 
-      out << "(" << type_name((*f_iter)->get_returntype(), false, true) << ")"; 
-    } 
-    out << "[service " << funname; 
-    // supplying arguments 
-    t_struct* arg_struct = (*f_iter)->get_arglist(); 
-    const vector<t_field*>& fields = arg_struct->get_members(); 
-    vector<t_field*>::const_iterator fld_iter; 
-    bool first = true; 
-    for (fld_iter = fields.begin(); fld_iter != fields.end(); ++fld_iter) { 
-      string fieldName = (*fld_iter)->get_name(); 
-      if (first) { 
-        first = false; 
-        out << ": [args " << fieldName << "]"; 
-      } else { 
-        out << " " << fieldName << ": [args " << fieldName << "]"; 
-      } 
-    } 
-    if (!fields.empty()) { 
-      out << " error"; 
-    } 
-    out << ": __thriftError];" << endl; 
-    out << indent() << "if (!serviceResult) return NO;" << endl; 
-    if (!(*f_iter)->get_returntype()->is_void()) { 
-      out << indent() << "[result setSuccess: " << unbox((*f_iter)->get_returntype(), "serviceResult") << "];" << endl; 
-    } 
- 
-    // write out the result if not oneway 
-    if (!(*f_iter)->is_oneway()) { 
-      out << indent() << "if (![outProtocol writeMessageBeginWithName: @\"" << funname << "\"" << endl; 
-      out << indent() << "                                       type: TMessageTypeREPLY" << endl; 
-      out << indent() << "                                 sequenceID: seqID" << endl; 
-      out << indent() << "                                      error: __thriftError]) return NO;" << endl; 
-      out << indent() << "if (![result write: outProtocol error: __thriftError]) return NO;" << endl; 
-      out << indent() << "if (![outProtocol writeMessageEnd: __thriftError]) return NO;" << endl; 
-      out << indent() << "if (![[outProtocol transport] flush: __thriftError]) return NO;" << endl; 
-    } 
-    out << indent() << "return YES;" << endl; 
- 
-    scope_down(out); 
-  } 
- 
-  out << "@end" << endl << endl; 
-} 
- 
-/** 
- * Deserializes a field of any type. 
- * 
- * @param tfield The field 
- * @param fieldName The variable name for this field 
- */ 
-void t_cocoa_generator::generate_deserialize_field(ostream& out, 
-                                                   t_field* tfield, 
-                                                   string fieldName) { 
-  t_type* type = get_true_type(tfield->get_type()); 
- 
-  if (type->is_void()) { 
-    throw "CANNOT GENERATE DESERIALIZE CODE FOR void TYPE: " + tfield->get_name(); 
-  } 
- 
-  if (type->is_struct() || type->is_xception()) { 
-    generate_deserialize_struct(out, (t_struct*)type, fieldName); 
-  } else if (type->is_container()) { 
-    generate_deserialize_container(out, type, fieldName); 
-  } else if (type->is_base_type() || type->is_enum()) { 
-    indent(out) << type_name(type) << " " << fieldName << ";" << endl; 
-    indent(out) << "if (![inProtocol "; 
- 
-    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: 
-        throw "compiler error: cannot serialize void field in a struct: " + tfield->get_name(); 
-        break; 
-      case t_base_type::TYPE_STRING: 
-        if (type->is_binary()) { 
-          out << "readBinary:&" << fieldName << " error: __thriftError]"; 
-        } else { 
-          out << "readString:&" << fieldName << " error: __thriftError]"; 
-        } 
-        break; 
-      case t_base_type::TYPE_BOOL: 
-        out << "readBool:&" << fieldName << " error: __thriftError]"; 
-        break; 
-      case t_base_type::TYPE_I8: 
-        out << "readByte:(UInt8 *)&" << fieldName << " error: __thriftError]"; 
-        break; 
-      case t_base_type::TYPE_I16: 
-        out << "readI16:&" << fieldName << " error: __thriftError]"; 
-        break; 
-      case t_base_type::TYPE_I32: 
-        out << "readI32:&" << fieldName << " error: __thriftError]"; 
-        break; 
-      case t_base_type::TYPE_I64: 
-        out << "readI64:&" << fieldName << " error: __thriftError]"; 
-        break; 
-      case t_base_type::TYPE_DOUBLE: 
-        out << "readDouble:&" << fieldName << " error: __thriftError]"; 
-        break; 
-      default: 
-        throw "compiler error: no Objective-C name for base type " 
-            + t_base_type::t_base_name(tbase); 
-      } 
-    } else if (type->is_enum()) { 
-      out << "readI32:&" << fieldName << " error: __thriftError]"; 
-    } 
-    out << ") return NO;" << endl; 
-  } else { 
-    printf("DO NOT KNOW HOW TO DESERIALIZE FIELD '%s' TYPE '%s'\n", 
-           tfield->get_name().c_str(), 
-           type_name(type).c_str()); 
-  } 
-} 
- 
-/** 
- * Generates an unserializer for a struct, allocates the struct and invokes read: 
- */ 
-void t_cocoa_generator::generate_deserialize_struct(ostream& out, 
-                                                    t_struct* tstruct, 
-                                                    string fieldName) { 
-  indent(out) << type_name(tstruct) << fieldName << " = [[" << type_name(tstruct, true) 
-              << " alloc] init];" << endl; 
-  indent(out) << "if (![" << fieldName << " read: inProtocol error: __thriftError]) return NO;" << endl; 
-} 
- 
-/** 
- * Deserializes a container by reading its size and then iterating 
- */ 
-void t_cocoa_generator::generate_deserialize_container(ostream& out, 
-                                                       t_type* ttype, 
-                                                       string fieldName) { 
-  string size = tmp("_size"); 
-  indent(out) << "SInt32 " << size << ";" << endl; 
- 
-  // Declare variables, read header 
-  if (ttype->is_map()) { 
-    indent(out) << "if (![inProtocol readMapBeginReturningKeyType: NULL valueType: NULL size: &" << size << " error: __thriftError]) return NO;" << endl; 
-    indent(out) << "NSMutableDictionary * " << fieldName 
-                << " = [[NSMutableDictionary alloc] initWithCapacity: " << size << "];" << endl; 
-  } else if (ttype->is_set()) { 
-    indent(out) << "if (![inProtocol readSetBeginReturningElementType: NULL size: &" << size << " error: __thriftError]) return NO;" 
-                << endl; 
-    indent(out) << "NSMutableSet * " << fieldName 
-                << " = [[NSMutableSet alloc] initWithCapacity: " << size << "];" << endl; 
-  } else if (ttype->is_list()) { 
-    indent(out) << "if (![inProtocol readListBeginReturningElementType: NULL size: &" << size << " error: __thriftError]) return NO;" 
-                << endl; 
-    indent(out) << "NSMutableArray * " << fieldName 
-                << " = [[NSMutableArray alloc] initWithCapacity: " << size << "];" << endl; 
-  } 
-  // FIXME - the code above does not verify that the element types of 
-  // the containers being read match the element types of the 
-  // containers we are reading into.  Does that matter? 
- 
-  // For loop iterates over elements 
-  string i = tmp("_i"); 
-  indent(out) << "int " << i << ";" << endl << indent() << "for (" << i << " = 0; " << i << " < " 
-              << size << "; " 
-              << "++" << i << ")" << endl; 
- 
-  scope_up(out); 
- 
-  if (ttype->is_map()) { 
-    generate_deserialize_map_element(out, (t_map*)ttype, fieldName); 
-  } else if (ttype->is_set()) { 
-    generate_deserialize_set_element(out, (t_set*)ttype, fieldName); 
-  } else if (ttype->is_list()) { 
-    generate_deserialize_list_element(out, (t_list*)ttype, fieldName); 
-  } 
- 
-  scope_down(out); 
- 
-  // Read container end 
-  if (ttype->is_map()) { 
-    indent(out) << "if (![inProtocol readMapEnd: __thriftError]) return NO;" << endl; 
-  } else if (ttype->is_set()) { 
-    indent(out) << "if (![inProtocol readSetEnd: __thriftError]) return NO;" << endl; 
-  } else if (ttype->is_list()) { 
-    indent(out) << "if (![inProtocol readListEnd: __thriftError]) return NO;" << endl; 
-  } 
-} 
- 
-/** 
- * Take a variable of a given type and wrap it in code to make it 
- * suitable for putting into a container, if necessary.  Basically, 
- * wrap scaler primitives in NSNumber objects. 
- */ 
-string t_cocoa_generator::box(t_type* ttype, string field_name) { 
- 
-  ttype = get_true_type(ttype); 
-  if (ttype->is_enum()) { 
-    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 box void"; 
-      case t_base_type::TYPE_BOOL: 
-      case t_base_type::TYPE_I8: 
-      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 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_I8: 
-        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; 
-} 
- 
-/** 
- * Generates code to deserialize a map element 
- */ 
-void t_cocoa_generator::generate_deserialize_map_element(ostream& out, 
-                                                         t_map* tmap, 
-                                                         string fieldName) { 
-  string key = tmp("_key"); 
-  string val = tmp("_val"); 
-  t_type* keyType = tmap->get_key_type(); 
-  t_type* valType = tmap->get_val_type(); 
-  t_field fkey(keyType, key); 
-  t_field fval(valType, val); 
- 
-  generate_deserialize_field(out, &fkey, key); 
-  generate_deserialize_field(out, &fval, val); 
- 
-  indent(out) << "[" << fieldName << " setObject: " << box(valType, val) 
-              << " forKey: " << box(keyType, key) << "];" << endl; 
-} 
- 
-/** 
- * Deserializes a set element 
- */ 
-void t_cocoa_generator::generate_deserialize_set_element(ostream& out, 
-                                                         t_set* tset, 
-                                                         string fieldName) { 
-  string elem = tmp("_elem"); 
-  t_type* type = tset->get_elem_type(); 
-  t_field felem(type, elem); 
- 
-  generate_deserialize_field(out, &felem, elem); 
- 
-  indent(out) << "[" << fieldName << " addObject: " << box(type, elem) << "];" << endl; 
-} 
- 
-/** 
- * Deserializes a list element 
- */ 
-void t_cocoa_generator::generate_deserialize_list_element(ostream& out, 
-                                                          t_list* tlist, 
-                                                          string fieldName) { 
-  string elem = tmp("_elem"); 
-  t_type* type = tlist->get_elem_type(); 
-  t_field felem(type, elem); 
- 
-  generate_deserialize_field(out, &felem, elem); 
- 
-  indent(out) << "[" << fieldName << " addObject: " << box(type, elem) << "];" << endl; 
-} 
- 
-/** 
- * Serializes a field of any type. 
- * 
- * @param tfield The field to serialize 
- * @param fieldName Name to of the variable holding the field 
- */ 
-void t_cocoa_generator::generate_serialize_field(ostream& out, t_field* tfield, string fieldName) { 
-  t_type* type = get_true_type(tfield->get_type()); 
- 
-  // Do nothing for void types 
-  if (type->is_void()) { 
-    throw "CANNOT GENERATE SERIALIZE CODE FOR void TYPE: " + tfield->get_name(); 
-  } 
- 
-  if (type->is_struct() || type->is_xception()) { 
-    generate_serialize_struct(out, (t_struct*)type, fieldName); 
-  } else if (type->is_container()) { 
-    generate_serialize_container(out, type, fieldName); 
-  } else if (type->is_base_type() || type->is_enum()) { 
-    indent(out) << "if (![outProtocol "; 
- 
-    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: 
-        throw "compiler error: cannot serialize void field in a struct: " + fieldName; 
-        break; 
-      case t_base_type::TYPE_STRING: 
-        if (type->is_binary()) { 
-          out << "writeBinary: " << fieldName << " error: __thriftError]"; 
-        } else { 
-          out << "writeString: " << fieldName << " error: __thriftError]"; 
-        } 
-        break; 
-      case t_base_type::TYPE_BOOL: 
-        out << "writeBool: " << fieldName << " error: __thriftError]"; 
-        break; 
-      case t_base_type::TYPE_I8: 
-        out << "writeByte: (UInt8)" << fieldName << " error: __thriftError]"; 
-        break; 
-      case t_base_type::TYPE_I16: 
-        out << "writeI16: " << fieldName << " error: __thriftError]"; 
-        break; 
-      case t_base_type::TYPE_I32: 
-        out << "writeI32: " << fieldName << " error: __thriftError]"; 
-        break; 
-      case t_base_type::TYPE_I64: 
-        out << "writeI64: " << fieldName << " error: __thriftError]"; 
-        break; 
-      case t_base_type::TYPE_DOUBLE: 
-        out << "writeDouble: " << fieldName << " error: __thriftError]"; 
-        break; 
-      default: 
-        throw "compiler error: no Objective-C name for base type " 
-            + t_base_type::t_base_name(tbase); 
-      } 
-    } else if (type->is_enum()) { 
-      out << "writeI32: " << fieldName << " error: __thriftError]"; 
-    } 
-    out << ") return NO;" << endl; 
-  } else { 
-    printf("DO NOT KNOW HOW TO SERIALIZE FIELD '%s' TYPE '%s'\n", 
-           tfield->get_name().c_str(), 
-           type_name(type).c_str()); 
-  } 
-} 
- 
-/** 
- * Serialize a struct. 
- * 
- * @param tstruct The struct to serialize 
- * @param fieldName Name of variable holding struct 
- */ 
-void t_cocoa_generator::generate_serialize_struct(ostream& out, 
-                                                  t_struct* tstruct, 
-                                                  string fieldName) { 
-  (void)tstruct; 
-  out << indent() << "if (![" << fieldName << " write: outProtocol error: __thriftError]) return NO;" << endl; 
-} 
- 
-/** 
- * Serializes a container by writing its size then the elements. 
- * 
- * @param ttype  The type of container 
- * @param fieldName Name of variable holding container 
- */ 
-void t_cocoa_generator::generate_serialize_container(ostream& out, 
-                                                     t_type* ttype, 
-                                                     string fieldName) { 
-  scope_up(out); 
- 
-  if (ttype->is_map()) { 
-    indent(out) << "if (![outProtocol writeMapBeginWithKeyType: " 
-                << type_to_enum(((t_map*)ttype)->get_key_type()) 
-                << " valueType: " << type_to_enum(((t_map*)ttype)->get_val_type()) << " size: (SInt32)[" 
-                << fieldName << " count] error: __thriftError]) return NO;" << endl; 
-  } else if (ttype->is_set()) { 
-    indent(out) << "if (![outProtocol writeSetBeginWithElementType: " 
-                << type_to_enum(((t_set*)ttype)->get_elem_type()) << " size: (SInt32)[" << fieldName 
-                << " count] error: __thriftError]) return NO;" << endl; 
-  } else if (ttype->is_list()) { 
-    indent(out) << "if (![outProtocol writeListBeginWithElementType: " 
-                << type_to_enum(((t_list*)ttype)->get_elem_type()) << " size: (SInt32)[" << fieldName 
-                << " count] error: __thriftError]) return NO;" << endl; 
-  } 
- 
-  string iter = tmp("_iter"); 
-  string key; 
-  if (ttype->is_map()) { 
-    key = tmp("key"); 
-    indent(out) << "NSEnumerator * " << iter << " = [" << fieldName << " keyEnumerator];" << endl; 
-    indent(out) << "id " << key << ";" << endl; 
-    indent(out) << "while ((" << key << " = [" << iter << " nextObject]))" << endl; 
-  } else if (ttype->is_set()) { 
-    key = tmp("obj"); 
-    indent(out) << "NSEnumerator * " << iter << " = [" << fieldName << " objectEnumerator];" 
-                << endl; 
-    indent(out) << "id " << key << ";" << endl; 
-    indent(out) << "while ((" << key << " = [" << iter << " nextObject]))" << endl; 
-  } else if (ttype->is_list()) { 
-    key = tmp("idx"); 
-    indent(out) << "int " << key << ";" << endl; 
-    indent(out) << "for (" << key << " = 0; " << key << " < [" << fieldName << " count]; " << key 
-                << "++)" << endl; 
-  } 
- 
-  scope_up(out); 
- 
-  if (ttype->is_map()) { 
-    generate_serialize_map_element(out, (t_map*)ttype, key, fieldName); 
-  } else if (ttype->is_set()) { 
-    generate_serialize_set_element(out, (t_set*)ttype, key); 
-  } else if (ttype->is_list()) { 
-    generate_serialize_list_element(out, (t_list*)ttype, key, fieldName); 
-  } 
- 
-  scope_down(out); 
- 
-  if (ttype->is_map()) { 
-    indent(out) << "if (![outProtocol writeMapEnd: __thriftError]) return NO;" << endl; 
-  } else if (ttype->is_set()) { 
-    indent(out) << "if (![outProtocol writeSetEnd: __thriftError]) return NO;" << endl; 
-  } else if (ttype->is_list()) { 
-    indent(out) << "if (![outProtocol writeListEnd: __thriftError]) return NO;" << endl; 
-  } 
- 
-  scope_down(out); 
-} 
- 
-/** 
- * Serializes the members of a map. 
- */ 
-void t_cocoa_generator::generate_serialize_map_element(ostream& out, 
-                                                       t_map* tmap, 
-                                                       string key, 
-                                                       string mapName) { 
-  t_field kfield(tmap->get_key_type(), 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, unbox(vfield.get_type(), vfield.get_name())); 
-} 
- 
-/** 
- * Serializes the members of a set. 
- */ 
-void t_cocoa_generator::generate_serialize_set_element(ostream& out, 
-                                                       t_set* tset, 
-                                                       string elementName) { 
-  t_field efield(tset->get_elem_type(), elementName); 
-  generate_serialize_field(out, &efield, unbox(efield.get_type(), elementName)); 
-} 
- 
-/** 
- * Serializes the members of a list. 
- */ 
-void t_cocoa_generator::generate_serialize_list_element(ostream& out, 
-                                                        t_list* tlist, 
-                                                        string index, 
-                                                        string listName) { 
-  t_field efield(tlist->get_elem_type(), "[" + listName + " objectAtIndex: " + index + "]"); 
-  generate_serialize_field(out, &efield, unbox(efield.get_type(), efield.get_name())); 
-} 
- 
-/** 
- * Returns an Objective-C name 
- * 
- * @param ttype The type 
- * @param class_ref Do we want a Class reference istead of a type reference? 
- * @return Objective-C type name, i.e. NSDictionary<Key,Value> * 
- */ 
-string t_cocoa_generator::type_name(t_type* ttype, bool class_ref, bool needs_mutable) { 
-  if (ttype->is_typedef()) { 
-    string name = (needs_mutable && ttype->get_true_type()->is_container()) ? "Mutable" + ttype->get_name() : ttype->get_name(); 
-    t_program* program = ttype->get_program(); 
-    return program ? (program->get_namespace("cocoa") + name) : name; 
-  } 
- 
-  string result; 
-  if (ttype->is_base_type()) { 
-    return base_type_name((t_base_type*)ttype); 
-  } else if (ttype->is_enum()) { 
-    return cocoa_prefix_ + ttype->get_name(); 
-  } else if (ttype->is_map()) { 
-    t_map *map = (t_map *)ttype; 
-    result = needs_mutable ? "NSMutableDictionary" : "NSDictionary"; 
-    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 += "<" + element_type_name(set->get_elem_type()) + ">"; 
-  } else if (ttype->is_list()) { 
-    t_list *list = (t_list *)ttype; 
-    result = needs_mutable ? "NSMutableArray" : "NSArray"; 
-    result += "<" + element_type_name(list->get_elem_type()) + ">"; 
-  } else { 
-    // Check for prefix 
-    t_program* program = ttype->get_program(); 
-    if (program != NULL) { 
-      result = program->get_namespace("cocoa") + ttype->get_name(); 
-    } else { 
-      result = ttype->get_name(); 
-    } 
-  } 
- 
-  if (!class_ref) { 
-    result += " *"; 
-  } 
-  return result; 
-} 
- 
-/** 
- * 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_enum()) { 
-      result = "NSNumber *"; 
-  } 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 
- */ 
-string t_cocoa_generator::base_type_name(t_base_type* type) { 
-  t_base_type::t_base tbase = type->get_base(); 
- 
-  switch (tbase) { 
-  case t_base_type::TYPE_VOID: 
-    return "void"; 
-  case t_base_type::TYPE_STRING: 
-    if (type->is_binary()) { 
-      return "NSData *"; 
-    } else { 
-      return "NSString *"; 
-    } 
-  case t_base_type::TYPE_BOOL: 
-    return "BOOL"; 
-  case t_base_type::TYPE_I8: 
-    return "SInt8"; 
-  case t_base_type::TYPE_I16: 
-    return "SInt16"; 
-  case t_base_type::TYPE_I32: 
-    return "SInt32"; 
-  case t_base_type::TYPE_I64: 
-    return "SInt64"; 
-  case t_base_type::TYPE_DOUBLE: 
-    return "double"; 
-  default: 
-    throw "compiler error: no Objective-C name for base type " + t_base_type::t_base_name(tbase); 
-  } 
-} 
- 
-/** 
- * Prints the value of a constant with the given type. Note that type checking 
- * 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(ostream& out, 
-                                          string name, 
-                                          t_type* type, 
-                                          t_const_value* value, 
-                                          bool defval) { 
-  type = get_true_type(type); 
- 
-  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*, t_const_value::value_compare>& val = value->get_map(); 
-    map<t_const_value*, t_const_value*, t_const_value::value_compare>::const_iterator v_iter; 
-    if (defval) 
-      out << type_name(type) << " "; 
-    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) { 
-        if ((*f_iter)->get_name() == v_iter->first->get_string()) { 
-          field_type = (*f_iter)->get_type(); 
-        } 
-      } 
-      if (field_type == NULL) { 
-        throw "type error: " + type->get_name() + " has no field " + v_iter->first->get_string(); 
-      } 
-      string val = render_const_value(out, field_type, v_iter->second); 
-      std::string cap_name = capitalize(v_iter->first->get_string()); 
-      indent(out) << "[" << name << " set" << cap_name << ":" << val << "];" << 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*, t_const_value::value_compare>& val = value->get_map(); 
-    map<t_const_value*, t_const_value*, t_const_value::value_compare>::const_iterator v_iter; 
-    if (defval) 
-      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 << ", "; 
-      } 
-    } 
-    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) 
-      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 << ", "; 
-      } 
-    } 
-    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) 
-      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 << ", "; 
-      } 
-    } 
-    setout << "]]"; 
-    out << setout.str(); 
-  } else { 
-    throw "compiler error: no const of type " + type->get_name(); 
-  } 
-} 
- 
-string t_cocoa_generator::render_const_value(ostream& out, 
-                                             t_type* type, 
-                                             t_const_value* value, 
-                                             bool box_it) { 
-  type = get_true_type(type); 
-  std::ostringstream render; 
- 
-  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: 
-      // We must handle binary constant but the syntax of IDL defines 
-      // nothing about binary constant. 
-      //   if type->is_binary()) 
-      //      // binary code 
-      render << "@\"" << get_escaped_string(value) << '"'; 
-      break; 
-    case t_base_type::TYPE_BOOL: 
-      render << ((value->get_integer() > 0) ? "YES" : "NO"); 
-      break; 
-    case t_base_type::TYPE_I8: 
-    case t_base_type::TYPE_I16: 
-    case t_base_type::TYPE_I32: 
-    case t_base_type::TYPE_I64: 
-      render << value->get_integer(); 
-      break; 
-    case t_base_type::TYPE_DOUBLE: 
-      if (value->get_type() == t_const_value::CV_INTEGER) { 
-        render << value->get_integer(); 
-      } else { 
-        render << value->get_double(); 
-      } 
-      break; 
-    default: 
-      throw "compiler error: no const of base type " + t_base_type::t_base_name(tbase); 
-    } 
-  } else if (type->is_enum()) { 
-    render << value->get_integer(); 
-  } else { 
-    string t = tmp("tmp"); 
-    print_const_value(out, t, type, value, true); 
-    out << ";" << endl; 
-    render << t; 
-  } 
- 
-  if (box_it) { 
-    return box(type, render.str()); 
-  } 
-  return render.str(); 
-} 
- 
-#if 0 
-/** 
-ORIGINAL 
- * Spit out code that evaluates to the specified constant value. 
- */ 
-string t_cocoa_generator::render_const_value(string name, 
-                                             t_type* type, 
-                                             t_const_value* value, 
-                                             bool box_it) { 
-  type = get_true_type(type); 
-  std::ostringstream render; 
- 
-  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: 
-      render << "@\"" << get_escaped_string(value) << '"'; 
-      break; 
-    case t_base_type::TYPE_BOOL: 
-      render << ((value->get_integer() > 0) ? "YES" : "NO"); 
-      break; 
-    case t_base_type::TYPE_I8: 
-    case t_base_type::TYPE_I16: 
-    case t_base_type::TYPE_I32: 
-    case t_base_type::TYPE_I64: 
-      render << value->get_integer(); 
-      break; 
-    case t_base_type::TYPE_DOUBLE: 
-      if (value->get_type() == t_const_value::CV_INTEGER) { 
-        render << value->get_integer(); 
-      } else { 
-        render << value->get_double(); 
-      } 
-      break; 
-    default: 
-      throw "compiler error: no const of base type " + t_base_type::t_base_name(tbase); 
-    } 
-  } else if (type->is_enum()) { 
-    render << value->get_integer(); 
-  } 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*, t_const_value::value_compare>& val = value->get_map(); 
-    map<t_const_value*, t_const_value*, t_const_value::value_compare>::const_iterator v_iter; 
-    if (val.size() > 0) 
-      render << "[[" << type_name(type, true) << " alloc] initWith"; 
-    else 
-      render << "[[" << type_name(type, true) << " alloc] init"; 
-    bool first = true; 
-    for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) { 
-      // FIXME The generated code does not match with initWithXXX 
-      //       initializer and causes compile error. 
-      //       Try: test/DebugProtoTest.thrift and test/SmallTest.thrift 
-      t_type* field_type = NULL; 
-      for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { 
-        if ((*f_iter)->get_name() == v_iter->first->get_string()) { 
-          field_type = (*f_iter)->get_type(); 
-        } 
-      } 
-      if (field_type == NULL) { 
-        throw "type error: " + type->get_name() + " has no field " + v_iter->first->get_string(); 
-      } 
-      if (first) { 
-        render << capitalize(v_iter->first->get_string()); 
-        first = false; 
-      } else { 
-        render << " " << v_iter->first->get_string(); 
-      } 
-      render << ": " << render_const_value(name, field_type, v_iter->second); 
-    } 
-    render << "]"; 
-  } else if (type->is_map()) { 
-    render << "[[NSDictionary alloc] initWithObjectsAndKeys: "; 
-    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*, t_const_value::value_compare>& val = value->get_map(); 
-    map<t_const_value*, t_const_value*, t_const_value::value_compare>::const_iterator v_iter; 
-    bool first = true; 
-    for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) { 
-      string key = render_const_value(name, ktype, v_iter->first, true); 
-      string val = render_const_value(name, vtype, v_iter->second, true); 
-      if (first) { 
-        first = false; 
-      } else { 
-        render << ", "; 
-      } 
-      render << val << ", " << key; 
-    } 
-    if (first) 
-      render << " nil]"; 
-    else 
-      render << ", nil]"; 
-  } else if (type->is_list()) { 
-    render << "[[NSArray alloc] initWithObjects: "; 
-    t_type * etype = ((t_list*)type)->get_elem_type(); 
-    const vector<t_const_value*>& val = value->get_list(); 
-    bool first = true; 
-    vector<t_const_value*>::const_iterator v_iter; 
-    for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) { 
-      if (first) { 
-        first = false; 
-      } else { 
-        render << ", "; 
-      } 
-      render << render_const_value(name, etype, *v_iter, true); 
-    } 
-    if (first) 
-      render << " nil]"; 
-    else 
-      render << ", nil]"; 
-  } else if (type->is_set()) { 
-    render << "[[NSSet alloc] initWithObjects: "; 
-    t_type * etype = ((t_set*)type)->get_elem_type(); 
-    const vector<t_const_value*>& val = value->get_list(); 
-    bool first = true; 
-    vector<t_const_value*>::const_iterator v_iter; 
-    for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) { 
-      if (first) { 
-        first = false; 
-      } else { 
-        render << ", "; 
-      } 
-      render << render_const_value(name, etype, *v_iter, true); 
-    } 
-    if (first) 
-      render << " nil]"; 
-    else 
-      render << ", nil]"; 
-  } else { 
-    throw "don't know how to render constant for type: " + type->get_name(); 
-  } 
- 
-  if (box_it) { 
-    return box(type, render.str()); 
-  } 
- 
-  return render.str(); 
-} 
-#endif 
- 
-/** 
- * Declares an Objective-C 2.0 property. 
- * 
- * @param tfield The field to declare a property for 
- */ 
-string t_cocoa_generator::declare_property(t_field* tfield) { 
-  std::ostringstream render; 
-  render << "@property ("; 
- 
-  if (type_can_be_copy(tfield->get_type())) { 
-    render << "copy, "; 
-  } else if (type_can_be_null(tfield->get_type())) { 
-    render << "strong, "; 
-  } else { 
-    render << "assign, "; 
-  } 
- 
-  render << "nonatomic) " << type_name(tfield->get_type(), false, true) << " " 
-  << tfield->get_name() << ";"; 
- 
-  // Check if the property name is an Objective-C return +1 count signal 
-  if ((tfield->get_name().length() >= 3 && tfield->get_name().substr(0,3) == "new") || 
-      (tfield->get_name().length() >= 6 && tfield->get_name().substr(0,6) == "create") || 
-      (tfield->get_name().length() >= 5 && tfield->get_name().substr(0,5) == "alloc")) { 
-    // Let Objective-C know not to return +1 for object pointers 
-    if (type_can_be_null(tfield->get_type())) { 
-      render << endl; 
-      render << "- (" + type_name(tfield->get_type()) + ") " + decapitalize(tfield->get_name()) + " __attribute__((objc_method_family(none)));"; 
-    } 
-  } 
- 
-  return render.str(); 
-} 
- 
-/** 
- * Declares an Objective-C 2.0 property. 
- * 
- * @param tfield The field to declare a property for 
- */ 
-string t_cocoa_generator::declare_property_isset(t_field* tfield) { 
-  return "@property (assign, nonatomic) BOOL " + decapitalize(tfield->get_name()) + "IsSet;"; 
-} 
- 
-/** 
- * Declares property unset method. 
- * 
- * @param tfield The field to declare a property for 
- */ 
-string t_cocoa_generator::declare_property_unset(t_field* tfield) { 
-  return "- (void) unset" + capitalize(tfield->get_name()) + ";"; 
-} 
- 
-/** 
- * Renders the early out return statement 
- * 
- * @param tfunction Function definition 
- * @return String of rendered invalid return statment 
- */ 
-string t_cocoa_generator::invalid_return_statement(t_function *tfunction) { 
-  if ((tfunction->get_returntype()->is_void())) { 
-    return "return NO;"; 
-  } 
-  return "return nil;"; 
-} 
- 
-/** 
- * Renders a function signature 
- * 
- * @param tfunction Function definition 
- * @return String of rendered function definition 
- */ 
-string t_cocoa_generator::function_signature(t_function* tfunction, bool include_error) { 
-  t_type* ttype = tfunction->get_returntype(); 
-  string result; 
-  if (ttype->is_void()) { 
-    result = "(BOOL)"; 
-  } 
-  else if (type_can_be_null(ttype)) { 
-    result = "(" + type_name(ttype) + ")"; 
-  } 
-  else { 
-    result = "(NSNumber *)"; 
-  } 
-  result += " " + tfunction->get_name() + argument_list(tfunction->get_arglist(), "", include_error); 
-  return result; 
-} 
- 
-/** 
- * Renders a function signature that returns asynchronously instead of 
- * literally returning. 
- * 
- * @param tfunction Function definition 
- * @return String of rendered function definition 
- */ 
-string t_cocoa_generator::async_function_signature(t_function* tfunction, bool include_error) { 
-  t_type* ttype = tfunction->get_returntype(); 
-  t_struct* targlist = tfunction->get_arglist(); 
-  string response_param = "void (^)(" + ((ttype->is_void()) ? "" : type_name(ttype)) + ")"; 
-  std::string result = "(void) " + tfunction->get_name() + argument_list(tfunction->get_arglist(), "", include_error) 
-  + (targlist->get_members().size() ? " response" : "") + ": (" 
-  + response_param + ") responseBlock " 
-  + "failure : (TAsyncFailureBlock) failureBlock"; 
-  return result; 
-} 
- 
-/** 
- * Renders a function signature that returns a promise instead of 
- * literally returning. 
- * 
- * @param tfunction Function definition 
- * @return String of rendered function definition 
- */ 
-string t_cocoa_generator::promise_function_signature(t_function* tfunction) { 
-  return "(AnyPromise *) " + tfunction->get_name() + argument_list(tfunction->get_arglist(), "", false); 
-} 
- 
-/** 
- * Renders a colon separated list of types and names, suitable for an 
- * objective-c parameter list 
- */ 
-string t_cocoa_generator::argument_list(t_struct* tstruct, string protocol_name, bool include_error) { 
-  string result = ""; 
-  bool include_protocol = !protocol_name.empty(); 
- 
-  const vector<t_field*>& fields = tstruct->get_members(); 
-  vector<t_field*>::const_iterator f_iter; 
-  bool first = true; 
-  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { 
-    string argPrefix = ""; 
-    if (first) { 
-      first = false; 
-    } else { 
-      argPrefix = (*f_iter)->get_name(); 
-      result += " "; 
-    } 
-    result += argPrefix + ": (" + type_name((*f_iter)->get_type()) + ") " + (*f_iter)->get_name(); 
-  } 
-  if (include_protocol) { 
-    if (!first) { 
-      result += " protocol"; 
-    } 
-    result += ": (id<TProtocol>) " + protocol_name; 
-    first = false; 
-  } 
-  if (include_error) { 
-    if (!first) { 
-      result += " error"; 
-    } 
-    result += ": (NSError *__autoreleasing *)__thriftError"; 
-    first = false; 
-  } 
-  return result; 
-} 
- 
-/** 
- * Converts the parse type to an Objective-C enum string for the given type. 
- */ 
-string t_cocoa_generator::type_to_enum(t_type* type) { 
-  type = get_true_type(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: 
-      throw "NO T_VOID CONSTRUCT"; 
-    case t_base_type::TYPE_STRING: 
-      return "TTypeSTRING"; 
-    case t_base_type::TYPE_BOOL: 
-      return "TTypeBOOL"; 
-    case t_base_type::TYPE_I8: 
-      return "TTypeBYTE"; 
-    case t_base_type::TYPE_I16: 
-      return "TTypeI16"; 
-    case t_base_type::TYPE_I32: 
-      return "TTypeI32"; 
-    case t_base_type::TYPE_I64: 
-      return "TTypeI64"; 
-    case t_base_type::TYPE_DOUBLE: 
-      return "TTypeDOUBLE"; 
-    } 
-  } else if (type->is_enum()) { 
-    return "TTypeI32"; 
-  } else if (type->is_struct() || type->is_xception()) { 
-    return "TTypeSTRUCT"; 
-  } else if (type->is_map()) { 
-    return "TTypeMAP"; 
-  } else if (type->is_set()) { 
-    return "TTypeSET"; 
-  } else if (type->is_list()) { 
-    return "TTypeLIST"; 
-  } 
- 
-  throw "INVALID TYPE IN type_to_enum: " + type->get_name(); 
-} 
- 
-/** 
- * Returns a format string specifier for the supplied parse type. 
- */ 
-string t_cocoa_generator::format_string_for_type(t_type* type) { 
-  type = get_true_type(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: 
-      throw "NO T_VOID CONSTRUCT"; 
-    case t_base_type::TYPE_STRING: 
-      return "\\\"%@\\\""; 
-    case t_base_type::TYPE_BOOL: 
-      return "%i"; 
-    case t_base_type::TYPE_I8: 
-      return "%i"; 
-    case t_base_type::TYPE_I16: 
-      return "%hi"; 
-    case t_base_type::TYPE_I32: 
-      return "%i"; 
-    case t_base_type::TYPE_I64: 
-      return "%qi"; 
-    case t_base_type::TYPE_DOUBLE: 
-      return "%f"; 
-    } 
-  } else if (type->is_enum()) { 
-    return "%i"; 
-  } else if (type->is_struct() || type->is_xception()) { 
-    return "%@"; 
-  } else if (type->is_map()) { 
-    return "%@"; 
-  } else if (type->is_set()) { 
-    return "%@"; 
-  } else if (type->is_list()) { 
-    return "%@"; 
-  } 
- 
-  throw "INVALID TYPE IN format_string_for_type: " + type->get_name(); 
-} 
- 
-/** 
- * Returns a format cast for the supplied parse type. 
- */ 
-string t_cocoa_generator::format_cast_for_type(t_type* type) { 
-  type = get_true_type(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: 
-      throw "NO T_VOID CONSTRUCT"; 
-    case t_base_type::TYPE_STRING: 
-      return ""; // "\\\"%@\\\""; 
-    case t_base_type::TYPE_BOOL: 
-      return ""; // "%i"; 
-    case t_base_type::TYPE_I8: 
-      return ""; // "%i"; 
-    case t_base_type::TYPE_I16: 
-      return ""; // "%hi"; 
-    case t_base_type::TYPE_I32: 
-      return "(int)"; // "%i"; 
-    case t_base_type::TYPE_I64: 
-      return ""; // "%qi"; 
-    case t_base_type::TYPE_DOUBLE: 
-      return ""; // "%f"; 
-    } 
-  } else if (type->is_enum()) { 
-    return "(int)"; // "%i"; 
-  } else if (type->is_struct() || type->is_xception()) { 
-    return ""; // "%@"; 
-  } else if (type->is_map()) { 
-    return ""; // "%@"; 
-  } else if (type->is_set()) { 
-    return ""; // "%@"; 
-  } else if (type->is_list()) { 
-    return ""; // "%@"; 
-  } 
- 
-  throw "INVALID TYPE IN format_cast_for_type: " + type->get_name(); 
-} 
- 
-/** 
- * Generate a call to a field's setter. 
- * 
- * @param tfield Field the setter is being called on 
- * @param fieldName Name of variable to pass to setter 
- */ 
- 
-string t_cocoa_generator::call_field_setter(t_field* tfield, string fieldName) { 
-  return "self." + tfield->get_name() + " = " + fieldName + ";"; 
-} 
- 
-THRIFT_REGISTER_GENERATOR( 
-    cocoa, 
-    "Cocoa", 
-    "    log_unexpected:  Log every time an unexpected field ID or type is encountered.\n" 
-    "    debug_descriptions:\n" 
-    "                     Allow use of debugDescription so the app can add description via a cateogory/extension\n" 
-    "    validate_required:\n" 
-    "                     Throws exception if any required field is not set.\n" 
-    "    async_clients:   Generate clients which invoke asynchronously via block syntax.\n" 
-    "    pods:            Generate imports in Cocopods framework format.\n" 
-    "    promise_kit:     Generate clients which invoke asynchronously via promises.\n") 
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#include <string>
+#include <fstream>
+#include <iostream>
+#include <vector>
+
+#include <stdlib.h>
+#include <sys/stat.h>
+#include <sstream>
+#include "thrift/platform.h"
+#include "thrift/generate/t_oop_generator.h"
+
+using std::map;
+using std::ostream;
+using std::ofstream;
+using std::ostringstream;
+using std::string;
+using std::stringstream;
+using std::vector;
+
+static const string endl = "\n"; // avoid ostream << std::endl flushes
+
+/**
+ * Objective-C code generator.
+ *
+ * mostly copy/pasting/tweaking from mcslee's work.
+ */
+class t_cocoa_generator : public t_oop_generator {
+public:
+  t_cocoa_generator(t_program* program,
+                    const std::map<std::string, std::string>& parsed_options,
+                    const std::string& option_string)
+    : t_oop_generator(program) {
+    (void)option_string;
+    std::map<std::string, std::string>::const_iterator iter;
+
+    log_unexpected_ = false;
+    validate_required_ = false;
+    async_clients_ = false;
+    promise_kit_ = false;
+    debug_descriptions_ = false;
+    pods_ = false;
+    for( iter = parsed_options.begin(); iter != parsed_options.end(); ++iter) {
+      if( iter->first.compare("log_unexpected") == 0) {
+        log_unexpected_ = true;
+      } else if( iter->first.compare("validate_required") == 0) {
+        validate_required_ = true;
+      } else if( iter->first.compare("async_clients") == 0) {
+        async_clients_ = true;
+      } else if( iter->first.compare("promise_kit") == 0) {
+        promise_kit_ = true;
+      } else if( iter->first.compare("debug_descriptions") == 0) {
+        debug_descriptions_ = true;
+      } else if( iter->first.compare("pods") == 0) {
+        pods_ = true;
+      } else {
+        throw "unknown option cocoa:" + iter->first;
+      }
+    }
+
+    out_dir_base_ = "gen-cocoa";
+  }
+
+  /**
+   * Init and close methods
+   */
+
+  void init_generator();
+  void close_generator();
+
+  void generate_consts(std::vector<t_const*> consts);
+
+  /**
+   * Program-level generation functions
+   */
+
+  void generate_typedef(t_typedef* ttypedef);
+  void generate_enum(t_enum* tenum);
+  void generate_struct(t_struct* tstruct);
+  void generate_xception(t_struct* txception);
+  void generate_service(t_service* tservice);
+
+  void print_const_value(ostream& out,
+                         string name,
+                         t_type* type,
+                         t_const_value* value,
+                         bool defval = false);
+  std::string render_const_value(ostream& out,
+                                 t_type* type,
+                                 t_const_value* value,
+                                 bool box_it = false);
+
+  void generate_cocoa_struct(t_struct* tstruct, bool is_exception);
+  void generate_cocoa_struct_interface(std::ostream& out,
+                                       t_struct* tstruct,
+                                       bool is_xception = false);
+  void generate_cocoa_struct_implementation(std::ostream& out,
+                                            t_struct* tstruct,
+                                            bool is_xception = false,
+                                            bool is_result = false);
+  void generate_cocoa_struct_initializer_signature(std::ostream& out, t_struct* tstruct);
+  void generate_cocoa_struct_init_with_coder_method(ostream& out,
+                                                    t_struct* tstruct,
+                                                    bool is_exception);
+  void generate_cocoa_struct_encode_with_coder_method(ostream& out,
+                                                      t_struct* tstruct,
+                                                      bool is_exception);
+  void generate_cocoa_struct_copy_method(ostream& out,
+                                         t_struct* tstruct,
+                                         bool is_exception);
+  void generate_cocoa_struct_hash_method(ostream& out, t_struct* tstruct);
+  void generate_cocoa_struct_is_equal_method(ostream& out,
+                                             t_struct* tstruct,
+                                             bool is_exception);
+  void generate_cocoa_struct_field_accessor_implementations(std::ostream& out,
+                                                            t_struct* tstruct,
+                                                            bool is_exception);
+  void generate_cocoa_struct_reader(std::ostream& out, t_struct* tstruct);
+  void generate_cocoa_struct_result_writer(std::ostream& out, t_struct* tstruct);
+  void generate_cocoa_struct_writer(std::ostream& out, t_struct* tstruct);
+  void generate_cocoa_struct_validator(std::ostream& out, t_struct* tstruct);
+  void generate_cocoa_struct_description(std::ostream& out, t_struct* tstruct);
+
+  std::string function_result_helper_struct_type(t_service *tservice, t_function* tfunction);
+  std::string function_args_helper_struct_type(t_service* tservice, t_function* tfunction);
+  void generate_function_helpers(t_service *tservice, t_function* tfunction);
+
+  /**
+   * Service-level generation functions
+   */
+
+  void generate_cocoa_service_protocol(std::ostream& out, t_service* tservice);
+  void generate_cocoa_service_async_protocol(std::ostream& out, t_service* tservice);
+
+  void generate_cocoa_service_client_interface(std::ostream& out, t_service* tservice);
+  void generate_cocoa_service_client_async_interface(std::ostream& out, t_service* tservice);
+
+  void generate_cocoa_service_client_send_function_implementation(ostream& out,
+                                                                  t_service* tservice,
+                                                                  t_function* tfunction,
+                                                                  bool needs_protocol);
+  void generate_cocoa_service_client_send_function_invocation(ostream& out, t_function* tfunction);
+  void generate_cocoa_service_client_send_async_function_invocation(ostream& out,
+                                                                    t_function* tfunction,
+                                                                    string failureBlockName);
+  void generate_cocoa_service_client_recv_function_implementation(ostream& out,
+                                                                  t_service* tservice,
+                                                                  t_function* tfunction,
+                                                                  bool needs_protocol);
+  void generate_cocoa_service_client_implementation(std::ostream& out, t_service* tservice);
+  void generate_cocoa_service_client_async_implementation(std::ostream& out, t_service* tservice);
+
+  void generate_cocoa_service_server_interface(std::ostream& out, t_service* tservice);
+  void generate_cocoa_service_server_implementation(std::ostream& out, t_service* tservice);
+  void generate_cocoa_service_helpers(t_service* tservice);
+  void generate_service_client(t_service* tservice);
+  void generate_service_server(t_service* tservice);
+  void generate_process_function(t_service* tservice, t_function* tfunction);
+
+  /**
+   * Serialization constructs
+   */
+
+  void generate_deserialize_field(std::ostream& out, t_field* tfield, std::string fieldName);
+
+  void generate_deserialize_struct(std::ostream& out, t_struct* tstruct, std::string prefix = "");
+
+  void generate_deserialize_container(std::ostream& out, t_type* ttype, std::string prefix = "");
+
+  void generate_deserialize_set_element(std::ostream& out, t_set* tset, std::string prefix = "");
+
+  void generate_deserialize_map_element(std::ostream& out, t_map* tmap, std::string prefix = "");
+
+  void generate_deserialize_list_element(std::ostream& out,
+                                         t_list* tlist,
+                                         std::string prefix = "");
+
+  void generate_serialize_field(std::ostream& out, t_field* tfield, std::string prefix = "");
+
+  void generate_serialize_struct(std::ostream& out, t_struct* tstruct, std::string fieldName = "");
+
+  void generate_serialize_container(std::ostream& out, t_type* ttype, std::string prefix = "");
+
+  void generate_serialize_map_element(std::ostream& out,
+                                      t_map* tmap,
+                                      std::string iter,
+                                      std::string map);
+
+  void generate_serialize_set_element(std::ostream& out, t_set* tmap, std::string iter);
+
+  void generate_serialize_list_element(std::ostream& out,
+                                       t_list* tlist,
+                                       std::string index,
+                                       std::string listName);
+
+  /**
+   * Helper rendering functions
+   */
+
+  std::string cocoa_prefix();
+  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);
+  std::string declare_property_unset(t_field* tfield);
+  std::string invalid_return_statement(t_function* tfunction);
+  std::string function_signature(t_function* tfunction, bool include_error);
+  std::string async_function_signature(t_function* tfunction, bool include_error);
+  std::string promise_function_signature(t_function* tfunction);
+  std::string argument_list(t_struct* tstruct, string protocol_name, bool include_error);
+  std::string type_to_enum(t_type* ttype);
+  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 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);
+
+  bool type_can_be_copy(t_type* ttype) {
+    ttype = get_true_type(ttype);
+    
+    return ttype->is_string();
+  }
+  
+  bool type_can_be_null(t_type* ttype) {
+    ttype = get_true_type(ttype);
+
+    return ttype->is_container() || ttype->is_struct() || ttype->is_xception()
+           || ttype->is_string();
+  }
+
+private:
+  std::string cocoa_prefix_;
+  std::string constants_declarations_;
+  int error_constant_;
+
+  /**
+   * File streams
+   */
+
+  ofstream_with_content_based_conditional_update f_header_;
+  ofstream_with_content_based_conditional_update f_impl_;
+
+  bool log_unexpected_;
+  bool validate_required_;
+  bool async_clients_;
+  bool promise_kit_;
+  bool debug_descriptions_;
+  bool pods_;
+};
+
+/**
+ * Prepares for file generation by opening up the necessary file output
+ * streams.
+ */
+void t_cocoa_generator::init_generator() {
+  // Make output directory
+  MKDIR(get_out_dir().c_str());
+  cocoa_prefix_ = program_->get_namespace("cocoa");
+
+  // we have a .h header file...
+  string f_header_name = cocoa_prefix_ + capitalize(program_name_) + ".h";
+  string f_header_fullname = get_out_dir() + f_header_name;
+  f_header_.open(f_header_fullname.c_str());
+
+  f_header_ << autogen_comment() << endl;
+
+  f_header_ << cocoa_imports() << cocoa_thrift_imports();
+
+  // ...and a .m implementation file
+  string f_impl_name = cocoa_prefix_ + capitalize(program_name_) + ".m";
+  string f_impl_fullname = get_out_dir() + f_impl_name;
+  f_impl_.open(f_impl_fullname.c_str());
+
+  f_impl_ << autogen_comment() << endl;
+
+  f_impl_ << cocoa_imports() << cocoa_thrift_imports() << "#import \"" << f_header_name << "\""
+          << endl << endl;
+
+  error_constant_ = 60000;
+}
+
+/**
+ * Prints standard Cocoa imports
+ *
+ * @return List of imports for Cocoa libraries
+ */
+string t_cocoa_generator::cocoa_imports() {
+  return string() + "#import <Foundation/Foundation.h>\n" + "\n";
+}
+
+/**
+ * Prints thrift runtime imports
+ *
+ * @return List of imports necessary for thrift runtime
+ */
+string t_cocoa_generator::cocoa_thrift_imports() {
+
+  vector<string> includes_list;
+  includes_list.push_back("TProtocol.h");
+  includes_list.push_back("TProtocolFactory.h");
+  includes_list.push_back("TApplicationError.h");
+  includes_list.push_back("TProtocolError.h");
+  includes_list.push_back("TProtocolUtil.h");
+  includes_list.push_back("TProcessor.h");
+  includes_list.push_back("TBase.h");
+  includes_list.push_back("TAsyncTransport.h");
+  includes_list.push_back("TBaseClient.h");
+
+  std::ostringstream includes;
+
+  vector<string>::const_iterator i_iter;
+  for (i_iter=includes_list.begin(); i_iter!=includes_list.end(); ++i_iter) {
+    includes << "#import ";
+    if (pods_) {
+      includes << "<Thrift/" << *i_iter << ">";
+    } else {
+      includes << "\"" << *i_iter << "\"";
+    }
+    includes << endl;
+  }
+
+  includes << endl;
+
+  if (promise_kit_) {
+    includes << "#import ";
+    if (pods_) {
+      includes << "<PromiseKit/PromiseKit.h>";
+    } else {
+      includes << "\"PromiseKit.h\"";
+    }
+    includes << endl;
+  }
+
+  // Include other Thrift includes
+  const vector<t_program*>& other_includes = program_->get_includes();
+  for (size_t i = 0; i < other_includes.size(); ++i) {
+    includes << "#import \""
+             << other_includes[i]->get_namespace("cocoa")
+             << capitalize(other_includes[i]->get_name())
+             << ".h\"" << endl;
+  }
+
+  includes << endl;
+
+  return includes.str();
+}
+
+/**
+ * Finish up generation.
+ */
+void t_cocoa_generator::close_generator() {
+  // stick our constants declarations at the end of the header file
+  // since they refer to things we are defining.
+  f_header_ << constants_declarations_ << endl;
+}
+
+/**
+ * Generates a typedef. This is just a simple 1-liner in objective-c
+ *
+ * @param ttypedef The type definition
+ */
+void t_cocoa_generator::generate_typedef(t_typedef* ttypedef) {
+  if (ttypedef->get_type()->is_map()) {
+    t_map *map = (t_map *)ttypedef->get_type();
+    if (map->get_key_type()->is_struct()) {
+      f_header_ << indent() << "@class " << type_name(map->get_key_type(), true) << ";" << endl;
+    }
+    if (map->get_val_type()->is_struct()) {
+      f_header_ << indent() << "@class " << type_name(map->get_val_type(), true) << ";" << endl;
+    }
+  }
+  else if (ttypedef->get_type()->is_set()) {
+    t_set *set = (t_set *)ttypedef->get_type();
+    if (set->get_elem_type()->is_struct()) {
+      f_header_ << indent() << "@class " << type_name(set->get_elem_type(), true) << ";" << endl;
+    }
+  }
+  else if (ttypedef->get_type()->is_list()) {
+    t_list *list = (t_list *)ttypedef->get_type();
+    if (list->get_elem_type()->is_struct()) {
+      f_header_ << indent() << "@class " << type_name(list->get_elem_type(), true) << ";" << endl;
+    }
+  }
+  f_header_ << indent() << "typedef " << type_name(ttypedef->get_type()) << " " << cocoa_prefix_
+            << ttypedef->get_symbolic() << ";" << endl << endl;
+  if (ttypedef->get_type()->is_container()) {
+    f_header_ << indent() << "typedef " << type_name(ttypedef->get_type(), false, true) << " " << cocoa_prefix_
+              << "Mutable" << ttypedef->get_symbolic() << ";" << endl << endl;
+  }
+}
+
+/**
+ * Generates code for an enumerated type. In Objective-C, this is
+ * essentially the same as the thrift definition itself, instead using
+ * NS_ENUM keyword in Objective-C.  For namespace purposes, the name of
+ * the enum is prefixed to each element in keeping with Cocoa & Swift
+ * standards.
+ *
+ * @param tenum The enumeration
+ */
+void t_cocoa_generator::generate_enum(t_enum* tenum) {
+  f_header_ << indent() << "typedef NS_ENUM(SInt32, " << cocoa_prefix_ << tenum->get_name() << ") {" << endl;
+  indent_up();
+
+  vector<t_enum_value*> constants = tenum->get_constants();
+  vector<t_enum_value*>::iterator c_iter;
+  bool first = true;
+  for (c_iter = constants.begin(); c_iter != constants.end(); ++c_iter) {
+    if (first) {
+      first = false;
+    } else {
+      f_header_ << "," << endl;
+    }
+    f_header_ << indent() << cocoa_prefix_ << tenum->get_name() << (*c_iter)->get_name();
+    f_header_ << " = " << (*c_iter)->get_value();
+  }
+
+  indent_down();
+  f_header_ << endl << "};" << endl << endl;
+}
+
+/**
+ * Generates a class that holds all the constants.
+ */
+void t_cocoa_generator::generate_consts(std::vector<t_const*> consts) {
+  std::ostringstream const_interface;
+
+  const_interface << "FOUNDATION_EXPORT NSString *" << cocoa_prefix_ << capitalize(program_name_) << "ErrorDomain;" << endl
+                  << endl;
+
+
+  bool needs_class = false;
+
+  // 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()->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;
+    }
+    else {
+      needs_class = true;
+    }
+  }
+
+
+  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);
+    scope_down(const_interface);
+
+    // 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()->get_true_type();
+      if (type->is_container() || type->is_struct()) {
+        t_type* type = (*c_iter)->get_type();
+        const_interface << endl << "+ (" << type_name(type) << ") " << name << ";" << endl;
+      }
+    }
+
+    const_interface << endl << "@end";
+  }
+
+  // this gets spit into the header file in ::close_generator
+  constants_declarations_ = const_interface.str();
+
+  f_impl_ << "NSString *" << cocoa_prefix_ << capitalize(program_name_) << "ErrorDomain = "
+          << "@\"" << cocoa_prefix_ << capitalize(program_name_) << "ErrorDomain\";" << endl << endl;
+
+  // variables in the .m hold all simple constant values
+  for (c_iter = consts.begin(); c_iter != consts.end(); ++c_iter) {
+    string name = (*c_iter)->get_name();
+    t_type* type = (*c_iter)->get_type();
+    f_impl_ << type_name(type) << " " << cocoa_prefix_ << name;
+    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;
+  }
+  f_impl_ << endl;
+
+  if (needs_class) {
+
+    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) {
+      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);
+        f_impl_ << ";" << endl;
+      }
+    }
+    scope_down(f_impl_);
+
+    // 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()->get_true_type();
+      if (type->is_container() || type->is_struct()) {
+        f_impl_ << endl << "+ (" << type_name(type) << ") " << name << " ";
+        scope_up(f_impl_);
+        indent(f_impl_) << "return " << cocoa_prefix_ << name << ";" << endl;
+        scope_down(f_impl_);
+      }
+    }
+
+    f_impl_ << "@end" << endl << endl;
+  }
+}
+
+/**
+ * Generates a struct definition for a thrift data type. This is a class
+ * with protected data members, read(), write(), and getters and setters.
+ *
+ * @param tstruct The struct definition
+ */
+void t_cocoa_generator::generate_struct(t_struct* tstruct) {
+  generate_cocoa_struct_interface(f_header_, tstruct, false);
+  generate_cocoa_struct_implementation(f_impl_, tstruct, false);
+}
+
+/**
+ * Exceptions are structs, but they inherit from NSException
+ *
+ * @param tstruct The struct definition
+ */
+void t_cocoa_generator::generate_xception(t_struct* txception) {
+  generate_cocoa_struct_interface(f_header_, txception, true);
+  generate_cocoa_struct_implementation(f_impl_, txception, true);
+}
+
+/**
+ * Generate the interface for a struct
+ *
+ * @param tstruct The struct definition
+ */
+void t_cocoa_generator::generate_cocoa_struct_interface(ostream& out,
+                                                        t_struct* tstruct,
+                                                        bool is_exception) {
+
+  if (is_exception) {
+    out << "enum {" << endl
+        << "  " << cocoa_prefix_ << capitalize(program_name_) << "Error" << tstruct->get_name() <<  " = -" << error_constant_++ << endl
+        << "};" << endl
+        << endl;
+  }
+
+  out << "@interface " << cocoa_prefix_ << tstruct->get_name() << " : ";
+
+  if (is_exception) {
+    out << "NSError ";
+  } else {
+    out << "NSObject ";
+  }
+  out << "<TBase, NSCoding, NSCopying> " << endl;
+
+  out << endl;
+
+  // properties
+  const vector<t_field*>& members = tstruct->get_members();
+  if (members.size() > 0) {
+    vector<t_field*>::const_iterator m_iter;
+    for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
+      out << indent() << declare_property(*m_iter) << endl;
+      out << indent() << declare_property_isset(*m_iter) << endl;
+      out << indent() << declare_property_unset(*m_iter) << endl;
+      out << endl;
+    }
+  }
+
+  out << endl;
+
+  // initializer for all fields
+  if (!members.empty()) {
+    generate_cocoa_struct_initializer_signature(out, tstruct);
+    out << ";" << endl;
+  }
+  out << endl;
+
+  out << "@end" << endl << endl;
+}
+
+/**
+ * Generate signature for initializer of struct with a parameter for
+ * each field.
+ */
+void t_cocoa_generator::generate_cocoa_struct_initializer_signature(ostream& out,
+                                                                    t_struct* tstruct) {
+  const vector<t_field*>& members = tstruct->get_members();
+  vector<t_field*>::const_iterator m_iter;
+  indent(out) << "- (instancetype) initWith";
+  for (m_iter = members.begin(); m_iter != members.end();) {
+    if (m_iter == members.begin()) {
+      out << capitalize((*m_iter)->get_name());
+    } else {
+      out << (*m_iter)->get_name();
+    }
+    out << ": (" << type_name((*m_iter)->get_type()) << ") " << (*m_iter)->get_name();
+    ++m_iter;
+    if (m_iter != members.end()) {
+      out << " ";
+    }
+  }
+}
+
+/**
+ * Generate the initWithCoder method for this struct so it's compatible with
+ * the NSCoding protocol
+ */
+void t_cocoa_generator::generate_cocoa_struct_init_with_coder_method(ostream& out,
+                                                                     t_struct* tstruct,
+                                                                     bool is_exception) {
+
+  indent(out) << "- (instancetype) initWithCoder: (NSCoder *) decoder" << endl;
+  scope_up(out);
+
+  if (is_exception) {
+    // NSExceptions conform to NSCoding, so we can call super
+    indent(out) << "self = [super initWithCoder: decoder];" << endl;
+  } else {
+    indent(out) << "self = [super init];" << endl;
+  }
+
+  indent(out) << "if (self) ";
+  scope_up(out);
+
+  const vector<t_field*>& members = tstruct->get_members();
+  vector<t_field*>::const_iterator m_iter;
+
+  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
+    t_type* t = get_true_type((*m_iter)->get_type());
+    out << indent() << "if ([decoder containsValueForKey: @\"" << (*m_iter)->get_name() << "\"])"
+        << endl;
+    scope_up(out);
+    out << indent() << "_" << (*m_iter)->get_name() << " = ";
+    if (type_can_be_null(t)) {
+      out << "[decoder decodeObjectForKey: @\"" << (*m_iter)->get_name() << "\"];"
+          << endl;
+    } else if (t->is_enum()) {
+      out << "[decoder decodeIntForKey: @\"" << (*m_iter)->get_name() << "\"];" << endl;
+    } else {
+      t_base_type::t_base tbase = ((t_base_type*)t)->get_base();
+      switch (tbase) {
+      case t_base_type::TYPE_BOOL:
+        out << "[decoder decodeBoolForKey: @\"" << (*m_iter)->get_name() << "\"];" << endl;
+        break;
+      case t_base_type::TYPE_I8:
+        out << "[decoder decodeIntForKey: @\"" << (*m_iter)->get_name() << "\"];" << endl;
+        break;
+      case t_base_type::TYPE_I16:
+        out << "[decoder decodeIntForKey: @\"" << (*m_iter)->get_name() << "\"];" << endl;
+        break;
+      case t_base_type::TYPE_I32:
+        out << "[decoder decodeInt32ForKey: @\"" << (*m_iter)->get_name() << "\"];" << endl;
+        break;
+      case t_base_type::TYPE_I64:
+        out << "[decoder decodeInt64ForKey: @\"" << (*m_iter)->get_name() << "\"];" << endl;
+        break;
+      case t_base_type::TYPE_DOUBLE:
+        out << "[decoder decodeDoubleForKey: @\"" << (*m_iter)->get_name() << "\"];" << endl;
+        break;
+      default:
+        throw "compiler error: don't know how to decode thrift type: "
+            + t_base_type::t_base_name(tbase);
+      }
+    }
+    out << indent() << "_" << (*m_iter)->get_name() << "IsSet = YES;" << endl;
+    scope_down(out);
+  }
+
+  scope_down(out);
+
+  out << indent() << "return self;" << endl;
+  scope_down(out);
+  out << endl;
+}
+
+/**
+ * Generate the encodeWithCoder method for this struct so it's compatible with
+ * the NSCoding protocol
+ */
+void t_cocoa_generator::generate_cocoa_struct_encode_with_coder_method(ostream& out,
+                                                                       t_struct* tstruct,
+                                                                       bool is_exception) {
+
+  indent(out) << "- (void) encodeWithCoder: (NSCoder *) encoder" << endl;
+  scope_up(out);
+
+  if (is_exception) {
+    // NSExceptions conform to NSCoding, so we can call super
+    out << indent() << "[super encodeWithCoder: encoder];" << endl;
+  }
+
+  const vector<t_field*>& members = tstruct->get_members();
+  vector<t_field*>::const_iterator m_iter;
+
+  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
+    t_type* t = get_true_type((*m_iter)->get_type());
+    out << indent() << "if (_" << (*m_iter)->get_name() << "IsSet)" << endl;
+    scope_up(out);
+    if (type_can_be_null(t)) {
+      out << indent() << "[encoder encodeObject: _" << (*m_iter)->get_name() << " forKey: @\""
+          << (*m_iter)->get_name() << "\"];" << endl;
+    } else if (t->is_enum()) {
+      out << indent() << "[encoder encodeInt: _" << (*m_iter)->get_name() << " forKey: @\""
+          << (*m_iter)->get_name() << "\"];" << endl;
+    } else {
+      t_base_type::t_base tbase = ((t_base_type*)t)->get_base();
+      switch (tbase) {
+      case t_base_type::TYPE_BOOL:
+        out << indent() << "[encoder encodeBool: _" << (*m_iter)->get_name() << " forKey: @\""
+            << (*m_iter)->get_name() << "\"];" << endl;
+        break;
+      case t_base_type::TYPE_I8:
+        out << indent() << "[encoder encodeInt: _" << (*m_iter)->get_name() << " forKey: @\""
+            << (*m_iter)->get_name() << "\"];" << endl;
+        break;
+      case t_base_type::TYPE_I16:
+        out << indent() << "[encoder encodeInt: _" << (*m_iter)->get_name() << " forKey: @\""
+            << (*m_iter)->get_name() << "\"];" << endl;
+        break;
+      case t_base_type::TYPE_I32:
+        out << indent() << "[encoder encodeInt32: _" << (*m_iter)->get_name() << " forKey: @\""
+            << (*m_iter)->get_name() << "\"];" << endl;
+        break;
+      case t_base_type::TYPE_I64:
+        out << indent() << "[encoder encodeInt64: _" << (*m_iter)->get_name() << " forKey: @\""
+            << (*m_iter)->get_name() << "\"];" << endl;
+        break;
+      case t_base_type::TYPE_DOUBLE:
+        out << indent() << "[encoder encodeDouble: _" << (*m_iter)->get_name() << " forKey: @\""
+            << (*m_iter)->get_name() << "\"];" << endl;
+        break;
+      default:
+        throw "compiler error: don't know how to encode thrift type: "
+            + t_base_type::t_base_name(tbase);
+      }
+    }
+    scope_down(out);
+  }
+
+  scope_down(out);
+  out << endl;
+}
+
+/**
+ * Generate the copy method for this struct
+ */
+void t_cocoa_generator::generate_cocoa_struct_copy_method(ostream& out, t_struct* tstruct, bool is_exception) {
+  out << indent() << "- (instancetype) copyWithZone:(NSZone *)zone" << endl;
+  scope_up(out);
+
+  if (is_exception) {
+    out << indent() << type_name(tstruct) << " val = [" << cocoa_prefix_ << tstruct->get_name() << " errorWithDomain: self.domain code: self.code userInfo: self.userInfo];" << endl;
+  } else {
+    out << indent() << type_name(tstruct) << " val = [" << cocoa_prefix_ << tstruct->get_name() << " new];" << endl;
+  }
+
+  const vector<t_field*>& members = tstruct->get_members();
+  vector<t_field*>::const_iterator m_iter;
+
+  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
+    t_type* t = get_true_type((*m_iter)->get_type());
+    out << indent() << "if (_" << (*m_iter)->get_name() << "IsSet)" << endl;
+    scope_up(out);
+    if (type_can_be_null(t)) {
+      out << indent() << "val." << (*m_iter)->get_name() << " = [self." << (*m_iter)->get_name() << " copy];";
+    } else {
+      out << indent() << "val." << (*m_iter)->get_name() << " = self." << (*m_iter)->get_name() << ";";
+    }
+    out << endl;
+    scope_down(out);
+  }
+
+  out << indent() << "return val;" << endl;
+
+  scope_down(out);
+  out << endl;
+}
+
+/**
+ * Generate the hash method for this struct
+ */
+void t_cocoa_generator::generate_cocoa_struct_hash_method(ostream& out, t_struct* tstruct) {
+  indent(out) << "- (NSUInteger) hash" << endl;
+  scope_up(out);
+  out << indent() << "NSUInteger hash = 17;" << endl;
+
+  const vector<t_field*>& members = tstruct->get_members();
+  vector<t_field*>::const_iterator m_iter;
+
+  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
+    t_type* t = get_true_type((*m_iter)->get_type());
+    out << indent() << "hash = (hash * 31) ^ _" << (*m_iter)->get_name()
+        << "IsSet ? 2654435761 : 0;" << endl;
+    out << indent() << "if (_" << (*m_iter)->get_name() << "IsSet)" << endl;
+    scope_up(out);
+    if (type_can_be_null(t)) {
+      out << indent() << "hash = (hash * 31) ^ [_" << (*m_iter)->get_name() << " hash];" << endl;
+    } else {
+      out << indent() << "hash = (hash * 31) ^ [@(_" << (*m_iter)->get_name() << ") hash];"
+          << endl;
+    }
+    scope_down(out);
+  }
+
+  out << indent() << "return hash;" << endl;
+  scope_down(out);
+  out << endl;
+}
+
+/**
+ * Generate the isEqual method for this struct
+ */
+void t_cocoa_generator::generate_cocoa_struct_is_equal_method(ostream& out, t_struct* tstruct, bool is_exception) {
+  indent(out) << "- (BOOL) isEqual: (id) anObject" << endl;
+  scope_up(out);
+
+  indent(out) << "if (self == anObject) {" << endl;
+  indent_up();
+  indent(out) << "return YES;" << endl;
+  indent_down();
+  indent(out) << "}" << endl;
+
+  string class_name = cocoa_prefix_ + tstruct->get_name();
+
+  if (is_exception) {
+    indent(out) << "if (![super isEqual:anObject]) {" << endl;
+    indent_up();
+    indent(out) << "return NO;" << endl;
+    indent_down();
+    indent(out) << "}" << endl << endl;
+  }
+  else {
+    indent(out) << "if (![anObject isKindOfClass:[" << class_name << " class]]) {" << endl;
+    indent_up();
+    indent(out) << "return NO;" << endl;
+    indent_down();
+    indent(out) << "}" << endl;
+  }
+
+  const vector<t_field*>& members = tstruct->get_members();
+  vector<t_field*>::const_iterator m_iter;
+
+  if (!members.empty()) {
+    indent(out) << class_name << " *other = (" << class_name << " *)anObject;" << endl;
+
+    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 (type_can_be_null(t)) {
+        out << indent() << "if ((_" << name << "IsSet != other->_" << name << "IsSet) ||" << endl
+            << indent() << "    "
+            << "(_" << name << "IsSet && "
+            << "((_" << name << " || other->_" << name << ") && "
+            << "![_" << name << " isEqual:other->_" << name << "]))) {" << endl;
+      } else {
+        out << indent() << "if ((_" << name << "IsSet != other->_" << name << "IsSet) ||" << endl
+            << indent() << "    "
+            << "(_" << name << "IsSet && "
+            << "(_" << name << " != other->_" << name << "))) {" << endl;
+      }
+      indent_up();
+      indent(out) << "return NO;" << endl;
+      indent_down();
+      indent(out) << "}" << endl;
+    }
+  }
+
+  out << indent() << "return YES;" << endl;
+  scope_down(out);
+  out << endl;
+}
+
+/**
+ * Generate struct implementation.
+ *
+ * @param tstruct      The struct definition
+ * @param is_exception Is this an exception?
+ * @param is_result    If this is a result it needs a different writer
+ */
+void t_cocoa_generator::generate_cocoa_struct_implementation(ostream& out,
+                                                             t_struct* tstruct,
+                                                             bool is_exception,
+                                                             bool is_result) {
+  indent(out) << "@implementation " << cocoa_prefix_ << tstruct->get_name() << endl << endl;
+
+  const vector<t_field*>& members = tstruct->get_members();
+  vector<t_field*>::const_iterator m_iter;
+
+  // exceptions need to call the designated initializer on NSException
+  if (is_exception) {
+    out << indent() << "- (instancetype) init" << endl;
+    scope_up(out);
+    out << indent() << "return [super initWithDomain: " << cocoa_prefix_ << capitalize(program_name_) << "ErrorDomain" << endl
+        << indent() << "                        code: " << cocoa_prefix_ << capitalize(program_name_) << "Error" << tstruct->get_name() << endl
+        << indent() << "                    userInfo: nil];" << endl;
+    scope_down(out);
+    out << endl;
+  } else {
+    // struct
+
+    // default initializer
+    // setup instance variables with default values
+    indent(out) << "- (instancetype) init" << endl;
+    scope_up(out);
+    indent(out) << "self = [super init];" << endl;
+    indent(out) << "if (self)";
+    scope_up(out);
+    if (members.size() > 0) {
+      for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
+        t_type* t = get_true_type((*m_iter)->get_type());
+        if ((*m_iter)->get_value() != NULL) {
+          print_const_value(out,
+                            "self." + (*m_iter)->get_name(),
+                            t,
+                            (*m_iter)->get_value(),
+                            false);
+        }
+      }
+    }
+    scope_down(out);
+    indent(out) << "return self;" << endl;
+    scope_down(out);
+    out << endl;
+  }
+
+  // initializer with all fields as params
+  if (!members.empty()) {
+    generate_cocoa_struct_initializer_signature(out, tstruct);
+    out << endl;
+    scope_up(out);
+    if (is_exception) {
+      out << indent() << "self = [self init];" << endl;
+    } else {
+      out << indent() << "self = [super init];" << endl;
+    }
+
+    indent(out) << "if (self)";
+    scope_up(out);
+    for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
+      out << indent() << "_" << (*m_iter)->get_name() << " = ";
+      if (get_true_type((*m_iter)->get_type())->is_container()) {
+        out << "[" << (*m_iter)->get_name() << " mutableCopy];" << endl;
+      } else {
+        out << (*m_iter)->get_name() << ";" << endl;
+      }
+      out << indent() << "_" << (*m_iter)->get_name() << "IsSet = YES;" << endl;
+    }
+    scope_down(out);
+
+    out << indent() << "return self;" << endl;
+    scope_down(out);
+    out << endl;
+  }
+
+  // initWithCoder for NSCoding
+  generate_cocoa_struct_init_with_coder_method(out, tstruct, is_exception);
+  // encodeWithCoder for NSCoding
+  generate_cocoa_struct_encode_with_coder_method(out, tstruct, is_exception);
+  // hash and isEqual for NSObject
+  generate_cocoa_struct_hash_method(out, tstruct);
+  generate_cocoa_struct_is_equal_method(out, tstruct, is_exception);
+  // copy for NSObject
+  generate_cocoa_struct_copy_method(out, tstruct, is_exception);
+
+  // the rest of the methods
+  generate_cocoa_struct_field_accessor_implementations(out, tstruct, is_exception);
+  generate_cocoa_struct_reader(out, tstruct);
+  if (is_result) {
+    generate_cocoa_struct_result_writer(out, tstruct);
+  } else {
+    generate_cocoa_struct_writer(out, tstruct);
+  }
+  generate_cocoa_struct_validator(out, tstruct);
+  generate_cocoa_struct_description(out, tstruct);
+
+  out << "@end" << endl << endl;
+}
+
+/**
+ * Generates a function to read all the fields of the struct.
+ *
+ * @param tstruct The struct definition
+ */
+void t_cocoa_generator::generate_cocoa_struct_reader(ostream& out, t_struct* tstruct) {
+  out << "- (BOOL) read: (id <TProtocol>) inProtocol error: (NSError *__autoreleasing *)__thriftError" << endl;
+  scope_up(out);
+
+  const vector<t_field*>& fields = tstruct->get_members();
+  vector<t_field*>::const_iterator f_iter;
+
+  // Declare stack tmp variables
+  indent(out) << "NSString * fieldName;" << endl;
+  indent(out) << "SInt32 fieldType;" << endl;
+  indent(out) << "SInt32 fieldID;" << endl;
+  out << endl;
+
+  indent(out) << "if (![inProtocol readStructBeginReturningName: NULL error: __thriftError]) return NO;" << endl;
+
+  // Loop over reading in fields
+  indent(out) << "while (true)" << endl;
+  scope_up(out);
+
+  // Read beginning field marker
+  indent(out)
+      << "if (![inProtocol readFieldBeginReturningName: &fieldName type: &fieldType fieldID: &fieldID error: __thriftError]) return NO;"
+      << endl;
+
+  // Check for field STOP marker and break
+  indent(out) << "if (fieldType == TTypeSTOP) { " << endl;
+  indent_up();
+  indent(out) << "break;" << endl;
+  indent_down();
+  indent(out) << "}" << endl;
+
+  // Switch statement on the field we are reading
+  indent(out) << "switch (fieldID)" << endl;
+
+  scope_up(out);
+
+  // Generate deserialization code for known cases
+  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+    indent(out) << "case " << (*f_iter)->get_key() << ":" << endl;
+    indent_up();
+    indent(out) << "if (fieldType == " << type_to_enum((*f_iter)->get_type()) << ") {" << endl;
+    indent_up();
+
+    generate_deserialize_field(out, *f_iter, "fieldValue");
+    indent(out) << call_field_setter(*f_iter, "fieldValue") << endl;
+
+    indent_down();
+    out << indent() << "} else { " << endl;
+    if (log_unexpected_) {
+      out << indent() << "  NSLog(@\"%s: field ID %i has unexpected type %i.  Skipping.\", "
+                         "__PRETTY_FUNCTION__, (int)fieldID, (int)fieldType);" << endl;
+    }
+
+    out << indent() << "  if (![TProtocolUtil skipType: fieldType onProtocol: inProtocol error: __thriftError]) return NO;" << endl;
+    out << indent() << "}" << endl << indent() << "break;" << endl;
+    indent_down();
+  }
+
+  // In the default case we skip the field
+  out << indent() << "default:" << endl;
+  if (log_unexpected_) {
+    out << indent() << "  NSLog(@\"%s: unexpected field ID %i with type %i.  Skipping.\", "
+                       "__PRETTY_FUNCTION__, (int)fieldID, (int)fieldType);" << endl;
+  }
+
+  out << indent() << "  if (![TProtocolUtil skipType: fieldType onProtocol: inProtocol error: __thriftError]) return NO;" << endl;
+
+  out << indent() << "  break;" << endl;
+
+  scope_down(out);
+
+  // Read field end marker
+  indent(out) << "if (![inProtocol readFieldEnd: __thriftError]) return NO;" << endl;
+
+  scope_down(out);
+
+  out << indent() << "if (![inProtocol readStructEnd: __thriftError]) return NO;" << endl;
+
+  // performs various checks (e.g. check that all required fields are set)
+  if (validate_required_) {
+    out << indent() << "if (![self validate: __thriftError]) return NO;" << endl;
+  }
+
+  indent(out) << "return YES;" << endl;
+
+  indent_down();
+  out << indent() << "}" << endl << endl;
+}
+
+/**
+ * Generates a function to write all the fields of the struct
+ *
+ * @param tstruct The struct definition
+ */
+void t_cocoa_generator::generate_cocoa_struct_writer(ostream& out, t_struct* tstruct) {
+  out << indent() << "- (BOOL) write: (id <TProtocol>) outProtocol error: (NSError *__autoreleasing *)__thriftError {" << endl;
+  indent_up();
+
+  string name = tstruct->get_name();
+  const vector<t_field*>& fields = tstruct->get_members();
+  vector<t_field*>::const_iterator f_iter;
+
+  out << indent() << "if (![outProtocol writeStructBeginWithName: @\"" << name << "\" error: __thriftError]) return NO;" << endl;
+
+  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+    out << indent() << "if (_" << (*f_iter)->get_name() << "IsSet) {" << endl;
+    indent_up();
+    bool null_allowed = type_can_be_null((*f_iter)->get_type());
+    if (null_allowed) {
+      out << indent() << "if (_" << (*f_iter)->get_name() << " != nil) {" << endl;
+      indent_up();
+    }
+
+    indent(out) << "if (![outProtocol writeFieldBeginWithName: @\"" << (*f_iter)->get_name()
+                << "\" type: " << type_to_enum((*f_iter)->get_type())
+                << " fieldID: " << (*f_iter)->get_key() << " error: __thriftError]) return NO;" << endl;
+
+    // Write field contents
+    generate_serialize_field(out, *f_iter, "_" + (*f_iter)->get_name());
+
+    // Write field closer
+    indent(out) << "if (![outProtocol writeFieldEnd: __thriftError]) return NO;" << endl;
+
+    if (null_allowed) {
+      scope_down(out);
+    }
+    scope_down(out);
+  }
+  // Write the struct map
+  out << indent() << "if (![outProtocol writeFieldStop: __thriftError]) return NO;" << endl
+      << indent() << "if (![outProtocol writeStructEnd: __thriftError]) return NO;" << endl;
+
+  indent(out) << "return YES;" << endl;
+
+  indent_down();
+  out << indent() << "}" << endl << endl;
+}
+
+/**
+ * Generates a function to write all the fields of the struct, which
+ * is a function result. These fields are only written if they are
+ * set, and only one of them can be set at a time.
+ *
+ * @param tstruct The struct definition
+ */
+void t_cocoa_generator::generate_cocoa_struct_result_writer(ostream& out, t_struct* tstruct) {
+  out << indent() << "- (BOOL) write: (id <TProtocol>) outProtocol error: (NSError *__autoreleasing *)__thriftError {" << endl;
+  indent_up();
+
+  string name = tstruct->get_name();
+  const vector<t_field*>& fields = tstruct->get_members();
+  vector<t_field*>::const_iterator f_iter;
+
+  out << indent() << "if (![outProtocol writeStructBeginWithName: @\"" << name << "\" error: __thriftError]) return NO;" << endl;
+
+  bool first = true;
+  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+    if (first) {
+      first = false;
+      out << endl << indent() << "if ";
+    } else {
+      out << " else if ";
+    }
+
+    out << "(_" << (*f_iter)->get_name() << "IsSet) {" << endl;
+    indent_up();
+
+    bool null_allowed = type_can_be_null((*f_iter)->get_type());
+    if (null_allowed) {
+      out << indent() << "if (_" << (*f_iter)->get_name() << " != nil) {" << endl;
+      indent_up();
+    }
+
+    indent(out) << "if (![outProtocol writeFieldBeginWithName: @\"" << (*f_iter)->get_name()
+                << "\" type: " << type_to_enum((*f_iter)->get_type())
+                << " fieldID: " << (*f_iter)->get_key() << " error: __thriftError]) return NO;" << endl;
+
+    // Write field contents
+    generate_serialize_field(out, *f_iter, "_" + (*f_iter)->get_name());
+
+    // Write field closer
+    indent(out) << "if (![outProtocol writeFieldEnd: __thriftError]) return NO;" << endl;
+
+    if (null_allowed) {
+      indent_down();
+      indent(out) << "}" << endl;
+    }
+
+    indent_down();
+    indent(out) << "}";
+  }
+  // Write the struct map
+  out << endl << indent() << "if (![outProtocol writeFieldStop: __thriftError]) return NO;"
+      << endl << indent() << "if (![outProtocol writeStructEnd: __thriftError]) return NO;"
+      << endl;
+
+  indent(out) << "return YES;" << endl;
+
+  indent_down();
+  out << indent() << "}" << endl << endl;
+}
+
+/**
+ * Generates a function to perform various checks
+ * (e.g. check that all required fields are set)
+ *
+ * @param tstruct The struct definition
+ */
+void t_cocoa_generator::generate_cocoa_struct_validator(ostream& out, t_struct* tstruct) {
+  out << indent() << "- (BOOL) validate: (NSError *__autoreleasing *)__thriftError {" << endl;
+  indent_up();
+
+  const vector<t_field*>& fields = tstruct->get_members();
+  vector<t_field*>::const_iterator f_iter;
+
+  out << indent() << "// check for required fields" << endl;
+  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+    t_field* field = (*f_iter);
+    if ((*f_iter)->get_req() == t_field::T_REQUIRED) {
+      out << indent() << "if (!_" << field->get_name() << "IsSet) ";
+      scope_up(out);
+      indent(out) << "if (__thriftError) ";
+      scope_up(out);
+      out << indent() << "*__thriftError = [NSError errorWithDomain: TProtocolErrorDomain" << endl
+          << indent() << "                                     code: TProtocolErrorUnknown" << endl
+          << indent() << "                                 userInfo: @{TProtocolErrorExtendedErrorKey: @(TProtocolExtendedErrorMissingRequiredField)," << endl
+          << indent() << "                                             TProtocolErrorFieldNameKey: @\"" << (*f_iter)->get_name() << "\"}];" << endl;
+      scope_down(out);
+      scope_down(out);
+    }
+  }
+  indent(out) << "return YES;" << endl;
+  indent_down();
+  out << indent() << "}" << endl << endl;
+}
+
+/**
+ * Generate property accessor methods for all fields in the struct.
+ * getter, setter, isset getter.
+ *
+ * @param tstruct The struct definition
+ */
+void t_cocoa_generator::generate_cocoa_struct_field_accessor_implementations(ostream& out,
+                                                                             t_struct* tstruct,
+                                                                             bool is_exception) {
+  (void)is_exception;
+  const vector<t_field*>& fields = tstruct->get_members();
+  vector<t_field*>::const_iterator f_iter;
+  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+    t_field* field = *f_iter;
+    t_type* type = get_true_type(field->get_type());
+    std::string field_name = field->get_name();
+    std::string cap_name = field_name;
+    cap_name[0] = toupper(cap_name[0]);
+
+    // Simple setter
+    indent(out) << "- (void) set" << cap_name << ": (" << type_name(type, false, true) << ") " << field_name
+                << " {" << endl;
+    indent_up();
+    indent(out) << "_" << field_name << " = " << field_name << ";" << endl;
+    indent(out) << "_" << field_name << "IsSet = YES;" << endl;
+    indent_down();
+    indent(out) << "}" << endl << endl;
+
+    // Unsetter - do we need this?
+    indent(out) << "- (void) unset" << cap_name << " {" << endl;
+    indent_up();
+    if (type_can_be_null(type)) {
+      indent(out) << "_" << field_name << " = nil;" << endl;
+    }
+    indent(out) << "_" << field_name << "IsSet = NO;" << endl;
+    indent_down();
+    indent(out) << "}" << endl << endl;
+  }
+}
+
+/**
+ * Generates a description method for the given struct
+ *
+ * @param tstruct The struct definition
+ */
+void t_cocoa_generator::generate_cocoa_struct_description(ostream& out, t_struct* tstruct) {
+
+  // Allow use of debugDescription so the app can add description via a cateogory/extension
+  if (debug_descriptions_) {
+    out << indent() << "- (NSString *) debugDescription {" << endl;
+  }
+  else {
+    out << indent() << "- (NSString *) description {" << endl;
+  }
+  indent_up();
+
+  out << indent() << "NSMutableString * ms = [NSMutableString stringWithString: @\""
+      << cocoa_prefix_ << tstruct->get_name() << "(\"];" << endl;
+
+  const vector<t_field*>& fields = tstruct->get_members();
+  vector<t_field*>::const_iterator f_iter;
+  bool first = true;
+  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+    if (first) {
+      first = false;
+      indent(out) << "[ms appendString: @\"" << (*f_iter)->get_name() << ":\"];" << endl;
+    } else {
+      indent(out) << "[ms appendString: @\"," << (*f_iter)->get_name() << ":\"];" << endl;
+    }
+    t_type* ttype = (*f_iter)->get_type();
+    indent(out) << "[ms appendFormat: @\"" << format_string_for_type(ttype) << "\", "
+                << format_cast_for_type(ttype) << "_" << (*f_iter)->get_name() << "];" << endl;
+  }
+  out << indent() << "[ms appendString: @\")\"];" << endl << indent()
+      << "return [NSString stringWithString: ms];" << endl;
+
+  indent_down();
+  indent(out) << "}" << endl << endl;
+}
+
+/**
+ * Generates a thrift service.  In Objective-C this consists of a
+ * protocol definition, a client interface and a client implementation.
+ *
+ * @param tservice The service definition
+ */
+void t_cocoa_generator::generate_service(t_service* tservice) {
+  generate_cocoa_service_protocol(f_header_, tservice);
+  generate_cocoa_service_client_interface(f_header_, tservice);
+  generate_cocoa_service_server_interface(f_header_, tservice);
+  generate_cocoa_service_helpers(tservice);
+  generate_cocoa_service_client_implementation(f_impl_, tservice);
+  generate_cocoa_service_server_implementation(f_impl_, tservice);
+  if (async_clients_) {
+    generate_cocoa_service_async_protocol(f_header_, tservice);
+    generate_cocoa_service_client_async_interface(f_header_, tservice);
+    generate_cocoa_service_client_async_implementation(f_impl_, tservice);
+  }
+}
+
+/**
+ * Generates structs for all the service return types
+ *
+ * @param tservice The service
+ */
+void t_cocoa_generator::generate_cocoa_service_helpers(t_service* tservice) {
+  vector<t_function*> functions = tservice->get_functions();
+  vector<t_function*>::iterator f_iter;
+  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
+
+    t_struct* ts = (*f_iter)->get_arglist();
+
+    string qname = function_args_helper_struct_type(tservice, *f_iter);
+
+    t_struct qname_ts = t_struct(ts->get_program(), qname);
+
+    const vector<t_field*>& members = ts->get_members();
+    vector<t_field*>::const_iterator m_iter;
+    for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
+      qname_ts.append(*m_iter);
+    }
+
+    generate_cocoa_struct_interface(f_impl_, &qname_ts, false);
+    generate_cocoa_struct_implementation(f_impl_, &qname_ts, false, false);
+    generate_function_helpers(tservice, *f_iter);
+  }
+}
+
+string t_cocoa_generator::function_result_helper_struct_type(t_service *tservice, t_function* tfunction) {
+  if (tfunction->is_oneway()) {
+    return tservice->get_name() + "_" + tfunction->get_name();
+  } else {
+    return tservice->get_name() + "_" + tfunction->get_name() + "_result";
+  }
+}
+
+string t_cocoa_generator::function_args_helper_struct_type(t_service *tservice, t_function* tfunction) {
+  return tservice->get_name() + "_" + tfunction->get_name() + "_args";
+}
+
+/**
+ * Generates a struct and helpers for a function.
+ *
+ * @param tfunction The function
+ */
+void t_cocoa_generator::generate_function_helpers(t_service *tservice, t_function* tfunction) {
+  if (tfunction->is_oneway()) {
+    return;
+  }
+
+  // create a result struct with a success field of the return type,
+  // and a field for each type of exception thrown
+  t_struct result(program_, function_result_helper_struct_type(tservice, tfunction));
+  t_field success(tfunction->get_returntype(), "success", 0);
+  if (!tfunction->get_returntype()->is_void()) {
+    result.append(&success);
+  }
+
+  t_struct* xs = tfunction->get_xceptions();
+  const vector<t_field*>& fields = xs->get_members();
+  vector<t_field*>::const_iterator f_iter;
+  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+    result.append(*f_iter);
+  }
+
+  // generate the result struct
+  generate_cocoa_struct_interface(f_impl_, &result, false);
+  generate_cocoa_struct_implementation(f_impl_, &result, false, true);
+}
+
+/**
+ * Generates a service protocol definition.
+ *
+ * @param tservice The service to generate a protocol definition for
+ */
+void t_cocoa_generator::generate_cocoa_service_protocol(ostream& out, t_service* tservice) {
+  out << "@protocol " << cocoa_prefix_ << tservice->get_name() << " <NSObject>" << endl;
+
+  vector<t_function*> functions = tservice->get_functions();
+  vector<t_function*>::iterator f_iter;
+  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
+    out << "- " << function_signature(*f_iter, true) << ";"
+        << "  // throws ";
+    t_struct* xs = (*f_iter)->get_xceptions();
+    const std::vector<t_field*>& xceptions = xs->get_members();
+    vector<t_field*>::const_iterator x_iter;
+    for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) {
+      out << type_name((*x_iter)->get_type()) + ", ";
+    }
+    out << "TException" << endl;
+  }
+  out << "@end" << endl << endl;
+}
+
+/**
+ * Generates an asynchronous service protocol definition.
+ *
+ * @param tservice The service to generate a protocol definition for
+ */
+void t_cocoa_generator::generate_cocoa_service_async_protocol(ostream& out, t_service* tservice) {
+  out << "@protocol " << cocoa_prefix_ << tservice->get_name() << "Async"
+      << " <NSObject>" << endl;
+
+  vector<t_function*> functions = tservice->get_functions();
+  vector<t_function*>::iterator f_iter;
+  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
+    out << "- " << async_function_signature(*f_iter, false) << ";" << endl;
+    if (promise_kit_) {
+      out << "- " << promise_function_signature(*f_iter) << ";" << endl;
+    }
+  }
+  out << "@end" << endl << endl;
+}
+
+/**
+ * Generates a service client interface definition.
+ *
+ * @param tservice The service to generate a client interface definition for
+ */
+void t_cocoa_generator::generate_cocoa_service_client_interface(ostream& out,
+                                                                t_service* tservice) {
+  out << "@interface " << cocoa_prefix_ << tservice->get_name() << "Client : TBaseClient <"
+      << cocoa_prefix_ << tservice->get_name() << "> " << endl;
+
+  out << "- (id) initWithProtocol: (id <TProtocol>) protocol;" << endl;
+  out << "- (id) initWithInProtocol: (id <TProtocol>) inProtocol outProtocol: (id <TProtocol>) "
+         "outProtocol;" << endl;
+  out << "@end" << endl << endl;
+}
+
+/**
+ * Generates a service client interface definition.
+ *
+ * @param tservice The service to generate a client interface definition for
+ */
+void t_cocoa_generator::generate_cocoa_service_client_async_interface(ostream& out,
+                                                                      t_service* tservice) {
+  out << "@interface " << cocoa_prefix_ << tservice->get_name() << "ClientAsync : TBaseClient <"
+      << cocoa_prefix_ << tservice->get_name() << "Async> " << endl
+      << endl;
+
+  out << "- (id) initWithProtocolFactory: (id <TProtocolFactory>) protocolFactory "
+      << "transportFactory: (id <TAsyncTransportFactory>) transportFactory;" << endl;
+  out << "@end" << endl << endl;
+}
+
+/**
+ * Generates a service server interface definition. In other words, the TProcess implementation for
+ *the
+ * service definition.
+ *
+ * @param tservice The service to generate a client interface definition for
+ */
+void t_cocoa_generator::generate_cocoa_service_server_interface(ostream& out,
+                                                                t_service* tservice) {
+  out << "@interface " << cocoa_prefix_ << tservice->get_name()
+      << "Processor : NSObject <TProcessor> " << endl;
+
+  out << "- (id) initWith" << tservice->get_name() << ": (id <" << cocoa_prefix_
+      << tservice->get_name() << ">) service;" << endl;
+  out << "- (id<" << cocoa_prefix_ << tservice->get_name() << ">) service;" << endl;
+
+  out << "@end" << endl << endl;
+}
+
+void t_cocoa_generator::generate_cocoa_service_client_send_function_implementation(
+    ostream& out,
+    t_service *tservice,
+    t_function* tfunction,
+    bool needs_protocol) {
+  string funname = tfunction->get_name();
+
+  t_function send_function(g_type_bool,
+                           string("send_") + tfunction->get_name(),
+                           tfunction->get_arglist());
+
+  string argsname = function_args_helper_struct_type(tservice, tfunction);
+
+  // Open function
+  indent(out) << "- (BOOL) send_" << tfunction->get_name() << argument_list(tfunction->get_arglist(), needs_protocol ? "outProtocol" : "", true) << endl;
+  scope_up(out);
+
+  // Serialize the request
+  out << indent() << "if (![outProtocol writeMessageBeginWithName: @\"" << funname << "\""
+      << (tfunction->is_oneway() ? " type: TMessageTypeONEWAY" : " type: TMessageTypeCALL")
+      << " sequenceID: 0 error: __thriftError]) return NO;" << endl;
+
+  out << indent() << "if (![outProtocol writeStructBeginWithName: @\"" << argsname
+                  << "\" error: __thriftError]) return NO;" << endl;
+
+  // write out function parameters
+  t_struct* arg_struct = tfunction->get_arglist();
+  const vector<t_field*>& fields = arg_struct->get_members();
+  vector<t_field*>::const_iterator fld_iter;
+  for (fld_iter = fields.begin(); fld_iter != fields.end(); ++fld_iter) {
+    string fieldName = (*fld_iter)->get_name();
+    if (type_can_be_null((*fld_iter)->get_type())) {
+      out << indent() << "if (" << fieldName << " != nil)";
+      scope_up(out);
+    }
+    out << indent() << "if (![outProtocol writeFieldBeginWithName: @\"" << fieldName
+        << "\""
+           " type: " << type_to_enum((*fld_iter)->get_type())
+        << " fieldID: " << (*fld_iter)->get_key() << " error: __thriftError]) return NO;" << endl;
+
+    generate_serialize_field(out, *fld_iter, fieldName);
+
+    out << indent() << "if (![outProtocol writeFieldEnd: __thriftError]) return NO;" << endl;
+
+    if (type_can_be_null((*fld_iter)->get_type())) {
+      indent_down();
+      out << indent() << "}" << endl;
+    }
+  }
+
+  out << indent() << "if (![outProtocol writeFieldStop: __thriftError]) return NO;" << endl;
+  out << indent() << "if (![outProtocol writeStructEnd: __thriftError]) return NO;" << endl;
+  out << indent() << "if (![outProtocol writeMessageEnd: __thriftError]) return NO;" << endl;
+  out << indent() << "return YES;" << endl;
+  scope_down(out);
+  out << endl;
+}
+
+void t_cocoa_generator::generate_cocoa_service_client_recv_function_implementation(
+    ostream& out,
+    t_service* tservice,
+    t_function* tfunction,
+    bool needs_protocol) {
+
+
+  // Open function
+  indent(out) << "- (BOOL) recv_" << tfunction->get_name();
+  if (!tfunction->get_returntype()->is_void()) {
+    out << ": (" << type_name(tfunction->get_returntype(), false, true) << " *) result ";
+    if (needs_protocol) {
+      out << "protocol";
+    } else {
+      out << "error";
+    }
+  }
+  if (needs_protocol) {
+    out << ": (id<TProtocol>) inProtocol error";
+  }
+  out << ": (NSError *__autoreleasing *)__thriftError" << endl;
+  scope_up(out);
+
+  // TODO(mcslee): Message validation here, was the seqid etc ok?
+
+  // check for an exception
+  out << indent() << "NSError *incomingException = [self checkIncomingMessageException: inProtocol];" << endl
+      << indent() << "if (incomingException)";
+  scope_up(out);
+  out << indent() << "if (__thriftError)";
+  scope_up(out);
+  out << indent() << "*__thriftError = incomingException;" << endl;
+  scope_down(out);
+  out << indent() << "return NO;" << endl;
+  scope_down(out);
+
+  // FIXME - could optimize here to reduce creation of temporary objects.
+  string resultname = function_result_helper_struct_type(tservice, tfunction);
+  out << indent() << cocoa_prefix_ << resultname << " * resulter = [" << cocoa_prefix_ << resultname << " new];" << endl;
+  indent(out) << "if (![resulter read: inProtocol error: __thriftError]) return NO;" << endl;
+  indent(out) << "if (![inProtocol readMessageEnd: __thriftError]) return NO;" << endl;
+
+  // Careful, only return _result if not a void function
+  if (!tfunction->get_returntype()->is_void()) {
+    out << indent() << "if (resulter.successIsSet)";
+    scope_up(out);
+    out << indent() << "*result = resulter.success;" << endl;
+    out << indent() << "return YES;" << endl;
+    scope_down(out);
+  }
+
+  t_struct* xs = tfunction->get_xceptions();
+  const std::vector<t_field*>& xceptions = xs->get_members();
+  vector<t_field*>::const_iterator x_iter;
+  for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) {
+    out << indent() << "if (resulter." << (*x_iter)->get_name() << "IsSet)";
+    scope_up(out);
+    out << indent() << "if (__thriftError)";
+    scope_up(out);
+    out << indent() << "*__thriftError = [resulter " << (*x_iter)->get_name() << "];" << endl;
+    scope_down(out);
+    out << indent() << "return NO;" << endl;
+    scope_down(out);
+  }
+
+  // If you get here it's an exception, unless a void function
+  if (tfunction->get_returntype()->is_void()) {
+    indent(out) << "return YES;" << endl;
+  } else {
+    out << indent() << "if (__thriftError)";
+    scope_up(out);
+    out << indent() << "*__thriftError = [NSError errorWithDomain: TApplicationErrorDomain" << endl
+        << indent() << "                                     code: TApplicationErrorMissingResult" << endl
+        << indent() << "                                 userInfo: @{TApplicationErrorMethodKey: @\""
+        << tfunction->get_name() << "\"}];" << endl;
+    scope_down(out);
+    out << indent() << "return NO;" << endl;
+  }
+
+  // Close function
+  scope_down(out);
+  out << endl;
+}
+
+/**
+ * Generates an invocation of a given 'send_' function.
+ *
+ * @param tfunction The service to generate an implementation for
+ */
+void t_cocoa_generator::generate_cocoa_service_client_send_function_invocation(
+                                                                               ostream& out,
+                                                                               t_function* tfunction) {
+
+  t_struct* arg_struct = tfunction->get_arglist();
+  const vector<t_field*>& fields = arg_struct->get_members();
+  vector<t_field*>::const_iterator fld_iter;
+  out << indent() << "if (![self send_" << tfunction->get_name();
+  bool first = true;
+  for (fld_iter = fields.begin(); fld_iter != fields.end(); ++fld_iter) {
+    string fieldName = (*fld_iter)->get_name();
+    out << " ";
+    if (first) {
+      first = false;
+      out << ": " << fieldName;
+    } else {
+      out << fieldName << ": " << fieldName;
+    }
+  }
+  if (!fields.empty()) {
+    out << " error";
+  }
+  out << ": __thriftError]) " << invalid_return_statement(tfunction) << endl;
+}
+
+/**
+ * Generates an invocation of a given 'send_' function.
+ *
+ * @param tfunction The service to generate an implementation for
+ */
+void t_cocoa_generator::generate_cocoa_service_client_send_async_function_invocation(
+                                                                                     ostream& out,
+                                                                                     t_function* tfunction,
+                                                                                     string failureBlockName) {
+
+  t_struct* arg_struct = tfunction->get_arglist();
+  const vector<t_field*>& fields = arg_struct->get_members();
+  vector<t_field*>::const_iterator fld_iter;
+  out << indent() << "if (![self send_" << tfunction->get_name();
+  bool first = true;
+  for (fld_iter = fields.begin(); fld_iter != fields.end(); ++fld_iter) {
+    string fieldName = (*fld_iter)->get_name();
+    out << " ";
+    if (first) {
+      first = false;
+      out << ": " << fieldName;
+    } else {
+      out << fieldName << ": " << fieldName;
+    }
+  }
+  if (!fields.empty()) {
+    out << " protocol";
+  }
+  out << ": protocol error: &thriftError]) ";
+  scope_up(out);
+  out << indent() << failureBlockName << "(thriftError);" << endl
+      << indent() << "return;" << endl;
+  scope_down(out);
+}
+
+/**
+ * Generates a service client implementation.
+ *
+ * @param tservice The service to generate an implementation for
+ */
+void t_cocoa_generator::generate_cocoa_service_client_implementation(ostream& out,
+                                                                     t_service* tservice) {
+
+  string name = cocoa_prefix_ + tservice->get_name() + "Client";
+
+  out << "@interface " << name << " () ";
+  scope_up(out);
+  out << endl;
+  out << indent() << "id<TProtocol> inProtocol;" << endl;
+  out << indent() << "id<TProtocol> outProtocol;" << endl;
+  out << endl;
+  scope_down(out);
+  out << endl;
+  out << "@end" << endl << endl;
+
+  out << "@implementation " << name << endl;
+
+  // initializers
+  out << "- (id) initWithProtocol: (id <TProtocol>) protocol" << endl;
+  scope_up(out);
+  out << indent() << "return [self initWithInProtocol: protocol outProtocol: protocol];" << endl;
+  scope_down(out);
+  out << endl;
+
+  out << "- (id) initWithInProtocol: (id <TProtocol>) anInProtocol outProtocol: (id <TProtocol>) "
+         "anOutProtocol" << endl;
+  scope_up(out);
+  out << indent() << "self = [super init];" << endl;
+  out << indent() << "if (self) ";
+  scope_up(out);
+  out << indent() << "inProtocol = anInProtocol;" << endl;
+  out << indent() << "outProtocol = anOutProtocol;" << endl;
+  scope_down(out);
+  out << indent() << "return self;" << endl;
+  scope_down(out);
+  out << endl;
+
+  // generate client method implementations
+  vector<t_function*> functions = tservice->get_functions();
+  vector<t_function*>::const_iterator f_iter;
+  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
+
+    generate_cocoa_service_client_send_function_implementation(out, tservice, *f_iter, false);
+
+    if (!(*f_iter)->is_oneway()) {
+      generate_cocoa_service_client_recv_function_implementation(out, tservice, *f_iter, false);
+    }
+
+    // Open function
+    indent(out) << "- " << function_signature(*f_iter, true) << endl;
+    scope_up(out);
+    generate_cocoa_service_client_send_function_invocation(out, *f_iter);
+
+    out << indent() << "if (![[outProtocol transport] flush: __thriftError]) " << invalid_return_statement(*f_iter) << endl;
+    if (!(*f_iter)->is_oneway()) {
+      if ((*f_iter)->get_returntype()->is_void()) {
+        out << indent() << "if (![self recv_" << (*f_iter)->get_name() << ": __thriftError]) return NO;" << endl;
+        out << indent() << "return YES;" << endl;
+      } else {
+        out << indent() << type_name((*f_iter)->get_returntype(), false, true) << " __result;" << endl
+            << indent() << "if (![self recv_" << (*f_iter)->get_name() << ": &__result error: __thriftError]) "
+            << invalid_return_statement(*f_iter) << endl;
+        if (type_can_be_null((*f_iter)->get_returntype())) {
+          out << indent() << "return __result;" << endl;
+        } else {
+          out << indent() << "return @(__result);" << endl;
+        }
+      }
+    }
+    else {
+      out << indent() << "return YES;" << endl;
+    }
+    scope_down(out);
+    out << endl;
+  }
+
+  out << "@end" << endl << endl;
+}
+
+/**
+ * Generates a service client implementation for its asynchronous interface.
+ *
+ * @param tservice The service to generate an implementation for
+ */
+void t_cocoa_generator::generate_cocoa_service_client_async_implementation(ostream& out,
+                                                                           t_service* tservice) {
+
+  string name = cocoa_prefix_ + tservice->get_name() + "ClientAsync";
+
+  out << "@interface " << name << " () ";
+  scope_up(out);
+  out << endl;
+  out << indent() << "id<TProtocolFactory> protocolFactory;" << endl;
+  out << indent() << "id<TAsyncTransportFactory> transportFactory;" << endl;
+  out << endl;
+  scope_down(out);
+  out << endl;
+  out << "@end" << endl << endl;
+
+
+  out << "@implementation " << name << endl
+      << endl << "- (id) initWithProtocolFactory: (id <TProtocolFactory>) aProtocolFactory "
+                 "transportFactory: (id <TAsyncTransportFactory>) aTransportFactory;" << endl;
+
+  scope_up(out);
+  out << indent() << "self = [super init];" << endl;
+  out << indent() << "if (self) {" << endl;
+  out << indent() << "  protocolFactory = aProtocolFactory;" << endl;
+  out << indent() << "  transportFactory = aTransportFactory;" << endl;
+  out << indent() << "}" << endl;
+  out << indent() << "return self;" << endl;
+  scope_down(out);
+  out << endl;
+
+  // generate client method implementations
+  vector<t_function*> functions = tservice->get_functions();
+  vector<t_function*>::const_iterator f_iter;
+  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
+
+    generate_cocoa_service_client_send_function_implementation(out, tservice, *f_iter, true);
+
+    if (!(*f_iter)->is_oneway()) {
+      generate_cocoa_service_client_recv_function_implementation(out, tservice, *f_iter, true);
+    }
+
+    // Open function
+    indent(out) << "- " << async_function_signature(*f_iter, false) << endl;
+    scope_up(out);
+
+    out << indent() << "NSError *thriftError;" << endl
+        << indent() << "id<TAsyncTransport> transport = [transportFactory newTransport];" << endl
+        << indent() << "id<TProtocol> protocol = [protocolFactory newProtocolOnTransport:transport];" << endl
+        << endl;
+
+    generate_cocoa_service_client_send_async_function_invocation(out, *f_iter, "failureBlock");
+
+    out << indent() << "[transport flushWithCompletion:^{" << endl;
+    indent_up();
+
+    if (!(*f_iter)->is_oneway()) {
+      out << indent() << "NSError *thriftError;" << endl;
+
+      if (!(*f_iter)->get_returntype()->is_void()) {
+        out << indent() << type_name((*f_iter)->get_returntype()) << " result;" << endl;
+      }
+      out << indent() << "if (![self recv_" << (*f_iter)->get_name();
+      if (!(*f_iter)->get_returntype()->is_void()) {
+        out << ": &result protocol";
+      }
+      out << ": protocol error: &thriftError]) ";
+      scope_up(out);
+      out << indent() << "failureBlock(thriftError);" << endl
+          << indent() << "return;" << endl;
+      scope_down(out);
+    }
+
+    out << indent() << "responseBlock(";
+    if (!(*f_iter)->is_oneway() && !(*f_iter)->get_returntype()->is_void()) {
+      out << "result";
+    }
+    out << ");" << endl;
+
+    indent_down();
+
+    out << indent() << "} failure:failureBlock];" << endl;
+
+    scope_down(out);
+
+    out << endl;
+
+    // Promise function
+    if (promise_kit_) {
+
+      indent(out) << "- " << promise_function_signature(*f_iter) << endl;
+      scope_up(out);
+
+      out << indent() << "return [AnyPromise promiseWithResolverBlock:^(PMKResolver resolver) {" << endl;
+      indent_up();
+
+      out << indent() << "NSError *thriftError;" << endl
+          << indent() << "id<TAsyncTransport> transport = [transportFactory newTransport];" << endl
+          << indent() << "id<TProtocol> protocol = [protocolFactory newProtocolOnTransport:transport];" << endl
+          << endl;
+
+      generate_cocoa_service_client_send_async_function_invocation(out, *f_iter, "resolver");
+
+      out << indent() << "[transport flushWithCompletion:^{" << endl;
+      indent_up();
+
+      if (!(*f_iter)->is_oneway()) {
+        out << indent() << "NSError *thriftError;" << endl;
+
+        if (!(*f_iter)->get_returntype()->is_void()) {
+          out << indent() << type_name((*f_iter)->get_returntype()) << " result;" << endl;
+        }
+        out << indent() << "if (![self recv_" << (*f_iter)->get_name();
+        if (!(*f_iter)->get_returntype()->is_void()) {
+          out << ": &result protocol";
+        }
+        out << ": protocol error: &thriftError]) ";
+        scope_up(out);
+        out << indent() << "resolver(thriftError);" << endl
+            << indent() << "return;" << endl;
+        scope_down(out);
+      }
+
+      out << indent() << "resolver(";
+      if ((*f_iter)->is_oneway() || (*f_iter)->get_returntype()->is_void()) {
+        out << "@YES";
+      } else if (type_can_be_null((*f_iter)->get_returntype())) {
+        out << "result";
+      } else {
+        out << "@(result)";
+      }
+      out << ");" << endl;
+
+      indent_down();
+
+      out << indent() << "} failure:^(NSError *error) {" << endl;
+      indent_up();
+      out << indent() << "resolver(error);" << endl;
+      indent_down();
+      out << indent() << "}];" << endl;
+
+      indent_down();
+      out << indent() << "}];" << endl;
+
+      scope_down(out);
+
+      out << endl;
+
+    }
+
+  }
+
+  out << "@end" << endl << endl;
+}
+
+/**
+ * Generates a service server implementation.  In other words the actual TProcessor implementation
+ * for the service.
+ *
+ * @param tservice The service to generate an implementation for
+ */
+void t_cocoa_generator::generate_cocoa_service_server_implementation(ostream& out,
+                                                                     t_service* tservice) {
+
+  string name = cocoa_prefix_ + tservice->get_name() + "Processor";
+
+  out << "@interface " << name << " () ";
+
+  scope_up(out);
+  out << indent() << "id <" << cocoa_prefix_ << tservice->get_name() << "> service;" << endl;
+  out << indent() << "NSDictionary * methodMap;" << endl;
+  scope_down(out);
+
+  out << "@end" << endl << endl;
+
+  out << "@implementation " << name << endl;
+
+  // initializer
+  out << endl;
+  out << "- (id) initWith" << tservice->get_name() << ": (id <" << cocoa_prefix_ << tservice->get_name() << ">) aService" << endl;
+  scope_up(out);
+  out << indent() << "self = [super init];" << endl;
+  out << indent() << "if (self) ";
+  scope_up(out);
+  out << indent() << "service = aService;" << endl;
+  out << indent() << "methodMap = [NSMutableDictionary dictionary];" << endl;
+
+  // generate method map for routing incoming calls
+  vector<t_function*> functions = tservice->get_functions();
+  vector<t_function*>::const_iterator f_iter;
+  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
+    string funname = (*f_iter)->get_name();
+    scope_up(out);
+    out << indent() << "SEL s = @selector(process_" << funname << "_withSequenceID:inProtocol:outProtocol:error:);" << endl;
+    out << indent() << "NSMethodSignature * sig = [self methodSignatureForSelector: s];" << endl;
+    out << indent() << "NSInvocation * invocation = [NSInvocation invocationWithMethodSignature: sig];" << endl;
+    out << indent() << "[invocation setSelector: s];" << endl;
+    out << indent() << "[invocation retainArguments];" << endl;
+    out << indent() << "[methodMap setValue: invocation forKey: @\"" << funname << "\"];" << endl;
+    scope_down(out);
+  }
+  scope_down(out);
+  out << indent() << "return self;" << endl;
+  scope_down(out);
+
+  // implementation of the 'service' method which returns the service associated with this
+  // processor
+  out << endl;
+  out << indent() << "- (id<" << cocoa_prefix_ << tservice->get_name() << ">) service" << endl;
+  out << indent() << "{" << endl;
+  out << indent() << "  return service;" << endl;
+  out << indent() << "}" << endl;
+
+  // implementation of the TProcess method, which dispatches the incoming call using the method map
+  out << endl;
+  out << indent() << "- (BOOL) processOnInputProtocol: (id <TProtocol>) inProtocol" << endl;
+  out << indent() << "                 outputProtocol: (id <TProtocol>) outProtocol" << endl;
+  out << indent() << "                          error: (NSError *__autoreleasing *)__thriftError" << endl;
+  out << indent() << "{" << endl;
+  out << indent() << "  NSString * messageName;" << endl;
+  out << indent() << "  SInt32 messageType;" << endl;
+  out << indent() << "  SInt32 seqID;" << endl;
+  out << indent() << "  if (![inProtocol readMessageBeginReturningName: &messageName" << endl;
+  out << indent() << "                                       type: &messageType" << endl;
+  out << indent() << "                                 sequenceID: &seqID" << endl;
+  out << indent() << "                                      error: __thriftError]) return NO;" << endl;
+  out << indent() << "  NSInvocation * invocation = [methodMap valueForKey: messageName];" << endl;
+  out << indent() << "  if (invocation == nil) {" << endl;
+  out << indent() << "    if (![TProtocolUtil skipType: TTypeSTRUCT onProtocol: inProtocol error: __thriftError]) return NO;" << endl;
+  out << indent() << "    if (![inProtocol readMessageEnd: __thriftError]) return NO;" << endl;
+  out << indent() << "    NSError * x = [NSError errorWithDomain: TApplicationErrorDomain" << endl;
+  out << indent() << "                                      code: TApplicationErrorUnknownMethod" << endl;
+  out << indent() << "                                  userInfo: @{TApplicationErrorMethodKey: messageName}];" << endl;
+  out << indent() << "    if (![outProtocol writeMessageBeginWithName: messageName" << endl;
+  out << indent() << "                                           type: TMessageTypeEXCEPTION" << endl;
+  out << indent() << "                                     sequenceID: seqID" << endl;
+  out << indent() << "                                          error: __thriftError]) return NO;" << endl;
+  out << indent() << "    if (![x write: outProtocol error: __thriftError]) return NO;" << endl;
+  out << indent() << "    if (![outProtocol writeMessageEnd: __thriftError]) return NO;" << endl;
+  out << indent() << "    if (![[outProtocol transport] flush: __thriftError]) return NO;" << endl;
+  out << indent() << "    return YES;" << endl;
+  out << indent() << "  }" << endl;
+  out << indent() << "  // NSInvocation does not conform to NSCopying protocol" << endl;
+  out << indent() << "  NSInvocation * i = [NSInvocation invocationWithMethodSignature: "
+                     "[invocation methodSignature]];" << endl;
+  out << indent() << "  [i setSelector: [invocation selector]];" << endl;
+  out << indent() << "  [i setArgument: &seqID atIndex: 2];" << endl;
+  out << indent() << "  [i setArgument: &inProtocol atIndex: 3];" << endl;
+  out << indent() << "  [i setArgument: &outProtocol atIndex: 4];" << endl;
+  out << indent() << "  [i setArgument: &__thriftError atIndex: 5];" << endl;
+  out << indent() << "  [i setTarget: self];" << endl;
+  out << indent() << "  [i invoke];" << endl;
+  out << indent() << "  return YES;" << endl;
+  out << indent() << "}" << endl;
+
+  // generate a process_XXXX method for each service function, which reads args, calls the service,
+  // and writes results
+  functions = tservice->get_functions();
+  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
+    out << endl;
+    string funname = (*f_iter)->get_name();
+    out << indent() << "- (BOOL) process_" << funname
+        << "_withSequenceID: (SInt32) seqID inProtocol: (id<TProtocol>) inProtocol outProtocol: "
+           "(id<TProtocol>) outProtocol error:(NSError *__autoreleasing *)__thriftError" << endl;
+    scope_up(out);
+    string argstype = cocoa_prefix_ + function_args_helper_struct_type(tservice, *f_iter);
+    out << indent() << argstype << " * args = [" << argstype << " new];" << endl;
+    out << indent() << "if (![args read: inProtocol error: __thriftError]) return NO;" << endl;
+    out << indent() << "if (![inProtocol readMessageEnd: __thriftError]) return NO;" << endl;
+
+    // prepare the result if not oneway
+    if (!(*f_iter)->is_oneway()) {
+      string resulttype = cocoa_prefix_ + function_result_helper_struct_type(tservice, *f_iter);
+      out << indent() << resulttype << " * result = [" << resulttype << " new];" << endl;
+    }
+
+    // make the call to the actual service object
+    out << indent();
+    if ((*f_iter)->get_returntype()->is_void()) {
+      out << "BOOL";
+    } else if (type_can_be_null((*f_iter)->get_returntype())) {
+      out << type_name((*f_iter)->get_returntype(), false, true);
+    } else {
+      out << "NSNumber *";
+    }
+    out << " serviceResult = ";
+    if ((*f_iter)->get_returntype()->get_true_type()->is_container()) {
+      out << "(" << type_name((*f_iter)->get_returntype(), false, true) << ")";
+    }
+    out << "[service " << funname;
+    // supplying arguments
+    t_struct* arg_struct = (*f_iter)->get_arglist();
+    const vector<t_field*>& fields = arg_struct->get_members();
+    vector<t_field*>::const_iterator fld_iter;
+    bool first = true;
+    for (fld_iter = fields.begin(); fld_iter != fields.end(); ++fld_iter) {
+      string fieldName = (*fld_iter)->get_name();
+      if (first) {
+        first = false;
+        out << ": [args " << fieldName << "]";
+      } else {
+        out << " " << fieldName << ": [args " << fieldName << "]";
+      }
+    }
+    if (!fields.empty()) {
+      out << " error";
+    }
+    out << ": __thriftError];" << endl;
+    out << indent() << "if (!serviceResult) return NO;" << endl;
+    if (!(*f_iter)->get_returntype()->is_void()) {
+      out << indent() << "[result setSuccess: " << unbox((*f_iter)->get_returntype(), "serviceResult") << "];" << endl;
+    }
+
+    // write out the result if not oneway
+    if (!(*f_iter)->is_oneway()) {
+      out << indent() << "if (![outProtocol writeMessageBeginWithName: @\"" << funname << "\"" << endl;
+      out << indent() << "                                       type: TMessageTypeREPLY" << endl;
+      out << indent() << "                                 sequenceID: seqID" << endl;
+      out << indent() << "                                      error: __thriftError]) return NO;" << endl;
+      out << indent() << "if (![result write: outProtocol error: __thriftError]) return NO;" << endl;
+      out << indent() << "if (![outProtocol writeMessageEnd: __thriftError]) return NO;" << endl;
+      out << indent() << "if (![[outProtocol transport] flush: __thriftError]) return NO;" << endl;
+    }
+    out << indent() << "return YES;" << endl;
+
+    scope_down(out);
+  }
+
+  out << "@end" << endl << endl;
+}
+
+/**
+ * Deserializes a field of any type.
+ *
+ * @param tfield The field
+ * @param fieldName The variable name for this field
+ */
+void t_cocoa_generator::generate_deserialize_field(ostream& out,
+                                                   t_field* tfield,
+                                                   string fieldName) {
+  t_type* type = get_true_type(tfield->get_type());
+
+  if (type->is_void()) {
+    throw "CANNOT GENERATE DESERIALIZE CODE FOR void TYPE: " + tfield->get_name();
+  }
+
+  if (type->is_struct() || type->is_xception()) {
+    generate_deserialize_struct(out, (t_struct*)type, fieldName);
+  } else if (type->is_container()) {
+    generate_deserialize_container(out, type, fieldName);
+  } else if (type->is_base_type() || type->is_enum()) {
+    indent(out) << type_name(type) << " " << fieldName << ";" << endl;
+    indent(out) << "if (![inProtocol ";
+
+    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:
+        throw "compiler error: cannot serialize void field in a struct: " + tfield->get_name();
+        break;
+      case t_base_type::TYPE_STRING:
+        if (type->is_binary()) {
+          out << "readBinary:&" << fieldName << " error: __thriftError]";
+        } else {
+          out << "readString:&" << fieldName << " error: __thriftError]";
+        }
+        break;
+      case t_base_type::TYPE_BOOL:
+        out << "readBool:&" << fieldName << " error: __thriftError]";
+        break;
+      case t_base_type::TYPE_I8:
+        out << "readByte:(UInt8 *)&" << fieldName << " error: __thriftError]";
+        break;
+      case t_base_type::TYPE_I16:
+        out << "readI16:&" << fieldName << " error: __thriftError]";
+        break;
+      case t_base_type::TYPE_I32:
+        out << "readI32:&" << fieldName << " error: __thriftError]";
+        break;
+      case t_base_type::TYPE_I64:
+        out << "readI64:&" << fieldName << " error: __thriftError]";
+        break;
+      case t_base_type::TYPE_DOUBLE:
+        out << "readDouble:&" << fieldName << " error: __thriftError]";
+        break;
+      default:
+        throw "compiler error: no Objective-C name for base type "
+            + t_base_type::t_base_name(tbase);
+      }
+    } else if (type->is_enum()) {
+      out << "readI32:&" << fieldName << " error: __thriftError]";
+    }
+    out << ") return NO;" << endl;
+  } else {
+    printf("DO NOT KNOW HOW TO DESERIALIZE FIELD '%s' TYPE '%s'\n",
+           tfield->get_name().c_str(),
+           type_name(type).c_str());
+  }
+}
+
+/**
+ * Generates an unserializer for a struct, allocates the struct and invokes read:
+ */
+void t_cocoa_generator::generate_deserialize_struct(ostream& out,
+                                                    t_struct* tstruct,
+                                                    string fieldName) {
+  indent(out) << type_name(tstruct) << fieldName << " = [[" << type_name(tstruct, true)
+              << " alloc] init];" << endl;
+  indent(out) << "if (![" << fieldName << " read: inProtocol error: __thriftError]) return NO;" << endl;
+}
+
+/**
+ * Deserializes a container by reading its size and then iterating
+ */
+void t_cocoa_generator::generate_deserialize_container(ostream& out,
+                                                       t_type* ttype,
+                                                       string fieldName) {
+  string size = tmp("_size");
+  indent(out) << "SInt32 " << size << ";" << endl;
+
+  // Declare variables, read header
+  if (ttype->is_map()) {
+    indent(out) << "if (![inProtocol readMapBeginReturningKeyType: NULL valueType: NULL size: &" << size << " error: __thriftError]) return NO;" << endl;
+    indent(out) << "NSMutableDictionary * " << fieldName
+                << " = [[NSMutableDictionary alloc] initWithCapacity: " << size << "];" << endl;
+  } else if (ttype->is_set()) {
+    indent(out) << "if (![inProtocol readSetBeginReturningElementType: NULL size: &" << size << " error: __thriftError]) return NO;"
+                << endl;
+    indent(out) << "NSMutableSet * " << fieldName
+                << " = [[NSMutableSet alloc] initWithCapacity: " << size << "];" << endl;
+  } else if (ttype->is_list()) {
+    indent(out) << "if (![inProtocol readListBeginReturningElementType: NULL size: &" << size << " error: __thriftError]) return NO;"
+                << endl;
+    indent(out) << "NSMutableArray * " << fieldName
+                << " = [[NSMutableArray alloc] initWithCapacity: " << size << "];" << endl;
+  }
+  // FIXME - the code above does not verify that the element types of
+  // the containers being read match the element types of the
+  // containers we are reading into.  Does that matter?
+
+  // For loop iterates over elements
+  string i = tmp("_i");
+  indent(out) << "int " << i << ";" << endl << indent() << "for (" << i << " = 0; " << i << " < "
+              << size << "; "
+              << "++" << i << ")" << endl;
+
+  scope_up(out);
+
+  if (ttype->is_map()) {
+    generate_deserialize_map_element(out, (t_map*)ttype, fieldName);
+  } else if (ttype->is_set()) {
+    generate_deserialize_set_element(out, (t_set*)ttype, fieldName);
+  } else if (ttype->is_list()) {
+    generate_deserialize_list_element(out, (t_list*)ttype, fieldName);
+  }
+
+  scope_down(out);
+
+  // Read container end
+  if (ttype->is_map()) {
+    indent(out) << "if (![inProtocol readMapEnd: __thriftError]) return NO;" << endl;
+  } else if (ttype->is_set()) {
+    indent(out) << "if (![inProtocol readSetEnd: __thriftError]) return NO;" << endl;
+  } else if (ttype->is_list()) {
+    indent(out) << "if (![inProtocol readListEnd: __thriftError]) return NO;" << endl;
+  }
+}
+
+/**
+ * Take a variable of a given type and wrap it in code to make it
+ * suitable for putting into a container, if necessary.  Basically,
+ * wrap scaler primitives in NSNumber objects.
+ */
+string t_cocoa_generator::box(t_type* ttype, string field_name) {
+
+  ttype = get_true_type(ttype);
+  if (ttype->is_enum()) {
+    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 box void";
+      case t_base_type::TYPE_BOOL:
+      case t_base_type::TYPE_I8:
+      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 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_I8:
+        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;
+}
+
+/**
+ * Generates code to deserialize a map element
+ */
+void t_cocoa_generator::generate_deserialize_map_element(ostream& out,
+                                                         t_map* tmap,
+                                                         string fieldName) {
+  string key = tmp("_key");
+  string val = tmp("_val");
+  t_type* keyType = tmap->get_key_type();
+  t_type* valType = tmap->get_val_type();
+  t_field fkey(keyType, key);
+  t_field fval(valType, val);
+
+  generate_deserialize_field(out, &fkey, key);
+  generate_deserialize_field(out, &fval, val);
+
+  indent(out) << "[" << fieldName << " setObject: " << box(valType, val)
+              << " forKey: " << box(keyType, key) << "];" << endl;
+}
+
+/**
+ * Deserializes a set element
+ */
+void t_cocoa_generator::generate_deserialize_set_element(ostream& out,
+                                                         t_set* tset,
+                                                         string fieldName) {
+  string elem = tmp("_elem");
+  t_type* type = tset->get_elem_type();
+  t_field felem(type, elem);
+
+  generate_deserialize_field(out, &felem, elem);
+
+  indent(out) << "[" << fieldName << " addObject: " << box(type, elem) << "];" << endl;
+}
+
+/**
+ * Deserializes a list element
+ */
+void t_cocoa_generator::generate_deserialize_list_element(ostream& out,
+                                                          t_list* tlist,
+                                                          string fieldName) {
+  string elem = tmp("_elem");
+  t_type* type = tlist->get_elem_type();
+  t_field felem(type, elem);
+
+  generate_deserialize_field(out, &felem, elem);
+
+  indent(out) << "[" << fieldName << " addObject: " << box(type, elem) << "];" << endl;
+}
+
+/**
+ * Serializes a field of any type.
+ *
+ * @param tfield The field to serialize
+ * @param fieldName Name to of the variable holding the field
+ */
+void t_cocoa_generator::generate_serialize_field(ostream& out, t_field* tfield, string fieldName) {
+  t_type* type = get_true_type(tfield->get_type());
+
+  // Do nothing for void types
+  if (type->is_void()) {
+    throw "CANNOT GENERATE SERIALIZE CODE FOR void TYPE: " + tfield->get_name();
+  }
+
+  if (type->is_struct() || type->is_xception()) {
+    generate_serialize_struct(out, (t_struct*)type, fieldName);
+  } else if (type->is_container()) {
+    generate_serialize_container(out, type, fieldName);
+  } else if (type->is_base_type() || type->is_enum()) {
+    indent(out) << "if (![outProtocol ";
+
+    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:
+        throw "compiler error: cannot serialize void field in a struct: " + fieldName;
+        break;
+      case t_base_type::TYPE_STRING:
+        if (type->is_binary()) {
+          out << "writeBinary: " << fieldName << " error: __thriftError]";
+        } else {
+          out << "writeString: " << fieldName << " error: __thriftError]";
+        }
+        break;
+      case t_base_type::TYPE_BOOL:
+        out << "writeBool: " << fieldName << " error: __thriftError]";
+        break;
+      case t_base_type::TYPE_I8:
+        out << "writeByte: (UInt8)" << fieldName << " error: __thriftError]";
+        break;
+      case t_base_type::TYPE_I16:
+        out << "writeI16: " << fieldName << " error: __thriftError]";
+        break;
+      case t_base_type::TYPE_I32:
+        out << "writeI32: " << fieldName << " error: __thriftError]";
+        break;
+      case t_base_type::TYPE_I64:
+        out << "writeI64: " << fieldName << " error: __thriftError]";
+        break;
+      case t_base_type::TYPE_DOUBLE:
+        out << "writeDouble: " << fieldName << " error: __thriftError]";
+        break;
+      default:
+        throw "compiler error: no Objective-C name for base type "
+            + t_base_type::t_base_name(tbase);
+      }
+    } else if (type->is_enum()) {
+      out << "writeI32: " << fieldName << " error: __thriftError]";
+    }
+    out << ") return NO;" << endl;
+  } else {
+    printf("DO NOT KNOW HOW TO SERIALIZE FIELD '%s' TYPE '%s'\n",
+           tfield->get_name().c_str(),
+           type_name(type).c_str());
+  }
+}
+
+/**
+ * Serialize a struct.
+ *
+ * @param tstruct The struct to serialize
+ * @param fieldName Name of variable holding struct
+ */
+void t_cocoa_generator::generate_serialize_struct(ostream& out,
+                                                  t_struct* tstruct,
+                                                  string fieldName) {
+  (void)tstruct;
+  out << indent() << "if (![" << fieldName << " write: outProtocol error: __thriftError]) return NO;" << endl;
+}
+
+/**
+ * Serializes a container by writing its size then the elements.
+ *
+ * @param ttype  The type of container
+ * @param fieldName Name of variable holding container
+ */
+void t_cocoa_generator::generate_serialize_container(ostream& out,
+                                                     t_type* ttype,
+                                                     string fieldName) {
+  scope_up(out);
+
+  if (ttype->is_map()) {
+    indent(out) << "if (![outProtocol writeMapBeginWithKeyType: "
+                << type_to_enum(((t_map*)ttype)->get_key_type())
+                << " valueType: " << type_to_enum(((t_map*)ttype)->get_val_type()) << " size: (SInt32)["
+                << fieldName << " count] error: __thriftError]) return NO;" << endl;
+  } else if (ttype->is_set()) {
+    indent(out) << "if (![outProtocol writeSetBeginWithElementType: "
+                << type_to_enum(((t_set*)ttype)->get_elem_type()) << " size: (SInt32)[" << fieldName
+                << " count] error: __thriftError]) return NO;" << endl;
+  } else if (ttype->is_list()) {
+    indent(out) << "if (![outProtocol writeListBeginWithElementType: "
+                << type_to_enum(((t_list*)ttype)->get_elem_type()) << " size: (SInt32)[" << fieldName
+                << " count] error: __thriftError]) return NO;" << endl;
+  }
+
+  string iter = tmp("_iter");
+  string key;
+  if (ttype->is_map()) {
+    key = tmp("key");
+    indent(out) << "NSEnumerator * " << iter << " = [" << fieldName << " keyEnumerator];" << endl;
+    indent(out) << "id " << key << ";" << endl;
+    indent(out) << "while ((" << key << " = [" << iter << " nextObject]))" << endl;
+  } else if (ttype->is_set()) {
+    key = tmp("obj");
+    indent(out) << "NSEnumerator * " << iter << " = [" << fieldName << " objectEnumerator];"
+                << endl;
+    indent(out) << "id " << key << ";" << endl;
+    indent(out) << "while ((" << key << " = [" << iter << " nextObject]))" << endl;
+  } else if (ttype->is_list()) {
+    key = tmp("idx");
+    indent(out) << "int " << key << ";" << endl;
+    indent(out) << "for (" << key << " = 0; " << key << " < [" << fieldName << " count]; " << key
+                << "++)" << endl;
+  }
+
+  scope_up(out);
+
+  if (ttype->is_map()) {
+    generate_serialize_map_element(out, (t_map*)ttype, key, fieldName);
+  } else if (ttype->is_set()) {
+    generate_serialize_set_element(out, (t_set*)ttype, key);
+  } else if (ttype->is_list()) {
+    generate_serialize_list_element(out, (t_list*)ttype, key, fieldName);
+  }
+
+  scope_down(out);
+
+  if (ttype->is_map()) {
+    indent(out) << "if (![outProtocol writeMapEnd: __thriftError]) return NO;" << endl;
+  } else if (ttype->is_set()) {
+    indent(out) << "if (![outProtocol writeSetEnd: __thriftError]) return NO;" << endl;
+  } else if (ttype->is_list()) {
+    indent(out) << "if (![outProtocol writeListEnd: __thriftError]) return NO;" << endl;
+  }
+
+  scope_down(out);
+}
+
+/**
+ * Serializes the members of a map.
+ */
+void t_cocoa_generator::generate_serialize_map_element(ostream& out,
+                                                       t_map* tmap,
+                                                       string key,
+                                                       string mapName) {
+  t_field kfield(tmap->get_key_type(), 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, unbox(vfield.get_type(), vfield.get_name()));
+}
+
+/**
+ * Serializes the members of a set.
+ */
+void t_cocoa_generator::generate_serialize_set_element(ostream& out,
+                                                       t_set* tset,
+                                                       string elementName) {
+  t_field efield(tset->get_elem_type(), elementName);
+  generate_serialize_field(out, &efield, unbox(efield.get_type(), elementName));
+}
+
+/**
+ * Serializes the members of a list.
+ */
+void t_cocoa_generator::generate_serialize_list_element(ostream& out,
+                                                        t_list* tlist,
+                                                        string index,
+                                                        string listName) {
+  t_field efield(tlist->get_elem_type(), "[" + listName + " objectAtIndex: " + index + "]");
+  generate_serialize_field(out, &efield, unbox(efield.get_type(), efield.get_name()));
+}
+
+/**
+ * Returns an Objective-C name
+ *
+ * @param ttype The type
+ * @param class_ref Do we want a Class reference istead of a type reference?
+ * @return Objective-C type name, i.e. NSDictionary<Key,Value> *
+ */
+string t_cocoa_generator::type_name(t_type* ttype, bool class_ref, bool needs_mutable) {
+  if (ttype->is_typedef()) {
+    string name = (needs_mutable && ttype->get_true_type()->is_container()) ? "Mutable" + ttype->get_name() : ttype->get_name();
+    t_program* program = ttype->get_program();
+    return program ? (program->get_namespace("cocoa") + name) : name;
+  }
+
+  string result;
+  if (ttype->is_base_type()) {
+    return base_type_name((t_base_type*)ttype);
+  } else if (ttype->is_enum()) {
+    return cocoa_prefix_ + ttype->get_name();
+  } else if (ttype->is_map()) {
+    t_map *map = (t_map *)ttype;
+    result = needs_mutable ? "NSMutableDictionary" : "NSDictionary";
+    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 += "<" + element_type_name(set->get_elem_type()) + ">";
+  } else if (ttype->is_list()) {
+    t_list *list = (t_list *)ttype;
+    result = needs_mutable ? "NSMutableArray" : "NSArray";
+    result += "<" + element_type_name(list->get_elem_type()) + ">";
+  } else {
+    // Check for prefix
+    t_program* program = ttype->get_program();
+    if (program != NULL) {
+      result = program->get_namespace("cocoa") + ttype->get_name();
+    } else {
+      result = ttype->get_name();
+    }
+  }
+
+  if (!class_ref) {
+    result += " *";
+  }
+  return result;
+}
+
+/**
+ * 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_enum()) {
+      result = "NSNumber *";
+  } 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
+ */
+string t_cocoa_generator::base_type_name(t_base_type* type) {
+  t_base_type::t_base tbase = type->get_base();
+
+  switch (tbase) {
+  case t_base_type::TYPE_VOID:
+    return "void";
+  case t_base_type::TYPE_STRING:
+    if (type->is_binary()) {
+      return "NSData *";
+    } else {
+      return "NSString *";
+    }
+  case t_base_type::TYPE_BOOL:
+    return "BOOL";
+  case t_base_type::TYPE_I8:
+    return "SInt8";
+  case t_base_type::TYPE_I16:
+    return "SInt16";
+  case t_base_type::TYPE_I32:
+    return "SInt32";
+  case t_base_type::TYPE_I64:
+    return "SInt64";
+  case t_base_type::TYPE_DOUBLE:
+    return "double";
+  default:
+    throw "compiler error: no Objective-C name for base type " + t_base_type::t_base_name(tbase);
+  }
+}
+
+/**
+ * Prints the value of a constant with the given type. Note that type checking
+ * 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(ostream& out,
+                                          string name,
+                                          t_type* type,
+                                          t_const_value* value,
+                                          bool defval) {
+  type = get_true_type(type);
+
+  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*, t_const_value::value_compare>& val = value->get_map();
+    map<t_const_value*, t_const_value*, t_const_value::value_compare>::const_iterator v_iter;
+    if (defval)
+      out << type_name(type) << " ";
+    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) {
+        if ((*f_iter)->get_name() == v_iter->first->get_string()) {
+          field_type = (*f_iter)->get_type();
+        }
+      }
+      if (field_type == NULL) {
+        throw "type error: " + type->get_name() + " has no field " + v_iter->first->get_string();
+      }
+      string val = render_const_value(out, field_type, v_iter->second);
+      std::string cap_name = capitalize(v_iter->first->get_string());
+      indent(out) << "[" << name << " set" << cap_name << ":" << val << "];" << 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*, t_const_value::value_compare>& val = value->get_map();
+    map<t_const_value*, t_const_value*, t_const_value::value_compare>::const_iterator v_iter;
+    if (defval)
+      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 << ", ";
+      }
+    }
+    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)
+      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 << ", ";
+      }
+    }
+    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)
+      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 << ", ";
+      }
+    }
+    setout << "]]";
+    out << setout.str();
+  } else {
+    throw "compiler error: no const of type " + type->get_name();
+  }
+}
+
+string t_cocoa_generator::render_const_value(ostream& out,
+                                             t_type* type,
+                                             t_const_value* value,
+                                             bool box_it) {
+  type = get_true_type(type);
+  std::ostringstream render;
+
+  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:
+      // We must handle binary constant but the syntax of IDL defines
+      // nothing about binary constant.
+      //   if type->is_binary())
+      //      // binary code
+      render << "@\"" << get_escaped_string(value) << '"';
+      break;
+    case t_base_type::TYPE_BOOL:
+      render << ((value->get_integer() > 0) ? "YES" : "NO");
+      break;
+    case t_base_type::TYPE_I8:
+    case t_base_type::TYPE_I16:
+    case t_base_type::TYPE_I32:
+    case t_base_type::TYPE_I64:
+      render << value->get_integer();
+      break;
+    case t_base_type::TYPE_DOUBLE:
+      if (value->get_type() == t_const_value::CV_INTEGER) {
+        render << value->get_integer();
+      } else {
+        render << value->get_double();
+      }
+      break;
+    default:
+      throw "compiler error: no const of base type " + t_base_type::t_base_name(tbase);
+    }
+  } else if (type->is_enum()) {
+    render << value->get_integer();
+  } else {
+    string t = tmp("tmp");
+    print_const_value(out, t, type, value, true);
+    out << ";" << endl;
+    render << t;
+  }
+
+  if (box_it) {
+    return box(type, render.str());
+  }
+  return render.str();
+}
+
+#if 0
+/**
+ORIGINAL
+ * Spit out code that evaluates to the specified constant value.
+ */
+string t_cocoa_generator::render_const_value(string name,
+                                             t_type* type,
+                                             t_const_value* value,
+                                             bool box_it) {
+  type = get_true_type(type);
+  std::ostringstream render;
+
+  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:
+      render << "@\"" << get_escaped_string(value) << '"';
+      break;
+    case t_base_type::TYPE_BOOL:
+      render << ((value->get_integer() > 0) ? "YES" : "NO");
+      break;
+    case t_base_type::TYPE_I8:
+    case t_base_type::TYPE_I16:
+    case t_base_type::TYPE_I32:
+    case t_base_type::TYPE_I64:
+      render << value->get_integer();
+      break;
+    case t_base_type::TYPE_DOUBLE:
+      if (value->get_type() == t_const_value::CV_INTEGER) {
+        render << value->get_integer();
+      } else {
+        render << value->get_double();
+      }
+      break;
+    default:
+      throw "compiler error: no const of base type " + t_base_type::t_base_name(tbase);
+    }
+  } else if (type->is_enum()) {
+    render << value->get_integer();
+  } 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*, t_const_value::value_compare>& val = value->get_map();
+    map<t_const_value*, t_const_value*, t_const_value::value_compare>::const_iterator v_iter;
+    if (val.size() > 0)
+      render << "[[" << type_name(type, true) << " alloc] initWith";
+    else
+      render << "[[" << type_name(type, true) << " alloc] init";
+    bool first = true;
+    for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
+      // FIXME The generated code does not match with initWithXXX
+      //       initializer and causes compile error.
+      //       Try: test/DebugProtoTest.thrift and test/SmallTest.thrift
+      t_type* field_type = NULL;
+      for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+        if ((*f_iter)->get_name() == v_iter->first->get_string()) {
+          field_type = (*f_iter)->get_type();
+        }
+      }
+      if (field_type == NULL) {
+        throw "type error: " + type->get_name() + " has no field " + v_iter->first->get_string();
+      }
+      if (first) {
+        render << capitalize(v_iter->first->get_string());
+        first = false;
+      } else {
+        render << " " << v_iter->first->get_string();
+      }
+      render << ": " << render_const_value(name, field_type, v_iter->second);
+    }
+    render << "]";
+  } else if (type->is_map()) {
+    render << "[[NSDictionary alloc] initWithObjectsAndKeys: ";
+    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*, t_const_value::value_compare>& val = value->get_map();
+    map<t_const_value*, t_const_value*, t_const_value::value_compare>::const_iterator v_iter;
+    bool first = true;
+    for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
+      string key = render_const_value(name, ktype, v_iter->first, true);
+      string val = render_const_value(name, vtype, v_iter->second, true);
+      if (first) {
+        first = false;
+      } else {
+        render << ", ";
+      }
+      render << val << ", " << key;
+    }
+    if (first)
+      render << " nil]";
+    else
+      render << ", nil]";
+  } else if (type->is_list()) {
+    render << "[[NSArray alloc] initWithObjects: ";
+    t_type * etype = ((t_list*)type)->get_elem_type();
+    const vector<t_const_value*>& val = value->get_list();
+    bool first = true;
+    vector<t_const_value*>::const_iterator v_iter;
+    for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
+      if (first) {
+        first = false;
+      } else {
+        render << ", ";
+      }
+      render << render_const_value(name, etype, *v_iter, true);
+    }
+    if (first)
+      render << " nil]";
+    else
+      render << ", nil]";
+  } else if (type->is_set()) {
+    render << "[[NSSet alloc] initWithObjects: ";
+    t_type * etype = ((t_set*)type)->get_elem_type();
+    const vector<t_const_value*>& val = value->get_list();
+    bool first = true;
+    vector<t_const_value*>::const_iterator v_iter;
+    for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
+      if (first) {
+        first = false;
+      } else {
+        render << ", ";
+      }
+      render << render_const_value(name, etype, *v_iter, true);
+    }
+    if (first)
+      render << " nil]";
+    else
+      render << ", nil]";
+  } else {
+    throw "don't know how to render constant for type: " + type->get_name();
+  }
+
+  if (box_it) {
+    return box(type, render.str());
+  }
+
+  return render.str();
+}
+#endif
+
+/**
+ * Declares an Objective-C 2.0 property.
+ *
+ * @param tfield The field to declare a property for
+ */
+string t_cocoa_generator::declare_property(t_field* tfield) {
+  std::ostringstream render;
+  render << "@property (";
+
+  if (type_can_be_copy(tfield->get_type())) {
+    render << "copy, ";
+  } else if (type_can_be_null(tfield->get_type())) {
+    render << "strong, ";
+  } else {
+    render << "assign, ";
+  }
+
+  render << "nonatomic) " << type_name(tfield->get_type(), false, true) << " "
+  << tfield->get_name() << ";";
+
+  // Check if the property name is an Objective-C return +1 count signal
+  if ((tfield->get_name().length() >= 3 && tfield->get_name().substr(0,3) == "new") ||
+      (tfield->get_name().length() >= 6 && tfield->get_name().substr(0,6) == "create") ||
+      (tfield->get_name().length() >= 5 && tfield->get_name().substr(0,5) == "alloc")) {
+    // Let Objective-C know not to return +1 for object pointers
+    if (type_can_be_null(tfield->get_type())) {
+      render << endl;
+      render << "- (" + type_name(tfield->get_type()) + ") " + decapitalize(tfield->get_name()) + " __attribute__((objc_method_family(none)));";
+    }
+  }
+
+  return render.str();
+}
+
+/**
+ * Declares an Objective-C 2.0 property.
+ *
+ * @param tfield The field to declare a property for
+ */
+string t_cocoa_generator::declare_property_isset(t_field* tfield) {
+  return "@property (assign, nonatomic) BOOL " + decapitalize(tfield->get_name()) + "IsSet;";
+}
+
+/**
+ * Declares property unset method.
+ *
+ * @param tfield The field to declare a property for
+ */
+string t_cocoa_generator::declare_property_unset(t_field* tfield) {
+  return "- (void) unset" + capitalize(tfield->get_name()) + ";";
+}
+
+/**
+ * Renders the early out return statement
+ *
+ * @param tfunction Function definition
+ * @return String of rendered invalid return statment
+ */
+string t_cocoa_generator::invalid_return_statement(t_function *tfunction) {
+  if ((tfunction->get_returntype()->is_void())) {
+    return "return NO;";
+  }
+  return "return nil;";
+}
+
+/**
+ * Renders a function signature
+ *
+ * @param tfunction Function definition
+ * @return String of rendered function definition
+ */
+string t_cocoa_generator::function_signature(t_function* tfunction, bool include_error) {
+  t_type* ttype = tfunction->get_returntype();
+  string result;
+  if (ttype->is_void()) {
+    result = "(BOOL)";
+  }
+  else if (type_can_be_null(ttype)) {
+    result = "(" + type_name(ttype) + ")";
+  }
+  else {
+    result = "(NSNumber *)";
+  }
+  result += " " + tfunction->get_name() + argument_list(tfunction->get_arglist(), "", include_error);
+  return result;
+}
+
+/**
+ * Renders a function signature that returns asynchronously instead of
+ * literally returning.
+ *
+ * @param tfunction Function definition
+ * @return String of rendered function definition
+ */
+string t_cocoa_generator::async_function_signature(t_function* tfunction, bool include_error) {
+  t_type* ttype = tfunction->get_returntype();
+  t_struct* targlist = tfunction->get_arglist();
+  string response_param = "void (^)(" + ((ttype->is_void()) ? "" : type_name(ttype)) + ")";
+  std::string result = "(void) " + tfunction->get_name() + argument_list(tfunction->get_arglist(), "", include_error)
+  + (targlist->get_members().size() ? " response" : "") + ": ("
+  + response_param + ") responseBlock "
+  + "failure : (TAsyncFailureBlock) failureBlock";
+  return result;
+}
+
+/**
+ * Renders a function signature that returns a promise instead of
+ * literally returning.
+ *
+ * @param tfunction Function definition
+ * @return String of rendered function definition
+ */
+string t_cocoa_generator::promise_function_signature(t_function* tfunction) {
+  return "(AnyPromise *) " + tfunction->get_name() + argument_list(tfunction->get_arglist(), "", false);
+}
+
+/**
+ * Renders a colon separated list of types and names, suitable for an
+ * objective-c parameter list
+ */
+string t_cocoa_generator::argument_list(t_struct* tstruct, string protocol_name, bool include_error) {
+  string result = "";
+  bool include_protocol = !protocol_name.empty();
+
+  const vector<t_field*>& fields = tstruct->get_members();
+  vector<t_field*>::const_iterator f_iter;
+  bool first = true;
+  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+    string argPrefix = "";
+    if (first) {
+      first = false;
+    } else {
+      argPrefix = (*f_iter)->get_name();
+      result += " ";
+    }
+    result += argPrefix + ": (" + type_name((*f_iter)->get_type()) + ") " + (*f_iter)->get_name();
+  }
+  if (include_protocol) {
+    if (!first) {
+      result += " protocol";
+    }
+    result += ": (id<TProtocol>) " + protocol_name;
+    first = false;
+  }
+  if (include_error) {
+    if (!first) {
+      result += " error";
+    }
+    result += ": (NSError *__autoreleasing *)__thriftError";
+    first = false;
+  }
+  return result;
+}
+
+/**
+ * Converts the parse type to an Objective-C enum string for the given type.
+ */
+string t_cocoa_generator::type_to_enum(t_type* type) {
+  type = get_true_type(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:
+      throw "NO T_VOID CONSTRUCT";
+    case t_base_type::TYPE_STRING:
+      return "TTypeSTRING";
+    case t_base_type::TYPE_BOOL:
+      return "TTypeBOOL";
+    case t_base_type::TYPE_I8:
+      return "TTypeBYTE";
+    case t_base_type::TYPE_I16:
+      return "TTypeI16";
+    case t_base_type::TYPE_I32:
+      return "TTypeI32";
+    case t_base_type::TYPE_I64:
+      return "TTypeI64";
+    case t_base_type::TYPE_DOUBLE:
+      return "TTypeDOUBLE";
+    }
+  } else if (type->is_enum()) {
+    return "TTypeI32";
+  } else if (type->is_struct() || type->is_xception()) {
+    return "TTypeSTRUCT";
+  } else if (type->is_map()) {
+    return "TTypeMAP";
+  } else if (type->is_set()) {
+    return "TTypeSET";
+  } else if (type->is_list()) {
+    return "TTypeLIST";
+  }
+
+  throw "INVALID TYPE IN type_to_enum: " + type->get_name();
+}
+
+/**
+ * Returns a format string specifier for the supplied parse type.
+ */
+string t_cocoa_generator::format_string_for_type(t_type* type) {
+  type = get_true_type(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:
+      throw "NO T_VOID CONSTRUCT";
+    case t_base_type::TYPE_STRING:
+      return "\\\"%@\\\"";
+    case t_base_type::TYPE_BOOL:
+      return "%i";
+    case t_base_type::TYPE_I8:
+      return "%i";
+    case t_base_type::TYPE_I16:
+      return "%hi";
+    case t_base_type::TYPE_I32:
+      return "%i";
+    case t_base_type::TYPE_I64:
+      return "%qi";
+    case t_base_type::TYPE_DOUBLE:
+      return "%f";
+    }
+  } else if (type->is_enum()) {
+    return "%i";
+  } else if (type->is_struct() || type->is_xception()) {
+    return "%@";
+  } else if (type->is_map()) {
+    return "%@";
+  } else if (type->is_set()) {
+    return "%@";
+  } else if (type->is_list()) {
+    return "%@";
+  }
+
+  throw "INVALID TYPE IN format_string_for_type: " + type->get_name();
+}
+
+/**
+ * Returns a format cast for the supplied parse type.
+ */
+string t_cocoa_generator::format_cast_for_type(t_type* type) {
+  type = get_true_type(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:
+      throw "NO T_VOID CONSTRUCT";
+    case t_base_type::TYPE_STRING:
+      return ""; // "\\\"%@\\\"";
+    case t_base_type::TYPE_BOOL:
+      return ""; // "%i";
+    case t_base_type::TYPE_I8:
+      return ""; // "%i";
+    case t_base_type::TYPE_I16:
+      return ""; // "%hi";
+    case t_base_type::TYPE_I32:
+      return "(int)"; // "%i";
+    case t_base_type::TYPE_I64:
+      return ""; // "%qi";
+    case t_base_type::TYPE_DOUBLE:
+      return ""; // "%f";
+    }
+  } else if (type->is_enum()) {
+    return "(int)"; // "%i";
+  } else if (type->is_struct() || type->is_xception()) {
+    return ""; // "%@";
+  } else if (type->is_map()) {
+    return ""; // "%@";
+  } else if (type->is_set()) {
+    return ""; // "%@";
+  } else if (type->is_list()) {
+    return ""; // "%@";
+  }
+
+  throw "INVALID TYPE IN format_cast_for_type: " + type->get_name();
+}
+
+/**
+ * Generate a call to a field's setter.
+ *
+ * @param tfield Field the setter is being called on
+ * @param fieldName Name of variable to pass to setter
+ */
+
+string t_cocoa_generator::call_field_setter(t_field* tfield, string fieldName) {
+  return "self." + tfield->get_name() + " = " + fieldName + ";";
+}
+
+THRIFT_REGISTER_GENERATOR(
+    cocoa,
+    "Cocoa",
+    "    log_unexpected:  Log every time an unexpected field ID or type is encountered.\n"
+    "    debug_descriptions:\n"
+    "                     Allow use of debugDescription so the app can add description via a cateogory/extension\n"
+    "    validate_required:\n"
+    "                     Throws exception if any required field is not set.\n"
+    "    async_clients:   Generate clients which invoke asynchronously via block syntax.\n"
+    "    pods:            Generate imports in Cocopods framework format.\n"
+    "    promise_kit:     Generate clients which invoke asynchronously via promises.\n")

+ 4489 - 4489
contrib/restricted/thrift/compiler/thrift/generate/t_cpp_generator.cc

@@ -1,4489 +1,4489 @@
-/* 
- * Licensed to the Apache Software Foundation (ASF) under one 
- * or more contributor license agreements. See the NOTICE file 
- * distributed with this work for additional information 
- * regarding copyright ownership. The ASF licenses this file 
- * to you under the Apache License, Version 2.0 (the 
- * "License"); you may not use this file except in compliance 
- * with the License. You may obtain a copy of the License at 
- * 
- *   http://www.apache.org/licenses/LICENSE-2.0 
- * 
- * Unless required by applicable law or agreed to in writing, 
- * software distributed under the License is distributed on an 
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 
- * KIND, either express or implied. See the License for the 
- * specific language governing permissions and limitations 
- * under the License. 
- * 
- * Contains some contributions under the Thrift Software License. 
- * Please see doc/old-thrift-license.txt in the Thrift distribution for 
- * details. 
- */ 
- 
-#include <cassert> 
- 
-#include <fstream> 
-#include <iomanip> 
-#include <iostream> 
-#include <limits> 
-#include <sstream> 
-#include <string> 
-#include <vector> 
- 
-#include <sys/stat.h> 
- 
-#include "thrift/platform.h" 
-#include "thrift/generate/t_oop_generator.h" 
- 
-using std::map; 
-using std::ofstream; 
-using std::ostream; 
-using std::string; 
-using std::vector; 
- 
-static const string endl = "\n"; // avoid ostream << std::endl flushes 
- 
-/** 
- * C++ code generator. This is legitimacy incarnate. 
- * 
- */ 
-class t_cpp_generator : public t_oop_generator { 
-public: 
-  t_cpp_generator(t_program* program, 
-                  const std::map<std::string, std::string>& parsed_options, 
-                  const std::string& option_string) 
-    : t_oop_generator(program) { 
-    (void)option_string; 
-    std::map<std::string, std::string>::const_iterator iter; 
- 
- 
-    gen_pure_enums_ = false; 
-    use_include_prefix_ = false; 
-    gen_cob_style_ = false; 
-    gen_no_client_completion_ = false; 
-    gen_no_default_operators_ = false; 
-    gen_templates_ = false; 
-    gen_templates_only_ = false; 
-    gen_moveable_ = false; 
-    gen_no_ostream_operators_ = false; 
-    gen_no_skeleton_ = false; 
- 
-    for( iter = parsed_options.begin(); iter != parsed_options.end(); ++iter) { 
-      if( iter->first.compare("pure_enums") == 0) { 
-        gen_pure_enums_ = true; 
-      } else if( iter->first.compare("include_prefix") == 0) { 
-        use_include_prefix_ = true; 
-      } else if( iter->first.compare("cob_style") == 0) { 
-        gen_cob_style_ = true; 
-      } else if( iter->first.compare("no_client_completion") == 0) { 
-        gen_no_client_completion_ = true; 
-      } else if( iter->first.compare("no_default_operators") == 0) { 
-        gen_no_default_operators_ = true; 
-      } else if( iter->first.compare("templates") == 0) { 
-        gen_templates_ = true; 
-        gen_templates_only_ = (iter->second == "only"); 
-      } else if( iter->first.compare("moveable_types") == 0) { 
-        gen_moveable_ = true; 
-      } else if ( iter->first.compare("no_ostream_operators") == 0) { 
-        gen_no_ostream_operators_ = true; 
-      } else if ( iter->first.compare("no_skeleton") == 0) { 
-        gen_no_skeleton_ = true; 
-      } else { 
-        throw "unknown option cpp:" + iter->first; 
-      } 
-    } 
- 
-    out_dir_base_ = "gen-cpp"; 
-  } 
- 
-  /** 
-   * Init and close methods 
-   */ 
- 
-  void init_generator(); 
-  void close_generator(); 
- 
-  void generate_consts(std::vector<t_const*> consts); 
- 
-  /** 
-   * Program-level generation functions 
-   */ 
- 
-  void generate_typedef(t_typedef* ttypedef); 
-  void generate_enum(t_enum* tenum); 
-  void generate_enum_ostream_operator_decl(std::ostream& out, t_enum* tenum); 
-  void generate_enum_ostream_operator(std::ostream& out, t_enum* tenum); 
-  void generate_forward_declaration(t_struct* tstruct); 
-  void generate_struct(t_struct* tstruct) { generate_cpp_struct(tstruct, false); } 
-  void generate_xception(t_struct* txception) { generate_cpp_struct(txception, true); } 
-  void generate_cpp_struct(t_struct* tstruct, bool is_exception); 
- 
-  void generate_service(t_service* tservice); 
- 
-  void print_const_value(std::ostream& out, std::string name, t_type* type, t_const_value* value); 
-  std::string render_const_value(std::ostream& out, 
-                                 std::string name, 
-                                 t_type* type, 
-                                 t_const_value* value); 
- 
-  void generate_struct_declaration(std::ostream& out, 
-                                   t_struct* tstruct, 
-                                   bool is_exception = false, 
-                                   bool pointers = false, 
-                                   bool read = true, 
-                                   bool write = true, 
-                                   bool swap = false, 
-                                   bool is_user_struct = false); 
-  void generate_struct_definition(std::ostream& out, 
-                                  std::ostream& force_cpp_out, 
-                                  t_struct* tstruct, 
-                                  bool setters = true, 
-                                  bool is_user_struct = false); 
-  void generate_copy_constructor(std::ostream& out, t_struct* tstruct, bool is_exception); 
-  void generate_move_constructor(std::ostream& out, t_struct* tstruct, bool is_exception); 
-  void generate_constructor_helper(std::ostream& out, 
-                                   t_struct* tstruct, 
-                                   bool is_excpetion, 
-                                   bool is_move); 
-  void generate_assignment_operator(std::ostream& out, t_struct* tstruct); 
-  void generate_move_assignment_operator(std::ostream& out, t_struct* tstruct); 
-  void generate_assignment_helper(std::ostream& out, t_struct* tstruct, bool is_move); 
-  void generate_struct_reader(std::ostream& out, t_struct* tstruct, bool pointers = false); 
-  void generate_struct_writer(std::ostream& out, t_struct* tstruct, bool pointers = false); 
-  void generate_struct_result_writer(std::ostream& out, t_struct* tstruct, bool pointers = false); 
-  void generate_struct_swap(std::ostream& out, t_struct* tstruct); 
-  void generate_struct_print_method(std::ostream& out, t_struct* tstruct); 
-  void generate_exception_what_method(std::ostream& out, t_struct* tstruct); 
- 
-  /** 
-   * Service-level generation functions 
-   */ 
- 
-  void generate_service_interface(t_service* tservice, string style); 
-  void generate_service_interface_factory(t_service* tservice, string style); 
-  void generate_service_null(t_service* tservice, string style); 
-  void generate_service_multiface(t_service* tservice); 
-  void generate_service_helpers(t_service* tservice); 
-  void generate_service_client(t_service* tservice, string style); 
-  void generate_service_processor(t_service* tservice, string style); 
-  void generate_service_skeleton(t_service* tservice); 
-  void generate_process_function(t_service* tservice, 
-                                 t_function* tfunction, 
-                                 string style, 
-                                 bool specialized = false); 
-  void generate_function_helpers(t_service* tservice, t_function* tfunction); 
-  void generate_service_async_skeleton(t_service* tservice); 
- 
-  /** 
-   * Serialization constructs 
-   */ 
- 
-  void generate_deserialize_field(std::ostream& out, 
-                                  t_field* tfield, 
-                                  std::string prefix = "", 
-                                  std::string suffix = ""); 
- 
-  void generate_deserialize_struct(std::ostream& out, 
-                                   t_struct* tstruct, 
-                                   std::string prefix = "", 
-                                   bool pointer = false); 
- 
-  void generate_deserialize_container(std::ostream& out, t_type* ttype, std::string prefix = ""); 
- 
-  void generate_deserialize_set_element(std::ostream& out, t_set* tset, std::string prefix = ""); 
- 
-  void generate_deserialize_map_element(std::ostream& out, t_map* tmap, std::string prefix = ""); 
- 
-  void generate_deserialize_list_element(std::ostream& out, 
-                                         t_list* tlist, 
-                                         std::string prefix, 
-                                         bool push_back, 
-                                         std::string index); 
- 
-  void generate_serialize_field(std::ostream& out, 
-                                t_field* tfield, 
-                                std::string prefix = "", 
-                                std::string suffix = ""); 
- 
-  void generate_serialize_struct(std::ostream& out, 
-                                 t_struct* tstruct, 
-                                 std::string prefix = "", 
-                                 bool pointer = false); 
- 
-  void generate_serialize_container(std::ostream& out, t_type* ttype, std::string prefix = ""); 
- 
-  void generate_serialize_map_element(std::ostream& out, t_map* tmap, std::string iter); 
- 
-  void generate_serialize_set_element(std::ostream& out, t_set* tmap, std::string iter); 
- 
-  void generate_serialize_list_element(std::ostream& out, t_list* tlist, std::string iter); 
- 
-  void generate_function_call(ostream& out, 
-                              t_function* tfunction, 
-                              string target, 
-                              string iface, 
-                              string arg_prefix); 
-  /* 
-   * Helper rendering functions 
-   */ 
- 
-  std::string namespace_prefix(std::string ns); 
-  std::string namespace_open(std::string ns); 
-  std::string namespace_close(std::string ns); 
-  std::string type_name(t_type* ttype, bool in_typedef = false, bool arg = false); 
-  std::string base_type_name(t_base_type::t_base tbase); 
-  std::string declare_field(t_field* tfield, 
-                            bool init = false, 
-                            bool pointer = false, 
-                            bool constant = false, 
-                            bool reference = false); 
-  std::string function_signature(t_function* tfunction, 
-                                 std::string style, 
-                                 std::string prefix = "", 
-                                 bool name_params = true); 
-  std::string cob_function_signature(t_function* tfunction, 
-                                     std::string prefix = "", 
-                                     bool name_params = true); 
-  std::string argument_list(t_struct* tstruct, bool name_params = true, bool start_comma = false); 
-  std::string type_to_enum(t_type* ttype); 
- 
-  void generate_enum_constant_list(std::ostream& f, 
-                                   const vector<t_enum_value*>& constants, 
-                                   const char* prefix, 
-                                   const char* suffix, 
-                                   bool include_values); 
- 
-  void generate_struct_ostream_operator_decl(std::ostream& f, t_struct* tstruct); 
-  void generate_struct_ostream_operator(std::ostream& f, t_struct* tstruct); 
-  void generate_struct_print_method_decl(std::ostream& f, t_struct* tstruct); 
-  void generate_exception_what_method_decl(std::ostream& f, 
-                                           t_struct* tstruct, 
-                                           bool external = false); 
- 
-  bool is_reference(t_field* tfield) { return tfield->get_reference(); } 
- 
-  bool is_complex_type(t_type* ttype) { 
-    ttype = get_true_type(ttype); 
- 
-    return ttype->is_container() || ttype->is_struct() || ttype->is_xception() 
-           || (ttype->is_base_type() 
-               && (((t_base_type*)ttype)->get_base() == t_base_type::TYPE_STRING)); 
-  } 
- 
-  void set_use_include_prefix(bool use_include_prefix) { use_include_prefix_ = use_include_prefix; } 
- 
-  /** 
-   * The compiler option "no_thrift_ostream_impl" can be used to prevent 
-   * the compiler from emitting implementations for operator <<.  In this 
-   * case the consuming application must provide any needed to build. 
-   * 
-   * To disable this on a per structure bases, one can alternatively set 
-   * the annotation "cpp.customostream" to prevent thrift from emitting an 
-   * operator << (std::ostream&). 
-   * 
-   * See AnnotationTest for validation of this annotation feature. 
-   */ 
-  bool has_custom_ostream(t_type* ttype) const { 
-    return (gen_no_ostream_operators_) || 
-           (ttype->annotations_.find("cpp.customostream") != ttype->annotations_.end()); 
-  } 
- 
-private: 
-  /** 
-   * Returns the include prefix to use for a file generated by program, or the 
-   * empty string if no include prefix should be used. 
-   */ 
-  std::string get_include_prefix(const t_program& program) const; 
- 
-  /** 
-   * True if we should generate pure enums for Thrift enums, instead of wrapper classes. 
-   */ 
-  bool gen_pure_enums_; 
- 
-  /** 
-   * True if we should generate templatized reader/writer methods. 
-   */ 
-  bool gen_templates_; 
- 
-  /** 
-   * True iff we should generate process function pointers for only templatized 
-   * reader/writer methods. 
-   */ 
-  bool gen_templates_only_; 
- 
-  /** 
-   * True if we should generate move constructors & assignment operators. 
-   */ 
-  bool gen_moveable_; 
- 
-  /** 
-   * True if we should generate ostream definitions 
-   */ 
-  bool gen_no_ostream_operators_; 
- 
-  /** 
-   * True iff we should use a path prefix in our #include statements for other 
-   * thrift-generated header files. 
-   */ 
-  bool use_include_prefix_; 
- 
-  /** 
-   * True if we should generate "Continuation OBject"-style classes as well. 
-   */ 
-  bool gen_cob_style_; 
- 
-  /** 
-   * True if we should omit calls to completion__() in CobClient class. 
-   */ 
-  bool gen_no_client_completion_; 
- 
-  /** 
-   * True if we should omit generating the default opeartors ==, != and <. 
-   */ 
-  bool gen_no_default_operators_; 
- 
-   /** 
-   * True if we should generate skeleton. 
-   */ 
-  bool gen_no_skeleton_; 
- 
-  /** 
-   * Strings for namespace, computed once up front then used directly 
-   */ 
- 
-  std::string ns_open_; 
-  std::string ns_close_; 
- 
-  /** 
-   * File streams, stored here to avoid passing them as parameters to every 
-   * function. 
-   */ 
- 
-  ofstream_with_content_based_conditional_update f_types_; 
-  ofstream_with_content_based_conditional_update f_types_impl_; 
-  ofstream_with_content_based_conditional_update f_types_tcc_; 
-  ofstream_with_content_based_conditional_update f_header_; 
-  ofstream_with_content_based_conditional_update f_service_; 
-  ofstream_with_content_based_conditional_update f_service_tcc_; 
- 
-  // The ProcessorGenerator is used to generate parts of the code, 
-  // so it needs access to many of our protected members and methods. 
-  // 
-  // TODO: The code really should be cleaned up so that helper methods for 
-  // writing to the output files are separate from the generator classes 
-  // themselves. 
-  friend class ProcessorGenerator; 
-}; 
- 
-/** 
- * Prepares for file generation by opening up the necessary file output 
- * streams. 
- */ 
-void t_cpp_generator::init_generator() { 
-  // Make output directory 
-  MKDIR(get_out_dir().c_str()); 
- 
-  // Make output file 
-  string f_types_name = get_out_dir() + program_name_ + "_types.h"; 
-  f_types_.open(f_types_name); 
- 
-  string f_types_impl_name = get_out_dir() + program_name_ + "_types.cpp"; 
-  f_types_impl_.open(f_types_impl_name.c_str()); 
- 
-  if (gen_templates_) { 
-    // If we don't open the stream, it appears to just discard data, 
-    // which is fine. 
-    string f_types_tcc_name = get_out_dir() + program_name_ + "_types.tcc"; 
-    f_types_tcc_.open(f_types_tcc_name.c_str()); 
-  } 
- 
-  // Print header 
-  f_types_ << autogen_comment(); 
-  f_types_impl_ << autogen_comment(); 
-  f_types_tcc_ << autogen_comment(); 
- 
-  // Start ifndef 
-  f_types_ << "#ifndef " << program_name_ << "_TYPES_H" << endl << "#define " << program_name_ 
-           << "_TYPES_H" << endl << endl; 
-  f_types_tcc_ << "#ifndef " << program_name_ << "_TYPES_TCC" << endl << "#define " << program_name_ 
-               << "_TYPES_TCC" << endl << endl; 
- 
-  // Include base types 
-  f_types_ << "#include <iosfwd>" << endl 
-           << endl 
-           << "#include <thrift/Thrift.h>" << endl 
-           << "#include <thrift/TApplicationException.h>" << endl 
-           << "#include <thrift/TBase.h>" << endl 
-           << "#include <thrift/protocol/TProtocol.h>" << endl 
-           << "#include <thrift/transport/TTransport.h>" << endl 
-           << endl; 
-  // Include C++xx compatibility header 
-  f_types_ << "#include <thrift/stdcxx.h>" << endl; 
- 
-  // Include other Thrift includes 
-  const vector<t_program*>& includes = program_->get_includes(); 
-  for (size_t i = 0; i < includes.size(); ++i) { 
-    f_types_ << "#include \"" << get_include_prefix(*(includes[i])) << includes[i]->get_name() 
-             << "_types.h\"" << endl; 
- 
-    // XXX(simpkins): If gen_templates_ is enabled, we currently assume all 
-    // included files were also generated with templates enabled. 
-    f_types_tcc_ << "#include \"" << get_include_prefix(*(includes[i])) << includes[i]->get_name() 
-                 << "_types.tcc\"" << endl; 
-  } 
-  f_types_ << endl; 
- 
-  // Include custom headers 
-  const vector<string>& cpp_includes = program_->get_cpp_includes(); 
-  for (size_t i = 0; i < cpp_includes.size(); ++i) { 
-    if (cpp_includes[i][0] == '<') { 
-      f_types_ << "#include " << cpp_includes[i] << endl; 
-    } else { 
-      f_types_ << "#include \"" << cpp_includes[i] << "\"" << endl; 
-    } 
-  } 
-  f_types_ << endl; 
- 
-  // Include the types file 
-  f_types_impl_ << "#include \"" << get_include_prefix(*get_program()) << program_name_ 
-                << "_types.h\"" << endl << endl; 
-  f_types_tcc_ << "#include \"" << get_include_prefix(*get_program()) << program_name_ 
-               << "_types.h\"" << endl << endl; 
- 
-  // The swap() code needs <algorithm> for std::swap() 
-  f_types_impl_ << "#include <algorithm>" << endl; 
-  // for operator<< 
-  f_types_impl_ << "#include <ostream>" << endl << endl; 
-  f_types_impl_ << "#include <thrift/TToString.h>" << endl << endl; 
- 
-  // Open namespace 
-  ns_open_ = namespace_open(program_->get_namespace("cpp")); 
-  ns_close_ = namespace_close(program_->get_namespace("cpp")); 
- 
-  f_types_ << ns_open_ << endl << endl; 
- 
-  f_types_impl_ << ns_open_ << endl << endl; 
- 
-  f_types_tcc_ << ns_open_ << endl << endl; 
-} 
- 
-/** 
- * Closes the output files. 
- */ 
-void t_cpp_generator::close_generator() { 
-  // Close namespace 
-  f_types_ << ns_close_ << endl << endl; 
-  f_types_impl_ << ns_close_ << endl; 
-  f_types_tcc_ << ns_close_ << endl << endl; 
- 
-  // Include the types.tcc file from the types header file, 
-  // so clients don't have to explicitly include the tcc file. 
-  // TODO(simpkins): Make this a separate option. 
-  if (gen_templates_) { 
-    f_types_ << "#include \"" << get_include_prefix(*get_program()) << program_name_ 
-             << "_types.tcc\"" << endl << endl; 
-  } 
- 
-  // Close ifndef 
-  f_types_ << "#endif" << endl; 
-  f_types_tcc_ << "#endif" << endl; 
- 
-  // Close output file 
-  f_types_.close(); 
-  f_types_impl_.close(); 
-  f_types_tcc_.close(); 
-} 
- 
-/** 
- * Generates a typedef. This is just a simple 1-liner in C++ 
- * 
- * @param ttypedef The type definition 
- */ 
-void t_cpp_generator::generate_typedef(t_typedef* ttypedef) { 
-  f_types_ << indent() << "typedef " << type_name(ttypedef->get_type(), true) << " " 
-           << ttypedef->get_symbolic() << ";" << endl << endl; 
-} 
- 
-void t_cpp_generator::generate_enum_constant_list(std::ostream& f, 
-                                                  const vector<t_enum_value*>& constants, 
-                                                  const char* prefix, 
-                                                  const char* suffix, 
-                                                  bool include_values) { 
-  f << " {" << endl; 
-  indent_up(); 
- 
-  vector<t_enum_value*>::const_iterator c_iter; 
-  bool first = true; 
-  for (c_iter = constants.begin(); c_iter != constants.end(); ++c_iter) { 
-    if (first) { 
-      first = false; 
-    } else { 
-      f << "," << endl; 
-    } 
-    indent(f) << prefix << (*c_iter)->get_name() << suffix; 
-    if (include_values) { 
-      f << " = " << (*c_iter)->get_value(); 
-    } 
-  } 
- 
-  f << endl; 
-  indent_down(); 
-  indent(f) << "};" << endl; 
-} 
- 
-/** 
- * Generates code for an enumerated type. In C++, this is essentially the same 
- * as the thrift definition itself, using the enum keyword in C++. 
- * 
- * @param tenum The enumeration 
- */ 
-void t_cpp_generator::generate_enum(t_enum* tenum) { 
-  vector<t_enum_value*> constants = tenum->get_constants(); 
- 
-  std::string enum_name = tenum->get_name(); 
-  if (!gen_pure_enums_) { 
-    enum_name = "type"; 
-    f_types_ << indent() << "struct " << tenum->get_name() << " {" << endl; 
-    indent_up(); 
-  } 
-  f_types_ << indent() << "enum " << enum_name; 
- 
-  generate_enum_constant_list(f_types_, constants, "", "", true); 
- 
-  if (!gen_pure_enums_) { 
-    indent_down(); 
-    f_types_ << "};" << endl; 
-  } 
- 
-  f_types_ << endl; 
- 
-  /** 
-     Generate a character array of enum names for debugging purposes. 
-  */ 
-  std::string prefix = ""; 
-  if (!gen_pure_enums_) { 
-    prefix = tenum->get_name() + "::"; 
-  } 
- 
-  f_types_impl_ << indent() << "int _k" << tenum->get_name() << "Values[] ="; 
-  generate_enum_constant_list(f_types_impl_, constants, prefix.c_str(), "", false); 
- 
-  f_types_impl_ << indent() << "const char* _k" << tenum->get_name() << "Names[] ="; 
-  generate_enum_constant_list(f_types_impl_, constants, "\"", "\"", false); 
- 
-  f_types_ << indent() << "extern const std::map<int, const char*> _" << tenum->get_name() 
-           << "_VALUES_TO_NAMES;" << endl << endl; 
- 
-  f_types_impl_ << indent() << "const std::map<int, const char*> _" << tenum->get_name() 
-                << "_VALUES_TO_NAMES(::apache::thrift::TEnumIterator(" << constants.size() << ", _k" 
-                << tenum->get_name() << "Values" 
-                << ", _k" << tenum->get_name() << "Names), " 
-                << "::apache::thrift::TEnumIterator(-1, NULL, NULL));" << endl << endl; 
- 
-  generate_enum_ostream_operator_decl(f_types_, tenum); 
-  generate_enum_ostream_operator(f_types_impl_, tenum); 
-} 
- 
-void t_cpp_generator::generate_enum_ostream_operator_decl(std::ostream& out, t_enum* tenum) { 
- 
-  out << "std::ostream& operator<<(std::ostream& out, const "; 
-  if (gen_pure_enums_) { 
-    out << tenum->get_name(); 
-  } else { 
-    out << tenum->get_name() << "::type&"; 
-  } 
-  out << " val);" << endl; 
-  out << endl; 
-} 
- 
-void t_cpp_generator::generate_enum_ostream_operator(std::ostream& out, t_enum* tenum) { 
- 
-  // If we've been told the consuming application will provide an ostream 
-  // operator definition then we only make a declaration: 
- 
-  if (!has_custom_ostream(tenum)) { 
-    out << "std::ostream& operator<<(std::ostream& out, const "; 
-    if (gen_pure_enums_) { 
-      out << tenum->get_name(); 
-    } else { 
-      out << tenum->get_name() << "::type&"; 
-    } 
-    out << " val) "; 
-    scope_up(out); 
- 
-    out << indent() << "std::map<int, const char*>::const_iterator it = _" 
-             << tenum->get_name() << "_VALUES_TO_NAMES.find(val);" << endl; 
-    out << indent() << "if (it != _" << tenum->get_name() << "_VALUES_TO_NAMES.end()) {" << endl; 
-    indent_up(); 
-    out << indent() << "out << it->second;" << endl; 
-    indent_down(); 
-    out << indent() << "} else {" << endl; 
-    indent_up(); 
-    out << indent() << "out << static_cast<int>(val);" << endl; 
-    indent_down(); 
-    out << indent() << "}" << endl; 
- 
-    out << indent() << "return out;" << endl; 
-    scope_down(out); 
-    out << endl; 
-  } 
-} 
- 
-/** 
- * Generates a class that holds all the constants. 
- */ 
-void t_cpp_generator::generate_consts(std::vector<t_const*> consts) { 
-  string f_consts_name = get_out_dir() + program_name_ + "_constants.h"; 
-  ofstream_with_content_based_conditional_update f_consts; 
-  f_consts.open(f_consts_name); 
- 
-  string f_consts_impl_name = get_out_dir() + program_name_ + "_constants.cpp"; 
-  ofstream_with_content_based_conditional_update f_consts_impl; 
-  f_consts_impl.open(f_consts_impl_name); 
- 
-  // Print header 
-  f_consts << autogen_comment(); 
-  f_consts_impl << autogen_comment(); 
- 
-  // Start ifndef 
-  f_consts << "#ifndef " << program_name_ << "_CONSTANTS_H" << endl << "#define " << program_name_ 
-           << "_CONSTANTS_H" << endl << endl << "#include \"" << get_include_prefix(*get_program()) 
-           << program_name_ << "_types.h\"" << endl << endl << ns_open_ << endl << endl; 
- 
-  f_consts_impl << "#include \"" << get_include_prefix(*get_program()) << program_name_ 
-                << "_constants.h\"" << endl << endl << ns_open_ << endl << endl; 
- 
-  f_consts << "class " << program_name_ << "Constants {" << endl << " public:" << endl << "  " 
-           << program_name_ << "Constants();" << endl << endl; 
-  indent_up(); 
-  vector<t_const*>::iterator c_iter; 
-  for (c_iter = consts.begin(); c_iter != consts.end(); ++c_iter) { 
-    string name = (*c_iter)->get_name(); 
-    t_type* type = (*c_iter)->get_type(); 
-    f_consts << indent() << type_name(type) << " " << name << ";" << endl; 
-  } 
-  indent_down(); 
-  f_consts << "};" << endl; 
- 
-  f_consts_impl << "const " << program_name_ << "Constants g_" << program_name_ << "_constants;" 
-                << endl << endl << program_name_ << "Constants::" << program_name_ 
-                << "Constants() {" << endl; 
-  indent_up(); 
-  for (c_iter = consts.begin(); c_iter != consts.end(); ++c_iter) { 
-    print_const_value(f_consts_impl, 
-                      (*c_iter)->get_name(), 
-                      (*c_iter)->get_type(), 
-                      (*c_iter)->get_value()); 
-  } 
-  indent_down(); 
-  indent(f_consts_impl) << "}" << endl; 
- 
-  f_consts << endl << "extern const " << program_name_ << "Constants g_" << program_name_ 
-           << "_constants;" << endl << endl << ns_close_ << endl << endl << "#endif" << endl; 
-  f_consts.close(); 
- 
-  f_consts_impl << endl << ns_close_ << endl << endl; 
-  f_consts_impl.close(); 
-} 
- 
-/** 
- * Prints the value of a constant with the given type. Note that type checking 
- * is NOT performed in this function as it is always run beforehand using the 
- * validate_types method in main.cc 
- */ 
-void t_cpp_generator::print_const_value(ostream& out, 
-                                        string name, 
-                                        t_type* type, 
-                                        t_const_value* value) { 
-  type = get_true_type(type); 
-  if (type->is_base_type()) { 
-    string v2 = render_const_value(out, name, type, value); 
-    indent(out) << name << " = " << v2 << ";" << endl << endl; 
-  } else if (type->is_enum()) { 
-    indent(out) << name << " = (" << type_name(type) << ")" << 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*, t_const_value::value_compare>& val = value->get_map(); 
-    map<t_const_value*, t_const_value*, t_const_value::value_compare>::const_iterator v_iter; 
-    bool is_nonrequired_field = false; 
-    for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) { 
-      t_type* field_type = NULL; 
-      is_nonrequired_field = false; 
-      for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { 
-        if ((*f_iter)->get_name() == v_iter->first->get_string()) { 
-          field_type = (*f_iter)->get_type(); 
-          is_nonrequired_field = (*f_iter)->get_req() != t_field::T_REQUIRED; 
-        } 
-      } 
-      if (field_type == NULL) { 
-        throw "type error: " + type->get_name() + " has no field " + v_iter->first->get_string(); 
-      } 
-      string val = render_const_value(out, name, field_type, v_iter->second); 
-      indent(out) << name << "." << v_iter->first->get_string() << " = " << val << ";" << endl; 
-      if (is_nonrequired_field) { 
-        indent(out) << name << ".__isset." << v_iter->first->get_string() << " = true;" << endl; 
-      } 
-    } 
-    out << endl; 
-  } else if (type->is_map()) { 
-    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*, t_const_value::value_compare>& val = value->get_map(); 
-    map<t_const_value*, t_const_value*, t_const_value::value_compare>::const_iterator v_iter; 
-    for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) { 
-      string key = render_const_value(out, name, ktype, v_iter->first); 
-      string val = render_const_value(out, name, vtype, v_iter->second); 
-      indent(out) << name << ".insert(std::make_pair(" << key << ", " << val << "));" << endl; 
-    } 
-    out << endl; 
-  } else if (type->is_list()) { 
-    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; 
-    for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) { 
-      string val = render_const_value(out, name, etype, *v_iter); 
-      indent(out) << name << ".push_back(" << val << ");" << endl; 
-    } 
-    out << endl; 
-  } else if (type->is_set()) { 
-    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; 
-    for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) { 
-      string val = render_const_value(out, name, etype, *v_iter); 
-      indent(out) << name << ".insert(" << val << ");" << endl; 
-    } 
-    out << endl; 
-  } else { 
-    throw "INVALID TYPE IN print_const_value: " + type->get_name(); 
-  } 
-} 
- 
-/** 
- * 
- */ 
-string t_cpp_generator::render_const_value(ostream& out, 
-                                           string name, 
-                                           t_type* type, 
-                                           t_const_value* value) { 
-  (void)name; 
-  std::ostringstream render; 
- 
-  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: 
-      render << '"' << get_escaped_string(value) << '"'; 
-      break; 
-    case t_base_type::TYPE_BOOL: 
-      render << ((value->get_integer() > 0) ? "true" : "false"); 
-      break; 
-    case t_base_type::TYPE_I8: 
-    case t_base_type::TYPE_I16: 
-    case t_base_type::TYPE_I32: 
-      render << value->get_integer(); 
-      break; 
-    case t_base_type::TYPE_I64: 
-      render << value->get_integer() << "LL"; 
-      break; 
-    case t_base_type::TYPE_DOUBLE: 
-      if (value->get_type() == t_const_value::CV_INTEGER) { 
-        render << "static_cast<double>(" << value->get_integer() << ")"; 
-      } else { 
-        render << emit_double_as_string(value->get_double()); 
-      } 
-      break; 
-    default: 
-      throw "compiler error: no const of base type " + t_base_type::t_base_name(tbase); 
-    } 
-  } else if (type->is_enum()) { 
-    render << "(" << type_name(type) << ")" << value->get_integer(); 
-  } else { 
-    string t = tmp("tmp"); 
-    indent(out) << type_name(type) << " " << t << ";" << endl; 
-    print_const_value(out, t, type, value); 
-    render << t; 
-  } 
- 
-  return render.str(); 
-} 
- 
-void t_cpp_generator::generate_forward_declaration(t_struct* tstruct) { 
-  // Forward declare struct def 
-  f_types_ << indent() << "class " << tstruct->get_name() << ";" << endl << endl; 
-} 
- 
-/** 
- * Generates a struct definition for a thrift data type. This is a class 
- * with data members and a read/write() function, plus a mirroring isset 
- * inner class. 
- * 
- * @param tstruct The struct definition 
- */ 
-void t_cpp_generator::generate_cpp_struct(t_struct* tstruct, bool is_exception) { 
-  generate_struct_declaration(f_types_, tstruct, is_exception, false, true, true, true, true); 
-  generate_struct_definition(f_types_impl_, f_types_impl_, tstruct, true, true); 
- 
-  std::ostream& out = (gen_templates_ ? f_types_tcc_ : f_types_impl_); 
-  generate_struct_reader(out, tstruct); 
-  generate_struct_writer(out, tstruct); 
-  generate_struct_swap(f_types_impl_, tstruct); 
-  generate_copy_constructor(f_types_impl_, tstruct, is_exception); 
-  if (gen_moveable_) { 
-    generate_move_constructor(f_types_impl_, tstruct, is_exception); 
-  } 
-  generate_assignment_operator(f_types_impl_, tstruct); 
-  if (gen_moveable_) { 
-    generate_move_assignment_operator(f_types_impl_, tstruct); 
-  } 
- 
-  if (!has_custom_ostream(tstruct)) { 
-    generate_struct_print_method(f_types_impl_, tstruct); 
-  } 
- 
-  if (is_exception) { 
-    generate_exception_what_method(f_types_impl_, tstruct); 
-  } 
-} 
- 
-void t_cpp_generator::generate_copy_constructor(ostream& out, 
-                                                t_struct* tstruct, 
-                                                bool is_exception) { 
-  generate_constructor_helper(out, tstruct, is_exception, /*is_move=*/false); 
-} 
- 
-void t_cpp_generator::generate_move_constructor(ostream& out, 
-                                                t_struct* tstruct, 
-                                                bool is_exception) { 
-  generate_constructor_helper(out, tstruct, is_exception, /*is_move=*/true); 
-} 
- 
-namespace { 
-// Helper to convert a variable to rvalue, if move is enabled 
-std::string maybeMove(std::string const& other, bool move) { 
-  if (move) { 
-    return "std::move(" + other + ")"; 
-  } 
-  return other; 
-} 
-} 
- 
-void t_cpp_generator::generate_constructor_helper(ostream& out, 
-                                                  t_struct* tstruct, 
-                                                  bool is_exception, 
-                                                  bool is_move) { 
- 
-  std::string tmp_name = tmp("other"); 
- 
-  indent(out) << tstruct->get_name() << "::" << tstruct->get_name(); 
- 
-  if (is_move) { 
-    out << "( " << tstruct->get_name() << "&& "; 
-  } else { 
-    out << "(const " << tstruct->get_name() << "& "; 
-  } 
-  out << tmp_name << ") "; 
-  if (is_exception) 
-    out << ": TException() "; 
-  out << "{" << endl; 
-  indent_up(); 
- 
-  const vector<t_field*>& members = tstruct->get_members(); 
- 
-  // eliminate compiler unused warning 
-  if (members.empty()) 
-    indent(out) << "(void) " << tmp_name << ";" << endl; 
- 
-  vector<t_field*>::const_iterator f_iter; 
-  bool has_nonrequired_fields = false; 
-  for (f_iter = members.begin(); f_iter != members.end(); ++f_iter) { 
-    if ((*f_iter)->get_req() != t_field::T_REQUIRED) 
-      has_nonrequired_fields = true; 
-    indent(out) << (*f_iter)->get_name() << " = " 
-                << maybeMove(tmp_name + "." + (*f_iter)->get_name(), is_move) << ";" << endl; 
-  } 
- 
-  if (has_nonrequired_fields) { 
-    indent(out) << "__isset = " << maybeMove(tmp_name + ".__isset", is_move) << ";" << endl; 
-  } 
- 
-  indent_down(); 
-  indent(out) << "}" << endl; 
-} 
- 
-void t_cpp_generator::generate_assignment_operator(ostream& out, t_struct* tstruct) { 
-  generate_assignment_helper(out, tstruct, /*is_move=*/false); 
-} 
- 
-void t_cpp_generator::generate_move_assignment_operator(ostream& out, t_struct* tstruct) { 
-  generate_assignment_helper(out, tstruct, /*is_move=*/true); 
-} 
- 
-void t_cpp_generator::generate_assignment_helper(ostream& out, t_struct* tstruct, bool is_move) { 
-  std::string tmp_name = tmp("other"); 
- 
-  indent(out) << tstruct->get_name() << "& " << tstruct->get_name() << "::operator=("; 
- 
-  if (is_move) { 
-    out << tstruct->get_name() << "&& "; 
-  } else { 
-    out << "const " << tstruct->get_name() << "& "; 
-  } 
-  out << tmp_name << ") {" << endl; 
- 
-  indent_up(); 
- 
-  const vector<t_field*>& members = tstruct->get_members(); 
- 
-  // eliminate compiler unused warning 
-  if (members.empty()) 
-    indent(out) << "(void) " << tmp_name << ";" << endl; 
- 
-  vector<t_field*>::const_iterator f_iter; 
-  bool has_nonrequired_fields = false; 
-  for (f_iter = members.begin(); f_iter != members.end(); ++f_iter) { 
-    if ((*f_iter)->get_req() != t_field::T_REQUIRED) 
-      has_nonrequired_fields = true; 
-    indent(out) << (*f_iter)->get_name() << " = " 
-                << maybeMove(tmp_name + "." + (*f_iter)->get_name(), is_move) << ";" << endl; 
-  } 
-  if (has_nonrequired_fields) { 
-    indent(out) << "__isset = " << maybeMove(tmp_name + ".__isset", is_move) << ";" << endl; 
-  } 
- 
-  indent(out) << "return *this;" << endl; 
-  indent_down(); 
-  indent(out) << "}" << endl; 
-} 
- 
-/** 
- * Writes the struct declaration into the header file 
- * 
- * @param out Output stream 
- * @param tstruct The struct 
- */ 
-void t_cpp_generator::generate_struct_declaration(ostream& out, 
-                                                  t_struct* tstruct, 
-                                                  bool is_exception, 
-                                                  bool pointers, 
-                                                  bool read, 
-                                                  bool write, 
-                                                  bool swap, 
-                                                  bool is_user_struct) { 
-  string extends = ""; 
-  if (is_exception) { 
-    extends = " : public ::apache::thrift::TException"; 
-  } else { 
-    if (is_user_struct && !gen_templates_) { 
-      extends = " : public virtual ::apache::thrift::TBase"; 
-    } 
-  } 
- 
-  // Get members 
-  vector<t_field*>::const_iterator m_iter; 
-  const vector<t_field*>& members = tstruct->get_members(); 
- 
-  // Write the isset structure declaration outside the class. This makes 
-  // the generated code amenable to processing by SWIG. 
-  // We only declare the struct if it gets used in the class. 
- 
-  // Isset struct has boolean fields, but only for non-required fields. 
-  bool has_nonrequired_fields = false; 
-  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { 
-    if ((*m_iter)->get_req() != t_field::T_REQUIRED) 
-      has_nonrequired_fields = true; 
-  } 
- 
-  if (has_nonrequired_fields && (!pointers || read)) { 
- 
-    out << indent() << "typedef struct _" << tstruct->get_name() << "__isset {" << endl; 
-    indent_up(); 
- 
-    indent(out) << "_" << tstruct->get_name() << "__isset() "; 
-    bool first = true; 
-    for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { 
-      if ((*m_iter)->get_req() == t_field::T_REQUIRED) { 
-        continue; 
-      } 
-      string isSet = ((*m_iter)->get_value() != NULL) ? "true" : "false"; 
-      if (first) { 
-        first = false; 
-        out << ": " << (*m_iter)->get_name() << "(" << isSet << ")"; 
-      } else { 
-        out << ", " << (*m_iter)->get_name() << "(" << isSet << ")"; 
-      } 
-    } 
-    out << " {}" << endl; 
- 
-    for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { 
-      if ((*m_iter)->get_req() != t_field::T_REQUIRED) { 
-        indent(out) << "bool " << (*m_iter)->get_name() << " :1;" << endl; 
-      } 
-    } 
- 
-    indent_down(); 
-    indent(out) << "} _" << tstruct->get_name() << "__isset;" << endl; 
-  } 
- 
-  out << endl; 
- 
-  // Open struct def 
-  out << indent() << "class " << tstruct->get_name() << extends << " {" << endl << indent() 
-      << " public:" << endl << endl; 
-  indent_up(); 
- 
-  if (!pointers) { 
-    // Copy constructor 
-    indent(out) << tstruct->get_name() << "(const " << tstruct->get_name() << "&);" << endl; 
- 
-    // Move constructor 
-    if (gen_moveable_) { 
-      indent(out) << tstruct->get_name() << "(" << tstruct->get_name() << "&&);" << endl; 
-    } 
- 
-    // Assignment Operator 
-    indent(out) << tstruct->get_name() << "& operator=(const " << tstruct->get_name() << "&);" 
-                << endl; 
- 
-    // Move assignment operator 
-    if (gen_moveable_) { 
-      indent(out) << tstruct->get_name() << "& operator=(" << tstruct->get_name() << "&&);" << endl; 
-    } 
- 
-    // 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 = get_true_type((*m_iter)->get_type()); 
-      if (t->is_base_type() || t->is_enum() || is_reference(*m_iter)) { 
-        string dval; 
-        if (t->is_enum()) { 
-          dval += "(" + type_name(t) + ")"; 
-        } 
-        dval += (t->is_string() || is_reference(*m_iter)) ? "" : "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; 
-          out << " : "; 
-          out << (*m_iter)->get_name() << "(" << dval << ")"; 
-        } else { 
-          out << ", " << (*m_iter)->get_name() << "(" << dval << ")"; 
-        } 
-      } 
-    } 
-    out << " {" << endl; 
-    indent_up(); 
-    // TODO(dreiss): When everything else in Thrift is perfect, 
-    // do more of these in the initializer list. 
-    for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { 
-      t_type* t = get_true_type((*m_iter)->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); 
-        } 
-      } 
-    } 
-    scope_down(out); 
-  } 
- 
-  if (tstruct->annotations_.find("final") == tstruct->annotations_.end()) { 
-    out << endl << indent() << "virtual ~" << tstruct->get_name() << "() throw();" << endl; 
-  } 
- 
-  // Declare all fields 
-  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { 
-    indent(out) << declare_field(*m_iter, 
-                                 false, 
-                                 (pointers && !(*m_iter)->get_type()->is_xception()), 
-                                 !read) << endl; 
-  } 
- 
-  // Add the __isset data member if we need it, using the definition from above 
-  if (has_nonrequired_fields && (!pointers || read)) { 
-    out << endl << indent() << "_" << tstruct->get_name() << "__isset __isset;" << endl; 
-  } 
- 
-  // Create a setter function for each field 
-  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { 
-    if (pointers) { 
-      continue; 
-    } 
-    if (is_reference((*m_iter))) { 
-      out << endl << indent() << "void __set_" << (*m_iter)->get_name() << "(::apache::thrift::stdcxx::shared_ptr<" 
-          << type_name((*m_iter)->get_type(), false, false) << ">"; 
-      out << " val);" << endl; 
-    } else { 
-      out << endl << indent() << "void __set_" << (*m_iter)->get_name() << "(" 
-          << type_name((*m_iter)->get_type(), false, true); 
-      out << " val);" << endl; 
-    } 
-  } 
-  out << endl; 
- 
-  if (!pointers) { 
-    // Should we generate default operators? 
-    if (!gen_no_default_operators_) { 
-      // Generate an equality testing operator.  Make it inline since the compiler 
-      // will do a better job than we would when deciding whether to inline it. 
-      out << indent() << "bool operator == (const " << tstruct->get_name() << " & " 
-          << (members.size() > 0 ? "rhs" : "/* rhs */") << ") const" << endl; 
-      scope_up(out); 
-      for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { 
-        // Most existing Thrift code does not use isset or optional/required, 
-        // so we treat "default" fields as required. 
-        if ((*m_iter)->get_req() != t_field::T_OPTIONAL) { 
-          out << indent() << "if (!(" << (*m_iter)->get_name() << " == rhs." 
-              << (*m_iter)->get_name() << "))" << endl << indent() << "  return false;" << endl; 
-        } else { 
-          out << indent() << "if (__isset." << (*m_iter)->get_name() << " != rhs.__isset." 
-              << (*m_iter)->get_name() << ")" << endl << indent() << "  return false;" << endl 
-              << indent() << "else if (__isset." << (*m_iter)->get_name() << " && !(" 
-              << (*m_iter)->get_name() << " == rhs." << (*m_iter)->get_name() << "))" << endl 
-              << indent() << "  return false;" << endl; 
-        } 
-      } 
-      indent(out) << "return true;" << endl; 
-      scope_down(out); 
-      out << indent() << "bool operator != (const " << tstruct->get_name() << " &rhs) const {" 
-          << endl << indent() << "  return !(*this == rhs);" << endl << indent() << "}" << endl 
-          << endl; 
- 
-      // Generate the declaration of a less-than operator.  This must be 
-      // implemented by the application developer if they wish to use it.  (They 
-      // will get a link error if they try to use it without an implementation.) 
-      out << indent() << "bool operator < (const " << tstruct->get_name() << " & ) const;" << endl 
-          << endl; 
-    } 
-  } 
- 
-  if (read) { 
-    if (gen_templates_) { 
-      out << indent() << "template <class Protocol_>" << endl << indent() 
-          << "uint32_t read(Protocol_* iprot);" << endl; 
-    } else { 
-      out << indent() << "uint32_t read(" 
-          << "::apache::thrift::protocol::TProtocol* iprot);" << endl; 
-    } 
-  } 
-  if (write) { 
-    if (gen_templates_) { 
-      out << indent() << "template <class Protocol_>" << endl << indent() 
-          << "uint32_t write(Protocol_* oprot) const;" << endl; 
-    } else { 
-      out << indent() << "uint32_t write(" 
-          << "::apache::thrift::protocol::TProtocol* oprot) const;" << endl; 
-    } 
-  } 
-  out << endl; 
- 
-  if (is_user_struct && !has_custom_ostream(tstruct)) { 
-    out << indent() << "virtual "; 
-    generate_struct_print_method_decl(out, NULL); 
-    out << ";" << endl; 
-  } 
- 
-  // std::exception::what() 
-  if (is_exception) { 
-    out << indent() << "mutable std::string thriftTExceptionMessageHolder_;" << endl; 
-    out << indent(); 
-    generate_exception_what_method_decl(out, tstruct, false); 
-    out << ";" << endl; 
-  } 
- 
-  indent_down(); 
-  indent(out) << "};" << endl << endl; 
- 
-  if (swap) { 
-    // Generate a namespace-scope swap() function 
-    out << indent() << "void swap(" << tstruct->get_name() << " &a, " << tstruct->get_name() 
-        << " &b);" << endl << endl; 
-  } 
- 
-  if (is_user_struct) { 
-    generate_struct_ostream_operator_decl(out, tstruct); 
-  } 
-} 
- 
-void t_cpp_generator::generate_struct_definition(ostream& out, 
-                                                 ostream& force_cpp_out, 
-                                                 t_struct* tstruct, 
-                                                 bool setters, 
-                                                 bool is_user_struct) { 
-  // Get members 
-  vector<t_field*>::const_iterator m_iter; 
-  const vector<t_field*>& members = tstruct->get_members(); 
- 
-  // Destructor 
-  if (tstruct->annotations_.find("final") == tstruct->annotations_.end()) { 
-    force_cpp_out << endl << indent() << tstruct->get_name() << "::~" << tstruct->get_name() 
-                  << "() throw() {" << endl; 
-    indent_up(); 
- 
-    indent_down(); 
-    force_cpp_out << indent() << "}" << endl << endl; 
-  } 
- 
-  // Create a setter function for each field 
-  if (setters) { 
-    for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { 
-      if (is_reference((*m_iter))) { 
-        std::string type = type_name((*m_iter)->get_type()); 
-        out << endl << indent() << "void " << tstruct->get_name() << "::__set_" 
-            << (*m_iter)->get_name() << "(::apache::thrift::stdcxx::shared_ptr<" 
-            << type_name((*m_iter)->get_type(), false, false) << ">"; 
-        out << " val) {" << endl; 
-      } else { 
-        out << endl << indent() << "void " << tstruct->get_name() << "::__set_" 
-            << (*m_iter)->get_name() << "(" << type_name((*m_iter)->get_type(), false, true); 
-        out << " val) {" << endl; 
-      } 
-      indent_up(); 
-      out << indent() << "this->" << (*m_iter)->get_name() << " = val;" << endl; 
-      indent_down(); 
- 
-      // assume all fields are required except optional fields. 
-      // for optional fields change __isset.name to true 
-      bool is_optional = (*m_iter)->get_req() == t_field::T_OPTIONAL; 
-      if (is_optional) { 
-        out << indent() << indent() << "__isset." << (*m_iter)->get_name() << " = true;" << endl; 
-      } 
-      out << indent() << "}" << endl; 
-    } 
-  } 
-  if (is_user_struct) { 
-    generate_struct_ostream_operator(out, tstruct); 
-  } 
-  out << endl; 
-} 
- 
-/** 
- * Makes a helper function to gen a struct reader. 
- * 
- * @param out Stream to write to 
- * @param tstruct The struct 
- */ 
-void t_cpp_generator::generate_struct_reader(ostream& out, t_struct* tstruct, bool pointers) { 
-  if (gen_templates_) { 
-    out << indent() << "template <class Protocol_>" << endl << indent() << "uint32_t " 
-        << tstruct->get_name() << "::read(Protocol_* iprot) {" << endl; 
-  } else { 
-    indent(out) << "uint32_t " << tstruct->get_name() 
-                << "::read(::apache::thrift::protocol::TProtocol* iprot) {" << endl; 
-  } 
-  indent_up(); 
- 
-  const vector<t_field*>& fields = tstruct->get_members(); 
-  vector<t_field*>::const_iterator f_iter; 
- 
-  // Declare stack tmp variables 
-  out << endl 
-      << indent() << "::apache::thrift::protocol::TInputRecursionTracker tracker(*iprot);" << endl 
-      << indent() << "uint32_t xfer = 0;" << endl 
-      << indent() << "std::string fname;" << endl 
-      << indent() << "::apache::thrift::protocol::TType ftype;" << endl 
-      << indent() << "int16_t fid;" << endl 
-      << endl 
-      << indent() << "xfer += iprot->readStructBegin(fname);" << endl 
-      << endl 
-      << indent() << "using ::apache::thrift::protocol::TProtocolException;" << endl 
-      << endl; 
- 
-  // Required variables aren't in __isset, so we need tmp vars to check them. 
-  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { 
-    if ((*f_iter)->get_req() == t_field::T_REQUIRED) 
-      indent(out) << "bool isset_" << (*f_iter)->get_name() << " = false;" << endl; 
-  } 
-  out << endl; 
- 
-  // Loop over reading in fields 
-  indent(out) << "while (true)" << endl; 
-  scope_up(out); 
- 
-  // Read beginning field marker 
-  indent(out) << "xfer += iprot->readFieldBegin(fname, ftype, fid);" << endl; 
- 
-  // Check for field STOP marker 
-  out << indent() << "if (ftype == ::apache::thrift::protocol::T_STOP) {" << endl << indent() 
-      << "  break;" << endl << indent() << "}" << endl; 
- 
-  if (fields.empty()) { 
-    out << indent() << "xfer += iprot->skip(ftype);" << endl; 
-  } else { 
-    // Switch statement on the field we are reading 
-    indent(out) << "switch (fid)" << endl; 
- 
-    scope_up(out); 
- 
-    // Generate deserialization code for known cases 
-    for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { 
-      indent(out) << "case " << (*f_iter)->get_key() << ":" << endl; 
-      indent_up(); 
-      indent(out) << "if (ftype == " << type_to_enum((*f_iter)->get_type()) << ") {" << endl; 
-      indent_up(); 
- 
-      const char* isset_prefix = ((*f_iter)->get_req() != t_field::T_REQUIRED) ? "this->__isset." 
-                                                                               : "isset_"; 
- 
-#if 0 
-          // This code throws an exception if the same field is encountered twice. 
-          // We've decided to leave it out for performance reasons. 
-          // TODO(dreiss): Generate this code and "if" it out to make it easier 
-          // for people recompiling thrift to include it. 
-          out << 
-            indent() << "if (" << isset_prefix << (*f_iter)->get_name() << ")" << endl << 
-            indent() << "  throw TProtocolException(TProtocolException::INVALID_DATA);" << endl; 
-#endif 
- 
-      if (pointers && !(*f_iter)->get_type()->is_xception()) { 
-        generate_deserialize_field(out, *f_iter, "(*(this->", "))"); 
-      } else { 
-        generate_deserialize_field(out, *f_iter, "this->"); 
-      } 
-      out << indent() << isset_prefix << (*f_iter)->get_name() << " = true;" << endl; 
-      indent_down(); 
-      out << indent() << "} else {" << endl << indent() << "  xfer += iprot->skip(ftype);" << endl 
-          << 
-          // TODO(dreiss): Make this an option when thrift structs 
-          // have a common base class. 
-          // indent() << "  throw TProtocolException(TProtocolException::INVALID_DATA);" << endl << 
-          indent() << "}" << endl << indent() << "break;" << endl; 
-      indent_down(); 
-    } 
- 
-    // In the default case we skip the field 
-    out << indent() << "default:" << endl << indent() << "  xfer += iprot->skip(ftype);" << endl 
-        << indent() << "  break;" << endl; 
- 
-    scope_down(out); 
-  } //!fields.empty() 
-  // Read field end marker 
-  indent(out) << "xfer += iprot->readFieldEnd();" << endl; 
- 
-  scope_down(out); 
- 
-  out << endl << indent() << "xfer += iprot->readStructEnd();" << endl; 
- 
-  // Throw if any required fields are missing. 
-  // We do this after reading the struct end so that 
-  // there might possibly be a chance of continuing. 
-  out << endl; 
-  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { 
-    if ((*f_iter)->get_req() == t_field::T_REQUIRED) 
-      out << indent() << "if (!isset_" << (*f_iter)->get_name() << ')' << endl << indent() 
-          << "  throw TProtocolException(TProtocolException::INVALID_DATA);" << endl; 
-  } 
- 
-  indent(out) << "return xfer;" << endl; 
- 
-  indent_down(); 
-  indent(out) << "}" << endl << endl; 
-} 
- 
-/** 
- * Generates the write function. 
- * 
- * @param out Stream to write to 
- * @param tstruct The struct 
- */ 
-void t_cpp_generator::generate_struct_writer(ostream& out, t_struct* tstruct, bool pointers) { 
-  string name = tstruct->get_name(); 
-  const vector<t_field*>& fields = tstruct->get_sorted_members(); 
-  vector<t_field*>::const_iterator f_iter; 
- 
-  if (gen_templates_) { 
-    out << indent() << "template <class Protocol_>" << endl << indent() << "uint32_t " 
-        << tstruct->get_name() << "::write(Protocol_* oprot) const {" << endl; 
-  } else { 
-    indent(out) << "uint32_t " << tstruct->get_name() 
-                << "::write(::apache::thrift::protocol::TProtocol* oprot) const {" << endl; 
-  } 
-  indent_up(); 
- 
-  out << indent() << "uint32_t xfer = 0;" << endl; 
- 
-  indent(out) << "::apache::thrift::protocol::TOutputRecursionTracker tracker(*oprot);" << endl; 
-  indent(out) << "xfer += oprot->writeStructBegin(\"" << name << "\");" << endl; 
- 
-  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { 
-    bool check_if_set = (*f_iter)->get_req() == t_field::T_OPTIONAL 
-                        || (*f_iter)->get_type()->is_xception(); 
-    if (check_if_set) { 
-      out << endl << indent() << "if (this->__isset." << (*f_iter)->get_name() << ") {" << endl; 
-      indent_up(); 
-    } else { 
-      out << endl; 
-    } 
- 
-    // Write field header 
-    out << indent() << "xfer += oprot->writeFieldBegin(" 
-        << "\"" << (*f_iter)->get_name() << "\", " << type_to_enum((*f_iter)->get_type()) << ", " 
-        << (*f_iter)->get_key() << ");" << endl; 
-    // Write field contents 
-    if (pointers && !(*f_iter)->get_type()->is_xception()) { 
-      generate_serialize_field(out, *f_iter, "(*(this->", "))"); 
-    } else { 
-      generate_serialize_field(out, *f_iter, "this->"); 
-    } 
-    // Write field closer 
-    indent(out) << "xfer += oprot->writeFieldEnd();" << endl; 
-    if (check_if_set) { 
-      indent_down(); 
-      indent(out) << '}'; 
-    } 
-  } 
- 
-  out << endl; 
- 
-  // Write the struct map 
-  out << indent() << "xfer += oprot->writeFieldStop();" << endl << indent() 
-      << "xfer += oprot->writeStructEnd();" << endl << indent() 
-      << "return xfer;" << endl; 
- 
-  indent_down(); 
-  indent(out) << "}" << endl << endl; 
-} 
- 
-/** 
- * Struct writer for result of a function, which can have only one of its 
- * fields set and does a conditional if else look up into the __isset field 
- * of the struct. 
- * 
- * @param out Output stream 
- * @param tstruct The result struct 
- */ 
-void t_cpp_generator::generate_struct_result_writer(ostream& out, 
-                                                    t_struct* tstruct, 
-                                                    bool pointers) { 
-  string name = tstruct->get_name(); 
-  const vector<t_field*>& fields = tstruct->get_sorted_members(); 
-  vector<t_field*>::const_iterator f_iter; 
- 
-  if (gen_templates_) { 
-    out << indent() << "template <class Protocol_>" << endl << indent() << "uint32_t " 
-        << tstruct->get_name() << "::write(Protocol_* oprot) const {" << endl; 
-  } else { 
-    indent(out) << "uint32_t " << tstruct->get_name() 
-                << "::write(::apache::thrift::protocol::TProtocol* oprot) const {" << endl; 
-  } 
-  indent_up(); 
- 
-  out << endl << indent() << "uint32_t xfer = 0;" << endl << endl; 
- 
-  indent(out) << "xfer += oprot->writeStructBegin(\"" << name << "\");" << endl; 
- 
-  bool first = true; 
-  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { 
-    if (first) { 
-      first = false; 
-      out << endl << indent() << "if "; 
-    } else { 
-      out << " else if "; 
-    } 
- 
-    out << "(this->__isset." << (*f_iter)->get_name() << ") {" << endl; 
- 
-    indent_up(); 
- 
-    // Write field header 
-    out << indent() << "xfer += oprot->writeFieldBegin(" 
-        << "\"" << (*f_iter)->get_name() << "\", " << type_to_enum((*f_iter)->get_type()) << ", " 
-        << (*f_iter)->get_key() << ");" << endl; 
-    // Write field contents 
-    if (pointers) { 
-      generate_serialize_field(out, *f_iter, "(*(this->", "))"); 
-    } else { 
-      generate_serialize_field(out, *f_iter, "this->"); 
-    } 
-    // Write field closer 
-    indent(out) << "xfer += oprot->writeFieldEnd();" << endl; 
- 
-    indent_down(); 
-    indent(out) << "}"; 
-  } 
- 
-  // Write the struct map 
-  out << endl << indent() << "xfer += oprot->writeFieldStop();" << endl << indent() 
-      << "xfer += oprot->writeStructEnd();" << endl << indent() << "return xfer;" << endl; 
- 
-  indent_down(); 
-  indent(out) << "}" << endl << endl; 
-} 
- 
-/** 
- * Generates the swap function. 
- * 
- * @param out Stream to write to 
- * @param tstruct The struct 
- */ 
-void t_cpp_generator::generate_struct_swap(ostream& out, t_struct* tstruct) { 
-  out << indent() << "void swap(" << tstruct->get_name() << " &a, " << tstruct->get_name() 
-      << " &b) {" << endl; 
-  indent_up(); 
- 
-  // Let argument-dependent name lookup find the correct swap() function to 
-  // use based on the argument types.  If none is found in the arguments' 
-  // namespaces, fall back to ::std::swap(). 
-  out << indent() << "using ::std::swap;" << endl; 
- 
-  bool has_nonrequired_fields = false; 
-  const vector<t_field*>& fields = tstruct->get_members(); 
-  for (vector<t_field*>::const_iterator f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { 
-    t_field* tfield = *f_iter; 
- 
-    if (tfield->get_req() != t_field::T_REQUIRED) { 
-      has_nonrequired_fields = true; 
-    } 
- 
-    out << indent() << "swap(a." << tfield->get_name() << ", b." << tfield->get_name() << ");" 
-        << endl; 
-  } 
- 
-  if (has_nonrequired_fields) { 
-    out << indent() << "swap(a.__isset, b.__isset);" << endl; 
-  } 
- 
-  // handle empty structs 
-  if (fields.size() == 0) { 
-    out << indent() << "(void) a;" << endl; 
-    out << indent() << "(void) b;" << endl; 
-  } 
- 
-  scope_down(out); 
-  out << endl; 
-} 
- 
-void t_cpp_generator::generate_struct_ostream_operator_decl(std::ostream& out, t_struct* tstruct) { 
-  out << "std::ostream& operator<<(std::ostream& out, const " 
-      << tstruct->get_name() 
-      << "& obj);" << endl; 
-  out << endl; 
-} 
- 
-void t_cpp_generator::generate_struct_ostream_operator(std::ostream& out, t_struct* tstruct) { 
-  if (!has_custom_ostream(tstruct)) { 
-    // thrift defines this behavior 
-    out << "std::ostream& operator<<(std::ostream& out, const " 
-        << tstruct->get_name() 
-        << "& obj)" << endl; 
-    scope_up(out); 
-    out << indent() << "obj.printTo(out);" << endl 
-        << indent() << "return out;" << endl; 
-    scope_down(out); 
-    out << endl; 
-  } 
-} 
- 
-void t_cpp_generator::generate_struct_print_method_decl(std::ostream& out, t_struct* tstruct) { 
-  out << "void "; 
-  if (tstruct) { 
-    out << tstruct->get_name() << "::"; 
-  } 
-  out << "printTo(std::ostream& out) const"; 
-} 
- 
-void t_cpp_generator::generate_exception_what_method_decl(std::ostream& out, 
-                                                          t_struct* tstruct, 
-                                                          bool external) { 
-  out << "const char* "; 
-  if (external) { 
-    out << tstruct->get_name() << "::"; 
-  } 
-  out << "what() const throw()"; 
-} 
- 
-namespace struct_ostream_operator_generator { 
-void generate_required_field_value(std::ostream& out, const t_field* field) { 
-  out << " << to_string(" << field->get_name() << ")"; 
-} 
- 
-void generate_optional_field_value(std::ostream& out, const t_field* field) { 
-  out << "; (__isset." << field->get_name() << " ? (out"; 
-  generate_required_field_value(out, field); 
-  out << ") : (out << \"<null>\"))"; 
-} 
- 
-void generate_field_value(std::ostream& out, const t_field* field) { 
-  if (field->get_req() == t_field::T_OPTIONAL) 
-    generate_optional_field_value(out, field); 
-  else 
-    generate_required_field_value(out, field); 
-} 
- 
-void generate_field_name(std::ostream& out, const t_field* field) { 
-  out << "\"" << field->get_name() << "=\""; 
-} 
- 
-void generate_field(std::ostream& out, const t_field* field) { 
-  generate_field_name(out, field); 
-  generate_field_value(out, field); 
-} 
- 
-void generate_fields(std::ostream& out, 
-                     const vector<t_field*>& fields, 
-                     const std::string& indent) { 
-  const vector<t_field*>::const_iterator beg = fields.begin(); 
-  const vector<t_field*>::const_iterator end = fields.end(); 
- 
-  for (vector<t_field*>::const_iterator it = beg; it != end; ++it) { 
-    out << indent << "out << "; 
- 
-    if (it != beg) { 
-      out << "\", \" << "; 
-    } 
- 
-    generate_field(out, *it); 
-    out << ";" << endl; 
-  } 
-} 
-} 
- 
-/** 
- * Generates operator<< 
- */ 
-void t_cpp_generator::generate_struct_print_method(std::ostream& out, t_struct* tstruct) { 
-  out << indent(); 
-  generate_struct_print_method_decl(out, tstruct); 
-  out << " {" << endl; 
- 
-  indent_up(); 
- 
-  out << indent() << "using ::apache::thrift::to_string;" << endl; 
-  out << indent() << "out << \"" << tstruct->get_name() << "(\";" << endl; 
-  struct_ostream_operator_generator::generate_fields(out, tstruct->get_members(), indent()); 
-  out << indent() << "out << \")\";" << endl; 
- 
-  indent_down(); 
-  out << "}" << endl << endl; 
-} 
- 
-/** 
- * Generates what() method for exceptions 
- */ 
-void t_cpp_generator::generate_exception_what_method(std::ostream& out, t_struct* tstruct) { 
-  out << indent(); 
-  generate_exception_what_method_decl(out, tstruct, true); 
-  out << " {" << endl; 
- 
-  indent_up(); 
-  out << indent() << "try {" << endl; 
- 
-  indent_up(); 
-  out << indent() << "std::stringstream ss;" << endl; 
-  out << indent() << "ss << \"TException - service has thrown: \" << *this;" << endl; 
-  out << indent() << "this->thriftTExceptionMessageHolder_ = ss.str();" << endl; 
-  out << indent() << "return this->thriftTExceptionMessageHolder_.c_str();" << endl; 
-  indent_down(); 
- 
-  out << indent() << "} catch (const std::exception&) {" << endl; 
- 
-  indent_up(); 
-  out << indent() << "return \"TException - service has thrown: " << tstruct->get_name() << "\";" 
-      << endl; 
-  indent_down(); 
- 
-  out << indent() << "}" << endl; 
- 
-  indent_down(); 
-  out << "}" << endl << endl; 
-} 
- 
-/** 
- * Generates a thrift service. In C++, this comprises an entirely separate 
- * header and source file. The header file defines the methods and includes 
- * the data types defined in the main header file, and the implementation 
- * file contains implementations of the basic printer and default interfaces. 
- * 
- * @param tservice The service definition 
- */ 
-void t_cpp_generator::generate_service(t_service* tservice) { 
-  string svcname = tservice->get_name(); 
- 
-  // Make output files 
-  string f_header_name = get_out_dir() + svcname + ".h"; 
-  f_header_.open(f_header_name.c_str()); 
- 
-  // Print header file includes 
-  f_header_ << autogen_comment(); 
-  f_header_ << "#ifndef " << svcname << "_H" << endl << "#define " << svcname << "_H" << endl 
-            << endl; 
-  if (gen_cob_style_) { 
-    f_header_ << "#include <thrift/transport/TBufferTransports.h>" << endl << // TMemoryBuffer 
-        "#include <thrift/stdcxx.h>" << endl 
-              << "namespace apache { namespace thrift { namespace async {" << endl 
-              << "class TAsyncChannel;" << endl << "}}}" << endl; 
-  } 
-  f_header_ << "#include <thrift/TDispatchProcessor.h>" << endl; 
-  if (gen_cob_style_) { 
-    f_header_ << "#include <thrift/async/TAsyncDispatchProcessor.h>" << endl; 
-  } 
-  f_header_ << "#include <thrift/async/TConcurrentClientSyncInfo.h>" << endl; 
-  f_header_ << "#include \"" << get_include_prefix(*get_program()) << program_name_ << "_types.h\"" 
-            << endl; 
- 
-  t_service* extends_service = tservice->get_extends(); 
-  if (extends_service != NULL) { 
-    f_header_ << "#include \"" << get_include_prefix(*(extends_service->get_program())) 
-              << extends_service->get_name() << ".h\"" << endl; 
-  } 
- 
-  f_header_ << endl << ns_open_ << endl << endl; 
- 
-  f_header_ << "#ifdef _MSC_VER\n" 
-               "  #pragma warning( push )\n" 
-               "  #pragma warning (disable : 4250 ) //inheriting methods via dominance \n" 
-               "#endif\n\n"; 
- 
-  // Service implementation file includes 
-  string f_service_name = get_out_dir() + svcname + ".cpp"; 
-  f_service_.open(f_service_name.c_str()); 
-  f_service_ << autogen_comment(); 
-  f_service_ << "#include \"" << get_include_prefix(*get_program()) << svcname << ".h\"" << endl; 
-  if (gen_cob_style_) { 
-    f_service_ << "#include \"thrift/async/TAsyncChannel.h\"" << endl; 
-  } 
-  if (gen_templates_) { 
-    f_service_ << "#include \"" << get_include_prefix(*get_program()) << svcname << ".tcc\"" 
-               << endl; 
- 
-    string f_service_tcc_name = get_out_dir() + svcname + ".tcc"; 
-    f_service_tcc_.open(f_service_tcc_name.c_str()); 
-    f_service_tcc_ << autogen_comment(); 
-    f_service_tcc_ << "#include \"" << get_include_prefix(*get_program()) << svcname << ".h\"" 
-                   << endl; 
- 
-    f_service_tcc_ << "#ifndef " << svcname << "_TCC" << endl << "#define " << svcname << "_TCC" 
-                   << endl << endl; 
- 
-    if (gen_cob_style_) { 
-      f_service_tcc_ << "#include \"thrift/async/TAsyncChannel.h\"" << endl; 
-    } 
-  } 
- 
-  f_service_ << endl << ns_open_ << endl << endl; 
-  f_service_tcc_ << endl << ns_open_ << endl << endl; 
- 
-  // Generate all the components 
-  generate_service_interface(tservice, ""); 
-  generate_service_interface_factory(tservice, ""); 
-  generate_service_null(tservice, ""); 
-  generate_service_helpers(tservice); 
-  generate_service_client(tservice, ""); 
-  generate_service_processor(tservice, ""); 
-  generate_service_multiface(tservice); 
-  generate_service_client(tservice, "Concurrent"); 
- 
-  // Generate skeleton 
-  if (!gen_no_skeleton_) { 
-      generate_service_skeleton(tservice); 
-  } 
- 
-  // Generate all the cob components 
-  if (gen_cob_style_) { 
-    generate_service_interface(tservice, "CobCl"); 
-    generate_service_interface(tservice, "CobSv"); 
-    generate_service_interface_factory(tservice, "CobSv"); 
-    generate_service_null(tservice, "CobSv"); 
-    generate_service_client(tservice, "Cob"); 
-    generate_service_processor(tservice, "Cob"); 
- 
-    if (!gen_no_skeleton_) { 
-      generate_service_async_skeleton(tservice); 
-    } 
- 
-  } 
- 
-  f_header_ << "#ifdef _MSC_VER\n" 
-               "  #pragma warning( pop )\n" 
-               "#endif\n\n"; 
- 
-  // Close the namespace 
-  f_service_ << ns_close_ << endl << endl; 
-  f_service_tcc_ << ns_close_ << endl << endl; 
-  f_header_ << ns_close_ << endl << endl; 
- 
-  // TODO(simpkins): Make this a separate option 
-  if (gen_templates_) { 
-    f_header_ << "#include \"" << get_include_prefix(*get_program()) << svcname << ".tcc\"" << endl 
-              << "#include \"" << get_include_prefix(*get_program()) << program_name_ 
-              << "_types.tcc\"" << endl << endl; 
-  } 
- 
-  f_header_ << "#endif" << endl; 
-  f_service_tcc_ << "#endif" << endl; 
- 
-  // Close the files 
-  f_service_tcc_.close(); 
-  f_service_.close(); 
-  f_header_.close(); 
-} 
- 
-/** 
- * Generates helper functions for a service. Basically, this generates types 
- * for all the arguments and results to functions. 
- * 
- * @param tservice The service to generate a header definition for 
- */ 
-void t_cpp_generator::generate_service_helpers(t_service* tservice) { 
-  vector<t_function*> functions = tservice->get_functions(); 
-  vector<t_function*>::iterator f_iter; 
-  std::ostream& out = (gen_templates_ ? f_service_tcc_ : f_service_); 
- 
-  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) { 
-    t_struct* ts = (*f_iter)->get_arglist(); 
-    string name_orig = ts->get_name(); 
- 
-    // TODO(dreiss): Why is this stuff not in generate_function_helpers? 
-    ts->set_name(tservice->get_name() + "_" + (*f_iter)->get_name() + "_args"); 
-    generate_struct_declaration(f_header_, ts, false); 
-    generate_struct_definition(out, f_service_, ts, false); 
-    generate_struct_reader(out, ts); 
-    generate_struct_writer(out, ts); 
-    ts->set_name(tservice->get_name() + "_" + (*f_iter)->get_name() + "_pargs"); 
-    generate_struct_declaration(f_header_, ts, false, true, false, true); 
-    generate_struct_definition(out, f_service_, ts, false); 
-    generate_struct_writer(out, ts, true); 
-    ts->set_name(name_orig); 
- 
-    generate_function_helpers(tservice, *f_iter); 
-  } 
-} 
- 
-/** 
- * Generates a service interface definition. 
- * 
- * @param tservice The service to generate a header definition for 
- */ 
-void t_cpp_generator::generate_service_interface(t_service* tservice, string style) { 
- 
-  string service_if_name = service_name_ + style + "If"; 
-  if (style == "CobCl") { 
-    // Forward declare the client. 
-    string client_name = service_name_ + "CobClient"; 
-    if (gen_templates_) { 
-      client_name += "T"; 
-      service_if_name += "T"; 
-      indent(f_header_) << "template <class Protocol_>" << endl; 
-    } 
-    indent(f_header_) << "class " << client_name << ";" << endl << endl; 
-  } 
- 
-  string extends = ""; 
-  if (tservice->get_extends() != NULL) { 
-    extends = " : virtual public " + type_name(tservice->get_extends()) + style + "If"; 
-    if (style == "CobCl" && gen_templates_) { 
-      // TODO(simpkins): If gen_templates_ is enabled, we currently assume all 
-      // parent services were also generated with templates enabled. 
-      extends += "T<Protocol_>"; 
-    } 
-  } 
- 
-  if (style == "CobCl" && gen_templates_) { 
-    f_header_ << "template <class Protocol_>" << endl; 
-  } 
-  f_header_ << "class " << service_if_name << extends << " {" << endl << " public:" << endl; 
-  indent_up(); 
-  f_header_ << indent() << "virtual ~" << service_if_name << "() {}" << endl; 
- 
-  vector<t_function*> functions = tservice->get_functions(); 
-  vector<t_function*>::iterator f_iter; 
-  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) { 
-    if ((*f_iter)->has_doc()) 
-      f_header_ << endl; 
-    generate_java_doc(f_header_, *f_iter); 
-    f_header_ << indent() << "virtual " << function_signature(*f_iter, style) << " = 0;" << endl; 
-  } 
-  indent_down(); 
-  f_header_ << "};" << endl << endl; 
- 
-  if (style == "CobCl" && gen_templates_) { 
-    // generate a backwards-compatible typedef for clients that do not 
-    // know about the new template-style code 
-    f_header_ << "typedef " << service_if_name << "< ::apache::thrift::protocol::TProtocol> " 
-              << service_name_ << style << "If;" << endl << endl; 
-  } 
-} 
- 
-/** 
- * Generates a service interface factory. 
- * 
- * @param tservice The service to generate an interface factory for. 
- */ 
-void t_cpp_generator::generate_service_interface_factory(t_service* tservice, string style) { 
-  string service_if_name = service_name_ + style + "If"; 
- 
-  // Figure out the name of the upper-most parent class. 
-  // Getting everything to work out properly with inheritance is annoying. 
-  // Here's what we're doing for now: 
-  // 
-  // - All handlers implement getHandler(), but subclasses use covariant return 
-  //   types to return their specific service interface class type.  We have to 
-  //   use raw pointers because of this; shared_ptr<> can't be used for 
-  //   covariant return types. 
-  // 
-  // - Since we're not using shared_ptr<>, we also provide a releaseHandler() 
-  //   function that must be called to release a pointer to a handler obtained 
-  //   via getHandler(). 
-  // 
-  //   releaseHandler() always accepts a pointer to the upper-most parent class 
-  //   type.  This is necessary since the parent versions of releaseHandler() 
-  //   may accept any of the parent types, not just the most specific subclass 
-  //   type.  Implementations can use dynamic_cast to cast the pointer to the 
-  //   subclass type if desired. 
-  t_service* base_service = tservice; 
-  while (base_service->get_extends() != NULL) { 
-    base_service = base_service->get_extends(); 
-  } 
-  string base_if_name = type_name(base_service) + style + "If"; 
- 
-  // Generate the abstract factory class 
-  string factory_name = service_if_name + "Factory"; 
-  string extends; 
-  if (tservice->get_extends() != NULL) { 
-    extends = " : virtual public " + type_name(tservice->get_extends()) + style + "IfFactory"; 
-  } 
- 
-  f_header_ << "class " << factory_name << extends << " {" << endl << " public:" << endl; 
-  indent_up(); 
-  f_header_ << indent() << "typedef " << service_if_name << " Handler;" << endl << endl << indent() 
-            << "virtual ~" << factory_name << "() {}" << endl << endl << indent() << "virtual " 
-            << service_if_name << "* getHandler(" 
-            << "const ::apache::thrift::TConnectionInfo& connInfo) = 0;" << endl << indent() 
-            << "virtual void releaseHandler(" << base_if_name << "* /* handler */) = 0;" << endl; 
- 
-  indent_down(); 
-  f_header_ << "};" << endl << endl; 
- 
-  // Generate the singleton factory class 
-  string singleton_factory_name = service_if_name + "SingletonFactory"; 
-  f_header_ << "class " << singleton_factory_name << " : virtual public " << factory_name << " {" 
-            << endl << " public:" << endl; 
-  indent_up(); 
-  f_header_ << indent() << singleton_factory_name << "(const ::apache::thrift::stdcxx::shared_ptr<" << service_if_name 
-            << ">& iface) : iface_(iface) {}" << endl << indent() << "virtual ~" 
-            << singleton_factory_name << "() {}" << endl << endl << indent() << "virtual " 
-            << service_if_name << "* getHandler(" 
-            << "const ::apache::thrift::TConnectionInfo&) {" << endl << indent() 
-            << "  return iface_.get();" << endl << indent() << "}" << endl << indent() 
-            << "virtual void releaseHandler(" << base_if_name << "* /* handler */) {}" << endl; 
- 
-  f_header_ << endl << " protected:" << endl << indent() << "::apache::thrift::stdcxx::shared_ptr<" << service_if_name 
-            << "> iface_;" << endl; 
- 
-  indent_down(); 
-  f_header_ << "};" << endl << endl; 
-} 
- 
-/** 
- * Generates a null implementation of the service. 
- * 
- * @param tservice The service to generate a header definition for 
- */ 
-void t_cpp_generator::generate_service_null(t_service* tservice, string style) { 
-  string extends = ""; 
-  if (tservice->get_extends() != NULL) { 
-    extends = " , virtual public " + type_name(tservice->get_extends()) + style + "Null"; 
-  } 
-  f_header_ << "class " << service_name_ << style << "Null : virtual public " << service_name_ 
-            << style << "If" << extends << " {" << endl << " public:" << endl; 
-  indent_up(); 
-  f_header_ << indent() << "virtual ~" << service_name_ << style << "Null() {}" << endl; 
-  vector<t_function*> functions = tservice->get_functions(); 
-  vector<t_function*>::iterator f_iter; 
-  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) { 
-    f_header_ << indent() << function_signature(*f_iter, style, "", false) << " {" << endl; 
-    indent_up(); 
- 
-    t_type* returntype = (*f_iter)->get_returntype(); 
-    t_field returnfield(returntype, "_return"); 
- 
-    if (style == "") { 
-      if (returntype->is_void() || is_complex_type(returntype)) { 
-        f_header_ << indent() << "return;" << endl; 
-      } else { 
-        f_header_ << indent() << declare_field(&returnfield, true) << endl << indent() 
-                  << "return _return;" << endl; 
-      } 
-    } else if (style == "CobSv") { 
-      if (returntype->is_void()) { 
-        f_header_ << indent() << "return cob();" << endl; 
-      } else { 
-        t_field returnfield(returntype, "_return"); 
-        f_header_ << indent() << declare_field(&returnfield, true) << endl << indent() 
-                  << "return cob(_return);" << endl; 
-      } 
- 
-    } else { 
-      throw "UNKNOWN STYLE"; 
-    } 
- 
-    indent_down(); 
-    f_header_ << indent() << "}" << endl; 
-  } 
-  indent_down(); 
-  f_header_ << "};" << endl << endl; 
-} 
- 
-void t_cpp_generator::generate_function_call(ostream& out, 
-                                             t_function* tfunction, 
-                                             string target, 
-                                             string iface, 
-                                             string arg_prefix) { 
-  bool first = true; 
-  t_type* ret_type = get_true_type(tfunction->get_returntype()); 
-  out << indent(); 
-  if (!tfunction->is_oneway() && !ret_type->is_void()) { 
-    if (is_complex_type(ret_type)) { 
-      first = false; 
-      out << iface << "->" << tfunction->get_name() << "(" << target; 
-    } else { 
-      out << target << " = " << iface << "->" << tfunction->get_name() << "("; 
-    } 
-  } else { 
-    out << iface << "->" << tfunction->get_name() << "("; 
-  } 
-  const std::vector<t_field*>& fields = tfunction->get_arglist()->get_members(); 
-  vector<t_field*>::const_iterator f_iter; 
-  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { 
-    if (first) { 
-      first = false; 
-    } else { 
-      out << ", "; 
-    } 
-    out << arg_prefix << (*f_iter)->get_name(); 
-  } 
-  out << ");" << endl; 
-} 
- 
-void t_cpp_generator::generate_service_async_skeleton(t_service* tservice) { 
-  string svcname = tservice->get_name(); 
- 
-  // Service implementation file includes 
-  string f_skeleton_name = get_out_dir() + svcname + "_async_server.skeleton.cpp"; 
- 
-  string ns = namespace_prefix(tservice->get_program()->get_namespace("cpp")); 
- 
-  ofstream_with_content_based_conditional_update f_skeleton; 
-  f_skeleton.open(f_skeleton_name.c_str()); 
-  f_skeleton << "// This autogenerated skeleton file illustrates one way to adapt a synchronous" 
-             << endl << "// interface into an asynchronous interface. You should copy it to another" 
-             << endl 
-             << "// filename to avoid overwriting it and rewrite as asynchronous any functions" 
-             << endl << "// that would otherwise introduce unwanted latency." << endl << endl 
-             << "#include \"" << get_include_prefix(*get_program()) << svcname << ".h\"" << endl 
-             << "#include <thrift/protocol/TBinaryProtocol.h>" << endl << endl 
-             << "using namespace ::apache::thrift;" << endl 
-             << "using namespace ::apache::thrift::protocol;" << endl 
-             << "using namespace ::apache::thrift::transport;" << endl 
-             << "using namespace ::apache::thrift::async;" << endl << endl; 
- 
-  // the following code would not compile: 
-  // using namespace ; 
-  // using namespace ::; 
-  if ((!ns.empty()) && (ns.compare(" ::") != 0)) { 
-    f_skeleton << "using namespace " << string(ns, 0, ns.size() - 2) << ";" << endl << endl; 
-  } 
- 
-  f_skeleton << "class " << svcname << "AsyncHandler : " 
-             << "public " << svcname << "CobSvIf {" << endl << " public:" << endl; 
-  indent_up(); 
-  f_skeleton << indent() << svcname << "AsyncHandler() {" << endl << indent() 
-             << "  syncHandler_ = std::auto_ptr<" << svcname << "Handler>(new " << svcname 
-             << "Handler);" << endl << indent() << "  // Your initialization goes here" << endl 
-             << indent() << "}" << endl; 
-  f_skeleton << indent() << "virtual ~" << service_name_ << "AsyncHandler();" << endl; 
- 
-  vector<t_function*> functions = tservice->get_functions(); 
-  vector<t_function*>::iterator f_iter; 
-  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) { 
-    f_skeleton << endl << indent() << function_signature(*f_iter, "CobSv", "", true) << " {" 
-               << endl; 
-    indent_up(); 
- 
-    t_type* returntype = (*f_iter)->get_returntype(); 
-    t_field returnfield(returntype, "_return"); 
- 
-    string target = returntype->is_void() ? "" : "_return"; 
-    if (!returntype->is_void()) { 
-      f_skeleton << indent() << declare_field(&returnfield, true) << endl; 
-    } 
-    generate_function_call(f_skeleton, *f_iter, target, "syncHandler_", ""); 
-    f_skeleton << indent() << "return cob(" << target << ");" << endl; 
- 
-    scope_down(f_skeleton); 
-  } 
-  f_skeleton << endl << " protected:" << endl << indent() << "std::auto_ptr<" << svcname 
-             << "Handler> syncHandler_;" << endl; 
-  indent_down(); 
-  f_skeleton << "};" << endl << endl; 
-} 
- 
-/** 
- * Generates a multiface, which is a single server that just takes a set 
- * of objects implementing the interface and calls them all, returning the 
- * value of the last one to be called. 
- * 
- * @param tservice The service to generate a multiserver for. 
- */ 
-void t_cpp_generator::generate_service_multiface(t_service* tservice) { 
-  // Generate the dispatch methods 
-  vector<t_function*> functions = tservice->get_functions(); 
-  vector<t_function*>::iterator f_iter; 
- 
-  string extends = ""; 
-  string extends_multiface = ""; 
-  if (tservice->get_extends() != NULL) { 
-    extends = type_name(tservice->get_extends()); 
-    extends_multiface = ", public " + extends + "Multiface"; 
-  } 
- 
-  string list_type = string("std::vector<apache::thrift::stdcxx::shared_ptr<") + service_name_ + "If> >"; 
- 
-  // Generate the header portion 
-  f_header_ << "class " << service_name_ << "Multiface : " 
-            << "virtual public " << service_name_ << "If" << extends_multiface << " {" << endl 
-            << " public:" << endl; 
-  indent_up(); 
-  f_header_ << indent() << service_name_ << "Multiface(" << list_type 
-            << "& ifaces) : ifaces_(ifaces) {" << endl; 
-  if (!extends.empty()) { 
-    f_header_ << indent() 
-              << "  std::vector<apache::thrift::stdcxx::shared_ptr<" + service_name_ + "If> >::iterator iter;" 
-              << endl << indent() << "  for (iter = ifaces.begin(); iter != ifaces.end(); ++iter) {" 
-              << endl << indent() << "    " << extends << "Multiface::add(*iter);" << endl 
-              << indent() << "  }" << endl; 
-  } 
-  f_header_ << indent() << "}" << endl << indent() << "virtual ~" << service_name_ 
-            << "Multiface() {}" << endl; 
-  indent_down(); 
- 
-  // Protected data members 
-  f_header_ << " protected:" << endl; 
-  indent_up(); 
-  f_header_ << indent() << list_type << " ifaces_;" << endl << indent() << service_name_ 
-            << "Multiface() {}" << endl << indent() << "void add(::apache::thrift::stdcxx::shared_ptr<" 
-            << service_name_ << "If> iface) {" << endl; 
-  if (!extends.empty()) { 
-    f_header_ << indent() << "  " << extends << "Multiface::add(iface);" << endl; 
-  } 
-  f_header_ << indent() << "  ifaces_.push_back(iface);" << endl << indent() << "}" << endl; 
-  indent_down(); 
- 
-  f_header_ << indent() << " public:" << endl; 
-  indent_up(); 
- 
-  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) { 
-    t_struct* arglist = (*f_iter)->get_arglist(); 
-    const vector<t_field*>& args = arglist->get_members(); 
-    vector<t_field*>::const_iterator a_iter; 
- 
-    string call = string("ifaces_[i]->") + (*f_iter)->get_name() + "("; 
-    bool first = true; 
-    if (is_complex_type((*f_iter)->get_returntype())) { 
-      call += "_return"; 
-      first = false; 
-    } 
-    for (a_iter = args.begin(); a_iter != args.end(); ++a_iter) { 
-      if (first) { 
-        first = false; 
-      } else { 
-        call += ", "; 
-      } 
-      call += (*a_iter)->get_name(); 
-    } 
-    call += ")"; 
- 
-    f_header_ << indent() << function_signature(*f_iter, "") << " {" << endl; 
-    indent_up(); 
-    f_header_ << indent() << "size_t sz = ifaces_.size();" << endl << indent() << "size_t i = 0;" 
-              << endl << indent() << "for (; i < (sz - 1); ++i) {" << endl; 
-    indent_up(); 
-    f_header_ << indent() << call << ";" << endl; 
-    indent_down(); 
-    f_header_ << indent() << "}" << endl; 
- 
-    if (!(*f_iter)->get_returntype()->is_void()) { 
-      if (is_complex_type((*f_iter)->get_returntype())) { 
-        f_header_ << indent() << call << ";" << endl << indent() << "return;" << endl; 
-      } else { 
-        f_header_ << indent() << "return " << call << ";" << endl; 
-      } 
-    } else { 
-      f_header_ << indent() << call << ";" << endl; 
-    } 
- 
-    indent_down(); 
-    f_header_ << indent() << "}" << endl << endl; 
-  } 
- 
-  indent_down(); 
-  f_header_ << indent() << "};" << endl << endl; 
-} 
- 
-/** 
- * Generates a service client definition. 
- * 
- * @param tservice The service to generate a server for. 
- */ 
-void t_cpp_generator::generate_service_client(t_service* tservice, string style) { 
-  string ifstyle; 
-  if (style == "Cob") { 
-    ifstyle = "CobCl"; 
-  } 
- 
-  std::ostream& out = (gen_templates_ ? f_service_tcc_ : f_service_); 
-  string template_header, template_suffix, short_suffix, protocol_type, _this; 
-  string const prot_factory_type = "::apache::thrift::protocol::TProtocolFactory"; 
-  if (gen_templates_) { 
-    template_header = "template <class Protocol_>\n"; 
-    short_suffix = "T"; 
-    template_suffix = "T<Protocol_>"; 
-    protocol_type = "Protocol_"; 
-    _this = "this->"; 
-  } else { 
-    protocol_type = "::apache::thrift::protocol::TProtocol"; 
-  } 
-  string prot_ptr = "apache::thrift::stdcxx::shared_ptr< " + protocol_type + ">"; 
-  string client_suffix = "Client" + template_suffix; 
-  string if_suffix = "If"; 
-  if (style == "Cob") { 
-    if_suffix += template_suffix; 
-  } 
- 
-  string extends = ""; 
-  string extends_client = ""; 
-  if (tservice->get_extends() != NULL) { 
-    // TODO(simpkins): If gen_templates_ is enabled, we currently assume all 
-    // parent services were also generated with templates enabled. 
-    extends = type_name(tservice->get_extends()); 
-    extends_client = ", public " + extends + style + client_suffix; 
-  } 
- 
-  // Generate the header portion 
-  if (style == "Concurrent") { 
-    f_header_ << "// The \'concurrent\' client is a thread safe client that correctly handles\n" 
-                 "// out of order responses.  It is slower than the regular client, so should\n" 
-                 "// only be used when you need to share a connection among multiple threads\n"; 
-  } 
-  f_header_ << template_header << "class " << service_name_ << style << "Client" << short_suffix 
-            << " : " 
-            << "virtual public " << service_name_ << ifstyle << if_suffix << extends_client << " {" 
-            << endl << " public:" << endl; 
- 
-  indent_up(); 
-  if (style != "Cob") { 
-    f_header_ << indent() << service_name_ << style << "Client" << short_suffix << "(" << prot_ptr 
-              << " prot) "; 
- 
-    if (extends.empty()) { 
-      f_header_ << "{" << endl; 
-      f_header_ << indent() << "  setProtocol" << short_suffix << "(prot);" << endl << indent() 
-                << "}" << endl; 
-    } else { 
-      f_header_ << ":" << endl; 
-      f_header_ << indent() << "  " << extends << style << client_suffix << "(prot, prot) {}" 
-                << endl; 
-    } 
- 
-    f_header_ << indent() << service_name_ << style << "Client" << short_suffix << "(" << prot_ptr 
-              << " iprot, " << prot_ptr << " oprot) "; 
-    if (extends.empty()) { 
-      f_header_ << "{" << endl; 
-      f_header_ << indent() << "  setProtocol" << short_suffix << "(iprot,oprot);" << endl 
-                << indent() << "}" << endl; 
-    } else { 
-      f_header_ << ":" << indent() << "  " << extends << style << client_suffix 
-                << "(iprot, oprot) {}" << endl; 
-    } 
- 
-    // create the setProtocol methods 
-    if (extends.empty()) { 
-      f_header_ << " private:" << endl; 
-      // 1: one parameter 
-      f_header_ << indent() << "void setProtocol" << short_suffix << "(" << prot_ptr << " prot) {" 
-                << endl; 
-      f_header_ << indent() << "setProtocol" << short_suffix << "(prot,prot);" << endl; 
-      f_header_ << indent() << "}" << endl; 
-      // 2: two parameter 
-      f_header_ << indent() << "void setProtocol" << short_suffix << "(" << prot_ptr << " iprot, " 
-                << prot_ptr << " oprot) {" << endl; 
- 
-      f_header_ << indent() << "  piprot_=iprot;" << endl << indent() << "  poprot_=oprot;" << endl 
-                << indent() << "  iprot_ = iprot.get();" << endl << indent() 
-                << "  oprot_ = oprot.get();" << endl; 
- 
-      f_header_ << indent() << "}" << endl; 
-      f_header_ << " public:" << endl; 
-    } 
- 
-    // Generate getters for the protocols. 
-    // Note that these are not currently templated for simplicity. 
-    // TODO(simpkins): should they be templated? 
-    f_header_ << indent() 
-              << "apache::thrift::stdcxx::shared_ptr< ::apache::thrift::protocol::TProtocol> getInputProtocol() {" 
-              << endl << indent() << "  return " << _this << "piprot_;" << endl << indent() << "}" 
-              << endl; 
- 
-    f_header_ << indent() 
-              << "apache::thrift::stdcxx::shared_ptr< ::apache::thrift::protocol::TProtocol> getOutputProtocol() {" 
-              << endl << indent() << "  return " << _this << "poprot_;" << endl << indent() << "}" 
-              << endl; 
- 
-  } else /* if (style == "Cob") */ { 
-    f_header_ << indent() << service_name_ << style << "Client" << short_suffix << "(" 
-              << "apache::thrift::stdcxx::shared_ptr< ::apache::thrift::async::TAsyncChannel> channel, " 
-              << "::apache::thrift::protocol::TProtocolFactory* protocolFactory) :" << endl; 
-    if (extends.empty()) { 
-      f_header_ << indent() << "  channel_(channel)," << endl << indent() 
-                << "  itrans_(new ::apache::thrift::transport::TMemoryBuffer())," << endl 
-                << indent() << "  otrans_(new ::apache::thrift::transport::TMemoryBuffer())," 
-                << endl; 
-      if (gen_templates_) { 
-        // TProtocolFactory classes return generic TProtocol pointers. 
-        // We have to dynamic cast to the Protocol_ type we are expecting. 
-        f_header_ << indent() << "  piprot_(::apache::thrift::stdcxx::dynamic_pointer_cast<Protocol_>(" 
-                  << "protocolFactory->getProtocol(itrans_)))," << endl << indent() 
-                  << "  poprot_(::apache::thrift::stdcxx::dynamic_pointer_cast<Protocol_>(" 
-                  << "protocolFactory->getProtocol(otrans_))) {" << endl; 
-        // Throw a TException if either dynamic cast failed. 
-        f_header_ << indent() << "  if (!piprot_ || !poprot_) {" << endl << indent() 
-                  << "    throw ::apache::thrift::TException(\"" 
-                  << "TProtocolFactory returned unexpected protocol type in " << service_name_ 
-                  << style << "Client" << short_suffix << " constructor\");" << endl << indent() 
-                  << "  }" << endl; 
-      } else { 
-        f_header_ << indent() << "  piprot_(protocolFactory->getProtocol(itrans_))," << endl 
-                  << indent() << "  poprot_(protocolFactory->getProtocol(otrans_)) {" << endl; 
-      } 
-      f_header_ << indent() << "  iprot_ = piprot_.get();" << endl << indent() 
-                << "  oprot_ = poprot_.get();" << endl << indent() << "}" << endl; 
-    } else { 
-      f_header_ << indent() << "  " << extends << style << client_suffix 
-                << "(channel, protocolFactory) {}" << endl; 
-    } 
-  } 
- 
-  if (style == "Cob") { 
-    f_header_ << indent() 
-              << "::apache::thrift::stdcxx::shared_ptr< ::apache::thrift::async::TAsyncChannel> getChannel() {" << endl 
-              << indent() << "  return " << _this << "channel_;" << endl << indent() << "}" << endl; 
-    if (!gen_no_client_completion_) { 
-      f_header_ << indent() << "virtual void completed__(bool /* success */) {}" << endl; 
-    } 
-  } 
- 
-  vector<t_function*> functions = tservice->get_functions(); 
-  vector<t_function*>::const_iterator f_iter; 
-  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) { 
-    indent(f_header_) << function_signature(*f_iter, ifstyle) << ";" << endl; 
-    // TODO(dreiss): Use private inheritance to avoid generating thise in cob-style. 
-    if (style == "Concurrent" && !(*f_iter)->is_oneway()) { 
-      // concurrent clients need to move the seqid from the send function to the 
-      // recv function.  Oneway methods don't have a recv function, so we don't need to 
-      // move the seqid for them.  Attempting to do so would result in a seqid leak. 
-      t_function send_function(g_type_i32, /*returning seqid*/ 
-                               string("send_") + (*f_iter)->get_name(), 
-                               (*f_iter)->get_arglist()); 
-      indent(f_header_) << function_signature(&send_function, "") << ";" << endl; 
-    } else { 
-      t_function send_function(g_type_void, 
-                               string("send_") + (*f_iter)->get_name(), 
-                               (*f_iter)->get_arglist()); 
-      indent(f_header_) << function_signature(&send_function, "") << ";" << endl; 
-    } 
-    if (!(*f_iter)->is_oneway()) { 
-      if (style == "Concurrent") { 
-        t_field seqIdArg(g_type_i32, "seqid"); 
-        t_struct seqIdArgStruct(program_); 
-        seqIdArgStruct.append(&seqIdArg); 
-        t_function recv_function((*f_iter)->get_returntype(), 
-                                 string("recv_") + (*f_iter)->get_name(), 
-                                 &seqIdArgStruct); 
-        indent(f_header_) << function_signature(&recv_function, "") << ";" << endl; 
-      } else { 
-        t_struct noargs(program_); 
-        t_function recv_function((*f_iter)->get_returntype(), 
-                                 string("recv_") + (*f_iter)->get_name(), 
-                                 &noargs); 
-        indent(f_header_) << function_signature(&recv_function, "") << ";" << endl; 
-      } 
-    } 
-  } 
-  indent_down(); 
- 
-  if (extends.empty()) { 
-    f_header_ << " protected:" << endl; 
-    indent_up(); 
- 
-    if (style == "Cob") { 
-      f_header_ << indent() 
-                << "::apache::thrift::stdcxx::shared_ptr< ::apache::thrift::async::TAsyncChannel> channel_;" << endl 
-                << indent() 
-                << "::apache::thrift::stdcxx::shared_ptr< ::apache::thrift::transport::TMemoryBuffer> itrans_;" << endl 
-                << indent() 
-                << "::apache::thrift::stdcxx::shared_ptr< ::apache::thrift::transport::TMemoryBuffer> otrans_;" 
-                << endl; 
-    } 
-    f_header_ << 
-      indent() << prot_ptr << " piprot_;" << endl << 
-      indent() << prot_ptr << " poprot_;" << endl << 
-      indent() << protocol_type << "* iprot_;" << endl << 
-      indent() << protocol_type << "* oprot_;" << endl; 
- 
-    if (style == "Concurrent") { 
-      f_header_ << 
-        indent() << "::apache::thrift::async::TConcurrentClientSyncInfo sync_;"<<endl; 
-    } 
-    indent_down(); 
-  } 
- 
-  f_header_ << "};" << endl << endl; 
- 
-  if (gen_templates_) { 
-    // Output a backwards compatibility typedef using 
-    // TProtocol as the template parameter. 
-    f_header_ << "typedef " << service_name_ << style 
-              << "ClientT< ::apache::thrift::protocol::TProtocol> " << service_name_ << style 
-              << "Client;" << endl << endl; 
-  } 
- 
-  string scope = service_name_ + style + client_suffix + "::"; 
- 
-  // Generate client method implementations 
-  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) { 
-    string seqIdCapture; 
-    string seqIdUse; 
-    string seqIdCommaUse; 
-    if (style == "Concurrent" && !(*f_iter)->is_oneway()) { 
-      seqIdCapture = "int32_t seqid = "; 
-      seqIdUse = "seqid"; 
-      seqIdCommaUse = ", seqid"; 
-    } 
- 
-    string funname = (*f_iter)->get_name(); 
- 
-    // Open function 
-    if (gen_templates_) { 
-      indent(out) << template_header; 
-    } 
-    indent(out) << function_signature(*f_iter, ifstyle, scope) << endl; 
-    scope_up(out); 
-    indent(out) << seqIdCapture << "send_" << funname << "("; 
- 
-    // Get the struct of function call params 
-    t_struct* arg_struct = (*f_iter)->get_arglist(); 
- 
-    // Declare the function arguments 
-    const vector<t_field*>& fields = arg_struct->get_members(); 
-    vector<t_field*>::const_iterator fld_iter; 
-    bool first = true; 
-    for (fld_iter = fields.begin(); fld_iter != fields.end(); ++fld_iter) { 
-      if (first) { 
-        first = false; 
-      } else { 
-        out << ", "; 
-      } 
-      out << (*fld_iter)->get_name(); 
-    } 
-    out << ");" << endl; 
- 
-    if (style != "Cob") { 
-      if (!(*f_iter)->is_oneway()) { 
-        out << indent(); 
-        if (!(*f_iter)->get_returntype()->is_void()) { 
-          if (is_complex_type((*f_iter)->get_returntype())) { 
-            out << "recv_" << funname << "(_return" << seqIdCommaUse << ");" << endl; 
-          } else { 
-            out << "return recv_" << funname << "(" << seqIdUse << ");" << endl; 
-          } 
-        } else { 
-          out << "recv_" << funname << "(" << seqIdUse << ");" << endl; 
-        } 
-      } 
-    } else { 
-      if (!(*f_iter)->is_oneway()) { 
-        out << indent() << _this << "channel_->sendAndRecvMessage(" 
-            << "::apache::thrift::stdcxx::bind(cob, this), " << _this << "otrans_.get(), " << _this << "itrans_.get());" 
-            << endl; 
-      } else { 
-        out << indent() << _this << "channel_->sendMessage(" 
-            << "::apache::thrift::stdcxx::bind(cob, this), " << _this << "otrans_.get());" << endl; 
-      } 
-    } 
-    scope_down(out); 
-    out << endl; 
- 
-    // if (style != "Cob") // TODO(dreiss): Libify the client and don't generate this for cob-style 
-    if (true) { 
-      t_type* send_func_return_type = g_type_void; 
-      if (style == "Concurrent" && !(*f_iter)->is_oneway()) { 
-        send_func_return_type = g_type_i32; 
-      } 
-      // Function for sending 
-      t_function send_function(send_func_return_type, 
-                               string("send_") + (*f_iter)->get_name(), 
-                               (*f_iter)->get_arglist()); 
- 
-      // Open the send function 
-      if (gen_templates_) { 
-        indent(out) << template_header; 
-      } 
-      indent(out) << function_signature(&send_function, "", scope) << endl; 
-      scope_up(out); 
- 
-      // Function arguments and results 
-      string argsname = tservice->get_name() + "_" + (*f_iter)->get_name() + "_pargs"; 
-      string resultname = tservice->get_name() + "_" + (*f_iter)->get_name() + "_presult"; 
- 
-      string cseqidVal = "0"; 
-      if (style == "Concurrent") { 
-        if (!(*f_iter)->is_oneway()) { 
-          cseqidVal = "this->sync_.generateSeqId()"; 
-        } 
-      } 
-      // Serialize the request 
-      out << 
-        indent() << "int32_t cseqid = " << cseqidVal << ";" << endl; 
-      if(style == "Concurrent") { 
-        out << 
-          indent() << "::apache::thrift::async::TConcurrentSendSentry sentry(&this->sync_);" << endl; 
-      } 
-      if (style == "Cob") { 
-        out << 
-          indent() << _this << "otrans_->resetBuffer();" << endl; 
-      } 
-      out << 
-        indent() << _this << "oprot_->writeMessageBegin(\"" << 
-        (*f_iter)->get_name() << 
-        "\", ::apache::thrift::protocol::" << ((*f_iter)->is_oneway() ? "T_ONEWAY" : "T_CALL") << 
-        ", cseqid);" << endl << endl << 
-        indent() << argsname << " args;" << endl; 
- 
-      for (fld_iter = fields.begin(); fld_iter != fields.end(); ++fld_iter) { 
-        out << indent() << "args." << (*fld_iter)->get_name() << " = &" << (*fld_iter)->get_name() 
-            << ";" << endl; 
-      } 
- 
-      out << indent() << "args.write(" << _this << "oprot_);" << endl << endl << indent() << _this 
-          << "oprot_->writeMessageEnd();" << endl << indent() << _this 
-          << "oprot_->getTransport()->writeEnd();" << endl << indent() << _this 
-          << "oprot_->getTransport()->flush();" << endl; 
- 
-      if (style == "Concurrent") { 
-        out << endl << indent() << "sentry.commit();" << endl; 
- 
-        if (!(*f_iter)->is_oneway()) { 
-          out << indent() << "return cseqid;" << endl; 
-        } 
-      } 
-      scope_down(out); 
-      out << endl; 
- 
-      // Generate recv function only if not an oneway function 
-      if (!(*f_iter)->is_oneway()) { 
-        t_struct noargs(program_); 
- 
-        t_field seqIdArg(g_type_i32, "seqid"); 
-        t_struct seqIdArgStruct(program_); 
-        seqIdArgStruct.append(&seqIdArg); 
- 
-        t_struct* recv_function_args = &noargs; 
-        if (style == "Concurrent") { 
-          recv_function_args = &seqIdArgStruct; 
-        } 
- 
-        t_function recv_function((*f_iter)->get_returntype(), 
-                                 string("recv_") + (*f_iter)->get_name(), 
-                                 recv_function_args); 
-        // Open the recv function 
-        if (gen_templates_) { 
-          indent(out) << template_header; 
-        } 
-        indent(out) << function_signature(&recv_function, "", scope) << endl; 
-        scope_up(out); 
- 
-        out << endl << 
-          indent() << "int32_t rseqid = 0;" << endl << 
-          indent() << "std::string fname;" << endl << 
-          indent() << "::apache::thrift::protocol::TMessageType mtype;" << endl; 
-        if(style == "Concurrent") { 
-          out << 
-            endl << 
-            indent() << "// the read mutex gets dropped and reacquired as part of waitForWork()" << endl << 
-            indent() << "// The destructor of this sentry wakes up other clients" << endl << 
-            indent() << "::apache::thrift::async::TConcurrentRecvSentry sentry(&this->sync_, seqid);" << endl; 
-        } 
-        if (style == "Cob" && !gen_no_client_completion_) { 
-          out << indent() << "bool completed = false;" << endl << endl << indent() << "try {"; 
-          indent_up(); 
-        } 
-        out << endl; 
-        if (style == "Concurrent") { 
-          out << 
-            indent() << "while(true) {" << endl << 
-            indent() << "  if(!this->sync_.getPending(fname, mtype, rseqid)) {" << endl; 
-          indent_up(); 
-          indent_up(); 
-        } 
-        out << 
-          indent() << _this << "iprot_->readMessageBegin(fname, mtype, rseqid);" << endl; 
-        if (style == "Concurrent") { 
-          scope_down(out); 
-          out << indent() << "if(seqid == rseqid) {" << endl; 
-          indent_up(); 
-        } 
-        out << 
-          indent() << "if (mtype == ::apache::thrift::protocol::T_EXCEPTION) {" << endl << 
-          indent() << "  ::apache::thrift::TApplicationException x;" << endl << 
-          indent() << "  x.read(" << _this << "iprot_);" << endl << 
-          indent() << "  " << _this << "iprot_->readMessageEnd();" << endl << 
-          indent() << "  " << _this << "iprot_->getTransport()->readEnd();" << endl; 
-        if (style == "Cob" && !gen_no_client_completion_) { 
-          out << indent() << "  completed = true;" << endl << indent() << "  completed__(true);" 
-              << endl; 
-        } 
-        if (style == "Concurrent") { 
-          out << indent() << "  sentry.commit();" << endl; 
-        } 
-        out << 
-          indent() << "  throw x;" << endl << 
-          indent() << "}" << endl << 
-          indent() << "if (mtype != ::apache::thrift::protocol::T_REPLY) {" << endl << 
-          indent() << "  " << _this << "iprot_->skip(" << "::apache::thrift::protocol::T_STRUCT);" << endl << 
-          indent() << "  " << _this << "iprot_->readMessageEnd();" << endl << 
-          indent() << "  " << _this << "iprot_->getTransport()->readEnd();" << endl; 
-        if (style == "Cob" && !gen_no_client_completion_) { 
-          out << indent() << "  completed = true;" << endl << indent() << "  completed__(false);" 
-              << endl; 
-        } 
-        out << 
-          indent() << "}" << endl << 
-          indent() << "if (fname.compare(\"" << (*f_iter)->get_name() << "\") != 0) {" << endl << 
-          indent() << "  " << _this << "iprot_->skip(" << "::apache::thrift::protocol::T_STRUCT);" << endl << 
-          indent() << "  " << _this << "iprot_->readMessageEnd();" << endl << 
-          indent() << "  " << _this << "iprot_->getTransport()->readEnd();" << endl; 
-        if (style == "Cob" && !gen_no_client_completion_) { 
-          out << indent() << "  completed = true;" << endl << indent() << "  completed__(false);" 
-              << endl; 
-        } 
-        if (style == "Concurrent") { 
-          out << endl << 
-            indent() << "  // in a bad state, don't commit" << endl << 
-            indent() << "  using ::apache::thrift::protocol::TProtocolException;" << endl << 
-            indent() << "  throw TProtocolException(TProtocolException::INVALID_DATA);" << endl; 
-        } 
-        out << indent() << "}" << endl; 
- 
-        if (!(*f_iter)->get_returntype()->is_void() 
-            && !is_complex_type((*f_iter)->get_returntype())) { 
-          t_field returnfield((*f_iter)->get_returntype(), "_return"); 
-          out << indent() << declare_field(&returnfield) << endl; 
-        } 
- 
-        out << indent() << resultname << " result;" << endl; 
- 
-        if (!(*f_iter)->get_returntype()->is_void()) { 
-          out << indent() << "result.success = &_return;" << endl; 
-        } 
- 
-        out << indent() << "result.read(" << _this << "iprot_);" << endl << indent() << _this 
-            << "iprot_->readMessageEnd();" << endl << indent() << _this 
-            << "iprot_->getTransport()->readEnd();" << endl << endl; 
- 
-        // Careful, only look for _result if not a void function 
-        if (!(*f_iter)->get_returntype()->is_void()) { 
-          if (is_complex_type((*f_iter)->get_returntype())) { 
-            out << 
-              indent() << "if (result.__isset.success) {" << endl; 
-            out << 
-              indent() << "  // _return pointer has now been filled" << endl; 
-            if (style == "Cob" && !gen_no_client_completion_) { 
-              out << indent() << "  completed = true;" << endl << indent() << "  completed__(true);" 
-                  << endl; 
-            } 
-            if (style == "Concurrent") { 
-              out << indent() << "  sentry.commit();" << endl; 
-            } 
-            out << 
-              indent() << "  return;" << endl << 
-              indent() << "}" << endl; 
-          } else { 
-            out << indent() << "if (result.__isset.success) {" << endl; 
-            if (style == "Cob" && !gen_no_client_completion_) { 
-              out << indent() << "  completed = true;" << endl << indent() << "  completed__(true);" 
-                  << endl; 
-            } 
-            if (style == "Concurrent") { 
-              out << indent() << "  sentry.commit();" << endl; 
-            } 
-            out << indent() << "  return _return;" << endl << indent() << "}" << endl; 
-          } 
-        } 
- 
-        t_struct* xs = (*f_iter)->get_xceptions(); 
-        const std::vector<t_field*>& xceptions = xs->get_members(); 
-        vector<t_field*>::const_iterator x_iter; 
-        for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) { 
-          out << indent() << "if (result.__isset." << (*x_iter)->get_name() << ") {" << endl; 
-          if (style == "Cob" && !gen_no_client_completion_) { 
-            out << indent() << "  completed = true;" << endl << indent() << "  completed__(true);" 
-                << endl; 
-          } 
-          if (style == "Concurrent") { 
-            out << indent() << "  sentry.commit();" << endl; 
-          } 
-          out << indent() << "  throw result." << (*x_iter)->get_name() << ";" << endl << indent() 
-              << "}" << endl; 
-        } 
- 
-        // We only get here if we are a void function 
-        if ((*f_iter)->get_returntype()->is_void()) { 
-          if (style == "Cob" && !gen_no_client_completion_) { 
-            out << indent() << "completed = true;" << endl << indent() << "completed__(true);" 
-                << endl; 
-          } 
-          if (style == "Concurrent") { 
-            out << indent() << "sentry.commit();" << endl; 
-          } 
-          indent(out) << "return;" << endl; 
-        } else { 
-          if (style == "Cob" && !gen_no_client_completion_) { 
-            out << indent() << "completed = true;" << endl << indent() << "completed__(true);" 
-                << endl; 
-          } 
-          if (style == "Concurrent") { 
-            out << indent() << "// in a bad state, don't commit" << endl; 
-          } 
-          out << indent() << "throw " 
-                             "::apache::thrift::TApplicationException(::apache::thrift::" 
-                             "TApplicationException::MISSING_RESULT, \"" << (*f_iter)->get_name() 
-              << " failed: unknown result\");" << endl; 
-        } 
-        if (style == "Concurrent") { 
-          indent_down(); 
-          indent_down(); 
-          out << 
-            indent() << "  }" << endl << 
-            indent() << "  // seqid != rseqid" << endl << 
-            indent() << "  this->sync_.updatePending(fname, mtype, rseqid);" << endl << 
-            endl << 
-            indent() << "  // this will temporarily unlock the readMutex, and let other clients get work done" << endl << 
-            indent() << "  this->sync_.waitForWork(seqid);" << endl << 
-            indent() << "} // end while(true)" << endl; 
-        } 
-        if (style == "Cob" && !gen_no_client_completion_) { 
-          indent_down(); 
-          out << indent() << "} catch (...) {" << endl << indent() << "  if (!completed) {" << endl 
-              << indent() << "    completed__(false);" << endl << indent() << "  }" << endl 
-              << indent() << "  throw;" << endl << indent() << "}" << endl; 
-        } 
-        // Close function 
-        scope_down(out); 
-        out << endl; 
-      } 
-    } 
-  } 
-} 
- 
-class ProcessorGenerator { 
-public: 
-  ProcessorGenerator(t_cpp_generator* generator, t_service* service, const string& style); 
- 
-  void run() { 
-    generate_class_definition(); 
- 
-    // Generate the dispatchCall() function 
-    generate_dispatch_call(false); 
-    if (generator_->gen_templates_) { 
-      generate_dispatch_call(true); 
-    } 
- 
-    // Generate all of the process subfunctions 
-    generate_process_functions(); 
- 
-    generate_factory(); 
-  } 
- 
-  void generate_class_definition(); 
-  void generate_dispatch_call(bool template_protocol); 
-  void generate_process_functions(); 
-  void generate_factory(); 
- 
-protected: 
-  std::string type_name(t_type* ttype, bool in_typedef = false, bool arg = false) { 
-    return generator_->type_name(ttype, in_typedef, arg); 
-  } 
- 
-  std::string indent() { return generator_->indent(); } 
-  std::ostream& indent(std::ostream& os) { return generator_->indent(os); } 
- 
-  void indent_up() { generator_->indent_up(); } 
-  void indent_down() { generator_->indent_down(); } 
- 
-  t_cpp_generator* generator_; 
-  t_service* service_; 
-  std::ostream& f_header_; 
-  std::ostream& f_out_; 
-  string service_name_; 
-  string style_; 
-  string pstyle_; 
-  string class_name_; 
-  string if_name_; 
-  string factory_class_name_; 
-  string finish_cob_; 
-  string finish_cob_decl_; 
-  string ret_type_; 
-  string call_context_; 
-  string cob_arg_; 
-  string call_context_arg_; 
-  string call_context_decl_; 
-  string template_header_; 
-  string template_suffix_; 
-  string typename_str_; 
-  string class_suffix_; 
-  string extends_; 
-}; 
- 
-ProcessorGenerator::ProcessorGenerator(t_cpp_generator* generator, 
-                                       t_service* service, 
-                                       const string& style) 
-  : generator_(generator), 
-    service_(service), 
-    f_header_(generator->f_header_), 
-    f_out_(generator->gen_templates_ ? generator->f_service_tcc_ : generator->f_service_), 
-    service_name_(generator->service_name_), 
-    style_(style) { 
-  if (style_ == "Cob") { 
-    pstyle_ = "Async"; 
-    class_name_ = service_name_ + pstyle_ + "Processor"; 
-    if_name_ = service_name_ + "CobSvIf"; 
- 
-    finish_cob_ = "::apache::thrift::stdcxx::function<void(bool ok)> cob, "; 
-    finish_cob_decl_ = "::apache::thrift::stdcxx::function<void(bool ok)>, "; 
-    cob_arg_ = "cob, "; 
-    ret_type_ = "void "; 
-  } else { 
-    class_name_ = service_name_ + "Processor"; 
-    if_name_ = service_name_ + "If"; 
- 
-    ret_type_ = "bool "; 
-    // TODO(edhall) callContext should eventually be added to TAsyncProcessor 
-    call_context_ = ", void* callContext"; 
-    call_context_arg_ = ", callContext"; 
-    call_context_decl_ = ", void*"; 
-  } 
- 
-  factory_class_name_ = class_name_ + "Factory"; 
- 
-  if (generator->gen_templates_) { 
-    template_header_ = "template <class Protocol_>\n"; 
-    template_suffix_ = "<Protocol_>"; 
-    typename_str_ = "typename "; 
-    class_name_ += "T"; 
-    factory_class_name_ += "T"; 
-  } 
- 
-  if (service_->get_extends() != NULL) { 
-    extends_ = type_name(service_->get_extends()) + pstyle_ + "Processor"; 
-    if (generator_->gen_templates_) { 
-      // TODO(simpkins): If gen_templates_ is enabled, we currently assume all 
-      // parent services were also generated with templates enabled. 
-      extends_ += "T<Protocol_>"; 
-    } 
-  } 
-} 
- 
-void ProcessorGenerator::generate_class_definition() { 
-  // Generate the dispatch methods 
-  vector<t_function*> functions = service_->get_functions(); 
-  vector<t_function*>::iterator f_iter; 
- 
-  string parent_class; 
-  if (service_->get_extends() != NULL) { 
-    parent_class = extends_; 
-  } else { 
-    if (style_ == "Cob") { 
-      parent_class = "::apache::thrift::async::TAsyncDispatchProcessor"; 
-    } else { 
-      parent_class = "::apache::thrift::TDispatchProcessor"; 
-    } 
- 
-    if (generator_->gen_templates_) { 
-      parent_class += "T<Protocol_>"; 
-    } 
-  } 
- 
-  // Generate the header portion 
-  f_header_ << template_header_ << "class " << class_name_ << " : public " << parent_class << " {" 
-            << endl; 
- 
-  // Protected data members 
-  f_header_ << " protected:" << endl; 
-  indent_up(); 
-  f_header_ << indent() << "::apache::thrift::stdcxx::shared_ptr<" << if_name_ << "> iface_;" << endl; 
-  f_header_ << indent() << "virtual " << ret_type_ << "dispatchCall(" << finish_cob_ 
-            << "::apache::thrift::protocol::TProtocol* iprot, " 
-            << "::apache::thrift::protocol::TProtocol* oprot, " 
-            << "const std::string& fname, int32_t seqid" << call_context_ << ");" << endl; 
-  if (generator_->gen_templates_) { 
-    f_header_ << indent() << "virtual " << ret_type_ << "dispatchCallTemplated(" << finish_cob_ 
-              << "Protocol_* iprot, Protocol_* oprot, " 
-              << "const std::string& fname, int32_t seqid" << call_context_ << ");" << endl; 
-  } 
-  indent_down(); 
- 
-  // Process function declarations 
-  f_header_ << " private:" << endl; 
-  indent_up(); 
- 
-  // Declare processMap_ 
-  f_header_ << indent() << "typedef  void (" << class_name_ << "::*" 
-            << "ProcessFunction)(" << finish_cob_decl_ << "int32_t, " 
-            << "::apache::thrift::protocol::TProtocol*, " 
-            << "::apache::thrift::protocol::TProtocol*" << call_context_decl_ << ");" << endl; 
-  if (generator_->gen_templates_) { 
-    f_header_ << indent() << "typedef void (" << class_name_ << "::*" 
-              << "SpecializedProcessFunction)(" << finish_cob_decl_ << "int32_t, " 
-              << "Protocol_*, Protocol_*" << call_context_decl_ << ");" << endl << indent() 
-              << "struct ProcessFunctions {" << endl << indent() << "  ProcessFunction generic;" 
-              << endl << indent() << "  SpecializedProcessFunction specialized;" << endl << indent() 
-              << "  ProcessFunctions(ProcessFunction g, " 
-              << "SpecializedProcessFunction s) :" << endl << indent() << "    generic(g)," << endl 
-              << indent() << "    specialized(s) {}" << endl << indent() 
-              << "  ProcessFunctions() : generic(NULL), specialized(NULL) " 
-              << "{}" << endl << indent() << "};" << endl << indent() 
-              << "typedef std::map<std::string, ProcessFunctions> " 
-              << "ProcessMap;" << endl; 
-  } else { 
-    f_header_ << indent() << "typedef std::map<std::string, ProcessFunction> " 
-              << "ProcessMap;" << endl; 
-  } 
-  f_header_ << indent() << "ProcessMap processMap_;" << endl; 
- 
-  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) { 
-    indent(f_header_) << "void process_" << (*f_iter)->get_name() << "(" << finish_cob_ 
-                      << "int32_t seqid, ::apache::thrift::protocol::TProtocol* iprot, " 
-                         "::apache::thrift::protocol::TProtocol* oprot" << call_context_ << ");" 
-                      << endl; 
-    if (generator_->gen_templates_) { 
-      indent(f_header_) << "void process_" << (*f_iter)->get_name() << "(" << finish_cob_ 
-                        << "int32_t seqid, Protocol_* iprot, Protocol_* oprot" << call_context_ 
-                        << ");" << endl; 
-    } 
-    if (style_ == "Cob") { 
-      // XXX Factor this out, even if it is a pain. 
-      string ret_arg = ((*f_iter)->get_returntype()->is_void() 
-                            ? "" 
-                            : ", const " + type_name((*f_iter)->get_returntype()) + "& _return"); 
-      f_header_ << indent() << "void return_" << (*f_iter)->get_name() 
-                << "(::apache::thrift::stdcxx::function<void(bool ok)> cob, int32_t seqid, " 
-                << "::apache::thrift::protocol::TProtocol* oprot, " 
-                << "void* ctx" << ret_arg << ");" << endl; 
-      if (generator_->gen_templates_) { 
-        f_header_ << indent() << "void return_" << (*f_iter)->get_name() 
-                  << "(::apache::thrift::stdcxx::function<void(bool ok)> cob, int32_t seqid, " 
-                  << "Protocol_* oprot, void* ctx" << ret_arg << ");" << endl; 
-      } 
-      // XXX Don't declare throw if it doesn't exist 
-      f_header_ << indent() << "void throw_" << (*f_iter)->get_name() 
-                << "(::apache::thrift::stdcxx::function<void(bool ok)> cob, int32_t seqid, " 
-                << "::apache::thrift::protocol::TProtocol* oprot, void* ctx, " 
-                << "::apache::thrift::TDelayedException* _throw);" << endl; 
-      if (generator_->gen_templates_) { 
-        f_header_ << indent() << "void throw_" << (*f_iter)->get_name() 
-                  << "(::apache::thrift::stdcxx::function<void(bool ok)> cob, int32_t seqid, " 
-                  << "Protocol_* oprot, void* ctx, " 
-                  << "::apache::thrift::TDelayedException* _throw);" << endl; 
-      } 
-    } 
-  } 
- 
-  f_header_ << " public:" << endl << indent() << class_name_ << "(::apache::thrift::stdcxx::shared_ptr<" << if_name_ 
-            << "> iface) :" << endl; 
-  if (!extends_.empty()) { 
-    f_header_ << indent() << "  " << extends_ << "(iface)," << endl; 
-  } 
-  f_header_ << indent() << "  iface_(iface) {" << endl; 
-  indent_up(); 
- 
-  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) { 
-    f_header_ << indent() << "processMap_[\"" << (*f_iter)->get_name() << "\"] = "; 
-    if (generator_->gen_templates_) { 
-      f_header_ << "ProcessFunctions(" << endl; 
-      if (generator_->gen_templates_only_) { 
-        indent(f_header_) << "  NULL," << endl; 
-      } else { 
-        indent(f_header_) << "  &" << class_name_ << "::process_" << (*f_iter)->get_name() << "," 
-                          << endl; 
-      } 
-      indent(f_header_) << "  &" << class_name_ << "::process_" << (*f_iter)->get_name() << ")"; 
-    } else { 
-      f_header_ << "&" << class_name_ << "::process_" << (*f_iter)->get_name(); 
-    } 
-    f_header_ << ";" << endl; 
-  } 
- 
-  indent_down(); 
-  f_header_ << indent() << "}" << endl << endl << indent() << "virtual ~" << class_name_ << "() {}" 
-            << endl; 
-  indent_down(); 
-  f_header_ << "};" << endl << endl; 
- 
-  if (generator_->gen_templates_) { 
-    // Generate a backwards compatible typedef, for callers who don't know 
-    // about the new template-style code. 
-    // 
-    // We can't use TProtocol as the template parameter, since ProcessorT 
-    // provides overloaded versions of most methods, one of which accepts 
-    // TProtocol pointers, and one which accepts Protocol_ pointers.  This 
-    // results in a compile error if instantiated with Protocol_ == TProtocol. 
-    // Therefore, we define TDummyProtocol solely so we can use it as the 
-    // template parameter here. 
-    f_header_ << "typedef " << class_name_ << "< ::apache::thrift::protocol::TDummyProtocol > " 
-              << service_name_ << pstyle_ << "Processor;" << endl << endl; 
-  } 
-} 
- 
-void ProcessorGenerator::generate_dispatch_call(bool template_protocol) { 
-  string protocol = "::apache::thrift::protocol::TProtocol"; 
-  string function_suffix; 
-  if (template_protocol) { 
-    protocol = "Protocol_"; 
-    // We call the generic version dispatchCall(), and the specialized 
-    // version dispatchCallTemplated().  We can't call them both 
-    // dispatchCall(), since this will cause the compiler to issue a warning if 
-    // a service that doesn't use templates inherits from a service that does 
-    // use templates: the compiler complains that the subclass only implements 
-    // the generic version of dispatchCall(), and hides the templated version. 
-    // Using different names for the two functions prevents this. 
-    function_suffix = "Templated"; 
-  } 
- 
-  f_out_ << template_header_ << ret_type_ << class_name_ << template_suffix_ << "::dispatchCall" 
-         << function_suffix << "(" << finish_cob_ << protocol << "* iprot, " << protocol 
-         << "* oprot, " 
-         << "const std::string& fname, int32_t seqid" << call_context_ << ") {" << endl; 
-  indent_up(); 
- 
-  // HOT: member function pointer map 
-  f_out_ << indent() << typename_str_ << "ProcessMap::iterator pfn;" << endl << indent() 
-         << "pfn = processMap_.find(fname);" << endl << indent() 
-         << "if (pfn == processMap_.end()) {" << endl; 
-  if (extends_.empty()) { 
-    f_out_ << indent() << "  iprot->skip(::apache::thrift::protocol::T_STRUCT);" << endl << indent() 
-           << "  iprot->readMessageEnd();" << endl << indent() 
-           << "  iprot->getTransport()->readEnd();" << endl << indent() 
-           << "  ::apache::thrift::TApplicationException " 
-              "x(::apache::thrift::TApplicationException::UNKNOWN_METHOD, \"Invalid method name: " 
-              "'\"+fname+\"'\");" << endl << indent() 
-           << "  oprot->writeMessageBegin(fname, ::apache::thrift::protocol::T_EXCEPTION, seqid);" 
-           << endl << indent() << "  x.write(oprot);" << endl << indent() 
-           << "  oprot->writeMessageEnd();" << endl << indent() 
-           << "  oprot->getTransport()->writeEnd();" << endl << indent() 
-           << "  oprot->getTransport()->flush();" << endl << indent() 
-           << (style_ == "Cob" ? "  return cob(true);" : "  return true;") << endl; 
-  } else { 
-    f_out_ << indent() << "  return " << extends_ << "::dispatchCall(" 
-           << (style_ == "Cob" ? "cob, " : "") << "iprot, oprot, fname, seqid" << call_context_arg_ 
-           << ");" << endl; 
-  } 
-  f_out_ << indent() << "}" << endl; 
-  if (template_protocol) { 
-    f_out_ << indent() << "(this->*(pfn->second.specialized))"; 
-  } else { 
-    if (generator_->gen_templates_only_) { 
-      // TODO: This is a null pointer, so nothing good will come from calling 
-      // it.  Throw an exception instead. 
-      f_out_ << indent() << "(this->*(pfn->second.generic))"; 
-    } else if (generator_->gen_templates_) { 
-      f_out_ << indent() << "(this->*(pfn->second.generic))"; 
-    } else { 
-      f_out_ << indent() << "(this->*(pfn->second))"; 
-    } 
-  } 
-  f_out_ << "(" << cob_arg_ << "seqid, iprot, oprot" << call_context_arg_ << ");" << endl; 
- 
-  // TODO(dreiss): return pfn ret? 
-  if (style_ == "Cob") { 
-    f_out_ << indent() << "return;" << endl; 
-  } else { 
-    f_out_ << indent() << "return true;" << endl; 
-  } 
- 
-  indent_down(); 
-  f_out_ << "}" << endl << endl; 
-} 
- 
-void ProcessorGenerator::generate_process_functions() { 
-  vector<t_function*> functions = service_->get_functions(); 
-  vector<t_function*>::iterator f_iter; 
-  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) { 
-    if (generator_->gen_templates_) { 
-      generator_->generate_process_function(service_, *f_iter, style_, false); 
-      generator_->generate_process_function(service_, *f_iter, style_, true); 
-    } else { 
-      generator_->generate_process_function(service_, *f_iter, style_, false); 
-    } 
-  } 
-} 
- 
-void ProcessorGenerator::generate_factory() { 
-  string if_factory_name = if_name_ + "Factory"; 
- 
-  // Generate the factory class definition 
-  f_header_ << template_header_ << "class " << factory_class_name_ << " : public ::apache::thrift::" 
-            << (style_ == "Cob" ? "async::TAsyncProcessorFactory" : "TProcessorFactory") << " {" 
-            << endl << " public:" << endl; 
-  indent_up(); 
- 
-  f_header_ << indent() << factory_class_name_ << "(const ::apache::thrift::stdcxx::shared_ptr< " << if_factory_name 
-            << " >& handlerFactory) :" << endl << indent() 
-            << "    handlerFactory_(handlerFactory) {}" << endl << endl << indent() 
-            << "::apache::thrift::stdcxx::shared_ptr< ::apache::thrift::" 
-            << (style_ == "Cob" ? "async::TAsyncProcessor" : "TProcessor") << " > " 
-            << "getProcessor(const ::apache::thrift::TConnectionInfo& connInfo);" << endl; 
- 
-  f_header_ << endl << " protected:" << endl << indent() << "::apache::thrift::stdcxx::shared_ptr< " 
-            << if_factory_name << " > handlerFactory_;" << endl; 
- 
-  indent_down(); 
-  f_header_ << "};" << endl << endl; 
- 
-  // If we are generating templates, output a typedef for the plain 
-  // factory name. 
-  if (generator_->gen_templates_) { 
-    f_header_ << "typedef " << factory_class_name_ 
-              << "< ::apache::thrift::protocol::TDummyProtocol > " << service_name_ << pstyle_ 
-              << "ProcessorFactory;" << endl << endl; 
-  } 
- 
-  // Generate the getProcessor() method 
-  f_out_ << template_header_ << indent() << "::apache::thrift::stdcxx::shared_ptr< ::apache::thrift::" 
-         << (style_ == "Cob" ? "async::TAsyncProcessor" : "TProcessor") << " > " 
-         << factory_class_name_ << template_suffix_ << "::getProcessor(" 
-         << "const ::apache::thrift::TConnectionInfo& connInfo) {" << endl; 
-  indent_up(); 
- 
-  f_out_ << indent() << "::apache::thrift::ReleaseHandler< " << if_factory_name 
-         << " > cleanup(handlerFactory_);" << endl << indent() << "::apache::thrift::stdcxx::shared_ptr< " 
-         << if_name_ << " > handler(" 
-         << "handlerFactory_->getHandler(connInfo), cleanup);" << endl << indent() 
-         << "::apache::thrift::stdcxx::shared_ptr< ::apache::thrift::" 
-         << (style_ == "Cob" ? "async::TAsyncProcessor" : "TProcessor") << " > " 
-         << "processor(new " << class_name_ << template_suffix_ << "(handler));" << endl << indent() 
-         << "return processor;" << endl; 
- 
-  indent_down(); 
-  f_out_ << indent() << "}" << endl << endl; 
-} 
- 
-/** 
- * Generates a service processor definition. 
- * 
- * @param tservice The service to generate a processor for. 
- */ 
-void t_cpp_generator::generate_service_processor(t_service* tservice, string style) { 
-  ProcessorGenerator generator(this, tservice, style); 
-  generator.run(); 
-} 
- 
-/** 
- * Generates a struct and helpers for a function. 
- * 
- * @param tfunction The function 
- */ 
-void t_cpp_generator::generate_function_helpers(t_service* tservice, t_function* tfunction) { 
-  if (tfunction->is_oneway()) { 
-    return; 
-  } 
- 
-  std::ostream& out = (gen_templates_ ? f_service_tcc_ : f_service_); 
- 
-  t_struct result(program_, tservice->get_name() + "_" + tfunction->get_name() + "_result"); 
-  t_field success(tfunction->get_returntype(), "success", 0); 
-  if (!tfunction->get_returntype()->is_void()) { 
-    result.append(&success); 
-  } 
- 
-  t_struct* xs = tfunction->get_xceptions(); 
-  const vector<t_field*>& fields = xs->get_members(); 
-  vector<t_field*>::const_iterator f_iter; 
-  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { 
-    result.append(*f_iter); 
-  } 
- 
-  generate_struct_declaration(f_header_, &result, false); 
-  generate_struct_definition(out, f_service_, &result, false); 
-  generate_struct_reader(out, &result); 
-  generate_struct_result_writer(out, &result); 
- 
-  result.set_name(tservice->get_name() + "_" + tfunction->get_name() + "_presult"); 
-  generate_struct_declaration(f_header_, &result, false, true, true, gen_cob_style_); 
-  generate_struct_definition(out, f_service_, &result, false); 
-  generate_struct_reader(out, &result, true); 
-  if (gen_cob_style_) { 
-    generate_struct_writer(out, &result, true); 
-  } 
-} 
- 
-/** 
- * Generates a process function definition. 
- * 
- * @param tfunction The function to write a dispatcher for 
- */ 
-void t_cpp_generator::generate_process_function(t_service* tservice, 
-                                                t_function* tfunction, 
-                                                string style, 
-                                                bool specialized) { 
-  t_struct* arg_struct = tfunction->get_arglist(); 
-  const std::vector<t_field*>& fields = arg_struct->get_members(); 
-  vector<t_field*>::const_iterator f_iter; 
- 
-  t_struct* xs = tfunction->get_xceptions(); 
-  const std::vector<t_field*>& xceptions = xs->get_members(); 
-  vector<t_field*>::const_iterator x_iter; 
-  string service_func_name = "\"" + tservice->get_name() + "." + tfunction->get_name() + "\""; 
- 
-  std::ostream& out = (gen_templates_ ? f_service_tcc_ : f_service_); 
- 
-  string prot_type = (specialized ? "Protocol_" : "::apache::thrift::protocol::TProtocol"); 
-  string class_suffix; 
-  if (gen_templates_) { 
-    class_suffix = "T<Protocol_>"; 
-  } 
- 
-  // I tried to do this as one function.  I really did.  But it was too hard. 
-  if (style != "Cob") { 
-    // Open function 
-    if (gen_templates_) { 
-      out << indent() << "template <class Protocol_>" << endl; 
-    } 
-    const bool unnamed_oprot_seqid = tfunction->is_oneway() && !(gen_templates_ && !specialized); 
-    out << "void " << tservice->get_name() << "Processor" << class_suffix << "::" 
-        << "process_" << tfunction->get_name() << "(" 
-        << "int32_t" << (unnamed_oprot_seqid ? ", " : " seqid, ") << prot_type << "* iprot, " 
-        << prot_type << "*" << (unnamed_oprot_seqid ? ", " : " oprot, ") << "void* callContext)" 
-        << endl; 
-    scope_up(out); 
- 
-    string argsname = tservice->get_name() + "_" + tfunction->get_name() + "_args"; 
-    string resultname = tservice->get_name() + "_" + tfunction->get_name() + "_result"; 
- 
-    if (tfunction->is_oneway() && !unnamed_oprot_seqid) { 
-      out << indent() << "(void) seqid;" << endl << indent() << "(void) oprot;" << endl; 
-    } 
- 
-    out << indent() << "void* ctx = NULL;" << endl << indent() 
-        << "if (this->eventHandler_.get() != NULL) {" << endl << indent() 
-        << "  ctx = this->eventHandler_->getContext(" << service_func_name << ", callContext);" 
-        << endl << indent() << "}" << endl << indent() 
-        << "::apache::thrift::TProcessorContextFreer freer(" 
-        << "this->eventHandler_.get(), ctx, " << service_func_name << ");" << endl << endl 
-        << indent() << "if (this->eventHandler_.get() != NULL) {" << endl << indent() 
-        << "  this->eventHandler_->preRead(ctx, " << service_func_name << ");" << endl << indent() 
-        << "}" << endl << endl << indent() << argsname << " args;" << endl << indent() 
-        << "args.read(iprot);" << endl << indent() << "iprot->readMessageEnd();" << endl << indent() 
-        << "uint32_t bytes = iprot->getTransport()->readEnd();" << endl << endl << indent() 
-        << "if (this->eventHandler_.get() != NULL) {" << endl << indent() 
-        << "  this->eventHandler_->postRead(ctx, " << service_func_name << ", bytes);" << endl 
-        << indent() << "}" << endl << endl; 
- 
-    // Declare result 
-    if (!tfunction->is_oneway()) { 
-      out << indent() << resultname << " result;" << endl; 
-    } 
- 
-    // Try block for functions with exceptions 
-    out << indent() << "try {" << endl; 
-    indent_up(); 
- 
-    // Generate the function call 
-    bool first = true; 
-    out << indent(); 
-    if (!tfunction->is_oneway() && !tfunction->get_returntype()->is_void()) { 
-      if (is_complex_type(tfunction->get_returntype())) { 
-        first = false; 
-        out << "iface_->" << tfunction->get_name() << "(result.success"; 
-      } else { 
-        out << "result.success = iface_->" << tfunction->get_name() << "("; 
-      } 
-    } else { 
-      out << "iface_->" << tfunction->get_name() << "("; 
-    } 
-    for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { 
-      if (first) { 
-        first = false; 
-      } else { 
-        out << ", "; 
-      } 
-      out << "args." << (*f_iter)->get_name(); 
-    } 
-    out << ");" << endl; 
- 
-    // Set isset on success field 
-    if (!tfunction->is_oneway() && !tfunction->get_returntype()->is_void()) { 
-      out << indent() << "result.__isset.success = true;" << endl; 
-    } 
- 
-    indent_down(); 
-    out << indent() << "}"; 
- 
-    if (!tfunction->is_oneway()) { 
-      for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) { 
-        out << " catch (" << type_name((*x_iter)->get_type()) << " &" << (*x_iter)->get_name() 
-            << ") {" << endl; 
-        if (!tfunction->is_oneway()) { 
-          indent_up(); 
-          out << indent() << "result." << (*x_iter)->get_name() << " = " << (*x_iter)->get_name() 
-              << ";" << endl << indent() << "result.__isset." << (*x_iter)->get_name() << " = true;" 
-              << endl; 
-          indent_down(); 
-          out << indent() << "}"; 
-        } else { 
-          out << "}"; 
-        } 
-      } 
-    } 
- 
-    if (!tfunction->is_oneway()) { 
-      out << " catch (const std::exception& e) {" << endl; 
-    } else { 
-      out << " catch (const std::exception&) {" << endl; 
-    } 
- 
-    indent_up(); 
-    out << indent() << "if (this->eventHandler_.get() != NULL) {" << endl << indent() 
-        << "  this->eventHandler_->handlerError(ctx, " << service_func_name << ");" << endl 
-        << indent() << "}" << endl; 
- 
-    if (!tfunction->is_oneway()) { 
-      out << endl << indent() << "::apache::thrift::TApplicationException x(e.what());" << endl 
-          << indent() << "oprot->writeMessageBegin(\"" << tfunction->get_name() 
-          << "\", ::apache::thrift::protocol::T_EXCEPTION, seqid);" << endl << indent() 
-          << "x.write(oprot);" << endl << indent() << "oprot->writeMessageEnd();" << endl 
-          << indent() << "oprot->getTransport()->writeEnd();" << endl << indent() 
-          << "oprot->getTransport()->flush();" << endl; 
-    } 
-    out << indent() << "return;" << endl; 
-    indent_down(); 
-    out << indent() << "}" << endl << endl; 
- 
-    // Shortcut out here for oneway functions 
-    if (tfunction->is_oneway()) { 
-      out << indent() << "if (this->eventHandler_.get() != NULL) {" << endl << indent() 
-          << "  this->eventHandler_->asyncComplete(ctx, " << service_func_name << ");" << endl 
-          << indent() << "}" << endl << endl << indent() << "return;" << endl; 
-      indent_down(); 
-      out << "}" << endl << endl; 
-      return; 
-    } 
- 
-    // Serialize the result into a struct 
-    out << indent() << "if (this->eventHandler_.get() != NULL) {" << endl << indent() 
-        << "  this->eventHandler_->preWrite(ctx, " << service_func_name << ");" << endl << indent() 
-        << "}" << endl << endl << indent() << "oprot->writeMessageBegin(\"" << tfunction->get_name() 
-        << "\", ::apache::thrift::protocol::T_REPLY, seqid);" << endl << indent() 
-        << "result.write(oprot);" << endl << indent() << "oprot->writeMessageEnd();" << endl 
-        << indent() << "bytes = oprot->getTransport()->writeEnd();" << endl << indent() 
-        << "oprot->getTransport()->flush();" << endl << endl << indent() 
-        << "if (this->eventHandler_.get() != NULL) {" << endl << indent() 
-        << "  this->eventHandler_->postWrite(ctx, " << service_func_name << ", bytes);" << endl 
-        << indent() << "}" << endl; 
- 
-    // Close function 
-    scope_down(out); 
-    out << endl; 
-  } 
- 
-  // Cob style. 
-  else { 
-    // Processor entry point. 
-    // TODO(edhall) update for callContext when TEventServer is ready 
-    if (gen_templates_) { 
-      out << indent() << "template <class Protocol_>" << endl; 
-    } 
-    out << "void " << tservice->get_name() << "AsyncProcessor" << class_suffix << "::process_" 
-        << tfunction->get_name() << "(::apache::thrift::stdcxx::function<void(bool ok)> cob, int32_t seqid, " 
-        << prot_type << "* iprot, " << prot_type << "* oprot)" << endl; 
-    scope_up(out); 
- 
-    // TODO(simpkins): we could try to consoldate this 
-    // with the non-cob code above 
-    if (gen_templates_ && !specialized) { 
-      // If these are instances of Protocol_, instead of any old TProtocol, 
-      // use the specialized process function instead. 
-      out << indent() << "Protocol_* _iprot = dynamic_cast<Protocol_*>(iprot);" << endl << indent() 
-          << "Protocol_* _oprot = dynamic_cast<Protocol_*>(oprot);" << endl << indent() 
-          << "if (_iprot && _oprot) {" << endl << indent() << "  return process_" 
-          << tfunction->get_name() << "(cob, seqid, _iprot, _oprot);" << endl << indent() << "}" 
-          << endl << indent() << "T_GENERIC_PROTOCOL(this, iprot, _iprot);" << endl << indent() 
-          << "T_GENERIC_PROTOCOL(this, oprot, _oprot);" << endl << endl; 
-    } 
- 
-    if (tfunction->is_oneway()) { 
-      out << indent() << "(void) seqid;" << endl << indent() << "(void) oprot;" << endl; 
-    } 
- 
-    out << indent() << tservice->get_name() + "_" + tfunction->get_name() << "_args args;" << endl 
-        << indent() << "void* ctx = NULL;" << endl << indent() 
-        << "if (this->eventHandler_.get() != NULL) {" << endl << indent() 
-        << "  ctx = this->eventHandler_->getContext(" << service_func_name << ", NULL);" << endl 
-        << indent() << "}" << endl << indent() << "::apache::thrift::TProcessorContextFreer freer(" 
-        << "this->eventHandler_.get(), ctx, " << service_func_name << ");" << endl << endl 
-        << indent() << "try {" << endl; 
-    indent_up(); 
-    out << indent() << "if (this->eventHandler_.get() != NULL) {" << endl << indent() 
-        << "  this->eventHandler_->preRead(ctx, " << service_func_name << ");" << endl << indent() 
-        << "}" << endl << indent() << "args.read(iprot);" << endl << indent() 
-        << "iprot->readMessageEnd();" << endl << indent() 
-        << "uint32_t bytes = iprot->getTransport()->readEnd();" << endl << indent() 
-        << "if (this->eventHandler_.get() != NULL) {" << endl << indent() 
-        << "  this->eventHandler_->postRead(ctx, " << service_func_name << ", bytes);" << endl 
-        << indent() << "}" << endl; 
-    scope_down(out); 
- 
-    // TODO(dreiss): Handle TExceptions?  Expose to server? 
-    out << indent() << "catch (const std::exception&) {" << endl << indent() 
-        << "  if (this->eventHandler_.get() != NULL) {" << endl << indent() 
-        << "    this->eventHandler_->handlerError(ctx, " << service_func_name << ");" << endl 
-        << indent() << "  }" << endl << indent() << "  return cob(false);" << endl << indent() 
-        << "}" << endl; 
- 
-    if (tfunction->is_oneway()) { 
-      out << indent() << "if (this->eventHandler_.get() != NULL) {" << endl << indent() 
-          << "  this->eventHandler_->asyncComplete(ctx, " << service_func_name << ");" << endl 
-          << indent() << "}" << endl; 
-    } 
-    // TODO(dreiss): Figure out a strategy for exceptions in async handlers. 
-    out << indent() << "freer.unregister();" << endl; 
-    if (tfunction->is_oneway()) { 
-      // No return.  Just hand off our cob. 
-      // TODO(dreiss): Call the cob immediately? 
-      out << indent() << "iface_->" << tfunction->get_name() << "(" 
-          << "::apache::thrift::stdcxx::bind(cob, true)" << endl; 
-      indent_up(); 
-      indent_up(); 
-    } else { 
-      string ret_arg, ret_placeholder; 
-      if (!tfunction->get_returntype()->is_void()) { 
-        ret_arg = ", const " + type_name(tfunction->get_returntype()) + "& _return"; 
-        ret_placeholder = ", ::apache::thrift::stdcxx::placeholders::_1"; 
-      } 
- 
-      // When gen_templates_ is true, the return_ and throw_ functions are 
-      // overloaded.  We have to declare pointers to them so that the compiler 
-      // can resolve the correct overloaded version. 
-      out << indent() << "void (" << tservice->get_name() << "AsyncProcessor" << class_suffix 
-          << "::*return_fn)(::apache::thrift::stdcxx::function<void(bool ok)> " 
-          << "cob, int32_t seqid, " << prot_type << "* oprot, void* ctx" << ret_arg 
-          << ") =" << endl; 
-      out << indent() << "  &" << tservice->get_name() << "AsyncProcessor" << class_suffix 
-          << "::return_" << tfunction->get_name() << ";" << endl; 
-      if (!xceptions.empty()) { 
-        out << indent() << "void (" << tservice->get_name() << "AsyncProcessor" << class_suffix 
-            << "::*throw_fn)(::apache::thrift::stdcxx::function<void(bool ok)> " 
-            << "cob, int32_t seqid, " << prot_type << "* oprot, void* ctx, " 
-            << "::apache::thrift::TDelayedException* _throw) =" << endl; 
-        out << indent() << "  &" << tservice->get_name() << "AsyncProcessor" << class_suffix 
-            << "::throw_" << tfunction->get_name() << ";" << endl; 
-      } 
- 
-      out << indent() << "iface_->" << tfunction->get_name() << "(" << endl; 
-      indent_up(); 
-      indent_up(); 
-      out << indent() << "::apache::thrift::stdcxx::bind(return_fn, this, cob, seqid, oprot, ctx" << ret_placeholder 
-          << ")"; 
-      if (!xceptions.empty()) { 
-        out << ',' << endl << indent() << "::apache::thrift::stdcxx::bind(throw_fn, this, cob, seqid, oprot, " 
-            << "ctx, ::apache::thrift::stdcxx::placeholders::_1)"; 
-      } 
-    } 
- 
-    // XXX Whitespace cleanup. 
-    for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { 
-      out << ',' << endl << indent() << "args." << (*f_iter)->get_name(); 
-    } 
-    out << ");" << endl; 
-    indent_down(); 
-    indent_down(); 
-    scope_down(out); 
-    out << endl; 
- 
-    // Normal return. 
-    if (!tfunction->is_oneway()) { 
-      string ret_arg_decl, ret_arg_name; 
-      if (!tfunction->get_returntype()->is_void()) { 
-        ret_arg_decl = ", const " + type_name(tfunction->get_returntype()) + "& _return"; 
-        ret_arg_name = ", _return"; 
-      } 
-      if (gen_templates_) { 
-        out << indent() << "template <class Protocol_>" << endl; 
-      } 
-      out << "void " << tservice->get_name() << "AsyncProcessor" << class_suffix << "::return_" 
-          << tfunction->get_name() << "(::apache::thrift::stdcxx::function<void(bool ok)> cob, int32_t seqid, " 
-          << prot_type << "* oprot, void* ctx" << ret_arg_decl << ')' << endl; 
-      scope_up(out); 
- 
-      if (gen_templates_ && !specialized) { 
-        // If oprot is a Protocol_ instance, 
-        // use the specialized return function instead. 
-        out << indent() << "Protocol_* _oprot = dynamic_cast<Protocol_*>(oprot);" << endl 
-            << indent() << "if (_oprot) {" << endl << indent() << "  return return_" 
-            << tfunction->get_name() << "(cob, seqid, _oprot, ctx" << ret_arg_name << ");" << endl 
-            << indent() << "}" << endl << indent() << "T_GENERIC_PROTOCOL(this, oprot, _oprot);" 
-            << endl << endl; 
-      } 
- 
-      out << indent() << tservice->get_name() << "_" << tfunction->get_name() << "_presult result;" 
-          << endl; 
-      if (!tfunction->get_returntype()->is_void()) { 
-        // The const_cast here is unfortunate, but it would be a pain to avoid, 
-        // and we only do a write with this struct, which is const-safe. 
-        out << indent() << "result.success = const_cast<" << type_name(tfunction->get_returntype()) 
-            << "*>(&_return);" << endl << indent() << "result.__isset.success = true;" << endl; 
-      } 
-      // Serialize the result into a struct 
-      out << endl << indent() << "if (this->eventHandler_.get() != NULL) {" << endl << indent() 
-          << "  ctx = this->eventHandler_->getContext(" << service_func_name << ", NULL);" << endl 
-          << indent() << "}" << endl << indent() 
-          << "::apache::thrift::TProcessorContextFreer freer(" 
-          << "this->eventHandler_.get(), ctx, " << service_func_name << ");" << endl << endl 
-          << indent() << "if (this->eventHandler_.get() != NULL) {" << endl << indent() 
-          << "  this->eventHandler_->preWrite(ctx, " << service_func_name << ");" << endl 
-          << indent() << "}" << endl << endl << indent() << "oprot->writeMessageBegin(\"" 
-          << tfunction->get_name() << "\", ::apache::thrift::protocol::T_REPLY, seqid);" << endl 
-          << indent() << "result.write(oprot);" << endl << indent() << "oprot->writeMessageEnd();" 
-          << endl << indent() << "uint32_t bytes = oprot->getTransport()->writeEnd();" << endl 
-          << indent() << "oprot->getTransport()->flush();" << endl << indent() 
-          << "if (this->eventHandler_.get() != NULL) {" << endl << indent() 
-          << "  this->eventHandler_->postWrite(ctx, " << service_func_name << ", bytes);" << endl 
-          << indent() << "}" << endl << indent() << "return cob(true);" << endl; 
-      scope_down(out); 
-      out << endl; 
-    } 
- 
-    // Exception return. 
-    if (!tfunction->is_oneway() && !xceptions.empty()) { 
-      if (gen_templates_) { 
-        out << indent() << "template <class Protocol_>" << endl; 
-      } 
-      out << "void " << tservice->get_name() << "AsyncProcessor" << class_suffix << "::throw_" 
-          << tfunction->get_name() << "(::apache::thrift::stdcxx::function<void(bool ok)> cob, int32_t seqid, " 
-          << prot_type << "* oprot, void* ctx, " 
-          << "::apache::thrift::TDelayedException* _throw)" << endl; 
-      scope_up(out); 
- 
-      if (gen_templates_ && !specialized) { 
-        // If oprot is a Protocol_ instance, 
-        // use the specialized throw function instead. 
-        out << indent() << "Protocol_* _oprot = dynamic_cast<Protocol_*>(oprot);" << endl 
-            << indent() << "if (_oprot) {" << endl << indent() << "  return throw_" 
-            << tfunction->get_name() << "(cob, seqid, _oprot, ctx, _throw);" << endl << indent() 
-            << "}" << endl << indent() << "T_GENERIC_PROTOCOL(this, oprot, _oprot);" << endl 
-            << endl; 
-      } 
- 
-      // Get the event handler context 
-      out << endl << indent() << "if (this->eventHandler_.get() != NULL) {" << endl << indent() 
-          << "  ctx = this->eventHandler_->getContext(" << service_func_name << ", NULL);" << endl 
-          << indent() << "}" << endl << indent() 
-          << "::apache::thrift::TProcessorContextFreer freer(" 
-          << "this->eventHandler_.get(), ctx, " << service_func_name << ");" << endl << endl; 
- 
-      // Throw the TDelayedException, and catch the result 
-      out << indent() << tservice->get_name() << "_" << tfunction->get_name() << "_result result;" 
-          << endl << endl << indent() << "try {" << endl; 
-      indent_up(); 
-      out << indent() << "_throw->throw_it();" << endl << indent() << "return cob(false);" 
-          << endl; // Is this possible?  TBD. 
-      indent_down(); 
-      out << indent() << '}'; 
-      for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) { 
-        out << "  catch (" << type_name((*x_iter)->get_type()) << " &" << (*x_iter)->get_name() 
-            << ") {" << endl; 
-        indent_up(); 
-        out << indent() << "result." << (*x_iter)->get_name() << " = " << (*x_iter)->get_name() 
-            << ";" << endl << indent() << "result.__isset." << (*x_iter)->get_name() << " = true;" 
-            << endl; 
-        scope_down(out); 
-      } 
- 
-      // Handle the case where an undeclared exception is thrown 
-      out << " catch (std::exception& e) {" << endl; 
-      indent_up(); 
-      out << indent() << "if (this->eventHandler_.get() != NULL) {" << endl << indent() 
-          << "  this->eventHandler_->handlerError(ctx, " << service_func_name << ");" << endl 
-          << indent() << "}" << endl << endl << indent() 
-          << "::apache::thrift::TApplicationException x(e.what());" << endl << indent() 
-          << "oprot->writeMessageBegin(\"" << tfunction->get_name() 
-          << "\", ::apache::thrift::protocol::T_EXCEPTION, seqid);" << endl << indent() 
-          << "x.write(oprot);" << endl << indent() << "oprot->writeMessageEnd();" << endl 
-          << indent() << "oprot->getTransport()->writeEnd();" << endl << indent() 
-          << "oprot->getTransport()->flush();" << endl << 
-          // We pass true to the cob here, since we did successfully write a 
-          // response, even though it is an exception response. 
-          // It looks like the argument is currently ignored, anyway. 
-          indent() << "return cob(true);" << endl; 
-      scope_down(out); 
- 
-      // Serialize the result into a struct 
-      out << indent() << "if (this->eventHandler_.get() != NULL) {" << endl << indent() 
-          << "  this->eventHandler_->preWrite(ctx, " << service_func_name << ");" << endl 
-          << indent() << "}" << endl << endl << indent() << "oprot->writeMessageBegin(\"" 
-          << tfunction->get_name() << "\", ::apache::thrift::protocol::T_REPLY, seqid);" << endl 
-          << indent() << "result.write(oprot);" << endl << indent() << "oprot->writeMessageEnd();" 
-          << endl << indent() << "uint32_t bytes = oprot->getTransport()->writeEnd();" << endl 
-          << indent() << "oprot->getTransport()->flush();" << endl << indent() 
-          << "if (this->eventHandler_.get() != NULL) {" << endl << indent() 
-          << "  this->eventHandler_->postWrite(ctx, " << service_func_name << ", bytes);" << endl 
-          << indent() << "}" << endl << indent() << "return cob(true);" << endl; 
-      scope_down(out); 
-      out << endl; 
-    } // for each function 
-  }   // cob style 
-} 
- 
-/** 
- * Generates a skeleton file of a server 
- * 
- * @param tservice The service to generate a server for. 
- */ 
-void t_cpp_generator::generate_service_skeleton(t_service* tservice) { 
-  string svcname = tservice->get_name(); 
- 
-  // Service implementation file includes 
-  string f_skeleton_name = get_out_dir() + svcname + "_server.skeleton.cpp"; 
- 
-  string ns = namespace_prefix(tservice->get_program()->get_namespace("cpp")); 
- 
-  ofstream_with_content_based_conditional_update f_skeleton; 
-  f_skeleton.open(f_skeleton_name.c_str()); 
-  f_skeleton << "// This autogenerated skeleton file illustrates how to build a server." << endl 
-             << "// You should copy it to another filename to avoid overwriting it." << endl << endl 
-             << "#include \"" << get_include_prefix(*get_program()) << svcname << ".h\"" << endl 
-             << "#include <thrift/protocol/TBinaryProtocol.h>" << endl 
-             << "#include <thrift/server/TSimpleServer.h>" << endl 
-             << "#include <thrift/transport/TServerSocket.h>" << endl 
-             << "#include <thrift/transport/TBufferTransports.h>" << endl << endl 
-             << "using namespace ::apache::thrift;" << endl 
-             << "using namespace ::apache::thrift::protocol;" << endl 
-             << "using namespace ::apache::thrift::transport;" << endl 
-             << "using namespace ::apache::thrift::server;" << endl << endl; 
- 
-  // the following code would not compile: 
-  // using namespace ; 
-  // using namespace ::; 
-  if ((!ns.empty()) && (ns.compare(" ::") != 0)) { 
-    f_skeleton << "using namespace " << string(ns, 0, ns.size() - 2) << ";" << endl << endl; 
-  } 
- 
-  f_skeleton << "class " << svcname << "Handler : virtual public " << svcname << "If {" << endl 
-             << " public:" << endl; 
-  indent_up(); 
-  f_skeleton << indent() << svcname << "Handler() {" << endl << indent() 
-             << "  // Your initialization goes here" << endl << indent() << "}" << endl << endl; 
- 
-  vector<t_function*> functions = tservice->get_functions(); 
-  vector<t_function*>::iterator f_iter; 
-  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) { 
-    generate_java_doc(f_skeleton, *f_iter); 
-    f_skeleton << indent() << function_signature(*f_iter, "") << " {" << endl << indent() 
-               << "  // Your implementation goes here" << endl << indent() << "  printf(\"" 
-               << (*f_iter)->get_name() << "\\n\");" << endl << indent() << "}" << endl << endl; 
-  } 
- 
-  indent_down(); 
-  f_skeleton << "};" << endl << endl; 
- 
-  f_skeleton << indent() << "int main(int argc, char **argv) {" << endl; 
-  indent_up(); 
-  f_skeleton 
-      << indent() << "int port = 9090;" << endl << indent() << "::apache::thrift::stdcxx::shared_ptr<" << svcname 
-      << "Handler> handler(new " << svcname << "Handler());" << endl << indent() 
-      << "::apache::thrift::stdcxx::shared_ptr<TProcessor> processor(new " << svcname << "Processor(handler));" << endl 
-      << indent() << "::apache::thrift::stdcxx::shared_ptr<TServerTransport> serverTransport(new TServerSocket(port));" 
-      << endl << indent() 
-      << "::apache::thrift::stdcxx::shared_ptr<TTransportFactory> transportFactory(new TBufferedTransportFactory());" << endl 
-      << indent() << "::apache::thrift::stdcxx::shared_ptr<TProtocolFactory> protocolFactory(new TBinaryProtocolFactory());" 
-      << endl << endl << indent() 
-      << "TSimpleServer server(processor, serverTransport, transportFactory, protocolFactory);" 
-      << endl << indent() << "server.serve();" << endl << indent() << "return 0;" << endl; 
-  indent_down(); 
-  f_skeleton << "}" << endl << endl; 
- 
-  // Close the files 
-  f_skeleton.close(); 
-} 
- 
-/** 
- * Deserializes a field of any type. 
- */ 
-void t_cpp_generator::generate_deserialize_field(ostream& out, 
-                                                 t_field* tfield, 
-                                                 string prefix, 
-                                                 string suffix) { 
-  t_type* type = get_true_type(tfield->get_type()); 
- 
-  if (type->is_void()) { 
-    throw "CANNOT GENERATE DESERIALIZE CODE FOR void TYPE: " + prefix + tfield->get_name(); 
-  } 
- 
-  string name = prefix + tfield->get_name() + suffix; 
- 
-  if (type->is_struct() || type->is_xception()) { 
-    generate_deserialize_struct(out, (t_struct*)type, name, is_reference(tfield)); 
-  } else if (type->is_container()) { 
-    generate_deserialize_container(out, type, name); 
-  } else if (type->is_base_type()) { 
-    indent(out) << "xfer += iprot->"; 
-    t_base_type::t_base tbase = ((t_base_type*)type)->get_base(); 
-    switch (tbase) { 
-    case t_base_type::TYPE_VOID: 
-      throw "compiler error: cannot serialize void field in a struct: " + name; 
-      break; 
-    case t_base_type::TYPE_STRING: 
-      if (type->is_binary()) { 
-        out << "readBinary(" << name << ");"; 
-      } else { 
-        out << "readString(" << name << ");"; 
-      } 
-      break; 
-    case t_base_type::TYPE_BOOL: 
-      out << "readBool(" << name << ");"; 
-      break; 
-    case t_base_type::TYPE_I8: 
-      out << "readByte(" << name << ");"; 
-      break; 
-    case t_base_type::TYPE_I16: 
-      out << "readI16(" << name << ");"; 
-      break; 
-    case t_base_type::TYPE_I32: 
-      out << "readI32(" << name << ");"; 
-      break; 
-    case t_base_type::TYPE_I64: 
-      out << "readI64(" << name << ");"; 
-      break; 
-    case t_base_type::TYPE_DOUBLE: 
-      out << "readDouble(" << name << ");"; 
-      break; 
-    default: 
-      throw "compiler error: no C++ reader for base type " + t_base_type::t_base_name(tbase) + name; 
-    } 
-    out << endl; 
-  } else if (type->is_enum()) { 
-    string t = tmp("ecast"); 
-    out << indent() << "int32_t " << t << ";" << endl << indent() << "xfer += iprot->readI32(" << t 
-        << ");" << endl << indent() << name << " = (" << type_name(type) << ")" << t << ";" << endl; 
-  } else { 
-    printf("DO NOT KNOW HOW TO DESERIALIZE FIELD '%s' TYPE '%s'\n", 
-           tfield->get_name().c_str(), 
-           type_name(type).c_str()); 
-  } 
-} 
- 
-/** 
- * Generates an unserializer for a variable. This makes two key assumptions, 
- * first that there is a const char* variable named data that points to the 
- * buffer for deserialization, and that there is a variable protocol which 
- * is a reference to a TProtocol serialization object. 
- */ 
-void t_cpp_generator::generate_deserialize_struct(ostream& out, 
-                                                  t_struct* tstruct, 
-                                                  string prefix, 
-                                                  bool pointer) { 
-  if (pointer) { 
-    indent(out) << "if (!" << prefix << ") { " << endl; 
-    indent(out) << "  " << prefix << " = ::apache::thrift::stdcxx::shared_ptr<" << type_name(tstruct) << ">(new " 
-                << type_name(tstruct) << ");" << endl; 
-    indent(out) << "}" << endl; 
-    indent(out) << "xfer += " << prefix << "->read(iprot);" << endl; 
-    indent(out) << "bool wasSet = false;" << endl; 
-    const vector<t_field*>& members = tstruct->get_members(); 
-    vector<t_field*>::const_iterator f_iter; 
-    for (f_iter = members.begin(); f_iter != members.end(); ++f_iter) { 
- 
-      indent(out) << "if (" << prefix << "->__isset." << (*f_iter)->get_name() 
-                  << ") { wasSet = true; }" << endl; 
-    } 
-    indent(out) << "if (!wasSet) { " << prefix << ".reset(); }" << endl; 
-  } else { 
-    indent(out) << "xfer += " << prefix << ".read(iprot);" << endl; 
-  } 
-} 
- 
-void t_cpp_generator::generate_deserialize_container(ostream& out, t_type* ttype, string prefix) { 
-  scope_up(out); 
- 
-  string size = tmp("_size"); 
-  string ktype = tmp("_ktype"); 
-  string vtype = tmp("_vtype"); 
-  string etype = tmp("_etype"); 
- 
-  t_container* tcontainer = (t_container*)ttype; 
-  bool use_push = tcontainer->has_cpp_name(); 
- 
-  indent(out) << prefix << ".clear();" << endl << indent() << "uint32_t " << size << ";" << endl; 
- 
-  // Declare variables, read header 
-  if (ttype->is_map()) { 
-    out << indent() << "::apache::thrift::protocol::TType " << ktype << ";" << endl << indent() 
-        << "::apache::thrift::protocol::TType " << vtype << ";" << endl << indent() 
-        << "xfer += iprot->readMapBegin(" << ktype << ", " << vtype << ", " << size << ");" << endl; 
-  } else if (ttype->is_set()) { 
-    out << indent() << "::apache::thrift::protocol::TType " << etype << ";" << endl << indent() 
-        << "xfer += iprot->readSetBegin(" << etype << ", " << size << ");" << endl; 
-  } else if (ttype->is_list()) { 
-    out << indent() << "::apache::thrift::protocol::TType " << etype << ";" << endl << indent() 
-        << "xfer += iprot->readListBegin(" << etype << ", " << size << ");" << endl; 
-    if (!use_push) { 
-      indent(out) << prefix << ".resize(" << size << ");" << endl; 
-    } 
-  } 
- 
-  // For loop iterates over elements 
-  string i = tmp("_i"); 
-  out << indent() << "uint32_t " << i << ";" << endl << indent() << "for (" << i << " = 0; " << i 
-      << " < " << size << "; ++" << i << ")" << endl; 
- 
-  scope_up(out); 
- 
-  if (ttype->is_map()) { 
-    generate_deserialize_map_element(out, (t_map*)ttype, prefix); 
-  } else if (ttype->is_set()) { 
-    generate_deserialize_set_element(out, (t_set*)ttype, prefix); 
-  } else if (ttype->is_list()) { 
-    generate_deserialize_list_element(out, (t_list*)ttype, prefix, use_push, i); 
-  } 
- 
-  scope_down(out); 
- 
-  // Read container end 
-  if (ttype->is_map()) { 
-    indent(out) << "xfer += iprot->readMapEnd();" << endl; 
-  } else if (ttype->is_set()) { 
-    indent(out) << "xfer += iprot->readSetEnd();" << endl; 
-  } else if (ttype->is_list()) { 
-    indent(out) << "xfer += iprot->readListEnd();" << endl; 
-  } 
- 
-  scope_down(out); 
-} 
- 
-/** 
- * Generates code to deserialize a map 
- */ 
-void t_cpp_generator::generate_deserialize_map_element(ostream& out, t_map* tmap, string prefix) { 
-  string key = tmp("_key"); 
-  string val = tmp("_val"); 
-  t_field fkey(tmap->get_key_type(), key); 
-  t_field fval(tmap->get_val_type(), val); 
- 
-  out << indent() << declare_field(&fkey) << endl; 
- 
-  generate_deserialize_field(out, &fkey); 
-  indent(out) << declare_field(&fval, false, false, false, true) << " = " << prefix << "[" << key 
-              << "];" << endl; 
- 
-  generate_deserialize_field(out, &fval); 
-} 
- 
-void t_cpp_generator::generate_deserialize_set_element(ostream& out, t_set* tset, string prefix) { 
-  string elem = tmp("_elem"); 
-  t_field felem(tset->get_elem_type(), elem); 
- 
-  indent(out) << declare_field(&felem) << endl; 
- 
-  generate_deserialize_field(out, &felem); 
- 
-  indent(out) << prefix << ".insert(" << elem << ");" << endl; 
-} 
- 
-void t_cpp_generator::generate_deserialize_list_element(ostream& out, 
-                                                        t_list* tlist, 
-                                                        string prefix, 
-                                                        bool use_push, 
-                                                        string index) { 
-  if (use_push) { 
-    string elem = tmp("_elem"); 
-    t_field felem(tlist->get_elem_type(), elem); 
-    indent(out) << declare_field(&felem) << endl; 
-    generate_deserialize_field(out, &felem); 
-    indent(out) << prefix << ".push_back(" << elem << ");" << endl; 
-  } else { 
-    t_field felem(tlist->get_elem_type(), prefix + "[" + index + "]"); 
-    generate_deserialize_field(out, &felem); 
-  } 
-} 
- 
-/** 
- * Serializes a field of any type. 
- * 
- * @param tfield The field to serialize 
- * @param prefix Name to prepend to field name 
- */ 
-void t_cpp_generator::generate_serialize_field(ostream& out, 
-                                               t_field* tfield, 
-                                               string prefix, 
-                                               string suffix) { 
-  t_type* type = get_true_type(tfield->get_type()); 
- 
-  string name = prefix + tfield->get_name() + suffix; 
- 
-  // Do nothing for void types 
-  if (type->is_void()) { 
-    throw "CANNOT GENERATE SERIALIZE CODE FOR void TYPE: " + name; 
-  } 
- 
-  if (type->is_struct() || type->is_xception()) { 
-    generate_serialize_struct(out, (t_struct*)type, name, is_reference(tfield)); 
-  } else if (type->is_container()) { 
-    generate_serialize_container(out, type, name); 
-  } else if (type->is_base_type() || type->is_enum()) { 
- 
-    indent(out) << "xfer += oprot->"; 
- 
-    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: 
-        throw "compiler error: cannot serialize void field in a struct: " + name; 
-        break; 
-      case t_base_type::TYPE_STRING: 
-        if (type->is_binary()) { 
-          out << "writeBinary(" << name << ");"; 
-        } else { 
-          out << "writeString(" << name << ");"; 
-        } 
-        break; 
-      case t_base_type::TYPE_BOOL: 
-        out << "writeBool(" << name << ");"; 
-        break; 
-      case t_base_type::TYPE_I8: 
-        out << "writeByte(" << name << ");"; 
-        break; 
-      case t_base_type::TYPE_I16: 
-        out << "writeI16(" << name << ");"; 
-        break; 
-      case t_base_type::TYPE_I32: 
-        out << "writeI32(" << name << ");"; 
-        break; 
-      case t_base_type::TYPE_I64: 
-        out << "writeI64(" << name << ");"; 
-        break; 
-      case t_base_type::TYPE_DOUBLE: 
-        out << "writeDouble(" << name << ");"; 
-        break; 
-      default: 
-        throw "compiler error: no C++ writer for base type " + t_base_type::t_base_name(tbase) 
-            + name; 
-      } 
-    } else if (type->is_enum()) { 
-      out << "writeI32((int32_t)" << name << ");"; 
-    } 
-    out << endl; 
-  } else { 
-    printf("DO NOT KNOW HOW TO SERIALIZE FIELD '%s' TYPE '%s'\n", 
-           name.c_str(), 
-           type_name(type).c_str()); 
-  } 
-} 
- 
-/** 
- * Serializes all the members of a struct. 
- * 
- * @param tstruct The struct to serialize 
- * @param prefix  String prefix to attach to all fields 
- */ 
-void t_cpp_generator::generate_serialize_struct(ostream& out, 
-                                                t_struct* tstruct, 
-                                                string prefix, 
-                                                bool pointer) { 
-  if (pointer) { 
-    indent(out) << "if (" << prefix << ") {" << endl; 
-    indent(out) << "  xfer += " << prefix << "->write(oprot); " << endl; 
-    indent(out) << "} else {" 
-                << "oprot->writeStructBegin(\"" << tstruct->get_name() << "\"); " << endl; 
-    indent(out) << "  oprot->writeStructEnd();" << endl; 
-    indent(out) << "  oprot->writeFieldStop();" << endl; 
-    indent(out) << "}" << endl; 
-  } else { 
-    indent(out) << "xfer += " << prefix << ".write(oprot);" << endl; 
-  } 
-} 
- 
-void t_cpp_generator::generate_serialize_container(ostream& out, t_type* ttype, string prefix) { 
-  scope_up(out); 
- 
-  if (ttype->is_map()) { 
-    indent(out) << "xfer += oprot->writeMapBegin(" << type_to_enum(((t_map*)ttype)->get_key_type()) 
-                << ", " << type_to_enum(((t_map*)ttype)->get_val_type()) << ", " 
-                << "static_cast<uint32_t>(" << prefix << ".size()));" << endl; 
-  } else if (ttype->is_set()) { 
-    indent(out) << "xfer += oprot->writeSetBegin(" << type_to_enum(((t_set*)ttype)->get_elem_type()) 
-                << ", " 
-                << "static_cast<uint32_t>(" << prefix << ".size()));" << endl; 
-  } else if (ttype->is_list()) { 
-    indent(out) << "xfer += oprot->writeListBegin(" 
-                << type_to_enum(((t_list*)ttype)->get_elem_type()) << ", " 
-                << "static_cast<uint32_t>(" << prefix << ".size()));" << endl; 
-  } 
- 
-  string iter = tmp("_iter"); 
-  out << indent() << type_name(ttype) << "::const_iterator " << iter << ";" << endl << indent() 
-      << "for (" << iter << " = " << prefix << ".begin(); " << iter << " != " << prefix 
-      << ".end(); ++" << iter << ")" << endl; 
-  scope_up(out); 
-  if (ttype->is_map()) { 
-    generate_serialize_map_element(out, (t_map*)ttype, iter); 
-  } else if (ttype->is_set()) { 
-    generate_serialize_set_element(out, (t_set*)ttype, iter); 
-  } else if (ttype->is_list()) { 
-    generate_serialize_list_element(out, (t_list*)ttype, iter); 
-  } 
-  scope_down(out); 
- 
-  if (ttype->is_map()) { 
-    indent(out) << "xfer += oprot->writeMapEnd();" << endl; 
-  } else if (ttype->is_set()) { 
-    indent(out) << "xfer += oprot->writeSetEnd();" << endl; 
-  } else if (ttype->is_list()) { 
-    indent(out) << "xfer += oprot->writeListEnd();" << endl; 
-  } 
- 
-  scope_down(out); 
-} 
- 
-/** 
- * Serializes the members of a map. 
- * 
- */ 
-void t_cpp_generator::generate_serialize_map_element(ostream& out, t_map* tmap, string iter) { 
-  t_field kfield(tmap->get_key_type(), iter + "->first"); 
-  generate_serialize_field(out, &kfield, ""); 
- 
-  t_field vfield(tmap->get_val_type(), iter + "->second"); 
-  generate_serialize_field(out, &vfield, ""); 
-} 
- 
-/** 
- * Serializes the members of a set. 
- */ 
-void t_cpp_generator::generate_serialize_set_element(ostream& out, t_set* tset, string iter) { 
-  t_field efield(tset->get_elem_type(), "(*" + iter + ")"); 
-  generate_serialize_field(out, &efield, ""); 
-} 
- 
-/** 
- * Serializes the members of a list. 
- */ 
-void t_cpp_generator::generate_serialize_list_element(ostream& out, t_list* tlist, string iter) { 
-  t_field efield(tlist->get_elem_type(), "(*" + iter + ")"); 
-  generate_serialize_field(out, &efield, ""); 
-} 
- 
-/** 
- * Makes a :: prefix for a namespace 
- * 
- * @param ns The namespace, w/ periods in it 
- * @return Namespaces 
- */ 
-string t_cpp_generator::namespace_prefix(string ns) { 
-  // Always start with "::", to avoid possible name collisions with 
-  // other names in one of the current namespaces. 
-  // 
-  // We also need a leading space, in case the name is used inside of a 
-  // template parameter.  "MyTemplate<::foo::Bar>" is not valid C++, 
-  // since "<:" is an alternative token for "[". 
-  string result = " ::"; 
- 
-  if (ns.size() == 0) { 
-    return result; 
-  } 
-  string::size_type loc; 
-  while ((loc = ns.find(".")) != string::npos) { 
-    result += ns.substr(0, loc); 
-    result += "::"; 
-    ns = ns.substr(loc + 1); 
-  } 
-  if (ns.size() > 0) { 
-    result += ns + "::"; 
-  } 
-  return result; 
-} 
- 
-/** 
- * Opens namespace. 
- * 
- * @param ns The namespace, w/ periods in it 
- * @return Namespaces 
- */ 
-string t_cpp_generator::namespace_open(string ns) { 
-  if (ns.size() == 0) { 
-    return ""; 
-  } 
-  string result = ""; 
-  string separator = ""; 
-  string::size_type loc; 
-  while ((loc = ns.find(".")) != string::npos) { 
-    result += separator; 
-    result += "namespace "; 
-    result += ns.substr(0, loc); 
-    result += " {"; 
-    separator = " "; 
-    ns = ns.substr(loc + 1); 
-  } 
-  if (ns.size() > 0) { 
-    result += separator + "namespace " + ns + " {"; 
-  } 
-  return result; 
-} 
- 
-/** 
- * Closes namespace. 
- * 
- * @param ns The namespace, w/ periods in it 
- * @return Namespaces 
- */ 
-string t_cpp_generator::namespace_close(string ns) { 
-  if (ns.size() == 0) { 
-    return ""; 
-  } 
-  string result = "}"; 
-  string::size_type loc; 
-  while ((loc = ns.find(".")) != string::npos) { 
-    result += "}"; 
-    ns = ns.substr(loc + 1); 
-  } 
-  result += " // namespace"; 
-  return result; 
-} 
- 
-/** 
- * Returns a C++ type name 
- * 
- * @param ttype The type 
- * @return String of the type name, i.e. std::set<type> 
- */ 
-string t_cpp_generator::type_name(t_type* ttype, bool in_typedef, bool arg) { 
-  if (ttype->is_base_type()) { 
-    string bname = base_type_name(((t_base_type*)ttype)->get_base()); 
-    std::map<string, string>::iterator it = ttype->annotations_.find("cpp.type"); 
-    if (it != ttype->annotations_.end()) { 
-      bname = it->second; 
-    } 
- 
-    if (!arg) { 
-      return bname; 
-    } 
- 
-    if (((t_base_type*)ttype)->get_base() == t_base_type::TYPE_STRING) { 
-      return "const " + bname + "&"; 
-    } else { 
-      return "const " + bname; 
-    } 
-  } 
- 
-  // Check for a custom overloaded C++ name 
-  if (ttype->is_container()) { 
-    string cname; 
- 
-    t_container* tcontainer = (t_container*)ttype; 
-    if (tcontainer->has_cpp_name()) { 
-      cname = tcontainer->get_cpp_name(); 
-    } else if (ttype->is_map()) { 
-      t_map* tmap = (t_map*)ttype; 
-      cname = "std::map<" + type_name(tmap->get_key_type(), in_typedef) + ", " 
-              + type_name(tmap->get_val_type(), in_typedef) + "> "; 
-    } else if (ttype->is_set()) { 
-      t_set* tset = (t_set*)ttype; 
-      cname = "std::set<" + type_name(tset->get_elem_type(), in_typedef) + "> "; 
-    } else if (ttype->is_list()) { 
-      t_list* tlist = (t_list*)ttype; 
-      cname = "std::vector<" + type_name(tlist->get_elem_type(), in_typedef) + "> "; 
-    } 
- 
-    if (arg) { 
-      return "const " + cname + "&"; 
-    } else { 
-      return cname; 
-    } 
-  } 
- 
-  string class_prefix; 
-  if (in_typedef && (ttype->is_struct() || ttype->is_xception())) { 
-    class_prefix = "class "; 
-  } 
- 
-  // Check if it needs to be namespaced 
-  string pname; 
-  t_program* program = ttype->get_program(); 
-  if (program != NULL && program != program_) { 
-    pname = class_prefix + namespace_prefix(program->get_namespace("cpp")) + ttype->get_name(); 
-  } else { 
-    pname = class_prefix + ttype->get_name(); 
-  } 
- 
-  if (ttype->is_enum() && !gen_pure_enums_) { 
-    pname += "::type"; 
-  } 
- 
-  if (arg) { 
-    if (is_complex_type(ttype)) { 
-      return "const " + pname + "&"; 
-    } else { 
-      return "const " + pname; 
-    } 
-  } else { 
-    return pname; 
-  } 
-} 
- 
-/** 
- * Returns the C++ type that corresponds to the thrift type. 
- * 
- * @param tbase The base type 
- * @return Explicit C++ type, i.e. "int32_t" 
- */ 
-string t_cpp_generator::base_type_name(t_base_type::t_base tbase) { 
-  switch (tbase) { 
-  case t_base_type::TYPE_VOID: 
-    return "void"; 
-  case t_base_type::TYPE_STRING: 
-    return "std::string"; 
-  case t_base_type::TYPE_BOOL: 
-    return "bool"; 
-  case t_base_type::TYPE_I8: 
-    return "int8_t"; 
-  case t_base_type::TYPE_I16: 
-    return "int16_t"; 
-  case t_base_type::TYPE_I32: 
-    return "int32_t"; 
-  case t_base_type::TYPE_I64: 
-    return "int64_t"; 
-  case t_base_type::TYPE_DOUBLE: 
-    return "double"; 
-  default: 
-    throw "compiler error: no C++ base type name for base type " + t_base_type::t_base_name(tbase); 
-  } 
-} 
- 
-/** 
- * Declares a field, which may include initialization as necessary. 
- * 
- * @param ttype The type 
- * @return Field declaration, i.e. int x = 0; 
- */ 
-string t_cpp_generator::declare_field(t_field* tfield, 
-                                      bool init, 
-                                      bool pointer, 
-                                      bool constant, 
-                                      bool reference) { 
-  // TODO(mcslee): do we ever need to initialize the field? 
-  string result = ""; 
-  if (constant) { 
-    result += "const "; 
-  } 
-  result += type_name(tfield->get_type()); 
-  if (is_reference(tfield)) { 
-    result = "::apache::thrift::stdcxx::shared_ptr<" + result + ">"; 
-  } 
-  if (pointer) { 
-    result += "*"; 
-  } 
-  if (reference) { 
-    result += "&"; 
-  } 
-  result += " " + tfield->get_name(); 
-  if (init) { 
-    t_type* type = get_true_type(tfield->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: 
-      case t_base_type::TYPE_STRING: 
-        break; 
-      case t_base_type::TYPE_BOOL: 
-        result += " = false"; 
-        break; 
-      case t_base_type::TYPE_I8: 
-      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 += " = (double)0"; 
-        break; 
-      default: 
-        throw "compiler error: no C++ initializer for base type " + t_base_type::t_base_name(tbase); 
-      } 
-    } else if (type->is_enum()) { 
-      result += " = (" + type_name(type) + ")0"; 
-    } 
-  } 
-  if (!reference) { 
-    result += ";"; 
-  } 
-  return result; 
-} 
- 
-/** 
- * Renders a function signature of the form 'type name(args)' 
- * 
- * @param tfunction Function definition 
- * @return String of rendered function definition 
- */ 
-string t_cpp_generator::function_signature(t_function* tfunction, 
-                                           string style, 
-                                           string prefix, 
-                                           bool name_params) { 
-  t_type* ttype = tfunction->get_returntype(); 
-  t_struct* arglist = tfunction->get_arglist(); 
-  bool has_xceptions = !tfunction->get_xceptions()->get_members().empty(); 
- 
-  if (style == "") { 
-    if (is_complex_type(ttype)) { 
-      return "void " + prefix + tfunction->get_name() + "(" + type_name(ttype) 
-             + (name_params ? "& _return" : "& /* _return */") 
-             + argument_list(arglist, name_params, true) + ")"; 
-    } else { 
-      return type_name(ttype) + " " + prefix + tfunction->get_name() + "(" 
-             + argument_list(arglist, name_params) + ")"; 
-    } 
-  } else if (style.substr(0, 3) == "Cob") { 
-    string cob_type; 
-    string exn_cob; 
-    if (style == "CobCl") { 
-      cob_type = "(" + service_name_ + "CobClient"; 
-      if (gen_templates_) { 
-        cob_type += "T<Protocol_>"; 
-      } 
-      cob_type += "* client)"; 
-    } else if (style == "CobSv") { 
-      cob_type = (ttype->is_void() ? "()" : ("(" + type_name(ttype) + " const& _return)")); 
-      if (has_xceptions) { 
-        exn_cob 
-            = ", ::apache::thrift::stdcxx::function<void(::apache::thrift::TDelayedException* _throw)> /* exn_cob */"; 
-      } 
-    } else { 
-      throw "UNKNOWN STYLE"; 
-    } 
- 
-    return "void " + prefix + tfunction->get_name() + "(::apache::thrift::stdcxx::function<void" + cob_type + "> cob" 
-           + exn_cob + argument_list(arglist, name_params, true) + ")"; 
-  } else { 
-    throw "UNKNOWN STYLE"; 
-  } 
-} 
- 
-/** 
- * Renders a field list 
- * 
- * @param tstruct The struct definition 
- * @return Comma sepearated list of all field names in that struct 
- */ 
-string t_cpp_generator::argument_list(t_struct* tstruct, bool name_params, bool start_comma) { 
-  string result = ""; 
- 
-  const vector<t_field*>& fields = tstruct->get_members(); 
-  vector<t_field*>::const_iterator f_iter; 
-  bool first = !start_comma; 
-  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { 
-    if (first) { 
-      first = false; 
-    } else { 
-      result += ", "; 
-    } 
-    result += type_name((*f_iter)->get_type(), false, true) + " " 
-              + (name_params ? (*f_iter)->get_name() : "/* " + (*f_iter)->get_name() + " */"); 
-  } 
-  return result; 
-} 
- 
-/** 
- * Converts the parse type to a C++ enum string for the given type. 
- * 
- * @param type Thrift Type 
- * @return String of C++ code to definition of that type constant 
- */ 
-string t_cpp_generator::type_to_enum(t_type* type) { 
-  type = get_true_type(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: 
-      throw "NO T_VOID CONSTRUCT"; 
-    case t_base_type::TYPE_STRING: 
-      return "::apache::thrift::protocol::T_STRING"; 
-    case t_base_type::TYPE_BOOL: 
-      return "::apache::thrift::protocol::T_BOOL"; 
-    case t_base_type::TYPE_I8: 
-      return "::apache::thrift::protocol::T_BYTE"; 
-    case t_base_type::TYPE_I16: 
-      return "::apache::thrift::protocol::T_I16"; 
-    case t_base_type::TYPE_I32: 
-      return "::apache::thrift::protocol::T_I32"; 
-    case t_base_type::TYPE_I64: 
-      return "::apache::thrift::protocol::T_I64"; 
-    case t_base_type::TYPE_DOUBLE: 
-      return "::apache::thrift::protocol::T_DOUBLE"; 
-    } 
-  } else if (type->is_enum()) { 
-    return "::apache::thrift::protocol::T_I32"; 
-  } else if (type->is_struct()) { 
-    return "::apache::thrift::protocol::T_STRUCT"; 
-  } else if (type->is_xception()) { 
-    return "::apache::thrift::protocol::T_STRUCT"; 
-  } else if (type->is_map()) { 
-    return "::apache::thrift::protocol::T_MAP"; 
-  } else if (type->is_set()) { 
-    return "::apache::thrift::protocol::T_SET"; 
-  } else if (type->is_list()) { 
-    return "::apache::thrift::protocol::T_LIST"; 
-  } 
- 
-  throw "INVALID TYPE IN type_to_enum: " + type->get_name(); 
-} 
- 
-string t_cpp_generator::get_include_prefix(const t_program& program) const { 
-  string include_prefix = program.get_include_prefix(); 
-  if (!use_include_prefix_ || (include_prefix.size() > 0 && include_prefix[0] == '/')) { 
-    // if flag is turned off or this is absolute path, return empty prefix 
-    return ""; 
-  } 
- 
-  string::size_type last_slash = string::npos; 
-  if ((last_slash = include_prefix.rfind("/")) != string::npos) { 
-    return include_prefix.substr(0, last_slash) 
-           + (get_program()->is_out_path_absolute() ? "/" : "/" + out_dir_base_ + "/"); 
-  } 
- 
-  return ""; 
-} 
- 
-THRIFT_REGISTER_GENERATOR( 
-    cpp, 
-    "C++", 
-    "    cob_style:       Generate \"Continuation OBject\"-style classes.\n" 
-    "    no_client_completion:\n" 
-    "                     Omit calls to completion__() in CobClient class.\n" 
-    "    no_default_operators:\n" 
-    "                     Omits generation of default operators ==, != and <\n" 
-    "    templates:       Generate templatized reader/writer methods.\n" 
-    "    pure_enums:      Generate pure enums instead of wrapper classes.\n" 
-    "    include_prefix:  Use full include paths in generated files.\n" 
-    "    moveable_types:  Generate move constructors and assignment operators.\n" 
-    "    no_ostream_operators:\n" 
-    "                     Omit generation of ostream definitions.\n" 
-    "    no_skeleton:     Omits generation of skeleton.\n") 
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ * Contains some contributions under the Thrift Software License.
+ * Please see doc/old-thrift-license.txt in the Thrift distribution for
+ * details.
+ */
+
+#include <cassert>
+
+#include <fstream>
+#include <iomanip>
+#include <iostream>
+#include <limits>
+#include <sstream>
+#include <string>
+#include <vector>
+
+#include <sys/stat.h>
+
+#include "thrift/platform.h"
+#include "thrift/generate/t_oop_generator.h"
+
+using std::map;
+using std::ofstream;
+using std::ostream;
+using std::string;
+using std::vector;
+
+static const string endl = "\n"; // avoid ostream << std::endl flushes
+
+/**
+ * C++ code generator. This is legitimacy incarnate.
+ *
+ */
+class t_cpp_generator : public t_oop_generator {
+public:
+  t_cpp_generator(t_program* program,
+                  const std::map<std::string, std::string>& parsed_options,
+                  const std::string& option_string)
+    : t_oop_generator(program) {
+    (void)option_string;
+    std::map<std::string, std::string>::const_iterator iter;
+
+
+    gen_pure_enums_ = false;
+    use_include_prefix_ = false;
+    gen_cob_style_ = false;
+    gen_no_client_completion_ = false;
+    gen_no_default_operators_ = false;
+    gen_templates_ = false;
+    gen_templates_only_ = false;
+    gen_moveable_ = false;
+    gen_no_ostream_operators_ = false;
+    gen_no_skeleton_ = false;
+
+    for( iter = parsed_options.begin(); iter != parsed_options.end(); ++iter) {
+      if( iter->first.compare("pure_enums") == 0) {
+        gen_pure_enums_ = true;
+      } else if( iter->first.compare("include_prefix") == 0) {
+        use_include_prefix_ = true;
+      } else if( iter->first.compare("cob_style") == 0) {
+        gen_cob_style_ = true;
+      } else if( iter->first.compare("no_client_completion") == 0) {
+        gen_no_client_completion_ = true;
+      } else if( iter->first.compare("no_default_operators") == 0) {
+        gen_no_default_operators_ = true;
+      } else if( iter->first.compare("templates") == 0) {
+        gen_templates_ = true;
+        gen_templates_only_ = (iter->second == "only");
+      } else if( iter->first.compare("moveable_types") == 0) {
+        gen_moveable_ = true;
+      } else if ( iter->first.compare("no_ostream_operators") == 0) {
+        gen_no_ostream_operators_ = true;
+      } else if ( iter->first.compare("no_skeleton") == 0) {
+        gen_no_skeleton_ = true;
+      } else {
+        throw "unknown option cpp:" + iter->first;
+      }
+    }
+
+    out_dir_base_ = "gen-cpp";
+  }
+
+  /**
+   * Init and close methods
+   */
+
+  void init_generator();
+  void close_generator();
+
+  void generate_consts(std::vector<t_const*> consts);
+
+  /**
+   * Program-level generation functions
+   */
+
+  void generate_typedef(t_typedef* ttypedef);
+  void generate_enum(t_enum* tenum);
+  void generate_enum_ostream_operator_decl(std::ostream& out, t_enum* tenum);
+  void generate_enum_ostream_operator(std::ostream& out, t_enum* tenum);
+  void generate_forward_declaration(t_struct* tstruct);
+  void generate_struct(t_struct* tstruct) { generate_cpp_struct(tstruct, false); }
+  void generate_xception(t_struct* txception) { generate_cpp_struct(txception, true); }
+  void generate_cpp_struct(t_struct* tstruct, bool is_exception);
+
+  void generate_service(t_service* tservice);
+
+  void print_const_value(std::ostream& out, std::string name, t_type* type, t_const_value* value);
+  std::string render_const_value(std::ostream& out,
+                                 std::string name,
+                                 t_type* type,
+                                 t_const_value* value);
+
+  void generate_struct_declaration(std::ostream& out,
+                                   t_struct* tstruct,
+                                   bool is_exception = false,
+                                   bool pointers = false,
+                                   bool read = true,
+                                   bool write = true,
+                                   bool swap = false,
+                                   bool is_user_struct = false);
+  void generate_struct_definition(std::ostream& out,
+                                  std::ostream& force_cpp_out,
+                                  t_struct* tstruct,
+                                  bool setters = true,
+                                  bool is_user_struct = false);
+  void generate_copy_constructor(std::ostream& out, t_struct* tstruct, bool is_exception);
+  void generate_move_constructor(std::ostream& out, t_struct* tstruct, bool is_exception);
+  void generate_constructor_helper(std::ostream& out,
+                                   t_struct* tstruct,
+                                   bool is_excpetion,
+                                   bool is_move);
+  void generate_assignment_operator(std::ostream& out, t_struct* tstruct);
+  void generate_move_assignment_operator(std::ostream& out, t_struct* tstruct);
+  void generate_assignment_helper(std::ostream& out, t_struct* tstruct, bool is_move);
+  void generate_struct_reader(std::ostream& out, t_struct* tstruct, bool pointers = false);
+  void generate_struct_writer(std::ostream& out, t_struct* tstruct, bool pointers = false);
+  void generate_struct_result_writer(std::ostream& out, t_struct* tstruct, bool pointers = false);
+  void generate_struct_swap(std::ostream& out, t_struct* tstruct);
+  void generate_struct_print_method(std::ostream& out, t_struct* tstruct);
+  void generate_exception_what_method(std::ostream& out, t_struct* tstruct);
+
+  /**
+   * Service-level generation functions
+   */
+
+  void generate_service_interface(t_service* tservice, string style);
+  void generate_service_interface_factory(t_service* tservice, string style);
+  void generate_service_null(t_service* tservice, string style);
+  void generate_service_multiface(t_service* tservice);
+  void generate_service_helpers(t_service* tservice);
+  void generate_service_client(t_service* tservice, string style);
+  void generate_service_processor(t_service* tservice, string style);
+  void generate_service_skeleton(t_service* tservice);
+  void generate_process_function(t_service* tservice,
+                                 t_function* tfunction,
+                                 string style,
+                                 bool specialized = false);
+  void generate_function_helpers(t_service* tservice, t_function* tfunction);
+  void generate_service_async_skeleton(t_service* tservice);
+
+  /**
+   * Serialization constructs
+   */
+
+  void generate_deserialize_field(std::ostream& out,
+                                  t_field* tfield,
+                                  std::string prefix = "",
+                                  std::string suffix = "");
+
+  void generate_deserialize_struct(std::ostream& out,
+                                   t_struct* tstruct,
+                                   std::string prefix = "",
+                                   bool pointer = false);
+
+  void generate_deserialize_container(std::ostream& out, t_type* ttype, std::string prefix = "");
+
+  void generate_deserialize_set_element(std::ostream& out, t_set* tset, std::string prefix = "");
+
+  void generate_deserialize_map_element(std::ostream& out, t_map* tmap, std::string prefix = "");
+
+  void generate_deserialize_list_element(std::ostream& out,
+                                         t_list* tlist,
+                                         std::string prefix,
+                                         bool push_back,
+                                         std::string index);
+
+  void generate_serialize_field(std::ostream& out,
+                                t_field* tfield,
+                                std::string prefix = "",
+                                std::string suffix = "");
+
+  void generate_serialize_struct(std::ostream& out,
+                                 t_struct* tstruct,
+                                 std::string prefix = "",
+                                 bool pointer = false);
+
+  void generate_serialize_container(std::ostream& out, t_type* ttype, std::string prefix = "");
+
+  void generate_serialize_map_element(std::ostream& out, t_map* tmap, std::string iter);
+
+  void generate_serialize_set_element(std::ostream& out, t_set* tmap, std::string iter);
+
+  void generate_serialize_list_element(std::ostream& out, t_list* tlist, std::string iter);
+
+  void generate_function_call(ostream& out,
+                              t_function* tfunction,
+                              string target,
+                              string iface,
+                              string arg_prefix);
+  /*
+   * Helper rendering functions
+   */
+
+  std::string namespace_prefix(std::string ns);
+  std::string namespace_open(std::string ns);
+  std::string namespace_close(std::string ns);
+  std::string type_name(t_type* ttype, bool in_typedef = false, bool arg = false);
+  std::string base_type_name(t_base_type::t_base tbase);
+  std::string declare_field(t_field* tfield,
+                            bool init = false,
+                            bool pointer = false,
+                            bool constant = false,
+                            bool reference = false);
+  std::string function_signature(t_function* tfunction,
+                                 std::string style,
+                                 std::string prefix = "",
+                                 bool name_params = true);
+  std::string cob_function_signature(t_function* tfunction,
+                                     std::string prefix = "",
+                                     bool name_params = true);
+  std::string argument_list(t_struct* tstruct, bool name_params = true, bool start_comma = false);
+  std::string type_to_enum(t_type* ttype);
+
+  void generate_enum_constant_list(std::ostream& f,
+                                   const vector<t_enum_value*>& constants,
+                                   const char* prefix,
+                                   const char* suffix,
+                                   bool include_values);
+
+  void generate_struct_ostream_operator_decl(std::ostream& f, t_struct* tstruct);
+  void generate_struct_ostream_operator(std::ostream& f, t_struct* tstruct);
+  void generate_struct_print_method_decl(std::ostream& f, t_struct* tstruct);
+  void generate_exception_what_method_decl(std::ostream& f,
+                                           t_struct* tstruct,
+                                           bool external = false);
+
+  bool is_reference(t_field* tfield) { return tfield->get_reference(); }
+
+  bool is_complex_type(t_type* ttype) {
+    ttype = get_true_type(ttype);
+
+    return ttype->is_container() || ttype->is_struct() || ttype->is_xception()
+           || (ttype->is_base_type()
+               && (((t_base_type*)ttype)->get_base() == t_base_type::TYPE_STRING));
+  }
+
+  void set_use_include_prefix(bool use_include_prefix) { use_include_prefix_ = use_include_prefix; }
+
+  /**
+   * The compiler option "no_thrift_ostream_impl" can be used to prevent
+   * the compiler from emitting implementations for operator <<.  In this
+   * case the consuming application must provide any needed to build.
+   *
+   * To disable this on a per structure bases, one can alternatively set
+   * the annotation "cpp.customostream" to prevent thrift from emitting an
+   * operator << (std::ostream&).
+   *
+   * See AnnotationTest for validation of this annotation feature.
+   */
+  bool has_custom_ostream(t_type* ttype) const {
+    return (gen_no_ostream_operators_) ||
+           (ttype->annotations_.find("cpp.customostream") != ttype->annotations_.end());
+  }
+
+private:
+  /**
+   * Returns the include prefix to use for a file generated by program, or the
+   * empty string if no include prefix should be used.
+   */
+  std::string get_include_prefix(const t_program& program) const;
+
+  /**
+   * True if we should generate pure enums for Thrift enums, instead of wrapper classes.
+   */
+  bool gen_pure_enums_;
+
+  /**
+   * True if we should generate templatized reader/writer methods.
+   */
+  bool gen_templates_;
+
+  /**
+   * True iff we should generate process function pointers for only templatized
+   * reader/writer methods.
+   */
+  bool gen_templates_only_;
+
+  /**
+   * True if we should generate move constructors & assignment operators.
+   */
+  bool gen_moveable_;
+
+  /**
+   * True if we should generate ostream definitions
+   */
+  bool gen_no_ostream_operators_;
+
+  /**
+   * True iff we should use a path prefix in our #include statements for other
+   * thrift-generated header files.
+   */
+  bool use_include_prefix_;
+
+  /**
+   * True if we should generate "Continuation OBject"-style classes as well.
+   */
+  bool gen_cob_style_;
+
+  /**
+   * True if we should omit calls to completion__() in CobClient class.
+   */
+  bool gen_no_client_completion_;
+
+  /**
+   * True if we should omit generating the default opeartors ==, != and <.
+   */
+  bool gen_no_default_operators_;
+
+   /**
+   * True if we should generate skeleton.
+   */
+  bool gen_no_skeleton_;
+
+  /**
+   * Strings for namespace, computed once up front then used directly
+   */
+
+  std::string ns_open_;
+  std::string ns_close_;
+
+  /**
+   * File streams, stored here to avoid passing them as parameters to every
+   * function.
+   */
+
+  ofstream_with_content_based_conditional_update f_types_;
+  ofstream_with_content_based_conditional_update f_types_impl_;
+  ofstream_with_content_based_conditional_update f_types_tcc_;
+  ofstream_with_content_based_conditional_update f_header_;
+  ofstream_with_content_based_conditional_update f_service_;
+  ofstream_with_content_based_conditional_update f_service_tcc_;
+
+  // The ProcessorGenerator is used to generate parts of the code,
+  // so it needs access to many of our protected members and methods.
+  //
+  // TODO: The code really should be cleaned up so that helper methods for
+  // writing to the output files are separate from the generator classes
+  // themselves.
+  friend class ProcessorGenerator;
+};
+
+/**
+ * Prepares for file generation by opening up the necessary file output
+ * streams.
+ */
+void t_cpp_generator::init_generator() {
+  // Make output directory
+  MKDIR(get_out_dir().c_str());
+
+  // Make output file
+  string f_types_name = get_out_dir() + program_name_ + "_types.h";
+  f_types_.open(f_types_name);
+
+  string f_types_impl_name = get_out_dir() + program_name_ + "_types.cpp";
+  f_types_impl_.open(f_types_impl_name.c_str());
+
+  if (gen_templates_) {
+    // If we don't open the stream, it appears to just discard data,
+    // which is fine.
+    string f_types_tcc_name = get_out_dir() + program_name_ + "_types.tcc";
+    f_types_tcc_.open(f_types_tcc_name.c_str());
+  }
+
+  // Print header
+  f_types_ << autogen_comment();
+  f_types_impl_ << autogen_comment();
+  f_types_tcc_ << autogen_comment();
+
+  // Start ifndef
+  f_types_ << "#ifndef " << program_name_ << "_TYPES_H" << endl << "#define " << program_name_
+           << "_TYPES_H" << endl << endl;
+  f_types_tcc_ << "#ifndef " << program_name_ << "_TYPES_TCC" << endl << "#define " << program_name_
+               << "_TYPES_TCC" << endl << endl;
+
+  // Include base types
+  f_types_ << "#include <iosfwd>" << endl
+           << endl
+           << "#include <thrift/Thrift.h>" << endl
+           << "#include <thrift/TApplicationException.h>" << endl
+           << "#include <thrift/TBase.h>" << endl
+           << "#include <thrift/protocol/TProtocol.h>" << endl
+           << "#include <thrift/transport/TTransport.h>" << endl
+           << endl;
+  // Include C++xx compatibility header
+  f_types_ << "#include <thrift/stdcxx.h>" << endl;
+
+  // Include other Thrift includes
+  const vector<t_program*>& includes = program_->get_includes();
+  for (size_t i = 0; i < includes.size(); ++i) {
+    f_types_ << "#include \"" << get_include_prefix(*(includes[i])) << includes[i]->get_name()
+             << "_types.h\"" << endl;
+
+    // XXX(simpkins): If gen_templates_ is enabled, we currently assume all
+    // included files were also generated with templates enabled.
+    f_types_tcc_ << "#include \"" << get_include_prefix(*(includes[i])) << includes[i]->get_name()
+                 << "_types.tcc\"" << endl;
+  }
+  f_types_ << endl;
+
+  // Include custom headers
+  const vector<string>& cpp_includes = program_->get_cpp_includes();
+  for (size_t i = 0; i < cpp_includes.size(); ++i) {
+    if (cpp_includes[i][0] == '<') {
+      f_types_ << "#include " << cpp_includes[i] << endl;
+    } else {
+      f_types_ << "#include \"" << cpp_includes[i] << "\"" << endl;
+    }
+  }
+  f_types_ << endl;
+
+  // Include the types file
+  f_types_impl_ << "#include \"" << get_include_prefix(*get_program()) << program_name_
+                << "_types.h\"" << endl << endl;
+  f_types_tcc_ << "#include \"" << get_include_prefix(*get_program()) << program_name_
+               << "_types.h\"" << endl << endl;
+
+  // The swap() code needs <algorithm> for std::swap()
+  f_types_impl_ << "#include <algorithm>" << endl;
+  // for operator<<
+  f_types_impl_ << "#include <ostream>" << endl << endl;
+  f_types_impl_ << "#include <thrift/TToString.h>" << endl << endl;
+
+  // Open namespace
+  ns_open_ = namespace_open(program_->get_namespace("cpp"));
+  ns_close_ = namespace_close(program_->get_namespace("cpp"));
+
+  f_types_ << ns_open_ << endl << endl;
+
+  f_types_impl_ << ns_open_ << endl << endl;
+
+  f_types_tcc_ << ns_open_ << endl << endl;
+}
+
+/**
+ * Closes the output files.
+ */
+void t_cpp_generator::close_generator() {
+  // Close namespace
+  f_types_ << ns_close_ << endl << endl;
+  f_types_impl_ << ns_close_ << endl;
+  f_types_tcc_ << ns_close_ << endl << endl;
+
+  // Include the types.tcc file from the types header file,
+  // so clients don't have to explicitly include the tcc file.
+  // TODO(simpkins): Make this a separate option.
+  if (gen_templates_) {
+    f_types_ << "#include \"" << get_include_prefix(*get_program()) << program_name_
+             << "_types.tcc\"" << endl << endl;
+  }
+
+  // Close ifndef
+  f_types_ << "#endif" << endl;
+  f_types_tcc_ << "#endif" << endl;
+
+  // Close output file
+  f_types_.close();
+  f_types_impl_.close();
+  f_types_tcc_.close();
+}
+
+/**
+ * Generates a typedef. This is just a simple 1-liner in C++
+ *
+ * @param ttypedef The type definition
+ */
+void t_cpp_generator::generate_typedef(t_typedef* ttypedef) {
+  f_types_ << indent() << "typedef " << type_name(ttypedef->get_type(), true) << " "
+           << ttypedef->get_symbolic() << ";" << endl << endl;
+}
+
+void t_cpp_generator::generate_enum_constant_list(std::ostream& f,
+                                                  const vector<t_enum_value*>& constants,
+                                                  const char* prefix,
+                                                  const char* suffix,
+                                                  bool include_values) {
+  f << " {" << endl;
+  indent_up();
+
+  vector<t_enum_value*>::const_iterator c_iter;
+  bool first = true;
+  for (c_iter = constants.begin(); c_iter != constants.end(); ++c_iter) {
+    if (first) {
+      first = false;
+    } else {
+      f << "," << endl;
+    }
+    indent(f) << prefix << (*c_iter)->get_name() << suffix;
+    if (include_values) {
+      f << " = " << (*c_iter)->get_value();
+    }
+  }
+
+  f << endl;
+  indent_down();
+  indent(f) << "};" << endl;
+}
+
+/**
+ * Generates code for an enumerated type. In C++, this is essentially the same
+ * as the thrift definition itself, using the enum keyword in C++.
+ *
+ * @param tenum The enumeration
+ */
+void t_cpp_generator::generate_enum(t_enum* tenum) {
+  vector<t_enum_value*> constants = tenum->get_constants();
+
+  std::string enum_name = tenum->get_name();
+  if (!gen_pure_enums_) {
+    enum_name = "type";
+    f_types_ << indent() << "struct " << tenum->get_name() << " {" << endl;
+    indent_up();
+  }
+  f_types_ << indent() << "enum " << enum_name;
+
+  generate_enum_constant_list(f_types_, constants, "", "", true);
+
+  if (!gen_pure_enums_) {
+    indent_down();
+    f_types_ << "};" << endl;
+  }
+
+  f_types_ << endl;
+
+  /**
+     Generate a character array of enum names for debugging purposes.
+  */
+  std::string prefix = "";
+  if (!gen_pure_enums_) {
+    prefix = tenum->get_name() + "::";
+  }
+
+  f_types_impl_ << indent() << "int _k" << tenum->get_name() << "Values[] =";
+  generate_enum_constant_list(f_types_impl_, constants, prefix.c_str(), "", false);
+
+  f_types_impl_ << indent() << "const char* _k" << tenum->get_name() << "Names[] =";
+  generate_enum_constant_list(f_types_impl_, constants, "\"", "\"", false);
+
+  f_types_ << indent() << "extern const std::map<int, const char*> _" << tenum->get_name()
+           << "_VALUES_TO_NAMES;" << endl << endl;
+
+  f_types_impl_ << indent() << "const std::map<int, const char*> _" << tenum->get_name()
+                << "_VALUES_TO_NAMES(::apache::thrift::TEnumIterator(" << constants.size() << ", _k"
+                << tenum->get_name() << "Values"
+                << ", _k" << tenum->get_name() << "Names), "
+                << "::apache::thrift::TEnumIterator(-1, NULL, NULL));" << endl << endl;
+
+  generate_enum_ostream_operator_decl(f_types_, tenum);
+  generate_enum_ostream_operator(f_types_impl_, tenum);
+}
+
+void t_cpp_generator::generate_enum_ostream_operator_decl(std::ostream& out, t_enum* tenum) {
+
+  out << "std::ostream& operator<<(std::ostream& out, const ";
+  if (gen_pure_enums_) {
+    out << tenum->get_name();
+  } else {
+    out << tenum->get_name() << "::type&";
+  }
+  out << " val);" << endl;
+  out << endl;
+}
+
+void t_cpp_generator::generate_enum_ostream_operator(std::ostream& out, t_enum* tenum) {
+
+  // If we've been told the consuming application will provide an ostream
+  // operator definition then we only make a declaration:
+
+  if (!has_custom_ostream(tenum)) {
+    out << "std::ostream& operator<<(std::ostream& out, const ";
+    if (gen_pure_enums_) {
+      out << tenum->get_name();
+    } else {
+      out << tenum->get_name() << "::type&";
+    }
+    out << " val) ";
+    scope_up(out);
+
+    out << indent() << "std::map<int, const char*>::const_iterator it = _"
+             << tenum->get_name() << "_VALUES_TO_NAMES.find(val);" << endl;
+    out << indent() << "if (it != _" << tenum->get_name() << "_VALUES_TO_NAMES.end()) {" << endl;
+    indent_up();
+    out << indent() << "out << it->second;" << endl;
+    indent_down();
+    out << indent() << "} else {" << endl;
+    indent_up();
+    out << indent() << "out << static_cast<int>(val);" << endl;
+    indent_down();
+    out << indent() << "}" << endl;
+
+    out << indent() << "return out;" << endl;
+    scope_down(out);
+    out << endl;
+  }
+}
+
+/**
+ * Generates a class that holds all the constants.
+ */
+void t_cpp_generator::generate_consts(std::vector<t_const*> consts) {
+  string f_consts_name = get_out_dir() + program_name_ + "_constants.h";
+  ofstream_with_content_based_conditional_update f_consts;
+  f_consts.open(f_consts_name);
+
+  string f_consts_impl_name = get_out_dir() + program_name_ + "_constants.cpp";
+  ofstream_with_content_based_conditional_update f_consts_impl;
+  f_consts_impl.open(f_consts_impl_name);
+
+  // Print header
+  f_consts << autogen_comment();
+  f_consts_impl << autogen_comment();
+
+  // Start ifndef
+  f_consts << "#ifndef " << program_name_ << "_CONSTANTS_H" << endl << "#define " << program_name_
+           << "_CONSTANTS_H" << endl << endl << "#include \"" << get_include_prefix(*get_program())
+           << program_name_ << "_types.h\"" << endl << endl << ns_open_ << endl << endl;
+
+  f_consts_impl << "#include \"" << get_include_prefix(*get_program()) << program_name_
+                << "_constants.h\"" << endl << endl << ns_open_ << endl << endl;
+
+  f_consts << "class " << program_name_ << "Constants {" << endl << " public:" << endl << "  "
+           << program_name_ << "Constants();" << endl << endl;
+  indent_up();
+  vector<t_const*>::iterator c_iter;
+  for (c_iter = consts.begin(); c_iter != consts.end(); ++c_iter) {
+    string name = (*c_iter)->get_name();
+    t_type* type = (*c_iter)->get_type();
+    f_consts << indent() << type_name(type) << " " << name << ";" << endl;
+  }
+  indent_down();
+  f_consts << "};" << endl;
+
+  f_consts_impl << "const " << program_name_ << "Constants g_" << program_name_ << "_constants;"
+                << endl << endl << program_name_ << "Constants::" << program_name_
+                << "Constants() {" << endl;
+  indent_up();
+  for (c_iter = consts.begin(); c_iter != consts.end(); ++c_iter) {
+    print_const_value(f_consts_impl,
+                      (*c_iter)->get_name(),
+                      (*c_iter)->get_type(),
+                      (*c_iter)->get_value());
+  }
+  indent_down();
+  indent(f_consts_impl) << "}" << endl;
+
+  f_consts << endl << "extern const " << program_name_ << "Constants g_" << program_name_
+           << "_constants;" << endl << endl << ns_close_ << endl << endl << "#endif" << endl;
+  f_consts.close();
+
+  f_consts_impl << endl << ns_close_ << endl << endl;
+  f_consts_impl.close();
+}
+
+/**
+ * Prints the value of a constant with the given type. Note that type checking
+ * is NOT performed in this function as it is always run beforehand using the
+ * validate_types method in main.cc
+ */
+void t_cpp_generator::print_const_value(ostream& out,
+                                        string name,
+                                        t_type* type,
+                                        t_const_value* value) {
+  type = get_true_type(type);
+  if (type->is_base_type()) {
+    string v2 = render_const_value(out, name, type, value);
+    indent(out) << name << " = " << v2 << ";" << endl << endl;
+  } else if (type->is_enum()) {
+    indent(out) << name << " = (" << type_name(type) << ")" << 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*, t_const_value::value_compare>& val = value->get_map();
+    map<t_const_value*, t_const_value*, t_const_value::value_compare>::const_iterator v_iter;
+    bool is_nonrequired_field = false;
+    for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
+      t_type* field_type = NULL;
+      is_nonrequired_field = false;
+      for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+        if ((*f_iter)->get_name() == v_iter->first->get_string()) {
+          field_type = (*f_iter)->get_type();
+          is_nonrequired_field = (*f_iter)->get_req() != t_field::T_REQUIRED;
+        }
+      }
+      if (field_type == NULL) {
+        throw "type error: " + type->get_name() + " has no field " + v_iter->first->get_string();
+      }
+      string val = render_const_value(out, name, field_type, v_iter->second);
+      indent(out) << name << "." << v_iter->first->get_string() << " = " << val << ";" << endl;
+      if (is_nonrequired_field) {
+        indent(out) << name << ".__isset." << v_iter->first->get_string() << " = true;" << endl;
+      }
+    }
+    out << endl;
+  } else if (type->is_map()) {
+    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*, t_const_value::value_compare>& val = value->get_map();
+    map<t_const_value*, t_const_value*, t_const_value::value_compare>::const_iterator v_iter;
+    for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
+      string key = render_const_value(out, name, ktype, v_iter->first);
+      string val = render_const_value(out, name, vtype, v_iter->second);
+      indent(out) << name << ".insert(std::make_pair(" << key << ", " << val << "));" << endl;
+    }
+    out << endl;
+  } else if (type->is_list()) {
+    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;
+    for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
+      string val = render_const_value(out, name, etype, *v_iter);
+      indent(out) << name << ".push_back(" << val << ");" << endl;
+    }
+    out << endl;
+  } else if (type->is_set()) {
+    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;
+    for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
+      string val = render_const_value(out, name, etype, *v_iter);
+      indent(out) << name << ".insert(" << val << ");" << endl;
+    }
+    out << endl;
+  } else {
+    throw "INVALID TYPE IN print_const_value: " + type->get_name();
+  }
+}
+
+/**
+ *
+ */
+string t_cpp_generator::render_const_value(ostream& out,
+                                           string name,
+                                           t_type* type,
+                                           t_const_value* value) {
+  (void)name;
+  std::ostringstream render;
+
+  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:
+      render << '"' << get_escaped_string(value) << '"';
+      break;
+    case t_base_type::TYPE_BOOL:
+      render << ((value->get_integer() > 0) ? "true" : "false");
+      break;
+    case t_base_type::TYPE_I8:
+    case t_base_type::TYPE_I16:
+    case t_base_type::TYPE_I32:
+      render << value->get_integer();
+      break;
+    case t_base_type::TYPE_I64:
+      render << value->get_integer() << "LL";
+      break;
+    case t_base_type::TYPE_DOUBLE:
+      if (value->get_type() == t_const_value::CV_INTEGER) {
+        render << "static_cast<double>(" << value->get_integer() << ")";
+      } else {
+        render << emit_double_as_string(value->get_double());
+      }
+      break;
+    default:
+      throw "compiler error: no const of base type " + t_base_type::t_base_name(tbase);
+    }
+  } else if (type->is_enum()) {
+    render << "(" << type_name(type) << ")" << value->get_integer();
+  } else {
+    string t = tmp("tmp");
+    indent(out) << type_name(type) << " " << t << ";" << endl;
+    print_const_value(out, t, type, value);
+    render << t;
+  }
+
+  return render.str();
+}
+
+void t_cpp_generator::generate_forward_declaration(t_struct* tstruct) {
+  // Forward declare struct def
+  f_types_ << indent() << "class " << tstruct->get_name() << ";" << endl << endl;
+}
+
+/**
+ * Generates a struct definition for a thrift data type. This is a class
+ * with data members and a read/write() function, plus a mirroring isset
+ * inner class.
+ *
+ * @param tstruct The struct definition
+ */
+void t_cpp_generator::generate_cpp_struct(t_struct* tstruct, bool is_exception) {
+  generate_struct_declaration(f_types_, tstruct, is_exception, false, true, true, true, true);
+  generate_struct_definition(f_types_impl_, f_types_impl_, tstruct, true, true);
+
+  std::ostream& out = (gen_templates_ ? f_types_tcc_ : f_types_impl_);
+  generate_struct_reader(out, tstruct);
+  generate_struct_writer(out, tstruct);
+  generate_struct_swap(f_types_impl_, tstruct);
+  generate_copy_constructor(f_types_impl_, tstruct, is_exception);
+  if (gen_moveable_) {
+    generate_move_constructor(f_types_impl_, tstruct, is_exception);
+  }
+  generate_assignment_operator(f_types_impl_, tstruct);
+  if (gen_moveable_) {
+    generate_move_assignment_operator(f_types_impl_, tstruct);
+  }
+
+  if (!has_custom_ostream(tstruct)) {
+    generate_struct_print_method(f_types_impl_, tstruct);
+  }
+
+  if (is_exception) {
+    generate_exception_what_method(f_types_impl_, tstruct);
+  }
+}
+
+void t_cpp_generator::generate_copy_constructor(ostream& out,
+                                                t_struct* tstruct,
+                                                bool is_exception) {
+  generate_constructor_helper(out, tstruct, is_exception, /*is_move=*/false);
+}
+
+void t_cpp_generator::generate_move_constructor(ostream& out,
+                                                t_struct* tstruct,
+                                                bool is_exception) {
+  generate_constructor_helper(out, tstruct, is_exception, /*is_move=*/true);
+}
+
+namespace {
+// Helper to convert a variable to rvalue, if move is enabled
+std::string maybeMove(std::string const& other, bool move) {
+  if (move) {
+    return "std::move(" + other + ")";
+  }
+  return other;
+}
+}
+
+void t_cpp_generator::generate_constructor_helper(ostream& out,
+                                                  t_struct* tstruct,
+                                                  bool is_exception,
+                                                  bool is_move) {
+
+  std::string tmp_name = tmp("other");
+
+  indent(out) << tstruct->get_name() << "::" << tstruct->get_name();
+
+  if (is_move) {
+    out << "( " << tstruct->get_name() << "&& ";
+  } else {
+    out << "(const " << tstruct->get_name() << "& ";
+  }
+  out << tmp_name << ") ";
+  if (is_exception)
+    out << ": TException() ";
+  out << "{" << endl;
+  indent_up();
+
+  const vector<t_field*>& members = tstruct->get_members();
+
+  // eliminate compiler unused warning
+  if (members.empty())
+    indent(out) << "(void) " << tmp_name << ";" << endl;
+
+  vector<t_field*>::const_iterator f_iter;
+  bool has_nonrequired_fields = false;
+  for (f_iter = members.begin(); f_iter != members.end(); ++f_iter) {
+    if ((*f_iter)->get_req() != t_field::T_REQUIRED)
+      has_nonrequired_fields = true;
+    indent(out) << (*f_iter)->get_name() << " = "
+                << maybeMove(tmp_name + "." + (*f_iter)->get_name(), is_move) << ";" << endl;
+  }
+
+  if (has_nonrequired_fields) {
+    indent(out) << "__isset = " << maybeMove(tmp_name + ".__isset", is_move) << ";" << endl;
+  }
+
+  indent_down();
+  indent(out) << "}" << endl;
+}
+
+void t_cpp_generator::generate_assignment_operator(ostream& out, t_struct* tstruct) {
+  generate_assignment_helper(out, tstruct, /*is_move=*/false);
+}
+
+void t_cpp_generator::generate_move_assignment_operator(ostream& out, t_struct* tstruct) {
+  generate_assignment_helper(out, tstruct, /*is_move=*/true);
+}
+
+void t_cpp_generator::generate_assignment_helper(ostream& out, t_struct* tstruct, bool is_move) {
+  std::string tmp_name = tmp("other");
+
+  indent(out) << tstruct->get_name() << "& " << tstruct->get_name() << "::operator=(";
+
+  if (is_move) {
+    out << tstruct->get_name() << "&& ";
+  } else {
+    out << "const " << tstruct->get_name() << "& ";
+  }
+  out << tmp_name << ") {" << endl;
+
+  indent_up();
+
+  const vector<t_field*>& members = tstruct->get_members();
+
+  // eliminate compiler unused warning
+  if (members.empty())
+    indent(out) << "(void) " << tmp_name << ";" << endl;
+
+  vector<t_field*>::const_iterator f_iter;
+  bool has_nonrequired_fields = false;
+  for (f_iter = members.begin(); f_iter != members.end(); ++f_iter) {
+    if ((*f_iter)->get_req() != t_field::T_REQUIRED)
+      has_nonrequired_fields = true;
+    indent(out) << (*f_iter)->get_name() << " = "
+                << maybeMove(tmp_name + "." + (*f_iter)->get_name(), is_move) << ";" << endl;
+  }
+  if (has_nonrequired_fields) {
+    indent(out) << "__isset = " << maybeMove(tmp_name + ".__isset", is_move) << ";" << endl;
+  }
+
+  indent(out) << "return *this;" << endl;
+  indent_down();
+  indent(out) << "}" << endl;
+}
+
+/**
+ * Writes the struct declaration into the header file
+ *
+ * @param out Output stream
+ * @param tstruct The struct
+ */
+void t_cpp_generator::generate_struct_declaration(ostream& out,
+                                                  t_struct* tstruct,
+                                                  bool is_exception,
+                                                  bool pointers,
+                                                  bool read,
+                                                  bool write,
+                                                  bool swap,
+                                                  bool is_user_struct) {
+  string extends = "";
+  if (is_exception) {
+    extends = " : public ::apache::thrift::TException";
+  } else {
+    if (is_user_struct && !gen_templates_) {
+      extends = " : public virtual ::apache::thrift::TBase";
+    }
+  }
+
+  // Get members
+  vector<t_field*>::const_iterator m_iter;
+  const vector<t_field*>& members = tstruct->get_members();
+
+  // Write the isset structure declaration outside the class. This makes
+  // the generated code amenable to processing by SWIG.
+  // We only declare the struct if it gets used in the class.
+
+  // Isset struct has boolean fields, but only for non-required fields.
+  bool has_nonrequired_fields = false;
+  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
+    if ((*m_iter)->get_req() != t_field::T_REQUIRED)
+      has_nonrequired_fields = true;
+  }
+
+  if (has_nonrequired_fields && (!pointers || read)) {
+
+    out << indent() << "typedef struct _" << tstruct->get_name() << "__isset {" << endl;
+    indent_up();
+
+    indent(out) << "_" << tstruct->get_name() << "__isset() ";
+    bool first = true;
+    for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
+      if ((*m_iter)->get_req() == t_field::T_REQUIRED) {
+        continue;
+      }
+      string isSet = ((*m_iter)->get_value() != NULL) ? "true" : "false";
+      if (first) {
+        first = false;
+        out << ": " << (*m_iter)->get_name() << "(" << isSet << ")";
+      } else {
+        out << ", " << (*m_iter)->get_name() << "(" << isSet << ")";
+      }
+    }
+    out << " {}" << endl;
+
+    for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
+      if ((*m_iter)->get_req() != t_field::T_REQUIRED) {
+        indent(out) << "bool " << (*m_iter)->get_name() << " :1;" << endl;
+      }
+    }
+
+    indent_down();
+    indent(out) << "} _" << tstruct->get_name() << "__isset;" << endl;
+  }
+
+  out << endl;
+
+  // Open struct def
+  out << indent() << "class " << tstruct->get_name() << extends << " {" << endl << indent()
+      << " public:" << endl << endl;
+  indent_up();
+
+  if (!pointers) {
+    // Copy constructor
+    indent(out) << tstruct->get_name() << "(const " << tstruct->get_name() << "&);" << endl;
+
+    // Move constructor
+    if (gen_moveable_) {
+      indent(out) << tstruct->get_name() << "(" << tstruct->get_name() << "&&);" << endl;
+    }
+
+    // Assignment Operator
+    indent(out) << tstruct->get_name() << "& operator=(const " << tstruct->get_name() << "&);"
+                << endl;
+
+    // Move assignment operator
+    if (gen_moveable_) {
+      indent(out) << tstruct->get_name() << "& operator=(" << tstruct->get_name() << "&&);" << endl;
+    }
+
+    // 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 = get_true_type((*m_iter)->get_type());
+      if (t->is_base_type() || t->is_enum() || is_reference(*m_iter)) {
+        string dval;
+        if (t->is_enum()) {
+          dval += "(" + type_name(t) + ")";
+        }
+        dval += (t->is_string() || is_reference(*m_iter)) ? "" : "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;
+          out << " : ";
+          out << (*m_iter)->get_name() << "(" << dval << ")";
+        } else {
+          out << ", " << (*m_iter)->get_name() << "(" << dval << ")";
+        }
+      }
+    }
+    out << " {" << endl;
+    indent_up();
+    // TODO(dreiss): When everything else in Thrift is perfect,
+    // do more of these in the initializer list.
+    for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
+      t_type* t = get_true_type((*m_iter)->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);
+        }
+      }
+    }
+    scope_down(out);
+  }
+
+  if (tstruct->annotations_.find("final") == tstruct->annotations_.end()) {
+    out << endl << indent() << "virtual ~" << tstruct->get_name() << "() throw();" << endl;
+  }
+
+  // Declare all fields
+  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
+    indent(out) << declare_field(*m_iter,
+                                 false,
+                                 (pointers && !(*m_iter)->get_type()->is_xception()),
+                                 !read) << endl;
+  }
+
+  // Add the __isset data member if we need it, using the definition from above
+  if (has_nonrequired_fields && (!pointers || read)) {
+    out << endl << indent() << "_" << tstruct->get_name() << "__isset __isset;" << endl;
+  }
+
+  // Create a setter function for each field
+  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
+    if (pointers) {
+      continue;
+    }
+    if (is_reference((*m_iter))) {
+      out << endl << indent() << "void __set_" << (*m_iter)->get_name() << "(::apache::thrift::stdcxx::shared_ptr<"
+          << type_name((*m_iter)->get_type(), false, false) << ">";
+      out << " val);" << endl;
+    } else {
+      out << endl << indent() << "void __set_" << (*m_iter)->get_name() << "("
+          << type_name((*m_iter)->get_type(), false, true);
+      out << " val);" << endl;
+    }
+  }
+  out << endl;
+
+  if (!pointers) {
+    // Should we generate default operators?
+    if (!gen_no_default_operators_) {
+      // Generate an equality testing operator.  Make it inline since the compiler
+      // will do a better job than we would when deciding whether to inline it.
+      out << indent() << "bool operator == (const " << tstruct->get_name() << " & "
+          << (members.size() > 0 ? "rhs" : "/* rhs */") << ") const" << endl;
+      scope_up(out);
+      for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
+        // Most existing Thrift code does not use isset or optional/required,
+        // so we treat "default" fields as required.
+        if ((*m_iter)->get_req() != t_field::T_OPTIONAL) {
+          out << indent() << "if (!(" << (*m_iter)->get_name() << " == rhs."
+              << (*m_iter)->get_name() << "))" << endl << indent() << "  return false;" << endl;
+        } else {
+          out << indent() << "if (__isset." << (*m_iter)->get_name() << " != rhs.__isset."
+              << (*m_iter)->get_name() << ")" << endl << indent() << "  return false;" << endl
+              << indent() << "else if (__isset." << (*m_iter)->get_name() << " && !("
+              << (*m_iter)->get_name() << " == rhs." << (*m_iter)->get_name() << "))" << endl
+              << indent() << "  return false;" << endl;
+        }
+      }
+      indent(out) << "return true;" << endl;
+      scope_down(out);
+      out << indent() << "bool operator != (const " << tstruct->get_name() << " &rhs) const {"
+          << endl << indent() << "  return !(*this == rhs);" << endl << indent() << "}" << endl
+          << endl;
+
+      // Generate the declaration of a less-than operator.  This must be
+      // implemented by the application developer if they wish to use it.  (They
+      // will get a link error if they try to use it without an implementation.)
+      out << indent() << "bool operator < (const " << tstruct->get_name() << " & ) const;" << endl
+          << endl;
+    }
+  }
+
+  if (read) {
+    if (gen_templates_) {
+      out << indent() << "template <class Protocol_>" << endl << indent()
+          << "uint32_t read(Protocol_* iprot);" << endl;
+    } else {
+      out << indent() << "uint32_t read("
+          << "::apache::thrift::protocol::TProtocol* iprot);" << endl;
+    }
+  }
+  if (write) {
+    if (gen_templates_) {
+      out << indent() << "template <class Protocol_>" << endl << indent()
+          << "uint32_t write(Protocol_* oprot) const;" << endl;
+    } else {
+      out << indent() << "uint32_t write("
+          << "::apache::thrift::protocol::TProtocol* oprot) const;" << endl;
+    }
+  }
+  out << endl;
+
+  if (is_user_struct && !has_custom_ostream(tstruct)) {
+    out << indent() << "virtual ";
+    generate_struct_print_method_decl(out, NULL);
+    out << ";" << endl;
+  }
+
+  // std::exception::what()
+  if (is_exception) {
+    out << indent() << "mutable std::string thriftTExceptionMessageHolder_;" << endl;
+    out << indent();
+    generate_exception_what_method_decl(out, tstruct, false);
+    out << ";" << endl;
+  }
+
+  indent_down();
+  indent(out) << "};" << endl << endl;
+
+  if (swap) {
+    // Generate a namespace-scope swap() function
+    out << indent() << "void swap(" << tstruct->get_name() << " &a, " << tstruct->get_name()
+        << " &b);" << endl << endl;
+  }
+
+  if (is_user_struct) {
+    generate_struct_ostream_operator_decl(out, tstruct);
+  }
+}
+
+void t_cpp_generator::generate_struct_definition(ostream& out,
+                                                 ostream& force_cpp_out,
+                                                 t_struct* tstruct,
+                                                 bool setters,
+                                                 bool is_user_struct) {
+  // Get members
+  vector<t_field*>::const_iterator m_iter;
+  const vector<t_field*>& members = tstruct->get_members();
+
+  // Destructor
+  if (tstruct->annotations_.find("final") == tstruct->annotations_.end()) {
+    force_cpp_out << endl << indent() << tstruct->get_name() << "::~" << tstruct->get_name()
+                  << "() throw() {" << endl;
+    indent_up();
+
+    indent_down();
+    force_cpp_out << indent() << "}" << endl << endl;
+  }
+
+  // Create a setter function for each field
+  if (setters) {
+    for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
+      if (is_reference((*m_iter))) {
+        std::string type = type_name((*m_iter)->get_type());
+        out << endl << indent() << "void " << tstruct->get_name() << "::__set_"
+            << (*m_iter)->get_name() << "(::apache::thrift::stdcxx::shared_ptr<"
+            << type_name((*m_iter)->get_type(), false, false) << ">";
+        out << " val) {" << endl;
+      } else {
+        out << endl << indent() << "void " << tstruct->get_name() << "::__set_"
+            << (*m_iter)->get_name() << "(" << type_name((*m_iter)->get_type(), false, true);
+        out << " val) {" << endl;
+      }
+      indent_up();
+      out << indent() << "this->" << (*m_iter)->get_name() << " = val;" << endl;
+      indent_down();
+
+      // assume all fields are required except optional fields.
+      // for optional fields change __isset.name to true
+      bool is_optional = (*m_iter)->get_req() == t_field::T_OPTIONAL;
+      if (is_optional) {
+        out << indent() << indent() << "__isset." << (*m_iter)->get_name() << " = true;" << endl;
+      }
+      out << indent() << "}" << endl;
+    }
+  }
+  if (is_user_struct) {
+    generate_struct_ostream_operator(out, tstruct);
+  }
+  out << endl;
+}
+
+/**
+ * Makes a helper function to gen a struct reader.
+ *
+ * @param out Stream to write to
+ * @param tstruct The struct
+ */
+void t_cpp_generator::generate_struct_reader(ostream& out, t_struct* tstruct, bool pointers) {
+  if (gen_templates_) {
+    out << indent() << "template <class Protocol_>" << endl << indent() << "uint32_t "
+        << tstruct->get_name() << "::read(Protocol_* iprot) {" << endl;
+  } else {
+    indent(out) << "uint32_t " << tstruct->get_name()
+                << "::read(::apache::thrift::protocol::TProtocol* iprot) {" << endl;
+  }
+  indent_up();
+
+  const vector<t_field*>& fields = tstruct->get_members();
+  vector<t_field*>::const_iterator f_iter;
+
+  // Declare stack tmp variables
+  out << endl
+      << indent() << "::apache::thrift::protocol::TInputRecursionTracker tracker(*iprot);" << endl
+      << indent() << "uint32_t xfer = 0;" << endl
+      << indent() << "std::string fname;" << endl
+      << indent() << "::apache::thrift::protocol::TType ftype;" << endl
+      << indent() << "int16_t fid;" << endl
+      << endl
+      << indent() << "xfer += iprot->readStructBegin(fname);" << endl
+      << endl
+      << indent() << "using ::apache::thrift::protocol::TProtocolException;" << endl
+      << endl;
+
+  // Required variables aren't in __isset, so we need tmp vars to check them.
+  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+    if ((*f_iter)->get_req() == t_field::T_REQUIRED)
+      indent(out) << "bool isset_" << (*f_iter)->get_name() << " = false;" << endl;
+  }
+  out << endl;
+
+  // Loop over reading in fields
+  indent(out) << "while (true)" << endl;
+  scope_up(out);
+
+  // Read beginning field marker
+  indent(out) << "xfer += iprot->readFieldBegin(fname, ftype, fid);" << endl;
+
+  // Check for field STOP marker
+  out << indent() << "if (ftype == ::apache::thrift::protocol::T_STOP) {" << endl << indent()
+      << "  break;" << endl << indent() << "}" << endl;
+
+  if (fields.empty()) {
+    out << indent() << "xfer += iprot->skip(ftype);" << endl;
+  } else {
+    // Switch statement on the field we are reading
+    indent(out) << "switch (fid)" << endl;
+
+    scope_up(out);
+
+    // Generate deserialization code for known cases
+    for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+      indent(out) << "case " << (*f_iter)->get_key() << ":" << endl;
+      indent_up();
+      indent(out) << "if (ftype == " << type_to_enum((*f_iter)->get_type()) << ") {" << endl;
+      indent_up();
+
+      const char* isset_prefix = ((*f_iter)->get_req() != t_field::T_REQUIRED) ? "this->__isset."
+                                                                               : "isset_";
+
+#if 0
+          // This code throws an exception if the same field is encountered twice.
+          // We've decided to leave it out for performance reasons.
+          // TODO(dreiss): Generate this code and "if" it out to make it easier
+          // for people recompiling thrift to include it.
+          out <<
+            indent() << "if (" << isset_prefix << (*f_iter)->get_name() << ")" << endl <<
+            indent() << "  throw TProtocolException(TProtocolException::INVALID_DATA);" << endl;
+#endif
+
+      if (pointers && !(*f_iter)->get_type()->is_xception()) {
+        generate_deserialize_field(out, *f_iter, "(*(this->", "))");
+      } else {
+        generate_deserialize_field(out, *f_iter, "this->");
+      }
+      out << indent() << isset_prefix << (*f_iter)->get_name() << " = true;" << endl;
+      indent_down();
+      out << indent() << "} else {" << endl << indent() << "  xfer += iprot->skip(ftype);" << endl
+          <<
+          // TODO(dreiss): Make this an option when thrift structs
+          // have a common base class.
+          // indent() << "  throw TProtocolException(TProtocolException::INVALID_DATA);" << endl <<
+          indent() << "}" << endl << indent() << "break;" << endl;
+      indent_down();
+    }
+
+    // In the default case we skip the field
+    out << indent() << "default:" << endl << indent() << "  xfer += iprot->skip(ftype);" << endl
+        << indent() << "  break;" << endl;
+
+    scope_down(out);
+  } //!fields.empty()
+  // Read field end marker
+  indent(out) << "xfer += iprot->readFieldEnd();" << endl;
+
+  scope_down(out);
+
+  out << endl << indent() << "xfer += iprot->readStructEnd();" << endl;
+
+  // Throw if any required fields are missing.
+  // We do this after reading the struct end so that
+  // there might possibly be a chance of continuing.
+  out << endl;
+  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+    if ((*f_iter)->get_req() == t_field::T_REQUIRED)
+      out << indent() << "if (!isset_" << (*f_iter)->get_name() << ')' << endl << indent()
+          << "  throw TProtocolException(TProtocolException::INVALID_DATA);" << endl;
+  }
+
+  indent(out) << "return xfer;" << endl;
+
+  indent_down();
+  indent(out) << "}" << endl << endl;
+}
+
+/**
+ * Generates the write function.
+ *
+ * @param out Stream to write to
+ * @param tstruct The struct
+ */
+void t_cpp_generator::generate_struct_writer(ostream& out, t_struct* tstruct, bool pointers) {
+  string name = tstruct->get_name();
+  const vector<t_field*>& fields = tstruct->get_sorted_members();
+  vector<t_field*>::const_iterator f_iter;
+
+  if (gen_templates_) {
+    out << indent() << "template <class Protocol_>" << endl << indent() << "uint32_t "
+        << tstruct->get_name() << "::write(Protocol_* oprot) const {" << endl;
+  } else {
+    indent(out) << "uint32_t " << tstruct->get_name()
+                << "::write(::apache::thrift::protocol::TProtocol* oprot) const {" << endl;
+  }
+  indent_up();
+
+  out << indent() << "uint32_t xfer = 0;" << endl;
+
+  indent(out) << "::apache::thrift::protocol::TOutputRecursionTracker tracker(*oprot);" << endl;
+  indent(out) << "xfer += oprot->writeStructBegin(\"" << name << "\");" << endl;
+
+  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+    bool check_if_set = (*f_iter)->get_req() == t_field::T_OPTIONAL
+                        || (*f_iter)->get_type()->is_xception();
+    if (check_if_set) {
+      out << endl << indent() << "if (this->__isset." << (*f_iter)->get_name() << ") {" << endl;
+      indent_up();
+    } else {
+      out << endl;
+    }
+
+    // Write field header
+    out << indent() << "xfer += oprot->writeFieldBegin("
+        << "\"" << (*f_iter)->get_name() << "\", " << type_to_enum((*f_iter)->get_type()) << ", "
+        << (*f_iter)->get_key() << ");" << endl;
+    // Write field contents
+    if (pointers && !(*f_iter)->get_type()->is_xception()) {
+      generate_serialize_field(out, *f_iter, "(*(this->", "))");
+    } else {
+      generate_serialize_field(out, *f_iter, "this->");
+    }
+    // Write field closer
+    indent(out) << "xfer += oprot->writeFieldEnd();" << endl;
+    if (check_if_set) {
+      indent_down();
+      indent(out) << '}';
+    }
+  }
+
+  out << endl;
+
+  // Write the struct map
+  out << indent() << "xfer += oprot->writeFieldStop();" << endl << indent()
+      << "xfer += oprot->writeStructEnd();" << endl << indent()
+      << "return xfer;" << endl;
+
+  indent_down();
+  indent(out) << "}" << endl << endl;
+}
+
+/**
+ * Struct writer for result of a function, which can have only one of its
+ * fields set and does a conditional if else look up into the __isset field
+ * of the struct.
+ *
+ * @param out Output stream
+ * @param tstruct The result struct
+ */
+void t_cpp_generator::generate_struct_result_writer(ostream& out,
+                                                    t_struct* tstruct,
+                                                    bool pointers) {
+  string name = tstruct->get_name();
+  const vector<t_field*>& fields = tstruct->get_sorted_members();
+  vector<t_field*>::const_iterator f_iter;
+
+  if (gen_templates_) {
+    out << indent() << "template <class Protocol_>" << endl << indent() << "uint32_t "
+        << tstruct->get_name() << "::write(Protocol_* oprot) const {" << endl;
+  } else {
+    indent(out) << "uint32_t " << tstruct->get_name()
+                << "::write(::apache::thrift::protocol::TProtocol* oprot) const {" << endl;
+  }
+  indent_up();
+
+  out << endl << indent() << "uint32_t xfer = 0;" << endl << endl;
+
+  indent(out) << "xfer += oprot->writeStructBegin(\"" << name << "\");" << endl;
+
+  bool first = true;
+  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+    if (first) {
+      first = false;
+      out << endl << indent() << "if ";
+    } else {
+      out << " else if ";
+    }
+
+    out << "(this->__isset." << (*f_iter)->get_name() << ") {" << endl;
+
+    indent_up();
+
+    // Write field header
+    out << indent() << "xfer += oprot->writeFieldBegin("
+        << "\"" << (*f_iter)->get_name() << "\", " << type_to_enum((*f_iter)->get_type()) << ", "
+        << (*f_iter)->get_key() << ");" << endl;
+    // Write field contents
+    if (pointers) {
+      generate_serialize_field(out, *f_iter, "(*(this->", "))");
+    } else {
+      generate_serialize_field(out, *f_iter, "this->");
+    }
+    // Write field closer
+    indent(out) << "xfer += oprot->writeFieldEnd();" << endl;
+
+    indent_down();
+    indent(out) << "}";
+  }
+
+  // Write the struct map
+  out << endl << indent() << "xfer += oprot->writeFieldStop();" << endl << indent()
+      << "xfer += oprot->writeStructEnd();" << endl << indent() << "return xfer;" << endl;
+
+  indent_down();
+  indent(out) << "}" << endl << endl;
+}
+
+/**
+ * Generates the swap function.
+ *
+ * @param out Stream to write to
+ * @param tstruct The struct
+ */
+void t_cpp_generator::generate_struct_swap(ostream& out, t_struct* tstruct) {
+  out << indent() << "void swap(" << tstruct->get_name() << " &a, " << tstruct->get_name()
+      << " &b) {" << endl;
+  indent_up();
+
+  // Let argument-dependent name lookup find the correct swap() function to
+  // use based on the argument types.  If none is found in the arguments'
+  // namespaces, fall back to ::std::swap().
+  out << indent() << "using ::std::swap;" << endl;
+
+  bool has_nonrequired_fields = false;
+  const vector<t_field*>& fields = tstruct->get_members();
+  for (vector<t_field*>::const_iterator f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+    t_field* tfield = *f_iter;
+
+    if (tfield->get_req() != t_field::T_REQUIRED) {
+      has_nonrequired_fields = true;
+    }
+
+    out << indent() << "swap(a." << tfield->get_name() << ", b." << tfield->get_name() << ");"
+        << endl;
+  }
+
+  if (has_nonrequired_fields) {
+    out << indent() << "swap(a.__isset, b.__isset);" << endl;
+  }
+
+  // handle empty structs
+  if (fields.size() == 0) {
+    out << indent() << "(void) a;" << endl;
+    out << indent() << "(void) b;" << endl;
+  }
+
+  scope_down(out);
+  out << endl;
+}
+
+void t_cpp_generator::generate_struct_ostream_operator_decl(std::ostream& out, t_struct* tstruct) {
+  out << "std::ostream& operator<<(std::ostream& out, const "
+      << tstruct->get_name()
+      << "& obj);" << endl;
+  out << endl;
+}
+
+void t_cpp_generator::generate_struct_ostream_operator(std::ostream& out, t_struct* tstruct) {
+  if (!has_custom_ostream(tstruct)) {
+    // thrift defines this behavior
+    out << "std::ostream& operator<<(std::ostream& out, const "
+        << tstruct->get_name()
+        << "& obj)" << endl;
+    scope_up(out);
+    out << indent() << "obj.printTo(out);" << endl
+        << indent() << "return out;" << endl;
+    scope_down(out);
+    out << endl;
+  }
+}
+
+void t_cpp_generator::generate_struct_print_method_decl(std::ostream& out, t_struct* tstruct) {
+  out << "void ";
+  if (tstruct) {
+    out << tstruct->get_name() << "::";
+  }
+  out << "printTo(std::ostream& out) const";
+}
+
+void t_cpp_generator::generate_exception_what_method_decl(std::ostream& out,
+                                                          t_struct* tstruct,
+                                                          bool external) {
+  out << "const char* ";
+  if (external) {
+    out << tstruct->get_name() << "::";
+  }
+  out << "what() const throw()";
+}
+
+namespace struct_ostream_operator_generator {
+void generate_required_field_value(std::ostream& out, const t_field* field) {
+  out << " << to_string(" << field->get_name() << ")";
+}
+
+void generate_optional_field_value(std::ostream& out, const t_field* field) {
+  out << "; (__isset." << field->get_name() << " ? (out";
+  generate_required_field_value(out, field);
+  out << ") : (out << \"<null>\"))";
+}
+
+void generate_field_value(std::ostream& out, const t_field* field) {
+  if (field->get_req() == t_field::T_OPTIONAL)
+    generate_optional_field_value(out, field);
+  else
+    generate_required_field_value(out, field);
+}
+
+void generate_field_name(std::ostream& out, const t_field* field) {
+  out << "\"" << field->get_name() << "=\"";
+}
+
+void generate_field(std::ostream& out, const t_field* field) {
+  generate_field_name(out, field);
+  generate_field_value(out, field);
+}
+
+void generate_fields(std::ostream& out,
+                     const vector<t_field*>& fields,
+                     const std::string& indent) {
+  const vector<t_field*>::const_iterator beg = fields.begin();
+  const vector<t_field*>::const_iterator end = fields.end();
+
+  for (vector<t_field*>::const_iterator it = beg; it != end; ++it) {
+    out << indent << "out << ";
+
+    if (it != beg) {
+      out << "\", \" << ";
+    }
+
+    generate_field(out, *it);
+    out << ";" << endl;
+  }
+}
+}
+
+/**
+ * Generates operator<<
+ */
+void t_cpp_generator::generate_struct_print_method(std::ostream& out, t_struct* tstruct) {
+  out << indent();
+  generate_struct_print_method_decl(out, tstruct);
+  out << " {" << endl;
+
+  indent_up();
+
+  out << indent() << "using ::apache::thrift::to_string;" << endl;
+  out << indent() << "out << \"" << tstruct->get_name() << "(\";" << endl;
+  struct_ostream_operator_generator::generate_fields(out, tstruct->get_members(), indent());
+  out << indent() << "out << \")\";" << endl;
+
+  indent_down();
+  out << "}" << endl << endl;
+}
+
+/**
+ * Generates what() method for exceptions
+ */
+void t_cpp_generator::generate_exception_what_method(std::ostream& out, t_struct* tstruct) {
+  out << indent();
+  generate_exception_what_method_decl(out, tstruct, true);
+  out << " {" << endl;
+
+  indent_up();
+  out << indent() << "try {" << endl;
+
+  indent_up();
+  out << indent() << "std::stringstream ss;" << endl;
+  out << indent() << "ss << \"TException - service has thrown: \" << *this;" << endl;
+  out << indent() << "this->thriftTExceptionMessageHolder_ = ss.str();" << endl;
+  out << indent() << "return this->thriftTExceptionMessageHolder_.c_str();" << endl;
+  indent_down();
+
+  out << indent() << "} catch (const std::exception&) {" << endl;
+
+  indent_up();
+  out << indent() << "return \"TException - service has thrown: " << tstruct->get_name() << "\";"
+      << endl;
+  indent_down();
+
+  out << indent() << "}" << endl;
+
+  indent_down();
+  out << "}" << endl << endl;
+}
+
+/**
+ * Generates a thrift service. In C++, this comprises an entirely separate
+ * header and source file. The header file defines the methods and includes
+ * the data types defined in the main header file, and the implementation
+ * file contains implementations of the basic printer and default interfaces.
+ *
+ * @param tservice The service definition
+ */
+void t_cpp_generator::generate_service(t_service* tservice) {
+  string svcname = tservice->get_name();
+
+  // Make output files
+  string f_header_name = get_out_dir() + svcname + ".h";
+  f_header_.open(f_header_name.c_str());
+
+  // Print header file includes
+  f_header_ << autogen_comment();
+  f_header_ << "#ifndef " << svcname << "_H" << endl << "#define " << svcname << "_H" << endl
+            << endl;
+  if (gen_cob_style_) {
+    f_header_ << "#include <thrift/transport/TBufferTransports.h>" << endl << // TMemoryBuffer
+        "#include <thrift/stdcxx.h>" << endl
+              << "namespace apache { namespace thrift { namespace async {" << endl
+              << "class TAsyncChannel;" << endl << "}}}" << endl;
+  }
+  f_header_ << "#include <thrift/TDispatchProcessor.h>" << endl;
+  if (gen_cob_style_) {
+    f_header_ << "#include <thrift/async/TAsyncDispatchProcessor.h>" << endl;
+  }
+  f_header_ << "#include <thrift/async/TConcurrentClientSyncInfo.h>" << endl;
+  f_header_ << "#include \"" << get_include_prefix(*get_program()) << program_name_ << "_types.h\""
+            << endl;
+
+  t_service* extends_service = tservice->get_extends();
+  if (extends_service != NULL) {
+    f_header_ << "#include \"" << get_include_prefix(*(extends_service->get_program()))
+              << extends_service->get_name() << ".h\"" << endl;
+  }
+
+  f_header_ << endl << ns_open_ << endl << endl;
+
+  f_header_ << "#ifdef _MSC_VER\n"
+               "  #pragma warning( push )\n"
+               "  #pragma warning (disable : 4250 ) //inheriting methods via dominance \n"
+               "#endif\n\n";
+
+  // Service implementation file includes
+  string f_service_name = get_out_dir() + svcname + ".cpp";
+  f_service_.open(f_service_name.c_str());
+  f_service_ << autogen_comment();
+  f_service_ << "#include \"" << get_include_prefix(*get_program()) << svcname << ".h\"" << endl;
+  if (gen_cob_style_) {
+    f_service_ << "#include \"thrift/async/TAsyncChannel.h\"" << endl;
+  }
+  if (gen_templates_) {
+    f_service_ << "#include \"" << get_include_prefix(*get_program()) << svcname << ".tcc\""
+               << endl;
+
+    string f_service_tcc_name = get_out_dir() + svcname + ".tcc";
+    f_service_tcc_.open(f_service_tcc_name.c_str());
+    f_service_tcc_ << autogen_comment();
+    f_service_tcc_ << "#include \"" << get_include_prefix(*get_program()) << svcname << ".h\""
+                   << endl;
+
+    f_service_tcc_ << "#ifndef " << svcname << "_TCC" << endl << "#define " << svcname << "_TCC"
+                   << endl << endl;
+
+    if (gen_cob_style_) {
+      f_service_tcc_ << "#include \"thrift/async/TAsyncChannel.h\"" << endl;
+    }
+  }
+
+  f_service_ << endl << ns_open_ << endl << endl;
+  f_service_tcc_ << endl << ns_open_ << endl << endl;
+
+  // Generate all the components
+  generate_service_interface(tservice, "");
+  generate_service_interface_factory(tservice, "");
+  generate_service_null(tservice, "");
+  generate_service_helpers(tservice);
+  generate_service_client(tservice, "");
+  generate_service_processor(tservice, "");
+  generate_service_multiface(tservice);
+  generate_service_client(tservice, "Concurrent");
+
+  // Generate skeleton
+  if (!gen_no_skeleton_) {
+      generate_service_skeleton(tservice);
+  }
+
+  // Generate all the cob components
+  if (gen_cob_style_) {
+    generate_service_interface(tservice, "CobCl");
+    generate_service_interface(tservice, "CobSv");
+    generate_service_interface_factory(tservice, "CobSv");
+    generate_service_null(tservice, "CobSv");
+    generate_service_client(tservice, "Cob");
+    generate_service_processor(tservice, "Cob");
+
+    if (!gen_no_skeleton_) {
+      generate_service_async_skeleton(tservice);
+    }
+
+  }
+
+  f_header_ << "#ifdef _MSC_VER\n"
+               "  #pragma warning( pop )\n"
+               "#endif\n\n";
+
+  // Close the namespace
+  f_service_ << ns_close_ << endl << endl;
+  f_service_tcc_ << ns_close_ << endl << endl;
+  f_header_ << ns_close_ << endl << endl;
+
+  // TODO(simpkins): Make this a separate option
+  if (gen_templates_) {
+    f_header_ << "#include \"" << get_include_prefix(*get_program()) << svcname << ".tcc\"" << endl
+              << "#include \"" << get_include_prefix(*get_program()) << program_name_
+              << "_types.tcc\"" << endl << endl;
+  }
+
+  f_header_ << "#endif" << endl;
+  f_service_tcc_ << "#endif" << endl;
+
+  // Close the files
+  f_service_tcc_.close();
+  f_service_.close();
+  f_header_.close();
+}
+
+/**
+ * Generates helper functions for a service. Basically, this generates types
+ * for all the arguments and results to functions.
+ *
+ * @param tservice The service to generate a header definition for
+ */
+void t_cpp_generator::generate_service_helpers(t_service* tservice) {
+  vector<t_function*> functions = tservice->get_functions();
+  vector<t_function*>::iterator f_iter;
+  std::ostream& out = (gen_templates_ ? f_service_tcc_ : f_service_);
+
+  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
+    t_struct* ts = (*f_iter)->get_arglist();
+    string name_orig = ts->get_name();
+
+    // TODO(dreiss): Why is this stuff not in generate_function_helpers?
+    ts->set_name(tservice->get_name() + "_" + (*f_iter)->get_name() + "_args");
+    generate_struct_declaration(f_header_, ts, false);
+    generate_struct_definition(out, f_service_, ts, false);
+    generate_struct_reader(out, ts);
+    generate_struct_writer(out, ts);
+    ts->set_name(tservice->get_name() + "_" + (*f_iter)->get_name() + "_pargs");
+    generate_struct_declaration(f_header_, ts, false, true, false, true);
+    generate_struct_definition(out, f_service_, ts, false);
+    generate_struct_writer(out, ts, true);
+    ts->set_name(name_orig);
+
+    generate_function_helpers(tservice, *f_iter);
+  }
+}
+
+/**
+ * Generates a service interface definition.
+ *
+ * @param tservice The service to generate a header definition for
+ */
+void t_cpp_generator::generate_service_interface(t_service* tservice, string style) {
+
+  string service_if_name = service_name_ + style + "If";
+  if (style == "CobCl") {
+    // Forward declare the client.
+    string client_name = service_name_ + "CobClient";
+    if (gen_templates_) {
+      client_name += "T";
+      service_if_name += "T";
+      indent(f_header_) << "template <class Protocol_>" << endl;
+    }
+    indent(f_header_) << "class " << client_name << ";" << endl << endl;
+  }
+
+  string extends = "";
+  if (tservice->get_extends() != NULL) {
+    extends = " : virtual public " + type_name(tservice->get_extends()) + style + "If";
+    if (style == "CobCl" && gen_templates_) {
+      // TODO(simpkins): If gen_templates_ is enabled, we currently assume all
+      // parent services were also generated with templates enabled.
+      extends += "T<Protocol_>";
+    }
+  }
+
+  if (style == "CobCl" && gen_templates_) {
+    f_header_ << "template <class Protocol_>" << endl;
+  }
+  f_header_ << "class " << service_if_name << extends << " {" << endl << " public:" << endl;
+  indent_up();
+  f_header_ << indent() << "virtual ~" << service_if_name << "() {}" << endl;
+
+  vector<t_function*> functions = tservice->get_functions();
+  vector<t_function*>::iterator f_iter;
+  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
+    if ((*f_iter)->has_doc())
+      f_header_ << endl;
+    generate_java_doc(f_header_, *f_iter);
+    f_header_ << indent() << "virtual " << function_signature(*f_iter, style) << " = 0;" << endl;
+  }
+  indent_down();
+  f_header_ << "};" << endl << endl;
+
+  if (style == "CobCl" && gen_templates_) {
+    // generate a backwards-compatible typedef for clients that do not
+    // know about the new template-style code
+    f_header_ << "typedef " << service_if_name << "< ::apache::thrift::protocol::TProtocol> "
+              << service_name_ << style << "If;" << endl << endl;
+  }
+}
+
+/**
+ * Generates a service interface factory.
+ *
+ * @param tservice The service to generate an interface factory for.
+ */
+void t_cpp_generator::generate_service_interface_factory(t_service* tservice, string style) {
+  string service_if_name = service_name_ + style + "If";
+
+  // Figure out the name of the upper-most parent class.
+  // Getting everything to work out properly with inheritance is annoying.
+  // Here's what we're doing for now:
+  //
+  // - All handlers implement getHandler(), but subclasses use covariant return
+  //   types to return their specific service interface class type.  We have to
+  //   use raw pointers because of this; shared_ptr<> can't be used for
+  //   covariant return types.
+  //
+  // - Since we're not using shared_ptr<>, we also provide a releaseHandler()
+  //   function that must be called to release a pointer to a handler obtained
+  //   via getHandler().
+  //
+  //   releaseHandler() always accepts a pointer to the upper-most parent class
+  //   type.  This is necessary since the parent versions of releaseHandler()
+  //   may accept any of the parent types, not just the most specific subclass
+  //   type.  Implementations can use dynamic_cast to cast the pointer to the
+  //   subclass type if desired.
+  t_service* base_service = tservice;
+  while (base_service->get_extends() != NULL) {
+    base_service = base_service->get_extends();
+  }
+  string base_if_name = type_name(base_service) + style + "If";
+
+  // Generate the abstract factory class
+  string factory_name = service_if_name + "Factory";
+  string extends;
+  if (tservice->get_extends() != NULL) {
+    extends = " : virtual public " + type_name(tservice->get_extends()) + style + "IfFactory";
+  }
+
+  f_header_ << "class " << factory_name << extends << " {" << endl << " public:" << endl;
+  indent_up();
+  f_header_ << indent() << "typedef " << service_if_name << " Handler;" << endl << endl << indent()
+            << "virtual ~" << factory_name << "() {}" << endl << endl << indent() << "virtual "
+            << service_if_name << "* getHandler("
+            << "const ::apache::thrift::TConnectionInfo& connInfo) = 0;" << endl << indent()
+            << "virtual void releaseHandler(" << base_if_name << "* /* handler */) = 0;" << endl;
+
+  indent_down();
+  f_header_ << "};" << endl << endl;
+
+  // Generate the singleton factory class
+  string singleton_factory_name = service_if_name + "SingletonFactory";
+  f_header_ << "class " << singleton_factory_name << " : virtual public " << factory_name << " {"
+            << endl << " public:" << endl;
+  indent_up();
+  f_header_ << indent() << singleton_factory_name << "(const ::apache::thrift::stdcxx::shared_ptr<" << service_if_name
+            << ">& iface) : iface_(iface) {}" << endl << indent() << "virtual ~"
+            << singleton_factory_name << "() {}" << endl << endl << indent() << "virtual "
+            << service_if_name << "* getHandler("
+            << "const ::apache::thrift::TConnectionInfo&) {" << endl << indent()
+            << "  return iface_.get();" << endl << indent() << "}" << endl << indent()
+            << "virtual void releaseHandler(" << base_if_name << "* /* handler */) {}" << endl;
+
+  f_header_ << endl << " protected:" << endl << indent() << "::apache::thrift::stdcxx::shared_ptr<" << service_if_name
+            << "> iface_;" << endl;
+
+  indent_down();
+  f_header_ << "};" << endl << endl;
+}
+
+/**
+ * Generates a null implementation of the service.
+ *
+ * @param tservice The service to generate a header definition for
+ */
+void t_cpp_generator::generate_service_null(t_service* tservice, string style) {
+  string extends = "";
+  if (tservice->get_extends() != NULL) {
+    extends = " , virtual public " + type_name(tservice->get_extends()) + style + "Null";
+  }
+  f_header_ << "class " << service_name_ << style << "Null : virtual public " << service_name_
+            << style << "If" << extends << " {" << endl << " public:" << endl;
+  indent_up();
+  f_header_ << indent() << "virtual ~" << service_name_ << style << "Null() {}" << endl;
+  vector<t_function*> functions = tservice->get_functions();
+  vector<t_function*>::iterator f_iter;
+  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
+    f_header_ << indent() << function_signature(*f_iter, style, "", false) << " {" << endl;
+    indent_up();
+
+    t_type* returntype = (*f_iter)->get_returntype();
+    t_field returnfield(returntype, "_return");
+
+    if (style == "") {
+      if (returntype->is_void() || is_complex_type(returntype)) {
+        f_header_ << indent() << "return;" << endl;
+      } else {
+        f_header_ << indent() << declare_field(&returnfield, true) << endl << indent()
+                  << "return _return;" << endl;
+      }
+    } else if (style == "CobSv") {
+      if (returntype->is_void()) {
+        f_header_ << indent() << "return cob();" << endl;
+      } else {
+        t_field returnfield(returntype, "_return");
+        f_header_ << indent() << declare_field(&returnfield, true) << endl << indent()
+                  << "return cob(_return);" << endl;
+      }
+
+    } else {
+      throw "UNKNOWN STYLE";
+    }
+
+    indent_down();
+    f_header_ << indent() << "}" << endl;
+  }
+  indent_down();
+  f_header_ << "};" << endl << endl;
+}
+
+void t_cpp_generator::generate_function_call(ostream& out,
+                                             t_function* tfunction,
+                                             string target,
+                                             string iface,
+                                             string arg_prefix) {
+  bool first = true;
+  t_type* ret_type = get_true_type(tfunction->get_returntype());
+  out << indent();
+  if (!tfunction->is_oneway() && !ret_type->is_void()) {
+    if (is_complex_type(ret_type)) {
+      first = false;
+      out << iface << "->" << tfunction->get_name() << "(" << target;
+    } else {
+      out << target << " = " << iface << "->" << tfunction->get_name() << "(";
+    }
+  } else {
+    out << iface << "->" << tfunction->get_name() << "(";
+  }
+  const std::vector<t_field*>& fields = tfunction->get_arglist()->get_members();
+  vector<t_field*>::const_iterator f_iter;
+  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+    if (first) {
+      first = false;
+    } else {
+      out << ", ";
+    }
+    out << arg_prefix << (*f_iter)->get_name();
+  }
+  out << ");" << endl;
+}
+
+void t_cpp_generator::generate_service_async_skeleton(t_service* tservice) {
+  string svcname = tservice->get_name();
+
+  // Service implementation file includes
+  string f_skeleton_name = get_out_dir() + svcname + "_async_server.skeleton.cpp";
+
+  string ns = namespace_prefix(tservice->get_program()->get_namespace("cpp"));
+
+  ofstream_with_content_based_conditional_update f_skeleton;
+  f_skeleton.open(f_skeleton_name.c_str());
+  f_skeleton << "// This autogenerated skeleton file illustrates one way to adapt a synchronous"
+             << endl << "// interface into an asynchronous interface. You should copy it to another"
+             << endl
+             << "// filename to avoid overwriting it and rewrite as asynchronous any functions"
+             << endl << "// that would otherwise introduce unwanted latency." << endl << endl
+             << "#include \"" << get_include_prefix(*get_program()) << svcname << ".h\"" << endl
+             << "#include <thrift/protocol/TBinaryProtocol.h>" << endl << endl
+             << "using namespace ::apache::thrift;" << endl
+             << "using namespace ::apache::thrift::protocol;" << endl
+             << "using namespace ::apache::thrift::transport;" << endl
+             << "using namespace ::apache::thrift::async;" << endl << endl;
+
+  // the following code would not compile:
+  // using namespace ;
+  // using namespace ::;
+  if ((!ns.empty()) && (ns.compare(" ::") != 0)) {
+    f_skeleton << "using namespace " << string(ns, 0, ns.size() - 2) << ";" << endl << endl;
+  }
+
+  f_skeleton << "class " << svcname << "AsyncHandler : "
+             << "public " << svcname << "CobSvIf {" << endl << " public:" << endl;
+  indent_up();
+  f_skeleton << indent() << svcname << "AsyncHandler() {" << endl << indent()
+             << "  syncHandler_ = std::auto_ptr<" << svcname << "Handler>(new " << svcname
+             << "Handler);" << endl << indent() << "  // Your initialization goes here" << endl
+             << indent() << "}" << endl;
+  f_skeleton << indent() << "virtual ~" << service_name_ << "AsyncHandler();" << endl;
+
+  vector<t_function*> functions = tservice->get_functions();
+  vector<t_function*>::iterator f_iter;
+  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
+    f_skeleton << endl << indent() << function_signature(*f_iter, "CobSv", "", true) << " {"
+               << endl;
+    indent_up();
+
+    t_type* returntype = (*f_iter)->get_returntype();
+    t_field returnfield(returntype, "_return");
+
+    string target = returntype->is_void() ? "" : "_return";
+    if (!returntype->is_void()) {
+      f_skeleton << indent() << declare_field(&returnfield, true) << endl;
+    }
+    generate_function_call(f_skeleton, *f_iter, target, "syncHandler_", "");
+    f_skeleton << indent() << "return cob(" << target << ");" << endl;
+
+    scope_down(f_skeleton);
+  }
+  f_skeleton << endl << " protected:" << endl << indent() << "std::auto_ptr<" << svcname
+             << "Handler> syncHandler_;" << endl;
+  indent_down();
+  f_skeleton << "};" << endl << endl;
+}
+
+/**
+ * Generates a multiface, which is a single server that just takes a set
+ * of objects implementing the interface and calls them all, returning the
+ * value of the last one to be called.
+ *
+ * @param tservice The service to generate a multiserver for.
+ */
+void t_cpp_generator::generate_service_multiface(t_service* tservice) {
+  // Generate the dispatch methods
+  vector<t_function*> functions = tservice->get_functions();
+  vector<t_function*>::iterator f_iter;
+
+  string extends = "";
+  string extends_multiface = "";
+  if (tservice->get_extends() != NULL) {
+    extends = type_name(tservice->get_extends());
+    extends_multiface = ", public " + extends + "Multiface";
+  }
+
+  string list_type = string("std::vector<apache::thrift::stdcxx::shared_ptr<") + service_name_ + "If> >";
+
+  // Generate the header portion
+  f_header_ << "class " << service_name_ << "Multiface : "
+            << "virtual public " << service_name_ << "If" << extends_multiface << " {" << endl
+            << " public:" << endl;
+  indent_up();
+  f_header_ << indent() << service_name_ << "Multiface(" << list_type
+            << "& ifaces) : ifaces_(ifaces) {" << endl;
+  if (!extends.empty()) {
+    f_header_ << indent()
+              << "  std::vector<apache::thrift::stdcxx::shared_ptr<" + service_name_ + "If> >::iterator iter;"
+              << endl << indent() << "  for (iter = ifaces.begin(); iter != ifaces.end(); ++iter) {"
+              << endl << indent() << "    " << extends << "Multiface::add(*iter);" << endl
+              << indent() << "  }" << endl;
+  }
+  f_header_ << indent() << "}" << endl << indent() << "virtual ~" << service_name_
+            << "Multiface() {}" << endl;
+  indent_down();
+
+  // Protected data members
+  f_header_ << " protected:" << endl;
+  indent_up();
+  f_header_ << indent() << list_type << " ifaces_;" << endl << indent() << service_name_
+            << "Multiface() {}" << endl << indent() << "void add(::apache::thrift::stdcxx::shared_ptr<"
+            << service_name_ << "If> iface) {" << endl;
+  if (!extends.empty()) {
+    f_header_ << indent() << "  " << extends << "Multiface::add(iface);" << endl;
+  }
+  f_header_ << indent() << "  ifaces_.push_back(iface);" << endl << indent() << "}" << endl;
+  indent_down();
+
+  f_header_ << indent() << " public:" << endl;
+  indent_up();
+
+  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
+    t_struct* arglist = (*f_iter)->get_arglist();
+    const vector<t_field*>& args = arglist->get_members();
+    vector<t_field*>::const_iterator a_iter;
+
+    string call = string("ifaces_[i]->") + (*f_iter)->get_name() + "(";
+    bool first = true;
+    if (is_complex_type((*f_iter)->get_returntype())) {
+      call += "_return";
+      first = false;
+    }
+    for (a_iter = args.begin(); a_iter != args.end(); ++a_iter) {
+      if (first) {
+        first = false;
+      } else {
+        call += ", ";
+      }
+      call += (*a_iter)->get_name();
+    }
+    call += ")";
+
+    f_header_ << indent() << function_signature(*f_iter, "") << " {" << endl;
+    indent_up();
+    f_header_ << indent() << "size_t sz = ifaces_.size();" << endl << indent() << "size_t i = 0;"
+              << endl << indent() << "for (; i < (sz - 1); ++i) {" << endl;
+    indent_up();
+    f_header_ << indent() << call << ";" << endl;
+    indent_down();
+    f_header_ << indent() << "}" << endl;
+
+    if (!(*f_iter)->get_returntype()->is_void()) {
+      if (is_complex_type((*f_iter)->get_returntype())) {
+        f_header_ << indent() << call << ";" << endl << indent() << "return;" << endl;
+      } else {
+        f_header_ << indent() << "return " << call << ";" << endl;
+      }
+    } else {
+      f_header_ << indent() << call << ";" << endl;
+    }
+
+    indent_down();
+    f_header_ << indent() << "}" << endl << endl;
+  }
+
+  indent_down();
+  f_header_ << indent() << "};" << endl << endl;
+}
+
+/**
+ * Generates a service client definition.
+ *
+ * @param tservice The service to generate a server for.
+ */
+void t_cpp_generator::generate_service_client(t_service* tservice, string style) {
+  string ifstyle;
+  if (style == "Cob") {
+    ifstyle = "CobCl";
+  }
+
+  std::ostream& out = (gen_templates_ ? f_service_tcc_ : f_service_);
+  string template_header, template_suffix, short_suffix, protocol_type, _this;
+  string const prot_factory_type = "::apache::thrift::protocol::TProtocolFactory";
+  if (gen_templates_) {
+    template_header = "template <class Protocol_>\n";
+    short_suffix = "T";
+    template_suffix = "T<Protocol_>";
+    protocol_type = "Protocol_";
+    _this = "this->";
+  } else {
+    protocol_type = "::apache::thrift::protocol::TProtocol";
+  }
+  string prot_ptr = "apache::thrift::stdcxx::shared_ptr< " + protocol_type + ">";
+  string client_suffix = "Client" + template_suffix;
+  string if_suffix = "If";
+  if (style == "Cob") {
+    if_suffix += template_suffix;
+  }
+
+  string extends = "";
+  string extends_client = "";
+  if (tservice->get_extends() != NULL) {
+    // TODO(simpkins): If gen_templates_ is enabled, we currently assume all
+    // parent services were also generated with templates enabled.
+    extends = type_name(tservice->get_extends());
+    extends_client = ", public " + extends + style + client_suffix;
+  }
+
+  // Generate the header portion
+  if (style == "Concurrent") {
+    f_header_ << "// The \'concurrent\' client is a thread safe client that correctly handles\n"
+                 "// out of order responses.  It is slower than the regular client, so should\n"
+                 "// only be used when you need to share a connection among multiple threads\n";
+  }
+  f_header_ << template_header << "class " << service_name_ << style << "Client" << short_suffix
+            << " : "
+            << "virtual public " << service_name_ << ifstyle << if_suffix << extends_client << " {"
+            << endl << " public:" << endl;
+
+  indent_up();
+  if (style != "Cob") {
+    f_header_ << indent() << service_name_ << style << "Client" << short_suffix << "(" << prot_ptr
+              << " prot) ";
+
+    if (extends.empty()) {
+      f_header_ << "{" << endl;
+      f_header_ << indent() << "  setProtocol" << short_suffix << "(prot);" << endl << indent()
+                << "}" << endl;
+    } else {
+      f_header_ << ":" << endl;
+      f_header_ << indent() << "  " << extends << style << client_suffix << "(prot, prot) {}"
+                << endl;
+    }
+
+    f_header_ << indent() << service_name_ << style << "Client" << short_suffix << "(" << prot_ptr
+              << " iprot, " << prot_ptr << " oprot) ";
+    if (extends.empty()) {
+      f_header_ << "{" << endl;
+      f_header_ << indent() << "  setProtocol" << short_suffix << "(iprot,oprot);" << endl
+                << indent() << "}" << endl;
+    } else {
+      f_header_ << ":" << indent() << "  " << extends << style << client_suffix
+                << "(iprot, oprot) {}" << endl;
+    }
+
+    // create the setProtocol methods
+    if (extends.empty()) {
+      f_header_ << " private:" << endl;
+      // 1: one parameter
+      f_header_ << indent() << "void setProtocol" << short_suffix << "(" << prot_ptr << " prot) {"
+                << endl;
+      f_header_ << indent() << "setProtocol" << short_suffix << "(prot,prot);" << endl;
+      f_header_ << indent() << "}" << endl;
+      // 2: two parameter
+      f_header_ << indent() << "void setProtocol" << short_suffix << "(" << prot_ptr << " iprot, "
+                << prot_ptr << " oprot) {" << endl;
+
+      f_header_ << indent() << "  piprot_=iprot;" << endl << indent() << "  poprot_=oprot;" << endl
+                << indent() << "  iprot_ = iprot.get();" << endl << indent()
+                << "  oprot_ = oprot.get();" << endl;
+
+      f_header_ << indent() << "}" << endl;
+      f_header_ << " public:" << endl;
+    }
+
+    // Generate getters for the protocols.
+    // Note that these are not currently templated for simplicity.
+    // TODO(simpkins): should they be templated?
+    f_header_ << indent()
+              << "apache::thrift::stdcxx::shared_ptr< ::apache::thrift::protocol::TProtocol> getInputProtocol() {"
+              << endl << indent() << "  return " << _this << "piprot_;" << endl << indent() << "}"
+              << endl;
+
+    f_header_ << indent()
+              << "apache::thrift::stdcxx::shared_ptr< ::apache::thrift::protocol::TProtocol> getOutputProtocol() {"
+              << endl << indent() << "  return " << _this << "poprot_;" << endl << indent() << "}"
+              << endl;
+
+  } else /* if (style == "Cob") */ {
+    f_header_ << indent() << service_name_ << style << "Client" << short_suffix << "("
+              << "apache::thrift::stdcxx::shared_ptr< ::apache::thrift::async::TAsyncChannel> channel, "
+              << "::apache::thrift::protocol::TProtocolFactory* protocolFactory) :" << endl;
+    if (extends.empty()) {
+      f_header_ << indent() << "  channel_(channel)," << endl << indent()
+                << "  itrans_(new ::apache::thrift::transport::TMemoryBuffer())," << endl
+                << indent() << "  otrans_(new ::apache::thrift::transport::TMemoryBuffer()),"
+                << endl;
+      if (gen_templates_) {
+        // TProtocolFactory classes return generic TProtocol pointers.
+        // We have to dynamic cast to the Protocol_ type we are expecting.
+        f_header_ << indent() << "  piprot_(::apache::thrift::stdcxx::dynamic_pointer_cast<Protocol_>("
+                  << "protocolFactory->getProtocol(itrans_)))," << endl << indent()
+                  << "  poprot_(::apache::thrift::stdcxx::dynamic_pointer_cast<Protocol_>("
+                  << "protocolFactory->getProtocol(otrans_))) {" << endl;
+        // Throw a TException if either dynamic cast failed.
+        f_header_ << indent() << "  if (!piprot_ || !poprot_) {" << endl << indent()
+                  << "    throw ::apache::thrift::TException(\""
+                  << "TProtocolFactory returned unexpected protocol type in " << service_name_
+                  << style << "Client" << short_suffix << " constructor\");" << endl << indent()
+                  << "  }" << endl;
+      } else {
+        f_header_ << indent() << "  piprot_(protocolFactory->getProtocol(itrans_))," << endl
+                  << indent() << "  poprot_(protocolFactory->getProtocol(otrans_)) {" << endl;
+      }
+      f_header_ << indent() << "  iprot_ = piprot_.get();" << endl << indent()
+                << "  oprot_ = poprot_.get();" << endl << indent() << "}" << endl;
+    } else {
+      f_header_ << indent() << "  " << extends << style << client_suffix
+                << "(channel, protocolFactory) {}" << endl;
+    }
+  }
+
+  if (style == "Cob") {
+    f_header_ << indent()
+              << "::apache::thrift::stdcxx::shared_ptr< ::apache::thrift::async::TAsyncChannel> getChannel() {" << endl
+              << indent() << "  return " << _this << "channel_;" << endl << indent() << "}" << endl;
+    if (!gen_no_client_completion_) {
+      f_header_ << indent() << "virtual void completed__(bool /* success */) {}" << endl;
+    }
+  }
+
+  vector<t_function*> functions = tservice->get_functions();
+  vector<t_function*>::const_iterator f_iter;
+  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
+    indent(f_header_) << function_signature(*f_iter, ifstyle) << ";" << endl;
+    // TODO(dreiss): Use private inheritance to avoid generating thise in cob-style.
+    if (style == "Concurrent" && !(*f_iter)->is_oneway()) {
+      // concurrent clients need to move the seqid from the send function to the
+      // recv function.  Oneway methods don't have a recv function, so we don't need to
+      // move the seqid for them.  Attempting to do so would result in a seqid leak.
+      t_function send_function(g_type_i32, /*returning seqid*/
+                               string("send_") + (*f_iter)->get_name(),
+                               (*f_iter)->get_arglist());
+      indent(f_header_) << function_signature(&send_function, "") << ";" << endl;
+    } else {
+      t_function send_function(g_type_void,
+                               string("send_") + (*f_iter)->get_name(),
+                               (*f_iter)->get_arglist());
+      indent(f_header_) << function_signature(&send_function, "") << ";" << endl;
+    }
+    if (!(*f_iter)->is_oneway()) {
+      if (style == "Concurrent") {
+        t_field seqIdArg(g_type_i32, "seqid");
+        t_struct seqIdArgStruct(program_);
+        seqIdArgStruct.append(&seqIdArg);
+        t_function recv_function((*f_iter)->get_returntype(),
+                                 string("recv_") + (*f_iter)->get_name(),
+                                 &seqIdArgStruct);
+        indent(f_header_) << function_signature(&recv_function, "") << ";" << endl;
+      } else {
+        t_struct noargs(program_);
+        t_function recv_function((*f_iter)->get_returntype(),
+                                 string("recv_") + (*f_iter)->get_name(),
+                                 &noargs);
+        indent(f_header_) << function_signature(&recv_function, "") << ";" << endl;
+      }
+    }
+  }
+  indent_down();
+
+  if (extends.empty()) {
+    f_header_ << " protected:" << endl;
+    indent_up();
+
+    if (style == "Cob") {
+      f_header_ << indent()
+                << "::apache::thrift::stdcxx::shared_ptr< ::apache::thrift::async::TAsyncChannel> channel_;" << endl
+                << indent()
+                << "::apache::thrift::stdcxx::shared_ptr< ::apache::thrift::transport::TMemoryBuffer> itrans_;" << endl
+                << indent()
+                << "::apache::thrift::stdcxx::shared_ptr< ::apache::thrift::transport::TMemoryBuffer> otrans_;"
+                << endl;
+    }
+    f_header_ <<
+      indent() << prot_ptr << " piprot_;" << endl <<
+      indent() << prot_ptr << " poprot_;" << endl <<
+      indent() << protocol_type << "* iprot_;" << endl <<
+      indent() << protocol_type << "* oprot_;" << endl;
+
+    if (style == "Concurrent") {
+      f_header_ <<
+        indent() << "::apache::thrift::async::TConcurrentClientSyncInfo sync_;"<<endl;
+    }
+    indent_down();
+  }
+
+  f_header_ << "};" << endl << endl;
+
+  if (gen_templates_) {
+    // Output a backwards compatibility typedef using
+    // TProtocol as the template parameter.
+    f_header_ << "typedef " << service_name_ << style
+              << "ClientT< ::apache::thrift::protocol::TProtocol> " << service_name_ << style
+              << "Client;" << endl << endl;
+  }
+
+  string scope = service_name_ + style + client_suffix + "::";
+
+  // Generate client method implementations
+  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
+    string seqIdCapture;
+    string seqIdUse;
+    string seqIdCommaUse;
+    if (style == "Concurrent" && !(*f_iter)->is_oneway()) {
+      seqIdCapture = "int32_t seqid = ";
+      seqIdUse = "seqid";
+      seqIdCommaUse = ", seqid";
+    }
+
+    string funname = (*f_iter)->get_name();
+
+    // Open function
+    if (gen_templates_) {
+      indent(out) << template_header;
+    }
+    indent(out) << function_signature(*f_iter, ifstyle, scope) << endl;
+    scope_up(out);
+    indent(out) << seqIdCapture << "send_" << funname << "(";
+
+    // Get the struct of function call params
+    t_struct* arg_struct = (*f_iter)->get_arglist();
+
+    // Declare the function arguments
+    const vector<t_field*>& fields = arg_struct->get_members();
+    vector<t_field*>::const_iterator fld_iter;
+    bool first = true;
+    for (fld_iter = fields.begin(); fld_iter != fields.end(); ++fld_iter) {
+      if (first) {
+        first = false;
+      } else {
+        out << ", ";
+      }
+      out << (*fld_iter)->get_name();
+    }
+    out << ");" << endl;
+
+    if (style != "Cob") {
+      if (!(*f_iter)->is_oneway()) {
+        out << indent();
+        if (!(*f_iter)->get_returntype()->is_void()) {
+          if (is_complex_type((*f_iter)->get_returntype())) {
+            out << "recv_" << funname << "(_return" << seqIdCommaUse << ");" << endl;
+          } else {
+            out << "return recv_" << funname << "(" << seqIdUse << ");" << endl;
+          }
+        } else {
+          out << "recv_" << funname << "(" << seqIdUse << ");" << endl;
+        }
+      }
+    } else {
+      if (!(*f_iter)->is_oneway()) {
+        out << indent() << _this << "channel_->sendAndRecvMessage("
+            << "::apache::thrift::stdcxx::bind(cob, this), " << _this << "otrans_.get(), " << _this << "itrans_.get());"
+            << endl;
+      } else {
+        out << indent() << _this << "channel_->sendMessage("
+            << "::apache::thrift::stdcxx::bind(cob, this), " << _this << "otrans_.get());" << endl;
+      }
+    }
+    scope_down(out);
+    out << endl;
+
+    // if (style != "Cob") // TODO(dreiss): Libify the client and don't generate this for cob-style
+    if (true) {
+      t_type* send_func_return_type = g_type_void;
+      if (style == "Concurrent" && !(*f_iter)->is_oneway()) {
+        send_func_return_type = g_type_i32;
+      }
+      // Function for sending
+      t_function send_function(send_func_return_type,
+                               string("send_") + (*f_iter)->get_name(),
+                               (*f_iter)->get_arglist());
+
+      // Open the send function
+      if (gen_templates_) {
+        indent(out) << template_header;
+      }
+      indent(out) << function_signature(&send_function, "", scope) << endl;
+      scope_up(out);
+
+      // Function arguments and results
+      string argsname = tservice->get_name() + "_" + (*f_iter)->get_name() + "_pargs";
+      string resultname = tservice->get_name() + "_" + (*f_iter)->get_name() + "_presult";
+
+      string cseqidVal = "0";
+      if (style == "Concurrent") {
+        if (!(*f_iter)->is_oneway()) {
+          cseqidVal = "this->sync_.generateSeqId()";
+        }
+      }
+      // Serialize the request
+      out <<
+        indent() << "int32_t cseqid = " << cseqidVal << ";" << endl;
+      if(style == "Concurrent") {
+        out <<
+          indent() << "::apache::thrift::async::TConcurrentSendSentry sentry(&this->sync_);" << endl;
+      }
+      if (style == "Cob") {
+        out <<
+          indent() << _this << "otrans_->resetBuffer();" << endl;
+      }
+      out <<
+        indent() << _this << "oprot_->writeMessageBegin(\"" <<
+        (*f_iter)->get_name() <<
+        "\", ::apache::thrift::protocol::" << ((*f_iter)->is_oneway() ? "T_ONEWAY" : "T_CALL") <<
+        ", cseqid);" << endl << endl <<
+        indent() << argsname << " args;" << endl;
+
+      for (fld_iter = fields.begin(); fld_iter != fields.end(); ++fld_iter) {
+        out << indent() << "args." << (*fld_iter)->get_name() << " = &" << (*fld_iter)->get_name()
+            << ";" << endl;
+      }
+
+      out << indent() << "args.write(" << _this << "oprot_);" << endl << endl << indent() << _this
+          << "oprot_->writeMessageEnd();" << endl << indent() << _this
+          << "oprot_->getTransport()->writeEnd();" << endl << indent() << _this
+          << "oprot_->getTransport()->flush();" << endl;
+
+      if (style == "Concurrent") {
+        out << endl << indent() << "sentry.commit();" << endl;
+
+        if (!(*f_iter)->is_oneway()) {
+          out << indent() << "return cseqid;" << endl;
+        }
+      }
+      scope_down(out);
+      out << endl;
+
+      // Generate recv function only if not an oneway function
+      if (!(*f_iter)->is_oneway()) {
+        t_struct noargs(program_);
+
+        t_field seqIdArg(g_type_i32, "seqid");
+        t_struct seqIdArgStruct(program_);
+        seqIdArgStruct.append(&seqIdArg);
+
+        t_struct* recv_function_args = &noargs;
+        if (style == "Concurrent") {
+          recv_function_args = &seqIdArgStruct;
+        }
+
+        t_function recv_function((*f_iter)->get_returntype(),
+                                 string("recv_") + (*f_iter)->get_name(),
+                                 recv_function_args);
+        // Open the recv function
+        if (gen_templates_) {
+          indent(out) << template_header;
+        }
+        indent(out) << function_signature(&recv_function, "", scope) << endl;
+        scope_up(out);
+
+        out << endl <<
+          indent() << "int32_t rseqid = 0;" << endl <<
+          indent() << "std::string fname;" << endl <<
+          indent() << "::apache::thrift::protocol::TMessageType mtype;" << endl;
+        if(style == "Concurrent") {
+          out <<
+            endl <<
+            indent() << "// the read mutex gets dropped and reacquired as part of waitForWork()" << endl <<
+            indent() << "// The destructor of this sentry wakes up other clients" << endl <<
+            indent() << "::apache::thrift::async::TConcurrentRecvSentry sentry(&this->sync_, seqid);" << endl;
+        }
+        if (style == "Cob" && !gen_no_client_completion_) {
+          out << indent() << "bool completed = false;" << endl << endl << indent() << "try {";
+          indent_up();
+        }
+        out << endl;
+        if (style == "Concurrent") {
+          out <<
+            indent() << "while(true) {" << endl <<
+            indent() << "  if(!this->sync_.getPending(fname, mtype, rseqid)) {" << endl;
+          indent_up();
+          indent_up();
+        }
+        out <<
+          indent() << _this << "iprot_->readMessageBegin(fname, mtype, rseqid);" << endl;
+        if (style == "Concurrent") {
+          scope_down(out);
+          out << indent() << "if(seqid == rseqid) {" << endl;
+          indent_up();
+        }
+        out <<
+          indent() << "if (mtype == ::apache::thrift::protocol::T_EXCEPTION) {" << endl <<
+          indent() << "  ::apache::thrift::TApplicationException x;" << endl <<
+          indent() << "  x.read(" << _this << "iprot_);" << endl <<
+          indent() << "  " << _this << "iprot_->readMessageEnd();" << endl <<
+          indent() << "  " << _this << "iprot_->getTransport()->readEnd();" << endl;
+        if (style == "Cob" && !gen_no_client_completion_) {
+          out << indent() << "  completed = true;" << endl << indent() << "  completed__(true);"
+              << endl;
+        }
+        if (style == "Concurrent") {
+          out << indent() << "  sentry.commit();" << endl;
+        }
+        out <<
+          indent() << "  throw x;" << endl <<
+          indent() << "}" << endl <<
+          indent() << "if (mtype != ::apache::thrift::protocol::T_REPLY) {" << endl <<
+          indent() << "  " << _this << "iprot_->skip(" << "::apache::thrift::protocol::T_STRUCT);" << endl <<
+          indent() << "  " << _this << "iprot_->readMessageEnd();" << endl <<
+          indent() << "  " << _this << "iprot_->getTransport()->readEnd();" << endl;
+        if (style == "Cob" && !gen_no_client_completion_) {
+          out << indent() << "  completed = true;" << endl << indent() << "  completed__(false);"
+              << endl;
+        }
+        out <<
+          indent() << "}" << endl <<
+          indent() << "if (fname.compare(\"" << (*f_iter)->get_name() << "\") != 0) {" << endl <<
+          indent() << "  " << _this << "iprot_->skip(" << "::apache::thrift::protocol::T_STRUCT);" << endl <<
+          indent() << "  " << _this << "iprot_->readMessageEnd();" << endl <<
+          indent() << "  " << _this << "iprot_->getTransport()->readEnd();" << endl;
+        if (style == "Cob" && !gen_no_client_completion_) {
+          out << indent() << "  completed = true;" << endl << indent() << "  completed__(false);"
+              << endl;
+        }
+        if (style == "Concurrent") {
+          out << endl <<
+            indent() << "  // in a bad state, don't commit" << endl <<
+            indent() << "  using ::apache::thrift::protocol::TProtocolException;" << endl <<
+            indent() << "  throw TProtocolException(TProtocolException::INVALID_DATA);" << endl;
+        }
+        out << indent() << "}" << endl;
+
+        if (!(*f_iter)->get_returntype()->is_void()
+            && !is_complex_type((*f_iter)->get_returntype())) {
+          t_field returnfield((*f_iter)->get_returntype(), "_return");
+          out << indent() << declare_field(&returnfield) << endl;
+        }
+
+        out << indent() << resultname << " result;" << endl;
+
+        if (!(*f_iter)->get_returntype()->is_void()) {
+          out << indent() << "result.success = &_return;" << endl;
+        }
+
+        out << indent() << "result.read(" << _this << "iprot_);" << endl << indent() << _this
+            << "iprot_->readMessageEnd();" << endl << indent() << _this
+            << "iprot_->getTransport()->readEnd();" << endl << endl;
+
+        // Careful, only look for _result if not a void function
+        if (!(*f_iter)->get_returntype()->is_void()) {
+          if (is_complex_type((*f_iter)->get_returntype())) {
+            out <<
+              indent() << "if (result.__isset.success) {" << endl;
+            out <<
+              indent() << "  // _return pointer has now been filled" << endl;
+            if (style == "Cob" && !gen_no_client_completion_) {
+              out << indent() << "  completed = true;" << endl << indent() << "  completed__(true);"
+                  << endl;
+            }
+            if (style == "Concurrent") {
+              out << indent() << "  sentry.commit();" << endl;
+            }
+            out <<
+              indent() << "  return;" << endl <<
+              indent() << "}" << endl;
+          } else {
+            out << indent() << "if (result.__isset.success) {" << endl;
+            if (style == "Cob" && !gen_no_client_completion_) {
+              out << indent() << "  completed = true;" << endl << indent() << "  completed__(true);"
+                  << endl;
+            }
+            if (style == "Concurrent") {
+              out << indent() << "  sentry.commit();" << endl;
+            }
+            out << indent() << "  return _return;" << endl << indent() << "}" << endl;
+          }
+        }
+
+        t_struct* xs = (*f_iter)->get_xceptions();
+        const std::vector<t_field*>& xceptions = xs->get_members();
+        vector<t_field*>::const_iterator x_iter;
+        for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) {
+          out << indent() << "if (result.__isset." << (*x_iter)->get_name() << ") {" << endl;
+          if (style == "Cob" && !gen_no_client_completion_) {
+            out << indent() << "  completed = true;" << endl << indent() << "  completed__(true);"
+                << endl;
+          }
+          if (style == "Concurrent") {
+            out << indent() << "  sentry.commit();" << endl;
+          }
+          out << indent() << "  throw result." << (*x_iter)->get_name() << ";" << endl << indent()
+              << "}" << endl;
+        }
+
+        // We only get here if we are a void function
+        if ((*f_iter)->get_returntype()->is_void()) {
+          if (style == "Cob" && !gen_no_client_completion_) {
+            out << indent() << "completed = true;" << endl << indent() << "completed__(true);"
+                << endl;
+          }
+          if (style == "Concurrent") {
+            out << indent() << "sentry.commit();" << endl;
+          }
+          indent(out) << "return;" << endl;
+        } else {
+          if (style == "Cob" && !gen_no_client_completion_) {
+            out << indent() << "completed = true;" << endl << indent() << "completed__(true);"
+                << endl;
+          }
+          if (style == "Concurrent") {
+            out << indent() << "// in a bad state, don't commit" << endl;
+          }
+          out << indent() << "throw "
+                             "::apache::thrift::TApplicationException(::apache::thrift::"
+                             "TApplicationException::MISSING_RESULT, \"" << (*f_iter)->get_name()
+              << " failed: unknown result\");" << endl;
+        }
+        if (style == "Concurrent") {
+          indent_down();
+          indent_down();
+          out <<
+            indent() << "  }" << endl <<
+            indent() << "  // seqid != rseqid" << endl <<
+            indent() << "  this->sync_.updatePending(fname, mtype, rseqid);" << endl <<
+            endl <<
+            indent() << "  // this will temporarily unlock the readMutex, and let other clients get work done" << endl <<
+            indent() << "  this->sync_.waitForWork(seqid);" << endl <<
+            indent() << "} // end while(true)" << endl;
+        }
+        if (style == "Cob" && !gen_no_client_completion_) {
+          indent_down();
+          out << indent() << "} catch (...) {" << endl << indent() << "  if (!completed) {" << endl
+              << indent() << "    completed__(false);" << endl << indent() << "  }" << endl
+              << indent() << "  throw;" << endl << indent() << "}" << endl;
+        }
+        // Close function
+        scope_down(out);
+        out << endl;
+      }
+    }
+  }
+}
+
+class ProcessorGenerator {
+public:
+  ProcessorGenerator(t_cpp_generator* generator, t_service* service, const string& style);
+
+  void run() {
+    generate_class_definition();
+
+    // Generate the dispatchCall() function
+    generate_dispatch_call(false);
+    if (generator_->gen_templates_) {
+      generate_dispatch_call(true);
+    }
+
+    // Generate all of the process subfunctions
+    generate_process_functions();
+
+    generate_factory();
+  }
+
+  void generate_class_definition();
+  void generate_dispatch_call(bool template_protocol);
+  void generate_process_functions();
+  void generate_factory();
+
+protected:
+  std::string type_name(t_type* ttype, bool in_typedef = false, bool arg = false) {
+    return generator_->type_name(ttype, in_typedef, arg);
+  }
+
+  std::string indent() { return generator_->indent(); }
+  std::ostream& indent(std::ostream& os) { return generator_->indent(os); }
+
+  void indent_up() { generator_->indent_up(); }
+  void indent_down() { generator_->indent_down(); }
+
+  t_cpp_generator* generator_;
+  t_service* service_;
+  std::ostream& f_header_;
+  std::ostream& f_out_;
+  string service_name_;
+  string style_;
+  string pstyle_;
+  string class_name_;
+  string if_name_;
+  string factory_class_name_;
+  string finish_cob_;
+  string finish_cob_decl_;
+  string ret_type_;
+  string call_context_;
+  string cob_arg_;
+  string call_context_arg_;
+  string call_context_decl_;
+  string template_header_;
+  string template_suffix_;
+  string typename_str_;
+  string class_suffix_;
+  string extends_;
+};
+
+ProcessorGenerator::ProcessorGenerator(t_cpp_generator* generator,
+                                       t_service* service,
+                                       const string& style)
+  : generator_(generator),
+    service_(service),
+    f_header_(generator->f_header_),
+    f_out_(generator->gen_templates_ ? generator->f_service_tcc_ : generator->f_service_),
+    service_name_(generator->service_name_),
+    style_(style) {
+  if (style_ == "Cob") {
+    pstyle_ = "Async";
+    class_name_ = service_name_ + pstyle_ + "Processor";
+    if_name_ = service_name_ + "CobSvIf";
+
+    finish_cob_ = "::apache::thrift::stdcxx::function<void(bool ok)> cob, ";
+    finish_cob_decl_ = "::apache::thrift::stdcxx::function<void(bool ok)>, ";
+    cob_arg_ = "cob, ";
+    ret_type_ = "void ";
+  } else {
+    class_name_ = service_name_ + "Processor";
+    if_name_ = service_name_ + "If";
+
+    ret_type_ = "bool ";
+    // TODO(edhall) callContext should eventually be added to TAsyncProcessor
+    call_context_ = ", void* callContext";
+    call_context_arg_ = ", callContext";
+    call_context_decl_ = ", void*";
+  }
+
+  factory_class_name_ = class_name_ + "Factory";
+
+  if (generator->gen_templates_) {
+    template_header_ = "template <class Protocol_>\n";
+    template_suffix_ = "<Protocol_>";
+    typename_str_ = "typename ";
+    class_name_ += "T";
+    factory_class_name_ += "T";
+  }
+
+  if (service_->get_extends() != NULL) {
+    extends_ = type_name(service_->get_extends()) + pstyle_ + "Processor";
+    if (generator_->gen_templates_) {
+      // TODO(simpkins): If gen_templates_ is enabled, we currently assume all
+      // parent services were also generated with templates enabled.
+      extends_ += "T<Protocol_>";
+    }
+  }
+}
+
+void ProcessorGenerator::generate_class_definition() {
+  // Generate the dispatch methods
+  vector<t_function*> functions = service_->get_functions();
+  vector<t_function*>::iterator f_iter;
+
+  string parent_class;
+  if (service_->get_extends() != NULL) {
+    parent_class = extends_;
+  } else {
+    if (style_ == "Cob") {
+      parent_class = "::apache::thrift::async::TAsyncDispatchProcessor";
+    } else {
+      parent_class = "::apache::thrift::TDispatchProcessor";
+    }
+
+    if (generator_->gen_templates_) {
+      parent_class += "T<Protocol_>";
+    }
+  }
+
+  // Generate the header portion
+  f_header_ << template_header_ << "class " << class_name_ << " : public " << parent_class << " {"
+            << endl;
+
+  // Protected data members
+  f_header_ << " protected:" << endl;
+  indent_up();
+  f_header_ << indent() << "::apache::thrift::stdcxx::shared_ptr<" << if_name_ << "> iface_;" << endl;
+  f_header_ << indent() << "virtual " << ret_type_ << "dispatchCall(" << finish_cob_
+            << "::apache::thrift::protocol::TProtocol* iprot, "
+            << "::apache::thrift::protocol::TProtocol* oprot, "
+            << "const std::string& fname, int32_t seqid" << call_context_ << ");" << endl;
+  if (generator_->gen_templates_) {
+    f_header_ << indent() << "virtual " << ret_type_ << "dispatchCallTemplated(" << finish_cob_
+              << "Protocol_* iprot, Protocol_* oprot, "
+              << "const std::string& fname, int32_t seqid" << call_context_ << ");" << endl;
+  }
+  indent_down();
+
+  // Process function declarations
+  f_header_ << " private:" << endl;
+  indent_up();
+
+  // Declare processMap_
+  f_header_ << indent() << "typedef  void (" << class_name_ << "::*"
+            << "ProcessFunction)(" << finish_cob_decl_ << "int32_t, "
+            << "::apache::thrift::protocol::TProtocol*, "
+            << "::apache::thrift::protocol::TProtocol*" << call_context_decl_ << ");" << endl;
+  if (generator_->gen_templates_) {
+    f_header_ << indent() << "typedef void (" << class_name_ << "::*"
+              << "SpecializedProcessFunction)(" << finish_cob_decl_ << "int32_t, "
+              << "Protocol_*, Protocol_*" << call_context_decl_ << ");" << endl << indent()
+              << "struct ProcessFunctions {" << endl << indent() << "  ProcessFunction generic;"
+              << endl << indent() << "  SpecializedProcessFunction specialized;" << endl << indent()
+              << "  ProcessFunctions(ProcessFunction g, "
+              << "SpecializedProcessFunction s) :" << endl << indent() << "    generic(g)," << endl
+              << indent() << "    specialized(s) {}" << endl << indent()
+              << "  ProcessFunctions() : generic(NULL), specialized(NULL) "
+              << "{}" << endl << indent() << "};" << endl << indent()
+              << "typedef std::map<std::string, ProcessFunctions> "
+              << "ProcessMap;" << endl;
+  } else {
+    f_header_ << indent() << "typedef std::map<std::string, ProcessFunction> "
+              << "ProcessMap;" << endl;
+  }
+  f_header_ << indent() << "ProcessMap processMap_;" << endl;
+
+  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
+    indent(f_header_) << "void process_" << (*f_iter)->get_name() << "(" << finish_cob_
+                      << "int32_t seqid, ::apache::thrift::protocol::TProtocol* iprot, "
+                         "::apache::thrift::protocol::TProtocol* oprot" << call_context_ << ");"
+                      << endl;
+    if (generator_->gen_templates_) {
+      indent(f_header_) << "void process_" << (*f_iter)->get_name() << "(" << finish_cob_
+                        << "int32_t seqid, Protocol_* iprot, Protocol_* oprot" << call_context_
+                        << ");" << endl;
+    }
+    if (style_ == "Cob") {
+      // XXX Factor this out, even if it is a pain.
+      string ret_arg = ((*f_iter)->get_returntype()->is_void()
+                            ? ""
+                            : ", const " + type_name((*f_iter)->get_returntype()) + "& _return");
+      f_header_ << indent() << "void return_" << (*f_iter)->get_name()
+                << "(::apache::thrift::stdcxx::function<void(bool ok)> cob, int32_t seqid, "
+                << "::apache::thrift::protocol::TProtocol* oprot, "
+                << "void* ctx" << ret_arg << ");" << endl;
+      if (generator_->gen_templates_) {
+        f_header_ << indent() << "void return_" << (*f_iter)->get_name()
+                  << "(::apache::thrift::stdcxx::function<void(bool ok)> cob, int32_t seqid, "
+                  << "Protocol_* oprot, void* ctx" << ret_arg << ");" << endl;
+      }
+      // XXX Don't declare throw if it doesn't exist
+      f_header_ << indent() << "void throw_" << (*f_iter)->get_name()
+                << "(::apache::thrift::stdcxx::function<void(bool ok)> cob, int32_t seqid, "
+                << "::apache::thrift::protocol::TProtocol* oprot, void* ctx, "
+                << "::apache::thrift::TDelayedException* _throw);" << endl;
+      if (generator_->gen_templates_) {
+        f_header_ << indent() << "void throw_" << (*f_iter)->get_name()
+                  << "(::apache::thrift::stdcxx::function<void(bool ok)> cob, int32_t seqid, "
+                  << "Protocol_* oprot, void* ctx, "
+                  << "::apache::thrift::TDelayedException* _throw);" << endl;
+      }
+    }
+  }
+
+  f_header_ << " public:" << endl << indent() << class_name_ << "(::apache::thrift::stdcxx::shared_ptr<" << if_name_
+            << "> iface) :" << endl;
+  if (!extends_.empty()) {
+    f_header_ << indent() << "  " << extends_ << "(iface)," << endl;
+  }
+  f_header_ << indent() << "  iface_(iface) {" << endl;
+  indent_up();
+
+  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
+    f_header_ << indent() << "processMap_[\"" << (*f_iter)->get_name() << "\"] = ";
+    if (generator_->gen_templates_) {
+      f_header_ << "ProcessFunctions(" << endl;
+      if (generator_->gen_templates_only_) {
+        indent(f_header_) << "  NULL," << endl;
+      } else {
+        indent(f_header_) << "  &" << class_name_ << "::process_" << (*f_iter)->get_name() << ","
+                          << endl;
+      }
+      indent(f_header_) << "  &" << class_name_ << "::process_" << (*f_iter)->get_name() << ")";
+    } else {
+      f_header_ << "&" << class_name_ << "::process_" << (*f_iter)->get_name();
+    }
+    f_header_ << ";" << endl;
+  }
+
+  indent_down();
+  f_header_ << indent() << "}" << endl << endl << indent() << "virtual ~" << class_name_ << "() {}"
+            << endl;
+  indent_down();
+  f_header_ << "};" << endl << endl;
+
+  if (generator_->gen_templates_) {
+    // Generate a backwards compatible typedef, for callers who don't know
+    // about the new template-style code.
+    //
+    // We can't use TProtocol as the template parameter, since ProcessorT
+    // provides overloaded versions of most methods, one of which accepts
+    // TProtocol pointers, and one which accepts Protocol_ pointers.  This
+    // results in a compile error if instantiated with Protocol_ == TProtocol.
+    // Therefore, we define TDummyProtocol solely so we can use it as the
+    // template parameter here.
+    f_header_ << "typedef " << class_name_ << "< ::apache::thrift::protocol::TDummyProtocol > "
+              << service_name_ << pstyle_ << "Processor;" << endl << endl;
+  }
+}
+
+void ProcessorGenerator::generate_dispatch_call(bool template_protocol) {
+  string protocol = "::apache::thrift::protocol::TProtocol";
+  string function_suffix;
+  if (template_protocol) {
+    protocol = "Protocol_";
+    // We call the generic version dispatchCall(), and the specialized
+    // version dispatchCallTemplated().  We can't call them both
+    // dispatchCall(), since this will cause the compiler to issue a warning if
+    // a service that doesn't use templates inherits from a service that does
+    // use templates: the compiler complains that the subclass only implements
+    // the generic version of dispatchCall(), and hides the templated version.
+    // Using different names for the two functions prevents this.
+    function_suffix = "Templated";
+  }
+
+  f_out_ << template_header_ << ret_type_ << class_name_ << template_suffix_ << "::dispatchCall"
+         << function_suffix << "(" << finish_cob_ << protocol << "* iprot, " << protocol
+         << "* oprot, "
+         << "const std::string& fname, int32_t seqid" << call_context_ << ") {" << endl;
+  indent_up();
+
+  // HOT: member function pointer map
+  f_out_ << indent() << typename_str_ << "ProcessMap::iterator pfn;" << endl << indent()
+         << "pfn = processMap_.find(fname);" << endl << indent()
+         << "if (pfn == processMap_.end()) {" << endl;
+  if (extends_.empty()) {
+    f_out_ << indent() << "  iprot->skip(::apache::thrift::protocol::T_STRUCT);" << endl << indent()
+           << "  iprot->readMessageEnd();" << endl << indent()
+           << "  iprot->getTransport()->readEnd();" << endl << indent()
+           << "  ::apache::thrift::TApplicationException "
+              "x(::apache::thrift::TApplicationException::UNKNOWN_METHOD, \"Invalid method name: "
+              "'\"+fname+\"'\");" << endl << indent()
+           << "  oprot->writeMessageBegin(fname, ::apache::thrift::protocol::T_EXCEPTION, seqid);"
+           << endl << indent() << "  x.write(oprot);" << endl << indent()
+           << "  oprot->writeMessageEnd();" << endl << indent()
+           << "  oprot->getTransport()->writeEnd();" << endl << indent()
+           << "  oprot->getTransport()->flush();" << endl << indent()
+           << (style_ == "Cob" ? "  return cob(true);" : "  return true;") << endl;
+  } else {
+    f_out_ << indent() << "  return " << extends_ << "::dispatchCall("
+           << (style_ == "Cob" ? "cob, " : "") << "iprot, oprot, fname, seqid" << call_context_arg_
+           << ");" << endl;
+  }
+  f_out_ << indent() << "}" << endl;
+  if (template_protocol) {
+    f_out_ << indent() << "(this->*(pfn->second.specialized))";
+  } else {
+    if (generator_->gen_templates_only_) {
+      // TODO: This is a null pointer, so nothing good will come from calling
+      // it.  Throw an exception instead.
+      f_out_ << indent() << "(this->*(pfn->second.generic))";
+    } else if (generator_->gen_templates_) {
+      f_out_ << indent() << "(this->*(pfn->second.generic))";
+    } else {
+      f_out_ << indent() << "(this->*(pfn->second))";
+    }
+  }
+  f_out_ << "(" << cob_arg_ << "seqid, iprot, oprot" << call_context_arg_ << ");" << endl;
+
+  // TODO(dreiss): return pfn ret?
+  if (style_ == "Cob") {
+    f_out_ << indent() << "return;" << endl;
+  } else {
+    f_out_ << indent() << "return true;" << endl;
+  }
+
+  indent_down();
+  f_out_ << "}" << endl << endl;
+}
+
+void ProcessorGenerator::generate_process_functions() {
+  vector<t_function*> functions = service_->get_functions();
+  vector<t_function*>::iterator f_iter;
+  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
+    if (generator_->gen_templates_) {
+      generator_->generate_process_function(service_, *f_iter, style_, false);
+      generator_->generate_process_function(service_, *f_iter, style_, true);
+    } else {
+      generator_->generate_process_function(service_, *f_iter, style_, false);
+    }
+  }
+}
+
+void ProcessorGenerator::generate_factory() {
+  string if_factory_name = if_name_ + "Factory";
+
+  // Generate the factory class definition
+  f_header_ << template_header_ << "class " << factory_class_name_ << " : public ::apache::thrift::"
+            << (style_ == "Cob" ? "async::TAsyncProcessorFactory" : "TProcessorFactory") << " {"
+            << endl << " public:" << endl;
+  indent_up();
+
+  f_header_ << indent() << factory_class_name_ << "(const ::apache::thrift::stdcxx::shared_ptr< " << if_factory_name
+            << " >& handlerFactory) :" << endl << indent()
+            << "    handlerFactory_(handlerFactory) {}" << endl << endl << indent()
+            << "::apache::thrift::stdcxx::shared_ptr< ::apache::thrift::"
+            << (style_ == "Cob" ? "async::TAsyncProcessor" : "TProcessor") << " > "
+            << "getProcessor(const ::apache::thrift::TConnectionInfo& connInfo);" << endl;
+
+  f_header_ << endl << " protected:" << endl << indent() << "::apache::thrift::stdcxx::shared_ptr< "
+            << if_factory_name << " > handlerFactory_;" << endl;
+
+  indent_down();
+  f_header_ << "};" << endl << endl;
+
+  // If we are generating templates, output a typedef for the plain
+  // factory name.
+  if (generator_->gen_templates_) {
+    f_header_ << "typedef " << factory_class_name_
+              << "< ::apache::thrift::protocol::TDummyProtocol > " << service_name_ << pstyle_
+              << "ProcessorFactory;" << endl << endl;
+  }
+
+  // Generate the getProcessor() method
+  f_out_ << template_header_ << indent() << "::apache::thrift::stdcxx::shared_ptr< ::apache::thrift::"
+         << (style_ == "Cob" ? "async::TAsyncProcessor" : "TProcessor") << " > "
+         << factory_class_name_ << template_suffix_ << "::getProcessor("
+         << "const ::apache::thrift::TConnectionInfo& connInfo) {" << endl;
+  indent_up();
+
+  f_out_ << indent() << "::apache::thrift::ReleaseHandler< " << if_factory_name
+         << " > cleanup(handlerFactory_);" << endl << indent() << "::apache::thrift::stdcxx::shared_ptr< "
+         << if_name_ << " > handler("
+         << "handlerFactory_->getHandler(connInfo), cleanup);" << endl << indent()
+         << "::apache::thrift::stdcxx::shared_ptr< ::apache::thrift::"
+         << (style_ == "Cob" ? "async::TAsyncProcessor" : "TProcessor") << " > "
+         << "processor(new " << class_name_ << template_suffix_ << "(handler));" << endl << indent()
+         << "return processor;" << endl;
+
+  indent_down();
+  f_out_ << indent() << "}" << endl << endl;
+}
+
+/**
+ * Generates a service processor definition.
+ *
+ * @param tservice The service to generate a processor for.
+ */
+void t_cpp_generator::generate_service_processor(t_service* tservice, string style) {
+  ProcessorGenerator generator(this, tservice, style);
+  generator.run();
+}
+
+/**
+ * Generates a struct and helpers for a function.
+ *
+ * @param tfunction The function
+ */
+void t_cpp_generator::generate_function_helpers(t_service* tservice, t_function* tfunction) {
+  if (tfunction->is_oneway()) {
+    return;
+  }
+
+  std::ostream& out = (gen_templates_ ? f_service_tcc_ : f_service_);
+
+  t_struct result(program_, tservice->get_name() + "_" + tfunction->get_name() + "_result");
+  t_field success(tfunction->get_returntype(), "success", 0);
+  if (!tfunction->get_returntype()->is_void()) {
+    result.append(&success);
+  }
+
+  t_struct* xs = tfunction->get_xceptions();
+  const vector<t_field*>& fields = xs->get_members();
+  vector<t_field*>::const_iterator f_iter;
+  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+    result.append(*f_iter);
+  }
+
+  generate_struct_declaration(f_header_, &result, false);
+  generate_struct_definition(out, f_service_, &result, false);
+  generate_struct_reader(out, &result);
+  generate_struct_result_writer(out, &result);
+
+  result.set_name(tservice->get_name() + "_" + tfunction->get_name() + "_presult");
+  generate_struct_declaration(f_header_, &result, false, true, true, gen_cob_style_);
+  generate_struct_definition(out, f_service_, &result, false);
+  generate_struct_reader(out, &result, true);
+  if (gen_cob_style_) {
+    generate_struct_writer(out, &result, true);
+  }
+}
+
+/**
+ * Generates a process function definition.
+ *
+ * @param tfunction The function to write a dispatcher for
+ */
+void t_cpp_generator::generate_process_function(t_service* tservice,
+                                                t_function* tfunction,
+                                                string style,
+                                                bool specialized) {
+  t_struct* arg_struct = tfunction->get_arglist();
+  const std::vector<t_field*>& fields = arg_struct->get_members();
+  vector<t_field*>::const_iterator f_iter;
+
+  t_struct* xs = tfunction->get_xceptions();
+  const std::vector<t_field*>& xceptions = xs->get_members();
+  vector<t_field*>::const_iterator x_iter;
+  string service_func_name = "\"" + tservice->get_name() + "." + tfunction->get_name() + "\"";
+
+  std::ostream& out = (gen_templates_ ? f_service_tcc_ : f_service_);
+
+  string prot_type = (specialized ? "Protocol_" : "::apache::thrift::protocol::TProtocol");
+  string class_suffix;
+  if (gen_templates_) {
+    class_suffix = "T<Protocol_>";
+  }
+
+  // I tried to do this as one function.  I really did.  But it was too hard.
+  if (style != "Cob") {
+    // Open function
+    if (gen_templates_) {
+      out << indent() << "template <class Protocol_>" << endl;
+    }
+    const bool unnamed_oprot_seqid = tfunction->is_oneway() && !(gen_templates_ && !specialized);
+    out << "void " << tservice->get_name() << "Processor" << class_suffix << "::"
+        << "process_" << tfunction->get_name() << "("
+        << "int32_t" << (unnamed_oprot_seqid ? ", " : " seqid, ") << prot_type << "* iprot, "
+        << prot_type << "*" << (unnamed_oprot_seqid ? ", " : " oprot, ") << "void* callContext)"
+        << endl;
+    scope_up(out);
+
+    string argsname = tservice->get_name() + "_" + tfunction->get_name() + "_args";
+    string resultname = tservice->get_name() + "_" + tfunction->get_name() + "_result";
+
+    if (tfunction->is_oneway() && !unnamed_oprot_seqid) {
+      out << indent() << "(void) seqid;" << endl << indent() << "(void) oprot;" << endl;
+    }
+
+    out << indent() << "void* ctx = NULL;" << endl << indent()
+        << "if (this->eventHandler_.get() != NULL) {" << endl << indent()
+        << "  ctx = this->eventHandler_->getContext(" << service_func_name << ", callContext);"
+        << endl << indent() << "}" << endl << indent()
+        << "::apache::thrift::TProcessorContextFreer freer("
+        << "this->eventHandler_.get(), ctx, " << service_func_name << ");" << endl << endl
+        << indent() << "if (this->eventHandler_.get() != NULL) {" << endl << indent()
+        << "  this->eventHandler_->preRead(ctx, " << service_func_name << ");" << endl << indent()
+        << "}" << endl << endl << indent() << argsname << " args;" << endl << indent()
+        << "args.read(iprot);" << endl << indent() << "iprot->readMessageEnd();" << endl << indent()
+        << "uint32_t bytes = iprot->getTransport()->readEnd();" << endl << endl << indent()
+        << "if (this->eventHandler_.get() != NULL) {" << endl << indent()
+        << "  this->eventHandler_->postRead(ctx, " << service_func_name << ", bytes);" << endl
+        << indent() << "}" << endl << endl;
+
+    // Declare result
+    if (!tfunction->is_oneway()) {
+      out << indent() << resultname << " result;" << endl;
+    }
+
+    // Try block for functions with exceptions
+    out << indent() << "try {" << endl;
+    indent_up();
+
+    // Generate the function call
+    bool first = true;
+    out << indent();
+    if (!tfunction->is_oneway() && !tfunction->get_returntype()->is_void()) {
+      if (is_complex_type(tfunction->get_returntype())) {
+        first = false;
+        out << "iface_->" << tfunction->get_name() << "(result.success";
+      } else {
+        out << "result.success = iface_->" << tfunction->get_name() << "(";
+      }
+    } else {
+      out << "iface_->" << tfunction->get_name() << "(";
+    }
+    for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+      if (first) {
+        first = false;
+      } else {
+        out << ", ";
+      }
+      out << "args." << (*f_iter)->get_name();
+    }
+    out << ");" << endl;
+
+    // Set isset on success field
+    if (!tfunction->is_oneway() && !tfunction->get_returntype()->is_void()) {
+      out << indent() << "result.__isset.success = true;" << endl;
+    }
+
+    indent_down();
+    out << indent() << "}";
+
+    if (!tfunction->is_oneway()) {
+      for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) {
+        out << " catch (" << type_name((*x_iter)->get_type()) << " &" << (*x_iter)->get_name()
+            << ") {" << endl;
+        if (!tfunction->is_oneway()) {
+          indent_up();
+          out << indent() << "result." << (*x_iter)->get_name() << " = " << (*x_iter)->get_name()
+              << ";" << endl << indent() << "result.__isset." << (*x_iter)->get_name() << " = true;"
+              << endl;
+          indent_down();
+          out << indent() << "}";
+        } else {
+          out << "}";
+        }
+      }
+    }
+
+    if (!tfunction->is_oneway()) {
+      out << " catch (const std::exception& e) {" << endl;
+    } else {
+      out << " catch (const std::exception&) {" << endl;
+    }
+
+    indent_up();
+    out << indent() << "if (this->eventHandler_.get() != NULL) {" << endl << indent()
+        << "  this->eventHandler_->handlerError(ctx, " << service_func_name << ");" << endl
+        << indent() << "}" << endl;
+
+    if (!tfunction->is_oneway()) {
+      out << endl << indent() << "::apache::thrift::TApplicationException x(e.what());" << endl
+          << indent() << "oprot->writeMessageBegin(\"" << tfunction->get_name()
+          << "\", ::apache::thrift::protocol::T_EXCEPTION, seqid);" << endl << indent()
+          << "x.write(oprot);" << endl << indent() << "oprot->writeMessageEnd();" << endl
+          << indent() << "oprot->getTransport()->writeEnd();" << endl << indent()
+          << "oprot->getTransport()->flush();" << endl;
+    }
+    out << indent() << "return;" << endl;
+    indent_down();
+    out << indent() << "}" << endl << endl;
+
+    // Shortcut out here for oneway functions
+    if (tfunction->is_oneway()) {
+      out << indent() << "if (this->eventHandler_.get() != NULL) {" << endl << indent()
+          << "  this->eventHandler_->asyncComplete(ctx, " << service_func_name << ");" << endl
+          << indent() << "}" << endl << endl << indent() << "return;" << endl;
+      indent_down();
+      out << "}" << endl << endl;
+      return;
+    }
+
+    // Serialize the result into a struct
+    out << indent() << "if (this->eventHandler_.get() != NULL) {" << endl << indent()
+        << "  this->eventHandler_->preWrite(ctx, " << service_func_name << ");" << endl << indent()
+        << "}" << endl << endl << indent() << "oprot->writeMessageBegin(\"" << tfunction->get_name()
+        << "\", ::apache::thrift::protocol::T_REPLY, seqid);" << endl << indent()
+        << "result.write(oprot);" << endl << indent() << "oprot->writeMessageEnd();" << endl
+        << indent() << "bytes = oprot->getTransport()->writeEnd();" << endl << indent()
+        << "oprot->getTransport()->flush();" << endl << endl << indent()
+        << "if (this->eventHandler_.get() != NULL) {" << endl << indent()
+        << "  this->eventHandler_->postWrite(ctx, " << service_func_name << ", bytes);" << endl
+        << indent() << "}" << endl;
+
+    // Close function
+    scope_down(out);
+    out << endl;
+  }
+
+  // Cob style.
+  else {
+    // Processor entry point.
+    // TODO(edhall) update for callContext when TEventServer is ready
+    if (gen_templates_) {
+      out << indent() << "template <class Protocol_>" << endl;
+    }
+    out << "void " << tservice->get_name() << "AsyncProcessor" << class_suffix << "::process_"
+        << tfunction->get_name() << "(::apache::thrift::stdcxx::function<void(bool ok)> cob, int32_t seqid, "
+        << prot_type << "* iprot, " << prot_type << "* oprot)" << endl;
+    scope_up(out);
+
+    // TODO(simpkins): we could try to consoldate this
+    // with the non-cob code above
+    if (gen_templates_ && !specialized) {
+      // If these are instances of Protocol_, instead of any old TProtocol,
+      // use the specialized process function instead.
+      out << indent() << "Protocol_* _iprot = dynamic_cast<Protocol_*>(iprot);" << endl << indent()
+          << "Protocol_* _oprot = dynamic_cast<Protocol_*>(oprot);" << endl << indent()
+          << "if (_iprot && _oprot) {" << endl << indent() << "  return process_"
+          << tfunction->get_name() << "(cob, seqid, _iprot, _oprot);" << endl << indent() << "}"
+          << endl << indent() << "T_GENERIC_PROTOCOL(this, iprot, _iprot);" << endl << indent()
+          << "T_GENERIC_PROTOCOL(this, oprot, _oprot);" << endl << endl;
+    }
+
+    if (tfunction->is_oneway()) {
+      out << indent() << "(void) seqid;" << endl << indent() << "(void) oprot;" << endl;
+    }
+
+    out << indent() << tservice->get_name() + "_" + tfunction->get_name() << "_args args;" << endl
+        << indent() << "void* ctx = NULL;" << endl << indent()
+        << "if (this->eventHandler_.get() != NULL) {" << endl << indent()
+        << "  ctx = this->eventHandler_->getContext(" << service_func_name << ", NULL);" << endl
+        << indent() << "}" << endl << indent() << "::apache::thrift::TProcessorContextFreer freer("
+        << "this->eventHandler_.get(), ctx, " << service_func_name << ");" << endl << endl
+        << indent() << "try {" << endl;
+    indent_up();
+    out << indent() << "if (this->eventHandler_.get() != NULL) {" << endl << indent()
+        << "  this->eventHandler_->preRead(ctx, " << service_func_name << ");" << endl << indent()
+        << "}" << endl << indent() << "args.read(iprot);" << endl << indent()
+        << "iprot->readMessageEnd();" << endl << indent()
+        << "uint32_t bytes = iprot->getTransport()->readEnd();" << endl << indent()
+        << "if (this->eventHandler_.get() != NULL) {" << endl << indent()
+        << "  this->eventHandler_->postRead(ctx, " << service_func_name << ", bytes);" << endl
+        << indent() << "}" << endl;
+    scope_down(out);
+
+    // TODO(dreiss): Handle TExceptions?  Expose to server?
+    out << indent() << "catch (const std::exception&) {" << endl << indent()
+        << "  if (this->eventHandler_.get() != NULL) {" << endl << indent()
+        << "    this->eventHandler_->handlerError(ctx, " << service_func_name << ");" << endl
+        << indent() << "  }" << endl << indent() << "  return cob(false);" << endl << indent()
+        << "}" << endl;
+
+    if (tfunction->is_oneway()) {
+      out << indent() << "if (this->eventHandler_.get() != NULL) {" << endl << indent()
+          << "  this->eventHandler_->asyncComplete(ctx, " << service_func_name << ");" << endl
+          << indent() << "}" << endl;
+    }
+    // TODO(dreiss): Figure out a strategy for exceptions in async handlers.
+    out << indent() << "freer.unregister();" << endl;
+    if (tfunction->is_oneway()) {
+      // No return.  Just hand off our cob.
+      // TODO(dreiss): Call the cob immediately?
+      out << indent() << "iface_->" << tfunction->get_name() << "("
+          << "::apache::thrift::stdcxx::bind(cob, true)" << endl;
+      indent_up();
+      indent_up();
+    } else {
+      string ret_arg, ret_placeholder;
+      if (!tfunction->get_returntype()->is_void()) {
+        ret_arg = ", const " + type_name(tfunction->get_returntype()) + "& _return";
+        ret_placeholder = ", ::apache::thrift::stdcxx::placeholders::_1";
+      }
+
+      // When gen_templates_ is true, the return_ and throw_ functions are
+      // overloaded.  We have to declare pointers to them so that the compiler
+      // can resolve the correct overloaded version.
+      out << indent() << "void (" << tservice->get_name() << "AsyncProcessor" << class_suffix
+          << "::*return_fn)(::apache::thrift::stdcxx::function<void(bool ok)> "
+          << "cob, int32_t seqid, " << prot_type << "* oprot, void* ctx" << ret_arg
+          << ") =" << endl;
+      out << indent() << "  &" << tservice->get_name() << "AsyncProcessor" << class_suffix
+          << "::return_" << tfunction->get_name() << ";" << endl;
+      if (!xceptions.empty()) {
+        out << indent() << "void (" << tservice->get_name() << "AsyncProcessor" << class_suffix
+            << "::*throw_fn)(::apache::thrift::stdcxx::function<void(bool ok)> "
+            << "cob, int32_t seqid, " << prot_type << "* oprot, void* ctx, "
+            << "::apache::thrift::TDelayedException* _throw) =" << endl;
+        out << indent() << "  &" << tservice->get_name() << "AsyncProcessor" << class_suffix
+            << "::throw_" << tfunction->get_name() << ";" << endl;
+      }
+
+      out << indent() << "iface_->" << tfunction->get_name() << "(" << endl;
+      indent_up();
+      indent_up();
+      out << indent() << "::apache::thrift::stdcxx::bind(return_fn, this, cob, seqid, oprot, ctx" << ret_placeholder
+          << ")";
+      if (!xceptions.empty()) {
+        out << ',' << endl << indent() << "::apache::thrift::stdcxx::bind(throw_fn, this, cob, seqid, oprot, "
+            << "ctx, ::apache::thrift::stdcxx::placeholders::_1)";
+      }
+    }
+
+    // XXX Whitespace cleanup.
+    for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+      out << ',' << endl << indent() << "args." << (*f_iter)->get_name();
+    }
+    out << ");" << endl;
+    indent_down();
+    indent_down();
+    scope_down(out);
+    out << endl;
+
+    // Normal return.
+    if (!tfunction->is_oneway()) {
+      string ret_arg_decl, ret_arg_name;
+      if (!tfunction->get_returntype()->is_void()) {
+        ret_arg_decl = ", const " + type_name(tfunction->get_returntype()) + "& _return";
+        ret_arg_name = ", _return";
+      }
+      if (gen_templates_) {
+        out << indent() << "template <class Protocol_>" << endl;
+      }
+      out << "void " << tservice->get_name() << "AsyncProcessor" << class_suffix << "::return_"
+          << tfunction->get_name() << "(::apache::thrift::stdcxx::function<void(bool ok)> cob, int32_t seqid, "
+          << prot_type << "* oprot, void* ctx" << ret_arg_decl << ')' << endl;
+      scope_up(out);
+
+      if (gen_templates_ && !specialized) {
+        // If oprot is a Protocol_ instance,
+        // use the specialized return function instead.
+        out << indent() << "Protocol_* _oprot = dynamic_cast<Protocol_*>(oprot);" << endl
+            << indent() << "if (_oprot) {" << endl << indent() << "  return return_"
+            << tfunction->get_name() << "(cob, seqid, _oprot, ctx" << ret_arg_name << ");" << endl
+            << indent() << "}" << endl << indent() << "T_GENERIC_PROTOCOL(this, oprot, _oprot);"
+            << endl << endl;
+      }
+
+      out << indent() << tservice->get_name() << "_" << tfunction->get_name() << "_presult result;"
+          << endl;
+      if (!tfunction->get_returntype()->is_void()) {
+        // The const_cast here is unfortunate, but it would be a pain to avoid,
+        // and we only do a write with this struct, which is const-safe.
+        out << indent() << "result.success = const_cast<" << type_name(tfunction->get_returntype())
+            << "*>(&_return);" << endl << indent() << "result.__isset.success = true;" << endl;
+      }
+      // Serialize the result into a struct
+      out << endl << indent() << "if (this->eventHandler_.get() != NULL) {" << endl << indent()
+          << "  ctx = this->eventHandler_->getContext(" << service_func_name << ", NULL);" << endl
+          << indent() << "}" << endl << indent()
+          << "::apache::thrift::TProcessorContextFreer freer("
+          << "this->eventHandler_.get(), ctx, " << service_func_name << ");" << endl << endl
+          << indent() << "if (this->eventHandler_.get() != NULL) {" << endl << indent()
+          << "  this->eventHandler_->preWrite(ctx, " << service_func_name << ");" << endl
+          << indent() << "}" << endl << endl << indent() << "oprot->writeMessageBegin(\""
+          << tfunction->get_name() << "\", ::apache::thrift::protocol::T_REPLY, seqid);" << endl
+          << indent() << "result.write(oprot);" << endl << indent() << "oprot->writeMessageEnd();"
+          << endl << indent() << "uint32_t bytes = oprot->getTransport()->writeEnd();" << endl
+          << indent() << "oprot->getTransport()->flush();" << endl << indent()
+          << "if (this->eventHandler_.get() != NULL) {" << endl << indent()
+          << "  this->eventHandler_->postWrite(ctx, " << service_func_name << ", bytes);" << endl
+          << indent() << "}" << endl << indent() << "return cob(true);" << endl;
+      scope_down(out);
+      out << endl;
+    }
+
+    // Exception return.
+    if (!tfunction->is_oneway() && !xceptions.empty()) {
+      if (gen_templates_) {
+        out << indent() << "template <class Protocol_>" << endl;
+      }
+      out << "void " << tservice->get_name() << "AsyncProcessor" << class_suffix << "::throw_"
+          << tfunction->get_name() << "(::apache::thrift::stdcxx::function<void(bool ok)> cob, int32_t seqid, "
+          << prot_type << "* oprot, void* ctx, "
+          << "::apache::thrift::TDelayedException* _throw)" << endl;
+      scope_up(out);
+
+      if (gen_templates_ && !specialized) {
+        // If oprot is a Protocol_ instance,
+        // use the specialized throw function instead.
+        out << indent() << "Protocol_* _oprot = dynamic_cast<Protocol_*>(oprot);" << endl
+            << indent() << "if (_oprot) {" << endl << indent() << "  return throw_"
+            << tfunction->get_name() << "(cob, seqid, _oprot, ctx, _throw);" << endl << indent()
+            << "}" << endl << indent() << "T_GENERIC_PROTOCOL(this, oprot, _oprot);" << endl
+            << endl;
+      }
+
+      // Get the event handler context
+      out << endl << indent() << "if (this->eventHandler_.get() != NULL) {" << endl << indent()
+          << "  ctx = this->eventHandler_->getContext(" << service_func_name << ", NULL);" << endl
+          << indent() << "}" << endl << indent()
+          << "::apache::thrift::TProcessorContextFreer freer("
+          << "this->eventHandler_.get(), ctx, " << service_func_name << ");" << endl << endl;
+
+      // Throw the TDelayedException, and catch the result
+      out << indent() << tservice->get_name() << "_" << tfunction->get_name() << "_result result;"
+          << endl << endl << indent() << "try {" << endl;
+      indent_up();
+      out << indent() << "_throw->throw_it();" << endl << indent() << "return cob(false);"
+          << endl; // Is this possible?  TBD.
+      indent_down();
+      out << indent() << '}';
+      for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) {
+        out << "  catch (" << type_name((*x_iter)->get_type()) << " &" << (*x_iter)->get_name()
+            << ") {" << endl;
+        indent_up();
+        out << indent() << "result." << (*x_iter)->get_name() << " = " << (*x_iter)->get_name()
+            << ";" << endl << indent() << "result.__isset." << (*x_iter)->get_name() << " = true;"
+            << endl;
+        scope_down(out);
+      }
+
+      // Handle the case where an undeclared exception is thrown
+      out << " catch (std::exception& e) {" << endl;
+      indent_up();
+      out << indent() << "if (this->eventHandler_.get() != NULL) {" << endl << indent()
+          << "  this->eventHandler_->handlerError(ctx, " << service_func_name << ");" << endl
+          << indent() << "}" << endl << endl << indent()
+          << "::apache::thrift::TApplicationException x(e.what());" << endl << indent()
+          << "oprot->writeMessageBegin(\"" << tfunction->get_name()
+          << "\", ::apache::thrift::protocol::T_EXCEPTION, seqid);" << endl << indent()
+          << "x.write(oprot);" << endl << indent() << "oprot->writeMessageEnd();" << endl
+          << indent() << "oprot->getTransport()->writeEnd();" << endl << indent()
+          << "oprot->getTransport()->flush();" << endl <<
+          // We pass true to the cob here, since we did successfully write a
+          // response, even though it is an exception response.
+          // It looks like the argument is currently ignored, anyway.
+          indent() << "return cob(true);" << endl;
+      scope_down(out);
+
+      // Serialize the result into a struct
+      out << indent() << "if (this->eventHandler_.get() != NULL) {" << endl << indent()
+          << "  this->eventHandler_->preWrite(ctx, " << service_func_name << ");" << endl
+          << indent() << "}" << endl << endl << indent() << "oprot->writeMessageBegin(\""
+          << tfunction->get_name() << "\", ::apache::thrift::protocol::T_REPLY, seqid);" << endl
+          << indent() << "result.write(oprot);" << endl << indent() << "oprot->writeMessageEnd();"
+          << endl << indent() << "uint32_t bytes = oprot->getTransport()->writeEnd();" << endl
+          << indent() << "oprot->getTransport()->flush();" << endl << indent()
+          << "if (this->eventHandler_.get() != NULL) {" << endl << indent()
+          << "  this->eventHandler_->postWrite(ctx, " << service_func_name << ", bytes);" << endl
+          << indent() << "}" << endl << indent() << "return cob(true);" << endl;
+      scope_down(out);
+      out << endl;
+    } // for each function
+  }   // cob style
+}
+
+/**
+ * Generates a skeleton file of a server
+ *
+ * @param tservice The service to generate a server for.
+ */
+void t_cpp_generator::generate_service_skeleton(t_service* tservice) {
+  string svcname = tservice->get_name();
+
+  // Service implementation file includes
+  string f_skeleton_name = get_out_dir() + svcname + "_server.skeleton.cpp";
+
+  string ns = namespace_prefix(tservice->get_program()->get_namespace("cpp"));
+
+  ofstream_with_content_based_conditional_update f_skeleton;
+  f_skeleton.open(f_skeleton_name.c_str());
+  f_skeleton << "// This autogenerated skeleton file illustrates how to build a server." << endl
+             << "// You should copy it to another filename to avoid overwriting it." << endl << endl
+             << "#include \"" << get_include_prefix(*get_program()) << svcname << ".h\"" << endl
+             << "#include <thrift/protocol/TBinaryProtocol.h>" << endl
+             << "#include <thrift/server/TSimpleServer.h>" << endl
+             << "#include <thrift/transport/TServerSocket.h>" << endl
+             << "#include <thrift/transport/TBufferTransports.h>" << endl << endl
+             << "using namespace ::apache::thrift;" << endl
+             << "using namespace ::apache::thrift::protocol;" << endl
+             << "using namespace ::apache::thrift::transport;" << endl
+             << "using namespace ::apache::thrift::server;" << endl << endl;
+
+  // the following code would not compile:
+  // using namespace ;
+  // using namespace ::;
+  if ((!ns.empty()) && (ns.compare(" ::") != 0)) {
+    f_skeleton << "using namespace " << string(ns, 0, ns.size() - 2) << ";" << endl << endl;
+  }
+
+  f_skeleton << "class " << svcname << "Handler : virtual public " << svcname << "If {" << endl
+             << " public:" << endl;
+  indent_up();
+  f_skeleton << indent() << svcname << "Handler() {" << endl << indent()
+             << "  // Your initialization goes here" << endl << indent() << "}" << endl << endl;
+
+  vector<t_function*> functions = tservice->get_functions();
+  vector<t_function*>::iterator f_iter;
+  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
+    generate_java_doc(f_skeleton, *f_iter);
+    f_skeleton << indent() << function_signature(*f_iter, "") << " {" << endl << indent()
+               << "  // Your implementation goes here" << endl << indent() << "  printf(\""
+               << (*f_iter)->get_name() << "\\n\");" << endl << indent() << "}" << endl << endl;
+  }
+
+  indent_down();
+  f_skeleton << "};" << endl << endl;
+
+  f_skeleton << indent() << "int main(int argc, char **argv) {" << endl;
+  indent_up();
+  f_skeleton
+      << indent() << "int port = 9090;" << endl << indent() << "::apache::thrift::stdcxx::shared_ptr<" << svcname
+      << "Handler> handler(new " << svcname << "Handler());" << endl << indent()
+      << "::apache::thrift::stdcxx::shared_ptr<TProcessor> processor(new " << svcname << "Processor(handler));" << endl
+      << indent() << "::apache::thrift::stdcxx::shared_ptr<TServerTransport> serverTransport(new TServerSocket(port));"
+      << endl << indent()
+      << "::apache::thrift::stdcxx::shared_ptr<TTransportFactory> transportFactory(new TBufferedTransportFactory());" << endl
+      << indent() << "::apache::thrift::stdcxx::shared_ptr<TProtocolFactory> protocolFactory(new TBinaryProtocolFactory());"
+      << endl << endl << indent()
+      << "TSimpleServer server(processor, serverTransport, transportFactory, protocolFactory);"
+      << endl << indent() << "server.serve();" << endl << indent() << "return 0;" << endl;
+  indent_down();
+  f_skeleton << "}" << endl << endl;
+
+  // Close the files
+  f_skeleton.close();
+}
+
+/**
+ * Deserializes a field of any type.
+ */
+void t_cpp_generator::generate_deserialize_field(ostream& out,
+                                                 t_field* tfield,
+                                                 string prefix,
+                                                 string suffix) {
+  t_type* type = get_true_type(tfield->get_type());
+
+  if (type->is_void()) {
+    throw "CANNOT GENERATE DESERIALIZE CODE FOR void TYPE: " + prefix + tfield->get_name();
+  }
+
+  string name = prefix + tfield->get_name() + suffix;
+
+  if (type->is_struct() || type->is_xception()) {
+    generate_deserialize_struct(out, (t_struct*)type, name, is_reference(tfield));
+  } else if (type->is_container()) {
+    generate_deserialize_container(out, type, name);
+  } else if (type->is_base_type()) {
+    indent(out) << "xfer += iprot->";
+    t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
+    switch (tbase) {
+    case t_base_type::TYPE_VOID:
+      throw "compiler error: cannot serialize void field in a struct: " + name;
+      break;
+    case t_base_type::TYPE_STRING:
+      if (type->is_binary()) {
+        out << "readBinary(" << name << ");";
+      } else {
+        out << "readString(" << name << ");";
+      }
+      break;
+    case t_base_type::TYPE_BOOL:
+      out << "readBool(" << name << ");";
+      break;
+    case t_base_type::TYPE_I8:
+      out << "readByte(" << name << ");";
+      break;
+    case t_base_type::TYPE_I16:
+      out << "readI16(" << name << ");";
+      break;
+    case t_base_type::TYPE_I32:
+      out << "readI32(" << name << ");";
+      break;
+    case t_base_type::TYPE_I64:
+      out << "readI64(" << name << ");";
+      break;
+    case t_base_type::TYPE_DOUBLE:
+      out << "readDouble(" << name << ");";
+      break;
+    default:
+      throw "compiler error: no C++ reader for base type " + t_base_type::t_base_name(tbase) + name;
+    }
+    out << endl;
+  } else if (type->is_enum()) {
+    string t = tmp("ecast");
+    out << indent() << "int32_t " << t << ";" << endl << indent() << "xfer += iprot->readI32(" << t
+        << ");" << endl << indent() << name << " = (" << type_name(type) << ")" << t << ";" << endl;
+  } else {
+    printf("DO NOT KNOW HOW TO DESERIALIZE FIELD '%s' TYPE '%s'\n",
+           tfield->get_name().c_str(),
+           type_name(type).c_str());
+  }
+}
+
+/**
+ * Generates an unserializer for a variable. This makes two key assumptions,
+ * first that there is a const char* variable named data that points to the
+ * buffer for deserialization, and that there is a variable protocol which
+ * is a reference to a TProtocol serialization object.
+ */
+void t_cpp_generator::generate_deserialize_struct(ostream& out,
+                                                  t_struct* tstruct,
+                                                  string prefix,
+                                                  bool pointer) {
+  if (pointer) {
+    indent(out) << "if (!" << prefix << ") { " << endl;
+    indent(out) << "  " << prefix << " = ::apache::thrift::stdcxx::shared_ptr<" << type_name(tstruct) << ">(new "
+                << type_name(tstruct) << ");" << endl;
+    indent(out) << "}" << endl;
+    indent(out) << "xfer += " << prefix << "->read(iprot);" << endl;
+    indent(out) << "bool wasSet = false;" << endl;
+    const vector<t_field*>& members = tstruct->get_members();
+    vector<t_field*>::const_iterator f_iter;
+    for (f_iter = members.begin(); f_iter != members.end(); ++f_iter) {
+
+      indent(out) << "if (" << prefix << "->__isset." << (*f_iter)->get_name()
+                  << ") { wasSet = true; }" << endl;
+    }
+    indent(out) << "if (!wasSet) { " << prefix << ".reset(); }" << endl;
+  } else {
+    indent(out) << "xfer += " << prefix << ".read(iprot);" << endl;
+  }
+}
+
+void t_cpp_generator::generate_deserialize_container(ostream& out, t_type* ttype, string prefix) {
+  scope_up(out);
+
+  string size = tmp("_size");
+  string ktype = tmp("_ktype");
+  string vtype = tmp("_vtype");
+  string etype = tmp("_etype");
+
+  t_container* tcontainer = (t_container*)ttype;
+  bool use_push = tcontainer->has_cpp_name();
+
+  indent(out) << prefix << ".clear();" << endl << indent() << "uint32_t " << size << ";" << endl;
+
+  // Declare variables, read header
+  if (ttype->is_map()) {
+    out << indent() << "::apache::thrift::protocol::TType " << ktype << ";" << endl << indent()
+        << "::apache::thrift::protocol::TType " << vtype << ";" << endl << indent()
+        << "xfer += iprot->readMapBegin(" << ktype << ", " << vtype << ", " << size << ");" << endl;
+  } else if (ttype->is_set()) {
+    out << indent() << "::apache::thrift::protocol::TType " << etype << ";" << endl << indent()
+        << "xfer += iprot->readSetBegin(" << etype << ", " << size << ");" << endl;
+  } else if (ttype->is_list()) {
+    out << indent() << "::apache::thrift::protocol::TType " << etype << ";" << endl << indent()
+        << "xfer += iprot->readListBegin(" << etype << ", " << size << ");" << endl;
+    if (!use_push) {
+      indent(out) << prefix << ".resize(" << size << ");" << endl;
+    }
+  }
+
+  // For loop iterates over elements
+  string i = tmp("_i");
+  out << indent() << "uint32_t " << i << ";" << endl << indent() << "for (" << i << " = 0; " << i
+      << " < " << size << "; ++" << i << ")" << endl;
+
+  scope_up(out);
+
+  if (ttype->is_map()) {
+    generate_deserialize_map_element(out, (t_map*)ttype, prefix);
+  } else if (ttype->is_set()) {
+    generate_deserialize_set_element(out, (t_set*)ttype, prefix);
+  } else if (ttype->is_list()) {
+    generate_deserialize_list_element(out, (t_list*)ttype, prefix, use_push, i);
+  }
+
+  scope_down(out);
+
+  // Read container end
+  if (ttype->is_map()) {
+    indent(out) << "xfer += iprot->readMapEnd();" << endl;
+  } else if (ttype->is_set()) {
+    indent(out) << "xfer += iprot->readSetEnd();" << endl;
+  } else if (ttype->is_list()) {
+    indent(out) << "xfer += iprot->readListEnd();" << endl;
+  }
+
+  scope_down(out);
+}
+
+/**
+ * Generates code to deserialize a map
+ */
+void t_cpp_generator::generate_deserialize_map_element(ostream& out, t_map* tmap, string prefix) {
+  string key = tmp("_key");
+  string val = tmp("_val");
+  t_field fkey(tmap->get_key_type(), key);
+  t_field fval(tmap->get_val_type(), val);
+
+  out << indent() << declare_field(&fkey) << endl;
+
+  generate_deserialize_field(out, &fkey);
+  indent(out) << declare_field(&fval, false, false, false, true) << " = " << prefix << "[" << key
+              << "];" << endl;
+
+  generate_deserialize_field(out, &fval);
+}
+
+void t_cpp_generator::generate_deserialize_set_element(ostream& out, t_set* tset, string prefix) {
+  string elem = tmp("_elem");
+  t_field felem(tset->get_elem_type(), elem);
+
+  indent(out) << declare_field(&felem) << endl;
+
+  generate_deserialize_field(out, &felem);
+
+  indent(out) << prefix << ".insert(" << elem << ");" << endl;
+}
+
+void t_cpp_generator::generate_deserialize_list_element(ostream& out,
+                                                        t_list* tlist,
+                                                        string prefix,
+                                                        bool use_push,
+                                                        string index) {
+  if (use_push) {
+    string elem = tmp("_elem");
+    t_field felem(tlist->get_elem_type(), elem);
+    indent(out) << declare_field(&felem) << endl;
+    generate_deserialize_field(out, &felem);
+    indent(out) << prefix << ".push_back(" << elem << ");" << endl;
+  } else {
+    t_field felem(tlist->get_elem_type(), prefix + "[" + index + "]");
+    generate_deserialize_field(out, &felem);
+  }
+}
+
+/**
+ * Serializes a field of any type.
+ *
+ * @param tfield The field to serialize
+ * @param prefix Name to prepend to field name
+ */
+void t_cpp_generator::generate_serialize_field(ostream& out,
+                                               t_field* tfield,
+                                               string prefix,
+                                               string suffix) {
+  t_type* type = get_true_type(tfield->get_type());
+
+  string name = prefix + tfield->get_name() + suffix;
+
+  // Do nothing for void types
+  if (type->is_void()) {
+    throw "CANNOT GENERATE SERIALIZE CODE FOR void TYPE: " + name;
+  }
+
+  if (type->is_struct() || type->is_xception()) {
+    generate_serialize_struct(out, (t_struct*)type, name, is_reference(tfield));
+  } else if (type->is_container()) {
+    generate_serialize_container(out, type, name);
+  } else if (type->is_base_type() || type->is_enum()) {
+
+    indent(out) << "xfer += oprot->";
+
+    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:
+        throw "compiler error: cannot serialize void field in a struct: " + name;
+        break;
+      case t_base_type::TYPE_STRING:
+        if (type->is_binary()) {
+          out << "writeBinary(" << name << ");";
+        } else {
+          out << "writeString(" << name << ");";
+        }
+        break;
+      case t_base_type::TYPE_BOOL:
+        out << "writeBool(" << name << ");";
+        break;
+      case t_base_type::TYPE_I8:
+        out << "writeByte(" << name << ");";
+        break;
+      case t_base_type::TYPE_I16:
+        out << "writeI16(" << name << ");";
+        break;
+      case t_base_type::TYPE_I32:
+        out << "writeI32(" << name << ");";
+        break;
+      case t_base_type::TYPE_I64:
+        out << "writeI64(" << name << ");";
+        break;
+      case t_base_type::TYPE_DOUBLE:
+        out << "writeDouble(" << name << ");";
+        break;
+      default:
+        throw "compiler error: no C++ writer for base type " + t_base_type::t_base_name(tbase)
+            + name;
+      }
+    } else if (type->is_enum()) {
+      out << "writeI32((int32_t)" << name << ");";
+    }
+    out << endl;
+  } else {
+    printf("DO NOT KNOW HOW TO SERIALIZE FIELD '%s' TYPE '%s'\n",
+           name.c_str(),
+           type_name(type).c_str());
+  }
+}
+
+/**
+ * Serializes all the members of a struct.
+ *
+ * @param tstruct The struct to serialize
+ * @param prefix  String prefix to attach to all fields
+ */
+void t_cpp_generator::generate_serialize_struct(ostream& out,
+                                                t_struct* tstruct,
+                                                string prefix,
+                                                bool pointer) {
+  if (pointer) {
+    indent(out) << "if (" << prefix << ") {" << endl;
+    indent(out) << "  xfer += " << prefix << "->write(oprot); " << endl;
+    indent(out) << "} else {"
+                << "oprot->writeStructBegin(\"" << tstruct->get_name() << "\"); " << endl;
+    indent(out) << "  oprot->writeStructEnd();" << endl;
+    indent(out) << "  oprot->writeFieldStop();" << endl;
+    indent(out) << "}" << endl;
+  } else {
+    indent(out) << "xfer += " << prefix << ".write(oprot);" << endl;
+  }
+}
+
+void t_cpp_generator::generate_serialize_container(ostream& out, t_type* ttype, string prefix) {
+  scope_up(out);
+
+  if (ttype->is_map()) {
+    indent(out) << "xfer += oprot->writeMapBegin(" << type_to_enum(((t_map*)ttype)->get_key_type())
+                << ", " << type_to_enum(((t_map*)ttype)->get_val_type()) << ", "
+                << "static_cast<uint32_t>(" << prefix << ".size()));" << endl;
+  } else if (ttype->is_set()) {
+    indent(out) << "xfer += oprot->writeSetBegin(" << type_to_enum(((t_set*)ttype)->get_elem_type())
+                << ", "
+                << "static_cast<uint32_t>(" << prefix << ".size()));" << endl;
+  } else if (ttype->is_list()) {
+    indent(out) << "xfer += oprot->writeListBegin("
+                << type_to_enum(((t_list*)ttype)->get_elem_type()) << ", "
+                << "static_cast<uint32_t>(" << prefix << ".size()));" << endl;
+  }
+
+  string iter = tmp("_iter");
+  out << indent() << type_name(ttype) << "::const_iterator " << iter << ";" << endl << indent()
+      << "for (" << iter << " = " << prefix << ".begin(); " << iter << " != " << prefix
+      << ".end(); ++" << iter << ")" << endl;
+  scope_up(out);
+  if (ttype->is_map()) {
+    generate_serialize_map_element(out, (t_map*)ttype, iter);
+  } else if (ttype->is_set()) {
+    generate_serialize_set_element(out, (t_set*)ttype, iter);
+  } else if (ttype->is_list()) {
+    generate_serialize_list_element(out, (t_list*)ttype, iter);
+  }
+  scope_down(out);
+
+  if (ttype->is_map()) {
+    indent(out) << "xfer += oprot->writeMapEnd();" << endl;
+  } else if (ttype->is_set()) {
+    indent(out) << "xfer += oprot->writeSetEnd();" << endl;
+  } else if (ttype->is_list()) {
+    indent(out) << "xfer += oprot->writeListEnd();" << endl;
+  }
+
+  scope_down(out);
+}
+
+/**
+ * Serializes the members of a map.
+ *
+ */
+void t_cpp_generator::generate_serialize_map_element(ostream& out, t_map* tmap, string iter) {
+  t_field kfield(tmap->get_key_type(), iter + "->first");
+  generate_serialize_field(out, &kfield, "");
+
+  t_field vfield(tmap->get_val_type(), iter + "->second");
+  generate_serialize_field(out, &vfield, "");
+}
+
+/**
+ * Serializes the members of a set.
+ */
+void t_cpp_generator::generate_serialize_set_element(ostream& out, t_set* tset, string iter) {
+  t_field efield(tset->get_elem_type(), "(*" + iter + ")");
+  generate_serialize_field(out, &efield, "");
+}
+
+/**
+ * Serializes the members of a list.
+ */
+void t_cpp_generator::generate_serialize_list_element(ostream& out, t_list* tlist, string iter) {
+  t_field efield(tlist->get_elem_type(), "(*" + iter + ")");
+  generate_serialize_field(out, &efield, "");
+}
+
+/**
+ * Makes a :: prefix for a namespace
+ *
+ * @param ns The namespace, w/ periods in it
+ * @return Namespaces
+ */
+string t_cpp_generator::namespace_prefix(string ns) {
+  // Always start with "::", to avoid possible name collisions with
+  // other names in one of the current namespaces.
+  //
+  // We also need a leading space, in case the name is used inside of a
+  // template parameter.  "MyTemplate<::foo::Bar>" is not valid C++,
+  // since "<:" is an alternative token for "[".
+  string result = " ::";
+
+  if (ns.size() == 0) {
+    return result;
+  }
+  string::size_type loc;
+  while ((loc = ns.find(".")) != string::npos) {
+    result += ns.substr(0, loc);
+    result += "::";
+    ns = ns.substr(loc + 1);
+  }
+  if (ns.size() > 0) {
+    result += ns + "::";
+  }
+  return result;
+}
+
+/**
+ * Opens namespace.
+ *
+ * @param ns The namespace, w/ periods in it
+ * @return Namespaces
+ */
+string t_cpp_generator::namespace_open(string ns) {
+  if (ns.size() == 0) {
+    return "";
+  }
+  string result = "";
+  string separator = "";
+  string::size_type loc;
+  while ((loc = ns.find(".")) != string::npos) {
+    result += separator;
+    result += "namespace ";
+    result += ns.substr(0, loc);
+    result += " {";
+    separator = " ";
+    ns = ns.substr(loc + 1);
+  }
+  if (ns.size() > 0) {
+    result += separator + "namespace " + ns + " {";
+  }
+  return result;
+}
+
+/**
+ * Closes namespace.
+ *
+ * @param ns The namespace, w/ periods in it
+ * @return Namespaces
+ */
+string t_cpp_generator::namespace_close(string ns) {
+  if (ns.size() == 0) {
+    return "";
+  }
+  string result = "}";
+  string::size_type loc;
+  while ((loc = ns.find(".")) != string::npos) {
+    result += "}";
+    ns = ns.substr(loc + 1);
+  }
+  result += " // namespace";
+  return result;
+}
+
+/**
+ * Returns a C++ type name
+ *
+ * @param ttype The type
+ * @return String of the type name, i.e. std::set<type>
+ */
+string t_cpp_generator::type_name(t_type* ttype, bool in_typedef, bool arg) {
+  if (ttype->is_base_type()) {
+    string bname = base_type_name(((t_base_type*)ttype)->get_base());
+    std::map<string, string>::iterator it = ttype->annotations_.find("cpp.type");
+    if (it != ttype->annotations_.end()) {
+      bname = it->second;
+    }
+
+    if (!arg) {
+      return bname;
+    }
+
+    if (((t_base_type*)ttype)->get_base() == t_base_type::TYPE_STRING) {
+      return "const " + bname + "&";
+    } else {
+      return "const " + bname;
+    }
+  }
+
+  // Check for a custom overloaded C++ name
+  if (ttype->is_container()) {
+    string cname;
+
+    t_container* tcontainer = (t_container*)ttype;
+    if (tcontainer->has_cpp_name()) {
+      cname = tcontainer->get_cpp_name();
+    } else if (ttype->is_map()) {
+      t_map* tmap = (t_map*)ttype;
+      cname = "std::map<" + type_name(tmap->get_key_type(), in_typedef) + ", "
+              + type_name(tmap->get_val_type(), in_typedef) + "> ";
+    } else if (ttype->is_set()) {
+      t_set* tset = (t_set*)ttype;
+      cname = "std::set<" + type_name(tset->get_elem_type(), in_typedef) + "> ";
+    } else if (ttype->is_list()) {
+      t_list* tlist = (t_list*)ttype;
+      cname = "std::vector<" + type_name(tlist->get_elem_type(), in_typedef) + "> ";
+    }
+
+    if (arg) {
+      return "const " + cname + "&";
+    } else {
+      return cname;
+    }
+  }
+
+  string class_prefix;
+  if (in_typedef && (ttype->is_struct() || ttype->is_xception())) {
+    class_prefix = "class ";
+  }
+
+  // Check if it needs to be namespaced
+  string pname;
+  t_program* program = ttype->get_program();
+  if (program != NULL && program != program_) {
+    pname = class_prefix + namespace_prefix(program->get_namespace("cpp")) + ttype->get_name();
+  } else {
+    pname = class_prefix + ttype->get_name();
+  }
+
+  if (ttype->is_enum() && !gen_pure_enums_) {
+    pname += "::type";
+  }
+
+  if (arg) {
+    if (is_complex_type(ttype)) {
+      return "const " + pname + "&";
+    } else {
+      return "const " + pname;
+    }
+  } else {
+    return pname;
+  }
+}
+
+/**
+ * Returns the C++ type that corresponds to the thrift type.
+ *
+ * @param tbase The base type
+ * @return Explicit C++ type, i.e. "int32_t"
+ */
+string t_cpp_generator::base_type_name(t_base_type::t_base tbase) {
+  switch (tbase) {
+  case t_base_type::TYPE_VOID:
+    return "void";
+  case t_base_type::TYPE_STRING:
+    return "std::string";
+  case t_base_type::TYPE_BOOL:
+    return "bool";
+  case t_base_type::TYPE_I8:
+    return "int8_t";
+  case t_base_type::TYPE_I16:
+    return "int16_t";
+  case t_base_type::TYPE_I32:
+    return "int32_t";
+  case t_base_type::TYPE_I64:
+    return "int64_t";
+  case t_base_type::TYPE_DOUBLE:
+    return "double";
+  default:
+    throw "compiler error: no C++ base type name for base type " + t_base_type::t_base_name(tbase);
+  }
+}
+
+/**
+ * Declares a field, which may include initialization as necessary.
+ *
+ * @param ttype The type
+ * @return Field declaration, i.e. int x = 0;
+ */
+string t_cpp_generator::declare_field(t_field* tfield,
+                                      bool init,
+                                      bool pointer,
+                                      bool constant,
+                                      bool reference) {
+  // TODO(mcslee): do we ever need to initialize the field?
+  string result = "";
+  if (constant) {
+    result += "const ";
+  }
+  result += type_name(tfield->get_type());
+  if (is_reference(tfield)) {
+    result = "::apache::thrift::stdcxx::shared_ptr<" + result + ">";
+  }
+  if (pointer) {
+    result += "*";
+  }
+  if (reference) {
+    result += "&";
+  }
+  result += " " + tfield->get_name();
+  if (init) {
+    t_type* type = get_true_type(tfield->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:
+      case t_base_type::TYPE_STRING:
+        break;
+      case t_base_type::TYPE_BOOL:
+        result += " = false";
+        break;
+      case t_base_type::TYPE_I8:
+      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 += " = (double)0";
+        break;
+      default:
+        throw "compiler error: no C++ initializer for base type " + t_base_type::t_base_name(tbase);
+      }
+    } else if (type->is_enum()) {
+      result += " = (" + type_name(type) + ")0";
+    }
+  }
+  if (!reference) {
+    result += ";";
+  }
+  return result;
+}
+
+/**
+ * Renders a function signature of the form 'type name(args)'
+ *
+ * @param tfunction Function definition
+ * @return String of rendered function definition
+ */
+string t_cpp_generator::function_signature(t_function* tfunction,
+                                           string style,
+                                           string prefix,
+                                           bool name_params) {
+  t_type* ttype = tfunction->get_returntype();
+  t_struct* arglist = tfunction->get_arglist();
+  bool has_xceptions = !tfunction->get_xceptions()->get_members().empty();
+
+  if (style == "") {
+    if (is_complex_type(ttype)) {
+      return "void " + prefix + tfunction->get_name() + "(" + type_name(ttype)
+             + (name_params ? "& _return" : "& /* _return */")
+             + argument_list(arglist, name_params, true) + ")";
+    } else {
+      return type_name(ttype) + " " + prefix + tfunction->get_name() + "("
+             + argument_list(arglist, name_params) + ")";
+    }
+  } else if (style.substr(0, 3) == "Cob") {
+    string cob_type;
+    string exn_cob;
+    if (style == "CobCl") {
+      cob_type = "(" + service_name_ + "CobClient";
+      if (gen_templates_) {
+        cob_type += "T<Protocol_>";
+      }
+      cob_type += "* client)";
+    } else if (style == "CobSv") {
+      cob_type = (ttype->is_void() ? "()" : ("(" + type_name(ttype) + " const& _return)"));
+      if (has_xceptions) {
+        exn_cob
+            = ", ::apache::thrift::stdcxx::function<void(::apache::thrift::TDelayedException* _throw)> /* exn_cob */";
+      }
+    } else {
+      throw "UNKNOWN STYLE";
+    }
+
+    return "void " + prefix + tfunction->get_name() + "(::apache::thrift::stdcxx::function<void" + cob_type + "> cob"
+           + exn_cob + argument_list(arglist, name_params, true) + ")";
+  } else {
+    throw "UNKNOWN STYLE";
+  }
+}
+
+/**
+ * Renders a field list
+ *
+ * @param tstruct The struct definition
+ * @return Comma sepearated list of all field names in that struct
+ */
+string t_cpp_generator::argument_list(t_struct* tstruct, bool name_params, bool start_comma) {
+  string result = "";
+
+  const vector<t_field*>& fields = tstruct->get_members();
+  vector<t_field*>::const_iterator f_iter;
+  bool first = !start_comma;
+  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+    if (first) {
+      first = false;
+    } else {
+      result += ", ";
+    }
+    result += type_name((*f_iter)->get_type(), false, true) + " "
+              + (name_params ? (*f_iter)->get_name() : "/* " + (*f_iter)->get_name() + " */");
+  }
+  return result;
+}
+
+/**
+ * Converts the parse type to a C++ enum string for the given type.
+ *
+ * @param type Thrift Type
+ * @return String of C++ code to definition of that type constant
+ */
+string t_cpp_generator::type_to_enum(t_type* type) {
+  type = get_true_type(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:
+      throw "NO T_VOID CONSTRUCT";
+    case t_base_type::TYPE_STRING:
+      return "::apache::thrift::protocol::T_STRING";
+    case t_base_type::TYPE_BOOL:
+      return "::apache::thrift::protocol::T_BOOL";
+    case t_base_type::TYPE_I8:
+      return "::apache::thrift::protocol::T_BYTE";
+    case t_base_type::TYPE_I16:
+      return "::apache::thrift::protocol::T_I16";
+    case t_base_type::TYPE_I32:
+      return "::apache::thrift::protocol::T_I32";
+    case t_base_type::TYPE_I64:
+      return "::apache::thrift::protocol::T_I64";
+    case t_base_type::TYPE_DOUBLE:
+      return "::apache::thrift::protocol::T_DOUBLE";
+    }
+  } else if (type->is_enum()) {
+    return "::apache::thrift::protocol::T_I32";
+  } else if (type->is_struct()) {
+    return "::apache::thrift::protocol::T_STRUCT";
+  } else if (type->is_xception()) {
+    return "::apache::thrift::protocol::T_STRUCT";
+  } else if (type->is_map()) {
+    return "::apache::thrift::protocol::T_MAP";
+  } else if (type->is_set()) {
+    return "::apache::thrift::protocol::T_SET";
+  } else if (type->is_list()) {
+    return "::apache::thrift::protocol::T_LIST";
+  }
+
+  throw "INVALID TYPE IN type_to_enum: " + type->get_name();
+}
+
+string t_cpp_generator::get_include_prefix(const t_program& program) const {
+  string include_prefix = program.get_include_prefix();
+  if (!use_include_prefix_ || (include_prefix.size() > 0 && include_prefix[0] == '/')) {
+    // if flag is turned off or this is absolute path, return empty prefix
+    return "";
+  }
+
+  string::size_type last_slash = string::npos;
+  if ((last_slash = include_prefix.rfind("/")) != string::npos) {
+    return include_prefix.substr(0, last_slash)
+           + (get_program()->is_out_path_absolute() ? "/" : "/" + out_dir_base_ + "/");
+  }
+
+  return "";
+}
+
+THRIFT_REGISTER_GENERATOR(
+    cpp,
+    "C++",
+    "    cob_style:       Generate \"Continuation OBject\"-style classes.\n"
+    "    no_client_completion:\n"
+    "                     Omit calls to completion__() in CobClient class.\n"
+    "    no_default_operators:\n"
+    "                     Omits generation of default operators ==, != and <\n"
+    "    templates:       Generate templatized reader/writer methods.\n"
+    "    pure_enums:      Generate pure enums instead of wrapper classes.\n"
+    "    include_prefix:  Use full include paths in generated files.\n"
+    "    moveable_types:  Generate move constructors and assignment operators.\n"
+    "    no_ostream_operators:\n"
+    "                     Omit generation of ostream definitions.\n"
+    "    no_skeleton:     Omits generation of skeleton.\n")

+ 3224 - 3224
contrib/restricted/thrift/compiler/thrift/generate/t_csharp_generator.cc

@@ -1,3224 +1,3224 @@
-/* 
- * Licensed to the Apache Software Foundation (ASF) under one 
- * or more contributor license agreements. See the NOTICE file 
- * distributed with this work for additional information 
- * regarding copyright ownership. The ASF licenses this file 
- * to you under the Apache License, Version 2.0 (the 
- * "License"); you may not use this file except in compliance 
- * with the License. You may obtain a copy of the License at 
- * 
- *   http://www.apache.org/licenses/LICENSE-2.0 
- * 
- * Unless required by applicable law or agreed to in writing, 
- * software distributed under the License is distributed on an 
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 
- * KIND, either express or implied. See the License for the 
- * specific language governing permissions and limitations 
- * under the License. 
- * 
- * Contains some contributions under the Thrift Software License. 
- * Please see doc/old-thrift-license.txt in the Thrift distribution for 
- * details. 
- */ 
- 
-#include <cassert> 
- 
-#include <string> 
-#include <fstream> 
-#include <iostream> 
-#include <vector> 
-#include <cctype> 
- 
-#include <stdlib.h> 
-#include <sys/stat.h> 
-#include <sstream> 
- 
-#include "thrift/platform.h" 
-#include "thrift/generate/t_oop_generator.h" 
- 
-using std::map; 
-using std::ostream; 
-using std::ostringstream; 
-using std::string; 
-using std::stringstream; 
-using std::vector; 
- 
-static const string endl = "\n"; // avoid ostream << std::endl flushes 
- 
-struct member_mapping_scope { 
-  void* scope_member; 
-  std::map<std::string, std::string> mapping_table; 
-}; 
- 
-class t_csharp_generator : public t_oop_generator { 
-public: 
-  t_csharp_generator(t_program* program, 
-                     const std::map<std::string, std::string>& parsed_options, 
-                     const std::string& option_string) 
-    : t_oop_generator(program) { 
-    (void)option_string; 
- 
-    std::map<std::string, std::string>::const_iterator iter; 
- 
-    async_ = false; 
-    nullable_ = false; 
-    hashcode_ = false; 
-    union_ = false; 
-    serialize_ = false; 
-    wcf_ = false; 
-    wcf_namespace_.clear(); 
-    for( iter = parsed_options.begin(); iter != parsed_options.end(); ++iter) { 
-      if( iter->first.compare("async") == 0) { 
-        async_ = true; 
-      } else if( iter->first.compare("nullable") == 0) { 
-        nullable_ = true; 
-      } else if( iter->first.compare("hashcode") == 0) { 
-        hashcode_ = true; 
-      } else if( iter->first.compare("union") == 0) { 
-        union_ = true; 
-      } else if( iter->first.compare("serial") == 0) { 
-        serialize_ = true; 
-        wcf_namespace_ = iter->second; // since there can be only one namespace 
-      } else if( iter->first.compare("wcf") == 0) { 
-        wcf_ = true; 
-        wcf_namespace_ = iter->second; 
-      } else { 
-        throw "unknown option csharp:" + iter->first; 
-      } 
-    } 
- 
-    out_dir_base_ = "gen-csharp"; 
-  } 
-  void init_generator(); 
-  void close_generator(); 
- 
-  void generate_consts(std::vector<t_const*> consts); 
- 
-  void generate_typedef(t_typedef* ttypedef); 
-  void generate_enum(t_enum* tenum); 
-  void generate_struct(t_struct* tstruct); 
-  void generate_union(t_struct* tunion); 
-  void generate_xception(t_struct* txception); 
-  void generate_service(t_service* tservice); 
-  void generate_property(ostream& out, t_field* tfield, bool isPublic, bool generateIsset); 
-  void generate_csharp_property(ostream& out, 
-                                t_field* tfield, 
-                                bool isPublic, 
-                                bool includeIsset = true, 
-                                std::string fieldPrefix = ""); 
-  bool print_const_value(std::ostream& out, 
-                         std::string name, 
-                         t_type* type, 
-                         t_const_value* value, 
-                         bool in_static, 
-                         bool defval = false, 
-                         bool needtype = false); 
-  std::string render_const_value(std::ostream& out, 
-                                 std::string name, 
-                                 t_type* type, 
-                                 t_const_value* value); 
-  void print_const_constructor(std::ostream& out, std::vector<t_const*> consts); 
-  void print_const_def_value(std::ostream& out, 
-                             std::string name, 
-                             t_type* type, 
-                             t_const_value* value); 
- 
-  void generate_csharp_struct(t_struct* tstruct, bool is_exception); 
-  void generate_csharp_union(t_struct* tunion); 
-  void generate_csharp_struct_definition(std::ostream& out, 
-                                         t_struct* tstruct, 
-                                         bool is_xception = false, 
-                                         bool in_class = false, 
-                                         bool is_result = false); 
-  void generate_csharp_union_definition(std::ostream& out, t_struct* tunion); 
-  void generate_csharp_union_class(std::ostream& out, t_struct* tunion, t_field* tfield); 
-  void generate_csharp_wcffault(std::ostream& out, t_struct* tstruct); 
-  void generate_csharp_struct_reader(std::ostream& out, t_struct* tstruct); 
-  void generate_csharp_struct_result_writer(std::ostream& out, t_struct* tstruct); 
-  void generate_csharp_struct_writer(std::ostream& out, t_struct* tstruct); 
-  void generate_csharp_struct_tostring(std::ostream& out, t_struct* tstruct); 
-  void generate_csharp_struct_equals(std::ostream& out, t_struct* tstruct); 
-  void generate_csharp_struct_hashcode(std::ostream& out, t_struct* tstruct); 
-  void generate_csharp_union_reader(std::ostream& out, t_struct* tunion); 
- 
-  void generate_function_helpers(t_function* tfunction); 
-  void generate_service_interface(t_service* tservice); 
-  void generate_separate_service_interfaces(t_service* tservice); 
-  void generate_sync_service_interface(t_service* tservice); 
-  void generate_async_service_interface(t_service* tservice); 
-  void generate_combined_service_interface(t_service* tservice); 
-  void generate_silverlight_async_methods(t_service* tservice); 
-  void generate_service_helpers(t_service* tservice); 
-  void generate_service_client(t_service* tservice); 
-  void generate_service_server(t_service* tservice); 
-  void generate_service_server_sync(t_service* tservice); 
-  void generate_service_server_async(t_service* tservice); 
-  void generate_process_function(t_service* tservice, t_function* function); 
-  void generate_process_function_async(t_service* tservice, t_function* function); 
- 
-  void generate_deserialize_field(std::ostream& out, 
-                                  t_field* tfield, 
-                                  std::string prefix = "", 
-                                  bool is_propertyless = false); 
-  void generate_deserialize_struct(std::ostream& out, t_struct* tstruct, std::string prefix = ""); 
-  void generate_deserialize_container(std::ostream& out, t_type* ttype, std::string prefix = ""); 
-  void generate_deserialize_set_element(std::ostream& out, t_set* tset, std::string prefix = ""); 
-  void generate_deserialize_map_element(std::ostream& out, t_map* tmap, std::string prefix = ""); 
-  void generate_deserialize_list_element(std::ostream& out, t_list* list, std::string prefix = ""); 
-  void generate_serialize_field(std::ostream& out, 
-                                t_field* tfield, 
-                                std::string prefix = "", 
-                                bool is_element = false, 
-                                bool is_propertyless = false); 
-  void generate_serialize_struct(std::ostream& out, t_struct* tstruct, std::string prefix = ""); 
-  void generate_serialize_container(std::ostream& out, t_type* ttype, std::string prefix = ""); 
-  void generate_serialize_map_element(std::ostream& out, 
-                                      t_map* tmap, 
-                                      std::string iter, 
-                                      std::string map); 
-  void generate_serialize_set_element(std::ostream& out, t_set* tmap, std::string iter); 
-  void generate_serialize_list_element(std::ostream& out, t_list* tlist, std::string iter); 
- 
-  void generate_csharp_doc(std::ostream& out, t_field* field); 
-  void generate_csharp_doc(std::ostream& out, t_doc* tdoc); 
-  void generate_csharp_doc(std::ostream& out, t_function* tdoc); 
-  void generate_csharp_docstring_comment(std::ostream& out, string contents); 
- 
-  void start_csharp_namespace(std::ostream& out); 
-  void end_csharp_namespace(std::ostream& out); 
- 
-  std::string csharp_type_usings(); 
-  std::string csharp_thrift_usings(); 
- 
-  std::string type_name(t_type* ttype, 
-                        bool in_countainer = false, 
-                        bool in_init = false, 
-                        bool in_param = false, 
-                        bool is_required = false); 
-  std::string base_type_name(t_base_type* tbase, 
-                             bool in_container = false, 
-                             bool in_param = false, 
-                             bool is_required = false); 
-  std::string declare_field(t_field* tfield, bool init = false, std::string prefix = ""); 
-  std::string function_signature_async_begin(t_function* tfunction, std::string prefix = ""); 
-  std::string function_signature_async_end(t_function* tfunction, std::string prefix = ""); 
-  std::string function_signature_async(t_function* tfunction, std::string prefix = ""); 
-  std::string function_signature(t_function* tfunction, std::string prefix = ""); 
-  std::string argument_list(t_struct* tstruct); 
-  std::string type_to_enum(t_type* ttype); 
-  std::string prop_name(t_field* tfield, bool suppress_mapping = false); 
-  std::string get_enum_class_name(t_type* type); 
- 
-  bool field_has_default(t_field* tfield) { return tfield->get_value() != NULL; } 
- 
-  bool field_is_required(t_field* tfield) { return tfield->get_req() == t_field::T_REQUIRED; } 
- 
-  bool type_can_be_null(t_type* ttype) { 
-    while (ttype->is_typedef()) { 
-      ttype = ((t_typedef*)ttype)->get_type(); 
-    } 
- 
-    return ttype->is_container() || ttype->is_struct() || ttype->is_xception() 
-           || ttype->is_string(); 
-  } 
- 
-private: 
-  std::string namespace_name_; 
-  ofstream_with_content_based_conditional_update f_service_; 
-  std::string namespace_dir_; 
-  bool async_; 
-  bool nullable_; 
-  bool union_; 
-  bool hashcode_; 
-  bool serialize_; 
-  bool wcf_; 
-  std::string wcf_namespace_; 
- 
-  std::map<std::string, int> csharp_keywords; 
-  std::vector<member_mapping_scope>  member_mapping_scopes; 
- 
-  void init_keywords(); 
-  std::string normalize_name(std::string name); 
-  std::string make_valid_csharp_identifier(std::string const& fromName); 
-  void prepare_member_name_mapping(t_struct* tstruct); 
-  void prepare_member_name_mapping(void* scope, 
-                                   const vector<t_field*>& members, 
-                                   const string& structname); 
-  void cleanup_member_name_mapping(void* scope); 
-  string get_mapped_member_name(string oldname); 
-}; 
- 
-void t_csharp_generator::init_generator() { 
-  MKDIR(get_out_dir().c_str()); 
-  namespace_name_ = program_->get_namespace("csharp"); 
- 
-  string dir = namespace_name_; 
-  string subdir = get_out_dir().c_str(); 
-  string::size_type loc; 
- 
-  while ((loc = dir.find(".")) != string::npos) { 
-    subdir = subdir + "/" + dir.substr(0, loc); 
-    MKDIR(subdir.c_str()); 
-    dir = dir.substr(loc + 1); 
-  } 
-  if (dir.size() > 0) { 
-    subdir = subdir + "/" + dir; 
-    MKDIR(subdir.c_str()); 
-  } 
- 
-  namespace_dir_ = subdir; 
-  init_keywords(); 
- 
-  while( ! member_mapping_scopes.empty()) { 
-    cleanup_member_name_mapping( member_mapping_scopes.back().scope_member); 
-  } 
- 
-  pverbose("C# options:\n"); 
-  pverbose("- async ...... %s\n", (async_ ? "ON" : "off")); 
-  pverbose("- nullable ... %s\n", (nullable_ ? "ON" : "off")); 
-  pverbose("- union ...... %s\n", (union_ ? "ON" : "off")); 
-  pverbose("- hashcode ... %s\n", (hashcode_ ? "ON" : "off")); 
-  pverbose("- serialize .. %s\n", (serialize_ ? "ON" : "off")); 
-  pverbose("- wcf ........ %s\n", (wcf_ ? "ON" : "off")); 
-} 
- 
-std::string t_csharp_generator::normalize_name(std::string name) { 
-  string tmp(name); 
-  std::transform(tmp.begin(), tmp.end(), tmp.begin(), static_cast<int (*)(int)>(std::tolower)); 
- 
-  // un-conflict keywords by prefixing with "@" 
-  if (csharp_keywords.find(tmp) != csharp_keywords.end()) { 
-    return "@" + name; 
-  } 
- 
-  // no changes necessary 
-  return name; 
-} 
- 
-void t_csharp_generator::init_keywords() { 
-  csharp_keywords.clear(); 
- 
-  // C# keywords 
-  csharp_keywords["abstract"] = 1; 
-  csharp_keywords["as"] = 1; 
-  csharp_keywords["base"] = 1; 
-  csharp_keywords["bool"] = 1; 
-  csharp_keywords["break"] = 1; 
-  csharp_keywords["byte"] = 1; 
-  csharp_keywords["case"] = 1; 
-  csharp_keywords["catch"] = 1; 
-  csharp_keywords["char"] = 1; 
-  csharp_keywords["checked"] = 1; 
-  csharp_keywords["class"] = 1; 
-  csharp_keywords["const"] = 1; 
-  csharp_keywords["continue"] = 1; 
-  csharp_keywords["decimal"] = 1; 
-  csharp_keywords["default"] = 1; 
-  csharp_keywords["delegate"] = 1; 
-  csharp_keywords["do"] = 1; 
-  csharp_keywords["double"] = 1; 
-  csharp_keywords["else"] = 1; 
-  csharp_keywords["enum"] = 1; 
-  csharp_keywords["event"] = 1; 
-  csharp_keywords["explicit"] = 1; 
-  csharp_keywords["extern"] = 1; 
-  csharp_keywords["false"] = 1; 
-  csharp_keywords["finally"] = 1; 
-  csharp_keywords["fixed"] = 1; 
-  csharp_keywords["float"] = 1; 
-  csharp_keywords["for"] = 1; 
-  csharp_keywords["foreach"] = 1; 
-  csharp_keywords["goto"] = 1; 
-  csharp_keywords["if"] = 1; 
-  csharp_keywords["implicit"] = 1; 
-  csharp_keywords["in"] = 1; 
-  csharp_keywords["int"] = 1; 
-  csharp_keywords["interface"] = 1; 
-  csharp_keywords["internal"] = 1; 
-  csharp_keywords["is"] = 1; 
-  csharp_keywords["lock"] = 1; 
-  csharp_keywords["long"] = 1; 
-  csharp_keywords["namespace"] = 1; 
-  csharp_keywords["new"] = 1; 
-  csharp_keywords["null"] = 1; 
-  csharp_keywords["object"] = 1; 
-  csharp_keywords["operator"] = 1; 
-  csharp_keywords["out"] = 1; 
-  csharp_keywords["override"] = 1; 
-  csharp_keywords["params"] = 1; 
-  csharp_keywords["private"] = 1; 
-  csharp_keywords["protected"] = 1; 
-  csharp_keywords["public"] = 1; 
-  csharp_keywords["readonly"] = 1; 
-  csharp_keywords["ref"] = 1; 
-  csharp_keywords["return"] = 1; 
-  csharp_keywords["sbyte"] = 1; 
-  csharp_keywords["sealed"] = 1; 
-  csharp_keywords["short"] = 1; 
-  csharp_keywords["sizeof"] = 1; 
-  csharp_keywords["stackalloc"] = 1; 
-  csharp_keywords["static"] = 1; 
-  csharp_keywords["string"] = 1; 
-  csharp_keywords["struct"] = 1; 
-  csharp_keywords["switch"] = 1; 
-  csharp_keywords["this"] = 1; 
-  csharp_keywords["throw"] = 1; 
-  csharp_keywords["true"] = 1; 
-  csharp_keywords["try"] = 1; 
-  csharp_keywords["typeof"] = 1; 
-  csharp_keywords["uint"] = 1; 
-  csharp_keywords["ulong"] = 1; 
-  csharp_keywords["unchecked"] = 1; 
-  csharp_keywords["unsafe"] = 1; 
-  csharp_keywords["ushort"] = 1; 
-  csharp_keywords["using"] = 1; 
-  csharp_keywords["virtual"] = 1; 
-  csharp_keywords["void"] = 1; 
-  csharp_keywords["volatile"] = 1; 
-  csharp_keywords["while"] = 1; 
- 
-  // C# contextual keywords 
-  csharp_keywords["add"] = 1; 
-  csharp_keywords["alias"] = 1; 
-  csharp_keywords["ascending"] = 1; 
-  csharp_keywords["async"] = 1; 
-  csharp_keywords["await"] = 1; 
-  csharp_keywords["descending"] = 1; 
-  csharp_keywords["dynamic"] = 1; 
-  csharp_keywords["from"] = 1; 
-  csharp_keywords["get"] = 1; 
-  csharp_keywords["global"] = 1; 
-  csharp_keywords["group"] = 1; 
-  csharp_keywords["into"] = 1; 
-  csharp_keywords["join"] = 1; 
-  csharp_keywords["let"] = 1; 
-  csharp_keywords["orderby"] = 1; 
-  csharp_keywords["partial"] = 1; 
-  csharp_keywords["remove"] = 1; 
-  csharp_keywords["select"] = 1; 
-  csharp_keywords["set"] = 1; 
-  csharp_keywords["value"] = 1; 
-  csharp_keywords["var"] = 1; 
-  csharp_keywords["where"] = 1; 
-  csharp_keywords["yield"] = 1; 
-} 
- 
-void t_csharp_generator::start_csharp_namespace(ostream& out) { 
-  if (!namespace_name_.empty()) { 
-    out << "namespace " << namespace_name_ << "\n"; 
-    scope_up(out); 
-  } 
-} 
- 
-void t_csharp_generator::end_csharp_namespace(ostream& out) { 
-  if (!namespace_name_.empty()) { 
-    scope_down(out); 
-  } 
-} 
- 
-string t_csharp_generator::csharp_type_usings() { 
-  return string() + "using System;\n" + "using System.Collections;\n" 
-         + "using System.Collections.Generic;\n" + "using System.Text;\n" + "using System.IO;\n" 
-         + ((async_) ? "using System.Threading.Tasks;\n" : "") + "using Thrift;\n" 
-         + "using Thrift.Collections;\n" + ((serialize_ || wcf_) ? "#if !SILVERLIGHT\n" : "") 
-         + ((serialize_ || wcf_) ? "using System.Xml.Serialization;\n" : "") 
-         + ((serialize_ || wcf_) ? "#endif\n" : "") + (wcf_ ? "//using System.ServiceModel;\n" : "") 
-         + "using System.Runtime.Serialization;\n"; 
-} 
- 
-string t_csharp_generator::csharp_thrift_usings() { 
-  return string() + "using Thrift.Protocol;\n" + "using Thrift.Transport;\n"; 
-} 
- 
-void t_csharp_generator::close_generator() { 
-} 
-void t_csharp_generator::generate_typedef(t_typedef* ttypedef) { 
-  (void)ttypedef; 
-} 
- 
-void t_csharp_generator::generate_enum(t_enum* tenum) { 
-  string f_enum_name = namespace_dir_ + "/" + (tenum->get_name()) + ".cs"; 
-  ofstream_with_content_based_conditional_update f_enum; 
-  f_enum.open(f_enum_name.c_str()); 
- 
-  f_enum << autogen_comment() << endl; 
- 
-  start_csharp_namespace(f_enum); 
- 
-  generate_csharp_doc(f_enum, tenum); 
- 
-  indent(f_enum) << "public enum " << tenum->get_name() << "\n"; 
-  scope_up(f_enum); 
- 
-  vector<t_enum_value*> constants = tenum->get_constants(); 
-  vector<t_enum_value*>::iterator c_iter; 
-  for (c_iter = constants.begin(); c_iter != constants.end(); ++c_iter) { 
-    generate_csharp_doc(f_enum, *c_iter); 
- 
-    int value = (*c_iter)->get_value(); 
-    indent(f_enum) << (*c_iter)->get_name() << " = " << value << "," << endl; 
-  } 
- 
-  scope_down(f_enum); 
- 
-  end_csharp_namespace(f_enum); 
- 
-  f_enum.close(); 
-} 
- 
-void t_csharp_generator::generate_consts(std::vector<t_const*> consts) { 
-  if (consts.empty()) { 
-    return; 
-  } 
-  string f_consts_name = namespace_dir_ + '/' + program_name_ + ".Constants.cs"; 
-  ofstream_with_content_based_conditional_update f_consts; 
-  f_consts.open(f_consts_name.c_str()); 
- 
-  f_consts << autogen_comment() << csharp_type_usings() << endl; 
- 
-  start_csharp_namespace(f_consts); 
- 
-  indent(f_consts) << "public static class " << make_valid_csharp_identifier(program_name_) 
-                   << "Constants" << endl; 
-  scope_up(f_consts); 
- 
-  vector<t_const*>::iterator c_iter; 
-  bool need_static_constructor = false; 
-  for (c_iter = consts.begin(); c_iter != consts.end(); ++c_iter) { 
-    generate_csharp_doc(f_consts, (*c_iter)); 
-    if (print_const_value(f_consts, 
-                          (*c_iter)->get_name(), 
-                          (*c_iter)->get_type(), 
-                          (*c_iter)->get_value(), 
-                          false)) { 
-      need_static_constructor = true; 
-    } 
-  } 
- 
-  if (need_static_constructor) { 
-    print_const_constructor(f_consts, consts); 
-  } 
- 
-  scope_down(f_consts); 
-  end_csharp_namespace(f_consts); 
-  f_consts.close(); 
-} 
- 
-void t_csharp_generator::print_const_def_value(std::ostream& out, 
-                                               string name, 
-                                               t_type* type, 
-                                               t_const_value* value) { 
-  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*, t_const_value::value_compare>& val = value->get_map(); 
-    map<t_const_value*, t_const_value*, t_const_value::value_compare>::const_iterator v_iter; 
-    prepare_member_name_mapping((t_struct*)type); 
-    for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) { 
-      t_field* field = NULL; 
-      for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { 
-        if ((*f_iter)->get_name() == v_iter->first->get_string()) { 
-          field = (*f_iter); 
-        } 
-      } 
-      if (field == NULL) { 
-        throw "type error: " + type->get_name() + " has no field " + v_iter->first->get_string(); 
-      } 
-      t_type* field_type = field->get_type(); 
-      string val = render_const_value(out, name, field_type, v_iter->second); 
-      indent(out) << name << "." << prop_name(field) << " = " << val << ";" << endl; 
-    } 
-    cleanup_member_name_mapping((t_struct*)type); 
-  } else if (type->is_map()) { 
-    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*, t_const_value::value_compare>& val = value->get_map(); 
-    map<t_const_value*, t_const_value*, t_const_value::value_compare>::const_iterator v_iter; 
-    for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) { 
-      string key = render_const_value(out, name, ktype, v_iter->first); 
-      string val = render_const_value(out, name, vtype, v_iter->second); 
-      indent(out) << name << "[" << key << "]" 
-                  << " = " << val << ";" << endl; 
-    } 
-  } else if (type->is_list() || type->is_set()) { 
-    t_type* etype; 
-    if (type->is_list()) { 
-      etype = ((t_list*)type)->get_elem_type(); 
-    } else { 
-      etype = ((t_set*)type)->get_elem_type(); 
-    } 
- 
-    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) { 
-      string val = render_const_value(out, name, etype, *v_iter); 
-      indent(out) << name << ".Add(" << val << ");" << endl; 
-    } 
-  } 
-} 
- 
-void t_csharp_generator::print_const_constructor(std::ostream& out, std::vector<t_const*> consts) { 
-  indent(out) << "static " << make_valid_csharp_identifier(program_name_).c_str() << "Constants()" 
-              << endl; 
-  scope_up(out); 
-  vector<t_const*>::iterator c_iter; 
-  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_const_value* value = (*c_iter)->get_value(); 
- 
-    print_const_def_value(out, name, type, value); 
-  } 
-  scope_down(out); 
-} 
- 
-// it seems like all that methods that call this are using in_static to be the opposite of what it 
-// would imply 
-bool t_csharp_generator::print_const_value(std::ostream& out, 
-                                           string name, 
-                                           t_type* type, 
-                                           t_const_value* value, 
-                                           bool in_static, 
-                                           bool defval, 
-                                           bool needtype) { 
-  indent(out); 
-  bool need_static_construction = !in_static; 
-  while (type->is_typedef()) { 
-    type = ((t_typedef*)type)->get_type(); 
-  } 
- 
-  if (!defval || needtype) { 
-    out << (in_static ? "" : type->is_base_type() ? "public const " : "public static ") 
-        << type_name(type) << " "; 
-  } 
-  if (type->is_base_type()) { 
-    string v2 = render_const_value(out, name, type, value); 
-    out << name << " = " << v2 << ";" << endl; 
-    need_static_construction = false; 
-  } else if (type->is_enum()) { 
-    out << name << " = " << type_name(type, false, true) << "." << value->get_identifier_name() 
-        << ";" << endl; 
-    need_static_construction = false; 
-  } else if (type->is_struct() || type->is_xception()) { 
-    out << name << " = new " << type_name(type) << "();" << endl; 
-  } else if (type->is_map()) { 
-    out << name << " = new " << type_name(type, true, true) << "();" << endl; 
-  } else if (type->is_list() || type->is_set()) { 
-    out << name << " = new " << type_name(type) << "();" << endl; 
-  } 
- 
-  if (defval && !type->is_base_type() && !type->is_enum()) { 
-    print_const_def_value(out, name, type, value); 
-  } 
- 
-  return need_static_construction; 
-} 
- 
-std::string t_csharp_generator::render_const_value(ostream& out, 
-                                                   string name, 
-                                                   t_type* type, 
-                                                   t_const_value* value) { 
-  (void)name; 
-  std::ostringstream render; 
- 
-  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: 
-      render << '"' << get_escaped_string(value) << '"'; 
-      break; 
-    case t_base_type::TYPE_BOOL: 
-      render << ((value->get_integer() > 0) ? "true" : "false"); 
-      break; 
-    case t_base_type::TYPE_I8: 
-    case t_base_type::TYPE_I16: 
-    case t_base_type::TYPE_I32: 
-    case t_base_type::TYPE_I64: 
-      render << value->get_integer(); 
-      break; 
-    case t_base_type::TYPE_DOUBLE: 
-      if (value->get_type() == t_const_value::CV_INTEGER) { 
-        render << value->get_integer(); 
-      } else { 
-        render << value->get_double(); 
-      } 
-      break; 
-    default: 
-      throw "compiler error: no const of base type " + t_base_type::t_base_name(tbase); 
-    } 
-  } else if (type->is_enum()) { 
-    render << type->get_name() << "." << value->get_identifier_name(); 
-  } else { 
-    string t = tmp("tmp"); 
-    print_const_value(out, t, type, value, true, true, true); 
-    render << t; 
-  } 
- 
-  return render.str(); 
-} 
- 
-void t_csharp_generator::generate_struct(t_struct* tstruct) { 
-  if (union_ && tstruct->is_union()) { 
-    generate_csharp_union(tstruct); 
-  } else { 
-    generate_csharp_struct(tstruct, false); 
-  } 
-} 
- 
-void t_csharp_generator::generate_xception(t_struct* txception) { 
-  generate_csharp_struct(txception, true); 
-} 
- 
-void t_csharp_generator::generate_csharp_struct(t_struct* tstruct, bool is_exception) { 
-  string f_struct_name = namespace_dir_ + "/" + (tstruct->get_name()) + ".cs"; 
-  ofstream_with_content_based_conditional_update f_struct; 
- 
-  f_struct.open(f_struct_name.c_str()); 
- 
-  f_struct << autogen_comment() << csharp_type_usings() << csharp_thrift_usings() << endl; 
- 
-  generate_csharp_struct_definition(f_struct, tstruct, is_exception); 
- 
-  f_struct.close(); 
-} 
- 
-void t_csharp_generator::generate_csharp_struct_definition(ostream& out, 
-                                                           t_struct* tstruct, 
-                                                           bool is_exception, 
-                                                           bool in_class, 
-                                                           bool is_result) { 
- 
-  if (!in_class) { 
-    start_csharp_namespace(out); 
-  } 
- 
-  out << endl; 
- 
-  generate_csharp_doc(out, tstruct); 
-  prepare_member_name_mapping(tstruct); 
- 
-  indent(out) << "#if !SILVERLIGHT" << endl; 
-  indent(out) << "[Serializable]" << endl; 
-  indent(out) << "#endif" << endl; 
-  if ((serialize_ || wcf_) && !is_exception) { 
-    indent(out) << "[DataContract(Namespace=\"" << wcf_namespace_ << "\")]" 
-                << endl; // do not make exception classes directly WCF serializable, we provide a 
-                         // separate "fault" for that 
-  } 
-  bool is_final = (tstruct->annotations_.find("final") != tstruct->annotations_.end()); 
- 
-  indent(out) << "public " << (is_final ? "sealed " : "") << "partial class " 
-              << normalize_name(tstruct->get_name()) << " : "; 
- 
-  if (is_exception) { 
-    out << "TException, "; 
-  } 
-  out << "TBase"; 
- 
-  out << endl; 
- 
-  scope_up(out); 
- 
-  const vector<t_field*>& members = tstruct->get_members(); 
-  vector<t_field*>::const_iterator m_iter; 
- 
-  // make private members with public Properties 
-  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { 
-    // if the field is requied, then we use auto-properties 
-    if (!field_is_required((*m_iter)) && (!nullable_ || field_has_default((*m_iter)))) { 
-      indent(out) << "private " << declare_field(*m_iter, false, "_") << endl; 
-    } 
-  } 
-  out << endl; 
- 
-  bool has_non_required_fields = false; 
-  bool has_non_required_default_value_fields = false; 
-  bool has_required_fields = false; 
-  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { 
-    generate_csharp_doc(out, *m_iter); 
-    generate_property(out, *m_iter, true, true); 
-    bool is_required = field_is_required((*m_iter)); 
-    bool has_default = field_has_default((*m_iter)); 
-    if (is_required) { 
-      has_required_fields = true; 
-    } else { 
-      if (has_default) { 
-        has_non_required_default_value_fields = true; 
-      } 
-      has_non_required_fields = true; 
-    } 
-  } 
- 
-  bool generate_isset = (nullable_ && has_non_required_default_value_fields) 
-                        || (!nullable_ && has_non_required_fields); 
-  if (generate_isset) { 
-    out << endl; 
-    if (serialize_ || wcf_) { 
-      out << indent() << "[XmlIgnore] // XmlSerializer" << endl << indent() 
-          << "[DataMember(Order = 1)]  // XmlObjectSerializer, DataContractJsonSerializer, etc." 
-          << endl; 
-    } 
-    out << indent() << "public Isset __isset;" << endl << indent() << "#if !SILVERLIGHT" << endl 
-        << indent() << "[Serializable]" << endl << indent() << "#endif" << endl; 
-    if (serialize_ || wcf_) { 
-      indent(out) << "[DataContract]" << endl; 
-    } 
-    indent(out) << "public struct Isset {" << endl; 
-    indent_up(); 
-    for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { 
-      bool is_required = field_is_required((*m_iter)); 
-      bool has_default = field_has_default((*m_iter)); 
-      // if it is required, don't need Isset for that variable 
-      // if it is not required, if it has a default value, we need to generate Isset 
-      // if we are not nullable, then we generate Isset 
-      if (!is_required && (!nullable_ || has_default)) { 
-        if (serialize_ || wcf_) { 
-          indent(out) << "[DataMember]" << endl; 
-        } 
-        indent(out) << "public bool " << normalize_name((*m_iter)->get_name()) << ";" << endl; 
-      } 
-    } 
- 
-    indent_down(); 
-    indent(out) << "}" << endl << endl; 
- 
-    if (generate_isset && (serialize_ || wcf_)) { 
-      indent(out) << "#region XmlSerializer support" << endl << endl; 
- 
-      for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { 
-        bool is_required = field_is_required((*m_iter)); 
-        bool has_default = field_has_default((*m_iter)); 
-        // if it is required, don't need Isset for that variable 
-        // if it is not required, if it has a default value, we need to generate Isset 
-        // if we are not nullable, then we generate Isset 
-        if (!is_required && (!nullable_ || has_default)) { 
-          indent(out) << "public bool ShouldSerialize" << prop_name((*m_iter)) << "()" << endl; 
-          indent(out) << "{" << endl; 
-          indent_up(); 
-          indent(out) << "return __isset." << normalize_name((*m_iter)->get_name()) << ";" << endl; 
-          indent_down(); 
-          indent(out) << "}" << endl << endl; 
-        } 
-      } 
- 
-      indent(out) << "#endregion XmlSerializer support" << endl << endl; 
-    } 
-  } 
- 
-  // We always want a default, no argument constructor for Reading 
-  indent(out) << "public " << normalize_name(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 ((*m_iter)->get_value() != NULL) { 
-      if (field_is_required((*m_iter))) { 
-        print_const_value(out, "this." + prop_name(*m_iter), t, (*m_iter)->get_value(), true, true); 
-      } else { 
-        print_const_value(out, 
-                          "this._" + (*m_iter)->get_name(), 
-                          t, 
-                          (*m_iter)->get_value(), 
-                          true, 
-                          true); 
-        // Optionals with defaults are marked set 
-        indent(out) << "this.__isset." << normalize_name((*m_iter)->get_name()) << " = true;" 
-                    << endl; 
-      } 
-    } 
-  } 
-  indent_down(); 
-  indent(out) << "}" << endl << endl; 
- 
-  if (has_required_fields) { 
-    indent(out) << "public " << tstruct->get_name() << "("; 
-    bool first = true; 
-    for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { 
-      if (field_is_required((*m_iter))) { 
-        if (first) { 
-          first = false; 
-        } else { 
-          out << ", "; 
-        } 
-        out << type_name((*m_iter)->get_type()) << " " << normalize_name((*m_iter)->get_name()); 
-      } 
-    } 
-    out << ") : this() {" << endl; 
-    indent_up(); 
- 
-    for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { 
-      if (field_is_required((*m_iter))) { 
-        indent(out) << "this." << prop_name((*m_iter)) << " = " << normalize_name((*m_iter)->get_name()) << ";" 
-                    << endl; 
-      } 
-    } 
- 
-    indent_down(); 
-    indent(out) << "}" << endl << endl; 
-  } 
- 
-  generate_csharp_struct_reader(out, tstruct); 
-  if (is_result) { 
-    generate_csharp_struct_result_writer(out, tstruct); 
-  } else { 
-    generate_csharp_struct_writer(out, tstruct); 
-  } 
-  if (hashcode_) { 
-    generate_csharp_struct_equals(out, tstruct); 
-    generate_csharp_struct_hashcode(out, tstruct); 
-  } 
-  generate_csharp_struct_tostring(out, tstruct); 
-  scope_down(out); 
-  out << endl; 
- 
-  // generate a corresponding WCF fault to wrap the exception 
-  if ((serialize_ || wcf_) && is_exception) { 
-    generate_csharp_wcffault(out, tstruct); 
-  } 
- 
-  cleanup_member_name_mapping(tstruct); 
-  if (!in_class) { 
-    end_csharp_namespace(out); 
-  } 
-} 
- 
-void t_csharp_generator::generate_csharp_wcffault(ostream& out, t_struct* tstruct) { 
-  out << endl; 
-  indent(out) << "#if !SILVERLIGHT" << endl; 
-  indent(out) << "[Serializable]" << endl; 
-  indent(out) << "#endif" << endl; 
-  indent(out) << "[DataContract]" << endl; 
-  bool is_final = (tstruct->annotations_.find("final") != tstruct->annotations_.end()); 
- 
-  indent(out) << "public " << (is_final ? "sealed " : "") << "partial class " << tstruct->get_name() 
-              << "Fault" << endl; 
- 
-  scope_up(out); 
- 
-  const vector<t_field*>& members = tstruct->get_members(); 
-  vector<t_field*>::const_iterator m_iter; 
- 
-  // make private members with public Properties 
-  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { 
-    indent(out) << "private " << declare_field(*m_iter, false, "_") << endl; 
-  } 
-  out << endl; 
- 
-  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { 
-    generate_property(out, *m_iter, true, false); 
-  } 
- 
-  scope_down(out); 
-  out << endl; 
-} 
- 
-void t_csharp_generator::generate_csharp_struct_reader(ostream& out, t_struct* tstruct) { 
-  indent(out) << "public void Read (TProtocol iprot)" << endl; 
-  scope_up(out); 
- 
-  out << indent() << "iprot.IncrementRecursionDepth();" << endl; 
-  out << indent() << "try" << endl; 
-  scope_up(out); 
- 
-  const vector<t_field*>& fields = tstruct->get_members(); 
-  vector<t_field*>::const_iterator f_iter; 
- 
-  // Required variables aren't in __isset, so we need tmp vars to check them 
-  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { 
-    if (field_is_required((*f_iter))) { 
-      indent(out) << "bool isset_" << (*f_iter)->get_name() << " = false;" << endl; 
-    } 
-  } 
- 
-  indent(out) << "TField field;" << endl << indent() << "iprot.ReadStructBegin();" << endl; 
- 
-  indent(out) << "while (true)" << endl; 
-  scope_up(out); 
- 
-  indent(out) << "field = iprot.ReadFieldBegin();" << endl; 
- 
-  indent(out) << "if (field.Type == TType.Stop) { " << endl; 
-  indent_up(); 
-  indent(out) << "break;" << endl; 
-  indent_down(); 
-  indent(out) << "}" << endl; 
- 
-  indent(out) << "switch (field.ID)" << endl; 
- 
-  scope_up(out); 
- 
-  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { 
-    bool is_required = field_is_required((*f_iter)); 
-    indent(out) << "case " << (*f_iter)->get_key() << ":" << endl; 
-    indent_up(); 
-    indent(out) << "if (field.Type == " << type_to_enum((*f_iter)->get_type()) << ") {" << endl; 
-    indent_up(); 
- 
-    generate_deserialize_field(out, *f_iter); 
-    if (is_required) { 
-      indent(out) << "isset_" << (*f_iter)->get_name() << " = true;" << endl; 
-    } 
- 
-    indent_down(); 
-    out << indent() << "} else { " << endl << indent() << "  TProtocolUtil.Skip(iprot, field.Type);" 
-        << endl << indent() << "}" << endl << indent() << "break;" << endl; 
-    indent_down(); 
-  } 
- 
-  indent(out) << "default: " << endl; 
-  indent_up(); 
-  indent(out) << "TProtocolUtil.Skip(iprot, field.Type);" << endl; 
-  indent(out) << "break;" << endl; 
-  indent_down(); 
- 
-  scope_down(out); 
- 
-  indent(out) << "iprot.ReadFieldEnd();" << endl; 
- 
-  scope_down(out); 
- 
-  indent(out) << "iprot.ReadStructEnd();" << endl; 
- 
-  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { 
-    if (field_is_required((*f_iter))) { 
-      indent(out) << "if (!isset_" << (*f_iter)->get_name() << ")" << endl; 
-      indent_up(); 
-      out << indent() 
-          << "throw new TProtocolException(TProtocolException.INVALID_DATA, " 
-          << "\"required field " << prop_name((*f_iter)) << " not set\");" 
-          << endl; 
-      indent_down(); 
-    } 
-  } 
- 
-  scope_down(out); 
-  out << indent() << "finally" << endl; 
-  scope_up(out); 
-  out << indent() << "iprot.DecrementRecursionDepth();" << endl; 
-  scope_down(out); 
- 
-  indent_down(); 
- 
-  indent(out) << "}" << endl << endl; 
-} 
- 
-void t_csharp_generator::generate_csharp_struct_writer(ostream& out, t_struct* tstruct) { 
-  out << indent() << "public void Write(TProtocol oprot) {" << endl; 
-  indent_up(); 
- 
-  out << indent() << "oprot.IncrementRecursionDepth();" << endl; 
-  out << indent() << "try" << endl; 
-  scope_up(out); 
- 
-  string name = tstruct->get_name(); 
-  const vector<t_field*>& fields = tstruct->get_sorted_members(); 
-  vector<t_field*>::const_iterator f_iter; 
- 
-  indent(out) << "TStruct struc = new TStruct(\"" << name << "\");" << endl; 
-  indent(out) << "oprot.WriteStructBegin(struc);" << endl; 
- 
-  if (fields.size() > 0) { 
-    indent(out) << "TField field = new TField();" << endl; 
-    for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { 
-      bool is_required = field_is_required((*f_iter)); 
-      bool has_default = field_has_default((*f_iter)); 
-      bool null_allowed = type_can_be_null((*f_iter)->get_type()); 
- 
-      if (is_required) 
-      { 
-        if (null_allowed) { 
-          indent(out) << "if (" << prop_name((*f_iter)) << " == null)" << endl; 
-          indent_up(); 
-          out << indent() 
-              << "throw new TProtocolException(TProtocolException.INVALID_DATA, " 
-              << "\"required field " << prop_name((*f_iter)) << " not set\");" 
-              << endl; 
-          indent_down(); 
-        } 
-      } 
-      else 
-      { 
-        if (nullable_ && !has_default) { 
-            indent(out) << "if (" << prop_name((*f_iter)) << " != null) {" << endl; 
-        } 
-        else if (null_allowed) { 
-          out << indent() 
-              << "if (" << prop_name((*f_iter)) << " != null && __isset." 
-              << normalize_name((*f_iter)->get_name()) << ") {" 
-              << endl; 
-        } 
-        else { 
-           indent(out) << "if (__isset." << normalize_name((*f_iter)->get_name()) << ") {" << endl; 
-        } 
-        indent_up(); 
-      } 
-      indent(out) << "field.Name = \"" << (*f_iter)->get_name() << "\";" << endl; 
-      indent(out) << "field.Type = " << type_to_enum((*f_iter)->get_type()) << ";" << endl; 
-      indent(out) << "field.ID = " << (*f_iter)->get_key() << ";" << endl; 
-      indent(out) << "oprot.WriteFieldBegin(field);" << endl; 
- 
-      generate_serialize_field(out, *f_iter); 
- 
-      indent(out) << "oprot.WriteFieldEnd();" << endl; 
-      if (!is_required) { 
-        indent_down(); 
-        indent(out) << "}" << endl; 
-      } 
-    } 
-  } 
- 
-  indent(out) << "oprot.WriteFieldStop();" << endl; 
-  indent(out) << "oprot.WriteStructEnd();" << endl; 
- 
-  scope_down(out); 
-  out << indent() << "finally" << endl; 
-  scope_up(out); 
-  out << indent() << "oprot.DecrementRecursionDepth();" << endl; 
-  scope_down(out); 
- 
-  indent_down(); 
- 
-  indent(out) << "}" << endl << endl; 
-} 
- 
-void t_csharp_generator::generate_csharp_struct_result_writer(ostream& out, t_struct* tstruct) { 
-  indent(out) << "public void Write(TProtocol oprot) {" << endl; 
-  indent_up(); 
- 
-  out << indent() << "oprot.IncrementRecursionDepth();" << endl; 
-  out << indent() << "try" << endl; 
-  scope_up(out); 
- 
-  string name = tstruct->get_name(); 
-  const vector<t_field*>& fields = tstruct->get_sorted_members(); 
-  vector<t_field*>::const_iterator f_iter; 
- 
-  indent(out) << "TStruct struc = new TStruct(\"" << name << "\");" << endl; 
-  indent(out) << "oprot.WriteStructBegin(struc);" << endl; 
- 
-  if (fields.size() > 0) { 
-    indent(out) << "TField field = new TField();" << endl; 
-    bool first = true; 
-    for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { 
-      if (first) { 
-        first = false; 
-        out << endl << indent() << "if "; 
-      } else { 
-        out << " else if "; 
-      } 
- 
-      if (nullable_) { 
-        out << "(this." << prop_name((*f_iter)) << " != null) {" << endl; 
-      } else { 
-        out << "(this.__isset." << normalize_name((*f_iter)->get_name()) << ") {" << endl; 
-      } 
-      indent_up(); 
- 
-      bool null_allowed = !nullable_ && type_can_be_null((*f_iter)->get_type()); 
-      if (null_allowed) { 
-        indent(out) << "if (" << prop_name(*f_iter) << " != null) {" << endl; 
-        indent_up(); 
-      } 
- 
-      indent(out) << "field.Name = \"" << prop_name(*f_iter) << "\";" << endl; 
-      indent(out) << "field.Type = " << type_to_enum((*f_iter)->get_type()) << ";" << endl; 
-      indent(out) << "field.ID = " << (*f_iter)->get_key() << ";" << endl; 
-      indent(out) << "oprot.WriteFieldBegin(field);" << endl; 
- 
-      generate_serialize_field(out, *f_iter); 
- 
-      indent(out) << "oprot.WriteFieldEnd();" << endl; 
- 
-      if (null_allowed) { 
-        indent_down(); 
-        indent(out) << "}" << endl; 
-      } 
- 
-      indent_down(); 
-      indent(out) << "}"; 
-    } 
-  } 
- 
-  out << endl << indent() << "oprot.WriteFieldStop();" << endl << indent() 
-      << "oprot.WriteStructEnd();" << endl; 
- 
-  scope_down(out); 
-  out << indent() << "finally" << endl; 
-  scope_up(out); 
-  out << indent() << "oprot.DecrementRecursionDepth();" << endl; 
-  scope_down(out); 
- 
-  indent_down(); 
- 
-  indent(out) << "}" << endl << endl; 
-} 
- 
-void t_csharp_generator::generate_csharp_struct_tostring(ostream& out, t_struct* tstruct) { 
-  indent(out) << "public override string ToString() {" << endl; 
-  indent_up(); 
- 
-  indent(out) << "StringBuilder __sb = new StringBuilder(\"" << tstruct->get_name() << "(\");" 
-              << endl; 
- 
-  const vector<t_field*>& fields = tstruct->get_members(); 
-  vector<t_field*>::const_iterator f_iter; 
- 
-  bool useFirstFlag = false; 
-  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { 
-    if (!field_is_required((*f_iter))) { 
-      indent(out) << "bool __first = true;" << endl; 
-      useFirstFlag = true; 
-    } 
-    break; 
-  } 
- 
-  bool had_required = false; // set to true after first required field has been processed 
- 
-  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { 
-    bool is_required = field_is_required((*f_iter)); 
-    bool has_default = field_has_default((*f_iter)); 
-    if (nullable_ && !has_default && !is_required) { 
-      indent(out) << "if (" << prop_name((*f_iter)) << " != null) {" << endl; 
-      indent_up(); 
-    } else if (!is_required) { 
-      bool null_allowed = type_can_be_null((*f_iter)->get_type()); 
-      if (null_allowed) { 
-        indent(out) << "if (" << prop_name((*f_iter)) << " != null && __isset." 
-                    << normalize_name((*f_iter)->get_name()) << ") {" << endl; 
-        indent_up(); 
-      } else { 
-        indent(out) << "if (__isset." << normalize_name((*f_iter)->get_name()) << ") {" << endl; 
-        indent_up(); 
-      } 
-    } 
- 
-    if (useFirstFlag && (!had_required)) { 
-      indent(out) << "if(!__first) { __sb.Append(\", \"); }" << endl; 
-      if (!is_required) { 
-        indent(out) << "__first = false;" << endl; 
-      } 
-      indent(out) << "__sb.Append(\"" << prop_name((*f_iter)) << ": \");" << endl; 
-    } else { 
-      indent(out) << "__sb.Append(\", " << prop_name((*f_iter)) << ": \");" << endl; 
-    } 
- 
-    t_type* ttype = (*f_iter)->get_type(); 
-    if (ttype->is_xception() || ttype->is_struct()) { 
-      indent(out) << "__sb.Append(" << prop_name((*f_iter)) 
-                  << "== null ? \"<null>\" : " << prop_name((*f_iter)) << ".ToString());" << endl; 
-    } else { 
-      indent(out) << "__sb.Append(" << prop_name((*f_iter)) << ");" << endl; 
-    } 
- 
-    if (!is_required) { 
-      indent_down(); 
-      indent(out) << "}" << endl; 
-    } else { 
-      had_required = true; // now __first must be false, so we don't need to check it anymore 
-    } 
-  } 
- 
-  indent(out) << "__sb.Append(\")\");" << endl; 
-  indent(out) << "return __sb.ToString();" << endl; 
- 
-  indent_down(); 
-  indent(out) << "}" << endl << endl; 
-} 
- 
-void t_csharp_generator::generate_csharp_union(t_struct* tunion) { 
-  string f_union_name = namespace_dir_ + "/" + (tunion->get_name()) + ".cs"; 
-  ofstream_with_content_based_conditional_update f_union; 
- 
-  f_union.open(f_union_name.c_str()); 
- 
-  f_union << autogen_comment() << csharp_type_usings() << csharp_thrift_usings() << endl; 
- 
-  generate_csharp_union_definition(f_union, tunion); 
- 
-  f_union.close(); 
-} 
- 
-void t_csharp_generator::generate_csharp_union_definition(std::ostream& out, t_struct* tunion) { 
-  // Let's define the class first 
-  start_csharp_namespace(out); 
- 
-  indent(out) << "public abstract partial class " << tunion->get_name() << " : TAbstractBase {" 
-              << endl; 
- 
-  indent_up(); 
- 
-  indent(out) << "public abstract void Write(TProtocol protocol);" << endl; 
-  indent(out) << "public readonly bool Isset;" << endl; 
-  indent(out) << "public abstract object Data { get; }" << endl; 
- 
-  indent(out) << "protected " << tunion->get_name() << "(bool isset) {" << endl; 
-  indent_up(); 
-  indent(out) << "Isset = isset;" << endl; 
-  indent_down(); 
-  indent(out) << "}" << endl << endl; 
- 
-  indent(out) << "public class ___undefined : " << tunion->get_name() << " {" << endl; 
-  indent_up(); 
- 
-  indent(out) << "public override object Data { get { return null; } }" << endl; 
- 
-  indent(out) << "public ___undefined() : base(false) {}" << endl << endl; 
- 
-  indent(out) << "public override void Write(TProtocol protocol) {" << endl; 
-  indent_up(); 
-  indent(out) << "throw new TProtocolException( TProtocolException.INVALID_DATA, \"Cannot persist " 
-                 "an union type which is not set.\");" << endl; 
-  indent_down(); 
-  indent(out) << "}" << endl << endl; 
- 
-  indent_down(); 
-  indent(out) << "}" << endl << endl; 
- 
-  const vector<t_field*>& fields = tunion->get_members(); 
-  vector<t_field*>::const_iterator f_iter; 
- 
-  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { 
-    generate_csharp_union_class(out, tunion, (*f_iter)); 
-  } 
- 
-  generate_csharp_union_reader(out, tunion); 
- 
-  indent_down(); 
-  indent(out) << "}" << endl << endl; 
- 
-  end_csharp_namespace(out); 
-} 
- 
-void t_csharp_generator::generate_csharp_union_class(std::ostream& out, 
-                                                     t_struct* tunion, 
-                                                     t_field* tfield) { 
-  indent(out) << "public class " << tfield->get_name() << " : " << tunion->get_name() << " {" 
-              << endl; 
-  indent_up(); 
-  indent(out) << "private " << type_name(tfield->get_type()) << " _data;" << endl; 
-  indent(out) << "public override object Data { get { return _data; } }" << endl; 
-  indent(out) << "public " << tfield->get_name() << "(" << type_name(tfield->get_type()) 
-              << " data) : base(true) {" << endl; 
-  indent_up(); 
-  indent(out) << "this._data = data;" << endl; 
-  indent_down(); 
-  indent(out) << "}" << endl; 
-  indent(out) << "public override void Write(TProtocol oprot) {" << endl; 
-  indent_up(); 
- 
-  out << indent() << "oprot.IncrementRecursionDepth();" << endl; 
-  out << indent() << "try" << endl; 
-  scope_up(out); 
- 
-  indent(out) << "TStruct struc = new TStruct(\"" << tunion->get_name() << "\");" << endl; 
-  indent(out) << "oprot.WriteStructBegin(struc);" << endl; 
- 
-  indent(out) << "TField field = new TField();" << endl; 
-  indent(out) << "field.Name = \"" << tfield->get_name() << "\";" << endl; 
-  indent(out) << "field.Type = " << type_to_enum(tfield->get_type()) << ";" << endl; 
-  indent(out) << "field.ID = " << tfield->get_key() << ";" << endl; 
-  indent(out) << "oprot.WriteFieldBegin(field);" << endl; 
- 
-  generate_serialize_field(out, tfield, "_data", true, true); 
- 
-  indent(out) << "oprot.WriteFieldEnd();" << endl; 
-  indent(out) << "oprot.WriteFieldStop();" << endl; 
-  indent(out) << "oprot.WriteStructEnd();" << endl; 
-  indent_down(); 
- 
-  scope_down(out); 
-  out << indent() << "finally" << endl; 
-  scope_up(out); 
-  out << indent() << "oprot.DecrementRecursionDepth();" << endl; 
-  scope_down(out); 
- 
-  indent(out) << "}" << endl; 
- 
-  indent_down(); 
-  indent(out) << "}" << endl << endl; 
-} 
- 
-void t_csharp_generator::generate_csharp_struct_equals(ostream& out, t_struct* tstruct) { 
-  indent(out) << "public override bool Equals(object that) {" << endl; 
-  indent_up(); 
- 
-  indent(out) << "var other = that as " << type_name(tstruct) << ";" << endl; 
-  indent(out) << "if (other == null) return false;" << endl; 
-  indent(out) << "if (ReferenceEquals(this, other)) return true;" << endl; 
- 
-  const vector<t_field*>& fields = tstruct->get_members(); 
-  vector<t_field*>::const_iterator f_iter; 
- 
-  bool first = true; 
- 
-  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { 
-    if (first) { 
-      first = false; 
-      indent(out) << "return "; 
-      indent_up(); 
-    } else { 
-      out << endl; 
-      indent(out) << "&& "; 
-    } 
-    if (!field_is_required((*f_iter)) && !(nullable_ && !field_has_default((*f_iter)))) { 
-      out << "((__isset." << normalize_name((*f_iter)->get_name()) << " == other.__isset." 
-          << normalize_name((*f_iter)->get_name()) << ") && ((!__isset." 
-          << normalize_name((*f_iter)->get_name()) << ") || ("; 
-    } 
-    t_type* ttype = (*f_iter)->get_type(); 
-    if (ttype->is_container() || ttype->is_binary()) { 
-      out << "TCollections.Equals("; 
-    } else { 
-      out << "System.Object.Equals("; 
-    } 
-    out << prop_name((*f_iter)) << ", other." << prop_name((*f_iter)) << ")"; 
-    if (!field_is_required((*f_iter)) && !(nullable_ && !field_has_default((*f_iter)))) { 
-      out << ")))"; 
-    } 
-  } 
-  if (first) { 
-    indent(out) << "return true;" << endl; 
-  } else { 
-    out << ";" << endl; 
-    indent_down(); 
-  } 
- 
-  indent_down(); 
-  indent(out) << "}" << endl << endl; 
-} 
- 
-void t_csharp_generator::generate_csharp_struct_hashcode(ostream& out, t_struct* tstruct) { 
-  indent(out) << "public override int GetHashCode() {" << endl; 
-  indent_up(); 
- 
-  indent(out) << "int hashcode = 0;" << endl; 
-  indent(out) << "unchecked {" << endl; 
-  indent_up(); 
- 
-  const vector<t_field*>& fields = tstruct->get_members(); 
-  vector<t_field*>::const_iterator f_iter; 
- 
-  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { 
-    t_type* ttype = (*f_iter)->get_type(); 
-    indent(out) << "hashcode = (hashcode * 397) ^ "; 
-    if (field_is_required((*f_iter))) { 
-      out << "("; 
-    } else if (nullable_) { 
-      out << "(" << prop_name((*f_iter)) << " == null ? 0 : "; 
-    } else { 
-      out << "(!__isset." << normalize_name((*f_iter)->get_name()) << " ? 0 : "; 
-    } 
-    if (ttype->is_container()) { 
-      out << "(TCollections.GetHashCode(" << prop_name((*f_iter)) << "))"; 
-    } else { 
-      out << "(" << prop_name((*f_iter)) << ".GetHashCode())"; 
-    } 
-    out << ");" << endl; 
-  } 
- 
-  indent_down(); 
-  indent(out) << "}" << endl; 
-  indent(out) << "return hashcode;" << endl; 
- 
-  indent_down(); 
-  indent(out) << "}" << endl << endl; 
-} 
- 
-void t_csharp_generator::generate_service(t_service* tservice) { 
-  string f_service_name = namespace_dir_ + "/" + service_name_ + ".cs"; 
-  f_service_.open(f_service_name.c_str()); 
- 
-  f_service_ << autogen_comment() << csharp_type_usings() << csharp_thrift_usings() << endl; 
- 
-  start_csharp_namespace(f_service_); 
- 
-  indent(f_service_) << "public partial class " << normalize_name(service_name_) << " {" << endl; 
-  indent_up(); 
- 
-  generate_service_interface(tservice); 
-  generate_service_client(tservice); 
-  generate_service_server(tservice); 
-  generate_service_helpers(tservice); 
- 
-  indent_down(); 
- 
-  indent(f_service_) << "}" << endl; 
-  end_csharp_namespace(f_service_); 
-  f_service_.close(); 
-} 
- 
-void t_csharp_generator::generate_service_interface(t_service* tservice) { 
-  generate_separate_service_interfaces(tservice); 
-} 
- 
-void t_csharp_generator::generate_separate_service_interfaces(t_service* tservice) { 
-  generate_sync_service_interface(tservice); 
- 
-  if (async_) { 
-    generate_async_service_interface(tservice); 
-  } 
- 
-  generate_combined_service_interface(tservice); 
-} 
- 
-void t_csharp_generator::generate_sync_service_interface(t_service* tservice) { 
-  string extends = ""; 
-  string extends_iface = ""; 
-  if (tservice->get_extends() != NULL) { 
-    extends = type_name(tservice->get_extends()); 
-    extends_iface = " : " + extends + ".ISync"; 
-  } 
- 
-  generate_csharp_doc(f_service_, tservice); 
- 
-  if (wcf_) { 
-    indent(f_service_) << "[ServiceContract(Namespace=\"" << wcf_namespace_ << "\")]" << endl; 
-  } 
-  indent(f_service_) << "public interface ISync" << extends_iface << " {" << endl; 
- 
-  indent_up(); 
-  vector<t_function*> functions = tservice->get_functions(); 
-  vector<t_function*>::iterator f_iter; 
-  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) { 
-    generate_csharp_doc(f_service_, *f_iter); 
- 
-    // if we're using WCF, add the corresponding attributes 
-    if (wcf_) { 
-      indent(f_service_) << "[OperationContract]" << endl; 
- 
-      const std::vector<t_field*>& xceptions = (*f_iter)->get_xceptions()->get_members(); 
-      vector<t_field*>::const_iterator x_iter; 
-      for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) { 
-        indent(f_service_) << "[FaultContract(typeof(" 
-          + type_name((*x_iter)->get_type(), false, false) + "Fault))]" << endl; 
-      } 
-    } 
- 
-    indent(f_service_) << function_signature(*f_iter) << ";" << endl; 
-  } 
-  indent_down(); 
-  f_service_ << indent() << "}" << endl << endl; 
-} 
- 
-void t_csharp_generator::generate_async_service_interface(t_service* tservice) { 
-  string extends = ""; 
-  string extends_iface = ""; 
-  if (tservice->get_extends() != NULL) { 
-    extends = type_name(tservice->get_extends()); 
-    extends_iface = " : " + extends + ".IAsync"; 
-  } 
- 
-  generate_csharp_doc(f_service_, tservice); 
- 
-  if (wcf_) { 
-    indent(f_service_) << "[ServiceContract(Namespace=\"" << wcf_namespace_ << "\")]" << endl; 
-  } 
-  indent(f_service_) << "public interface IAsync" << extends_iface << " {" << endl; 
- 
-  indent_up(); 
-  vector<t_function*> functions = tservice->get_functions(); 
-  vector<t_function*>::iterator f_iter; 
-  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) { 
-    generate_csharp_doc(f_service_, *f_iter); 
- 
-    // if we're using WCF, add the corresponding attributes 
-    if (wcf_) { 
-      indent(f_service_) << "[OperationContract]" << endl; 
- 
-      const std::vector<t_field*>& xceptions = (*f_iter)->get_xceptions()->get_members(); 
-      vector<t_field*>::const_iterator x_iter; 
-      for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) { 
-        indent(f_service_) << "[FaultContract(typeof(" 
-          + type_name((*x_iter)->get_type(), false, false) + "Fault))]" << endl; 
-      } 
-    } 
- 
-    indent(f_service_) << function_signature_async(*f_iter) << ";" << endl; 
-  } 
-  indent_down(); 
-  f_service_ << indent() << "}" << endl << endl; 
-} 
- 
-void t_csharp_generator::generate_combined_service_interface(t_service* tservice) { 
-  string extends_iface = " : ISync"; 
- 
-  if (async_) { 
-    extends_iface += ", IAsync"; 
-  } 
- 
-  generate_csharp_doc(f_service_, tservice); 
- 
-  if (wcf_) { 
-    indent(f_service_) << "[ServiceContract(Namespace=\"" << wcf_namespace_ << "\")]" << endl; 
-  } 
- 
-  indent(f_service_) << "public interface Iface" << extends_iface << " {" << endl; 
- 
-  indent_up(); 
- 
-  // We need to generate extra old style async methods for silverlight. Since 
-  // this isn't something you'd want to implement server-side, just put them into 
-  // the main Iface interface. 
-  generate_silverlight_async_methods(tservice); 
- 
-  indent_down(); 
- 
-  f_service_ << indent() << "}" << endl << endl; 
-} 
- 
-void t_csharp_generator::generate_silverlight_async_methods(t_service* tservice) { 
-  vector<t_function*> functions = tservice->get_functions(); 
-  vector<t_function*>::iterator f_iter; 
-  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) { 
-    generate_csharp_doc(f_service_, *f_iter); 
- 
-    // For backwards compatibility, include the Begin_, End_ methods if we're generating 
-    // with the async flag. I'm not sure this is necessary, so someone with more knowledge 
-    // can maybe remove these checks if they know it's safe. 
-    if (!async_) { 
-      indent(f_service_) << "#if SILVERLIGHT" << endl; 
-    } 
- 
-    indent(f_service_) << function_signature_async_begin(*f_iter, "Begin_") << ";" << endl; 
-    indent(f_service_) << function_signature_async_end(*f_iter, "End_") << ";" << endl; 
- 
-    if (!async_) { 
-      indent(f_service_) << "#endif" << endl; 
-    } 
-  } 
-} 
- 
-void t_csharp_generator::generate_service_helpers(t_service* tservice) { 
-  vector<t_function*> functions = tservice->get_functions(); 
-  vector<t_function*>::iterator f_iter; 
- 
-  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) { 
-    t_struct* ts = (*f_iter)->get_arglist(); 
-    generate_csharp_struct_definition(f_service_, ts, false, true); 
-    generate_function_helpers(*f_iter); 
-  } 
-} 
- 
-void t_csharp_generator::generate_service_client(t_service* tservice) { 
-  string extends = ""; 
-  string extends_client = ""; 
-  if (tservice->get_extends() != NULL) { 
-    extends = type_name(tservice->get_extends()); 
-    extends_client = extends + ".Client, "; 
-  } else { 
-    extends_client = "IDisposable, "; 
-  } 
- 
-  generate_csharp_doc(f_service_, tservice); 
- 
-  indent(f_service_) << "public class Client : " << extends_client << "Iface {" << endl; 
-  indent_up(); 
-  indent(f_service_) << "public Client(TProtocol prot) : this(prot, prot)" << endl; 
-  scope_up(f_service_); 
-  scope_down(f_service_); 
-  f_service_ << endl; 
- 
-  indent(f_service_) << "public Client(TProtocol iprot, TProtocol oprot)"; 
-  if (!extends.empty()) { 
-    f_service_ << " : base(iprot, oprot)"; 
-  } 
-  f_service_ << endl; 
- 
-  scope_up(f_service_); 
-  if (extends.empty()) { 
-    f_service_ << indent() << "iprot_ = iprot;" << endl << indent() << "oprot_ = oprot;" << endl; 
-  } 
-  scope_down(f_service_); 
- 
-  f_service_ << endl; 
- 
-  if (extends.empty()) { 
-    f_service_ << indent() << "protected TProtocol iprot_;" << endl << indent() 
-               << "protected TProtocol oprot_;" << endl << indent() << "protected int seqid_;" 
-               << endl << endl; 
- 
-    f_service_ << indent() << "public TProtocol InputProtocol" << endl; 
-    scope_up(f_service_); 
-    indent(f_service_) << "get { return iprot_; }" << endl; 
-    scope_down(f_service_); 
- 
-    f_service_ << indent() << "public TProtocol OutputProtocol" << endl; 
-    scope_up(f_service_); 
-    indent(f_service_) << "get { return oprot_; }" << endl; 
-    scope_down(f_service_); 
-    f_service_ << endl << endl; 
- 
-    indent(f_service_) << "#region \" IDisposable Support \"" << endl; 
-    indent(f_service_) << "private bool _IsDisposed;" << endl << endl; 
-    indent(f_service_) << "// IDisposable" << endl; 
-    indent(f_service_) << "public void Dispose()" << endl; 
-    scope_up(f_service_); 
-    indent(f_service_) << "Dispose(true);" << endl; 
-    scope_down(f_service_); 
-    indent(f_service_) << endl << endl; 
-    indent(f_service_) << "protected virtual void Dispose(bool disposing)" << endl; 
-    scope_up(f_service_); 
-    indent(f_service_) << "if (!_IsDisposed)" << endl; 
-    scope_up(f_service_); 
-    indent(f_service_) << "if (disposing)" << endl; 
-    scope_up(f_service_); 
-    indent(f_service_) << "if (iprot_ != null)" << endl; 
-    scope_up(f_service_); 
-    indent(f_service_) << "((IDisposable)iprot_).Dispose();" << endl; 
-    scope_down(f_service_); 
-    indent(f_service_) << "if (oprot_ != null)" << endl; 
-    scope_up(f_service_); 
-    indent(f_service_) << "((IDisposable)oprot_).Dispose();" << endl; 
-    scope_down(f_service_); 
-    scope_down(f_service_); 
-    scope_down(f_service_); 
-    indent(f_service_) << "_IsDisposed = true;" << endl; 
-    scope_down(f_service_); 
-    indent(f_service_) << "#endregion" << endl; 
-    f_service_ << endl << endl; 
-  } 
- 
-  vector<t_function*> functions = tservice->get_functions(); 
-  vector<t_function*>::const_iterator f_iter; 
-  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) { 
-    string funname = (*f_iter)->get_name(); 
- 
-    indent(f_service_) << endl; 
- 
-    if (!async_) { 
-      indent(f_service_) << "#if SILVERLIGHT" << endl; 
-    } 
-    // Begin_ 
-    indent(f_service_) << "public " << function_signature_async_begin(*f_iter, "Begin_") << endl; 
-    scope_up(f_service_); 
-    indent(f_service_) << "return " 
-                       << "send_" << funname << "(callback, state"; 
- 
-    t_struct* arg_struct = (*f_iter)->get_arglist(); 
-    prepare_member_name_mapping(arg_struct); 
- 
-    const vector<t_field*>& fields = arg_struct->get_members(); 
-    vector<t_field*>::const_iterator fld_iter; 
-    for (fld_iter = fields.begin(); fld_iter != fields.end(); ++fld_iter) { 
-      f_service_ << ", "; 
-      f_service_ << normalize_name((*fld_iter)->get_name()); 
-    } 
-    f_service_ << ");" << endl; 
-    scope_down(f_service_); 
-    f_service_ << endl; 
- 
-    // End 
-    indent(f_service_) << "public " << function_signature_async_end(*f_iter, "End_") << endl; 
-    scope_up(f_service_); 
-    indent(f_service_) << "oprot_.Transport.EndFlush(asyncResult);" << endl; 
-    if (!(*f_iter)->is_oneway()) { 
-      f_service_ << indent(); 
-      if (!(*f_iter)->get_returntype()->is_void()) { 
-        f_service_ << "return "; 
-      } 
-      f_service_ << "recv_" << funname << "();" << endl; 
-    } 
-    scope_down(f_service_); 
-    f_service_ << endl; 
- 
-    // async 
-    bool first; 
-    if (async_) { 
-      indent(f_service_) << "public async " << function_signature_async(*f_iter, "") << endl; 
-      scope_up(f_service_); 
- 
-      if (!(*f_iter)->get_returntype()->is_void()) { 
-        indent(f_service_) << type_name((*f_iter)->get_returntype()) << " retval;" << endl; 
-        indent(f_service_) << "retval = "; 
-      } else { 
-        indent(f_service_); 
-      } 
-      f_service_ << "await Task.Run(() =>" << endl; 
-      scope_up(f_service_); 
-      indent(f_service_); 
-      if (!(*f_iter)->get_returntype()->is_void()) { 
-        f_service_ << "return "; 
-      } 
-      f_service_ << funname << "("; 
-      first = true; 
-      for (fld_iter = fields.begin(); fld_iter != fields.end(); ++fld_iter) { 
-        if (first) { 
-          first = false; 
-        } else { 
-          f_service_ << ", "; 
-        } 
-        f_service_ << (*fld_iter)->get_name(); 
-      } 
-      f_service_ << ");" << endl; 
-      indent_down(); 
-      indent(f_service_) << "});" << endl; 
-      if (!(*f_iter)->get_returntype()->is_void()) { 
-        indent(f_service_) << "return retval;" << endl; 
-      } 
-      scope_down(f_service_); 
-      f_service_ << endl; 
-    } 
- 
-    if (!async_) { 
-      indent(f_service_) << "#endif" << endl << endl; 
-    } 
- 
-    // "Normal" Synchronous invoke 
-    generate_csharp_doc(f_service_, *f_iter); 
-    indent(f_service_) << "public " << function_signature(*f_iter) << endl; 
-    scope_up(f_service_); 
- 
-    if (!async_) { 
-      indent(f_service_) << "#if !SILVERLIGHT" << endl; 
-      indent(f_service_) << "send_" << funname << "("; 
- 
-      first = true; 
-      for (fld_iter = fields.begin(); fld_iter != fields.end(); ++fld_iter) { 
-        if (first) { 
-          first = false; 
-        } else { 
-          f_service_ << ", "; 
-        } 
-        f_service_ << normalize_name((*fld_iter)->get_name()); 
-      } 
-      f_service_ << ");" << endl; 
- 
-      if (!(*f_iter)->is_oneway()) { 
-        f_service_ << indent(); 
-        if (!(*f_iter)->get_returntype()->is_void()) { 
-          f_service_ << "return "; 
-        } 
-        f_service_ << "recv_" << funname << "();" << endl; 
-      } 
-      f_service_ << endl; 
- 
-      indent(f_service_) << "#else" << endl; 
-    } 
- 
-    // Silverlight synchronous invoke 
-    indent(f_service_) << "var asyncResult = Begin_" << funname << "(null, null"; 
-    for (fld_iter = fields.begin(); fld_iter != fields.end(); ++fld_iter) { 
-      f_service_ << ", " << normalize_name((*fld_iter)->get_name()); 
-    } 
-    f_service_ << ");" << endl; 
- 
-    if (!(*f_iter)->is_oneway()) { 
-      f_service_ << indent(); 
-      if (!(*f_iter)->get_returntype()->is_void()) { 
-        f_service_ << "return "; 
-      } 
-      f_service_ << "End_" << funname << "(asyncResult);" << endl; 
-    } 
-    f_service_ << endl; 
- 
-    if (!async_) { 
-      indent(f_service_) << "#endif" << endl; 
-    } 
-    scope_down(f_service_); 
- 
-    // Send 
-    t_function send_function(g_type_void, 
-                             string("send_") + (*f_iter)->get_name(), 
-                             (*f_iter)->get_arglist()); 
- 
-    string argsname = (*f_iter)->get_name() + "_args"; 
- 
-    if (!async_) { 
-      indent(f_service_) << "#if SILVERLIGHT" << endl; 
-    } 
-    indent(f_service_) << "public " << function_signature_async_begin(&send_function) << endl; 
-    if (!async_) { 
-      indent(f_service_) << "#else" << endl; 
-      indent(f_service_) << "public " << function_signature(&send_function) << endl; 
-      indent(f_service_) << "#endif" << endl; 
-    } 
-    scope_up(f_service_); 
- 
-    f_service_ << indent() << "oprot_.WriteMessageBegin(new TMessage(\"" << funname << "\", " 
-               << ((*f_iter)->is_oneway() ? "TMessageType.Oneway" : "TMessageType.Call") 
-               << ", seqid_));" << endl << indent() << argsname << " args = new " << argsname 
-               << "();" << endl; 
- 
-    for (fld_iter = fields.begin(); fld_iter != fields.end(); ++fld_iter) { 
-      f_service_ << indent() << "args." << prop_name(*fld_iter) << " = " 
-                 << normalize_name((*fld_iter)->get_name()) << ";" << endl; 
-    } 
- 
-    f_service_ << indent() << "args.Write(oprot_);" << endl << indent() 
-               << "oprot_.WriteMessageEnd();" << endl; 
-    ; 
- 
-    if (!async_) { 
-      indent(f_service_) << "#if SILVERLIGHT" << endl; 
-    } 
-    indent(f_service_) << "return oprot_.Transport.BeginFlush(callback, state);" << endl; 
-    if (!async_) { 
-      indent(f_service_) << "#else" << endl; 
-      indent(f_service_) << "oprot_.Transport.Flush();" << endl; 
-      indent(f_service_) << "#endif" << endl; 
-    } 
- 
-    cleanup_member_name_mapping(arg_struct); 
-    scope_down(f_service_); 
-    f_service_ << endl; 
- 
-    if (!(*f_iter)->is_oneway()) { 
-      string resultname = (*f_iter)->get_name() + "_result"; 
- 
-      t_struct noargs(program_); 
-      t_function recv_function((*f_iter)->get_returntype(), 
-                               string("recv_") + (*f_iter)->get_name(), 
-                               &noargs, 
-                               (*f_iter)->get_xceptions()); 
-      indent(f_service_) << "public " << function_signature(&recv_function) << endl; 
-      scope_up(f_service_); 
- 
-      t_struct* xs = (*f_iter)->get_xceptions(); 
-      prepare_member_name_mapping(xs, xs->get_members(), resultname); 
- 
-      f_service_ << indent() << "TMessage msg = iprot_.ReadMessageBegin();" << endl << indent() 
-                 << "if (msg.Type == TMessageType.Exception) {" << endl; 
-      indent_up(); 
-      f_service_ << indent() << "TApplicationException x = TApplicationException.Read(iprot_);" 
-                 << endl << indent() << "iprot_.ReadMessageEnd();" << endl << indent() << "throw x;" 
-                 << endl; 
-      indent_down(); 
-      f_service_ << indent() << "}" << endl << indent() << resultname << " result = new " 
-                 << resultname << "();" << endl << indent() << "result.Read(iprot_);" << endl 
-                 << indent() << "iprot_.ReadMessageEnd();" << endl; 
- 
-      if (!(*f_iter)->get_returntype()->is_void()) { 
-        if (nullable_) { 
-          if (type_can_be_null((*f_iter)->get_returntype())) { 
-            f_service_ << indent() << "if (result.Success != null) {" << endl << indent() 
-                       << "  return result.Success;" << endl << indent() << "}" << endl; 
-          } else { 
-            f_service_ << indent() << "if (result.Success.HasValue) {" << endl << indent() 
-                       << "  return result.Success.Value;" << endl << indent() << "}" << endl; 
-          } 
-        } else { 
-          f_service_ << indent() << "if (result.__isset.success) {" << endl << indent() 
-                     << "  return result.Success;" << endl << indent() << "}" << endl; 
-        } 
-      } 
- 
-      const std::vector<t_field*>& xceptions = xs->get_members(); 
-      vector<t_field*>::const_iterator x_iter; 
-      for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) { 
-        if (nullable_) { 
-          f_service_ << indent() << "if (result." << prop_name(*x_iter) << " != null) {" << endl 
-                     << indent() << "  throw result." << prop_name(*x_iter) << ";" << endl 
-                     << indent() << "}" << endl; 
-        } else { 
-          f_service_ << indent() << "if (result.__isset." << normalize_name((*x_iter)->get_name()) 
-                     << ") {" << endl << indent() << "  throw result." << prop_name(*x_iter) << ";" 
-                     << endl << indent() << "}" << endl; 
-        } 
-      } 
- 
-      if ((*f_iter)->get_returntype()->is_void()) { 
-        indent(f_service_) << "return;" << endl; 
-      } else { 
-        f_service_ << indent() 
-                   << "throw new " 
-                      "TApplicationException(TApplicationException.ExceptionType.MissingResult, \"" 
-                   << (*f_iter)->get_name() << " failed: unknown result\");" << endl; 
-      } 
- 
-      cleanup_member_name_mapping((*f_iter)->get_xceptions()); 
-      scope_down(f_service_); 
-      f_service_ << endl; 
-    } 
-  } 
- 
-  indent_down(); 
-  indent(f_service_) << "}" << endl; 
-} 
- 
-void t_csharp_generator::generate_service_server(t_service* tservice) { 
-  if (async_) { 
-    generate_service_server_async(tservice); 
-    generate_service_server_sync(tservice); 
-  } 
-  else { 
-    generate_service_server_sync(tservice); 
-  } 
-} 
- 
-void t_csharp_generator::generate_service_server_sync(t_service* tservice) { 
-  vector<t_function*> functions = tservice->get_functions(); 
-  vector<t_function*>::iterator f_iter; 
- 
-  string extends = ""; 
-  string extends_processor = ""; 
-  if (tservice->get_extends() != NULL) { 
-    extends = type_name(tservice->get_extends()); 
-    extends_processor = extends + ".Processor, "; 
-  } 
- 
-  indent(f_service_) << "public class Processor : " << extends_processor << "TProcessor {" << endl; 
-  indent_up(); 
- 
-  indent(f_service_) << "public Processor(ISync iface)"; 
- 
-  if (!extends.empty()) { 
-    f_service_ << " : base(iface)"; 
-  } 
-  f_service_ << endl; 
-  scope_up(f_service_); 
-  f_service_ << indent() << "iface_ = iface;" << endl; 
- 
-  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) { 
-    f_service_ << indent() << "processMap_[\"" << (*f_iter)->get_name() 
-      << "\"] = " << (*f_iter)->get_name() << "_Process;" << endl; 
-  } 
- 
-  scope_down(f_service_); 
-  f_service_ << endl; 
- 
-  if (extends.empty()) { 
-    f_service_ 
-      << indent() 
-      << "protected delegate void ProcessFunction(int seqid, TProtocol iprot, TProtocol oprot);" 
-      << endl; 
-  } 
- 
-  f_service_ << indent() << "private ISync iface_;" << endl; 
- 
-  if (extends.empty()) { 
-    f_service_ << indent() << "protected Dictionary<string, ProcessFunction> processMap_ = new " 
-      "Dictionary<string, ProcessFunction>();" << endl; 
-  } 
- 
-  f_service_ << endl; 
- 
-  if (extends.empty()) { 
-    indent(f_service_) << "public bool Process(TProtocol iprot, TProtocol oprot)" << endl; 
-  } 
-  else { 
-    indent(f_service_) << "public new bool Process(TProtocol iprot, TProtocol oprot)" << endl; 
-  } 
-  scope_up(f_service_); 
- 
-  f_service_ << indent() << "try" << endl; 
-  scope_up(f_service_); 
- 
-  f_service_ << indent() << "TMessage msg = iprot.ReadMessageBegin();" << endl; 
- 
-  f_service_ 
-    << indent() << "ProcessFunction fn;" << endl << indent() 
-    << "processMap_.TryGetValue(msg.Name, out fn);" << endl << indent() << "if (fn == null) {" 
-    << endl << indent() << "  TProtocolUtil.Skip(iprot, TType.Struct);" << endl << indent() 
-    << "  iprot.ReadMessageEnd();" << endl << indent() 
-    << "  TApplicationException x = new TApplicationException " 
-    "(TApplicationException.ExceptionType.UnknownMethod, \"Invalid method name: '\" + " 
-    "msg.Name + \"'\");" << endl << indent() 
-    << "  oprot.WriteMessageBegin(new TMessage(msg.Name, TMessageType.Exception, msg.SeqID));" 
-    << endl << indent() << "  x.Write(oprot);" << endl << indent() << "  oprot.WriteMessageEnd();" 
-    << endl << indent() << "  oprot.Transport.Flush();" << endl << indent() << "  return true;" 
-    << endl << indent() << "}" << endl << indent() << "fn(msg.SeqID, iprot, oprot);" << endl; 
- 
-  scope_down(f_service_); 
- 
-  f_service_ << indent() << "catch (IOException)" << endl; 
-  scope_up(f_service_); 
-  f_service_ << indent() << "return false;" << endl; 
-  scope_down(f_service_); 
- 
-  f_service_ << indent() << "return true;" << endl; 
- 
-  scope_down(f_service_); 
-  f_service_ << endl; 
- 
-  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) { 
-    generate_process_function(tservice, *f_iter); 
-  } 
- 
-  indent_down(); 
-  indent(f_service_) << "}" << endl << endl; 
-} 
- 
-void t_csharp_generator::generate_service_server_async(t_service* tservice) { 
-  vector<t_function*> functions = tservice->get_functions(); 
-  vector<t_function*>::iterator f_iter; 
- 
-  string extends = ""; 
-  string extends_processor = ""; 
-  if (tservice->get_extends() != NULL) { 
-    extends = type_name(tservice->get_extends()); 
-    extends_processor = extends + ".Processor, "; 
-  } 
- 
-  indent(f_service_) << "public class AsyncProcessor : " << extends_processor << "TAsyncProcessor {" << endl; 
-  indent_up(); 
- 
-  indent(f_service_) << "public AsyncProcessor(IAsync iface)"; 
-  if (!extends.empty()) { 
-    f_service_ << " : base(iface)"; 
-  } 
-  f_service_ << endl; 
-  scope_up(f_service_); 
-  f_service_ << indent() << "iface_ = iface;" << endl; 
- 
-  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) { 
-    f_service_ << indent() << "processMap_[\"" << (*f_iter)->get_name() 
-      << "\"] = " << (*f_iter)->get_name() << "_ProcessAsync;" << endl; 
-  } 
- 
-  scope_down(f_service_); 
-  f_service_ << endl; 
- 
-  if (extends.empty()) { 
-    f_service_ 
-      << indent() 
-      << "protected delegate Task ProcessFunction(int seqid, TProtocol iprot, TProtocol oprot);" 
-      << endl; 
-  } 
- 
-  f_service_ << indent() << "private IAsync iface_;" << endl; 
- 
-  if (extends.empty()) { 
-    f_service_ << indent() << "protected Dictionary<string, ProcessFunction> processMap_ = new " 
-      "Dictionary<string, ProcessFunction>();" << endl; 
-  } 
- 
-  f_service_ << endl; 
- 
-  if (extends.empty()) { 
-    indent(f_service_) << "public async Task<bool> ProcessAsync(TProtocol iprot, TProtocol oprot)" << endl; 
-  } 
-  else { 
-    indent(f_service_) << "public new async Task<bool> ProcessAsync(TProtocol iprot, TProtocol oprot)" << endl; 
-  } 
-  scope_up(f_service_); 
- 
-  f_service_ << indent() << "try" << endl; 
-  scope_up(f_service_); 
- 
-  f_service_ << indent() << "TMessage msg = iprot.ReadMessageBegin();" << endl; 
- 
-  f_service_ 
-    << indent() << "ProcessFunction fn;" << endl << indent() 
-    << "processMap_.TryGetValue(msg.Name, out fn);" << endl << indent() << "if (fn == null) {" 
-    << endl << indent() << "  TProtocolUtil.Skip(iprot, TType.Struct);" << endl << indent() 
-    << "  iprot.ReadMessageEnd();" << endl << indent() 
-    << "  TApplicationException x = new TApplicationException " 
-    "(TApplicationException.ExceptionType.UnknownMethod, \"Invalid method name: '\" + " 
-    "msg.Name + \"'\");" << endl << indent() 
-    << "  oprot.WriteMessageBegin(new TMessage(msg.Name, TMessageType.Exception, msg.SeqID));" 
-    << endl << indent() << "  x.Write(oprot);" << endl << indent() << "  oprot.WriteMessageEnd();" 
-    << endl << indent() << "  oprot.Transport.Flush();" << endl << indent() << "  return true;" 
-    << endl << indent() << "}" << endl << indent() << "await fn(msg.SeqID, iprot, oprot);" << endl; 
- 
-  scope_down(f_service_); 
- 
-  f_service_ << indent() << "catch (IOException)" << endl; 
-  scope_up(f_service_); 
-  f_service_ << indent() << "return false;" << endl; 
-  scope_down(f_service_); 
- 
-  f_service_ << indent() << "return true;" << endl; 
- 
-  scope_down(f_service_); 
-  f_service_ << endl; 
- 
-  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) { 
-    generate_process_function_async(tservice, *f_iter); 
-  } 
- 
-  indent_down(); 
-  indent(f_service_) << "}" << endl << endl; 
-} 
- 
-void t_csharp_generator::generate_function_helpers(t_function* tfunction) { 
-  if (tfunction->is_oneway()) { 
-    return; 
-  } 
- 
-  t_struct result(program_, tfunction->get_name() + "_result"); 
-  t_field success(tfunction->get_returntype(), "success", 0); 
-  if (!tfunction->get_returntype()->is_void()) { 
-    result.append(&success); 
-  } 
- 
-  t_struct* xs = tfunction->get_xceptions(); 
-  const vector<t_field*>& fields = xs->get_members(); 
-  vector<t_field*>::const_iterator f_iter; 
-  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { 
-    result.append(*f_iter); 
-  } 
- 
-  generate_csharp_struct_definition(f_service_, &result, false, true, true); 
-} 
- 
-void t_csharp_generator::generate_process_function(t_service* tservice, t_function* tfunction) { 
-  (void)tservice; 
-  indent(f_service_) << "public void " << tfunction->get_name() 
-                     << "_Process(int seqid, TProtocol iprot, TProtocol oprot)" << endl; 
-  scope_up(f_service_); 
- 
-  string argsname = tfunction->get_name() + "_args"; 
-  string resultname = tfunction->get_name() + "_result"; 
- 
-  f_service_ << indent() << argsname << " args = new " << argsname << "();" << endl 
-             << indent() << "args.Read(iprot);" << endl 
-             << indent() << "iprot.ReadMessageEnd();" << endl; 
- 
-  t_struct* xs = tfunction->get_xceptions(); 
-  const std::vector<t_field*>& xceptions = xs->get_members(); 
-  vector<t_field*>::const_iterator x_iter; 
- 
-  if (!tfunction->is_oneway()) { 
-    f_service_ << indent() << resultname << " result = new " << resultname << "();" << endl; 
-  } 
- 
-  f_service_ << indent() << "try" << endl 
-             << indent() << "{" << endl; 
-  indent_up(); 
- 
-  if (xceptions.size() > 0) { 
-    f_service_ << indent() << "try" << endl 
-               << indent() << "{" << endl; 
-    indent_up(); 
-  } 
- 
-  t_struct* arg_struct = tfunction->get_arglist(); 
-  const std::vector<t_field*>& fields = arg_struct->get_members(); 
-  vector<t_field*>::const_iterator f_iter; 
- 
-  f_service_ << indent(); 
-  if (!tfunction->is_oneway() && !tfunction->get_returntype()->is_void()) { 
-    f_service_ << "result.Success = "; 
-  } 
-  f_service_ << "iface_." << normalize_name(tfunction->get_name()) << "("; 
-  bool first = true; 
-  prepare_member_name_mapping(arg_struct); 
-  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { 
-    if (first) { 
-      first = false; 
-    } else { 
-      f_service_ << ", "; 
-    } 
-    f_service_ << "args." << prop_name(*f_iter); 
-    if (nullable_ && !type_can_be_null((*f_iter)->get_type())) { 
-      f_service_ << ".Value"; 
-    } 
-  } 
-  cleanup_member_name_mapping(arg_struct); 
-  f_service_ << ");" << endl; 
- 
-  prepare_member_name_mapping(xs, xs->get_members(), resultname); 
-  if (xceptions.size() > 0) { 
-    indent_down(); 
-    f_service_ << indent() << "}" << endl; 
-    for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) { 
-      f_service_ << indent() << "catch (" << type_name((*x_iter)->get_type(), false, false) << " " 
-                 << (*x_iter)->get_name() << ")" << endl 
-                 << indent() << "{" << endl; 
-      if (!tfunction->is_oneway()) { 
-        indent_up(); 
-        f_service_ << indent() << "result." << prop_name(*x_iter) << " = " << (*x_iter)->get_name() 
-                   << ";" << endl; 
-        indent_down(); 
-      } 
-      f_service_ << indent() << "}" << endl; 
-    } 
-  } 
-  if (!tfunction->is_oneway()) { 
-    f_service_ << indent() << "oprot.WriteMessageBegin(new TMessage(\"" << tfunction->get_name() 
-               << "\", TMessageType.Reply, seqid)); " << endl; 
-    f_service_ << indent() << "result.Write(oprot);" << endl; 
-  } 
-  indent_down(); 
- 
-  cleanup_member_name_mapping(xs); 
- 
-  f_service_ << indent() << "}" << endl 
-             << indent() << "catch (TTransportException)" << endl 
-             << indent() << "{" << endl 
-             << indent() << "  throw;" << endl 
-             << indent() << "}" << endl 
-             << indent() << "catch (Exception ex)" << endl 
-             << indent() << "{" << endl 
-             << indent() << "  Console.Error.WriteLine(\"Error occurred in processor:\");" << endl 
-             << indent() << "  Console.Error.WriteLine(ex.ToString());" << endl; 
- 
-  if (tfunction->is_oneway()) { 
-    f_service_ << indent() << "}" << endl; 
-  } else { 
-    f_service_ << indent() << "  TApplicationException x = new TApplicationException" << indent() 
-               << "(TApplicationException.ExceptionType.InternalError,\" Internal error.\");" 
-               << endl 
-               << indent() << "  oprot.WriteMessageBegin(new TMessage(\"" << tfunction->get_name() 
-               << "\", TMessageType.Exception, seqid));" << endl 
-               << indent() << "  x.Write(oprot);" << endl 
-               << indent() << "}" << endl; 
-    f_service_ << indent() << "oprot.WriteMessageEnd();" << endl 
-               << indent() << "oprot.Transport.Flush();" << endl; 
-  } 
- 
-  scope_down(f_service_); 
- 
-  f_service_ << endl; 
-} 
- 
-void t_csharp_generator::generate_process_function_async(t_service* tservice, t_function* tfunction) { 
-  (void)tservice; 
-  indent(f_service_) << "public async Task " << tfunction->get_name() 
-    << "_ProcessAsync(int seqid, TProtocol iprot, TProtocol oprot)" << endl; 
-  scope_up(f_service_); 
- 
-  string argsname = tfunction->get_name() + "_args"; 
-  string resultname = tfunction->get_name() + "_result"; 
- 
-  f_service_ << indent() << argsname << " args = new " << argsname << "();" << endl 
-    << indent() << "args.Read(iprot);" << endl 
-    << indent() << "iprot.ReadMessageEnd();" << endl; 
- 
-  t_struct* xs = tfunction->get_xceptions(); 
-  const std::vector<t_field*>& xceptions = xs->get_members(); 
-  vector<t_field*>::const_iterator x_iter; 
- 
-  if (!tfunction->is_oneway()) { 
-    f_service_ << indent() << resultname << " result = new " << resultname << "();" << endl; 
-  } 
- 
-  f_service_ << indent() << "try" << endl 
-    << indent() << "{" << endl; 
-  indent_up(); 
- 
-  if (xceptions.size() > 0) { 
-    f_service_ << indent() << "try" << endl 
-      << indent() << "{" << endl; 
-    indent_up(); 
-  } 
- 
-  t_struct* arg_struct = tfunction->get_arglist(); 
-  const std::vector<t_field*>& fields = arg_struct->get_members(); 
-  vector<t_field*>::const_iterator f_iter; 
- 
-  f_service_ << indent(); 
-  if (!tfunction->is_oneway() && !tfunction->get_returntype()->is_void()) { 
-    f_service_ << "result.Success = "; 
-  } 
-  f_service_ << "await iface_." << normalize_name(tfunction->get_name()) << "Async("; 
-  bool first = true; 
-  prepare_member_name_mapping(arg_struct); 
-  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { 
-    if (first) { 
-      first = false; 
-    } 
-    else { 
-      f_service_ << ", "; 
-    } 
-    f_service_ << "args." << prop_name(*f_iter); 
-    if (nullable_ && !type_can_be_null((*f_iter)->get_type())) { 
-      f_service_ << ".Value"; 
-    } 
-  } 
-  cleanup_member_name_mapping(arg_struct); 
-  f_service_ << ");" << endl; 
- 
-  prepare_member_name_mapping(xs, xs->get_members(), resultname); 
-  if (xceptions.size() > 0) { 
-    indent_down(); 
-    f_service_ << indent() << "}" << endl; 
-    for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) { 
-      f_service_ << indent() << "catch (" << type_name((*x_iter)->get_type(), false, false) << " " 
-        << (*x_iter)->get_name() << ")" << endl 
-        << indent() << "{" << endl; 
-      if (!tfunction->is_oneway()) { 
-        indent_up(); 
-        f_service_ << indent() << "result." << prop_name(*x_iter) << " = " << (*x_iter)->get_name() 
-          << ";" << endl; 
-        indent_down(); 
-      } 
-      f_service_ << indent() << "}" << endl; 
-    } 
-  } 
-  if (!tfunction->is_oneway()) { 
-    f_service_ << indent() << "oprot.WriteMessageBegin(new TMessage(\"" << tfunction->get_name() 
-      << "\", TMessageType.Reply, seqid)); " << endl; 
-    f_service_ << indent() << "result.Write(oprot);" << endl; 
-  } 
-  indent_down(); 
- 
-  cleanup_member_name_mapping(xs); 
- 
-  f_service_ << indent() << "}" << endl 
-    << indent() << "catch (TTransportException)" << endl 
-    << indent() << "{" << endl 
-    << indent() << "  throw;" << endl 
-    << indent() << "}" << endl 
-    << indent() << "catch (Exception ex)" << endl 
-    << indent() << "{" << endl 
-    << indent() << "  Console.Error.WriteLine(\"Error occurred in processor:\");" << endl 
-    << indent() << "  Console.Error.WriteLine(ex.ToString());" << endl; 
- 
-  if (tfunction->is_oneway()) { 
-    f_service_ << indent() << "}" << endl; 
-  } 
-  else { 
-    f_service_ << indent() << "  TApplicationException x = new TApplicationException" << indent() 
-      << "(TApplicationException.ExceptionType.InternalError,\" Internal error.\");" 
-      << endl 
-      << indent() << "  oprot.WriteMessageBegin(new TMessage(\"" << tfunction->get_name() 
-      << "\", TMessageType.Exception, seqid));" << endl 
-      << indent() << "  x.Write(oprot);" << endl 
-      << indent() << "}" << endl; 
-    f_service_ << indent() << "oprot.WriteMessageEnd();" << endl 
-      << indent() << "oprot.Transport.Flush();" << endl; 
-  } 
- 
-  scope_down(f_service_); 
- 
-  f_service_ << endl; 
-} 
- 
-void t_csharp_generator::generate_csharp_union_reader(std::ostream& out, t_struct* tunion) { 
-  // Thanks to THRIFT-1768, we don't need to check for required fields in the union 
-  const vector<t_field*>& fields = tunion->get_members(); 
-  vector<t_field*>::const_iterator f_iter; 
- 
-  indent(out) << "public static " << tunion->get_name() << " Read(TProtocol iprot)" << endl; 
-  scope_up(out); 
- 
-  out << indent() << "iprot.IncrementRecursionDepth();" << endl; 
-  out << indent() << "try" << endl; 
-  scope_up(out); 
- 
-  indent(out) << tunion->get_name() << " retval;" << endl; 
-  indent(out) << "iprot.ReadStructBegin();" << endl; 
-  indent(out) << "TField field = iprot.ReadFieldBegin();" << endl; 
-  // we cannot have the first field be a stop -- we must have a single field defined 
-  indent(out) << "if (field.Type == TType.Stop)" << endl; 
-  scope_up(out); 
-  indent(out) << "iprot.ReadFieldEnd();" << endl; 
-  indent(out) << "retval = new ___undefined();" << endl; 
-  scope_down(out); 
-  indent(out) << "else" << endl; 
-  scope_up(out); 
-  indent(out) << "switch (field.ID)" << endl; 
-  scope_up(out); 
- 
-  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { 
-    indent(out) << "case " << (*f_iter)->get_key() << ":" << endl; 
-    indent_up(); 
-    indent(out) << "if (field.Type == " << type_to_enum((*f_iter)->get_type()) << ") {" << endl; 
-    indent_up(); 
- 
-    indent(out) << type_name((*f_iter)->get_type()) << " temp;" << endl; 
-    generate_deserialize_field(out, (*f_iter), "temp", true); 
-    indent(out) << "retval = new " << (*f_iter)->get_name() << "(temp);" << endl; 
- 
-    indent_down(); 
-    out << indent() << "} else { " << endl << indent() << "  TProtocolUtil.Skip(iprot, field.Type);" 
-        << endl << indent() << "  retval = new ___undefined();" << endl << indent() << "}" << endl 
-        << indent() << "break;" << endl; 
-    indent_down(); 
-  } 
- 
-  indent(out) << "default: " << endl; 
-  indent_up(); 
-  indent(out) << "TProtocolUtil.Skip(iprot, field.Type);" << endl << indent() 
-              << "retval = new ___undefined();" << endl; 
-  indent(out) << "break;" << endl; 
-  indent_down(); 
- 
-  scope_down(out); 
- 
-  indent(out) << "iprot.ReadFieldEnd();" << endl; 
- 
-  indent(out) << "if (iprot.ReadFieldBegin().Type != TType.Stop)" << endl; 
-  scope_up(out); 
-  indent(out) << "throw new TProtocolException(TProtocolException.INVALID_DATA);" << endl; 
-  scope_down(out); 
- 
-  // end of else for TStop 
-  scope_down(out); 
-  indent(out) << "iprot.ReadStructEnd();" << endl; 
-  indent(out) << "return retval;" << endl; 
-  indent_down(); 
- 
-  scope_down(out); 
-  out << indent() << "finally" << endl; 
-  scope_up(out); 
-  out << indent() << "iprot.DecrementRecursionDepth();" << endl; 
-  scope_down(out); 
- 
-  indent(out) << "}" << endl << endl; 
-} 
- 
-void t_csharp_generator::generate_deserialize_field(ostream& out, 
-                                                    t_field* tfield, 
-                                                    string prefix, 
-                                                    bool is_propertyless) { 
-  t_type* type = tfield->get_type(); 
-  while (type->is_typedef()) { 
-    type = ((t_typedef*)type)->get_type(); 
-  } 
- 
-  if (type->is_void()) { 
-    throw "CANNOT GENERATE DESERIALIZE CODE FOR void TYPE: " + prefix + tfield->get_name(); 
-  } 
- 
-  string name = prefix + (is_propertyless ? "" : prop_name(tfield)); 
- 
-  if (type->is_struct() || type->is_xception()) { 
-    generate_deserialize_struct(out, (t_struct*)type, name); 
-  } else if (type->is_container()) { 
-    generate_deserialize_container(out, type, name); 
-  } else if (type->is_base_type() || type->is_enum()) { 
-    indent(out) << name << " = "; 
- 
-    if (type->is_enum()) { 
-      out << "(" << type_name(type, false, true) << ")"; 
-    } 
- 
-    out << "iprot."; 
- 
-    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: 
-        throw "compiler error: cannot serialize void field in a struct: " + name; 
-        break; 
-      case t_base_type::TYPE_STRING: 
-        if (type->is_binary()) { 
-          out << "ReadBinary();"; 
-        } else { 
-          out << "ReadString();"; 
-        } 
-        break; 
-      case t_base_type::TYPE_BOOL: 
-        out << "ReadBool();"; 
-        break; 
-      case t_base_type::TYPE_I8: 
-        out << "ReadByte();"; 
-        break; 
-      case t_base_type::TYPE_I16: 
-        out << "ReadI16();"; 
-        break; 
-      case t_base_type::TYPE_I32: 
-        out << "ReadI32();"; 
-        break; 
-      case t_base_type::TYPE_I64: 
-        out << "ReadI64();"; 
-        break; 
-      case t_base_type::TYPE_DOUBLE: 
-        out << "ReadDouble();"; 
-        break; 
-      default: 
-        throw "compiler error: no C# name for base type " + t_base_type::t_base_name(tbase); 
-      } 
-    } else if (type->is_enum()) { 
-      out << "ReadI32();"; 
-    } 
-    out << endl; 
-  } else { 
-    printf("DO NOT KNOW HOW TO DESERIALIZE FIELD '%s' TYPE '%s'\n", 
-           tfield->get_name().c_str(), 
-           type_name(type).c_str()); 
-  } 
-} 
- 
-void t_csharp_generator::generate_deserialize_struct(ostream& out, 
-                                                     t_struct* tstruct, 
-                                                     string prefix) { 
-  if (union_ && tstruct->is_union()) { 
-    out << indent() << prefix << " = " << type_name(tstruct) << ".Read(iprot);" << endl; 
-  } else { 
-    out << indent() << prefix << " = new " << type_name(tstruct) << "();" << endl << indent() 
-        << prefix << ".Read(iprot);" << endl; 
-  } 
-} 
- 
-void t_csharp_generator::generate_deserialize_container(ostream& out, 
-                                                        t_type* ttype, 
-                                                        string prefix) { 
-  scope_up(out); 
- 
-  string obj; 
- 
-  if (ttype->is_map()) { 
-    obj = tmp("_map"); 
-  } else if (ttype->is_set()) { 
-    obj = tmp("_set"); 
-  } else if (ttype->is_list()) { 
-    obj = tmp("_list"); 
-  } 
- 
-  indent(out) << prefix << " = new " << type_name(ttype, false, true) << "();" << endl; 
-  if (ttype->is_map()) { 
-    out << indent() << "TMap " << obj << " = iprot.ReadMapBegin();" << endl; 
-  } else if (ttype->is_set()) { 
-    out << indent() << "TSet " << obj << " = iprot.ReadSetBegin();" << endl; 
-  } else if (ttype->is_list()) { 
-    out << indent() << "TList " << obj << " = iprot.ReadListBegin();" << endl; 
-  } 
- 
-  string i = tmp("_i"); 
-  indent(out) << "for( int " << i << " = 0; " << i << " < " << obj << ".Count" 
-              << "; " 
-              << "++" << i << ")" << endl; 
-  scope_up(out); 
- 
-  if (ttype->is_map()) { 
-    generate_deserialize_map_element(out, (t_map*)ttype, prefix); 
-  } else if (ttype->is_set()) { 
-    generate_deserialize_set_element(out, (t_set*)ttype, prefix); 
-  } else if (ttype->is_list()) { 
-    generate_deserialize_list_element(out, (t_list*)ttype, prefix); 
-  } 
- 
-  scope_down(out); 
- 
-  if (ttype->is_map()) { 
-    indent(out) << "iprot.ReadMapEnd();" << endl; 
-  } else if (ttype->is_set()) { 
-    indent(out) << "iprot.ReadSetEnd();" << endl; 
-  } else if (ttype->is_list()) { 
-    indent(out) << "iprot.ReadListEnd();" << endl; 
-  } 
- 
-  scope_down(out); 
-} 
- 
-void t_csharp_generator::generate_deserialize_map_element(ostream& out, 
-                                                          t_map* tmap, 
-                                                          string prefix) { 
-  string key = tmp("_key"); 
-  string val = tmp("_val"); 
- 
-  t_field fkey(tmap->get_key_type(), key); 
-  t_field fval(tmap->get_val_type(), val); 
- 
-  indent(out) << declare_field(&fkey) << endl; 
-  indent(out) << declare_field(&fval) << endl; 
- 
-  generate_deserialize_field(out, &fkey); 
-  generate_deserialize_field(out, &fval); 
- 
-  indent(out) << prefix << "[" << key << "] = " << val << ";" << endl; 
-} 
- 
-void t_csharp_generator::generate_deserialize_set_element(ostream& out, 
-                                                          t_set* tset, 
-                                                          string prefix) { 
-  string elem = tmp("_elem"); 
-  t_field felem(tset->get_elem_type(), elem); 
- 
-  indent(out) << declare_field(&felem) << endl; 
- 
-  generate_deserialize_field(out, &felem); 
- 
-  indent(out) << prefix << ".Add(" << elem << ");" << endl; 
-} 
- 
-void t_csharp_generator::generate_deserialize_list_element(ostream& out, 
-                                                           t_list* tlist, 
-                                                           string prefix) { 
-  string elem = tmp("_elem"); 
-  t_field felem(tlist->get_elem_type(), elem); 
- 
-  indent(out) << declare_field(&felem) << endl; 
- 
-  generate_deserialize_field(out, &felem); 
- 
-  indent(out) << prefix << ".Add(" << elem << ");" << endl; 
-} 
- 
-void t_csharp_generator::generate_serialize_field(ostream& out, 
-                                                  t_field* tfield, 
-                                                  string prefix, 
-                                                  bool is_element, 
-                                                  bool is_propertyless) { 
-  t_type* type = tfield->get_type(); 
-  while (type->is_typedef()) { 
-    type = ((t_typedef*)type)->get_type(); 
-  } 
- 
-  string name = prefix + (is_propertyless ? "" : prop_name(tfield)); 
- 
-  if (type->is_void()) { 
-    throw "CANNOT GENERATE SERIALIZE CODE FOR void TYPE: " + name; 
-  } 
- 
-  if (type->is_struct() || type->is_xception()) { 
-    generate_serialize_struct(out, (t_struct*)type, name); 
-  } else if (type->is_container()) { 
-    generate_serialize_container(out, type, name); 
-  } else if (type->is_base_type() || type->is_enum()) { 
-    indent(out) << "oprot."; 
- 
-    string nullable_name = nullable_ && !is_element && !field_is_required(tfield) ? name + ".Value" 
-                                                                                  : name; 
- 
-    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: 
-        throw "compiler error: cannot serialize void field in a struct: " + name; 
-        break; 
-      case t_base_type::TYPE_STRING: 
-        if (type->is_binary()) { 
-          out << "WriteBinary("; 
-        } else { 
-          out << "WriteString("; 
-        } 
-        out << name << ");"; 
-        break; 
-      case t_base_type::TYPE_BOOL: 
-        out << "WriteBool(" << nullable_name << ");"; 
-        break; 
-      case t_base_type::TYPE_I8: 
-        out << "WriteByte(" << nullable_name << ");"; 
-        break; 
-      case t_base_type::TYPE_I16: 
-        out << "WriteI16(" << nullable_name << ");"; 
-        break; 
-      case t_base_type::TYPE_I32: 
-        out << "WriteI32(" << nullable_name << ");"; 
-        break; 
-      case t_base_type::TYPE_I64: 
-        out << "WriteI64(" << nullable_name << ");"; 
-        break; 
-      case t_base_type::TYPE_DOUBLE: 
-        out << "WriteDouble(" << nullable_name << ");"; 
-        break; 
-      default: 
-        throw "compiler error: no C# name for base type " + t_base_type::t_base_name(tbase); 
-      } 
-    } else if (type->is_enum()) { 
-      out << "WriteI32((int)" << nullable_name << ");"; 
-    } 
-    out << endl; 
-  } else { 
-    printf("DO NOT KNOW HOW TO SERIALIZE '%s%s' TYPE '%s'\n", 
-           prefix.c_str(), 
-           tfield->get_name().c_str(), 
-           type_name(type).c_str()); 
-  } 
-} 
- 
-void t_csharp_generator::generate_serialize_struct(ostream& out, 
-                                                   t_struct* tstruct, 
-                                                   string prefix) { 
-  (void)tstruct; 
-  out << indent() << prefix << ".Write(oprot);" << endl; 
-} 
- 
-void t_csharp_generator::generate_serialize_container(ostream& out, t_type* ttype, string prefix) { 
-  scope_up(out); 
- 
-  if (ttype->is_map()) { 
-    indent(out) << "oprot.WriteMapBegin(new TMap(" << type_to_enum(((t_map*)ttype)->get_key_type()) 
-                << ", " << type_to_enum(((t_map*)ttype)->get_val_type()) << ", " << prefix 
-                << ".Count));" << endl; 
-  } else if (ttype->is_set()) { 
-    indent(out) << "oprot.WriteSetBegin(new TSet(" << type_to_enum(((t_set*)ttype)->get_elem_type()) 
-                << ", " << prefix << ".Count));" << endl; 
-  } else if (ttype->is_list()) { 
-    indent(out) << "oprot.WriteListBegin(new TList(" 
-                << type_to_enum(((t_list*)ttype)->get_elem_type()) << ", " << prefix << ".Count));" 
-                << endl; 
-  } 
- 
-  string iter = tmp("_iter"); 
-  if (ttype->is_map()) { 
-    indent(out) << "foreach (" << type_name(((t_map*)ttype)->get_key_type()) << " " << iter 
-                << " in " << prefix << ".Keys)"; 
-  } else if (ttype->is_set()) { 
-    indent(out) << "foreach (" << type_name(((t_set*)ttype)->get_elem_type()) << " " << iter 
-                << " in " << prefix << ")"; 
-  } else if (ttype->is_list()) { 
-    indent(out) << "foreach (" << type_name(((t_list*)ttype)->get_elem_type()) << " " << iter 
-                << " in " << prefix << ")"; 
-  } 
- 
-  out << endl; 
-  scope_up(out); 
- 
-  if (ttype->is_map()) { 
-    generate_serialize_map_element(out, (t_map*)ttype, iter, prefix); 
-  } else if (ttype->is_set()) { 
-    generate_serialize_set_element(out, (t_set*)ttype, iter); 
-  } else if (ttype->is_list()) { 
-    generate_serialize_list_element(out, (t_list*)ttype, iter); 
-  } 
- 
-  scope_down(out); 
- 
-  if (ttype->is_map()) { 
-    indent(out) << "oprot.WriteMapEnd();" << endl; 
-  } else if (ttype->is_set()) { 
-    indent(out) << "oprot.WriteSetEnd();" << endl; 
-  } else if (ttype->is_list()) { 
-    indent(out) << "oprot.WriteListEnd();" << endl; 
-  } 
- 
-  scope_down(out); 
-} 
- 
-void t_csharp_generator::generate_serialize_map_element(ostream& out, 
-                                                        t_map* tmap, 
-                                                        string iter, 
-                                                        string map) { 
-  t_field kfield(tmap->get_key_type(), iter); 
-  generate_serialize_field(out, &kfield, "", true); 
-  t_field vfield(tmap->get_val_type(), map + "[" + iter + "]"); 
-  generate_serialize_field(out, &vfield, "", true); 
-} 
- 
-void t_csharp_generator::generate_serialize_set_element(ostream& out, t_set* tset, string iter) { 
-  t_field efield(tset->get_elem_type(), iter); 
-  generate_serialize_field(out, &efield, "", true); 
-} 
- 
-void t_csharp_generator::generate_serialize_list_element(ostream& out, 
-                                                         t_list* tlist, 
-                                                         string iter) { 
-  t_field efield(tlist->get_elem_type(), iter); 
-  generate_serialize_field(out, &efield, "", true); 
-} 
- 
-void t_csharp_generator::generate_property(ostream& out, 
-                                           t_field* tfield, 
-                                           bool isPublic, 
-                                           bool generateIsset) { 
-  generate_csharp_property(out, tfield, isPublic, generateIsset, "_"); 
-} 
-void t_csharp_generator::generate_csharp_property(ostream& out, 
-                                                  t_field* tfield, 
-                                                  bool isPublic, 
-                                                  bool generateIsset, 
-                                                  std::string fieldPrefix) { 
-  if ((serialize_ || wcf_) && isPublic) { 
-    indent(out) << "[DataMember(Order = 0)]" << endl; 
-  } 
-  bool has_default = field_has_default(tfield); 
-  bool is_required = field_is_required(tfield); 
-  if ((nullable_ && !has_default) || (is_required)) { 
-    indent(out) << (isPublic ? "public " : "private ") 
-                << type_name(tfield->get_type(), false, false, true, is_required) << " " 
-                << prop_name(tfield) << " { get; set; }" << endl; 
-  } else { 
-    indent(out) << (isPublic ? "public " : "private ") 
-                << type_name(tfield->get_type(), false, false, true) << " " << prop_name(tfield) 
-                << endl; 
-    scope_up(out); 
-    indent(out) << "get" << endl; 
-    scope_up(out); 
-    bool use_nullable = false; 
-    if (nullable_) { 
-      t_type* ttype = tfield->get_type(); 
-      while (ttype->is_typedef()) { 
-        ttype = ((t_typedef*)ttype)->get_type(); 
-      } 
-      if (ttype->is_base_type()) { 
-        use_nullable = ((t_base_type*)ttype)->get_base() != t_base_type::TYPE_STRING; 
-      } else if (ttype->is_enum()) { 
-        use_nullable = true; 
-      } 
-    } 
-    indent(out) << "return " << fieldPrefix + tfield->get_name() << ";" << endl; 
-    scope_down(out); 
-    indent(out) << "set" << endl; 
-    scope_up(out); 
-    if (use_nullable) { 
-      if (generateIsset) { 
-        indent(out) << "__isset." << normalize_name(tfield->get_name()) << " = value.HasValue;" 
-                    << endl; 
-      } 
-      indent(out) << "if (value.HasValue) this." << fieldPrefix + tfield->get_name() 
-                  << " = value.Value;" << endl; 
-    } else { 
-      if (generateIsset) { 
-        indent(out) << "__isset." << normalize_name(tfield->get_name()) << " = true;" << endl; 
-      } 
-      indent(out) << "this." << fieldPrefix + tfield->get_name() << " = value;" << endl; 
-    } 
-    scope_down(out); 
-    scope_down(out); 
-  } 
-  out << endl; 
-} 
- 
-std::string t_csharp_generator::make_valid_csharp_identifier(std::string const& fromName) { 
-  std::string str = fromName; 
-  if (str.empty()) { 
-    return str; 
-  } 
- 
-  // tests rely on this 
-  assert(('A' < 'Z') && ('a' < 'z') && ('0' < '9')); 
- 
-  // if the first letter is a number, we add an additional underscore in front of it 
-  char c = str.at(0); 
-  if (('0' <= c) && (c <= '9')) { 
-    str = "_" + str; 
-  } 
- 
-  // following chars: letter, number or underscore 
-  for (size_t i = 0; i < str.size(); ++i) { 
-    c = str.at(i); 
-    if ((('A' > c) || (c > 'Z')) && (('a' > c) || (c > 'z')) && (('0' > c) || (c > '9')) 
-        && ('_' != c)) { 
-      str.replace(i, 1, "_"); 
-    } 
-  } 
- 
-  return str; 
-} 
- 
-void t_csharp_generator::cleanup_member_name_mapping(void* scope) { 
-  if( member_mapping_scopes.empty()) { 
-    throw "internal error: cleanup_member_name_mapping() no scope active"; 
-  } 
- 
-  member_mapping_scope& active = member_mapping_scopes.back(); 
-  if (active.scope_member != scope) { 
-    throw "internal error: cleanup_member_name_mapping() called for wrong struct"; 
-  } 
- 
-  member_mapping_scopes.pop_back(); 
-} 
- 
-string t_csharp_generator::get_mapped_member_name(string name) { 
-  if( ! member_mapping_scopes.empty()) { 
-    member_mapping_scope& active = member_mapping_scopes.back(); 
-    map<string, string>::iterator iter = active.mapping_table.find(name); 
-    if (active.mapping_table.end() != iter) { 
-      return iter->second; 
-    } 
-  } 
- 
-  pverbose("no mapping for member %s\n", name.c_str()); 
-  return name; 
-} 
- 
-void t_csharp_generator::prepare_member_name_mapping(t_struct* tstruct) { 
-  prepare_member_name_mapping(tstruct, tstruct->get_members(), tstruct->get_name()); 
-} 
- 
-void t_csharp_generator::prepare_member_name_mapping(void* scope, 
-                                                     const vector<t_field*>& members, 
-                                                     const string& structname) { 
-  // begin new scope 
-  member_mapping_scope dummy; 
-  dummy.scope_member = 0; 
-  member_mapping_scopes.push_back(dummy); 
-  member_mapping_scope& active = member_mapping_scopes.back(); 
-  active.scope_member = scope; 
- 
-  // current C# generator policy: 
-  // - prop names are always rendered with an Uppercase first letter 
-  // - struct names are used as given 
-  std::set<std::string> used_member_names; 
-  vector<t_field*>::const_iterator iter; 
- 
-  // prevent name conflicts with struct (CS0542 error) 
-  used_member_names.insert(structname); 
- 
-  // prevent name conflicts with known methods (THRIFT-2942) 
-  used_member_names.insert("Read"); 
-  used_member_names.insert("Write"); 
- 
-  for (iter = members.begin(); iter != members.end(); ++iter) { 
-    string oldname = (*iter)->get_name(); 
-    string newname = prop_name(*iter, true); 
-    while (true) { 
- 
-      // new name conflicts with another member 
-      if (used_member_names.find(newname) != used_member_names.end()) { 
-        pverbose("struct %s: member %s conflicts with another member\n", 
-                 structname.c_str(), 
-                 newname.c_str()); 
-        newname += '_'; 
-        continue; 
-      } 
- 
-      // add always, this helps us to detect edge cases like 
-      // different spellings ("foo" and "Foo") within the same struct 
-      pverbose("struct %s: member mapping %s => %s\n", 
-               structname.c_str(), 
-               oldname.c_str(), 
-               newname.c_str()); 
-      active.mapping_table[oldname] = newname; 
-      used_member_names.insert(newname); 
-      break; 
-    } 
-  } 
-} 
- 
-std::string t_csharp_generator::prop_name(t_field* tfield, bool suppress_mapping) { 
-  string name(tfield->get_name()); 
-  if (suppress_mapping) { 
-    name[0] = toupper(name[0]); 
-  } else { 
-    name = get_mapped_member_name(name); 
-  } 
-  return name; 
-} 
- 
-string t_csharp_generator::type_name(t_type* ttype, 
-                                     bool in_container, 
-                                     bool in_init, 
-                                     bool in_param, 
-                                     bool is_required) { 
-  (void)in_init; 
-  while (ttype->is_typedef()) { 
-    ttype = ((t_typedef*)ttype)->get_type(); 
-  } 
- 
-  if (ttype->is_base_type()) { 
-    return base_type_name((t_base_type*)ttype, in_container, in_param, is_required); 
-  } else if (ttype->is_map()) { 
-    t_map* tmap = (t_map*)ttype; 
-    return "Dictionary<" + 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; 
-    return "THashSet<" + type_name(tset->get_elem_type(), true) + ">"; 
-  } else if (ttype->is_list()) { 
-    t_list* tlist = (t_list*)ttype; 
-    return "List<" + type_name(tlist->get_elem_type(), true) + ">"; 
-  } 
- 
-  t_program* program = ttype->get_program(); 
-  string postfix = (!is_required && nullable_ && in_param && ttype->is_enum()) ? "?" : ""; 
-  if (program != NULL && program != program_) { 
-    string ns = program->get_namespace("csharp"); 
-    if (!ns.empty()) { 
-      return ns + "." + normalize_name(ttype->get_name()) + postfix; 
-    } 
-  } 
- 
-  return normalize_name(ttype->get_name()) + postfix; 
-} 
- 
-string t_csharp_generator::base_type_name(t_base_type* tbase, 
-                                          bool in_container, 
-                                          bool in_param, 
-                                          bool is_required) { 
-  (void)in_container; 
-  string postfix = (!is_required && nullable_ && in_param) ? "?" : ""; 
-  switch (tbase->get_base()) { 
-  case t_base_type::TYPE_VOID: 
-    return "void"; 
-  case t_base_type::TYPE_STRING: 
-    if (tbase->is_binary()) { 
-      return "byte[]"; 
-    } else { 
-      return "string"; 
-    } 
-  case t_base_type::TYPE_BOOL: 
-    return "bool" + postfix; 
-  case t_base_type::TYPE_I8: 
-    return "sbyte" + postfix; 
-  case t_base_type::TYPE_I16: 
-    return "short" + postfix; 
-  case t_base_type::TYPE_I32: 
-    return "int" + postfix; 
-  case t_base_type::TYPE_I64: 
-    return "long" + postfix; 
-  case t_base_type::TYPE_DOUBLE: 
-    return "double" + postfix; 
-  default: 
-    throw "compiler error: no C# name for base type " + t_base_type::t_base_name(tbase->get_base()); 
-  } 
-} 
- 
-string t_csharp_generator::declare_field(t_field* tfield, bool init, std::string prefix) { 
-  string result = type_name(tfield->get_type()) + " " + prefix + tfield->get_name(); 
-  if (init) { 
-    t_type* ttype = tfield->get_type(); 
-    while (ttype->is_typedef()) { 
-      ttype = ((t_typedef*)ttype)->get_type(); 
-    } 
-    if (ttype->is_base_type() && field_has_default(tfield)) { 
-      std::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 += " = null"; 
-        break; 
-      case t_base_type::TYPE_BOOL: 
-        result += " = false"; 
-        break; 
-      case t_base_type::TYPE_I8: 
-      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 += " = (double)0"; 
-        break; 
-      } 
-    } else if (ttype->is_enum()) { 
-      result += " = (" + type_name(ttype, false, true) + ")0"; 
-    } else if (ttype->is_container()) { 
-      result += " = new " + type_name(ttype, false, true) + "()"; 
-    } else { 
-      result += " = new " + type_name(ttype, false, true) + "()"; 
-    } 
-  } 
-  return result + ";"; 
-} 
- 
-string t_csharp_generator::function_signature(t_function* tfunction, string prefix) { 
-  t_type* ttype = tfunction->get_returntype(); 
-  return type_name(ttype) + " " + normalize_name(prefix + tfunction->get_name()) + "(" 
-         + argument_list(tfunction->get_arglist()) + ")"; 
-} 
- 
-string t_csharp_generator::function_signature_async_begin(t_function* tfunction, string prefix) { 
-  string comma = (tfunction->get_arglist()->get_members().size() > 0 ? ", " : ""); 
-  return "IAsyncResult " + normalize_name(prefix + tfunction->get_name()) 
-         + "(AsyncCallback callback, object state" + comma + argument_list(tfunction->get_arglist()) 
-         + ")"; 
-} 
- 
-string t_csharp_generator::function_signature_async_end(t_function* tfunction, string prefix) { 
-  t_type* ttype = tfunction->get_returntype(); 
-  return type_name(ttype) + " " + normalize_name(prefix + tfunction->get_name()) 
-         + "(IAsyncResult asyncResult)"; 
-} 
- 
-string t_csharp_generator::function_signature_async(t_function* tfunction, string prefix) { 
-  t_type* ttype = tfunction->get_returntype(); 
-  string task = "Task"; 
-  if (!ttype->is_void()) 
-    task += "<" + type_name(ttype) + ">"; 
-  return task + " " + normalize_name(prefix + tfunction->get_name()) + "Async(" 
-         + argument_list(tfunction->get_arglist()) + ")"; 
-} 
- 
-string t_csharp_generator::argument_list(t_struct* tstruct) { 
-  string result = ""; 
-  const vector<t_field*>& fields = tstruct->get_members(); 
-  vector<t_field*>::const_iterator f_iter; 
-  bool first = true; 
-  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { 
-    if (first) { 
-      first = false; 
-    } else { 
-      result += ", "; 
-    } 
-    result += type_name((*f_iter)->get_type()) + " " + normalize_name((*f_iter)->get_name()); 
-  } 
-  return result; 
-} 
- 
-string t_csharp_generator::type_to_enum(t_type* 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: 
-      throw "NO T_VOID CONSTRUCT"; 
-    case t_base_type::TYPE_STRING: 
-      return "TType.String"; 
-    case t_base_type::TYPE_BOOL: 
-      return "TType.Bool"; 
-    case t_base_type::TYPE_I8: 
-      return "TType.Byte"; 
-    case t_base_type::TYPE_I16: 
-      return "TType.I16"; 
-    case t_base_type::TYPE_I32: 
-      return "TType.I32"; 
-    case t_base_type::TYPE_I64: 
-      return "TType.I64"; 
-    case t_base_type::TYPE_DOUBLE: 
-      return "TType.Double"; 
-    } 
-  } else if (type->is_enum()) { 
-    return "TType.I32"; 
-  } else if (type->is_struct() || type->is_xception()) { 
-    return "TType.Struct"; 
-  } else if (type->is_map()) { 
-    return "TType.Map"; 
-  } else if (type->is_set()) { 
-    return "TType.Set"; 
-  } else if (type->is_list()) { 
-    return "TType.List"; 
-  } 
- 
-  throw "INVALID TYPE IN type_to_enum: " + type->get_name(); 
-} 
- 
-void t_csharp_generator::generate_csharp_docstring_comment(ostream& out, string contents) { 
-  generate_docstring_comment(out, "/// <summary>\n", "/// ", contents, "/// </summary>\n"); 
-} 
- 
-void t_csharp_generator::generate_csharp_doc(ostream& out, t_field* field) { 
-  if (field->get_type()->is_enum()) { 
-    string combined_message = field->get_doc() + "\n<seealso cref=\"" 
-                              + get_enum_class_name(field->get_type()) + "\"/>"; 
-    generate_csharp_docstring_comment(out, combined_message); 
-  } else { 
-    generate_csharp_doc(out, (t_doc*)field); 
-  } 
-} 
- 
-void t_csharp_generator::generate_csharp_doc(ostream& out, t_doc* tdoc) { 
-  if (tdoc->has_doc()) { 
-    generate_csharp_docstring_comment(out, tdoc->get_doc()); 
-  } 
-} 
- 
-void t_csharp_generator::generate_csharp_doc(ostream& out, t_function* tfunction) { 
-  if (tfunction->has_doc()) { 
-    stringstream ps; 
-    const vector<t_field*>& fields = tfunction->get_arglist()->get_members(); 
-    vector<t_field*>::const_iterator p_iter; 
-    for (p_iter = fields.begin(); p_iter != fields.end(); ++p_iter) { 
-      t_field* p = *p_iter; 
-      ps << "\n<param name=\"" << p->get_name() << "\">"; 
-      if (p->has_doc()) { 
-        std::string str = p->get_doc(); 
-        str.erase(std::remove(str.begin(), str.end(), '\n'), 
-                  str.end()); // remove the newlines that appear from the parser 
-        ps << str; 
-      } 
-      ps << "</param>"; 
-    } 
-    generate_docstring_comment(out, 
-                               "", 
-                               "/// ", 
-                               "<summary>\n" + tfunction->get_doc() + "</summary>" + ps.str(), 
-                               ""); 
-  } 
-} 
- 
-std::string t_csharp_generator::get_enum_class_name(t_type* type) { 
-  string package = ""; 
-  t_program* program = type->get_program(); 
-  if (program != NULL && program != program_) { 
-    package = program->get_namespace("csharp") + "."; 
-  } 
-  return package + type->get_name(); 
-} 
- 
- 
-THRIFT_REGISTER_GENERATOR( 
-    csharp, 
-    "C#", 
-    "    async:           Adds Async support using Task.Run.\n" 
-    "    wcf:             Adds bindings for WCF to generated classes.\n" 
-    "    serial:          Add serialization support to generated classes.\n" 
-    "    nullable:        Use nullable types for properties.\n" 
-    "    hashcode:        Generate a hashcode and equals implementation for classes.\n" 
-    "    union:           Use new union typing, which includes a static read function for union " 
-    "types.\n") 
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ * Contains some contributions under the Thrift Software License.
+ * Please see doc/old-thrift-license.txt in the Thrift distribution for
+ * details.
+ */
+
+#include <cassert>
+
+#include <string>
+#include <fstream>
+#include <iostream>
+#include <vector>
+#include <cctype>
+
+#include <stdlib.h>
+#include <sys/stat.h>
+#include <sstream>
+
+#include "thrift/platform.h"
+#include "thrift/generate/t_oop_generator.h"
+
+using std::map;
+using std::ostream;
+using std::ostringstream;
+using std::string;
+using std::stringstream;
+using std::vector;
+
+static const string endl = "\n"; // avoid ostream << std::endl flushes
+
+struct member_mapping_scope {
+  void* scope_member;
+  std::map<std::string, std::string> mapping_table;
+};
+
+class t_csharp_generator : public t_oop_generator {
+public:
+  t_csharp_generator(t_program* program,
+                     const std::map<std::string, std::string>& parsed_options,
+                     const std::string& option_string)
+    : t_oop_generator(program) {
+    (void)option_string;
+
+    std::map<std::string, std::string>::const_iterator iter;
+
+    async_ = false;
+    nullable_ = false;
+    hashcode_ = false;
+    union_ = false;
+    serialize_ = false;
+    wcf_ = false;
+    wcf_namespace_.clear();
+    for( iter = parsed_options.begin(); iter != parsed_options.end(); ++iter) {
+      if( iter->first.compare("async") == 0) {
+        async_ = true;
+      } else if( iter->first.compare("nullable") == 0) {
+        nullable_ = true;
+      } else if( iter->first.compare("hashcode") == 0) {
+        hashcode_ = true;
+      } else if( iter->first.compare("union") == 0) {
+        union_ = true;
+      } else if( iter->first.compare("serial") == 0) {
+        serialize_ = true;
+        wcf_namespace_ = iter->second; // since there can be only one namespace
+      } else if( iter->first.compare("wcf") == 0) {
+        wcf_ = true;
+        wcf_namespace_ = iter->second;
+      } else {
+        throw "unknown option csharp:" + iter->first;
+      }
+    }
+
+    out_dir_base_ = "gen-csharp";
+  }
+  void init_generator();
+  void close_generator();
+
+  void generate_consts(std::vector<t_const*> consts);
+
+  void generate_typedef(t_typedef* ttypedef);
+  void generate_enum(t_enum* tenum);
+  void generate_struct(t_struct* tstruct);
+  void generate_union(t_struct* tunion);
+  void generate_xception(t_struct* txception);
+  void generate_service(t_service* tservice);
+  void generate_property(ostream& out, t_field* tfield, bool isPublic, bool generateIsset);
+  void generate_csharp_property(ostream& out,
+                                t_field* tfield,
+                                bool isPublic,
+                                bool includeIsset = true,
+                                std::string fieldPrefix = "");
+  bool print_const_value(std::ostream& out,
+                         std::string name,
+                         t_type* type,
+                         t_const_value* value,
+                         bool in_static,
+                         bool defval = false,
+                         bool needtype = false);
+  std::string render_const_value(std::ostream& out,
+                                 std::string name,
+                                 t_type* type,
+                                 t_const_value* value);
+  void print_const_constructor(std::ostream& out, std::vector<t_const*> consts);
+  void print_const_def_value(std::ostream& out,
+                             std::string name,
+                             t_type* type,
+                             t_const_value* value);
+
+  void generate_csharp_struct(t_struct* tstruct, bool is_exception);
+  void generate_csharp_union(t_struct* tunion);
+  void generate_csharp_struct_definition(std::ostream& out,
+                                         t_struct* tstruct,
+                                         bool is_xception = false,
+                                         bool in_class = false,
+                                         bool is_result = false);
+  void generate_csharp_union_definition(std::ostream& out, t_struct* tunion);
+  void generate_csharp_union_class(std::ostream& out, t_struct* tunion, t_field* tfield);
+  void generate_csharp_wcffault(std::ostream& out, t_struct* tstruct);
+  void generate_csharp_struct_reader(std::ostream& out, t_struct* tstruct);
+  void generate_csharp_struct_result_writer(std::ostream& out, t_struct* tstruct);
+  void generate_csharp_struct_writer(std::ostream& out, t_struct* tstruct);
+  void generate_csharp_struct_tostring(std::ostream& out, t_struct* tstruct);
+  void generate_csharp_struct_equals(std::ostream& out, t_struct* tstruct);
+  void generate_csharp_struct_hashcode(std::ostream& out, t_struct* tstruct);
+  void generate_csharp_union_reader(std::ostream& out, t_struct* tunion);
+
+  void generate_function_helpers(t_function* tfunction);
+  void generate_service_interface(t_service* tservice);
+  void generate_separate_service_interfaces(t_service* tservice);
+  void generate_sync_service_interface(t_service* tservice);
+  void generate_async_service_interface(t_service* tservice);
+  void generate_combined_service_interface(t_service* tservice);
+  void generate_silverlight_async_methods(t_service* tservice);
+  void generate_service_helpers(t_service* tservice);
+  void generate_service_client(t_service* tservice);
+  void generate_service_server(t_service* tservice);
+  void generate_service_server_sync(t_service* tservice);
+  void generate_service_server_async(t_service* tservice);
+  void generate_process_function(t_service* tservice, t_function* function);
+  void generate_process_function_async(t_service* tservice, t_function* function);
+
+  void generate_deserialize_field(std::ostream& out,
+                                  t_field* tfield,
+                                  std::string prefix = "",
+                                  bool is_propertyless = false);
+  void generate_deserialize_struct(std::ostream& out, t_struct* tstruct, std::string prefix = "");
+  void generate_deserialize_container(std::ostream& out, t_type* ttype, std::string prefix = "");
+  void generate_deserialize_set_element(std::ostream& out, t_set* tset, std::string prefix = "");
+  void generate_deserialize_map_element(std::ostream& out, t_map* tmap, std::string prefix = "");
+  void generate_deserialize_list_element(std::ostream& out, t_list* list, std::string prefix = "");
+  void generate_serialize_field(std::ostream& out,
+                                t_field* tfield,
+                                std::string prefix = "",
+                                bool is_element = false,
+                                bool is_propertyless = false);
+  void generate_serialize_struct(std::ostream& out, t_struct* tstruct, std::string prefix = "");
+  void generate_serialize_container(std::ostream& out, t_type* ttype, std::string prefix = "");
+  void generate_serialize_map_element(std::ostream& out,
+                                      t_map* tmap,
+                                      std::string iter,
+                                      std::string map);
+  void generate_serialize_set_element(std::ostream& out, t_set* tmap, std::string iter);
+  void generate_serialize_list_element(std::ostream& out, t_list* tlist, std::string iter);
+
+  void generate_csharp_doc(std::ostream& out, t_field* field);
+  void generate_csharp_doc(std::ostream& out, t_doc* tdoc);
+  void generate_csharp_doc(std::ostream& out, t_function* tdoc);
+  void generate_csharp_docstring_comment(std::ostream& out, string contents);
+
+  void start_csharp_namespace(std::ostream& out);
+  void end_csharp_namespace(std::ostream& out);
+
+  std::string csharp_type_usings();
+  std::string csharp_thrift_usings();
+
+  std::string type_name(t_type* ttype,
+                        bool in_countainer = false,
+                        bool in_init = false,
+                        bool in_param = false,
+                        bool is_required = false);
+  std::string base_type_name(t_base_type* tbase,
+                             bool in_container = false,
+                             bool in_param = false,
+                             bool is_required = false);
+  std::string declare_field(t_field* tfield, bool init = false, std::string prefix = "");
+  std::string function_signature_async_begin(t_function* tfunction, std::string prefix = "");
+  std::string function_signature_async_end(t_function* tfunction, std::string prefix = "");
+  std::string function_signature_async(t_function* tfunction, std::string prefix = "");
+  std::string function_signature(t_function* tfunction, std::string prefix = "");
+  std::string argument_list(t_struct* tstruct);
+  std::string type_to_enum(t_type* ttype);
+  std::string prop_name(t_field* tfield, bool suppress_mapping = false);
+  std::string get_enum_class_name(t_type* type);
+
+  bool field_has_default(t_field* tfield) { return tfield->get_value() != NULL; }
+
+  bool field_is_required(t_field* tfield) { return tfield->get_req() == t_field::T_REQUIRED; }
+
+  bool type_can_be_null(t_type* ttype) {
+    while (ttype->is_typedef()) {
+      ttype = ((t_typedef*)ttype)->get_type();
+    }
+
+    return ttype->is_container() || ttype->is_struct() || ttype->is_xception()
+           || ttype->is_string();
+  }
+
+private:
+  std::string namespace_name_;
+  ofstream_with_content_based_conditional_update f_service_;
+  std::string namespace_dir_;
+  bool async_;
+  bool nullable_;
+  bool union_;
+  bool hashcode_;
+  bool serialize_;
+  bool wcf_;
+  std::string wcf_namespace_;
+
+  std::map<std::string, int> csharp_keywords;
+  std::vector<member_mapping_scope>  member_mapping_scopes;
+
+  void init_keywords();
+  std::string normalize_name(std::string name);
+  std::string make_valid_csharp_identifier(std::string const& fromName);
+  void prepare_member_name_mapping(t_struct* tstruct);
+  void prepare_member_name_mapping(void* scope,
+                                   const vector<t_field*>& members,
+                                   const string& structname);
+  void cleanup_member_name_mapping(void* scope);
+  string get_mapped_member_name(string oldname);
+};
+
+void t_csharp_generator::init_generator() {
+  MKDIR(get_out_dir().c_str());
+  namespace_name_ = program_->get_namespace("csharp");
+
+  string dir = namespace_name_;
+  string subdir = get_out_dir().c_str();
+  string::size_type loc;
+
+  while ((loc = dir.find(".")) != string::npos) {
+    subdir = subdir + "/" + dir.substr(0, loc);
+    MKDIR(subdir.c_str());
+    dir = dir.substr(loc + 1);
+  }
+  if (dir.size() > 0) {
+    subdir = subdir + "/" + dir;
+    MKDIR(subdir.c_str());
+  }
+
+  namespace_dir_ = subdir;
+  init_keywords();
+
+  while( ! member_mapping_scopes.empty()) {
+    cleanup_member_name_mapping( member_mapping_scopes.back().scope_member);
+  }
+
+  pverbose("C# options:\n");
+  pverbose("- async ...... %s\n", (async_ ? "ON" : "off"));
+  pverbose("- nullable ... %s\n", (nullable_ ? "ON" : "off"));
+  pverbose("- union ...... %s\n", (union_ ? "ON" : "off"));
+  pverbose("- hashcode ... %s\n", (hashcode_ ? "ON" : "off"));
+  pverbose("- serialize .. %s\n", (serialize_ ? "ON" : "off"));
+  pverbose("- wcf ........ %s\n", (wcf_ ? "ON" : "off"));
+}
+
+std::string t_csharp_generator::normalize_name(std::string name) {
+  string tmp(name);
+  std::transform(tmp.begin(), tmp.end(), tmp.begin(), static_cast<int (*)(int)>(std::tolower));
+
+  // un-conflict keywords by prefixing with "@"
+  if (csharp_keywords.find(tmp) != csharp_keywords.end()) {
+    return "@" + name;
+  }
+
+  // no changes necessary
+  return name;
+}
+
+void t_csharp_generator::init_keywords() {
+  csharp_keywords.clear();
+
+  // C# keywords
+  csharp_keywords["abstract"] = 1;
+  csharp_keywords["as"] = 1;
+  csharp_keywords["base"] = 1;
+  csharp_keywords["bool"] = 1;
+  csharp_keywords["break"] = 1;
+  csharp_keywords["byte"] = 1;
+  csharp_keywords["case"] = 1;
+  csharp_keywords["catch"] = 1;
+  csharp_keywords["char"] = 1;
+  csharp_keywords["checked"] = 1;
+  csharp_keywords["class"] = 1;
+  csharp_keywords["const"] = 1;
+  csharp_keywords["continue"] = 1;
+  csharp_keywords["decimal"] = 1;
+  csharp_keywords["default"] = 1;
+  csharp_keywords["delegate"] = 1;
+  csharp_keywords["do"] = 1;
+  csharp_keywords["double"] = 1;
+  csharp_keywords["else"] = 1;
+  csharp_keywords["enum"] = 1;
+  csharp_keywords["event"] = 1;
+  csharp_keywords["explicit"] = 1;
+  csharp_keywords["extern"] = 1;
+  csharp_keywords["false"] = 1;
+  csharp_keywords["finally"] = 1;
+  csharp_keywords["fixed"] = 1;
+  csharp_keywords["float"] = 1;
+  csharp_keywords["for"] = 1;
+  csharp_keywords["foreach"] = 1;
+  csharp_keywords["goto"] = 1;
+  csharp_keywords["if"] = 1;
+  csharp_keywords["implicit"] = 1;
+  csharp_keywords["in"] = 1;
+  csharp_keywords["int"] = 1;
+  csharp_keywords["interface"] = 1;
+  csharp_keywords["internal"] = 1;
+  csharp_keywords["is"] = 1;
+  csharp_keywords["lock"] = 1;
+  csharp_keywords["long"] = 1;
+  csharp_keywords["namespace"] = 1;
+  csharp_keywords["new"] = 1;
+  csharp_keywords["null"] = 1;
+  csharp_keywords["object"] = 1;
+  csharp_keywords["operator"] = 1;
+  csharp_keywords["out"] = 1;
+  csharp_keywords["override"] = 1;
+  csharp_keywords["params"] = 1;
+  csharp_keywords["private"] = 1;
+  csharp_keywords["protected"] = 1;
+  csharp_keywords["public"] = 1;
+  csharp_keywords["readonly"] = 1;
+  csharp_keywords["ref"] = 1;
+  csharp_keywords["return"] = 1;
+  csharp_keywords["sbyte"] = 1;
+  csharp_keywords["sealed"] = 1;
+  csharp_keywords["short"] = 1;
+  csharp_keywords["sizeof"] = 1;
+  csharp_keywords["stackalloc"] = 1;
+  csharp_keywords["static"] = 1;
+  csharp_keywords["string"] = 1;
+  csharp_keywords["struct"] = 1;
+  csharp_keywords["switch"] = 1;
+  csharp_keywords["this"] = 1;
+  csharp_keywords["throw"] = 1;
+  csharp_keywords["true"] = 1;
+  csharp_keywords["try"] = 1;
+  csharp_keywords["typeof"] = 1;
+  csharp_keywords["uint"] = 1;
+  csharp_keywords["ulong"] = 1;
+  csharp_keywords["unchecked"] = 1;
+  csharp_keywords["unsafe"] = 1;
+  csharp_keywords["ushort"] = 1;
+  csharp_keywords["using"] = 1;
+  csharp_keywords["virtual"] = 1;
+  csharp_keywords["void"] = 1;
+  csharp_keywords["volatile"] = 1;
+  csharp_keywords["while"] = 1;
+
+  // C# contextual keywords
+  csharp_keywords["add"] = 1;
+  csharp_keywords["alias"] = 1;
+  csharp_keywords["ascending"] = 1;
+  csharp_keywords["async"] = 1;
+  csharp_keywords["await"] = 1;
+  csharp_keywords["descending"] = 1;
+  csharp_keywords["dynamic"] = 1;
+  csharp_keywords["from"] = 1;
+  csharp_keywords["get"] = 1;
+  csharp_keywords["global"] = 1;
+  csharp_keywords["group"] = 1;
+  csharp_keywords["into"] = 1;
+  csharp_keywords["join"] = 1;
+  csharp_keywords["let"] = 1;
+  csharp_keywords["orderby"] = 1;
+  csharp_keywords["partial"] = 1;
+  csharp_keywords["remove"] = 1;
+  csharp_keywords["select"] = 1;
+  csharp_keywords["set"] = 1;
+  csharp_keywords["value"] = 1;
+  csharp_keywords["var"] = 1;
+  csharp_keywords["where"] = 1;
+  csharp_keywords["yield"] = 1;
+}
+
+void t_csharp_generator::start_csharp_namespace(ostream& out) {
+  if (!namespace_name_.empty()) {
+    out << "namespace " << namespace_name_ << "\n";
+    scope_up(out);
+  }
+}
+
+void t_csharp_generator::end_csharp_namespace(ostream& out) {
+  if (!namespace_name_.empty()) {
+    scope_down(out);
+  }
+}
+
+string t_csharp_generator::csharp_type_usings() {
+  return string() + "using System;\n" + "using System.Collections;\n"
+         + "using System.Collections.Generic;\n" + "using System.Text;\n" + "using System.IO;\n"
+         + ((async_) ? "using System.Threading.Tasks;\n" : "") + "using Thrift;\n"
+         + "using Thrift.Collections;\n" + ((serialize_ || wcf_) ? "#if !SILVERLIGHT\n" : "")
+         + ((serialize_ || wcf_) ? "using System.Xml.Serialization;\n" : "")
+         + ((serialize_ || wcf_) ? "#endif\n" : "") + (wcf_ ? "//using System.ServiceModel;\n" : "")
+         + "using System.Runtime.Serialization;\n";
+}
+
+string t_csharp_generator::csharp_thrift_usings() {
+  return string() + "using Thrift.Protocol;\n" + "using Thrift.Transport;\n";
+}
+
+void t_csharp_generator::close_generator() {
+}
+void t_csharp_generator::generate_typedef(t_typedef* ttypedef) {
+  (void)ttypedef;
+}
+
+void t_csharp_generator::generate_enum(t_enum* tenum) {
+  string f_enum_name = namespace_dir_ + "/" + (tenum->get_name()) + ".cs";
+  ofstream_with_content_based_conditional_update f_enum;
+  f_enum.open(f_enum_name.c_str());
+
+  f_enum << autogen_comment() << endl;
+
+  start_csharp_namespace(f_enum);
+
+  generate_csharp_doc(f_enum, tenum);
+
+  indent(f_enum) << "public enum " << tenum->get_name() << "\n";
+  scope_up(f_enum);
+
+  vector<t_enum_value*> constants = tenum->get_constants();
+  vector<t_enum_value*>::iterator c_iter;
+  for (c_iter = constants.begin(); c_iter != constants.end(); ++c_iter) {
+    generate_csharp_doc(f_enum, *c_iter);
+
+    int value = (*c_iter)->get_value();
+    indent(f_enum) << (*c_iter)->get_name() << " = " << value << "," << endl;
+  }
+
+  scope_down(f_enum);
+
+  end_csharp_namespace(f_enum);
+
+  f_enum.close();
+}
+
+void t_csharp_generator::generate_consts(std::vector<t_const*> consts) {
+  if (consts.empty()) {
+    return;
+  }
+  string f_consts_name = namespace_dir_ + '/' + program_name_ + ".Constants.cs";
+  ofstream_with_content_based_conditional_update f_consts;
+  f_consts.open(f_consts_name.c_str());
+
+  f_consts << autogen_comment() << csharp_type_usings() << endl;
+
+  start_csharp_namespace(f_consts);
+
+  indent(f_consts) << "public static class " << make_valid_csharp_identifier(program_name_)
+                   << "Constants" << endl;
+  scope_up(f_consts);
+
+  vector<t_const*>::iterator c_iter;
+  bool need_static_constructor = false;
+  for (c_iter = consts.begin(); c_iter != consts.end(); ++c_iter) {
+    generate_csharp_doc(f_consts, (*c_iter));
+    if (print_const_value(f_consts,
+                          (*c_iter)->get_name(),
+                          (*c_iter)->get_type(),
+                          (*c_iter)->get_value(),
+                          false)) {
+      need_static_constructor = true;
+    }
+  }
+
+  if (need_static_constructor) {
+    print_const_constructor(f_consts, consts);
+  }
+
+  scope_down(f_consts);
+  end_csharp_namespace(f_consts);
+  f_consts.close();
+}
+
+void t_csharp_generator::print_const_def_value(std::ostream& out,
+                                               string name,
+                                               t_type* type,
+                                               t_const_value* value) {
+  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*, t_const_value::value_compare>& val = value->get_map();
+    map<t_const_value*, t_const_value*, t_const_value::value_compare>::const_iterator v_iter;
+    prepare_member_name_mapping((t_struct*)type);
+    for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
+      t_field* field = NULL;
+      for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+        if ((*f_iter)->get_name() == v_iter->first->get_string()) {
+          field = (*f_iter);
+        }
+      }
+      if (field == NULL) {
+        throw "type error: " + type->get_name() + " has no field " + v_iter->first->get_string();
+      }
+      t_type* field_type = field->get_type();
+      string val = render_const_value(out, name, field_type, v_iter->second);
+      indent(out) << name << "." << prop_name(field) << " = " << val << ";" << endl;
+    }
+    cleanup_member_name_mapping((t_struct*)type);
+  } else if (type->is_map()) {
+    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*, t_const_value::value_compare>& val = value->get_map();
+    map<t_const_value*, t_const_value*, t_const_value::value_compare>::const_iterator v_iter;
+    for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
+      string key = render_const_value(out, name, ktype, v_iter->first);
+      string val = render_const_value(out, name, vtype, v_iter->second);
+      indent(out) << name << "[" << key << "]"
+                  << " = " << val << ";" << endl;
+    }
+  } else if (type->is_list() || type->is_set()) {
+    t_type* etype;
+    if (type->is_list()) {
+      etype = ((t_list*)type)->get_elem_type();
+    } else {
+      etype = ((t_set*)type)->get_elem_type();
+    }
+
+    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) {
+      string val = render_const_value(out, name, etype, *v_iter);
+      indent(out) << name << ".Add(" << val << ");" << endl;
+    }
+  }
+}
+
+void t_csharp_generator::print_const_constructor(std::ostream& out, std::vector<t_const*> consts) {
+  indent(out) << "static " << make_valid_csharp_identifier(program_name_).c_str() << "Constants()"
+              << endl;
+  scope_up(out);
+  vector<t_const*>::iterator c_iter;
+  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_const_value* value = (*c_iter)->get_value();
+
+    print_const_def_value(out, name, type, value);
+  }
+  scope_down(out);
+}
+
+// it seems like all that methods that call this are using in_static to be the opposite of what it
+// would imply
+bool t_csharp_generator::print_const_value(std::ostream& out,
+                                           string name,
+                                           t_type* type,
+                                           t_const_value* value,
+                                           bool in_static,
+                                           bool defval,
+                                           bool needtype) {
+  indent(out);
+  bool need_static_construction = !in_static;
+  while (type->is_typedef()) {
+    type = ((t_typedef*)type)->get_type();
+  }
+
+  if (!defval || needtype) {
+    out << (in_static ? "" : type->is_base_type() ? "public const " : "public static ")
+        << type_name(type) << " ";
+  }
+  if (type->is_base_type()) {
+    string v2 = render_const_value(out, name, type, value);
+    out << name << " = " << v2 << ";" << endl;
+    need_static_construction = false;
+  } else if (type->is_enum()) {
+    out << name << " = " << type_name(type, false, true) << "." << value->get_identifier_name()
+        << ";" << endl;
+    need_static_construction = false;
+  } else if (type->is_struct() || type->is_xception()) {
+    out << name << " = new " << type_name(type) << "();" << endl;
+  } else if (type->is_map()) {
+    out << name << " = new " << type_name(type, true, true) << "();" << endl;
+  } else if (type->is_list() || type->is_set()) {
+    out << name << " = new " << type_name(type) << "();" << endl;
+  }
+
+  if (defval && !type->is_base_type() && !type->is_enum()) {
+    print_const_def_value(out, name, type, value);
+  }
+
+  return need_static_construction;
+}
+
+std::string t_csharp_generator::render_const_value(ostream& out,
+                                                   string name,
+                                                   t_type* type,
+                                                   t_const_value* value) {
+  (void)name;
+  std::ostringstream render;
+
+  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:
+      render << '"' << get_escaped_string(value) << '"';
+      break;
+    case t_base_type::TYPE_BOOL:
+      render << ((value->get_integer() > 0) ? "true" : "false");
+      break;
+    case t_base_type::TYPE_I8:
+    case t_base_type::TYPE_I16:
+    case t_base_type::TYPE_I32:
+    case t_base_type::TYPE_I64:
+      render << value->get_integer();
+      break;
+    case t_base_type::TYPE_DOUBLE:
+      if (value->get_type() == t_const_value::CV_INTEGER) {
+        render << value->get_integer();
+      } else {
+        render << value->get_double();
+      }
+      break;
+    default:
+      throw "compiler error: no const of base type " + t_base_type::t_base_name(tbase);
+    }
+  } else if (type->is_enum()) {
+    render << type->get_name() << "." << value->get_identifier_name();
+  } else {
+    string t = tmp("tmp");
+    print_const_value(out, t, type, value, true, true, true);
+    render << t;
+  }
+
+  return render.str();
+}
+
+void t_csharp_generator::generate_struct(t_struct* tstruct) {
+  if (union_ && tstruct->is_union()) {
+    generate_csharp_union(tstruct);
+  } else {
+    generate_csharp_struct(tstruct, false);
+  }
+}
+
+void t_csharp_generator::generate_xception(t_struct* txception) {
+  generate_csharp_struct(txception, true);
+}
+
+void t_csharp_generator::generate_csharp_struct(t_struct* tstruct, bool is_exception) {
+  string f_struct_name = namespace_dir_ + "/" + (tstruct->get_name()) + ".cs";
+  ofstream_with_content_based_conditional_update f_struct;
+
+  f_struct.open(f_struct_name.c_str());
+
+  f_struct << autogen_comment() << csharp_type_usings() << csharp_thrift_usings() << endl;
+
+  generate_csharp_struct_definition(f_struct, tstruct, is_exception);
+
+  f_struct.close();
+}
+
+void t_csharp_generator::generate_csharp_struct_definition(ostream& out,
+                                                           t_struct* tstruct,
+                                                           bool is_exception,
+                                                           bool in_class,
+                                                           bool is_result) {
+
+  if (!in_class) {
+    start_csharp_namespace(out);
+  }
+
+  out << endl;
+
+  generate_csharp_doc(out, tstruct);
+  prepare_member_name_mapping(tstruct);
+
+  indent(out) << "#if !SILVERLIGHT" << endl;
+  indent(out) << "[Serializable]" << endl;
+  indent(out) << "#endif" << endl;
+  if ((serialize_ || wcf_) && !is_exception) {
+    indent(out) << "[DataContract(Namespace=\"" << wcf_namespace_ << "\")]"
+                << endl; // do not make exception classes directly WCF serializable, we provide a
+                         // separate "fault" for that
+  }
+  bool is_final = (tstruct->annotations_.find("final") != tstruct->annotations_.end());
+
+  indent(out) << "public " << (is_final ? "sealed " : "") << "partial class "
+              << normalize_name(tstruct->get_name()) << " : ";
+
+  if (is_exception) {
+    out << "TException, ";
+  }
+  out << "TBase";
+
+  out << endl;
+
+  scope_up(out);
+
+  const vector<t_field*>& members = tstruct->get_members();
+  vector<t_field*>::const_iterator m_iter;
+
+  // make private members with public Properties
+  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
+    // if the field is requied, then we use auto-properties
+    if (!field_is_required((*m_iter)) && (!nullable_ || field_has_default((*m_iter)))) {
+      indent(out) << "private " << declare_field(*m_iter, false, "_") << endl;
+    }
+  }
+  out << endl;
+
+  bool has_non_required_fields = false;
+  bool has_non_required_default_value_fields = false;
+  bool has_required_fields = false;
+  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
+    generate_csharp_doc(out, *m_iter);
+    generate_property(out, *m_iter, true, true);
+    bool is_required = field_is_required((*m_iter));
+    bool has_default = field_has_default((*m_iter));
+    if (is_required) {
+      has_required_fields = true;
+    } else {
+      if (has_default) {
+        has_non_required_default_value_fields = true;
+      }
+      has_non_required_fields = true;
+    }
+  }
+
+  bool generate_isset = (nullable_ && has_non_required_default_value_fields)
+                        || (!nullable_ && has_non_required_fields);
+  if (generate_isset) {
+    out << endl;
+    if (serialize_ || wcf_) {
+      out << indent() << "[XmlIgnore] // XmlSerializer" << endl << indent()
+          << "[DataMember(Order = 1)]  // XmlObjectSerializer, DataContractJsonSerializer, etc."
+          << endl;
+    }
+    out << indent() << "public Isset __isset;" << endl << indent() << "#if !SILVERLIGHT" << endl
+        << indent() << "[Serializable]" << endl << indent() << "#endif" << endl;
+    if (serialize_ || wcf_) {
+      indent(out) << "[DataContract]" << endl;
+    }
+    indent(out) << "public struct Isset {" << endl;
+    indent_up();
+    for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
+      bool is_required = field_is_required((*m_iter));
+      bool has_default = field_has_default((*m_iter));
+      // if it is required, don't need Isset for that variable
+      // if it is not required, if it has a default value, we need to generate Isset
+      // if we are not nullable, then we generate Isset
+      if (!is_required && (!nullable_ || has_default)) {
+        if (serialize_ || wcf_) {
+          indent(out) << "[DataMember]" << endl;
+        }
+        indent(out) << "public bool " << normalize_name((*m_iter)->get_name()) << ";" << endl;
+      }
+    }
+
+    indent_down();
+    indent(out) << "}" << endl << endl;
+
+    if (generate_isset && (serialize_ || wcf_)) {
+      indent(out) << "#region XmlSerializer support" << endl << endl;
+
+      for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
+        bool is_required = field_is_required((*m_iter));
+        bool has_default = field_has_default((*m_iter));
+        // if it is required, don't need Isset for that variable
+        // if it is not required, if it has a default value, we need to generate Isset
+        // if we are not nullable, then we generate Isset
+        if (!is_required && (!nullable_ || has_default)) {
+          indent(out) << "public bool ShouldSerialize" << prop_name((*m_iter)) << "()" << endl;
+          indent(out) << "{" << endl;
+          indent_up();
+          indent(out) << "return __isset." << normalize_name((*m_iter)->get_name()) << ";" << endl;
+          indent_down();
+          indent(out) << "}" << endl << endl;
+        }
+      }
+
+      indent(out) << "#endregion XmlSerializer support" << endl << endl;
+    }
+  }
+
+  // We always want a default, no argument constructor for Reading
+  indent(out) << "public " << normalize_name(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 ((*m_iter)->get_value() != NULL) {
+      if (field_is_required((*m_iter))) {
+        print_const_value(out, "this." + prop_name(*m_iter), t, (*m_iter)->get_value(), true, true);
+      } else {
+        print_const_value(out,
+                          "this._" + (*m_iter)->get_name(),
+                          t,
+                          (*m_iter)->get_value(),
+                          true,
+                          true);
+        // Optionals with defaults are marked set
+        indent(out) << "this.__isset." << normalize_name((*m_iter)->get_name()) << " = true;"
+                    << endl;
+      }
+    }
+  }
+  indent_down();
+  indent(out) << "}" << endl << endl;
+
+  if (has_required_fields) {
+    indent(out) << "public " << tstruct->get_name() << "(";
+    bool first = true;
+    for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
+      if (field_is_required((*m_iter))) {
+        if (first) {
+          first = false;
+        } else {
+          out << ", ";
+        }
+        out << type_name((*m_iter)->get_type()) << " " << normalize_name((*m_iter)->get_name());
+      }
+    }
+    out << ") : this() {" << endl;
+    indent_up();
+
+    for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
+      if (field_is_required((*m_iter))) {
+        indent(out) << "this." << prop_name((*m_iter)) << " = " << normalize_name((*m_iter)->get_name()) << ";"
+                    << endl;
+      }
+    }
+
+    indent_down();
+    indent(out) << "}" << endl << endl;
+  }
+
+  generate_csharp_struct_reader(out, tstruct);
+  if (is_result) {
+    generate_csharp_struct_result_writer(out, tstruct);
+  } else {
+    generate_csharp_struct_writer(out, tstruct);
+  }
+  if (hashcode_) {
+    generate_csharp_struct_equals(out, tstruct);
+    generate_csharp_struct_hashcode(out, tstruct);
+  }
+  generate_csharp_struct_tostring(out, tstruct);
+  scope_down(out);
+  out << endl;
+
+  // generate a corresponding WCF fault to wrap the exception
+  if ((serialize_ || wcf_) && is_exception) {
+    generate_csharp_wcffault(out, tstruct);
+  }
+
+  cleanup_member_name_mapping(tstruct);
+  if (!in_class) {
+    end_csharp_namespace(out);
+  }
+}
+
+void t_csharp_generator::generate_csharp_wcffault(ostream& out, t_struct* tstruct) {
+  out << endl;
+  indent(out) << "#if !SILVERLIGHT" << endl;
+  indent(out) << "[Serializable]" << endl;
+  indent(out) << "#endif" << endl;
+  indent(out) << "[DataContract]" << endl;
+  bool is_final = (tstruct->annotations_.find("final") != tstruct->annotations_.end());
+
+  indent(out) << "public " << (is_final ? "sealed " : "") << "partial class " << tstruct->get_name()
+              << "Fault" << endl;
+
+  scope_up(out);
+
+  const vector<t_field*>& members = tstruct->get_members();
+  vector<t_field*>::const_iterator m_iter;
+
+  // make private members with public Properties
+  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
+    indent(out) << "private " << declare_field(*m_iter, false, "_") << endl;
+  }
+  out << endl;
+
+  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
+    generate_property(out, *m_iter, true, false);
+  }
+
+  scope_down(out);
+  out << endl;
+}
+
+void t_csharp_generator::generate_csharp_struct_reader(ostream& out, t_struct* tstruct) {
+  indent(out) << "public void Read (TProtocol iprot)" << endl;
+  scope_up(out);
+
+  out << indent() << "iprot.IncrementRecursionDepth();" << endl;
+  out << indent() << "try" << endl;
+  scope_up(out);
+
+  const vector<t_field*>& fields = tstruct->get_members();
+  vector<t_field*>::const_iterator f_iter;
+
+  // Required variables aren't in __isset, so we need tmp vars to check them
+  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+    if (field_is_required((*f_iter))) {
+      indent(out) << "bool isset_" << (*f_iter)->get_name() << " = false;" << endl;
+    }
+  }
+
+  indent(out) << "TField field;" << endl << indent() << "iprot.ReadStructBegin();" << endl;
+
+  indent(out) << "while (true)" << endl;
+  scope_up(out);
+
+  indent(out) << "field = iprot.ReadFieldBegin();" << endl;
+
+  indent(out) << "if (field.Type == TType.Stop) { " << endl;
+  indent_up();
+  indent(out) << "break;" << endl;
+  indent_down();
+  indent(out) << "}" << endl;
+
+  indent(out) << "switch (field.ID)" << endl;
+
+  scope_up(out);
+
+  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+    bool is_required = field_is_required((*f_iter));
+    indent(out) << "case " << (*f_iter)->get_key() << ":" << endl;
+    indent_up();
+    indent(out) << "if (field.Type == " << type_to_enum((*f_iter)->get_type()) << ") {" << endl;
+    indent_up();
+
+    generate_deserialize_field(out, *f_iter);
+    if (is_required) {
+      indent(out) << "isset_" << (*f_iter)->get_name() << " = true;" << endl;
+    }
+
+    indent_down();
+    out << indent() << "} else { " << endl << indent() << "  TProtocolUtil.Skip(iprot, field.Type);"
+        << endl << indent() << "}" << endl << indent() << "break;" << endl;
+    indent_down();
+  }
+
+  indent(out) << "default: " << endl;
+  indent_up();
+  indent(out) << "TProtocolUtil.Skip(iprot, field.Type);" << endl;
+  indent(out) << "break;" << endl;
+  indent_down();
+
+  scope_down(out);
+
+  indent(out) << "iprot.ReadFieldEnd();" << endl;
+
+  scope_down(out);
+
+  indent(out) << "iprot.ReadStructEnd();" << endl;
+
+  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+    if (field_is_required((*f_iter))) {
+      indent(out) << "if (!isset_" << (*f_iter)->get_name() << ")" << endl;
+      indent_up();
+      out << indent()
+          << "throw new TProtocolException(TProtocolException.INVALID_DATA, "
+          << "\"required field " << prop_name((*f_iter)) << " not set\");"
+          << endl;
+      indent_down();
+    }
+  }
+
+  scope_down(out);
+  out << indent() << "finally" << endl;
+  scope_up(out);
+  out << indent() << "iprot.DecrementRecursionDepth();" << endl;
+  scope_down(out);
+
+  indent_down();
+
+  indent(out) << "}" << endl << endl;
+}
+
+void t_csharp_generator::generate_csharp_struct_writer(ostream& out, t_struct* tstruct) {
+  out << indent() << "public void Write(TProtocol oprot) {" << endl;
+  indent_up();
+
+  out << indent() << "oprot.IncrementRecursionDepth();" << endl;
+  out << indent() << "try" << endl;
+  scope_up(out);
+
+  string name = tstruct->get_name();
+  const vector<t_field*>& fields = tstruct->get_sorted_members();
+  vector<t_field*>::const_iterator f_iter;
+
+  indent(out) << "TStruct struc = new TStruct(\"" << name << "\");" << endl;
+  indent(out) << "oprot.WriteStructBegin(struc);" << endl;
+
+  if (fields.size() > 0) {
+    indent(out) << "TField field = new TField();" << endl;
+    for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+      bool is_required = field_is_required((*f_iter));
+      bool has_default = field_has_default((*f_iter));
+      bool null_allowed = type_can_be_null((*f_iter)->get_type());
+
+      if (is_required)
+      {
+        if (null_allowed) {
+          indent(out) << "if (" << prop_name((*f_iter)) << " == null)" << endl;
+          indent_up();
+          out << indent()
+              << "throw new TProtocolException(TProtocolException.INVALID_DATA, "
+              << "\"required field " << prop_name((*f_iter)) << " not set\");"
+              << endl;
+          indent_down();
+        }
+      }
+      else
+      {
+        if (nullable_ && !has_default) {
+            indent(out) << "if (" << prop_name((*f_iter)) << " != null) {" << endl;
+        }
+        else if (null_allowed) {
+          out << indent()
+              << "if (" << prop_name((*f_iter)) << " != null && __isset."
+              << normalize_name((*f_iter)->get_name()) << ") {"
+              << endl;
+        }
+        else {
+           indent(out) << "if (__isset." << normalize_name((*f_iter)->get_name()) << ") {" << endl;
+        }
+        indent_up();
+      }
+      indent(out) << "field.Name = \"" << (*f_iter)->get_name() << "\";" << endl;
+      indent(out) << "field.Type = " << type_to_enum((*f_iter)->get_type()) << ";" << endl;
+      indent(out) << "field.ID = " << (*f_iter)->get_key() << ";" << endl;
+      indent(out) << "oprot.WriteFieldBegin(field);" << endl;
+
+      generate_serialize_field(out, *f_iter);
+
+      indent(out) << "oprot.WriteFieldEnd();" << endl;
+      if (!is_required) {
+        indent_down();
+        indent(out) << "}" << endl;
+      }
+    }
+  }
+
+  indent(out) << "oprot.WriteFieldStop();" << endl;
+  indent(out) << "oprot.WriteStructEnd();" << endl;
+
+  scope_down(out);
+  out << indent() << "finally" << endl;
+  scope_up(out);
+  out << indent() << "oprot.DecrementRecursionDepth();" << endl;
+  scope_down(out);
+
+  indent_down();
+
+  indent(out) << "}" << endl << endl;
+}
+
+void t_csharp_generator::generate_csharp_struct_result_writer(ostream& out, t_struct* tstruct) {
+  indent(out) << "public void Write(TProtocol oprot) {" << endl;
+  indent_up();
+
+  out << indent() << "oprot.IncrementRecursionDepth();" << endl;
+  out << indent() << "try" << endl;
+  scope_up(out);
+
+  string name = tstruct->get_name();
+  const vector<t_field*>& fields = tstruct->get_sorted_members();
+  vector<t_field*>::const_iterator f_iter;
+
+  indent(out) << "TStruct struc = new TStruct(\"" << name << "\");" << endl;
+  indent(out) << "oprot.WriteStructBegin(struc);" << endl;
+
+  if (fields.size() > 0) {
+    indent(out) << "TField field = new TField();" << endl;
+    bool first = true;
+    for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+      if (first) {
+        first = false;
+        out << endl << indent() << "if ";
+      } else {
+        out << " else if ";
+      }
+
+      if (nullable_) {
+        out << "(this." << prop_name((*f_iter)) << " != null) {" << endl;
+      } else {
+        out << "(this.__isset." << normalize_name((*f_iter)->get_name()) << ") {" << endl;
+      }
+      indent_up();
+
+      bool null_allowed = !nullable_ && type_can_be_null((*f_iter)->get_type());
+      if (null_allowed) {
+        indent(out) << "if (" << prop_name(*f_iter) << " != null) {" << endl;
+        indent_up();
+      }
+
+      indent(out) << "field.Name = \"" << prop_name(*f_iter) << "\";" << endl;
+      indent(out) << "field.Type = " << type_to_enum((*f_iter)->get_type()) << ";" << endl;
+      indent(out) << "field.ID = " << (*f_iter)->get_key() << ";" << endl;
+      indent(out) << "oprot.WriteFieldBegin(field);" << endl;
+
+      generate_serialize_field(out, *f_iter);
+
+      indent(out) << "oprot.WriteFieldEnd();" << endl;
+
+      if (null_allowed) {
+        indent_down();
+        indent(out) << "}" << endl;
+      }
+
+      indent_down();
+      indent(out) << "}";
+    }
+  }
+
+  out << endl << indent() << "oprot.WriteFieldStop();" << endl << indent()
+      << "oprot.WriteStructEnd();" << endl;
+
+  scope_down(out);
+  out << indent() << "finally" << endl;
+  scope_up(out);
+  out << indent() << "oprot.DecrementRecursionDepth();" << endl;
+  scope_down(out);
+
+  indent_down();
+
+  indent(out) << "}" << endl << endl;
+}
+
+void t_csharp_generator::generate_csharp_struct_tostring(ostream& out, t_struct* tstruct) {
+  indent(out) << "public override string ToString() {" << endl;
+  indent_up();
+
+  indent(out) << "StringBuilder __sb = new StringBuilder(\"" << tstruct->get_name() << "(\");"
+              << endl;
+
+  const vector<t_field*>& fields = tstruct->get_members();
+  vector<t_field*>::const_iterator f_iter;
+
+  bool useFirstFlag = false;
+  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+    if (!field_is_required((*f_iter))) {
+      indent(out) << "bool __first = true;" << endl;
+      useFirstFlag = true;
+    }
+    break;
+  }
+
+  bool had_required = false; // set to true after first required field has been processed
+
+  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+    bool is_required = field_is_required((*f_iter));
+    bool has_default = field_has_default((*f_iter));
+    if (nullable_ && !has_default && !is_required) {
+      indent(out) << "if (" << prop_name((*f_iter)) << " != null) {" << endl;
+      indent_up();
+    } else if (!is_required) {
+      bool null_allowed = type_can_be_null((*f_iter)->get_type());
+      if (null_allowed) {
+        indent(out) << "if (" << prop_name((*f_iter)) << " != null && __isset."
+                    << normalize_name((*f_iter)->get_name()) << ") {" << endl;
+        indent_up();
+      } else {
+        indent(out) << "if (__isset." << normalize_name((*f_iter)->get_name()) << ") {" << endl;
+        indent_up();
+      }
+    }
+
+    if (useFirstFlag && (!had_required)) {
+      indent(out) << "if(!__first) { __sb.Append(\", \"); }" << endl;
+      if (!is_required) {
+        indent(out) << "__first = false;" << endl;
+      }
+      indent(out) << "__sb.Append(\"" << prop_name((*f_iter)) << ": \");" << endl;
+    } else {
+      indent(out) << "__sb.Append(\", " << prop_name((*f_iter)) << ": \");" << endl;
+    }
+
+    t_type* ttype = (*f_iter)->get_type();
+    if (ttype->is_xception() || ttype->is_struct()) {
+      indent(out) << "__sb.Append(" << prop_name((*f_iter))
+                  << "== null ? \"<null>\" : " << prop_name((*f_iter)) << ".ToString());" << endl;
+    } else {
+      indent(out) << "__sb.Append(" << prop_name((*f_iter)) << ");" << endl;
+    }
+
+    if (!is_required) {
+      indent_down();
+      indent(out) << "}" << endl;
+    } else {
+      had_required = true; // now __first must be false, so we don't need to check it anymore
+    }
+  }
+
+  indent(out) << "__sb.Append(\")\");" << endl;
+  indent(out) << "return __sb.ToString();" << endl;
+
+  indent_down();
+  indent(out) << "}" << endl << endl;
+}
+
+void t_csharp_generator::generate_csharp_union(t_struct* tunion) {
+  string f_union_name = namespace_dir_ + "/" + (tunion->get_name()) + ".cs";
+  ofstream_with_content_based_conditional_update f_union;
+
+  f_union.open(f_union_name.c_str());
+
+  f_union << autogen_comment() << csharp_type_usings() << csharp_thrift_usings() << endl;
+
+  generate_csharp_union_definition(f_union, tunion);
+
+  f_union.close();
+}
+
+void t_csharp_generator::generate_csharp_union_definition(std::ostream& out, t_struct* tunion) {
+  // Let's define the class first
+  start_csharp_namespace(out);
+
+  indent(out) << "public abstract partial class " << tunion->get_name() << " : TAbstractBase {"
+              << endl;
+
+  indent_up();
+
+  indent(out) << "public abstract void Write(TProtocol protocol);" << endl;
+  indent(out) << "public readonly bool Isset;" << endl;
+  indent(out) << "public abstract object Data { get; }" << endl;
+
+  indent(out) << "protected " << tunion->get_name() << "(bool isset) {" << endl;
+  indent_up();
+  indent(out) << "Isset = isset;" << endl;
+  indent_down();
+  indent(out) << "}" << endl << endl;
+
+  indent(out) << "public class ___undefined : " << tunion->get_name() << " {" << endl;
+  indent_up();
+
+  indent(out) << "public override object Data { get { return null; } }" << endl;
+
+  indent(out) << "public ___undefined() : base(false) {}" << endl << endl;
+
+  indent(out) << "public override void Write(TProtocol protocol) {" << endl;
+  indent_up();
+  indent(out) << "throw new TProtocolException( TProtocolException.INVALID_DATA, \"Cannot persist "
+                 "an union type which is not set.\");" << endl;
+  indent_down();
+  indent(out) << "}" << endl << endl;
+
+  indent_down();
+  indent(out) << "}" << endl << endl;
+
+  const vector<t_field*>& fields = tunion->get_members();
+  vector<t_field*>::const_iterator f_iter;
+
+  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+    generate_csharp_union_class(out, tunion, (*f_iter));
+  }
+
+  generate_csharp_union_reader(out, tunion);
+
+  indent_down();
+  indent(out) << "}" << endl << endl;
+
+  end_csharp_namespace(out);
+}
+
+void t_csharp_generator::generate_csharp_union_class(std::ostream& out,
+                                                     t_struct* tunion,
+                                                     t_field* tfield) {
+  indent(out) << "public class " << tfield->get_name() << " : " << tunion->get_name() << " {"
+              << endl;
+  indent_up();
+  indent(out) << "private " << type_name(tfield->get_type()) << " _data;" << endl;
+  indent(out) << "public override object Data { get { return _data; } }" << endl;
+  indent(out) << "public " << tfield->get_name() << "(" << type_name(tfield->get_type())
+              << " data) : base(true) {" << endl;
+  indent_up();
+  indent(out) << "this._data = data;" << endl;
+  indent_down();
+  indent(out) << "}" << endl;
+  indent(out) << "public override void Write(TProtocol oprot) {" << endl;
+  indent_up();
+
+  out << indent() << "oprot.IncrementRecursionDepth();" << endl;
+  out << indent() << "try" << endl;
+  scope_up(out);
+
+  indent(out) << "TStruct struc = new TStruct(\"" << tunion->get_name() << "\");" << endl;
+  indent(out) << "oprot.WriteStructBegin(struc);" << endl;
+
+  indent(out) << "TField field = new TField();" << endl;
+  indent(out) << "field.Name = \"" << tfield->get_name() << "\";" << endl;
+  indent(out) << "field.Type = " << type_to_enum(tfield->get_type()) << ";" << endl;
+  indent(out) << "field.ID = " << tfield->get_key() << ";" << endl;
+  indent(out) << "oprot.WriteFieldBegin(field);" << endl;
+
+  generate_serialize_field(out, tfield, "_data", true, true);
+
+  indent(out) << "oprot.WriteFieldEnd();" << endl;
+  indent(out) << "oprot.WriteFieldStop();" << endl;
+  indent(out) << "oprot.WriteStructEnd();" << endl;
+  indent_down();
+
+  scope_down(out);
+  out << indent() << "finally" << endl;
+  scope_up(out);
+  out << indent() << "oprot.DecrementRecursionDepth();" << endl;
+  scope_down(out);
+
+  indent(out) << "}" << endl;
+
+  indent_down();
+  indent(out) << "}" << endl << endl;
+}
+
+void t_csharp_generator::generate_csharp_struct_equals(ostream& out, t_struct* tstruct) {
+  indent(out) << "public override bool Equals(object that) {" << endl;
+  indent_up();
+
+  indent(out) << "var other = that as " << type_name(tstruct) << ";" << endl;
+  indent(out) << "if (other == null) return false;" << endl;
+  indent(out) << "if (ReferenceEquals(this, other)) return true;" << endl;
+
+  const vector<t_field*>& fields = tstruct->get_members();
+  vector<t_field*>::const_iterator f_iter;
+
+  bool first = true;
+
+  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+    if (first) {
+      first = false;
+      indent(out) << "return ";
+      indent_up();
+    } else {
+      out << endl;
+      indent(out) << "&& ";
+    }
+    if (!field_is_required((*f_iter)) && !(nullable_ && !field_has_default((*f_iter)))) {
+      out << "((__isset." << normalize_name((*f_iter)->get_name()) << " == other.__isset."
+          << normalize_name((*f_iter)->get_name()) << ") && ((!__isset."
+          << normalize_name((*f_iter)->get_name()) << ") || (";
+    }
+    t_type* ttype = (*f_iter)->get_type();
+    if (ttype->is_container() || ttype->is_binary()) {
+      out << "TCollections.Equals(";
+    } else {
+      out << "System.Object.Equals(";
+    }
+    out << prop_name((*f_iter)) << ", other." << prop_name((*f_iter)) << ")";
+    if (!field_is_required((*f_iter)) && !(nullable_ && !field_has_default((*f_iter)))) {
+      out << ")))";
+    }
+  }
+  if (first) {
+    indent(out) << "return true;" << endl;
+  } else {
+    out << ";" << endl;
+    indent_down();
+  }
+
+  indent_down();
+  indent(out) << "}" << endl << endl;
+}
+
+void t_csharp_generator::generate_csharp_struct_hashcode(ostream& out, t_struct* tstruct) {
+  indent(out) << "public override int GetHashCode() {" << endl;
+  indent_up();
+
+  indent(out) << "int hashcode = 0;" << endl;
+  indent(out) << "unchecked {" << endl;
+  indent_up();
+
+  const vector<t_field*>& fields = tstruct->get_members();
+  vector<t_field*>::const_iterator f_iter;
+
+  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+    t_type* ttype = (*f_iter)->get_type();
+    indent(out) << "hashcode = (hashcode * 397) ^ ";
+    if (field_is_required((*f_iter))) {
+      out << "(";
+    } else if (nullable_) {
+      out << "(" << prop_name((*f_iter)) << " == null ? 0 : ";
+    } else {
+      out << "(!__isset." << normalize_name((*f_iter)->get_name()) << " ? 0 : ";
+    }
+    if (ttype->is_container()) {
+      out << "(TCollections.GetHashCode(" << prop_name((*f_iter)) << "))";
+    } else {
+      out << "(" << prop_name((*f_iter)) << ".GetHashCode())";
+    }
+    out << ");" << endl;
+  }
+
+  indent_down();
+  indent(out) << "}" << endl;
+  indent(out) << "return hashcode;" << endl;
+
+  indent_down();
+  indent(out) << "}" << endl << endl;
+}
+
+void t_csharp_generator::generate_service(t_service* tservice) {
+  string f_service_name = namespace_dir_ + "/" + service_name_ + ".cs";
+  f_service_.open(f_service_name.c_str());
+
+  f_service_ << autogen_comment() << csharp_type_usings() << csharp_thrift_usings() << endl;
+
+  start_csharp_namespace(f_service_);
+
+  indent(f_service_) << "public partial class " << normalize_name(service_name_) << " {" << endl;
+  indent_up();
+
+  generate_service_interface(tservice);
+  generate_service_client(tservice);
+  generate_service_server(tservice);
+  generate_service_helpers(tservice);
+
+  indent_down();
+
+  indent(f_service_) << "}" << endl;
+  end_csharp_namespace(f_service_);
+  f_service_.close();
+}
+
+void t_csharp_generator::generate_service_interface(t_service* tservice) {
+  generate_separate_service_interfaces(tservice);
+}
+
+void t_csharp_generator::generate_separate_service_interfaces(t_service* tservice) {
+  generate_sync_service_interface(tservice);
+
+  if (async_) {
+    generate_async_service_interface(tservice);
+  }
+
+  generate_combined_service_interface(tservice);
+}
+
+void t_csharp_generator::generate_sync_service_interface(t_service* tservice) {
+  string extends = "";
+  string extends_iface = "";
+  if (tservice->get_extends() != NULL) {
+    extends = type_name(tservice->get_extends());
+    extends_iface = " : " + extends + ".ISync";
+  }
+
+  generate_csharp_doc(f_service_, tservice);
+
+  if (wcf_) {
+    indent(f_service_) << "[ServiceContract(Namespace=\"" << wcf_namespace_ << "\")]" << endl;
+  }
+  indent(f_service_) << "public interface ISync" << extends_iface << " {" << endl;
+
+  indent_up();
+  vector<t_function*> functions = tservice->get_functions();
+  vector<t_function*>::iterator f_iter;
+  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
+    generate_csharp_doc(f_service_, *f_iter);
+
+    // if we're using WCF, add the corresponding attributes
+    if (wcf_) {
+      indent(f_service_) << "[OperationContract]" << endl;
+
+      const std::vector<t_field*>& xceptions = (*f_iter)->get_xceptions()->get_members();
+      vector<t_field*>::const_iterator x_iter;
+      for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) {
+        indent(f_service_) << "[FaultContract(typeof("
+          + type_name((*x_iter)->get_type(), false, false) + "Fault))]" << endl;
+      }
+    }
+
+    indent(f_service_) << function_signature(*f_iter) << ";" << endl;
+  }
+  indent_down();
+  f_service_ << indent() << "}" << endl << endl;
+}
+
+void t_csharp_generator::generate_async_service_interface(t_service* tservice) {
+  string extends = "";
+  string extends_iface = "";
+  if (tservice->get_extends() != NULL) {
+    extends = type_name(tservice->get_extends());
+    extends_iface = " : " + extends + ".IAsync";
+  }
+
+  generate_csharp_doc(f_service_, tservice);
+
+  if (wcf_) {
+    indent(f_service_) << "[ServiceContract(Namespace=\"" << wcf_namespace_ << "\")]" << endl;
+  }
+  indent(f_service_) << "public interface IAsync" << extends_iface << " {" << endl;
+
+  indent_up();
+  vector<t_function*> functions = tservice->get_functions();
+  vector<t_function*>::iterator f_iter;
+  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
+    generate_csharp_doc(f_service_, *f_iter);
+
+    // if we're using WCF, add the corresponding attributes
+    if (wcf_) {
+      indent(f_service_) << "[OperationContract]" << endl;
+
+      const std::vector<t_field*>& xceptions = (*f_iter)->get_xceptions()->get_members();
+      vector<t_field*>::const_iterator x_iter;
+      for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) {
+        indent(f_service_) << "[FaultContract(typeof("
+          + type_name((*x_iter)->get_type(), false, false) + "Fault))]" << endl;
+      }
+    }
+
+    indent(f_service_) << function_signature_async(*f_iter) << ";" << endl;
+  }
+  indent_down();
+  f_service_ << indent() << "}" << endl << endl;
+}
+
+void t_csharp_generator::generate_combined_service_interface(t_service* tservice) {
+  string extends_iface = " : ISync";
+
+  if (async_) {
+    extends_iface += ", IAsync";
+  }
+
+  generate_csharp_doc(f_service_, tservice);
+
+  if (wcf_) {
+    indent(f_service_) << "[ServiceContract(Namespace=\"" << wcf_namespace_ << "\")]" << endl;
+  }
+
+  indent(f_service_) << "public interface Iface" << extends_iface << " {" << endl;
+
+  indent_up();
+
+  // We need to generate extra old style async methods for silverlight. Since
+  // this isn't something you'd want to implement server-side, just put them into
+  // the main Iface interface.
+  generate_silverlight_async_methods(tservice);
+
+  indent_down();
+
+  f_service_ << indent() << "}" << endl << endl;
+}
+
+void t_csharp_generator::generate_silverlight_async_methods(t_service* tservice) {
+  vector<t_function*> functions = tservice->get_functions();
+  vector<t_function*>::iterator f_iter;
+  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
+    generate_csharp_doc(f_service_, *f_iter);
+
+    // For backwards compatibility, include the Begin_, End_ methods if we're generating
+    // with the async flag. I'm not sure this is necessary, so someone with more knowledge
+    // can maybe remove these checks if they know it's safe.
+    if (!async_) {
+      indent(f_service_) << "#if SILVERLIGHT" << endl;
+    }
+
+    indent(f_service_) << function_signature_async_begin(*f_iter, "Begin_") << ";" << endl;
+    indent(f_service_) << function_signature_async_end(*f_iter, "End_") << ";" << endl;
+
+    if (!async_) {
+      indent(f_service_) << "#endif" << endl;
+    }
+  }
+}
+
+void t_csharp_generator::generate_service_helpers(t_service* tservice) {
+  vector<t_function*> functions = tservice->get_functions();
+  vector<t_function*>::iterator f_iter;
+
+  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
+    t_struct* ts = (*f_iter)->get_arglist();
+    generate_csharp_struct_definition(f_service_, ts, false, true);
+    generate_function_helpers(*f_iter);
+  }
+}
+
+void t_csharp_generator::generate_service_client(t_service* tservice) {
+  string extends = "";
+  string extends_client = "";
+  if (tservice->get_extends() != NULL) {
+    extends = type_name(tservice->get_extends());
+    extends_client = extends + ".Client, ";
+  } else {
+    extends_client = "IDisposable, ";
+  }
+
+  generate_csharp_doc(f_service_, tservice);
+
+  indent(f_service_) << "public class Client : " << extends_client << "Iface {" << endl;
+  indent_up();
+  indent(f_service_) << "public Client(TProtocol prot) : this(prot, prot)" << endl;
+  scope_up(f_service_);
+  scope_down(f_service_);
+  f_service_ << endl;
+
+  indent(f_service_) << "public Client(TProtocol iprot, TProtocol oprot)";
+  if (!extends.empty()) {
+    f_service_ << " : base(iprot, oprot)";
+  }
+  f_service_ << endl;
+
+  scope_up(f_service_);
+  if (extends.empty()) {
+    f_service_ << indent() << "iprot_ = iprot;" << endl << indent() << "oprot_ = oprot;" << endl;
+  }
+  scope_down(f_service_);
+
+  f_service_ << endl;
+
+  if (extends.empty()) {
+    f_service_ << indent() << "protected TProtocol iprot_;" << endl << indent()
+               << "protected TProtocol oprot_;" << endl << indent() << "protected int seqid_;"
+               << endl << endl;
+
+    f_service_ << indent() << "public TProtocol InputProtocol" << endl;
+    scope_up(f_service_);
+    indent(f_service_) << "get { return iprot_; }" << endl;
+    scope_down(f_service_);
+
+    f_service_ << indent() << "public TProtocol OutputProtocol" << endl;
+    scope_up(f_service_);
+    indent(f_service_) << "get { return oprot_; }" << endl;
+    scope_down(f_service_);
+    f_service_ << endl << endl;
+
+    indent(f_service_) << "#region \" IDisposable Support \"" << endl;
+    indent(f_service_) << "private bool _IsDisposed;" << endl << endl;
+    indent(f_service_) << "// IDisposable" << endl;
+    indent(f_service_) << "public void Dispose()" << endl;
+    scope_up(f_service_);
+    indent(f_service_) << "Dispose(true);" << endl;
+    scope_down(f_service_);
+    indent(f_service_) << endl << endl;
+    indent(f_service_) << "protected virtual void Dispose(bool disposing)" << endl;
+    scope_up(f_service_);
+    indent(f_service_) << "if (!_IsDisposed)" << endl;
+    scope_up(f_service_);
+    indent(f_service_) << "if (disposing)" << endl;
+    scope_up(f_service_);
+    indent(f_service_) << "if (iprot_ != null)" << endl;
+    scope_up(f_service_);
+    indent(f_service_) << "((IDisposable)iprot_).Dispose();" << endl;
+    scope_down(f_service_);
+    indent(f_service_) << "if (oprot_ != null)" << endl;
+    scope_up(f_service_);
+    indent(f_service_) << "((IDisposable)oprot_).Dispose();" << endl;
+    scope_down(f_service_);
+    scope_down(f_service_);
+    scope_down(f_service_);
+    indent(f_service_) << "_IsDisposed = true;" << endl;
+    scope_down(f_service_);
+    indent(f_service_) << "#endregion" << endl;
+    f_service_ << endl << endl;
+  }
+
+  vector<t_function*> functions = tservice->get_functions();
+  vector<t_function*>::const_iterator f_iter;
+  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
+    string funname = (*f_iter)->get_name();
+
+    indent(f_service_) << endl;
+
+    if (!async_) {
+      indent(f_service_) << "#if SILVERLIGHT" << endl;
+    }
+    // Begin_
+    indent(f_service_) << "public " << function_signature_async_begin(*f_iter, "Begin_") << endl;
+    scope_up(f_service_);
+    indent(f_service_) << "return "
+                       << "send_" << funname << "(callback, state";
+
+    t_struct* arg_struct = (*f_iter)->get_arglist();
+    prepare_member_name_mapping(arg_struct);
+
+    const vector<t_field*>& fields = arg_struct->get_members();
+    vector<t_field*>::const_iterator fld_iter;
+    for (fld_iter = fields.begin(); fld_iter != fields.end(); ++fld_iter) {
+      f_service_ << ", ";
+      f_service_ << normalize_name((*fld_iter)->get_name());
+    }
+    f_service_ << ");" << endl;
+    scope_down(f_service_);
+    f_service_ << endl;
+
+    // End
+    indent(f_service_) << "public " << function_signature_async_end(*f_iter, "End_") << endl;
+    scope_up(f_service_);
+    indent(f_service_) << "oprot_.Transport.EndFlush(asyncResult);" << endl;
+    if (!(*f_iter)->is_oneway()) {
+      f_service_ << indent();
+      if (!(*f_iter)->get_returntype()->is_void()) {
+        f_service_ << "return ";
+      }
+      f_service_ << "recv_" << funname << "();" << endl;
+    }
+    scope_down(f_service_);
+    f_service_ << endl;
+
+    // async
+    bool first;
+    if (async_) {
+      indent(f_service_) << "public async " << function_signature_async(*f_iter, "") << endl;
+      scope_up(f_service_);
+
+      if (!(*f_iter)->get_returntype()->is_void()) {
+        indent(f_service_) << type_name((*f_iter)->get_returntype()) << " retval;" << endl;
+        indent(f_service_) << "retval = ";
+      } else {
+        indent(f_service_);
+      }
+      f_service_ << "await Task.Run(() =>" << endl;
+      scope_up(f_service_);
+      indent(f_service_);
+      if (!(*f_iter)->get_returntype()->is_void()) {
+        f_service_ << "return ";
+      }
+      f_service_ << funname << "(";
+      first = true;
+      for (fld_iter = fields.begin(); fld_iter != fields.end(); ++fld_iter) {
+        if (first) {
+          first = false;
+        } else {
+          f_service_ << ", ";
+        }
+        f_service_ << (*fld_iter)->get_name();
+      }
+      f_service_ << ");" << endl;
+      indent_down();
+      indent(f_service_) << "});" << endl;
+      if (!(*f_iter)->get_returntype()->is_void()) {
+        indent(f_service_) << "return retval;" << endl;
+      }
+      scope_down(f_service_);
+      f_service_ << endl;
+    }
+
+    if (!async_) {
+      indent(f_service_) << "#endif" << endl << endl;
+    }
+
+    // "Normal" Synchronous invoke
+    generate_csharp_doc(f_service_, *f_iter);
+    indent(f_service_) << "public " << function_signature(*f_iter) << endl;
+    scope_up(f_service_);
+
+    if (!async_) {
+      indent(f_service_) << "#if !SILVERLIGHT" << endl;
+      indent(f_service_) << "send_" << funname << "(";
+
+      first = true;
+      for (fld_iter = fields.begin(); fld_iter != fields.end(); ++fld_iter) {
+        if (first) {
+          first = false;
+        } else {
+          f_service_ << ", ";
+        }
+        f_service_ << normalize_name((*fld_iter)->get_name());
+      }
+      f_service_ << ");" << endl;
+
+      if (!(*f_iter)->is_oneway()) {
+        f_service_ << indent();
+        if (!(*f_iter)->get_returntype()->is_void()) {
+          f_service_ << "return ";
+        }
+        f_service_ << "recv_" << funname << "();" << endl;
+      }
+      f_service_ << endl;
+
+      indent(f_service_) << "#else" << endl;
+    }
+
+    // Silverlight synchronous invoke
+    indent(f_service_) << "var asyncResult = Begin_" << funname << "(null, null";
+    for (fld_iter = fields.begin(); fld_iter != fields.end(); ++fld_iter) {
+      f_service_ << ", " << normalize_name((*fld_iter)->get_name());
+    }
+    f_service_ << ");" << endl;
+
+    if (!(*f_iter)->is_oneway()) {
+      f_service_ << indent();
+      if (!(*f_iter)->get_returntype()->is_void()) {
+        f_service_ << "return ";
+      }
+      f_service_ << "End_" << funname << "(asyncResult);" << endl;
+    }
+    f_service_ << endl;
+
+    if (!async_) {
+      indent(f_service_) << "#endif" << endl;
+    }
+    scope_down(f_service_);
+
+    // Send
+    t_function send_function(g_type_void,
+                             string("send_") + (*f_iter)->get_name(),
+                             (*f_iter)->get_arglist());
+
+    string argsname = (*f_iter)->get_name() + "_args";
+
+    if (!async_) {
+      indent(f_service_) << "#if SILVERLIGHT" << endl;
+    }
+    indent(f_service_) << "public " << function_signature_async_begin(&send_function) << endl;
+    if (!async_) {
+      indent(f_service_) << "#else" << endl;
+      indent(f_service_) << "public " << function_signature(&send_function) << endl;
+      indent(f_service_) << "#endif" << endl;
+    }
+    scope_up(f_service_);
+
+    f_service_ << indent() << "oprot_.WriteMessageBegin(new TMessage(\"" << funname << "\", "
+               << ((*f_iter)->is_oneway() ? "TMessageType.Oneway" : "TMessageType.Call")
+               << ", seqid_));" << endl << indent() << argsname << " args = new " << argsname
+               << "();" << endl;
+
+    for (fld_iter = fields.begin(); fld_iter != fields.end(); ++fld_iter) {
+      f_service_ << indent() << "args." << prop_name(*fld_iter) << " = "
+                 << normalize_name((*fld_iter)->get_name()) << ";" << endl;
+    }
+
+    f_service_ << indent() << "args.Write(oprot_);" << endl << indent()
+               << "oprot_.WriteMessageEnd();" << endl;
+    ;
+
+    if (!async_) {
+      indent(f_service_) << "#if SILVERLIGHT" << endl;
+    }
+    indent(f_service_) << "return oprot_.Transport.BeginFlush(callback, state);" << endl;
+    if (!async_) {
+      indent(f_service_) << "#else" << endl;
+      indent(f_service_) << "oprot_.Transport.Flush();" << endl;
+      indent(f_service_) << "#endif" << endl;
+    }
+
+    cleanup_member_name_mapping(arg_struct);
+    scope_down(f_service_);
+    f_service_ << endl;
+
+    if (!(*f_iter)->is_oneway()) {
+      string resultname = (*f_iter)->get_name() + "_result";
+
+      t_struct noargs(program_);
+      t_function recv_function((*f_iter)->get_returntype(),
+                               string("recv_") + (*f_iter)->get_name(),
+                               &noargs,
+                               (*f_iter)->get_xceptions());
+      indent(f_service_) << "public " << function_signature(&recv_function) << endl;
+      scope_up(f_service_);
+
+      t_struct* xs = (*f_iter)->get_xceptions();
+      prepare_member_name_mapping(xs, xs->get_members(), resultname);
+
+      f_service_ << indent() << "TMessage msg = iprot_.ReadMessageBegin();" << endl << indent()
+                 << "if (msg.Type == TMessageType.Exception) {" << endl;
+      indent_up();
+      f_service_ << indent() << "TApplicationException x = TApplicationException.Read(iprot_);"
+                 << endl << indent() << "iprot_.ReadMessageEnd();" << endl << indent() << "throw x;"
+                 << endl;
+      indent_down();
+      f_service_ << indent() << "}" << endl << indent() << resultname << " result = new "
+                 << resultname << "();" << endl << indent() << "result.Read(iprot_);" << endl
+                 << indent() << "iprot_.ReadMessageEnd();" << endl;
+
+      if (!(*f_iter)->get_returntype()->is_void()) {
+        if (nullable_) {
+          if (type_can_be_null((*f_iter)->get_returntype())) {
+            f_service_ << indent() << "if (result.Success != null) {" << endl << indent()
+                       << "  return result.Success;" << endl << indent() << "}" << endl;
+          } else {
+            f_service_ << indent() << "if (result.Success.HasValue) {" << endl << indent()
+                       << "  return result.Success.Value;" << endl << indent() << "}" << endl;
+          }
+        } else {
+          f_service_ << indent() << "if (result.__isset.success) {" << endl << indent()
+                     << "  return result.Success;" << endl << indent() << "}" << endl;
+        }
+      }
+
+      const std::vector<t_field*>& xceptions = xs->get_members();
+      vector<t_field*>::const_iterator x_iter;
+      for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) {
+        if (nullable_) {
+          f_service_ << indent() << "if (result." << prop_name(*x_iter) << " != null) {" << endl
+                     << indent() << "  throw result." << prop_name(*x_iter) << ";" << endl
+                     << indent() << "}" << endl;
+        } else {
+          f_service_ << indent() << "if (result.__isset." << normalize_name((*x_iter)->get_name())
+                     << ") {" << endl << indent() << "  throw result." << prop_name(*x_iter) << ";"
+                     << endl << indent() << "}" << endl;
+        }
+      }
+
+      if ((*f_iter)->get_returntype()->is_void()) {
+        indent(f_service_) << "return;" << endl;
+      } else {
+        f_service_ << indent()
+                   << "throw new "
+                      "TApplicationException(TApplicationException.ExceptionType.MissingResult, \""
+                   << (*f_iter)->get_name() << " failed: unknown result\");" << endl;
+      }
+
+      cleanup_member_name_mapping((*f_iter)->get_xceptions());
+      scope_down(f_service_);
+      f_service_ << endl;
+    }
+  }
+
+  indent_down();
+  indent(f_service_) << "}" << endl;
+}
+
+void t_csharp_generator::generate_service_server(t_service* tservice) {
+  if (async_) {
+    generate_service_server_async(tservice);
+    generate_service_server_sync(tservice);
+  }
+  else {
+    generate_service_server_sync(tservice);
+  }
+}
+
+void t_csharp_generator::generate_service_server_sync(t_service* tservice) {
+  vector<t_function*> functions = tservice->get_functions();
+  vector<t_function*>::iterator f_iter;
+
+  string extends = "";
+  string extends_processor = "";
+  if (tservice->get_extends() != NULL) {
+    extends = type_name(tservice->get_extends());
+    extends_processor = extends + ".Processor, ";
+  }
+
+  indent(f_service_) << "public class Processor : " << extends_processor << "TProcessor {" << endl;
+  indent_up();
+
+  indent(f_service_) << "public Processor(ISync iface)";
+
+  if (!extends.empty()) {
+    f_service_ << " : base(iface)";
+  }
+  f_service_ << endl;
+  scope_up(f_service_);
+  f_service_ << indent() << "iface_ = iface;" << endl;
+
+  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
+    f_service_ << indent() << "processMap_[\"" << (*f_iter)->get_name()
+      << "\"] = " << (*f_iter)->get_name() << "_Process;" << endl;
+  }
+
+  scope_down(f_service_);
+  f_service_ << endl;
+
+  if (extends.empty()) {
+    f_service_
+      << indent()
+      << "protected delegate void ProcessFunction(int seqid, TProtocol iprot, TProtocol oprot);"
+      << endl;
+  }
+
+  f_service_ << indent() << "private ISync iface_;" << endl;
+
+  if (extends.empty()) {
+    f_service_ << indent() << "protected Dictionary<string, ProcessFunction> processMap_ = new "
+      "Dictionary<string, ProcessFunction>();" << endl;
+  }
+
+  f_service_ << endl;
+
+  if (extends.empty()) {
+    indent(f_service_) << "public bool Process(TProtocol iprot, TProtocol oprot)" << endl;
+  }
+  else {
+    indent(f_service_) << "public new bool Process(TProtocol iprot, TProtocol oprot)" << endl;
+  }
+  scope_up(f_service_);
+
+  f_service_ << indent() << "try" << endl;
+  scope_up(f_service_);
+
+  f_service_ << indent() << "TMessage msg = iprot.ReadMessageBegin();" << endl;
+
+  f_service_
+    << indent() << "ProcessFunction fn;" << endl << indent()
+    << "processMap_.TryGetValue(msg.Name, out fn);" << endl << indent() << "if (fn == null) {"
+    << endl << indent() << "  TProtocolUtil.Skip(iprot, TType.Struct);" << endl << indent()
+    << "  iprot.ReadMessageEnd();" << endl << indent()
+    << "  TApplicationException x = new TApplicationException "
+    "(TApplicationException.ExceptionType.UnknownMethod, \"Invalid method name: '\" + "
+    "msg.Name + \"'\");" << endl << indent()
+    << "  oprot.WriteMessageBegin(new TMessage(msg.Name, TMessageType.Exception, msg.SeqID));"
+    << endl << indent() << "  x.Write(oprot);" << endl << indent() << "  oprot.WriteMessageEnd();"
+    << endl << indent() << "  oprot.Transport.Flush();" << endl << indent() << "  return true;"
+    << endl << indent() << "}" << endl << indent() << "fn(msg.SeqID, iprot, oprot);" << endl;
+
+  scope_down(f_service_);
+
+  f_service_ << indent() << "catch (IOException)" << endl;
+  scope_up(f_service_);
+  f_service_ << indent() << "return false;" << endl;
+  scope_down(f_service_);
+
+  f_service_ << indent() << "return true;" << endl;
+
+  scope_down(f_service_);
+  f_service_ << endl;
+
+  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
+    generate_process_function(tservice, *f_iter);
+  }
+
+  indent_down();
+  indent(f_service_) << "}" << endl << endl;
+}
+
+void t_csharp_generator::generate_service_server_async(t_service* tservice) {
+  vector<t_function*> functions = tservice->get_functions();
+  vector<t_function*>::iterator f_iter;
+
+  string extends = "";
+  string extends_processor = "";
+  if (tservice->get_extends() != NULL) {
+    extends = type_name(tservice->get_extends());
+    extends_processor = extends + ".Processor, ";
+  }
+
+  indent(f_service_) << "public class AsyncProcessor : " << extends_processor << "TAsyncProcessor {" << endl;
+  indent_up();
+
+  indent(f_service_) << "public AsyncProcessor(IAsync iface)";
+  if (!extends.empty()) {
+    f_service_ << " : base(iface)";
+  }
+  f_service_ << endl;
+  scope_up(f_service_);
+  f_service_ << indent() << "iface_ = iface;" << endl;
+
+  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
+    f_service_ << indent() << "processMap_[\"" << (*f_iter)->get_name()
+      << "\"] = " << (*f_iter)->get_name() << "_ProcessAsync;" << endl;
+  }
+
+  scope_down(f_service_);
+  f_service_ << endl;
+
+  if (extends.empty()) {
+    f_service_
+      << indent()
+      << "protected delegate Task ProcessFunction(int seqid, TProtocol iprot, TProtocol oprot);"
+      << endl;
+  }
+
+  f_service_ << indent() << "private IAsync iface_;" << endl;
+
+  if (extends.empty()) {
+    f_service_ << indent() << "protected Dictionary<string, ProcessFunction> processMap_ = new "
+      "Dictionary<string, ProcessFunction>();" << endl;
+  }
+
+  f_service_ << endl;
+
+  if (extends.empty()) {
+    indent(f_service_) << "public async Task<bool> ProcessAsync(TProtocol iprot, TProtocol oprot)" << endl;
+  }
+  else {
+    indent(f_service_) << "public new async Task<bool> ProcessAsync(TProtocol iprot, TProtocol oprot)" << endl;
+  }
+  scope_up(f_service_);
+
+  f_service_ << indent() << "try" << endl;
+  scope_up(f_service_);
+
+  f_service_ << indent() << "TMessage msg = iprot.ReadMessageBegin();" << endl;
+
+  f_service_
+    << indent() << "ProcessFunction fn;" << endl << indent()
+    << "processMap_.TryGetValue(msg.Name, out fn);" << endl << indent() << "if (fn == null) {"
+    << endl << indent() << "  TProtocolUtil.Skip(iprot, TType.Struct);" << endl << indent()
+    << "  iprot.ReadMessageEnd();" << endl << indent()
+    << "  TApplicationException x = new TApplicationException "
+    "(TApplicationException.ExceptionType.UnknownMethod, \"Invalid method name: '\" + "
+    "msg.Name + \"'\");" << endl << indent()
+    << "  oprot.WriteMessageBegin(new TMessage(msg.Name, TMessageType.Exception, msg.SeqID));"
+    << endl << indent() << "  x.Write(oprot);" << endl << indent() << "  oprot.WriteMessageEnd();"
+    << endl << indent() << "  oprot.Transport.Flush();" << endl << indent() << "  return true;"
+    << endl << indent() << "}" << endl << indent() << "await fn(msg.SeqID, iprot, oprot);" << endl;
+
+  scope_down(f_service_);
+
+  f_service_ << indent() << "catch (IOException)" << endl;
+  scope_up(f_service_);
+  f_service_ << indent() << "return false;" << endl;
+  scope_down(f_service_);
+
+  f_service_ << indent() << "return true;" << endl;
+
+  scope_down(f_service_);
+  f_service_ << endl;
+
+  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
+    generate_process_function_async(tservice, *f_iter);
+  }
+
+  indent_down();
+  indent(f_service_) << "}" << endl << endl;
+}
+
+void t_csharp_generator::generate_function_helpers(t_function* tfunction) {
+  if (tfunction->is_oneway()) {
+    return;
+  }
+
+  t_struct result(program_, tfunction->get_name() + "_result");
+  t_field success(tfunction->get_returntype(), "success", 0);
+  if (!tfunction->get_returntype()->is_void()) {
+    result.append(&success);
+  }
+
+  t_struct* xs = tfunction->get_xceptions();
+  const vector<t_field*>& fields = xs->get_members();
+  vector<t_field*>::const_iterator f_iter;
+  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+    result.append(*f_iter);
+  }
+
+  generate_csharp_struct_definition(f_service_, &result, false, true, true);
+}
+
+void t_csharp_generator::generate_process_function(t_service* tservice, t_function* tfunction) {
+  (void)tservice;
+  indent(f_service_) << "public void " << tfunction->get_name()
+                     << "_Process(int seqid, TProtocol iprot, TProtocol oprot)" << endl;
+  scope_up(f_service_);
+
+  string argsname = tfunction->get_name() + "_args";
+  string resultname = tfunction->get_name() + "_result";
+
+  f_service_ << indent() << argsname << " args = new " << argsname << "();" << endl
+             << indent() << "args.Read(iprot);" << endl
+             << indent() << "iprot.ReadMessageEnd();" << endl;
+
+  t_struct* xs = tfunction->get_xceptions();
+  const std::vector<t_field*>& xceptions = xs->get_members();
+  vector<t_field*>::const_iterator x_iter;
+
+  if (!tfunction->is_oneway()) {
+    f_service_ << indent() << resultname << " result = new " << resultname << "();" << endl;
+  }
+
+  f_service_ << indent() << "try" << endl
+             << indent() << "{" << endl;
+  indent_up();
+
+  if (xceptions.size() > 0) {
+    f_service_ << indent() << "try" << endl
+               << indent() << "{" << endl;
+    indent_up();
+  }
+
+  t_struct* arg_struct = tfunction->get_arglist();
+  const std::vector<t_field*>& fields = arg_struct->get_members();
+  vector<t_field*>::const_iterator f_iter;
+
+  f_service_ << indent();
+  if (!tfunction->is_oneway() && !tfunction->get_returntype()->is_void()) {
+    f_service_ << "result.Success = ";
+  }
+  f_service_ << "iface_." << normalize_name(tfunction->get_name()) << "(";
+  bool first = true;
+  prepare_member_name_mapping(arg_struct);
+  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+    if (first) {
+      first = false;
+    } else {
+      f_service_ << ", ";
+    }
+    f_service_ << "args." << prop_name(*f_iter);
+    if (nullable_ && !type_can_be_null((*f_iter)->get_type())) {
+      f_service_ << ".Value";
+    }
+  }
+  cleanup_member_name_mapping(arg_struct);
+  f_service_ << ");" << endl;
+
+  prepare_member_name_mapping(xs, xs->get_members(), resultname);
+  if (xceptions.size() > 0) {
+    indent_down();
+    f_service_ << indent() << "}" << endl;
+    for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) {
+      f_service_ << indent() << "catch (" << type_name((*x_iter)->get_type(), false, false) << " "
+                 << (*x_iter)->get_name() << ")" << endl
+                 << indent() << "{" << endl;
+      if (!tfunction->is_oneway()) {
+        indent_up();
+        f_service_ << indent() << "result." << prop_name(*x_iter) << " = " << (*x_iter)->get_name()
+                   << ";" << endl;
+        indent_down();
+      }
+      f_service_ << indent() << "}" << endl;
+    }
+  }
+  if (!tfunction->is_oneway()) {
+    f_service_ << indent() << "oprot.WriteMessageBegin(new TMessage(\"" << tfunction->get_name()
+               << "\", TMessageType.Reply, seqid)); " << endl;
+    f_service_ << indent() << "result.Write(oprot);" << endl;
+  }
+  indent_down();
+
+  cleanup_member_name_mapping(xs);
+
+  f_service_ << indent() << "}" << endl
+             << indent() << "catch (TTransportException)" << endl
+             << indent() << "{" << endl
+             << indent() << "  throw;" << endl
+             << indent() << "}" << endl
+             << indent() << "catch (Exception ex)" << endl
+             << indent() << "{" << endl
+             << indent() << "  Console.Error.WriteLine(\"Error occurred in processor:\");" << endl
+             << indent() << "  Console.Error.WriteLine(ex.ToString());" << endl;
+
+  if (tfunction->is_oneway()) {
+    f_service_ << indent() << "}" << endl;
+  } else {
+    f_service_ << indent() << "  TApplicationException x = new TApplicationException" << indent()
+               << "(TApplicationException.ExceptionType.InternalError,\" Internal error.\");"
+               << endl
+               << indent() << "  oprot.WriteMessageBegin(new TMessage(\"" << tfunction->get_name()
+               << "\", TMessageType.Exception, seqid));" << endl
+               << indent() << "  x.Write(oprot);" << endl
+               << indent() << "}" << endl;
+    f_service_ << indent() << "oprot.WriteMessageEnd();" << endl
+               << indent() << "oprot.Transport.Flush();" << endl;
+  }
+
+  scope_down(f_service_);
+
+  f_service_ << endl;
+}
+
+void t_csharp_generator::generate_process_function_async(t_service* tservice, t_function* tfunction) {
+  (void)tservice;
+  indent(f_service_) << "public async Task " << tfunction->get_name()
+    << "_ProcessAsync(int seqid, TProtocol iprot, TProtocol oprot)" << endl;
+  scope_up(f_service_);
+
+  string argsname = tfunction->get_name() + "_args";
+  string resultname = tfunction->get_name() + "_result";
+
+  f_service_ << indent() << argsname << " args = new " << argsname << "();" << endl
+    << indent() << "args.Read(iprot);" << endl
+    << indent() << "iprot.ReadMessageEnd();" << endl;
+
+  t_struct* xs = tfunction->get_xceptions();
+  const std::vector<t_field*>& xceptions = xs->get_members();
+  vector<t_field*>::const_iterator x_iter;
+
+  if (!tfunction->is_oneway()) {
+    f_service_ << indent() << resultname << " result = new " << resultname << "();" << endl;
+  }
+
+  f_service_ << indent() << "try" << endl
+    << indent() << "{" << endl;
+  indent_up();
+
+  if (xceptions.size() > 0) {
+    f_service_ << indent() << "try" << endl
+      << indent() << "{" << endl;
+    indent_up();
+  }
+
+  t_struct* arg_struct = tfunction->get_arglist();
+  const std::vector<t_field*>& fields = arg_struct->get_members();
+  vector<t_field*>::const_iterator f_iter;
+
+  f_service_ << indent();
+  if (!tfunction->is_oneway() && !tfunction->get_returntype()->is_void()) {
+    f_service_ << "result.Success = ";
+  }
+  f_service_ << "await iface_." << normalize_name(tfunction->get_name()) << "Async(";
+  bool first = true;
+  prepare_member_name_mapping(arg_struct);
+  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+    if (first) {
+      first = false;
+    }
+    else {
+      f_service_ << ", ";
+    }
+    f_service_ << "args." << prop_name(*f_iter);
+    if (nullable_ && !type_can_be_null((*f_iter)->get_type())) {
+      f_service_ << ".Value";
+    }
+  }
+  cleanup_member_name_mapping(arg_struct);
+  f_service_ << ");" << endl;
+
+  prepare_member_name_mapping(xs, xs->get_members(), resultname);
+  if (xceptions.size() > 0) {
+    indent_down();
+    f_service_ << indent() << "}" << endl;
+    for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) {
+      f_service_ << indent() << "catch (" << type_name((*x_iter)->get_type(), false, false) << " "
+        << (*x_iter)->get_name() << ")" << endl
+        << indent() << "{" << endl;
+      if (!tfunction->is_oneway()) {
+        indent_up();
+        f_service_ << indent() << "result." << prop_name(*x_iter) << " = " << (*x_iter)->get_name()
+          << ";" << endl;
+        indent_down();
+      }
+      f_service_ << indent() << "}" << endl;
+    }
+  }
+  if (!tfunction->is_oneway()) {
+    f_service_ << indent() << "oprot.WriteMessageBegin(new TMessage(\"" << tfunction->get_name()
+      << "\", TMessageType.Reply, seqid)); " << endl;
+    f_service_ << indent() << "result.Write(oprot);" << endl;
+  }
+  indent_down();
+
+  cleanup_member_name_mapping(xs);
+
+  f_service_ << indent() << "}" << endl
+    << indent() << "catch (TTransportException)" << endl
+    << indent() << "{" << endl
+    << indent() << "  throw;" << endl
+    << indent() << "}" << endl
+    << indent() << "catch (Exception ex)" << endl
+    << indent() << "{" << endl
+    << indent() << "  Console.Error.WriteLine(\"Error occurred in processor:\");" << endl
+    << indent() << "  Console.Error.WriteLine(ex.ToString());" << endl;
+
+  if (tfunction->is_oneway()) {
+    f_service_ << indent() << "}" << endl;
+  }
+  else {
+    f_service_ << indent() << "  TApplicationException x = new TApplicationException" << indent()
+      << "(TApplicationException.ExceptionType.InternalError,\" Internal error.\");"
+      << endl
+      << indent() << "  oprot.WriteMessageBegin(new TMessage(\"" << tfunction->get_name()
+      << "\", TMessageType.Exception, seqid));" << endl
+      << indent() << "  x.Write(oprot);" << endl
+      << indent() << "}" << endl;
+    f_service_ << indent() << "oprot.WriteMessageEnd();" << endl
+      << indent() << "oprot.Transport.Flush();" << endl;
+  }
+
+  scope_down(f_service_);
+
+  f_service_ << endl;
+}
+
+void t_csharp_generator::generate_csharp_union_reader(std::ostream& out, t_struct* tunion) {
+  // Thanks to THRIFT-1768, we don't need to check for required fields in the union
+  const vector<t_field*>& fields = tunion->get_members();
+  vector<t_field*>::const_iterator f_iter;
+
+  indent(out) << "public static " << tunion->get_name() << " Read(TProtocol iprot)" << endl;
+  scope_up(out);
+
+  out << indent() << "iprot.IncrementRecursionDepth();" << endl;
+  out << indent() << "try" << endl;
+  scope_up(out);
+
+  indent(out) << tunion->get_name() << " retval;" << endl;
+  indent(out) << "iprot.ReadStructBegin();" << endl;
+  indent(out) << "TField field = iprot.ReadFieldBegin();" << endl;
+  // we cannot have the first field be a stop -- we must have a single field defined
+  indent(out) << "if (field.Type == TType.Stop)" << endl;
+  scope_up(out);
+  indent(out) << "iprot.ReadFieldEnd();" << endl;
+  indent(out) << "retval = new ___undefined();" << endl;
+  scope_down(out);
+  indent(out) << "else" << endl;
+  scope_up(out);
+  indent(out) << "switch (field.ID)" << endl;
+  scope_up(out);
+
+  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+    indent(out) << "case " << (*f_iter)->get_key() << ":" << endl;
+    indent_up();
+    indent(out) << "if (field.Type == " << type_to_enum((*f_iter)->get_type()) << ") {" << endl;
+    indent_up();
+
+    indent(out) << type_name((*f_iter)->get_type()) << " temp;" << endl;
+    generate_deserialize_field(out, (*f_iter), "temp", true);
+    indent(out) << "retval = new " << (*f_iter)->get_name() << "(temp);" << endl;
+
+    indent_down();
+    out << indent() << "} else { " << endl << indent() << "  TProtocolUtil.Skip(iprot, field.Type);"
+        << endl << indent() << "  retval = new ___undefined();" << endl << indent() << "}" << endl
+        << indent() << "break;" << endl;
+    indent_down();
+  }
+
+  indent(out) << "default: " << endl;
+  indent_up();
+  indent(out) << "TProtocolUtil.Skip(iprot, field.Type);" << endl << indent()
+              << "retval = new ___undefined();" << endl;
+  indent(out) << "break;" << endl;
+  indent_down();
+
+  scope_down(out);
+
+  indent(out) << "iprot.ReadFieldEnd();" << endl;
+
+  indent(out) << "if (iprot.ReadFieldBegin().Type != TType.Stop)" << endl;
+  scope_up(out);
+  indent(out) << "throw new TProtocolException(TProtocolException.INVALID_DATA);" << endl;
+  scope_down(out);
+
+  // end of else for TStop
+  scope_down(out);
+  indent(out) << "iprot.ReadStructEnd();" << endl;
+  indent(out) << "return retval;" << endl;
+  indent_down();
+
+  scope_down(out);
+  out << indent() << "finally" << endl;
+  scope_up(out);
+  out << indent() << "iprot.DecrementRecursionDepth();" << endl;
+  scope_down(out);
+
+  indent(out) << "}" << endl << endl;
+}
+
+void t_csharp_generator::generate_deserialize_field(ostream& out,
+                                                    t_field* tfield,
+                                                    string prefix,
+                                                    bool is_propertyless) {
+  t_type* type = tfield->get_type();
+  while (type->is_typedef()) {
+    type = ((t_typedef*)type)->get_type();
+  }
+
+  if (type->is_void()) {
+    throw "CANNOT GENERATE DESERIALIZE CODE FOR void TYPE: " + prefix + tfield->get_name();
+  }
+
+  string name = prefix + (is_propertyless ? "" : prop_name(tfield));
+
+  if (type->is_struct() || type->is_xception()) {
+    generate_deserialize_struct(out, (t_struct*)type, name);
+  } else if (type->is_container()) {
+    generate_deserialize_container(out, type, name);
+  } else if (type->is_base_type() || type->is_enum()) {
+    indent(out) << name << " = ";
+
+    if (type->is_enum()) {
+      out << "(" << type_name(type, false, true) << ")";
+    }
+
+    out << "iprot.";
+
+    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:
+        throw "compiler error: cannot serialize void field in a struct: " + name;
+        break;
+      case t_base_type::TYPE_STRING:
+        if (type->is_binary()) {
+          out << "ReadBinary();";
+        } else {
+          out << "ReadString();";
+        }
+        break;
+      case t_base_type::TYPE_BOOL:
+        out << "ReadBool();";
+        break;
+      case t_base_type::TYPE_I8:
+        out << "ReadByte();";
+        break;
+      case t_base_type::TYPE_I16:
+        out << "ReadI16();";
+        break;
+      case t_base_type::TYPE_I32:
+        out << "ReadI32();";
+        break;
+      case t_base_type::TYPE_I64:
+        out << "ReadI64();";
+        break;
+      case t_base_type::TYPE_DOUBLE:
+        out << "ReadDouble();";
+        break;
+      default:
+        throw "compiler error: no C# name for base type " + t_base_type::t_base_name(tbase);
+      }
+    } else if (type->is_enum()) {
+      out << "ReadI32();";
+    }
+    out << endl;
+  } else {
+    printf("DO NOT KNOW HOW TO DESERIALIZE FIELD '%s' TYPE '%s'\n",
+           tfield->get_name().c_str(),
+           type_name(type).c_str());
+  }
+}
+
+void t_csharp_generator::generate_deserialize_struct(ostream& out,
+                                                     t_struct* tstruct,
+                                                     string prefix) {
+  if (union_ && tstruct->is_union()) {
+    out << indent() << prefix << " = " << type_name(tstruct) << ".Read(iprot);" << endl;
+  } else {
+    out << indent() << prefix << " = new " << type_name(tstruct) << "();" << endl << indent()
+        << prefix << ".Read(iprot);" << endl;
+  }
+}
+
+void t_csharp_generator::generate_deserialize_container(ostream& out,
+                                                        t_type* ttype,
+                                                        string prefix) {
+  scope_up(out);
+
+  string obj;
+
+  if (ttype->is_map()) {
+    obj = tmp("_map");
+  } else if (ttype->is_set()) {
+    obj = tmp("_set");
+  } else if (ttype->is_list()) {
+    obj = tmp("_list");
+  }
+
+  indent(out) << prefix << " = new " << type_name(ttype, false, true) << "();" << endl;
+  if (ttype->is_map()) {
+    out << indent() << "TMap " << obj << " = iprot.ReadMapBegin();" << endl;
+  } else if (ttype->is_set()) {
+    out << indent() << "TSet " << obj << " = iprot.ReadSetBegin();" << endl;
+  } else if (ttype->is_list()) {
+    out << indent() << "TList " << obj << " = iprot.ReadListBegin();" << endl;
+  }
+
+  string i = tmp("_i");
+  indent(out) << "for( int " << i << " = 0; " << i << " < " << obj << ".Count"
+              << "; "
+              << "++" << i << ")" << endl;
+  scope_up(out);
+
+  if (ttype->is_map()) {
+    generate_deserialize_map_element(out, (t_map*)ttype, prefix);
+  } else if (ttype->is_set()) {
+    generate_deserialize_set_element(out, (t_set*)ttype, prefix);
+  } else if (ttype->is_list()) {
+    generate_deserialize_list_element(out, (t_list*)ttype, prefix);
+  }
+
+  scope_down(out);
+
+  if (ttype->is_map()) {
+    indent(out) << "iprot.ReadMapEnd();" << endl;
+  } else if (ttype->is_set()) {
+    indent(out) << "iprot.ReadSetEnd();" << endl;
+  } else if (ttype->is_list()) {
+    indent(out) << "iprot.ReadListEnd();" << endl;
+  }
+
+  scope_down(out);
+}
+
+void t_csharp_generator::generate_deserialize_map_element(ostream& out,
+                                                          t_map* tmap,
+                                                          string prefix) {
+  string key = tmp("_key");
+  string val = tmp("_val");
+
+  t_field fkey(tmap->get_key_type(), key);
+  t_field fval(tmap->get_val_type(), val);
+
+  indent(out) << declare_field(&fkey) << endl;
+  indent(out) << declare_field(&fval) << endl;
+
+  generate_deserialize_field(out, &fkey);
+  generate_deserialize_field(out, &fval);
+
+  indent(out) << prefix << "[" << key << "] = " << val << ";" << endl;
+}
+
+void t_csharp_generator::generate_deserialize_set_element(ostream& out,
+                                                          t_set* tset,
+                                                          string prefix) {
+  string elem = tmp("_elem");
+  t_field felem(tset->get_elem_type(), elem);
+
+  indent(out) << declare_field(&felem) << endl;
+
+  generate_deserialize_field(out, &felem);
+
+  indent(out) << prefix << ".Add(" << elem << ");" << endl;
+}
+
+void t_csharp_generator::generate_deserialize_list_element(ostream& out,
+                                                           t_list* tlist,
+                                                           string prefix) {
+  string elem = tmp("_elem");
+  t_field felem(tlist->get_elem_type(), elem);
+
+  indent(out) << declare_field(&felem) << endl;
+
+  generate_deserialize_field(out, &felem);
+
+  indent(out) << prefix << ".Add(" << elem << ");" << endl;
+}
+
+void t_csharp_generator::generate_serialize_field(ostream& out,
+                                                  t_field* tfield,
+                                                  string prefix,
+                                                  bool is_element,
+                                                  bool is_propertyless) {
+  t_type* type = tfield->get_type();
+  while (type->is_typedef()) {
+    type = ((t_typedef*)type)->get_type();
+  }
+
+  string name = prefix + (is_propertyless ? "" : prop_name(tfield));
+
+  if (type->is_void()) {
+    throw "CANNOT GENERATE SERIALIZE CODE FOR void TYPE: " + name;
+  }
+
+  if (type->is_struct() || type->is_xception()) {
+    generate_serialize_struct(out, (t_struct*)type, name);
+  } else if (type->is_container()) {
+    generate_serialize_container(out, type, name);
+  } else if (type->is_base_type() || type->is_enum()) {
+    indent(out) << "oprot.";
+
+    string nullable_name = nullable_ && !is_element && !field_is_required(tfield) ? name + ".Value"
+                                                                                  : name;
+
+    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:
+        throw "compiler error: cannot serialize void field in a struct: " + name;
+        break;
+      case t_base_type::TYPE_STRING:
+        if (type->is_binary()) {
+          out << "WriteBinary(";
+        } else {
+          out << "WriteString(";
+        }
+        out << name << ");";
+        break;
+      case t_base_type::TYPE_BOOL:
+        out << "WriteBool(" << nullable_name << ");";
+        break;
+      case t_base_type::TYPE_I8:
+        out << "WriteByte(" << nullable_name << ");";
+        break;
+      case t_base_type::TYPE_I16:
+        out << "WriteI16(" << nullable_name << ");";
+        break;
+      case t_base_type::TYPE_I32:
+        out << "WriteI32(" << nullable_name << ");";
+        break;
+      case t_base_type::TYPE_I64:
+        out << "WriteI64(" << nullable_name << ");";
+        break;
+      case t_base_type::TYPE_DOUBLE:
+        out << "WriteDouble(" << nullable_name << ");";
+        break;
+      default:
+        throw "compiler error: no C# name for base type " + t_base_type::t_base_name(tbase);
+      }
+    } else if (type->is_enum()) {
+      out << "WriteI32((int)" << nullable_name << ");";
+    }
+    out << endl;
+  } else {
+    printf("DO NOT KNOW HOW TO SERIALIZE '%s%s' TYPE '%s'\n",
+           prefix.c_str(),
+           tfield->get_name().c_str(),
+           type_name(type).c_str());
+  }
+}
+
+void t_csharp_generator::generate_serialize_struct(ostream& out,
+                                                   t_struct* tstruct,
+                                                   string prefix) {
+  (void)tstruct;
+  out << indent() << prefix << ".Write(oprot);" << endl;
+}
+
+void t_csharp_generator::generate_serialize_container(ostream& out, t_type* ttype, string prefix) {
+  scope_up(out);
+
+  if (ttype->is_map()) {
+    indent(out) << "oprot.WriteMapBegin(new TMap(" << type_to_enum(((t_map*)ttype)->get_key_type())
+                << ", " << type_to_enum(((t_map*)ttype)->get_val_type()) << ", " << prefix
+                << ".Count));" << endl;
+  } else if (ttype->is_set()) {
+    indent(out) << "oprot.WriteSetBegin(new TSet(" << type_to_enum(((t_set*)ttype)->get_elem_type())
+                << ", " << prefix << ".Count));" << endl;
+  } else if (ttype->is_list()) {
+    indent(out) << "oprot.WriteListBegin(new TList("
+                << type_to_enum(((t_list*)ttype)->get_elem_type()) << ", " << prefix << ".Count));"
+                << endl;
+  }
+
+  string iter = tmp("_iter");
+  if (ttype->is_map()) {
+    indent(out) << "foreach (" << type_name(((t_map*)ttype)->get_key_type()) << " " << iter
+                << " in " << prefix << ".Keys)";
+  } else if (ttype->is_set()) {
+    indent(out) << "foreach (" << type_name(((t_set*)ttype)->get_elem_type()) << " " << iter
+                << " in " << prefix << ")";
+  } else if (ttype->is_list()) {
+    indent(out) << "foreach (" << type_name(((t_list*)ttype)->get_elem_type()) << " " << iter
+                << " in " << prefix << ")";
+  }
+
+  out << endl;
+  scope_up(out);
+
+  if (ttype->is_map()) {
+    generate_serialize_map_element(out, (t_map*)ttype, iter, prefix);
+  } else if (ttype->is_set()) {
+    generate_serialize_set_element(out, (t_set*)ttype, iter);
+  } else if (ttype->is_list()) {
+    generate_serialize_list_element(out, (t_list*)ttype, iter);
+  }
+
+  scope_down(out);
+
+  if (ttype->is_map()) {
+    indent(out) << "oprot.WriteMapEnd();" << endl;
+  } else if (ttype->is_set()) {
+    indent(out) << "oprot.WriteSetEnd();" << endl;
+  } else if (ttype->is_list()) {
+    indent(out) << "oprot.WriteListEnd();" << endl;
+  }
+
+  scope_down(out);
+}
+
+void t_csharp_generator::generate_serialize_map_element(ostream& out,
+                                                        t_map* tmap,
+                                                        string iter,
+                                                        string map) {
+  t_field kfield(tmap->get_key_type(), iter);
+  generate_serialize_field(out, &kfield, "", true);
+  t_field vfield(tmap->get_val_type(), map + "[" + iter + "]");
+  generate_serialize_field(out, &vfield, "", true);
+}
+
+void t_csharp_generator::generate_serialize_set_element(ostream& out, t_set* tset, string iter) {
+  t_field efield(tset->get_elem_type(), iter);
+  generate_serialize_field(out, &efield, "", true);
+}
+
+void t_csharp_generator::generate_serialize_list_element(ostream& out,
+                                                         t_list* tlist,
+                                                         string iter) {
+  t_field efield(tlist->get_elem_type(), iter);
+  generate_serialize_field(out, &efield, "", true);
+}
+
+void t_csharp_generator::generate_property(ostream& out,
+                                           t_field* tfield,
+                                           bool isPublic,
+                                           bool generateIsset) {
+  generate_csharp_property(out, tfield, isPublic, generateIsset, "_");
+}
+void t_csharp_generator::generate_csharp_property(ostream& out,
+                                                  t_field* tfield,
+                                                  bool isPublic,
+                                                  bool generateIsset,
+                                                  std::string fieldPrefix) {
+  if ((serialize_ || wcf_) && isPublic) {
+    indent(out) << "[DataMember(Order = 0)]" << endl;
+  }
+  bool has_default = field_has_default(tfield);
+  bool is_required = field_is_required(tfield);
+  if ((nullable_ && !has_default) || (is_required)) {
+    indent(out) << (isPublic ? "public " : "private ")
+                << type_name(tfield->get_type(), false, false, true, is_required) << " "
+                << prop_name(tfield) << " { get; set; }" << endl;
+  } else {
+    indent(out) << (isPublic ? "public " : "private ")
+                << type_name(tfield->get_type(), false, false, true) << " " << prop_name(tfield)
+                << endl;
+    scope_up(out);
+    indent(out) << "get" << endl;
+    scope_up(out);
+    bool use_nullable = false;
+    if (nullable_) {
+      t_type* ttype = tfield->get_type();
+      while (ttype->is_typedef()) {
+        ttype = ((t_typedef*)ttype)->get_type();
+      }
+      if (ttype->is_base_type()) {
+        use_nullable = ((t_base_type*)ttype)->get_base() != t_base_type::TYPE_STRING;
+      } else if (ttype->is_enum()) {
+        use_nullable = true;
+      }
+    }
+    indent(out) << "return " << fieldPrefix + tfield->get_name() << ";" << endl;
+    scope_down(out);
+    indent(out) << "set" << endl;
+    scope_up(out);
+    if (use_nullable) {
+      if (generateIsset) {
+        indent(out) << "__isset." << normalize_name(tfield->get_name()) << " = value.HasValue;"
+                    << endl;
+      }
+      indent(out) << "if (value.HasValue) this." << fieldPrefix + tfield->get_name()
+                  << " = value.Value;" << endl;
+    } else {
+      if (generateIsset) {
+        indent(out) << "__isset." << normalize_name(tfield->get_name()) << " = true;" << endl;
+      }
+      indent(out) << "this." << fieldPrefix + tfield->get_name() << " = value;" << endl;
+    }
+    scope_down(out);
+    scope_down(out);
+  }
+  out << endl;
+}
+
+std::string t_csharp_generator::make_valid_csharp_identifier(std::string const& fromName) {
+  std::string str = fromName;
+  if (str.empty()) {
+    return str;
+  }
+
+  // tests rely on this
+  assert(('A' < 'Z') && ('a' < 'z') && ('0' < '9'));
+
+  // if the first letter is a number, we add an additional underscore in front of it
+  char c = str.at(0);
+  if (('0' <= c) && (c <= '9')) {
+    str = "_" + str;
+  }
+
+  // following chars: letter, number or underscore
+  for (size_t i = 0; i < str.size(); ++i) {
+    c = str.at(i);
+    if ((('A' > c) || (c > 'Z')) && (('a' > c) || (c > 'z')) && (('0' > c) || (c > '9'))
+        && ('_' != c)) {
+      str.replace(i, 1, "_");
+    }
+  }
+
+  return str;
+}
+
+void t_csharp_generator::cleanup_member_name_mapping(void* scope) {
+  if( member_mapping_scopes.empty()) {
+    throw "internal error: cleanup_member_name_mapping() no scope active";
+  }
+
+  member_mapping_scope& active = member_mapping_scopes.back();
+  if (active.scope_member != scope) {
+    throw "internal error: cleanup_member_name_mapping() called for wrong struct";
+  }
+
+  member_mapping_scopes.pop_back();
+}
+
+string t_csharp_generator::get_mapped_member_name(string name) {
+  if( ! member_mapping_scopes.empty()) {
+    member_mapping_scope& active = member_mapping_scopes.back();
+    map<string, string>::iterator iter = active.mapping_table.find(name);
+    if (active.mapping_table.end() != iter) {
+      return iter->second;
+    }
+  }
+
+  pverbose("no mapping for member %s\n", name.c_str());
+  return name;
+}
+
+void t_csharp_generator::prepare_member_name_mapping(t_struct* tstruct) {
+  prepare_member_name_mapping(tstruct, tstruct->get_members(), tstruct->get_name());
+}
+
+void t_csharp_generator::prepare_member_name_mapping(void* scope,
+                                                     const vector<t_field*>& members,
+                                                     const string& structname) {
+  // begin new scope
+  member_mapping_scope dummy;
+  dummy.scope_member = 0;
+  member_mapping_scopes.push_back(dummy);
+  member_mapping_scope& active = member_mapping_scopes.back();
+  active.scope_member = scope;
+
+  // current C# generator policy:
+  // - prop names are always rendered with an Uppercase first letter
+  // - struct names are used as given
+  std::set<std::string> used_member_names;
+  vector<t_field*>::const_iterator iter;
+
+  // prevent name conflicts with struct (CS0542 error)
+  used_member_names.insert(structname);
+
+  // prevent name conflicts with known methods (THRIFT-2942)
+  used_member_names.insert("Read");
+  used_member_names.insert("Write");
+
+  for (iter = members.begin(); iter != members.end(); ++iter) {
+    string oldname = (*iter)->get_name();
+    string newname = prop_name(*iter, true);
+    while (true) {
+
+      // new name conflicts with another member
+      if (used_member_names.find(newname) != used_member_names.end()) {
+        pverbose("struct %s: member %s conflicts with another member\n",
+                 structname.c_str(),
+                 newname.c_str());
+        newname += '_';
+        continue;
+      }
+
+      // add always, this helps us to detect edge cases like
+      // different spellings ("foo" and "Foo") within the same struct
+      pverbose("struct %s: member mapping %s => %s\n",
+               structname.c_str(),
+               oldname.c_str(),
+               newname.c_str());
+      active.mapping_table[oldname] = newname;
+      used_member_names.insert(newname);
+      break;
+    }
+  }
+}
+
+std::string t_csharp_generator::prop_name(t_field* tfield, bool suppress_mapping) {
+  string name(tfield->get_name());
+  if (suppress_mapping) {
+    name[0] = toupper(name[0]);
+  } else {
+    name = get_mapped_member_name(name);
+  }
+  return name;
+}
+
+string t_csharp_generator::type_name(t_type* ttype,
+                                     bool in_container,
+                                     bool in_init,
+                                     bool in_param,
+                                     bool is_required) {
+  (void)in_init;
+  while (ttype->is_typedef()) {
+    ttype = ((t_typedef*)ttype)->get_type();
+  }
+
+  if (ttype->is_base_type()) {
+    return base_type_name((t_base_type*)ttype, in_container, in_param, is_required);
+  } else if (ttype->is_map()) {
+    t_map* tmap = (t_map*)ttype;
+    return "Dictionary<" + 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;
+    return "THashSet<" + type_name(tset->get_elem_type(), true) + ">";
+  } else if (ttype->is_list()) {
+    t_list* tlist = (t_list*)ttype;
+    return "List<" + type_name(tlist->get_elem_type(), true) + ">";
+  }
+
+  t_program* program = ttype->get_program();
+  string postfix = (!is_required && nullable_ && in_param && ttype->is_enum()) ? "?" : "";
+  if (program != NULL && program != program_) {
+    string ns = program->get_namespace("csharp");
+    if (!ns.empty()) {
+      return ns + "." + normalize_name(ttype->get_name()) + postfix;
+    }
+  }
+
+  return normalize_name(ttype->get_name()) + postfix;
+}
+
+string t_csharp_generator::base_type_name(t_base_type* tbase,
+                                          bool in_container,
+                                          bool in_param,
+                                          bool is_required) {
+  (void)in_container;
+  string postfix = (!is_required && nullable_ && in_param) ? "?" : "";
+  switch (tbase->get_base()) {
+  case t_base_type::TYPE_VOID:
+    return "void";
+  case t_base_type::TYPE_STRING:
+    if (tbase->is_binary()) {
+      return "byte[]";
+    } else {
+      return "string";
+    }
+  case t_base_type::TYPE_BOOL:
+    return "bool" + postfix;
+  case t_base_type::TYPE_I8:
+    return "sbyte" + postfix;
+  case t_base_type::TYPE_I16:
+    return "short" + postfix;
+  case t_base_type::TYPE_I32:
+    return "int" + postfix;
+  case t_base_type::TYPE_I64:
+    return "long" + postfix;
+  case t_base_type::TYPE_DOUBLE:
+    return "double" + postfix;
+  default:
+    throw "compiler error: no C# name for base type " + t_base_type::t_base_name(tbase->get_base());
+  }
+}
+
+string t_csharp_generator::declare_field(t_field* tfield, bool init, std::string prefix) {
+  string result = type_name(tfield->get_type()) + " " + prefix + tfield->get_name();
+  if (init) {
+    t_type* ttype = tfield->get_type();
+    while (ttype->is_typedef()) {
+      ttype = ((t_typedef*)ttype)->get_type();
+    }
+    if (ttype->is_base_type() && field_has_default(tfield)) {
+      std::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 += " = null";
+        break;
+      case t_base_type::TYPE_BOOL:
+        result += " = false";
+        break;
+      case t_base_type::TYPE_I8:
+      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 += " = (double)0";
+        break;
+      }
+    } else if (ttype->is_enum()) {
+      result += " = (" + type_name(ttype, false, true) + ")0";
+    } else if (ttype->is_container()) {
+      result += " = new " + type_name(ttype, false, true) + "()";
+    } else {
+      result += " = new " + type_name(ttype, false, true) + "()";
+    }
+  }
+  return result + ";";
+}
+
+string t_csharp_generator::function_signature(t_function* tfunction, string prefix) {
+  t_type* ttype = tfunction->get_returntype();
+  return type_name(ttype) + " " + normalize_name(prefix + tfunction->get_name()) + "("
+         + argument_list(tfunction->get_arglist()) + ")";
+}
+
+string t_csharp_generator::function_signature_async_begin(t_function* tfunction, string prefix) {
+  string comma = (tfunction->get_arglist()->get_members().size() > 0 ? ", " : "");
+  return "IAsyncResult " + normalize_name(prefix + tfunction->get_name())
+         + "(AsyncCallback callback, object state" + comma + argument_list(tfunction->get_arglist())
+         + ")";
+}
+
+string t_csharp_generator::function_signature_async_end(t_function* tfunction, string prefix) {
+  t_type* ttype = tfunction->get_returntype();
+  return type_name(ttype) + " " + normalize_name(prefix + tfunction->get_name())
+         + "(IAsyncResult asyncResult)";
+}
+
+string t_csharp_generator::function_signature_async(t_function* tfunction, string prefix) {
+  t_type* ttype = tfunction->get_returntype();
+  string task = "Task";
+  if (!ttype->is_void())
+    task += "<" + type_name(ttype) + ">";
+  return task + " " + normalize_name(prefix + tfunction->get_name()) + "Async("
+         + argument_list(tfunction->get_arglist()) + ")";
+}
+
+string t_csharp_generator::argument_list(t_struct* tstruct) {
+  string result = "";
+  const vector<t_field*>& fields = tstruct->get_members();
+  vector<t_field*>::const_iterator f_iter;
+  bool first = true;
+  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+    if (first) {
+      first = false;
+    } else {
+      result += ", ";
+    }
+    result += type_name((*f_iter)->get_type()) + " " + normalize_name((*f_iter)->get_name());
+  }
+  return result;
+}
+
+string t_csharp_generator::type_to_enum(t_type* 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:
+      throw "NO T_VOID CONSTRUCT";
+    case t_base_type::TYPE_STRING:
+      return "TType.String";
+    case t_base_type::TYPE_BOOL:
+      return "TType.Bool";
+    case t_base_type::TYPE_I8:
+      return "TType.Byte";
+    case t_base_type::TYPE_I16:
+      return "TType.I16";
+    case t_base_type::TYPE_I32:
+      return "TType.I32";
+    case t_base_type::TYPE_I64:
+      return "TType.I64";
+    case t_base_type::TYPE_DOUBLE:
+      return "TType.Double";
+    }
+  } else if (type->is_enum()) {
+    return "TType.I32";
+  } else if (type->is_struct() || type->is_xception()) {
+    return "TType.Struct";
+  } else if (type->is_map()) {
+    return "TType.Map";
+  } else if (type->is_set()) {
+    return "TType.Set";
+  } else if (type->is_list()) {
+    return "TType.List";
+  }
+
+  throw "INVALID TYPE IN type_to_enum: " + type->get_name();
+}
+
+void t_csharp_generator::generate_csharp_docstring_comment(ostream& out, string contents) {
+  generate_docstring_comment(out, "/// <summary>\n", "/// ", contents, "/// </summary>\n");
+}
+
+void t_csharp_generator::generate_csharp_doc(ostream& out, t_field* field) {
+  if (field->get_type()->is_enum()) {
+    string combined_message = field->get_doc() + "\n<seealso cref=\""
+                              + get_enum_class_name(field->get_type()) + "\"/>";
+    generate_csharp_docstring_comment(out, combined_message);
+  } else {
+    generate_csharp_doc(out, (t_doc*)field);
+  }
+}
+
+void t_csharp_generator::generate_csharp_doc(ostream& out, t_doc* tdoc) {
+  if (tdoc->has_doc()) {
+    generate_csharp_docstring_comment(out, tdoc->get_doc());
+  }
+}
+
+void t_csharp_generator::generate_csharp_doc(ostream& out, t_function* tfunction) {
+  if (tfunction->has_doc()) {
+    stringstream ps;
+    const vector<t_field*>& fields = tfunction->get_arglist()->get_members();
+    vector<t_field*>::const_iterator p_iter;
+    for (p_iter = fields.begin(); p_iter != fields.end(); ++p_iter) {
+      t_field* p = *p_iter;
+      ps << "\n<param name=\"" << p->get_name() << "\">";
+      if (p->has_doc()) {
+        std::string str = p->get_doc();
+        str.erase(std::remove(str.begin(), str.end(), '\n'),
+                  str.end()); // remove the newlines that appear from the parser
+        ps << str;
+      }
+      ps << "</param>";
+    }
+    generate_docstring_comment(out,
+                               "",
+                               "/// ",
+                               "<summary>\n" + tfunction->get_doc() + "</summary>" + ps.str(),
+                               "");
+  }
+}
+
+std::string t_csharp_generator::get_enum_class_name(t_type* type) {
+  string package = "";
+  t_program* program = type->get_program();
+  if (program != NULL && program != program_) {
+    package = program->get_namespace("csharp") + ".";
+  }
+  return package + type->get_name();
+}
+
+
+THRIFT_REGISTER_GENERATOR(
+    csharp,
+    "C#",
+    "    async:           Adds Async support using Task.Run.\n"
+    "    wcf:             Adds bindings for WCF to generated classes.\n"
+    "    serial:          Add serialization support to generated classes.\n"
+    "    nullable:        Use nullable types for properties.\n"
+    "    hashcode:        Generate a hashcode and equals implementation for classes.\n"
+    "    union:           Use new union typing, which includes a static read function for union "
+    "types.\n")

Some files were not shown because too many files changed in this diff