File Coverage

XS.xs
Criterion Covered Total %
statement 65 70 92.8
branch 56 72 77.7
condition n/a
subroutine n/a
pod n/a
total 121 142 85.2


line stmt bran cond sub pod time code
1             #ifdef __cplusplus
2             extern "C" {
3             #endif
4              
5             #define PERL_NO_GET_CONTEXT /* we want efficiency */
6             #include
7             #include
8             #include
9              
10             #ifdef __cplusplus
11             } /* extern "C" */
12             #endif
13              
14             #include "ppport.h"
15              
16             static char hextbl[256] =
17             /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */
18             {
19             0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0 */
20             0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 1 */
21             0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 2 */
22             0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0, 0, 0, 0, /* 3 0-9 */
23             0,10,11,12,13,14,15, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 4 @,A-Z */
24             0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 5 */
25             0,10,11,12,13,14,15, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 6 `,a-z */
26             0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 7 */
27             0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 8 */
28             0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 9 */
29             0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* a */
30             0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* b */
31             0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* c */
32             0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* d */
33             0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* e */
34             0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* f */
35             };
36              
37             static
38             void
39 60           url_decode_key(const char *src, int src_len, char *d, int *key_len) {
40 60           int i, dlen=0;
41 2294 100         for (i = 0; i < src_len; i++ ) {
42 2234 100         if ((i + 2) < src_len && src[i] == '%' && isxdigit(src[i+1]) && isxdigit(src[i+2]) ) {
    50          
    0          
    0          
43 0           d[dlen++] = hextbl[(U8)src[i+1]] * 16 + hextbl[(U8)src[i+2]];
44 0           i += 2;
45             }
46             else {
47 2234           d[dlen++] = src[i];
48             }
49             }
50 60           *key_len = dlen;
51 60           }
52              
53             static SV *
54 56           url_decode_val(pTHX_ const char *src, int src_len) {
55 56           int dlen = 0, i = 0;
56             char *d;
57             SV * dst;
58              
59             // Values can be quoted
60 56 100         if (src_len > 1 && src[0] == '"' && src[src_len-1] == '"' ) {
    100          
    100          
61 4           src++;
62 4           src_len -= 2;
63             }
64              
65 56           dst = newSV(0);
66 56 50         (void)SvUPGRADE(dst, SVt_PV);
67 56 50         d = SvGROW(dst, src_len + 1);
    50          
68              
69 280 100         for (i = 0; i < src_len; i++ ) {
70 224 100         if ( (i + 2) < src_len && src[i] == '%' && isxdigit(src[i+1]) && isxdigit(src[i+2]) ) {
    100          
    50          
    50          
71 16           d[dlen++] = hextbl[(U8)src[i+1]] * 16 + hextbl[(U8)src[i+2]];
72 16           i += 2;
73             }
74             else {
75 208           d[dlen++] = src[i];
76             }
77             }
78              
79 56           SvCUR_set(dst, dlen);
80 56           *SvEND(dst) = '\0';
81 56           SvPOK_only(dst);
82 56           return dst;
83             }
84              
85              
86             static
87             void
88 60           renewmem(pTHX_ char **d, int *cur, const int req) {
89 60 100         if ( req > *cur ) {
90 2           *cur = req;
91 2           Renew(*d, *cur, char);
92             }
93 60           }
94              
95              
96             MODULE = Cookie::Baker::XS PACKAGE = Cookie::Baker::XS
97              
98             PROTOTYPES: DISABLE
99              
100             SV *
101             crush_cookie(cookie)
102             SV *cookie
103             PREINIT:
104             char *key, *key_p, *val_p, *val_end_p;
105 25           int cur_len, key_len, val_len, key_size=64;
106             STRLEN len_left_from_orig;
107             HV *hv;
108             CODE:
109 25           hv = newHV();
110 25 100         if ( SvOK(cookie) ) {
    50          
    50          
111 24           Newx(key, key_size, char);
112 24 50         key_p = (char *)SvPV(cookie, len_left_from_orig);
113              
114 68 100         while(len_left_from_orig > 0) {
115             /* strip starting spaces */
116 133 100         while(len_left_from_orig > 0 && (key_p[0] == ' ' || key_p[0] == ';')) {
    100          
    100          
117 66           key_p++;
118 66           len_left_from_orig--;
119             }
120              
121 67 100         if (len_left_from_orig == 0) {
122 4           break;
123             }
124              
125 63           val_end_p = memchr(key_p, ';', len_left_from_orig);
126              
127             /* set cur_len to not count the ; */
128 63 100         if (val_end_p == NULL) {
129 6           cur_len = len_left_from_orig;
130 6           val_end_p = key_p + cur_len;
131 6           len_left_from_orig = 0;
132             } else {
133 57           cur_len = val_end_p - key_p;
134 57           len_left_from_orig -= cur_len + 1;
135             }
136              
137 63           val_p = memchr(key_p, '=', cur_len);
138 63 100         if (val_p != NULL) {
139 60           key_len = val_p - key_p;
140              
141             /* drop trailing spaces from key */
142 60 50         while(key_len > 0 && key_p[key_len-1] == ' ') {
    50          
143 0           key_len--;
144             }
145              
146             /* skip the = */
147 60           val_p++;
148 60           val_len = val_end_p - val_p;
149              
150             /* skip starting spaces from value */
151 60 100         while(val_len > 0 && val_p[0] == ' ') {
    50          
152 0           val_p++;
153 0           val_len--;
154             }
155             /* skip trailing spaces from value */
156 87 100         while(val_len > 0 && val_p[val_len-1] == ' ') {
    100          
157 27           val_len--;
158             }
159              
160 60           renewmem(aTHX_ &key, &key_size, key_len);
161 60           url_decode_key(key_p, key_len, key, &key_len);
162 60 100         if ( !hv_exists(hv, key, key_len) ) {
163 56           (void)hv_store(hv, key, key_len,
164             url_decode_val(aTHX_ val_p, val_len), 0);
165             }
166             }
167              
168 63 100         if (len_left_from_orig == 0) {
169             /* bypass bogus ptr math below */
170 19           break;
171             }
172              
173 44           key_p = val_end_p + 1;
174             }
175              
176 24           Safefree(key);
177             }
178 25           RETVAL = newRV_noinc((SV *)hv);
179             OUTPUT:
180             RETVAL
181