]>
Commit | Line | Data |
---|---|---|
d8f41ccd A |
1 | /* |
2 | * The contents of this file are subject to the Mozilla Public | |
3 | * License Version 1.1 (the "License"); you may not use this file | |
4 | * except in compliance with the License. You may obtain a copy of | |
5 | * the License at http://www.mozilla.org/MPL/ | |
6 | * | |
7 | * Software distributed under the License is distributed on an "AS | |
8 | * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or | |
9 | * implied. See the License for the specific language governing | |
10 | * rights and limitations under the License. | |
11 | * | |
12 | * The Original Code is the Netscape security libraries. | |
13 | * | |
14 | * The Initial Developer of the Original Code is Netscape | |
15 | * Communications Corporation. Portions created by Netscape are | |
16 | * Copyright (C) 1994-2000 Netscape Communications Corporation. All | |
17 | * Rights Reserved. | |
18 | * | |
19 | * Contributor(s): | |
20 | * | |
21 | * Alternatively, the contents of this file may be used under the | |
22 | * terms of the GNU General Public License Version 2 or later (the | |
23 | * "GPL"), in which case the provisions of the GPL are applicable | |
24 | * instead of those above. If you wish to allow use of your | |
25 | * version of this file only under the terms of the GPL and not to | |
26 | * allow others to use your version of this file under the MPL, | |
27 | * indicate your decision by deleting the provisions above and | |
28 | * replace them with the notice and other provisions required by | |
29 | * the GPL. If you do not delete the provisions above, a recipient | |
30 | * may use your version of this file under either the MPL or the | |
31 | * GPL. | |
32 | */ | |
33 | ||
34 | /* | |
35 | * CMS array functions. | |
36 | */ | |
37 | ||
38 | #include "cmslocal.h" | |
39 | ||
40 | #include <security_asn1/secerr.h> | |
41 | ||
42 | /* | |
43 | * ARRAY FUNCTIONS | |
44 | * | |
45 | * In NSS, arrays are rather primitive arrays of pointers. | |
46 | * Makes it easy to walk the array, but hard to count elements | |
47 | * and manage the storage. | |
48 | * | |
49 | * This is a feeble attempt to encapsulate the functionality | |
50 | * and get rid of hundreds of lines of similar code | |
51 | */ | |
52 | ||
53 | /* | |
54 | * SecCmsArrayAlloc - allocate an array in an arena | |
55 | * | |
56 | * This allocates space for the array of pointers | |
57 | */ | |
58 | void ** | |
59 | SecCmsArrayAlloc(PRArenaPool *poolp, int n) | |
60 | { | |
61 | return (void **)PORT_ArenaZAlloc(poolp, n * sizeof(void *)); | |
62 | } | |
63 | ||
64 | /* | |
65 | * SecCmsArrayAdd - add an element to the end of an array | |
66 | * | |
67 | * The array of pointers is either created (if array was empty before) or grown. | |
68 | */ | |
69 | OSStatus | |
70 | SecCmsArrayAdd(PRArenaPool *poolp, void ***array, void *obj) | |
71 | { | |
72 | void **p; | |
73 | int n; | |
74 | void **dest; | |
75 | ||
76 | PORT_Assert(array != NULL); | |
77 | if (array == NULL) | |
78 | return SECFailure; | |
79 | ||
80 | if (*array == NULL) { | |
81 | dest = (void **)PORT_ArenaAlloc(poolp, 2 * sizeof(void *)); | |
82 | n = 0; | |
83 | } else { | |
84 | n = 0; p = *array; | |
85 | while (*p++) | |
86 | n++; | |
87 | dest = (void **)PORT_ArenaGrow (poolp, | |
88 | *array, | |
89 | (n + 1) * sizeof(void *), | |
90 | (n + 2) * sizeof(void *)); | |
91 | } | |
92 | ||
93 | if (dest == NULL) | |
94 | return SECFailure; | |
95 | ||
96 | dest[n] = obj; | |
97 | dest[n+1] = NULL; | |
98 | *array = dest; | |
99 | return SECSuccess; | |
100 | } | |
101 | ||
102 | /* | |
103 | * SecCmsArrayIsEmpty - check if array is empty | |
104 | */ | |
105 | Boolean | |
106 | SecCmsArrayIsEmpty(void **array) | |
107 | { | |
108 | return (array == NULL || array[0] == NULL); | |
109 | } | |
110 | ||
111 | /* | |
112 | * SecCmsArrayCount - count number of elements in array | |
113 | */ | |
114 | int | |
115 | SecCmsArrayCount(void **array) | |
116 | { | |
117 | int n = 0; | |
118 | ||
119 | if (array == NULL) | |
120 | return 0; | |
121 | ||
122 | while (*array++ != NULL) | |
123 | n++; | |
124 | ||
125 | return n; | |
126 | } | |
127 | ||
128 | /* | |
129 | * SecCmsArraySort - sort an array in place | |
130 | * | |
131 | * If "secondary" or "tertiary are not NULL, it must be arrays with the same | |
132 | * number of elements as "primary". The same reordering will get applied to it. | |
133 | * | |
134 | * "compare" is a function that returns | |
135 | * < 0 when the first element is less than the second | |
136 | * = 0 when the first element is equal to the second | |
137 | * > 0 when the first element is greater than the second | |
138 | * to acheive ascending ordering. | |
139 | */ | |
140 | void | |
141 | SecCmsArraySort(void **primary, int (*compare)(void *,void *), void **secondary, void **tertiary) | |
142 | { | |
143 | int n, i, limit, lastxchg; | |
144 | void *tmp; | |
145 | ||
146 | n = SecCmsArrayCount(primary); | |
147 | ||
148 | PORT_Assert(secondary == NULL || SecCmsArrayCount(secondary) == n); | |
149 | PORT_Assert(tertiary == NULL || SecCmsArrayCount(tertiary) == n); | |
150 | ||
151 | if (n <= 1) /* ordering is fine */ | |
152 | return; | |
153 | ||
154 | /* yes, ladies and gentlemen, it's BUBBLE SORT TIME! */ | |
155 | limit = n - 1; | |
156 | while (1) { | |
157 | lastxchg = 0; | |
158 | for (i = 0; i < limit; i++) { | |
159 | if ((*compare)(primary[i], primary[i+1]) > 0) { | |
160 | /* exchange the neighbours */ | |
161 | tmp = primary[i+1]; | |
162 | primary[i+1] = primary[i]; | |
163 | primary[i] = tmp; | |
164 | if (secondary) { /* secondary array? */ | |
165 | tmp = secondary[i+1]; /* exchange there as well */ | |
166 | secondary[i+1] = secondary[i]; | |
167 | secondary[i] = tmp; | |
168 | } | |
169 | if (tertiary) { /* tertiary array? */ | |
170 | tmp = tertiary[i+1]; /* exchange there as well */ | |
171 | tertiary[i+1] = tertiary[i]; | |
172 | tertiary[i] = tmp; | |
173 | } | |
174 | lastxchg = i+1; /* index of the last element bubbled up */ | |
175 | } | |
176 | } | |
177 | if (lastxchg == 0) /* no exchanges, so array is sorted */ | |
178 | break; /* we're done */ | |
179 | limit = lastxchg; /* array is sorted up to [limit] */ | |
180 | } | |
181 | } | |
182 | ||
183 | #if 0 | |
184 | ||
185 | /* array iterator stuff... not used */ | |
186 | ||
187 | typedef void **SecCmsArrayIterator; | |
188 | ||
189 | /* iterator */ | |
190 | SecCmsArrayIterator | |
191 | SecCmsArrayFirst(void **array) | |
192 | { | |
193 | if (array == NULL || array[0] == NULL) | |
194 | return NULL; | |
195 | return (SecCmsArrayIterator)&(array[0]); | |
196 | } | |
197 | ||
198 | void * | |
199 | SecCmsArrayObj(SecCmsArrayIterator iter) | |
200 | { | |
201 | void **p = (void **)iter; | |
202 | ||
203 | return *iter; /* which is NULL if we are at the end of the array */ | |
204 | } | |
205 | ||
206 | SecCmsArrayIterator | |
207 | SecCmsArrayNext(SecCmsArrayIterator iter) | |
208 | { | |
209 | void **p = (void **)iter; | |
210 | ||
211 | return (SecCmsArrayIterator)(p + 1); | |
212 | } | |
213 | ||
214 | #endif |