File Coverage

encode_gen.h
Criterion Covered Total %
statement 121 145 83.4
branch 132 404 32.6
condition n/a
subroutine n/a
pod n/a
total 253 549 46.0


line stmt bran cond sub pod time code
1             // vim: filetype=xs
2              
3 58           STRLEN CONCAT(estimate_, NAME)(SV * sv, int depth){
4 58 0         if( sv!=NULL ){
    50          
    0          
    100          
5 57 0         if( SvROK(sv) && (!UNBLESSED || !sv_isobject(sv)) ){
    0          
    100          
    100          
    0          
    100          
6 26           SV * rvs = SvRV(sv);
7 33 0         for(int i=visited_p-1; i>=0; --i)
    100          
    0          
    100          
8 8 0         if( visited[i] == rvs )
    50          
    0          
    100          
9 1           return 4;
10 25           reserve_visited_capacity();
11 25           visited[visited_p++] = rvs;
12 25           switch( SvTYPE(rvs) ){
13             case SVt_PVAV: {
14 15           AV * av = (AV*) rvs;
15 15           SSize_t n = av_len(av);
16 15           if( n<0 ){
17 0           --visited_p;
18 0           return 2;
19             }
20              
21 15           STRLEN len = 2 + n;
22 15           SV ** elems = AvARRAY(av);
23 48 0         for(int i=0; i<=n; ++i)
    100          
    0          
    100          
24 33           len += CONCAT(estimate_, NAME)(elems[i], depth+1);
25 0 0         if( PRETTY && n>0 )
    0          
26 0           len += (n+1) * (depth*2+2);
27 15           --visited_p;
28 15           return len;
29             }
30             case SVt_PVHV: {
31 5           HV * hv = (HV*) rvs;
32              
33 5           STRLEN len = 1;
34 5           hv_iterinit(hv);
35 10 0         for(HE * entry = hv_iternext(hv); entry; entry = hv_iternext(hv)){
    0          
    0          
    100          
36 5           len += 2; // : ,
37              
38             I32 keylen;
39 5           char * key = hv_iterkey(entry, &keylen);
40 5           len += estimate_str((unsigned char*)key, (STRLEN) keylen);
41              
42 5           SV * val = hv_iterval(hv, entry);
43 5           len += CONCAT(estimate_, NAME)(val, depth+1);
44             if( PRETTY )
45 0           len += depth*2 + 3;
46             }
47 5 0         if( len==1 )
    0          
    0          
    50          
48 0           ++len;
49              
50 5           --visited_p;
51 5           return len;
52             }
53             default:
54 5           --visited_p;
55 5           break;
56             }
57 5 0         if( SvTYPE(rvs) < SVt_PVAV ){
    50          
    0          
    50          
58 5 0         NV nv = SvNV(rvs);
    50          
    0          
    100          
59             IV iv;
60 5           STRLEN len=0;
61 10 0         if( !Perl_isnan(nv) && nv == (NV)(iv = (IV) nv) ){
    0          
    50          
    50          
    0          
    0          
    50          
    50          
62 5 0         if( iv == 0 )
    50          
    0          
    50          
63 0           return 1;
64 5 0         if( iv < 0 )
    50          
    0          
    50          
65 0           ++len;
66 12 0         while( iv ){
    100          
    0          
    100          
67 7           ++len;
68 7           iv /= 10;
69             }
70             }
71             else{
72             char buffer[100];
73 0           snprintf(buffer, 100, "%g", (double) nv);
74 0 0         while( buffer[len] )
    0          
    0          
    0          
75 0           ++len;
76             }
77 5           return len;
78             }
79             }
80 31 0         if( SvOK(sv) ){
    0          
    0          
    50          
    0          
    0          
    0          
    0          
    0          
    100          
    50          
    50          
81             STRLEN len;
82 29 0         char * str = SvPV(sv, len);
    100          
    0          
    100          
83 29           return estimate_str((unsigned char*)str, len);
84             }
85             }
86 3           return 4;
87             }
88              
89 58           unsigned char * CONCAT(encode_, NAME)(unsigned char * buffer, SV * sv, int depth){
90 58 0         if( sv!=NULL ){
    50          
    50          
    100          
91 57 0         if( SvROK(sv) && (!UNBLESSED || !sv_isobject(sv)) ){
    0          
    100          
    100          
    100          
    100          
92 26           SV * rvs = SvRV(sv);
93 33 0         for(int i=visited_p-1; i>=0; --i)
    100          
    100          
    100          
94 8 0         if( visited[i] == rvs )
    50          
    50          
    100          
95 1           goto DEGENERATE;
96 25           reserve_visited_capacity();
97 25           visited[visited_p++] = rvs;
98 25           switch( SvTYPE(rvs) ){
99             case SVt_PVAV: {
100 15           *buffer++ = '[';
101              
102 15           AV * av = (AV*) rvs;
103 15           SSize_t n = av_len(av);
104 15           if( n>=0 ){
105 15           SV ** elems = AvARRAY(av);
106 33 0         for(int i=0; i
    100          
    100          
    100          
107             if( PRETTY )
108 2           *buffer++ = ' ';
109 18           buffer = CONCAT(encode_, NAME)(buffer, elems[i], depth+1);
110             if( PRETTY ){
111 2           *buffer++ = '\n';
112 2 0         for(int i=0; i
    50          
113 0           *buffer++ = ' ';
114 0           *buffer++ = ' ';
115             }
116             }
117 18           *buffer++ = ',';
118             }
119 3 0         if( PRETTY && n>0 )
    100          
120 2           *buffer++ = ' ';
121 15           buffer = CONCAT(encode_, NAME)(buffer, elems[n], depth+1);
122 3           if( PRETTY && n>0 ){
123 2           *buffer++ = '\n';
124 2 0         for(int i=0; i
    50          
125 0           *buffer++ = ' ';
126 0           *buffer++ = ' ';
127             }
128             }
129             }
130              
131 15           *buffer++ = ']';
132 15           --visited_p;
133 15           return buffer;
134             }
135             case SVt_PVHV: {
136 5           *buffer++ = '{';
137 5           HV * hv = (HV*) rvs;
138              
139 5           hv_iterinit(hv);
140 10 0         for(HE * entry = hv_iternext(hv); entry; entry = hv_iternext(hv)){
    0          
    100          
    100          
141             if( PRETTY )
142 2           *buffer++ = ' ';
143              
144             I32 keylen;
145 5           char * key = hv_iterkey(entry, &keylen);
146 5           buffer = encode_str(buffer, (unsigned char*)key, (STRLEN) keylen);
147              
148 5           *buffer++ = ':';
149             if( PRETTY )
150 2           *buffer++ = ' ';
151              
152 5           SV * val = hv_iterval(hv, entry);
153 5           buffer = CONCAT(encode_, NAME)(buffer, val, depth+1);
154              
155             if( PRETTY ){
156 2           *buffer++ = '\n';
157 3 0         for(int i=0; i
    100          
158 1           *buffer++ = ' ';
159 1           *buffer++ = ' ';
160             }
161             }
162 5           *buffer++ = ',';
163             }
164              
165 5 0         if( *(buffer-1) == '{' )
    0          
    50          
    50          
166 0           *buffer++ = '}';
167             else
168 5           *(buffer-1) = '}';
169 5           --visited_p;
170 5           return buffer;
171             }
172             default:
173 5           --visited_p;
174 5           break;
175             }
176 5 0         if( SvTYPE(rvs) < SVt_PVAV ){
    50          
    0          
    50          
177 5 0         NV nv = SvNV(rvs);
    50          
    0          
    100          
178             IV iv;
179 5 0         if( !Perl_isnan(nv) && nv == (NV)(iv = (IV) nv) ){
    0          
    50          
    50          
    0          
    0          
    50          
    50          
180 10 0         if( -59074 <= iv && iv <= 59074 ){
    0          
    50          
    50          
    0          
    0          
    50          
    50          
181             // (stolen from JSON::XS)
182             // optimise the "small number case"
183             // code will likely be branchless and use only a single multiplication
184             // works for numbers up to 59074
185             U32 u;
186 5           char digit, nz = 0;
187 5 0         if( iv < 0 ){
    50          
    0          
    50          
188 0           *buffer++ = '-';
189 0           u = -iv;
190             }
191             else
192 5           u = iv;
193             // convert to 4.28 fixed-point representation
194 5           u = u * ((0xfffffff + 10000) / 10000); // 10**5, 5 fractional digits
195              
196             // now output digit by digit, each time masking out the integer part
197             // and multiplying by 5 while moving the decimal point one to the right,
198             // resulting in a net multiplication by 10.
199             // we always write the digit to memory but conditionally increment
200             // the pointer, to enable the use of conditional move instructions.
201 5 0         digit = u >> 28; *buffer = digit + '0'; buffer += (nz = nz || digit); u = (u & 0xfffffffUL) * 5;
    0          
    50          
    50          
    0          
    0          
    50          
    50          
202 5 0         digit = u >> 27; *buffer = digit + '0'; buffer += (nz = nz || digit); u = (u & 0x7ffffffUL) * 5;
    0          
    50          
    50          
    0          
    0          
    50          
    50          
203 5 0         digit = u >> 26; *buffer = digit + '0'; buffer += (nz = nz || digit); u = (u & 0x3ffffffUL) * 5;
    0          
    50          
    50          
    0          
    0          
    50          
    50          
204 5 0         digit = u >> 25; *buffer = digit + '0'; buffer += (nz = nz || digit); u = (u & 0x1ffffffUL) * 5;
    0          
    50          
    50          
    0          
    0          
    50          
    100          
205 5           digit = u >> 24; *buffer = digit + '0'; buffer += 1; // correctly generate '0'
206             }
207             else{
208 0           snprintf((char*)buffer, 100, "%lld", (long long)iv);
209 0 0         while( *buffer )
    0          
    0          
    0          
210 0           ++buffer;
211             }
212             }
213             else{
214 0           snprintf((char*)buffer, 100, "%g", (double) nv);
215 0 0         while( *buffer )
    0          
    0          
    0          
216 0           ++buffer;
217             }
218 5           return buffer;
219             }
220             }
221 31 0         if( SvOK(sv) ){
    0          
    0          
    50          
    0          
    0          
    50          
    0          
    0          
    100          
    50          
    50          
222             STRLEN len;
223 29 0         char * str = SvPV(sv, len);
    100          
    50          
    100          
224 29           return encode_str(buffer, (unsigned char*)str, len);
225             }
226             }
227             DEGENERATE:
228 4           *buffer++ = 'n';
229 4           *buffer++ = 'u';
230 4           *buffer++ = 'l';
231 4           *buffer++ = 'l';
232 4           return buffer;
233             }
234