Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

170 lines
4.7 KiB

  1. #include "priv.h"
  2. //*** FDSA -- small/fast DSA routines
  3. // DESCRIPTION
  4. // We attempt to behave as much like an array as possible (semantics
  5. // and performance and to some extent allocation). In particular,
  6. // - indexing (FDSA_GetItemXxx) is done entirely inline; and...
  7. // - ... involves only 1 extra indirection vs. a true array; and...
  8. // - ... knows the data type so sizeof is a constant; and...
  9. // - ... does no range checks (except possibly in DEBUG versions).
  10. // - part of the FDSA is statically alloc'ed, so one can put critical
  11. // items in the static part to ensure that they'll be there even under
  12. // low memory conditions.
  13. // NOTES
  14. // For now we only implement:
  15. // Initialize, Destroy, GetItemPtr, GetItemCount, InsertItem, AppendItem
  16. // FEATURE eventually these come from comctl...
  17. #define DABreak() /*NOTHING*/
  18. // ReAlloc and Free come from inc/heapaloc.h
  19. //*** SDSA_PITEM -- get item the hard way
  20. //
  21. #define SDSA_PITEM(pfdsa, i) \
  22. ((void *)(((BYTE *)(pfdsa)->aItem) + ((i) * (pfdsa)->cbItem)))
  23. //*** FDSA_Initialize -- initialize
  24. //
  25. BOOL WINAPI FDSA_Initialize(int cbItem, int cItemGrow,
  26. PFDSA pfdsa, void * aItemStatic, int cItemStatic)
  27. {
  28. ASSERT(pfdsa != NULL); // WARNING how handle?
  29. if (cItemGrow == 0)
  30. cItemGrow = 1;
  31. // for implementation simplicity, cItemStatic must be a multiple of
  32. // cItemGrow. o.w. our 1st grow from static->dynamic is messy and
  33. // probably buggy.
  34. if (cItemStatic % cItemGrow != 0) {
  35. AssertMsg(0, TEXT("CItemStatic must be a multiple of cItemGrow"));
  36. return FALSE;
  37. }
  38. if (aItemStatic != NULL) {
  39. // since we're (eventually) in comctl, we can't assume caller's
  40. // buffer was 0'ed
  41. ZeroMemory(aItemStatic, cItemStatic * cbItem);
  42. }
  43. if (pfdsa) {
  44. pfdsa->cItem = 0;
  45. pfdsa->cItemAlloc = cItemStatic;
  46. pfdsa->aItem = aItemStatic;
  47. pfdsa->fAllocated = FALSE;
  48. pfdsa->cbItem = cbItem;
  49. ASSERT(pfdsa->cbItem == cbItem); // bitfield overflow
  50. pfdsa->cItemGrow = cItemGrow;
  51. ASSERT(pfdsa->cItemGrow == cItemGrow); // bitfield overflow
  52. }
  53. return TRUE;
  54. }
  55. BOOL WINAPI FDSA_Destroy(PFDSA pdsa)
  56. {
  57. if (pdsa == NULL) // allow NULL for low memory cases
  58. return TRUE;
  59. if (pdsa->fAllocated && pdsa->aItem && !LocalFree(pdsa->aItem))
  60. return FALSE;
  61. return TRUE;
  62. }
  63. void* _LocalReAlloc(void* p, UINT uBytes)
  64. {
  65. if (uBytes) {
  66. if (p) {
  67. return LocalReAlloc(p, uBytes, LMEM_MOVEABLE | LMEM_ZEROINIT);
  68. } else {
  69. return LocalAlloc(LPTR, uBytes);
  70. }
  71. } else {
  72. if (p)
  73. LocalFree(p);
  74. return NULL;
  75. }
  76. }
  77. //*** FDSA_InsertItem -- insert an item
  78. // ENTRY/EXIT
  79. // index insertion point; index > count (e.g. DA_LAST) means append
  80. // NOTES
  81. // param called 'pdsa' (vs. pfdsa) for easy diff'ing w/ DSA_InsertItem
  82. int WINAPI FDSA_InsertItem(PFDSA pdsa, int index, void FAR* pitem)
  83. {
  84. ASSERT(pitem);
  85. if (index < 0) {
  86. TraceMsg(DM_ERROR, "FDSA: InsertItem: Invalid index: %d", index);
  87. DABreak();
  88. return -1;
  89. }
  90. if (index > pdsa->cItem)
  91. index = pdsa->cItem;
  92. if (pdsa->cItem + 1 > pdsa->cItemAlloc) {
  93. void FAR* aItemNew = _LocalReAlloc(pdsa->fAllocated ? pdsa->aItem : NULL,
  94. (pdsa->cItemAlloc + pdsa->cItemGrow) * pdsa->cbItem);
  95. if (!aItemNew)
  96. return -1;
  97. if (!pdsa->fAllocated) {
  98. // when we go from static->dynamic, we need to copy
  99. pdsa->fAllocated = TRUE;
  100. hmemcpy(aItemNew, pdsa->aItem, pdsa->cItem * pdsa->cbItem);
  101. }
  102. pdsa->aItem = aItemNew;
  103. pdsa->cItemAlloc += pdsa->cItemGrow;
  104. }
  105. if (index < pdsa->cItem) {
  106. hmemcpy(SDSA_PITEM(pdsa, index + 1), SDSA_PITEM(pdsa, index),
  107. (pdsa->cItem - index) * pdsa->cbItem);
  108. }
  109. pdsa->cItem++;
  110. hmemcpy(SDSA_PITEM(pdsa, index), pitem, pdsa->cbItem);
  111. return index;
  112. }
  113. BOOL WINAPI FDSA_DeleteItem(PFDSA pdsa, int index)
  114. {
  115. ASSERT(pdsa);
  116. if (index < 0 || index >= pdsa->cItem)
  117. {
  118. TraceMsg(TF_ERROR, "FDSA: DeleteItem: Invalid index: %d", index);
  119. DABreak();
  120. return FALSE;
  121. }
  122. if (index < pdsa->cItem - 1)
  123. {
  124. hmemcpy(SDSA_PITEM(pdsa, index), SDSA_PITEM(pdsa, index + 1),
  125. (pdsa->cItem - (index + 1)) * pdsa->cbItem);
  126. }
  127. pdsa->cItem--;
  128. #if 0
  129. // this doesn't work yet for FDsA
  130. if (pdsa->cItemAlloc - pdsa->cItem > pdsa->cItemGrow)
  131. {
  132. void FAR* aItemNew = ReAlloc(pdsa->aItem,
  133. (pdsa->cItemAlloc - pdsa->cItemGrow) * pdsa->cbItem);
  134. ASSERT(aItemNew);
  135. pdsa->aItem = aItemNew;
  136. pdsa->cItemAlloc -= pdsa->cItemGrow;
  137. }
  138. #endif
  139. return TRUE;
  140. }