File Coverage

XS.xs
Criterion Covered Total %
statement 103 109 94.5
branch 86 98 87.7
condition n/a
subroutine n/a
pod n/a
total 189 207 91.3


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_L1(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_L1(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 45           STATIC U8* _minify_utf8(pTHX_ U8* src, STRLEN len, STRLEN* packed) {
78             U8* dest;
79              
80 45           Newx(dest, len + 1, U8);
81              
82 45 50         if (!dest) /* malloc failed */
83 0           return dest;
84              
85             /* initialize to end-of-string in case string contains only spaces */
86 45           *dest = 0;
87              
88 45           U8* end = src + len;
89 45           U8* ptr = dest;
90 45           U8* leading = ptr; /* start of leading whitespace, or NULL if none */
91 45           U8* trailing = NULL; /* start of trailing whitespace, or NULL if none */
92              
93 45 100         if (len == 0) {
94 2           *packed = len;
95 2           return dest;
96             }
97              
98 324 100         while (src < end) {
99              
100 289           UV c = *src;
101              
102 289 100         if (UTF8_IS_INVARIANT(c)) {
103 269           src ++;
104 269           len --;
105             }
106             else {
107             STRLEN skip;
108 20           c = utf8_to_uvchr_buf(src, end, &skip);
109              
110 20 100         if (skip == (STRLEN) -1) {
111 8           croak_nocontext("Malformed UTF-8 %s", src);
112             }
113             else {
114 12           src += skip;
115 12           len -= skip;
116             }
117             }
118              
119 281 100         if (leading && !isSPACE(c))
    100          
    100          
120 41           leading = NULL;
121              
122 281 100         if (!leading) {
123              
124 208 100         if (isEOL_UTF8(c)) {
    100          
    50          
    100          
    50          
125 24 100         if (trailing) ptr = trailing;
126 24 100         if ( c == '\r' ) c = '\n'; /* Normalise EOL */
127 24           leading = ptr;
128             }
129 184 100         else if (isSPACE(c)) {
    100          
130 28 100         if (!trailing) trailing = ptr;
131             }
132             else {
133 156           trailing = NULL;
134             }
135              
136 208 100         if (UTF8_IS_INVARIANT(c))
137 196           *ptr++ = c;
138             else
139 12           ptr = uvchr_to_utf8( ptr, c);
140              
141             }
142              
143             }
144              
145 35 100         if (trailing) {
146 12           ptr = trailing;
147 12           UV c = *ptr;
148 12           STRLEN skip = UTF8SKIP(ptr);
149 12 100         if (!UTF8_IS_INVARIANT(c)) {
150 2           c = utf8_to_uvchr_buf(ptr, ptr + skip, &skip);
151 2 50         if (c == 0) {
152 0           c = *ptr;
153             }
154             }
155 12 50         if (isEOL_UTF8(c)) {
    100          
    50          
    100          
    50          
156 8 50         if ((int) skip <= 0) {
157 0           skip = 1;
158             }
159 8           ptr += skip;
160             }
161             }
162              
163 35           *packed = ptr - dest;
164              
165 35           return dest;
166             }
167             MODULE = Text::Minify::XS PACKAGE = Text::Minify::XS
168              
169             PROTOTYPES: ENABLE
170              
171             SV*
172             minify(inStr)
173             SV* inStr
174             INIT:
175 46           char* outStr = NULL;
176 46           RETVAL = &PL_sv_undef;
177             CODE:
178             char* src;
179             STRLEN len;
180 46           STRLEN packed = 0;
181             U32 is_utf8;
182 46 100         if (SvOK(inStr)) {
183 45           src = SvPVX(inStr);
184 45           len = SvCUR(inStr);
185 45           outStr = _minify_utf8(aTHX_ src, len, &packed);
186 37 50         if (outStr != NULL) {
187 37           SV* result = newSVpvn(outStr, packed);
188 37           is_utf8 = SvUTF8(inStr);
189 37 100         if (is_utf8)
190 3           SvUTF8_on(result);
191 37           RETVAL = result;
192 37           Safefree(outStr);
193             }
194             else {
195 0           croak("_minify_utf8 returned NULL");
196             }
197             }
198             OUTPUT:
199             RETVAL
200              
201             SV*
202             minify_ascii(inStr)
203             SV* inStr
204             INIT:
205 19           char* outStr = NULL;
206 19           RETVAL = &PL_sv_undef;
207             CODE:
208             char* src;
209             STRLEN len;
210 19           STRLEN packed = 0;
211 19 100         if (SvOK(inStr)) {
212 18           src = SvPVX(inStr);
213 18           len = SvCUR(inStr);
214 18           outStr = _minify_ascii(aTHX_ src, len, &packed);
215 18 50         if (outStr != NULL) {
216 18           SV* result = newSVpvn(outStr, packed);
217 18           RETVAL = result;
218 18           Safefree(outStr);
219             }
220             else {
221 0           croak("_minify_ascii returned NULL");
222             }
223             }
224             OUTPUT:
225             RETVAL