Permalink
Browse files

Add curl MLton FFI bindings

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 4, 2010
1 parent a6f0e65 commit 36a705474c8e27f2cf2a589d00c1bf92bf3a267c
Showing with 107 additions and 0 deletions.
  1. +5 −0 curl/README
  2. +9 −0 curl/curl.mlb
  3. +3 −0 curl/curl.sig
  4. +31 −0 curl/curl.sml
  5. +59 −0 curl/curl_supereasy.c
View
@@ -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
View
@@ -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
View
@@ -0,0 +1,3 @@
+signature CURL = sig
+ val curl : string -> string
+end
View
@@ -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
View
@@ -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.