SpColl.cpp
上传用户:zhanglf88
上传日期:2013-11-19
资源大小:6036k
文件大小:31k
源码类别:

金融证券系统

开发平台:

Visual C++

  1. /*
  2. Cross Platform Core Code.
  3. Copyright(R) 2001-2002 Balang Software.
  4. All rights reserved.
  5. Using:
  6. class CSPArray;
  7. class CSPPtrArray;
  8. class CSPDWordArray;
  9. class CSPObArray;
  10. class CSPStringArray;
  11. class CSPMapStringToPtr;
  12. */
  13. #include "StdAfx.h"
  14. #include "../Include/SpColl.h"
  15. #ifdef _DEBUG
  16. #undef THIS_FILE
  17. static char THIS_FILE[] = __FILE__;
  18. #endif
  19. #ifdef _DEBUG
  20. #define new DEBUG_NEW
  21. #endif
  22. #ifndef _SP_ENABLE_INLINES
  23. #define _SPCOLL_INLINE
  24. #include "../Include/SpColl.inl"
  25. #undef _SPCOLL_INLINE
  26. #endif
  27. /////////////////////////////////////////////////////////////////////////////
  28. // CSPPtrArray out-of-line functions
  29. CSPPtrArray::CSPPtrArray()
  30. {
  31. m_pData = NULL;
  32. m_nSize = m_nMaxSize = m_nGrowBy = 0;
  33. }
  34. CSPPtrArray::~CSPPtrArray()
  35. {
  36. delete [] (BYTE*)m_pData;
  37. }
  38. void CSPPtrArray::SetSize(int nNewSize, int nGrowBy /* = -1 */)
  39. {
  40. SP_ASSERT(nNewSize >= 0);
  41. if (nGrowBy != -1)
  42. m_nGrowBy = nGrowBy;  // set new size
  43. if (nNewSize == 0)
  44. {
  45. // shrink to nothing
  46. delete [] (BYTE*)m_pData;
  47. m_pData = NULL;
  48. m_nSize = m_nMaxSize = 0;
  49. }
  50. else if (m_pData == NULL)
  51. {
  52. // create one with exact size
  53. #ifdef SIZE_T_MAX
  54. SP_ASSERT((long)nNewSize * sizeof(void*) <= SIZE_T_MAX);  // no overflow
  55. #endif
  56. m_pData = (void**) new BYTE[nNewSize * sizeof(void*)];
  57. memset(m_pData, 0, nNewSize * sizeof(void*));  // zero fill
  58. m_nSize = m_nMaxSize = nNewSize;
  59. }
  60. else if (nNewSize <= m_nMaxSize)
  61. {
  62. // it fits
  63. if (nNewSize > m_nSize)
  64. {
  65. // initialize the new elements
  66. memset(&m_pData[m_nSize], 0, (nNewSize-m_nSize) * sizeof(void*));
  67. }
  68. m_nSize = nNewSize;
  69. }
  70. else
  71. {
  72. // Otherwise grow array
  73. int nNewMax;
  74. if (nNewSize < m_nMaxSize + m_nGrowBy)
  75. nNewMax = m_nMaxSize + m_nGrowBy;  // granularity
  76. else
  77. nNewMax = nNewSize;  // no slush
  78. #ifdef SIZE_T_MAX
  79. SP_ASSERT((long)nNewMax * sizeof(void*) <= SIZE_T_MAX);  // no overflow
  80. #endif
  81. void** pNewData = (void**) new BYTE[nNewMax * sizeof(void*)];
  82. // copy new data from old
  83. memcpy(pNewData, m_pData, m_nSize * sizeof(void*));
  84. // construct remaining elements
  85. SP_ASSERT(nNewSize > m_nSize);
  86. memset(&pNewData[m_nSize], 0, (nNewSize-m_nSize) * sizeof(void*));
  87. // get rid of old stuff (note: no destructors called)
  88. delete [] (BYTE*)m_pData;
  89. m_pData = pNewData;
  90. m_nSize = nNewSize;
  91. m_nMaxSize = nNewMax;
  92. }
  93. }
  94. void CSPPtrArray::FreeExtra()
  95. {
  96. if (m_nSize != m_nMaxSize)
  97. {
  98. // shrink to desired size
  99. #ifdef SIZE_T_MAX
  100. SP_ASSERT((long)m_nSize * sizeof(void*) <= SIZE_T_MAX);  // no overflow
  101. #endif
  102. void** pNewData = NULL;
  103. if (m_nSize != 0)
  104. {
  105. pNewData = (void**) new BYTE[m_nSize * sizeof(void*)];
  106. // copy new data from old
  107. memcpy(pNewData, m_pData, m_nSize * sizeof(void*));
  108. }
  109. // get rid of old stuff (note: no destructors called)
  110. delete [] (BYTE*)m_pData;
  111. m_pData = pNewData;
  112. m_nMaxSize = m_nSize;
  113. }
  114. }
  115. void CSPPtrArray::SetAtGrow(int nIndex, void* newElement)
  116. {
  117. SP_ASSERT(nIndex >= 0);
  118. if (nIndex >= m_nSize)
  119. SetSize(nIndex+1);
  120. m_pData[nIndex] = newElement;
  121. }
  122. void CSPPtrArray::InsertAt(int nIndex, void* newElement, int nCount /*=1*/)
  123. {
  124. SP_ASSERT(nIndex >= 0);    // will expand to meet need
  125. SP_ASSERT(nCount > 0);     // zero or negative size not allowed
  126. if (nIndex >= m_nSize)
  127. {
  128. // adding after the end of the array
  129. SetSize(nIndex + nCount);  // grow so nIndex is valid
  130. }
  131. else
  132. {
  133. // inserting in the middle of the array
  134. int nOldSize = m_nSize;
  135. SetSize(m_nSize + nCount);  // grow it to new size
  136. // shift old data up to fill gap
  137. memmove(&m_pData[nIndex+nCount], &m_pData[nIndex],
  138. (nOldSize-nIndex) * sizeof(void*));
  139. // re-init slots we copied from
  140. memset(&m_pData[nIndex], 0, nCount * sizeof(void*));
  141. }
  142. // insert new value in the gap
  143. SP_ASSERT(nIndex + nCount <= m_nSize);
  144. while (nCount--)
  145. m_pData[nIndex++] = newElement;
  146. }
  147. void CSPPtrArray::RemoveAt(int nIndex, int nCount /* = 1 */)
  148. {
  149. SP_ASSERT(nIndex >= 0);
  150. SP_ASSERT(nCount >= 0);
  151. SP_ASSERT(nIndex + nCount <= m_nSize);
  152. // just remove a range
  153. int nMoveCount = m_nSize - (nIndex + nCount);
  154. if (nMoveCount)
  155. memcpy(&m_pData[nIndex], &m_pData[nIndex + nCount],
  156. nMoveCount * sizeof(void*));
  157. m_nSize -= nCount;
  158. }
  159. void CSPPtrArray::InsertAt(int nStartIndex, CSPPtrArray* pNewArray)
  160. {
  161. SP_ASSERT(pNewArray != NULL);
  162. SP_ASSERT(nStartIndex >= 0);
  163. if (pNewArray->GetSize() > 0)
  164. {
  165. InsertAt(nStartIndex, pNewArray->GetAt(0), pNewArray->GetSize());
  166. for (int i = 0; i < pNewArray->GetSize(); i++)
  167. SetAt(nStartIndex + i, pNewArray->GetAt(i));
  168. }
  169. }
  170. int CSPPtrArray::Append(const CSPPtrArray& src)
  171. {
  172. SP_ASSERT_VALID(this);
  173. SP_ASSERT(this != &src);   // cannot append to itself
  174. int nOldSize = m_nSize;
  175. SetSize(m_nSize + src.m_nSize);
  176. memcpy(m_pData + nOldSize, src.m_pData, src.m_nSize * sizeof(void*));
  177. return nOldSize;
  178. }
  179. void CSPPtrArray::Copy(const CSPPtrArray& src)
  180. {
  181. SP_ASSERT_VALID(this);
  182. SP_ASSERT(this != &src);   // cannot append to itself
  183. SetSize(src.m_nSize);
  184. memcpy(m_pData, src.m_pData, src.m_nSize * sizeof(void*));
  185. }
  186. #ifdef _DEBUG
  187. void CSPPtrArray::AssertValid( ) const
  188. {
  189. Object::AssertValid();
  190. if (m_pData == NULL)
  191. {
  192. SP_ASSERT(m_nSize == 0);
  193. SP_ASSERT(m_nMaxSize == 0);
  194. }
  195. else
  196. {
  197. SP_ASSERT(m_nSize >= 0);
  198. SP_ASSERT(m_nMaxSize >= 0);
  199. SP_ASSERT(m_nSize <= m_nMaxSize);
  200. SP_ASSERT( SP_IsValidAddress(m_pData, m_nMaxSize * sizeof(void*)) );
  201. }
  202. }
  203. void CSPPtrArray::Dump( ) const
  204. {
  205. Object::Dump( );
  206. }
  207. #endif //_DEBUG
  208. /////////////////////////////////////////////////////////////////////////////
  209. // CSPDWordArray out-of-line functions
  210. CSPDWordArray::CSPDWordArray()
  211. {
  212. m_pData = NULL;
  213. m_nSize = m_nMaxSize = m_nGrowBy = 0;
  214. }
  215. CSPDWordArray::~CSPDWordArray()
  216. {
  217. delete [] (BYTE*)m_pData;
  218. }
  219. void CSPDWordArray::SetSize(int nNewSize, int nGrowBy /* = -1 */)
  220. {
  221. SP_ASSERT(nNewSize >= 0);
  222. if (nGrowBy != -1)
  223. m_nGrowBy = nGrowBy;  // set new size
  224. if (nNewSize == 0)
  225. {
  226. // shrink to nothing
  227. delete [] (BYTE*)m_pData;
  228. m_pData = NULL;
  229. m_nSize = m_nMaxSize = 0;
  230. }
  231. else if (m_pData == NULL)
  232. {
  233. // create one with exact size
  234. #ifdef SIZE_T_MAX
  235. SP_ASSERT((long)nNewSize * sizeof(DWORD) <= SIZE_T_MAX);  // no overflow
  236. #endif
  237. m_pData = (DWORD*) new BYTE[nNewSize * sizeof(DWORD)];
  238. memset(m_pData, 0, nNewSize * sizeof(DWORD));  // zero fill
  239. m_nSize = m_nMaxSize = nNewSize;
  240. }
  241. else if (nNewSize <= m_nMaxSize)
  242. {
  243. // it fits
  244. if (nNewSize > m_nSize)
  245. {
  246. // initialize the new elements
  247. memset(&m_pData[m_nSize], 0, (nNewSize-m_nSize) * sizeof(DWORD));
  248. }
  249. m_nSize = nNewSize;
  250. }
  251. else
  252. {
  253. // Otherwise grow array
  254. int nNewMax;
  255. if (nNewSize < m_nMaxSize + m_nGrowBy)
  256. nNewMax = m_nMaxSize + m_nGrowBy;  // granularity
  257. else
  258. nNewMax = nNewSize;  // no slush
  259. #ifdef SIZE_T_MAX
  260. SP_ASSERT((long)nNewMax * sizeof(DWORD) <= SIZE_T_MAX);  // no overflow
  261. #endif
  262. DWORD* pNewData = (DWORD*) new BYTE[nNewMax * sizeof(DWORD)];
  263. // copy new data from old
  264. memcpy(pNewData, m_pData, m_nSize * sizeof(DWORD));
  265. // construct remaining elements
  266. SP_ASSERT(nNewSize > m_nSize);
  267. memset(&pNewData[m_nSize], 0, (nNewSize-m_nSize) * sizeof(DWORD));
  268. // get rid of old stuff (note: no destructors called)
  269. delete [] (BYTE*)m_pData;
  270. m_pData = pNewData;
  271. m_nSize = nNewSize;
  272. m_nMaxSize = nNewMax;
  273. }
  274. }
  275. void CSPDWordArray::Copy(const CSPDWordArray& src)
  276. {
  277. SP_ASSERT_VALID(this);
  278. SP_ASSERT(this != &src);   // cannot append to itself
  279. SetSize(src.m_nSize);
  280. memcpy(m_pData, src.m_pData, src.m_nSize * sizeof(DWORD));
  281. }
  282. void CSPDWordArray::FreeExtra()
  283. {
  284. if (m_nSize != m_nMaxSize)
  285. {
  286. // shrink to desired size
  287. #ifdef SIZE_T_MAX
  288. SP_ASSERT((long)m_nSize * sizeof(DWORD) <= SIZE_T_MAX);  // no overflow
  289. #endif
  290. DWORD* pNewData = NULL;
  291. if (m_nSize != 0)
  292. {
  293. pNewData = (DWORD*) new BYTE[m_nSize * sizeof(DWORD)];
  294. // copy new data from old
  295. memcpy(pNewData, m_pData, m_nSize * sizeof(DWORD));
  296. }
  297. // get rid of old stuff (note: no destructors called)
  298. delete [] (BYTE*)m_pData;
  299. m_pData = pNewData;
  300. m_nMaxSize = m_nSize;
  301. }
  302. }
  303. void CSPDWordArray::SetAtGrow(int nIndex, DWORD newElement)
  304. {
  305. SP_ASSERT(nIndex >= 0);
  306. if (nIndex >= m_nSize)
  307. SetSize(nIndex+1);
  308. m_pData[nIndex] = newElement;
  309. }
  310. void CSPDWordArray::InsertAt(int nIndex, DWORD newElement, int nCount /*=1*/)
  311. {
  312. SP_ASSERT(nIndex >= 0);    // will expand to meet need
  313. SP_ASSERT(nCount > 0);     // zero or negative size not allowed
  314. if (nIndex >= m_nSize)
  315. {
  316. // adding after the end of the array
  317. SetSize(nIndex + nCount);  // grow so nIndex is valid
  318. }
  319. else
  320. {
  321. // inserting in the middle of the array
  322. int nOldSize = m_nSize;
  323. SetSize(m_nSize + nCount);  // grow it to new size
  324. // shift old data up to fill gap
  325. memmove(&m_pData[nIndex+nCount], &m_pData[nIndex],
  326. (nOldSize-nIndex) * sizeof(DWORD));
  327. // re-init slots we copied from
  328. memset(&m_pData[nIndex], 0, nCount * sizeof(DWORD));
  329. }
  330. // insert new value in the gap
  331. SP_ASSERT(nIndex + nCount <= m_nSize);
  332. while (nCount--)
  333. m_pData[nIndex++] = newElement;
  334. }
  335. void CSPDWordArray::RemoveAt(int nIndex, int nCount /* = 1 */)
  336. {
  337. SP_ASSERT(nIndex >= 0);
  338. SP_ASSERT(nCount >= 0);
  339. SP_ASSERT(nIndex + nCount <= m_nSize);
  340. // just remove a range
  341. int nMoveCount = m_nSize - (nIndex + nCount);
  342. if (nMoveCount)
  343. memcpy(&m_pData[nIndex], &m_pData[nIndex + nCount],
  344. nMoveCount * sizeof(DWORD));
  345. m_nSize -= nCount;
  346. }
  347. void CSPDWordArray::InsertAt(int nStartIndex, CSPDWordArray* pNewArray)
  348. {
  349. SP_ASSERT(pNewArray != NULL);
  350. SP_ASSERT(nStartIndex >= 0);
  351. if (pNewArray->GetSize() > 0)
  352. {
  353. InsertAt(nStartIndex, pNewArray->GetAt(0), pNewArray->GetSize());
  354. for (int i = 0; i < pNewArray->GetSize(); i++)
  355. SetAt(nStartIndex + i, pNewArray->GetAt(i));
  356. }
  357. }
  358. int CSPDWordArray::AddUnique( DWORD newElement )
  359. {
  360. for( int i=0; i<GetSize(); i++ )
  361. {
  362. if( ElementAt(i) == newElement )
  363. return i;
  364. }
  365. return Add( newElement );
  366. }
  367. int SortDWord(const void *p1,const void *p2)
  368. {
  369. DWORD *pTemp1 = (DWORD *)p1;
  370. DWORD *pTemp2 = (DWORD *)p2;
  371. if( pTemp1 && pTemp2 && *pTemp1 < *pTemp2 )
  372. return -1;
  373. else if( pTemp1 && pTemp2 && *pTemp1 > *pTemp2 )
  374. return 1;
  375. return 0;
  376. }
  377. void CSPDWordArray::Sort( )
  378. {
  379. if( m_pData )
  380. qsort( m_pData, GetSize(), sizeof(DWORD), SortDWord );
  381. }
  382. BOOL CSPDWordArray::IsEqualTo( CSPDWordArray & adw )
  383. {
  384. if( GetSize() != adw.GetSize() )
  385. return FALSE;
  386. for( int i=0; i<GetSize(); i++ )
  387. {
  388. if( ElementAt(i) != adw.ElementAt(i) )
  389. return FALSE;
  390. }
  391. return TRUE;
  392. }
  393. DWORD * CSPDWordArray::GetData()
  394. {
  395. return m_pData;
  396. }
  397. void CSPDWordArray::Serialize(CSPArchive& ar)
  398. {
  399. SP_ASSERT_VALID(this);
  400. if (ar.IsStoring())
  401. {
  402. ar << GetSize();
  403. // write each item individually so that it will be byte-swapped
  404. for (int i = 0; i < m_nSize; i++)
  405. ar << m_pData[i];
  406. }
  407. else
  408. {
  409. int size;
  410. ar >> size;
  411. SetSize(size);
  412. for (int i = 0; i < size; i++)
  413. {
  414. DWORD dw;
  415. ar >> dw;
  416. SetAt(i,dw);
  417. }
  418. }
  419. }
  420. #ifdef _DEBUG
  421. void CSPDWordArray::AssertValid() const
  422. {
  423. Object::AssertValid();
  424. if (m_pData == NULL)
  425. {
  426. SP_ASSERT(m_nSize == 0);
  427. SP_ASSERT(m_nMaxSize == 0);
  428. }
  429. else
  430. {
  431. SP_ASSERT(m_nSize >= 0);
  432. SP_ASSERT(m_nMaxSize >= 0);
  433. SP_ASSERT(m_nSize <= m_nMaxSize);
  434. SP_ASSERT( SP_IsValidAddress(m_pData, m_nMaxSize * sizeof(DWORD)) );
  435. }
  436. }
  437. void CSPDWordArray::Dump( ) const
  438. {
  439. Object::Dump( );
  440. }
  441. #endif //_DEBUG
  442. /////////////////////////////////////////////////////////////////////////////
  443. // CSPObArray out-of-line functions
  444. CSPObArray::CSPObArray()
  445. {
  446. m_pData = NULL;
  447. m_nSize = m_nMaxSize = m_nGrowBy = 0;
  448. }
  449. CSPObArray::~CSPObArray()
  450. {
  451. SP_ASSERT_VALID(this);
  452. delete [] (BYTE*)m_pData;
  453. }
  454. void CSPObArray::SetSize(int nNewSize, int nGrowBy /* = -1 */)
  455. {
  456. SP_ASSERT_VALID(this);
  457. SP_ASSERT(nNewSize >= 0);
  458. if (nGrowBy != -1)
  459. m_nGrowBy = nGrowBy;  // set new size
  460. if (nNewSize == 0)
  461. {
  462. // shrink to nothing
  463. delete [] (BYTE*)m_pData;
  464. m_pData = NULL;
  465. m_nSize = m_nMaxSize = 0;
  466. }
  467. else if (m_pData == NULL)
  468. {
  469. // create one with exact size
  470. #ifdef SIZE_T_MAX
  471. SP_ASSERT((long)nNewSize * sizeof(Object*) <= SIZE_T_MAX);  // no overflow
  472. #endif
  473. m_pData = (Object**) new BYTE[nNewSize * sizeof(Object*)];
  474. memset(m_pData, 0, nNewSize * sizeof(Object*));  // zero fill
  475. m_nSize = m_nMaxSize = nNewSize;
  476. }
  477. else if (nNewSize <= m_nMaxSize)
  478. {
  479. // it fits
  480. if (nNewSize > m_nSize)
  481. {
  482. // initialize the new elements
  483. memset(&m_pData[m_nSize], 0, (nNewSize-m_nSize) * sizeof(Object*));
  484. }
  485. m_nSize = nNewSize;
  486. }
  487. else
  488. {
  489. // Otherwise grow array
  490. int nNewMax;
  491. if (nNewSize < m_nMaxSize + m_nGrowBy)
  492. nNewMax = m_nMaxSize + m_nGrowBy;  // granularity
  493. else
  494. nNewMax = nNewSize;  // no slush
  495. #ifdef SIZE_T_MAX
  496. SP_ASSERT((long)nNewMax * sizeof(Object*) <= SIZE_T_MAX);  // no overflow
  497. #endif
  498. Object** pNewData = (Object**) new BYTE[nNewMax * sizeof(Object*)];
  499. // copy new data from old
  500. memcpy(pNewData, m_pData, m_nSize * sizeof(Object*));
  501. // construct remaining elements
  502. SP_ASSERT(nNewSize > m_nSize);
  503. memset(&pNewData[m_nSize], 0, (nNewSize-m_nSize) * sizeof(Object*));
  504. // get rid of old stuff (note: no destructors called)
  505. delete [] (BYTE*)m_pData;
  506. m_pData = pNewData;
  507. m_nSize = nNewSize;
  508. m_nMaxSize = nNewMax;
  509. }
  510. }
  511. void CSPObArray::FreeExtra()
  512. {
  513. SP_ASSERT_VALID(this);
  514. if (m_nSize != m_nMaxSize)
  515. {
  516. // shrink to desired size
  517. #ifdef SIZE_T_MAX
  518. SP_ASSERT((long)m_nSize * sizeof(Object*) <= SIZE_T_MAX);  // no overflow
  519. #endif
  520. Object** pNewData = NULL;
  521. if (m_nSize != 0)
  522. {
  523. pNewData = (Object**) new BYTE[m_nSize * sizeof(Object*)];
  524. // copy new data from old
  525. memcpy(pNewData, m_pData, m_nSize * sizeof(Object*));
  526. }
  527. // get rid of old stuff (note: no destructors called)
  528. delete [] (BYTE*)m_pData;
  529. m_pData = pNewData;
  530. m_nMaxSize = m_nSize;
  531. }
  532. }
  533. void CSPObArray::SetAtGrow(int nIndex, Object* newElement)
  534. {
  535. SP_ASSERT_VALID(this);
  536. SP_ASSERT(nIndex >= 0);
  537. if (nIndex >= m_nSize)
  538. SetSize(nIndex+1);
  539. m_pData[nIndex] = newElement;
  540. }
  541. void CSPObArray::InsertAt(int nIndex, Object* newElement, int nCount /*=1*/)
  542. {
  543. SP_ASSERT_VALID(this);
  544. SP_ASSERT(nIndex >= 0);    // will expand to meet need
  545. SP_ASSERT(nCount > 0);     // zero or negative size not allowed
  546. if (nIndex >= m_nSize)
  547. {
  548. // adding after the end of the array
  549. SetSize(nIndex + nCount);  // grow so nIndex is valid
  550. }
  551. else
  552. {
  553. // inserting in the middle of the array
  554. int nOldSize = m_nSize;
  555. SetSize(m_nSize + nCount);  // grow it to new size
  556. // shift old data up to fill gap
  557. memmove(&m_pData[nIndex+nCount], &m_pData[nIndex],
  558. (nOldSize-nIndex) * sizeof(Object*));
  559. // re-init slots we copied from
  560. memset(&m_pData[nIndex], 0, nCount * sizeof(Object*));
  561. }
  562. // insert new value in the gap
  563. SP_ASSERT(nIndex + nCount <= m_nSize);
  564. while (nCount--)
  565. m_pData[nIndex++] = newElement;
  566. }
  567. void CSPObArray::RemoveAt(int nIndex, int nCount /* = 1 */)
  568. {
  569. SP_ASSERT_VALID(this);
  570. SP_ASSERT(nIndex >= 0);
  571. SP_ASSERT(nCount >= 0);
  572. SP_ASSERT(nIndex + nCount <= m_nSize);
  573. // just remove a range
  574. int nMoveCount = m_nSize - (nIndex + nCount);
  575. if (nMoveCount)
  576. memcpy(&m_pData[nIndex], &m_pData[nIndex + nCount],
  577. nMoveCount * sizeof(Object*));
  578. m_nSize -= nCount;
  579. }
  580. void CSPObArray::InsertAt(int nStartIndex, CSPObArray* pNewArray)
  581. {
  582. SP_ASSERT_VALID(this);
  583. SP_ASSERT(pNewArray != NULL);
  584. SP_ASSERT_VALID(pNewArray);
  585. SP_ASSERT(nStartIndex >= 0);
  586. if (pNewArray->GetSize() > 0)
  587. {
  588. InsertAt(nStartIndex, pNewArray->GetAt(0), pNewArray->GetSize());
  589. for (int i = 0; i < pNewArray->GetSize(); i++)
  590. SetAt(nStartIndex + i, pNewArray->GetAt(i));
  591. }
  592. }
  593. // Diagnostics
  594. #ifdef _DEBUG
  595. void CSPObArray::Dump() const
  596. {
  597. Object::Dump( );
  598. }
  599. void CSPObArray::AssertValid() const
  600. {
  601. Object::AssertValid();
  602. if (m_pData == NULL)
  603. {
  604. SP_ASSERT(m_nSize == 0);
  605. SP_ASSERT(m_nMaxSize == 0);
  606. }
  607. else
  608. {
  609. SP_ASSERT(m_nSize >= 0);
  610. SP_ASSERT(m_nMaxSize >= 0);
  611. SP_ASSERT(m_nSize <= m_nMaxSize);
  612. SP_ASSERT(SP_IsValidAddress(m_pData, m_nMaxSize * sizeof(Object*)));
  613. }
  614. }
  615. #endif //_DEBUG
  616. /////////////////////////////////////////////////////////////////////////////
  617. // CSPStringArray out-of-line functions
  618. CSPStringArray::CSPStringArray()
  619. {
  620. m_pData = NULL;
  621. m_nSize = m_nMaxSize = m_nGrowBy = 0;
  622. }
  623. CSPStringArray::~CSPStringArray()
  624. {
  625. SP_ASSERT_VALID(this);
  626. SPDestructElements(m_pData, m_nSize);
  627. delete [] (BYTE*)m_pData;
  628. }
  629. void CSPStringArray::SetSize(int nNewSize, int nGrowBy /* = -1 */)
  630. {
  631. SP_ASSERT_VALID(this);
  632. SP_ASSERT(nNewSize >= 0);
  633. if (nGrowBy != -1)
  634. m_nGrowBy = nGrowBy;  // set new size
  635. if (nNewSize == 0)
  636. {
  637. // shrink to nothing
  638. SPDestructElements(m_pData, m_nSize);
  639. delete [] (BYTE*)m_pData;
  640. m_pData = NULL;
  641. m_nSize = m_nMaxSize = 0;
  642. }
  643. else if (m_pData == NULL)
  644. {
  645. // create one with exact size
  646. #ifdef SIZE_T_MAX
  647. SP_ASSERT((long)nNewSize * sizeof(CSPString) <= SIZE_T_MAX);  // no overflow
  648. #endif
  649. m_pData = (CSPString*) new BYTE[nNewSize * sizeof(CSPString)];
  650. SPConstructElements(m_pData, nNewSize);
  651. m_nSize = m_nMaxSize = nNewSize;
  652. }
  653. else if (nNewSize <= m_nMaxSize)
  654. {
  655. // it fits
  656. if (nNewSize > m_nSize)
  657. {
  658. // initialize the new elements
  659. SPConstructElements(&m_pData[m_nSize], nNewSize-m_nSize);
  660. }
  661. else if (m_nSize > nNewSize)  // destroy the old elements
  662. SPDestructElements(&m_pData[nNewSize], m_nSize-nNewSize);
  663. m_nSize = nNewSize;
  664. }
  665. else
  666. {
  667. // Otherwise grow array
  668. int nNewMax;
  669. if (nNewSize < m_nMaxSize + m_nGrowBy)
  670. nNewMax = m_nMaxSize + m_nGrowBy;  // granularity
  671. else
  672. nNewMax = nNewSize;  // no slush
  673. #ifdef SIZE_T_MAX
  674. SP_ASSERT((long)nNewMax * sizeof(CSPString) <= SIZE_T_MAX);  // no overflow
  675. #endif
  676. CSPString* pNewData = (CSPString*) new BYTE[nNewMax * sizeof(CSPString)];
  677. // copy new data from old
  678. memcpy(pNewData, m_pData, m_nSize * sizeof(CSPString));
  679. // construct remaining elements
  680. SP_ASSERT(nNewSize > m_nSize);
  681. SPConstructElements(&pNewData[m_nSize], nNewSize-m_nSize);
  682. // get rid of old stuff (note: no destructors called)
  683. delete [] (BYTE*)m_pData;
  684. m_pData = pNewData;
  685. m_nSize = nNewSize;
  686. m_nMaxSize = nNewMax;
  687. }
  688. }
  689. int CSPStringArray::Append(const CSPStringArray& src)
  690. {
  691. SP_ASSERT_VALID(this);
  692. SP_ASSERT(this != &src);   // cannot append to itself
  693. int nOldSize = m_nSize;
  694. SetSize(m_nSize + src.m_nSize);
  695. SPCopyElements(m_pData + nOldSize, src.m_pData, src.m_nSize);
  696. return nOldSize;
  697. }
  698. void CSPStringArray::Copy(const CSPStringArray& src)
  699. {
  700. SP_ASSERT_VALID(this);
  701. SP_ASSERT(this != &src);   // cannot append to itself
  702. SetSize(src.m_nSize);
  703. SPCopyElements(m_pData, src.m_pData, src.m_nSize);
  704. }
  705. void CSPStringArray::FreeExtra()
  706. {
  707. SP_ASSERT_VALID(this);
  708. if (m_nSize != m_nMaxSize)
  709. {
  710. // shrink to desired size
  711. #ifdef SIZE_T_MAX
  712. SP_ASSERT((long)m_nSize * sizeof(CSPString) <= SIZE_T_MAX);  // no overflow
  713. #endif
  714. CSPString* pNewData = NULL;
  715. if (m_nSize != 0)
  716. {
  717. pNewData = (CSPString*) new BYTE[m_nSize * sizeof(CSPString)];
  718. // copy new data from old
  719. memcpy(pNewData, m_pData, m_nSize * sizeof(CSPString));
  720. }
  721. // get rid of old stuff (note: no destructors called)
  722. delete [] (BYTE*)m_pData;
  723. m_pData = pNewData;
  724. m_nMaxSize = m_nSize;
  725. }
  726. }
  727. void CSPStringArray::SetAtGrow(int nIndex, const char* newElement)
  728. {
  729. SP_ASSERT_VALID(this);
  730. SP_ASSERT(nIndex >= 0);
  731. if (nIndex >= m_nSize)
  732. SetSize(nIndex+1);
  733. m_pData[nIndex] = newElement;
  734. }
  735. void CSPStringArray::InsertAt(int nIndex, const char* newElement, int nCount /*=1*/)
  736. {
  737. SP_ASSERT_VALID(this);
  738. SP_ASSERT(nIndex >= 0);    // will expand to meet need
  739. SP_ASSERT(nCount > 0);     // zero or negative size not allowed
  740. if (nIndex >= m_nSize)
  741. {
  742. // adding after the end of the array
  743. SetSize(nIndex + nCount);  // grow so nIndex is valid
  744. }
  745. else
  746. {
  747. // inserting in the middle of the array
  748. int nOldSize = m_nSize;
  749. SetSize(m_nSize + nCount);  // grow it to new size
  750. // shift old data up to fill gap
  751. memmove(&m_pData[nIndex+nCount], &m_pData[nIndex],
  752. (nOldSize-nIndex) * sizeof(CSPString));
  753. // re-init slots we copied from
  754. SPConstructElements(&m_pData[nIndex], nCount);
  755. }
  756. // insert new value in the gap
  757. SP_ASSERT(nIndex + nCount <= m_nSize);
  758. while (nCount--)
  759. m_pData[nIndex++] = newElement;
  760. }
  761. void CSPStringArray::RemoveAt(int nIndex, int nCount /* = 1 */)
  762. {
  763. SP_ASSERT_VALID(this);
  764. SP_ASSERT(nIndex >= 0);
  765. SP_ASSERT(nCount >= 0);
  766. SP_ASSERT(nIndex + nCount <= m_nSize);
  767. // just remove a range
  768. int nMoveCount = m_nSize - (nIndex + nCount);
  769. SPDestructElements(&m_pData[nIndex], nCount);
  770. if (nMoveCount)
  771. memcpy(&m_pData[nIndex], &m_pData[nIndex + nCount],
  772. nMoveCount * sizeof(CSPString));
  773. m_nSize -= nCount;
  774. }
  775. void CSPStringArray::InsertAt(int nStartIndex, CSPStringArray* pNewArray)
  776. {
  777. SP_ASSERT_VALID(this);
  778. SP_ASSERT(pNewArray != NULL);
  779. SP_ASSERT_VALID(pNewArray);
  780. SP_ASSERT(nStartIndex >= 0);
  781. if (pNewArray->GetSize() > 0)
  782. {
  783. InsertAt(nStartIndex, pNewArray->GetAt(0), pNewArray->GetSize());
  784. for (int i = 0; i < pNewArray->GetSize(); i++)
  785. SetAt(nStartIndex + i, pNewArray->GetAt(i));
  786. }
  787. }
  788. CSPStringArray * CSPStringArray::m_pSortSPStringArray = NULL;
  789. int SortSPString(const void *p1,const void *p2)
  790. {
  791. if( NULL == p1 || NULL == p2 )
  792. return 0;
  793. DWORD dw1 = *(DWORD *)p1;
  794. DWORD dw2 = *(DWORD *)p2;
  795. if( NULL == CSPStringArray::m_pSortSPStringArray
  796. || dw1 < 0 || dw1 >= (DWORD)CSPStringArray::m_pSortSPStringArray->GetSize()
  797. || dw2 < 0 || dw2 >= (DWORD)CSPStringArray::m_pSortSPStringArray->GetSize() )
  798. {
  799. SP_ASSERT(FALSE);
  800. return 0;
  801. }
  802. return strcmp(CSPStringArray::m_pSortSPStringArray->ElementAt(dw1),
  803. CSPStringArray::m_pSortSPStringArray->ElementAt(dw2) );
  804. }
  805. BOOL CSPStringArray::GetSortIDArray( CSPDWordArray & adwSortID )
  806. {
  807. adwSortID.SetSize( 0, GetSize() + 1 );
  808. for( DWORD i=0; i<(DWORD)GetSize(); i++ )
  809. adwSortID.Add( i );
  810. m_pSortSPStringArray = this;
  811. if( adwSortID.GetData() )
  812. qsort( adwSortID.GetData(), adwSortID.GetSize(), sizeof(DWORD), SortSPString );
  813. m_pSortSPStringArray = NULL;
  814. return TRUE;
  815. }
  816. void CSPStringArray::Serialize(CSPArchive& ar)
  817. {
  818. SP_ASSERT_VALID(this);
  819. if (ar.IsStoring())
  820. {
  821. ar.WriteCount(GetSize());
  822. for (int i = 0; i < m_nSize; i++)
  823. ar << m_pData[i];
  824. }
  825. else
  826. {
  827. DWORD nOldSize = ar.ReadCount();
  828. SetSize(nOldSize);
  829. for (DWORD i = 0; i < nOldSize; i++)
  830. ar >> m_pData[i];
  831. }
  832. }
  833. void CSPStringArray::SPConstructElements(CSPString* pElements, int nCount)
  834. {
  835. SP_ASSERT(nCount == 0 ||
  836. SP_IsValidAddress(pElements, nCount * sizeof(CSPString)));
  837. for (; nCount--; ++pElements)
  838. memcpy(pElements, &afxEmptySPString, sizeof(*pElements));
  839. }
  840. void CSPStringArray::SPDestructElements(CSPString* pElements, int nCount)
  841. {
  842. SP_ASSERT(nCount == 0 ||
  843. SP_IsValidAddress(pElements, nCount * sizeof(CSPString)));
  844. // call the destructor(s)
  845. for (; nCount--; pElements++)
  846. pElements->~CSPString();
  847. }
  848. // Diagnostics
  849. #ifdef _DEBUG
  850. void CSPStringArray::Dump() const
  851. {
  852. Object::Dump( );
  853. }
  854. void CSPStringArray::AssertValid() const
  855. {
  856. Object::AssertValid();
  857. if (m_pData == NULL)
  858. {
  859. SP_ASSERT(m_nSize == 0);
  860. SP_ASSERT(m_nMaxSize == 0);
  861. }
  862. else
  863. {
  864. SP_ASSERT(m_nSize >= 0);
  865. SP_ASSERT(m_nMaxSize >= 0);
  866. SP_ASSERT(m_nSize <= m_nMaxSize);
  867. SP_ASSERT(SP_IsValidAddress(m_pData, m_nMaxSize * sizeof(CSPString)));
  868. }
  869. }
  870. #endif //_DEBUG
  871. /////////////////////////////////////////////////////////////////////////////
  872. // CSPPlex
  873. CSPPlex* PASCAL CSPPlex::Create(CSPPlex*& pHead, UINT nMax, UINT cbElement)
  874. {
  875. SP_ASSERT(nMax > 0 && cbElement > 0);
  876. CSPPlex* p = (CSPPlex*) new BYTE[sizeof(CSPPlex) + nMax * cbElement];
  877. // may throw exception
  878. p->pNext = pHead;
  879. pHead = p;  // change head (adds in reverse order for simplicity)
  880. return p;
  881. }
  882. void CSPPlex::FreeDataChain()     // free this one and links
  883. {
  884. CSPPlex* p = this;
  885. while (p != NULL)
  886. {
  887. BYTE* bytes = (BYTE*) p;
  888. CSPPlex* pNext = p->pNext;
  889. delete[] bytes;
  890. p = pNext;
  891. }
  892. }
  893. /////////////////////////////////////////////////////////////////////////////
  894. // CSPMapStringToPtr out-of-line functions
  895. CSPMapStringToPtr::CSPMapStringToPtr(int nBlockSize)
  896. {
  897. SP_ASSERT(nBlockSize > 0);
  898. m_pHashTable = NULL;
  899. m_nHashTableSize = 17;  // default size
  900. m_nCount = 0;
  901. m_pFreeList = NULL;
  902. m_pBlocks = NULL;
  903. m_nBlockSize = nBlockSize;
  904. }
  905. inline UINT CSPMapStringToPtr::HashKey(LPCTSTR key) const
  906. {
  907. UINT nHash = 0;
  908. while (*key)
  909. nHash = (nHash<<5) + nHash + *key++;
  910. return nHash;
  911. }
  912. void CSPMapStringToPtr::InitHashTable(
  913. UINT nHashSize, BOOL bAllocNow)
  914. //
  915. // Used to force allocation of a hash table or to override the default
  916. //   hash table size of (which is fairly small)
  917. {
  918. SP_ASSERT_VALID(this);
  919. SP_ASSERT(m_nCount == 0);
  920. SP_ASSERT(nHashSize > 0);
  921. if (m_pHashTable != NULL)
  922. {
  923. // free hash table
  924. delete[] m_pHashTable;
  925. m_pHashTable = NULL;
  926. }
  927. if (bAllocNow)
  928. {
  929. m_pHashTable = new CAssoc* [nHashSize];
  930. memset(m_pHashTable, 0, sizeof(CAssoc*) * nHashSize);
  931. }
  932. m_nHashTableSize = nHashSize;
  933. }
  934. static inline void DestructElement(CSPString* pOldData)
  935. {
  936. pOldData->~CSPString();
  937. }
  938. void CSPMapStringToPtr::RemoveAll()
  939. {
  940. SP_ASSERT_VALID(this);
  941. if (m_pHashTable != NULL)
  942. {
  943. // destroy elements
  944. for (UINT nHash = 0; nHash < m_nHashTableSize; nHash++)
  945. {
  946. CAssoc* pAssoc;
  947. for (pAssoc = m_pHashTable[nHash]; pAssoc != NULL;
  948.   pAssoc = pAssoc->pNext)
  949. {
  950. DestructElement(&pAssoc->key);  // free up string data
  951. }
  952. }
  953. // free hash table
  954. delete [] m_pHashTable;
  955. m_pHashTable = NULL;
  956. }
  957. m_nCount = 0;
  958. m_pFreeList = NULL;
  959. m_pBlocks->FreeDataChain();
  960. m_pBlocks = NULL;
  961. }
  962. CSPMapStringToPtr::~CSPMapStringToPtr()
  963. {
  964. RemoveAll();
  965. SP_ASSERT(m_nCount == 0);
  966. }
  967. // Assoc helpers
  968. // same as CList implementation except we store CAssoc's not CNode's
  969. //    and CAssoc's are singly linked all the time
  970. CSPMapStringToPtr::CAssoc*
  971. CSPMapStringToPtr::NewAssoc()
  972. {
  973. if (m_pFreeList == NULL)
  974. {
  975. // add another block
  976. CSPPlex* newBlock = CSPPlex::Create(m_pBlocks, m_nBlockSize,
  977. sizeof(CSPMapStringToPtr::CAssoc));
  978. // chain them into free list
  979. CSPMapStringToPtr::CAssoc* pAssoc =
  980. (CSPMapStringToPtr::CAssoc*) newBlock->data();
  981. // free in reverse order to make it easier to debug
  982. pAssoc += m_nBlockSize - 1;
  983. for (int i = m_nBlockSize-1; i >= 0; i--, pAssoc--)
  984. {
  985. pAssoc->pNext = m_pFreeList;
  986. m_pFreeList = pAssoc;
  987. }
  988. }
  989. SP_ASSERT(m_pFreeList != NULL);  // we must have something
  990. CSPMapStringToPtr::CAssoc* pAssoc = m_pFreeList;
  991. m_pFreeList = m_pFreeList->pNext;
  992. m_nCount++;
  993. SP_ASSERT(m_nCount > 0);  // make sure we don't overflow
  994. //CSPString emptyString;
  995. //memcpy(&pAssoc->key, &emptyString, sizeof(CSPString));
  996. memcpy(&pAssoc->key, &afxEmptySPString, sizeof(pAssoc->key));
  997. pAssoc->value = 0;
  998. return pAssoc;
  999. }
  1000. void CSPMapStringToPtr::FreeAssoc(CSPMapStringToPtr::CAssoc* pAssoc)
  1001. {
  1002. DestructElement(&pAssoc->key);  // free up string data
  1003. pAssoc->pNext = m_pFreeList;
  1004. m_pFreeList = pAssoc;
  1005. m_nCount--;
  1006. SP_ASSERT(m_nCount >= 0);  // make sure we don't underflow
  1007. // if no more elements, cleanup completely
  1008. if (m_nCount == 0)
  1009. RemoveAll();
  1010. }
  1011. CSPMapStringToPtr::CAssoc*
  1012. CSPMapStringToPtr::GetAssocAt(LPCTSTR key, UINT& nHash) const
  1013. // find association (or return NULL)
  1014. {
  1015. nHash = HashKey(key) % m_nHashTableSize;
  1016. if (m_pHashTable == NULL)
  1017. return NULL;
  1018. // see if it exists
  1019. CAssoc* pAssoc;
  1020. for (pAssoc = m_pHashTable[nHash]; pAssoc != NULL; pAssoc = pAssoc->pNext)
  1021. {
  1022. if (pAssoc->key == key)
  1023. return pAssoc;
  1024. }
  1025. return NULL;
  1026. }
  1027. BOOL CSPMapStringToPtr::Lookup(LPCTSTR key, void*& rValue) const
  1028. {
  1029. SP_ASSERT_VALID(this);
  1030. UINT nHash;
  1031. CAssoc* pAssoc = GetAssocAt(key, nHash);
  1032. if (pAssoc == NULL)
  1033. return FALSE;  // not in map
  1034. rValue = pAssoc->value;
  1035. return TRUE;
  1036. }
  1037. BOOL CSPMapStringToPtr::LookupKey(LPCTSTR key, LPCTSTR& rKey) const
  1038. {
  1039. SP_ASSERT_VALID(this);
  1040. UINT nHash;
  1041. CAssoc* pAssoc = GetAssocAt(key, nHash);
  1042. if (pAssoc == NULL)
  1043. return FALSE;  // not in map
  1044. rKey = pAssoc->key;
  1045. return TRUE;
  1046. }
  1047. void*& CSPMapStringToPtr::operator[](LPCTSTR key)
  1048. {
  1049. SP_ASSERT_VALID(this);
  1050. UINT nHash;
  1051. CAssoc* pAssoc;
  1052. if ((pAssoc = GetAssocAt(key, nHash)) == NULL)
  1053. {
  1054. if (m_pHashTable == NULL)
  1055. InitHashTable(m_nHashTableSize);
  1056. // it doesn't exist, add a new Association
  1057. pAssoc = NewAssoc();
  1058. pAssoc->nHashValue = nHash;
  1059. pAssoc->key = key;
  1060. // 'pAssoc->value' is a constructed object, nothing more
  1061. // put into hash table
  1062. pAssoc->pNext = m_pHashTable[nHash];
  1063. m_pHashTable[nHash] = pAssoc;
  1064. }
  1065. return pAssoc->value;  // return new reference
  1066. }
  1067. BOOL CSPMapStringToPtr::RemoveKey(LPCTSTR key)
  1068. // remove key - return TRUE if removed
  1069. {
  1070. SP_ASSERT_VALID(this);
  1071. if (m_pHashTable == NULL)
  1072. return FALSE;  // nothing in the table
  1073. CAssoc** ppAssocPrev;
  1074. ppAssocPrev = &m_pHashTable[HashKey(key) % m_nHashTableSize];
  1075. CAssoc* pAssoc;
  1076. for (pAssoc = *ppAssocPrev; pAssoc != NULL; pAssoc = pAssoc->pNext)
  1077. {
  1078. if (pAssoc->key == key)
  1079. {
  1080. // remove it
  1081. *ppAssocPrev = pAssoc->pNext;  // remove from list
  1082. FreeAssoc(pAssoc);
  1083. return TRUE;
  1084. }
  1085. ppAssocPrev = &pAssoc->pNext;
  1086. }
  1087. return FALSE;  // not found
  1088. }
  1089. // Iterating
  1090. void CSPMapStringToPtr::GetNextAssoc(SPPOSITION& rNextPosition,
  1091. CSPString& rKey, void*& rValue) const
  1092. {
  1093. SP_ASSERT_VALID(this);
  1094. SP_ASSERT(m_pHashTable != NULL);  // never call on empty map
  1095. CAssoc* pAssocRet = (CAssoc*)rNextPosition;
  1096. SP_ASSERT(pAssocRet != NULL);
  1097. if (pAssocRet == (CAssoc*) BEFORE_START_SPPOSITION)
  1098. {
  1099. // find the first association
  1100. for (UINT nBucket = 0; nBucket < m_nHashTableSize; nBucket++)
  1101. if ((pAssocRet = m_pHashTable[nBucket]) != NULL)
  1102. break;
  1103. SP_ASSERT(pAssocRet != NULL);  // must find something
  1104. }
  1105. // find next association
  1106. SP_ASSERT(SP_IsValidAddress(pAssocRet, sizeof(CAssoc)));
  1107. CAssoc* pAssocNext;
  1108. if ((pAssocNext = pAssocRet->pNext) == NULL)
  1109. {
  1110. // go to next bucket
  1111. for (UINT nBucket = pAssocRet->nHashValue + 1;
  1112.   nBucket < m_nHashTableSize; nBucket++)
  1113. if ((pAssocNext = m_pHashTable[nBucket]) != NULL)
  1114. break;
  1115. }
  1116. rNextPosition = (SPPOSITION) pAssocNext;
  1117. // fill in return data
  1118. rKey = pAssocRet->key;
  1119. rValue = pAssocRet->value;
  1120. }
  1121. // Diagnostics
  1122. #ifdef _DEBUG
  1123. void CSPMapStringToPtr::Dump( ) const
  1124. {
  1125. Object::Dump();
  1126. }
  1127. void CSPMapStringToPtr::AssertValid() const
  1128. {
  1129. Object::AssertValid();
  1130. SP_ASSERT(m_nHashTableSize > 0);
  1131. SP_ASSERT(m_nCount == 0 || m_pHashTable != NULL);
  1132. // non-empty map should have hash table
  1133. }
  1134. #endif //_DEBUG