Index: ChangeLog
===================================================================
--- ChangeLog	(revision 7392)
+++ ChangeLog	(working copy)
@@ -0,0 +1,10 @@
+2008-08-24  Zbigniew Chyla  <zbigniew.chyla@gmail.com>
+
+	Bug 503096 - add inline function for overflow-resistant add/subtract
+
+	* glib/gutils.h (g_int_add_with_saturation, g_int_sub_with_saturation):
+        New inline functions
+
+	* tests/saturation-test.c, tests/Makefile.am:
+	Simple test for g_int_{add,sub}_with_saturation.
+
Index: tests/saturation-test.c
===================================================================
--- tests/saturation-test.c	(revision 0)
+++ tests/saturation-test.c	(revision 0)
@@ -0,0 +1,78 @@
+#include "glib.h"
+
+static void
+test_int_add_with_saturation (void)
+{
+  struct {
+    int a;
+    int b;
+    int result;
+  } cases[] = {
+    {123, 456, 579},
+    {-123, 456, 333},
+    {123, -456, -333},
+
+    {G_MAXINT, -1, G_MAXINT - 1},
+    {G_MAXINT, 0, G_MAXINT},
+    {G_MAXINT, 1, G_MAXINT},
+    {G_MAXINT, 2, G_MAXINT},
+    {G_MAXINT, G_MININT, G_MAXINT + G_MININT},
+
+    {-1, G_MAXINT, G_MAXINT - 1},
+    {0, G_MAXINT, G_MAXINT},
+    {1, G_MAXINT, G_MAXINT},
+    {2, G_MAXINT, G_MAXINT},
+    {G_MININT, G_MAXINT, G_MAXINT + G_MININT},
+
+    {G_MININT, G_MININT, G_MININT},
+    {G_MAXINT, G_MAXINT, G_MAXINT}
+  };
+  guint i;
+
+  for (i = 0; i < G_N_ELEMENTS (cases); i++) {
+    g_assert (g_int_add_with_saturation (cases[i].a, cases[i].b) == cases[i].result);
+  }
+}
+
+static void
+test_int_sub_with_saturation (void)
+{
+  struct {
+    int a;
+    int b;
+    int result;
+  } cases[] = {
+    {123, 456, -333},
+    {-123, 456, -579},
+    {123, -456, 579},
+
+    {G_MININT, -1, G_MININT + 1},
+    {G_MININT, 0, G_MININT},
+    {G_MININT, 1, G_MININT},
+    {G_MININT, 2, G_MININT},
+    {G_MININT, G_MAXINT, G_MININT},
+
+    {-1, G_MININT, -1 - G_MININT},
+    {0, G_MININT, G_MAXINT},
+    {1, G_MININT, G_MAXINT},
+    {2, G_MININT, G_MAXINT},
+    {G_MAXINT, G_MININT, G_MAXINT},
+
+    {G_MAXINT, G_MAXINT, 0},
+    {G_MININT, G_MININT, 0}
+  };
+  int i;
+
+  for (i = 0; i < G_N_ELEMENTS (cases); i++) {
+    g_assert (g_int_sub_with_saturation (cases[i].a, cases[i].b) == cases[i].result);
+  }
+}
+
+int
+main (void)
+{
+  test_int_add_with_saturation ();
+  test_int_sub_with_saturation ();
+    
+  return 0;
+}
Index: tests/Makefile.am
===================================================================
--- tests/Makefile.am	(revision 7392)
+++ tests/Makefile.am	(working copy)
@@ -125,6 +125,7 @@
 	qsort-test				\
 	rand-test				\
 	relation-test				\
+	saturation-test				\
 	sequence-test				\
 	shell-test				\
 	slist-test				\
@@ -192,6 +193,7 @@
 qsort_test_LDADD = $(progs_ldadd)
 rand_test_LDADD = $(progs_ldadd)
 relation_test_LDADD = $(progs_ldadd)
+saturation_test_LDADD = $(progs_ldadd)
 sequence_test_LDADD = $(progs_ldadd)
 shell_test_LDADD = $(progs_ldadd)
 slist_test_LDADD = $(progs_ldadd)
Index: glib/gutils.h
===================================================================
--- glib/gutils.h	(revision 7392)
+++ glib/gutils.h	(working copy)
@@ -311,6 +311,13 @@
 G_INLINE_FUNC gpointer	g_trash_stack_peek	(GTrashStack **stack_p);
 G_INLINE_FUNC guint	g_trash_stack_height	(GTrashStack **stack_p);
 
+/* Integer addition/subtraction with saturation
+ * (yields G_MAXINT on overflow and G_MININT on underflow)
+ */
+
+G_INLINE_FUNC int g_int_add_with_saturation(int a, int b);
+G_INLINE_FUNC int g_int_sub_with_saturation(int a, int b);
+
 /* inline function implementations
  */
 #if defined (G_CAN_INLINE) || defined (__G_UTILS_C__)
@@ -406,6 +413,29 @@
 
   return i;
 }
+
+G_INLINE_FUNC int
+g_int_add_with_saturation(int a, int b)
+{
+  if (G_UNLIKELY (b >= 0 && a > G_MAXINT - b))
+    return G_MAXINT;
+  else if (G_UNLIKELY (b < 0 && a < G_MININT - b))
+    return G_MININT;
+  else
+    return a + b;
+}
+
+
+G_INLINE_FUNC int
+g_int_sub_with_saturation(int a, int b)
+{
+  if (G_UNLIKELY (b < 0 && a > G_MAXINT + b))
+    return G_MAXINT;
+  else if (G_UNLIKELY (b >= 0 && a < G_MININT + b))
+    return G_MININT;
+  else
+    return a - b;
+}
 #endif  /* G_CAN_INLINE || __G_UTILS_C__ */
 
 /* Glib version.
