Esempio n. 1
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;
}
Esempio n. 2
0
QVariant qvariant_from_sexp(SEXP rvalue, int index) {
  QVariant variant;
  if (index == -1) {
    /* If a particular element is not selected, then non-lists of
       length one are considered scalars. Otherwise, collections.
       Except for raw vectors, which are naturally QByteArrays.
    */
    if (TYPEOF(rvalue) == RAWSXP)
      return QVariant(from_sexp<QByteArray>(rvalue));
    else if (TYPEOF(rvalue) == VECSXP || length(rvalue) > 1) {
      SEXP rlist = coerceVector(rvalue, VECSXP);
      if (getAttrib(rvalue, R_NamesSymbol) != R_NilValue)
        variant = asQVariantOfType(rlist, QMetaType::QVariantMap);
      else variant = asQVariantOfType(rlist, QMetaType::QVariantList);
      return variant;
    }
    index = 0;
  }
  switch(TYPEOF(rvalue)) {
  case RAWSXP:
    variant = qVariantFromValue(RAW(rvalue)[index]);
    break;
  case LGLSXP:
    // Rprintf("Logical\n");
    // FIXME: by converting to 'bool' all NA become TRUE
    variant = QVariant((bool)LOGICAL(rvalue)[index]);
    break;
  case REALSXP:
    // Rprintf("Real\n");
    variant = QVariant(REAL(rvalue)[index]);
    break;
  case INTSXP:
    // Rprintf("Integer\n");
    {
      SEXP levels;
      if ((levels = getAttrib(rvalue, R_LevelsSymbol)) != R_NilValue) {
        int level = INTEGER(rvalue)[index];
        SEXP level_str = NA_STRING;
        /*Rprintf("getting level: %d\n", level);*/
        if (level != NA_INTEGER)
          level_str = STRING_ELT(levels, level - 1);
        variant = QVariant(sexp2qstring(level_str));
      } else variant = QVariant(INTEGER(rvalue)[index]);
      break;
    }
  case STRSXP:
    // Rprintf("String\n");
    variant = QVariant(sexp2qstring(STRING_ELT(rvalue, index)));
    break;
  case EXTPTRSXP:
    // Rprintf("External pointer\n");
    variant = qVariantFromValue(unwrapPointer(rvalue, void));
    break;
  case VECSXP:
    variant = from_sexp<QVariant>(VECTOR_ELT(rvalue, index));
    break;
  case ENVSXP: {
    SmokeObject *so = SmokeObject::fromSexp(rvalue);
    if (so->instanceOf("QWidget"))
      variant =
        qVariantFromValue(reinterpret_cast<QWidget *>(so->castPtr("QWidget")));
    else if (so->instanceOf("QObject"))
      variant =
        qVariantFromValue(reinterpret_cast<QObject *>(so->castPtr("QObject")));
    else {
      QMetaType::Type type = (QMetaType::Type) QMetaType::type(so->className());
      if (type)
        variant = asQVariantOfType(rvalue, type, false);
      else variant = qVariantFromValue(so->ptr());
    }
  }
    break;
  case NILSXP: // invalid QVariant
    break;
  default:
    error("Converting to QVariant: unhandled R type");
  }
  return variant;
}