jsort.inc 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  1. /*##############################################################################
  2. HPCC SYSTEMS software Copyright (C) 2012 HPCC Systems®.
  3. Licensed under the Apache License, Version 2.0 (the "License");
  4. you may not use this file except in compliance with the License.
  5. You may obtain a copy of the License at
  6. http://www.apache.org/licenses/LICENSE-2.0
  7. Unless required by applicable law or agreed to in writing, software
  8. distributed under the License is distributed on an "AS IS" BASIS,
  9. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. See the License for the specific language governing permissions and
  11. limitations under the License.
  12. ############################################################################## */
  13. //This function is included twice in order to common up the code....
  14. /*
  15. void * binary_add(const void *newitem, const void *base,
  16. size_t nmemb,
  17. WIDTH_PROTOTYPE
  18. COMPARE_PROTOTYPE
  19. bool * ItemAdded)
  20. {
  21. */
  22. /*
  23. * Perform a binary search and add. The entry is only added if it
  24. * does not already exist.
  25. * A pointer to the new entry is returned.
  26. */
  27. size_t right;
  28. size_t middle;
  29. size_t left = 0;
  30. int result;
  31. char * CurEntry;
  32. #ifndef ALWAYS_ADD
  33. *ItemAdded = false;
  34. #endif
  35. if (nmemb == 0)
  36. {
  37. middle = 0;
  38. goto AddEntry;
  39. }
  40. right = nmemb-1;
  41. /*
  42. * Loop until we've narrowed down the search range to one or two
  43. * items. This ensures that middle != 0, preventing 'right' from wrapping.
  44. */
  45. while (right - left > 1)
  46. {
  47. /* Calculate the middle entry in the array - NOT the middle offset */
  48. middle = (right + left) >> 1;
  49. CurEntry = (char *)base + middle * width;
  50. result = COMPARE(newitem, CurEntry);
  51. if (result < 0)
  52. right = middle - 1;
  53. else if (result > 0)
  54. left = middle + 1;
  55. else
  56. goto Done;
  57. }
  58. middle = left;
  59. /*
  60. * The range has been narrowed down to 1 or 2 items.
  61. * Perform an optimal check on these last two elements.
  62. */
  63. result = COMPARE(newitem, (char *)base + middle * width);
  64. if (result == 0)
  65. goto Done;
  66. if (result > 0)
  67. {
  68. ++middle;
  69. if (right == left + 1)
  70. {
  71. result = COMPARE(newitem, (char *)base + middle * width);
  72. if (result == 0)
  73. goto Done;
  74. if (result > 0)
  75. ++middle;
  76. }
  77. }
  78. AddEntry:
  79. #ifndef NEVER_ADD
  80. #ifdef ALWAYS_ADD
  81. Done:
  82. #endif
  83. CurEntry = (char *)base + middle * width;
  84. #ifdef SEEK_LAST_MATCH
  85. while((middle < nmemb) && (COMPARE(newitem, CurEntry) == 0))
  86. {
  87. ++middle;
  88. CurEntry += width;
  89. }
  90. #endif
  91. memmove(CurEntry + width, CurEntry, (nmemb - middle) * width);
  92. INSERT(CurEntry, newitem);
  93. #ifndef ALWAYS_ADD
  94. *ItemAdded = true;
  95. Done:
  96. #endif
  97. #else
  98. *ItemAdded = true;
  99. Done:
  100. #endif
  101. return (char *)base + middle * width;
  102. /*
  103. }
  104. */