#include "config.h"

// Implementation
#include "PosixRegex.hpp"

// Local
#include "Text.hpp"

namespace UI {
namespace Util {

std::string PosixRegex::getErrorMessage(int result) const
{
	int const maxSize(256);
	std::string msg;
	msg.resize(maxSize);
	regerror(result, &preg_, &msg[0], maxSize-1);
	return msg.c_str();
}

PosixRegex::PosixRegex(std::string const & regex, int cflags)
{
	int result(::regcomp(&preg_, regex.c_str(), cflags));
	if (result != 0)
	{
		std::string msg(getErrorMessage(result));
		::regfree(&preg_);
		UI_THROW_CODE((reg_errcode_t)result, "Error compiling posix regex \"" + regex + "\": " + msg);
	}
}

PosixRegex::~PosixRegex()
{
	::regfree(&preg_);
}

PosixRegex::Match PosixRegex::runMatch(std::string const & text, int eflags)
{
	Match result;
	::regmatch_t pmatch[1];
	int posixErr(::regexec(&preg_, text.c_str(), 1, pmatch, eflags));
	if (posixErr == 0)
	{
		result.matches = true;
		result.begin = pmatch[0].rm_so;
		result.end = pmatch[0].rm_eo;
	}
	else if (posixErr == REG_NOMATCH)
	{
		result.matches = false;
	}
	else
	{
		UI_THROW_CODE((reg_errcode_t)posixErr, "Error matching \"" + text + "\" against posix regex: " + getErrorMessage(posixErr));
	}
	return result;
}

bool PosixRegex::run(std::string const & text, int eflags)
{
	return runMatch(text, eflags).matches;
}

}}
