aboutsummaryrefslogtreecommitdiff
path: root/win32/actype.h
blob: 5cc837de847cc19a8a19c3d960390172f9c5eaac (plain)
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
#ifndef ACTYPE_H
#define ACTYPE_H

/* actype/isactype: char equivalent to C99/POSIX wctype/iswctype.
 * actype: char-class type from name.
 * isactype: test if char c is of type t.
 *
 * actype returns integral actype_t, which is 0 only for unknown name.
 * isactype returns 0 if t==0 or c is not type t, else non-0.
 * valid c is EOF or unsigned char. valid t is any value from actype/actail.
 */

/* config options:
 *
 * ACTYPE_ENUM (0 or 1) decides whether actype_t is enum which can be used
 * to test match of specific classes, or a slightly more efficient uintptr_t
 * which is a direct function pointer to isalnum, etc, and without a way to
 * test match of specific classes (just like wctype/iswctype).
 *
 * Both modes return 0 for actype("UNKNOWN-NAME"), and isactype(c, 0),
 * and both should be compliant if POSIX had actype/isactype/actype_t.
 *
 * The implementation is O(1) function table access either way, where with
 * enum this happens at isactype, while without enum the function is chosen
 * at actype/actail, so isactype and especially isactype_not0 are very quick.
 */
#define ACTYPE_ENUM 0


typedef int (*_isactype_t)(int);  /* isalpha et-al prototype */

#if ACTYPE_ENUM
  typedef enum {
	AC_NONE = 0,
	AC_ALNUM, AC_ALPHA, AC_BLANK, AC_CNTRL, AC_DIGIT, AC_GRAPH,
	AC_LOWER, AC_PRINT, AC_PUNCT, AC_SPACE, AC_UPPER, AC_XDIGIT
  } actype_t;
  extern const _isactype_t _actype_fns[];
  #define _isactype_not0(c, t) (_actype_fns[t](c))
#else
  #include <stdint.h>  /* uintptr_t */
  typedef uintptr_t actype_t;
  #define _isactype_not0(c, t) (((_isactype_t)t)(c))
#endif

extern actype_t actype(const char *name);
extern int isactype(int c, actype_t t);

/* actype above is the official prototype, but in practice we invoke actail */
#define actype(name) (actail((name), (int*)0))


/* extensions */

/* same as isactype but faster, and will crash if t==0.
 * useful if isactype is needed multiple times with the same non-0 t.
 */
#define isactype_not0(c, t) _isactype_not0((c), (t))

/* if str starts with NAME:]... and actype("NAME") != 0:
 *   set *len=strlen("NAME:]") and return non-0 actype("NAME").
 * else return 0.
 * useful in typical char-class parsing scenarios.
 * if len is NULL: identical to actype.
 */
extern actype_t actail(const char *str, int *len);

#endif  /* ACTYPE_H */