diff options
| author | 2023-03-20 18:12:53 -0400 | |
|---|---|---|
| committer | 2023-03-20 18:12:53 -0400 | |
| commit | 33923ba6779dbb6f42e5849cad2236b8cd8445d3 (patch) | |
| tree | b99965bf196d662b7cf1eb1ab53f2fc8f2a6399f | |
| parent | add curl global init/cleanup (diff) | |
add slist argument handling, extra cleanup
when a curl_easy_setopt expects an slist, we convert an indexed datatype
that is expected to be filled with strings into an slist,
registering it for cleanup in a way that should avoid memory leaks
| -rw-r--r-- | jurl.c | 20 | ||||
| -rw-r--r-- | jurl.h | 13 | ||||
| -rw-r--r-- | jurl_setopt.c | 21 |
3 files changed, 51 insertions, 3 deletions
@@ -7,6 +7,18 @@ int jurl_gc(void *p, size_t s) { (void) s; jurl_handle *jurl = (jurl_handle*)p; if (jurl->handle) curl_easy_cleanup(jurl->handle); + while (jurl->cleanup) { + struct jurl_cleanup *cur = jurl->cleanup; + switch (cur->type) { + case JURL_CLEANUP_TYPE_SLIST: + curl_slist_free_all(cur->slist); + break; + default: + janet_panic("unknown type of cleanup data in jurl_gc"); + } + jurl->cleanup = cur->next; + free(cur); + } return 0; } @@ -27,6 +39,14 @@ JANET_CFUN(jurl_new) { return janet_wrap_abstract(jurl); } +struct jurl_cleanup *register_cleanup(jurl_handle *jurl, enum jurl_cleanup_type type) { + struct jurl_cleanup *out = malloc(sizeof(struct jurl_cleanup)); + out->next = jurl->cleanup; + jurl->cleanup = out; + out->type = type; + return out; +} + JANET_CFUN(jurl_reset) { janet_fixarity(argc, 1); jurl_handle *jurl = (jurl_handle*)janet_getabstract(argv, 0, &jurl_type); @@ -3,12 +3,25 @@ #include <janet.h> // jurl globals +enum jurl_cleanup_type { + JURL_CLEANUP_TYPE_SLIST, +}; +struct jurl_cleanup { + struct jurl_cleanup *next; + enum jurl_cleanup_type type; + union { + struct curl_slist *slist; // when JURL_CLEANUP_TYPE_SLIST + }; +}; + struct jurl_handle { CURL* handle; + struct jurl_cleanup* cleanup; }; typedef struct jurl_handle jurl_handle; // jurl.c +struct jurl_cleanup *register_cleanup(jurl_handle *jurl, enum jurl_cleanup_type type); JANET_CFUN(jurl_new); JANET_CFUN(jurl_reset); JANET_CFUN(jurl_dup); diff --git a/jurl_setopt.c b/jurl_setopt.c index a3cf8e6..f0b0cd7 100644 --- a/jurl_setopt.c +++ b/jurl_setopt.c @@ -312,10 +312,25 @@ JANET_CFUN(jurl_setopt) { // TODO: how to clean up leak? janet_panic("jurl_setopt: FILE* not implemented"); break; - case JURL_PARAMTYPE_SLIST: - // TODO: make sure all slits are plain strings - janet_panic("jurl_setopt: slist not implemented"); + case JURL_PARAMTYPE_SLIST: { + // we register the cleanup ahead of time, because... + struct jurl_cleanup *clean = register_cleanup(jurl, JURL_CLEANUP_TYPE_SLIST); + + JanetView args = janet_getindexed(argv, 2); + for (int32_t i = 0; i < args.len; i++) { + const char *s = janet_getcstring(args.items, i); + // we use the cleanup pointer directly, this way... + struct curl_slist *newlist = curl_slist_append(clean->slist, s); + if (!newlist) { + // if we ever panic in the *middle* of handling, + // the slist will get cleaned up during garbage collection anyway + janet_panic("failed to append to slist in jurl_setopt"); + } + clean->slist = newlist; + } + curl_easy_setopt(jurl->handle, opt->opt, clean->slist); break; + } case JURL_PARAMTYPE_BITMASK: // TODO: bitmask table janet_panic("jurl_setopt: bitmasks not implemented"); |
