Line data Source code
1 : #include "testitall.h"
2 :
3 : /**
4 : * @brief Match managed memory buffers against a PCRE2 pattern.
5 : *
6 : * @param text Text descriptor that stores subject data.
7 : * @param pattern Pattern descriptor interpreted as PCRE2 expression.
8 : * @return SUCCESS on match, FAILURE otherwise.
9 : */
10 142 : Return match_pattern(
11 : const memory *text,
12 : const memory *pattern,
13 : ...)
14 : {
15 142 : Return status = SUCCESS;
16 142 : const char *text_view = NULL;
17 142 : const char *pattern_view = NULL;
18 142 : const char *filename = NULL;
19 : #if 0
20 : char *diff = NULL;
21 : #endif
22 :
23 142 : if((text == NULL) || (pattern == NULL))
24 : {
25 0 : status = FAILURE;
26 : }
27 :
28 142 : if(SUCCESS == status)
29 : {
30 : /* Acquire null-terminated views guarded by libmem */
31 142 : text_view = getcstring(text);
32 142 : pattern_view = getcstring(pattern);
33 :
34 142 : if((text_view == NULL) || (pattern_view == NULL))
35 : {
36 0 : status = FAILURE;
37 : }
38 : }
39 :
40 : va_list args;
41 142 : va_start(args,pattern);
42 :
43 : /* Optional third argument carries template filename for diagnostics */
44 142 : filename = va_arg(args,const char *);
45 142 : va_end(args);
46 :
47 : /* Compile the regular expression */
48 142 : pcre2_code *compiled_pattern = NULL;
49 142 : pcre2_match_data *match_data = NULL;
50 :
51 142 : if(SUCCESS == status)
52 : {
53 142 : int errornumber = 0;
54 142 : PCRE2_SIZE erroroffset = 0;
55 :
56 : /* Compile the regular expression with multiline and dot-all flags */
57 142 : compiled_pattern = pcre2_compile(
58 : (PCRE2_SPTR)pattern_view,
59 : PCRE2_ZERO_TERMINATED,
60 : PCRE2_MULTILINE | PCRE2_DOTALL, /* Enable multiline, extended mode and dot matching newline */
61 : &errornumber,
62 : &erroroffset,
63 : NULL);
64 :
65 142 : if(compiled_pattern == NULL)
66 : {
67 : PCRE2_UCHAR buffer[MAX_CHARACTERS];
68 0 : pcre2_get_error_message(errornumber,buffer,sizeof(buffer));
69 0 : echo(STDERR,"ERROR: Regex compilation error at offset %d: %s\n",
70 : (int)erroroffset,buffer);
71 0 : status = FAILURE;
72 : }
73 : }
74 :
75 142 : if(SUCCESS == status)
76 : {
77 : /* Allocate memory for match data */
78 142 : match_data = pcre2_match_data_create_from_pattern(compiled_pattern,NULL);
79 :
80 142 : if(match_data == NULL)
81 : {
82 0 : echo(STDERR,"ERROR: Failed to allocate PCRE2 match data\n");
83 0 : status = FAILURE;
84 : }
85 : }
86 :
87 142 : if(SUCCESS == status)
88 : {
89 : /* Attempt to match */
90 142 : int match_result = pcre2_match(
91 : compiled_pattern,
92 : (PCRE2_SPTR)text_view,
93 : PCRE2_ZERO_TERMINATED,
94 : 0,
95 : 0,
96 : match_data,
97 : NULL);
98 :
99 142 : if(match_result < 0)
100 : {
101 : /* Surface mismatch context or raw PCRE error */
102 0 : if(match_result == PCRE2_ERROR_NOMATCH)
103 : {
104 : #if 0
105 : /* Get diff */
106 : status = compare_strings(&diff,text_view,pattern_view);
107 : #endif
108 :
109 : #if 0
110 : {
111 : // Sequentially match increasing portions of the subject string
112 : size_t mismatch_offset = 0;
113 : size_t subject_length = strlen(text_view);
114 :
115 : for(size_t i = 1; i <= subject_length; i++)
116 : {
117 : match_result = pcre2_match(
118 : compiled_pattern,
119 : (PCRE2_SPTR)text_view,
120 : i,
121 : 0,
122 : 0,
123 : match_data,
124 : NULL);
125 :
126 : if(match_result < 0)
127 : {
128 : mismatch_offset = i - 1; // Last valid match position
129 : break;
130 : }
131 : }
132 :
133 : if(mismatch_offset < subject_length)
134 : {
135 : echo(STDERR,"Mismatch starts at offset %zu.\n",mismatch_offset);
136 : }
137 : }
138 : #endif
139 :
140 0 : if(filename != NULL)
141 : {
142 0 : echo(STDERR,YELLOW "ERROR: The pattern not match!" RESET "\n"
143 : #if 0
144 : YELLOW "Diff:\n>>" RESET "%s" YELLOW "<<" RESET "\n"
145 : #endif
146 : YELLOW "Output:\n>>" RESET "%s" YELLOW "<<" RESET "\n"
147 : YELLOW "Compared to a pattern from the file %s:\n>>" RESET "%s" YELLOW "<<" RESET "\n",
148 : #if 0
149 : diff,
150 : #endif
151 : text_view,filename,pattern_view);
152 : } else {
153 0 : echo(STDERR,YELLOW "ERROR: The pattern not match!" RESET "\n"
154 : #if 0
155 : YELLOW "Diff:\n>>" RESET "%s" YELLOW "<<" RESET "\n"
156 : #endif
157 : YELLOW "Output:\n>>" RESET "%s" YELLOW "<<" RESET "\n"
158 : YELLOW "Compared to a pattern:\n>>" RESET "%s" YELLOW "<<" RESET "\n",
159 : #if 0
160 : diff,
161 : #endif
162 : text_view,pattern_view);
163 : }
164 : } else {
165 0 : echo(STDERR,YELLOW "ERROR: pcre2_match error: %d" RESET "\n",match_result);
166 : }
167 :
168 0 : status = FAILURE;
169 : }
170 : }
171 :
172 142 : if(match_data != NULL)
173 : {
174 142 : pcre2_match_data_free(match_data);
175 : }
176 :
177 142 : if(compiled_pattern != NULL)
178 : {
179 142 : pcre2_code_free(compiled_pattern);
180 : }
181 :
182 : #if 0
183 : /* Release diff buffer produced by optional comparison helpers */
184 : free(diff);
185 : #endif
186 :
187 142 : return(status);
188 : }
|