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

📄 memmap.cpp

📁 memory map file class for C++ builder
💻 CPP
📖 第 1 页 / 共 3 页
字号:

	ASSERT ( m_pMappedViews );
	ASSERT ( uPage );
	ASSERT ( lpOffset );

	LPBYTE lpBytePos	= *lpOffset;
	LPBYTE lpDebugView  = (LPBYTE)m_pMappedViews[*uPage]; // enable the watch view

	// Check if we need to span the page
	UINT uAvailable = ((UINT)m_pMappedViews[*uPage] + MMF_PAGESIZE) - (UINT)*lpOffset;
	if ( uLen > uAvailable ) {

		// calc how many more pages we need
		UINT uNeeded = uLen  - uAvailable;
		uNeeded = UPPER_BOUNDARY(uNeeded);
		uNeeded /= MMF_PAGESIZE;

		// Check if we need to create a page 
		// (maybe user defined a size or strings were deleted)
		if ( *uPage == m_uPageCount-1 )
			if ( Grow(uNeeded) != ERROR_SUCCESS )
				throw _T("Unable to grow");

		// copy the data block by block
		LPBYTE lpBufPos = (LPBYTE)lpIn;

		// fill the remainder of this page
		memcpy(lpBytePos,lpBufPos,uAvailable);
		lpBufPos += uAvailable;

		// loop through filling the pages
		for (UINT i=*uPage+1; i<*uPage+uNeeded; i++) {
			lpBytePos = (LPBYTE)m_pMappedViews[i];

			memcpy(lpBytePos,lpBufPos,MMF_PAGESIZE);
			lpBufPos += MMF_PAGESIZE;
		}

		// calc size of the remainder
		UINT uRemaining = (uLen - uAvailable) % MMF_PAGESIZE;

		// copy the remainder
		lpBytePos = (LPBYTE)m_pMappedViews[i];
		memcpy(lpBytePos,lpBufPos,uRemaining);

		// set the new pointer
		*uPage = i;
		*lpOffset = lpBytePos + uRemaining;
	}
	else {
		// write directly to the file
		memcpy(lpBytePos,lpIn,uLen);
		*lpOffset += uLen;
	}
}

LPBYTE CMemMap::Read(UINT *uPage, LPBYTE *lpOffset, UINT uLen, LPVOID lpOut)
{
	/*************************************************************
	* Read uLen of lpOffset into lpOut
	* lpOffset may be spanned
	* Always return a pointer to the start of the written data
	* Returned value must be sequencial
	* Set lpOffset and uPage to the end of the read data
	* If lpOut is NULL only seek
	**************************************************************/

	ASSERT ( m_pMappedViews );
	ASSERT ( uPage );
	ASSERT ( lpOffset );

	LPBYTE lpBytePos = *lpOffset;

	// Check if spanned
	UINT uRemaining = ((UINT)m_pMappedViews[*uPage] + MMF_PAGESIZE) - (UINT)*lpOffset;
	if ( uLen > uRemaining ) {

		// Calc how many pages are spanned
		UINT pages = uLen - uRemaining;
		pages = UPPER_BOUNDARY(pages);
		pages /= MMF_PAGESIZE;

		// find the last page
		pages += *uPage;

		// Check if last page is within bounds
		if ( pages >= m_uPageCount ) {
			// Try to open the page
			UINT uGrowBy = pages - m_uPageCount;
			DWORD dw = Grow(uGrowBy);
			if ( dw != ERROR_ALREADY_EXISTS ) {
				// We have a serious problem

				// roll back
				Shrink(uGrowBy);

				// throw an exception
				throw _T("Error, page out of bounds");
			}
		}

		// calc size of the remainder
		UINT uSize = (uLen - uRemaining) % MMF_PAGESIZE;

		if ( lpOut ) {

			// delete previous buffer if used
			if ( m_lpDataBuffer )
				delete [] m_lpDataBuffer;

			// allocate new buffer
			m_lpDataBuffer = new BYTE [uLen];

			// copy the data block by block
			LPBYTE lpBufPos = m_lpDataBuffer;

			// fill the remainder of this page
			memcpy(lpBufPos,lpBytePos,uRemaining);
			lpBufPos += uRemaining;

			// loop through filling the pages
			for (UINT i=*uPage+1; i<pages; i++) {
				lpBytePos = (LPBYTE)m_pMappedViews[i];

				memcpy(lpBufPos,lpBytePos,MMF_PAGESIZE);
				lpBufPos += MMF_PAGESIZE;
			}

			// copy the remainder
			lpBytePos = (LPBYTE)m_pMappedViews[i];
			memcpy(lpBufPos,lpBytePos,uSize);

			// copy the pointer
			lpBufPos  = m_lpDataBuffer;

			// Copy to lpOut
			memcpy(lpOut,lpBufPos,uLen);

			// update the pointers
			*uPage    = pages;
			*lpOffset = (LPBYTE)m_pMappedViews[pages] + uSize;

			return lpBufPos;
		}

		// Copy the pointer
		*uPage    = pages;
		*lpOffset = (LPBYTE)m_pMappedViews[pages] + uSize;

		return (LPBYTE)lpOut;
	}
	else {
		// just read and return
		if ( lpOut )
			memcpy(lpOut,lpBytePos,uLen);

		*lpOffset += uLen;
		return lpBytePos;
	}

	// We shouldn't be here
	ASSERT ( 1 );
	return NULL;
}

BOOL CMemMap::UpdateBinary(LPVOID lpBin, UINT uSize, UINT uId)
{
	/*******************************************************
	* Check if string exists already and if the same length
	* Convert binary to string and add as a string
	*******************************************************/

	ASSERT ( lpBin );
	ASSERT ( m_pMappedViews );

	CheckForNewPages();

	// Validate the ID
	if ( uId == 0xFFFFFFFF || uId == 0xFFFFFF00 )
		return FALSE;

	LPBYTE lpBytePos = 0;
	UINT   uPage     = 0;
	UINT   uBuf      = 1;

	// Check if the id already exists
	if ( FindID(uId,&uPage,&lpBytePos) == FALSE )
		return AddBinary(lpBin,uSize,uId);

	// skip the id
	Read(&uPage,&lpBytePos,4,&uBuf); // read the id

	// Get the string length
	Read(&uPage,&lpBytePos,4,&uBuf); // read the size

	// Check if can overwrite existing
	if ( uBuf == uSize + 1) {
		// overwrite
		Write(&uPage,&lpBytePos,uSize,lpBin);
		return TRUE;
	}

	// Delete the exisiting
	DeleteID(uId);

	// Add the new
	return AddBinary(lpBin,uSize,uId);
}

BOOL CMemMap::AddBinary(LPVOID lpBin, UINT uSize, UINT uId)
{
	/*******************************************************
	* Convert to and add as a byte array
	*******************************************************/

	ASSERT ( m_pMappedViews );

	CheckForNewPages();

	// Validate the ID
	if ( uId == 0xFFFFFFFF || uId == 0xFFFFFF00 )
		return FALSE;

	LPBYTE lpBytePos = 0;
	UINT   uPage	 = 0;

	LPBYTE lpDebugView = (LPBYTE)m_pMappedViews[uPage]; // enable the watch view

	// Check if the id already exists
	if ( FindID(uId,&uPage,&lpBytePos) == TRUE )
		return FALSE;

	// Copy the binary to a buffer and null terminate
	LPBYTE lpTmp = new BYTE [uSize + 1];
	memcpy(lpTmp,lpBin,uSize);
	lpTmp[uSize] = 0;
	uSize++;

	// write tha data
	Write(&uPage,&lpBytePos,4,		&uId);
	Write(&uPage,&lpBytePos,4,		&uSize);
	Write(&uPage,&lpBytePos,uSize,	lpTmp);
	Write(&uPage,&lpBytePos,4,		DOUBLE_NULL);

	delete [] lpTmp;

	return TRUE;
}

UINT CMemMap::GetBinary(LPVOID lpBin, UINT uSize, UINT uId)
{
	/*******************************************************
	* Check if data stream exists
	* if lpBin is NULL, return the size
	* copy data to lpBin
	*******************************************************/

	ASSERT ( m_pMappedViews );

	CheckForNewPages();

	// Validate the ID
	if ( uId == 0xFFFFFFFF || uId == 0xFFFFFF00 )
		return FALSE;

	LPBYTE lpBytePos = 0;
	UINT   uPage     = 0;
	UINT   uLen      = 0;

	// Check if the id exists
	if ( FindID(uId,&uPage,&lpBytePos) == FALSE )
		return 0;

	Read(&uPage,&lpBytePos,4/*id*/,		NULL);
	Read(&uPage,&lpBytePos,4/*strlen*/,	&uLen);
	uLen -= 1/*null*/;

	if ( ! lpBin )
		return uLen;

	if ( uLen > uSize )
		uLen = uSize;

	// Read the data
	Read(&uPage,&lpBytePos,uLen,lpBin);

	// return the size
	return uLen;
}

LPVOID CMemMap::GetBinary(UINT uId)
{
	/*******************************************************
	* Check if data stream exists
	* Convert data stream to binary
	*******************************************************/

	ASSERT ( m_pMappedViews );

	CheckForNewPages();

	// Validate the ID
	if ( uId == 0xFFFFFFFF || uId == 0xFFFFFF00 )
		return FALSE;

	LPBYTE lpBytePos = 0;
	UINT   uPage     = 0;
	UINT   ulen      = 0;

	// Check if the id exists
	if ( FindID(uId,&uPage,&lpBytePos) == FALSE )
		return 0;

	ulen = GetLength(uPage,lpBytePos);
	ulen -= 1/*null*/;

	// set pointer to the data
	Read(&uPage,&lpBytePos,8/*id & strlen*/,NULL);

	// Create a return Buffer
	if ( m_lpReturnBuffer )
		delete [] m_lpReturnBuffer;
	m_lpReturnBuffer = new BYTE [ulen];

	// Read the data
	Read(&uPage,&lpBytePos,ulen,m_lpReturnBuffer);

	// return the buffer
	return (LPVOID)*m_lpReturnBuffer;
}

BOOL CMemMap::AddString(LPCTSTR szString, UINT uId)
{
	ASSERT ( szString );
	ASSERT ( m_pMappedViews );

	CheckForNewPages();

	// Validate the ID
	if ( uId == 0xFFFFFFFF || uId == 0xFFFFFF00 )
		return FALSE;

	LPBYTE	lpBytePos	= 0;
	UINT	uPage		= 0;

	// Check if the id already exists
	if ( FindID(uId,&uPage,&lpBytePos) == TRUE )
		return FALSE;

	LPBYTE lpDebugView = (LPBYTE)m_pMappedViews[uPage];

	// Calc how many bytes we need
	UINT uStrlen = (_tcslen(szString) + 1 ) * sizeof(TCHAR);

	Write(&uPage, &lpBytePos, 4,		&uId);
	Write(&uPage, &lpBytePos, 4,		&uStrlen);
	Write(&uPage, &lpBytePos, uStrlen,  (LPVOID)szString);
	Write(&uPage, &lpBytePos, 4,		DOUBLE_NULL);

	return TRUE;
}

UINT CMemMap::GetStringLength(UINT uId)
{
	ASSERT ( m_pMappedViews );

	CheckForNewPages();

	// Validate the ID
	if ( uId == 0xFFFFFFFF || uId == 0xFFFFFF00 )
		return 0;

	LPBYTE lpBytePos	= 0;
	UINT   uPage		= 0;
	UINT   uLen			= 0;

	// Check if the id already exists
	if ( FindID(uId,&uPage,&lpBytePos) == FALSE )
		return 0;

	// Get the string length
	uLen = GetLength(uPage,lpBytePos);

	return uLen - sizeof(TCHAR);
}

UINT CMemMap::GetString(LPCTSTR szString, UINT uLen, UINT uId)
{
	/********************************************************
	* If szString then copy to there
	* return length of string or copied data
	********************************************************/

	ASSERT ( m_pMappedViews );

	CheckForNewPages();

	// Validate the ID
	if ( uId == 0xFFFFFFFF || uId == 0xFFFFFF00 )
		return NULL;

	LPTSTR lpString    = NULL;	// The string to return
	LPBYTE lpBytePos   = 0;		// a navigation pointer
	UINT   uPage = 0;

	// Check if the id already exists
	if ( FindID(uId,&uPage,&lpBytePos) == FALSE )
		return 0;

	UINT _uLen = 0;
	Read(&uPage,&lpBytePos,4,NULL);
	Read(&uPage,&lpBytePos,4,&_uLen);

	if ( ! szString )
		return _uLen;

	if ( _uLen > uLen )
		_uLen = uLen;

	Read(&uPage,&lpBytePos,_uLen,(LPBYTE)szString);

	return _uLen;
}

LPCTSTR CMemMap::GetString(UINT uId)
{
	/********************************************************
	* Return a pointer to the string
	********************************************************/

	ASSERT ( m_pMappedViews );

	CheckForNewPages();

	// Validate the ID
	if ( uId == 0xFFFFFFFF || uId == 0xFFFFFF00 )
		return NULL;

	LPTSTR lpString    = NULL;	// The string to return
	LPBYTE lpBytePos   = 0;		// a navigation pointer
	UINT   uPage	   = 0;

	// Check if the id already exists
	if ( FindID(uId,&uPage,&lpBytePos) == FALSE )
		return NULL;

	UINT uLen = 0;
	Read(&uPage,&lpBytePos,4,NULL);
	Read(&uPage,&lpBytePos,4,&uLen);

	// Check if the string is spanned
	UINT uRemaining = ((UINT)m_pMappedViews[uPage] + MMF_PAGESIZE) - (UINT)lpBytePos;
	if ( uLen > uRemaining ) {

		try
		{
			// delete previous buffer if used
			if ( m_lpReturnBuffer )
				delete [] m_lpReturnBuffer;

			// allocate new buffer
			m_lpReturnBuffer = new BYTE [uLen];
		}
		catch (...)
		{
			TRACE ( _T("Buffer allocation failed in GetString") );
		}

		return (LPTSTR)Read(&uPage,&lpBytePos,uLen,m_lpReturnBuffer);
	}
	else
		return (LPTSTR)Read(&uPage,&lpBytePos,uLen,NULL);
}

VOID CMemMap::NextID(UINT *uPage, LPBYTE *lpOffset)
{
	/********************************************************
	* Move the pointer to the next ID location
	* Pointer should be pointing to an ID before calling
	********************************************************/

	ASSERT( lpOffset );
	ASSERT( uPage );

	if ( ! m_pMappedViews )
		return;

	LPBYTE lpCurPos		= *lpOffset;	// a navigation pointer
	UINT   uCurPage		= *uPage;
	UINT   iLen			= 0;

	// Get the string length
	iLen = GetLength(uCurPage,lpCurPos);
	iLen += 8;
	Read(&uCurPage,&lpCurPos,iLen,NULL);

	// Update the pointer
	*uPage		= uCurPage;

⌨️ 快捷键说明

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