Commit 049ae7d0 authored by Rusty Russell's avatar Rusty Russell

str: add STR_MAX_CHARS().

Signed-off-by: default avatarRusty Russell <rusty@rustcorp.com.au>
parent 7b122371
......@@ -4,6 +4,7 @@
#include "config.h"
#include <string.h>
#include <stdbool.h>
#include <limits.h>
#include <ctype.h>
/**
......@@ -72,6 +73,33 @@ static inline bool strends(const char *str, const char *postfix)
*/
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
......
#include <ccan/str/str.h>
struct s {
int val;
};
int main(int argc, char *argv[])
{
struct s
#ifdef FAIL
#if !HAVE_TYPEOF
#error We need typeof to check STR_MAX_CHARS.
#endif
#else
/* A pointer is OK. */
*
#endif
val;
char str[STR_MAX_CHARS(val)];
str[0] = '\0';
return str[0] ? 0 : 1;
}
#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();
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment