Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
C
ccan
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
mirror
ccan
Commits
118ace35
Commit
118ace35
authored
Mar 02, 2011
by
Rusty Russell
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
cast: new limited cast package inspired by Jan Engelhardt's libhx.
parent
ce6eef41
Changes
15
Hide whitespace changes
Inline
Side-by-side
Showing
15 changed files
with
468 additions
and
0 deletions
+468
-0
ccan/cast/LICENSE
ccan/cast/LICENSE
+1
-0
ccan/cast/_info
ccan/cast/_info
+84
-0
ccan/cast/cast.h
ccan/cast/cast.h
+131
-0
ccan/cast/test/compile_fail-cast_const-sizesame.c
ccan/cast/test/compile_fail-cast_const-sizesame.c
+28
-0
ccan/cast/test/compile_fail-cast_const.c
ccan/cast/test/compile_fail-cast_const.c
+17
-0
ccan/cast/test/compile_fail-cast_const2-sizesame.c
ccan/cast/test/compile_fail-cast_const2-sizesame.c
+28
-0
ccan/cast/test/compile_fail-cast_const2.c
ccan/cast/test/compile_fail-cast_const2.c
+17
-0
ccan/cast/test/compile_fail-cast_const3-sizesame.c
ccan/cast/test/compile_fail-cast_const3-sizesame.c
+28
-0
ccan/cast/test/compile_fail-cast_const3.c
ccan/cast/test/compile_fail-cast_const3.c
+17
-0
ccan/cast/test/compile_fail-cast_signed-const.c
ccan/cast/test/compile_fail-cast_signed-const.c
+15
-0
ccan/cast/test/compile_fail-cast_signed-sizesame.c
ccan/cast/test/compile_fail-cast_signed-sizesame.c
+28
-0
ccan/cast/test/compile_fail-cast_signed.c
ccan/cast/test/compile_fail-cast_signed.c
+16
-0
ccan/cast/test/compile_fail-cast_static-2.c
ccan/cast/test/compile_fail-cast_static-2.c
+22
-0
ccan/cast/test/compile_fail-cast_static-3.c
ccan/cast/test/compile_fail-cast_static-3.c
+20
-0
ccan/cast/test/compile_fail-cast_static.c
ccan/cast/test/compile_fail-cast_static.c
+16
-0
No files found.
ccan/cast/LICENSE
0 → 120000
View file @
118ace35
../../licenses/LGPL-3
\ No newline at end of file
ccan/cast/_info
0 → 100644
View file @
118ace35
#include <string.h>
#include "config.h"
/**
* cast - routines for safer casting.
*
* Often you want to cast in a limited way, such as removing a const or
* switching between integer types. However, normal casts will work on
* almost any type, making them dangerous when the code changes.
*
* These C++-inspired macros serve two purposes: they make it clear the
* exact reason for the cast, and they also (with some compilers) cause
* errors when misused.
*
* Based on Jan Engelhardt's libHX macros: http://libhx.sourceforge.net/
*
* Author: Jan Engelhardt
* Maintainer: Rusty Russell <rusty@rustcorp.com.au>
* License: LGPL
*
* Example:
* // Given "test" contains "3 t's in 'test string'
* #include <ccan/cast/cast.h>
* #include <stdint.h>
* #include <stdio.h>
*
* // Find char @orig in @str, if @repl, replace them. Return number.
* static size_t find_chars(char *str, char orig, char repl)
* {
* size_t i, count = 0;
* for (i = 0; str[i]; i++) {
* if (str[i] == orig) {
* count++;
* if (repl)
* str[i] = repl;
* }
* }
* return count;
* }
*
* // Terrible hash function.
* static uint64_t hash_string(const unsigned char *str)
* {
* size_t i;
* uint64_t hash = 0;
* for (i = 0; str[i]; i++)
* hash += str[i];
* return hash;
* }
*
* int main(int argc, char *argv[])
* {
* uint64_t hash;
*
* // find_chars wants a non-const string, but doesn't
* // need it if repl == 0.
* printf("%zu %c's in 'test string'\n",
* find_chars(cast_const(char *, "test string"),
* argv[1][0], 0),
* argv[1][0]);
*
* // hash_string wants an unsigned char.
* hash = hash_string(cast_signed(unsigned char *, argv[1]));
*
* // Need a long long to hand to printf.
* printf("Hash of '%s' = %llu\n", argv[1],
* cast_static(unsigned long long, hash));
* return 0;
* }
*
*/
int main(int argc, char *argv[])
{
/* Expect exactly one argument */
if (argc != 2)
return 1;
if (strcmp(argv[1], "depends") == 0) {
printf("ccan/build_assert\n");
return 0;
}
return 1;
}
ccan/cast/cast.h
0 → 100644
View file @
118ace35
#ifndef CCAN_CAST_H
#define CCAN_CAST_H
#include "config.h"
#include <ccan/build_assert/build_assert.h>
/**
* 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) \
+ EXPR_BUILD_ASSERT(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)(expr) \
+ EXPR_BUILD_ASSERT(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)(expr) \
+ EXPR_BUILD_ASSERT(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)(expr) \
+ EXPR_BUILD_ASSERT(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) \
(sizeof(*(expr)) == sizeof(*(type)0))
#define cast_const_compat2(expr, type) \
(sizeof(**(expr)) == sizeof(**(type)0))
#define cast_const_compat3(expr, type) \
(sizeof(***(expr)) == sizeof(***(type)0))
#endif
#endif
/* CCAN_CAST_H */
ccan/cast/test/compile_fail-cast_const-sizesame.c
0 → 100644
View file @
118ace35
#include <ccan/cast/cast.h>
#include <stdlib.h>
/* Note: this *isn't* sizeof(char) on all platforms. */
struct
char_struct
{
char
c
;
};
int
main
(
int
argc
,
char
*
argv
[])
{
char
*
uc
;
const
#ifdef FAIL
struct
char_struct
#else
char
#endif
*
p
=
NULL
;
uc
=
cast_const
(
char
*
,
p
);
return
0
;
}
#ifdef FAIL
#if !HAVE_TYPEOF||!HAVE_BUILTIN_CHOOSE_EXPR||!HAVE_BUILTIN_TYPES_COMPATIBLE_P
#error "Unfortunately we don't fail if cast_const can only use size"
#endif
#endif
ccan/cast/test/compile_fail-cast_const.c
0 → 100644
View file @
118ace35
#include <ccan/cast/cast.h>
#include <stdlib.h>
int
main
(
int
argc
,
char
*
argv
[])
{
char
*
uc
;
const
#ifdef FAIL
int
#else
char
#endif
*
p
=
NULL
;
uc
=
cast_const
(
char
*
,
p
);
return
0
;
}
ccan/cast/test/compile_fail-cast_const2-sizesame.c
0 → 100644
View file @
118ace35
#include <ccan/cast/cast.h>
#include <stdlib.h>
/* Note: this *isn't* sizeof(char) on all platforms. */
struct
char_struct
{
char
c
;
};
int
main
(
int
argc
,
char
*
argv
[])
{
char
**
uc
;
const
#ifdef FAIL
struct
char_struct
#else
char
#endif
**
p
=
NULL
;
uc
=
cast_const2
(
char
**
,
p
);
return
0
;
}
#ifdef FAIL
#if !HAVE_TYPEOF||!HAVE_BUILTIN_CHOOSE_EXPR||!HAVE_BUILTIN_TYPES_COMPATIBLE_P
#error "Unfortunately we don't fail if cast_const can only use size"
#endif
#endif
ccan/cast/test/compile_fail-cast_const2.c
0 → 100644
View file @
118ace35
#include <ccan/cast/cast.h>
#include <stdlib.h>
int
main
(
int
argc
,
char
*
argv
[])
{
char
**
uc
;
const
#ifdef FAIL
int
#else
char
#endif
**
p
=
NULL
;
uc
=
cast_const2
(
char
**
,
p
);
return
0
;
}
ccan/cast/test/compile_fail-cast_const3-sizesame.c
0 → 100644
View file @
118ace35
#include <ccan/cast/cast.h>
#include <stdlib.h>
/* Note: this *isn't* sizeof(char) on all platforms. */
struct
char_struct
{
char
c
;
};
int
main
(
int
argc
,
char
*
argv
[])
{
char
***
uc
;
const
#ifdef FAIL
struct
char_struct
#else
char
#endif
***
p
=
NULL
;
uc
=
cast_const3
(
char
***
,
p
);
return
0
;
}
#ifdef FAIL
#if !HAVE_TYPEOF||!HAVE_BUILTIN_CHOOSE_EXPR||!HAVE_BUILTIN_TYPES_COMPATIBLE_P
#error "Unfortunately we don't fail if cast_const can only use size"
#endif
#endif
ccan/cast/test/compile_fail-cast_const3.c
0 → 100644
View file @
118ace35
#include <ccan/cast/cast.h>
#include <stdlib.h>
int
main
(
int
argc
,
char
*
argv
[])
{
char
***
uc
;
const
#ifdef FAIL
int
#else
char
#endif
***
p
=
NULL
;
uc
=
cast_const3
(
char
***
,
p
);
return
0
;
}
ccan/cast/test/compile_fail-cast_signed-const.c
0 → 100644
View file @
118ace35
#include <ccan/cast/cast.h>
#include <stdlib.h>
int
main
(
int
argc
,
char
*
argv
[])
{
unsigned
char
*
uc
;
#ifdef FAIL
const
#endif
char
*
p
=
NULL
;
uc
=
cast_signed
(
unsigned
char
*
,
p
);
return
0
;
}
ccan/cast/test/compile_fail-cast_signed-sizesame.c
0 → 100644
View file @
118ace35
#include <ccan/cast/cast.h>
#include <stdlib.h>
/* Note: this *isn't* sizeof(char) on all platforms. */
struct
char_struct
{
char
c
;
};
int
main
(
int
argc
,
char
*
argv
[])
{
unsigned
char
*
uc
;
#ifdef FAIL
struct
char_struct
#else
char
#endif
*
p
=
NULL
;
uc
=
cast_signed
(
unsigned
char
*
,
p
);
return
0
;
}
#ifdef FAIL
#if !HAVE_TYPEOF||!HAVE_BUILTIN_CHOOSE_EXPR||!HAVE_BUILTIN_TYPES_COMPATIBLE_P
#error "Unfortunately we don't fail if cast_signed can only use size"
#endif
#endif
ccan/cast/test/compile_fail-cast_signed.c
0 → 100644
View file @
118ace35
#include <ccan/cast/cast.h>
#include <stdlib.h>
int
main
(
int
argc
,
char
*
argv
[])
{
unsigned
char
*
uc
;
#ifdef FAIL
int
#else
char
#endif
*
p
=
NULL
;
uc
=
cast_signed
(
unsigned
char
*
,
p
);
return
0
;
}
ccan/cast/test/compile_fail-cast_static-2.c
0 → 100644
View file @
118ace35
#include <ccan/cast/cast.h>
#include <stdlib.h>
int
main
(
int
argc
,
char
*
argv
[])
{
char
*
c
;
#ifdef FAIL
long
#else
char
#endif
*
p
=
0
;
c
=
cast_static
(
char
*
,
p
);
return
0
;
}
#ifdef FAIL
#if !HAVE_COMPOUND_LITERALS
#error "Unfortunately we don't fail if cast_static is a noop"
#endif
#endif
ccan/cast/test/compile_fail-cast_static-3.c
0 → 100644
View file @
118ace35
#include <ccan/cast/cast.h>
#include <stdlib.h>
int
main
(
int
argc
,
char
*
argv
[])
{
char
*
c
;
#ifdef FAIL
const
#endif
char
*
p
=
0
;
c
=
cast_static
(
char
*
,
p
);
return
0
;
}
#ifdef FAIL
#if !HAVE_COMPOUND_LITERALS
#error "Unfortunately we don't fail if cast_static is a noop"
#endif
#endif
ccan/cast/test/compile_fail-cast_static.c
0 → 100644
View file @
118ace35
#include <ccan/cast/cast.h>
#include <stdlib.h>
int
main
(
int
argc
,
char
*
argv
[])
{
char
c
;
#ifdef FAIL
char
*
#else
long
#endif
x
=
0
;
c
=
cast_static
(
char
,
x
);
return
0
;
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment