This patch adds the following three macros: count_bytes(bits) - the number of bytes needed to hold 'bits' count_4byte_units(bytes) - the number of 4-byte units to hold 'bytes' pad_to_4(bytes) - the closest multiple of 4 equal to or larger than 'bytes'.
All three operations are common in protocol processing and currently the server has ((foo + 7)/8 + 3)/4 operations all over the place. A common set of macros reduce the error rate of these (albeit simple) calculations and improve readability of the code. The macros do not protect against overflow. Signed-off-by: Peter Hutterer <[email protected]> --- I've over the last week debugged at least three or four occasions where I got a parenthesis wrong, forgot about a *4 or /4, etc. And I'm getting sick of it, let's just use some common macros already. My local xserver/Xi/ is switched and I'll probably do the same to other parts of the code. Any complaints? I'm open for better names if necessary. include/misc.h | 20 ++++++++++++++++++++ test/input.c | 39 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 59 insertions(+), 0 deletions(-) diff --git a/include/misc.h b/include/misc.h index 61dd947..3d52d5b 100644 --- a/include/misc.h +++ b/include/misc.h @@ -180,6 +180,26 @@ typedef struct _xReq *xReqPtr; #endif +/** + * Calculate the number of bytes needed to hold bits. + * @param bits The minimum number of bits needed. + * @return The number of bytes needed to hold bits. + */ +#define count_bytes(bits) (((bits) + 7)/8) +/** + * Calculate the number of 4-byte units needed to hold the given number of + * bytes. + * @param bytes The minimum number of bytes needed. + * @return The number of 4-byte units neede to hold bytes. + */ +#define count_4byte_units(bytes) (((bytes) + 3)/4) +/** + * Calculate the number of bytes (in multiples of 4) needed to hold bytes. + * @param bytes The minimum number of bytes needed. + * @return The closest multiple of 4 that is equal or higher than bytes. + */ +#define pad_to_4(bytes) (count_4byte_units((bytes)) * 4) + /* some macros to help swap requests, replies, and events */ #define LengthRestB(stuff) \ diff --git a/test/input.c b/test/input.c index b80e1f5..6d988f5 100644 --- a/test/input.c +++ b/test/input.c @@ -677,6 +677,44 @@ static void dix_grab_matching(void) g_assert(rc == TRUE); } +static void include_byte_padding_macros(void) +{ + int i; + g_test_message("Testing count_bytes()"); + + /* the macros don't provide overflow protection */ + for (i = 0; i < INT_MAX - 7; i++) + { + int expected_bytes; + expected_bytes = (i + 7)/8; + + g_assert(count_bytes(i) >= i/8); + g_assert((count_bytes(i) * 8) - i <= 7); + } + + g_test_message("Testing count_4byte_units()"); + for (i = 0; i < INT_MAX - 3; i++) + { + int expected_4byte; + expected_4byte = (i + 3)/4; + + g_assert(count_4byte_units(i) <= i); + g_assert((count_4byte_units(i) * 4) - i <= 3); + } + + g_test_message("Testing pad_to_4"); + + for (i = 0; i < INT_MAX - 3; i++) + { + int expected_bytes; + expected_bytes = ((i + 3)/4) * 4; + + g_assert(pad_to_4(i) >= i); + g_assert(pad_to_4(i) - i <= 3); + } + +} + int main(int argc, char** argv) { g_test_init(&argc, &argv,NULL); @@ -687,6 +725,7 @@ int main(int argc, char** argv) g_test_add_func("/dix/input/check-grab-values", dix_check_grab_values); g_test_add_func("/dix/input/xi2-struct-sizes", xi2_struct_sizes); g_test_add_func("/dix/input/grab_matching", dix_grab_matching); + g_test_add_func("/include/byte_padding_macros", include_byte_padding_macros); return g_test_run(); } -- 1.6.3.rc1.2.g0164.dirty _______________________________________________ xorg-devel mailing list [email protected] http://lists.x.org/mailman/listinfo/xorg-devel
