Skip to content

Commit 038ce2b

Browse files
remove targetDesc helper in favor of splitting cases for i18n (#6489)
1 parent c581ffa commit 038ce2b

File tree

2 files changed

+31
-18
lines changed

2 files changed

+31
-18
lines changed

inst/tests/tests.Rraw

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14480,7 +14480,7 @@ test(2005.10, set(DT, 1L, "d", expression(x+2)), error="type 'expression' cannot
1448014480
test(2005.11, set(DT, 1L, "e", expression(x+2)), error="type 'expression' cannot be coerced to 'double'")
1448114481
test(2005.12, set(DT, 1L, "f", expression(x+2)), error="type 'expression' cannot be coerced to 'complex'")
1448214482
test(2005.30, DT[2:3,c:=c(TRUE,FALSE), verbose=3L]$c, as.raw(INT(7,1,0)), ## note verbose=3L for more deeper verbose output due to memrecycle messages when it is being re-used internally #4491
14483-
output="Zero-copy coerce when assigning 'logical' to 'raw' column 3 named 'c'")
14483+
output="Zero-copy coerce when assigning 'logical' to column 3 named 'c' which is 'raw'")
1448414484
test(2005.31, set(DT,1L,"c",NA)$c, as.raw(INT(0,1,0)))
1448514485
test(2005.32, set(DT,1:2,"c",INT(-1,255))$c, as.raw(INT(0,255,0)),
1448614486
warning="-1.*integer.*position 1 taken as 0 when assigning.*raw.*column 3 named 'c'")

src/assign.c

Lines changed: 30 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -742,12 +742,6 @@ SEXP assign(SEXP dt, SEXP rows, SEXP cols, SEXP newcolnames, SEXP values)
742742
#define MSGSIZE 1000
743743
static char memrecycle_message[MSGSIZE+1]; // returned to rbindlist so it can prefix with which one of the list of data.table-like objects
744744

745-
const char *targetDesc(const int colnum, const char *colname) {
746-
static char str[501]; // #5463
747-
snprintf(str, 500, colnum==0 ? _("target vector") : _("column %d named '%s'"), colnum, colname);
748-
return str;
749-
}
750-
751745
const char *memrecycle(const SEXP target, const SEXP where, const int start, const int len, SEXP source, const int sourceStart, const int sourceLen, const int colnum, const char *colname)
752746
// like memcpy but recycles single-item source
753747
// 'where' a 1-based INTEGER vector subset of target to assign to, or NULL or integer()
@@ -792,7 +786,10 @@ const char *memrecycle(const SEXP target, const SEXP where, const int start, con
792786
for (int i=0; i<slen; ++i) {
793787
const int val = sd[i+soff];
794788
if ((val<1 && val!=NA_INTEGER) || val>nlevel) {
795-
error(_("Assigning factor numbers to %s. But %d is outside the level range [1,%d]"), targetDesc(colnum, colname), val, nlevel);
789+
if (colnum == 0)
790+
error(_("Assigning factor numbers to target vector. But %d is outside the level range [1,%d]"), val, nlevel);
791+
else
792+
error(_("Assigning factor numbers to column %d named '%s'. But %d is outside the level range [1,%d]"), colnum, colname, val, nlevel);
796793
}
797794
}
798795
} else {
@@ -801,7 +798,10 @@ const char *memrecycle(const SEXP target, const SEXP where, const int start, con
801798
const double val = sd[i+soff];
802799
// Since nlevel is an int, val < 1 || val > nlevel will deflect UB guarded against in PR #5832
803800
if (!ISNAN(val) && (val < 1 || val > nlevel || val != (int)val)) {
804-
error(_("Assigning factor numbers to %s. But %f is outside the level range [1,%d], or is not a whole number."), targetDesc(colnum, colname), val, nlevel);
801+
if (colnum == 0)
802+
error(_("Assigning factor numbers to target vector. But %f is outside the level range [1,%d], or is not a whole number."), val, nlevel);
803+
else
804+
error(_("Assigning factor numbers to column %d named '%s'. But %f is outside the level range [1,%d], or is not a whole number."), colnum, colname, val, nlevel);
805805
}
806806
}
807807
}
@@ -893,27 +893,38 @@ const char *memrecycle(const SEXP target, const SEXP where, const int start, con
893893
}
894894
}
895895
} else if (isString(source) && !isString(target) && !isNewList(target)) {
896-
warning(_("Coercing 'character' RHS to '%s' to match the type of %s."), targetIsI64?"integer64":type2char(TYPEOF(target)), targetDesc(colnum, colname));
896+
if (colnum == 0)
897+
warning(_("Coercing 'character' RHS to '%s' to match the type of target vector."), targetIsI64?"integer64":type2char(TYPEOF(target)));
898+
else
899+
warning(_("Coercing 'character' RHS to '%s' to match the type of column %d named '%s'."), targetIsI64?"integer64":type2char(TYPEOF(target)), colnum, colname);
897900
// this "Coercing ..." warning first to give context in case coerceVector warns 'NAs introduced by coercion'
898901
// and also because 'character' to integer/double coercion is often a user mistake (e.g. wrong target column, or wrong
899902
// variable on RHS) which they are more likely to appreciate than find inconvenient
900903
source = PROTECT(coerceVector(source, TYPEOF(target))); protecti++;
901904
} else if (isNewList(source) && !isNewList(target)) {
902905
if (targetIsI64) {
903-
error(_("Cannot coerce 'list' RHS to 'integer64' to match the type of %s."), targetDesc(colnum, colname));
906+
if (colnum == 0)
907+
error(_("Cannot coerce 'list' RHS to 'integer64' to match the type of target vector."));
908+
else
909+
error(_("Cannot coerce 'list' RHS to 'integer64' to match the type of column %d named '%s'."), colnum, colname);
904910
// because R's coerceVector doesn't know about integer64
905911
}
906912
// as in base R; e.g. let as.double(list(1,2,3)) work but not as.double(list(1,c(2,4),3))
907913
// relied on by NNS, simstudy and table.express; tests 1294.*
908-
warning(_("Coercing 'list' RHS to '%s' to match the type of %s."), type2char(TYPEOF(target)), targetDesc(colnum, colname));
914+
if (colnum == 0)
915+
warning(_("Coercing 'list' RHS to '%s' to match the type of target vector."), type2char(TYPEOF(target)));
916+
else
917+
warning(_("Coercing 'list' RHS to '%s' to match the type of column %d named '%s'."), type2char(TYPEOF(target)), colnum, colname);
909918
source = PROTECT(coerceVector(source, TYPEOF(target))); protecti++;
910919
} else if ((TYPEOF(target)!=TYPEOF(source) || targetIsI64!=sourceIsI64) && !isNewList(target)) {
911920
if (GetVerbose()>=3) {
912921
// only take the (small) cost of GetVerbose() (search of options() list) when types don't match
913-
Rprintf(_("Zero-copy coerce when assigning '%s' to '%s' %s.\n"),
914-
sourceIsI64 ? "integer64" : type2char(TYPEOF(source)),
915-
targetIsI64 ? "integer64" : type2char(TYPEOF(target)),
916-
targetDesc(colnum, colname));
922+
const char *sourceType = sourceIsI64 ? "integer64" : type2char(TYPEOF(source));
923+
const char *targetType = targetIsI64 ? "integer64" : type2char(TYPEOF(target));
924+
if (colnum == 0)
925+
Rprintf(_("Zero-copy coerce when assigning '%s' to '%s' target vector.\n"), sourceType, targetType);
926+
else
927+
Rprintf(_("Zero-copy coerce when assigning '%s' to column %d named '%s' which is '%s'.\n"), sourceType, colnum, colname, targetType);
917928
}
918929
// The following checks are up front here, otherwise we'd need them twice in the two branches
919930
// inside BODY that cater for 'where' or not. Maybe there's a way to merge the two macros in future.
@@ -927,8 +938,10 @@ const char *memrecycle(const SEXP target, const SEXP where, const int start, con
927938
const char *sType = sourceIsI64 ? "integer64" : type2char(TYPEOF(source)); \
928939
const char *tType = targetIsI64 ? "integer64" : type2char(TYPEOF(target)); \
929940
snprintf(memrecycle_message, MSGSIZE, \
930-
"%"FMT" (type '%s') at RHS position %d "TO" when assigning to type '%s' (%s)", \
931-
FMTVAL, sType, i+1, tType, targetDesc(colnum, colname)); \
941+
colnum == 0 \
942+
? _("%"FMT" (type '%s') at RHS position %d "TO" when assigning to type '%s' (target vector)") \
943+
: _("%"FMT" (type '%s') at RHS position %d "TO" when assigning to type '%s' (column %d named '%s')"), \
944+
FMTVAL, sType, i+1, tType, colnum, colname); \
932945
/* string returned so that rbindlist/dogroups can prefix it with which item of its list this refers to */ \
933946
break; \
934947
} \

0 commit comments

Comments
 (0)