File: listparser.hc

package info (click to toggle)
util-vserver 0.30.212-1
  • links: PTS
  • area: main
  • in suites: etch, etch-m68k
  • size: 6,648 kB
  • ctags: 3,145
  • sloc: ansic: 19,781; sh: 13,258; xml: 1,618; makefile: 364; perl: 85
file content (102 lines) | stat: -rw-r--r-- 3,259 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
// $Id: listparser.hc 2037 2005-04-24 20:23:11Z ensc $    --*- c -*--

// Copyright (C) 2004 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de>
//  
// 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 <config.h>
#endif

#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,		\
				   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;								\
  }