port test/unit/test_ccc.rb to Perl 5
[unicorn.git] / ext / unicorn_http / c_util.h
blob577461543e915b336594860b5425d955de4571e2
1 /*
2 * Generic C functions and macros go here, there are no dependencies
3 * on Unicorn internal structures or the Ruby C API in here.
4 */
6 #ifndef UH_util_h
7 #define UH_util_h
9 #include <unistd.h>
10 #include <assert.h>
11 #include <limits.h>
13 #define MIN(a,b) (a < b ? a : b)
14 #define ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0]))
16 #if SIZEOF_OFF_T == SIZEOF_INT
17 # define UH_OFF_T_MAX INT_MAX
18 #elif SIZEOF_OFF_T == SIZEOF_LONG_LONG
19 # define UH_OFF_T_MAX LLONG_MAX
20 #else
21 # error off_t size unknown for this platform!
22 #endif /* SIZEOF_OFF_T check */
25 * ragel enforces fpc as a const, and merely casting can make picky
26 * compilers unhappy, so we have this little helper do our dirty work
28 static inline void *deconst(const void *in)
30 union { const void *in; void *out; } tmp;
32 tmp.in = in;
34 return tmp.out;
38 * capitalizes all lower-case ASCII characters and converts dashes
39 * to underscores for HTTP headers. Locale-agnostic.
41 static void snake_upcase_char(char *c)
43 if (*c >= 'a' && *c <= 'z')
44 *c &= ~0x20;
45 else if (*c == '-')
46 *c = '_';
49 /* Downcases a single ASCII character. Locale-agnostic. */
50 static void downcase_char(char *c)
52 if (*c >= 'A' && *c <= 'Z')
53 *c |= 0x20;
56 static int hexchar2int(int xdigit)
58 if (xdigit >= 'A' && xdigit <= 'F')
59 return xdigit - 'A' + 10;
60 if (xdigit >= 'a' && xdigit <= 'f')
61 return xdigit - 'a' + 10;
63 /* Ragel already does runtime range checking for us in Unicorn: */
64 assert(xdigit >= '0' && xdigit <= '9' && "invalid digit character");
66 return xdigit - '0';
70 * multiplies +i+ by +base+ and increments the result by the parsed
71 * integer value of +xdigit+. +xdigit+ is a character byte
72 * representing a number the range of 0..(base-1)
73 * returns the new value of +i+ on success
74 * returns -1 on errors (including overflow)
76 static off_t step_incr(off_t i, int xdigit, const int base)
78 static const off_t max = UH_OFF_T_MAX;
79 const off_t next_max = (max - (max % base)) / base;
80 off_t offset = hexchar2int(xdigit);
82 if (offset > (base - 1))
83 return -1;
84 if (i > next_max)
85 return -1;
86 i *= base;
88 if ((offset > (base - 1)) || ((max - i) < offset))
89 return -1;
91 return i + offset;
95 * parses a non-negative length according to base-10 and
96 * returns it as an off_t value. Returns -1 on errors
97 * (including overflow).
99 static off_t parse_length(const char *value, size_t length)
101 off_t rv;
103 for (rv = 0; length-- && rv >= 0; ++value) {
104 if (*value >= '0' && *value <= '9')
105 rv = step_incr(rv, *value, 10);
106 else
107 return -1;
110 return rv;
113 #define CONST_MEM_EQ(const_p, buf, len) \
114 ((sizeof(const_p) - 1) == len && !memcmp(const_p, buf, sizeof(const_p) - 1))
116 #endif /* UH_util_h */