blob: 4d8463a6d76fdc29591629676d6f8d8557429f55 [file] [log] [blame]
bigbiff7b4c7a62015-01-01 19:44:14 -05001#ifndef UTIL_LINUX_STRUTILS
2#define UTIL_LINUX_STRUTILS
3
4#include <stdlib.h>
5#include <inttypes.h>
6#include <string.h>
7#include <sys/types.h>
8#include <ctype.h>
9
10/* default strtoxx_or_err() exit code */
11#ifndef STRTOXX_EXIT_CODE
12# define STRTOXX_EXIT_CODE EXIT_FAILURE
13#endif
14
15
16extern int parse_size(const char *str, uintmax_t *res, int *power);
17extern int strtosize(const char *str, uintmax_t *res);
18extern uintmax_t strtosize_or_err(const char *str, const char *errmesg);
19
20extern int16_t strtos16_or_err(const char *str, const char *errmesg);
21extern uint16_t strtou16_or_err(const char *str, const char *errmesg);
22
23extern int32_t strtos32_or_err(const char *str, const char *errmesg);
24extern uint32_t strtou32_or_err(const char *str, const char *errmesg);
25
26extern int64_t strtos64_or_err(const char *str, const char *errmesg);
27extern uint64_t strtou64_or_err(const char *str, const char *errmesg);
28
29extern double strtod_or_err(const char *str, const char *errmesg);
30
31extern long strtol_or_err(const char *str, const char *errmesg);
32extern unsigned long strtoul_or_err(const char *str, const char *errmesg);
33
34extern void strtotimeval_or_err(const char *str, struct timeval *tv,
35 const char *errmesg);
36
37extern int isdigit_string(const char *str);
38
39#ifndef HAVE_MEMPCPY
40extern void *mempcpy(void *restrict dest, const void *restrict src, size_t n);
41#endif
42#ifndef HAVE_STRNLEN
43extern size_t strnlen(const char *s, size_t maxlen);
44#endif
45#ifndef HAVE_STRNDUP
46extern char *strndup(const char *s, size_t n);
47#endif
48#ifndef HAVE_STRNCHR
49extern char *strnchr(const char *s, size_t maxlen, int c);
50#endif
51
52/* caller guarantees n > 0 */
53static inline void xstrncpy(char *dest, const char *src, size_t n)
54{
55 strncpy(dest, src, n-1);
56 dest[n-1] = 0;
57}
58
59static inline char *strdup_to_offset(void *stru, size_t offset, const char *str)
60{
61 char *n = NULL;
62 char **o = (char **) ((char *) stru + offset);
63
64 if (str) {
65 n = strdup(str);
66 if (!n)
67 return NULL;
68 }
69
70 free(*o);
71 *o = n;
72 return n;
73}
74
75#define strdup_to_struct_member(_s, _m, _str) \
76 strdup_to_offset((void *) _s, offsetof(__typeof__(*(_s)), _m), _str)
77
78extern void strmode(mode_t mode, char *str);
79
80/* Options for size_to_human_string() */
81enum
82{
83 SIZE_SUFFIX_1LETTER = 0,
84 SIZE_SUFFIX_3LETTER = 1,
85 SIZE_SUFFIX_SPACE = 2
86};
87
88extern char *size_to_human_string(int options, uint64_t bytes);
89
90extern int string_to_idarray(const char *list, int ary[], size_t arysz,
91 int (name2id)(const char *, size_t));
92extern int string_add_to_idarray(const char *list, int ary[],
93 size_t arysz, int *ary_pos,
94 int (name2id)(const char *, size_t));
95
96extern int string_to_bitarray(const char *list, char *ary,
97 int (*name2bit)(const char *, size_t));
98
99extern int string_to_bitmask(const char *list,
100 unsigned long *mask,
101 long (*name2flag)(const char *, size_t));
102extern int parse_range(const char *str, int *lower, int *upper, int def);
103
104extern int streq_except_trailing_slash(const char *s1, const char *s2);
105
106/*
107 * Match string beginning.
108 */
109static inline const char *startswith(const char *s, const char *prefix)
110{
111 size_t sz = prefix ? strlen(prefix) : 0;
112
113 if (s && sz && strncmp(s, prefix, sz) == 0)
114 return s + sz;
115 return NULL;
116}
117
118/*
119 * Case insensitive match string beginning.
120 */
121static inline const char *startswith_no_case(const char *s, const char *prefix)
122{
123 size_t sz = prefix ? strlen(prefix) : 0;
124
125 if (s && sz && strncasecmp(s, prefix, sz) == 0)
126 return s + sz;
127 return NULL;
128}
129
130/*
131 * Match string ending.
132 */
133static inline const char *endswith(const char *s, const char *postfix)
134{
135 size_t sl = s ? strlen(s) : 0;
136 size_t pl = postfix ? strlen(postfix) : 0;
137
138 if (pl == 0)
139 return (char *)s + sl;
140 if (sl < pl)
141 return NULL;
142 if (memcmp(s + sl - pl, postfix, pl) != 0)
143 return NULL;
144 return (char *)s + sl - pl;
145}
146
147/*
148 * Skip leading white space.
149 */
150static inline const char *skip_space(const char *p)
151{
152 while (isspace(*p))
153 ++p;
154 return p;
155}
156
157static inline const char *skip_blank(const char *p)
158{
159 while (isblank(*p))
160 ++p;
161 return p;
162}
163
164
165/* Removes whitespace from the right-hand side of a string (trailing
166 * whitespace).
167 *
168 * Returns size of the new string (without \0).
169 */
170static inline size_t rtrim_whitespace(unsigned char *str)
171{
172 size_t i = strlen((char *) str);
173
174 while (i) {
175 i--;
176 if (!isspace(str[i])) {
177 i++;
178 break;
179 }
180 }
181 str[i] = '\0';
182 return i;
183}
184
185/* Removes whitespace from the left-hand side of a string.
186 *
187 * Returns size of the new string (without \0).
188 */
189static inline size_t ltrim_whitespace(unsigned char *str)
190{
191 size_t len;
192 unsigned char *p;
193
194 for (p = str; p && isspace(*p); p++);
195
196 len = strlen((char *) p);
197
198 if (len && p > str)
199 memmove(str, p, len + 1);
200
201 return len;
202}
203
204#endif