#include "stdafx.h"
#include "utils.h"

namespace utils
{
    const unsigned short CRC16_TABLE[16] = {
    0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50A5, 0x60C6, 0x70E7,
    0x8108, 0x9129, 0xA14A, 0xB16B, 0xC18C, 0xD1AD, 0xE1CE, 0xF1EF
    };

    std::string& trim(std::string& str)
    {
#if _MSC_VER >= 1200 && _MSC_VER < 1600
        for (std::string::iterator it = str.begin(); it != str.end();) {
            !isspace(*it) ? it++ : it = it = str.erase(it);
        }
#elif _MSC_VER >= 1600
        str.erase(std::remove_if(str.begin(), str.end(), [](unsigned char x) {return std::isspace(x); }), str.end()); //C++17
#endif
        return str;
    }

    std::string _dprintf(CHAR* pszStr, ...)
    {
        const int LOGLEN = 8912;
        char szData[LOGLEN] = { 0 };
#if _MSC_VER >= 1200 && _MSC_VER < 1500
        sprintf(szData, _T("[%s %s]\n\t"), _T("Db"), CTime::GetCurrentTime().Format(_T("%H:%M:%S")));
#elif _MSC_VER >= 1500
        _stprintf_s(szData, _T("[%s %s]\n\t"), _T("Db"), CTime::GetCurrentTime().Format(_T("%H:%M:%S")).GetString());
#endif
        int len = strlen(szData);
        va_list args;
        va_start(args, pszStr);
#if _MSC_VER >= 1200 && _MSC_VER < 1500
        _vsnprintf(szData + len, LOGLEN - len, pszStr, args);
#elif _MSC_VER >= 1500
        _vsntprintf_s(szData + len, LOGLEN - len, _TRUNCATE, pszStr, args);
#endif
        va_end(args);
        if (szData[strlen(szData) - 1] != '\n')
#if _MSC_VER >= 1200 && _MSC_VER < 1500
            strcat(szData, "\n");
#elif _MSC_VER >= 1500
            strcat_s(szData, "\n");
#endif
        OutputDebugStringA(szData);

        return std::string(szData);
    }

    std::string ByteToChars(byte b)
    {
        char szhex[3] = { 0 };

#if _MSC_VER >= 1200 && _MSC_VER < 1500
        sprintf(szhex, "%02X", b);
#elif _MSC_VER >= 1500
        _stprintf_s(szhex, "%02X", b);
#endif

        return std::string(szhex);
    }

    BOOL IsValidString(LPCTSTR lpszString)
    {
        if (lpszString == NULL)
            return FALSE;

        do {
            // ASCII����ʾ���ַ�;
            if (*lpszString < 32 || *lpszString > 126) {
                return FALSE;
            }
        } while (*++lpszString);

        return TRUE;
    }

    unsigned char TwoHexCharToInteger(char high, char low)
    {
        std::string str = "0123456789AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz";
        if (str.find_first_of(high) == std::string::npos || str.find_first_of(low) == std::string::npos)
        {
            return 0;
        }

        char Numb1 = high >= 'A' ? (toupper(high) - '0' - 7) * 16 : (high - '0') * 16;
        char Numb2 = low >= 'A' ? (toupper(low) - '0' - 7) : (low - '0');

        return (Numb1 + Numb2);
    }

    std::string BytesToHexString(const unsigned char* pbuffer, int nLen)
    {
        std::string hex;
        char szhex[5] = { 0 };
        for (int i = 0; i < nLen; i++)
        {
            memset(szhex, 0, 5);

#if _MSC_VER >= 1200 && _MSC_VER < 1500
            sprintf(szhex, "%02X", pbuffer[i]);
#elif _MSC_VER >= 1500
            _stprintf_s(szhex, "%02X", pbuffer[i]);
#endif
            hex.append(szhex);
        }

        return hex;
    }

    std::string BytesToHexString(const unsigned char* pbuffer, int nLen, char chSpace)
    {
        std::string hex;
        char szhex[5] = { 0 };
        for (int i = 0; i < nLen; i++)
        {
            memset(szhex, 0, 5);
#if _MSC_VER >= 1200 && _MSC_VER < 1500
            sprintf(szhex, "%02X%c", pbuffer[i], chSpace);
#elif _MSC_VER >= 1500
            _stprintf_s(szhex, "%02X%c", pbuffer[i], chSpace);
#endif
            hex.append(szhex);
        }

        return hex.substr(0, hex.size() - 1);
    }

    std::string HexStringToBytes(std::string strHex, const int& len)
    {
        byte value = 0;
        std::string strBytes;
        int nSize = strHex.size();
        for (int i = 0; i < nSize; i += len)
        {
#if _MSC_VER >=1200 && _MSC_VER < 1500
            strBytes.append((char)TwoHexCharToInteger(strHex[i], strHex[i + 1]), 1);
#elif _MSC_VER >=1500
            strBytes.push_back((char)TwoHexCharToInteger(strHex[i], strHex[i + 1]));
#endif
        }

        return strBytes;
    }

    unsigned short CRC16Calculate(byte* pBuffer, unsigned int wordLength)
    {
        byte byteTemp(0);
        unsigned short wordCRC(0);

        wordCRC = 0xFFFF;
        while (wordLength--) {
            byteTemp = (byte)(wordCRC >> 0x0C);
            wordCRC <<= 4;
            wordCRC ^= CRC16_TABLE[byteTemp ^ ((*pBuffer) >> 0x04)];
            byteTemp = (byte)(wordCRC >> 0x0C);
            wordCRC <<= 4;
            wordCRC ^= CRC16_TABLE[byteTemp ^ ((*pBuffer) & 0x0F)];
            pBuffer++;
        }

        return wordCRC;
    }

    bool GetResourceData(DWORD dwResourceID, LPCTSTR lpExt, std::string &rtnData)
    {
        HGLOBAL hGlobal = NULL;
        HRSRC   hSource = NULL;
        LPVOID  lpBuffer = NULL;
        DWORD   dwSize = 0;
        BOOL    bResult = FALSE;

        // 1.������Դ,���û�ҵ�����Null
        hSource = FindResource(NULL, MAKEINTRESOURCE(dwResourceID), lpExt);
        if (hSource == NULL) {
            _dprintf(_T("������Դʧ��:%s,ID=%d"), lpExt, dwResourceID);
            return false;
        }

        // 2.��ȡ��Դ��С;
        dwSize = (UINT)SizeofResource(NULL, hSource);

        // 3.������Դ;
        hGlobal = LoadResource(NULL, hSource);
        if (hGlobal == NULL) {
            _dprintf(_T("������Դʧ��:%s,ID=%d"), lpExt, dwResourceID);
            return false;
        }

        // 4.��ȡ��buffer��;
        lpBuffer = LockResource(hGlobal);
        if (lpBuffer == NULL) {
            _dprintf(_T("������Դʧ��:%s,ID=%d"), lpExt, dwResourceID);
            return false;
        }

#if _MSC_VER >=1200 && _MSC_VER < 1500
		rtnData = "";
#elif _MSC_VER >= 1500
        rtnData.clear();
#endif
        rtnData.append((char*)lpBuffer, dwSize);

        // �ͷ���Դ;
        UnlockResource(hGlobal);
        FreeResource(hGlobal);

        return true;
    }
}