#pragma once

#include <cstdlib>
#include <vector>
#include <string>


namespace util
{


//! std::stringの補助機能
class String
{
public:
	//! 文字列の分割機能
	static void Split(const std::string& str , std::vector<std::string>& o_sList, const char splitter);

	//! ワイド文字列からマルチバイト文字列
	//! ロケール依存
	static void ToMultiByte(const std::wstring &src, std::string &dst);
	static std::string ToMultiByte(const std::wstring &src);


	//! マルチバイト文字列からワイド文字列
	//! ロケール依存
	static void ToUnicode(const std::string &src, std::wstring &dst);
	static std::wstring ToUnicode(const std::string &src);

	//! トリム(半角空白, タブのみ)
	static void Trim(std::string& s);
	//! 指定文字のトリム. 文字列両端の括弧の除去などに使用する.
	static void Trim(std::string& s, const char* pattern);
};


// ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

//! 文字列の分割機能
inline void String::Split(const std::string& str , std::vector<std::string>& o_sList, const char splitter)
{
	o_sList.clear();

	size_t next_head = 0;
	for(size_t i=0;i<str.size();++i)
	{
		if( str.c_str()[i] == splitter )
		{
			if( next_head != i )
				o_sList.push_back( str.substr( next_head , i - next_head ) );
			next_head = i + 1;
		}
	}

	if( next_head < str.size() ) o_sList.push_back( str.substr( next_head ) );
}


//! ワイド文字列からマルチバイト文字列
//! ロケール依存
inline void String::ToMultiByte(const std::wstring &src, std::string &dst)
{
	if( src.empty() )
		return;

	std::vector< char > mbs( src.length() * MB_CUR_MAX + 1 );

	wcstombs(&mbs[0], src.c_str(), src.length() * MB_CUR_MAX + 1);
	dst = &mbs[0];
}

//! ワイド文字列からマルチバイト文字列
//! ロケール依存
inline std::string String::ToMultiByte(const std::wstring &src)
{
	std::string dst;
	ToMultiByte( src , dst );
	return dst;
}


//! マルチバイト文字列からワイド文字列
//! ロケール依存
inline void String::ToUnicode(const std::string &src, std::wstring &dst)
{
	if( src.empty() )
		return;

	std::vector< wchar_t > wcs( src.length() + 1 );
	mbstowcs(&wcs[0], src.c_str(), src.length() + 1);
	dst = &wcs[0];
}

//! マルチバイト文字列からワイド文字列
//! ロケール依存
inline std::wstring String::ToUnicode(const std::string &src)
{
	std::wstring dst;
	ToUnicode( src , dst );
	return dst;
}


//! トリム(半角空白, タブのみ)
inline void String::Trim(std::string& s)
{
	Trim(s, " \t\r\n");
}

//! 指定文字のトリム. 文字列両端の括弧の除去などに使用する.
inline void String::Trim(std::string& s, const char* pattern)
{
	typedef std::string::size_type size_type;

	size_type p1 = s.find_first_not_of( pattern );
	if(p1 == std::string::npos)
	{
		s.clear();
		return;
	}

	size_type p2 = s.find_last_not_of(pattern);
	s = s.substr(p1, p2 - p1 + 1);
}


}
