Skip to content

Commit

Permalink
Support seekfunction callback
Browse files Browse the repository at this point in the history
Fixes #307
  • Loading branch information
jeroen committed Aug 8, 2023
1 parent 7dc1413 commit 68e84e0
Show file tree
Hide file tree
Showing 4 changed files with 20 additions and 1 deletion.
1 change: 1 addition & 0 deletions NEWS
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
5.0.2
- Fix a unit test for behavioral change in libcurl 8.0.0
- Support seekfunction callback

5.0.1
- Setting verbose=TRUE now prints to R's stderr instead of the process, such that
Expand Down
10 changes: 10 additions & 0 deletions src/callbacks.c
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,16 @@ size_t R_curl_callback_read(char *buffer, size_t size, size_t nitems, SEXP fun)
return bytes_read;
}

/* origin is always SEEK_SET in libcurl, not really useful to pass on */
int R_curl_callback_seek(SEXP fun, curl_off_t offset, int origin){
SEXP soffset = PROTECT(ScalarReal(offset));
SEXP call = PROTECT(Rf_lang2(fun, soffset));
int ok;
R_tryEval(call, R_GlobalEnv, &ok);
UNPROTECT(2);
return ok ? CURL_SEEKFUNC_FAIL : CURL_SEEKFUNC_OK;
}

int R_curl_callback_debug(CURL *handle, curl_infotype type_, char *data,
size_t size, SEXP fun) {

Expand Down
1 change: 1 addition & 0 deletions src/callbacks.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
int R_curl_callback_progress(SEXP fun, double dltotal, double dlnow,
double ultotal, double ulnow);
size_t R_curl_callback_read(char *buffer, size_t size, size_t nitems, SEXP fun);
int R_curl_callback_seek(SEXP fun, curl_off_t offset, int origin);
int R_curl_callback_debug(CURL *handle, curl_infotype type_, char *data,
size_t size, SEXP fun);

Expand Down
9 changes: 8 additions & 1 deletion src/handle.c
Original file line number Diff line number Diff line change
Expand Up @@ -208,7 +208,7 @@ SEXP R_new_handle(void){
ref->handle = curl_easy_init();
total_handles++;
set_handle_defaults(ref);
SEXP prot = PROTECT(allocVector(VECSXP, 6)); //for protecting callback functions
SEXP prot = PROTECT(allocVector(VECSXP, 7)); //for protecting callback functions
SEXP ptr = PROTECT(R_MakeExternalPtr(ref, R_NilValue, prot));
R_RegisterCFinalizerEx(ptr, fin_handle, TRUE);
setAttrib(ptr, R_ClassSymbol, mkString("curl_handle"));
Expand Down Expand Up @@ -314,6 +314,13 @@ SEXP R_handle_setopt(SEXP ptr, SEXP keys, SEXP values){
(curl_ssl_ctx_callback) R_curl_callback_ssl_ctx));
assert(curl_easy_setopt(handle, CURLOPT_SSL_CTX_DATA, val));
SET_VECTOR_ELT(prot, 5, val); //protect gc
} else if (key == CURLOPT_SEEKFUNCTION) {
if (TYPEOF(val) != CLOSXP)
error("Value for option %s (%d) must be a function.", optname, key);
assert(curl_easy_setopt(handle, CURLOPT_SEEKFUNCTION,
(curl_seek_callback) R_curl_callback_seek));
assert(curl_easy_setopt(handle, CURLOPT_SEEKDATA, val));
SET_VECTOR_ELT(prot, 6, val); //protect gc
} else if (key == CURLOPT_URL) {
/* always use utf-8 for urls */
const char * url_utf8 = translateCharUTF8(STRING_ELT(val, 0));
Expand Down

0 comments on commit 68e84e0

Please sign in to comment.