Line data Source code
1 : #include "testitall.h"
2 :
3 25 : Return replace_placeholder(
4 : memory *pattern,
5 : const char *placeholder,
6 : const char *replacement)
7 : {
8 25 : Return status = SUCCESS;
9 :
10 25 : if((pattern == NULL) || (placeholder == NULL) || (replacement == NULL))
11 : {
12 0 : return FAILURE;
13 : }
14 :
15 25 : const char *subject = getcstring(pattern);
16 :
17 25 : if(subject == NULL)
18 : {
19 0 : return FAILURE;
20 : }
21 :
22 25 : const size_t subject_len = strlen(subject);
23 :
24 25 : pcre2_code *re = NULL;
25 25 : pcre2_match_data *match_data = NULL;
26 25 : create(char,replacement_buffer);
27 :
28 25 : const PCRE2_SPTR pattern_str = (PCRE2_SPTR)placeholder;
29 25 : const PCRE2_SPTR subject_str = (PCRE2_SPTR)subject;
30 25 : const PCRE2_SPTR replacement_str = (PCRE2_SPTR)replacement;
31 :
32 25 : int err_code = 0;
33 25 : PCRE2_SIZE err_offset = 0;
34 :
35 25 : re = pcre2_compile(
36 : pattern_str,
37 : PCRE2_ZERO_TERMINATED,
38 : 0,
39 : &err_code,
40 : &err_offset,
41 : NULL
42 : );
43 :
44 25 : if(re == NULL)
45 : {
46 : PCRE2_UCHAR err_msg[MAX_CHARACTERS];
47 0 : pcre2_get_error_message(err_code,err_msg,sizeof(err_msg));
48 0 : echo(STDERR,"ERROR: PCRE2 compilation failed at offset %d: %s\n",(int)err_offset,err_msg);
49 0 : status = FAILURE;
50 : }
51 :
52 25 : if(SUCCESS == status)
53 : {
54 25 : match_data = pcre2_match_data_create_from_pattern(re,NULL);
55 :
56 25 : if(match_data == NULL)
57 : {
58 0 : echo(STDERR,"ERROR: Failed to allocate match data\n");
59 0 : status = FAILURE;
60 : }
61 : }
62 :
63 25 : PCRE2_SIZE out_len = subject_len + 1;
64 :
65 25 : if(SUCCESS == status)
66 : {
67 25 : int rc = pcre2_match(re,subject_str,subject_len,0,0,match_data,NULL);
68 :
69 271 : while(rc >= 0)
70 : {
71 738 : out_len += strlen(replacement) - (pcre2_get_ovector_pointer(match_data)[1] -
72 246 : pcre2_get_ovector_pointer(match_data)[0]);
73 246 : rc = pcre2_match(re,subject_str,subject_len,
74 246 : pcre2_get_ovector_pointer(match_data)[1],0,match_data,NULL);
75 : }
76 :
77 25 : if(out_len == 0)
78 : {
79 0 : out_len = 1;
80 : }
81 :
82 25 : status = resize(replacement_buffer,(size_t)out_len);
83 : }
84 :
85 25 : PCRE2_SIZE out_len_actual = out_len;
86 :
87 25 : if(SUCCESS == status)
88 : {
89 25 : char *output = data(char,replacement_buffer);
90 :
91 25 : if(output == NULL)
92 : {
93 0 : status = FAILURE;
94 : } else {
95 25 : int rc = pcre2_substitute(
96 : re,
97 : subject_str,
98 : subject_len,
99 : 0,
100 : PCRE2_SUBSTITUTE_GLOBAL,
101 : match_data,
102 : NULL,
103 : replacement_str,
104 : PCRE2_ZERO_TERMINATED,
105 : (PCRE2_UCHAR8 *)output,
106 : &out_len_actual);
107 :
108 25 : if(rc < 0)
109 : {
110 0 : echo(STDERR,"ERROR: PCRE2 substitution error: %d\n",rc);
111 0 : status = FAILURE;
112 : } else {
113 25 : const size_t actual_length = (size_t)out_len_actual;
114 :
115 25 : if(actual_length + 1 > replacement_buffer->length)
116 : {
117 0 : status = resize(replacement_buffer,actual_length + 1);
118 :
119 0 : output = data(char,replacement_buffer);
120 :
121 0 : if(output == NULL)
122 : {
123 0 : status = FAILURE;
124 : }
125 : }
126 :
127 25 : if(SUCCESS == status)
128 : {
129 25 : output[actual_length] = '\0';
130 25 : status = resize(replacement_buffer,actual_length + 1);
131 : }
132 : }
133 : }
134 : }
135 :
136 25 : run(copy(pattern,replacement_buffer));
137 :
138 25 : call(del(replacement_buffer));
139 :
140 25 : if(match_data != NULL)
141 : {
142 25 : pcre2_match_data_free(match_data);
143 : }
144 :
145 25 : if(re != NULL)
146 : {
147 25 : pcre2_code_free(re);
148 : }
149 :
150 25 : return(status);
151 : }
|