📄 jxinifile.cpp
字号:
/************************************
REVISION LOG ENTRY
Written and Revision By: Zhang, Zhefu
Contact: codetiger@hotmail
URL: http://www.chi.c.dendai.ac.jp/~zhang/index.htm
Revised on 2001/09/27 in FujiSoftABC Ltd. Japan
Comment: JXINIFile Implementation File
************************************/
//
//
//Last Modified 2001/9/4
//Reason: NotePad add 0xFF FE to the text file header, make the first
// section unrecognizable.
//Fixment: Add member m_pTrueData to pass the 2 byte head
#include "stdAfx.h"
#include "JXIniFile.h"
//dwSize = -1 if szMultiByte null terminated
//dwSize not include the ending null
//return WCHARs
LPWSTR _A2W(LPSTR szMultiByte, DWORD dwSize, DWORD& dwRetSize)
{
static WCHAR szInternalBuffer[8096];
if(szMultiByte == NULL || (dwSize == -1 && ::strlen(szMultiByte) == 0))
{ dwRetSize = 0; return NULL; }
int nLen = MultiByteToWideChar(CP_ACP, 0,szMultiByte, dwSize, NULL, NULL);
if(nLen > 8096) { dwRetSize = 0; return NULL; }
//dwRetSize in WCHARs, include null if szMultiByte nulled ended
dwRetSize = MultiByteToWideChar(CP_ACP, 0, szMultiByte, dwSize, szInternalBuffer, 8096);
if(dwSize == -1)
dwRetSize--;
else
szInternalBuffer[dwRetSize] = WCHAR('\0');
return szInternalBuffer;
}
//return BYTEs
LPSTR _W2A(LPWSTR szUnicode, DWORD dwSize, DWORD& dwRetSize)
{
static char szInternalBuffer[8096];
if(szUnicode == NULL || (dwSize == -1 && ::wcslen(szUnicode) == 0))
{ dwRetSize = 0; return NULL; }
int nLen = WideCharToMultiByte(CP_ACP, 0,szUnicode, dwSize, NULL, 0, NULL, FALSE);
if(nLen > 8096) { dwRetSize = 0; return NULL; }
//Ret: in BYTEs, The number includes the byte for the null terminator. if szUnicode null ended
dwRetSize = WideCharToMultiByte(CP_ACP, 0, szUnicode, dwSize, szInternalBuffer, nLen, NULL, FALSE);
if(dwSize == -1) //dwRetSize include null, szInternalBuffer null ended
dwRetSize--;
else
szInternalBuffer[dwRetSize] = char('\0');
return szInternalBuffer;
}
CJXINIFile::CJXINIFile()
{
m_strFilename = _T("");
m_hFile = INVALID_HANDLE_VALUE;
m_hMMF = NULL;
m_dwSize = 0;
m_pData = 0;
m_bSectionMapDirty = TRUE; //No Section Map
m_bSectionMapLock = FALSE;
m_mapSection.InitHashTable(700, TRUE);
}
CJXINIFile::~CJXINIFile()
{
UnloadIniFile();
if(m_pData)
{
::UnmapViewOfFile(m_pData);
m_pData = NULL;
}
if(m_hMMF != NULL)
{
::CloseHandle(m_hMMF);
m_hMMF = NULL;
}
if(m_hFile != INVALID_HANDLE_VALUE)
{
::CloseHandle(m_hFile);
m_hFile = INVALID_HANDLE_VALUE;
}
}
//CMap m_mapSection;
void CJXINIFile::UpdateMapA()
{
if(m_bSectionMapLock) return;
LPSTR pHead = (LPSTR)m_pTrueData;
LPSTR p1 = pHead;
LPSTR p2 = pHead;
p1 = pHead;
while(p1- pHead < (int)(m_dwUseSize/sizeof(char)) - 1)
{
while(p1- pHead < (int)(m_dwUseSize/sizeof(char)) - 1 &&
*p1 != char('['))
p1++;
p2 = p1;
while(p2- pHead < (int)(m_dwUseSize/sizeof(char)) - 1 &&
*p2 != char(']'))
p2++;
if(p1- pHead < (int)(m_dwUseSize/sizeof(char)) &&
p2- pHead < (int)(m_dwUseSize/sizeof(char)))
{
//Found, Ready To Map
int lenSection = p2 - p1 - 1;
//Section Name Length must >= 1
if(lenSection >= 1)
{
p1++;
CString strSection;
#ifdef _UNICODE
DWORD dwRetSize;
PWSTR pTemp = _A2W(p1, lenSection, dwRetSize);
::wcsncpy(strSection.GetBuffer(dwRetSize), pTemp, dwRetSize);
strSection.ReleaseBuffer(dwRetSize);
#else
::strncpy(strSection.GetBuffer(lenSection), p1, lenSection);
strSection.ReleaseBuffer(lenSection);
#endif
p1--; //point to [
m_mapSection.SetAt(strSection, (LPVOID)p1);
}
}
p1 = p2 + 1;
}
//Debug Part
m_bSectionMapDirty = FALSE;
return ;
}
void CJXINIFile::UpdateMapW()
{
if(m_bSectionMapLock) return;
LPWSTR pHead = (LPWSTR)m_pTrueData;
LPWSTR p1 = pHead;
LPWSTR p2 = pHead;
//Calculate the section number
// int nSection = 0;
// while(p1- pHead < (int)(m_dwUseSize/sizeof(WCHAR)) - 1)
// {
// if(*p1 == WCHAR('[')) nSection++;
// p1++;
// }
// if(nSection < 13) nSection = 13;
// //allow 20% margine
// m_mapSection.InitHashTable((UINT)(1.2*nSection), TRUE);
p1 = pHead;
while(p1- pHead < (int)(m_dwUseSize/sizeof(WCHAR)) - 1)
{
while(p1- pHead < (int)(m_dwUseSize/sizeof(WCHAR)) - 1 &&
*p1 != WCHAR('['))
p1++;
p2 = p1;
while(p2- pHead < (int)(m_dwUseSize/sizeof(WCHAR)) - 1 &&
*p2 != WCHAR(']'))
p2++;
if(p1- pHead < (int)(m_dwUseSize/sizeof(WCHAR)) &&
p2- pHead < (int)(m_dwUseSize/sizeof(WCHAR)))
{
//Found, Ready To Map
int lenSection = p2 - p1 - 1;
//Section Name Length must >= 1
if(lenSection >= 1)
{
p1++;
CString strSection;
#ifdef _UNICODE
::wcsncpy(strSection.GetBuffer(lenSection), p1, lenSection);
strSection.ReleaseBuffer(lenSection);
#else
DWORD dwRetSize;
PSTR pTemp = _W2A(p1, lenSection, dwRetSize);
::strncpy(strSection.GetBuffer(dwRetSize), pTemp, dwRetSize);
strSection.ReleaseBuffer(dwRetSize);
#endif
p1--; //point to [
m_mapSection.SetAt(strSection, (LPVOID)p1);
}
}
p1 = p2 + 1;
}
//Debug Part
m_bSectionMapDirty = FALSE;
// int count = m_mapSection.GetCount();
// CString str; str.Format(_T("UpdateW %d"), count);
// AfxMessageBox(str);
/*
POSITION pos = m_mapSection.GetStartPosition();
while(pos)
{
CString strKey;
LPVOID lpPos;
m_mapSection.GetNextAssoc(pos, strKey, lpPos);
if(AfxMessageBox(strKey, MB_YESNO | MB_ICONINFORMATION) == IDNO)
return;
}
*/
return ;
}
void CJXINIFile::ResizeMap(int nNewSize)
{
ASSERT(nNewSize > 0);
m_mapSection.RemoveAll();
m_mapSection.InitHashTable(nNewSize);
}
// return 0 -- no key, size too small to put value
//return -1 -- error
//return string length (of course > 1)
//Ex Version use Map
DWORD CJXINIFile::GetPrivateProfileStringExA(
LPCSTR lpAppName, // section name
LPCSTR lpKeyName, // key name
LPCSTR lpDefault, // default string
LPSTR lpReturnedString, // destination buffer
DWORD nSize,
// size of destination buffer,Specifies the size, in TCHARs,
LPCSTR lpFileName // initialization file name
)
{
BOOL bRet = LoadIniFile(lpFileName, 1);
if(!bRet) return (UINT)-1;
if(lpDefault == NULL) return -1;
if(m_dwUseSize == 0) return -1;
//Section Map Not Available
if(m_bSectionMapDirty && m_bSectionMapLock) //
return GetPrivateProfileStringA(lpAppName,lpKeyName,
lpDefault,lpReturnedString,nSize,lpFileName);
else if(!m_bSectionMapLock && m_bSectionMapDirty)
{
UpdateMapA();
}
//AfxMessageBox(_T("Using Section Map"));
//Now Map Info Available
if(lpAppName == NULL) //get all section
{
return GetSectionsExA(lpReturnedString, nSize, lpFileName);
}
if(lpKeyName == NULL) //get all key in one section
{
return GetKeysExA(lpAppName, lpReturnedString, nSize, lpFileName);
}
LPSTR pHead = (LPSTR)m_pTrueData;
UINT uSec, uKey;
uSec = (UINT) -1;
uKey = (UINT)-1;
uKey = GetKeyExA(pHead, (UINT)m_dwUseSize,
lpAppName, lpKeyName, uSec);
if(uKey == (UINT)-1) //not key
{
if(::strlen(lpDefault) > (int)nSize) return -1;
::strncpy(lpReturnedString, lpDefault, ::strlen(lpDefault));
//append a null
lpReturnedString[::strlen(lpDefault)+1] = char('\0');
return 0;
}
char buffer[MAX_PATH];
LPSTR pValue = pHead + uKey;
while(pValue - pHead < (int)((m_dwUseSize)/sizeof(char)) &&
*pValue != char('\r') && *pValue != char('\n'))
{
pValue++; //in unicode, +2 byte
}
int len = pValue - pHead - uKey;
pValue = pHead + uKey;
::strncpy(buffer, pValue, len);
if(nSize <= (UINT)len)
{
::strncpy(lpReturnedString, pValue, nSize);
lpReturnedString[nSize - 1] = char('\0');
return 0;
}
else
{
::strncpy(lpReturnedString, pValue, len);
//append null
lpReturnedString[len] = char('\0');
return len;
}
return (UINT) -1;
}
// return 0 -- no key, size too small to put value
//return -1 -- error
//return string length (of course > 1)
//Ex Version use Map
DWORD CJXINIFile::GetPrivateProfileStringExW(
LPCWSTR lpAppName, // section name
LPCWSTR lpKeyName, // key name
LPCWSTR lpDefault, // default string
LPWSTR lpReturnedString, // destination buffer
DWORD nSize,
// size of destination buffer,Specifies the size, in TCHARs,
LPCWSTR lpFileName // initialization file name
)
{
BOOL bRet = LoadIniFile(lpFileName, 2);
if(!bRet) return (UINT)-1;
if(lpDefault == NULL) return -1;
if(m_dwUseSize == 0) return -1;
//Section Map Not Available
if(m_bSectionMapDirty && m_bSectionMapLock) //
return GetPrivateProfileStringW(lpAppName,lpKeyName,
lpDefault,lpReturnedString,nSize,lpFileName);
else if(!m_bSectionMapLock && m_bSectionMapDirty)
{
UpdateMapW();
}
//AfxMessageBox(_T("Using Section Map"));
//Now Map Info Available
if(lpAppName == NULL) //get all section
{
return GetSectionsExW(lpReturnedString, nSize, lpFileName);
}
if(lpKeyName == NULL) //get all key in one section
{
return GetKeysExW(lpAppName, lpReturnedString, nSize, lpFileName);
}
LPWSTR pHead = (LPWSTR)m_pTrueData;
UINT uSec, uKey;
uSec = (UINT) -1;
uKey = (UINT)-1;
uKey = GetKeyExW(pHead, (UINT)m_dwUseSize,
lpAppName, lpKeyName, uSec);
if(uKey == (UINT)-1) //not key
{
if(::wcslen(lpDefault) > (int)nSize) return -1;
::wcsncpy(lpReturnedString, lpDefault, ::wcslen(lpDefault));
//append a null
lpReturnedString[::wcslen(lpDefault)+1] = WCHAR('\0');
return 0;
}
WCHAR buffer[MAX_PATH];
LPWSTR pValue = pHead + uKey;
while(pValue - pHead < (int)((m_dwUseSize)/sizeof(WCHAR)) &&
*pValue != WCHAR('\r') && *pValue != WCHAR('\n'))
{
pValue++; //in unicode, +2 byte
}
int len = pValue - pHead - uKey;
pValue = pHead + uKey;
::wcsncpy(buffer, pValue, len);
if(nSize <= (UINT)len)
{
::wcsncpy(lpReturnedString, pValue, nSize);
lpReturnedString[nSize - 1] = WCHAR('\0');
return 0;
}
else
{
::wcsncpy(lpReturnedString, pValue, len);
//append null
lpReturnedString[len] = WCHAR('\0');
return len;
}
return (UINT) -1;
}
//User Query All Section Name in INI File
DWORD CJXINIFile::GetSectionsExA(
LPSTR lpReturnedString, // destination buffer
DWORD nSize, // size of destination buffer, In WCHAR
LPCSTR lpFileName // initialization file name
)
{
ASSERT(!m_bSectionMapDirty);
BYTE wNULL = 0x00;
int posRet = 0;
POSITION pos = m_mapSection.GetStartPosition();
while(pos)
{
CString strKey;
LPVOID lpPos;
m_mapSection.GetNextAssoc(pos, strKey, lpPos);
#ifdef _UNICODE
int lenSection = strKey.GetLength();
DWORD dwRetSize;
LPSTR pTemp = _W2A(strKey.GetBuffer(lenSection), lenSection, dwRetSize);
if(dwRetSize + 1 + posRet > (int)nSize) return 0; //nSize - 1;
::strncpy(lpReturnedString + posRet, pTemp, dwRetSize);
posRet += dwRetSize;
#else
int lenSection = strKey.GetLength();
if(lenSection + 1 + posRet > (int)nSize) return 0; //nSize - 1;
::strncpy(lpReturnedString + posRet, (LPCSTR)strKey, lenSection);
posRet += lenSection;
#endif
//NULL = 0x00 , 2 Byte
::memcpy(lpReturnedString + posRet, &wNULL, 1);
posRet += 1;
}
//last NULL
if(1 + posRet > (int)nSize) return 0; //nSize - 1;
::memcpy(lpReturnedString + posRet, &wNULL, 1);
posRet += 1;
return posRet;
}
//User Query All Section Name in INI File
DWORD CJXINIFile::GetSectionsExW(
LPWSTR lpReturnedString, // destination buffer
DWORD nSize, // size of destination buffer, In WCHAR
LPCWSTR lpFileName // initialization file name
)
{
ASSERT(!m_bSectionMapDirty);
WORD wNULL = 0x0000;
int posRet = 0;
POSITION pos = m_mapSection.GetStartPosition();
while(pos)
{
CString strKey;
LPVOID lpPos;
m_mapSection.GetNextAssoc(pos, strKey, lpPos);
#ifdef _UNICODE
int lenSection = strKey.GetLength();
if(lenSection + 1 + posRet > (int)nSize) return 0; //nSize - 1;
::wcsncpy(lpReturnedString + posRet, (LPCWSTR)strKey, lenSection);
posRet += lenSection;
#else
int lenSection = strKey.GetLength();
DWORD dwRetSize;
PWSTR pTemp = _A2W(strKey.GetBuffer(lenSection), lenSection, dwRetSize);
if(dwRetSize + 1 + posRet > (int)nSize) return 0; //nSize - 1;
::wcsncpy(lpReturnedString + posRet, pTemp, dwRetSize);
posRet += dwRetSize;
#endif
//NULL = 0x00 00, 2 Byte
::memcpy(lpReturnedString + posRet, &wNULL, 2);
posRet += 1;
}
//last NULL
if(1 + posRet > (int)nSize) return 0; //nSize - 1;
::memcpy(lpReturnedString + posRet, &wNULL, 2);
posRet += 1;
return posRet;
}
//User Query All Keys in a Given Section
DWORD CJXINIFile::GetKeysExA(
LPCSTR lpAppName, // section name
LPSTR lpReturnedString, // destination buffer
DWORD nSize, // size of destination buffer
LPCSTR lpFileName // initialization file name
)
{
int posRet = 0;
int secLen = ::strlen(lpAppName);
LPSTR pHead = (LPSTR)m_pTrueData;
LPSTR pSecHead = NULL; //pointing to [
//Section Map Must be Available
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -