665 lines
19 KiB
C++
665 lines
19 KiB
C++
// =============================================================================
|
|
// Class Implementation : COXFileChanger
|
|
// =============================================================================
|
|
//
|
|
|
|
// Version: 9.3
|
|
|
|
// This software along with its related components, documentation and files ("The Libraries")
|
|
// is © 1994-2007 The Code Project (1612916 Ontario Limited) and use of The Libraries is
|
|
// governed by a software license agreement ("Agreement"). Copies of the Agreement are
|
|
// available at The Code Project (www.codeproject.com), as part of the package you downloaded
|
|
// to obtain this file, or directly from our office. For a copy of the license governing
|
|
// this software, you may contact us at legalaffairs@codeproject.com, or by calling 416-849-8900.
|
|
|
|
// //////////////////////////////////////////////////////////////////////////
|
|
|
|
#include "stdafx.h"
|
|
#include "OXFileChanger.h"
|
|
|
|
#include "UTBStrOp.h"
|
|
#include "UTB64Bit.h"
|
|
|
|
#ifdef _DEBUG
|
|
#define new DEBUG_NEW
|
|
#undef THIS_FILE
|
|
static char THIS_FILE[] = __FILE__;
|
|
#endif
|
|
|
|
IMPLEMENT_DYNAMIC(COXFileChanger, CObject)
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// Definition of static members
|
|
|
|
LONG COXFileChanger::m_nBufferSize = 0xFFFF;
|
|
|
|
const int COXFileChanger::m_nFlagUseCFile = 0x0001;
|
|
// --- 00000001 1: UseFiles(CFile*); 0: UseFiles(pszFileName)
|
|
const int COXFileChanger::m_nFlagOverwrite = 0x0002;
|
|
// --- 00000010 1: Overwrite; 0: Output to another file
|
|
const int COXFileChanger::m_nFlagReplace = 0x0004;
|
|
// --- 00000100 1: Replace(); 0: Search()
|
|
const int COXFileChanger::m_nFlagText = 0x0008;
|
|
// --- 00001000 1: Text; 0: Binary
|
|
const int COXFileChanger::m_nFlagAll = 0x0010;
|
|
// --- 00010000 bAll ? 1 : 0
|
|
const int COXFileChanger::m_nFlagMatchCase = 0x0020;
|
|
// --- 00100000 bMatchCase ? 1 : 0
|
|
const int COXFileChanger::m_nFlagWholeWord = 0x0040;
|
|
// --- 01000000 bWholeWordOnly ? 1 : 0
|
|
|
|
TCHAR szTempFilePrefix[] = _T("~fc");
|
|
LPCTSTR COXFileChanger::m_sTempFilePrefix = szTempFilePrefix;
|
|
// ---- Prefix used to create temporary file
|
|
|
|
// Data members -------------------------------------------------------------
|
|
// protected:
|
|
// UINT m_nFlag;
|
|
// --- Internal status flags
|
|
|
|
// CFile* m_pFileIn;
|
|
// --- Actual input file
|
|
|
|
// CFile* m_pFileOut;
|
|
// --- Actual output file
|
|
|
|
// CFile m_fileIn;
|
|
// --- Used when file name is supplied
|
|
|
|
// CFile m_fileOut;
|
|
// --- Used when file name is supplied
|
|
|
|
// CString m_sInputFileName;
|
|
// --- Supplied input file name
|
|
|
|
// CString m_sOutputFileName;
|
|
// --- Supplied output file name
|
|
|
|
// CByteArray* m_pSearch;
|
|
// --- Search bytes
|
|
|
|
// CByteArray* m_pSearchOppositeCase;
|
|
// --- Search bytes with opposite case
|
|
|
|
// CByteArray* m_pReplace;
|
|
// --- Replace bytes
|
|
|
|
// Member functions ---------------------------------------------------------
|
|
COXFileChanger::COXFileChanger()
|
|
:
|
|
m_hNotifyWnd(NULL),
|
|
m_nFlag(0),
|
|
m_pFileIn(NULL),
|
|
m_pFileOut(NULL),
|
|
m_fileIn(),
|
|
m_fileOut(),
|
|
m_sInputFileName(),
|
|
m_sOutputFileName(),
|
|
m_pSearch(NULL),
|
|
m_pSearchOppositeCase(NULL),
|
|
m_pReplace(NULL)
|
|
{
|
|
}
|
|
|
|
COXFileChanger::~COXFileChanger()
|
|
{
|
|
}
|
|
|
|
void COXFileChanger::UseFiles(LPCTSTR pszInputFileName,
|
|
LPCTSTR pszOutputFileName /* = NULL */)
|
|
{
|
|
ASSERT(pszInputFileName);
|
|
|
|
m_pFileIn = &m_fileIn;
|
|
m_pFileOut = &m_fileOut;
|
|
m_sInputFileName = pszInputFileName;
|
|
ASSERT(!m_sInputFileName.IsEmpty());
|
|
m_sOutputFileName = pszOutputFileName;
|
|
SetFlag(m_nFlagUseCFile, FALSE);
|
|
SetFlag(m_nFlagOverwrite, (pszOutputFileName == NULL ||
|
|
m_sInputFileName.CompareNoCase(m_sOutputFileName) == 0));
|
|
}
|
|
|
|
void COXFileChanger::UseFiles(CFile* pInputFile, CFile* pOutputFile /* = NULL */)
|
|
{
|
|
ASSERT((pInputFile != NULL) && (pInputFile != pOutputFile));
|
|
|
|
m_pFileIn = pInputFile;
|
|
m_pFileOut = pOutputFile;
|
|
m_sInputFileName.Empty();
|
|
m_sOutputFileName.Empty();
|
|
SetFlag(m_nFlagUseCFile);
|
|
SetFlag(m_nFlagOverwrite, FALSE);
|
|
}
|
|
|
|
void COXFileChanger::SetNotificationWnd(CWnd* pNotifyWnd)
|
|
{
|
|
m_hNotifyWnd = pNotifyWnd->GetSafeHwnd();
|
|
}
|
|
|
|
UINT COXFileChanger::Search (LPCTSTR pszText,
|
|
BOOL bAll /* = FALSE */, BOOL bMatchCase /* = FALSE */,
|
|
BOOL bWholeWordOnly /* = FALSE */)
|
|
{
|
|
ASSERT(m_pFileIn != NULL);
|
|
|
|
CByteArray searchText, searchTextRevCase;
|
|
CopyTextToByteArray(pszText, m_pSearch = &searchText);
|
|
if (!bMatchCase)
|
|
{
|
|
CString sText = pszText;
|
|
ReverseCase(sText);
|
|
CopyTextToByteArray(sText, m_pSearchOppositeCase = &searchTextRevCase);
|
|
}
|
|
SetFlag(m_nFlagReplace, FALSE);
|
|
SetFlag(m_nFlagText);
|
|
SetFlag(m_nFlagAll, bAll);
|
|
SetFlag(m_nFlagMatchCase, bMatchCase);
|
|
SetFlag(m_nFlagWholeWord, bWholeWordOnly);
|
|
return Run();
|
|
}
|
|
|
|
UINT COXFileChanger::Search (const CByteArray& binary, BOOL bAll /* = FALSE */)
|
|
{
|
|
ASSERT(m_pFileIn != NULL);
|
|
|
|
m_pSearch = (CByteArray*)&binary;
|
|
SetFlag(m_nFlagReplace, FALSE);
|
|
SetFlag(m_nFlagText, FALSE);
|
|
SetFlag(m_nFlagAll, bAll);
|
|
return Run();
|
|
}
|
|
|
|
UINT COXFileChanger::Replace(LPCTSTR pszText, LPCTSTR pszReplaceText,
|
|
BOOL bAll /* = FALSE */, BOOL bMatchCase /* = FALSE */,
|
|
BOOL bWholeWordOnly /* = FALSE */)
|
|
{
|
|
ASSERT((m_pFileIn != NULL) && (m_pFileOut != NULL));
|
|
|
|
CByteArray searchText, searchTextRevCase, replaceText;
|
|
CopyTextToByteArray(pszText, m_pSearch = &searchText);
|
|
if (!bMatchCase)
|
|
{
|
|
CString sText = pszText;
|
|
ReverseCase(sText);
|
|
CopyTextToByteArray(sText, m_pSearchOppositeCase = &searchTextRevCase);
|
|
}
|
|
CopyTextToByteArray(pszReplaceText, m_pReplace = &replaceText);
|
|
SetFlag(m_nFlagReplace);
|
|
SetFlag(m_nFlagText);
|
|
SetFlag(m_nFlagAll, bAll);
|
|
SetFlag(m_nFlagMatchCase, bMatchCase);
|
|
SetFlag(m_nFlagWholeWord, bWholeWordOnly);
|
|
return Run();
|
|
}
|
|
|
|
UINT COXFileChanger::Replace(const CByteArray& binary, const CByteArray& replaceBinary,
|
|
BOOL bAll /* = FALSE */)
|
|
{
|
|
ASSERT((m_pFileIn != NULL) && (m_pFileOut != NULL));
|
|
|
|
m_pSearch = (CByteArray*)&binary;
|
|
m_pReplace = (CByteArray*)&replaceBinary;
|
|
SetFlag(m_nFlagReplace);
|
|
SetFlag(m_nFlagText, FALSE);
|
|
SetFlag(m_nFlagAll, bAll);
|
|
return Run();
|
|
}
|
|
|
|
#ifdef _DEBUG
|
|
void COXFileChanger::AssertValid() const
|
|
{
|
|
CObject::AssertValid();
|
|
}
|
|
|
|
void COXFileChanger::Dump(CDumpContext& dc) const
|
|
{
|
|
CObject::Dump(dc);
|
|
|
|
dc << "\nm_nBufferSize=" << m_nBufferSize;
|
|
dc << "\nm_hNotifyWnd=" << m_hNotifyWnd;
|
|
|
|
dc << "\nm_nFlag=" << m_nFlag;
|
|
dc << "\nm_pFileIn=" << m_pFileIn;
|
|
dc << "\nm_pFileOut=" << m_pFileOut;
|
|
dc << "\nm_fileIn=" << m_fileIn;
|
|
dc << "\nm_fileOut=" << m_fileOut;
|
|
dc << "\nm_sInputFileName=" << m_sInputFileName;
|
|
dc << "\nm_sOutputFileName=" << m_sOutputFileName;
|
|
|
|
dc << "\nm_pSearch=" << m_pSearch;
|
|
dc << "\nm_pSearchOppositeCase=" << m_pSearchOppositeCase;
|
|
dc << "\nm_pReplace=" << m_pReplace;
|
|
|
|
dc << "\nm_nFlagUseCFile=" << m_nFlagUseCFile;
|
|
dc << "\nm_nFlagOverwrite=" << m_nFlagOverwrite;
|
|
dc << "\nm_nFlagReplace=" << m_nFlagReplace;
|
|
dc << "\nm_nFlagText=" << m_nFlagText;
|
|
dc << "\nm_nFlagAll=" << m_nFlagAll;
|
|
dc << "\nm_nFlagMatchCase=" << m_nFlagMatchCase;
|
|
dc << "\nm_nFlagWholeWord=" << m_nFlagWholeWord;
|
|
dc << "\nm_sTempFilePrefix=" << m_sTempFilePrefix;
|
|
|
|
dc << "\n";
|
|
}
|
|
#endif //_DEBUG
|
|
|
|
// protected:
|
|
BOOL COXFileChanger::OnFound (CFile* pInputFile, LONG nInPos, BOOL& bContinue)
|
|
// --- In : pInputFile, a CFile pointer to the input file
|
|
// nInPos, the absolute position (zero-based) of the first
|
|
// character of the found part in the input file
|
|
// --- Out : bContinue, TRUE by default if bAll was TRUE, otherwise
|
|
// FALSE by default. It may be changed within the
|
|
// function to specify whether to continue searching
|
|
// --- Returns : whether this occurrence should be ignored (FALSE) or not
|
|
// (TRUE, default)
|
|
// --- Effect : This function is called when an occurrence has been found
|
|
// during the Search().
|
|
// NOTE: The current position of the file specified by
|
|
// pInputFile may be changed within this function. It
|
|
// will be automatically reset to the last search
|
|
// position after the function returns.
|
|
{
|
|
BOOL bResult = TRUE;
|
|
if (m_hNotifyWnd != NULL)
|
|
{
|
|
COXFileChangerData fileChangerData(pInputFile, nInPos, bContinue);
|
|
bResult = (BOOL)::SendMessage(m_hNotifyWnd, WM_OX_FILE_MATCH_FOUND, (WPARAM)&fileChangerData, NULL);
|
|
}
|
|
|
|
return bResult;
|
|
}
|
|
|
|
BOOL COXFileChanger::OnPreReplace (CFile* pInputFile, LONG nInPos, BOOL& bContinue)
|
|
// --- In : pInputFile, a CFile pointer to the input file
|
|
// nInPos, the absolute position (zero-based) of the first
|
|
// character of the found part in the input file
|
|
// --- Out : bContinue, TRUE by default if bAll was TRUE, otherwise
|
|
// FALSE by default. It may be changed within the
|
|
// function to specify whether to continue searching after
|
|
// the current replacement is processed
|
|
// --- Returns : whether this occurrence should be ignored (FALSE) thus
|
|
// not replaced, or not (TRUE, default)
|
|
// --- Effect : This function is called when an occurrence has been found
|
|
// during the Replace().
|
|
// NOTE: The current position of the file specified by
|
|
// pInputFile may be changed within this function. It
|
|
// will be automatically reset to the last search
|
|
// position after the function returns.
|
|
{
|
|
BOOL bResult = TRUE;
|
|
if (m_hNotifyWnd != NULL)
|
|
{
|
|
COXFileChangerData fileChangerData(pInputFile, nInPos, bContinue);
|
|
bResult = (BOOL)::SendMessage(m_hNotifyWnd, WM_OX_FILE_PRE_REPLACE, (WPARAM)&fileChangerData, NULL);
|
|
}
|
|
|
|
return bResult;
|
|
}
|
|
|
|
void COXFileChanger::OnPostReplace (CFile* pOutputFile, LONG nOutPos)
|
|
// --- In : pOutputFile, a CFile pointer to the output file
|
|
// nOutPos, the absolute position (zero-based) of the first
|
|
// character of the replaced part in the output file.
|
|
// --- Out :
|
|
// --- Returns :
|
|
// --- Effect : This function is called after the replacement has been
|
|
// taken place. The replacing contents has already been
|
|
// written to file when this is called.
|
|
// NOTE: The current position of the file specified by
|
|
// pOutputFile may be changed within this function. It
|
|
// will be automatically reset after the function returns.
|
|
// NOTE: If a previous OnPreReplace() returns FALSE,
|
|
// OnPostReplace will not be called. In this situation
|
|
// the search may still continue depending on the value
|
|
// of the out parameter bContinue in OnPreReplace().
|
|
{
|
|
if (m_hNotifyWnd != NULL)
|
|
{
|
|
BOOL bDummy = FALSE;
|
|
COXFileChangerData fileChangerData(pOutputFile, nOutPos, bDummy);
|
|
::SendMessage(m_hNotifyWnd, WM_OX_FILE_POST_REPLACE, (WPARAM)&fileChangerData, NULL);
|
|
}
|
|
}
|
|
|
|
void COXFileChanger::SetFlag(UINT nOXFCFLAG, BOOL bValue /* = TRUE */)
|
|
// --- In : nOXFCFLAG, specify which flag to set
|
|
// bValue, specify the value to set
|
|
// --- Out :
|
|
// --- Returns :
|
|
// --- Effect : set a flag to 0 or 1
|
|
{
|
|
if (bValue)
|
|
m_nFlag |= nOXFCFLAG;
|
|
else
|
|
m_nFlag &= ~nOXFCFLAG;
|
|
}
|
|
|
|
BOOL COXFileChanger::GetFlag(UINT nOXFCFLAG)
|
|
// --- In : nOXFCFLAG, specify which flag to get
|
|
// --- Out :
|
|
// --- Returns :
|
|
// --- Effect : retreive flag status
|
|
{
|
|
return m_nFlag & nOXFCFLAG;
|
|
}
|
|
|
|
UINT COXFileChanger::Run()
|
|
// --- In :
|
|
// --- Out :
|
|
// --- Returns : occurences of found match or replacement
|
|
// --- Effect : perform search/replace
|
|
{
|
|
int M = PtrToInt(m_pSearch->GetSize());
|
|
// ... search text/binary length
|
|
int M_1 = M - 1;
|
|
// ... array max subscript
|
|
int MM_1 = M + M_1;
|
|
// ... i shift value when found
|
|
int n = 0;
|
|
// ... actual bytes read from the file at one time
|
|
int i = 0;
|
|
// ... scanning position pointer of file buffer
|
|
int j = 0;
|
|
// ... scanning position pointer of search text/binary
|
|
int w = 0;
|
|
// ... write position pointer in the loaded file buffer
|
|
int t = 0;
|
|
// ... temp value
|
|
int skip[255];
|
|
// ... skip array for each byte value
|
|
|
|
LONG lPos0 = 0;
|
|
// ... file position of the current buffer[0]
|
|
LONG nCurInPos = 0;
|
|
// ... loading position of the input file
|
|
LONG nInPos = 0;
|
|
// ... match found position of the input file
|
|
LONG nCurOutPos = 0;
|
|
// ... writing position of the output file
|
|
LONG nOutPos = 0;
|
|
// ... replace text/binary position of the output file
|
|
LONG nChPos = 0;
|
|
// ... position of prev/next char for whole word match
|
|
LONG nChPosMax = 0;
|
|
// ... maximum file position of prev/next char for whole word match
|
|
UINT nResult = 0;
|
|
// ... match occurence
|
|
BYTE* pBuffer = NULL;
|
|
// ... file buffer
|
|
|
|
BOOL bEOF = FALSE;
|
|
// ... end of file
|
|
BOOL bContinue = TRUE;
|
|
// ... default bContinue value
|
|
BOOL bReplace = GetFlag(m_nFlagReplace);
|
|
// ... Replace() (TRUE) or Search() (FALSE)
|
|
BOOL bText = GetFlag(m_nFlagText);
|
|
// ... whether text search
|
|
BOOL bMatchCase = (!bText || GetFlag(m_nFlagMatchCase));
|
|
// ... whether case-insensitive
|
|
BOOL bWholeWord = (bText && GetFlag(m_nFlagWholeWord));
|
|
// ... whether whole word
|
|
char ch = '\0';
|
|
// ... prev/next char for whole word match
|
|
CString sSafeStack;
|
|
// Increases the stack size
|
|
|
|
if (M == 0)
|
|
{
|
|
TRACE0("COXFileChanger::Run(): aborted: zero length search text/binary encountered.\r\n");
|
|
return 0;
|
|
}
|
|
|
|
if (m_nBufferSize < M)
|
|
{
|
|
TRACE0("COXFileChanger::Run(): aborted: length of search text/binary exceeds upper limit.\r\n");
|
|
return 0;
|
|
}
|
|
|
|
// Initialize skip array
|
|
for (j = 0; j < 256; j++)
|
|
skip[j] = M;
|
|
for (j = 0, t = M; j < M; j++)
|
|
skip[m_pSearch->GetAt(j)] = --t;
|
|
if (!bMatchCase)
|
|
for (j = 0, t = M; j < M; j++)
|
|
skip[m_pSearchOppositeCase->GetAt(j)] = --t;
|
|
|
|
try
|
|
{
|
|
// Alllocate the buffer
|
|
pBuffer = new BYTE[m_nBufferSize];
|
|
|
|
OpenFiles();
|
|
nChPosMax = (LONG) m_pFileIn->GetLength() - 1;
|
|
while (!bEOF && (n = m_pFileIn->Read(pBuffer, m_nBufferSize)) > 0)
|
|
{
|
|
bEOF = (n < m_nBufferSize);
|
|
if (!bContinue && bReplace)
|
|
{
|
|
// Cycle until all remaining contents are copied
|
|
m_pFileOut->Write(pBuffer, n);
|
|
continue;
|
|
}
|
|
|
|
if (!bContinue || n < M)
|
|
break;
|
|
i = - M; w = 0;
|
|
while (bContinue)
|
|
{
|
|
// search one occurence
|
|
for (i += MM_1, j = M_1; 0 <= j && i < n; i--, j--)
|
|
{
|
|
while (pBuffer[i] != m_pSearch->GetAt(j) && (bMatchCase ||
|
|
pBuffer[i] != m_pSearchOppositeCase->GetAt(j)))
|
|
{
|
|
t = skip[pBuffer[i]];
|
|
i += __max(M - j, t);
|
|
if (n <= i)
|
|
{
|
|
i++;
|
|
break;
|
|
}
|
|
j = M_1;
|
|
}
|
|
}
|
|
// out of buffer boundary
|
|
if (n <= i)
|
|
{
|
|
if (bReplace)
|
|
m_pFileOut->Write(pBuffer + w, (bEOF ? n : i - M_1) - w);
|
|
if (!bEOF)
|
|
lPos0 = (LONG) m_pFileIn->Seek(i - M_1 - n, CFile::current);
|
|
break;
|
|
}
|
|
|
|
i++;
|
|
nCurInPos = (LONG) m_pFileIn->GetPosition();
|
|
nInPos = lPos0 + i;
|
|
|
|
// test wholeword match
|
|
if (bWholeWord)
|
|
{
|
|
nChPos = i - 1;
|
|
for (t = 0; t < 2; t++)
|
|
{
|
|
// look in buffer first
|
|
if (0 <= nChPos && nChPos < n)
|
|
ch = *(pBuffer + nChPos);
|
|
else
|
|
{ // look in the file
|
|
nChPos += lPos0;
|
|
if (0 <= nChPos && nChPos <= nChPosMax)
|
|
{
|
|
m_pFileIn->Seek(nChPos, CFile::begin);
|
|
m_pFileIn->Read(&ch, 1);
|
|
}
|
|
else
|
|
// beginning or the end of the file
|
|
ch = ' ';
|
|
}
|
|
if (isalnum(ch))
|
|
break;
|
|
nChPos = i + M;
|
|
}
|
|
if (t < 2)
|
|
{
|
|
m_pFileIn->Seek(nCurInPos, CFile::begin);
|
|
i -= M_1;
|
|
continue;
|
|
}
|
|
}
|
|
|
|
// found one match
|
|
bContinue = GetFlag(m_nFlagAll);
|
|
m_pFileIn->Seek(nInPos, CFile::begin);
|
|
if (bReplace)
|
|
{
|
|
if (OnPreReplace(m_pFileIn, nInPos, bContinue))
|
|
{
|
|
nResult++;
|
|
m_pFileOut->Write(pBuffer + w, i - w);
|
|
nOutPos = (LONG) m_pFileOut->GetPosition();
|
|
m_pFileOut->Write(m_pReplace->GetData(), PtrToUint(m_pReplace->GetSize()));
|
|
w = i + M;
|
|
nCurOutPos = (LONG) m_pFileOut->GetPosition();
|
|
m_pFileOut->Seek(nOutPos, CFile::begin);
|
|
OnPostReplace(m_pFileOut, nOutPos);
|
|
m_pFileOut->Seek(nCurOutPos, CFile::begin);
|
|
}
|
|
if (!bContinue)
|
|
m_pFileOut->Write(pBuffer + w, n - w);
|
|
}
|
|
else
|
|
{
|
|
if (OnFound(m_pFileIn, nInPos, bContinue))
|
|
nResult++;
|
|
}
|
|
m_pFileIn->Seek(nCurInPos, CFile::begin);
|
|
}
|
|
}
|
|
CloseFiles();
|
|
}
|
|
catch (...)
|
|
{
|
|
if (!GetFlag(m_nFlagUseCFile))
|
|
{
|
|
CString sTempFileName = m_pFileOut->GetFilePath();
|
|
m_pFileIn->Abort();
|
|
m_pFileOut->Abort();
|
|
if (bReplace && GetFlag(m_nFlagOverwrite) && !sTempFileName.IsEmpty())
|
|
::DeleteFile(sTempFileName);
|
|
}
|
|
m_pFileIn = NULL;
|
|
m_pFileOut = NULL;
|
|
delete[] pBuffer;
|
|
pBuffer = NULL;
|
|
throw;
|
|
}
|
|
|
|
// Clean up
|
|
delete[] pBuffer;
|
|
pBuffer = NULL;
|
|
m_pFileIn = NULL;
|
|
m_pFileOut = NULL;
|
|
return nResult;
|
|
}
|
|
|
|
void COXFileChanger::OpenFiles()
|
|
// --- In :
|
|
// --- Out :
|
|
// --- Returns :
|
|
// --- Effect : prepare m_pFileIn and m_pFileOut
|
|
{
|
|
if (!GetFlag(m_nFlagUseCFile))
|
|
{
|
|
m_pFileIn->Open(m_sInputFileName, CFile::modeRead | CFile::shareDenyWrite);
|
|
if (GetFlag(m_nFlagReplace))
|
|
{
|
|
CString sOutputFileName = (GetFlag(m_nFlagOverwrite) ?
|
|
GetUniqueTempName() : m_sOutputFileName);
|
|
ASSERT(!sOutputFileName.IsEmpty());
|
|
m_pFileOut->Open(sOutputFileName, CFile::modeReadWrite | CFile::modeCreate);
|
|
}
|
|
}
|
|
|
|
m_pFileIn->SeekToBegin();
|
|
}
|
|
|
|
void COXFileChanger::CloseFiles()
|
|
// --- In :
|
|
// --- Out :
|
|
// --- Returns :
|
|
// --- Effect : close m_pFileIn and m_pFileOut
|
|
{
|
|
if (!GetFlag(m_nFlagUseCFile))
|
|
{
|
|
m_pFileIn->Close();
|
|
if (GetFlag(m_nFlagReplace))
|
|
{
|
|
CString sTempFileName = m_pFileOut->GetFilePath();
|
|
m_pFileOut->Close();
|
|
if (GetFlag(m_nFlagOverwrite) && (!::DeleteFile(m_sInputFileName) ||
|
|
!::MoveFile(sTempFileName, m_sInputFileName)))
|
|
CFileException::ThrowOsError((LONG)::GetLastError(), m_sInputFileName);
|
|
}
|
|
}
|
|
}
|
|
|
|
void COXFileChanger::CopyTextToByteArray(LPCTSTR pszText, CByteArray* pBuffer)
|
|
// --- In : pszText, the text to copy
|
|
// pBuffer, the byte array to store result
|
|
// --- Out :
|
|
// --- Returns :
|
|
// --- Effect : copy a string (ANSI or UNICODE) into a byte array
|
|
// Unicode characters are converted to ansi characters
|
|
{
|
|
#ifdef _UNICODE
|
|
size_t nLen = 0;
|
|
|
|
UTBStr::wcstombs(&nLen, NULL, 0, pszText, 0);
|
|
if (nLen < 0)
|
|
{
|
|
TRACE0("COXFileChanger::CopyTextToByteArray : Conversion of Unicode to Ansi failed, using empty string\n");
|
|
nLen = 0;
|
|
}
|
|
pBuffer->SetSize(nLen);
|
|
char* pByte = (LPSTR)pBuffer->GetData();
|
|
// ... Convert Unicode to ansi
|
|
size_t t;
|
|
UTBStr::wcstombs(&t, pByte, nLen, pszText, nLen);
|
|
#else
|
|
int nLen = _tcslen(pszText);
|
|
pBuffer->SetSize(nLen);
|
|
char* pByte = (LPSTR)pBuffer->GetData();
|
|
// ... Just copy Ansi sting
|
|
::CopyMemory(pByte, pszText, nLen);
|
|
#endif // _UNICODE
|
|
}
|
|
|
|
void COXFileChanger::ReverseCase(CString& sText)
|
|
// --- In : sText, the text to reverse case
|
|
// --- Out :
|
|
// --- Returns : a string with reversed case for each character
|
|
// --- Effect : reverse every character's case in a string
|
|
{
|
|
TCHAR ch;
|
|
for (int i = 0; i < sText.GetLength(); i++)
|
|
{
|
|
ch = sText[i];
|
|
sText.SetAt(i, (_istlower(ch) ? (TCHAR)_totupper(ch) : (TCHAR)_totlower(ch)));
|
|
}
|
|
}
|
|
|
|
CString COXFileChanger::GetUniqueTempName()
|
|
{
|
|
TCHAR szTempPath[MAX_PATH];
|
|
TCHAR szTempFile[MAX_PATH];
|
|
VERIFY(::GetTempPath(MAX_PATH, szTempPath));
|
|
VERIFY(::GetTempFileName(szTempPath, m_sTempFilePrefix, 0, szTempFile));
|
|
return CString(szTempFile);
|
|
}
|
|
|
|
// end of OXFileChanger.cpp
|