⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 filepartition.cpp

📁 类似VC自带的那个windeff,来源于codeproject
💻 CPP
字号:

#include "stdafx.h"
#include "FilePartition.h"



// CFileLine ///////////////////////////////////////////////////
//
//

// Constructor
CFileLine::CFileLine()
{
	SetStatus(Normal);
}

// Accessors
long CFileLine::SetLine(/*in*/CString &s, /*in*/CFileOptions &o) // store string and build token
{
	m_s = s;

	CString so = GetLineWithOptions(s,o);
	
	long nToken = 0;
	long nLength = so.GetLength();
	TCHAR *lpString = so.GetBuffer(0);

	for (long i=0; i<nLength; i++)
		nToken += 2*nToken + *(lpString++); // (George V. Reilly hint)

	return nToken;
}

void CFileLine::SetLine(/*in*/CString &s, /*in*/LineStatus ls) // store string and status (does not eval ID)
{
	m_s = s;
	SetStatus(ls);
}


CString CFileLine::GetLine(/*in*/CFileOptions &o)
{
	if ( o.IsDefaultOptions() )
		return m_s;
	else
		return GetLineWithOptions(m_s,o);
}
	

CString CFileLine::GetLineWithOptions(/*in*/CString s,/*in*/CFileOptions &o)
{
	if ( o.IsDefaultOptions() )
		return s;
	
	CString so = s;

	// should we take care about indentation differences ?
	CString szIndentoption = o.GetOption( CString("indent") );
	if ( !szIndentoption.IsEmpty() && szIndentoption!="yes")
	{
		// no, then remove all 09 and 20 chars from the begin of the string
		long nSize = so.GetLength();
		if (nSize>0)
		{
			TCHAR c;
			BOOL bIndentation = TRUE;

			for (long i=0; i<nSize && bIndentation; i++)
			{
				c = so.GetAt(i);
				if (c!=0x20 && c!=0x09)
					bIndentation = FALSE;
			}
			so = bIndentation ? so : so.Right( so.GetLength()+1 - i);
		}
	}

	// should we care about case differences ?
	CString szCaseoption = o.GetOption( CString("case") );
	if ( !szCaseoption.IsEmpty() && szCaseoption!="yes")
	{
		// no, then make sure we lower the case
		so.MakeLower();
	}

	return so;
}

void CFileLine::SetStatus(/*in*/LineStatus ls)
{
	m_status = ls;
}

LineStatus CFileLine::GetStatus()
{
	return m_status;
}






// CFileOptions /////////////////////////////////////////////////////
//
/////////////////////////////////////////////////////////////////////
// shanzy - 2006
/////////////////////////////////////////////////////////////////////
//
//

CFileOptions::CFileOptions()
{
}

// Accessors
void CFileOptions::SetOption(/*in*/CString &szOptionName, /*in*/CString &szOptionValue)
{
	// is it a new option ?
	long nSize = arrOptions.GetSize();
	BOOL bFound = FALSE;
	for (long i=0; i<nSize && !bFound; i++)
	{
		CString s = arrOptions.GetAt(i);
		if (!s.IsEmpty() && s.Find(szOptionName,0)==0)
		{
			bFound = TRUE;
			long n = s.Find(';',0);
			if (n>-1)
				s = s.Left(n) + ";" + szOptionValue;
			else
				s = s + ";" + szOptionValue;

			arrOptions.SetAt(i, s);
		}
	} // for

	if (!bFound)
	{
		CString s = szOptionName + ";" + szOptionValue;
		arrOptions.Add(s);
	}
}

CString CFileOptions::GetOption(/*in*/CString &szOptionName)
{
	long nSize = arrOptions.GetSize();
	for (long i=0; i<nSize; i++)
	{
		CString s = arrOptions.GetAt(i);
		if (!s.IsEmpty() && s.Find(szOptionName,0)==0)
		{
			long n = s.Find(';',0);
			if (n>-1)
				return s.Right( s.GetLength() - (n+1) );
			else
				return CString("");
		}
	} // for

	return CString("");
}


BOOL CFileOptions::IsDefaultOptions()
{
	return GetOptionCount()==0;
}

long CFileOptions::GetOptionCount()
{
	return arrOptions.GetSize();
}

CString CFileOptions::GetOption(long i)
{
	return (i>=0 && i<GetOptionCount()) ? arrOptions.GetAt(i) : CString("");
}


// Methods
void CFileOptions::Copy(CFileOptions &src)
{
	long nbOptions = src.GetOptionCount();
	for (long i=0; i<nbOptions; i++)
		arrOptions.Add( src.GetOption(i) );
}









// CFilePartition ///////////////////////////////////////////////////
//
//


CFilePartition::CFilePartition()
{
}

CFilePartition::~CFilePartition()
{
	// remember to destroy those CFileLine objects
	long nSize = GetNBLines();
	for (long i=0; i<nSize; i++)
		delete m_arrLines.GetAt(i);
}

void CFilePartition::SetName(CString &szName)
{
	m_szFilename = szName;
}

CString CFilePartition::GetName()
{
	return m_szFilename;
}


void CFilePartition::SetOptions(/*in*/CFileOptions &options)
{
	m_options.Copy(options);
}

long CFilePartition::GetNBLines()
{
	return m_arrLines.GetSize();
}

CString CFilePartition::GetLine(/*in*/long i)
{
	ASSERT( i>=0 && i<GetNBLines());

	CFileLine *pLine = NULL;
	if (i>=0 && i<GetNBLines())
		pLine = m_arrLines.GetAt(i);

	return pLine ? pLine->GetLine(m_options) : CString("");
}

CString CFilePartition::GetRawLine(/*in*/long i) // returns an arbitrary line (not filtered)
{
	CFileOptions o; // default options

	ASSERT( i>=0 && i<GetNBLines());

	CFileLine *pLine = NULL;
	if (i>=0 && i<GetNBLines())
		pLine = m_arrLines.GetAt(i);

	return pLine ? pLine->GetLine(o) : CString("");
}

LineStatus CFilePartition::GetStatusLine(/*in*/long i)
{
	ASSERT( i>=0 && i<GetNBLines());

	CFileLine *pLine = NULL;
	if (i>=0 && i<GetNBLines())
		pLine = m_arrLines.GetAt(i);

	return pLine ? pLine->GetStatus() : Normal;
}

long *CFilePartition::GetTokens()
{
	return m_arrTokens.GetData();
}


void CFilePartition::HowManyChanges(/*out*/int &nAdded, /*out*/int &nChanged, /*out*/int &nDeleted)
{
	nAdded = nChanged = nDeleted = 0;

	LineStatus currentStatus = Normal;

	CFileLine *pLine = NULL;
	long nSize = GetNBLines();
	for (long i=0; i<nSize; i++)
	{
		pLine = m_arrLines.GetAt(i);
		if (!pLine) continue;

		LineStatus ls = pLine->GetStatus();
		if (ls!=Normal && currentStatus!=ls)
		{
			switch (ls)
			{
				case Added: nAdded++; break;
				case Changed: nChanged++; break;
				case Deleted: nDeleted++; break;
			}
		}
	} // end for all lines
}


// PreProcess
//
// purpose : reads a file, on a line-by-line basis
//
BOOL CFilePartition::PreProcess(/*in*/CString &szFilename, /*in*/CFileOptions &options)
{
	ASSERT( !szFilename.IsEmpty() );
	if (szFilename.IsEmpty())
	{
		OutputDebugString("error : empty input filename\r\n");
		return FALSE;
	}

	SetName(szFilename);
	SetOptions(options);

	// read the file first,
	// and build the table of tokens

	CStdioFile f;
	if ( !f.Open(szFilename, CFile::modeRead) )
	{
		TCHAR szError[MAX_PATH];
		sprintf(szError, "error : cannot open %s\r\n", szFilename.GetBuffer(0) );
		OutputDebugString(szError);
		return FALSE;
	}

	// 
	CString s;
	while ( f.ReadString(s) )
		AddString(s);

	f.Close();

	return TRUE;
}


// PreProcessFolder
//
// purpose : list folders, files and subfolders
//           and then build a tree-like list out of it
//
BOOL CFilePartition::PreProcessFolder(/*in*/CString &szFolder, /*in*/CFileOptions &options)
{

	SetName(szFolder);
	SetOptions(options);

	long nIndent = 0;

	// make sure there is no trailing backslash
	while (!szFolder.IsEmpty() && szFolder.GetAt( szFolder.GetLength()-1 )=='\\')
		szFolder = szFolder.Left( szFolder.GetLength()-1 );

	return PreProcessFolder(szFolder, options, nIndent);
}

BOOL CFilePartition::PreProcessFolder(/*in*/CString &szFolder, /*in*/CFileOptions &options, /*in/out*/long nIndent)
{
	if (szFolder.IsEmpty()) return FALSE;

	CSortedArray arrFiles;

	long i;
	CString szIndent;
	for (i=0; i<nIndent; i++)
		szIndent += "  ";

	// add this folder
	CString szCurrentFolder = szFolder;
	int nBackSlash = szCurrentFolder.ReverseFind('\\');
	if (nBackSlash>-1)
		szCurrentFolder = szCurrentFolder.Right( szCurrentFolder.GetLength()-(nBackSlash+1) );

	// add the folder in the partition
	AddString( szIndent + "+ " + szCurrentFolder );


	CString szFolderWildCard = szFolder + "\\*.*";

	WIN32_FIND_DATA findFile;
	HANDLE hContext;
	hContext=::FindFirstFile(szFolderWildCard.GetBuffer(0), &findFile);
	if (  hContext != INVALID_HANDLE_VALUE )
	{
		do
		{
			if (strcmp(findFile.cFileName,".")!=0 
				&& strcmp(findFile.cFileName,"..")!=0)
			{

				if (findFile.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) 
				{
					// it's a folder
					//
					CString szSubFolder = szFolder + "\\" + findFile.cFileName;
					PreProcessFolder(szSubFolder, options, nIndent+1);
				}
				else
				{
					// it's a file
					//
					// GetInformationByHandle
					
					OFSTRUCT ofstruct;
					BY_HANDLE_FILE_INFORMATION infostruct;
					HFILE hFile = ::OpenFile(szFolder + "\\" + findFile.cFileName, 
											 &ofstruct, 
											 OF_READ | OF_SHARE_DENY_NONE);
					if (hFile!=HFILE_ERROR && ::GetFileInformationByHandle( (HANDLE)hFile, &infostruct) )
					{
						SYSTEMTIME stCreate;

						// Convert the local file time from UTC to system time.
						FileTimeToSystemTime(&infostruct.ftLastWriteTime, &stCreate);

						TCHAR sDate[128];
						sprintf(sDate, "%02d/%02d/%d  %02d:%02d",
								stCreate.wDay, stCreate.wMonth, stCreate.wYear,
								stCreate.wHour, stCreate.wMinute);

						::_lclose(hFile);

						arrFiles.InsertSorted( CString(findFile.cFileName + CString(" (") + sDate + ")") );
					}
				}

			}
		}
		while (	::FindNextFile(hContext, &findFile) );

		::FindClose(hContext);
	}

	// add all files at this point
	long nbFiles = arrFiles.GetSize();
	for (i=0; i<nbFiles; i++)
		AddString( szIndent + "    " + arrFiles.GetAt(i) );

	return TRUE;
}


void CFilePartition::AddString(/*in*/CString &s, /*in*/LineStatus ls)
{
	CFileLine *p = new CFileLine();
	ASSERT(p);
	if (p)
	{
		p->SetLine(s, ls);
		m_arrLines.Add( p );
	}
}

void CFilePartition::AddBlankLine()
{
	AddString(CString(""), Normal);
}

void CFilePartition::AddString(/*in*/CString &s)
{
	CFileLine *p = new CFileLine();
	ASSERT(p);
	if (p)
	{
		m_arrTokens.Add( p->SetLine(s, m_options) );
		m_arrLines.Add( p );
	}
}


void CFilePartition::Dump(/*in*/CString &szTitle)
{
	TCHAR s[MAX_PATH];
	sprintf(s, "%s : %d lines\r\n\r\n", szTitle.GetBuffer(0), GetNBLines() );
	OutputDebugString(s);

	long nSize = GetNBLines();
	for (long i=0; i<nSize; i++)
	{
		LineStatus ls = GetStatusLine(i);
		if (ls==Normal) 
			OutputDebugString("Normal ");
		else if (ls==Changed)
			OutputDebugString("Changed ");
		else if (ls==Added)
			OutputDebugString("Added ");
		else if (ls==Deleted)
			OutputDebugString("Deleted ");

		OutputDebugString( GetLine(i) );
		OutputDebugString("\r\n");
	}
}

BOOL CFilePartition::MatchLine(/*in*/long i1, /*in*/CFilePartition &f2, /*out*/long &i2)
{
	ASSERT( m_arrTokens.GetSize()>0 );
	if ( m_arrTokens.GetSize()==0 ) return FALSE;

	ASSERT( i1<GetNBLines() );
	if ( i1>=GetNBLines() ) return FALSE; // should never happen though

	// try to match the current token from f1, into the a subset of f2 tokens
	//
	
	long nf1Token;
	nf1Token = m_arrTokens[i1];

	long *pf2Tokens = f2.GetTokens();
	if (!pf2Tokens)
		return FALSE;

	BOOL bFound = FALSE;
	long i = 0;
	long nf2SubsetLines = f2.GetNBLines() - i2;

	long *pf2Token = pf2Tokens + i2; // points to the right token

	while (!bFound && i<nf2SubsetLines)
	{
		if (nf1Token == *pf2Token) // fast compare
		{
			// make sure strings really match
			bFound = ( GetLine(i1).Compare( f2.GetLine(i2+i) )==0 ); 
		}

		pf2Token++;
		i++;
	}
	i--;

	if (bFound)
	{
		i2 += i;
		return TRUE;
	}

	return FALSE;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -