summaryrefslogtreecommitdiff
path: root/lib/xsize.h
diff options
context:
space:
mode:
Diffstat (limited to 'lib/xsize.h')
-rw-r--r--lib/xsize.h28
1 files changed, 24 insertions, 4 deletions
diff --git a/lib/xsize.h b/lib/xsize.h
index 71c9c073..5ae86006 100644
--- a/lib/xsize.h
+++ b/lib/xsize.h
@@ -26,7 +26,7 @@
/* Get size_t. */
#include <stddef.h>
-/* Get SIZE_MAX. */
+/* Get INT_MAX, SIZE_MAX. */
#include <limits.h>
#if HAVE_STDINT_H
# include <stdint.h>
@@ -40,6 +40,11 @@ _GL_INLINE_HEADER_BEGIN
# define XSIZE_INLINE _GL_INLINE
#endif
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
/* The size of memory objects is often computed through expressions of
type size_t. Example:
void* p = malloc (header_size + n * element_size).
@@ -56,7 +61,8 @@ _GL_INLINE_HEADER_BEGIN
void *p = (size_in_bounds_p (size) ? malloc (size) : NULL);
*/
-/* Convert an arbitrary value >= 0 to type size_t. */
+/* Convert an arbitrary N >= 0 to type size_t.
+ N should not have side effects. */
#define xcast_size_t(N) \
((N) <= SIZE_MAX ? (size_t) (N) : SIZE_MAX)
@@ -64,8 +70,15 @@ _GL_INLINE_HEADER_BEGIN
XSIZE_INLINE size_t ATTRIBUTE_PURE
xsum (size_t size1, size_t size2)
{
- size_t sum = size1 + size2;
- return (sum >= size1 ? sum : SIZE_MAX);
+ if (INT_MAX < SIZE_MAX)
+ {
+ /* Optimize for the common case where size_t arithmetic wraps
+ around without undefined behavior. */
+ size_t sum = size1 + size2;
+ return size1 <= sum ? sum : SIZE_MAX;
+ }
+
+ return size1 <= SIZE_MAX - size2 ? size1 + size2 : SIZE_MAX;
}
/* Sum of three sizes, with overflow check. */
@@ -93,6 +106,8 @@ xmax (size_t size1, size_t size2)
/* Multiplication of a count with an element size, with overflow check.
The count must be >= 0 and the element size must be > 0.
+ Arguments should not have side effects.
+ The element size's type should be no wider than size_t.
This is a macro, not a function, so that it works correctly even
when N is of a wider type and N > SIZE_MAX. */
#define xtimes(N, ELSIZE) \
@@ -105,6 +120,11 @@ xmax (size_t size1, size_t size2)
#define size_in_bounds_p(SIZE) \
((SIZE) != SIZE_MAX)
+
+#ifdef __cplusplus
+}
+#endif
+
_GL_INLINE_HEADER_END
#endif /* _XSIZE_H */