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

📄 kfile.cpp

📁 一个简单而又高效的嵌入式操作系统.包括GUI及文件系统.仿Windows设计,类似于MFC风格
💻 CPP
字号:
// KFile.cpp: implementation of the KFile class.
//
//////////////////////////////////////////////////////////////////////

#include "..\stdafx.h"
#include "KFile.h"

PDWORD KFile::m_pUsedBitmap=NULL;
PBYTE KFile::m_pBuffer=NULL;
int KFile::m_nBufferBlock=0;
KArray<KFile::FILE> KFile::m_arrFile;
	//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

KFile::KFile()
{
	m_nFile=-1;
}

KFile::~KFile()
{
	Close();
}
DWORD KFile::Verify(BOOL bWrite)
{
	DWORD i,j,nCnt;
	PDWORD pData;
	pData=(DWORD*)m_pBuffer;
	nCnt=FILE_BLOCKBYTES/sizeof(DWORD)-1;
	j=-1;
	for(i=0;i<nCnt;i++)
	{
		j^=*pData++;
	}
	if(bWrite)*pData=j;
	else j=(j==*pData)?TRUE:FALSE;
	return j;
}

void KFile::Init()
{
	int i,j,nCnt,nCnt2;
	DWORD nPos;

	m_pBuffer=(PBYTE)HeapAlloc(FILE_BLOCKBYTES);
	m_nBufferBlock=0;

	FILE_READBLOCK(m_pBuffer,m_nBufferBlock);
	if(!Verify(FALSE))
	{
		//格式化
		ZeroMemory(m_pBuffer,FILE_BLOCKBYTES);
		FILE_WRITEBLOCK(m_pBuffer,m_nBufferBlock);
	}
	
	nPos=(DWORD)m_pBuffer;

	//读使用位图
	i=sizeof(DWORD)*8;
	nCnt=FILE_BLOCKCOUNT/i;
	if(FILE_BLOCKCOUNT%i)nCnt++;
	m_pUsedBitmap=new DWORD[nCnt];
	CopyMemory(m_pUsedBitmap,PVOID(nPos),sizeof(DWORD)*nCnt);
	nPos+=sizeof(DWORD)*nCnt;

	//读取文件列表
	nCnt=*PDWORD(nPos);
	nPos+=sizeof(DWORD);
	m_arrFile.SetSize(nCnt,-1);
	for(i=0;i<nCnt;i++)
	{
		FILE& f=m_arrFile[i];
		f.strName=LPCTSTR(nPos);
		nPos+=sizeof(TCHAR)*(f.strName.GetLength()+1);
		f.nDate=*PDWORD(nPos);nPos+=sizeof(DWORD);
		f.nSize=*PDWORD(nPos);nPos+=sizeof(DWORD);

		nCnt2=f.nSize/FILE_BLOCKBYTES;
		if(f.nSize%FILE_BLOCKBYTES)nCnt2++;
		f.pBlock=new USHORT[(nCnt2&~7)+8];
		j=sizeof(USHORT)*((nCnt2 & 1)?nCnt2+1:nCnt2);
		CopyMemory(f.pBlock,PVOID(nPos),j);
		nPos+=sizeof(USHORT)*j;
	}
}

void KFile::Unload()
{
	int i,j,nCnt,nCnt2;
	DWORD nPos;
	PDWORD pOld,pNew;

	if(m_nBufferBlock<0)
	{
		FILE_WRITEBLOCK(m_pBuffer,-m_nBufferBlock);
	}
	nPos=(DWORD)m_pBuffer;

	//写使用位图
	i=sizeof(DWORD)*8;
	nCnt=FILE_BLOCKCOUNT/i;
	if(FILE_BLOCKCOUNT%i)nCnt++;
	CopyMemory(PVOID(nPos),m_pUsedBitmap,sizeof(DWORD)*nCnt);
	nPos+=sizeof(DWORD)*nCnt;
	delete[] m_pUsedBitmap;

	//写文件列表
	*PDWORD(nPos)=nCnt=m_arrFile.GetSize();
	nPos+=sizeof(DWORD);
	for(i=0;i<nCnt;i++)
	{
		FILE& f=m_arrFile[i];
		j=sizeof(TCHAR)*(f.strName.GetLength()+1);
		CopyMemory(PVOID(nPos),f.strName,j);
		nPos+=j;
		*PDWORD(nPos)=f.nDate;nPos+=sizeof(DWORD);
		*PDWORD(nPos)=f.nSize;nPos+=sizeof(DWORD);

		nCnt2=f.nSize/FILE_BLOCKBYTES;
		if(f.nSize%FILE_BLOCKBYTES)nCnt2++;
		j=sizeof(USHORT)*((nCnt2 & 1)?nCnt2+1:nCnt2);
		CopyMemory(PVOID(nPos),f.pBlock,j);
		nPos+=sizeof(USHORT)*j;
		delete[] f.pBlock;
	}
	m_arrFile.SetSize(0,-1);
	m_nBufferBlock=0;
	Verify(TRUE);

	pNew=(PDWORD)m_pBuffer;
	pOld=(PDWORD)HeapAlloc(FILE_BLOCKBYTES);
	FILE_READBLOCK(pOld,m_nBufferBlock);
	nCnt=FILE_BLOCKBYTES/sizeof(DWORD);
	for(i=0;i<nCnt;i++)
	{
		if(pNew[i]!=pOld[i])
		{
			FILE_WRITEBLOCK(m_pBuffer,m_nBufferBlock);
			break;
		}
	}
	HeapFree(pOld);
	HeapFree(m_pBuffer);
}

int KFile::GetFileIndex(LPCTSTR szFile)
{
	int i,j;
	for(i=m_arrFile.GetSize()-1;i>=0;i--)
	{
		j=m_arrFile[i].strName.GetLength()+1;
		if(m_arrFile[i].strName.Compare(szFile,-j)==0)
		{
			break;
		}
	}
	return i;
}

LPCTSTR KFile::FindFirst()
{
	if(m_arrFile.GetSize()<1)return NULL;
	Close();
	m_nFile=0;
	m_nPostion=0;
	return m_arrFile[0].strName;
}

LPCTSTR KFile::FindNext()
{
	if(m_nFile>-1)
	{
		if(m_nFile<m_arrFile.GetSize()-1)
		{
			int i=m_nFile;
			Close();
			m_nFile=i+1;
			m_nPostion=0;
		}
		else m_nFile=-1;
	}
	return m_nFile>-1?LPCTSTR(m_arrFile[m_nFile].strName):NULL;
}

BOOL KFile::Delete()
{
	int i=m_nFile;
	SetLength(0);
	Close();
	delete[] m_arrFile[i].pBlock;
	m_arrFile.RemoveAt(i);
	return TRUE;
}

BOOL KFile::MoveTo(LPCTSTR szNewName)
{
	int i=GetFileIndex(szNewName);
	if(i<0)
	{
		m_arrFile[m_nFile].strName=szNewName;
	}
	return i>-1;
}

BOOL KFile::CopyTo(LPCTSTR szNewName,BOOL bOverWrite)
{
	int i=GetFileIndex(szNewName);

	if(i<0)
	{
		FILE f;
		f.strName=szNewName;
		f.nSize=0;
		f.nDate=0;
		f.pBlock=new USHORT[8];
		i=m_arrFile.Add(f);
	}
	else if(bOverWrite)
	{
		m_arrFile[i].strName=szNewName;
	}
	else i=-1;
	
	if(i>-1)
	{
		int nBlock,nOffset,nBytes;
		int nCount=m_nFile,nPos=0;

		m_nFile=i;
		SetLength(m_arrFile[nCount].nSize);
		m_nFile=nCount;

		if(m_nBufferBlock<0)
		{
			FILE_WRITEBLOCK(m_pBuffer,-m_nBufferBlock);
		}
		nCount=m_arrFile[m_nFile].nSize;
		while(nCount>0)
		{
			nBlock=nPos/FILE_BLOCKBYTES;
			nOffset=nPos%FILE_BLOCKBYTES;
			nBytes=FILE_BLOCKBYTES-nOffset;

			m_nBufferBlock=m_arrFile[m_nFile].pBlock[nBlock];
			FILE_READBLOCK(m_pBuffer,m_nBufferBlock);
			FILE_WRITEBLOCK(m_pBuffer,m_arrFile[i].pBlock[nBlock]);

			nCount-=nBytes;
			nPos+=nBytes;
		}
	}
	return i>-1;
}

BOOL KFile::Open(LPCTSTR szFile,int nFlags)
{
	m_nFile=GetFileIndex(szFile);
	if(m_nFile==-1  && (nFlags & modeCreate))
	{
		FILE f;
		f.strName=szFile;
		f.nSize=0;
		f.nDate=0;
		f.pBlock=new USHORT[8];
		m_nFile=m_arrFile.Add(f);
	}
	m_nPostion=0;
	return m_nFile>-1;
}

void KFile::Close()
{
	m_nFile=-1;
}

void KFile::ReadWriteBuffer(PBYTE& pBuf, int& nCount)
{
	int nBlock,nOffset,nBytes;
	nBlock=nCount;
	nBlock=ABS(nBlock);
	nOffset=m_nPostion%FILE_BLOCKBYTES;
	nBytes=FILE_BLOCKBYTES-nOffset;
	nBytes=min(nBytes,nBlock);
	nBlock=m_nPostion/FILE_BLOCKBYTES;
	nBlock=m_arrFile[m_nFile].pBlock[nBlock];
	if(ABS(m_nBufferBlock)!=nBlock)
	{
		if(m_nBufferBlock<0)
		{
			FILE_WRITEBLOCK(m_pBuffer,-m_nBufferBlock);
		}
		m_nBufferBlock=nBlock;
		FILE_READBLOCK(m_pBuffer,m_nBufferBlock);
	}
	if(nCount>0) //读
	{
		CopyMemory(pBuf,m_pBuffer+nOffset,nBytes);
		nCount-=nBytes;
	}
	else if(nCount<0) //写
	{
		CopyMemory(m_pBuffer+nOffset,pBuf,nBytes);
		m_nBufferBlock=-nBlock;
		nCount+=nBytes;
	}
	pBuf+=nBytes;
	m_nPostion+=nBytes;
}

int KFile::Write(LPCVOID pBuf, int nCount)
{
	int nBytes;
	PBYTE pData=PBYTE(pBuf);
	nBytes=m_nPostion+nCount;
	if(nBytes>m_arrFile[m_nFile].nSize)SetLength(nBytes);
	nBytes=nCount;
	nCount=-nCount;
	while(nCount<0)
	{
		ReadWriteBuffer(pData,nCount);
	}
	return nBytes;
}

int KFile::Read(PVOID pBuf, int nCount)
{
	int nBytes;
	PBYTE pData=PBYTE(pBuf);
	nBytes=m_arrFile[m_nFile].nSize-m_nPostion;
	nBytes=nCount=min(nBytes,nCount);
	while(nCount>0)
	{
		ReadWriteBuffer(pData,nCount);
	}
	return nBytes;
}

void KFile::WriteString(LPCTSTR lpsz)
{
	LPCTSTR s=lpsz;
	while(*s) 
	{
		switch(*s)
		{
		case '\r':
			if(*(s+1)=='\n')break;
		case '\n':
			Write(lpsz,s-lpsz);
			Write("\r\n",2);
			lpsz=s+1;
			break;
		}
		s++;
	}
	Write(lpsz,s-lpsz);
	Write("\r\n",2);
}

int KFile::ReadString(LPTSTR lpsz, int nMax)
{
	int nCount;
	PBYTE pStart,pData=PBYTE(lpsz);

	nMax--;
	nCount=m_arrFile[m_nFile].nSize-m_nPostion;
	nCount=min(nMax,nCount);
	if(nCount==0)return 0;
	do
	{
		pStart=pData;
		ReadWriteBuffer(pData,nCount);
		nMax=pData-pStart;
		while(pStart<pData)
		{
			switch(*pStart)
			{
			case '\r':
			case '\n':
			case '\0':
				m_nPostion-=pData-pStart-1;
				pData=pStart;
				nMax=0;
				break;
			}
			if(!nMax)break;
			pStart++;
		}
		if(!nMax)break;
	}while(nCount>0);
	if(nMax)
	{
		nCount=1;ReadWriteBuffer(pData,nCount);
		if(!nCount)
		{
			pData--;
			if(*pData!='\r')m_nPostion-=1;
		}
		
	}
	if(*pData=='\r')
	{
		nCount=1;ReadWriteBuffer(pData,nCount);
		if(!nCount)
		{
			pData--;
			if(*pData!='\n')m_nPostion-=1;
		}
	}
	*pData=0;
	return LPTSTR(pData)-lpsz;
}

int KFile::ReadString(KString &String)
{
	int nBuf,nLen;
	LPTSTR pData;

	nBuf=String.GetLength();
	nBuf=max(64,nBuf);
	pData=String.GetBuffer(nBuf);
	nLen=ReadString(pData,nBuf+1);
	if(nLen==nBuf)
	{
		for(;;)
		{
			String.ReleaseBuffer(nBuf);
			pData=String.GetBuffer(nBuf<<1)+nBuf;
			nLen=ReadString(pData,nBuf+1);
			if(nLen!=nBuf)break;
			nBuf<<=1;
		}
		nLen+=nBuf;
	}
	String.ReleaseBuffer(nLen);
	return nLen;
}

int KFile::Seek(int nOffset, int nFrom)
{
	switch(nFrom)
	{
	case end:
		nOffset=m_arrFile[m_nFile].nSize-nOffset;
		break;
	case current:
		nOffset+=m_nPostion;
		break;
	}
	if(nOffset<=m_arrFile[m_nFile].nSize)m_nPostion=nOffset;
	else nOffset=-1;
	return nOffset;
}

int KFile::SetLength(int nNewLength)
{
	int i,j,nCnt,nNewCnt,nBits;

	//调整索引数组的大小
	nCnt=m_arrFile[m_nFile].nSize/FILE_BLOCKBYTES;
	if(m_arrFile[m_nFile].nSize%FILE_BLOCKBYTES)nCnt++;
	nNewCnt=nNewLength/FILE_BLOCKBYTES;
	if(nNewLength%FILE_BLOCKBYTES)nNewCnt++;
	
	if((nCnt&~7)+8 < (nNewCnt&~7)+8)
	{
		PUSHORT pBlock=m_arrFile[m_nFile].pBlock;
		m_arrFile[m_nFile].pBlock=new USHORT[(nNewCnt&~7)+8];
		CopyMemory(m_arrFile[m_nFile].pBlock,pBlock,nCnt*sizeof(USHORT));
		delete[] pBlock;
	}
	nBits=sizeof(DWORD)*8;
	if(nNewCnt>nCnt)
	{
		//分配块
		j=1;
		for(i=nCnt;i<nNewCnt;i++)
		{
			while(j<FILE_BLOCKCOUNT)
			{
				if(!(m_pUsedBitmap[j/nBits] & (1<<(j%nBits))))
				{
					m_pUsedBitmap[j/nBits] |= (1<<(j%nBits));
					m_arrFile[m_nFile].pBlock[i]=j;
					break;
				}
				j++;
			}
		}
	}
	else if(nNewCnt<nCnt)
	{
		//释放块
		for(i=nNewCnt;i<nCnt;i++)
		{
			j=m_arrFile[m_nFile].pBlock[i];
			m_pUsedBitmap[j/nBits] &= ~(1<<(j%nBits));
		}
	}
	m_arrFile[m_nFile].nSize=nNewLength;

	return nNewLength;
}

⌨️ 快捷键说明

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