본문 바로가기

Windows/MFC

CStringConvert 7bit alphabet

[code]// DATE        : April 6, 2007
// CODER    : aucd29 (aucd29@gmail.com)
//
//
//
// --------------------------------------------------------
// NOTE : April 09, 2007
// --------------------------------------------------------
// * 7BIT UNICODE -> 7BIT ASCII -> UCS2 변경
//

#include "StdAfx.h"
#include "StringConvert.h"

// --------------------------------------------------------
// 7Bit Ascii Table
// --+---+---+----+----+---+---+---+---+---+---+---+---+---
// | | |    | B7 | 0 | 0 | 0 | 0 | 1 | 1 | 1 | 1 |
// | | |    | B6 | 0 | 0 | 1 | 1 | 0 | 0 | 1 | 1 |
// | | |    | B5 | 0 | 1 | 0 | 1 | 0 | 1 | 0 | 1 |
// --+---+---+----+----+---+---+---+---+---+---+---+---+
// B4| B3| B2| B1 |    | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
// --+---+---+----+----+---+---+---+---+---+---+---+---+
// 0 | 0 | 0 | 0 | 0 | @ | Δ| SP| 0 | - | P | | |
// --+---+---+----+----+---+---+---+---+---+---+---+---+
// 0 | 0 | 0 | 1 | 1 | | | ! | 1 | A | Q | a | p |
// --+---+---+----+----+---+---+---+---+---+---+---+---+
// 0 | 0 | 1 | 0 | 2 | $ | Φ| " | 2 | B | R | b | q |
// --+---+---+----+----+---+---+---+---+---+---+---+---+
// 0 | 0 | 1 | 1 | 3 | | Γ| # | 3 | C | S | c | r |
// --+---+---+----+----+---+---+---+---+---+---+---+---+
// 0 | 1 | 0 | 0 | 4 | | Λ| | 4 | D | T | d | s |
// --+---+---+----+----+---+---+---+---+---+---+---+---+
// 0 | 1 | 0 | 1 | 5 | | Ω| % | 5 | E | U | e | t |
// --+---+---+----+----+---+---+---+---+---+---+---+---+
// 0 | 1 | 1 | 0 | 6 | | Π| & | 6 | F | V | f | u |
// --+---+---+----+----+---+---+---+---+---+---+---+---+
// 0 | 1 | 1 | 1 | 7 | | Ψ| ' | 7 | G | W | g | v |
// --+---+---+----+----+---+---+---+---+---+---+---+---+
// 1 | 0 | 0 | 0 | 8 | | Σ| ( | 8 | H | X | h | w |
// --+---+---+----+----+---+---+---+---+---+---+---+---+
// 1 | 0 | 0 | 1 | 9 | | Θ| ) | 9 | I | Y | i | x |
// --+---+---+----+----+---+---+---+---+---+---+---+---+
// 1 | 0 | 1 | 0 | 10 | LF| Ξ| * | : | J | Z | j | y |
// --+---+---+----+----+---+---+---+---+---+---+---+---+
// 1 | 0 | 1 | 1 | 11 | | | + | ; | K | | k | z |
// --+---+---+----+----+---+---+---+---+---+---+---+---+
// 1 | 1 | 0 | 0 | 12 | | | , | < | L | | l | |
// --+---+---+----+----+---+---+---+---+---+---+---+---+
// 1 | 1 | 0 | 1 | 13 | CR| | - | = | M | | m | |
// --+---+---+----+----+---+---+---+---+---+---+---+---+
// 1 | 1 | 1 | 0 | 14 | | β| . | > | N | | n | |
// --+---+---+----+----+---+---+---+---+---+---+---+---+
// 1 | 1 | 1 | 1 | 15 | | | / | ? | O | | o | |
// --+---+---+----+----+---+---+---+---+---+---+---+---+
//


CStringConvert::CStringConvert(void)
: m_bChanged(false)
{
    m_mapBinaryTable[L'0'] = 0x00;
    m_mapBinaryTable[L'1'] = 0x01;
    m_mapBinaryTable[L'2'] = 0x02;
    m_mapBinaryTable[L'3'] = 0x03;
    m_mapBinaryTable[L'4'] = 0x04;
    m_mapBinaryTable[L'5'] = 0x05;
    m_mapBinaryTable[L'6'] = 0x06;
    m_mapBinaryTable[L'7'] = 0x07;
    m_mapBinaryTable[L'8'] = 0x08;
    m_mapBinaryTable[L'9'] = 0x09;
    m_mapBinaryTable[L'A'] = 0x0A;
    m_mapBinaryTable[L'B'] = 0x0B;
    m_mapBinaryTable[L'C'] = 0x0C;
    m_mapBinaryTable[L'D'] = 0x0D;
    m_mapBinaryTable[L'E'] = 0x0E;
    m_mapBinaryTable[L'F'] = 0x0F;

    // 특수문자는 유니코드변환시 약간 번호가 다르니깐
    // 따로 값을 주고 나머진 바로 변환 가능하다.
    m_map7bitToUnicode[0x00] = L'@';
    m_map7bitToUnicode[0x02] = L'$';
    m_map7bitToUnicode[0x10] = L'Δ';
    m_map7bitToUnicode[0x12] = L'Φ';
    m_map7bitToUnicode[0x13] = L'Γ';
    m_map7bitToUnicode[0x14] = L'Λ';
    m_map7bitToUnicode[0x15] = L'Ω';
    m_map7bitToUnicode[0x16] = L'Π';
    m_map7bitToUnicode[0x17] = L'Ψ';
    m_map7bitToUnicode[0x18] = L'Σ';
    m_map7bitToUnicode[0x19] = L'Θ';
    m_map7bitToUnicode[0x1A] = L'Ξ';
    m_map7bitToUnicode[0x1E] = L'β';
}

CStringConvert::CStringConvert(CString szData)
: m_szText(szData)
{
    
}

CStringConvert::~CStringConvert(void)
{

}

void CStringConvert::Trace(void)
{
    TRACE(L"-----------------------------------------------------\n");
    TRACE(L"| CStringConvert                                    |\n");
    TRACE(L"-----------------------------------------------------\n");
    TRACE(m_szText + L"\n");
    TRACE(L"-----------------------------------------------------\n");
}

// Operator -----------------------------------------------------

void CStringConvert::operator = (CString szData)
{
    m_szText = szData;
}

CString CStringConvert::PC2SerialUnicode(void)
{
    // serial로 보낼 unicode형식에 string을 만들자.
    //
    CString szTemp = m_szText;
    wchar_t* pStr = const_cast<wchar_t*>(static_cast<LPCTSTR>(szTemp));
    wchar_t wString[5] = {0};
    m_szText = L"";
    
    while (*pStr)
    {
        wsprintf(wString, L"%04x", *pStr);
        m_szText += wString;
        pStr++;
    }

    return m_szText;
}

CString CStringConvert::PC2Serial7Bit(void)
{
    // serial로 보낼 7bit 형식에 string을 만든다.
    //
    wchar_t* pStr = const_cast<wchar_t*>(static_cast<LPCTSTR>(m_szText));
    int nLength     = m_szText.GetLength();
    int nIndex     = 0;
    m_strText     = new unsigned char[nLength + 1];
    memset(m_strText, 0, nLength + 1);

    // 8bit style로 구성
    while (nLength--)
    {
        m_strText[nIndex] = IsSpecialCharacter(pStr);

        if (!m_bChanged)
        {
            m_strText[nIndex] = static_cast<char>(*pStr);
        }

        m_bChanged = false;
        ++pStr;
        ++nIndex;
    }

    // 7bit style로 구성
    list<unsigned char> m_listTemp;
    unsigned char cTemp = 0;
    unsigned char* pPrePosition;
    unsigned char* pThisPosition;
    int nShift = 0;
    
    nLength = m_szText.GetLength() + 1;
    pPrePosition = pThisPosition = m_strText;
    
    while (nLength--)
    {        
        cTemp             = *pThisPosition;
        *pThisPosition >>= nShift;
        cTemp            <<= (8 - nShift);
        *pPrePosition    |= cTemp;

        if (++nShift == 8)
        {
            nShift = 0;
        }

        pPrePosition = pThisPosition;
        pThisPosition++;
    }

    nLength         = m_szText.GetLength();
    pThisPosition = m_strText;
    CString szFormat;
    m_szText = L"";
    while (nLength--)
    {
        // 0 값은 제외 시키기 위해서
        if (*pThisPosition)
        {
            szFormat.Format(L"%02x", *pThisPosition);
            m_szText += szFormat;
        }
        pThisPosition++;
    }

    delete m_strText;
    return m_szText;
}

CString CStringConvert::Serial2PCUnicode(void)
{
    // serial로 받은 unicode 형식(0045) 에 string을
    // 문자로 바꾸자
    //
    int nLen = m_szText.GetLength();
    int nWord = nLen / 4;
    int nFirst = 0, i = 0;
    long N;
    wchar_t szDumy[7] = {0};

    m_wstrText = new wchar_t[nWord + 1];
    memset(m_wstrText, 0, sizeof(wchar_t) * (nWord + 1));
    do
    {
        wsprintf(szDumy, L"0x%s", m_szText.Mid(nFirst, 4));
        swscanf_s(szDumy, L"%x", &N);
        wsprintf(&m_wstrText[i++], L"%c", N);
        memset(szDumy, 0, sizeof(wchar_t) * 7);

        nFirst += 4;
    }
    while(--nWord);
    m_wstrText[i] = 0;
    m_szText.Format(L"%s", m_wstrText);
    delete m_wstrText;

    return m_szText;
}

CString CStringConvert::Serial2PC7Bit(void)
{
    // serial로 받은 7bit 문자를 일반 문자로
    // 바꾸자.

    // E8 : 11101000
    // 32 : 00110010
    // 9B : 10011011
    // FD : 11111101
    // 46 : 01000110
    // 97 : 10010111
    // D9 : 11011001
    // EC : 11101100
    // 37 : 110111

    // 1 1101000            7
    // 00 110010            6
    // 100 11011            5
    // 1111 1101            4
    // 01000 110            5
    // 100101 11            2
    // 1101100 1100101        1
    // 1 1101100
    // 11 0111

    // H 1101000
    // E 1100101
    // L 1101100
    // L 1101100
    // O 1101111
    // H 1101000
    // E 1100101
    // L 1101100
    // L 1101100
    // O 1101111

    // MFC에서는 좀 특수한 상황이라 -_ -;;
    // 영 ㅈㄹ같군...
    // 우선은 UNICODE 로 들어온 7BIT GSM 코드를
    // ASCII 로 변경하고 이후에 8BIT ASCII로 변경하고
    // 8BIT ASCII를 다시 -_ - UNICODE로 변경해야된다..
    // 한마디로... 미치겠다 -_-

    // wchar_t 로 type casting 했으니 이제 손쉽게 jump
    int nStrLength = (m_szText.GetLength() / 2) + 1;    // terminate를 위해 + 1
    bool bFirst        = true;
    wchar_t* pPos = const_cast<wchar_t*>(static_cast<LPCTSTR>(m_szText));        
    unsigned char* p7bitCode = new unsigned char[nStrLength];
    unsigned char* pJump = p7bitCode;
    memset(p7bitCode, 0, nStrLength);

    while(*pPos)
    {
        if (bFirst)
        {
            // left shift 4bit
            //TRACE(L"INDEX CODE :%c ", *pPos);
            //TRACE(L"RETURN VALUE : %x ", m_mapBinaryTable[*pPos]);
            *pJump = m_mapBinaryTable[*pPos] << 4;
            //TRACE(L"VALUE : %x\n", *pJump);
        }
        else
        {    
            //TRACE(L"INDEX CODE :%c ", *pPos);
            //TRACE(L"RETURN VALUE : %x ", m_mapBinaryTable[*pPos]);
            *pJump |= m_mapBinaryTable[*pPos];
            //TRACE(L"VALUE : %x\n", *pJump);
            pJump++;
        }
        pPos++;
        bFirst = !bFirst;
    }
    *pJump = 0;

    // 자 여기까지 7bit ascii 코드 완성
    // 이제부턴 8bit ascii 코드를 맹글어야 하는데 말이지...

    // jump code를 초기화 시키고
    pJump = p7bitCode;
    unsigned char pTemp = 0, pTemp2 = 0;
    int nShift = 7;
    list<unsigned char> listTempCharacter;
    while (*pJump)
    {
        // copy data
        //pTemp = *pJump;                        // E8 : 1110 1000, 32 : 0011 0010
        pTemp    = *pJump >> nShift;            // E8 : 0000 0001, 32 : 0000 0000
        *pJump <<= (8 - nShift);                // E8 : 1101 0000, 32 : 1100 1000
        *pJump >>= 1;                            // E8 : 0110 1000, 32 : 0011 0010
        *pJump |= pTemp2;                        //     0110 1000, 32 : 0011 0011
        
        listTempCharacter.push_back(*pJump);
        pJump++;
        
        if (--nShift == 0)
        {
            nShift = 7;
            listTempCharacter.push_back(pTemp);
            pTemp2 = 0;
        }
        else
        {
            pTemp2 = pTemp;                        // E8 : 0000 0001
        }
    }    
    delete p7bitCode;

    list<unsigned char>::iterator it;
    nStrLength = static_cast<int>(listTempCharacter.size());
    it         = listTempCharacter.begin();

    wchar_t wTemp;
    while (nStrLength--)
    {
        // 해당 테이블에 값이 있으면 그 값을 넣어주고
        // 없다면 casting 한다.
        if (wTemp = m_map7bitToUnicode[*it])
        {
            m_szText.AppendChar(wTemp);
        }
        else
        {
            m_szText.AppendChar(static_cast<wchar_t>(*it));
        }

        it++;
    }

    return m_szText;
}

void CStringConvert::UniToChar(char* pStr, int nLen)
{
    memset(pStr, 0, nLen);
    WideCharToMultiByte(CP_ACP, 0, m_szText, -1, pStr, nLen, NULL, NULL);
}

void CStringConvert::CharToUni(char* szSrc)
{
    int nLen = static_cast<int>(strlen(szSrc));
    wchar_t* m_wstrText = new wchar_t[nLen];

    memset(m_wstrText, 0, sizeof(wchar_t) * nLen);
    MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, szSrc, nLen, m_wstrText, nLen);
    m_szText.Format(L"%s", szSrc);

    delete m_wstrText;
}

unsigned char CStringConvert::IsSpecialCharacter(wchar_t* pwCharacter)
{
    map<unsigned char, wchar_t>::iterator it = m_map7bitToUnicode.begin();
    int nLength = static_cast<int>(m_map7bitToUnicode.size());

    while (nLength--)
    {
        if (it->second == *pwCharacter)
        {
            m_bChanged = true;
            return it->first;
        }

        it++;
    }

    return false;
}
[/code]

[code]
#pragma once

#include <map>
#include <list>
using namespace std;

class CStringConvert
{
protected:
    CString m_szText;
    unsigned char* m_strText;
    wchar_t* m_wstrText;
    bool m_bStr, m_bWstr, m_bChanged;

    // 다소 부하가 있지만... 그렇다고
    // 더 나은 방법이 있는것도 아닌것이..
    map<wchar_t, unsigned char> m_mapBinaryTable;
    map<unsigned char, wchar_t> m_map7bitToUnicode;        // 어차피 난 출력은 unicode를 써야잖아.

public:
    CStringConvert(void);
    CStringConvert(CString szData);
    ~CStringConvert(void);
    void Trace(void);

    // operator
    void operator = (CString szData);

    CString PC2SerialUnicode(void);
    CString PC2Serial7Bit(void);
    CString Serial2PCUnicode(void);
    CString Serial2PC7Bit(void);
    void UniToChar(char* pStr, int nLen);
    void CharToUni(char* szSrc);
    unsigned char IsSpecialCharacter(wchar_t* pwCharacter);
};
[/code]

'Windows > MFC' 카테고리의 다른 글

CListCtrl OnNMClick  (0) 2013.10.02
CRichEditCtrl (Auto Scrolling)  (0) 2013.10.02
XmlLite  (0) 2013.10.02
WS_EX_APPWINDOW 윈도우를 작업표시줄(taskbar) 에 나타나지 않게 하기  (0) 2013.10.02
NMEA Parser  (0) 2013.10.02