Marshall::HandlerFn getMarshallFn(const SmokeType &type) { if(type.elem()) return marshall_basetype; if(!type.name()) return marshall_void; TypeHandler *h = type_handlers[type.name()]; if(h == 0 && type.isConst() && strlen(type.name()) > strlen("const ")) { h = type_handlers[type.name() + strlen("const ")]; } if(h != 0) { return h->fn; } return marshall_unknown; }
/* C++ compilers select overloaded methods by ranking each argument in terms of its implicit conversions. There are three different types of implicit conversions: standard, user and ellipsis. We only consider the former, as the others probably are not relevant for Qt. Within standard conversions, there are three ranks: exact, promotion and conversion. We assign these scores 3, 2 and 1, respectively, while 0 indicates no conversion and -1 indicates an error (e.g. unsupported type). The method with better or same ranks for all of its parameters is selected. If there is a tie for the best method, there is an error (in our code). */ int scoreArg_basetype(SEXP arg, const SmokeType &type) { int score = 0; SEXP value = arg; int rtype = TYPEOF(value); unsigned short elem = type.elem(); switch(rtype) { // try the simple cases first case RAWSXP: switch(elem) { case Smoke::t_uchar: score = 3; break; case Smoke::t_short: case Smoke::t_ushort: score = 2; break; case Smoke::t_int: case Smoke::t_uint: case Smoke::t_long: case Smoke::t_ulong: case Smoke::t_float: case Smoke::t_double: score = 1; break; default: break; } break; case INTSXP: switch(elem) { case Smoke::t_enum: if (inherits(value, "QtEnum")) score = 2; else score = 1; break; case Smoke::t_int: score = 3; break; case Smoke::t_uint: if (inherits(value, "QtEnum")) { score = 3; // favor QFlags over enums break; } case Smoke::t_long: case Smoke::t_ulong: case Smoke::t_float: case Smoke::t_double: score = 2; break; case Smoke::t_short: case Smoke::t_ushort: case Smoke::t_uchar: score = 1; break; default: break; } break; case REALSXP: switch(elem) { case Smoke::t_double: score = 3; break; case Smoke::t_float: case Smoke::t_uint: // to distinguish int/uint score = 2; break; case Smoke::t_int: case Smoke::t_long: case Smoke::t_ulong: case Smoke::t_short: case Smoke::t_ushort: case Smoke::t_uchar: case Smoke::t_enum: score = 1; break; default: break; } break; case STRSXP: if (elem == Smoke::t_char && strlen(CHAR(asChar(value))) == 1) score = 2; break; case ENVSXP: if (elem == Smoke::t_class) { SmokeObject *o = SmokeObject::fromSexp(value); if (o) { const char *smokeClass = type.className(); if (o->className() == smokeClass) score = 3; else if (o->instanceOf(smokeClass)) score = 2; /* Not clear if we want to support this C++ feature else { Method *m = Class::fromSmokeType(type)->findImplicitConverter(o); if (m) { score = 1; delete m; } } */ } } break; case NILSXP: if (type.isPtr()) score = 1; break; default: break; } return score; }