replace int RegExp replace string str string out const char replace un

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
// replace
int RegExp::replace(string &str, string &out, const char *replace, unsigned int replace_length, ReplaceCallback callback, unsigned int limit) {
char backrefs_exists = 0; // 1 - exists, 2 - not_exists, 0 - search
int end, start, replaced = 0;
int glocal_offset = 0;
while (exec(str, pcre_last_offset) > 0) {
start = result_vector[0] + glocal_offset;
end = result_vector[1] + glocal_offset;
if (callback) {
string replace_str = callback(this);
out.replace(out.begin() + start, out.begin() + end, replace_str);
glocal_offset += replace_str.length() - (end - start);
continue;
}
out.replace(out.begin() + start, out.begin() + end, replace, replace_length);
glocal_offset += replace_length - (end - start);
end += replace_length - (end - start);
// Обрабатывает бэкслэши
if (backrefs_exists != 2) {
int start_backref = -1, end_backref = -1;
bool is_brace = false;
char last_c = 0, backref;
if (backrefs_exists == 0)
backrefs_exists = 2;
for (int i = start; i < end; ++i) {
if (out[i] == '$') {
start_backref = i++;
// Если бэкреф инкапсулирован в фигурные скобки
is_brace = i < end && out[i] == '{';
if (is_brace) ++i;
// Парсим первую цифру номера бэкрефа
if (i < end && isdigit(out[i])) {
backref = out[i] - '0';
++i;
// Заэкранированный доллар, значит не нужно обрабатывать бэкрефы
if (last_c == '\\') {
out.erase(start_backref, 1);
glocal_offset -= 1;
end -= 1; i -= 1;
continue;
}
// Парсим вторую цифру номера бэкрефа
if (i < end && isdigit(out[i])) {
backref = (out[i] - '0') + (backref * 10);
++i;
}
if (!is_brace || (i < end && out[i] == '}')) {
// Ставим метку, что бэкрефы найдены
if (backrefs_exists == 2)
backrefs_exists = 1;
if (out[i] == '}') ++i;
end_backref = i;
if (backref < pcre_last_matches) {
// Замена бекрефа на найденный результат
int m_backref_start = result_vector[backref * 2];
int m_backref_end = result_vector[backref * 2 + 1];
int diff = (m_backref_end - m_backref_start) - (end_backref - start_backref);
out.replace(out.begin() + start_backref, out.begin() + end_backref, str.begin() + m_backref_start, str.begin() + m_backref_end);
glocal_offset += diff; end += diff; i += diff;
} else {
// Если бэкреф не найден в результате - выпиливаем его
out.erase(start_backref, end_backref - start_backref);
glocal_offset -= end_backref - start_backref;
end -= end_backref - start_backref;
i -= end_backref - start_backref;
}
}
}
}
if (i < end)
last_c = out[i];
}
}
++replaced;
if (limit && replaced == limit)
break;
}
return replaced;
}