Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[cbindlist/mergelist] Add some C utilities: NROW/NCOL/isDataTable/isDataList/perhapsDataTable #6433

Open
wants to merge 1 commit into
base: cbind-merge-list-mult-err
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions src/data.table.h
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,12 @@ SEXP islockedR(SEXP x);
bool need2utf8(SEXP x);
SEXP coerceUtf8IfNeeded(SEXP x);
SEXP coerceAs(SEXP x, SEXP as, SEXP copyArg);
int n_rows(SEXP x);
int n_columns(SEXP x);
bool isDataTable(SEXP x);
bool isRectangularList(SEXP x);
bool perhapsDataTable(SEXP x);
SEXP perhapsDataTableR(SEXP x);
void internal_error(const char *call_name, const char *format, ...);

// types.c
Expand Down
89 changes: 89 additions & 0 deletions src/utils.c
Original file line number Diff line number Diff line change
Expand Up @@ -439,6 +439,95 @@
return ScalarLogical(false);
}

// if (length(x)) length(x[[1L]]) else 0L
// used in src/mergelist.c and below in commented out set_row_names
int n_rows(SEXP x) {
if (!LENGTH(x))

Check warning on line 445 in src/utils.c

View check run for this annotation

Codecov / codecov/patch

src/utils.c#L444-L445

Added lines #L444 - L445 were not covered by tests
return 0; // # nocov. Not yet reached from anywhere, cbindlist uses it but escapes for !n_columns(x)
return length(VECTOR_ELT(x, 0));

Check warning on line 447 in src/utils.c

View check run for this annotation

Codecov / codecov/patch

src/utils.c#L447

Added line #L447 was not covered by tests
}

// length(x)
// used in src/mergelist.c
// to be an abstraction layer on C level
int n_columns(SEXP x) {
return LENGTH(x);

Check warning on line 454 in src/utils.c

View check run for this annotation

Codecov / codecov/patch

src/utils.c#L453-L454

Added lines #L453 - L454 were not covered by tests
}

/*
Below commented out functions will be uncommented when addressing #4439
// c("data.table","data.frame")
static SEXP char2_dtdf() {
SEXP char2_dtdf = PROTECT(allocVector(STRSXP, 2));
SET_STRING_ELT(char2_dtdf, 0, char_datatable);
SET_STRING_ELT(char2_dtdf, 1, char_dataframe);
UNPROTECT(1);
return char2_dtdf;
}

// .set_row_names(x)
static SEXP set_row_names(int n) {
SEXP ans = R_NilValue;
if (n) {
ans = PROTECT(allocVector(INTSXP, 2));
INTEGER(ans)[0] = NA_INTEGER;
INTEGER(ans)[1] = -n;
} else {
ans = PROTECT(allocVector(INTSXP, 0));
}
UNPROTECT(1);
return ans;
}

// setDT(x) ## not in-place!
SEXP setDT(SEXP x) {
if (!isNewList(x))
error("internal error: C setDT should be called only on a list"); // # nocov
setAttrib(x, R_ClassSymbol, char2_dtdf());
setAttrib(x, sym_rownames, set_row_names(n_rows(x)));
return alloccolwrapper(x, GetOption(sym_alloccol, R_NilValue), GetOption(sym_verbose, R_NilValue));
}*/

// inherits(x, "data.table")
bool isDataTable(SEXP x) {
return INHERITS(x, char_datatable);

Check warning on line 493 in src/utils.c

View check run for this annotation

Codecov / codecov/patch

src/utils.c#L492-L493

Added lines #L492 - L493 were not covered by tests
}

// rectangular list; NB does not allow length-1 recycling
// length(x) <= 1L || length(unique(lengths(x))) == 1L
static inline bool isRectangular(SEXP x) {
int n = LENGTH(x);
if (n < 2)
return true;
R_xlen_t nr = xlength(VECTOR_ELT(x, 0));
for (int i=1; i<n; ++i) {
if (xlength(VECTOR_ELT(x, i)) != nr)
return false;

Check warning on line 505 in src/utils.c

View check run for this annotation

Codecov / codecov/patch

src/utils.c#L498-L505

Added lines #L498 - L505 were not covered by tests
}
return true;

Check warning on line 507 in src/utils.c

View check run for this annotation

Codecov / codecov/patch

src/utils.c#L507

Added line #L507 was not covered by tests
}

// setDT()-friendly rectangular list, i.e.
// a named list() with all entries of equal length()
bool isRectangularList(SEXP x) {
if (!isNewList(x))
return false;
if (!LENGTH(x))
return true;
if (isNull(getAttrib(x, R_NamesSymbol)))
return false;
return isRectangular(x);

Check warning on line 519 in src/utils.c

View check run for this annotation

Codecov / codecov/patch

src/utils.c#L512-L519

Added lines #L512 - L519 were not covered by tests
}

// TODO: use isDataFrame (when included in any R release).
// isDataTable(x) || isFrame(x) || isRectangularList(x)
bool perhapsDataTable(SEXP x) {
return isDataTable(x) || isFrame(x) || isRectangularList(x);

Check warning on line 525 in src/utils.c

View check run for this annotation

Codecov / codecov/patch

src/utils.c#L524-L525

Added lines #L524 - L525 were not covered by tests
}
SEXP perhapsDataTableR(SEXP x) {
return ScalarLogical(perhapsDataTable(x));

Check warning on line 528 in src/utils.c

View check run for this annotation

Codecov / codecov/patch

src/utils.c#L527-L528

Added lines #L527 - L528 were not covered by tests
}

void internal_error(const char *call_name, const char *format, ...) {
char buff[1024];
va_list args;
Expand Down
Loading