Adam Langley | 95c29f3 | 2014-06-20 12:00:00 -0700 | [diff] [blame] | 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 OPENSSL_HEADER_STACK_H |
| 59 | |
| 60 | #include <openssl/base.h> |
| 61 | |
Adam Langley | 95c29f3 | 2014-06-20 12:00:00 -0700 | [diff] [blame] | 62 | #if defined(__cplusplus) |
| 63 | extern "C" { |
| 64 | #endif |
| 65 | |
| 66 | |
David Benjamin | 4512b79 | 2017-08-18 19:21:50 -0400 | [diff] [blame] | 67 | // A stack, in OpenSSL, is an array of pointers. They are the most commonly |
| 68 | // used collection object. |
| 69 | // |
David Benjamin | 7f857ea | 2022-06-13 11:47:31 -0400 | [diff] [blame] | 70 | // This file defines macros for type-safe use of the stack functions. A stack |
| 71 | // type is named like |STACK_OF(FOO)| and is accessed with functions named |
| 72 | // like |sk_FOO_*|. Note the stack will typically contain /pointers/ to |FOO|. |
David Benjamin | 4512b79 | 2017-08-18 19:21:50 -0400 | [diff] [blame] | 73 | // |
David Benjamin | 7f857ea | 2022-06-13 11:47:31 -0400 | [diff] [blame] | 74 | // The |DECLARE_STACK_OF| macro makes |STACK_OF(FOO)| available, and |
| 75 | // |DEFINE_STACK_OF| makes the corresponding functions available. |
Adam Langley | 95c29f3 | 2014-06-20 12:00:00 -0700 | [diff] [blame] | 76 | |
| 77 | |
David Benjamin | 7f857ea | 2022-06-13 11:47:31 -0400 | [diff] [blame] | 78 | // Defining stacks. |
| 79 | |
| 80 | // STACK_OF expands to the stack type for |type|. |
| 81 | #define STACK_OF(type) struct stack_st_##type |
| 82 | |
| 83 | // DECLARE_STACK_OF declares the |STACK_OF(type)| type. It does not make the |
| 84 | // corresponding |sk_type_*| functions available. This macro should be used in |
| 85 | // files which only need the type. |
| 86 | #define DECLARE_STACK_OF(type) STACK_OF(type); |
| 87 | |
| 88 | // DEFINE_NAMED_STACK_OF defines |STACK_OF(name)| to be a stack whose elements |
| 89 | // are |type| *. This macro makes the |sk_name_*| functions available. |
| 90 | // |
| 91 | // It is not necessary to use |DECLARE_STACK_OF| in files which use this macro. |
| 92 | #define DEFINE_NAMED_STACK_OF(name, type) \ |
| 93 | BORINGSSL_DEFINE_STACK_OF_IMPL(name, type *, const type *) \ |
| 94 | BORINGSSL_DEFINE_STACK_TRAITS(name, type, false) |
| 95 | |
| 96 | // DEFINE_STACK_OF defines |STACK_OF(type)| to be a stack whose elements are |
| 97 | // |type| *. This macro makes the |sk_type_*| functions available. |
| 98 | // |
| 99 | // It is not necessary to use |DECLARE_STACK_OF| in files which use this macro. |
| 100 | #define DEFINE_STACK_OF(type) DEFINE_NAMED_STACK_OF(type, type) |
| 101 | |
| 102 | // DEFINE_CONST_STACK_OF defines |STACK_OF(type)| to be a stack whose elements |
| 103 | // are const |type| *. This macro makes the |sk_type_*| functions available. |
| 104 | // |
| 105 | // It is not necessary to use |DECLARE_STACK_OF| in files which use this macro. |
| 106 | #define DEFINE_CONST_STACK_OF(type) \ |
| 107 | BORINGSSL_DEFINE_STACK_OF_IMPL(type, const type *, const type *) \ |
| 108 | BORINGSSL_DEFINE_STACK_TRAITS(type, const type, true) |
| 109 | |
| 110 | |
| 111 | // Using stacks. |
| 112 | // |
| 113 | // After the |DEFINE_STACK_OF| macro is used, the following functions are |
| 114 | // available. |
| 115 | |
| 116 | #if 0 // Sample |
| 117 | |
| 118 | // sk_SAMPLE_free_func is a callback to free an element in a stack. |
| 119 | typedef void (*sk_SAMPLE_free_func)(SAMPLE *); |
| 120 | |
| 121 | // sk_SAMPLE_copy_func is a callback to copy an element in a stack. It should |
| 122 | // return the copy or NULL on error. |
David Benjamin | df8a55b | 2023-01-04 15:52:36 -0800 | [diff] [blame] | 123 | typedef SAMPLE *(*sk_SAMPLE_copy_func)(const SAMPLE *); |
David Benjamin | 7f857ea | 2022-06-13 11:47:31 -0400 | [diff] [blame] | 124 | |
| 125 | // sk_SAMPLE_cmp_func is a callback to compare |*a| to |*b|. It should return a |
| 126 | // value < 0, 0, or > 0 if |*a| is less than, equal to, or greater than |*b|, |
| 127 | // respectively. Note the extra indirection - the function is given a pointer |
| 128 | // to a pointer to the element. This is the |qsort|/|bsearch| comparison |
| 129 | // function applied to an array of |SAMPLE*|. |
| 130 | // |
| 131 | // TODO(https://crbug.com/boringssl/498): The parameters should be |
| 132 | // |const SAMPLE *const *|. |
| 133 | typedef int (*sk_SAMPLE_cmp_func)(const SAMPLE **a, const SAMPLE **b); |
| 134 | |
| 135 | // sk_SAMPLE_new creates a new, empty stack with the given comparison function, |
| 136 | // which may be NULL. It returns the new stack or NULL on allocation failure. |
| 137 | STACK_OF(SAMPLE) *sk_SAMPLE_new(sk_SAMPLE_cmp_func comp); |
| 138 | |
| 139 | // sk_SAMPLE_new_null creates a new, empty stack. It returns the new stack or |
| 140 | // NULL on allocation failure. |
| 141 | STACK_OF(SAMPLE) *sk_SAMPLE_new_null(void); |
| 142 | |
| 143 | // sk_SAMPLE_num returns the number of elements in |sk|. |
| 144 | size_t sk_SAMPLE_num(const STACK_OF(SAMPLE) *sk); |
| 145 | |
| 146 | // sk_SAMPLE_zero resets |sk| to the empty state but does nothing to free the |
| 147 | // individual elements themselves. |
| 148 | void sk_SAMPLE_zero(STACK_OF(SAMPLE) *sk); |
| 149 | |
| 150 | // sk_SAMPLE_value returns the |i|th pointer in |sk|, or NULL if |i| is out of |
| 151 | // range. |
| 152 | SAMPLE *sk_SAMPLE_value(const STACK_OF(SAMPLE) *sk, size_t i); |
| 153 | |
| 154 | // sk_SAMPLE_set sets the |i|th pointer in |sk| to |p| and returns |p|. If |i| |
| 155 | // is out of range, it returns NULL. |
| 156 | SAMPLE *sk_SAMPLE_set(STACK_OF(SAMPLE) *sk, size_t i, SAMPLE *p); |
| 157 | |
| 158 | // sk_SAMPLE_free frees |sk|, but does nothing to free the individual elements. |
| 159 | // Use |sk_SAMPLE_pop_free| to also free the elements. |
| 160 | void sk_SAMPLE_free(STACK_OF(SAMPLE) *sk); |
| 161 | |
| 162 | // sk_SAMPLE_pop_free calls |free_func| on each element in |sk| and then |
| 163 | // frees the stack itself. |
| 164 | void sk_SAMPLE_pop_free(STACK_OF(SAMPLE) *sk, sk_SAMPLE_free_func free_func); |
| 165 | |
| 166 | // sk_SAMPLE_insert inserts |p| into the stack at index |where|, moving existing |
| 167 | // elements if needed. It returns the length of the new stack, or zero on |
| 168 | // error. |
| 169 | size_t sk_SAMPLE_insert(STACK_OF(SAMPLE) *sk, SAMPLE *p, size_t where); |
| 170 | |
| 171 | // sk_SAMPLE_delete removes the pointer at index |where|, moving other elements |
| 172 | // down if needed. It returns the removed pointer, or NULL if |where| is out of |
| 173 | // range. |
| 174 | SAMPLE *sk_SAMPLE_delete(STACK_OF(SAMPLE) *sk, size_t where); |
| 175 | |
| 176 | // sk_SAMPLE_delete_ptr removes, at most, one instance of |p| from |sk| based on |
| 177 | // pointer equality. If an instance of |p| is found then |p| is returned, |
| 178 | // otherwise it returns NULL. |
| 179 | SAMPLE *sk_SAMPLE_delete_ptr(STACK_OF(SAMPLE) *sk, const SAMPLE *p); |
| 180 | |
David Benjamin | 49e0791 | 2022-12-26 10:41:26 -0500 | [diff] [blame] | 181 | // sk_SAMPLE_delete_if_func is the callback function for |sk_SAMPLE_delete_if|. |
| 182 | // It should return one to remove |p| and zero to keep it. |
| 183 | typedef int (*sk_SAMPLE_delete_if_func)(SAMPLE *p, void *data); |
| 184 | |
| 185 | // sk_SAMPLE_delete_if calls |func| with each element of |sk| and removes the |
| 186 | // entries where |func| returned one. This function does not free or return |
| 187 | // removed pointers so, if |sk| owns its contents, |func| should release the |
| 188 | // pointers prior to returning one. |
| 189 | void sk_SAMPLE_delete_if(STACK_OF(SAMPLE) *sk, sk_SAMPLE_delete_if_func func, |
| 190 | void *data); |
| 191 | |
David Benjamin | 7f857ea | 2022-06-13 11:47:31 -0400 | [diff] [blame] | 192 | // sk_SAMPLE_find find the first value in |sk| equal to |p|. |sk|'s comparison |
| 193 | // function determines equality, or pointer equality if |sk| has no comparison |
| 194 | // function. |
| 195 | // |
| 196 | // If the stack is sorted (see |sk_SAMPLE_sort|), this function uses a binary |
| 197 | // search. Otherwise it performs a linear search. If it finds a matching |
| 198 | // element, it writes the index to |*out_index| (if |out_index| is not NULL) and |
| 199 | // returns one. Otherwise, it returns zero. |
| 200 | // |
| 201 | // Note this differs from OpenSSL. The type signature is slightly different, and |
| 202 | // OpenSSL's version will implicitly sort |sk| if it has a comparison function |
| 203 | // defined. |
| 204 | int sk_SAMPLE_find(const STACK_OF(SAMPLE) *sk, size_t *out_index, |
| 205 | const SAMPLE *p); |
| 206 | |
| 207 | // sk_SAMPLE_shift removes and returns the first element in |sk|, or NULL if |
| 208 | // |sk| is empty. |
| 209 | SAMPLE *sk_SAMPLE_shift(STACK_OF(SAMPLE) *sk); |
| 210 | |
| 211 | // sk_SAMPLE_push appends |p| to |sk| and returns the length of the new stack, |
| 212 | // or 0 on allocation failure. |
| 213 | size_t sk_SAMPLE_push(STACK_OF(SAMPLE) *sk, SAMPLE *p); |
| 214 | |
| 215 | // sk_SAMPLE_pop removes and returns the last element of |sk|, or NULL if |sk| |
| 216 | // is empty. |
| 217 | SAMPLE *sk_SAMPLE_pop(STACK_OF(SAMPLE) *sk); |
| 218 | |
| 219 | // sk_SAMPLE_dup performs a shallow copy of a stack and returns the new stack, |
| 220 | // or NULL on error. Use |sk_SAMPLE_deep_copy| to also copy the elements. |
| 221 | STACK_OF(SAMPLE) *sk_SAMPLE_dup(const STACK_OF(SAMPLE) *sk); |
| 222 | |
| 223 | // sk_SAMPLE_sort sorts the elements of |sk| into ascending order based on the |
| 224 | // comparison function. The stack maintains a "sorted" flag and sorting an |
| 225 | // already sorted stack is a no-op. |
| 226 | void sk_SAMPLE_sort(STACK_OF(SAMPLE) *sk); |
| 227 | |
| 228 | // sk_SAMPLE_is_sorted returns one if |sk| is known to be sorted and zero |
| 229 | // otherwise. |
| 230 | int sk_SAMPLE_is_sorted(const STACK_OF(SAMPLE) *sk); |
| 231 | |
| 232 | // sk_SAMPLE_set_cmp_func sets the comparison function to be used by |sk| and |
| 233 | // returns the previous one. |
| 234 | sk_SAMPLE_cmp_func sk_SAMPLE_set_cmp_func(STACK_OF(SAMPLE) *sk, |
| 235 | sk_SAMPLE_cmp_func comp); |
| 236 | |
| 237 | // sk_SAMPLE_deep_copy performs a copy of |sk| and of each of the non-NULL |
| 238 | // elements in |sk| by using |copy_func|. If an error occurs, it calls |
| 239 | // |free_func| to free any copies already made and returns NULL. |
| 240 | STACK_OF(SAMPLE) *sk_SAMPLE_deep_copy(const STACK_OF(SAMPLE) *sk, |
| 241 | sk_SAMPLE_copy_func copy_func, |
| 242 | sk_SAMPLE_free_func free_func); |
| 243 | |
| 244 | #endif // Sample |
| 245 | |
| 246 | |
| 247 | // Private functions. |
| 248 | // |
| 249 | // TODO(https://crbug.com/boringssl/499): Rename to |OPENSSL_sk_foo|, after |
| 250 | // external code that calls them is fixed. |
| 251 | |
| 252 | // OPENSSL_sk_free_func is a function that frees an element in a stack. Note its |
David Benjamin | fb4e2e0 | 2018-09-23 15:59:51 -0500 | [diff] [blame] | 253 | // actual type is void (*)(T *) for some T. Low-level |sk_*| functions will be |
| 254 | // passed a type-specific wrapper to call it correctly. |
David Benjamin | 7f857ea | 2022-06-13 11:47:31 -0400 | [diff] [blame] | 255 | typedef void (*OPENSSL_sk_free_func)(void *ptr); |
David Benjamin | fb4e2e0 | 2018-09-23 15:59:51 -0500 | [diff] [blame] | 256 | |
David Benjamin | 7f857ea | 2022-06-13 11:47:31 -0400 | [diff] [blame] | 257 | // OPENSSL_sk_copy_func is a function that copies an element in a stack. Note |
David Benjamin | df8a55b | 2023-01-04 15:52:36 -0800 | [diff] [blame] | 258 | // its actual type is T *(*)(const T *) for some T. Low-level |sk_*| functions |
| 259 | // will be passed a type-specific wrapper to call it correctly. |
| 260 | typedef void *(*OPENSSL_sk_copy_func)(const void *ptr); |
David Benjamin | fb4e2e0 | 2018-09-23 15:59:51 -0500 | [diff] [blame] | 261 | |
David Benjamin | 7f857ea | 2022-06-13 11:47:31 -0400 | [diff] [blame] | 262 | // OPENSSL_sk_cmp_func is a comparison function that returns a value < 0, 0 or > |
| 263 | // 0 if |*a| is less than, equal to or greater than |*b|, respectively. Note |
| 264 | // the extra indirection - the function is given a pointer to a pointer to the |
David Benjamin | 4512b79 | 2017-08-18 19:21:50 -0400 | [diff] [blame] | 265 | // element. This differs from the usual qsort/bsearch comparison function. |
David Benjamin | 5248399 | 2018-09-23 16:31:03 -0500 | [diff] [blame] | 266 | // |
David Benjamin | 167f176 | 2022-06-12 13:47:08 -0400 | [diff] [blame] | 267 | // Note its actual type is |int (*)(const T **a, const T **b)|. Low-level |sk_*| |
David Benjamin | 5248399 | 2018-09-23 16:31:03 -0500 | [diff] [blame] | 268 | // functions will be passed a type-specific wrapper to call it correctly. |
David Benjamin | 167f176 | 2022-06-12 13:47:08 -0400 | [diff] [blame] | 269 | // |
David Benjamin | ff23b7c | 2022-12-27 00:21:35 -0500 | [diff] [blame] | 270 | // TODO(https://crbug.com/boringssl/498): This type should be |
| 271 | // |const T *const *|. It is already fixed in OpenSSL 1.1.1, so hopefully we can |
| 272 | // fix this compatibly. |
David Benjamin | 7f857ea | 2022-06-13 11:47:31 -0400 | [diff] [blame] | 273 | typedef int (*OPENSSL_sk_cmp_func)(const void **a, const void **b); |
Adam Langley | 95c29f3 | 2014-06-20 12:00:00 -0700 | [diff] [blame] | 274 | |
David Benjamin | 49e0791 | 2022-12-26 10:41:26 -0500 | [diff] [blame] | 275 | // OPENSSL_sk_delete_if_func is the generic version of |
| 276 | // |sk_SAMPLE_delete_if_func|. |
| 277 | typedef int (*OPENSSL_sk_delete_if_func)(void *obj, void *data); |
| 278 | |
David Benjamin | 167f176 | 2022-06-12 13:47:08 -0400 | [diff] [blame] | 279 | // The following function types call the above type-erased signatures with the |
| 280 | // true types. |
David Benjamin | 7f857ea | 2022-06-13 11:47:31 -0400 | [diff] [blame] | 281 | typedef void (*OPENSSL_sk_call_free_func)(OPENSSL_sk_free_func, void *); |
David Benjamin | df8a55b | 2023-01-04 15:52:36 -0800 | [diff] [blame] | 282 | typedef void *(*OPENSSL_sk_call_copy_func)(OPENSSL_sk_copy_func, const void *); |
David Benjamin | 7f857ea | 2022-06-13 11:47:31 -0400 | [diff] [blame] | 283 | typedef int (*OPENSSL_sk_call_cmp_func)(OPENSSL_sk_cmp_func, |
| 284 | const void *const *, |
| 285 | const void *const *); |
David Benjamin | 49e0791 | 2022-12-26 10:41:26 -0500 | [diff] [blame] | 286 | typedef int (*OPENSSL_sk_call_delete_if_func)(OPENSSL_sk_delete_if_func, void *, |
| 287 | void *); |
David Benjamin | 167f176 | 2022-06-12 13:47:08 -0400 | [diff] [blame] | 288 | |
David Benjamin | 4512b79 | 2017-08-18 19:21:50 -0400 | [diff] [blame] | 289 | // stack_st contains an array of pointers. It is not designed to be used |
| 290 | // directly, rather the wrapper macros should be used. |
Adam Langley | 95c29f3 | 2014-06-20 12:00:00 -0700 | [diff] [blame] | 291 | typedef struct stack_st { |
David Benjamin | 4512b79 | 2017-08-18 19:21:50 -0400 | [diff] [blame] | 292 | // num contains the number of valid pointers in |data|. |
Adam Langley | 95c29f3 | 2014-06-20 12:00:00 -0700 | [diff] [blame] | 293 | size_t num; |
| 294 | void **data; |
David Benjamin | 4512b79 | 2017-08-18 19:21:50 -0400 | [diff] [blame] | 295 | // sorted is non-zero if the values pointed to by |data| are in ascending |
| 296 | // order, based on |comp|. |
David Benjamin | 22edd87 | 2016-08-04 21:38:40 +0000 | [diff] [blame] | 297 | int sorted; |
David Benjamin | 4512b79 | 2017-08-18 19:21:50 -0400 | [diff] [blame] | 298 | // num_alloc contains the number of pointers allocated in the buffer pointed |
| 299 | // to by |data|, which may be larger than |num|. |
Adam Langley | 95c29f3 | 2014-06-20 12:00:00 -0700 | [diff] [blame] | 300 | size_t num_alloc; |
David Benjamin | 4512b79 | 2017-08-18 19:21:50 -0400 | [diff] [blame] | 301 | // comp is an optional comparison function. |
David Benjamin | 7f857ea | 2022-06-13 11:47:31 -0400 | [diff] [blame] | 302 | OPENSSL_sk_cmp_func comp; |
Adam Langley | 95c29f3 | 2014-06-20 12:00:00 -0700 | [diff] [blame] | 303 | } _STACK; |
| 304 | |
David Benjamin | 7f857ea | 2022-06-13 11:47:31 -0400 | [diff] [blame] | 305 | // The following are raw stack functions. They implement the corresponding typed |
| 306 | // |sk_SAMPLE_*| functions generated by |DEFINE_STACK_OF|. Callers shouldn't be |
| 307 | // using them. Rather, callers should use the typed functions. |
| 308 | OPENSSL_EXPORT _STACK *sk_new(OPENSSL_sk_cmp_func comp); |
Adam Langley | eb7d2ed | 2014-07-30 16:02:14 -0700 | [diff] [blame] | 309 | OPENSSL_EXPORT _STACK *sk_new_null(void); |
Adam Langley | eb7d2ed | 2014-07-30 16:02:14 -0700 | [diff] [blame] | 310 | OPENSSL_EXPORT size_t sk_num(const _STACK *sk); |
Adam Langley | eb7d2ed | 2014-07-30 16:02:14 -0700 | [diff] [blame] | 311 | OPENSSL_EXPORT void sk_zero(_STACK *sk); |
Adam Langley | eb7d2ed | 2014-07-30 16:02:14 -0700 | [diff] [blame] | 312 | OPENSSL_EXPORT void *sk_value(const _STACK *sk, size_t i); |
Adam Langley | eb7d2ed | 2014-07-30 16:02:14 -0700 | [diff] [blame] | 313 | OPENSSL_EXPORT void *sk_set(_STACK *sk, size_t i, void *p); |
Adam Langley | eb7d2ed | 2014-07-30 16:02:14 -0700 | [diff] [blame] | 314 | OPENSSL_EXPORT void sk_free(_STACK *sk); |
David Benjamin | fb4e2e0 | 2018-09-23 15:59:51 -0500 | [diff] [blame] | 315 | OPENSSL_EXPORT void sk_pop_free_ex(_STACK *sk, |
David Benjamin | 7f857ea | 2022-06-13 11:47:31 -0400 | [diff] [blame] | 316 | OPENSSL_sk_call_free_func call_free_func, |
| 317 | OPENSSL_sk_free_func free_func); |
Adam Langley | eb7d2ed | 2014-07-30 16:02:14 -0700 | [diff] [blame] | 318 | OPENSSL_EXPORT size_t sk_insert(_STACK *sk, void *p, size_t where); |
Adam Langley | eb7d2ed | 2014-07-30 16:02:14 -0700 | [diff] [blame] | 319 | OPENSSL_EXPORT void *sk_delete(_STACK *sk, size_t where); |
David Benjamin | 8d2f4b9 | 2018-09-23 15:11:41 -0500 | [diff] [blame] | 320 | OPENSSL_EXPORT void *sk_delete_ptr(_STACK *sk, const void *p); |
David Benjamin | 49e0791 | 2022-12-26 10:41:26 -0500 | [diff] [blame] | 321 | OPENSSL_EXPORT void sk_delete_if(_STACK *sk, |
| 322 | OPENSSL_sk_call_delete_if_func call_func, |
| 323 | OPENSSL_sk_delete_if_func func, void *data); |
David Benjamin | 5248399 | 2018-09-23 16:31:03 -0500 | [diff] [blame] | 324 | OPENSSL_EXPORT int sk_find(const _STACK *sk, size_t *out_index, const void *p, |
David Benjamin | 7f857ea | 2022-06-13 11:47:31 -0400 | [diff] [blame] | 325 | OPENSSL_sk_call_cmp_func call_cmp_func); |
Adam Langley | eb7d2ed | 2014-07-30 16:02:14 -0700 | [diff] [blame] | 326 | OPENSSL_EXPORT void *sk_shift(_STACK *sk); |
Adam Langley | eb7d2ed | 2014-07-30 16:02:14 -0700 | [diff] [blame] | 327 | OPENSSL_EXPORT size_t sk_push(_STACK *sk, void *p); |
Adam Langley | eb7d2ed | 2014-07-30 16:02:14 -0700 | [diff] [blame] | 328 | OPENSSL_EXPORT void *sk_pop(_STACK *sk); |
Adam Langley | eb7d2ed | 2014-07-30 16:02:14 -0700 | [diff] [blame] | 329 | OPENSSL_EXPORT _STACK *sk_dup(const _STACK *sk); |
David Benjamin | 7f857ea | 2022-06-13 11:47:31 -0400 | [diff] [blame] | 330 | OPENSSL_EXPORT void sk_sort(_STACK *sk, OPENSSL_sk_call_cmp_func call_cmp_func); |
Adam Langley | eb7d2ed | 2014-07-30 16:02:14 -0700 | [diff] [blame] | 331 | OPENSSL_EXPORT int sk_is_sorted(const _STACK *sk); |
David Benjamin | 7f857ea | 2022-06-13 11:47:31 -0400 | [diff] [blame] | 332 | OPENSSL_EXPORT OPENSSL_sk_cmp_func sk_set_cmp_func(_STACK *sk, |
| 333 | OPENSSL_sk_cmp_func comp); |
David Benjamin | 167f176 | 2022-06-12 13:47:08 -0400 | [diff] [blame] | 334 | OPENSSL_EXPORT _STACK *sk_deep_copy(const _STACK *sk, |
David Benjamin | 7f857ea | 2022-06-13 11:47:31 -0400 | [diff] [blame] | 335 | OPENSSL_sk_call_copy_func call_copy_func, |
| 336 | OPENSSL_sk_copy_func copy_func, |
| 337 | OPENSSL_sk_call_free_func call_free_func, |
| 338 | OPENSSL_sk_free_func free_func); |
David Benjamin | fb4e2e0 | 2018-09-23 15:59:51 -0500 | [diff] [blame] | 339 | |
| 340 | // sk_pop_free behaves like |sk_pop_free_ex| but performs an invalid function |
| 341 | // pointer cast. It exists because some existing callers called |sk_pop_free| |
| 342 | // directly. |
| 343 | // |
| 344 | // TODO(davidben): Migrate callers to bssl::UniquePtr and remove this. |
David Benjamin | 7f857ea | 2022-06-13 11:47:31 -0400 | [diff] [blame] | 345 | OPENSSL_EXPORT void sk_pop_free(_STACK *sk, OPENSSL_sk_free_func free_func); |
David Benjamin | 01f8a8c | 2017-04-15 18:12:55 -0400 | [diff] [blame] | 346 | |
David Benjamin | 0121953 | 2017-07-25 22:33:06 -0400 | [diff] [blame] | 347 | #if !defined(BORINGSSL_NO_CXX) |
| 348 | extern "C++" { |
Joshua Liebow-Feeser | 8c7c635 | 2018-08-26 18:53:36 -0700 | [diff] [blame] | 349 | BSSL_NAMESPACE_BEGIN |
David Benjamin | 0121953 | 2017-07-25 22:33:06 -0400 | [diff] [blame] | 350 | namespace internal { |
| 351 | template <typename T> |
| 352 | struct StackTraits {}; |
| 353 | } |
Joshua Liebow-Feeser | 8c7c635 | 2018-08-26 18:53:36 -0700 | [diff] [blame] | 354 | BSSL_NAMESPACE_END |
David Benjamin | 0121953 | 2017-07-25 22:33:06 -0400 | [diff] [blame] | 355 | } |
| 356 | |
David Benjamin | ec78383 | 2017-07-25 23:23:03 -0400 | [diff] [blame] | 357 | #define BORINGSSL_DEFINE_STACK_TRAITS(name, type, is_const) \ |
| 358 | extern "C++" { \ |
Joshua Liebow-Feeser | 8c7c635 | 2018-08-26 18:53:36 -0700 | [diff] [blame] | 359 | BSSL_NAMESPACE_BEGIN \ |
David Benjamin | ec78383 | 2017-07-25 23:23:03 -0400 | [diff] [blame] | 360 | namespace internal { \ |
| 361 | template <> \ |
| 362 | struct StackTraits<STACK_OF(name)> { \ |
| 363 | static constexpr bool kIsStack = true; \ |
| 364 | using Type = type; \ |
| 365 | static constexpr bool kIsConst = is_const; \ |
| 366 | }; \ |
| 367 | } \ |
Joshua Liebow-Feeser | 8c7c635 | 2018-08-26 18:53:36 -0700 | [diff] [blame] | 368 | BSSL_NAMESPACE_END \ |
David Benjamin | 0121953 | 2017-07-25 22:33:06 -0400 | [diff] [blame] | 369 | } |
| 370 | |
| 371 | #else |
David Benjamin | ec78383 | 2017-07-25 23:23:03 -0400 | [diff] [blame] | 372 | #define BORINGSSL_DEFINE_STACK_TRAITS(name, type, is_const) |
David Benjamin | 0121953 | 2017-07-25 22:33:06 -0400 | [diff] [blame] | 373 | #endif |
| 374 | |
David Benjamin | 7f857ea | 2022-06-13 11:47:31 -0400 | [diff] [blame] | 375 | #define BORINGSSL_DEFINE_STACK_OF_IMPL(name, ptrtype, constptrtype) \ |
| 376 | /* We disable MSVC C4191 in this macro, which warns when pointers are cast \ |
| 377 | * to the wrong type. While the cast itself is valid, it is often a bug \ |
| 378 | * because calling it through the cast is UB. However, we never actually \ |
| 379 | * call functions as |OPENSSL_sk_cmp_func|. The type is just a type-erased \ |
| 380 | * function pointer. (C does not guarantee function pointers fit in \ |
| 381 | * |void*|, and GCC will warn on this.) Thus we just disable the false \ |
| 382 | * positive warning. */ \ |
| 383 | OPENSSL_MSVC_PRAGMA(warning(push)) \ |
| 384 | OPENSSL_MSVC_PRAGMA(warning(disable : 4191)) \ |
| 385 | \ |
| 386 | DECLARE_STACK_OF(name) \ |
| 387 | \ |
| 388 | typedef void (*sk_##name##_free_func)(ptrtype); \ |
David Benjamin | df8a55b | 2023-01-04 15:52:36 -0800 | [diff] [blame] | 389 | typedef ptrtype (*sk_##name##_copy_func)(constptrtype); \ |
David Benjamin | 49e0791 | 2022-12-26 10:41:26 -0500 | [diff] [blame] | 390 | typedef int (*sk_##name##_cmp_func)(constptrtype *, constptrtype *); \ |
| 391 | typedef int (*sk_##name##_delete_if_func)(ptrtype, void *); \ |
David Benjamin | 7f857ea | 2022-06-13 11:47:31 -0400 | [diff] [blame] | 392 | \ |
| 393 | OPENSSL_INLINE void sk_##name##_call_free_func( \ |
| 394 | OPENSSL_sk_free_func free_func, void *ptr) { \ |
| 395 | ((sk_##name##_free_func)free_func)((ptrtype)ptr); \ |
| 396 | } \ |
| 397 | \ |
| 398 | OPENSSL_INLINE void *sk_##name##_call_copy_func( \ |
David Benjamin | df8a55b | 2023-01-04 15:52:36 -0800 | [diff] [blame] | 399 | OPENSSL_sk_copy_func copy_func, const void *ptr) { \ |
| 400 | return (void *)((sk_##name##_copy_func)copy_func)((constptrtype)ptr); \ |
David Benjamin | 7f857ea | 2022-06-13 11:47:31 -0400 | [diff] [blame] | 401 | } \ |
| 402 | \ |
| 403 | OPENSSL_INLINE int sk_##name##_call_cmp_func(OPENSSL_sk_cmp_func cmp_func, \ |
| 404 | const void *const *a, \ |
| 405 | const void *const *b) { \ |
| 406 | /* The data is actually stored as |void*| pointers, so read the pointer \ |
| 407 | * as |void*| and then pass the corrected type into the caller-supplied \ |
| 408 | * function, which expects |constptrtype*|. */ \ |
| 409 | constptrtype a_ptr = (constptrtype)*a; \ |
| 410 | constptrtype b_ptr = (constptrtype)*b; \ |
| 411 | return ((sk_##name##_cmp_func)cmp_func)(&a_ptr, &b_ptr); \ |
| 412 | } \ |
| 413 | \ |
David Benjamin | 49e0791 | 2022-12-26 10:41:26 -0500 | [diff] [blame] | 414 | OPENSSL_INLINE int sk_##name##_call_delete_if_func( \ |
| 415 | OPENSSL_sk_delete_if_func func, void *obj, void *data) { \ |
| 416 | return ((sk_##name##_delete_if_func)func)((ptrtype)obj, data); \ |
| 417 | } \ |
| 418 | \ |
David Benjamin | 7f857ea | 2022-06-13 11:47:31 -0400 | [diff] [blame] | 419 | OPENSSL_INLINE STACK_OF(name) *sk_##name##_new(sk_##name##_cmp_func comp) { \ |
| 420 | return (STACK_OF(name) *)sk_new((OPENSSL_sk_cmp_func)comp); \ |
| 421 | } \ |
| 422 | \ |
| 423 | OPENSSL_INLINE STACK_OF(name) *sk_##name##_new_null(void) { \ |
| 424 | return (STACK_OF(name) *)sk_new_null(); \ |
| 425 | } \ |
| 426 | \ |
| 427 | OPENSSL_INLINE size_t sk_##name##_num(const STACK_OF(name) *sk) { \ |
| 428 | return sk_num((const _STACK *)sk); \ |
| 429 | } \ |
| 430 | \ |
| 431 | OPENSSL_INLINE void sk_##name##_zero(STACK_OF(name) *sk) { \ |
| 432 | sk_zero((_STACK *)sk); \ |
| 433 | } \ |
| 434 | \ |
| 435 | OPENSSL_INLINE ptrtype sk_##name##_value(const STACK_OF(name) *sk, \ |
| 436 | size_t i) { \ |
| 437 | return (ptrtype)sk_value((const _STACK *)sk, i); \ |
| 438 | } \ |
| 439 | \ |
| 440 | OPENSSL_INLINE ptrtype sk_##name##_set(STACK_OF(name) *sk, size_t i, \ |
| 441 | ptrtype p) { \ |
| 442 | return (ptrtype)sk_set((_STACK *)sk, i, (void *)p); \ |
| 443 | } \ |
| 444 | \ |
| 445 | OPENSSL_INLINE void sk_##name##_free(STACK_OF(name) *sk) { \ |
| 446 | sk_free((_STACK *)sk); \ |
| 447 | } \ |
| 448 | \ |
| 449 | OPENSSL_INLINE void sk_##name##_pop_free(STACK_OF(name) *sk, \ |
| 450 | sk_##name##_free_func free_func) { \ |
| 451 | sk_pop_free_ex((_STACK *)sk, sk_##name##_call_free_func, \ |
| 452 | (OPENSSL_sk_free_func)free_func); \ |
| 453 | } \ |
| 454 | \ |
| 455 | OPENSSL_INLINE size_t sk_##name##_insert(STACK_OF(name) *sk, ptrtype p, \ |
| 456 | size_t where) { \ |
| 457 | return sk_insert((_STACK *)sk, (void *)p, where); \ |
| 458 | } \ |
| 459 | \ |
| 460 | OPENSSL_INLINE ptrtype sk_##name##_delete(STACK_OF(name) *sk, \ |
| 461 | size_t where) { \ |
| 462 | return (ptrtype)sk_delete((_STACK *)sk, where); \ |
| 463 | } \ |
| 464 | \ |
| 465 | OPENSSL_INLINE ptrtype sk_##name##_delete_ptr(STACK_OF(name) *sk, \ |
| 466 | constptrtype p) { \ |
| 467 | return (ptrtype)sk_delete_ptr((_STACK *)sk, (const void *)p); \ |
| 468 | } \ |
| 469 | \ |
David Benjamin | 49e0791 | 2022-12-26 10:41:26 -0500 | [diff] [blame] | 470 | OPENSSL_INLINE void sk_##name##_delete_if( \ |
| 471 | STACK_OF(name) *sk, sk_##name##_delete_if_func func, void *data) { \ |
| 472 | sk_delete_if((_STACK *)sk, sk_##name##_call_delete_if_func, \ |
| 473 | (OPENSSL_sk_delete_if_func)func, data); \ |
| 474 | } \ |
| 475 | \ |
David Benjamin | 7f857ea | 2022-06-13 11:47:31 -0400 | [diff] [blame] | 476 | OPENSSL_INLINE int sk_##name##_find(const STACK_OF(name) *sk, \ |
| 477 | size_t *out_index, constptrtype p) { \ |
| 478 | return sk_find((const _STACK *)sk, out_index, (const void *)p, \ |
| 479 | sk_##name##_call_cmp_func); \ |
| 480 | } \ |
| 481 | \ |
| 482 | OPENSSL_INLINE ptrtype sk_##name##_shift(STACK_OF(name) *sk) { \ |
| 483 | return (ptrtype)sk_shift((_STACK *)sk); \ |
| 484 | } \ |
| 485 | \ |
| 486 | OPENSSL_INLINE size_t sk_##name##_push(STACK_OF(name) *sk, ptrtype p) { \ |
| 487 | return sk_push((_STACK *)sk, (void *)p); \ |
| 488 | } \ |
| 489 | \ |
| 490 | OPENSSL_INLINE ptrtype sk_##name##_pop(STACK_OF(name) *sk) { \ |
| 491 | return (ptrtype)sk_pop((_STACK *)sk); \ |
| 492 | } \ |
| 493 | \ |
| 494 | OPENSSL_INLINE STACK_OF(name) *sk_##name##_dup(const STACK_OF(name) *sk) { \ |
| 495 | return (STACK_OF(name) *)sk_dup((const _STACK *)sk); \ |
| 496 | } \ |
| 497 | \ |
| 498 | OPENSSL_INLINE void sk_##name##_sort(STACK_OF(name) *sk) { \ |
| 499 | sk_sort((_STACK *)sk, sk_##name##_call_cmp_func); \ |
| 500 | } \ |
| 501 | \ |
| 502 | OPENSSL_INLINE int sk_##name##_is_sorted(const STACK_OF(name) *sk) { \ |
| 503 | return sk_is_sorted((const _STACK *)sk); \ |
| 504 | } \ |
| 505 | \ |
| 506 | OPENSSL_INLINE sk_##name##_cmp_func sk_##name##_set_cmp_func( \ |
| 507 | STACK_OF(name) *sk, sk_##name##_cmp_func comp) { \ |
| 508 | return (sk_##name##_cmp_func)sk_set_cmp_func((_STACK *)sk, \ |
| 509 | (OPENSSL_sk_cmp_func)comp); \ |
| 510 | } \ |
| 511 | \ |
| 512 | OPENSSL_INLINE STACK_OF(name) *sk_##name##_deep_copy( \ |
| 513 | const STACK_OF(name) *sk, sk_##name##_copy_func copy_func, \ |
| 514 | sk_##name##_free_func free_func) { \ |
| 515 | return (STACK_OF(name) *)sk_deep_copy( \ |
| 516 | (const _STACK *)sk, sk_##name##_call_copy_func, \ |
| 517 | (OPENSSL_sk_copy_func)copy_func, sk_##name##_call_free_func, \ |
| 518 | (OPENSSL_sk_free_func)free_func); \ |
| 519 | } \ |
| 520 | \ |
David Benjamin | 167f176 | 2022-06-12 13:47:08 -0400 | [diff] [blame] | 521 | OPENSSL_MSVC_PRAGMA(warning(pop)) |
David Benjamin | 01f8a8c | 2017-04-15 18:12:55 -0400 | [diff] [blame] | 522 | |
David Benjamin | 35b4a12 | 2018-07-14 17:04:41 -0400 | [diff] [blame] | 523 | |
David Benjamin | 7f857ea | 2022-06-13 11:47:31 -0400 | [diff] [blame] | 524 | // Built-in stacks. |
David Benjamin | 01f8a8c | 2017-04-15 18:12:55 -0400 | [diff] [blame] | 525 | |
David Benjamin | 01f8a8c | 2017-04-15 18:12:55 -0400 | [diff] [blame] | 526 | typedef char *OPENSSL_STRING; |
| 527 | |
| 528 | DEFINE_STACK_OF(void) |
David Benjamin | 1500ad0 | 2022-06-13 12:33:07 -0400 | [diff] [blame] | 529 | DEFINE_NAMED_STACK_OF(OPENSSL_STRING, char) |
David Benjamin | 01f8a8c | 2017-04-15 18:12:55 -0400 | [diff] [blame] | 530 | |
| 531 | |
Adam Langley | 95c29f3 | 2014-06-20 12:00:00 -0700 | [diff] [blame] | 532 | #if defined(__cplusplus) |
David Benjamin | 4512b79 | 2017-08-18 19:21:50 -0400 | [diff] [blame] | 533 | } // extern C |
Adam Langley | 95c29f3 | 2014-06-20 12:00:00 -0700 | [diff] [blame] | 534 | #endif |
| 535 | |
David Benjamin | 0121953 | 2017-07-25 22:33:06 -0400 | [diff] [blame] | 536 | #if !defined(BORINGSSL_NO_CXX) |
| 537 | extern "C++" { |
| 538 | |
| 539 | #include <type_traits> |
| 540 | |
Joshua Liebow-Feeser | 8c7c635 | 2018-08-26 18:53:36 -0700 | [diff] [blame] | 541 | BSSL_NAMESPACE_BEGIN |
David Benjamin | 0121953 | 2017-07-25 22:33:06 -0400 | [diff] [blame] | 542 | |
| 543 | namespace internal { |
| 544 | |
| 545 | // Stacks defined with |DEFINE_CONST_STACK_OF| are freed with |sk_free|. |
| 546 | template <typename Stack> |
David Benjamin | 493d5cb | 2022-04-18 17:20:27 -0400 | [diff] [blame] | 547 | struct DeleterImpl<Stack, std::enable_if_t<StackTraits<Stack>::kIsConst>> { |
David Benjamin | 0121953 | 2017-07-25 22:33:06 -0400 | [diff] [blame] | 548 | static void Free(Stack *sk) { sk_free(reinterpret_cast<_STACK *>(sk)); } |
| 549 | }; |
| 550 | |
| 551 | // Stacks defined with |DEFINE_STACK_OF| are freed with |sk_pop_free| and the |
| 552 | // corresponding type's deleter. |
| 553 | template <typename Stack> |
David Benjamin | 493d5cb | 2022-04-18 17:20:27 -0400 | [diff] [blame] | 554 | struct DeleterImpl<Stack, std::enable_if_t<!StackTraits<Stack>::kIsConst>> { |
David Benjamin | 0121953 | 2017-07-25 22:33:06 -0400 | [diff] [blame] | 555 | static void Free(Stack *sk) { |
David Benjamin | fb4e2e0 | 2018-09-23 15:59:51 -0500 | [diff] [blame] | 556 | // sk_FOO_pop_free is defined by macros and bound by name, so we cannot |
| 557 | // access it from C++ here. |
| 558 | using Type = typename StackTraits<Stack>::Type; |
| 559 | sk_pop_free_ex(reinterpret_cast<_STACK *>(sk), |
David Benjamin | 7f857ea | 2022-06-13 11:47:31 -0400 | [diff] [blame] | 560 | [](OPENSSL_sk_free_func /* unused */, void *ptr) { |
David Benjamin | fb4e2e0 | 2018-09-23 15:59:51 -0500 | [diff] [blame] | 561 | DeleterImpl<Type>::Free(reinterpret_cast<Type *>(ptr)); |
| 562 | }, |
| 563 | nullptr); |
David Benjamin | 0121953 | 2017-07-25 22:33:06 -0400 | [diff] [blame] | 564 | } |
| 565 | }; |
| 566 | |
David Benjamin | ec78383 | 2017-07-25 23:23:03 -0400 | [diff] [blame] | 567 | template <typename Stack> |
| 568 | class StackIteratorImpl { |
| 569 | public: |
| 570 | using Type = typename StackTraits<Stack>::Type; |
| 571 | // Iterators must be default-constructable. |
| 572 | StackIteratorImpl() : sk_(nullptr), idx_(0) {} |
| 573 | StackIteratorImpl(const Stack *sk, size_t idx) : sk_(sk), idx_(idx) {} |
| 574 | |
| 575 | bool operator==(StackIteratorImpl other) const { |
| 576 | return sk_ == other.sk_ && idx_ == other.idx_; |
| 577 | } |
| 578 | bool operator!=(StackIteratorImpl other) const { |
| 579 | return !(*this == other); |
| 580 | } |
| 581 | |
| 582 | Type *operator*() const { |
| 583 | return reinterpret_cast<Type *>( |
| 584 | sk_value(reinterpret_cast<const _STACK *>(sk_), idx_)); |
| 585 | } |
| 586 | |
| 587 | StackIteratorImpl &operator++(/* prefix */) { |
| 588 | idx_++; |
| 589 | return *this; |
| 590 | } |
| 591 | |
| 592 | StackIteratorImpl operator++(int /* postfix */) { |
| 593 | StackIteratorImpl copy(*this); |
| 594 | ++(*this); |
| 595 | return copy; |
| 596 | } |
| 597 | |
| 598 | private: |
| 599 | const Stack *sk_; |
| 600 | size_t idx_; |
| 601 | }; |
| 602 | |
| 603 | template <typename Stack> |
David Benjamin | 493d5cb | 2022-04-18 17:20:27 -0400 | [diff] [blame] | 604 | using StackIterator = |
| 605 | std::enable_if_t<StackTraits<Stack>::kIsStack, StackIteratorImpl<Stack>>; |
David Benjamin | ec78383 | 2017-07-25 23:23:03 -0400 | [diff] [blame] | 606 | |
David Benjamin | 0121953 | 2017-07-25 22:33:06 -0400 | [diff] [blame] | 607 | } // namespace internal |
| 608 | |
David Benjamin | 6e9321f | 2017-07-25 23:49:58 -0400 | [diff] [blame] | 609 | // PushToStack pushes |elem| to |sk|. It returns true on success and false on |
| 610 | // allocation failure. |
| 611 | template <typename Stack> |
David Benjamin | 493d5cb | 2022-04-18 17:20:27 -0400 | [diff] [blame] | 612 | inline std::enable_if_t<!internal::StackTraits<Stack>::kIsConst, bool> |
| 613 | PushToStack(Stack *sk, |
| 614 | UniquePtr<typename internal::StackTraits<Stack>::Type> elem) { |
David Benjamin | 6e9321f | 2017-07-25 23:49:58 -0400 | [diff] [blame] | 615 | if (!sk_push(reinterpret_cast<_STACK *>(sk), elem.get())) { |
| 616 | return false; |
| 617 | } |
| 618 | // sk_push takes ownership on success. |
| 619 | elem.release(); |
| 620 | return true; |
| 621 | } |
| 622 | |
Joshua Liebow-Feeser | 8c7c635 | 2018-08-26 18:53:36 -0700 | [diff] [blame] | 623 | BSSL_NAMESPACE_END |
David Benjamin | 0121953 | 2017-07-25 22:33:06 -0400 | [diff] [blame] | 624 | |
David Benjamin | ec78383 | 2017-07-25 23:23:03 -0400 | [diff] [blame] | 625 | // Define begin() and end() for stack types so C++ range for loops work. |
| 626 | template <typename Stack> |
David Benjamin | a943613 | 2018-09-23 18:36:01 -0500 | [diff] [blame] | 627 | inline bssl::internal::StackIterator<Stack> begin(const Stack *sk) { |
David Benjamin | ec78383 | 2017-07-25 23:23:03 -0400 | [diff] [blame] | 628 | return bssl::internal::StackIterator<Stack>(sk, 0); |
| 629 | } |
| 630 | |
| 631 | template <typename Stack> |
David Benjamin | a943613 | 2018-09-23 18:36:01 -0500 | [diff] [blame] | 632 | inline bssl::internal::StackIterator<Stack> end(const Stack *sk) { |
David Benjamin | ec78383 | 2017-07-25 23:23:03 -0400 | [diff] [blame] | 633 | return bssl::internal::StackIterator<Stack>( |
| 634 | sk, sk_num(reinterpret_cast<const _STACK *>(sk))); |
| 635 | } |
| 636 | |
David Benjamin | 0121953 | 2017-07-25 22:33:06 -0400 | [diff] [blame] | 637 | } // extern C++ |
| 638 | #endif |
| 639 | |
David Benjamin | 4512b79 | 2017-08-18 19:21:50 -0400 | [diff] [blame] | 640 | #endif // OPENSSL_HEADER_STACK_H |