//======================================================================
//-----------------------------------------------------------------------
/**
 * @file		iutest_regex.ipp
 * @brief		regex
 *
 * @author		t.shirayanagi
 * @par			copyright
 * Copyright (C) 2011-2015, Takazumi Shirayanagi\n
 * This software is released under the new BSD License,
 * see LICENSE
*/
//-----------------------------------------------------------------------
//======================================================================
#ifndef INCG_IRIS_IUTEST_REGEX_IPP_1575CB44_189A_4248_B305_DB4882E3BFC2_
#define INCG_IRIS_IUTEST_REGEX_IPP_1575CB44_189A_4248_B305_DB4882E3BFC2_

//======================================================================
// include
#include "../internal/iutest_regex.hpp"

namespace iutest {
namespace detail
{

IUTEST_IPP_INLINE bool iuFilterRegex::match_impl(const char* begin, const char* end, const char* src)
{
	const char* tp = begin;
	if( *tp == '\0' ) return false;
	while( tp != end )
	{
		if( *tp == '*' )	// 任意の文字列にマッチ
		{
			++tp;
			while( *tp == '*' ) ++tp;
			if( tp == end ) return true;

			{
				const char nc = *tp;
				if( nc == '\0' ) return true;

				for( ; ; )
				{
					while( *src != nc )
					{
						++src;
						if( *src == '\0' ) return false;
					}
					// つづきを検査
					if( match_impl(tp+1, end, ++src) ) return true;
				}
			}
		}
		else if( *tp == '?' )	// 任意の一文字にマッチ
		{
			if( *src == '\0' ) return false;
		}
		else	// 指定文字にマッチ
		{
			if( *tp != *src ) return false;
		}
		++tp;
		++src;
	}
	if( *src != '\0' ) return false;
	return true;
}

IUTEST_IPP_INLINE bool iuFilterRegex::match_impl_group(const char* begin, const char* end, const char* src)
{
	bool match = true;
	const char* tp = begin;
	const char* end2 = tp;
	while( end2 != end )
	{
		++end2;
		while( *end2 != '-' && end2 != end ) ++end2;
		if( *tp == '-' )
		{
			if( match_impl(tp + 1, end2, src) ) match = false;
		}
		else
		{
			if( !match_impl(tp, end2, src) ) match = false;
		}
		tp = end2;
	}
	return match;
}

IUTEST_IPP_INLINE bool iuFilterRegex::match(const char* regex, const char* src)
{
	const char* tp = regex;
	bool positive = false;
	bool positive_checked = false;
	bool negative = true;

	while( *tp != '\0' )
	{
		const char* end = tp;
		while( *end != '\0' && *end != ':' ) ++end;

		if( tp != end )
		{
			if( *tp == '-' )
			{
				if( match_impl(tp + 1, end, src) )
				{
					return false;
				}
				negative = false;
			}
			else
			{
				positive_checked = true;
				if( match_impl_group(tp, end, src) )
				{
					positive = true;
				}
			}
			tp = end;
		}
		if( *tp == ':' ) ++tp;
	}
	if( !negative && !positive_checked )
	{
		positive = true;
	}
	return positive;
}

#if IUTEST_HAS_CXX_HDR_REGEX

IUTEST_IPP_INLINE bool iuRegex::FullMatch(const char* str) const
{
	if( str == NULL ) return false;
	return ::std::regex_match(str, m_re);
}

IUTEST_IPP_INLINE bool iuRegex::PartialMatch(const char* str) const
{
	if( str == NULL ) return false;
	return ::std::regex_search(str, m_re);
}

IUTEST_IPP_INLINE void iuRegex::Init(const char* str)
{
	m_re.assign(str);
	m_pattern = str;
}

#endif

}	// end of namespace detail
}	// end of namespace iutest

#endif // INCG_IRIS_IUTEST_REGEX_IPP_1575CB44_189A_4248_B305_DB4882E3BFC2_
