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