Restructure repository to include all source folders

Move git root from Client/ to src/ to track all source code:
- Client: Game client source (moved to Client/Client/)
- Server: Game server source
- GameTools: Development tools
- CryptoSource: Encryption utilities
- database: Database scripts
- Script: Game scripts
- rylCoder_16.02.2008_src: Legacy coder tools
- GMFont, Game: Additional resources

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2025-11-29 20:17:20 +09:00
parent 5d3cd64a25
commit dd97ddec92
11602 changed files with 1446576 additions and 0 deletions

View File

@@ -0,0 +1,100 @@
#include "Nave.h"
#include "NFIni.h"
namespace Nave {
NFIni::NFIni()
{
ZeroMemory(m_szFileName, sizeof(m_szFileName));
}
NFIni::~NFIni()
{
}
BOOL NFIni::Open(LPCWSTR fileName)
{
if (!fileName)
return FALSE;
wcsncpy(m_szFileName, fileName, MAX_PATH);
return TRUE;
}
BOOL NFIni::Close()
{
return TRUE;
}
BOOL NFIni::GetValue(LPCWSTR keyName, LPCWSTR valueName, LPDWORD value)
{
if (!keyName || !valueName || !value)
return FALSE;
*value = GetPrivateProfileIntW(keyName, valueName, 0, m_szFileName);
return TRUE;
}
BOOL NFIni::GetValue(LPCWSTR keyName, LPCWSTR valueName, FLOAT *value)
{
if (!keyName || !valueName || !value)
return FALSE;
WCHAR Value[16] = {0,};
GetPrivateProfileStringW(keyName, valueName, L"", Value, 16, m_szFileName);
*value = (FLOAT)_wtof(Value);
return TRUE;
}
BOOL NFIni::GetValue(LPCWSTR keyName, LPCWSTR valueName, LPWSTR value, DWORD bufferLength)
{
if (!keyName || !valueName || !value || bufferLength == 0)
return FALSE;
GetPrivateProfileStringW(keyName, valueName, L"", value, bufferLength, m_szFileName);
return TRUE;
}
BOOL NFIni::SetValue(LPCWSTR keyName, LPCWSTR valueName, DWORD value)
{
if (!keyName || !valueName)
return FALSE;
WCHAR Value[16] = {0,};
_itow(value, Value, 10);
WritePrivateProfileStringW(keyName, valueName, Value, m_szFileName);
return TRUE;
}
BOOL NFIni::SetValue(LPCWSTR keyName, LPCWSTR valueName, LPCWSTR value)
{
if (!keyName || !valueName || !value)
return FALSE;
WritePrivateProfileStringW(keyName, valueName, value, m_szFileName);
return TRUE;
}
BOOL NFIni::SetValue(LPCWSTR keyName, LPCWSTR valueName, FLOAT value)
{
if (!keyName || !valueName)
return FALSE;
WCHAR Value[16] = {0,};
swprintf(Value, L"%f", value);
WritePrivateProfileStringW(keyName, valueName, Value, m_szFileName);
return TRUE;
}
}

View File

@@ -0,0 +1,103 @@
/**
* @file NFIni.h
* @brief INI 파일 관리자
* @remarks
* @author 강동명(edith2580@gmail.com)
* @date 2009-04-02
*/
#pragma once
namespace Nave {
/**
* @class NFIni
* @brief INI파일을 사용하기 쉽게 만든 관리 클래스
* @remarks NFIni ini; \r\n
* ini.Open(L"c:\\Init.ini"); \r\n
* ini.SetValue(L"SERVER CONFIG", L"PORT", dwPort); \r\n
* ini.Close(); \r\n
*
* @par
* @author Edith
* @date 2009-04-04
*/
class NFIni
{
public:
/// NFIni 생성자
NFIni();
/// NFIni 소멸자
~NFIni();
public:
/**
* @brief INI파일을 오픈합니다.
* @param fileName 파일명
* @return 성공여부
*/
BOOL Open(LPCWSTR fileName);
/**
* @brief INI파일을 종료합니다.
* @return 성공여부
*/
BOOL Close();
/**
* @brief INI파일에 값을 넣습니다.
* @param keyName Key 이름
* @param valueName Value 이름
* @param value 값
* @return 성공여부
*/
BOOL SetValue(LPCWSTR keyName, LPCWSTR valueName, LPCWSTR value);
/**
* @brief INI파일에 값을 넣습니다.
* @param keyName Key 이름
* @param valueName Value 이름
* @param value 값
* @return 성공여부
*/
BOOL SetValue(LPCWSTR keyName, LPCWSTR valueName, DWORD value);
/**
* @brief INI파일에 값을 넣습니다.
* @param keyName Key 이름
* @param valueName Value 이름
* @param value 값
* @return 성공여부
*/
BOOL SetValue(LPCWSTR keyName, LPCWSTR valueName, FLOAT value);
/**
* @brief INI파일에 값을 가져옵니다.
* @param keyName Key 이름
* @param valueName Value 이름
* @param value 저장 버퍼
* @param bufferLength 퍼버의 길이
* @return 성공여부
*/
BOOL GetValue(LPCWSTR keyName, LPCWSTR valueName, LPWSTR value, DWORD bufferLength);
/**
* @brief INI파일에 값을 가져옵니다.
* @param keyName Key 이름
* @param valueName Value 이름
* @param value 저장 버퍼
* @return 성공여부
*/
BOOL GetValue(LPCWSTR keyName, LPCWSTR valueName, LPDWORD value);
/**
* @brief INI파일에 값을 가져옵니다.
* @param keyName Key 이름
* @param valueName Value 이름
* @param value 저장 버퍼
* @return 성공여부
*/
BOOL GetValue(LPCWSTR keyName, LPCWSTR valueName, FLOAT *value);
private:
/// INI 파일명
WCHAR m_szFileName[MAX_PATH];
};
}

View File

@@ -0,0 +1,252 @@
#include "Nave.h"
#include "NFStringUtil.h"
#include <list>
#include "NFLog.h"
namespace Nave {
HWND NFLog::s_hLogHandel = NULL;
BOOL NFLog::s_bEnableLogPrint = TRUE;
BOOL NFLog::s_bSaveLogFile = FALSE;
int NFLog::s_iLogLimit = NFLog::Info;
BOOL NFLog::s_bLogDetail = FALSE;
NFLogManager* NFLog::s_pLogManager = NULL;
// Message를 출력할 윈도우 핸들을 셋팅한다.
void NFLog::SetLogHandel(HWND hListWnd)
{
s_hLogHandel = hListWnd;
}
void NFLog::SetLogPrint(BOOL enable)
{
s_bEnableLogPrint = enable;
}
void NFLog::SetLogOutput(BOOL enable, DWORD dwSize)
{
s_bSaveLogFile = enable;
SetLogPrint(enable);
_DELETE(s_pLogManager);
if(s_bSaveLogFile)
{
s_pLogManager = new NFLogManager();
s_pLogManager->Initialize(FALSE);
s_pLogManager->SetLogMaxSize(dwSize);
}
}
void NFLog::CloseLog()
{
if(s_pLogManager)
{
s_pLogManager->Flush();
_DELETE(s_pLogManager);
}
}
void NFLog::SetLogLimit(int limit)
{
s_iLogLimit=limit;
}
void NFLog::SetLogDetail(BOOL detail)
{
s_bLogDetail = detail;
}
void NFLog::AddLogMsg( HWND hWnd, WCHAR* String, int Len )
{
// 삭제
int iCount = (int)SendMessageW( hWnd, LB_GETCOUNT, 0, 0L )-256;
for(int i = 0; i < iCount; ++i)
SendMessageW( hWnd, LB_DELETESTRING, 0, 0L );
// 추가
WCHAR* p;
int k;
p = String;
int iAdd = 0;
k = 0;
while( k++ < Len )
{
switch( *String )
{
case L'\n':
*String = 0;
++iAdd;
SendMessageW( hWnd, LB_ADDSTRING, 0, (LPARAM)(LPWSTR)p );
p = ++String;
break;
default :
++String;
}
}
if( *p )
{
++iAdd;
SendMessageW( hWnd, LB_ADDSTRING, 0, (LPARAM)(LPWSTR)p );
}
int Top = (int)SendMessageW( hWnd, LB_GETTOPINDEX, 0, 0L );
SendMessageW( hWnd, LB_SETTOPINDEX, Top+iAdd, 0L );
}
void NFLog::LogPrintf( WCHAR* msg, ... )
{
va_list v;
WCHAR buf[1024];
int len;
va_start( v, msg );
len = vswprintf( buf, msg, v );
va_end( v );
LogPrintf( Info, buf);
}
void NFLog::OutputLog(const WCHAR* log)
{
static CHAR stDot[4] = "\r\n";
static CHAR stTime[32];
SYSTEMTIME sysTime;
GetLocalTime(&sysTime);
sprintf(stTime, "[%04d.%02d.%02d-%02d:%02d:%02d]", sysTime.wYear, sysTime.wMonth, sysTime.wDay, sysTime.wHour, sysTime.wMinute, sysTime.wSecond);
Nave::StringA str = stTime;
str += ToASCII(log);
str += stDot;
int iSize = str.size();
char* pPoint = s_pLogManager->ReserveBuffer(iSize);
memcpy(pPoint, str.c_str(), iSize);
}
void NFLog::LogPrintf( int group, WCHAR* msg )
{
if (group < s_iLogLimit)
return;
if(s_bEnableLogPrint)
{
if(s_hLogHandel == NULL)
{
// setlocale 함수를 지정해야 한글이 출력됨
wprintf(msg);
wprintf(L"\n");
}
else
AddLogMsg( s_hLogHandel, msg, (int)wcslen(msg) );
}
#ifdef _DEBUG
OutputDebugStringW( msg );
OutputDebugStringW( L"\r\n" );
#endif
if(s_bSaveLogFile)
{
Nave::StringW tmp = msg;
Nave::StringW logmsg;
switch (group) {
case Info:
logmsg=L"[INF] " + tmp;
break;
case Warning:
logmsg=L"[WAR] " + tmp;
break;
case Error:
logmsg=L"[ERR] " + tmp;
break;
case Exception:
logmsg=L"[EXP] " + tmp;
break;
case Important:
logmsg=L"[DET] " + tmp;
break;
};
OutputLog(logmsg.c_str());
}
}
void NFLog::LogPrintf( int group, const WCHAR* pFile, int pLinenum, const WCHAR* pFunc, WCHAR* msg )
{
if (group < s_iLogLimit)
return;
if(s_bEnableLogPrint)
{
if(s_hLogHandel == NULL)
{
wprintf(msg);
wprintf(L"\n");
}
else
AddLogMsg( s_hLogHandel, msg, (int)wcslen(msg) );
}
#ifdef _DEBUG
OutputDebugStringW( msg );
OutputDebugStringW( L"\r\n" );
#endif
if(s_bSaveLogFile)
{
Nave::StringW tmp = msg;
Nave::StringW logmsg;
switch (group) {
case Info:
logmsg=L"[INF]" + tmp;
break;
case Warning:
logmsg=L"[WAR]" + tmp;
break;
case Error:
logmsg=L"[ERR]" + tmp;
break;
case Exception:
logmsg=L"[EXP]" + tmp;
break;
case Important:
logmsg=L"[DET]" + tmp;
break;
};
OutputLog(logmsg.c_str());
static WCHAR deta[1024];
swprintf(deta, L" -> [%s,%d,%s]", pFile, pLinenum, pFunc);
OutputLog(deta);
}
}
NFLog::Proxy::Proxy(int pGroup, const WCHAR* pFile, int pLinenum, const WCHAR* pFunc) : file(pFile),linenum(pLinenum), func(pFunc), group(pGroup)
{
}
void NFLog::Proxy::Log(const WCHAR* msg, ...)
{
if (group < NFLog::s_iLogLimit)
return;
WCHAR txt[1024];
va_list l;
va_start(l,msg);
_vsnwprintf( txt, 1024, msg, l );
va_end(l);
if(!NFLog::s_bLogDetail)
LogPrintf(group,txt);
else
LogPrintf(group,file,linenum,func,txt); // 이건 파일과 기타 정보를 남길때..
}
}

View File

@@ -0,0 +1,142 @@
/**
* @file NFLog.h
* @brief Log 출력 클래스
* @remarks
* @author 강동명(edith2580@gmail.com)
* @date 2009-04-02
*/
#pragma once
#include <stdio.h>
#include <stdarg.h>
#include <string>
#include "NFLogManager.h"
namespace Nave {
/**
* @class NFLog
* @brief Log 출력 클래스
* @remarks NFLog::SetLogHandel(hList); // 특정 윈도우로 로그를 출력한다. \r\n
* NFLog::EnableLogPrint(TRUE); // 로그를 화면에 출력한다. \r\n
* NFLog::EnableLogOutput(TRUE); // 로그를 파일로 저장한다 \r\n
* NFLog::SetLogDetail(TRUE); // 상세 로그로 설정합니다. \r\n
* NFLog::SetLogLimit(NFLog::Proxy::Info) // 로그 리미터를 정의합니다. \r\n
* // 로그 사용 \r\n
* LOG_IMPORTANT((L"Test Start")); \r\n
* // 로그를 마무리합니다. \r\n
* NFLog::CloseLog(); \r\n
* @warning NFLog::CloseLog()를 호출하지 않을경우 파일로 로그가 저장되지
* 않습니다.
*
* @par
* @author Edith
* @date 2009-04-04
*/
class NFLog
{
public:
/// 각 로그의 Index 타입
enum Groups {
Info = 1 << 0,
Warning = 1 << 1,
Error = 1 << 2,
Exception = 1 << 3,
Important = 1 << 4,
};
/// 로그 출력용 구조체
struct Proxy
{
/// 로그가 호출된 함수
const WCHAR* func;
/// 로그가 호출된 파일
const WCHAR* file;
/// 로그가 호출된 라인번호
int linenum;
/// 로그의 그룹아이디
int group;
Proxy(int pGroup, const WCHAR* pFile, int pLinenum, const WCHAR* pFunc);
void Log(const WCHAR* msg, ...);
};
/// Message를 출력할 윈도우 핸들을 셋팅한다.
static void SetLogHandel(HWND hListWnd);
/// 화면에 로고를 찍을꺼냐
static void SetLogPrint(BOOL enable = TRUE);
/// 파일로 로그를 찍을꺼냐
static void SetLogOutput(BOOL enable = TRUE, DWORD dwSize = 100 * 1024 * 1024);
/// 로그의 사용 리미터를 정의합니다. NFLog::Info ~ NFLog::Important
static void SetLogLimit(int limit);
/// 상세 로그를 남깁니다.
static void SetLogDetail(BOOL detail);
/// 로그를 종료합니다. (임시변수에 저장된 로그를 파일로 저장합니다.)
static void CloseLog();
private:
/**
* @brief hWnd에 String을 출력한다.
* @param hWnd 윈도우 핸들
* @param String 메시지
* @param Len 메시지길이
*/
static void AddLogMsg( HWND hWnd, WCHAR* String, int Len );
/**
* @brief 메시지를 출력한다. 콘솔일때 printf로 윈도우모드일때 Msg윈도우로 출력
* @param *msg 출력 메시지
* @param ... 인자
*/
static void LogPrintf( WCHAR* msg, ... );
/**
* @brief 메시지를 출력한다. 콘솔일때 printf로 윈도우모드일때 Msg윈도우로 출력
* @param group 그룹인덱스
* @param *msg 메시지
*/
static void LogPrintf( int group, WCHAR* msg );
/**
* @brief 메시지를 출력한다. 콘솔일때 printf로 윈도우모드일때 Msg윈도우로 출력
* @param group 그룹인덱스
* @param pFile 호출파일명
* @param pLinenum 호출라인
* @param pFunc 호출함수
* @param *msg 메시지
*/
static void LogPrintf( int group, const WCHAR* pFile, int pLinenum, const WCHAR* pFunc, WCHAR* msg );
/// 로그 문자열을 추가합니다.
static void OutputLog(const WCHAR* log);
private:
/// Message를 출력할 윈도우 핸들
static HWND s_hLogHandel;
/// 로그출력을 활성화 합니다.
static BOOL s_bEnableLogPrint;
/// 로그를 파일로 저장합니다.
static BOOL s_bSaveLogFile;
/// 로그 Limit
static int s_iLogLimit;
/// 로그 Detail
static BOOL s_bLogDetail;
/// 로그를 파일을 관리하는 매니져
static NFLogManager* s_pLogManager;
};
}
/// Info Log
#define LOG_INFO(LOGMESSAGE) {Nave::NFLog::Proxy(Nave::NFLog::Info, __WFILE__, __LINE__,__WFUNCSIG__).Log LOGMESSAGE;}
/// Warning Log
#define LOG_WARNING(LOGMESSAGE) {Nave::NFLog::Proxy(Nave::NFLog::Warning,__WFILE__, __LINE__,__WFUNCSIG__).Log LOGMESSAGE;}
/// Error Log
#define LOG_ERROR(LOGMESSAGE) {Nave::NFLog::Proxy(Nave::NFLog::Error,__WFILE__, __LINE__,__WFUNCSIG__).Log LOGMESSAGE;}
/// Exeption Log
#define LOG_EXCEPTION(LOGMESSAGE) {Nave::NFLog::Proxy(Nave::NFLog::Exception,__WFILE__, __LINE__,__WFUNCSIG__).Log LOGMESSAGE;}
/// Important Log
#define LOG_IMPORTANT(LOGMESSAGE) {Nave::NFLog::Proxy(Nave::NFLog::Important,__WFILE__, __LINE__,__WFUNCSIG__).Log LOGMESSAGE;}

View File

@@ -0,0 +1,348 @@
#include "Nave.h"
#include "NFLog.h"
#include "NFLogManager.h"
#include "NFThreadManager.h"
namespace Nave {
NFLogThread::NFLogThread() : m_pLogHandle(NULL), m_bCompress(TRUE),
m_hFlush(CreateEvent(0, TRUE, FALSE, 0)),
m_hFile(INVALID_HANDLE_VALUE), m_dwTotalWritten(0),
m_dwMaxFileSize(MAX_FILE_SIZE)
{
InterlockedExchange(&m_bEnd, FALSE);
}
NFLogThread::~NFLogThread()
{
if(INVALID_HANDLE_VALUE != m_hFile)
{
CloseHandle(m_hFile);
m_hFile = INVALID_HANDLE_VALUE;
}
if(0 != m_hFlush)
{
CloseHandle(m_hFlush);
m_hFlush = 0;
}
}
VOID NFLogThread::Initialize(NFLogManager* pLog, BOOL bCompress)
{
m_bCompress = bCompress;
m_pLogHandle = pLog;
}
unsigned int NFLogThread::Run()
{
// 여기서 m_bEnd가 TRUE가 아니면 스레드가 작동하고 있다.
for(;TRUE != InterlockedCompareExchange(&m_bEnd, TRUE, TRUE);)
{
// 현재 이벤트가 사용중이면 1초간 대기후 다시 확인.
if(WAIT_TIMEOUT == WaitForSingleObject(m_hFlush, 1000))
{
continue;
}
WriteLog();
};
WriteLog();
return 0;
}
BOOL NFLogThread::End()
{
InterlockedExchange(&m_bEnd, TRUE);
SetEvent(m_hFlush);
return TRUE;
}
BOOL NFLogThread::WriteLog()
{
// 로그에서 버퍼를 읽어온다.
if(!m_pLogHandle)
return FALSE;
m_pLogHandle->SpliceInWriteBuffer(m_WriteBufferList);
if(m_WriteBufferList.empty())
return TRUE;
if(INVALID_HANDLE_VALUE == m_hFile)
{
SetLogFileName();
m_hFile = CreateFileW(m_szLogFileName, GENERIC_WRITE,
FILE_SHARE_READ, 0, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
if(INVALID_HANDLE_VALUE == m_hFile)
{
return FALSE;
}
}
unsigned long dwWritten = 0;
for(NFLogBuffer::List::iterator itr = m_WriteBufferList.begin();
itr != m_WriteBufferList.end(); ++itr)
{
NFLogBuffer* pLogBuffer = *itr;
if(FALSE == WriteFile(m_hFile, pLogBuffer->m_Buffer, pLogBuffer->m_dwUsage, &dwWritten, 0))
{
LOG_ERROR((L"로그 파일 기록에 실패했습니다. ErrorNum : %d, FileHandle:0x%p, 버퍼 크기:%d",
GetLastError(), m_hFile, pLogBuffer->m_dwUsage));
}
m_dwTotalWritten += dwWritten;
}
m_pLogHandle->SpliceInFreeBuffer(m_WriteBufferList);
// 파일은 계속 열어놓는다.
if(m_dwTotalWritten > m_dwMaxFileSize)
{
if(INVALID_HANDLE_VALUE != m_hFile) { CloseHandle(m_hFile); m_hFile = INVALID_HANDLE_VALUE; } // 파일 닫고...
m_dwTotalWritten = 0;
}
return TRUE;
}
BOOL NFLogThread::SetLogFileName()
{
SYSTEMTIME sysTime;
GetLocalTime(&sysTime);
unsigned long dwSpinCount = 0;
WCHAR szProgramName[MAX_PATH];
WCHAR szLogFilePrefix[MAX_PATH];
// 프로그램이름과 동일한 하위폴더를 생성한다.
Nave::GetProgramName(szProgramName, MAX_PATH);
if(m_pLogHandle)
_snwprintf(szLogFilePrefix, MAX_PATH - 1, L"%s", m_pLogHandle->GetLogFilePrefix());
else
wcsncpy(szLogFilePrefix, szProgramName, MAX_PATH);
if (INVALID_FILE_ATTRIBUTES == GetFileAttributesW(szProgramName))
{
if (!CreateDirectoryW(szProgramName, 0))
{
return FALSE;
}
}
while (TRUE)
{
int LogLen = _snwprintf(m_szLogFileName, MAX_PATH,
L"%s\\%s-%04d%02d%02d-%02d%02d%02d-%04d.log",
szProgramName, szLogFilePrefix, sysTime.wYear, sysTime.wMonth, sysTime.wDay,
sysTime.wHour, sysTime.wMinute, sysTime.wSecond, dwSpinCount);
if(LogLen <= 0)
{
LOG_ERROR((L"상세 로그를 위한 파일 이름을 생성할 수 없습니다."));
return FALSE;
}
if (INVALID_FILE_ATTRIBUTES == GetFileAttributesW(m_szLogFileName))
{
break;
}
++dwSpinCount;
}
return TRUE;
}
NFLogManager::NFLogManager(void) : m_lpDetailBuffer(0)
{
}
NFLogManager::~NFLogManager(void)
{
Destroy();
}
BOOL NFLogManager::Initialize(BOOL bCompress, const WCHAR* szLogFilePrefix)
{
WCHAR strName[MAX_PATH];
Nave::GetProgramName(strName, MAX_PATH);
wcsncpy(m_szLogFilePrefix, strName, MAX_PATH);
if(szLogFilePrefix != 0)
{
wcscat(m_szLogFilePrefix, szLogFilePrefix);
}
// 처음에 프리버퍼 개수만큼 만든다.
for(int nCount = 0; nCount < DEFAULT_FREE_LOG_BUFFER_NUM; ++nCount)
{
NFLogBuffer* pDetailBuffer = new NFLogBuffer;
if(0 == pDetailBuffer)
{
LOG_ERROR((L"상세 로그 버퍼를 할당하는 데 실패했습니다"));
Destroy();
return FALSE;
}
m_FreeList.push_back(pDetailBuffer);
};
// 버퍼가 없으니 우선 1개 가져옴.
if(m_lpDetailBuffer == 0)
{
m_lpDetailBuffer = GetBuffer();
}
m_LogSaveThread.Initialize(this, bCompress);
if(INVALID_HANDLE_VALUE == NFThreadManager::Run(&m_LogSaveThread))
{
LOG_ERROR((L"Flush스레드를 생성하는 데 실패했습니다"));
return FALSE;
}
return TRUE;
}
BOOL NFLogManager::Destroy()
{
Flush();
NFThreadManager::Stop(&m_LogSaveThread, INFINITE);
// 싱크건다.
NFSyncLock CL(&m_LogSync);
NFLogBuffer* pDetailBuffer;
for(NFLogBuffer::List::iterator itr = m_FreeList.begin(); itr != m_FreeList.end(); ++itr)
{
pDetailBuffer = (*itr);
_DELETE(pDetailBuffer);
}
m_FreeList.clear();
for(NFLogBuffer::List::iterator itr = m_WriteList.begin(); itr != m_WriteList.end(); ++itr)
{
pDetailBuffer = (*itr);
_DELETE(pDetailBuffer);
}
m_WriteList.clear();
return TRUE;
}
VOID NFLogManager::SetLogMaxSize(DWORD dwSize)
{
m_LogSaveThread.SetLogMaxSize(dwSize);
}
NFLogBuffer* NFLogManager::GetBuffer()
{
// 싱크건다.
NFSyncLock CL(&m_LogSync);
NFLogBuffer* pLogBuffer = 0;
if(m_FreeList.empty())
{
// 남는 버퍼가 없으면 실시간으로 생성해버린다. 어쩔수없다.
pLogBuffer = new NFLogBuffer;
}
else
{
pLogBuffer = m_FreeList.front();
m_FreeList.pop_front();
}
if(0 == pLogBuffer)
{
LOG_ERROR((L"상세 로그 버퍼를 할당할 수 없습니다."));
return 0;
}
pLogBuffer->Initialize();
return pLogBuffer;
};
BOOL NFLogManager::Flush()
{
// 버퍼를 넣는다.
PushBuffer(&m_lpDetailBuffer);
return m_LogSaveThread.FlushSignal();
}
char* NFLogManager::ReserveBuffer(unsigned short usReserve)
{
NFSyncLock CL(&m_LogSync);
if(0 == m_lpDetailBuffer)
{
m_lpDetailBuffer = GetBuffer();
}
if(NFLogBuffer::MAX_LOG_BUFFER < m_lpDetailBuffer->m_dwUsage + usReserve)
{
Flush(); // 버퍼가 꽉찼으니 저장해라.
m_lpDetailBuffer = GetBuffer();
}
if(0 == m_lpDetailBuffer)
{
LOG_ERROR((L"로그 버퍼가 0입니다."));
return 0;
}
// 컴플리트를 먼저해서 해당영역을 확보한다.
char* pPoint = &m_lpDetailBuffer->m_Buffer[m_lpDetailBuffer->m_dwUsage];
Complete(usReserve);
return pPoint;
}
VOID NFLogManager::SpliceInWriteBuffer(NFLogBuffer::List& logBufferList)
{
NFSyncLock CL(&m_LogSync);
if(m_WriteList.empty())
return;
// WriteBuffer 를 가져온다.
logBufferList.splice(logBufferList.end(), m_WriteList);
}
VOID NFLogManager::SpliceInFreeBuffer(NFLogBuffer::List& logBufferList)
{
NFSyncLock CL(&m_LogSync);
if(logBufferList.empty())
return;
m_FreeList.splice(m_FreeList.end(), logBufferList);
}
VOID NFLogManager::PushBuffer(NFLogBuffer** ppDetailBuffer)
{
if(0 == *ppDetailBuffer) { return; }
NFSyncLock CL(&m_LogSync);
if(0 == (*ppDetailBuffer)->m_dwUsage)
{
// 사이즈가 0이니 다시 Free에 넣음.
m_FreeList.push_back(*ppDetailBuffer);
}
else
{
m_WriteList.push_back(*ppDetailBuffer);
}
// 이부분 대문에 이중포인터로 변수를 받은것.
*ppDetailBuffer = 0;
}
}

View File

@@ -0,0 +1,241 @@
/**
* @file NFLogManager.h
* @brief LogManager 클래스
* @remarks
* @author 강동명(edith2580@gmail.com)
* @date 2009-04-02
*/
#pragma once
#include <stdio.h>
#include <stdarg.h>
#include <string>
#include <time.h>
#include <list>
#include "NFSync.h"
#include "NFThread.h"
namespace Nave {
class NFLogManager;
/**
* @class NFLogBuffer
* @brief 로그가 저장되는 로그 버퍼 이게 파일로 저장된다.
* @remarks
*
* @par
* @author Edith
* @date 2009-04-04
*/
class NFLogBuffer
{
public:
/// Write, Free 버퍼를 리스트로 관리하게 되는데 typedef를 여기서 했다.
typedef std::list<NFLogBuffer*> List;
enum
{
MAX_LOG_BUFFER = 65536 /// 로그버퍼의 크기
};
/// 사용된 버퍼의 사이즈
unsigned long m_dwUsage;
/// 실제 버퍼
char m_Buffer[MAX_LOG_BUFFER];
/// NFLogBuffer 생성자
NFLogBuffer() : m_dwUsage(0)
{
}
/// 초기화 함수
VOID Initialize()
{
m_dwUsage = 0;
}
};
/**
* @class NFLogThread
* @brief 로그를 관리하는 로그 스레드이다. 로그매니져에서 사용됨.
* @remarks
*
* @par
* @author Edith
* @date 2009-04-04
*/
class NFLogThread : public NFThread
{
public:
/// NFLogThread 생성자
NFLogThread();
/// NFLogThread 소멸자
~NFLogThread();
/**
* @brief 로그를 초기화한다.
* @param pLog 로그메니져 객체
* @param bCompress 압축여부
*/
VOID Initialize(NFLogManager* pLog, BOOL bCompress);
/**
* @brief 로그파일의 크기를 조절한다. 이크기가 되면 다른 파일로 로그를남긴다.
* @param dwSize 로그파일의 크기 byte 수로 남긴다 10 * 1024 * 1024 는 10메가
*/
inline VOID SetLogMaxSize(DWORD dwSize = MAX_FILE_SIZE) { m_dwMaxFileSize = dwSize; }
/// 로그를 저장한다.
BOOL FlushSignal() { return PulseEvent(m_hFlush); }
/// 로그 스레드를 실행한다.
virtual unsigned int Run();
/// 로그 스레드를 종료합니다.
virtual BOOL End();
private:
enum
{
MAX_FILE_SIZE = 100 * 1024 * 1024 /// 기본 파일 사이즈 100메가
};
/**
* @brief 로그파일의 이름을 설정합니다.
* @return 성공여부
*/
BOOL SetLogFileName();
/**
* @brief 로그버퍼에 로그를 Write 합니다.
* @return 성공여부
*/
BOOL WriteLog();
private:
/// 해당 스레드가 종료됬는지 보는로직
volatile LONG m_bEnd;
/// 현재 해당 스레드가 작동중인지 확인하는 이벤트
HANDLE m_hFlush;
/// 로그가 저장되는 파일핸들
HANDLE m_hFile;
/// 사용된 파일크기
DWORD m_dwTotalWritten;
/// 로그 메니져
NFLogManager* m_pLogHandle;
/// 압축 유무
BOOL m_bCompress;
/// 쓰기 로그 버퍼
NFLogBuffer::List m_WriteBufferList;
/// 로그의 파일이름
WCHAR m_szLogFileName[MAX_PATH];
/// 로그파일의 최대 크기
DWORD m_dwMaxFileSize;
};
/**
* @class NFLogManager
* @brief 로그를 저장할때 사용하는 로그 매니져 클래스
* @remarks 로그 매니져는 한 어플이 여러개의 로그를 종류별로 출력할 수도 있기 때문에 싱글톤으로 만들지 않는다.\r\n
* 디테일로그는 바이너리리를 넣기위해 존재하는 로그다. \r\n
* 안에 들어가는 로그는 게임 별로 해당 로그 구조체등을 구현해야한다. \r\n
* 디테일 로그의 경우 속도증가를 위해 처음엔 메모리상에 버퍼를 적고 버퍼가 꽉 찼으면 해당 버퍼를 \r\n
* WriteList에 넣은후 해당 버퍼를 처리한다. \r\n
*
* @par
* @author Edith
* @date 2009-04-04
*/
class NFLogManager
{
public:
/// NFLogManager 생성자
NFLogManager(void);
/// NFLogManager 소멸자
~NFLogManager(void);
/**
* @brief 로그 메니져를 초기화 합니다.
* @param bCompress 압축유무
* @param szLogFilePrefix 로그파일명
* @return 성공여부
*/
BOOL Initialize(BOOL bCompress, const WCHAR* szLogFilePrefix = 0);
/// 로그매니져를 종료합니다.
BOOL Destroy();
/// 로그버퍼의 사이즈를 조절한다.
VOID SetLogMaxSize(DWORD dwSize = 10 * 1024 * 1024);
/**
* @brief 로그파일의 이름
* @return 로그파일이름
*/
const WCHAR* GetLogFilePrefix() const { return m_szLogFilePrefix; }
/**
* @brief 로그를 저장합니다.
* @return 성공여부
*/
BOOL Flush();
/**
* @brief 현재 사용되는 로그 버퍼를 구합니다.
* @return 로그버퍼
*/
NFLogBuffer* GetBuffer();
/**
* @brief 로그버퍼를 할당한다.
* @param usReserve 할당 사이즈
* @return 로그버퍼의 위치포인터
*/
char* ReserveBuffer(unsigned short usReserve);
/**
* @brief 할당된 로그버퍼를 적용시킵니다.
* @param usRealUse 사이즈
*/
VOID Complete(unsigned short usRealUse) { m_lpDetailBuffer->m_dwUsage += usRealUse; }
/**
* @brief 출력상태로 로그버퍼를 할당합니다.
* @param ppDetailBuffer
*/
VOID PushBuffer(NFLogBuffer** ppDetailBuffer);
VOID SpliceInWriteBuffer(NFLogBuffer::List& logBufferList);
VOID SpliceInFreeBuffer(NFLogBuffer::List& logBufferList);
private:
enum
{
DEFAULT_FREE_LOG_BUFFER_NUM = 10 /// 최대 10개까지 프리버퍼를 생성한다.
};
/// Sync 객체
NFSync m_LogSync;
/// 로그 파일명
WCHAR m_szLogFilePrefix[MAX_PATH];
/// 로그 저장용 스레드 변수
NFLogThread m_LogSaveThread;
/// 비어있는 버퍼
NFLogBuffer::List m_FreeList;
/// 파일에 쓰여질 버퍼
NFLogBuffer::List m_WriteList;
/// 현재 사용되는 버퍼
NFLogBuffer* m_lpDetailBuffer;
};
}

View File

@@ -0,0 +1,128 @@
/**
* @file NFSingleton.h
* @brief 싱글톤 클래스
* @remarks
* @author 강동명(edith2580@gmail.com)
* @date 2009-04-02
*/
#pragma once
#include <windows.h>
#include <stdio.h>
#include <assert.h>
/*
#include "NFSingleton.h"
class Test : public Nave::NFSingleton<Test>
{
public:
Test()
{
printf("Test::Test()\n");
}
~Test()
{
printf("Test::~Test()\n");
}
int GetType()
{
return 0;
}
};
INT _tmain(INT argc, WCHAR* argv[])
{
// 만약 싱글톤 객체를 사용하려면
// 아래와 같이 사용하기 위해서 한번 New를 하고
Test* pTest = new Test;
// 다른 위치의 다른함수.
Test::GetInstance().GetType(); 와 같이 사용하면 된다.
delete pTest;
}
*/
#pragma warning (disable : 4311)
#pragma warning (disable : 4312)
namespace Nave {
/**
* @class NFSingleton
* @brief 클래스 객체를 싱글톤으로 생성합니다.
* @remarks
*
* @warning 해당 싱글톤 객체는 처음 생성은 직접 new로 생성을 해주고 \r\n
* delete가 될때까지 싱글톤 같이 사용하며 프로그램이 종료될때\r\n
* delete를 해주면 된다.
* @par
* @author Edith
* @date 2009-04-05
*/
template <typename T> class NFSingleton
{
public:
/// NFSingleton 생성자
NFSingleton (void)
{
assert( !s_pSingleton && "NFSingleton : You can't create more"
" object, because this object is SINGLETON.");
#if defined( _MSC_VER ) && _MSC_VER < 1200
int iOffset = (int)(T*)1 - (int)(NFSingleton <T>*)(T*)1;
s_pSingleton = (T*)((int) this + iOffset);
#else
s_pSingleton = static_cast< T* >( this );
#endif
}
/// NFSingleton 소멸자
~NFSingleton (void)
{
assert( s_pSingleton && "NFSingleton : This object may be "
"destroyed by someone's memory control or other causes.");
s_pSingleton = 0;
}
/// 해당 싱글톤 객체가 생성되는지 확인한다.
static bool IsAlive()
{
return s_pSingleton ? true : false;
}
/// 싱글톤 객체의 인스턴스를 얻는다.
static T& GetInstance(void)
{
assert (s_pSingleton && "NFSingleton : Something is wrong."
" This object destroyed by something bad method or"
"you didn't create yet!");
return *s_pSingleton;
}
/// 싱글톤 객체의 유일한 인스턴스의 포인터를 얻는다
static T* GetInstancePtr(void)
{
assert (s_pSingleton && "NFSingleton : Something is wrong."
" This object destroyed by something bad method.");
return s_pSingleton;
}
private:
/// 싱글톤 객체를 담을 객체의 포인터
static T* s_pSingleton;
};
/// 싱글톤 객체 변수를 초기화 한다.
template<typename T> T* NFSingleton<T>::s_pSingleton = 0;
}

View File

@@ -0,0 +1,45 @@
/**
* @file NFStringCompare.h
* @brief ¹®ÀÚ¿­ Compare Ŭ·¡½º
* @remarks
* @author °­µ¿¸í(edith2580@gmail.com)
* @date 2009-04-02
*/
#pragma once
namespace Nave {
template <typename fc> inline BOOL Compare(fc i1,const fc& iend1,fc i2,const fc& iend2) {
for (;(i1 != iend1) && ( i2 != iend2); ++i1, ++i2) {
if ((*i1) != (*i2)) return FALSE;
}
if ( (i1 == iend1) && ( i2 == iend2)) return TRUE;
return FALSE;
}
template <typename fc> inline BOOL Compare(std::pair<fc,fc>& a, std::pair<fc,fc>& b) {
Compare(a.first,a.second,b.first,b.second);
}
inline BOOL Compare(std::string::const_iterator i1,const std::string::const_iterator& iend1, const char* i2) {
for (;(i1 != iend1) && ( *i2 != 0); ++i1, ++i2) {
if ((*i1) != (*i2)) return FALSE;
}
if ( (i1 == iend1) && ( *i2 == 0)) return TRUE;
return FALSE;
}
inline BOOL Compare(std::wstring::const_iterator i1,const std::wstring::const_iterator& iend1, const wchar_t* i2) {
for (;(i1 != iend1) && ( *i2 != 0); ++i1, ++i2) {
if ((*i1) != (*i2)) return FALSE;
}
if ( (i1 == iend1) && ( *i2 == 0)) return TRUE;
return FALSE;
}
inline BOOL Compare(const std::pair<std::string::const_iterator,std::string::const_iterator>& a, const char* b) {
return Compare(a.first,a.second,b);
}
}

View File

@@ -0,0 +1,54 @@
#include "NFStringUtil.h"
namespace Nave {
std::string Format(char* format, ...) {
static char txt[1024];
va_list l;
va_start(l,format);
_vsnprintf( txt, 1024, format, l );
va_end(l);
return txt;
}
std::wstring Format(wchar_t* format, ...) {
static wchar_t txt[1024];
va_list l;
va_start(l,format);
_vsnwprintf( txt, 1024, format, l );
va_end(l);
return txt;
}
std::wstring RemoveDots(const std::wstring& str2)
{
std::wstring str=str2;
// balal/rear/../reareako.txt
size_t pos1=str.find(L"/..");
while ( pos1 != std::wstring::npos)
{
BOOL found = FALSE;
for ( int i=int(pos1)-1; i >= 0; --i)
{
if ( str[i] == L'/' )
{
str=str.substr(0,i)+str.substr(pos1+3);
found=TRUE;
break;
}
}
if (!found)
{
str=str.substr(pos1+3);
}
pos1=str.find(L"/..");
}
return str;
}
}

View File

@@ -0,0 +1,126 @@
/**
* @file NFStringGeneral.h
* @brief 문자열 파싱 및 생성클래스
* @remarks
* @author 강동명(edith2580@gmail.com)
* @date 2009-04-02
*/
#pragma once
#include <string>
namespace Nave {
inline std::pair<const wchar_t*, const wchar_t*> Split(const wchar_t* ibegin,const wchar_t* iend, wchar_t delimiter) {
for ( const wchar_t* i=ibegin; i != iend; ++i) {
if ( (*i) == delimiter ) {
if (i == ibegin) {
++ibegin;
continue;
}
return std::pair<const wchar_t*,const wchar_t*>(ibegin,i);
}
}
return std::pair<const wchar_t*,const wchar_t*>(ibegin,iend);
}
template <typename fc> inline std::pair<fc, fc> Split(fc ibegin,const fc& iend, typename fc::value_type delimiter) {
for ( fc i=ibegin; i != iend; ++i) {
if ( (*i) == delimiter ) {
if (i == ibegin) {
++ibegin;
continue;
}
return std::pair<fc,fc>(ibegin,i);
}
}
return std::pair<fc,fc>(ibegin,iend);
}
template <typename iterator, typename container> void
Split(iterator ibegin, const iterator& iend, typename iterator::value_type delimiter,
container& result)
{
std::pair<iterator, iterator> p(ibegin, ibegin);
while(p.second!=iend)
{
p=Split(p.first, iend, delimiter);
container::value_type str(p.first, p.second);
result.push_back(str);
p.first=p.second;
}
}
inline void LeftTrim(std::string& s) { s.erase(0, s.find_first_not_of(" ")); }
inline void LeftTrim(std::wstring& s) { s.erase(0, s.find_first_not_of(L" ")); }
inline void RightTrim(std::string& s) { s.resize(s.find_last_not_of(" ") + 1); }
inline void RightTrim(std::wstring& s) { s.resize(s.find_last_not_of(L" ") + 1); }
template <typename fc > inline void Trim(fc& s)
{
LeftTrim(s);
RightTrim(s);
}
std::string Format(char* format, ...);
std::wstring Format(wchar_t* format, ...);
std::string PositionalFormat(char* format, ...);
std::wstring PositionalFormat(wchar_t* format, ...);
template <typename fc> inline fc ParseFileNameNoPath(const fc& str) {
fc tmp=ParseFileName(str);
fc::size_type pos = tmp.find_last_of(L"\\/:");
if (pos != std::wstring::npos)
return tmp.substr(pos+1);
return tmp;
}
/**
Extract filename, "filename|itemname" -> filename
file name includes path
"c:\data\bla|something" -> "c:\data\bla"
*/
template <typename fc> inline fc ParseFileName(const fc& str) {
std::pair<typename fc::const_iterator,typename fc::const_iterator> pair=Split(str.begin(),str.end(),L'|');
return fc(pair.first, pair.second);
}
/**
extracts the item name "filename|itenmae" -> itenname
"c:\data\blabla.xml\hellsemething" -> "something"
*/
template <typename fc> inline fc ParseItemName(const fc& str) {
std::pair<typename fc::const_iterator,typename fc::const_iterator> pair=Split(str.begin(),str.end(),L'|');
if ( pair.second == str.end() ) return fc();
return fc(++pair.second, str.end());
}
/**
"c:\data\blabla.xml\hellsemething" -> "c:\data"
*/
inline std::wstring ParseFilePath(const std::wstring& str) {
std::wstring::size_type pos = str.find_last_of(L"\\/:");
if (pos != std::wstring::npos)
return str.substr(0,pos);
return str;
}
std::wstring RemoveDots(const std::wstring& str2);
}

View File

@@ -0,0 +1,547 @@
#include <windows.h>
#include <stdlib.h>
#include <string>
#include "NFStringGenericConversion.h"
namespace Nave {
unsigned int Hash(const WCHAR* str)
{
//wchar_t* p=const_cast<wchar_t*>(str); <--
//replaced this, we shouldnt be doing const_cast's for no reason @juhnu
const WCHAR* p=str;
unsigned int hashcode=0;
wchar_t c=0;
while(*p)
{
c=*p; hashcode=(31*hashcode+(c%31))%64000000; ++p;
}
return hashcode;
}
unsigned int Hash(const CHAR* str)
{
//wchar_t* p=const_cast<wchar_t*>(str); <--
//replaced this, we shouldnt be doing const_cast's for no reason @juhnu
const CHAR* p=str;
unsigned int hashcode=0;
wchar_t c=0;
while(*p)
{
c=*p;
hashcode=(31*hashcode+(c%31))%64000000; ++p;
}
return hashcode;
}
template<> std::string To(const wchar_t* wstr) {
//int iWstrSize = (int)wcslen(wstr);
int iSize = WideCharToMultiByte(CP_ACP,0,wstr,-1,NULL,0,NULL,NULL);
std::string str(iSize -1, 0);
::WideCharToMultiByte(CP_ACP, 0, wstr, -1, &str[0], iSize, NULL, NULL);
return str;
}
template<> std::wstring To(const wchar_t* wstr) {
//int iWstrSize = (int)wcslen(wstr);
std::wstring tstr(wstr);
return tstr;
}
template <> std::string To(const wstringIteratorPair& StrPair) {
//int iWstrSize = (int)(StrPair.second - StrPair.first);
int iSize = WideCharToMultiByte(CP_ACP,0,&(*StrPair.first), -1 ,NULL,0,NULL,NULL);
//int iSize = (int)(StrPair.second - StrPair.first);
std::string str(iSize -1, 0);
::WideCharToMultiByte(CP_ACP, 0, &(*StrPair.first), -1, &str[0], iSize, NULL, NULL);
return str;
}
template<> std::string To(const char* str) {
std::string tstr(str);
return tstr;
}
template<> std::wstring To(const char* str) {
//int iStrSize = (int)strlen(str);
int iSize = MultiByteToWideChar(CP_ACP,0,str,-1,NULL,0);
//int iSize = (int)strlen(str);
std::wstring wstr(iSize-1, 0);
::MultiByteToWideChar(CP_ACP, 0, str, -1, &wstr[0], iSize);
return wstr;
}
template <> std::wstring To(const stringIteratorPair& StrPair) {
//int iStrSize =(int)(StrPair.second - StrPair.first);
int iSize = MultiByteToWideChar(CP_ACP,0,&(*StrPair.first),-1,NULL,0);
//int iSize = (int)(StrPair.second - StrPair.first);
std::wstring wstr(iSize-1, 0);
::MultiByteToWideChar(CP_ACP, 0, &(*StrPair.first), -1, &wstr[0], iSize);
return wstr;
}
template <> std::string To(int value) {
char szBuffer[12]; //mamximum 10 + 1 sign + 1 null.
_itoa(value, szBuffer, 10);
return std::string(szBuffer);
}
template <> std::wstring To(int value) {
wchar_t wszBuffer[12];
_itow(value, wszBuffer, 10);
return std::wstring(wszBuffer);
}
template <> std::string To(short value) {
char szBuffer[12];
_itoa((int)value, szBuffer, 10);
return std::string(szBuffer);
}
template <> std::wstring To(short value) {
wchar_t wszBuffer[12];
_itow((int)value, wszBuffer, 10);
return std::wstring(wszBuffer);
}
template <> std::string To(unsigned short value) {
char szBuffer[12];
_itoa((int)value, szBuffer, 10);
return std::string(szBuffer);
}
template <> std::wstring To(unsigned short value) {
wchar_t wszBuffer[12];
_itow((int)value, wszBuffer, 10);
return std::wstring(wszBuffer);
}
template <> std::string To(unsigned int value) {
char szBuffer[24];
_ui64toa((unsigned long)value, szBuffer, 10);
return std::string(szBuffer);
}
template <> std::wstring To(unsigned int value) {
wchar_t wszBuffer[24];
_ui64tow((unsigned long)value, wszBuffer, 10);
return std::wstring(wszBuffer);
}
template <> std::string To(__int64 value) {
char szBuffer[24];
_i64toa((unsigned long)value, szBuffer, 10);
return std::string(szBuffer);
}
template <> std::wstring To(__int64 value) {
wchar_t wszBuffer[24];
_ui64tow((unsigned long)value, wszBuffer, 10);
return std::wstring(wszBuffer);
}
template <> std::string To(unsigned __int64 value) {
char szBuffer[24];
_ui64toa((unsigned long)value, szBuffer, 10);
return std::string(szBuffer);
}
template <> std::wstring To(unsigned __int64 value) {
wchar_t wszBuffer[24];
_ui64tow((unsigned long)value, wszBuffer, 10);
return std::wstring(wszBuffer);
}
template <> std::string To(long value) {
char szBuffer[48];
_i64toa(value, szBuffer, 10);
return std::string(szBuffer);
}
template <> std::wstring To(long value) {
wchar_t wszBuffer[48];
_i64tow(value, wszBuffer, 10);
return std::wstring(wszBuffer);
}
template <> std::string To(unsigned long value) {
char szBuffer[100];
_ui64toa(value, szBuffer, 10);
return std::string(szBuffer);
}
template <> std::wstring To(unsigned long value) {
wchar_t wszBuffer[100];
_ui64tow(value, wszBuffer, 10);
return std::wstring(wszBuffer);
}
template <> std::string To(float value) {
char szBuffer[100];
sprintf(szBuffer, "%f", value);
return std::string(szBuffer);
}
template <> std::wstring To(float value) {
wchar_t wszBuffer[100];
swprintf(wszBuffer, L"%f", value);
return std::wstring(wszBuffer);
}
template <> std::string To(double value) {
char szBuffer[100];
sprintf(szBuffer, "%f", value);
return std::string(szBuffer);
}
template <> std::wstring To(double value) {
wchar_t wszBuffer[100];
swprintf(wszBuffer, L"%f", value);
return std::wstring(wszBuffer);
}
template <> std::string To(float2 value) {
char szBuffer[100*3];
sprintf(szBuffer, "(%f, %f)", value.x, value.y);
return std::string(szBuffer);
}
template <> std::wstring To(float2 value) {
wchar_t wszBuffer[100*3];
swprintf(wszBuffer, L"(%f, %f)", value.x, value.y);
return std::wstring(wszBuffer);
}
template <> std::string To(float3 value) {
char szBuffer[100*4];
sprintf(szBuffer, "(%f, %f, %f)", value.x, value.y, value.z);
return std::string(szBuffer);
}
template <> std::wstring To(float3 value) {
wchar_t wszBuffer[100*4];
swprintf(wszBuffer, L"(%f, %f, %f)", value.x, value.y, value.z);
return std::wstring(wszBuffer);
}
template <> std::string To(float4 value) {
char szBuffer[100*4];
sprintf(szBuffer, "(%f, %f, %f, %f)", value.x, value.y, value.z, value.w);
return std::string(szBuffer);
}
template <> std::wstring To(float4 value) {
wchar_t wszBuffer[100*4];
swprintf(wszBuffer, L"(%f, %f, %f, %f)", value.x, value.y, value.z, value.w);
return std::wstring(wszBuffer);
}
template <> double To(const char* str) { return atof(str); }
template <> double To(const stringIteratorPair& StrPair) { return To<double>(std::string(StrPair.first, StrPair.second)); }
template <> float To(const char* str) { return (float)To<double>(str); }
template <> float To(const stringIteratorPair& StrPair) { return (float)To<double>(StrPair); }
template <> int To(const char* str) { return atoi(str); }
template <> int To(const stringIteratorPair& StrPair) { return To<int>(std::string(StrPair.first, StrPair.second)); }
template <> double To(const wchar_t* wstr) { return _wtof(wstr); }
template <> double To(const wstringIteratorPair& StrPair) { return To<double>(std::wstring(StrPair.first, StrPair.second)); }
template <> float To(const wchar_t* wstr) { return (float)To<double>(wstr); }
template <> float To(const wstringIteratorPair& StrPair) { return (float)To<double>(StrPair); }
template <> int To(const wchar_t* str) { return _wtoi(str); }
template <> int To(const wstringIteratorPair& StrPair) { return To<int>(std::wstring(StrPair.first, StrPair.second)); }
/*
template <> short To(const wchar_t* str) { return (short)_wtoi(str); }
template <> short To(const wstringIteratorPair& StrPair) { return To<short>(std::wstring(StrPair.first, StrPair.second)); }
template <> long To(const wchar_t* str) { return _wtol(str); }
template <> long To(const wstringIteratorPair& StrPair) { return To<long>(std::wstring(StrPair.first, StrPair.second)); }
template <> unsigned int To(const wchar_t* str) { return (unsigned int)_wtoi(str); }
template <> unsigned int To(const wstringIteratorPair& StrPair) { return To<unsigned int>(std::wstring(StrPair.first, StrPair.second)); }
template <> unsigned short To(const wchar_t* str) { return (unsigned short)_wtoi(str); }
template <> unsigned short To(const wstringIteratorPair& StrPair) { return To<unsigned short>(std::wstring(StrPair.first, StrPair.second)); }
template <> unsigned long To(const wchar_t* str) { return (unsigned long)_wtol(str); }
template <> unsigned long To(const wstringIteratorPair& StrPair) { return To<unsigned long>(std::wstring(StrPair.first, StrPair.second)); }
*/
namespace Private {
template<typename T>
class Tokens {};
template<>
class Tokens<char> {
public:
static const char Minus = '-';
static const char LeftParenthesis = '(';
static const char RightParenthesis = ')';
static const char Comma = ',';
static const char Point = '.';
static const char Null = '\0';
static const char Zero = '0';
static const char Nine = '9';
static const char Space = ' ';
static const char Tab = '\t';
static const char LineFeed = '\n';
static const char CarriageReturn = '\r';
};
template<>
class Tokens<wchar_t> {
public:
static const wchar_t Minus = L'-';
static const wchar_t LeftParenthesis = L'(';
static const wchar_t RightParenthesis = L')';
static const wchar_t Comma = L',';
static const wchar_t Point = L'.';
static const wchar_t Null = L'\0';
static const wchar_t Zero = L'0';
static const wchar_t Nine = L'9';
static const wchar_t Space = L' ';
static const wchar_t Tab = L'\t';
static const wchar_t LineFeed = L'\n';
static const wchar_t CarriageReturn = L'\r';
};
template<typename T>
BOOL GetToken(T** pStr, T tToken) {
if( **pStr == tToken ) { (*pStr)++; return TRUE; }
return FALSE;
}
template<typename T>
BOOL IsNumber(T tChar) {
return (Tokens<T>::Zero <= tChar && tChar <= Tokens<T>::Nine) ? TRUE : FALSE;
}
template<typename T>
BOOL IsWhiteSpace(T tChar) {
return (tChar == Tokens<T>::Space || tChar == Tokens<T>::Tab ||
tChar == Tokens<T>::LineFeed || tChar == Tokens<T>::CarriageReturn) ? TRUE : FALSE;
}
template<typename T>
void SkipWhitespace(T** pStr) {
while( IsWhiteSpace(**pStr) ) (*pStr)++;
}
template<typename T>
void SkipNumbers(T** pStr) {
while( IsNumber(**pStr) ) (*pStr)++;
}
template<typename T>
void SkipFloat(T** pStr) {
//sign
GetToken(pStr, Tokens<T>::Minus);
//number before point
SkipNumbers(pStr);
//point
GetToken(pStr, Tokens<T>::Point);
//number after point
SkipNumbers(pStr);
}
}
template <> float2 To(const char* str) {
using namespace Private;
float2 ret;
char* pRead = const_cast<char*>(str);
//(
SkipWhitespace(&pRead);
if( !GetToken(&pRead, '(') ) return ret;
//x
SkipWhitespace(&pRead);
ret.x = To<float>(pRead);
SkipFloat(&pRead);
//,
SkipWhitespace(&pRead);
if( !GetToken(&pRead, ',') ) return ret;
//y
SkipWhitespace(&pRead);
ret.y = To<float>(pRead);
SkipFloat(&pRead);
//need not check )
return ret;
}
template<> float2 To(const stringIteratorPair &StrPair) { return To<float2>(std::string(StrPair.first, StrPair.second).c_str()); }
template <> float3 To(const char* str) {
using namespace Private;
float3 ret;
char* pRead = const_cast<char*>(str);
//(
SkipWhitespace(&pRead);
if( !GetToken(&pRead, '(') ) return ret;
//x
SkipWhitespace(&pRead);
ret.x = To<float>(pRead);
SkipFloat(&pRead);
//,
SkipWhitespace(&pRead);
if( !GetToken(&pRead, ',') ) return ret;
//y
SkipWhitespace(&pRead);
ret.y = To<float>(pRead);
SkipFloat(&pRead);
//,
SkipWhitespace(&pRead);
if( !GetToken(&pRead, ',') ) return ret;
//z
SkipWhitespace(&pRead);
ret.z = To<float>(pRead);
SkipFloat(&pRead);
//need not check )
return ret;
}
template<> float3 To(const stringIteratorPair &StrPair) { return To<float3>(std::string(StrPair.first, StrPair.second).c_str()); }
template <> float4 To(const char* str) {
using namespace Private;
float4 ret;
char* pRead = const_cast<char*>(str);
//(
SkipWhitespace(&pRead);
if( !GetToken(&pRead, '(') ) return ret;
//x
SkipWhitespace(&pRead);
ret.x = To<float>(pRead);
SkipFloat(&pRead);
//,
SkipWhitespace(&pRead);
if( !GetToken(&pRead, ',') ) return ret;
//y
SkipWhitespace(&pRead);
ret.y = To<float>(pRead);
SkipFloat(&pRead);
//,
SkipWhitespace(&pRead);
if( !GetToken(&pRead, ',') ) return ret;
//z
SkipWhitespace(&pRead);
ret.z = To<float>(pRead);
SkipFloat(&pRead);
//,
SkipWhitespace(&pRead);
if( !GetToken(&pRead, ',') ) return ret;
//w
SkipWhitespace(&pRead);
ret.w = To<float>(pRead);
SkipFloat(&pRead);
//need not check )
return ret;
}
template<> float4 To(const stringIteratorPair &StrPair) { return To<float4>(std::string(StrPair.first, StrPair.second).c_str()); }
template <> float2 To(const wchar_t* str) {
using namespace Private;
float2 ret;
wchar_t* pRead = const_cast<wchar_t*>(str);
//(
SkipWhitespace(&pRead);
if( !GetToken(&pRead, L'(') ) return ret;
//x
SkipWhitespace(&pRead);
ret.x = To<float>(pRead);
SkipFloat(&pRead);
//,
SkipWhitespace(&pRead);
if( !GetToken(&pRead, L',') ) return ret;
//y
SkipWhitespace(&pRead);
ret.y = To<float>(pRead);
SkipFloat(&pRead);
//need not check )
return ret;
}
template<> float2 To(const wstringIteratorPair &StrPair) { return To<float2>(std::wstring(StrPair.first, StrPair.second).c_str()); }
template <> float3 To(const wchar_t* str) {
using namespace Private;
float3 ret;
wchar_t* pRead = const_cast<wchar_t*>(str);
//(
SkipWhitespace(&pRead);
if( !GetToken(&pRead, L'(') ) return ret;
//x
SkipWhitespace(&pRead);
ret.x = To<float>(pRead);
SkipFloat(&pRead);
//,
SkipWhitespace(&pRead);
if( !GetToken(&pRead, L',') ) return ret;
//y
SkipWhitespace(&pRead);
ret.y = To<float>(pRead);
SkipFloat(&pRead);
//,
SkipWhitespace(&pRead);
if( !GetToken(&pRead, L',') ) return ret;
//z
SkipWhitespace(&pRead);
ret.z = To<float>(pRead);
SkipFloat(&pRead);
//need not check )
return ret;
}
template<> float3 To(const wstringIteratorPair &StrPair) { return To<float3>(std::wstring(StrPair.first, StrPair.second).c_str()); }
template <> float4 To(const wchar_t* str) {
using namespace Private;
float4 ret;
wchar_t* pRead = const_cast<wchar_t*>(str);
//(
SkipWhitespace(&pRead);
if( !GetToken(&pRead, L'(') ) return ret;
//x
SkipWhitespace(&pRead);
ret.x = To<float>(pRead);
SkipFloat(&pRead);
//,
SkipWhitespace(&pRead);
if( !GetToken(&pRead, L',') ) return ret;
//y
SkipWhitespace(&pRead);
ret.y = To<float>(pRead);
SkipFloat(&pRead);
//,
SkipWhitespace(&pRead);
if( !GetToken(&pRead, L',') ) return ret;
//z
SkipWhitespace(&pRead);
ret.z = To<float>(pRead);
SkipFloat(&pRead);
//,
SkipWhitespace(&pRead);
if( !GetToken(&pRead, L',') ) return ret;
//w
SkipWhitespace(&pRead);
ret.w = To<float>(pRead);
SkipFloat(&pRead);
//need not check )
return ret;
}
template<> float4 To(const wstringIteratorPair &StrPair) { return To<float4>(std::wstring(StrPair.first, StrPair.second).c_str()); }
}

View File

@@ -0,0 +1,97 @@
/**
* @file NFStringGenericConversion.h
* @brief 문자열 컨버팅 클래스
* @remarks
* @author 강동명(edith2580@gmail.com)
* @date 2009-04-02
*/
#pragma once
#include "NFTypes.h"
namespace Nave {
/**
Conversions work like
To<float>("123");
To<float>(L"123");
To<std::string>(L"hello world");
To<std::wstring>("hello world");
*/
unsigned int Hash(const WCHAR* str);
unsigned int Hash(const CHAR* str);
typedef std::pair<std::string::const_iterator,std::string::const_iterator> stringIteratorPair;
typedef std::pair<std::wstring::const_iterator,std::wstring::const_iterator> wstringIteratorPair;
template <typename T1, typename T2> T1 To(T2 value);
//generic conversion functions from string to actual type, also supports single(ascii)-wide(unicode conversions) character, if conversion to
//some type is not supported you will get a LINKING error
template <typename T> T To(const char* str);
template <typename T> inline T To(char* str) { return To<T>((const char*)str); }
template <typename T> inline T To(const std::string& str) { return To<T>(str.c_str()); }
template <typename T> T To(const stringIteratorPair& StrPair);
template <typename T> T To(const wchar_t* wstr);
template <typename T> inline T To(wchar_t* wstr) { return To<T>((const wchar_t*)wstr); }
template <typename T> inline T To(const std::wstring& wstr) { return To<T>(wstr.c_str()); }
template <typename T> T To(const wstringIteratorPair& StrPair);
//methods for converting between upper and lower case, supports both single and wide byte conversions
template <typename fc> inline void ToUpperCase(fc& s) { std::transform(s.begin(),s.end(),s.begin(),toupper); }
template <typename fc> inline void ToLowerCase(fc& s) { std::transform(s.begin(),s.end(),s.begin(),tolower); }
template <typename T> inline float ToFloat(const T& p) { return To<float>(p); }
template <typename T> inline float ToFloat(const T* p) { return To<float>(p); }
template <typename T> inline double ToDouble(const T& p) { return To<double>(p); }
template <typename T> inline double ToDouble(const T* p) { return To<double>(p); }
template <typename T> inline int ToInt(const T& p) { return To<int>(p); }
template <typename T> inline int ToInt(const T* p) { return To<int>(p); }
template <typename T> inline float2 ToFloat2(const T& p) { return To<float2>(p); }
template <typename T> inline float2 ToFloat2(const T* p) { return To<float2>(p); }
template <typename T> inline float3 ToFloat3(const T& p) { return To<float3>(p); }
template <typename T> inline float3 ToFloat3(const T* p) { return To<float3>(p); }
template <typename T> inline float4 ToFloat4(const T& p) { return To<float4>(p); }
template <typename T> inline float4 ToFloat4(const T* p) { return To<float4>(p); }
//@deprecated: convenience methods for single - wide byte conversions
inline Nave::String ToString(const std::string p)
{
return To<std::wstring>(p);
}
inline Nave::String ToString(const std::wstring p)
{
return p;
}
template <typename T> inline Nave::String ToNumber(const T& p)
{
Nave::String pstr = To<Nave::String>(p);
return ToString(pstr);
}
template <typename T> inline Nave::String ToNumber(const T* p)
{
Nave::String pstr = To<Nave::String>(p);
return ToString(pstr);
}
template <typename T> inline std::string ToASCII(const T& p) { return To<std::string>(p); }
template <typename T> inline std::string ToASCII(const T* p) { return To<std::string>(p); }
template <typename T> inline std::wstring ToUnicode(const T& p) { return To<std::wstring>(p); }
template <typename T> inline std::wstring ToUnicode(const T* p) { return To<std::wstring>(p); }
}

View File

@@ -0,0 +1,24 @@
/**
* @file NFStringUtil.h
* @brief 문자열 유틸리티 선언
* @remarks
* @author 강동명(edith2580@gmail.com)
* @date 2009-04-02
*/
#pragma once
#include <windows.h>
#include <mmsystem.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <memory.h>
#include <tchar.h>
#include <stddef.h> // 템플릿 라이브러리 헤더?
#include <conio.h>
#include "NFStringGenericConversion.h"
#include "NFStringGeneral.h"
#include "NFStringCompare.h"

View File

@@ -0,0 +1,80 @@
/**
* @file NFSync.h
* @brief Sync 클래스
* @remarks
* @author 강동명(edith2580@gmail.com)
* @date 2009-04-02
*/
#pragma once
namespace Nave {
/**
* @class NFSync
* @brief Sync 클래스
* @remarks
* NFSync Sync; \r\n
* NFSyncLock CL(&Sync);
*
* @par
* @author Edith
* @date 2009-04-05
*/
class NFSync
{
public:
NFSync(VOID)
{
InitializeCriticalSection(&m_Sync);
}
~NFSync(VOID)
{
DeleteCriticalSection(&m_Sync);
}
inline VOID Enter(VOID)
{
EnterCriticalSection(&m_Sync);
}
inline VOID Leave(VOID)
{
LeaveCriticalSection(&m_Sync);
}
private:
CRITICAL_SECTION m_Sync;
};
/**
* @class NFSyncLock
* @brief 싱글스레드용 싱크
* @remarks
*
* @par
* @author Edith
* @date 2009-04-05
*/
class NFSyncLock
{
public:
NFSyncLock(LPVOID lpVoid)
{
m_pThis = (NFSync*)lpVoid;
m_pThis->Enter();
}
~NFSyncLock(VOID)
{
if(m_pThis)
m_pThis->Leave();
}
private:
NFSync *m_pThis;
};
}

View File

@@ -0,0 +1,61 @@
/**
* @file NFThread.h
* @brief Auto Thread 생성 클래스
* @remarks
* @author 강동명(edith2580@gmail.com)
* @date 2009-04-02
*/
#pragma once
#include <windows.h>
namespace Nave {
/**
* @class NFThread
* @brief 스레드 객체 클래스
* @remarks
*
* @par
* @author Edith
* @date 2009-04-05
*/
class NFThread
{
public:
NFThread() : m_hThreadHandle(INVALID_HANDLE_VALUE)
{
}
~NFThread()
{
}
typedef unsigned int(__stdcall *LPThreadFunc)(void*);
/// 스레드 함수포인터
static inline unsigned int __stdcall ThreadFunc(void* pArg);
/// 스레드 핸들을 리턴한다.
inline HANDLE GetHandle() { return m_hThreadHandle; }
/// 스레드 핸들을 설정한다.
inline void SetHandle(HANDLE hHandle) { m_hThreadHandle = hHandle; }
/// 실제 실행 되는 루프를 넣는다.
virtual unsigned int Run() = 0;
/// 루프가 끝날 수 있는 루틴을 넣는다.
virtual BOOL End() = 0;
private:
/// 스레드핸들
HANDLE m_hThreadHandle;
// friend class NFThreadManager;
};
/// 스레드 호출함수
inline unsigned int __stdcall NFThread::ThreadFunc(void* pArg)
{
return static_cast<NFThread*>(pArg)->Run();
}
}

View File

@@ -0,0 +1,129 @@
#include "Nave.h"
#include "NFThread.h"
#include "NFThreadManager.h"
namespace Nave {
HANDLE NFThreadManager::Run(NFThread* lpThread)
{
unsigned int nThreadID = 0;
HANDLE hThread = reinterpret_cast<HANDLE>(_beginthreadex(0,
0, NFThread::ThreadFunc, lpThread, 0, &nThreadID));
lpThread->SetHandle(hThread);
return hThread;
}
BOOL NFThreadManager::Stop(NFThread* lpThread, unsigned long dwTimeout)
{
if(0 == lpThread)
{
return FALSE;
}
HANDLE hThread = lpThread->GetHandle();
if(INVALID_HANDLE_VALUE == hThread)
{
return FALSE;
}
lpThread->SetHandle(INVALID_HANDLE_VALUE);
lpThread->End();
WaitForSingleObject(hThread, dwTimeout);
return (TRUE == CloseHandle(hThread));
}
NFThreadManager::NFThreadManager() : m_nThreadNum(0), m_bUnRegStarted(FALSE)
{
for(int i = 0; i < MAX_THREAD_NUM; ++i)
{
m_lpThreads[i] = NULL;
m_hThreads[i] = NULL;
}
}
NFThreadManager::~NFThreadManager()
{
UnRegister();
}
BOOL NFThreadManager::Register(NFThread* llpThread)
{
unsigned int nThreadID = 0;
unsigned int nThreadIndex = 0;
if(0 == llpThread)
{
return FALSE;
}
// Lock
{
Nave::NFSyncLock Sync(&m_ThreadLock);
if(MAX_THREAD_NUM <= m_nThreadNum || TRUE == m_bUnRegStarted)
{
return FALSE;
}
nThreadIndex = m_nThreadNum;
++m_nThreadNum;
}
m_lpThreads[nThreadIndex] = llpThread;
m_hThreads[nThreadIndex] = reinterpret_cast<HANDLE>(_beginthreadex(0, 0,
NFThread::ThreadFunc, llpThread, 0, &nThreadID));
return (0 != m_hThreads[nThreadIndex]);
}
BOOL NFThreadManager::UnRegister()
{
{
Nave::NFSyncLock Sync(&m_ThreadLock);
if(0 == m_nThreadNum)
{
return TRUE;
}
// 조인이 시작되면, 더이상의 스레드 생성 및 등록을 금지함.
m_bUnRegStarted = TRUE;
}
// 스레드 전부 종료 & 대기.
for(int i = 0; i < (int)m_nThreadNum; ++i)
{
if(m_lpThreads[i])
{
m_lpThreads[i]->End();
}
}
WaitForMultipleObjects(m_nThreadNum, m_hThreads, TRUE, INFINITE);
// 스레드 소멸.
for(int i = 0; i < MAX_THREAD_NUM; ++i)
{
_DELETE(m_lpThreads[i]);
if(m_hThreads[i])
{
CloseHandle(m_hThreads[i]);
m_hThreads[i] = NULL;
}
}
{
// 스레드 개수 및 조인 여부 리셋.
Nave::NFSyncLock Sync(&m_ThreadLock);
m_nThreadNum = 0;
m_bUnRegStarted = FALSE;
}
return TRUE;
}
}

View File

@@ -0,0 +1,75 @@
/**
* @file NFThreadManager.h
* @brief Auto ThreadManager 클래스
* @remarks
* @author 강동명(edith2580@gmail.com)
* @date 2009-04-02
*/
#pragma once
#define WINDOWS_LEAN_AND_MEAN
#include <windows.h>
#include <process.h>
#include "NFSync.h"
#include "NFThread.h"
namespace Nave {
/**
* @class NFThreadManager
* @brief 스레드 매니져
* @remarks
* 1) NFThread 를 상속받은 녀석 \r\n
* \r\n
* Nave::NFThreadManager::Run(this); \r\n
* Nave::NFThreadManager::Stop(this, 2000); \r\n
* \r\n
* 2) 스레드 매니져를 사용하려면 \r\n
* Nave::NFThreadManager::GetInstance().Register( new CTest(this) ); \r\n
* \r\n
* // 소멸시 자동으로 UnRegister가 호출되어메모리에서 삭제됨.. \r\n
*
* @par
* @author Edith
* @date 2009-04-05
*/
class NFThreadManager : public Nave::NFSingleton<NFThreadManager>
{
public:
/// NFThreadManager 생성자
NFThreadManager();
/// NFThreadManager 소멸자
virtual ~NFThreadManager();
/// 스레드를 등록한다. 최대 32개까지 등록할 수 있다.
BOOL Register(NFThread* lpThread);
/// 모든 스레드를 종료시킨다.
BOOL UnRegister();
/// 매니저를 사용하지 않고, 그냥 실행 시킨다.
static HANDLE Run(NFThread* lpThread);
/// 매니저를 사용하지 않고, 그냥 종료 시킨다.
static BOOL Stop(NFThread* lpThread, unsigned long dwTimeout = INFINITE);
private:
enum {
MAX_THREAD_NUM = 32 /// 최대 스레드 개수
};
/// 스레드 객체 포인터
NFThread* m_lpThreads[MAX_THREAD_NUM];
/// 스레드 핸들
HANDLE m_hThreads[MAX_THREAD_NUM];
/// 스레드 Lock
Nave::NFSync m_ThreadLock;
/// 스레드 개수
Nave::uint32 m_nThreadNum;
/// UnRegister의 진행여부
Nave::uint32 m_bUnRegStarted;
};
}

View File

@@ -0,0 +1,322 @@
#include "Nave.h"
#include "NFTokenizer.h"
namespace Nave {
NFTokenizerA::NFTokenizerA(const std::string& _str, const std::string& _delim)
{
if ((_str.length() == 0) || (_delim.length() == 0)) return;
token_str = _str;
delim = _delim;
/*
Remove sequential delimiter
*/
unsigned int curr_pos = 0;
while(true)
{
if ((curr_pos = token_str.find(delim,curr_pos)) != std::string::npos)
{
curr_pos += delim.length();
while(token_str.find(delim,curr_pos) == curr_pos)
{
token_str.erase(curr_pos,delim.length());
}
}
else
break;
}
/*
Trim leading delimiter
*/
if (token_str.find(delim,0) == 0)
{
token_str.erase(0,delim.length());
}
/*
Trim ending delimiter
*/
curr_pos = 0;
if ((curr_pos = token_str.rfind(delim)) != std::string::npos)
{
if (curr_pos != (token_str.length() - delim.length())) return;
token_str.erase(token_str.length() - delim.length(),delim.length());
}
}
int NFTokenizerA::CountTokens()
{
unsigned int prev_pos = 0;
int num_tokens = 0;
if (token_str.length() > 0)
{
num_tokens = 0;
unsigned int curr_pos = 0;
while(true)
{
if ((curr_pos = token_str.find(delim,curr_pos)) != std::string::npos)
{
num_tokens++;
prev_pos = curr_pos;
curr_pos += delim.length();
}
else
break;
}
return ++num_tokens;
}
else
{
return 0;
}
}
bool NFTokenizerA::HasMoreTokens()
{
return (token_str.length() > 0);
}
std::string NFTokenizerA::NextToken()
{
if (token_str.length() == 0)
return "";
std::string tmp_str = "";
unsigned int pos = token_str.find(delim,0);
if (pos != std::string::npos)
{
tmp_str = token_str.substr(0,pos);
token_str = token_str.substr(pos+delim.length(),token_str.length()-pos);
}
else
{
tmp_str = token_str.substr(0,token_str.length());
token_str = "";
}
return tmp_str;
}
int NFTokenizerA::NextIntToken()
{
return atoi(NextToken().c_str());
}
double NFTokenizerA::NextFloatToken()
{
return atof(NextToken().c_str());
}
std::string NFTokenizerA::NextToken(const std::string& delimiter)
{
if (token_str.length() == 0)
return "";
std::string tmp_str = "";
unsigned int pos = token_str.find(delimiter,0);
if (pos != std::string::npos)
{
tmp_str = token_str.substr(0,pos);
token_str = token_str.substr(pos + delimiter.length(),token_str.length() - pos);
}
else
{
tmp_str = token_str.substr(0,token_str.length());
token_str = "";
}
return tmp_str;
}
std::string& NFTokenizerA::RemainingString()
{
return token_str;
}
std::string NFTokenizerA::FilterNextToken(const std::string& filterStr)
{
std::string tmp_str = NextToken();
unsigned int currentPos = 0;
while((currentPos = tmp_str.find(filterStr,currentPos)) != std::string::npos)
{
tmp_str.erase(currentPos,filterStr.length());
}
return tmp_str;
}
// unicode type
NFTokenizerW::NFTokenizerW(const std::wstring& _str, const std::wstring& _delim)
{
if ((_str.length() == 0) || (_delim.length() == 0)) return;
token_str = _str;
delim = _delim;
/*
Remove sequential delimiter
*/
unsigned int curr_pos = 0;
while(true)
{
if ((curr_pos = token_str.find(delim,curr_pos)) != std::wstring::npos)
{
curr_pos += delim.length();
while(token_str.find(delim,curr_pos) == curr_pos)
{
token_str.erase(curr_pos,delim.length());
}
}
else
break;
}
/*
Trim leading delimiter
*/
if (token_str.find(delim,0) == 0)
{
token_str.erase(0,delim.length());
}
/*
Trim ending delimiter
*/
curr_pos = 0;
if ((curr_pos = token_str.rfind(delim)) != std::wstring::npos)
{
if (curr_pos != (token_str.length() - delim.length())) return;
token_str.erase(token_str.length() - delim.length(),delim.length());
}
}
int NFTokenizerW::CountTokens()
{
unsigned int prev_pos = 0;
int num_tokens = 0;
if (token_str.length() > 0)
{
num_tokens = 0;
unsigned int curr_pos = 0;
while(true)
{
if ((curr_pos = token_str.find(delim,curr_pos)) != std::wstring::npos)
{
num_tokens++;
prev_pos = curr_pos;
curr_pos += delim.length();
}
else
break;
}
return ++num_tokens;
}
else
{
return 0;
}
}
bool NFTokenizerW::HasMoreTokens()
{
return (token_str.length() > 0);
}
std::wstring NFTokenizerW::NextToken()
{
if (token_str.length() == 0)
return L"";
std::wstring tmp_str = L"";
unsigned int pos = token_str.find(delim,0);
if (pos != std::wstring::npos)
{
tmp_str = token_str.substr(0,pos);
token_str = token_str.substr(pos+delim.length(),token_str.length()-pos);
}
else
{
tmp_str = token_str.substr(0,token_str.length());
token_str = L"";
}
return tmp_str;
}
int NFTokenizerW::NextIntToken()
{
return _wtoi(NextToken().c_str());
}
double NFTokenizerW::NextFloatToken()
{
return _wtof(NextToken().c_str());
}
std::wstring NFTokenizerW::NextToken(const std::wstring& delimiter)
{
if (token_str.length() == 0)
return L"";
std::wstring tmp_str = L"";
unsigned int pos = token_str.find(delimiter,0);
if (pos != std::wstring::npos)
{
tmp_str = token_str.substr(0,pos);
token_str = token_str.substr(pos + delimiter.length(),token_str.length() - pos);
}
else
{
tmp_str = token_str.substr(0,token_str.length());
token_str = L"";
}
return tmp_str;
}
std::wstring& NFTokenizerW::RemainingString()
{
return token_str;
}
std::wstring NFTokenizerW::FilterNextToken(const std::wstring& filterStr)
{
std::wstring tmp_str = NextToken();
unsigned int currentPos = 0;
while((currentPos = tmp_str.find(filterStr,currentPos)) != std::wstring::npos)
{
tmp_str.erase(currentPos,filterStr.length());
}
return tmp_str;
}
}

View File

@@ -0,0 +1,120 @@
/**
* @file NFTokenizer.h
* @brief Tokenizer 클래스
* @remarks
* @author 강동명(edith2580@gmail.com)
* @date 2009-04-02
*/
#pragma once
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <string>
namespace Nave {
/**
* @class NFTokenizerA
* @brief 멀티바이트용 Tokenizer
* @remarks
* Nave::String tempStr = L"01|02|03|04|05|06|07|08|09|10|11|12"; \r\n
* \r\n
* Nave::NFTokenizer strtok = Nave::NFTokenizer(tempStr, L"|"); \r\n
* \r\n
* LOG_IMPORTANT((L"Number Of Tokens: %d"), strtok.CountTokens()); \r\n
* LOG_IMPORTANT((L"String: %s"), strtok.RemainingString().c_str()); \r\n
* \r\n
* int cnt = strtok.CountTokens(); \r\n
* Nave::String finalString = L""; \r\n
* \r\n
* for(int i = 0; i < cnt; i++) \r\n
* { \r\n
* Nave::String tempStr = L""; \r\n
* \r\n
* LOG_IMPORTANT((L"Token[%d] ----> [%s]"), i, strtok.NextToken().c_str());\r\n
* LOG_IMPORTANT((L"Token Count : %d"), strtok.CountTokens()); \r\n
* \r\n
* finalString += tempStr; \r\n
* } \r\n
* \r\n
* LOG_IMPORTANT((L"Final String : %s"), finalString.c_str());
*
* @par
* @author Edith
* @date 2009-04-05
*/
class NFTokenizerA
{
public:
NFTokenizerA(const std::string& _str, const std::string& _delim);
~NFTokenizerA(){};
int CountTokens();
bool HasMoreTokens();
std::string NextToken();
int NextIntToken();
double NextFloatToken();
std::string NextToken(const std::string& delim);
std::string& RemainingString();
std::string FilterNextToken(const std::string& filterStr);
private:
std::string token_str;
std::string delim;
};
/**
* @class NFTokenizerW
* @brief 유니코드용 Tokenizer
* @remarks
* Nave::String tempStr = L"01|02|03|04|05|06|07|08|09|10|11|12"; \r\n
* \r\n
* Nave::NFTokenizer strtok = Nave::NFTokenizer(tempStr, L"|"); \r\n
* \r\n
* LOG_IMPORTANT((L"Number Of Tokens: %d"), strtok.CountTokens()); \r\n
* LOG_IMPORTANT((L"String: %s"), strtok.RemainingString().c_str()); \r\n
* \r\n
* int cnt = strtok.CountTokens(); \r\n
* Nave::String finalString = L""; \r\n
* \r\n
* for(int i = 0; i < cnt; i++) \r\n
* { \r\n
* Nave::String tempStr = L""; \r\n
* \r\n
* LOG_IMPORTANT((L"Token[%d] ----> [%s]"), i, strtok.NextToken().c_str());\r\n
* LOG_IMPORTANT((L"Token Count : %d"), strtok.CountTokens()); \r\n
* \r\n
* finalString += tempStr; \r\n
* } \r\n
* \r\n
* LOG_IMPORTANT((L"Final String : %s"), finalString.c_str());
* @par
* @author Edith
* @date 2009-04-05
*/
class NFTokenizerW
{
public:
NFTokenizerW(const std::wstring& _str, const std::wstring& _delim);
~NFTokenizerW(){};
int CountTokens();
bool HasMoreTokens();
std::wstring NextToken();
int NextIntToken();
double NextFloatToken();
std::wstring NextToken(const std::wstring& delim);
std::wstring& RemainingString();
std::wstring FilterNextToken(const std::wstring& filterStr);
private:
std::wstring token_str;
std::wstring delim;
};
typedef NFTokenizerW NFTokenizer;
}

View File

@@ -0,0 +1,93 @@
/**
* @file NFTypes.h
* @brief Nave Basic Type 선언
* @remarks
* @author 강동명(edith2580@gmail.com)
* @date 2009-04-02
*/
#pragma once
#include <string>
#include <d3dx9math.h>
#include <atltypes.h>
#pragma warning (disable : 4996)
namespace Nave {
/*
int * signed, signed int System dependent
unsigned int * unsigned System dependent
__int8 1 char, signed char -128 to 127
__int16 2 short, short int, signed short int -32,768 to 32,767
__int32 4 signed, signed int -2,147,483,648 to 2,147,483,647
__int64 8 none -9,223,372,036,854,775,808 to 9,223,372,036,854,775,807
bool 1 none false or true
char 1 signed char -128 to 127
unsigned char 1 none 0 to 255
short 2 short int, signed short int -32,768 to 32,767
unsigned short 2 unsigned short int 0 to 65,535
long 4 long int, signed long int -2,147,483,648 to 2,147,483,647
long long 8 none (but equivalent to __int64) -9,223,372,036,854,775,808 to 9,223,372,036,854,775,807
unsigned long 4 unsigned long int 0 to 4,294,967,295
enum * none Same as int
float 4 none 3.4E +/- 38 (7 digits)
double 8 none 1.7E +/- 308 (15 digits)
long double same as double none same as double
wchar_t 2 __wchar_t 0 to 65,535
strlen _tcslen
strcpy _tcscpy
strncpy _tcsncpy
strcat _tcscat
strcmp _tcscmp
strncmp _tcsncmp
stricmp _tcsicmp
strnicmp _tcsnicmp
sscanf _stscanf
strtok _tcstok
_strdate _tstrdate
_strtime _tstrtime
sprintf _stprintf
printf _tprintf
atoi _tstoi
atof _tstof
fopen _tfopen
fprintf _ftprintf
fgets _fgetts
*/
// AddFontResource : 특정경로의 ttf폰트를 로드한다, 다한다음 ReleaseAddFone 해줘야한다.
// res = AddFontResource("C:\Fonts\Nordic__.ttf")
// 폰트리스트 EnumFontFamilies
// gdi+에서 폰트등록 PrivateFontCollection::AddFontFile(...)
// basic value types
typedef std::wstring StringW; /// std::wstring
typedef std::string StringA; /// std::string
typedef StringW String; /// default string
typedef char int8; /// -128 to 127
typedef short int16; /// -32,768 to 32,767
typedef long int32; /// -2,147,483,648 to 2,147,483,647
typedef __int64 int64; /// -9,223,372,036,854,775,808 to 9,223,372,036,854,775,807
typedef unsigned char uint8; /// 0 to 255
typedef unsigned short int uint16; /// 0 to 65535
typedef unsigned long uint32; /// 0 to 4,294,967,295
typedef unsigned __int64 uint64; /// 0 to 18,446,744,073,709,551,615
typedef D3DXVECTOR2 float2; /// 2vector float
typedef D3DXVECTOR3 float3; /// 3vector float
typedef D3DXVECTOR4 float4; /// 4vector float
}

View File

@@ -0,0 +1,396 @@
#include "Nave.h"
namespace Nave {
HWND hMainWnd = NULL;
HINSTANCE hInstance = NULL;
void EnableLFH()
{
HANDLE hHeap[1025];
UINT uEA = GetProcessHeaps(1024, hHeap);
for (UINT i=0; i<uEA; ++i)
{
ULONG HeapFragValue = 2;
HeapSetInformation(hHeap[i],
HeapCompatibilityInformation,
&HeapFragValue,
sizeof(HeapFragValue) );
}
}
void SetLocale(CHAR* pLocale)
{
::setlocale(LC_ALL, pLocale);
}
DWORD GetGUID()
{
static DWORD s_dwPerGUID = 0;
return ++s_dwPerGUID;
}
SIZE GetStringSize( const WCHAR* string, HFONT font )
{
HWND hWnd = Nave::hMainWnd;
HDC hDC = ::GetDC(hWnd);
SIZE size;
HFONT hOldFont = (HFONT)SelectObject(hDC, font);
GetTextExtentPoint32W(hDC, string, (INT)wcslen(string), &size);
TEXTMETRICW tm;
GetTextMetricsW(hDC, &tm);
size.cx -= tm.tmOverhang;
SelectObject(hDC, hOldFont);
::ReleaseDC(hWnd, hDC);
return size;
}
POINT GetMousePos()
{
POINT Point;
GetCursorPos(&Point);
ScreenToClient(hMainWnd, &Point);
return Point;
}
POINT GetMousePos( HWND wnd )
{
POINT Point;
GetCursorPos(&Point);
ScreenToClient(wnd, &Point);
return Point;
}
HWND IsWindowFromPoint()
{
POINT Point;
GetCursorPos(&Point);
return WindowFromPoint(Point);
}
INT GetProgramName( LPWSTR buf, INT len )
{
WCHAR szDrive[MAX_PATH], szDir[MAX_PATH], szFilename[MAX_PATH], szExt[MAX_PATH];
// Figure out what the report file will be named, and store it away
GetModuleFileNameW(0, buf, len);
LPWSTR pszDot = buf;
// Look for the '.' before the "EXE" extension. Replace '.' to '\0'
if((pszDot = wcsrchr( pszDot, L'.')))
{
*pszDot = 0;
}
_wsplitpath(buf, szDrive, szDir, szFilename, szExt);
wcsncpy(buf, szFilename, len);
return (INT)wcslen( buf );
}
INT GetProgramDir( LPWSTR buf, INT len )
{
WCHAR* ProgDir;
INT result;
result = GetModuleFileNameW( hInstance, buf, len - 1 );
if( result == 0 )
return 0;
WCHAR pgmPtr[1024];
wcscpy( pgmPtr, buf );
ProgDir = buf;
ProgDir += wcslen( pgmPtr ) - 1;
while( *ProgDir != L'\\' && ProgDir != pgmPtr )
ProgDir--;
*ProgDir = 0;
return (INT)wcslen( buf );
}
INT GetDir( LPCWSTR path, LPWSTR buf )
{
wcscpy(buf, path);
WCHAR* ProgDir;
ProgDir = buf;
ProgDir += wcslen(buf);
while( *ProgDir != L'\\')
{
ProgDir[0] = 0;
ProgDir--;
}
ProgDir[0] = 0;
return (INT)wcslen( buf );
}
BOOL GetLine( const CHAR* sBuf, INT maxsBuf, CHAR* tBuf, INT maxtBuf, LONG& index )
{
ZeroMemory(tBuf, sizeof(tBuf));
INT DestIndex = index;
CHAR* pLine = "\n";
INT pLen = strlen(pLine);
for(INT i = 0; i < maxsBuf; i++)
{
if(index+i >= maxtBuf)
break;
if(strncmp(&sBuf[index+i], pLine, pLen) == 0)
{
CopyMemory(tBuf, sBuf+index, i);
index += (i+pLen);
tBuf[i] = 0;
return TRUE;
}
}
INT len = maxsBuf-index;
if(maxtBuf <= len)
len = maxtBuf-index;
CopyMemory(tBuf, sBuf+index, len);
tBuf[len] = 0;
index += len;
return FALSE;
}
VOID GetString( const CHAR* sBuf, CHAR* tBuf, INT len, LONG& index )
{
CopyMemory(tBuf, sBuf+index, len);
tBuf[len] = 0;
index += len;
}
BYTE GetByte( const CHAR* sBuf, LONG& index )
{
INT t_index = index;
index += sizeof(BYTE);
return *(BYTE*)(sBuf+t_index);
}
SHORT GetShort( const CHAR* sBuf, LONG& index )
{
INT t_index = index;
index += sizeof(SHORT);
return *(SHORT*)(sBuf+t_index);
}
INT GetInt( const CHAR* sBuf, LONG& index )
{
INT t_index = index;
index += sizeof(INT);
return *(INT*)(sBuf+t_index);
}
DWORD GetDWORD( const CHAR* sBuf, LONG& index )
{
INT t_index = index;
index += sizeof(DWORD);
return *(DWORD*)(sBuf+t_index);
}
FLOAT GetFloat( const CHAR* sBuf, LONG& index )
{
INT t_index = index;
index += sizeof(FLOAT);
return *(FLOAT*)(sBuf+t_index);
}
DOUBLE GetDouble( const CHAR* sBuf, LONG& index )
{
INT t_index = index;
index += sizeof(DOUBLE);
return *(DOUBLE*)(sBuf+t_index);
}
VOID SetString( CHAR* tBuf, const CHAR* sBuf, INT len, LONG& index )
{
CopyMemory(tBuf+index, sBuf, len);
index += len;
}
VOID SetByte( CHAR* tBuf, BYTE sByte, LONG& index )
{
*(tBuf+index) = (BYTE)sByte;
index++;
}
VOID SetShort( CHAR* tBuf, SHORT sShort, LONG& index )
{
SHORT temp = (SHORT)sShort;
CopyMemory( tBuf+index, &temp, sizeof(SHORT));
index += sizeof(SHORT);
}
VOID SetInt( CHAR* tBuf, INT sInt, LONG& index )
{
CopyMemory( tBuf+index, &sInt, sizeof(INT));
index += sizeof(INT);
}
VOID SetDWORD( CHAR* tBuf, DWORD sDword, LONG& index )
{
CopyMemory( tBuf+index, &sDword, sizeof(DWORD));
index += sizeof(DWORD);
}
VOID SetFloat( CHAR* tBuf, FLOAT sFloat, LONG& index )
{
CopyMemory( tBuf+index, &sFloat, sizeof(FLOAT));
index += sizeof(FLOAT);
}
VOID SetDouble( CHAR* tBuf, DOUBLE sDouble, LONG& index )
{
CopyMemory( tBuf+index, &sDouble, sizeof(DOUBLE));
index += sizeof(DOUBLE);
}
BOOL GetLine( const WCHAR* sBuf, INT maxsBuf, WCHAR* tBuf, INT maxtBuf, LONG& index )
{
ZeroMemory(tBuf, sizeof(tBuf));
INT DestIndex = index;
WCHAR* pLine = L"\n";
INT pLen = wcslen(pLine);
for(INT i = 0; i < maxsBuf; i++)
{
if(index+i >= maxtBuf)
break;
if(wcsncmp(&sBuf[index+i], pLine, pLen) == 0)
{
CopyMemory(tBuf, sBuf+index, sizeof(WCHAR)*i);
index += (i+pLen);
tBuf[index-1] = 0;
return TRUE;
}
}
INT len = maxsBuf-index;
CopyMemory(tBuf, sBuf+index, sizeof(WCHAR)*len);
tBuf[len] = 0;
index += len;
return FALSE;
}
VOID GetString( const WCHAR* sBuf, WCHAR* tBuf, INT len, LONG& index )
{
CopyMemory(tBuf, sBuf+index, sizeof(WCHAR)*len);
tBuf[len] = 0;
index += len;
}
BYTE GetByte( const WCHAR* sBuf, LONG& index )
{
INT t_index = index;
index += sizeof(BYTE);
return *(BYTE*)(sBuf+t_index);
}
SHORT GetShort( const WCHAR* sBuf, LONG& index )
{
INT t_index = index;
index += sizeof(SHORT);
return *(SHORT*)(sBuf+t_index);
}
INT GetInt( const WCHAR* sBuf, LONG& index )
{
INT t_index = index;
index += sizeof(INT);
return *(INT*)(sBuf+t_index);
}
DWORD GetDWORD( const WCHAR* sBuf, LONG& index )
{
INT t_index = index;
index += sizeof(DWORD);
return *(DWORD*)(sBuf+t_index);
}
FLOAT GetFloat( const WCHAR* sBuf, LONG& index )
{
INT t_index = index;
index += sizeof(FLOAT);
return *(FLOAT*)(sBuf+t_index);
}
DOUBLE GetDouble( const WCHAR* sBuf, LONG& index )
{
INT t_index = index;
index += sizeof(DOUBLE);
return *(DOUBLE*)(sBuf+t_index);
}
VOID SetString( WCHAR* tBuf, const WCHAR* sBuf, INT len, LONG& index )
{
CopyMemory(tBuf+index, sBuf, sizeof(WCHAR)*len);
index += len;
}
VOID SetByte( WCHAR* tBuf, BYTE sByte, LONG& index )
{
*(tBuf+index) = (BYTE)sByte;
index++;
}
VOID SetShort( WCHAR* tBuf, SHORT sShort, LONG& index )
{
SHORT temp = (SHORT)sShort;
CopyMemory( tBuf+index, &temp, sizeof(SHORT));
index += sizeof(SHORT);
}
VOID SetInt( WCHAR* tBuf, INT sInt, LONG& index )
{
CopyMemory( tBuf+index, &sInt, sizeof(INT));
index += sizeof(INT);
}
VOID SetDWORD( WCHAR* tBuf, DWORD sDword, LONG& index )
{
CopyMemory( tBuf+index, &sDword, sizeof(DWORD));
index += sizeof(DWORD);
}
VOID SetFloat( WCHAR* tBuf, FLOAT sFloat, LONG& index )
{
CopyMemory( tBuf+index, &sFloat, sizeof(FLOAT));
index += sizeof(FLOAT);
}
VOID SetDouble( WCHAR* tBuf, DOUBLE sDouble, LONG& index )
{
CopyMemory( tBuf+index, &sDouble, sizeof(DOUBLE));
index += sizeof(DOUBLE);
}
VOID Read( const char* sBuf, void* tBuf, INT len, LONG& seek )
{
CopyMemory(tBuf, &sBuf[seek], len);
seek += len;
}
VOID Write( const void* sBuf, char* tBuf, INT len, LONG& seek )
{
CopyMemory(&tBuf[seek], sBuf, len);
seek += len;
}
}

View File

@@ -0,0 +1,436 @@
/**
* @file Nave.h
* @brief Nave Library Core Header
* @remarks NaveGDK 라이브러리의 선언부 Header
* @author 강동명(edith2580@gmail.com)
* @date 2009-04-02
*/
#pragma once
/// 거의 사용되지 않는 내용은 Windows 헤더에서 제외합니다.
#define WIN32_LEAN_AND_MEAN
#pragma comment(lib,"winmm.lib")
#pragma comment(lib,"imm32.lib")
#include <windows.h>
#include <mmsystem.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <memory.h>
#include <WCHAR.h>
#include <stddef.h>
#include <conio.h>
#include "NFTypes.h"
#include "NFSingleton.h"
/// 문자열 앞에 L을 연결하여 WCHAR 타입으로 변환함
#define WIDEN2(x) L ## x
/// CHAR의 값을 WCHAR로 변환하기 위한 정의
#define WIDEN(x) WIDEN2(x)
/// __FILE__ 의 WCHAR형 정의
#define __WFILE__ WIDEN(__FILE__)
/// __FUNCSIG__ 의 WCHAR형 정의
#define __WFUNCSIG__ WIDEN(__FUNCSIG__)
/// 단일 객체 DELETE 디파인
#ifndef _DELETE
#define _DELETE(p) { if(p) { delete (p); (p)=NULL; } }
#endif
/// 배열형 객체 DELETE 디파인
#ifndef _DELETE_ARRAY
#define _DELETE_ARRAY(p) { if(p) { delete[] (p); (p)=NULL; } }
#endif
/// RELEASE 디파인
#ifndef _RELEASE
#define _RELEASE(p) { if(p) { (p)->Release(); (p)=NULL; } }
#endif
/// MAKEINTRESOURCE 재정의
#define MIS(a) MAKEINTRESOURCEW(a)
/// InvalidateRect 재정의
#define Redraw(hWnd, bErase) InvalidateRect(hWnd, NULL, bErase)
/// DWORD 에서 Alpha 구하기
#define GetAColor(Color) ((BYTE)((Color)>>24)&0xff)
/// DWORD 에서 Red 구하기
#define GetRColor(Color) ((BYTE)((Color)>>16)&0xff)
/// DWORD 에서 Green 구하기
#define GetGColor(Color) ((BYTE)(((WORD)(Color)) >> 8)&0xff)
/// DWORD 에서 Blue 구하기
#define GetBColor(Color) ((BYTE)(Color)&0xff)
namespace Nave {
/// 메인 윈도우 핸들
extern HWND hMainWnd;
/// 윈도으의 인스턴스
extern HINSTANCE hInstance;
/**
* @brief LFH 메모리풀을 사용한다
* @remarks
* Low-Fragmentation Heap의 사용 \r\n
* 프로그램이 시작할때 한번호출해준다. \r\n
* 디버거가 연결되면(F5) 디버그 힙을 사용하므로 CTRL+F5를 눌러야 \r\n
* Low-Fragmentation Heap이 사용되고, TRUE가 리턴되는것을 알수있다. \r\n
* \r\n
* Low-Fragmentation Heap의 장점 \r\n
* 특별히 프로그래머는 신경쓰지 않아도, 메모리풀을 사용, \r\n
* 프로그램의 질을 높일수있다. \r\n
* 메모리 단편화를 예방할수있고, 힙메모리생성, 삭제시 효율이 높아진다. \r\n
* 특히, 멀티코어 시스템에서 높은 성능향상이 있다. \r\n
* \r\n
* Low-Fragmentation Heap사용시 참고 \r\n
* 이 함수가 호출되지 않아도, 이코드가 있으면 Win2000Pro Sp4이상의 \r\n
* OS에서만 동작하므로, Win98을 지원하려고 한다면, 주석화시켜야 한다. \r\n
* \r\n
* 비스타는 이함수를 호출하지 않아도 기본동작한다. \r\n
* 16K보다 작은 메모리를 할당하면, LFH에 메모리가 할당, \r\n
* 그이상은 기존힙에서 할당된다. \r\n
*/
void EnableLFH();
/**
* @brief 프로그램의 국가언어 정보를 설정합니다.
* @param pLocale 언어명
* @remarks wprintf 등 유니코드 문자열을 콘솔에 출력하기 위해서는 로케일 설정을 해야함. \r\n
* 한국어 : Korean \r\n
* 영어 : English \r\n
*/
void SetLocale(CHAR* pLocale);
/**
* @brief 게임에서 사용할 Object의 GUID를 얻어온다
* @return 생성된 GUID값 0x00000001 ~ 0xFFFFFFFF 까지
*/
DWORD GetGUID();
/**
* @brief String의 크기Pixel을 구한다.
* @param string 사이즈를 구할 스트링
* @param font 사용할 폰트
* @return 얻어진 String의 크기
*/
SIZE GetStringSize( const WCHAR* string, HFONT font );
/**
* @brief 윈도우 커서를 가져온다.
* @return Main윈도우에서의 마우스 포지션
* @warning Nave::hMainWnd 가 설정되어있어야한다.
*/
POINT GetMousePos();
/**
* @brief 윈도우 커서를 가져온다.
* @param wnd 윈도우 핸들
* @return 윈도우에서의 마우스 포지션
*/
POINT GetMousePos( HWND wnd );
/**
* @brief 현재 마우스가 어느 윈도우에 올라가 있는지
* @return 마우스가 존재하는 윈도우의 핸들
*/
HWND IsWindowFromPoint();
/**
* @brief 현재 프로그램의 이름을 구한다
* @param buf 어플리케이션의 이름을 저장할 버퍼
* @param len 버퍼의 크기
* @return 어플리케이션 이름의 길이
*/
INT GetProgramName( LPWSTR buf, INT len );
/**
* @brief 현재 프로그램의 경로를 구한다.
* @param buf 어플리케이션의 디렉토리를 저장할 버퍼
* @param len 버퍼의 크기
* @return 어플리케이션 디렉토리의 길이
*/
INT GetProgramDir( LPWSTR buf, INT len );
/**
* @brief Path에서 경로를 구한다
* @param path 경로 정보
* @param buf 경로에서 구한 디렉토리
* @return 디렉토리의 길이
*/
INT GetDir( LPCWSTR path, LPWSTR buf );
/**
* @brief 문자열에서 1Line을 읽어들인다 한라인은 \n으로 구분된다.
* @param sBuf 소스 버퍼
* @param maxsBuf 소스 버퍼 크기
* @param tBuf 저장 버퍼
* @param maxtBuf 저장 버퍼 크기
* @param index 소스 버퍼에서 읽어들일 시작위치
* @return 성공여부
*/
BOOL GetLine( const CHAR* sBuf, INT maxsBuf, CHAR* tBuf, INT maxtBuf, LONG& index );
/**
* @brief 문자열을 읽어들인다.
* @param sBuf 소스 버퍼
* @param tBuf 저장 버퍼
* @param len 저장 버퍼 크기
* @param index 소스 버퍼에서 읽어들일 시작위치
*/
VOID GetString( const CHAR* sBuf, CHAR* tBuf, INT len, LONG& index );
/**
* @brief 1바이트를 읽어들인다.
* @param sBuf 소스 버퍼
* @param index 소스 버퍼에서 읽어들일 시작위치
* @return BYTE 결과값
*/
BYTE GetByte( const CHAR* sBuf, LONG& index );
/**
* @brief 2바이트를 읽어들인다.
* @param sBuf 소스 버퍼
* @param index 소스 버퍼에서 읽어들일 시작위치
* @return SHORT 결과값
*/
SHORT GetShort( const CHAR* sBuf, LONG& index );
/**
* @brief 4바이트를 읽어들인다.
* @param sBuf 소스 버퍼
* @param index 소스 버퍼에서 읽어들일 시작위치
* @return INT 결과값
*/
INT GetInt( const CHAR* sBuf, LONG& index );
/**
* @brief 4바이트 읽어들인다.
* @param sBuf 소스 버퍼
* @param index 소스 버퍼에서 읽어들일 시작위치
* @return DWORD 결과값
*/
DWORD GetDWORD( const CHAR* sBuf, LONG& index );
/**
* @brief 4바이트를 읽어들인다.
* @param sBuf 소스 버퍼
* @param index 소스 버퍼에서 읽어들일 시작위치
* @return FLOAT 결과값
*/
FLOAT GetFloat( const CHAR* sBuf, LONG& index );
/**
* @brief 8바이트를 읽어들인다.
* @param sBuf 소스 버퍼
* @param index 소스 버퍼에서 읽어들일 시작위치
* @return DOUBLE 결과값
*/
DOUBLE GetDouble( const CHAR* sBuf, LONG& index );
/**
* @brief 문자열을 셋팅한다
* @param tBuf 저장 버퍼
* @param sBuf 저장할 값
* @param len 저장할 길이
* @param index 저장 버퍼에서 저장될 시작위치
*/
VOID SetString( CHAR* tBuf, const CHAR* sBuf, INT len, LONG& index );
/**
* @brief 1바이트 BYTE를 셋팅한다.
* @param tBuf 저장 버퍼
* @param sByte 저장할 값
* @param index 저장 버퍼에서 저장될 시작위치
*/
VOID SetByte( CHAR* tBuf, BYTE sByte, LONG& index );
/**
* @brief 2바이트 SHORT를 셋팅한다.
* @param tBuf 저장 버퍼
* @param sShort 저장할 값
* @param index 저장 버퍼에서 저장될 시작위치
*/
VOID SetShort( CHAR* tBuf, SHORT sShort, LONG& index );
/**
* @brief 4바이트 INT를 셋팅한다.
* @param tBuf 저장 버퍼
* @param sInt 저장할 값
* @param index 저장 버퍼에서 저장될 시작위치
*/
VOID SetInt( CHAR* tBuf, INT sInt, LONG& index);
/**
* @brief 4바이트 DWORD를 셋팅한다.
* @param tBuf 저장 버퍼
* @param sDword 저장할 값
* @param index 저장 버퍼에서 저장될 시작위치
*/
VOID SetDWORD( CHAR* tBuf, DWORD sDword, LONG& index );
/**
* @brief 4바이트 FLOAT를 셋팅한다.
* @param tBuf 저장 버퍼
* @param sFloat 저장할 값
* @param index 저장 버퍼에서 저장될 시작위치
*/
VOID SetFloat( CHAR* tBuf, FLOAT sFloat, LONG& index );
/**
* @brief 8바이트 double를 셋팅한다.
* @param tBuf 저장 버퍼
* @param sDouble 저장할 값
* @param index 저장 버퍼에서 저장될 시작위치
*/
VOID SetDouble( CHAR* tBuf, DOUBLE sDouble, LONG& index );
/**
* @brief 문자열에서 1Line을 읽어들인다 한라인은 \n으로 구분된다.
* @param sBuf 소스 버퍼
* @param maxsBuf 소스 버퍼 크기
* @param tBuf 저장 버퍼
* @param maxtBuf 저장 버퍼 크기
* @param index 소스 버퍼에서 읽어들일 시작위치
* @return 성공여부
*/
BOOL GetLine( const WCHAR* sBuf, INT maxsBuf, WCHAR* tBuf, INT maxtBuf, LONG& index );
/**
* @brief 문자열을 읽어들인다.
* @param sBuf 소스 버퍼
* @param tBuf 저장 버퍼
* @param len 저장 버퍼 크기
* @param index 소스 버퍼에서 읽어들일 시작위치
*/
VOID GetString( const WCHAR* sBuf, WCHAR* tBuf, INT len, LONG& index );
/**
* @brief 1바이트를 읽어들인다.
* @param sBuf 소스 버퍼
* @param index 소스 버퍼에서 읽어들일 시작위치
* @return BYTE 결과값
*/
BYTE GetByte( const WCHAR* sBuf, LONG& index );
/**
* @brief 2바이트를 읽어들인다.
* @param sBuf 소스 버퍼
* @param index 소스 버퍼에서 읽어들일 시작위치
* @return SHORT 결과값
*/
SHORT GetShort( const WCHAR* sBuf, LONG& index );
/**
* @brief 4바이트를 읽어들인다.
* @param sBuf 소스 버퍼
* @param index 소스 버퍼에서 읽어들일 시작위치
* @return INT 결과값
*/
INT GetInt( const WCHAR* sBuf, LONG& index );
/**
* @brief 4바이트 읽어들인다.
* @param sBuf 소스 버퍼
* @param index 소스 버퍼에서 읽어들일 시작위치
* @return DWORD 결과값
*/
DWORD GetDWORD( const WCHAR* sBuf, LONG& index );
/**
* @brief 4바이트를 읽어들인다.
* @param sBuf 소스 버퍼
* @param index 소스 버퍼에서 읽어들일 시작위치
* @return FLOAT 결과값
*/
FLOAT GetFloat( const WCHAR* sBuf, LONG& index );
/**
* @brief 8바이트를 읽어들인다.
* @param sBuf 소스 버퍼
* @param index 소스 버퍼에서 읽어들일 시작위치
* @return DOUBLE 결과값
*/
DOUBLE GetDouble( const WCHAR* sBuf, LONG& index );
/**
* @brief 문자열을 셋팅한다
* @param tBuf 저장 버퍼
* @param sBuf 저장할 값
* @param len 저장할 길이
* @param index 저장 버퍼에서 저장될 시작위치
*/
VOID SetString( WCHAR* tBuf, const WCHAR* sBuf, INT len, LONG& index );
/**
* @brief 1바이트 BYTE를 셋팅한다.
* @param tBuf 저장 버퍼
* @param sByte 저장할 값
* @param index 저장 버퍼에서 저장될 시작위치
*/
VOID SetByte( WCHAR* tBuf, BYTE sByte, LONG& index );
/**
* @brief 2바이트 SHORT를 셋팅한다.
* @param tBuf 저장 버퍼
* @param sShort 저장할 값
* @param index 저장 버퍼에서 저장될 시작위치
*/
VOID SetShort( WCHAR* tBuf, SHORT sShort, LONG& index );
/**
* @brief 4바이트 INT를 셋팅한다.
* @param tBuf 저장 버퍼
* @param sInt 저장할 값
* @param index 저장 버퍼에서 저장될 시작위치
*/
VOID SetInt( WCHAR* tBuf, INT sInt, LONG& index);
/**
* @brief 4바이트 DWORD를 셋팅한다.
* @param tBuf 저장 버퍼
* @param sDword 저장할 값
* @param index 저장 버퍼에서 저장될 시작위치
*/
VOID SetDWORD( WCHAR* tBuf, DWORD sDword, LONG& index );
/**
* @brief 4바이트 FLOAT를 셋팅한다.
* @param tBuf 저장 버퍼
* @param sFloat 저장할 값
* @param index 저장 버퍼에서 저장될 시작위치
*/
VOID SetFloat( WCHAR* tBuf, FLOAT sFloat, LONG& index );
/**
* @brief 8바이트 double를 셋팅한다.
* @param tBuf 저장 버퍼
* @param sDouble 저장할 값
* @param index 저장 버퍼에서 저장될 시작위치
*/
VOID SetDouble( WCHAR* tBuf, DOUBLE sDouble, LONG& index );
/**
* @brief 바이너리 정보를 Read 들입니다.
* @param sBuf 소스 버퍼
* @param tBuf 저장 버퍼
* @param len 읽을 길이
* @param seek 소스 버퍼에서 읽을 시작위치
*/
VOID Read( const char* sBuf, void* tBuf, INT len, LONG& seek );
/**
* @brief 바이너리 정보를 Write 합니다.
* @param sBuf 저장 버퍼
* @param tBuf 저장할 값
* @param len 저장할 길이
* @param seek 저장 버퍼에서 저장될 시작위치
*/
VOID Write( const void* sBuf, char* tBuf, INT len, LONG& seek );
}