#pragma once

#include <string>
#include <vector>

#include <boost/regex.hpp>


namespace util
{


class RegexParser
{
public:
	RegexParser(const std::string& text, const std::string& pattern) :
		m_TextIterator(text.begin()),
		m_TextEnd(text.end()),
		m_Pattern(pattern)
	{}

public:
	bool ParseNext(void)
	{
		if(!boost::regex_search(m_TextIterator, m_TextEnd, m_Smatch, m_Pattern))
			return false;

		m_TextIterator = m_Smatch[0].second;
		return true;
	}

	std::string GetResult(int idx) const
	{
		return m_Smatch.str(idx);
	}

	int GetNumElements(void) const
	{
		return m_Smatch.size();
	}

private:
	std::string::const_iterator m_TextIterator;
	const std::string::const_iterator m_TextEnd;
	const boost::regex m_Pattern;
	boost::smatch m_Smatch;
};

class WRegexParser
{
public:
	WRegexParser(const std::wstring& text, const std::wstring& pattern) :
		m_TextIterator(text.begin()),
		m_TextEnd(text.end()),
		m_Pattern(pattern)
	{}

public:
	bool ParseNext(void)
	{
		if(!boost::regex_search(m_TextIterator, m_TextEnd, m_Smatch, m_Pattern))
			return false;

		m_TextIterator = m_Smatch[0].second;
		return true;
	}

	std::wstring GetResult(int idx) const
	{
		return m_Smatch.str(idx);
	}

	int GetNumElements(void) const
	{
		return m_Smatch.size();
	}

private:
	std::wstring::const_iterator m_TextIterator;
	const std::wstring::const_iterator m_TextEnd;
	const boost::wregex m_Pattern;
	boost::wsmatch m_Smatch;
};


class Regex
{
public:
	//! 単一要素のパース. 正規表現を用いた単一行の構文解析などに使用
	static bool Parse(const std::string& text, const std::string& pattern, std::vector<std::string>& elements)
	{
		const std::string::const_iterator tex_beg = text.begin();
		const std::string::const_iterator tex_end = text.end();

		const boost::regex pattern_regex(pattern);

		boost::smatch s;
		if(!boost::regex_search(tex_beg, tex_end, s, pattern_regex))
			return false;

		elements.resize(s.size());
		for(size_t i = 0; i < elements.size(); ++i)
		{
			elements[i] = s.str(i);
		}

		return true;
	}
	//! 単一要素のパース. 正規表現を用いた単一行の構文解析などに使用
	static bool Parse(const std::wstring& text, const std::wstring& pattern, std::vector<std::wstring>& elements)
	{
		const std::wstring::const_iterator tex_beg = text.begin();
		const std::wstring::const_iterator tex_end = text.end();

		const boost::wregex pattern_regex(pattern);

		boost::wsmatch s;
		if(!boost::regex_search(tex_beg, tex_end, s, pattern_regex))
			return false;

		elements.resize(s.size());
		for(size_t i = 0; i < elements.size(); ++i)
		{
			elements[i] = s.str(i);
		}

		return true;
	}

	//! 指定正規表現が１回以上マッチするかどうかを判定
	static bool IsMatch(const std::string& text, const std::string& pattern)
	{
		const std::string::const_iterator tex_beg = text.begin();
		const std::string::const_iterator tex_end = text.end();

		const boost::regex pattern_regex(pattern);

		boost::smatch s;
		return boost::regex_search(tex_beg, tex_end, s, pattern_regex);
	}

	//! 指定正規表現が１回以上マッチするかどうかを判定
	static bool IsMatch(const std::wstring& text, const std::wstring& pattern)
	{
		const std::wstring::const_iterator tex_beg = text.begin();
		const std::wstring::const_iterator tex_end = text.end();

		const boost::wregex pattern_regex(pattern);

		boost::wsmatch s;
		return boost::regex_search(tex_beg, tex_end, s, pattern_regex);
	}
};


}
