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