Skip to content

Commit

Permalink
add support for altrep state serialization
Browse files Browse the repository at this point in the history
  • Loading branch information
traversc committed Dec 14, 2023
1 parent 40c02b8 commit b8db2bb
Show file tree
Hide file tree
Showing 12 changed files with 386 additions and 50 deletions.
6 changes: 3 additions & 3 deletions DESCRIPTION
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
Package: qs
Type: Package
Title: Quick Serialization of R Objects
Version: 0.25.7
Date: 2023-12-05
Version: 0.26.0
Date: 2023-12-13
Authors@R: c(
person("Travers", "Ching", email = "traversc@gmail.com", role = c("aut", "cre", "cph")),
person("Yann", "Collet", role = c("ctb", "cph"), comment = "Yann Collet is the author of the bundled zstd, lz4 and xxHash code"),
Expand All @@ -22,7 +22,7 @@ Biarch: true
Depends: R (>= 3.0.2)
Imports:
Rcpp, RApiSerialize (>= 0.1.1), stringfish (>= 0.15.1)
LinkingTo: Rcpp, RApiSerialize, stringfish
LinkingTo: Rcpp, RApiSerialize, stringfish, BH
Encoding: UTF-8
Roxygen: list(markdown = TRUE)
RoxygenNote: 7.2.3
Expand Down
3 changes: 3 additions & 0 deletions NAMESPACE
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ export(blosc_unshuffle_raw)
export(catquo)
export(decode_source)
export(encode_source)
export(get_altrep_class_info)
export(is_big_endian)
export(lz4_compress_bound)
export(lz4_compress_raw)
Expand All @@ -29,6 +30,8 @@ export(qsave_fd)
export(qsave_handle)
export(qsavem)
export(qserialize)
export(register_altrep_class)
export(unregister_altrep_class)
export(zstd_compress_bound)
export(zstd_compress_raw)
export(zstd_decompress_raw)
Expand Down
12 changes: 12 additions & 0 deletions R/RcppExports.R
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,18 @@ closeWinMapView <- function(pointer) {
.Call(`_qs_closeWinMapView`, pointer)
}

register_altrep_class <- function(classname, pkgname) {
invisible(.Call(`_qs_register_altrep_class`, classname, pkgname))
}

unregister_altrep_class <- function(classname, pkgname) {
invisible(.Call(`_qs_unregister_altrep_class`, classname, pkgname))
}

get_altrep_class_info <- function(obj) {
.Call(`_qs_get_altrep_class_info`, obj)
}

# Register entry points for exported C++ functions
methods::setLoadAction(function(ns) {
.Call(`_qs_RcppExport_registerCCallable`)
Expand Down
50 changes: 50 additions & 0 deletions R/zz_help_files.R
Original file line number Diff line number Diff line change
Expand Up @@ -540,3 +540,53 @@ NULL
#' @examples
#' data(starnames)
"starnames"


#' Register ALTREP class for serialization
#'
#' Register an ALTREP class to serialize using base R serialization.
#'
#' @usage register_altrep_class(classname, pkgname)
#'
#' @param classname The ALTREP class name
#' @param pkgname The package the ALTREP class comes from
#'
#' @export
#' @name register_altrep_class
#'
#' @examples
#' register_altrep_class("compact_intseq", "base")
NULL

#' Unegister ALTREP class for serialization
#'
#' Unegister an ALTREP class to not use base R serialization.
#'
#' @usage unregister_altrep_class(classname, pkgname)
#'
#' @param classname The ALTREP class name
#' @param pkgname The package the ALTREP class comes from
#'
#' @export
#' @name unregister_altrep_class
#'
#' @examples
#' unregister_altrep_class("compact_intseq", "base")
NULL

#' Get the class information of an ALTREP object
#'
#' Gets the formal name of the class and package of an ALTREP object
#'
#' @usage get_altrep_class_info(obj)
#'
#' @param obj The ALTREP class name
#' @return The class information (class name and package name) of an ALTREP object, a character vector of length two.
#' If the object is not an ALTREP object, returns NULL.
#'
#' @export
#' @name get_altrep_class_info
#'
#' @examples
#' get_altrep_class_info(1:5)
NULL
58 changes: 58 additions & 0 deletions inst/include/qs_RcppExports.h
Original file line number Diff line number Diff line change
Expand Up @@ -824,6 +824,64 @@ namespace qs {
return Rcpp::as<bool >(rcpp_result_gen);
}

inline void register_altrep_class(const std::string& classname, const std::string& pkgname) {
typedef SEXP(*Ptr_register_altrep_class)(SEXP,SEXP);
static Ptr_register_altrep_class p_register_altrep_class = NULL;
if (p_register_altrep_class == NULL) {
validateSignature("void(*register_altrep_class)(const std::string&,const std::string&)");
p_register_altrep_class = (Ptr_register_altrep_class)R_GetCCallable("qs", "_qs_register_altrep_class");
}
RObject rcpp_result_gen;
{
rcpp_result_gen = p_register_altrep_class(Shield<SEXP>(Rcpp::wrap(classname)), Shield<SEXP>(Rcpp::wrap(pkgname)));
}
if (rcpp_result_gen.inherits("interrupted-error"))
throw Rcpp::internal::InterruptedException();
if (Rcpp::internal::isLongjumpSentinel(rcpp_result_gen))
throw Rcpp::LongjumpException(rcpp_result_gen);
if (rcpp_result_gen.inherits("try-error"))
throw Rcpp::exception(Rcpp::as<std::string>(rcpp_result_gen).c_str());
}

inline void unregister_altrep_class(const std::string& classname, const std::string& pkgname) {
typedef SEXP(*Ptr_unregister_altrep_class)(SEXP,SEXP);
static Ptr_unregister_altrep_class p_unregister_altrep_class = NULL;
if (p_unregister_altrep_class == NULL) {
validateSignature("void(*unregister_altrep_class)(const std::string&,const std::string&)");
p_unregister_altrep_class = (Ptr_unregister_altrep_class)R_GetCCallable("qs", "_qs_unregister_altrep_class");
}
RObject rcpp_result_gen;
{
rcpp_result_gen = p_unregister_altrep_class(Shield<SEXP>(Rcpp::wrap(classname)), Shield<SEXP>(Rcpp::wrap(pkgname)));
}
if (rcpp_result_gen.inherits("interrupted-error"))
throw Rcpp::internal::InterruptedException();
if (Rcpp::internal::isLongjumpSentinel(rcpp_result_gen))
throw Rcpp::LongjumpException(rcpp_result_gen);
if (rcpp_result_gen.inherits("try-error"))
throw Rcpp::exception(Rcpp::as<std::string>(rcpp_result_gen).c_str());
}

inline SEXP get_altrep_class_info(SEXP obj) {
typedef SEXP(*Ptr_get_altrep_class_info)(SEXP);
static Ptr_get_altrep_class_info p_get_altrep_class_info = NULL;
if (p_get_altrep_class_info == NULL) {
validateSignature("SEXP(*get_altrep_class_info)(SEXP)");
p_get_altrep_class_info = (Ptr_get_altrep_class_info)R_GetCCallable("qs", "_qs_get_altrep_class_info");
}
RObject rcpp_result_gen;
{
rcpp_result_gen = p_get_altrep_class_info(Shield<SEXP>(Rcpp::wrap(obj)));
}
if (rcpp_result_gen.inherits("interrupted-error"))
throw Rcpp::internal::InterruptedException();
if (Rcpp::internal::isLongjumpSentinel(rcpp_result_gen))
throw Rcpp::LongjumpException(rcpp_result_gen);
if (rcpp_result_gen.inherits("try-error"))
throw Rcpp::exception(Rcpp::as<std::string>(rcpp_result_gen).c_str());
return Rcpp::as<SEXP >(rcpp_result_gen);
}

}

#endif // RCPP_qs_RCPPEXPORTS_H_GEN_
21 changes: 21 additions & 0 deletions man/get_altrep_class_info.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

19 changes: 19 additions & 0 deletions man/register_altrep_class.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

19 changes: 19 additions & 0 deletions man/unregister_altrep_class.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

108 changes: 108 additions & 0 deletions src/RcppExports.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1398,6 +1398,105 @@ RcppExport SEXP _qs_closeWinMapView(SEXP pointerSEXP) {
UNPROTECT(1);
return rcpp_result_gen;
}
// register_altrep_class
void register_altrep_class(const std::string& classname, const std::string& pkgname);
static SEXP _qs_register_altrep_class_try(SEXP classnameSEXP, SEXP pkgnameSEXP) {
BEGIN_RCPP
Rcpp::traits::input_parameter< const std::string& >::type classname(classnameSEXP);
Rcpp::traits::input_parameter< const std::string& >::type pkgname(pkgnameSEXP);
register_altrep_class(classname, pkgname);
return R_NilValue;
END_RCPP_RETURN_ERROR
}
RcppExport SEXP _qs_register_altrep_class(SEXP classnameSEXP, SEXP pkgnameSEXP) {
SEXP rcpp_result_gen;
{
rcpp_result_gen = PROTECT(_qs_register_altrep_class_try(classnameSEXP, pkgnameSEXP));
}
Rboolean rcpp_isInterrupt_gen = Rf_inherits(rcpp_result_gen, "interrupted-error");
if (rcpp_isInterrupt_gen) {
UNPROTECT(1);
Rf_onintr();
}
bool rcpp_isLongjump_gen = Rcpp::internal::isLongjumpSentinel(rcpp_result_gen);
if (rcpp_isLongjump_gen) {
Rcpp::internal::resumeJump(rcpp_result_gen);
}
Rboolean rcpp_isError_gen = Rf_inherits(rcpp_result_gen, "try-error");
if (rcpp_isError_gen) {
SEXP rcpp_msgSEXP_gen = Rf_asChar(rcpp_result_gen);
UNPROTECT(1);
Rf_error("%s", CHAR(rcpp_msgSEXP_gen));
}
UNPROTECT(1);
return rcpp_result_gen;
}
// unregister_altrep_class
void unregister_altrep_class(const std::string& classname, const std::string& pkgname);
static SEXP _qs_unregister_altrep_class_try(SEXP classnameSEXP, SEXP pkgnameSEXP) {
BEGIN_RCPP
Rcpp::traits::input_parameter< const std::string& >::type classname(classnameSEXP);
Rcpp::traits::input_parameter< const std::string& >::type pkgname(pkgnameSEXP);
unregister_altrep_class(classname, pkgname);
return R_NilValue;
END_RCPP_RETURN_ERROR
}
RcppExport SEXP _qs_unregister_altrep_class(SEXP classnameSEXP, SEXP pkgnameSEXP) {
SEXP rcpp_result_gen;
{
rcpp_result_gen = PROTECT(_qs_unregister_altrep_class_try(classnameSEXP, pkgnameSEXP));
}
Rboolean rcpp_isInterrupt_gen = Rf_inherits(rcpp_result_gen, "interrupted-error");
if (rcpp_isInterrupt_gen) {
UNPROTECT(1);
Rf_onintr();
}
bool rcpp_isLongjump_gen = Rcpp::internal::isLongjumpSentinel(rcpp_result_gen);
if (rcpp_isLongjump_gen) {
Rcpp::internal::resumeJump(rcpp_result_gen);
}
Rboolean rcpp_isError_gen = Rf_inherits(rcpp_result_gen, "try-error");
if (rcpp_isError_gen) {
SEXP rcpp_msgSEXP_gen = Rf_asChar(rcpp_result_gen);
UNPROTECT(1);
Rf_error("%s", CHAR(rcpp_msgSEXP_gen));
}
UNPROTECT(1);
return rcpp_result_gen;
}
// get_altrep_class_info
SEXP get_altrep_class_info(SEXP obj);
static SEXP _qs_get_altrep_class_info_try(SEXP objSEXP) {
BEGIN_RCPP
Rcpp::RObject rcpp_result_gen;
Rcpp::traits::input_parameter< SEXP >::type obj(objSEXP);
rcpp_result_gen = Rcpp::wrap(get_altrep_class_info(obj));
return rcpp_result_gen;
END_RCPP_RETURN_ERROR
}
RcppExport SEXP _qs_get_altrep_class_info(SEXP objSEXP) {
SEXP rcpp_result_gen;
{
rcpp_result_gen = PROTECT(_qs_get_altrep_class_info_try(objSEXP));
}
Rboolean rcpp_isInterrupt_gen = Rf_inherits(rcpp_result_gen, "interrupted-error");
if (rcpp_isInterrupt_gen) {
UNPROTECT(1);
Rf_onintr();
}
bool rcpp_isLongjump_gen = Rcpp::internal::isLongjumpSentinel(rcpp_result_gen);
if (rcpp_isLongjump_gen) {
Rcpp::internal::resumeJump(rcpp_result_gen);
}
Rboolean rcpp_isError_gen = Rf_inherits(rcpp_result_gen, "try-error");
if (rcpp_isError_gen) {
SEXP rcpp_msgSEXP_gen = Rf_asChar(rcpp_result_gen);
UNPROTECT(1);
Rf_error("%s", CHAR(rcpp_msgSEXP_gen));
}
UNPROTECT(1);
return rcpp_result_gen;
}

// validate (ensure exported C++ functions exist before calling them)
static int _qs_RcppExport_validate(const char* sig) {
Expand Down Expand Up @@ -1443,6 +1542,9 @@ static int _qs_RcppExport_validate(const char* sig) {
signatures.insert("SEXP(*openWinFileMapping)(SEXP const,const double)");
signatures.insert("SEXP(*openWinMapView)(SEXP const,const double)");
signatures.insert("bool(*closeWinMapView)(SEXP const)");
signatures.insert("void(*register_altrep_class)(const std::string&,const std::string&)");
signatures.insert("void(*unregister_altrep_class)(const std::string&,const std::string&)");
signatures.insert("SEXP(*get_altrep_class_info)(SEXP)");
}
return signatures.find(sig) != signatures.end();
}
Expand Down Expand Up @@ -1489,6 +1591,9 @@ RcppExport SEXP _qs_RcppExport_registerCCallable() {
R_RegisterCCallable("qs", "_qs_openWinFileMapping", (DL_FUNC)_qs_openWinFileMapping_try);
R_RegisterCCallable("qs", "_qs_openWinMapView", (DL_FUNC)_qs_openWinMapView_try);
R_RegisterCCallable("qs", "_qs_closeWinMapView", (DL_FUNC)_qs_closeWinMapView_try);
R_RegisterCCallable("qs", "_qs_register_altrep_class", (DL_FUNC)_qs_register_altrep_class_try);
R_RegisterCCallable("qs", "_qs_unregister_altrep_class", (DL_FUNC)_qs_unregister_altrep_class_try);
R_RegisterCCallable("qs", "_qs_get_altrep_class_info", (DL_FUNC)_qs_get_altrep_class_info_try);
R_RegisterCCallable("qs", "_qs_RcppExport_validate", (DL_FUNC)_qs_RcppExport_validate);
return R_NilValue;
}
Expand Down Expand Up @@ -1534,6 +1639,9 @@ static const R_CallMethodDef CallEntries[] = {
{"_qs_openWinFileMapping", (DL_FUNC) &_qs_openWinFileMapping, 2},
{"_qs_openWinMapView", (DL_FUNC) &_qs_openWinMapView, 2},
{"_qs_closeWinMapView", (DL_FUNC) &_qs_closeWinMapView, 1},
{"_qs_register_altrep_class", (DL_FUNC) &_qs_register_altrep_class, 2},
{"_qs_unregister_altrep_class", (DL_FUNC) &_qs_unregister_altrep_class, 2},
{"_qs_get_altrep_class_info", (DL_FUNC) &_qs_get_altrep_class_info, 1},
{"_qs_RcppExport_registerCCallable", (DL_FUNC) &_qs_RcppExport_registerCCallable, 0},
{NULL, NULL, 0}
};
Expand Down
2 changes: 2 additions & 0 deletions src/qs_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ You can contact the author at:
#include <climits>
#include <cstdint>
#include <unordered_map>
#include <unordered_set>
#include <boost/functional/hash.hpp> // hash for altrep_registry

// platform specific headers
#ifdef _WIN32
Expand Down
Loading

0 comments on commit b8db2bb

Please sign in to comment.