JoinVisitor* join_visitor( SEXP left, SEXP right, const std::string& name_left, const std::string& name_right){ switch( TYPEOF(left) ){ case INTSXP: { bool lhs_factor = Rf_inherits( left, "factor" ) ; switch( TYPEOF(right) ){ case INTSXP: { bool rhs_factor = Rf_inherits( right, "factor" ) ; if( lhs_factor && rhs_factor){ return new JoinFactorFactorVisitor(left, right) ; } else if( !lhs_factor && !rhs_factor) { return new JoinVisitorImpl<INTSXP, INTSXP>( left, right ) ; } break ; } case REALSXP: { if( lhs_factor ){ incompatible_join_visitor(left, right, name_left, name_right) ; } else if( is_bare_vector(right) ) { return new JoinVisitorImpl<INTSXP, REALSXP>( left, right) ; } else { incompatible_join_visitor(left, right, name_left, name_right) ; } break ; // what else: perhaps we can have INTSXP which is a Date and REALSXP which is a Date too ? } case LGLSXP: { if( lhs_factor ){ incompatible_join_visitor(left, right, name_left, name_right) ; } else { return new JoinVisitorImpl<INTSXP, LGLSXP>( left, right) ; } break ; } case STRSXP: { if( lhs_factor ){ return new JoinFactorStringVisitor( left, right ); } } default: break ; } break ; } case REALSXP: { bool lhs_date = Rf_inherits( left, "Date" ) ; bool lhs_time = Rf_inherits( left, "POSIXct" ); switch( TYPEOF(right) ){ case REALSXP: { if( Rf_inherits( right, "Date") ){ if(lhs_date) return new DateJoinVisitor(left, right ) ; incompatible_join_visitor(left, right, name_left, name_right) ; } if( Rf_inherits( right, "POSIXct" ) ){ if( lhs_time ) return new POSIXctJoinVisitor(left, right ) ; incompatible_join_visitor(left, right, name_left, name_right) ; } if( is_bare_vector( right ) ){ return new JoinVisitorImpl<REALSXP, REALSXP>( left, right) ; } break ; } case INTSXP: { if( is_bare_vector(right) ){ return new JoinVisitorImpl<REALSXP, INTSXP>( left, right) ; } } default: break ; } } case LGLSXP: { switch( TYPEOF(right) ){ case LGLSXP: { return new JoinVisitorImpl<LGLSXP,LGLSXP> ( left, right ) ; } case INTSXP: { if( is_bare_vector(right) ){ return new JoinVisitorImpl<LGLSXP, INTSXP>( left, right ) ; } break ; } case REALSXP: { if( is_bare_vector(right) ){ return new JoinVisitorImpl<LGLSXP, REALSXP>( left, right ) ; } } default: break ; } break ; } case STRSXP: { switch( TYPEOF(right) ){ case INTSXP: { if( Rf_inherits(right, "factor" ) ){ return new JoinStringFactorVisitor( left, right ) ; } break ; } case STRSXP: { return new JoinVisitorImpl<STRSXP,STRSXP> ( left, right ) ; } default: break ; } break ; } default: break ; } incompatible_join_visitor(left, right, name_left, name_right) ; return 0 ; }
JoinVisitor* join_visitor(SEXP left, SEXP right, const SymbolString& name_left, const SymbolString& name_right, bool warn_) { // handle Date separately bool lhs_date = Rf_inherits(left, "Date"); bool rhs_date = Rf_inherits(right, "Date"); switch (lhs_date + rhs_date) { case 2: return date_join_visitor<ACCEPT_NA_MATCH>(left, right); case 1: stop("cannot join a Date object with an object that is not a Date object"); case 0: break; default: break; } bool lhs_time = Rf_inherits(left, "POSIXct"); bool rhs_time = Rf_inherits(right, "POSIXct"); switch (lhs_time + rhs_time) { case 2: return new POSIXctJoinVisitor<ACCEPT_NA_MATCH>(left, right); case 1: stop("cannot join a POSIXct object with an object that is not a POSIXct object"); case 0: break; default: break; } switch (TYPEOF(left)) { case CPLXSXP: { switch (TYPEOF(right)) { case CPLXSXP: return new JoinVisitorImpl<CPLXSXP, CPLXSXP, ACCEPT_NA_MATCH>(left, right); default: break; } break; } case INTSXP: { bool lhs_factor = Rf_inherits(left, "factor"); switch (TYPEOF(right)) { case INTSXP: { bool rhs_factor = Rf_inherits(right, "factor"); if (lhs_factor && rhs_factor) { if (same_levels(left, right)) { return new JoinVisitorImpl<INTSXP, INTSXP, ACCEPT_NA_MATCH>(left, right); } else { if (warn_) Rf_warning("joining factors with different levels, coercing to character vector"); return new JoinVisitorImpl<STRSXP, STRSXP, ACCEPT_NA_MATCH>(reencode_char(left), reencode_char(right)); } } else if (!lhs_factor && !rhs_factor) { return new JoinVisitorImpl<INTSXP, INTSXP, ACCEPT_NA_MATCH>(left, right); } break; } case REALSXP: { if (!lhs_factor && is_bare_vector(right)) { return new JoinVisitorImpl<INTSXP, REALSXP, ACCEPT_NA_MATCH>(left, right); } break; // what else: perhaps we can have INTSXP which is a Date and REALSXP which is a Date too ? } case LGLSXP: { if (!lhs_factor) { return new JoinVisitorImpl<INTSXP, LGLSXP, ACCEPT_NA_MATCH>(left, right); } break; } case STRSXP: { if (lhs_factor) { if (warn_) Rf_warning("joining factor and character vector, coercing into character vector"); return new JoinVisitorImpl<STRSXP, STRSXP, ACCEPT_NA_MATCH>(reencode_char(left), reencode_char(right)); } } default: break; } break; } case REALSXP: { switch (TYPEOF(right)) { case REALSXP: return new JoinVisitorImpl<REALSXP, REALSXP, ACCEPT_NA_MATCH>(left, right); case INTSXP: return new JoinVisitorImpl<REALSXP, INTSXP, ACCEPT_NA_MATCH>(left, right); default: break; } } case LGLSXP: { switch (TYPEOF(right)) { case LGLSXP: return new JoinVisitorImpl<LGLSXP, LGLSXP, ACCEPT_NA_MATCH> (left, right); case INTSXP: return new JoinVisitorImpl<LGLSXP, INTSXP, ACCEPT_NA_MATCH>(left, right); case REALSXP: return new JoinVisitorImpl<LGLSXP, REALSXP, ACCEPT_NA_MATCH>(left, right); default: break; } break; } case STRSXP: { switch (TYPEOF(right)) { case INTSXP: { if (Rf_inherits(right, "factor")) { if (warn_) Rf_warning("joining character vector and factor, coercing into character vector"); return new JoinVisitorImpl<STRSXP, STRSXP, ACCEPT_NA_MATCH>(reencode_char(left), reencode_char(right)); } break; } case STRSXP: { return new JoinVisitorImpl<STRSXP, STRSXP, ACCEPT_NA_MATCH>(reencode_char(left), reencode_char(right)); } default: break; } break; } default: break; } stop("Can't join on '%s' x '%s' because of incompatible types (%s / %s)", name_left.get_utf8_cstring(), name_right.get_utf8_cstring(), get_single_class(left), get_single_class(right) ); return 0; }
JoinVisitor* join_visitor( SEXP left, SEXP right, const std::string& name_left, const std::string& name_right, bool warn_ ){ // handle Date separately bool lhs_date = Rf_inherits( left, "Date") ; bool rhs_date = Rf_inherits( right, "Date") ; switch( lhs_date + rhs_date ){ case 2: return new DateJoinVisitor( left, right ) ; case 1: stop( "cannot join a Date object with an object that is not a Date object" ) ; case 0: break ; default: break ; } bool lhs_time = Rf_inherits( left, "POSIXct" ); bool rhs_time = Rf_inherits( right, "POSIXct" ); switch( lhs_time + rhs_time ){ case 2: return new POSIXctJoinVisitor( left, right) ; case 1: stop( "cannot join a POSIXct object with an object that is not a POSIXct object" ) ; case 0: break; default: break ; } switch( TYPEOF(left) ){ case CPLXSXP: { switch( TYPEOF(right) ){ case CPLXSXP: return new JoinVisitorImpl<CPLXSXP, CPLXSXP>( left, right ) ; default: break ; } break ; } case INTSXP: { bool lhs_factor = Rf_inherits( left, "factor" ) ; switch( TYPEOF(right) ){ case INTSXP: { bool rhs_factor = Rf_inherits( right, "factor" ) ; if( lhs_factor && rhs_factor){ if( same_levels(left, right) ){ return new JoinFactorFactorVisitor_SameLevels(left, right) ; } else { if(warn_) Rf_warning( "joining factors with different levels, coercing to character vector" ); return new JoinFactorFactorVisitor(left, right) ; } } else if( !lhs_factor && !rhs_factor) { return new JoinVisitorImpl<INTSXP, INTSXP>( left, right ) ; } break ; } case REALSXP: { if( lhs_factor ){ incompatible_join_visitor(left, right, name_left, name_right) ; } else if( is_bare_vector(right) ) { return new JoinVisitorImpl<INTSXP, REALSXP>( left, right) ; } else { incompatible_join_visitor(left, right, name_left, name_right) ; } break ; // what else: perhaps we can have INTSXP which is a Date and REALSXP which is a Date too ? } case LGLSXP: { if( lhs_factor ){ incompatible_join_visitor(left, right, name_left, name_right) ; } else { return new JoinVisitorImpl<INTSXP, LGLSXP>( left, right) ; } break ; } case STRSXP: { if( lhs_factor ){ if(warn_) Rf_warning( "joining factor and character vector, coercing into character vector" ) ; return new JoinFactorStringVisitor( left, right ); } } default: break ; } break ; } case REALSXP: { switch( TYPEOF(right) ){ case REALSXP: { if( is_bare_vector( right ) ){ return new JoinVisitorImpl<REALSXP, REALSXP>( left, right) ; } break ; } case INTSXP: { if( is_bare_vector(right) ){ return new JoinVisitorImpl<REALSXP, INTSXP>( left, right) ; } } default: break ; } } case LGLSXP: { switch( TYPEOF(right) ){ case LGLSXP: { return new JoinVisitorImpl<LGLSXP,LGLSXP> ( left, right ) ; } case INTSXP: { if( is_bare_vector(right) ){ return new JoinVisitorImpl<LGLSXP, INTSXP>( left, right ) ; } break ; } case REALSXP: { if( is_bare_vector(right) ){ return new JoinVisitorImpl<LGLSXP, REALSXP>( left, right ) ; } } default: break ; } break ; } case STRSXP: { switch( TYPEOF(right) ){ case INTSXP: { if( Rf_inherits(right, "factor" ) ){ if(warn_) Rf_warning( "joining character vector and factor, coercing into character vector" ) ; return new JoinStringFactorVisitor( left, right ) ; } break ; } case STRSXP: { return new JoinStringStringVisitor( left, right ) ; } default: break ; } break ; } default: break ; } incompatible_join_visitor(left, right, name_left, name_right) ; return 0 ; }