Esempio n. 1
0
template<> int scoreArg<QByteArray>(SEXP arg, const SmokeType &type) {
  if (TYPEOF(arg) == STRSXP)
    return type.isPtr() ? 1 : 2;
  else if (TYPEOF(arg) == RAWSXP)
    return type.isPtr() ? 2 : 3;
  else return scoreArg_basetype(arg, type);
}
Esempio n. 2
0
template<> int scoreArg<unsigned char>(SEXP arg, const SmokeType &type) {
  int score = 0;
  // we consider ptr as array of bytes, and Qt will not copy, but R might free
  if (!type.isPtr()) {
    switch(TYPEOF(arg)) {
    case RAWSXP:
      score = 3;
      break;
    case INTSXP:
    case REALSXP:
      score = 1;
      break;
    default:
      break;
    }
  }
  return score;
}
Esempio n. 3
0
template<> int scoreArg<QString>(SEXP arg, const SmokeType &type) {
  if (TYPEOF(arg) == STRSXP)
    return type.isPtr() ? 1 : 3;
  else return 0;
}
Esempio n. 4
0
/* 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;
}