From 754c677b0bbf3ea6c7d2a73c93848f1b0d68c91e Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Mon, 20 Jun 2011 16:54:15 +0930 Subject: lib: import ccan modules for tdb2 Imported from git://git.ozlabs.org/~ccan/ccan init-1161-g661d41f Signed-off-by: Rusty Russell --- lib/ccan/cast/cast.h | 129 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 129 insertions(+) create mode 100644 lib/ccan/cast/cast.h (limited to 'lib/ccan/cast/cast.h') diff --git a/lib/ccan/cast/cast.h b/lib/ccan/cast/cast.h new file mode 100644 index 0000000000..daebd85723 --- /dev/null +++ b/lib/ccan/cast/cast.h @@ -0,0 +1,129 @@ +#ifndef CCAN_CAST_H +#define CCAN_CAST_H +#include "config.h" +#include +#include + +/** + * cast_signed - cast a (const) char * to/from (const) signed/unsigned char *. + * @type: some char * variant. + * @expr: expression (of some char * variant) to cast. + * + * Some libraries insist on an unsigned char in various places; cast_signed + * makes sure (with suitable compiler) that the expression you are casting + * only differs in signed/unsigned, not in type or const-ness. + */ +#define cast_signed(type, expr) \ + ((type)(expr) \ + + BUILD_ASSERT_OR_ZERO(cast_sign_compatible(type, (expr)))) + +/** + * cast_const - remove a const qualifier from a pointer. + * @type: some pointer type. + * @expr: expression to cast. + * + * This ensures that you are only removing the const qualifier from an + * expression. The expression must otherwise match @type. + * + * If @type is a pointer to a pointer, you must use cast_const2 (etc). + * + * Example: + * // Dumb open-coded strstr variant. + * static char *find_needle(const char *haystack) + * { + * size_t i; + * for (i = 0; i < strlen(haystack); i++) + * if (memcmp("needle", haystack+i, strlen("needle")) == 0) + * return cast_const(char *, haystack+i); + * return NULL; + * } + */ +#define cast_const(type, expr) \ + ((type)((intptr_t)(expr) \ + + BUILD_ASSERT_OR_ZERO(cast_const_compat1((expr), type)))) + +/** + * cast_const2 - remove a const qualifier from a pointer to a pointer. + * @type: some pointer to pointer type. + * @expr: expression to cast. + * + * This ensures that you are only removing the const qualifier from an + * expression. The expression must otherwise match @type. + */ +#define cast_const2(type, expr) \ + ((type)((intptr_t)(expr) \ + + BUILD_ASSERT_OR_ZERO(cast_const_compat2((expr), type)))) + +/** + * cast_const3 - remove a const from a pointer to a pointer to a pointer.. + * @type: some pointer to pointer to pointer type. + * @expr: expression to cast. + * + * This ensures that you are only removing the const qualifier from an + * expression. The expression must otherwise match @type. + */ +#define cast_const3(type, expr) \ + ((type)((intptr_t)(expr) \ + + BUILD_ASSERT_OR_ZERO(cast_const_compat3((expr), type)))) + + +/** + * cast_static - explicit mimic of implicit cast. + * @type: some type. + * @expr: expression to cast. + * + * This ensures that the cast is not to or from a pointer: it can only be + * an implicit cast, such as a pointer to a similar const pointer, or between + * integral types. + */ +#if HAVE_COMPOUND_LITERALS +#define cast_static(type, expr) \ + ((struct { type x; }){(expr)}.x) +#else +#define cast_static(type, expr) \ + ((type)(expr)) +#endif + +/* Herein lies the gcc magic to evoke compile errors. */ +#if HAVE_BUILTIN_CHOOSE_EXPR && HAVE_BUILTIN_TYPES_COMPATIBLE_P && HAVE_TYPEOF +#define cast_sign_compatible(t, e) \ + __builtin_choose_expr( \ + __builtin_types_compatible_p(__typeof__(t), char *) || \ + __builtin_types_compatible_p(__typeof__(t), signed char *) || \ + __builtin_types_compatible_p(__typeof__(t), unsigned char *), \ + /* if type is not const qualified */ \ + __builtin_types_compatible_p(__typeof__(e), char *) || \ + __builtin_types_compatible_p(__typeof__(e), signed char *) || \ + __builtin_types_compatible_p(__typeof__(e), unsigned char *), \ + /* and if it is... */ \ + __builtin_types_compatible_p(__typeof__(e), const char *) || \ + __builtin_types_compatible_p(__typeof__(e), const signed char *) || \ + __builtin_types_compatible_p(__typeof__(e), const unsigned char *) ||\ + __builtin_types_compatible_p(__typeof__(e), char *) || \ + __builtin_types_compatible_p(__typeof__(e), signed char *) || \ + __builtin_types_compatible_p(__typeof__(e), unsigned char *) \ + ) + +#define cast_const_strip1(expr) \ + __typeof__(*(struct { int z; __typeof__(expr) x; }){0}.x) +#define cast_const_strip2(expr) \ + __typeof__(**(struct { int z; __typeof__(expr) x; }){0}.x) +#define cast_const_strip3(expr) \ + __typeof__(***(struct { int z; __typeof__(expr) x; }){0}.x) +#define cast_const_compat1(expr, type) \ + __builtin_types_compatible_p(cast_const_strip1(expr), \ + cast_const_strip1(type)) +#define cast_const_compat2(expr, type) \ + __builtin_types_compatible_p(cast_const_strip2(expr), \ + cast_const_strip2(type)) +#define cast_const_compat3(expr, type) \ + __builtin_types_compatible_p(cast_const_strip3(expr), \ + cast_const_strip3(type)) +#else +#define cast_sign_compatible(type, expr) \ + (sizeof(*(type)0) == 1 && sizeof(*(expr)) == 1) +#define cast_const_compat1(expr, type) (1) +#define cast_const_compat2(expr, type) (1) +#define cast_const_compat3(expr, type) (1) +#endif +#endif /* CCAN_CAST_H */ -- cgit