include: introduce byte counting functions.

This patch adds the following three functions:
 bits_to_bytes(bits) - the number of bytes needed to hold 'bits'
 bytes_to_int32(bytes) - the number of 4-byte units to hold 'bytes'
 pad_to_int32(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 functions reduce the error rate of these (albeit simple) calculations and
improve readability of the code.

The functions do not check for overflow.

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
This commit is contained in:
Peter Hutterer 2009-06-29 13:09:57 +10:00
parent 2c535b6f13
commit 912402fd71
2 changed files with 69 additions and 0 deletions

View File

@ -180,6 +180,36 @@ 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.
*/
static inline int
bits_to_bytes(const int bits) {
return ((bits + 7) >> 3);
}
/**
* 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 needed to hold bytes.
*/
static inline int
bytes_to_int32(const int bytes) {
return (((bytes) + 3) >> 2);
}
/**
* 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.
*/
static inline int
pad_to_int32(const int bytes) {
return (((bytes) + 3) & ~3);
}
/* some macros to help swap requests, replies, and events */
#define LengthRestB(stuff) \

View File

@ -678,6 +678,44 @@ static void dix_grab_matching(void)
g_assert(rc == TRUE);
}
static void include_byte_padding_macros(void)
{
int i;
g_test_message("Testing bits_to_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(bits_to_bytes(i) >= i/8);
g_assert((bits_to_bytes(i) * 8) - i <= 7);
}
g_test_message("Testing bytes_to_int32()");
for (i = 0; i < INT_MAX - 3; i++)
{
int expected_4byte;
expected_4byte = (i + 3)/4;
g_assert(bytes_to_int32(i) <= i);
g_assert((bytes_to_int32(i) * 4) - i <= 3);
}
g_test_message("Testing pad_to_int32");
for (i = 0; i < INT_MAX - 3; i++)
{
int expected_bytes;
expected_bytes = ((i + 3)/4) * 4;
g_assert(pad_to_int32(i) >= i);
g_assert(pad_to_int32(i) - i <= 3);
}
}
int main(int argc, char** argv)
{
g_test_init(&argc, &argv,NULL);
@ -688,6 +726,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();
}