#include "config.h"
#include <string.h>
#include <stdbool.h>
+#include <limits.h>
#include <ctype.h>
/**
*/
size_t strcount(const char *haystack, const char *needle);
+/**
+ * STR_MAX_CHARS - Maximum possible size of numeric string for this type.
+ * @type_or_expr: a pointer or integer type or expression.
+ *
+ * This provides enough space for a nul-terminated string which represents the
+ * largest possible value for the type or expression.
+ *
+ * Note: The implementation adds extra space so hex values or negative
+ * values will fit (eg. sprintf(... "%p"). )
+ *
+ * Example:
+ * char str[STR_MAX_CHARS(i)];
+ *
+ * sprintf(str, "%i", i);
+ */
+#define STR_MAX_CHARS(type_or_expr) \
+ ((sizeof(type_or_expr) * CHAR_BIT + 8) / 9 * 3 + 2 \
+ + STR_MAX_CHARS_TCHECK_(type_or_expr))
+
+#if HAVE_TYPEOF
+/* Only a simple type can have 0 assigned, so test that. */
+#define STR_MAX_CHARS_TCHECK_(type_or_expr) \
+ ({ typeof(type_or_expr) x = 0; (void)x; 0; })
+#else
+#define STR_MAX_CHARS_TCHECK_(type_or_expr) 0
+#endif
+
/**
* cisalnum - isalnum() which takes a char (and doesn't accept EOF)
* @c: a character
--- /dev/null
+#include <ccan/str/str.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <ccan/tap/tap.h>
+#include <stdint.h>
+
+int main(int argc, char *argv[])
+{
+ char str[1000];
+ struct {
+ uint8_t u1byte;
+ int8_t s1byte;
+ uint16_t u2byte;
+ int16_t s2byte;
+ uint32_t u4byte;
+ int32_t s4byte;
+ uint64_t u8byte;
+ int64_t s8byte;
+ void *ptr;
+ } types;
+
+ plan_tests(13);
+
+ memset(&types, 0xFF, sizeof(types));
+
+ /* Hex versions */
+ sprintf(str, "0x%llx", (unsigned long long)types.u1byte);
+ ok1(strlen(str) < STR_MAX_CHARS(types.u1byte));
+ sprintf(str, "0x%llx", (unsigned long long)types.u2byte);
+ ok1(strlen(str) < STR_MAX_CHARS(types.u2byte));
+ sprintf(str, "0x%llx", (unsigned long long)types.u4byte);
+ ok1(strlen(str) < STR_MAX_CHARS(types.u4byte));
+ sprintf(str, "0x%llx", (unsigned long long)types.u8byte);
+ ok1(strlen(str) < STR_MAX_CHARS(types.u8byte));
+
+ /* Decimal versions */
+ sprintf(str, "%u", types.u1byte);
+ ok1(strlen(str) < STR_MAX_CHARS(types.u1byte));
+ sprintf(str, "%d", types.s1byte);
+ ok1(strlen(str) < STR_MAX_CHARS(types.s1byte));
+ sprintf(str, "%u", types.u2byte);
+ ok1(strlen(str) < STR_MAX_CHARS(types.u2byte));
+ sprintf(str, "%d", types.s2byte);
+ ok1(strlen(str) < STR_MAX_CHARS(types.s2byte));
+ sprintf(str, "%u", types.u4byte);
+ ok1(strlen(str) < STR_MAX_CHARS(types.u4byte));
+ sprintf(str, "%d", types.s4byte);
+ ok1(strlen(str) < STR_MAX_CHARS(types.s4byte));
+ sprintf(str, "%llu", (unsigned long long)types.u8byte);
+ ok1(strlen(str) < STR_MAX_CHARS(types.u8byte));
+ sprintf(str, "%lld", (long long)types.s8byte);
+ ok1(strlen(str) < STR_MAX_CHARS(types.s8byte));
+
+ /* Pointer version. */
+ sprintf(str, "%p", types.ptr);
+ ok1(strlen(str) < STR_MAX_CHARS(types.ptr));
+
+ return exit_status();
+}