]> git.ozlabs.org Git - ccan/blob - ccan/cast/cast.h
tdb2: begin tdb1 to tdb2 porting guide.
[ccan] / ccan / cast / cast.h
1 #ifndef CCAN_CAST_H
2 #define CCAN_CAST_H
3 #include "config.h"
4 #include <ccan/build_assert/build_assert.h>
5
6 /**
7  * cast_signed - cast a (const) char * to/from (const) signed/unsigned char *.
8  * @type: some char * variant.
9  * @expr: expression (of some char * variant) to cast.
10  *
11  * Some libraries insist on an unsigned char in various places; cast_signed
12  * makes sure (with suitable compiler) that the expression you are casting
13  * only differs in signed/unsigned, not in type or const-ness.
14  */
15 #define cast_signed(type, expr)                                         \
16         ((type)(expr)                                                   \
17          + BUILD_ASSERT_OR_ZERO(cast_sign_compatible(type, (expr))))
18
19 /**
20  * cast_const - remove a const qualifier from a pointer.
21  * @type: some pointer type.
22  * @expr: expression to cast.
23  *
24  * This ensures that you are only removing the const qualifier from an
25  * expression.  The expression must otherwise match @type.
26  *
27  * If @type is a pointer to a pointer, you must use cast_const2 (etc).
28  *
29  * Example:
30  *      // Dumb open-coded strstr variant.
31  *      static char *find_needle(const char *haystack)
32  *      {
33  *              size_t i;
34  *              for (i = 0; i < strlen(haystack); i++)
35  *              if (memcmp("needle", haystack+i, strlen("needle")) == 0)
36  *                      return cast_const(char *, haystack+i);
37  *              return NULL;
38  *      }
39  */
40 #define cast_const(type, expr)                                  \
41         ((type)(expr)                                           \
42          + BUILD_ASSERT_OR_ZERO(cast_const_compat1((expr), type)))
43
44 /**
45  * cast_const2 - remove a const qualifier from a pointer to a pointer.
46  * @type: some pointer to pointer type.
47  * @expr: expression to cast.
48  *
49  * This ensures that you are only removing the const qualifier from an
50  * expression.  The expression must otherwise match @type.
51  */
52 #define cast_const2(type, expr)                                 \
53         ((type)(expr)                                           \
54          + BUILD_ASSERT_OR_ZERO(cast_const_compat2((expr), type)))
55
56 /**
57  * cast_const3 - remove a const from a pointer to a pointer to a pointer..
58  * @type: some pointer to pointer to pointer type.
59  * @expr: expression to cast.
60  *
61  * This ensures that you are only removing the const qualifier from an
62  * expression.  The expression must otherwise match @type.
63  */
64 #define cast_const3(type, expr)                                 \
65         ((type)(expr)                                           \
66          + BUILD_ASSERT_OR_ZERO(cast_const_compat3((expr), type)))
67
68
69 /**
70  * cast_static - explicit mimic of implicit cast.
71  * @type: some type.
72  * @expr: expression to cast.
73  *
74  * This ensures that the cast is not to or from a pointer: it can only be
75  * an implicit cast, such as a pointer to a similar const pointer, or between
76  * integral types.
77  */
78 #if HAVE_COMPOUND_LITERALS
79 #define cast_static(type, expr)                 \
80         ((struct { type x; }){(expr)}.x)
81 #else
82 #define cast_static(type, expr)                 \
83         ((type)(expr))
84 #endif
85
86 /* Herein lies the gcc magic to evoke compile errors. */
87 #if HAVE_BUILTIN_CHOOSE_EXPR && HAVE_BUILTIN_TYPES_COMPATIBLE_P && HAVE_TYPEOF
88 #define cast_sign_compatible(t, e) \
89   __builtin_choose_expr(                                                \
90           __builtin_types_compatible_p(__typeof__(t), char *) ||        \
91           __builtin_types_compatible_p(__typeof__(t), signed char *) || \
92           __builtin_types_compatible_p(__typeof__(t), unsigned char *), \
93           /* if type is not const qualified */                          \
94           __builtin_types_compatible_p(__typeof__(e), char *) ||        \
95           __builtin_types_compatible_p(__typeof__(e), signed char *) || \
96           __builtin_types_compatible_p(__typeof__(e), unsigned char *), \
97           /* and if it is... */                                         \
98           __builtin_types_compatible_p(__typeof__(e), const char *) ||  \
99           __builtin_types_compatible_p(__typeof__(e), const signed char *) || \
100           __builtin_types_compatible_p(__typeof__(e), const unsigned char *) ||\
101           __builtin_types_compatible_p(__typeof__(e), char *) ||        \
102           __builtin_types_compatible_p(__typeof__(e), signed char *) || \
103           __builtin_types_compatible_p(__typeof__(e), unsigned char *)  \
104           )
105
106 #define cast_const_strip1(expr)                 \
107         __typeof__(*(struct { int z; __typeof__(expr) x; }){0}.x)
108 #define cast_const_strip2(expr) \
109         __typeof__(**(struct { int z; __typeof__(expr) x; }){0}.x)
110 #define cast_const_strip3(expr) \
111         __typeof__(***(struct { int z; __typeof__(expr) x; }){0}.x)
112 #define cast_const_compat1(expr, type)                                  \
113         __builtin_types_compatible_p(cast_const_strip1(expr),           \
114                                      cast_const_strip1(type))
115 #define cast_const_compat2(expr, type)                                  \
116         __builtin_types_compatible_p(cast_const_strip2(expr),           \
117                                      cast_const_strip2(type))
118 #define cast_const_compat3(expr, type)                                  \
119         __builtin_types_compatible_p(cast_const_strip3(expr),           \
120                                      cast_const_strip3(type))
121 #else
122 #define cast_sign_compatible(type, expr)                \
123         (sizeof(*(type)0) == 1 && sizeof(*(expr)) == 1)
124 #define cast_const_compat1(expr, type)          \
125         (sizeof(*(expr)) == sizeof(*(type)0))
126 #define cast_const_compat2(expr, type)          \
127         (sizeof(**(expr)) == sizeof(**(type)0))
128 #define cast_const_compat3(expr, type)                  \
129         (sizeof(***(expr)) == sizeof(***(type)0))
130 #endif
131 #endif /* CCAN_CAST_H */