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

📄 spcoll.cpp

📁 股软 通达信行情接收接口, 包括美元汇率
💻 CPP
📖 第 1 页 / 共 3 页
字号:
	// insert new value in the gap
	SP_ASSERT(nIndex + nCount <= m_nSize);
	while (nCount--)
		m_pData[nIndex++] = newElement;
}

void CSPStringArray::RemoveAt(int nIndex, int nCount /* = 1 */)
{
	SP_ASSERT_VALID(this);
	SP_ASSERT(nIndex >= 0);
	SP_ASSERT(nCount >= 0);
	SP_ASSERT(nIndex + nCount <= m_nSize);

	// just remove a range
	int nMoveCount = m_nSize - (nIndex + nCount);

	SPDestructElements(&m_pData[nIndex], nCount);

	if (nMoveCount)
		memcpy(&m_pData[nIndex], &m_pData[nIndex + nCount],
			nMoveCount * sizeof(CSPString));
	m_nSize -= nCount;
}

void CSPStringArray::InsertAt(int nStartIndex, CSPStringArray* pNewArray)
{
	SP_ASSERT_VALID(this);
	SP_ASSERT(pNewArray != NULL);
	SP_ASSERT_VALID(pNewArray);
	SP_ASSERT(nStartIndex >= 0);

	if (pNewArray->GetSize() > 0)
	{
		InsertAt(nStartIndex, pNewArray->GetAt(0), pNewArray->GetSize());
		for (int i = 0; i < pNewArray->GetSize(); i++)
			SetAt(nStartIndex + i, pNewArray->GetAt(i));
	}
}

CSPStringArray * CSPStringArray::m_pSortSPStringArray = NULL;

int SortSPString(const void *p1,const void *p2)
{
	if( NULL == p1 || NULL == p2 )
		return 0;

	DWORD dw1 = *(DWORD *)p1;
	DWORD dw2 = *(DWORD *)p2;

	if( NULL == CSPStringArray::m_pSortSPStringArray
		|| dw1 < 0 || dw1 >= (DWORD)CSPStringArray::m_pSortSPStringArray->GetSize()
		|| dw2 < 0 || dw2 >= (DWORD)CSPStringArray::m_pSortSPStringArray->GetSize() )
	{
		SP_ASSERT(FALSE);
		return 0;
	}

	return strcmp(CSPStringArray::m_pSortSPStringArray->ElementAt(dw1),
				CSPStringArray::m_pSortSPStringArray->ElementAt(dw2) );
}

BOOL CSPStringArray::GetSortIDArray( CSPDWordArray & adwSortID )
{
	adwSortID.SetSize( 0, GetSize() + 1 );

	for( DWORD i=0; i<(DWORD)GetSize(); i++ )
		adwSortID.Add( i );

	m_pSortSPStringArray = this;
	if( adwSortID.GetData() )
		qsort( adwSortID.GetData(), adwSortID.GetSize(), sizeof(DWORD), SortSPString );
	m_pSortSPStringArray = NULL;

	return TRUE;
}

void CSPStringArray::Serialize(CSPArchive& ar)
{
	SP_ASSERT_VALID(this);

	if (ar.IsStoring())
	{
		ar.WriteCount(GetSize());
		for (int i = 0; i < m_nSize; i++)
			ar << m_pData[i];
	}
	else
	{
		DWORD nOldSize = ar.ReadCount();
		SetSize(nOldSize);
		for (DWORD i = 0; i < nOldSize; i++)
			ar >> m_pData[i];
	}
}

void CSPStringArray::SPConstructElements(CSPString* pElements, int nCount)
{
	SP_ASSERT(nCount == 0 ||
		SP_IsValidAddress(pElements, nCount * sizeof(CSPString)));

	for (; nCount--; ++pElements)
		memcpy(pElements, &afxEmptySPString, sizeof(*pElements));
}

void CSPStringArray::SPDestructElements(CSPString* pElements, int nCount)
{
	SP_ASSERT(nCount == 0 ||
		SP_IsValidAddress(pElements, nCount * sizeof(CSPString)));

	// call the destructor(s)
	for (; nCount--; pElements++)
		pElements->~CSPString();
}

// Diagnostics

#ifdef _DEBUG
void CSPStringArray::Dump() const
{
	Object::Dump( );
}

void CSPStringArray::AssertValid() const
{
	Object::AssertValid();
	if (m_pData == NULL)
	{
		SP_ASSERT(m_nSize == 0);
		SP_ASSERT(m_nMaxSize == 0);
	}
	else
	{
		SP_ASSERT(m_nSize >= 0);
		SP_ASSERT(m_nMaxSize >= 0);
		SP_ASSERT(m_nSize <= m_nMaxSize);
		SP_ASSERT(SP_IsValidAddress(m_pData, m_nMaxSize * sizeof(CSPString)));
	}
}
#endif //_DEBUG

/////////////////////////////////////////////////////////////////////////////
// CSPPlex

CSPPlex* PASCAL CSPPlex::Create(CSPPlex*& pHead, UINT nMax, UINT cbElement)
{
	SP_ASSERT(nMax > 0 && cbElement > 0);
	CSPPlex* p = (CSPPlex*) new BYTE[sizeof(CSPPlex) + nMax * cbElement];
			// may throw exception
	p->pNext = pHead;
	pHead = p;  // change head (adds in reverse order for simplicity)
	return p;
}

void CSPPlex::FreeDataChain()     // free this one and links
{
	CSPPlex* p = this;
	while (p != NULL)
	{
		BYTE* bytes = (BYTE*) p;
		CSPPlex* pNext = p->pNext;
		delete[] bytes;
		p = pNext;
	}
}

/////////////////////////////////////////////////////////////////////////////
// CSPMapStringToPtr out-of-line functions

CSPMapStringToPtr::CSPMapStringToPtr(int nBlockSize)
{
	SP_ASSERT(nBlockSize > 0);

	m_pHashTable = NULL;
	m_nHashTableSize = 17;  // default size
	m_nCount = 0;
	m_pFreeList = NULL;
	m_pBlocks = NULL;
	m_nBlockSize = nBlockSize;
}

inline UINT CSPMapStringToPtr::HashKey(LPCTSTR key) const
{
	UINT nHash = 0;
	while (*key)
		nHash = (nHash<<5) + nHash + *key++;
	return nHash;
}

void CSPMapStringToPtr::InitHashTable(
	UINT nHashSize, BOOL bAllocNow)
//
// Used to force allocation of a hash table or to override the default
//   hash table size of (which is fairly small)
{
	SP_ASSERT_VALID(this);
	SP_ASSERT(m_nCount == 0);
	SP_ASSERT(nHashSize > 0);

	if (m_pHashTable != NULL)
	{
		// free hash table
		delete[] m_pHashTable;
		m_pHashTable = NULL;
	}

	if (bAllocNow)
	{
		m_pHashTable = new CAssoc* [nHashSize];
		memset(m_pHashTable, 0, sizeof(CAssoc*) * nHashSize);
	}
	m_nHashTableSize = nHashSize;
}

static inline void DestructElement(CSPString* pOldData)
{
	pOldData->~CSPString();
}

void CSPMapStringToPtr::RemoveAll()
{
	SP_ASSERT_VALID(this);

	if (m_pHashTable != NULL)
	{
		// destroy elements
		for (UINT nHash = 0; nHash < m_nHashTableSize; nHash++)
		{
			CAssoc* pAssoc;
			for (pAssoc = m_pHashTable[nHash]; pAssoc != NULL;
			  pAssoc = pAssoc->pNext)
			{
				DestructElement(&pAssoc->key);  // free up string data
			}
		}

		// free hash table
		delete [] m_pHashTable;
		m_pHashTable = NULL;
	}

	m_nCount = 0;
	m_pFreeList = NULL;
	m_pBlocks->FreeDataChain();
	m_pBlocks = NULL;
}

CSPMapStringToPtr::~CSPMapStringToPtr()
{
	RemoveAll();
	SP_ASSERT(m_nCount == 0);
}

// Assoc helpers
// same as CList implementation except we store CAssoc's not CNode's
//    and CAssoc's are singly linked all the time

CSPMapStringToPtr::CAssoc*
CSPMapStringToPtr::NewAssoc()
{
	if (m_pFreeList == NULL)
	{
		// add another block
		CSPPlex* newBlock = CSPPlex::Create(m_pBlocks, m_nBlockSize,
							sizeof(CSPMapStringToPtr::CAssoc));
		// chain them into free list
		CSPMapStringToPtr::CAssoc* pAssoc =
				(CSPMapStringToPtr::CAssoc*) newBlock->data();
		// free in reverse order to make it easier to debug
		pAssoc += m_nBlockSize - 1;
		for (int i = m_nBlockSize-1; i >= 0; i--, pAssoc--)
		{
			pAssoc->pNext = m_pFreeList;
			m_pFreeList = pAssoc;
		}
	}
	SP_ASSERT(m_pFreeList != NULL);  // we must have something

	CSPMapStringToPtr::CAssoc* pAssoc = m_pFreeList;
	m_pFreeList = m_pFreeList->pNext;
	m_nCount++;
	SP_ASSERT(m_nCount > 0);  // make sure we don't overflow
	//CSPString	emptyString;
	//memcpy(&pAssoc->key, &emptyString, sizeof(CSPString));
	memcpy(&pAssoc->key, &afxEmptySPString, sizeof(pAssoc->key));

	pAssoc->value = 0;

	return pAssoc;
}

void CSPMapStringToPtr::FreeAssoc(CSPMapStringToPtr::CAssoc* pAssoc)
{
	DestructElement(&pAssoc->key);  // free up string data

	pAssoc->pNext = m_pFreeList;
	m_pFreeList = pAssoc;
	m_nCount--;
	SP_ASSERT(m_nCount >= 0);  // make sure we don't underflow

	// if no more elements, cleanup completely
	if (m_nCount == 0)
		RemoveAll();
}

CSPMapStringToPtr::CAssoc*
CSPMapStringToPtr::GetAssocAt(LPCTSTR key, UINT& nHash) const
// find association (or return NULL)
{
	nHash = HashKey(key) % m_nHashTableSize;

	if (m_pHashTable == NULL)
		return NULL;

	// see if it exists
	CAssoc* pAssoc;
	for (pAssoc = m_pHashTable[nHash]; pAssoc != NULL; pAssoc = pAssoc->pNext)
	{
		if (pAssoc->key == key)
			return pAssoc;
	}
	return NULL;
}

BOOL CSPMapStringToPtr::Lookup(LPCTSTR key, void*& rValue) const
{
	SP_ASSERT_VALID(this);

	UINT nHash;
	CAssoc* pAssoc = GetAssocAt(key, nHash);
	if (pAssoc == NULL)
		return FALSE;  // not in map

	rValue = pAssoc->value;
	return TRUE;
}

BOOL CSPMapStringToPtr::LookupKey(LPCTSTR key, LPCTSTR& rKey) const
{
	SP_ASSERT_VALID(this);

	UINT nHash;
	CAssoc* pAssoc = GetAssocAt(key, nHash);
	if (pAssoc == NULL)
		return FALSE;  // not in map

	rKey = pAssoc->key;
	return TRUE;
}

void*& CSPMapStringToPtr::operator[](LPCTSTR key)
{
	SP_ASSERT_VALID(this);

	UINT nHash;
	CAssoc* pAssoc;
	if ((pAssoc = GetAssocAt(key, nHash)) == NULL)
	{
		if (m_pHashTable == NULL)
			InitHashTable(m_nHashTableSize);

		// it doesn't exist, add a new Association
		pAssoc = NewAssoc();
		pAssoc->nHashValue = nHash;
		pAssoc->key = key;
		// 'pAssoc->value' is a constructed object, nothing more

		// put into hash table
		pAssoc->pNext = m_pHashTable[nHash];
		m_pHashTable[nHash] = pAssoc;
	}
	return pAssoc->value;  // return new reference
}


BOOL CSPMapStringToPtr::RemoveKey(LPCTSTR key)
// remove key - return TRUE if removed
{
	SP_ASSERT_VALID(this);

	if (m_pHashTable == NULL)
		return FALSE;  // nothing in the table

	CAssoc** ppAssocPrev;
	ppAssocPrev = &m_pHashTable[HashKey(key) % m_nHashTableSize];

	CAssoc* pAssoc;
	for (pAssoc = *ppAssocPrev; pAssoc != NULL; pAssoc = pAssoc->pNext)
	{
		if (pAssoc->key == key)
		{
			// remove it
			*ppAssocPrev = pAssoc->pNext;  // remove from list
			FreeAssoc(pAssoc);
			return TRUE;
		}
		ppAssocPrev = &pAssoc->pNext;
	}
	return FALSE;  // not found
}


// Iterating

void CSPMapStringToPtr::GetNextAssoc(SPPOSITION& rNextPosition,
	CSPString& rKey, void*& rValue) const
{
	SP_ASSERT_VALID(this);
	SP_ASSERT(m_pHashTable != NULL);  // never call on empty map

	CAssoc* pAssocRet = (CAssoc*)rNextPosition;
	SP_ASSERT(pAssocRet != NULL);

	if (pAssocRet == (CAssoc*) BEFORE_START_SPPOSITION)
	{
		// find the first association
		for (UINT nBucket = 0; nBucket < m_nHashTableSize; nBucket++)
			if ((pAssocRet = m_pHashTable[nBucket]) != NULL)
				break;
		SP_ASSERT(pAssocRet != NULL);  // must find something
	}

	// find next association
	SP_ASSERT(SP_IsValidAddress(pAssocRet, sizeof(CAssoc)));
	CAssoc* pAssocNext;
	if ((pAssocNext = pAssocRet->pNext) == NULL)
	{
		// go to next bucket
		for (UINT nBucket = pAssocRet->nHashValue + 1;
		  nBucket < m_nHashTableSize; nBucket++)
			if ((pAssocNext = m_pHashTable[nBucket]) != NULL)
				break;
	}

	rNextPosition = (SPPOSITION) pAssocNext;

	// fill in return data
	rKey = pAssocRet->key;
	rValue = pAssocRet->value;
}


// Diagnostics

#ifdef _DEBUG
void CSPMapStringToPtr::Dump( ) const
{
	Object::Dump();
}

void CSPMapStringToPtr::AssertValid() const
{
	Object::AssertValid();

	SP_ASSERT(m_nHashTableSize > 0);
	SP_ASSERT(m_nCount == 0 || m_pHashTable != NULL);
		// non-empty map should have hash table
}
#endif //_DEBUG

⌨️ 快捷键说明

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