[PATCH] include: introduce byte counting macros.

Peter Hutterer peter.hutterer at who-t.net
Mon Jun 15 17:56:39 PDT 2009


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 <peter.hutterer at who-t.net>
---
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


More information about the xorg-devel mailing list