#include <stdlib.h>
#include <string.h>
+#include <strings.h>
+
+#define TONUMBER_uint64(S,E,B) strtoll(S,E,B)
+#define TONUMBER_uint32(S,E,B) strtol (S,E,B)
+
+#define ISNUMBER(TYPE,SHORT) \
+ static inline ALWAYSINLINE bool \
+ isNumber_##SHORT(char const **str,size_t *len,TYPE *res,char end_chr) \
+ { \
+ char *err_ptr; \
+ if (**str=='^') { \
+ *res = ((TYPE)(1)) << TONUMBER_##SHORT(++*str, &err_ptr, 0); \
+ if (len) --*len; \
+ } \
+ else \
+ *res = TONUMBER_##SHORT(*str, &err_ptr, 0); \
+ return err_ptr>*str && *err_ptr==end_chr; \
+ }
+
#define LISTPARSER(TYPE,SHORT) \
+ ISNUMBER(TYPE,SHORT) \
int \
utilvserver_listparser_ ## SHORT(char const *str, size_t len, \
char const **err_ptr, \
{ \
if (len==0) len = strlen(str); \
for (;len>0;) { \
- char const *ptr = strchr(str, ','); \
- size_t cnt = ptr ? (size_t)(ptr-str) : len; \
- TYPE tmp; \
- bool is_neg; \
- \
- is_neg = len>1 && (*str=='!' || *str=='~'); \
- if (is_neg) { \
+ char const *ptr = strchr(str, ','); \
+ size_t cnt; \
+ TYPE tmp = 0; \
+ bool is_neg = false; \
+ bool allow_zero = true; \
+ \
+ while (len>0 && (*str=='!' || *str=='~')) { \
+ is_neg = !is_neg; \
++str; \
--len; \
} \
- \
+ \
+ cnt = ptr ? (size_t)(ptr-str) : len; \
if (cnt>=len) { cnt=len; len=0; } \
else len-=(cnt+1); \
\
- tmp = (*func)(str,cnt); \
+ if (cnt==0) \
+ allow_zero = false; \
+ else if (strncasecmp(str,"all",cnt)==0 || \
+ strncasecmp(str,"any",cnt)==0) \
+ tmp = ~(TYPE)(0); \
+ else if (strncasecmp(str,"none",cnt)==0) {} \
+ else if (!isNumber_##SHORT(&str, &cnt, &tmp, str[cnt])) { \
+ tmp = (*func)(str,cnt); \
+ allow_zero = false; \
+ } \
\
- if (tmp!=0) { \
- if (!is_neg) *flag |= tmp; \
+ if (tmp!=0 || allow_zero) { \
+ if (!is_neg) *flag |= tmp; \
+ else *flag &= ~tmp; \
*mask |= tmp; \
} \
else { \