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