From: Ben Pfaff Date: Wed, 18 Jan 2012 00:53:29 +0000 (-0800) Subject: util: New function bitwise_zero(). X-Git-Tag: sliver-openvswitch-0.1-1~405 X-Git-Url: http://git.onelab.eu/?a=commitdiff_plain;h=6cc7ea5ea05a71f01526577439ebedcc133f99cd;p=sliver-openvswitch.git util: New function bitwise_zero(). Signed-off-by: Ben Pfaff --- diff --git a/lib/util.c b/lib/util.c index 811902afb..dfdc51eae 100644 --- a/lib/util.c +++ b/lib/util.c @@ -803,6 +803,54 @@ bitwise_copy(const void *src_, unsigned int src_len, unsigned int src_ofs, } } +/* Zeros the 'n_bits' bits starting from bit 'dst_ofs' in 'dst'. 'dst' is + * 'dst_len' bytes long. + * + * If you consider all of 'dst' to be a single unsigned integer in network byte + * order, then bit N is the bit with value 2**N. That is, bit 0 is the bit + * with value 1 in dst[dst_len - 1], bit 1 is the bit with value 2, bit 2 is + * the bit with value 4, ..., bit 8 is the bit with value 1 in dst[dst_len - + * 2], and so on. + * + * Required invariant: + * dst_ofs + n_bits <= dst_len * 8 + */ +void +bitwise_zero(void *dst_, unsigned int dst_len, unsigned dst_ofs, + unsigned int n_bits) +{ + uint8_t *dst = dst_; + + if (!n_bits) { + return; + } + + dst += dst_len - (dst_ofs / 8 + 1); + dst_ofs %= 8; + + if (dst_ofs) { + unsigned int chunk = MIN(n_bits, 8 - dst_ofs); + + *dst &= ~(((1 << chunk) - 1) << dst_ofs); + + n_bits -= chunk; + if (!n_bits) { + return; + } + + dst--; + } + + while (n_bits >= 8) { + *dst-- = 0; + n_bits -= 8; + } + + if (n_bits) { + *dst &= ~((1 << n_bits) - 1); + } +} + /* Copies the 'n_bits' low-order bits of 'value' into the 'n_bits' bits * starting at bit 'dst_ofs' in 'dst', which is 'dst_len' bytes long. * diff --git a/lib/util.h b/lib/util.h index c8eb0046d..d504f2fe9 100644 --- a/lib/util.h +++ b/lib/util.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2009, 2010, 2011 Nicira Networks. + * Copyright (c) 2008, 2009, 2010, 2011, 2012 Nicira Networks. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -211,6 +211,8 @@ bool is_all_ones(const uint8_t *, size_t); void bitwise_copy(const void *src, unsigned int src_len, unsigned int src_ofs, void *dst, unsigned int dst_len, unsigned int dst_ofs, unsigned int n_bits); +void bitwise_zero(void *dst_, unsigned int dst_len, unsigned dst_ofs, + unsigned int n_bits); void bitwise_put(uint64_t value, void *dst, unsigned int dst_len, unsigned int dst_ofs, unsigned int n_bits); diff --git a/tests/test-util.c b/tests/test-util.c index 45ea8f29f..82d08610d 100644 --- a/tests/test-util.c +++ b/tests/test-util.c @@ -102,6 +102,47 @@ check_bitwise_copy(void) } } +static void +check_bitwise_zero(void) +{ + unsigned int n_loops; + int dst_ofs; + int n_bits; + + n_loops = 0; + for (n_bits = 0; n_bits <= 64; n_bits++) { + for (dst_ofs = 0; dst_ofs < 64 - n_bits; dst_ofs++) { + ovs_be64 dst = htonll(random_uint64()); + ovs_be64 orig_dst = dst; + ovs_be64 expect; + + if (n_bits == 64) { + expect = htonll(0); + } else { + uint64_t mask = (UINT64_C(1) << n_bits) - 1; + expect = orig_dst & ~htonll(mask << dst_ofs); + } + + bitwise_zero(&dst, sizeof dst, dst_ofs, n_bits); + if (expect != dst) { + fprintf(stderr,"bitwise_zero(0x%016"PRIx64",8,%d, %d) " + "yielded 0x%016"PRIx64" " + "instead of the expected 0x%016"PRIx64"\n", + ntohll(orig_dst), dst_ofs, + n_bits, + ntohll(dst), ntohll(expect)); + abort(); + } + + n_loops++; + } + } + + if (n_loops != 64 * (64 + 1) / 2) { + abort(); + } +} + int main(void) { @@ -127,5 +168,7 @@ main(void) check_bitwise_copy(); + check_bitwise_zero(); + return 0; }