Skip to content

Commit

Permalink
Add curl MLton FFI bindings
Browse files Browse the repository at this point in the history
Getting the data at a URL can be a useful thing to do. The best way to
do it is probably with libcurl bindings. This unfortunately requires a
small C wrapper to do some bookkeeping (curl only wants to write via a
function pointer or a FILE*) but it's still pretty braindead.
  • Loading branch information
jwatzman authored and Jacob Potter committed Aug 7, 2010
1 parent a6f0e65 commit 36a7054
Show file tree
Hide file tree
Showing 5 changed files with 107 additions and 0 deletions.
5 changes: 5 additions & 0 deletions curl/README
@@ -0,0 +1,5 @@
This attempts to be a very simple interface to libcurl. Pass in your URL, get the data at that URL back.

Because MLton's build system is half-assed, in order to use this lib you must:
- add "-link-opt -lcurl" to your mlton command line parameters
- add ".../stilts/curl/curl_supereasy.c" after your mlb file on the mlton command line
9 changes: 9 additions & 0 deletions curl/curl.mlb
@@ -0,0 +1,9 @@
ann
"allowFFI true"
in
$(SML_LIB)/basis/basis.mlb
$(SML_LIB)/basis/mlton.mlb
$(SML_LIB)/basis/c-types.mlb
curl.sig
curl.sml
end
3 changes: 3 additions & 0 deletions curl/curl.sig
@@ -0,0 +1,3 @@
signature CURL = sig
val curl : string -> string
end
31 changes: 31 additions & 0 deletions curl/curl.sml
@@ -0,0 +1,31 @@
structure Curl :> CURL = struct

type ptr = MLton.Pointer.t

fun read_bytes (p, n) =
Word8Vector.tabulate (n, fn i => MLton.Pointer.getWord8 (p, i))

fun curl url =
let
val p =
(_import "curl_supereasy" : string -> ptr;)
(url)

val len =
(_import "curl_supereasy_len" : ptr -> int;)
(p)

val data =
(_import "curl_supereasy_data" : ptr -> ptr;)
(p)

val ret = Byte.bytesToString (read_bytes (data, len))

val _ =
(_import "curl_supereasy_cleanup" : ptr -> unit;)
(p)
in
ret
end

end
59 changes: 59 additions & 0 deletions curl/curl_supereasy.c
@@ -0,0 +1,59 @@
#include <stdlib.h>
#include <string.h>
#include <curl/curl.h>

typedef struct
{
char *data;
size_t len;
}
curl_supereasy_data_t;

size_t curl_supereasy_callback(
void *buffer,
size_t size,
size_t nmemb,
curl_supereasy_data_t *datat)
{
size_t old_len = datat->len;
size_t additional_len = size*nmemb;

datat->data = realloc(datat->data, old_len + additional_len);
datat->len = old_len + additional_len;

memcpy(datat->data + old_len, buffer, additional_len);

return additional_len;
}

curl_supereasy_data_t* curl_supereasy(char *url)
{
curl_supereasy_data_t *datat = malloc(sizeof(curl_supereasy_data_t));
datat->data = NULL;
datat->len = 0;

CURL *curl = curl_easy_init();
curl_easy_setopt(curl, CURLOPT_URL, url);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, curl_supereasy_callback);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, datat);
curl_easy_perform(curl);
curl_easy_cleanup(curl);

return datat;
}

char* curl_supereasy_data(curl_supereasy_data_t *datat)
{
return datat->data;
}

size_t curl_supereasy_len(curl_supereasy_data_t *datat)
{
return datat->len;
}

void curl_supereasy_cleanup(curl_supereasy_data_t *datat)
{
free(datat->data);
free(datat);
}

0 comments on commit 36a7054

Please sign in to comment.