1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/security/nss/lib/smime/cmsarray.c Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,185 @@ 1.4 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.5 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.6 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.7 + 1.8 +/* 1.9 + * CMS array functions. 1.10 + */ 1.11 + 1.12 +#include "cmslocal.h" 1.13 + 1.14 +#include "secerr.h" 1.15 + 1.16 +/* 1.17 + * ARRAY FUNCTIONS 1.18 + * 1.19 + * In NSS, arrays are rather primitive arrays of pointers. 1.20 + * Makes it easy to walk the array, but hard to count elements 1.21 + * and manage the storage. 1.22 + * 1.23 + * This is a feeble attempt to encapsulate the functionality 1.24 + * and get rid of hundreds of lines of similar code 1.25 + */ 1.26 + 1.27 +/* 1.28 + * NSS_CMSArray_Alloc - allocate an array in an arena 1.29 + * 1.30 + * This allocates space for the array of pointers 1.31 + */ 1.32 +void ** 1.33 +NSS_CMSArray_Alloc(PLArenaPool *poolp, int n) 1.34 +{ 1.35 + return (void **)PORT_ArenaZAlloc(poolp, n * sizeof(void *)); 1.36 +} 1.37 + 1.38 +/* 1.39 + * NSS_CMSArray_Add - add an element to the end of an array 1.40 + * 1.41 + * The array of pointers is either created (if array was empty before) or grown. 1.42 + */ 1.43 +SECStatus 1.44 +NSS_CMSArray_Add(PLArenaPool *poolp, void ***array, void *obj) 1.45 +{ 1.46 + void **p; 1.47 + int n; 1.48 + void **dest; 1.49 + 1.50 + PORT_Assert(array != NULL); 1.51 + if (array == NULL) 1.52 + return SECFailure; 1.53 + 1.54 + if (*array == NULL) { 1.55 + dest = (void **)PORT_ArenaAlloc(poolp, 2 * sizeof(void *)); 1.56 + n = 0; 1.57 + } else { 1.58 + n = 0; p = *array; 1.59 + while (*p++) 1.60 + n++; 1.61 + dest = (void **)PORT_ArenaGrow (poolp, 1.62 + *array, 1.63 + (n + 1) * sizeof(void *), 1.64 + (n + 2) * sizeof(void *)); 1.65 + } 1.66 + 1.67 + if (dest == NULL) 1.68 + return SECFailure; 1.69 + 1.70 + dest[n] = obj; 1.71 + dest[n+1] = NULL; 1.72 + *array = dest; 1.73 + return SECSuccess; 1.74 +} 1.75 + 1.76 +/* 1.77 + * NSS_CMSArray_IsEmpty - check if array is empty 1.78 + */ 1.79 +PRBool 1.80 +NSS_CMSArray_IsEmpty(void **array) 1.81 +{ 1.82 + return (array == NULL || array[0] == NULL); 1.83 +} 1.84 + 1.85 +/* 1.86 + * NSS_CMSArray_Count - count number of elements in array 1.87 + */ 1.88 +int 1.89 +NSS_CMSArray_Count(void **array) 1.90 +{ 1.91 + int n = 0; 1.92 + 1.93 + if (array == NULL) 1.94 + return 0; 1.95 + 1.96 + while (*array++ != NULL) 1.97 + n++; 1.98 + 1.99 + return n; 1.100 +} 1.101 + 1.102 +/* 1.103 + * NSS_CMSArray_Sort - sort an array in place 1.104 + * 1.105 + * If "secondary" or "tertiary are not NULL, it must be arrays with the same 1.106 + * number of elements as "primary". The same reordering will get applied to it. 1.107 + * 1.108 + * "compare" is a function that returns 1.109 + * < 0 when the first element is less than the second 1.110 + * = 0 when the first element is equal to the second 1.111 + * > 0 when the first element is greater than the second 1.112 + * to acheive ascending ordering. 1.113 + */ 1.114 +void 1.115 +NSS_CMSArray_Sort(void **primary, int (*compare)(void *,void *), void **secondary, void **tertiary) 1.116 +{ 1.117 + int n, i, limit, lastxchg; 1.118 + void *tmp; 1.119 + 1.120 + n = NSS_CMSArray_Count(primary); 1.121 + 1.122 + PORT_Assert(secondary == NULL || NSS_CMSArray_Count(secondary) == n); 1.123 + PORT_Assert(tertiary == NULL || NSS_CMSArray_Count(tertiary) == n); 1.124 + 1.125 + if (n <= 1) /* ordering is fine */ 1.126 + return; 1.127 + 1.128 + /* yes, ladies and gentlemen, it's BUBBLE SORT TIME! */ 1.129 + limit = n - 1; 1.130 + while (1) { 1.131 + lastxchg = 0; 1.132 + for (i = 0; i < limit; i++) { 1.133 + if ((*compare)(primary[i], primary[i+1]) > 0) { 1.134 + /* exchange the neighbours */ 1.135 + tmp = primary[i+1]; 1.136 + primary[i+1] = primary[i]; 1.137 + primary[i] = tmp; 1.138 + if (secondary) { /* secondary array? */ 1.139 + tmp = secondary[i+1]; /* exchange there as well */ 1.140 + secondary[i+1] = secondary[i]; 1.141 + secondary[i] = tmp; 1.142 + } 1.143 + if (tertiary) { /* tertiary array? */ 1.144 + tmp = tertiary[i+1]; /* exchange there as well */ 1.145 + tertiary[i+1] = tertiary[i]; 1.146 + tertiary[i] = tmp; 1.147 + } 1.148 + lastxchg = i+1; /* index of the last element bubbled up */ 1.149 + } 1.150 + } 1.151 + if (lastxchg == 0) /* no exchanges, so array is sorted */ 1.152 + break; /* we're done */ 1.153 + limit = lastxchg; /* array is sorted up to [limit] */ 1.154 + } 1.155 +} 1.156 + 1.157 +#if 0 1.158 + 1.159 +/* array iterator stuff... not used */ 1.160 + 1.161 +typedef void **NSSCMSArrayIterator; 1.162 + 1.163 +/* iterator */ 1.164 +NSSCMSArrayIterator 1.165 +NSS_CMSArray_First(void **array) 1.166 +{ 1.167 + if (array == NULL || array[0] == NULL) 1.168 + return NULL; 1.169 + return (NSSCMSArrayIterator)&(array[0]); 1.170 +} 1.171 + 1.172 +void * 1.173 +NSS_CMSArray_Obj(NSSCMSArrayIterator iter) 1.174 +{ 1.175 + void **p = (void **)iter; 1.176 + 1.177 + return *iter; /* which is NULL if we are at the end of the array */ 1.178 +} 1.179 + 1.180 +NSSCMSArrayIterator 1.181 +NSS_CMSArray_Next(NSSCMSArrayIterator iter) 1.182 +{ 1.183 + void **p = (void **)iter; 1.184 + 1.185 + return (NSSCMSArrayIterator)(p + 1); 1.186 +} 1.187 + 1.188 +#endif