summaryrefslogblamecommitdiffstats
path: root/include/strutils.h
blob: d1f3da1b65f77159cf84ae2ddca0c74ff502d52c (plain) (tree)
1
2
3
4
5
6
7
8
9


                           
                   

                     
                      
                  
                  
                  
 

                                                              
 
                                                                   
                                                      



                                                                        
                                                                      


                                                                      
                                                                      


                                                                      
                                                                      
 
                                                                  
 
                                                                
                                                                          
 


                                                                    





                                                              
 
                                                                   
 


                                                                              















                                                                  
 



























                                                                                  
                                                                              

                       
                 
 



                                               


                                
                                       



                 
                 




                                                                                    
                                              



                                        



                                        


                                                               
 

                                                                       
                                                             
                                                               

                                                                      


                                                                   


                                                                      
                                                                         
 
                                                     
 
































                                                                               
                              



                                                  
                           
 
 
















                                                   







                                                                    
                 
 


                                 



                                       
                              
                 
         
                      











                                                          


                                              


                                 
                    




                                         









                                                         


                              


                                  
                  

 

                                                                     

                                                                 

                                                                                           

                                
      
#ifndef UTIL_LINUX_STRUTILS
#define UTIL_LINUX_STRUTILS

#include <stdlib.h>
#include <inttypes.h>
#include <string.h>
#include <sys/types.h>
#include <ctype.h>
#include <stdio.h>
#include <errno.h>

/* initialize a custom exit code for all *_or_err functions */
extern void strutils_set_exitcode(int exit_code);

extern int parse_size(const char *str, uintmax_t *res, int *power);
extern int strtosize(const char *str, uintmax_t *res);
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 uint16_t strtox16_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 uint32_t strtox32_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);
extern uint64_t strtox64_or_err(const char *str, const char *errmesg);

extern double strtod_or_err(const char *str, const char *errmesg);

extern long strtol_or_err(const char *str, const char *errmesg);
extern unsigned long strtoul_or_err(const char *str, const char *errmesg);

extern void strtotimeval_or_err(const char *str, struct timeval *tv,
		const char *errmesg);

extern int isdigit_strend(const char *str, const char **end);
#define isdigit_string(_s)	isdigit_strend(_s, NULL)

extern int isxdigit_strend(const char *str, const char **end);
#define isxdigit_string(_s)	isxdigit_strend(_s, NULL)


extern int parse_switch(const char *arg, const char *errmesg, ...);

#ifndef HAVE_MEMPCPY
extern void *mempcpy(void *restrict dest, const void *restrict src, size_t n);
#endif
#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;
}

/* This is like strncpy(), but based on memcpy(), so compilers and static
 * analyzers do not complain when sizeof(destination) is the same as 'n' and
 * result is not terminated by zero.
 *
 * Use this function to copy string to logs with fixed sizes (wtmp/utmp. ...)
 * where string terminator is optional.
 */
static inline void *str2memcpy(void *dest, const char *src, size_t n)
{
	size_t bytes = strlen(src) + 1;

	if (bytes > n)
		bytes = n;

	memcpy(dest, src, bytes);
	return dest;
}

static inline char *mem2strcpy(char *dest, const void *src, size_t n, size_t nmax)
{
	if (n + 1 > nmax)
		n = nmax - 1;

	memcpy(dest, src, n);
	dest[nmax-1] = '\0';
	return dest;
}

static inline int strdup_to_offset(void *stru, size_t offset, const char *str)
{
	char *n = NULL;
	char **o;

	if (!stru)
		return -EINVAL;

	o = (char **) ((char *) stru + offset);
	if (str) {
		n = strdup(str);
		if (!n)
			return -ENOMEM;
	}

	free(*o);
	*o = n;
	return 0;
}

#define strdup_to_struct_member(_s, _m, _str) \
		strdup_to_offset((void *) _s, offsetof(__typeof__(*(_s)), _m), _str)

extern char *xstrmode(mode_t mode, char *str);

/* Options for size_to_human_string() */
enum
{
	SIZE_SUFFIX_1LETTER  = 0,
	SIZE_SUFFIX_3LETTER  = (1 << 0),
	SIZE_SUFFIX_SPACE    = (1 << 1),
	SIZE_DECIMAL_2DIGITS = (1 << 2)
};

extern char *size_to_human_string(int options, uint64_t bytes);

extern int string_to_idarray(const char *list, int ary[], size_t arysz,
			   int (name2id)(const char *, size_t));
extern int string_add_to_idarray(const char *list, int ary[],
				 size_t arysz, size_t *ary_pos,
				 int (name2id)(const char *, size_t));

extern int string_to_bitarray(const char *list, char *ary,
			    int (*name2bit)(const char *, size_t));

extern int string_to_bitmask(const char *list,
			     unsigned long *mask,
			     long (*name2flag)(const char *, size_t));
extern int parse_range(const char *str, int *lower, int *upper, int def);

extern int streq_paths(const char *a, const char *b);

/*
 * 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 s + sl;
	if (sl < pl)
		return NULL;
	if (memcmp(s + sl - pl, postfix, pl) != 0)
		return NULL;
	return s + sl - pl;
}

/*
 * 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;
}


/* 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;

	if (!str)
		return 0;
	i = strlen((char *) str);
	while (i) {
		i--;
		if (!isspace(str[i])) {
			i++;
			break;
		}
	}
	str[i] = '\0';
	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;

	if (!str)
		return 0;
	for (p = str; *p && isspace(*p); p++);

	len = strlen((char *) p);

	if (p > str)
		memmove(str, p, len + 1);

	return len;
}

static inline void strrep(char *s, int find, int replace)
{
	while (s && *s && (s = strchr(s, find)) != NULL)
		*s++ = replace;
}

static inline void strrem(char *s, int rem)
{
	char *p;

	if (!s)
		return;
	for (p = s; *s; s++) {
		if (*s != rem)
			*p++ = *s;
	}
	*p = '\0';
}

extern char *strnappend(const char *s, const char *suffix, size_t b);
extern char *strappend(const char *s, const char *suffix);
extern char *strfappend(const char *s, const char *format, ...)
		 __attribute__ ((__format__ (__printf__, 2, 0)));
extern const char *split(const char **state, size_t *l, const char *separator, int quoted);

extern int skip_fline(FILE *fp);

#endif