2010-11-16 10:47:35 -03:00
|
|
|
#ifndef UTIL_LINUX_STRUTILS
|
|
|
|
#define UTIL_LINUX_STRUTILS
|
|
|
|
|
2013-01-29 15:25:47 +01:00
|
|
|
#include <stdlib.h>
|
2010-11-16 10:47:35 -03:00
|
|
|
#include <inttypes.h>
|
|
|
|
#include <string.h>
|
2010-11-24 16:41:20 +01:00
|
|
|
#include <sys/types.h>
|
2013-09-23 15:39:34 +02:00
|
|
|
#include <ctype.h>
|
2010-11-16 10:47:35 -03:00
|
|
|
|
2012-03-30 16:11:31 +02:00
|
|
|
/* default strtoxx_or_err() exit code */
|
|
|
|
#ifndef STRTOXX_EXIT_CODE
|
|
|
|
# define STRTOXX_EXIT_CODE EXIT_FAILURE
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
2013-01-29 15:25:47 +01:00
|
|
|
extern int parse_size(const char *str, uintmax_t *res, int *power);
|
2010-11-16 10:47:35 -03:00
|
|
|
extern int strtosize(const char *str, uintmax_t *res);
|
2012-05-15 17:40:03 +02:00
|
|
|
extern uintmax_t strtosize_or_err(const char *str, const char *errmesg);
|
|
|
|
|
|
|
|
extern int16_t strtos16_or_err(const char *str, const char *errmesg);
|
|
|
|
extern uint16_t strtou16_or_err(const char *str, const char *errmesg);
|
|
|
|
|
|
|
|
extern int32_t strtos32_or_err(const char *str, const char *errmesg);
|
|
|
|
extern uint32_t strtou32_or_err(const char *str, const char *errmesg);
|
|
|
|
|
|
|
|
extern int64_t strtos64_or_err(const char *str, const char *errmesg);
|
|
|
|
extern uint64_t strtou64_or_err(const char *str, const char *errmesg);
|
|
|
|
|
2011-09-25 11:03:07 +02:00
|
|
|
extern double strtod_or_err(const char *str, const char *errmesg);
|
2012-05-15 17:40:03 +02:00
|
|
|
|
2010-11-16 10:47:35 -03:00
|
|
|
extern long strtol_or_err(const char *str, const char *errmesg);
|
2011-05-24 22:56:38 +02:00
|
|
|
extern unsigned long strtoul_or_err(const char *str, const char *errmesg);
|
2010-11-16 10:47:35 -03:00
|
|
|
|
2013-03-13 11:51:15 +01:00
|
|
|
extern void strtotimeval_or_err(const char *str, struct timeval *tv,
|
|
|
|
const char *errmesg);
|
|
|
|
|
2013-01-28 16:16:11 +01:00
|
|
|
extern int isdigit_string(const char *str);
|
|
|
|
|
2015-02-24 12:04:22 +01:00
|
|
|
extern int parse_switch(const char *arg, const char *errmesg, ...);
|
2015-02-22 14:41:37 +00:00
|
|
|
|
2013-01-30 18:49:08 -05:00
|
|
|
#ifndef HAVE_MEMPCPY
|
|
|
|
extern void *mempcpy(void *restrict dest, const void *restrict src, size_t n);
|
|
|
|
#endif
|
2010-11-16 10:47:35 -03:00
|
|
|
#ifndef HAVE_STRNLEN
|
|
|
|
extern size_t strnlen(const char *s, size_t maxlen);
|
|
|
|
#endif
|
|
|
|
#ifndef HAVE_STRNDUP
|
|
|
|
extern char *strndup(const char *s, size_t n);
|
|
|
|
#endif
|
|
|
|
#ifndef HAVE_STRNCHR
|
|
|
|
extern char *strnchr(const char *s, size_t maxlen, int c);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/* caller guarantees n > 0 */
|
|
|
|
static inline void xstrncpy(char *dest, const char *src, size_t n)
|
|
|
|
{
|
|
|
|
strncpy(dest, src, n-1);
|
|
|
|
dest[n-1] = 0;
|
|
|
|
}
|
2010-11-24 16:41:20 +01:00
|
|
|
|
2013-01-29 15:25:47 +01:00
|
|
|
static inline char *strdup_to_offset(void *stru, size_t offset, const char *str)
|
|
|
|
{
|
|
|
|
char *n = NULL;
|
|
|
|
char **o = (char **) ((char *) stru + offset);
|
|
|
|
|
|
|
|
if (str) {
|
|
|
|
n = strdup(str);
|
|
|
|
if (!n)
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
free(*o);
|
|
|
|
*o = n;
|
|
|
|
return n;
|
|
|
|
}
|
|
|
|
|
|
|
|
#define strdup_to_struct_member(_s, _m, _str) \
|
|
|
|
strdup_to_offset((void *) _s, offsetof(__typeof__(*(_s)), _m), _str)
|
|
|
|
|
2010-11-24 16:41:20 +01:00
|
|
|
extern void strmode(mode_t mode, char *str);
|
2011-05-26 15:17:25 +02:00
|
|
|
|
|
|
|
/* Options for size_to_human_string() */
|
|
|
|
enum
|
|
|
|
{
|
|
|
|
SIZE_SUFFIX_1LETTER = 0,
|
|
|
|
SIZE_SUFFIX_3LETTER = 1,
|
|
|
|
SIZE_SUFFIX_SPACE = 2
|
|
|
|
};
|
|
|
|
|
|
|
|
extern char *size_to_human_string(int options, uint64_t bytes);
|
2010-11-24 16:41:20 +01:00
|
|
|
|
2011-07-27 16:41:21 +02:00
|
|
|
extern int string_to_idarray(const char *list, int ary[], size_t arysz,
|
|
|
|
int (name2id)(const char *, size_t));
|
2012-07-26 15:52:04 +02:00
|
|
|
extern int string_add_to_idarray(const char *list, int ary[],
|
2015-04-22 11:08:05 +02:00
|
|
|
size_t arysz, size_t *ary_pos,
|
2012-07-26 15:52:04 +02:00
|
|
|
int (name2id)(const char *, size_t));
|
|
|
|
|
2011-07-27 16:41:21 +02:00
|
|
|
extern int string_to_bitarray(const char *list, char *ary,
|
|
|
|
int (*name2bit)(const char *, size_t));
|
|
|
|
|
2012-05-03 17:28:44 +02:00
|
|
|
extern int string_to_bitmask(const char *list,
|
|
|
|
unsigned long *mask,
|
|
|
|
long (*name2flag)(const char *, size_t));
|
2011-10-14 16:32:15 -04:00
|
|
|
extern int parse_range(const char *str, int *lower, int *upper, int def);
|
2011-10-11 23:18:12 -04:00
|
|
|
|
2011-11-08 16:25:01 +01:00
|
|
|
extern int streq_except_trailing_slash(const char *s1, const char *s2);
|
|
|
|
|
2013-09-10 12:18:20 +02:00
|
|
|
/*
|
|
|
|
* Match string beginning.
|
|
|
|
*/
|
|
|
|
static inline const char *startswith(const char *s, const char *prefix)
|
|
|
|
{
|
|
|
|
size_t sz = prefix ? strlen(prefix) : 0;
|
|
|
|
|
|
|
|
if (s && sz && strncmp(s, prefix, sz) == 0)
|
|
|
|
return s + sz;
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Case insensitive match string beginning.
|
|
|
|
*/
|
|
|
|
static inline const char *startswith_no_case(const char *s, const char *prefix)
|
|
|
|
{
|
|
|
|
size_t sz = prefix ? strlen(prefix) : 0;
|
|
|
|
|
|
|
|
if (s && sz && strncasecmp(s, prefix, sz) == 0)
|
|
|
|
return s + sz;
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Match string ending.
|
|
|
|
*/
|
|
|
|
static inline const char *endswith(const char *s, const char *postfix)
|
|
|
|
{
|
|
|
|
size_t sl = s ? strlen(s) : 0;
|
|
|
|
size_t pl = postfix ? strlen(postfix) : 0;
|
|
|
|
|
|
|
|
if (pl == 0)
|
|
|
|
return (char *)s + sl;
|
|
|
|
if (sl < pl)
|
|
|
|
return NULL;
|
|
|
|
if (memcmp(s + sl - pl, postfix, pl) != 0)
|
|
|
|
return NULL;
|
|
|
|
return (char *)s + sl - pl;
|
|
|
|
}
|
2013-08-29 15:50:17 +01:00
|
|
|
|
2013-09-23 15:39:34 +02:00
|
|
|
/*
|
|
|
|
* Skip leading white space.
|
|
|
|
*/
|
|
|
|
static inline const char *skip_space(const char *p)
|
|
|
|
{
|
|
|
|
while (isspace(*p))
|
|
|
|
++p;
|
|
|
|
return p;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline const char *skip_blank(const char *p)
|
|
|
|
{
|
|
|
|
while (isblank(*p))
|
|
|
|
++p;
|
|
|
|
return p;
|
|
|
|
}
|
|
|
|
|
2014-08-25 15:31:53 +02:00
|
|
|
|
|
|
|
/* Removes whitespace from the right-hand side of a string (trailing
|
|
|
|
* whitespace).
|
|
|
|
*
|
|
|
|
* Returns size of the new string (without \0).
|
|
|
|
*/
|
|
|
|
static inline size_t rtrim_whitespace(unsigned char *str)
|
|
|
|
{
|
|
|
|
size_t i = strlen((char *) str);
|
|
|
|
|
2014-11-22 08:18:17 +00:00
|
|
|
while (i) {
|
|
|
|
i--;
|
|
|
|
if (!isspace(str[i])) {
|
|
|
|
i++;
|
2014-08-25 15:31:53 +02:00
|
|
|
break;
|
2014-11-22 08:18:17 +00:00
|
|
|
}
|
2014-08-25 15:31:53 +02:00
|
|
|
}
|
2014-11-22 08:18:17 +00:00
|
|
|
str[i] = '\0';
|
2014-08-25 15:31:53 +02:00
|
|
|
return i;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Removes whitespace from the left-hand side of a string.
|
|
|
|
*
|
|
|
|
* Returns size of the new string (without \0).
|
|
|
|
*/
|
|
|
|
static inline size_t ltrim_whitespace(unsigned char *str)
|
|
|
|
{
|
|
|
|
size_t len;
|
|
|
|
unsigned char *p;
|
|
|
|
|
|
|
|
for (p = str; p && isspace(*p); p++);
|
|
|
|
|
|
|
|
len = strlen((char *) p);
|
|
|
|
|
|
|
|
if (len && p > str)
|
|
|
|
memmove(str, p, len + 1);
|
|
|
|
|
|
|
|
return len;
|
|
|
|
}
|
|
|
|
|
2015-05-15 14:57:04 +02:00
|
|
|
extern char *strnappend(const char *s, const char *suffix, size_t b);
|
|
|
|
extern char *strappend(const char *s, const char *suffix);
|
|
|
|
extern const char *split(const char **state, size_t *l, const char *separator, int quoted);
|
|
|
|
|
2010-11-16 10:47:35 -03:00
|
|
|
#endif
|