File Coverage

json-whitespace.c
Criterion Covered Total %
statement 28 52 53.8
branch 6 14 42.8
condition n/a
subroutine n/a
pod n/a
total 34 66 51.5


line stmt bran cond sub pod time code
1             /* Type for adding whitespace. */
2              
3             typedef struct json_s {
4             SV * sv;
5             char * s;
6             STRLEN sl;
7             }
8             json_s_t;
9              
10             typedef struct json_ws {
11             SV * news;
12             SV * olds;
13             /* Length of original string. */
14             STRLEN olds_l;
15             /* Length of new string. */
16             unsigned int news_l;
17             /* Copy point. */
18             char * q;
19             /* Origin */
20             char * p;
21             /* Top of token tree. */
22             json_token_t * t;
23             /* Token under examination now. */
24             json_token_t * next;
25              
26             /* Whitespace to add before and after. */
27             char * before[n_json_tokens];
28             char * after[n_json_tokens];
29             int array_depth;
30             int object_depth;
31             char * array_indent;
32             char * object_indent;
33             }
34             json_ws_t;
35              
36 0           static void copy_whitespace (json_ws_t * ws, char * w)
37             {
38             char * q;
39 0           q = ws->q;
40 0 0         while (*w) {
41 0           *q++ = *w++;
42             }
43 0           ws->q = q;
44 0           }
45              
46             static INLINE int whitespace_json (json_ws_t * ws)
47             {
48             /* Copy place. */
49             char * c;
50             /* Value of q at entry to this routine, used to calculate added
51             length. */
52             char * qorig;
53             json_token_t * next;
54             char * q;
55              
56             q = ws->q;
57             qorig = q;
58             next = ws->next;
59              
60             while (next) {
61             /* Copy start of string. */
62             copy_whitespace (ws, ws->before[next->type]);
63             switch (next->type) {
64             case json_token_object:
65             *q++ = '{';
66             ws->object_depth++;
67             ws->q = q;
68             q += whitespace_json (ws);
69             ws->object_depth--;
70             *q++ = '}';
71             break;
72             case json_token_array:
73             *q++ = '[';
74             ws->array_depth++;
75             ws->q = q;
76             q += whitespace_json (ws);
77             ws->object_depth--;
78             *q++ = ']';
79             break;
80             case json_token_string:
81             case json_token_key:
82             case json_token_literal:
83             case json_token_number:
84             for (c = ws->p + next->start; c <= ws->p + next->end; c++) {
85             *q++ = *c;
86             }
87             break;
88             case json_token_comma:
89             *q++ = ',';
90             break;
91             case json_token_colon:
92             *q++ = ':';
93             break;
94             default:
95             croak ("unhandled token type %d", next->type);
96             }
97             /* Copy end of string. */
98             c = ws->after[next->type];
99             while (*c) {
100             *q++ = *c++;
101             }
102             next = next->next;
103             }
104             return q - qorig;
105             }
106              
107 6           static int copy_json (char * p, char * q, json_token_t * t)
108             {
109             /* Loop variable. */
110             json_token_t * next;
111             /* Copy place. */
112             char * c;
113             /* Value of q at entry to this routine, used to calculate added
114             length. */
115             char * qorig;
116              
117 6           next = t;
118 6           qorig = q;
119 86 100         while (next) {
120 80           switch (next->type) {
121             case json_token_object:
122 5           *q++ = '{';
123 5           q += copy_json (p, q, next->child);
124 5           *q++ = '}';
125 5           break;
126             case json_token_array:
127 0           *q++ = '[';
128 0           q += copy_json (p, q, next->child);
129 0           *q++ = ']';
130 0           break;
131             case json_token_string:
132             case json_token_key:
133             case json_token_literal:
134             case json_token_number:
135 244 100         for (c = p + next->start; c < p + next->end; c++) {
136 206           *q++ = *c;
137             }
138 38           break;
139             case json_token_comma:
140 16           *q++ = ',';
141 16           break;
142             case json_token_colon:
143 21           *q++ = ':';
144 21           break;
145             default:
146 0           croak ("unhandled token type %d", next->type);
147             }
148 80           next = next->next;
149             }
150 6           return q - qorig;
151             }
152              
153             /* Remove all the whitespace. */
154              
155 1           static SV * strip_whitespace (json_token_t * tokens, SV * json)
156             {
157             SV * stripped;
158             char * p;
159             char * q;
160             /* Original length. */
161             STRLEN l;
162             /* Length of output. */
163             unsigned int m;
164 1 50         p = SvPV (json, l);
165 1           stripped = newSV (l);
166             /* Tell Perl it's a string. */
167 1           SvPOK_on (stripped);
168             /* Set UTF-8 if necessary. */
169 1 50         if (SvUTF8 (json)) {
170 1           SvUTF8_on (stripped);
171             }
172             /* Get a pointer to the string inside "stripped". */
173 1           q = SvPVX (stripped);
174 1           m = copy_json (p, q, tokens);
175             /* Set the length. */
176 1           SvCUR_set (stripped, m);
177 1           return stripped;
178             }
179              
180 0           static SV * indent (json_token_t * tokens, SV * json)
181             {
182             int i;
183 0           json_ws_t j = {0};
184              
185 0           j.olds = json;
186 0 0         j.p = SvPV (j.olds, j.olds_l);
187 0           j.t = tokens;
188 0           j.next = tokens;
189 0 0         for (i = 0; i < n_json_tokens; i++) {
190 0           j.before[i] = "";
191 0           j.after[i] = "";
192             }
193 0           j.after[json_token_comma] = "\n";
194 0           j.after[json_token_object] = "\n";
195 0           j.after[json_token_array] = "\n";
196 0           return &PL_sv_undef;
197             }