Instantly share code, notes, and snippets.
-
Star
0
(0)
You must be signed in to star a gist -
Fork
0
(0)
You must be signed in to fork a gist
-
Save mkmik/61026ba399bead6c7e25 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* Dummy port of the Amiga tag based extensible api. See: | |
* | |
* http://amigadev.elowar.com/read/ADCD_2.1/Includes_and_Autodocs_3._guide/node03D6.html | |
* | |
* | |
* note that the amiga api relied on the fact that the calling convention was | |
* very simple so the vararg stub could just take the pointer to the last argument, | |
* and get an array of TagItem records. | |
* | |
* see: | |
* http://amigadev.elowar.com/read/ADCD_2.1/Includes_and_Autodocs_3._guide/node03D4.html | |
* | |
* we cannot do the same with portable C, so this port uses a slightly different approach, | |
* taking some ideas from https://gist.github.com/mmikulicic/9a02109c8f3b66092038 . | |
* | |
*/ | |
#include <stdarg.h> | |
#include <stdio.h> | |
#include <stdlib.h> | |
#include <string.h> | |
typedef int (*tag_func_t)(void* opts, void* data); | |
typedef void* tag_t; | |
struct tag_item { | |
tag_func_t tag; | |
void* data; | |
struct tag_item* next; | |
}; | |
typedef struct tag_item tag_item_t; | |
int TAG_END(void* opts, void* data) { | |
return -1; | |
} | |
int TAG_IGNORE(void* opts, void* data) { | |
return -1; | |
} | |
void process_tags_va(va_list argp, tag_t tag, void *opts) { | |
while(1) { | |
void *data = va_arg(argp, void*); | |
if (((tag_func_t)tag)(opts, data) == -1) { | |
break; | |
} | |
tag = va_arg(argp, tag_t); | |
} | |
} | |
void process_tag_list(tag_item_t *tags, void *opts) { | |
while(tags) { | |
if(tags->tag(opts, tags->data) == -1) { | |
break; | |
} | |
tags = tags->next; | |
} | |
} | |
void tag_add(tag_item_t **tags, tag_item_t *item) { | |
// yeah its in the revrse order, I'm lazy. | |
item->next = *tags; | |
*tags = item; | |
} | |
// ----- ns_send | |
typedef struct { | |
int deadline; | |
int n_headers; | |
} ns_send_opts_t; | |
int ns_deadline(void* vopts, void* data) { | |
ns_send_opts_t* opts = (ns_send_opts_t*)vopts; | |
opts->deadline = (int)data; | |
printf("processing ns_deadline: %d\n", opts->deadline); | |
return 0; | |
} | |
typedef struct { | |
char* key; | |
char* value; | |
} ns_header_value_t; | |
int ns_header(void* vopts, void* data) { | |
ns_header_value_t* args = (ns_header_value_t*)data; | |
printf("processing ns_header: %s:%s\n", args->key, args->value); | |
free(args); | |
ns_send_opts_t* opts = (ns_send_opts_t*)vopts; | |
opts->n_headers++; | |
return 0; | |
} | |
void* ns_header_value(char* key, char* value) { | |
ns_header_value_t* args = malloc(sizeof(ns_header_value_t)); | |
args->key = key; | |
args->value = value; | |
return args; | |
} | |
static ns_send_opts_t ns_send_default_opts = {-1, 0}; | |
void ns_send_opts(char* addr, char* body, ns_send_opts_t opts) { | |
printf("sending %s to %s, deadline: %d, num headers: %d\n", body, addr, opts.deadline, opts.n_headers); | |
} | |
void ns_send_tags(char* addr, char* body, tag_t tag, ...) { | |
ns_send_opts_t opts = ns_send_default_opts; | |
va_list argp; | |
va_start(argp, tag); | |
process_tags_va(argp, tag, &opts); | |
va_end(argp); | |
ns_send_opts(addr, body, opts); | |
} | |
void ns_send_tag_list(char* addr, char* body, tag_item_t *tags) { | |
ns_send_opts_t opts = ns_send_default_opts; | |
process_tag_list(tags, &opts); | |
ns_send_opts(addr, body, opts); | |
} | |
void ns_send(char* addr, char* body) { | |
ns_send_tags(addr, body, TAG_END); | |
} | |
int main() { | |
ns_send("foo", "bar"); | |
ns_send_tags("foo", "bar", ns_deadline, 3600, TAG_END); | |
ns_send_tags("foo", "bar", ns_header, ns_header_value("content-type", "poo"), ns_deadline, 3600, TAG_END); | |
tag_item_t *tags = {0}; | |
tag_item_t deadline = {ns_deadline, (void*)3600}; | |
tag_add(&tags, &deadline); | |
tag_item_t header; | |
if (42==42) { | |
header = (tag_item_t){ns_header,ns_header_value("content-type", "dummy")}; | |
tag_add(&tags, &header); | |
} | |
ns_send_tag_list("foo", "bar", tags); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment