| line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
|
1
|
|
|
|
|
|
|
/* |
|
2
|
|
|
|
|
|
|
* |
|
3
|
|
|
|
|
|
|
* Copyright (c) 2018, cPanel, LLC. |
|
4
|
|
|
|
|
|
|
* All rights reserved. |
|
5
|
|
|
|
|
|
|
* http://cpanel.net |
|
6
|
|
|
|
|
|
|
* |
|
7
|
|
|
|
|
|
|
* This is free software; you can redistribute it and/or modify it under the |
|
8
|
|
|
|
|
|
|
* same terms as Perl itself. |
|
9
|
|
|
|
|
|
|
* |
|
10
|
|
|
|
|
|
|
*/ |
|
11
|
|
|
|
|
|
|
|
|
12
|
|
|
|
|
|
|
#include |
|
13
|
|
|
|
|
|
|
#include |
|
14
|
|
|
|
|
|
|
#include |
|
15
|
|
|
|
|
|
|
#include |
|
16
|
|
|
|
|
|
|
|
|
17
|
|
|
|
|
|
|
#define _REPLACE_BUFFER_SIZE 64 |
|
18
|
|
|
|
|
|
|
|
|
19
|
|
|
|
|
|
|
SV *_replace_str( char *src, int len, SV *map ); |
|
20
|
|
|
|
|
|
|
|
|
21
|
8
|
|
|
|
|
|
SV *_replace_str( char *src, int len, SV *map ) { |
|
22
|
8
|
|
|
|
|
|
char buffer[_REPLACE_BUFFER_SIZE] = { 0 }; |
|
23
|
|
|
|
|
|
|
|
|
24
|
8
|
|
|
|
|
|
int i = 0; |
|
25
|
8
|
|
|
|
|
|
char *ptr = src; |
|
26
|
8
|
|
|
|
|
|
char *str = buffer; /* the new string we are going to use */ |
|
27
|
|
|
|
|
|
|
char *tmp; /* used to grow */ |
|
28
|
8
|
|
|
|
|
|
int str_size = _REPLACE_BUFFER_SIZE; /* we start with the buffer */ |
|
29
|
8
|
|
|
|
|
|
int ix_newstr = 0; |
|
30
|
|
|
|
|
|
|
AV *mapav; |
|
31
|
|
|
|
|
|
|
SV *reply; |
|
32
|
|
|
|
|
|
|
|
|
33
|
|
|
|
|
|
|
|
|
34
|
8
|
50
|
|
|
|
|
if ( !map || SvTYPE(map) != SVt_RV || SvTYPE(SvRV(map)) != SVt_PVAV |
|
|
|
100
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
35
|
7
|
0
|
|
|
|
|
|| AvFILL( SvRV(map) ) <= 0 |
|
|
|
100
|
|
|
|
|
|
|
36
|
|
|
|
|
|
|
) { |
|
37
|
2
|
|
|
|
|
|
return newSVpv( src, len ); /* no alteration */ |
|
38
|
|
|
|
|
|
|
} |
|
39
|
|
|
|
|
|
|
|
|
40
|
6
|
|
|
|
|
|
mapav = (AV *)SvRV(map); |
|
41
|
6
|
|
|
|
|
|
SV **ary = AvARRAY(mapav); |
|
42
|
|
|
|
|
|
|
|
|
43
|
|
|
|
|
|
|
|
|
44
|
366
|
100
|
|
|
|
|
for ( i = 0; i < len; ++i, ++ptr, ++ix_newstr ) { |
|
45
|
360
|
|
|
|
|
|
char c = *ptr; |
|
46
|
360
|
|
|
|
|
|
int ix = (int) ( c ); |
|
47
|
360
|
100
|
|
|
|
|
if ( ix < 0 ) ix = 256 + ix; |
|
48
|
|
|
|
|
|
|
// need to croak in DEBUG mode if char is invalid |
|
49
|
|
|
|
|
|
|
|
|
50
|
360
|
|
|
|
|
|
str[ix_newstr] = c; /* default always performed... */ |
|
51
|
360
|
50
|
|
|
|
|
if ( ix >= AvFILL(mapav) || !AvARRAY(mapav)[ix] ) { |
|
|
|
100
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
52
|
1
|
|
|
|
|
|
continue; |
|
53
|
|
|
|
|
|
|
} else { |
|
54
|
359
|
|
|
|
|
|
SV *entry = AvARRAY(mapav)[ix]; |
|
55
|
359
|
50
|
|
|
|
|
if ( SvPOK( entry ) ) { |
|
56
|
359
|
|
|
|
|
|
int slen = SvCUR( entry ); /* length of the string used for replacement */ |
|
57
|
359
|
50
|
|
|
|
|
if ( slen <= 0 ) { |
|
58
|
0
|
|
|
|
|
|
continue; |
|
59
|
|
|
|
|
|
|
} else { |
|
60
|
359
|
|
|
|
|
|
char *replace = SvPVX( entry ); |
|
61
|
359
|
|
|
|
|
|
int j = 0; |
|
62
|
|
|
|
|
|
|
|
|
63
|
|
|
|
|
|
|
/* Check if we need to expand. */ |
|
64
|
359
|
100
|
|
|
|
|
if (str_size <= (ix_newstr + slen + 1) ) { /* +1 for \0 */ |
|
65
|
|
|
|
|
|
|
//printf( "neew to grow %d -> %d\n", str_size, ix_newstr + slen ); |
|
66
|
4
|
|
|
|
|
|
str_size *= 2; |
|
67
|
|
|
|
|
|
|
|
|
68
|
4
|
100
|
|
|
|
|
if ( str == buffer ) { |
|
69
|
|
|
|
|
|
|
/* our first malloc */ |
|
70
|
2
|
50
|
|
|
|
|
Newx(str, str_size, char*); |
|
71
|
2
|
|
|
|
|
|
strncpy( str, buffer, ix_newstr ); |
|
72
|
|
|
|
|
|
|
} else { |
|
73
|
|
|
|
|
|
|
/* grow the string */ |
|
74
|
2
|
|
|
|
|
|
tmp = Perl_realloc( str, str_size ); |
|
75
|
2
|
50
|
|
|
|
|
if ( !tmp ) Perl_croak(aTHX_ "failed to realloc string" ); |
|
76
|
2
|
|
|
|
|
|
str = tmp; |
|
77
|
|
|
|
|
|
|
} |
|
78
|
|
|
|
|
|
|
} |
|
79
|
|
|
|
|
|
|
|
|
80
|
|
|
|
|
|
|
/* replace all characters except the last one, which avoids us to do a --ix_newstr after */ |
|
81
|
480
|
100
|
|
|
|
|
for ( ; j < slen - 1; ++j ) { |
|
82
|
121
|
|
|
|
|
|
str[ix_newstr++] = replace[j]; |
|
83
|
|
|
|
|
|
|
} |
|
84
|
|
|
|
|
|
|
/* handle the last character */ |
|
85
|
359
|
|
|
|
|
|
str[ix_newstr] = replace[j]; |
|
86
|
|
|
|
|
|
|
} |
|
87
|
|
|
|
|
|
|
} /* end - SvPOK */ |
|
88
|
|
|
|
|
|
|
} /* end - AvFILL || AvARRAY */ |
|
89
|
|
|
|
|
|
|
} |
|
90
|
|
|
|
|
|
|
|
|
91
|
6
|
|
|
|
|
|
str[ix_newstr] = '\0'; /* add the final trailing \0 character */ |
|
92
|
6
|
|
|
|
|
|
reply = newSVpv( str, ix_newstr ); |
|
93
|
|
|
|
|
|
|
|
|
94
|
|
|
|
|
|
|
/* free our tmp buffer if needed */ |
|
95
|
6
|
100
|
|
|
|
|
if ( str != buffer ) free(str); |
|
96
|
|
|
|
|
|
|
|
|
97
|
8
|
|
|
|
|
|
return reply; |
|
98
|
|
|
|
|
|
|
} |
|
99
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
MODULE = Char__Replace PACKAGE = Char::Replace |
|
101
|
|
|
|
|
|
|
|
|
102
|
|
|
|
|
|
|
|
|
103
|
|
|
|
|
|
|
SV* |
|
104
|
|
|
|
|
|
|
replace(str, map) |
|
105
|
|
|
|
|
|
|
SV *str; |
|
106
|
|
|
|
|
|
|
SV *map; |
|
107
|
|
|
|
|
|
|
CODE: |
|
108
|
11
|
50
|
|
|
|
|
if ( str && SvPOK(str) ) { |
|
|
|
100
|
|
|
|
|
|
|
109
|
8
|
|
|
|
|
|
RETVAL = _replace_str( SvPVX(str), SvCUR(str), map ); |
|
110
|
|
|
|
|
|
|
} else { |
|
111
|
3
|
|
|
|
|
|
RETVAL = &PL_sv_undef; |
|
112
|
|
|
|
|
|
|
} |
|
113
|
|
|
|
|
|
|
OUTPUT: |
|
114
|
|
|
|
|
|
|
RETVAL |