v8_generator.cpp

Go to the documentation of this file.
00001 /*
00002  *
00003  *
00004  * Distributed under the OpenDDS License.
00005  * See: http://www.opendds.org/license.html
00006  */
00007 
00008 #include "v8_generator.h"
00009 #include "be_extern.h"
00010 
00011 #include "utl_identifier.h"
00012 
00013 using namespace AstTypeClassification;
00014 
00015 void v8_generator::fwd_decl()
00016 {
00017   if (first_) {
00018     be_global->add_include("<v8.h>", BE_GlobalData::STREAM_CPP);
00019     first_ = false;
00020     be_global->header_ <<
00021       "namespace v8 {\n"
00022       "  class Value;\n"
00023       "}\n\n";
00024   }
00025 }
00026 
00027 bool v8_generator::gen_enum(AST_Enum*, UTL_ScopedName*, const std::vector<AST_EnumVal*>&,
00028                             const char*)
00029 {
00030   return true;
00031 }
00032 
00033 namespace {
00034 
00035   std::string getV8Type(AST_Type* type,
00036                         AST_PredefinedType::PredefinedType* pt = 0)
00037   {
00038     const Classification cls = classify(type);
00039     if (cls & (CL_ENUM | CL_STRING)) return "String";
00040     if (cls & (CL_STRUCTURE | CL_UNION)) return "Object";
00041     if (cls & (CL_ARRAY | CL_SEQUENCE)) return "Array";
00042     if (cls & CL_PRIMITIVE) {
00043       AST_Type* actual = resolveActualType(type);
00044       AST_PredefinedType* p = AST_PredefinedType::narrow_from_decl(actual);
00045       if (pt) *pt = p->pt();
00046       switch (p->pt()) {
00047       case AST_PredefinedType::PT_char:
00048       case AST_PredefinedType::PT_wchar:
00049         return "String";
00050       case AST_PredefinedType::PT_boolean:
00051         return "Boolean";
00052       case AST_PredefinedType::PT_octet:
00053       case AST_PredefinedType::PT_ushort:
00054       case AST_PredefinedType::PT_short:
00055       case AST_PredefinedType::PT_ulong:
00056       case AST_PredefinedType::PT_long:
00057         return "Integer";
00058       default:
00059         return "Number";
00060       }
00061     }
00062     return "";
00063   }
00064 
00065   bool builtInSeq(AST_Type* type)
00066   {
00067     const std::string name = scoped(type->name());
00068     static const char PRE[] = "CORBA::";
00069     if (std::strncmp(name.c_str(), PRE, sizeof(PRE) - 1)) return false;
00070     return name.rfind("Seq") == name.size() - 3;
00071   }
00072 
00073   void gen_copyto(const char* tgt, const char* src, AST_Type* type,
00074                   const char* prop)
00075   {
00076     const Classification cls = classify(type);
00077     AST_PredefinedType::PredefinedType pt = AST_PredefinedType::PT_void;
00078     const std::string v8Type = getV8Type(type, &pt),
00079       propName = std::string(tgt) + "->Set(" + prop + ", ";
00080 
00081     if (cls & CL_SCALAR) {
00082       std::string prefix, suffix, v8fn = "New";
00083 
00084       if (cls & CL_ENUM) {
00085         const std::string underscores =
00086           dds_generator::scoped_helper(type->name(), "_"),
00087           array = "gen_" + underscores + "_names";
00088         prefix = '(' + std::string(src) + " >= sizeof(" + array + ")/sizeof(" +
00089           array + "[0])) ? \"<<invalid>>\" : " + array + "[static_cast<int>(";
00090         suffix = ")]";
00091 
00092       } else if (cls & CL_STRING) {
00093         if (cls & CL_WIDE) {
00094           be_global->impl_ <<
00095             "  {\n"
00096             "    const size_t len = ACE_OS::strlen(" << src << ".in());\n"
00097             "    uint16_t* const str = new uint16_t[len + 1];\n"
00098             "    for (size_t i = 0; i <= len; ++i) {\n"
00099             "      str[i] = " << src << "[i];\n"
00100             "    }\n"
00101             "    " << propName << "v8::String::New(str));\n"
00102             "    delete[] str;\n"
00103             "  }\n";
00104           return;
00105         }
00106         suffix = ".in()";
00107 
00108       } else if (pt == AST_PredefinedType::PT_char) {
00109         be_global->impl_ <<
00110           "  {\n"
00111           "    const char str[] = {" << src << ", 0};\n"
00112           "    " << propName << "v8::String::New(str));\n"
00113           "  }\n";
00114         return;
00115 
00116       } else if (pt == AST_PredefinedType::PT_wchar) {
00117         be_global->impl_ <<
00118           "  {\n"
00119           "    const uint16_t str[] = {" << src << ", 0};\n"
00120           "    " << propName << "v8::String::New(str));\n"
00121           "  }\n";
00122         return;
00123 
00124       } else if (pt == AST_PredefinedType::PT_ulong) {
00125         v8fn = "NewFromUnsigned";
00126       }
00127 
00128       be_global->impl_ <<
00129         "  " << propName << "v8::" << v8Type << "::" << v8fn << '('
00130              << prefix << src << suffix << "));\n";
00131 
00132     } else if ((cls & CL_SEQUENCE) && builtInSeq(type)) {
00133       AST_Type* real_type = resolveActualType(type);
00134       AST_Sequence* seq = AST_Sequence::narrow_from_decl(real_type);
00135       AST_Type* elem = seq->base_type();
00136       be_global->impl_ <<
00137         "  {\n"
00138         "    const v8::Local<v8::Array> seq = v8::Array::New(" << src
00139                        << ".length());\n"
00140         "    for (CORBA::ULong j = 0; j < " << src << ".length(); ++j) {\n";
00141       gen_copyto("seq", (std::string(src) + "[j]").c_str(), elem, "j");
00142       be_global->impl_ <<
00143         "    }\n"
00144         "    " << propName << "seq" << ");\n"
00145         "  }\n";
00146 
00147     } else { // struct, sequence, etc.
00148       be_global->impl_ <<
00149         "  " << propName << "v8::Handle<v8::Value>(copyToV8("
00150              << src << ")));\n";
00151     }
00152   }
00153 
00154   struct gen_field_copyto {
00155     gen_field_copyto(const char* tgt, const char* src) : tgt_(tgt), src_(src) {}
00156     const std::string tgt_, src_;
00157     void operator()(AST_Field* field) const
00158     {
00159       const std::string fieldName = field->local_name()->get_string(),
00160         source = src_ + '.' + fieldName,
00161         prop = "v8::String::NewSymbol(\"" + fieldName + "\")";
00162       gen_copyto(tgt_.c_str(), source.c_str(),
00163                  field->field_type(), prop.c_str());
00164     }
00165   };
00166 }
00167 
00168 bool v8_generator::gen_struct(AST_Structure*, UTL_ScopedName* name,
00169                               const std::vector<AST_Field*>& fields,
00170                               AST_Type::SIZE_TYPE, const char*)
00171 {
00172   fwd_decl();
00173   {
00174     NamespaceGuard ng;
00175     const std::string clazz = scoped(name);
00176     {
00177       Function ctv("copyToV8", "v8::Value*");
00178       ctv.addArg("src", "const " + clazz + '&');
00179       ctv.endArgs();
00180       be_global->impl_ <<
00181         "  const v8::Local<v8::Object> stru = v8::Object::New();\n";
00182       std::for_each(fields.begin(), fields.end(),
00183                     gen_field_copyto("stru", "src"));
00184       be_global->impl_ <<
00185         "  return *stru;\n";
00186     }
00187   }
00188 
00189   if (idl_global->is_dcps_type(name)) {
00190     be_global->add_include("dds/DCPS/V8TypeConverter.h",
00191                            BE_GlobalData::STREAM_CPP);
00192     ScopedNamespaceGuard cppGuard(name, be_global->impl_);
00193     const std::string lname = name->last_component()->get_string(),
00194       tsv8 = lname + "TypeSupportV8Impl";
00195     be_global->impl_ <<
00196       "class " << tsv8 << "\n"
00197       "  : public virtual " << lname << "TypeSupportImpl\n"
00198       "  , public virtual OpenDDS::DCPS::V8TypeConverter {\n\n"
00199       "  v8::Value* toV8(const void* source) const\n"
00200       "  {\n"
00201       "    return OpenDDS::DCPS::copyToV8(*static_cast<const " << lname
00202                  << "*>(source));\n"
00203       "  }\n\n"
00204       "public:\n"
00205       "  struct Initializer {\n"
00206       "    Initializer()\n"
00207       "    {\n"
00208       "      " << lname << "TypeSupport_var ts = new " << tsv8 << ";\n"
00209       "      ts->register_type(0, \"\");\n"
00210       "    }\n"
00211       "  };\n"
00212       "};\n\n" <<
00213       tsv8 << "::Initializer init_tsv8_" << lname << ";\n";
00214   }
00215   return true;
00216 }
00217 
00218 bool v8_generator::gen_typedef(AST_Typedef*, UTL_ScopedName* name, AST_Type* type,
00219                                const char* /*repoid*/)
00220 {
00221   fwd_decl();
00222   switch (type->node_type()) {
00223   case AST_Decl::NT_sequence: {
00224     NamespaceGuard ng;
00225     AST_Sequence* seq = AST_Sequence::narrow_from_decl(type);
00226     const std::string cxx = scoped(name);
00227     AST_Type* elem = seq->base_type();
00228     {
00229       Function ctv("copyToV8", "v8::Value*");
00230       ctv.addArg("src", "const " + cxx + '&');
00231       ctv.endArgs();
00232       be_global->impl_ <<
00233         "  const v8::Local<v8::Array> tgt = v8::Array::New(src.length());\n"
00234         "  for (CORBA::ULong i = 0; i < src.length(); ++i) {\n"
00235         "  ";
00236       gen_copyto("tgt", "src[i]", elem, "i");
00237       be_global->impl_ <<
00238         "  }\n"
00239         "  return *tgt;\n";
00240     }
00241     break;
00242   }
00243   case AST_Decl::NT_array: {
00244     //TODO: support arrays
00245     break;
00246   }
00247   default:
00248     return true;
00249   }
00250   return true;
00251 }
00252 
00253 bool v8_generator::gen_union(AST_Union*, UTL_ScopedName* /*name*/,
00254                              const std::vector<AST_UnionBranch*>& /*branches*/,
00255                              AST_Type* /*type*/, const char* /*repoid*/)
00256 {
00257   fwd_decl();
00258   return true;
00259 }

Generated on Fri Feb 12 20:05:29 2016 for OpenDDS by  doxygen 1.4.7