<commit_before>#include "matcher.h"

#include <cassert>
#include <cinttypes>
#include <ctime>
#include <regex.h>
#include <sstream>
#include <sys/time.h>
#include <vector>

#include "logger.h"
#include "matchable.h"
#include "matcherexception.h"
#include "scopemeasure.h"
#include "utils.h"

namespace newsboat {

Matcher::Matcher() {}

Matcher::Matcher(const std::string& expr)
	: exp(expr)
{
	parse(expr);
}

std::string Matcher::get_expression()
{
	return exp;
}

bool Matcher::parse(const std::string& expr)
{
	struct timeval tv1, tv2;
	gettimeofday(&tv1, nullptr);

	errmsg = "";

	bool b = p.parse_string(expr);

	if (b) {
		exp = expr;
	} else {
		errmsg = utils::wstr2str(p.get_error());
	}

	gettimeofday(&tv2, nullptr);
	const uint64_t diff =
		(((tv2.tv_sec - tv1.tv_sec) * 1000000) + tv2.tv_usec) -
		tv1.tv_usec;
	LOG(Level::DEBUG,
		"Matcher::parse: parsing `%s' took %" PRIu64 " µs (success = %d)",
		expr,
		diff,
		b ? 1 : 0);

	return b;
}

bool Matcher::matches(Matchable* item)
{
	/*
	 * with this method, every class that is derived from Matchable can be
	 * matched against a filter expression that was previously passed to the
	 * class with the parse() method.
	 *
	 * This makes it easy to use the Matcher virtually everywhere, since C++
	 * allows multiple inheritance (i.e. deriving from Matchable can even be
	 * used in class hierarchies), and deriving from Matchable means that
	 * you only have to implement the method attribute_value().
	 *
	 * The whole matching code is speed-critical, as the matching happens on<commit_msg>Matcher: use ScopeMeasure instead of gettimeofday()<commit_after>#include "matcher.h"

#include <cassert>
#include <cinttypes>
#include <ctime>
#include <regex.h>
#include <sstream>
#include <vector>

#include "logger.h"
#include "matchable.h"
#include "matcherexception.h"
#include "scopemeasure.h"
#include "utils.h"

namespace newsboat {

Matcher::Matcher() {}

Matcher::Matcher(const std::string& expr)
	: exp(expr)
{
	parse(expr);
}

std::string Matcher::get_expression()
{
	return exp;
}

bool Matcher::parse(const std::string& expr)
{
	ScopeMeasure measurer("Matcher::parse");

	errmsg = "";

	bool b = p.parse_string(expr);

	if (b) {
		exp = expr;
	} else {
		errmsg = utils::wstr2str(p.get_error());
	}

	LOG(Level::DEBUG,
		"Matcher::parse: parsing `%s' succeeded: %d",
		expr,
		b ? 1 : 0);

	return b;
}

bool Matcher::matches(Matchable* item)
{
	/*
	 * with this method, every class that is derived from Matchable can be
	 * matched against a filter expression that was previously passed to the
	 * class with the parse() method.
	 *
	 * This makes it easy to use the Matcher virtually everywhere, since C++
	 * allows multiple inheritance (i.e. deriving from Matchable can even be
	 * used in class hierarchies), and deriving from Matchable means that
	 * you only have to implement the method attribute_value().
	 *
	 * The whole matching code is speed-critical, as the matching happens on
{'fraction_non_alphanumeric': 0.12993587580155247, 'fraction_numerical': 0.008437394532568343, 'mean_word_length': 4.418647166361974, 'pattern_counts': {'":': 0, '<': 16, '<?xml version=': 0, '>': 16, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6765583', 'n_tokens_mistral': 1060, 'n_tokens_neox': 994, 'n_words': 318}