X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=lib%2Flistparser.hc;fp=lib%2Flistparser.hc;h=ebf5facbe083308f5cbdb1042b8a7173b671a267;hb=8cf13bb177d92c93eb73dc8939777150536c2d00;hp=0000000000000000000000000000000000000000;hpb=6bf3f95de36c804c97716b2d0bdf10680c559044;p=util-vserver.git diff --git a/lib/listparser.hc b/lib/listparser.hc new file mode 100644 index 0000000..ebf5fac --- /dev/null +++ b/lib/listparser.hc @@ -0,0 +1,102 @@ +// $Id: listparser.hc,v 1.5 2005/04/24 20:23:11 ensc Exp $ --*- c -*-- + +// Copyright (C) 2004 Enrico Scholz +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; version 2 of the License. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include +#include + +#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, \ + size_t *err_len, \ + TYPE * const flag, \ + TYPE * const mask, \ + TYPE (*func)(char const *, \ + size_t, bool *)) \ + { \ + if (len==0) len = strlen(str); \ + for (;len>0;) { \ + char const *ptr = strchr(str, ','); \ + size_t cnt; \ + TYPE tmp = 0; \ + bool is_neg = false; \ + bool failed = false; \ + \ + while (mask!=0 && 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); \ + \ + if (cnt==0) \ + failed = true; \ + else if (mask!=0 && \ + (strncasecmp(str,"all",cnt)==0 || \ + strncasecmp(str,"any",cnt)==0)) \ + tmp = ~(TYPE)(0); \ + else if (mask!=0 && strncasecmp(str,"none",cnt)==0) {} \ + else if (!isNumber_##SHORT(&str, &cnt, &tmp, str[cnt])) \ + tmp = (*func)(str,cnt, &failed); \ + \ + if (!failed) { \ + if (!is_neg) *flag |= tmp; \ + else *flag &= ~tmp; \ + if (mask!=0) *mask |= tmp; \ + } \ + else { \ + if (err_ptr) *err_ptr = str; \ + if (err_len) *err_len = cnt; \ + return -1; \ + } \ + \ + if (ptr==0) break; \ + str = ptr+1; \ + } \ + \ + if (err_ptr) *err_ptr = 0; \ + if (err_len) *err_len = 0; \ + return 0; \ + }