cmsarray.c 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187
  1. /* This Source Code Form is subject to the terms of the Mozilla Public
  2. * License, v. 2.0. If a copy of the MPL was not distributed with this
  3. * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
  4. /*
  5. * CMS array functions.
  6. */
  7. #include "cmslocal.h"
  8. #include "secerr.h"
  9. /*
  10. * ARRAY FUNCTIONS
  11. *
  12. * In NSS, arrays are rather primitive arrays of pointers.
  13. * Makes it easy to walk the array, but hard to count elements
  14. * and manage the storage.
  15. *
  16. * This is a feeble attempt to encapsulate the functionality
  17. * and get rid of hundreds of lines of similar code
  18. */
  19. /*
  20. * NSS_CMSArray_Alloc - allocate an array in an arena
  21. *
  22. * This allocates space for the array of pointers
  23. */
  24. void **
  25. NSS_CMSArray_Alloc(PLArenaPool *poolp, int n)
  26. {
  27. return (void **)PORT_ArenaZAlloc(poolp, n * sizeof(void *));
  28. }
  29. /*
  30. * NSS_CMSArray_Add - add an element to the end of an array
  31. *
  32. * The array of pointers is either created (if array was empty before) or grown.
  33. */
  34. SECStatus
  35. NSS_CMSArray_Add(PLArenaPool *poolp, void ***array, void *obj)
  36. {
  37. void **p;
  38. int n;
  39. void **dest;
  40. PORT_Assert(array != NULL);
  41. if (array == NULL)
  42. return SECFailure;
  43. if (*array == NULL) {
  44. dest = (void **)PORT_ArenaAlloc(poolp, 2 * sizeof(void *));
  45. n = 0;
  46. } else {
  47. n = 0;
  48. p = *array;
  49. while (*p++)
  50. n++;
  51. dest = (void **)PORT_ArenaGrow(poolp,
  52. *array,
  53. (n + 1) * sizeof(void *),
  54. (n + 2) * sizeof(void *));
  55. }
  56. if (dest == NULL)
  57. return SECFailure;
  58. dest[n] = obj;
  59. dest[n + 1] = NULL;
  60. *array = dest;
  61. return SECSuccess;
  62. }
  63. /*
  64. * NSS_CMSArray_IsEmpty - check if array is empty
  65. */
  66. PRBool
  67. NSS_CMSArray_IsEmpty(void **array)
  68. {
  69. return (array == NULL || array[0] == NULL);
  70. }
  71. /*
  72. * NSS_CMSArray_Count - count number of elements in array
  73. */
  74. int
  75. NSS_CMSArray_Count(void **array)
  76. {
  77. int n = 0;
  78. if (array == NULL)
  79. return 0;
  80. while (*array++ != NULL)
  81. n++;
  82. return n;
  83. }
  84. /*
  85. * NSS_CMSArray_Sort - sort an array in place
  86. *
  87. * If "secondary" or "tertiary are not NULL, it must be arrays with the same
  88. * number of elements as "primary". The same reordering will get applied to it.
  89. *
  90. * "compare" is a function that returns
  91. * < 0 when the first element is less than the second
  92. * = 0 when the first element is equal to the second
  93. * > 0 when the first element is greater than the second
  94. * to acheive ascending ordering.
  95. */
  96. void
  97. NSS_CMSArray_Sort(void **primary, int (*compare)(void *, void *), void **secondary, void **tertiary)
  98. {
  99. int n, i, limit, lastxchg;
  100. void *tmp;
  101. n = NSS_CMSArray_Count(primary);
  102. PORT_Assert(secondary == NULL || NSS_CMSArray_Count(secondary) == n);
  103. PORT_Assert(tertiary == NULL || NSS_CMSArray_Count(tertiary) == n);
  104. if (n <= 1) /* ordering is fine */
  105. return;
  106. /* yes, ladies and gentlemen, it's BUBBLE SORT TIME! */
  107. limit = n - 1;
  108. while (1) {
  109. lastxchg = 0;
  110. for (i = 0; i < limit; i++) {
  111. if ((*compare)(primary[i], primary[i + 1]) > 0) {
  112. /* exchange the neighbours */
  113. tmp = primary[i + 1];
  114. primary[i + 1] = primary[i];
  115. primary[i] = tmp;
  116. if (secondary) { /* secondary array? */
  117. tmp = secondary[i + 1]; /* exchange there as well */
  118. secondary[i + 1] = secondary[i];
  119. secondary[i] = tmp;
  120. }
  121. if (tertiary) { /* tertiary array? */
  122. tmp = tertiary[i + 1]; /* exchange there as well */
  123. tertiary[i + 1] = tertiary[i];
  124. tertiary[i] = tmp;
  125. }
  126. lastxchg = i + 1; /* index of the last element bubbled up */
  127. }
  128. }
  129. if (lastxchg == 0) /* no exchanges, so array is sorted */
  130. break; /* we're done */
  131. limit = lastxchg; /* array is sorted up to [limit] */
  132. }
  133. }
  134. #if 0
  135. /* array iterator stuff... not used */
  136. typedef void **NSSCMSArrayIterator;
  137. /* iterator */
  138. NSSCMSArrayIterator
  139. NSS_CMSArray_First(void **array)
  140. {
  141. if (array == NULL || array[0] == NULL)
  142. return NULL;
  143. return (NSSCMSArrayIterator)&(array[0]);
  144. }
  145. void *
  146. NSS_CMSArray_Obj(NSSCMSArrayIterator iter)
  147. {
  148. void **p = (void **)iter;
  149. return *iter; /* which is NULL if we are at the end of the array */
  150. }
  151. NSSCMSArrayIterator
  152. NSS_CMSArray_Next(NSSCMSArrayIterator iter)
  153. {
  154. void **p = (void **)iter;
  155. return (NSSCMSArrayIterator)(p + 1);
  156. }
  157. #endif