Linux/gcc에서 CStringA MFC Class 사용하기
CStringA는 MFC/ATL Class로, gcc를 사용하는 Linux에서는 컴파일할 수 없습니다. 그래서 만일, CStringA 기반으로 작성된 코드를 Linux에서 compile하려면, 추가 - 작업 - 이 필요할 수 있습니다. 이러한 불편을 줄이고자, LinuxCStringA.h를 공유(GPL 3.0, No commercial)로 공유합니다. (상업적 용도로 사용시, 댓글로 요청 바람. 큰 이견 없다면 사용 허락 부여함)
현재 CStringA, 즉, char만 허용되는데, wchar_t 즉, WCHAR에 해당되는 CString은 지원하지 않았습니다. 왜냐하면, wchar_t가 Windows/Linux의 크기가 달라, 자칫 one-source로 compile은 되더라도, 혹시나 모를 실행시의 이슈가 발생할 소지가 있기 때문입니다. 그래서, one-source로 CString을 사용하려면, ANSI만 사용하라, 라고 강제화 시킨 겁니다(사실, Windows에서는 MBCS, Linux에서는 UTF-8이 사용되겠지만서도요...).
std string으로 CStringA를 흉내낸 것인데, 주로 사용하는 CStringA 함수만 추가하였습니다. 혹시나, AppendFormat등을 사용하셨다면, 직접 구현하셔야 할 겁니다. 미리 만들어놓은 틀이 있으니, 수정하는데에는 큰 어려움은 없을 것으로 보여집니다.
std string으로 흉내낸 것이라 했는데, 이는, Windows에서도 사용 가능하다라는 말도 됩니다. LinuxCStringA에서 _MSC_VER를 체크하여, Windows라면 <atlstr.h>를 include하고 종료하는데, 만일, ATL/MFC를 사용하지 않고, std만 가지고 코딩하시는 경우에는, 해당 line을 주석처리하면 해결되리라 봅니다.
LinuxCStringA.zip은 Visual Studio Project인데, linux에서는,
$ g++ stl_string.cpp |
와 같이 compile하면 되며,
$ ./a.out |
와 같이 Windows(ATL의 CStringA), Linux(LinuxCStringA.h) 모두 동일한 결과가 나왔음을 확인하였습니다.
사용은,
#include "LinuxCStringA.h" ... CStringA strTmp; ... |
와 같이 사용하면 되며, Windows/Linux 관련없이 CStringA를 사용할 수 있습니다.
앞서 얘기한바대로, 해당 .h은 GPL 3.0 with no commercial이니, 주의하시기 바랍니다.
Source
#pragma once
/*
http://www.gnu.org/licenses/gpl-3.0.html
LinuxCStringA, LinuxCStringA.h
Copyright (C) 2015-11-24 greenfish @ gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
And,
No Commercial only,
If you want to use it commercially, contact to author.
*/
#ifdef _MSC_VER
// VC로 compile하는 경우에는 CAtlStringA, 즉, CStringA를 사용하도록 한다.
#include <atlstr.h>
#else
// gcc로 compile하는 경우에는 아래 Class를 참고하도록 한다.
#include <string>
#include <vector>
#include <string.h>
#include <stdarg.h>
#include <stdio.h>
class CStringA
{
public:
CStringA(void) { };
~CStringA(void) { };
public:
CStringA(const CStringA& obj) {m_str = obj.m_str;}
void operator=(const CStringA& obj) {m_str = obj.m_str;}
void operator=(const char* p) {if (NULL != p) m_str = p;}
CStringA& operator+=(const char* p) {if (NULL != p) m_str += p; return (*this);}
friend CStringA operator+(const CStringA& str1, const char* psz2 )
{CStringA r; r.m_str=str1.m_str; if (NULL != psz2) {r.m_str = r.m_str + psz2;} return r;}
bool operator==(const char* p) {return (m_str.compare(p) == 0);}
operator const char*() {return m_str.c_str();}
int GetLength(void) {return m_str.length();}
bool IsEmpty() {return(GetLength()==0);}
int Find(const char* pszSub, int iStart=0) {if (NULL == pszSub) return -1; return m_str.find(pszSub, iStart);}
int Find(const char ch, int iStart=0) {return m_str.find(ch, iStart);}
CStringA Mid(int iFirst, int nCount)
{
CStringA r;
try
{
r.m_str = m_str.substr(iFirst, nCount);
}
catch(...)
{
}
return r;
}
CStringA Mid(int iFirst)
{
CStringA r;
try
{
r.m_str = m_str.substr(iFirst);
}
catch(...)
{
}
return r;
}
int Delete(int iIndex, int nCount = 1)
{
try
{
m_str.erase(iIndex, nCount);
}
catch(...)
{
}
return m_str.length();
}
int Insert(int iIndex, const char* psz)
{
try
{
if (NULL != psz) m_str.insert(iIndex, psz);
}
catch(...)
{
m_str += psz;
}
return m_str.length();
}
int Insert(int iIndex, char ch)
{
try
{
m_str.insert(iIndex, 1, ch);
}
catch(...)
{
m_str += ch;
}
return m_str.length();
}
CStringA& TrimRight(char chTarget)
{
size_t l = 0;
l = m_str.length();
for (;;)
{
if (0 == l) break;
if (m_str[l-1] != chTarget)
{
break;
}
else
{
m_str.erase(l-1, 1);
l--;
}
}
return (*this);
}
CStringA& TrimRight(const char* pszTargets)
{
size_t l = 0;
if (NULL == pszTargets) return (*this);
l = m_str.length();
for (;;)
{
if (0 == l) break;
if (NULL == strchr(pszTargets, m_str[l-1]))
{
break;
}
else
{
m_str.erase(l-1, 1);
l--;
}
}
return (*this);
}
CStringA& TrimLeft(char chTarget)
{
for (;;)
{
if (m_str[0] != chTarget)
{
break;
}
else
{
m_str.erase(0, 1);
}
}
return (*this);
}
CStringA& TrimLeft(const char* pszTargets)
{
if (NULL == pszTargets) return (*this);
for (;;)
{
if (NULL == strchr(pszTargets, m_str[0]))
{
break;
}
else
{
m_str.erase(0, 1);
}
}
return (*this);
}
int Replace(const char* pszOld, const char* pszNew)
{
int r = 0;
size_t l = 0;
std::string::size_type offset = 0;
if ((NULL == pszOld) || (NULL == pszNew)) return 0;
for (;;)
{
offset = m_str.find(pszOld, offset);
if (std::string::npos == offset)
{
break;
}
else
{
if (0 == l)
{
l = strlen(pszOld);
if (0 == l) return 0;
}
m_str.replace(offset, l, pszNew);
offset += l;
r++;
}
}
return r;
}
void Format(const char* pszFormat, ...)
{
int len = 0;
va_list vl;
va_start(vl, pszFormat);
// 포맷의 길이를 구한다.
#if (_MSC_VER >= 1400) // Visual studio 2005 이상
len = _vscprintf(pszFormat, vl) + 1;
#else
len = vsnprintf(NULL, 0, pszFormat, vl) + 1;
#endif
// 버퍼의 크기를 조정한다.
m_str.resize(len, '\0');
// 포맷을 적용한다.
va_start(vl, pszFormat);
#if (_MSC_VER >= 1400) // Visual studio 2005 이상
if (vsnprintf_s(&m_str[0], len, _TRUNCATE, pszFormat, vl) > len)
#else
if (vsnprintf(&m_str[0], len, pszFormat, vl) > len)
#endif
{
// Error
}
va_end(vl);
}
protected:
std::string m_str;
};
#endif |