diff --git a/Clib/eiffel_curl.c b/Clib/eiffel_curl.c index a3ea435d..635ea00c 100644 --- a/Clib/eiffel_curl.c +++ b/Clib/eiffel_curl.c @@ -34,6 +34,17 @@ typedef EIF_INTEGER (* EIF_CURL_WRITE_PROC) ( EIF_INTEGER, /* a_nmemb */ EIF_POINTER /* a_write_pointer */ ); + +typedef EIF_INTEGER (* EIF_CURL_READ_PROC) ( +#ifndef EIF_IL_DLL + EIF_REFERENCE, /* CURL_FUNCTION Eiffel object */ +#endif + EIF_POINTER, /* a_data_pointer */ + EIF_INTEGER, /* a_size */ + EIF_INTEGER, /* a_nmemb */ + EIF_POINTER /* a_write_pointer */ + ); + typedef EIF_INTEGER (* EIF_CURL_DEBUG_PROC) ( #ifndef EIF_IL_DLL @@ -54,7 +65,10 @@ static EIF_CURL_PROGRESS_PROC eiffel_progress_function = NULL; static EIF_CURL_WRITE_PROC eiffel_write_function = NULL; /* Address of Eiffel CURL_FUNCTION.write_function */ - + +static EIF_CURL_READ_PROC eiffel_read_function = NULL; + /* Address of Eiffel CURL_FUNCTION.read_function */ + static EIF_CURL_DEBUG_PROC eiffel_debug_function = NULL; /* Address of Eiffel CURL_FUNCTION.debug_function */ @@ -86,6 +100,12 @@ void c_set_write_function_address( EIF_POINTER a_address) eiffel_write_function = (EIF_CURL_WRITE_PROC) a_address; } +/* Set CURL_FUNCTOIN.read_function address */ +void c_set_read_function_address( EIF_POINTER a_address) +{ + eiffel_read_function = (EIF_CURL_READ_PROC) a_address; +} + /* Set CURL_FUNCTOIN.debug_function address */ void c_set_debug_function_address (EIF_POINTER a_address) { @@ -110,6 +130,25 @@ size_t curl_write_function (void *ptr, size_t size, size_t nmemb, void *data) } } +/* Eiffel adapter function for CURLOPT_READFUNCTION + We need this function since Eiffel function call need first parameter is EIF_REFERENCE. */ +size_t curl_read_function (void *ptr, size_t size, size_t nmemb, void *data) +{ + if (eiffel_function_object) { + return (size_t) ((eiffel_read_function) ( +#ifndef EIF_IL_DLL + (EIF_REFERENCE) eif_access (eiffel_function_object), +#endif + (EIF_POINTER) ptr, + (EIF_INTEGER) size, + (EIF_INTEGER) nmemb, + (EIF_POINTER) data)); + } else { + return 0; + } +} + + /* Eiffel adapter function for CURLOPT_PROGRESSFUNCTION We need this function since Eiffel function call need first parameter is EIF_REFERENCE. */ size_t curl_progress_function (void * a_object_id, double a_dltotal, double a_dlnow, double a_ultotal, double a_ulnow) diff --git a/curl_default_function.e b/curl_default_function.e index 099fd32f..796c45b9 100644 --- a/curl_default_function.e +++ b/curl_default_function.e @@ -1,4 +1,4 @@ -note +indexing description: "[ Default implementation of CURL_FUNCTION. ]" @@ -48,6 +48,11 @@ feature -- Command end end + read_function (a_data_pointer: POINTER; a_size, a_nmemb: INTEGER; a_object_id: POINTER): INTEGER + -- A callback readfunction + do + end + debug_function (a_curl_handle: POINTER; a_curl_infotype: INTEGER; a_char_pointer: POINTER; a_size: INTEGER; a_object_id: POINTER): INTEGER -- Redefine local diff --git a/curl_easy_externals.e b/curl_easy_externals.e index 4ee7d90e..ea16da24 100644 --- a/curl_easy_externals.e +++ b/curl_easy_externals.e @@ -1,4 +1,4 @@ -note +indexing description: "[ cURL easy externals. For more informaton see: @@ -95,6 +95,16 @@ feature -- Command end end + setopt_file (a_curl_handle: POINTER; a_opt: INTEGER; a_file: FILE) + -- Declared as curl_easy_setopt(). + require + exists: a_curl_handle /= default_pointer + valid: a_opt = {CURL_OPT_CONSTANTS}.curlopt_readdata + readable: a_file /= void and then a_file.file_readable + do + setopt_void_star (a_curl_handle, a_opt, a_file.file_pointer) + end + perform (a_curl_handle: POINTER): INTEGER -- Declared as curl_easy_perform(). -- Result is one value from {CURL_CODES} @@ -170,6 +180,21 @@ feature -- Special setting end end + set_read_function (a_curl_handle: POINTER) + -- Set cURL read function + -- Set cURL read function with Eiffel default read function. + -- So we can use a c file pointer as parameter in {CURL_EASY_EXTERNALS}.setopt_file_pointer when the option is {CURL_OPT_CONSTANTS}.curlopt_readdata + require + exists: a_curl_handle /= default_pointer + local + l_api: POINTER + do + l_api := api_loader.safe_load_api (module_name, "curl_easy_setopt") + if l_api /= default_pointer then + curl_function.c_set_read_function (l_api, a_curl_handle) + end + end + set_progress_function (a_curl_handle: POINTER) -- Set cURL progress function for upload/download progress. require diff --git a/curl_function.e b/curl_function.e index 28f2e78a..cb26ad1f 100644 --- a/curl_function.e +++ b/curl_function.e @@ -1,4 +1,4 @@ -note +indexing description: "[ cURL curl_easy_setopt callback functions' Eiffel wrappers. We need this class since cURL need a c function pointer as value but @@ -20,11 +20,12 @@ feature -- Interactive with C set_object_and_function_address -- Set object and function addresses. - -- Call this feature before call `c_set_progress_function', `c_set_debug_function' and `c_set_write_function'. + -- Call this feature before call `c_set_progress_function', `c_set_debug_function' and `c_set_write_function, c_set_read_function'. do c_set_object ($Current) c_set_progress_function_address ($progress_function) c_set_write_function_address ($write_function) + c_set_read_function_address ($read_function) c_set_debug_function_address ($debug_function) end @@ -83,6 +84,24 @@ feature -- Interactive with C ]" end + c_set_read_function (a_setopt_api: POINTER; a_curl_handle: POINTER) + -- Setting CURLOPT_READFUNCTION option of `a_curl_handle'. + -- We need this function since cURL need a c function pointer as value. + require + exists: a_setopt_api /= default_pointer + external + "C inline use " + alias + "[ + { + (FUNCTION_CAST(void, (CURL *, CURLoption, ...)) $a_setopt_api) + ((CURL *) $a_curl_handle, + (CURLoption)CURLOPT_READFUNCTION, + curl_read_function); + } + ]" + end + feature -- cURL curl_easy_setopt functions progress_function (a_object_id: POINTER; a_download_total, a_download_now, a_upload_total, a_upload_now: REAL_64): INTEGER @@ -99,6 +118,13 @@ feature -- cURL curl_easy_setopt functions deferred end + read_function (a_data_pointer: POINTER; a_size, a_nmemb: INTEGER; a_object_id: POINTER): INTEGER + -- Function correspond to {CURL_OPT_CONSTANTS}.curlopt_readfunction + -- Note, pass a {IDENTIFIED}.object_id as `a_object_id' value is helpful since we can't directly pass an Eiffel Object address which + -- may changed during GC. + deferred + end + debug_function (a_curl_handle: POINTER; a_curl_infotype: INTEGER; a_char_pointer: POINTER; a_size: INTEGER; a_object_id: POINTER): INTEGER -- Function correspond to {CURL_OPT_CONSTANTS}.curlopt_debugfunction -- Note, pass a {IDENTIFIED}.object_id as `a_object_id' value is helpful since we can't directly pass an Eiffel Object address which @@ -134,6 +160,12 @@ feature {NONE} -- Externals "C use %"eiffel_curl.h%"" end + c_set_read_function_address (a_address: POINTER) + -- Set read function address. + external + "C use %"eiffel_curl.h%"" + end + c_set_debug_function_address (a_address: POINTER) -- Set write function address. external diff --git a/curl_opt_constants.e b/curl_opt_constants.e index b2a611ea..5fa9fee1 100644 --- a/curl_opt_constants.e +++ b/curl_opt_constants.e @@ -216,8 +216,58 @@ feature -- Enumerations. ]" end + curlopt_readfunction: INTEGER + -- Declared as CURLOPT_READFUNCTION. + external + "C inline use " + alias + "[ + return CURLOPT_READFUNCTION; + ]" + end + + curlopt_upload: INTEGER + -- Declared as CURLOPT_UPLOAD. + external + "C inline use " + alias + "[ + return CURLOPT_UPLOAD; + ]" + end + + curlopt_put: INTEGER + -- Declared as CURLOPT_PUT. + external + "C inline use " + alias + "[ + return CURLOPT_PUT; + ]" + end + + curlopt_readdata: INTEGER + -- Declared as CURLOPT_READDATA. + external + "C inline use " + alias + "[ + return CURLOPT_READDATA; + ]" + end + + curlopt_infilesize_large: INTEGER + -- Declared as CURLOPT_INFILESIZE_LARGE. + external + "C inline use " + alias + "[ + return CURLOPT_INFILESIZE_LARGE; + ]" + end + is_valid (a_integer: INTEGER): BOOLEAN - -- If `a_integer' value vaild? + -- If `a_integer' value valid? do Result := a_integer = curlopt_cookie or a_integer = curlopt_cookiefile or @@ -238,7 +288,12 @@ feature -- Enumerations. a_integer = curlopt_progressdata or a_integer = curlopt_noprogress or a_integer = curlopt_referer or - a_integer = curlopt_httpget + a_integer = curlopt_httpget or + a_integer = curlopt_readfunction or + a_integer = curlopt_upload or + a_integer = curlopt_put or + a_integer = curlopt_readdata or + a_integer = curlopt_infilesize_large end note diff --git a/spec/include/eiffel_curl.h b/spec/include/eiffel_curl.h index e9138e2e..3dd9b005 100644 --- a/spec/include/eiffel_curl.h +++ b/spec/include/eiffel_curl.h @@ -32,9 +32,11 @@ extern "C" { extern void c_set_object(EIF_REFERENCE a_address); extern void c_release_object(void); extern void c_set_progress_function_address( EIF_POINTER a_address); +extern void c_set_read_function_address( EIF_POINTER a_address); extern void c_set_write_function_address( EIF_POINTER a_address); extern void c_set_debug_function_address (EIF_POINTER a_address); extern size_t curl_write_function (void *ptr, size_t size, size_t nmemb, void *data); +extern size_t curl_read_function (void *ptr, size_t size, size_t nmemb, void *data); extern size_t curl_progress_function (void * a_object_id, double a_dltotal, double a_dlnow, double a_ultotal, double a_ulnow); extern size_t curl_debug_function (CURL * a_curl_handle, curl_infotype a_curl_infotype, unsigned char * a_char_pointer, size_t a_size, void * a_object_id);