Skip to content

Commit 4b2dae9

Browse files
authored
Merge branch 'master' into issue2855
2 parents 64b859e + 8039a23 commit 4b2dae9

File tree

5 files changed

+29
-15
lines changed

5 files changed

+29
-15
lines changed

NEWS.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,8 @@
105105
106106
17. `t1 - t2`, where one is an `IDate` and the other is a `Date`, are now consistent with the case where both are `IDate` or both are `Date`, [#4749](https://github.com/Rdatatable/data.table/issues/4749). Thanks @George9000 for the report and @MichaelChirico for the fix.
107107
108+
18. `fwrite` now allows `dec` to be the same as `sep` for edge cases where only one will be written, e.g. 0-row or 1-column tables. [#7227](https://github.com/Rdatatable/data.table/issues/7227). Thanks @MichaelChirico for the report and @venom1204 for the fix.
109+
108110
### NOTES
109111
110112
1. The following in-progress deprecations have proceeded:

R/fwrite.R

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ fwrite = function(x, file="", append=FALSE, quote="auto",
4444
is.character(sep) && length(sep)==1L && (nchar(sep) == 1L || identical(sep, "")),
4545
is.character(sep2) && length(sep2)==3L && nchar(sep2[2L])==1L,
4646
is.character(dec) && length(dec)==1L && nchar(dec) == 1L,
47-
dec != sep, # sep2!=dec and sep2!=sep checked at C level when we know if list columns are present
47+
`dec and sep must be distinct whenever both might be needed` = (!NROW(x) || NCOL(x) <= 1L || dec != sep), # sep2!=dec and sep2!=sep checked at C level when we know if list columns are present
4848
is.character(eol) && length(eol)==1L,
4949
length(qmethod) == 1L && qmethod %chin% c("double", "escape"),
5050
length(compress) == 1L && compress %chin% c("auto", "none", "gzip"),

inst/tests/tests.Rraw

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10977,9 +10977,9 @@ test(1732.7, fwrite(DT, quote='auto'), output='A,B\n,5\nNA,7\n"",0\nmonty,')
1097710977
test(1732.8, fwrite(DT, quote='auto', na="NA"), output='A,B\nNA,5\n"NA",7\n"",0\n"monty",NA')
1097810978

1097910979
# dec=","
10980-
test(1733.1, fwrite(data.table(pi),dec=","), error=base_messages$stopifnot("dec != sep"))
10980+
# Test 1733.1 removed, see #7227
1098110981
test(1733.2, fwrite(data.table(c(1.2,-8.0,pi,67.99),1:4),dec=",",sep=";"),
10982-
output="V1;V2\n1,2;1\n-8;2\n3,14159265358979;3\n67,99;4")
10982+
output="V1;V2\n1,2;1\n-8;2\n3,14159265358979;3\n67,99;4")
1098310983

1098410984
# fwrite implied and actual row.names
1098510985
DT = data.table(foo=1:3,bar=c(1.2,9.8,-6.0))
@@ -21593,3 +21593,12 @@ test(2336.3, all.equal(as.Date(t1) - t2, t1 - t2))
2159321593
test(2336.4, all.equal(as.Date(t2) - t1, t2 - t1))
2159421594
test(2336.5, all.equal(t1 - as.Date(t2), t1 - t2))
2159521595
test(2336.6, all.equal(t2 - as.Date(t1), t2 - t1))
21596+
21597+
# fwrite: allow dec=',' with single column, #7227
21598+
test(2337.1, fwrite(data.table(1), dec=","), NULL)
21599+
if (getRversion() >= "4.0.0") { # rely on stopifnot(named = ...) for correct message
21600+
test(2337.2, fwrite(data.table(0.1, 0.2), dec=",", sep=","), error = "dec and sep must be distinct")
21601+
}
21602+
test(2337.3, is.null(fwrite(data.table(c(0.1, 0.2)), dec=",", sep="\t")))
21603+
test(2337.4, is.null(fwrite(data.table(a=numeric(), b=numeric()), dec=",", sep=",")))
21604+
test(2337.5, is.null(fwrite(data.table(a=numeric()), dec=",", sep=",")))

src/fmelt.c

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -103,12 +103,14 @@ static const char *concat(SEXP vec, SEXP idx) {
103103
// with missing inputs, and -1 in the positions with column names not
104104
// found. Column names not found will eventually cause error via
105105
// uniq_diff().
106-
SEXP chmatch_na(SEXP x, SEXP table){
107-
SEXP ans;
108-
PROTECT(ans = chmatch(x, table, -1));
109-
for(int i=0; i<length(ans); i++){
110-
if(STRING_ELT(x, i) == NA_STRING){
111-
INTEGER(ans)[i] = NA_INTEGER;
106+
SEXP chmatch_na(SEXP x, SEXP table)
107+
{
108+
SEXP ans = chmatch(x, table, -1);
109+
PROTECT(ans);
110+
int *restrict target = INTEGER(ans);
111+
for (int i = 0; i < length(ans); i++) {
112+
if (STRING_ELT(x, i) == NA_STRING) {
113+
target[i] = NA_INTEGER;
112114
}
113115
}
114116
UNPROTECT(1);

src/nqrecreateindices.c

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,24 @@
11
#include "data.table.h"
2+
#include <string.h>
23

34
// TODO: Add oxygen style comments and cleanup var names.
45
// See other TODOs inside the function.
56
SEXP nqRecreateIndices(SEXP xo, SEXP len, SEXP indices, SEXP nArg, SEXP nomatch)
67
{
7-
R_len_t n = INTEGER(nArg)[0], xn = length(xo);
8+
const R_len_t n = INTEGER_RO(nArg)[0], xn = length(xo);
89
SEXP ans, newstarts, newlen;
910
ans = PROTECT(allocVector(VECSXP, 2));
1011
SET_VECTOR_ELT(ans, 0, (newstarts = allocVector(INTSXP, n)));
1112
SET_VECTOR_ELT(ans, 1, (newlen = allocVector(INTSXP, n)));
1213

1314
int *inewlen = INTEGER(newlen);
14-
const int *iindices = INTEGER(indices);
15-
const int *ilen = INTEGER(len);
16-
const int *ixo = INTEGER(xo);
17-
const int inomatch = isNull(nomatch) ? 0 : INTEGER(nomatch)[0];
15+
const int *iindices = INTEGER_RO(indices);
16+
const int *ilen = INTEGER_RO(len);
17+
const int *ixo = INTEGER_RO(xo);
18+
const int inomatch = isNull(nomatch) ? 0 : INTEGER_RO(nomatch)[0];
1819
int *inewstarts = INTEGER(newstarts);
1920

20-
for (int i = 0; i < n; i++) inewlen[i] = 0;
21+
memset(inewlen, 0, n * sizeof(int));
2122

2223
// simplifying logic ... also fixes #2275
2324
for (int i = 0; i < length(indices); i++) {

0 commit comments

Comments
 (0)