Skip to content

Commit

Permalink
fwrite: prefetch levels of factor columns. Should be faster when many…
Browse files Browse the repository at this point in the history
… factor columns. #580
  • Loading branch information
mattdowle committed Apr 12, 2016
1 parent d392ffc commit 9f9a4c3
Showing 1 changed file with 15 additions and 8 deletions.
23 changes: 15 additions & 8 deletions src/fwrite.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ void writefile(SEXP list_of_columns,
error("Column %d's length (%d) is not the same as column 1's length (%d)", i+1, length(VECTOR_ELT(list_of_columns, i)), nrows);
}

int error_number = 0;
//int error_number = 0;
int qmethod_escape = *LOGICAL(qmethod_escape_exp);

errno = 0; /* clear flag possibly set by previous errors */
Expand All @@ -36,9 +36,16 @@ void writefile(SEXP list_of_columns,
const char *open_mode = "wb";
if (*LOGICAL(append)) open_mode = "ab";
FILE *f = fopen(CHAR(STRING_ELT(filename, 0)), open_mode);
if (f == NULL) goto end;
if (f == NULL) error("Unable to open file: %s", filename);
int true_false;

// prefetch levels of factor columns (if any) to save getAttrib on every field on every row of any factor column
SEXP levels[ncols]; // on-stack vla
for (int col_i=0; col_i<ncols; col_i++) {
SEXP column = VECTOR_ELT(list_of_columns, col_i);
levels[col_i] = isFactor(column) ? getAttrib(column, R_LevelsSymbol) : NULL;
}

for (RLEN row_i = 0; row_i < nrows; ++row_i) {
for (int col_i = 0; col_i < ncols; ++col_i) {

Expand All @@ -60,8 +67,8 @@ void writefile(SEXP list_of_columns,
fputs(na_str, f);
break;
}
if (isFactor(column)) {
str = STRING_ELT(getAttrib(column, R_LevelsSymbol), INTEGER(column)[row_i]-1);
if (levels[col_i] != NULL) { // isFactor(column) == TRUE
str = STRING_ELT(levels[col_i], INTEGER(column)[row_i]-1);
// fall through to STRSXP case
} else {
fprintf(f, "%d", INTEGER(column)[row_i]);
Expand Down Expand Up @@ -90,13 +97,13 @@ void writefile(SEXP list_of_columns,
error("Column %d's type is '%s' - not yet implemented.", col_i+1,type2char(TYPEOF(column)) );
}
}
if (fputs(row_sep, f) < 0) goto end;
fputs(row_sep, f);
}

end:
error_number = errno;
//end: // don't mind the goto really. it's more that the levels vla prevents goto in gcc. Will do differently anyway.
// error_number = errno;
if (f != NULL) fclose(f);
if (error_number) error(strerror(errno));
//if (error_number) error(strerror(errno));
}


0 comments on commit 9f9a4c3

Please sign in to comment.