1 | /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) |
2 | * All rights reserved. |
3 | * |
4 | * This package is an SSL implementation written |
5 | * by Eric Young (eay@cryptsoft.com). |
6 | * The implementation was written so as to conform with Netscapes SSL. |
7 | * |
8 | * This library is free for commercial and non-commercial use as long as |
9 | * the following conditions are aheared to. The following conditions |
10 | * apply to all code found in this distribution, be it the RC4, RSA, |
11 | * lhash, DES, etc., code; not just the SSL code. The SSL documentation |
12 | * included with this distribution is covered by the same copyright terms |
13 | * except that the holder is Tim Hudson (tjh@cryptsoft.com). |
14 | * |
15 | * Copyright remains Eric Young's, and as such any Copyright notices in |
16 | * the code are not to be removed. |
17 | * If this package is used in a product, Eric Young should be given attribution |
18 | * as the author of the parts of the library used. |
19 | * This can be in the form of a textual message at program startup or |
20 | * in documentation (online or textual) provided with the package. |
21 | * |
22 | * Redistribution and use in source and binary forms, with or without |
23 | * modification, are permitted provided that the following conditions |
24 | * are met: |
25 | * 1. Redistributions of source code must retain the copyright |
26 | * notice, this list of conditions and the following disclaimer. |
27 | * 2. Redistributions in binary form must reproduce the above copyright |
28 | * notice, this list of conditions and the following disclaimer in the |
29 | * documentation and/or other materials provided with the distribution. |
30 | * 3. All advertising materials mentioning features or use of this software |
31 | * must display the following acknowledgement: |
32 | * "This product includes cryptographic software written by |
33 | * Eric Young (eay@cryptsoft.com)" |
34 | * The word 'cryptographic' can be left out if the rouines from the library |
35 | * being used are not cryptographic related :-). |
36 | * 4. If you include any Windows specific code (or a derivative thereof) from |
37 | * the apps directory (application code) you must include an acknowledgement: |
38 | * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" |
39 | * |
40 | * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND |
41 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
42 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
43 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE |
44 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
45 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
46 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
47 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
48 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
49 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
50 | * SUCH DAMAGE. |
51 | * |
52 | * The licence and distribution terms for any publically available version or |
53 | * derivative of this code cannot be changed. i.e. this code cannot simply be |
54 | * copied and put under another distribution licence |
55 | * [including the GNU Public Licence.] */ |
56 | |
57 | #ifndef OPENSSL_HEADER_STACK_H |
58 | #define |
59 | |
60 | #include <openssl/base.h> |
61 | |
62 | #include <openssl/type_check.h> |
63 | |
64 | #if defined(__cplusplus) |
65 | extern "C" { |
66 | #endif |
67 | |
68 | |
69 | // A stack, in OpenSSL, is an array of pointers. They are the most commonly |
70 | // used collection object. |
71 | // |
72 | // This file defines macros for type safe use of the stack functions. A stack |
73 | // of a specific type of object has type |STACK_OF(type)|. This can be defined |
74 | // (once) with |DEFINE_STACK_OF(type)| and declared where needed with |
75 | // |DECLARE_STACK_OF(type)|. For example: |
76 | // |
77 | // typedef struct foo_st { |
78 | // int bar; |
79 | // } FOO; |
80 | // |
81 | // DEFINE_STACK_OF(FOO) |
82 | // |
83 | // Although note that the stack will contain /pointers/ to |FOO|. |
84 | // |
85 | // A macro will be defined for each of the sk_* functions below. For |
86 | // STACK_OF(FOO), the macros would be sk_FOO_new, sk_FOO_pop etc. |
87 | |
88 | |
89 | // stack_free_func is a function that frees an element in a stack. Note its |
90 | // actual type is void (*)(T *) for some T. Low-level |sk_*| functions will be |
91 | // passed a type-specific wrapper to call it correctly. |
92 | typedef void (*stack_free_func)(void *ptr); |
93 | |
94 | // stack_copy_func is a function that copies an element in a stack. Note its |
95 | // actual type is T *(*)(T *) for some T. Low-level |sk_*| functions will be |
96 | // passed a type-specific wrapper to call it correctly. |
97 | typedef void *(*stack_copy_func)(void *ptr); |
98 | |
99 | // stack_cmp_func is a comparison function that returns a value < 0, 0 or > 0 |
100 | // if |*a| is less than, equal to or greater than |*b|, respectively. Note the |
101 | // extra indirection - the function is given a pointer to a pointer to the |
102 | // element. This differs from the usual qsort/bsearch comparison function. |
103 | // |
104 | // Note its actual type is int (*)(const T **, const T **). Low-level |sk_*| |
105 | // functions will be passed a type-specific wrapper to call it correctly. |
106 | typedef int (*stack_cmp_func)(const void **a, const void **b); |
107 | |
108 | // stack_st contains an array of pointers. It is not designed to be used |
109 | // directly, rather the wrapper macros should be used. |
110 | typedef struct stack_st { |
111 | // num contains the number of valid pointers in |data|. |
112 | size_t num; |
113 | void **data; |
114 | // sorted is non-zero if the values pointed to by |data| are in ascending |
115 | // order, based on |comp|. |
116 | int sorted; |
117 | // num_alloc contains the number of pointers allocated in the buffer pointed |
118 | // to by |data|, which may be larger than |num|. |
119 | size_t num_alloc; |
120 | // comp is an optional comparison function. |
121 | stack_cmp_func comp; |
122 | } _STACK; |
123 | |
124 | |
125 | #define STACK_OF(type) struct stack_st_##type |
126 | |
127 | #define DECLARE_STACK_OF(type) STACK_OF(type); |
128 | |
129 | // These are the raw stack functions, you shouldn't be using them. Rather you |
130 | // should be using the type stack macros implemented above. |
131 | |
132 | // sk_new creates a new, empty stack with the given comparison function, which |
133 | // may be zero. It returns the new stack or NULL on allocation failure. |
134 | OPENSSL_EXPORT _STACK *sk_new(stack_cmp_func comp); |
135 | |
136 | // sk_new_null creates a new, empty stack. It returns the new stack or NULL on |
137 | // allocation failure. |
138 | OPENSSL_EXPORT _STACK *sk_new_null(void); |
139 | |
140 | // sk_num returns the number of elements in |s|. |
141 | OPENSSL_EXPORT size_t sk_num(const _STACK *sk); |
142 | |
143 | // sk_zero resets |sk| to the empty state but does nothing to free the |
144 | // individual elements themselves. |
145 | OPENSSL_EXPORT void sk_zero(_STACK *sk); |
146 | |
147 | // sk_value returns the |i|th pointer in |sk|, or NULL if |i| is out of |
148 | // range. |
149 | OPENSSL_EXPORT void *sk_value(const _STACK *sk, size_t i); |
150 | |
151 | // sk_set sets the |i|th pointer in |sk| to |p| and returns |p|. If |i| is out |
152 | // of range, it returns NULL. |
153 | OPENSSL_EXPORT void *sk_set(_STACK *sk, size_t i, void *p); |
154 | |
155 | // sk_free frees the given stack and array of pointers, but does nothing to |
156 | // free the individual elements. Also see |sk_pop_free_ex|. |
157 | OPENSSL_EXPORT void sk_free(_STACK *sk); |
158 | |
159 | // sk_pop_free_ex calls |free_func| on each element in the stack and then frees |
160 | // the stack itself. Note this corresponds to |sk_FOO_pop_free|. It is named |
161 | // |sk_pop_free_ex| as a workaround for existing code calling an older version |
162 | // of |sk_pop_free|. |
163 | OPENSSL_EXPORT void sk_pop_free_ex(_STACK *sk, |
164 | void (*call_free_func)(stack_free_func, |
165 | void *), |
166 | stack_free_func free_func); |
167 | |
168 | // sk_insert inserts |p| into the stack at index |where|, moving existing |
169 | // elements if needed. It returns the length of the new stack, or zero on |
170 | // error. |
171 | OPENSSL_EXPORT size_t sk_insert(_STACK *sk, void *p, size_t where); |
172 | |
173 | // sk_delete removes the pointer at index |where|, moving other elements down |
174 | // if needed. It returns the removed pointer, or NULL if |where| is out of |
175 | // range. |
176 | OPENSSL_EXPORT void *sk_delete(_STACK *sk, size_t where); |
177 | |
178 | // sk_delete_ptr removes, at most, one instance of |p| from the stack based on |
179 | // pointer equality. If an instance of |p| is found then |p| is returned, |
180 | // otherwise it returns NULL. |
181 | OPENSSL_EXPORT void *sk_delete_ptr(_STACK *sk, const void *p); |
182 | |
183 | // sk_find returns the first value in the stack equal to |p|. If a comparison |
184 | // function has been set on the stack, equality is defined by it, otherwise |
185 | // pointer equality is used. If the stack is sorted, then a binary search is |
186 | // used, otherwise a linear search is performed. If a matching element is found, |
187 | // its index is written to |
188 | // |*out_index| (if |out_index| is not NULL) and one is returned. Otherwise zero |
189 | // is returned. |
190 | // |
191 | // Note this differs from OpenSSL. The type signature is slightly different, and |
192 | // OpenSSL's sk_find will implicitly sort |sk| if it has a comparison function |
193 | // defined. |
194 | OPENSSL_EXPORT int sk_find(const _STACK *sk, size_t *out_index, const void *p, |
195 | int (*call_cmp_func)(stack_cmp_func, const void **, |
196 | const void **)); |
197 | |
198 | // sk_shift removes and returns the first element in the stack, or returns NULL |
199 | // if the stack is empty. |
200 | OPENSSL_EXPORT void *sk_shift(_STACK *sk); |
201 | |
202 | // sk_push appends |p| to the stack and returns the length of the new stack, or |
203 | // 0 on allocation failure. |
204 | OPENSSL_EXPORT size_t sk_push(_STACK *sk, void *p); |
205 | |
206 | // sk_pop returns and removes the last element on the stack, or NULL if the |
207 | // stack is empty. |
208 | OPENSSL_EXPORT void *sk_pop(_STACK *sk); |
209 | |
210 | // sk_dup performs a shallow copy of a stack and returns the new stack, or NULL |
211 | // on error. |
212 | OPENSSL_EXPORT _STACK *sk_dup(const _STACK *sk); |
213 | |
214 | // sk_sort sorts the elements of |sk| into ascending order based on the |
215 | // comparison function. The stack maintains a |sorted| flag and sorting an |
216 | // already sorted stack is a no-op. |
217 | OPENSSL_EXPORT void sk_sort(_STACK *sk); |
218 | |
219 | // sk_is_sorted returns one if |sk| is known to be sorted and zero |
220 | // otherwise. |
221 | OPENSSL_EXPORT int sk_is_sorted(const _STACK *sk); |
222 | |
223 | // sk_set_cmp_func sets the comparison function to be used by |sk| and returns |
224 | // the previous one. |
225 | OPENSSL_EXPORT stack_cmp_func sk_set_cmp_func(_STACK *sk, stack_cmp_func comp); |
226 | |
227 | // sk_deep_copy performs a copy of |sk| and of each of the non-NULL elements in |
228 | // |sk| by using |copy_func|. If an error occurs, |free_func| is used to free |
229 | // any copies already made and NULL is returned. |
230 | OPENSSL_EXPORT _STACK *sk_deep_copy( |
231 | const _STACK *sk, void *(*call_copy_func)(stack_copy_func, void *), |
232 | stack_copy_func copy_func, void (*call_free_func)(stack_free_func, void *), |
233 | stack_free_func free_func); |
234 | |
235 | |
236 | // Deprecated functions. |
237 | |
238 | // sk_pop_free behaves like |sk_pop_free_ex| but performs an invalid function |
239 | // pointer cast. It exists because some existing callers called |sk_pop_free| |
240 | // directly. |
241 | // |
242 | // TODO(davidben): Migrate callers to bssl::UniquePtr and remove this. |
243 | OPENSSL_EXPORT void sk_pop_free(_STACK *sk, stack_free_func free_func); |
244 | |
245 | |
246 | // Defining stack types. |
247 | // |
248 | // This set of macros is used to emit the typed functions that act on a |
249 | // |STACK_OF(T)|. |
250 | |
251 | #if !defined(BORINGSSL_NO_CXX) |
252 | extern "C++" { |
253 | BSSL_NAMESPACE_BEGIN |
254 | namespace internal { |
255 | template <typename T> |
256 | struct StackTraits {}; |
257 | } |
258 | BSSL_NAMESPACE_END |
259 | } |
260 | |
261 | #define BORINGSSL_DEFINE_STACK_TRAITS(name, type, is_const) \ |
262 | extern "C++" { \ |
263 | BSSL_NAMESPACE_BEGIN \ |
264 | namespace internal { \ |
265 | template <> \ |
266 | struct StackTraits<STACK_OF(name)> { \ |
267 | static constexpr bool kIsStack = true; \ |
268 | using Type = type; \ |
269 | static constexpr bool kIsConst = is_const; \ |
270 | }; \ |
271 | } \ |
272 | BSSL_NAMESPACE_END \ |
273 | } |
274 | |
275 | #else |
276 | #define BORINGSSL_DEFINE_STACK_TRAITS(name, type, is_const) |
277 | #endif |
278 | |
279 | #define BORINGSSL_DEFINE_STACK_OF_IMPL(name, ptrtype, constptrtype) \ |
280 | DECLARE_STACK_OF(name) \ |
281 | \ |
282 | typedef void (*stack_##name##_free_func)(ptrtype); \ |
283 | typedef ptrtype (*stack_##name##_copy_func)(ptrtype); \ |
284 | typedef int (*stack_##name##_cmp_func)(constptrtype *a, constptrtype *b); \ |
285 | \ |
286 | OPENSSL_INLINE void sk_##name##_call_free_func(stack_free_func free_func, \ |
287 | void *ptr) { \ |
288 | ((stack_##name##_free_func)free_func)((ptrtype)ptr); \ |
289 | } \ |
290 | \ |
291 | OPENSSL_INLINE void *sk_##name##_call_copy_func(stack_copy_func copy_func, \ |
292 | void *ptr) { \ |
293 | return (void *)((stack_##name##_copy_func)copy_func)((ptrtype)ptr); \ |
294 | } \ |
295 | \ |
296 | OPENSSL_INLINE int sk_##name##_call_cmp_func( \ |
297 | stack_cmp_func cmp_func, const void **a, const void **b) { \ |
298 | constptrtype a_ptr = (constptrtype)*a; \ |
299 | constptrtype b_ptr = (constptrtype)*b; \ |
300 | return ((stack_##name##_cmp_func)cmp_func)(&a_ptr, &b_ptr); \ |
301 | } \ |
302 | \ |
303 | OPENSSL_INLINE STACK_OF(name) * \ |
304 | sk_##name##_new(stack_##name##_cmp_func comp) { \ |
305 | return (STACK_OF(name) *)sk_new((stack_cmp_func)comp); \ |
306 | } \ |
307 | \ |
308 | OPENSSL_INLINE STACK_OF(name) *sk_##name##_new_null(void) { \ |
309 | return (STACK_OF(name) *)sk_new_null(); \ |
310 | } \ |
311 | \ |
312 | OPENSSL_INLINE size_t sk_##name##_num(const STACK_OF(name) *sk) { \ |
313 | return sk_num((const _STACK *)sk); \ |
314 | } \ |
315 | \ |
316 | OPENSSL_INLINE void sk_##name##_zero(STACK_OF(name) *sk) { \ |
317 | sk_zero((_STACK *)sk); \ |
318 | } \ |
319 | \ |
320 | OPENSSL_INLINE ptrtype sk_##name##_value(const STACK_OF(name) *sk, \ |
321 | size_t i) { \ |
322 | return (ptrtype)sk_value((const _STACK *)sk, i); \ |
323 | } \ |
324 | \ |
325 | OPENSSL_INLINE ptrtype sk_##name##_set(STACK_OF(name) *sk, size_t i, \ |
326 | ptrtype p) { \ |
327 | return (ptrtype)sk_set((_STACK *)sk, i, (void *)p); \ |
328 | } \ |
329 | \ |
330 | OPENSSL_INLINE void sk_##name##_free(STACK_OF(name) * sk) { \ |
331 | sk_free((_STACK *)sk); \ |
332 | } \ |
333 | \ |
334 | OPENSSL_INLINE void sk_##name##_pop_free( \ |
335 | STACK_OF(name) * sk, stack_##name##_free_func free_func) { \ |
336 | sk_pop_free_ex((_STACK *)sk, sk_##name##_call_free_func, \ |
337 | (stack_free_func)free_func); \ |
338 | } \ |
339 | \ |
340 | OPENSSL_INLINE size_t sk_##name##_insert(STACK_OF(name) *sk, ptrtype p, \ |
341 | size_t where) { \ |
342 | return sk_insert((_STACK *)sk, (void *)p, where); \ |
343 | } \ |
344 | \ |
345 | OPENSSL_INLINE ptrtype sk_##name##_delete(STACK_OF(name) *sk, \ |
346 | size_t where) { \ |
347 | return (ptrtype)sk_delete((_STACK *)sk, where); \ |
348 | } \ |
349 | \ |
350 | OPENSSL_INLINE ptrtype sk_##name##_delete_ptr(STACK_OF(name) *sk, \ |
351 | constptrtype p) { \ |
352 | return (ptrtype)sk_delete_ptr((_STACK *)sk, (const void *)p); \ |
353 | } \ |
354 | \ |
355 | OPENSSL_INLINE int sk_##name##_find(const STACK_OF(name) *sk, \ |
356 | size_t * out_index, constptrtype p) { \ |
357 | return sk_find((const _STACK *)sk, out_index, (const void *)p, \ |
358 | sk_##name##_call_cmp_func); \ |
359 | } \ |
360 | \ |
361 | OPENSSL_INLINE ptrtype sk_##name##_shift(STACK_OF(name) *sk) { \ |
362 | return (ptrtype)sk_shift((_STACK *)sk); \ |
363 | } \ |
364 | \ |
365 | OPENSSL_INLINE size_t sk_##name##_push(STACK_OF(name) *sk, ptrtype p) { \ |
366 | return sk_push((_STACK *)sk, (void *)p); \ |
367 | } \ |
368 | \ |
369 | OPENSSL_INLINE ptrtype sk_##name##_pop(STACK_OF(name) *sk) { \ |
370 | return (ptrtype)sk_pop((_STACK *)sk); \ |
371 | } \ |
372 | \ |
373 | OPENSSL_INLINE STACK_OF(name) * sk_##name##_dup(const STACK_OF(name) *sk) { \ |
374 | return (STACK_OF(name) *)sk_dup((const _STACK *)sk); \ |
375 | } \ |
376 | \ |
377 | OPENSSL_INLINE void sk_##name##_sort(STACK_OF(name) *sk) { \ |
378 | sk_sort((_STACK *)sk); \ |
379 | } \ |
380 | \ |
381 | OPENSSL_INLINE int sk_##name##_is_sorted(const STACK_OF(name) *sk) { \ |
382 | return sk_is_sorted((const _STACK *)sk); \ |
383 | } \ |
384 | \ |
385 | OPENSSL_INLINE stack_##name##_cmp_func sk_##name##_set_cmp_func( \ |
386 | STACK_OF(name) *sk, stack_##name##_cmp_func comp) { \ |
387 | return (stack_##name##_cmp_func)sk_set_cmp_func((_STACK *)sk, \ |
388 | (stack_cmp_func)comp); \ |
389 | } \ |
390 | \ |
391 | OPENSSL_INLINE STACK_OF(name) * \ |
392 | sk_##name##_deep_copy(const STACK_OF(name) *sk, \ |
393 | ptrtype(*copy_func)(ptrtype), \ |
394 | void (*free_func)(ptrtype)) { \ |
395 | return (STACK_OF(name) *)sk_deep_copy( \ |
396 | (const _STACK *)sk, sk_##name##_call_copy_func, \ |
397 | (stack_copy_func)copy_func, sk_##name##_call_free_func, \ |
398 | (stack_free_func)free_func); \ |
399 | } |
400 | |
401 | // DEFINE_NAMED_STACK_OF defines |STACK_OF(name)| to be a stack whose elements |
402 | // are |type| *. |
403 | #define DEFINE_NAMED_STACK_OF(name, type) \ |
404 | BORINGSSL_DEFINE_STACK_OF_IMPL(name, type *, const type *) \ |
405 | BORINGSSL_DEFINE_STACK_TRAITS(name, type, false) |
406 | |
407 | // DEFINE_STACK_OF defines |STACK_OF(type)| to be a stack whose elements are |
408 | // |type| *. |
409 | #define DEFINE_STACK_OF(type) DEFINE_NAMED_STACK_OF(type, type) |
410 | |
411 | // DEFINE_CONST_STACK_OF defines |STACK_OF(type)| to be a stack whose elements |
412 | // are const |type| *. |
413 | #define DEFINE_CONST_STACK_OF(type) \ |
414 | BORINGSSL_DEFINE_STACK_OF_IMPL(type, const type *, const type *) \ |
415 | BORINGSSL_DEFINE_STACK_TRAITS(type, const type, true) |
416 | |
417 | // DEFINE_SPECIAL_STACK_OF defines |STACK_OF(type)| to be a stack whose elements |
418 | // are |type|, where |type| must be a typedef for a pointer. |
419 | #define DEFINE_SPECIAL_STACK_OF(type) \ |
420 | OPENSSL_STATIC_ASSERT(sizeof(type) == sizeof(void *), \ |
421 | #type " is not a pointer"); \ |
422 | BORINGSSL_DEFINE_STACK_OF_IMPL(type, type, const type) |
423 | |
424 | |
425 | typedef char *OPENSSL_STRING; |
426 | |
427 | DEFINE_STACK_OF(void) |
428 | DEFINE_SPECIAL_STACK_OF(OPENSSL_STRING) |
429 | |
430 | |
431 | #if defined(__cplusplus) |
432 | } // extern C |
433 | #endif |
434 | |
435 | #if !defined(BORINGSSL_NO_CXX) |
436 | extern "C++" { |
437 | |
438 | #include <type_traits> |
439 | |
440 | BSSL_NAMESPACE_BEGIN |
441 | |
442 | namespace internal { |
443 | |
444 | // Stacks defined with |DEFINE_CONST_STACK_OF| are freed with |sk_free|. |
445 | template <typename Stack> |
446 | struct DeleterImpl< |
447 | Stack, typename std::enable_if<StackTraits<Stack>::kIsConst>::type> { |
448 | static void Free(Stack *sk) { sk_free(reinterpret_cast<_STACK *>(sk)); } |
449 | }; |
450 | |
451 | // Stacks defined with |DEFINE_STACK_OF| are freed with |sk_pop_free| and the |
452 | // corresponding type's deleter. |
453 | template <typename Stack> |
454 | struct DeleterImpl< |
455 | Stack, typename std::enable_if<!StackTraits<Stack>::kIsConst>::type> { |
456 | static void Free(Stack *sk) { |
457 | // sk_FOO_pop_free is defined by macros and bound by name, so we cannot |
458 | // access it from C++ here. |
459 | using Type = typename StackTraits<Stack>::Type; |
460 | sk_pop_free_ex(reinterpret_cast<_STACK *>(sk), |
461 | [](stack_free_func /* unused */, void *ptr) { |
462 | DeleterImpl<Type>::Free(reinterpret_cast<Type *>(ptr)); |
463 | }, |
464 | nullptr); |
465 | } |
466 | }; |
467 | |
468 | template <typename Stack> |
469 | class StackIteratorImpl { |
470 | public: |
471 | using Type = typename StackTraits<Stack>::Type; |
472 | // Iterators must be default-constructable. |
473 | StackIteratorImpl() : sk_(nullptr), idx_(0) {} |
474 | StackIteratorImpl(const Stack *sk, size_t idx) : sk_(sk), idx_(idx) {} |
475 | |
476 | bool operator==(StackIteratorImpl other) const { |
477 | return sk_ == other.sk_ && idx_ == other.idx_; |
478 | } |
479 | bool operator!=(StackIteratorImpl other) const { |
480 | return !(*this == other); |
481 | } |
482 | |
483 | Type *operator*() const { |
484 | return reinterpret_cast<Type *>( |
485 | sk_value(reinterpret_cast<const _STACK *>(sk_), idx_)); |
486 | } |
487 | |
488 | StackIteratorImpl &operator++(/* prefix */) { |
489 | idx_++; |
490 | return *this; |
491 | } |
492 | |
493 | StackIteratorImpl operator++(int /* postfix */) { |
494 | StackIteratorImpl copy(*this); |
495 | ++(*this); |
496 | return copy; |
497 | } |
498 | |
499 | private: |
500 | const Stack *sk_; |
501 | size_t idx_; |
502 | }; |
503 | |
504 | template <typename Stack> |
505 | using StackIterator = typename std::enable_if<StackTraits<Stack>::kIsStack, |
506 | StackIteratorImpl<Stack>>::type; |
507 | |
508 | } // namespace internal |
509 | |
510 | // PushToStack pushes |elem| to |sk|. It returns true on success and false on |
511 | // allocation failure. |
512 | template <typename Stack> |
513 | inline |
514 | typename std::enable_if<!internal::StackTraits<Stack>::kIsConst, bool>::type |
515 | PushToStack(Stack *sk, |
516 | UniquePtr<typename internal::StackTraits<Stack>::Type> elem) { |
517 | if (!sk_push(reinterpret_cast<_STACK *>(sk), elem.get())) { |
518 | return false; |
519 | } |
520 | // sk_push takes ownership on success. |
521 | elem.release(); |
522 | return true; |
523 | } |
524 | |
525 | BSSL_NAMESPACE_END |
526 | |
527 | // Define begin() and end() for stack types so C++ range for loops work. |
528 | template <typename Stack> |
529 | inline bssl::internal::StackIterator<Stack> begin(const Stack *sk) { |
530 | return bssl::internal::StackIterator<Stack>(sk, 0); |
531 | } |
532 | |
533 | template <typename Stack> |
534 | inline bssl::internal::StackIterator<Stack> end(const Stack *sk) { |
535 | return bssl::internal::StackIterator<Stack>( |
536 | sk, sk_num(reinterpret_cast<const _STACK *>(sk))); |
537 | } |
538 | |
539 | } // extern C++ |
540 | #endif |
541 | |
542 | #endif // OPENSSL_HEADER_STACK_H |
543 | |