File Coverage

lib/Term/ANSI/Sprintf.xs
Criterion Covered Total %
statement 55 55 100.0
branch 20 26 76.9
condition n/a
subroutine n/a
pod n/a
total 75 81 92.5


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             #include // rand()
6             #include
7              
8             char * basic_format_map[][2] = {
9             {"%bold", "1"},
10             {"%italic", "3"},
11             {"%underline", "4"},
12             };
13              
14             char * basic_color_map[][3] = {
15             {"%black_on_red", "30", "41"},
16             {"%black_on_green", "30", "42"},
17             {"%black_on_yellow", "30", "43"},
18             {"%black_on_blue", "30", "44"},
19             {"%black_on_magenta", "30", "45"},
20             {"%black_on_cyan", "30", "46"},
21             {"%black_on_white", "30", "47"},
22             {"%black_on_bright_red", "30", "101"},
23             {"%black_on_bright_green", "30", "102"},
24             {"%black_on_bright_yellow", "30", "103"},
25             {"%black_on_bright_blue", "30", "104"},
26             {"%black_on_bright_magenta", "30", "105"},
27             {"%black_on_bright_cyan", "30", "106"},
28             {"%black_on_bright_white", "30", "107"},
29             {"%bright_black_on_red", "90", "41"},
30             {"%bright_black_on_green", "90", "42"},
31             {"%bright_black_on_yellow", "90", "43"},
32             {"%bright_black_on_blue", "90", "44"},
33             {"%bright_black_on_magenta", "90", "45"},
34             {"%bright_black_on_cyan", "90", "46"},
35             {"%bright_black_on_white", "90", "47"},
36             {"%bright_black_on_bright_red", "90", "101"},
37             {"%bright_black_on_bright_green", "90", "102"},
38             {"%bright_black_on_bright_yellow", "90", "103"},
39             {"%bright_black_on_bright_blue", "90", "104"},
40             {"%bright_black_on_bright_magenta", "90", "105"},
41             {"%bright_black_on_bright_cyan", "90", "106"},
42             {"%bright_black_on_bright_white", "90", "107"},
43             {"%red_on_black", "31", "40"},
44             {"%red_on_green", "31", "42"},
45             {"%red_on_yellow", "31", "43"},
46             {"%red_on_blue", "31", "44"},
47             {"%red_on_magenta", "31", "45"},
48             {"%red_on_cyan", "31", "46"},
49             {"%red_on_white", "31", "47"},
50             {"%red_on_bright_black", "31", "100"},
51             {"%red_on_bright_green", "31", "102"},
52             {"%red_on_bright_yellow", "31", "103"},
53             {"%red_on_bright_blue", "31", "104"},
54             {"%red_on_bright_magenta", "31", "105"},
55             {"%red_on_bright_cyan", "31", "106"},
56             {"%red_on_bright_white", "31", "107"},
57             {"%bright_red_on_black", "91", "40"},
58             {"%bright_red_on_green", "91", "42"},
59             {"%bright_red_on_yellow", "91", "43"},
60             {"%bright_red_on_blue", "91", "44"},
61             {"%bright_red_on_magenta", "91", "45"},
62             {"%bright_red_on_cyan", "91", "46"},
63             {"%bright_red_on_white", "91", "47"},
64             {"%bright_red_on_bright_black", "91", "100"},
65             {"%bright_red_on_bright_green", "91", "102"},
66             {"%bright_red_on_bright_yellow", "91", "103"},
67             {"%bright_red_on_bright_blue", "91", "104"},
68             {"%bright_red_on_bright_magenta", "91", "105"},
69             {"%bright_red_on_bright_cyan", "91", "106"},
70             {"%bright_red_on_bright_white", "91", "107"},
71             {"%green_on_black", "32", "40"},
72             {"%green_on_red", "32", "41"},
73             {"%green_on_yellow", "32", "43"},
74             {"%green_on_blue", "32", "44"},
75             {"%green_on_magenta", "32", "45"},
76             {"%green_on_cyan", "32", "46"},
77             {"%green_on_white", "32", "47"},
78             {"%green_on_bright_black", "32", "100"},
79             {"%green_on_bright_red", "32", "101"},
80             {"%green_on_bright_yellow", "32", "103"},
81             {"%green_on_bright_blue", "32", "104"},
82             {"%green_on_bright_magenta", "32", "105"},
83             {"%green_on_bright_cyan", "32", "106"},
84             {"%green_on_bright_white", "32", "107"},
85             {"%bright_green_on_black", "92", "40"},
86             {"%bright_green_on_red", "92", "41"},
87             {"%bright_green_on_yellow", "92", "43"},
88             {"%bright_green_on_blue", "92", "44"},
89             {"%bright_green_on_magenta", "92", "45"},
90             {"%bright_green_on_cyan", "92", "46"},
91             {"%bright_green_on_white", "92", "47"},
92             {"%bright_green_on_bright_black", "92", "100"},
93             {"%bright_green_on_bright_red", "92", "101"},
94             {"%bright_green_on_bright_yellow", "92", "103"},
95             {"%bright_green_on_bright_blue", "92", "104"},
96             {"%bright_green_on_bright_magenta", "92", "105"},
97             {"%bright_green_on_bright_cyan", "92", "106"},
98             {"%bright_green_on_bright_white", "92", "107"},
99             {"%yellow_on_black", "33", "40"},
100             {"%yellow_on_red", "33", "41"},
101             {"%yellow_on_green", "33", "42"},
102             {"%yellow_on_blue", "33", "44"},
103             {"%yellow_on_magenta", "33", "45"},
104             {"%yellow_on_cyan", "33", "46"},
105             {"%yellow_on_white", "33", "47"},
106             {"%yellow_on_bright_black", "33", "100"},
107             {"%yellow_on_bright_red", "33", "101"},
108             {"%yellow_on_bright_green", "33", "102"},
109             {"%yellow_on_bright_blue", "33", "104"},
110             {"%yellow_on_bright_magenta", "33", "105"},
111             {"%yellow_on_bright_cyan", "33", "106"},
112             {"%yellow_on_bright_white", "33", "107"},
113             {"%bright_yellow_on_black", "93", "40"},
114             {"%bright_yellow_on_red", "93", "41"},
115             {"%bright_yellow_on_green", "93", "42"},
116             {"%bright_yellow_on_blue", "93", "44"},
117             {"%bright_yellow_on_magenta", "93", "45"},
118             {"%bright_yellow_on_cyan", "93", "46"},
119             {"%bright_yellow_on_white", "93", "47"},
120             {"%bright_yellow_on_bright_black", "93", "100"},
121             {"%bright_yellow_on_bright_red", "93", "101"},
122             {"%bright_yellow_on_bright_green", "93", "102"},
123             {"%bright_yellow_on_bright_blue", "93", "104"},
124             {"%bright_yellow_on_bright_magenta", "93", "105"},
125             {"%bright_yellow_on_bright_cyan", "93", "106"},
126             {"%bright_yellow_on_bright_white", "93", "107"},
127             {"%blue_on_black", "34", "40"},
128             {"%blue_on_red", "34", "41"},
129             {"%blue_on_green", "34", "42"},
130             {"%blue_on_yellow", "34", "43"},
131             {"%blue_on_magenta", "34", "45"},
132             {"%blue_on_cyan", "34", "46"},
133             {"%blue_on_white", "34", "47"},
134             {"%blue_on_bright_black", "34", "100"},
135             {"%blue_on_bright_red", "34", "101"},
136             {"%blue_on_bright_green", "34", "102"},
137             {"%blue_on_bright_yellow", "34", "103"},
138             {"%blue_on_bright_magenta", "34", "105"},
139             {"%blue_on_bright_cyan", "34", "106"},
140             {"%blue_on_bright_white", "34", "107"},
141             {"%bright_blue_on_black", "94", "40"},
142             {"%bright_blue_on_red", "94", "41"},
143             {"%bright_blue_on_green", "94", "42"},
144             {"%bright_blue_on_yellow", "94", "43"},
145             {"%bright_blue_on_magenta", "94", "45"},
146             {"%bright_blue_on_cyan", "94", "46"},
147             {"%bright_blue_on_white", "94", "47"},
148             {"%bright_blue_on_bright_black", "94", "100"},
149             {"%bright_blue_on_bright_red", "94", "101"},
150             {"%bright_blue_on_bright_green", "94", "102"},
151             {"%bright_blue_on_bright_yellow", "94", "103"},
152             {"%bright_blue_on_bright_magenta", "94", "105"},
153             {"%bright_blue_on_bright_cyan", "94", "106"},
154             {"%bright_blue_on_bright_white", "94", "107"},
155             {"%magenta_on_black", "35", "40"},
156             {"%magenta_on_red", "35", "41"},
157             {"%magenta_on_green", "35", "42"},
158             {"%magenta_on_yellow", "35", "43"},
159             {"%magenta_on_blue", "35", "44"},
160             {"%magenta_on_cyan", "35", "46"},
161             {"%magenta_on_white", "35", "47"},
162             {"%magenta_on_bright_black", "35", "100"},
163             {"%magenta_on_bright_red", "35", "101"},
164             {"%magenta_on_bright_green", "35", "102"},
165             {"%magenta_on_bright_yellow", "35", "103"},
166             {"%magenta_on_bright_blue", "35", "104"},
167             {"%magenta_on_bright_cyan", "35", "106"},
168             {"%magenta_on_bright_white", "35", "107"},
169             {"%bright_magenta_on_black", "95", "40"},
170             {"%bright_magenta_on_red", "95", "41"},
171             {"%bright_magenta_on_green", "95", "42"},
172             {"%bright_magenta_on_yellow", "95", "43"},
173             {"%bright_magenta_on_blue", "95", "44"},
174             {"%bright_magenta_on_cyan", "95", "46"},
175             {"%bright_magenta_on_white", "95", "47"},
176             {"%bright_magenta_on_bright_black", "95", "100"},
177             {"%bright_magenta_on_bright_red", "95", "101"},
178             {"%bright_magenta_on_bright_green", "95", "102"},
179             {"%bright_magenta_on_bright_yellow", "95", "103"},
180             {"%bright_magenta_on_bright_blue", "95", "104"},
181             {"%bright_magenta_on_bright_cyan", "95", "106"},
182             {"%bright_magenta_on_bright_white", "95", "107"},
183             {"%cyan_on_black", "36", "40"},
184             {"%cyan_on_red", "36", "41"},
185             {"%cyan_on_green", "36", "42"},
186             {"%cyan_on_yellow", "36", "43"},
187             {"%cyan_on_blue", "36", "44"},
188             {"%cyan_on_magenta", "36", "45"},
189             {"%cyan_on_white", "36", "47"},
190             {"%cyan_on_bright_black", "36", "100"},
191             {"%cyan_on_bright_red", "36", "101"},
192             {"%cyan_on_bright_green", "36", "102"},
193             {"%cyan_on_bright_yellow", "36", "103"},
194             {"%cyan_on_bright_blue", "36", "104"},
195             {"%cyan_on_bright_magenta", "36", "105"},
196             {"%cyan_on_bright_white", "36", "107"},
197             {"%bright_cyan_on_black", "96", "40"},
198             {"%bright_cyan_on_red", "96", "41"},
199             {"%bright_cyan_on_green", "96", "42"},
200             {"%bright_cyan_on_yellow", "96", "43"},
201             {"%bright_cyan_on_blue", "96", "44"},
202             {"%bright_cyan_on_magenta", "96", "45"},
203             {"%bright_cyan_on_white", "96", "47"},
204             {"%bright_cyan_on_bright_black", "96", "100"},
205             {"%bright_cyan_on_bright_red", "96", "101"},
206             {"%bright_cyan_on_bright_green", "96", "102"},
207             {"%bright_cyan_on_bright_yellow", "96", "103"},
208             {"%bright_cyan_on_bright_blue", "96", "104"},
209             {"%bright_cyan_on_bright_magenta", "96", "105"},
210             {"%bright_cyan_on_bright_white", "96", "107"},
211             {"%white_on_black", "37", "40"},
212             {"%white_on_red", "37", "41"},
213             {"%white_on_green", "37", "42"},
214             {"%white_on_yellow", "37", "43"},
215             {"%white_on_blue", "37", "44"},
216             {"%white_on_magenta", "37", "45"},
217             {"%white_on_cyan", "37", "46"},
218             {"%white_on_bright_black", "37", "100"},
219             {"%white_on_bright_red", "37", "101"},
220             {"%white_on_bright_green", "37", "102"},
221             {"%white_on_bright_yellow", "37", "103"},
222             {"%white_on_bright_blue", "37", "104"},
223             {"%white_on_bright_magenta", "37", "105"},
224             {"%white_on_bright_cyan", "37", "106"},
225             {"%bright_white_on_black", "97", "40"},
226             {"%bright_white_on_red", "97", "41"},
227             {"%bright_white_on_green", "97", "42"},
228             {"%bright_white_on_yellow", "97", "43"},
229             {"%bright_white_on_blue", "97", "44"},
230             {"%bright_white_on_magenta", "97", "45"},
231             {"%bright_white_on_cyan", "97", "46"},
232             {"%bright_white_on_bright_black", "97", "100"},
233             {"%bright_white_on_bright_red", "97", "101"},
234             {"%bright_white_on_bright_green", "97", "102"},
235             {"%bright_white_on_bright_yellow", "97", "103"},
236             {"%bright_white_on_bright_blue", "97", "104"},
237             {"%bright_white_on_bright_magenta", "97", "105"},
238             {"%bright_white_on_bright_cyan", "97", "106"},
239             {"%black", "30"},
240             {"%red", "31"},
241             {"%green", "32"},
242             {"%yellow", "33"},
243             {"%blue", "34"},
244             {"%magenta", "35"},
245             {"%cyan", "36"},
246             {"%white", "37"},
247             {"%bright_black", "90"},
248             {"%bright_red", "91"},
249             {"%bright_green", "92"},
250             {"%bright_yellow", "93"},
251             {"%bright_blue", "94"},
252             {"%bright_magenta", "95"},
253             {"%bright_cyan", "96"},
254             {"%bright_white", "97"},
255             };
256              
257 22           char * concat(char* s1, char* s2) {
258             dTHX;
259 22           char *result = malloc(strlen(s1) + strlen(s2) + 1);
260 22           strcpy(result, s1);
261 22           strcat(result, s2);
262 22           return result;
263             }
264              
265 972           char *str_replace(char *orig, char *rep, char * map[3], int colour) {
266             dTHX;
267             char * result, * ins, * tmp, * with;
268             int len_rep, len_with, len_front, count;
269 972           len_rep = strlen(rep);
270 972 50         if (len_rep == 0) return orig;
271 972           ins = orig;
272 979 100         for (count = 0; (tmp = strstr(ins, rep)); ++count) {
273 7           ins = tmp + len_rep;
274             }
275 972 100         if (count == 0) return orig;
276 7 100         if (colour) {
277 4           with = concat("\e[", map[1]);
278 4 50         if (map[2]) {
279 4           with = concat(with, ";");
280 4           with = concat(with, map[2]);
281             }
282 4           with = concat(with, "m%s\e[0m");
283             } else {
284 3           with = concat(concat("\e[", map[1]), "m");
285             }
286 7           len_with = strlen(with);
287 7           tmp = result = malloc(strlen(orig) + (len_with - len_rep) * count + 1);
288 7 50         if (!result) return orig;
289 14 100         while (count--) {
290 7           ins = strstr(orig, rep);
291 7           len_front = ins - orig;
292 7           tmp = strncpy(tmp, orig, len_front) + len_front;
293 7           tmp = strcpy(tmp, with) + len_with;
294 7           orig += len_front + len_rep; // move to next "end of rep"
295             }
296 7           strcpy(tmp, orig);
297 7           return result;
298             }
299              
300 4           char * preprocess (char * sprint) {
301             dTHX;
302 4           int i = 0;
303 4           int size = sizeof(basic_format_map)/sizeof(basic_format_map[0]);
304 16 100         for (i = 0; i < size; i++) {
305 12           sprint = str_replace(sprint, basic_format_map[i][0], basic_format_map[i], 0);
306             }
307 4           size = sizeof(basic_color_map)/sizeof(basic_color_map[0]);
308 964 100         for (i = 0; i < size; i++) {
309 960           sprint = str_replace(sprint, basic_color_map[i][0], basic_color_map[i], 1);
310             }
311 4           return sprint;
312             }
313            
314             MODULE = Term::ANSI::Sprintf PACKAGE = Term::ANSI::Sprintf
315             PROTOTYPES: ENABLE
316              
317             SV *
318             sprintf(...)
319             CODE:
320 4           AV * params = av_make(items, MARK+1);
321 4           SV * spr = av_shift(params);
322 4           char * sprint = preprocess(SvPV_nolen(spr));
323 4           int len = av_len(params);
324 4           dSP;
325 4 50         PUSHMARK(SP);
326 4 50         EXTEND(SP, len + 2);
    50          
327 4           PUSHs(sv_2mortal(newSVpv("Term::ANSI::Sprintf", 0)));
328 4           PUSHs(newSVpv(sprint, 0));
329 4           int i = 0;
330 8 100         for (i = 0; i <= len; i++) {
331 4           PUSHs(newSVsv(*av_fetch(params, i, 0)));
332             }
333 4           PUTBACK;
334 4           call_method("_sprintf", 3);
335 4           SPAGAIN;
336 4           RETVAL = newSVsv(POPs);
337             OUTPUT:
338             RETVAL
339