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

Generated on 10 Aug 2018 for OpenDDS by  doxygen 1.6.1