Click here to Skip to main content
15,885,546 members
Articles / Web Development / HTML

A Comprehensive CE Class Library to Replace ATL and MFC

Rate me:
Please Sign up or sign in to vote.
4.48/5 (14 votes)
4 Oct 2000CPOL 278.7K   998   70  
A collection of classes for CE that do not use ATL or MFC, plus an FTP client, database viewer, and sample application that solves beam deflection equations.
#include "stdafx.h"
#include "CeDb.h"

#include <winnls.h>


char* WideToAscii( char* s, const wchar_t* ws )
{
	char* pszSave = (char*) s;
    while (*s++ = (char) *ws++ )
		;

	return (pszSave);
}


bool CeDb::ReadRec(CeDbRecord& rec)
{
	ASSERT(IsOpen());

	if (! rec.m_bLocalAlloc && rec.m_pProps)
		delete[] rec.m_pProps;

	rec.m_pProps = NULL;
	rec.m_cbProps = 0;
	rec.m_bLocalAlloc = true;

	// Getting a record WILL overwrite the old values
	rec.m_wProps = 0;

	// read all properties
	rec.m_oid = ::CeReadRecordProps(
		m_hDb,					// this database
		CEDB_ALLOWREALLOC,		// no realloc
		&rec.m_wProps,			// number of properties in THIS record
		NULL,					// get all columnsfor THIS record
		(BYTE**) &rec.m_pProps,	// the properties values
		&rec.m_cbProps			// size of the allocated space	
	);

	return (rec.m_oid && rec.m_pProps && rec.m_wProps);
}

//
// CEVT_BLOB		A CEBLOB structure. 
// CEVT_FILETIME	A FILETIME structure. 
// CEVT_I2			A 16-bit signed integer. 
// CEVT_I4			A 32-bit signed integer. 
// CEVT_LPWSTR		A null-terminated string. 
// CEVT_UI2			A 16-bit unsigned integer. 
// CEVT_UI4			A 32-bit unsigned integer. 
//
// And beginning in 2.11
// CEVT_BOOL		A boolean value.
// CEVT_R8			A double floating point value.
//

bool CeDbRecord::GetIndexVal(int nProp, SHORT& iProp) const
{
//	ASSERT(nProp < m_wProps && nProp >= 0);
	if (nProp < 0 || nProp >= m_wProps)
		return false;
	ASSERT(LOWORD(m_pProps[nProp].propid) == CEVT_I2);
	iProp = m_pProps[nProp].val.iVal;
	return true;
}


bool CeDbRecord::GetIndexVal(int nProp, USHORT& uiProp) const
{
//	ASSERT(nProp < m_wProps && nProp >= 0);
	if (nProp < 0 || nProp >= m_wProps)
		return false;
	ASSERT(LOWORD(m_pProps[nProp].propid) == CEVT_UI2);
	uiProp = m_pProps[nProp].val.uiVal;
	return true;
}


bool CeDbRecord::GetIndexVal(int nProp, LONG& lProp) const
{
//	ASSERT(nProp < m_wProps && nProp >= 0);
	if (nProp < 0 || nProp >= m_wProps)
		return false;
	ASSERT(LOWORD(m_pProps[nProp].propid) == CEVT_I4);
	lProp = m_pProps[nProp].val.lVal;
	return true;
}


bool CeDbRecord::GetIndexVal(int nProp, ULONG& ulProp) const
{
//	ASSERT(nProp < m_wProps && nProp >= 0);
	if (nProp < 0 || nProp >= m_wProps)
		return false;
	ASSERT(LOWORD(m_pProps[nProp].propid) == CEVT_UI4);
	ulProp = m_pProps[nProp].val.ulVal;
	return true;
}


bool CeDbRecord::GetIndexVal(int nProp, FILETIME& ftProp) const
{
//	ASSERT(nProp < m_wProps && nProp >= 0);
	if (nProp < 0 || nProp >= m_wProps)
		return false;
	ASSERT(LOWORD(m_pProps[nProp].propid) == CEVT_FILETIME);
	ftProp = m_pProps[nProp].val.filetime;
	return true;
}


#ifdef CEVT_BOOL
#pragma warning(disable: 4800)
bool CeDbRecord::GetIndexVal(int nProp, bool& bProp) const
{
//	ASSERT(nProp < m_wProps && nProp >= 0);
	if (nProp < 0 || nProp >= m_wProps)
		return false;
	ASSERT(LOWORD(m_pProps[nProp].propid) == CEVT_BOOL);
	bProp = m_pProps[nProp].val.boolVal;
	return true;
}
#endif

#ifdef CEVT_R8
bool CeDbRecord::GetIndexVal(int nProp, double& dblProp) const
{
//	ASSERT(nProp < m_wProps && nProp >= 0);
	if (nProp < 0 || nProp >= m_wProps)
		return false;
	ASSERT(LOWORD(m_pProps[nProp].propid) == CEVT_R8);
	dblProp = m_pProps[nProp].val.dblVal;
	return true;
}
#endif


bool CeDbRecord::GetIndexVal(int nProp, CEBLOB& blobProp) const
{
//	ASSERT(nProp < m_wProps && nProp >= 0);
	if (nProp < 0 || nProp >= m_wProps)
		return false;
	ASSERT(LOWORD(m_pProps[nProp].propid) == CEVT_BLOB);
	return true;
}

inline char HiNibble(BYTE by)	{ return (by >> 4);   }
inline char LoNibble(BYTE by)	{ return (by & 0x0F); }

static CeString GetBlob(DWORD dwSize, BYTE* lpByte)
{
	CeString str;
	LPTSTR lpsz = str.GetBufferSetLength(3 * dwSize);
	for (DWORD ii = 0; ii < dwSize; ii++)
	{
		BYTE byTmp;

		byTmp = HiNibble(*lpByte);
		*lpsz++ = (TCHAR) (byTmp < 0x0A) ? _T('0') + byTmp: _T('A') + (byTmp - 0x0A);

		byTmp = LoNibble(*lpByte);
		*lpsz++ = (TCHAR) (byTmp < 0x0A) ? _T('0') + byTmp: _T('A') + (byTmp - 0x0A);
	
		*lpsz++ = _T(' ');
		lpByte++;
	}
	*lpsz = 0;
	str.ReleaseBuffer();
	return str;
}

// valid for all types, limited to 256 bytes for Blob
bool CeDbRecord::GetIndexVal(int nProp, CeString& strProp) const
{
	//ASSERT(nProp < m_wProps && nProp >= 0);
	if (nProp < 0 || nProp >= m_wProps)
	{
		strProp.Empty();
		return false;
	}

	switch ( LOWORD(m_pProps[nProp].propid) )
	{
	case CEVT_BLOB:
		strProp = GetBlob(m_pProps[nProp].val.blob.dwCount, m_pProps[nProp].val.blob.lpb);
		break;
	case CEVT_FILETIME:
		{
			SYSTEMTIME st;

			BOOL bSuccess = ::FileTimeToSystemTime(&m_pProps[nProp].val.filetime, &st);
			if (! bSuccess || st.wYear > 9999)
			{
				strProp.Empty();
				return true;
			}

			CeString strTime;

			::GetDateFormat(LOCALE_SYSTEM_DEFAULT, DATE_SHORTDATE,
				&st, NULL, strProp.GetBufferSetLength(32), 32);
			strProp.ReleaseBuffer();

			::GetTimeFormat(LOCALE_SYSTEM_DEFAULT, TIME_NOSECONDS,
				&st, NULL, strTime.GetBufferSetLength(32), 32);
			strTime.ReleaseBuffer();

			strProp += _T(" ");
			strProp += strTime;
		}
		break;
	case CEVT_I2:
		strProp = CeString(m_pProps[nProp].val.iVal);
		break;
	case CEVT_I4:
		strProp = CeString(m_pProps[nProp].val.lVal);
		break;
	case CEVT_LPWSTR:
#ifdef UNICODE
		strProp = m_pProps[nProp].val.lpwstr;
#else
		WideToAscii( strProp.GetBufferSetLength( wcslen(m_pProps[nProp].val.lpwstr) ),
			m_pProps[nProp].val.lpwstr );
		strProp.ReleaseBuffer();
#endif
		break;
	case CEVT_UI2:
		strProp = CeString((ULONG)m_pProps[nProp].val.uiVal);
		break;
	case CEVT_UI4:
		strProp = CeString((ULONG)m_pProps[nProp].val.ulVal);
		break;
#ifdef CEVT_BOOL
	case CEVT_BOOL:
		strProp = m_pProps[nProp].val.boolVal ? _T("true"): _T("false");
		break;
#endif
#ifdef CEVT_R8
	case CEVT_R8:
		strProp = CeString(m_pProps[nProp].val.dblVal);
		break;
#endif
	default:
		return false;
	}

	return true;
}


bool CeDbRecord::SetIndexVal(int nProp, SHORT iProp)
{
//	ASSERT(nProp < m_wProps && nProp >= 0);
	if (nProp < 0 || nProp >= m_wProps)
		return false;
	ASSERT(LOWORD(m_pProps[nProp].propid) == CEVT_I2);
	m_pProps[nProp].val.iVal = iProp;
	return true;
}

bool CeDbRecord::SetIndexVal(int nProp, USHORT uiProp)
{
//	ASSERT(nProp < m_wProps && nProp >= 0);
	if (nProp < 0 || nProp >= m_wProps)
		return false;
	ASSERT(LOWORD(m_pProps[nProp].propid) == CEVT_UI2);
	m_pProps[nProp].val.uiVal = uiProp;
	return true;
}

bool CeDbRecord::SetIndexVal(int nProp, LONG lProp)
{
//	ASSERT(nProp < m_wProps && nProp >= 0);
	if (nProp < 0 || nProp >= m_wProps)
		return false;
	ASSERT(LOWORD(m_pProps[nProp].propid) == CEVT_I4);
	m_pProps[nProp].val.lVal = lProp;
	return true;
}

bool CeDbRecord::SetIndexVal(int nProp, ULONG ulProp)
{
//	ASSERT(nProp < m_wProps && nProp >= 0);
	if (nProp < 0 || nProp >= m_wProps)
		return false;
	ASSERT(LOWORD(m_pProps[nProp].propid) == CEVT_UI4);
	m_pProps[nProp].val.ulVal = ulProp;
	return true;
}

bool CeDbRecord::SetIndexVal(int nProp, FILETIME ftProp)
{
//	ASSERT(nProp < m_wProps && nProp >= 0);
	if (nProp < 0 || nProp >= m_wProps)
		return false;
	ASSERT(LOWORD(m_pProps[nProp].propid) == CEVT_FILETIME);
	m_pProps[nProp].val.filetime = ftProp;
	return true;
}

#ifdef CEVT_BOOL
bool CeDbRecord::SetIndexVal(int nProp, bool bProp)
{
//	ASSERT(nProp < m_wProps && nProp >= 0);
	if (nProp < 0 || nProp >= m_wProps)
		return false;
	ASSERT(LOWORD(m_pProps[nProp].propid) == CEVT_BOOL);
	m_pProps[nProp].val.boolVal = bProp;
	return true;
}
#endif

#ifdef CEVT_R8
bool CeDbRecord::SetIndexVal(int nProp, double dblProp)
{
//	ASSERT(nProp < m_wProps && nProp >= 0);
	if (nProp < 0 || nProp >= m_wProps)
		return false;
	ASSERT(LOWORD(m_pProps[nProp].propid) == CEVT_R8);
	m_pProps[nProp].val.dblVal = dblProp;
	return true;
}
#endif


CEPROPVAL* CeDbRecord::DupProps(CEPROPVAL* pPropsOrig, WORD wProps, DWORD cbNewProps)
{
	// allocate a buffer
	CEPROPVAL* pProps = (CEPROPVAL*) new BYTE[cbNewProps];
	ASSERT(NULL != pProps);
	if (NULL == pProps)
		return NULL;

	// assumes structure and pointer are word aligned
	BYTE* pData = (BYTE*) pProps + sizeof CEPROPVAL * wProps;

	for (WORD ii = 0; ii < wProps; ii++)
	{
		// shallow copy, don't require extra memory space to store the value
		pProps[ii] = pPropsOrig[ii];

		// check if deep copy required
		if ( CEVT_BLOB == LOWORD(pPropsOrig[ii].propid) )
		{
			// Note: could be a NULL value
			if (0 == pPropsOrig[ii].val.blob.dwCount || NULL == pProps[ii].val.blob.lpb)
				continue;

			// NOTE: this has to be on a WORD boundry!!!
			DWORD dwLen = pPropsOrig[ii].val.blob.dwCount;
			pProps[ii].val.blob.lpb = pData;

			memcpy( pProps[ii].val.blob.lpb, pPropsOrig[ii].val.blob.lpb, dwLen );

			// required so character indexes are even
			pData += (dwLen + (dwLen % sizeof WORD));
		}
		else if ( CEVT_LPWSTR == LOWORD(pPropsOrig[ii].propid) )
		{
			// Note: could be a NULL value
			if (NULL == pPropsOrig[ii].val.lpwstr)
				continue;

			// note: results are always word alligned
			// since the characters are the size of the word
			DWORD dwLen = (wcslen(pPropsOrig[ii].val.lpwstr) + 1) * sizeof WCHAR;
			pProps[ii].val.lpwstr = (WCHAR *) pData;

			memcpy(pData, pPropsOrig[ii].val.lpwstr, dwLen);

			pData += dwLen;
		}
	}

	return pProps;
}

bool CeDbRecord::SetIndexVal(int nProp, CEBLOB blobProp)
{
	ASSERT(nProp < m_wProps && nProp >= 0);
	ASSERT(LOWORD(m_pProps[nProp].propid) == CEVT_BLOB);

	if (m_pProps[nProp].val.blob.dwCount < blobProp.dwCount)
	{
		// need to reallocate the ENTIRE record and copy in this one
		// Note: THIS will ONLY work when EXPANDING the allocated memory

		DWORD cbProps = (blobProp.dwCount - m_pProps[nProp].val.blob.dwCount);
		//cbProps += (dwLen % sizeof WORD)

		m_pProps[nProp].val.blob.lpb = blobProp.lpb;
		m_pProps[nProp].val.blob.dwCount = blobProp.dwCount;

		CEPROPVAL* pProps = DupProps(m_pProps, m_wProps, cbProps);
		if (NULL == pProps)
			return false;
		if (m_bLocalAlloc)
			::LocalFree(m_pProps);
		else
			delete[] (BYTE*) m_pProps;
		m_pProps = pProps;
		m_cbProps = cbProps;
		m_bLocalAlloc = false;
	}
	else
	{
		memcpy(m_pProps[nProp].val.blob.lpb, blobProp.lpb, blobProp.dwCount);
		m_pProps[nProp].val.blob.dwCount = blobProp.dwCount;
	}

	return false;
}

bool CeDbRecord::SetIndexVal(int nProp, LPCWSTR lpszProp)
{
	ASSERT(nProp < m_wProps && nProp >= 0);
	ASSERT(LOWORD(m_pProps[nProp].propid) == CEVT_LPWSTR);

	int nOldLen = (m_pProps[nProp].val.lpwstr) ? wcslen(m_pProps[nProp].val.lpwstr) + 2 : 0;
	int nNewLen = wcslen(lpszProp) + 2;
	
	if (nOldLen < nNewLen)
	{
		// need to reallocate the ENTIRE record and copy in this one
		// Note: THIS will ONLY work when EXPANDING the allocated memory

		DWORD cbProps = m_cbProps + (nNewLen - nOldLen) * sizeof WCHAR;

		// set pointer
		m_pProps[nProp].val.lpwstr = (LPWSTR) lpszProp;

		CEPROPVAL* pProps = DupProps(m_pProps, m_wProps, cbProps);
		if (NULL == pProps)
			return false;
		if (m_bLocalAlloc)
			::LocalFree(m_pProps);
		else
			delete[] (BYTE*) m_pProps;
		m_cbProps = cbProps;
		m_pProps = pProps;
		m_bLocalAlloc = false;
	}
	else
		wcscpy(m_pProps[nProp].val.lpwstr, lpszProp);

	return true;
}


bool CeDbRecord::AddProp(WORD wProp, WORD wType)
{
	CEPROPVAL* pProps = NULL;

	if (NULL == m_pProps)
	{
		// append to end
		pProps = (CEPROPVAL*) new BYTE[sizeof CEPROPVAL];
		DWORD dwErr = GetLastError();
		ASSERT(NULL != pProps);
	}
	else
	{
		{
			// enlarge
			pProps = (CEPROPVAL*) new BYTE[m_cbProps + sizeof CEPROPVAL];
			memcpy(pProps, m_pProps, m_cbProps);
		}

		DWORD dwErr = GetLastError();
		ASSERT(NULL != pProps);

		// move data from end
		for (int ii = m_wProps - 1; ii >= 0 ; ii--)
		{
			DWORD dwLen;

			if (CEVT_BLOB == LOWORD(pProps[ii].propid))
			{
				// NOTE: this has to be on a WORD boundry!!!
				dwLen = pProps[ii].val.blob.dwCount;

				if (0 != dwLen && NULL != pProps[ii].val.blob.lpb)
					pProps[ii].val.blob.lpb = (BYTE*) memmove( pProps[ii].val.blob.lpb + sizeof CEPROPVAL, pProps[ii].val.blob.lpb, dwLen);
			}
			else if (CEVT_LPWSTR == LOWORD(pProps[ii].propid))
			{
				// note: results are always word alligned
				// since the characters are the size of the word
				dwLen = pProps[ii].val.lpwstr ? (wcslen(pProps[ii].val.lpwstr) + 1) * sizeof WCHAR: 0;

				if (0 != dwLen)
					pProps[ii].val.lpwstr = (WCHAR*) memmove(pProps[ii].val.lpwstr + sizeof CEPROPVAL, pProps[ii].val.lpwstr, dwLen);
			}
		}
	}

	if (m_bLocalAlloc)
		::LocalFree(m_pProps);
	else
		delete[] (BYTE*) m_pProps;

	m_pProps = pProps;
	m_bLocalAlloc = false;
	m_cbProps += sizeof CEPROPVAL;
	m_wProps++;
	ZeroMemory(&m_pProps[m_wProps-1], sizeof CEPROPVAL);
	m_pProps[m_wProps-1].propid = MAKELPARAM(wType, wProp);

	return true;
}

bool CeDbRecord::RemProp(int nIndex)
{
//	memmove();
//	DupProps();
	return false;
}

bool CeDbRecord::RemProp(WORD wProp)
{
//	int nProp = FindProp(wProp);
//	memmove();
//	DupProps();
	return false;
}



By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
United States United States
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions