diff options
Diffstat (limited to 'handy.h')
-rw-r--r-- | handy.h | 26 |
1 files changed, 21 insertions, 5 deletions
@@ -1094,11 +1094,27 @@ patched there. The file as of this writing is cpan/Devel-PPPort/parts/inc/misc #define FITS_IN_8_BITS(c) (1) #endif -/* Returns true if c is in the range l..u - * Written with the cast so it only needs one conditional test - */ -#define inRANGE(c, l, u) (__ASSERT_((u) >= (l)) \ - ((WIDEST_UTYPE) (((c) - (l)) | 0) <= ((WIDEST_UTYPE) ((u) - (l))))) +/* Returns true if c is in the range l..u, where 'l' is non-negative + * Written this way so that after optimization, only one conditional test is + * needed. + * + * This isn't fully general, except for the special cased 'signed char' (which + * should be resolved at compile time): It won't work if 'c' is negative, and + * 'l' is larger than the max for that signed type. Thus if 'c' is a negative + * int, and 'l' is larger than INT_MAX, it will fail. To protect agains this + * happening, there is an assert that will generate a warning if c is larger + * than e.g. INT_MAX if it is an 'unsigned int'. This could be a false + * positive, but khw couldn't figure out a way to make it better. It's good + * enough so far */ +#define inRANGE(c, l, u) (__ASSERT_((l) >= 0) __ASSERT_((u) >= (l)) \ + ((sizeof(c) == 1) \ + ? (((WIDEST_UTYPE) ((((U8) (c))|0) - (l))) <= ((WIDEST_UTYPE) ((u) - (l)))) \ + : (__ASSERT_( (((WIDEST_UTYPE) 1) << (CHARBITS * sizeof(c) - 1) & (c)) \ + /* sign bit of c is 0 */ == 0 \ + || (((~ ((WIDEST_UTYPE) 1) << ((CHARBITS * sizeof(c) - 1) - 1))\ + /* l not larger than largest value in c's signed type */ \ + & ~ ((WIDEST_UTYPE) 0)) & (l)) == 0) \ + ((WIDEST_UTYPE) (((c) - (l)) | 0) <= ((WIDEST_UTYPE) ((u) - (l))))))) #ifdef EBCDIC # ifndef _ALL_SOURCE |