#include "MyStringUtils.h"
#include <regex>


#include "windows.h"
#include <stringapiset.h>
string MyStringUtils::UTF8ToGBK(const std::string strUTF8)
{
	int len = MultiByteToWideChar(CP_UTF8, 0, strUTF8.c_str(), -1, NULL, 0);
	WCHAR* wszGBK = new WCHAR[len + 1];
	memset(wszGBK, 0, len * 2 + 2);
	MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)(LPCTSTR)strUTF8.c_str(), -1, wszGBK, len);

	len = WideCharToMultiByte(CP_ACP, 0, wszGBK, -1, NULL, 0, NULL, NULL);
	char* szGBK = new char[len + 1];
	memset(szGBK, 0, len + 1);
	WideCharToMultiByte(CP_ACP, 0, wszGBK, -1, szGBK, len, NULL, NULL);
	std::string strTemp(szGBK);
	delete[]szGBK;
	delete[]wszGBK;
	return strTemp;
}

string MyStringUtils::GBKToUTF8(const std::string szGbk)
{
#if false
	int len = MultiByteToWideChar(CP_ACP, 0, szGbk.c_str(), -1, NULL, 0);
	if (len == 0) return "";

	WCHAR* wstr = new WCHAR[len];
	if (wstr == nullptr) return "";
	MultiByteToWideChar(CP_ACP, 0, szGbk.c_str(), -1, wstr, len);
	len = WideCharToMultiByte(CP_UTF8, 0, wstr, -1, NULL, 0, NULL, NULL);
	char* szUtf8 = new char[len + 1];
	WideCharToMultiByte(CP_UTF8, 0, wstr, -1, szUtf8, len, NULL, NULL);
	std::string strTemp(szUtf8);
	delete[] wstr;
	delete[] szUtf8;
	return strTemp;
#endif
	return szGbk;
}

void MyStringUtils::split(std::vector<std::string>& vecLine, const std::string& str, const std::string& delim /*= "\n"*/)
{
	vecLine.clear();

	size_t pos = 0;
	size_t len = str.length();
	size_t delim_len = delim.length();
	if (delim_len == 0) return;
	while (pos < len)
	{
		int find_pos = (int)str.find(delim, pos);
		if (find_pos < 0)
		{
			vecLine.push_back(str.substr(pos, len - pos));
			break;
		}
		string tempString = str.substr(pos, find_pos - pos);
		vecLine.push_back(tempString);
		pos = find_pos + delim_len;
	}

	return;
}

void MyStringUtils::toUpper(std::string& str)
{
	transform(str.begin(), str.end(), str.begin(), ::toupper);
}

void MyStringUtils::toLower(std::string& str)
{
	transform(str.begin(), str.end(), str.begin(), ::tolower);
}

std::string& MyStringUtils::trim(std::string& str, const std::string& strTrim)
{
	if (str.empty())
	{
		return str;
	}

	str.erase(0, str.find_first_not_of(strTrim));
	str.erase(str.find_last_not_of(strTrim) + 1);
	return str;
}

std::string MyStringUtils::replace(std::string& str, std::string strOld, std::string strNew)
{
	std::string::size_type pos = 0;
	while ((pos = str.find(strOld)) != std::string::npos)
	{
		str.replace(pos, strOld.length(), strNew);
	}
	return str;
}

unsigned long MyStringUtils::toLong(std::string& strCount, int nType /* = 10 */)
{
	std::string str = strCount;
	trim(str);

	return (unsigned long)(strtoul(str.c_str(), NULL, nType));
}

int MyStringUtils::toInt(std::string& strCount)
{
	return atoi(strCount.c_str());
}

std::string MyStringUtils::toString(unsigned char* buffer, int len)
{
	if (len <= 0)
	{
		return "";
	}

	char* str_buffer = new char[len * 3 + 1];
	memset(str_buffer, 0, sizeof(str_buffer));

	for (int i = 0; i < len; i++) {
		sprintf(str_buffer + i * 3, "%02X ", buffer[i]);
	}

	string strBuffer = str_buffer;

	delete[] str_buffer;

	return strBuffer;
}

std::string MyStringUtils::toString(unsigned int nValue)
{
	char buffer[32] = { 0 };
	sprintf(buffer, "%04X", nValue);

	std::string str(buffer);
	return str;
}

std::string MyStringUtils::toString(int nValue, int radix)
{
	char buffer[32] = { 0 };
	if (radix == 16)
		sprintf(buffer, "%04X", nValue);
	else
		sprintf(buffer, "%d", nValue);

	std::string str(buffer);
	return str;
}

std::string MyStringUtils::toString(uint8_t nValue)
{
	char buffer[32] = { 0 };
	sprintf(buffer, "%02d", nValue);

	std::string str(buffer);
	return str;
}

void MyStringUtils::CutOut(std::string& strCount, const std::string& strCut)
{
	if (strCount.find(strCut) != string::npos)
	{
		strCount = strCount.substr(0, strCount.find(strCut));
	}
}

int MyStringUtils::SplitStringByRegExp(const std::string& str, std::vector<std::string>& vecLine, const std::string& reg)
{
	vecLine.clear();

	std::smatch m;
	std::regex regexStr(reg);
	string::const_iterator citer = str.cbegin();
	while (std::regex_search(citer, str.cend(), m, regexStr))
	{
		std::string preStr = m.prefix().str();
		if (preStr.length() > 0) {
			vecLine.push_back(preStr);
		}
		citer = m[0].second;
	}

	std::string last_str = "";
	while (citer != str.cend())
	{
		last_str.push_back(*citer);
		citer++;
	}
	if (last_str.length() > 0) {
		vecLine.push_back(last_str);
	}

	return (int)vecLine.size();
}

void MyStringUtils::BufferToString(std::string& strLog, unsigned char* buff, int len, unsigned char type)
{
	strLog = "";

	int nDataSize = 4 + len * 3 + 1;
	char* str = new char[nDataSize];
	memset(str, '\0', nDataSize);

	strcpy(str, type == 0 ? "REQ=" : "RES=");
	for (int i = 0; i < len; i++)
		sprintf(str + 4 + i * 3, "%.2X ", buff[i]);

	strLog = str;
	delete[] str;
}

bool MyStringUtils::startWith(const std::string& str, std::string prefix)
{
	if (str.compare(0, prefix.length(), prefix) == 0) {
		return true;
	}
	return false;
}

bool MyStringUtils::endWith(const std::string& str, std::string suffix)
{
	size_t len_str = str.length();
	size_t len_suffix = suffix.length();

	if (len_suffix > len_str) {
		return false;
	}

	if (str.compare(len_str - len_suffix, len_suffix, suffix) == 0) {
		return true;
	}
	return false;
}

std::string MyStringUtils::desensitize(std::string& str, int plainLen)
{
	if (str.length() <= 2 * plainLen) {

		return str;
	}
	else {
		for (int i = plainLen; i < str.length() - plainLen; i++) {
			str.replace(i, 1, "*");
		}
	}

	return str;;
}

bool MyStringUtils::radix_array2Hex(uint8_t* inParams, int inLen, string& str, const std::string strHold)
{
	int ret = true;

	const size_t perWidth = 2 + strHold.length();
	char* outBuffer = (char*)malloc(inLen * perWidth);
	memset(outBuffer, 0, inLen * perWidth);

	for (size_t i = 0; i < inLen; i++)
	{
		uint8_t highByte = inParams[i] >> 4;
		uint8_t lowByte = inParams[i] & 0x0F;

		if (highByte >= 0x0A && highByte <= 0x0F)
			outBuffer[perWidth * i] = 'A' + highByte - 10;
		else if (highByte >= 0x00 && highByte <= 0x09)
			outBuffer[perWidth * i] = '0' + highByte;
		else {
			ret = false;
			break;
		}

		if (lowByte >= 0x0A && lowByte <= 0x0F)
			outBuffer[perWidth * i + 1] = 'A' + lowByte - 10;
		else if (lowByte >= 0x00 && lowByte <= 0x09)
			outBuffer[perWidth * i + 1] = '0' + lowByte;
		else {
			ret = false;
			break;
		}

		if ((perWidth > 2) && (i < inLen - 1)) {
			memcpy(&outBuffer[perWidth * i + 2], strHold.c_str(), strHold.length());
		}
	}

	if (ret) {
		str.assign(outBuffer, (inLen * perWidth - strHold.length()));
	}
	free(outBuffer);
	return ret;
}
