/src/mozilla-central/security/nss/lib/smime/cmsarray.c
Line | Count | Source (jump to first uncovered line) |
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 | 0 | { |
32 | 0 | return (void **)PORT_ArenaZAlloc(poolp, n * sizeof(void *)); |
33 | 0 | } |
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 | 0 | { |
43 | 0 | void **p; |
44 | 0 | int n; |
45 | 0 | void **dest; |
46 | 0 |
|
47 | 0 | PORT_Assert(array != NULL); |
48 | 0 | if (array == NULL) |
49 | 0 | return SECFailure; |
50 | 0 | |
51 | 0 | if (*array == NULL) { |
52 | 0 | dest = (void **)PORT_ArenaAlloc(poolp, 2 * sizeof(void *)); |
53 | 0 | n = 0; |
54 | 0 | } else { |
55 | 0 | n = 0; |
56 | 0 | p = *array; |
57 | 0 | while (*p++) |
58 | 0 | n++; |
59 | 0 | dest = (void **)PORT_ArenaGrow(poolp, |
60 | 0 | *array, |
61 | 0 | (n + 1) * sizeof(void *), |
62 | 0 | (n + 2) * sizeof(void *)); |
63 | 0 | } |
64 | 0 |
|
65 | 0 | if (dest == NULL) |
66 | 0 | return SECFailure; |
67 | 0 | |
68 | 0 | dest[n] = obj; |
69 | 0 | dest[n + 1] = NULL; |
70 | 0 | *array = dest; |
71 | 0 | return SECSuccess; |
72 | 0 | } |
73 | | |
74 | | /* |
75 | | * NSS_CMSArray_IsEmpty - check if array is empty |
76 | | */ |
77 | | PRBool |
78 | | NSS_CMSArray_IsEmpty(void **array) |
79 | 0 | { |
80 | 0 | return (array == NULL || array[0] == NULL); |
81 | 0 | } |
82 | | |
83 | | /* |
84 | | * NSS_CMSArray_Count - count number of elements in array |
85 | | */ |
86 | | int |
87 | | NSS_CMSArray_Count(void **array) |
88 | 0 | { |
89 | 0 | int n = 0; |
90 | 0 |
|
91 | 0 | if (array == NULL) |
92 | 0 | return 0; |
93 | 0 | |
94 | 0 | while (*array++ != NULL) |
95 | 0 | n++; |
96 | 0 |
|
97 | 0 | return n; |
98 | 0 | } |
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 | 0 | { |
115 | 0 | int n, i, limit, lastxchg; |
116 | 0 | void *tmp; |
117 | 0 |
|
118 | 0 | n = NSS_CMSArray_Count(primary); |
119 | 0 |
|
120 | 0 | PORT_Assert(secondary == NULL || NSS_CMSArray_Count(secondary) == n); |
121 | 0 | PORT_Assert(tertiary == NULL || NSS_CMSArray_Count(tertiary) == n); |
122 | 0 |
|
123 | 0 | if (n <= 1) /* ordering is fine */ |
124 | 0 | return; |
125 | 0 | |
126 | 0 | /* yes, ladies and gentlemen, it's BUBBLE SORT TIME! */ |
127 | 0 | limit = n - 1; |
128 | 0 | while (1) { |
129 | 0 | lastxchg = 0; |
130 | 0 | for (i = 0; i < limit; i++) { |
131 | 0 | if ((*compare)(primary[i], primary[i + 1]) > 0) { |
132 | 0 | /* exchange the neighbours */ |
133 | 0 | tmp = primary[i + 1]; |
134 | 0 | primary[i + 1] = primary[i]; |
135 | 0 | primary[i] = tmp; |
136 | 0 | if (secondary) { /* secondary array? */ |
137 | 0 | tmp = secondary[i + 1]; /* exchange there as well */ |
138 | 0 | secondary[i + 1] = secondary[i]; |
139 | 0 | secondary[i] = tmp; |
140 | 0 | } |
141 | 0 | if (tertiary) { /* tertiary array? */ |
142 | 0 | tmp = tertiary[i + 1]; /* exchange there as well */ |
143 | 0 | tertiary[i + 1] = tertiary[i]; |
144 | 0 | tertiary[i] = tmp; |
145 | 0 | } |
146 | 0 | lastxchg = i + 1; /* index of the last element bubbled up */ |
147 | 0 | } |
148 | 0 | } |
149 | 0 | if (lastxchg == 0) /* no exchanges, so array is sorted */ |
150 | 0 | break; /* we're done */ |
151 | 0 | limit = lastxchg; /* array is sorted up to [limit] */ |
152 | 0 | } |
153 | 0 | } |
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 |