File Coverage

XS.xs
Criterion Covered Total %
statement 106 112 94.6
branch 92 108 85.1
condition n/a
subroutine n/a
pod n/a
total 198 220 90.0


line stmt bran cond sub pod time code
1             #define PERL_NO_GET_CONTEXT // we'll define thread context if necessary (faster)
2             #include "EXTERN.h" // globals/constant import locations
3             #include "perl.h" // Perl symbols, structures and constants definition
4             #include "XSUB.h" // xsubpp functions and macros
5             #define NEED_utf8_to_uvchr_buf
6             #include "ppport.h"
7              
8             #include
9             #include
10              
11             #define isEOL(c) ((c >= 0xa) && (c <= 0xd ) || (c == 0x85))
12             #define isEOL_UTF8(c) (isEOL(c) || c == 0x2028 || c == 0x2029)
13              
14 18           char* _minify_ascii(pTHX_ char* src, STRLEN len, STRLEN* packed) {
15              
16             char* dest;
17              
18 18           Newx(dest, len + 1, char);
19              
20 18 50         if (!dest) /* malloc failed */
21 0           return dest;
22              
23             /* initialize to end-of-string in case string contains only spaces */
24 18           *dest = 0;
25              
26 18           char* end = src + len;
27 18           char* ptr = dest;
28 18           char* leading = ptr; /* start of leading whitespace, or NULL if none */
29 18           char* trailing = NULL; /* start of trailing whitespace, or NULL if none */
30              
31 18 100         if (len == 0) {
32 1           *packed = len;
33 1           return dest;
34             }
35              
36 152 100         while (len > 0) {
37              
38 135           char c = *src;
39              
40 135           src ++;
41 135           len --;
42              
43 135 100         if (leading && !isSPACE(c))
    100          
44 18           leading = NULL;
45              
46 135 100         if (!leading) {
47              
48 99 100         if (isEOL(c)) {
    100          
49 9 100         if (trailing) ptr = trailing;
50 9 100         if ( c == '\r' ) c = '\n'; /* Normalise EOL */
51 9           leading = ptr;
52             }
53 90 100         else if (isSPACE(c)) {
54 13 100         if (!trailing) trailing = ptr;
55             }
56             else {
57 77           trailing = NULL;
58             }
59              
60 99           *ptr++ = c;
61             }
62              
63             }
64              
65 17 100         if (trailing) {
66 6           ptr = trailing;
67 6           char c = *ptr;
68 6 50         if (isEOL(c)) { ptr++; }
    100          
69             }
70              
71 17           *packed = ptr - dest;
72              
73 17           return dest;
74              
75             }
76              
77 38           STATIC U8* _minify_utf8(pTHX_ U8* src, STRLEN len, STRLEN* packed) {
78             U8* dest;
79              
80 38           Newx(dest, len + 1, U8);
81              
82 38 50         if (!dest) /* malloc failed */
83 0           return dest;
84              
85             /* initialize to end-of-string in case string contains only spaces */
86 38           *dest = 0;
87              
88 38           U8* end = src + len;
89 38           U8* ptr = dest;
90 38           U8* leading = ptr; /* start of leading whitespace, or NULL if none */
91 38           U8* trailing = NULL; /* start of trailing whitespace, or NULL if none */
92              
93 38 100         if (len == 0) {
94 2           *packed = len;
95 2           return dest;
96             }
97              
98 318 100         while (len > 0) {
99              
100 282           UV c = *src;
101              
102 282 100         if (UTF8_IS_INVARIANT(c)) {
103 269           src ++;
104 269           len --;
105             }
106             else {
107             STRLEN skip;
108 13           c = utf8_to_uvchr_buf(src, end, &skip);
109 13 100         if (c == 0) {
110 2           c = *src;
111             }
112 13 100         if ((int) skip > 0) {
113 11           src += skip;
114 11           len -= skip;
115             }
116             else {
117 2           src ++;
118 13           len --;
119             }
120             if (len < 0) {
121             croak("UTF-8 character overflow");
122             src = end;
123             len = 0;
124             trailing = NULL;
125             }
126             }
127              
128 282 100         if (leading && !isSPACE(c))
    100          
    100          
129 42           leading = NULL;
130              
131 282 100         if (!leading) {
132              
133 206 100         if (isEOL_UTF8(c)) {
    100          
    50          
    100          
    50          
134 25 100         if (trailing) ptr = trailing;
135 25 100         if ( c == '\r' ) c = '\n'; /* Normalise EOL */
136 25           leading = ptr;
137             }
138 181 100         else if (isSPACE(c)) {
    100          
139 30 100         if (!trailing) trailing = ptr;
140             }
141             else {
142 151           trailing = NULL;
143             }
144              
145 206 100         if (UTF8_IS_INVARIANT(c))
146 193           *ptr++ = c;
147             else
148 13           ptr = uvchr_to_utf8( ptr, c);
149              
150             }
151              
152             }
153              
154 36 100         if (trailing) {
155 13           ptr = trailing;
156 13           UV c = *ptr;
157 13           STRLEN skip = UTF8SKIP(ptr);
158 13 100         if (!UTF8_IS_INVARIANT(c)) {
159 2           c = utf8_to_uvchr_buf(ptr, ptr + skip, &skip);
160 2 50         if (c == 0) {
161 0           c = *ptr;
162             }
163             }
164 13 50         if (isEOL_UTF8(c)) {
    100          
    50          
    100          
    50          
165 9 50         if ((int) skip <= 0) {
166 0           skip = 1;
167             }
168 13           ptr += skip;
169             }
170             }
171              
172 36           *packed = ptr - dest;
173              
174 36           return dest;
175             }
176             MODULE = Text::Minify::XS PACKAGE = Text::Minify::XS
177              
178             PROTOTYPES: ENABLE
179              
180             SV*
181             minify(inStr)
182             SV* inStr
183             INIT:
184 39           char* outStr = NULL;
185 39           RETVAL = &PL_sv_undef;
186             CODE:
187             char* src;
188             STRLEN len;
189 39           STRLEN packed = 0;
190             U32 is_utf8;
191 39 100         if (SvOK(inStr)) {
    50          
    50          
192 38           src = SvPVX(inStr);
193 38           len = SvCUR(inStr);
194 38           outStr = _minify_utf8(aTHX_ src, len, &packed);
195 38 50         if (outStr != NULL) {
196 38           SV* result = newSVpvn(outStr, packed);
197 38           is_utf8 = SvUTF8(inStr);
198 38 100         if (is_utf8)
199 2           SvUTF8_on(result);
200 38           RETVAL = result;
201 38           Safefree(outStr);
202             }
203             else {
204 0           croak("_minify_utf8 returned NULL");
205             }
206             }
207             OUTPUT:
208             RETVAL
209              
210             SV*
211             minify_ascii(inStr)
212             SV* inStr
213             INIT:
214 19           char* outStr = NULL;
215 19           RETVAL = &PL_sv_undef;
216             CODE:
217             char* src;
218             STRLEN len;
219 19           STRLEN packed = 0;
220 19 100         if (SvOK(inStr)) {
    50          
    50          
221 18           src = SvPVX(inStr);
222 18           len = SvCUR(inStr);
223 18           outStr = _minify_ascii(aTHX_ src, len, &packed);
224 18 50         if (outStr != NULL) {
225 18           SV* result = newSVpvn(outStr, packed);
226 18           RETVAL = result;
227 18           Safefree(outStr);
228             }
229             else {
230 0           croak("_minify_ascii returned NULL");
231             }
232             }
233             OUTPUT:
234             RETVAL