diff options
author | Karl Williamson <khw@cpan.org> | 2019-06-26 12:01:05 -0600 |
---|---|---|
committer | Karl Williamson <khw@cpan.org> | 2019-09-14 22:26:49 -0600 |
commit | 833b0f46f2b673765c7e3d42e8530db0ad65ceeb (patch) | |
tree | 8c6ac4fe41ccac6338975c2bc7d2d886daa5c629 /handy.h | |
parent | a15223fd18aff8e134dce76a2e5428202c0f2df1 (diff) | |
download | perl-833b0f46f2b673765c7e3d42e8530db0ad65ceeb.tar.gz |
Add withinCOUNT() macro and change inRANGE to use it
This uses just one conditional to see if a value is between low and
(low + n).
Diffstat (limited to 'handy.h')
-rw-r--r-- | handy.h | 11 |
1 files changed, 9 insertions, 2 deletions
@@ -1317,6 +1317,12 @@ or casts #define FITS_IN_8_BITS(c) (1) #endif +/* Returns true if l <= c <= l + n, where 'l' and 'n' are non-negative + * Written this way so that after optimization, only one conditional test is + * needed. */ +#define withinCOUNT(c, l, n) (__ASSERT_((l) >= 0) __ASSERT_((n) >= (0)) \ + (((WIDEST_UTYPE) (((c) | 0) - ((l) | 0))) <= (((WIDEST_UTYPE) ((n) | 0))))) + /* 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. @@ -1329,15 +1335,16 @@ or casts * 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)))) \ + ? withinCOUNT(((U8) (c)), (l), ((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))))))) + withinCOUNT((c), (l), ((u) - (l)))))) #ifdef EBCDIC # ifndef _ALL_SOURCE |