]>
Commit | Line | Data |
---|---|---|
b1ab9ed8 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> | |
d8f41ccd | 41 | #include <security_asn1/secport.h> |
b1ab9ed8 A |
42 | |
43 | /* | |
44 | * ARRAY FUNCTIONS | |
45 | * | |
46 | * In NSS, arrays are rather primitive arrays of pointers. | |
47 | * Makes it easy to walk the array, but hard to count elements | |
48 | * and manage the storage. | |
49 | * | |
50 | * This is a feeble attempt to encapsulate the functionality | |
51 | * and get rid of hundreds of lines of similar code | |
52 | */ | |
53 | ||
54 | /* | |
55 | * SecCmsArrayAlloc - allocate an array in an arena | |
56 | * | |
57 | * This allocates space for the array of pointers | |
58 | */ | |
59 | void ** | |
60 | SecCmsArrayAlloc(PRArenaPool *poolp, int n) | |
61 | { | |
62 | return (void **)PORT_ArenaZAlloc(poolp, n * sizeof(void *)); | |
63 | } | |
64 | ||
65 | /* | |
66 | * SecCmsArrayAdd - add an element to the end of an array | |
67 | * | |
68 | * The array of pointers is either created (if array was empty before) or grown. | |
69 | */ | |
70 | OSStatus | |
71 | SecCmsArrayAdd(PRArenaPool *poolp, void ***array, void *obj) | |
72 | { | |
73 | void **p; | |
74 | int n; | |
75 | void **dest; | |
76 | ||
77 | PORT_Assert(array != NULL); | |
78 | if (array == NULL) | |
79 | return SECFailure; | |
80 | ||
81 | if (*array == NULL) { | |
82 | dest = (void **)PORT_ArenaAlloc(poolp, 2 * sizeof(void *)); | |
83 | n = 0; | |
84 | } else { | |
85 | n = 0; p = *array; | |
86 | while (*p++) | |
87 | n++; | |
88 | dest = (void **)PORT_ArenaGrow (poolp, | |
89 | *array, | |
90 | (n + 1) * sizeof(void *), | |
91 | (n + 2) * sizeof(void *)); | |
92 | } | |
93 | ||
94 | if (dest == NULL) | |
95 | return SECFailure; | |
96 | ||
97 | dest[n] = obj; | |
98 | dest[n+1] = NULL; | |
99 | *array = dest; | |
100 | return SECSuccess; | |
101 | } | |
102 | ||
103 | /* | |
104 | * SecCmsArrayIsEmpty - check if array is empty | |
105 | */ | |
106 | Boolean | |
107 | SecCmsArrayIsEmpty(void **array) | |
108 | { | |
109 | return (array == NULL || array[0] == NULL); | |
110 | } | |
111 | ||
112 | /* | |
113 | * SecCmsArrayCount - count number of elements in array | |
114 | */ | |
115 | int | |
116 | SecCmsArrayCount(void **array) | |
117 | { | |
118 | int n = 0; | |
119 | ||
120 | if (array == NULL) | |
121 | return 0; | |
122 | ||
123 | while (*array++ != NULL) | |
124 | n++; | |
125 | ||
126 | return n; | |
127 | } | |
128 | ||
129 | /* | |
130 | * SecCmsArraySort - sort an array in place | |
131 | * | |
132 | * If "secondary" or "tertiary are not NULL, it must be arrays with the same | |
133 | * number of elements as "primary". The same reordering will get applied to it. | |
134 | * | |
135 | * "compare" is a function that returns | |
136 | * < 0 when the first element is less than the second | |
137 | * = 0 when the first element is equal to the second | |
138 | * > 0 when the first element is greater than the second | |
139 | * to acheive ascending ordering. | |
140 | */ | |
141 | void | |
142 | SecCmsArraySort(void **primary, int (*compare)(void *,void *), void **secondary, void **tertiary) | |
143 | { | |
144 | int n, i, limit, lastxchg; | |
145 | void *tmp; | |
146 | ||
147 | n = SecCmsArrayCount(primary); | |
148 | ||
149 | PORT_Assert(secondary == NULL || SecCmsArrayCount(secondary) == n); | |
150 | PORT_Assert(tertiary == NULL || SecCmsArrayCount(tertiary) == n); | |
151 | ||
152 | if (n <= 1) /* ordering is fine */ | |
153 | return; | |
154 | ||
155 | /* yes, ladies and gentlemen, it's BUBBLE SORT TIME! */ | |
156 | limit = n - 1; | |
157 | while (1) { | |
158 | lastxchg = 0; | |
159 | for (i = 0; i < limit; i++) { | |
160 | if ((*compare)(primary[i], primary[i+1]) > 0) { | |
161 | /* exchange the neighbours */ | |
162 | tmp = primary[i+1]; | |
163 | primary[i+1] = primary[i]; | |
164 | primary[i] = tmp; | |
165 | if (secondary) { /* secondary array? */ | |
166 | tmp = secondary[i+1]; /* exchange there as well */ | |
167 | secondary[i+1] = secondary[i]; | |
168 | secondary[i] = tmp; | |
169 | } | |
170 | if (tertiary) { /* tertiary array? */ | |
171 | tmp = tertiary[i+1]; /* exchange there as well */ | |
172 | tertiary[i+1] = tertiary[i]; | |
173 | tertiary[i] = tmp; | |
174 | } | |
175 | lastxchg = i+1; /* index of the last element bubbled up */ | |
176 | } | |
177 | } | |
178 | if (lastxchg == 0) /* no exchanges, so array is sorted */ | |
179 | break; /* we're done */ | |
180 | limit = lastxchg; /* array is sorted up to [limit] */ | |
181 | } | |
182 | } | |
183 | ||
184 | #if 0 | |
185 | ||
186 | /* array iterator stuff... not used */ | |
187 | ||
188 | typedef void **SecCmsArrayIterator; | |
189 | ||
190 | /* iterator */ | |
191 | SecCmsArrayIterator | |
192 | SecCmsArrayFirst(void **array) | |
193 | { | |
194 | if (array == NULL || array[0] == NULL) | |
195 | return NULL; | |
196 | return (SecCmsArrayIterator)&(array[0]); | |
197 | } | |
198 | ||
199 | void * | |
200 | SecCmsArrayObj(SecCmsArrayIterator iter) | |
201 | { | |
202 | void **p = (void **)iter; | |
203 | ||
204 | return *iter; /* which is NULL if we are at the end of the array */ | |
205 | } | |
206 | ||
207 | SecCmsArrayIterator | |
208 | SecCmsArrayNext(SecCmsArrayIterator iter) | |
209 | { | |
210 | void **p = (void **)iter; | |
211 | ||
212 | return (SecCmsArrayIterator)(p + 1); | |
213 | } | |
214 | ||
215 | #endif |