Team Fortress 2 Source Code as on 22/4/2020
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.

112 lines
5.6 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. /******************************************************************/
  3. /* qsort.c -- Non-Recursive ANSI Quicksort function */
  4. /* */
  5. /* Public domain by Raymond Gardner, Englewood CO February 1991 */
  6. /* */
  7. /* Usage: */
  8. /* qsort(base, nbr_elements, width_bytes, compare_function); */
  9. /* void *base; */
  10. /* size_t nbr_elements, width_bytes; */
  11. /* int (*compare_function)(const void *, const void *); */
  12. /* */
  13. /* Sorts an array starting at base, of length nbr_elements, each */
  14. /* element of size width_bytes, ordered via compare_function, */
  15. /* which is called as (*compare_function)(ptr_to_element1, */
  16. /* ptr_to_element2) and returns < 0 if element1 < element2, */
  17. /* 0 if element1 = element2, > 0 if element1 > element2. */
  18. /* Most refinements are due to R. Sedgewick. See "Implementing */
  19. /* Quicksort Programs", Comm. ACM, Oct. 1978, and Corrigendum, */
  20. /* Comm. ACM, June 1979. */
  21. /******************************************************************/
  22. // modified to take (and use) a context object, ala Microsoft's qsort_s
  23. // "extension" to the stdlib
  24. #include <stddef.h> /* for size_t definition */
  25. /*
  26. ** swap nbytes between a and b
  27. */
  28. static void swap_bytes(char *a, char *b, size_t nbytes)
  29. {
  30. char tmp;
  31. do {
  32. tmp = *a; *a++ = *b; *b++ = tmp;
  33. } while ( --nbytes );
  34. }
  35. #define SWAP(a, b) (swap_bytes((char *)(a), (char *)(b), size))
  36. #define COMP(ctx, a, b) ((*comp)((void *)ctx, (void *)(a), (void *)(b)))
  37. #define T 7 /* subfiles of T or fewer elements will */
  38. /* be sorted by a simple insertion sort */
  39. /* Note! T must be at least 3 */
  40. extern "C" void qsort_s(void *basep, size_t nelems, size_t size,
  41. int (*comp)(void *, const void *, const void *),
  42. void *ctx)
  43. {
  44. char *stack[40], **sp; /* stack and stack pointer */
  45. char *i, *j, *limit; /* scan and limit pointers */
  46. size_t thresh; /* size of T elements in bytes */
  47. char *base; /* base pointer as char * */
  48. base = (char *)basep; /* set up char * base pointer */
  49. thresh = T * size; /* init threshold */
  50. sp = stack; /* init stack pointer */
  51. limit = base + nelems * size;/* pointer past end of array */
  52. for ( ;; ) { /* repeat until break... */
  53. if ( limit - base > thresh ) { /* if more than T elements */
  54. /* swap base with middle */
  55. SWAP((((limit-base)/size)/2)*size+base, base);
  56. i = base + size; /* i scans left to right */
  57. j = limit - size; /* j scans right to left */
  58. if ( COMP(ctx, i, j) > 0 ) /* Sedgewick's */
  59. SWAP(i, j); /* three-element sort */
  60. if ( COMP(ctx, base, j) > 0 )/* sets things up */
  61. SWAP(base, j); /* so that */
  62. if ( COMP(ctx, i, base) > 0 )/* *i <= *base <= *j */
  63. SWAP(i, base); /* *base is pivot element */
  64. for ( ;; ) { /* loop until break */
  65. do /* move i right */
  66. i += size; /* until *i >= pivot */
  67. while ( COMP(ctx, i, base) < 0 );
  68. do /* move j left */
  69. j -= size; /* until *j <= pivot */
  70. while ( COMP(ctx, j, base) > 0 );
  71. if ( i > j ) /* if pointers crossed */
  72. break; /* break loop */
  73. SWAP(i, j); /* else swap elements, keep scanning*/
  74. }
  75. SWAP(base, j); /* move pivot into correct place */
  76. if ( j - base > limit - i ) { /* if left subfile larger */
  77. sp[0] = base; /* stack left subfile base */
  78. sp[1] = j; /* and limit */
  79. base = i; /* sort the right subfile */
  80. } else { /* else right subfile larger*/
  81. sp[0] = i; /* stack right subfile base */
  82. sp[1] = limit; /* and limit */
  83. limit = j; /* sort the left subfile */
  84. }
  85. sp += 2; /* increment stack pointer */
  86. } else { /* else subfile is small, use insertion sort */
  87. for ( j = base, i = j+size; i < limit; j = i, i += size )
  88. for ( ; COMP(ctx, j, j+size) > 0; j -= size ) {
  89. SWAP(j, j+size);
  90. if ( j == base )
  91. break;
  92. }
  93. if ( sp != stack ) { /* if any entries on stack */
  94. sp -= 2; /* pop the base and limit */
  95. base = sp[0];
  96. limit = sp[1];
  97. } else /* else stack empty, done */
  98. break;
  99. }
  100. }
  101. }