1 // Licensed to the .NET Foundation under one or more agreements.
2 // The .NET Foundation licenses this file to you under the MIT license.
3 // See the LICENSE file in the project root for more information.
10 #pragma warning(disable:22008) // "Suppress PREfast warnings about integer overflow"
13 inline ULONG GrowBuffer(ULONG startingSize)
15 int toAdd = startingSize >> 1;
20 return startingSize + toAdd;
23 /*****************************************************************************/
24 /* LIFO (stack) and FIFO (queue) templates (must precede #include "method.h")*/
31 LIST_EL(T *item) {m_Next = NULL; m_Ptr = item; };
38 inline LIFO() { m_pHead = NULL; };
39 inline ~LIFO() {T *val; while((val = POP()) != NULL) delete val; };
42 m_pTemp = new LIST_EL <T>(item);
43 m_pTemp->m_Next = m_pHead;
49 if((m_pTemp = m_pHead) != NULL)
51 m_pHead = m_pHead->m_Next;
67 FIFO() { m_Arr = NULL; m_ulArrLen = 0; m_ulCount = 0; m_ulOffset = 0; };
70 for(ULONG i=0; i < m_ulCount; i++) {
71 if(m_Arr[i+m_ulOffset]) delete m_Arr[i+m_ulOffset];
76 void RESET(bool DeleteElements = true) {
78 for(ULONG i=0; i < m_ulCount; i++) {
79 if(DeleteElements) delete m_Arr[i+m_ulOffset];
80 m_Arr[i+m_ulOffset] = NULL;
90 if(m_ulCount+m_ulOffset >= m_ulArrLen)
94 memcpy(m_Arr,&m_Arr[m_ulOffset],m_ulCount*sizeof(T*));
99 m_ulArrLen = GrowBuffer(m_ulArrLen);
100 T** tmp = new T*[m_ulArrLen];
105 memcpy(tmp,m_Arr,m_ulCount*sizeof(T*));
110 else fprintf(stderr,"\nOut of memory!\n");
113 m_Arr[m_ulOffset+m_ulCount] = item;
117 ULONG COUNT() { return m_ulCount; };
123 ret = m_Arr[m_ulOffset++];
128 T* PEEK(ULONG idx) { return (idx < m_ulCount) ? m_Arr[m_ulOffset+idx] : NULL; };
137 template <class T> struct Indx256
140 Indx256() { memset(table,0,sizeof(table)); };
144 for(int i = 1; i < 256; i++) delete ((Indx256*)(table[i]));
146 T** IndexString(BYTE* psz, T* pObj)
150 table[0] = (void*)pObj;
155 Indx256* pInd = (Indx256*)(table[*psz]);
163 _ASSERTE(!"Out of memory in Indx256::IndexString!");
164 fprintf(stderr,"\nOut of memory in Indx256::IndexString!\n");
168 return pInd->IndexString(psz+1,pObj);
171 T* FindString(BYTE* psz)
175 Indx256* pInd = (Indx256*)(table[*psz]);
176 return (pInd == NULL) ? NULL : pInd->FindString(psz+1);
178 return (T*)(table[0]); // if i==0
181 void ClearAll(bool DeleteObj)
183 if(DeleteObj) delete (T*)(table[0]);
185 for(unsigned i = 1; i < 256; i++)
189 Indx256* pInd = (Indx256*)(table[i]);
190 pInd->ClearAll(DeleteObj);
199 // Template intended for named objects, that expose function char* NameOf()
205 FIFO_INDEXED() { m_Arr = NULL; m_ulArrLen = 0; m_ulCount = 0; m_ulOffset = 0; };
213 void RESET(bool DeleteElements = true) {
218 for(i=m_ulOffset; i < m_ulOffset+m_ulCount; i++)
224 for(i=m_ulOffset; i < m_ulOffset+m_ulCount; i++)
228 memset(&m_Arr[m_ulOffset],0,m_ulCount*sizeof(void*));
237 T** itemaddr = m_Index.IndexString((BYTE*)(item->NameOf()),item);
238 if(m_ulCount+m_ulOffset >= m_ulArrLen)
242 memcpy(m_Arr,&m_Arr[m_ulOffset],m_ulCount*sizeof(T*));
247 m_ulArrLen = GrowBuffer(m_ulArrLen);
248 T*** tmp = new T**[m_ulArrLen];
253 memcpy(tmp,m_Arr,m_ulCount*sizeof(T**));
258 else fprintf(stderr,"\nOut of memory!\n");
261 m_Arr[m_ulOffset+m_ulCount] = itemaddr;
265 ULONG COUNT() { return m_ulCount; };
271 ret = *(m_Arr[m_ulOffset]);
272 *m_Arr[m_ulOffset] = NULL;
278 T* PEEK(ULONG idx) { return (idx < m_ulCount) ? *(m_Arr[m_ulOffset+idx]) : NULL; };
279 T* FIND(T* item) { return m_Index.FindString((BYTE*)(item->NameOf())); };
292 SORTEDARRAY() { m_Arr = NULL; m_ulArrLen = 0; m_ulCount = 0; m_ulOffset = 0; };
295 for(ULONG i=0; i < m_ulCount; i++) {
296 if(m_Arr[i+m_ulOffset]) delete m_Arr[i+m_ulOffset];
301 void RESET(bool DeleteElements = true) {
305 for(ULONG i=0; i < m_ulCount; i++) {
306 delete m_Arr[i+m_ulOffset];
309 memset(m_Arr,0,m_ulArrLen*sizeof(T*));
318 if(m_ulCount+m_ulOffset >= m_ulArrLen)
322 memcpy(m_Arr,&m_Arr[m_ulOffset],m_ulCount*sizeof(T*));
327 m_ulArrLen = GrowBuffer(m_ulArrLen);
328 T** tmp = new T*[m_ulArrLen];
333 memcpy(tmp,m_Arr,m_ulCount*sizeof(T*));
338 else fprintf(stderr,"\nOut of memory!\n");
343 // find 1st arr.element > item
344 T** low = &m_Arr[m_ulOffset];
345 T** high = &m_Arr[m_ulOffset+m_ulCount-1];
348 if(item->ComparedTo(*high) > 0) mid = high+1;
349 else if(item->ComparedTo(*low) < 0) mid = low;
352 mid = &low[(high - low) >> 1];
354 int cmp = item->ComparedTo(*mid);
362 if (cmp > 0) low = mid;
366 /////////////////////////////////////////////
367 memmove(mid+1,mid,(BYTE*)&m_Arr[m_ulOffset+m_ulCount]-(BYTE*)mid);
370 else m_Arr[m_ulOffset+m_ulCount] = item;
374 ULONG COUNT() { return m_ulCount; };
380 ret = m_Arr[m_ulOffset++];
385 T* PEEK(ULONG idx) { return (idx < m_ulCount) ? m_Arr[m_ulOffset+idx] : NULL; };
390 T** low = &m_Arr[m_ulOffset];
391 T** high = &m_Arr[m_ulOffset+m_ulCount-1];
393 if(item->ComparedTo(*high) == 0) return(*high);
396 mid = &low[(high - low) >> 1];
397 int cmp = item->ComparedTo(*mid);
398 if (cmp == 0) return(*mid);
399 if (mid == low) break;
400 if (cmp > 0) low = mid;
411 T** low = &m_Arr[m_ulOffset];
412 T** high = &m_Arr[m_ulOffset+m_ulCount-1];
414 if((*high)->Compare(item) == 0) return(*high);
417 mid = &low[(high - low) >> 1];
418 int cmp = (*mid)->Compare(item);
419 if (cmp == 0) return(*mid);
420 if (mid == low) break;
421 if (cmp > 0) low = mid;
432 T** low = &m_Arr[m_ulOffset];
433 T** high = &m_Arr[m_ulOffset+m_ulCount-1];
435 if(item->ComparedTo(*high) == 0)
443 mid = &low[(high - low) >> 1];
444 int cmp = item->ComparedTo(*mid);
448 memcpy(mid,mid+1,(BYTE*)&m_Arr[m_ulOffset+m_ulCount]-(BYTE*)mid-1);
452 if (mid == low) break;
453 if (cmp > 0) low = mid;
466 template <class T> struct RBNODE
478 pLeft = pRight = pParent = NULL;
482 RBNODE(T* pVal, DWORD dwColor)
484 pLeft = pRight = pParent = NULL;
489 bool IsRed() { return (dwRed != 0); };
490 void SetRed() { dwRed = 1; };
491 void SetBlack() { dwRed = 0; };
494 #define BUCKETCOUNT 512
496 template <class T> class RBNODEBUCKET
499 RBNODEBUCKET<T>* pNext;
500 RBNODE<T> bucket[BUCKETCOUNT];
501 unsigned alloc_count;
510 ~RBNODEBUCKET() { if(pNext) delete pNext; };
512 bool CanAlloc() { return (alloc_count < BUCKETCOUNT); };
514 RBNODE<T>* AllocNode()
517 for(unsigned i = 0; i < BUCKETCOUNT; i++)
519 if(bucket[i].dwInUse == 0)
523 memset(pRet, 0, sizeof(RBNODE<T>));
528 _ASSERTE(!"AllocNode returns NULL");
532 bool FreeNode(RBNODE<T>* ptr)
534 size_t idx = ((size_t)ptr - (size_t)bucket)/sizeof(RBNODE<T>);
535 if(idx < BUCKETCOUNT)
537 bucket[idx].dwInUse = 0;
544 RBNODEBUCKET<T>* Next() { return pNext; };
546 void Append(RBNODEBUCKET<T>* ptr) { pNext = ptr; };
549 template <class T> class RBNODEPOOL
552 RBNODEBUCKET<T> base;
557 memset(&base,0,sizeof(RBNODEBUCKET<T>));
560 RBNODE<T>* AllocNode()
562 RBNODEBUCKET<T>* pBucket = &base;
563 RBNODEBUCKET<T>* pLastBucket = &base;
566 if(pBucket->CanAlloc())
568 return pBucket->AllocNode();
570 pLastBucket = pBucket;
571 pBucket = pBucket->Next();
573 while (pBucket != NULL);
574 pLastBucket->Append(new RBNODEBUCKET<T>);
575 return pLastBucket->Next()->AllocNode();
578 void FreeNode(RBNODE<T>* ptr)
580 RBNODEBUCKET<T>* pBucket = &base;
583 if(pBucket->FreeNode(ptr))
585 pBucket = pBucket->Next();
587 while (pBucket != NULL);
591 template <class T> class RBTREE
596 RBNODEPOOL<T> NodePool;
597 void RotateLeft(RBNODE<T>* pX)
602 pX->pRight = pY->pLeft;
604 if(pY->pLeft != pNil)
605 pY->pLeft->pParent = pX;
607 pY->pParent = pX->pParent;
609 if(pX == pX->pParent->pLeft)
610 pX->pParent->pLeft = pY;
612 pX->pParent->pRight = pY;
618 void RotateRight(RBNODE<T>* pX)
623 pX->pLeft = pY->pRight;
625 if(pY->pRight != pNil)
626 pY->pRight->pParent = pX;
628 pY->pParent = pX->pParent;
630 if(pX == pX->pParent->pLeft)
631 pX->pParent->pLeft = pY;
633 pX->pParent->pRight = pY;
640 void InsertNode(RBNODE<T>* pZ)
645 pZ->pLeft = pZ->pRight = pNil;
654 if(pX->tVal->ComparedTo(pZ->tVal) > 0)
661 if((pY == pRoot) || (pY->tVal->ComparedTo(pZ->tVal) > 0))
667 void InitSpecNode(RBNODE<T>* pNode)
669 pNode->pLeft = pNode->pRight = pNode->pParent = pNode;
672 void DeleteNode(RBNODE<T>* pNode, bool DeletePayload = true)
674 if((pNode != pNil)&&(pNode != pRoot))
676 DeleteNode(pNode->pLeft, DeletePayload);
677 DeleteNode(pNode->pRight, DeletePayload);
680 NodePool.FreeNode(pNode);
687 pRoot = NodePool.AllocNode();
690 pNil = NodePool.AllocNode();
697 //NodePool.FreeNode(pRoot);
698 //NodePool.FreeNode(pNil);
701 void RESET(bool DeletePayload = true)
703 DeleteNode(pRoot->pLeft, DeletePayload);
712 RBNODE<T>* pNewNode = NodePool.AllocNode();
717 InsertNode(pNewNode);
719 for(pX = pNewNode; pX->pParent->IsRed();)
721 if(pX->pParent == pX->pParent->pLeft)
723 pY = pX->pParent->pRight;
726 pX->pParent->SetBlack();
728 pX->pParent->pParent->SetRed();
729 pX = pX->pParent->pParent;
733 if(pX == pX->pParent->pRight)
738 pX->pParent->SetBlack();
739 pX->pParent->pParent->SetRed();
740 RotateRight(pX->pParent->pParent);
743 else // if(pX->pParent == pX->pParent->pRight)
745 pY = pX->pParent->pParent->pLeft;
748 pX->pParent->SetBlack();
750 pX->pParent->pParent->SetRed();
751 pX = pX->pParent->pParent;
755 if(pX == pX->pParent->pLeft)
760 pX->pParent->SetBlack();
761 pX->pParent->pParent->SetRed();
762 RotateLeft(pX->pParent->pParent);
764 }// end if(pX->pParent == pX->pParent->pLeft) -- else
765 } // end for(pX = pNewNode; pX->pParent->IsRed();)
766 pRoot->pLeft->SetBlack();
771 RBNODE<T>* pX = pRoot->pLeft;
772 if((pX != pNil) && (pX != pRoot))
774 int cmp = pX->tVal->ComparedTo(pT);
783 cmp = pX->tVal->ComparedTo(pT);
795 #endif //ASMTEMPLATES_H