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 |