Skip to content

Commit 41fc24f

Browse files
Use STRING_PTR_RO, not STRING_PTR (#6312)
* Move to STRING_PTR_RO in all sure-fire 'const' cases * Remaining cases compile as well * Conditionally define STRING_PTR_RO on 3.3.0<=R<3.5.0
1 parent 1600b51 commit 41fc24f

16 files changed

+59
-56
lines changed

src/assign.c

+10-10
Original file line numberDiff line numberDiff line change
@@ -799,7 +799,7 @@ const char *memrecycle(const SEXP target, const SEXP where, const int start, con
799799
if (sourceIsFactor) { sourceLevels=PROTECT(getAttrib(source, R_LevelsSymbol)); protecti++; }
800800
if (!sourceIsFactor || !R_compute_identical(sourceLevels, targetLevels, 0)) { // !sourceIsFactor for test 2115.6
801801
const int nTargetLevels=length(targetLevels), nSourceLevels=length(sourceLevels);
802-
const SEXP *targetLevelsD=STRING_PTR(targetLevels), *sourceLevelsD=STRING_PTR(sourceLevels);
802+
const SEXP *targetLevelsD=STRING_PTR_RO(targetLevels), *sourceLevelsD=STRING_PTR_RO(sourceLevels);
803803
SEXP newSource = PROTECT(allocVector(INTSXP, length(source))); protecti++;
804804
savetl_init();
805805
for (int k=0; k<nTargetLevels; ++k) {
@@ -835,7 +835,7 @@ const char *memrecycle(const SEXP target, const SEXP where, const int start, con
835835
newSourceD[i] = val==NA_INTEGER ? NA_INTEGER : -TRUELENGTH(sourceLevelsD[val-1]); // retains NA factor levels here via TL(NA_STRING); e.g. ordered factor
836836
}
837837
} else {
838-
const SEXP *sourceD = STRING_PTR(source);
838+
const SEXP *sourceD = STRING_PTR_RO(source);
839839
for (int i=0; i<nSource; ++i) { // convert source integers to refer to target levels
840840
const SEXP val = sourceD[i];
841841
newSourceD[i] = val==NA_STRING ? NA_INTEGER : -TRUELENGTH(val);
@@ -1103,7 +1103,7 @@ const char *memrecycle(const SEXP target, const SEXP where, const int start, con
11031103
} break;
11041104
case STRSXP :
11051105
if (sourceIsFactor) {
1106-
const SEXP *ld = STRING_PTR(PROTECT(getAttrib(source, R_LevelsSymbol))); protecti++;
1106+
const SEXP *ld = STRING_PTR_RO(PROTECT(getAttrib(source, R_LevelsSymbol))); protecti++;
11071107
BODY(int, INTEGER, SEXP, val==NA_INTEGER ? NA_STRING : ld[val-1], SET_STRING_ELT(target, off+i, cval))
11081108
} else {
11091109
if (!isString(source)) {
@@ -1125,7 +1125,7 @@ const char *memrecycle(const SEXP target, const SEXP where, const int start, con
11251125
source = PROTECT(coerceVector(source, STRSXP)); protecti++;
11261126
}
11271127
}
1128-
BODY(SEXP, STRING_PTR, SEXP, val, SET_STRING_ELT(target, off+i, cval))
1128+
BODY(SEXP, STRING_PTR_RO, SEXP, val, SET_STRING_ELT(target, off+i, cval))
11291129
}
11301130
case VECSXP :
11311131
case EXPRSXP : { // #546 #4350
@@ -1140,12 +1140,12 @@ const char *memrecycle(const SEXP target, const SEXP where, const int start, con
11401140
// the UNPROTECT can be at the end of the CAST before the SET_VECTOR_ELT, because SET_VECTOR_ELT will protect it and there's no other code in between
11411141
// the PROTECT is now needed because of the call to LOGICAL() which could feasibly gc inside it.
11421142
// copyMostAttrib is inside CAST so as to be outside loop. See the history in #4350 and its follow up
1143-
case RAWSXP: BODY(Rbyte, RAW, SEXP, PROTECT(allocVector(RAWSXP, 1));RAW(cval)[0]=val;copyMostAttrib(source,cval);UNPROTECT(1), SET_VECTOR_ELT(target,off+i,cval))
1144-
case LGLSXP: BODY(int, LOGICAL, SEXP, PROTECT(allocVector(LGLSXP, 1));LOGICAL(cval)[0]=val;copyMostAttrib(source,cval);UNPROTECT(1), SET_VECTOR_ELT(target,off+i,cval))
1145-
case INTSXP: BODY(int, INTEGER, SEXP, PROTECT(allocVector(INTSXP, 1));INTEGER(cval)[0]=val;copyMostAttrib(source,cval);UNPROTECT(1), SET_VECTOR_ELT(target,off+i,cval))
1146-
case REALSXP: BODY(double, REAL, SEXP, PROTECT(allocVector(REALSXP, 1));REAL(cval)[0]=val;copyMostAttrib(source,cval);UNPROTECT(1), SET_VECTOR_ELT(target,off+i,cval))
1147-
case CPLXSXP: BODY(Rcomplex, COMPLEX, SEXP, PROTECT(allocVector(CPLXSXP, 1));COMPLEX(cval)[0]=val;copyMostAttrib(source,cval);UNPROTECT(1), SET_VECTOR_ELT(target,off+i,cval))
1148-
case STRSXP: BODY(SEXP, STRING_PTR, SEXP, PROTECT(allocVector(STRSXP, 1));SET_STRING_ELT(cval, 0, val);copyMostAttrib(source,cval);UNPROTECT(1), SET_VECTOR_ELT(target,off+i,cval))
1143+
case RAWSXP: BODY(Rbyte, RAW, SEXP, PROTECT(allocVector(RAWSXP, 1));RAW(cval)[0]=val;copyMostAttrib(source,cval);UNPROTECT(1), SET_VECTOR_ELT(target,off+i,cval))
1144+
case LGLSXP: BODY(int, LOGICAL, SEXP, PROTECT(allocVector(LGLSXP, 1));LOGICAL(cval)[0]=val;copyMostAttrib(source,cval);UNPROTECT(1), SET_VECTOR_ELT(target,off+i,cval))
1145+
case INTSXP: BODY(int, INTEGER, SEXP, PROTECT(allocVector(INTSXP, 1));INTEGER(cval)[0]=val;copyMostAttrib(source,cval);UNPROTECT(1), SET_VECTOR_ELT(target,off+i,cval))
1146+
case REALSXP: BODY(double, REAL, SEXP, PROTECT(allocVector(REALSXP, 1));REAL(cval)[0]=val;copyMostAttrib(source,cval);UNPROTECT(1), SET_VECTOR_ELT(target,off+i,cval))
1147+
case CPLXSXP: BODY(Rcomplex, COMPLEX, SEXP, PROTECT(allocVector(CPLXSXP, 1));COMPLEX(cval)[0]=val;copyMostAttrib(source,cval);UNPROTECT(1), SET_VECTOR_ELT(target,off+i,cval))
1148+
case STRSXP: BODY(SEXP, STRING_PTR_RO, SEXP, PROTECT(allocVector(STRSXP, 1));SET_STRING_ELT(cval, 0, val);copyMostAttrib(source,cval);UNPROTECT(1), SET_VECTOR_ELT(target,off+i,cval))
11491149
case VECSXP:
11501150
case EXPRSXP: BODY(SEXP, SEXPPTR_RO, SEXP, val, SET_VECTOR_ELT(target,off+i,cval))
11511151
default: COERCE_ERROR("list");

src/between.c

+3-3
Original file line numberDiff line numberDiff line change
@@ -160,9 +160,9 @@ SEXP between(SEXP x, SEXP lower, SEXP upper, SEXP incbounds, SEXP NAboundsArg, S
160160
break;
161161

162162
case STRSXP: {
163-
const SEXP *lp = STRING_PTR(lower);
164-
const SEXP *up = STRING_PTR(upper);
165-
const SEXP *xp = STRING_PTR(x);
163+
const SEXP *lp = STRING_PTR_RO(lower);
164+
const SEXP *up = STRING_PTR_RO(upper);
165+
const SEXP *xp = STRING_PTR_RO(x);
166166
#define LCMP (strcmp(CHAR(ENC2UTF8(l)),CHAR(ENC2UTF8(elem)))<=-open)
167167
#define UCMP (strcmp(CHAR(ENC2UTF8(elem)),CHAR(ENC2UTF8(u)))<=-open)
168168
// TODO if all ascii can be parallel, otherwise ENC2UTF8 could allocate

src/bmerge.c

+2-2
Original file line numberDiff line numberDiff line change
@@ -340,8 +340,8 @@ void bmerge_r(int xlowIn, int xuppIn, int ilowIn, int iuppIn, int col, int thisg
340340
case STRSXP : {
341341
// op[col]==EQ checked up front to avoid an if() here and non-thread-safe error()
342342
// not sure why non-EQ is not supported for STRSXP though as it seems straightforward (StrCmp returns sign to indicate GT or LT)
343-
const SEXP *icv = STRING_PTR(ic);
344-
const SEXP *xcv = STRING_PTR(xc);
343+
const SEXP *icv = STRING_PTR_RO(ic);
344+
const SEXP *xcv = STRING_PTR_RO(xc);
345345
const SEXP ival = ENC2UTF8(icv[ir]);
346346
#undef ISNAT
347347
#undef WRAP

src/chmatch.c

+3-3
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ static SEXP chmatchMain(SEXP x, SEXP table, int nomatch, bool chin, bool chmatch
1010
if (TYPEOF(x) == SYMSXP) {
1111
if (xlen!=1)
1212
error(_("Internal error: length of SYMSXP is %d not 1"), xlen); // # nocov
13-
sym = PRINTNAME(x); // so we can do &sym to get a length 1 (const SEXP *)STRING_PTR(x) and save an alloc for coerce to STRSXP
13+
sym = PRINTNAME(x); // so we can do &sym to get a length 1 (const SEXP *)STRING_PTR_RO(x) and save an alloc for coerce to STRSXP
1414
} else if (!isString(x) && !isSymbol(x) && !isNull(x)) {
1515
if (chin && !isVectorAtomic(x)) {
1616
return ScalarLogical(FALSE);
@@ -40,9 +40,9 @@ static SEXP chmatchMain(SEXP x, SEXP table, int nomatch, bool chin, bool chmatch
4040
if (isSymbol(x)) {
4141
xd = &sym;
4242
} else {
43-
xd = STRING_PTR(PROTECT(coerceUtf8IfNeeded(x))); nprotect++;
43+
xd = STRING_PTR_RO(PROTECT(coerceUtf8IfNeeded(x))); nprotect++;
4444
}
45-
const SEXP *td = STRING_PTR(PROTECT(coerceUtf8IfNeeded(table))); nprotect++;
45+
const SEXP *td = STRING_PTR_RO(PROTECT(coerceUtf8IfNeeded(table))); nprotect++;
4646
if (xlen==1) {
4747
ansd[0] = nomatch;
4848
for (int i=0; i<tablelen; ++i) {

src/cj.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ SEXP cj(SEXP base_list) {
6262
}
6363
} break;
6464
case STRSXP: {
65-
const SEXP *sourceP = STRING_PTR(source);
65+
const SEXP *sourceP = STRING_PTR_RO(source);
6666
int start = 0;
6767
for (int i=0; i<ncopy; ++i) {
6868
for (int j=0; j<thislen; ++j) {

src/coalesce.c

+2-2
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,7 @@ SEXP coalesce(SEXP x, SEXP inplaceArg) {
141141
}
142142
} break;
143143
case STRSXP: {
144-
const SEXP *xP = STRING_PTR(first);
144+
const SEXP *xP = STRING_PTR_RO(first);
145145
SEXP finalVal=NA_STRING;
146146
int k=0;
147147
for (int j=0; j<nval; ++j) {
@@ -152,7 +152,7 @@ SEXP coalesce(SEXP x, SEXP inplaceArg) {
152152
finalVal = tt;
153153
break;
154154
}
155-
valP[k++] = STRING_PTR(item);
155+
valP[k++] = STRING_PTR_RO(item);
156156
}
157157
const bool final = (finalVal!=NA_STRING);
158158
for (int i=0; i<nrow; ++i) {

src/data.table.h

+3
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@
1212
#endif
1313
#include <Rinternals.h>
1414
#define SEXPPTR_RO(x) ((const SEXP *)DATAPTR_RO(x)) // to avoid overhead of looped STRING_ELT and VECTOR_ELT
15+
#ifndef STRING_PTR_RO
16+
#define STRING_PTR_RO STRING_PTR
17+
#endif
1518
#include <stdint.h> // for uint64_t rather than unsigned long long
1619
#include <stdbool.h>
1720
#include "types.h"

src/fifelse.c

+5-5
Original file line numberDiff line numberDiff line change
@@ -146,9 +146,9 @@ SEXP fifelseR(SEXP l, SEXP a, SEXP b, SEXP na) {
146146
}
147147
} break;
148148
case STRSXP : {
149-
const SEXP *restrict pa = na_a ? NULL : STRING_PTR(a);
150-
const SEXP *restrict pb = na_b ? NULL : STRING_PTR(b);
151-
const SEXP *restrict pna = na_n ? NULL : STRING_PTR(na);
149+
const SEXP *restrict pa = na_a ? NULL : STRING_PTR_RO(a);
150+
const SEXP *restrict pb = na_b ? NULL : STRING_PTR_RO(b);
151+
const SEXP *restrict pna = na_n ? NULL : STRING_PTR_RO(na);
152152
const SEXP na = NA_STRING;
153153
for (int64_t i=0; i<len0; ++i) {
154154
SET_STRING_ELT(
@@ -358,8 +358,8 @@ SEXP fcaseR(SEXP na, SEXP rho, SEXP args) {
358358
}
359359
} break;
360360
case STRSXP: {
361-
const SEXP *restrict pouts = STRING_PTR(outs);
362-
const SEXP pna = nonna ? STRING_PTR(na)[0] : NA_STRING;
361+
const SEXP *restrict pouts = STRING_PTR_RO(outs);
362+
const SEXP pna = nonna ? STRING_PTR_RO(na)[0] : NA_STRING;
363363
for (int64_t j=0; j<len2; ++j) {
364364
const int64_t idx = imask ? j : p[j];
365365
if (pcons[idx]==1) {

src/fmelt.c

+3-3
Original file line numberDiff line numberDiff line change
@@ -402,13 +402,13 @@ static SEXP combineFactorLevels(SEXP factorLevels, SEXP target, int * factorType
402402
SEXP ans = PROTECT(allocVector(INTSXP, nrow));
403403
SEXP *levelsRaw = (SEXP *)R_alloc(maxlevels, sizeof(SEXP)); // allocate for worst-case all-unique levels
404404
int *ansd = INTEGER(ans);
405-
const SEXP *targetd = STRING_PTR(target);
405+
const SEXP *targetd = STRING_PTR_RO(target);
406406
savetl_init();
407407
// no alloc or any fail point until savetl_end()
408408
int nlevel=0;
409409
for (int i=0; i<nitem; ++i) {
410410
const SEXP this = VECTOR_ELT(factorLevels, i);
411-
const SEXP *thisd = STRING_PTR(this);
411+
const SEXP *thisd = STRING_PTR_RO(this);
412412
const int thisn = length(this);
413413
for (int k=0; k<thisn; ++k) {
414414
SEXP s = thisd[k];
@@ -745,7 +745,7 @@ SEXP getidcols(SEXP DT, SEXP dtnames, Rboolean verbose, struct processData *data
745745
counter += thislen;
746746
}
747747
} else {
748-
const SEXP *s = STRING_PTR(thiscol); // to reduce overhead of STRING_ELT() inside loop below. Read-only hence const.
748+
const SEXP *s = STRING_PTR_RO(thiscol); // to reduce overhead of STRING_ELT() inside loop below. Read-only hence const.
749749
for (int j=0; j<data->lmax; ++j) {
750750
for (int k=0; k<data->nrow; ++k) {
751751
SET_STRING_ELT(target, j*data->nrow + k, s[k]);

src/forder.c

+7-7
Original file line numberDiff line numberDiff line change
@@ -277,7 +277,7 @@ static void cradix(SEXP *x, int n)
277277
free(cradix_xtmp); cradix_xtmp=NULL;
278278
}
279279

280-
static void range_str(SEXP *x, int n, uint64_t *out_min, uint64_t *out_max, int *out_na_count)
280+
static void range_str(const SEXP *x, int n, uint64_t *out_min, uint64_t *out_max, int *out_na_count)
281281
// group numbers are left in truelength to be fetched by WRITE_KEY
282282
{
283283
int na_count=0;
@@ -323,7 +323,7 @@ static void range_str(SEXP *x, int n, uint64_t *out_min, uint64_t *out_max, int
323323
SEXP *ustr3 = (SEXP *)malloc(ustr_n * sizeof(SEXP));
324324
if (!ustr3)
325325
STOP(_("Failed to alloc ustr3 when converting strings to UTF8")); // # nocov
326-
memcpy(ustr3, STRING_PTR(ustr2), ustr_n*sizeof(SEXP));
326+
memcpy(ustr3, STRING_PTR_RO(ustr2), ustr_n*sizeof(SEXP));
327327
// need to reset ustr_maxlen because we need ustr_maxlen for utf8 strings
328328
ustr_maxlen = 0;
329329
for (int i=0; i<ustr_n; i++) {
@@ -342,7 +342,7 @@ static void range_str(SEXP *x, int n, uint64_t *out_min, uint64_t *out_max, int
342342
int *tl = (int *)malloc(ustr_n * sizeof(int));
343343
if (!tl)
344344
STOP(_("Failed to alloc tl when converting strings to UTF8")); // # nocov
345-
SEXP *tt = STRING_PTR(ustr2);
345+
const SEXP *tt = STRING_PTR_RO(ustr2);
346346
for (int i=0; i<ustr_n; i++) tl[i] = TRUELENGTH(tt[i]); // fetches the o in ustr3 into tl which is ordered by ustr
347347
for (int i=0; i<ustr_n; i++) SET_TRUELENGTH(ustr3[i], 0); // reset to 0 tl of the UTF8 (and possibly non-UTF in ustr too)
348348
for (int i=0; i<ustr_n; i++) SET_TRUELENGTH(ustr[i], tl[i]); // put back the o into ustr's tl
@@ -552,7 +552,7 @@ SEXP forder(SEXP DT, SEXP by, SEXP retGrpArg, SEXP sortGroupsArg, SEXP ascArg, S
552552
break;
553553
case STRSXP :
554554
// need2utf8 now happens inside range_str on the uniques
555-
range_str(STRING_PTR(x), nrow, &min, &max, &na_count);
555+
range_str(STRING_PTR_RO(x), nrow, &min, &max, &na_count);
556556
break;
557557
default:
558558
STOP(_("Column %d passed to [f]order is type '%s', not yet supported."), col+1, type2char(TYPEOF(x)));
@@ -693,7 +693,7 @@ SEXP forder(SEXP DT, SEXP by, SEXP retGrpArg, SEXP sortGroupsArg, SEXP ascArg, S
693693
}
694694
break;
695695
case STRSXP : {
696-
SEXP *xd = STRING_PTR(x);
696+
const SEXP *xd = STRING_PTR_RO(x);
697697
#pragma omp parallel for num_threads(getDTthreads(nrow, true))
698698
for (int i=0; i<nrow; i++) {
699699
uint64_t elem=0;
@@ -1326,7 +1326,7 @@ SEXP issorted(SEXP x, SEXP by)
13261326
}
13271327
break;
13281328
case STRSXP : {
1329-
SEXP *xd = STRING_PTR(x);
1329+
const SEXP *xd = STRING_PTR_RO(x);
13301330
i = 0;
13311331
while (i<n && xd[i]==NA_STRING) i++;
13321332
if (i==n) break; // xd consists only of NA_STRING #5070
@@ -1369,7 +1369,7 @@ SEXP issorted(SEXP x, SEXP by)
13691369
break;
13701370
case STRSXP:
13711371
types[j] = 3;
1372-
ptrs[j] = (const char *)STRING_PTR(col);
1372+
ptrs[j] = (const char *)STRING_PTR_RO(col);
13731373
break;
13741374
default:
13751375
STOP(_("type '%s' is not yet supported"), type2char(TYPEOF(col))); // # nocov

src/frank.c

+2-2
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ SEXP dt_na(SEXP x, SEXP cols) {
3434
}
3535
break;
3636
case STRSXP: {
37-
const SEXP *sv = STRING_PTR(v);
37+
const SEXP *sv = STRING_PTR_RO(v);
3838
for (int j=0; j<n; ++j) ians[j] |= (sv[j] == NA_STRING);
3939
}
4040
break;
@@ -209,7 +209,7 @@ SEXP anyNA(SEXP x, SEXP cols) {
209209
while(j<n && iv[j]!=NA_INTEGER) j++;
210210
} break;
211211
case STRSXP: {
212-
const SEXP *sv = STRING_PTR(v);
212+
const SEXP *sv = STRING_PTR_RO(v);
213213
while (j<n && sv[j]!=NA_STRING) j++;
214214
} break;
215215
case REALSXP:

src/fwriteR.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ int getMaxStringLen(const SEXP *col, const int64_t n) {
4444
int getMaxCategLen(SEXP col) {
4545
col = getAttrib(col, R_LevelsSymbol);
4646
if (!isString(col)) error(_("Internal error: col passed to getMaxCategLen is missing levels"));
47-
return getMaxStringLen( STRING_PTR(col), LENGTH(col) );
47+
return getMaxStringLen( STRING_PTR_RO(col), LENGTH(col) );
4848
}
4949

5050
const char *getCategString(SEXP col, int64_t row) {

src/gsumm.c

+4-4
Original file line numberDiff line numberDiff line change
@@ -763,8 +763,8 @@ static SEXP gminmax(SEXP x, SEXP narm, const bool min)
763763
break;
764764
case STRSXP: {
765765
ans = PROTECT(allocVector(STRSXP, ngrp));
766-
const SEXP *ansd = STRING_PTR(ans);
767-
const SEXP *xd = STRING_PTR(x);
766+
const SEXP *ansd = STRING_PTR_RO(ans);
767+
const SEXP *xd = STRING_PTR_RO(x);
768768
if (!LOGICAL(narm)[0]) {
769769
const SEXP init = min ? char_maxString : R_BlankString; // char_maxString == "\xFF\xFF..." in init.c
770770
for (int i=0; i<ngrp; ++i) SET_STRING_ELT(ans, i, init);
@@ -978,7 +978,7 @@ static SEXP gfirstlast(SEXP x, const bool first, const int w, const bool headw)
978978
int64_t *ansd=(int64_t *)REAL(ans); DO(int64_t, REAL, NA_INTEGER64, ansd[ansi++]=val) }
979979
else { double *ansd=REAL(ans); DO(double, REAL, NA_REAL, ansd[ansi++]=val) } break;
980980
case CPLXSXP: { Rcomplex *ansd=COMPLEX(ans); DO(Rcomplex, COMPLEX, NA_CPLX, ansd[ansi++]=val) } break;
981-
case STRSXP: DO(SEXP, STRING_PTR, NA_STRING, SET_STRING_ELT(ans,ansi++,val)) break;
981+
case STRSXP: DO(SEXP, STRING_PTR_RO, NA_STRING, SET_STRING_ELT(ans,ansi++,val)) break;
982982
case VECSXP: DO(SEXP, SEXPPTR_RO, ScalarLogical(NA_LOGICAL), SET_VECTOR_ELT(ans,ansi++,val)) break;
983983
default:
984984
error(_("Type '%s' is not supported by GForce head/tail/first/last/`[`. Either add the namespace prefix (e.g. utils::head(.)) or turn off GForce optimization using options(datatable.optimize=1)"), type2char(TYPEOF(x)));
@@ -1266,7 +1266,7 @@ SEXP gshift(SEXP x, SEXP nArg, SEXP fillArg, SEXP typeArg) {
12661266
case REALSXP: { double *ansd=REAL(tmp); SHIFT(double, REAL, ansd[ansi++]=val); } break;
12671267
// integer64 is shifted as if it's REAL; and assigning fill=NA_INTEGER64 is ok as REAL
12681268
case CPLXSXP: { Rcomplex *ansd=COMPLEX(tmp); SHIFT(Rcomplex, COMPLEX, ansd[ansi++]=val); } break;
1269-
case STRSXP: { SHIFT(SEXP, STRING_PTR, SET_STRING_ELT(tmp,ansi++,val)); } break;
1269+
case STRSXP: { SHIFT(SEXP, STRING_PTR_RO, SET_STRING_ELT(tmp,ansi++,val)); } break;
12701270
//case VECSXP: { SHIFT(SEXP, SEXPPTR_RO, SET_VECTOR_ELT(tmp,ansi++,val)); } break;
12711271
default:
12721272
error(_("Type '%s' is not supported by GForce gshift. Either add the namespace prefix (e.g. data.table::shift(.)) or turn off GForce optimization using options(datatable.optimize=1)"), type2char(TYPEOF(x)));

0 commit comments

Comments
 (0)