damus

nostr ios client
git clone git://jb55.com/damus
Log | Files | Refs | README | LICENSE

_info (4415B)


      1 #include "config.h"
      2 #include <stdio.h>
      3 #include <string.h>
      4 
      5 /**
      6  * typesafe_cb - macros for safe callbacks.
      7  *
      8  * The basis of the typesafe_cb header is typesafe_cb_cast(): a
      9  * conditional cast macro.   If an expression exactly matches a given
     10  * type, it is cast to the target type, otherwise it is left alone.
     11  *
     12  * This allows us to create functions which take a small number of
     13  * specific types, rather than being forced to use a void *.  In
     14  * particular, it is useful for creating typesafe callbacks as the
     15  * helpers typesafe_cb(), typesafe_cb_preargs() and
     16  * typesafe_cb_postargs() demonstrate.
     17  * 
     18  * The standard way of passing arguments to callback functions in C is
     19  * to use a void pointer, which the callback then casts back to the
     20  * expected type.  This unfortunately subverts the type checking the
     21  * compiler would perform if it were a direct call.  Here's an example:
     22  *
     23  *	static void my_callback(void *_obj)
     24  *	{
     25  *		struct obj *obj = _obj;
     26  *		...
     27  *	}
     28  *	...
     29  *		register_callback(my_callback, &my_obj);
     30  *
     31  * If we wanted to use the natural type for my_callback (ie. "void
     32  * my_callback(struct obj *obj)"), we could make register_callback()
     33  * take a void * as its first argument, but this would subvert all
     34  * type checking.  We really want register_callback() to accept only
     35  * the exactly correct function type to match the argument, or a
     36  * function which takes a void *.
     37  *
     38  * This is where typesafe_cb() comes in: it uses typesafe_cb_cast() to
     39  * cast the callback function if it matches the argument type:
     40  *
     41  *	void _register_callback(void (*cb)(void *arg), void *arg);
     42  *	#define register_callback(cb, arg)				\
     43  *		_register_callback(typesafe_cb(void, void *, (cb), (arg)), \
     44  *				   (arg))
     45  *
     46  * On compilers which don't support the extensions required
     47  * typesafe_cb_cast() and friend become an unconditional cast, so your
     48  * code will compile but you won't get type checking.
     49  *
     50  * Example:
     51  *	#include <ccan/typesafe_cb/typesafe_cb.h>
     52  *	#include <stdlib.h>
     53  *	#include <stdio.h>
     54  *
     55  *	// Generic callback infrastructure.
     56  *	struct callback {
     57  *		struct callback *next;
     58  *		int value;
     59  *		int (*callback)(int value, void *arg);
     60  *		void *arg;
     61  *	};
     62  *	static struct callback *callbacks;
     63  *	
     64  *	static void _register_callback(int value, int (*cb)(int, void *),
     65  *				       void *arg)
     66  *	{
     67  *		struct callback *new = malloc(sizeof(*new));
     68  *		new->next = callbacks;
     69  *		new->value = value;
     70  *		new->callback = cb;
     71  *		new->arg = arg;
     72  *		callbacks = new;
     73  *	}
     74  *	#define register_callback(value, cb, arg)			\
     75  *		_register_callback(value,				\
     76  *				   typesafe_cb_preargs(int, void *,	\
     77  *						       (cb), (arg), int),\
     78  *				   (arg))
     79  *	
     80  *	static struct callback *find_callback(int value)
     81  *	{
     82  *		struct callback *i;
     83  *	
     84  *		for (i = callbacks; i; i = i->next)
     85  *			if (i->value == value)
     86  *				return i;
     87  *		return NULL;
     88  *	}   
     89  *
     90  *	// Define several silly callbacks.  Note they don't use void *!
     91  *	#define DEF_CALLBACK(name, op)			\
     92  *		static int name(int val, int *arg)	\
     93  *		{					\
     94  *			printf("%s", #op);		\
     95  *			return val op *arg;		\
     96  *		}
     97  *	DEF_CALLBACK(multiply, *);
     98  *	DEF_CALLBACK(add, +);
     99  *	DEF_CALLBACK(divide, /);
    100  *	DEF_CALLBACK(sub, -);
    101  *	DEF_CALLBACK(or, |);
    102  *	DEF_CALLBACK(and, &);
    103  *	DEF_CALLBACK(xor, ^);
    104  *	DEF_CALLBACK(assign, =);
    105  *
    106  *	// Silly game to find the longest chain of values.
    107  *	int main(int argc, char *argv[])
    108  *	{
    109  *		int i, run = 1, num = argc > 1 ? atoi(argv[1]) : 0;
    110  *	
    111  *		for (i = 1; i < 1024;) {
    112  *			// Since run is an int, compiler checks "add" does too.
    113  *			register_callback(i++, add, &run);
    114  *			register_callback(i++, divide, &run);
    115  *			register_callback(i++, sub, &run);
    116  *			register_callback(i++, multiply, &run);
    117  *			register_callback(i++, or, &run);
    118  *			register_callback(i++, and, &run);
    119  *			register_callback(i++, xor, &run);
    120  *			register_callback(i++, assign, &run);
    121  *		}
    122  *	
    123  *		printf("%i ", num);
    124  *		while (run < 56) {
    125  *			struct callback *cb = find_callback(num % i);
    126  *			if (!cb) {
    127  *				printf("-> STOP\n");
    128  *				return 1;
    129  *			}
    130  *			num = cb->callback(num, cb->arg);
    131  *			printf("->%i ", num);
    132  *			run++;
    133  *		}
    134  *		printf("-> Winner!\n");
    135  *		return 0;
    136  *	}
    137  *
    138  * License: CC0 (Public domain)
    139  * Author: Rusty Russell <rusty@rustcorp.com.au>
    140  */
    141 int main(int argc, char *argv[])
    142 {
    143 	if (argc != 2)
    144 		return 1;
    145 
    146 	if (strcmp(argv[1], "depends") == 0) {
    147 		return 0;
    148 	}
    149 
    150 	return 1;
    151 }