listparser.hc (3212B)
1 // $Id$ --*- c -*-- 2 3 // Copyright (C) 2004 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de> 4 // 5 // This program is free software; you can redistribute it and/or modify 6 // it under the terms of the GNU General Public License as published by 7 // the Free Software Foundation; version 2 of the License. 8 // 9 // This program is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU General Public License for more details. 13 // 14 // You should have received a copy of the GNU General Public License 15 // along with this program; if not, write to the Free Software 16 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 17 18 19 #ifdef HAVE_CONFIG_H 20 # include <config.h> 21 #endif 22 23 #include <stdlib.h> 24 #include <string.h> 25 #include <strings.h> 26 27 #define TONUMBER_uint64(S,E,B) strtoll(S,E,B) 28 #define TONUMBER_uint32(S,E,B) strtol (S,E,B) 29 30 #define ISNUMBER(TYPE,SHORT) \ 31 static inline ALWAYSINLINE bool \ 32 isNumber_##SHORT(char const **str,size_t *len,TYPE *res,char end_chr) \ 33 { \ 34 char *err_ptr; \ 35 if (**str=='^') { \ 36 *res = ((TYPE)(1)) << TONUMBER_##SHORT(++*str, &err_ptr, 0); \ 37 if (len) --*len; \ 38 } \ 39 else \ 40 *res = TONUMBER_##SHORT(*str, &err_ptr, 0); \ 41 return err_ptr>*str && *err_ptr==end_chr; \ 42 } 43 44 45 #define LISTPARSER(TYPE,SHORT) \ 46 ISNUMBER(TYPE,SHORT) \ 47 int \ 48 utilvserver_listparser_ ## SHORT(char const *str, size_t len, \ 49 char const **err_ptr, \ 50 size_t *err_len, \ 51 TYPE * const flag, \ 52 TYPE * const mask, \ 53 TYPE (*func)(char const *, \ 54 size_t, bool *)) \ 55 { \ 56 if (len==0) len = strlen(str); \ 57 for (;len>0;) { \ 58 char const *ptr = strchr(str, ','); \ 59 size_t cnt; \ 60 TYPE tmp = 0; \ 61 bool is_neg = false; \ 62 bool failed = false; \ 63 \ 64 while (mask!=0 && len>0 && (*str=='!' || *str=='~')) { \ 65 is_neg = !is_neg; \ 66 ++str; \ 67 --len; \ 68 } \ 69 \ 70 cnt = ptr ? (size_t)(ptr-str) : len; \ 71 if (cnt>=len) { cnt=len; len=0; } \ 72 else len-=(cnt+1); \ 73 \ 74 if (cnt==0) \ 75 failed = true; \ 76 else if (mask!=0 && \ 77 (strncasecmp(str,"all",cnt)==0 || \ 78 strncasecmp(str,"any",cnt)==0)) \ 79 tmp = ~(TYPE)(0); \ 80 else if (mask!=0 && strncasecmp(str,"none",cnt)==0) {} \ 81 else if (!isNumber_##SHORT(&str, &cnt, &tmp, str[cnt])) \ 82 tmp = (*func)(str,cnt, &failed); \ 83 \ 84 if (!failed) { \ 85 if (!is_neg) *flag |= tmp; \ 86 else *flag &= ~tmp; \ 87 if (mask!=0) *mask |= tmp; \ 88 } \ 89 else { \ 90 if (err_ptr) *err_ptr = str; \ 91 if (err_len) *err_len = cnt; \ 92 return -1; \ 93 } \ 94 \ 95 if (ptr==0) break; \ 96 str = ptr+1; \ 97 } \ 98 \ 99 if (err_ptr) *err_ptr = 0; \ 100 if (err_len) *err_len = 0; \ 101 return 0; \ 102 }