bool InspIRCd::Match(const std::string &str, const std::string &mask, unsigned const char *map) { if (!map) map = national_case_insensitive_map; return match_internal((const unsigned char *)str.c_str(), (const unsigned char *)mask.c_str(), map); }
static void match_internal(match_context_t *context) { size_t j; for (j = 0; j < context->state->patterns.used; j++) { full_pcre_t *regex; int options = PCRE_NO_UTF8_CHECK; /* If the regex member == NULL, this highlight is either a pointer to another state which we should search here ("use"), or it is an end pattern with a dynamic back reference. */ if (context->state->patterns.data[j].regex.regex == NULL) { if (context->state->patterns.data[j].next_state >= 0) { state_t *save_state; save_state = context->state; context->state = &context->match->highlight->states.data[context->state->patterns.data[j].next_state]; match_internal(context); context->state = save_state; continue; } regex = &context->match->mapping.data[context->match->state].dynamic->regex; } else { regex = &context->state->patterns.data[j].regex; /* For items that do not change state, we do not want an empty match ever (makes no progress). */ if (context->state->patterns.data[j].next_state == NO_CHANGE) options |= PCRE_NOTEMPTY; /* The default behaviour is to not allow start patterns to be empty, such that progress will be guaranteed. */ else if (context->state->patterns.data[j].next_state > NO_CHANGE && !(context->match->highlight->flags & T3_HIGHLIGHT_ALLOW_EMPTY_START)) options |= PCRE_NOTEMPTY; } if (pcre_exec(regex->regex, regex->extra, context->line, context->size, context->match->match_start, options, context->ovector, sizeof(context->ovector) / sizeof(context->ovector[0])) >= 0 && context->ovector[1] > context->best_end) { context->best = &context->state->patterns.data[j]; context->best_end = context->ovector[1]; if (context->best->extra != NULL && context->best->extra->dynamic_name != NULL) { int string_number = pcre_get_stringnumber(context->best->regex.regex, context->best->extra->dynamic_name); if (string_number == PCRE_ERROR_NOSUBSTRING || string_number > 10) { context->extract_start = 0; context->extract_end = 0; } else { context->extract_start = context->ovector[string_number * 2]; context->extract_end = context->ovector[string_number * 2 + 1]; } } } } }
bool InspIRCd::Match(const char *str, const char *mask, unsigned const char *map) { if (!map) map = national_case_insensitive_map; return match_internal((const unsigned char *)str, (const unsigned char *)mask, map); }
t3_bool t3_highlight_match(t3_highlight_match_t *match, const char *line, size_t size) { match_context_t context; if ((match->highlight->flags & (T3_HIGHLIGHT_UTF8 | T3_HIGHLIGHT_UTF8_NOCHECK)) == T3_HIGHLIGHT_UTF8 && !match->utf8_checked) { if (!t3_highlight_utf8check(line, size)) { match->state = 0; match->begin_attribute = 0; match->match_attribute = 0; match->start = match->match_start = match->end = -1; return t3_false; } match->utf8_checked = t3_true; } context.match = match; context.line = line; context.size = size; context.state = &match->highlight->states.data[match->mapping.data[match->state].highlight_state]; context.best = NULL; context.best_end = -1; match->start = match->end; match->begin_attribute = context.state->attribute_idx; if (match->last_progress != match->end) { match->last_progress = match->end; match->last_progress_state = match->state; } else if (match->last_progress_state < match->state) { match->last_progress_state = match->state; } for (match->match_start = match->end; match->match_start <= size; match->match_start += (match->highlight->flags & T3_HIGHLIGHT_UTF8) ? step_utf8(line[match->match_start]) : 1) { match_internal(&context); if (context.best != NULL) { dst_idx_t next_state = find_state(match, context.best->next_state, context.best->extra, line + context.extract_start, context.extract_end - context.extract_start, context.best->extra != NULL ? context.best->extra->dynamic_pattern : NULL); /* Check if we have come full circle. If so, continue to the next byte and start over. */ if (match->last_progress == (size_t) context.best_end && context.best->next_state > NO_CHANGE && match->last_progress_state == next_state) { context.best = NULL; continue; } match->end = context.best_end; match->state = next_state; if (context.best->extra != NULL && context.best->extra->on_entry != NULL) { int i; for (i = 0; i < context.best->extra->on_entry_cnt; i++) { match->state = find_state(match, context.best->extra->on_entry[i].state, context.best->extra, line + context.extract_start, context.extract_end - context.extract_start, context.best->extra->on_entry[i].end_pattern); } } match->match_attribute = context.best->attribute_idx; return t3_true; } } match->match_start = size; match->end = size; return t3_false; }