| /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) | 
 |  * All rights reserved. | 
 |  * | 
 |  * This package is an SSL implementation written | 
 |  * by Eric Young (eay@cryptsoft.com). | 
 |  * The implementation was written so as to conform with Netscapes SSL. | 
 |  * | 
 |  * This library is free for commercial and non-commercial use as long as | 
 |  * the following conditions are aheared to.  The following conditions | 
 |  * apply to all code found in this distribution, be it the RC4, RSA, | 
 |  * lhash, DES, etc., code; not just the SSL code.  The SSL documentation | 
 |  * included with this distribution is covered by the same copyright terms | 
 |  * except that the holder is Tim Hudson (tjh@cryptsoft.com). | 
 |  * | 
 |  * Copyright remains Eric Young's, and as such any Copyright notices in | 
 |  * the code are not to be removed. | 
 |  * If this package is used in a product, Eric Young should be given attribution | 
 |  * as the author of the parts of the library used. | 
 |  * This can be in the form of a textual message at program startup or | 
 |  * in documentation (online or textual) provided with the package. | 
 |  * | 
 |  * Redistribution and use in source and binary forms, with or without | 
 |  * modification, are permitted provided that the following conditions | 
 |  * are met: | 
 |  * 1. Redistributions of source code must retain the copyright | 
 |  *    notice, this list of conditions and the following disclaimer. | 
 |  * 2. Redistributions in binary form must reproduce the above copyright | 
 |  *    notice, this list of conditions and the following disclaimer in the | 
 |  *    documentation and/or other materials provided with the distribution. | 
 |  * 3. All advertising materials mentioning features or use of this software | 
 |  *    must display the following acknowledgement: | 
 |  *    "This product includes cryptographic software written by | 
 |  *     Eric Young (eay@cryptsoft.com)" | 
 |  *    The word 'cryptographic' can be left out if the rouines from the library | 
 |  *    being used are not cryptographic related :-). | 
 |  * 4. If you include any Windows specific code (or a derivative thereof) from | 
 |  *    the apps directory (application code) you must include an acknowledgement: | 
 |  *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" | 
 |  * | 
 |  * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND | 
 |  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | 
 |  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | 
 |  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE | 
 |  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | 
 |  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | 
 |  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | 
 |  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | 
 |  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | 
 |  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | 
 |  * SUCH DAMAGE. | 
 |  * | 
 |  * The licence and distribution terms for any publically available version or | 
 |  * derivative of this code cannot be changed.  i.e. this code cannot simply be | 
 |  * copied and put under another distribution licence | 
 |  * [including the GNU Public Licence.] */ | 
 |  | 
 | #ifndef OPENSSL_HEADER_STACK_H | 
 | #define OPENSSL_HEADER_STACK_H | 
 |  | 
 | #include <openssl/base.h> | 
 |  | 
 | #if defined(__cplusplus) | 
 | extern "C" { | 
 | #endif | 
 |  | 
 |  | 
 | // A stack, in OpenSSL, is an array of pointers. They are the most commonly | 
 | // used collection object. | 
 | // | 
 | // This file defines macros for type-safe use of the stack functions. A stack | 
 | // type is named like |STACK_OF(FOO)| and is accessed with functions named | 
 | // like |sk_FOO_*|. Note the stack will typically contain /pointers/ to |FOO|. | 
 | // | 
 | // The |DECLARE_STACK_OF| macro makes |STACK_OF(FOO)| available, and | 
 | // |DEFINE_STACK_OF| makes the corresponding functions available. | 
 |  | 
 |  | 
 | // Defining stacks. | 
 |  | 
 | // STACK_OF expands to the stack type for |type|. | 
 | #define STACK_OF(type) struct stack_st_##type | 
 |  | 
 | // DECLARE_STACK_OF declares the |STACK_OF(type)| type. It does not make the | 
 | // corresponding |sk_type_*| functions available. This macro should be used in | 
 | // files which only need the type. | 
 | #define DECLARE_STACK_OF(type) STACK_OF(type); | 
 |  | 
 | // DEFINE_NAMED_STACK_OF defines |STACK_OF(name)| to be a stack whose elements | 
 | // are |type| *. This macro makes the |sk_name_*| functions available. | 
 | // | 
 | // It is not necessary to use |DECLARE_STACK_OF| in files which use this macro. | 
 | #define DEFINE_NAMED_STACK_OF(name, type)                    \ | 
 |   BORINGSSL_DEFINE_STACK_OF_IMPL(name, type *, const type *) \ | 
 |   BORINGSSL_DEFINE_STACK_TRAITS(name, type, false) | 
 |  | 
 | // DEFINE_STACK_OF defines |STACK_OF(type)| to be a stack whose elements are | 
 | // |type| *. This macro makes the |sk_type_*| functions available. | 
 | // | 
 | // It is not necessary to use |DECLARE_STACK_OF| in files which use this macro. | 
 | #define DEFINE_STACK_OF(type) DEFINE_NAMED_STACK_OF(type, type) | 
 |  | 
 | // DEFINE_CONST_STACK_OF defines |STACK_OF(type)| to be a stack whose elements | 
 | // are const |type| *. This macro makes the |sk_type_*| functions available. | 
 | // | 
 | // It is not necessary to use |DECLARE_STACK_OF| in files which use this macro. | 
 | #define DEFINE_CONST_STACK_OF(type)                                \ | 
 |   BORINGSSL_DEFINE_STACK_OF_IMPL(type, const type *, const type *) \ | 
 |   BORINGSSL_DEFINE_STACK_TRAITS(type, const type, true) | 
 |  | 
 |  | 
 | // Using stacks. | 
 | // | 
 | // After the |DEFINE_STACK_OF| macro is used, the following functions are | 
 | // available. | 
 |  | 
 | #if 0  // Sample | 
 |  | 
 | // sk_SAMPLE_free_func is a callback to free an element in a stack. | 
 | typedef void (*sk_SAMPLE_free_func)(SAMPLE *); | 
 |  | 
 | // sk_SAMPLE_copy_func is a callback to copy an element in a stack. It should | 
 | // return the copy or NULL on error. | 
 | typedef SAMPLE *(*sk_SAMPLE_copy_func)(const SAMPLE *); | 
 |  | 
 | // sk_SAMPLE_cmp_func is a callback to compare |*a| to |*b|. It should return a | 
 | // value < 0, 0, or > 0 if |*a| is less than, equal to, or greater than |*b|, | 
 | // respectively.  Note the extra indirection - the function is given a pointer | 
 | // to a pointer to the element. This is the |qsort|/|bsearch| comparison | 
 | // function applied to an array of |SAMPLE*|. | 
 | typedef int (*sk_SAMPLE_cmp_func)(const SAMPLE *const *a, | 
 |                                   const SAMPLE *const *b); | 
 |  | 
 | // sk_SAMPLE_new creates a new, empty stack with the given comparison function, | 
 | // which may be NULL. It returns the new stack or NULL on allocation failure. | 
 | STACK_OF(SAMPLE) *sk_SAMPLE_new(sk_SAMPLE_cmp_func comp); | 
 |  | 
 | // sk_SAMPLE_new_null creates a new, empty stack. It returns the new stack or | 
 | // NULL on allocation failure. | 
 | STACK_OF(SAMPLE) *sk_SAMPLE_new_null(void); | 
 |  | 
 | // sk_SAMPLE_num returns the number of elements in |sk|. | 
 | size_t sk_SAMPLE_num(const STACK_OF(SAMPLE) *sk); | 
 |  | 
 | // sk_SAMPLE_zero resets |sk| to the empty state but does nothing to free the | 
 | // individual elements themselves. | 
 | void sk_SAMPLE_zero(STACK_OF(SAMPLE) *sk); | 
 |  | 
 | // sk_SAMPLE_value returns the |i|th pointer in |sk|, or NULL if |i| is out of | 
 | // range. | 
 | SAMPLE *sk_SAMPLE_value(const STACK_OF(SAMPLE) *sk, size_t i); | 
 |  | 
 | // sk_SAMPLE_set sets the |i|th pointer in |sk| to |p| and returns |p|. If |i| | 
 | // is out of range, it returns NULL. | 
 | SAMPLE *sk_SAMPLE_set(STACK_OF(SAMPLE) *sk, size_t i, SAMPLE *p); | 
 |  | 
 | // sk_SAMPLE_free frees |sk|, but does nothing to free the individual elements. | 
 | // Use |sk_SAMPLE_pop_free| to also free the elements. | 
 | void sk_SAMPLE_free(STACK_OF(SAMPLE) *sk); | 
 |  | 
 | // sk_SAMPLE_pop_free calls |free_func| on each element in |sk| and then | 
 | // frees the stack itself. | 
 | void sk_SAMPLE_pop_free(STACK_OF(SAMPLE) *sk, sk_SAMPLE_free_func free_func); | 
 |  | 
 | // sk_SAMPLE_insert inserts |p| into the stack at index |where|, moving existing | 
 | // elements if needed. It returns the length of the new stack, or zero on | 
 | // error. | 
 | size_t sk_SAMPLE_insert(STACK_OF(SAMPLE) *sk, SAMPLE *p, size_t where); | 
 |  | 
 | // sk_SAMPLE_delete removes the pointer at index |where|, moving other elements | 
 | // down if needed. It returns the removed pointer, or NULL if |where| is out of | 
 | // range. | 
 | SAMPLE *sk_SAMPLE_delete(STACK_OF(SAMPLE) *sk, size_t where); | 
 |  | 
 | // sk_SAMPLE_delete_ptr removes, at most, one instance of |p| from |sk| based on | 
 | // pointer equality. If an instance of |p| is found then |p| is returned, | 
 | // otherwise it returns NULL. | 
 | SAMPLE *sk_SAMPLE_delete_ptr(STACK_OF(SAMPLE) *sk, const SAMPLE *p); | 
 |  | 
 | // sk_SAMPLE_delete_if_func is the callback function for |sk_SAMPLE_delete_if|. | 
 | // It should return one to remove |p| and zero to keep it. | 
 | typedef int (*sk_SAMPLE_delete_if_func)(SAMPLE *p, void *data); | 
 |  | 
 | // sk_SAMPLE_delete_if calls |func| with each element of |sk| and removes the | 
 | // entries where |func| returned one. This function does not free or return | 
 | // removed pointers so, if |sk| owns its contents, |func| should release the | 
 | // pointers prior to returning one. | 
 | void sk_SAMPLE_delete_if(STACK_OF(SAMPLE) *sk, sk_SAMPLE_delete_if_func func, | 
 |                          void *data); | 
 |  | 
 | // sk_SAMPLE_find find the first value in |sk| equal to |p|. |sk|'s comparison | 
 | // function determines equality, or pointer equality if |sk| has no comparison | 
 | // function. | 
 | // | 
 | // If the stack is sorted (see |sk_SAMPLE_sort|), this function uses a binary | 
 | // search. Otherwise it performs a linear search. If it finds a matching | 
 | // element, it writes the index to |*out_index| (if |out_index| is not NULL) and | 
 | // returns one. Otherwise, it returns zero. | 
 | // | 
 | // Note this differs from OpenSSL. The type signature is slightly different, and | 
 | // OpenSSL's version will implicitly sort |sk| if it has a comparison function | 
 | // defined. | 
 | int sk_SAMPLE_find(const STACK_OF(SAMPLE) *sk, size_t *out_index, | 
 |                    const SAMPLE *p); | 
 |  | 
 | // sk_SAMPLE_shift removes and returns the first element in |sk|, or NULL if | 
 | // |sk| is empty. | 
 | SAMPLE *sk_SAMPLE_shift(STACK_OF(SAMPLE) *sk); | 
 |  | 
 | // sk_SAMPLE_push appends |p| to |sk| and returns the length of the new stack, | 
 | // or 0 on allocation failure. | 
 | size_t sk_SAMPLE_push(STACK_OF(SAMPLE) *sk, SAMPLE *p); | 
 |  | 
 | // sk_SAMPLE_pop removes and returns the last element of |sk|, or NULL if |sk| | 
 | // is empty. | 
 | SAMPLE *sk_SAMPLE_pop(STACK_OF(SAMPLE) *sk); | 
 |  | 
 | // sk_SAMPLE_dup performs a shallow copy of a stack and returns the new stack, | 
 | // or NULL on error. Use |sk_SAMPLE_deep_copy| to also copy the elements. | 
 | STACK_OF(SAMPLE) *sk_SAMPLE_dup(const STACK_OF(SAMPLE) *sk); | 
 |  | 
 | // sk_SAMPLE_sort sorts the elements of |sk| into ascending order based on the | 
 | // comparison function. The stack maintains a "sorted" flag and sorting an | 
 | // already sorted stack is a no-op. | 
 | void sk_SAMPLE_sort(STACK_OF(SAMPLE) *sk); | 
 |  | 
 | // sk_SAMPLE_is_sorted returns one if |sk| is known to be sorted and zero | 
 | // otherwise. | 
 | int sk_SAMPLE_is_sorted(const STACK_OF(SAMPLE) *sk); | 
 |  | 
 | // sk_SAMPLE_set_cmp_func sets the comparison function to be used by |sk| and | 
 | // returns the previous one. | 
 | sk_SAMPLE_cmp_func sk_SAMPLE_set_cmp_func(STACK_OF(SAMPLE) *sk, | 
 |                                           sk_SAMPLE_cmp_func comp); | 
 |  | 
 | // sk_SAMPLE_deep_copy performs a copy of |sk| and of each of the non-NULL | 
 | // elements in |sk| by using |copy_func|. If an error occurs, it calls | 
 | // |free_func| to free any copies already made and returns NULL. | 
 | STACK_OF(SAMPLE) *sk_SAMPLE_deep_copy(const STACK_OF(SAMPLE) *sk, | 
 |                                       sk_SAMPLE_copy_func copy_func, | 
 |                                       sk_SAMPLE_free_func free_func); | 
 |  | 
 | #endif  // Sample | 
 |  | 
 |  | 
 | // Private functions. | 
 | // | 
 | // TODO(https://crbug.com/boringssl/499): Rename to |OPENSSL_sk_foo|, after | 
 | // external code that calls them is fixed. | 
 |  | 
 | // OPENSSL_sk_free_func is a function that frees an element in a stack. Note its | 
 | // actual type is void (*)(T *) for some T. Low-level |sk_*| functions will be | 
 | // passed a type-specific wrapper to call it correctly. | 
 | typedef void (*OPENSSL_sk_free_func)(void *ptr); | 
 |  | 
 | // OPENSSL_sk_copy_func is a function that copies an element in a stack. Note | 
 | // its actual type is T *(*)(const T *) for some T. Low-level |sk_*| functions | 
 | // will be passed a type-specific wrapper to call it correctly. | 
 | typedef void *(*OPENSSL_sk_copy_func)(const void *ptr); | 
 |  | 
 | // OPENSSL_sk_cmp_func is a comparison function that returns a value < 0, 0 or > | 
 | // 0 if |*a| is less than, equal to or greater than |*b|, respectively.  Note | 
 | // the extra indirection - the function is given a pointer to a pointer to the | 
 | // element. This differs from the usual qsort/bsearch comparison function. | 
 | // | 
 | // Note its actual type is |int (*)(const T *const *a, const T *const *b)|. | 
 | // Low-level |sk_*| functions will be passed a type-specific wrapper to call it | 
 | // correctly. | 
 | typedef int (*OPENSSL_sk_cmp_func)(const void *const *a, const void *const *b); | 
 |  | 
 | // OPENSSL_sk_delete_if_func is the generic version of | 
 | // |sk_SAMPLE_delete_if_func|. | 
 | typedef int (*OPENSSL_sk_delete_if_func)(void *obj, void *data); | 
 |  | 
 | // The following function types call the above type-erased signatures with the | 
 | // true types. | 
 | typedef void (*OPENSSL_sk_call_free_func)(OPENSSL_sk_free_func, void *); | 
 | typedef void *(*OPENSSL_sk_call_copy_func)(OPENSSL_sk_copy_func, const void *); | 
 | typedef int (*OPENSSL_sk_call_cmp_func)(OPENSSL_sk_cmp_func, | 
 |                                         const void *const *, | 
 |                                         const void *const *); | 
 | typedef int (*OPENSSL_sk_call_delete_if_func)(OPENSSL_sk_delete_if_func, void *, | 
 |                                               void *); | 
 |  | 
 | // stack_st contains an array of pointers. It is not designed to be used | 
 | // directly, rather the wrapper macros should be used. | 
 | typedef struct stack_st { | 
 |   // num contains the number of valid pointers in |data|. | 
 |   size_t num; | 
 |   void **data; | 
 |   // sorted is non-zero if the values pointed to by |data| are in ascending | 
 |   // order, based on |comp|. | 
 |   int sorted; | 
 |   // num_alloc contains the number of pointers allocated in the buffer pointed | 
 |   // to by |data|, which may be larger than |num|. | 
 |   size_t num_alloc; | 
 |   // comp is an optional comparison function. | 
 |   OPENSSL_sk_cmp_func comp; | 
 | } _STACK; | 
 |  | 
 | // The following are raw stack functions. They implement the corresponding typed | 
 | // |sk_SAMPLE_*| functions generated by |DEFINE_STACK_OF|. Callers shouldn't be | 
 | // using them. Rather, callers should use the typed functions. | 
 | OPENSSL_EXPORT _STACK *sk_new(OPENSSL_sk_cmp_func comp); | 
 | OPENSSL_EXPORT _STACK *sk_new_null(void); | 
 | OPENSSL_EXPORT size_t sk_num(const _STACK *sk); | 
 | OPENSSL_EXPORT void sk_zero(_STACK *sk); | 
 | OPENSSL_EXPORT void *sk_value(const _STACK *sk, size_t i); | 
 | OPENSSL_EXPORT void *sk_set(_STACK *sk, size_t i, void *p); | 
 | OPENSSL_EXPORT void sk_free(_STACK *sk); | 
 | OPENSSL_EXPORT void sk_pop_free_ex(_STACK *sk, | 
 |                                    OPENSSL_sk_call_free_func call_free_func, | 
 |                                    OPENSSL_sk_free_func free_func); | 
 | OPENSSL_EXPORT size_t sk_insert(_STACK *sk, void *p, size_t where); | 
 | OPENSSL_EXPORT void *sk_delete(_STACK *sk, size_t where); | 
 | OPENSSL_EXPORT void *sk_delete_ptr(_STACK *sk, const void *p); | 
 | OPENSSL_EXPORT void sk_delete_if(_STACK *sk, | 
 |                                  OPENSSL_sk_call_delete_if_func call_func, | 
 |                                  OPENSSL_sk_delete_if_func func, void *data); | 
 | OPENSSL_EXPORT int sk_find(const _STACK *sk, size_t *out_index, const void *p, | 
 |                            OPENSSL_sk_call_cmp_func call_cmp_func); | 
 | OPENSSL_EXPORT void *sk_shift(_STACK *sk); | 
 | OPENSSL_EXPORT size_t sk_push(_STACK *sk, void *p); | 
 | OPENSSL_EXPORT void *sk_pop(_STACK *sk); | 
 | OPENSSL_EXPORT _STACK *sk_dup(const _STACK *sk); | 
 | OPENSSL_EXPORT void sk_sort(_STACK *sk, OPENSSL_sk_call_cmp_func call_cmp_func); | 
 | OPENSSL_EXPORT int sk_is_sorted(const _STACK *sk); | 
 | OPENSSL_EXPORT OPENSSL_sk_cmp_func sk_set_cmp_func(_STACK *sk, | 
 |                                                    OPENSSL_sk_cmp_func comp); | 
 | OPENSSL_EXPORT _STACK *sk_deep_copy(const _STACK *sk, | 
 |                                     OPENSSL_sk_call_copy_func call_copy_func, | 
 |                                     OPENSSL_sk_copy_func copy_func, | 
 |                                     OPENSSL_sk_call_free_func call_free_func, | 
 |                                     OPENSSL_sk_free_func free_func); | 
 |  | 
 | // sk_pop_free behaves like |sk_pop_free_ex| but performs an invalid function | 
 | // pointer cast. It exists because some existing callers called |sk_pop_free| | 
 | // directly. | 
 | // | 
 | // TODO(davidben): Migrate callers to bssl::UniquePtr and remove this. | 
 | OPENSSL_EXPORT void sk_pop_free(_STACK *sk, OPENSSL_sk_free_func free_func); | 
 |  | 
 | #if !defined(BORINGSSL_NO_CXX) | 
 | extern "C++" { | 
 | BSSL_NAMESPACE_BEGIN | 
 | namespace internal { | 
 | template <typename T> | 
 | struct StackTraits {}; | 
 | } | 
 | BSSL_NAMESPACE_END | 
 | } | 
 |  | 
 | #define BORINGSSL_DEFINE_STACK_TRAITS(name, type, is_const) \ | 
 |   extern "C++" {                                            \ | 
 |   BSSL_NAMESPACE_BEGIN                                      \ | 
 |   namespace internal {                                      \ | 
 |   template <>                                               \ | 
 |   struct StackTraits<STACK_OF(name)> {                      \ | 
 |     static constexpr bool kIsStack = true;                  \ | 
 |     using Type = type;                                      \ | 
 |     static constexpr bool kIsConst = is_const;              \ | 
 |   };                                                        \ | 
 |   }                                                         \ | 
 |   BSSL_NAMESPACE_END                                        \ | 
 |   } | 
 |  | 
 | #else | 
 | #define BORINGSSL_DEFINE_STACK_TRAITS(name, type, is_const) | 
 | #endif | 
 |  | 
 | #define BORINGSSL_DEFINE_STACK_OF_IMPL(name, ptrtype, constptrtype)           \ | 
 |   /* We disable MSVC C4191 in this macro, which warns when pointers are cast  \ | 
 |    * to the wrong type. While the cast itself is valid, it is often a bug     \ | 
 |    * because calling it through the cast is UB. However, we never actually    \ | 
 |    * call functions as |OPENSSL_sk_cmp_func|. The type is just a type-erased  \ | 
 |    * function pointer. (C does not guarantee function pointers fit in         \ | 
 |    * |void*|, and GCC will warn on this.) Thus we just disable the false      \ | 
 |    * positive warning. */                                                     \ | 
 |   OPENSSL_MSVC_PRAGMA(warning(push))                                          \ | 
 |   OPENSSL_MSVC_PRAGMA(warning(disable : 4191))                                \ | 
 |                                                                               \ | 
 |   DECLARE_STACK_OF(name)                                                      \ | 
 |                                                                               \ | 
 |   typedef void (*sk_##name##_free_func)(ptrtype);                             \ | 
 |   typedef ptrtype (*sk_##name##_copy_func)(constptrtype);                     \ | 
 |   typedef int (*sk_##name##_cmp_func)(constptrtype const *,                   \ | 
 |                                       constptrtype const *);                  \ | 
 |   typedef int (*sk_##name##_delete_if_func)(ptrtype, void *);                 \ | 
 |                                                                               \ | 
 |   OPENSSL_INLINE void sk_##name##_call_free_func(                             \ | 
 |       OPENSSL_sk_free_func free_func, void *ptr) {                            \ | 
 |     ((sk_##name##_free_func)free_func)((ptrtype)ptr);                         \ | 
 |   }                                                                           \ | 
 |                                                                               \ | 
 |   OPENSSL_INLINE void *sk_##name##_call_copy_func(                            \ | 
 |       OPENSSL_sk_copy_func copy_func, const void *ptr) {                      \ | 
 |     return (void *)((sk_##name##_copy_func)copy_func)((constptrtype)ptr);     \ | 
 |   }                                                                           \ | 
 |                                                                               \ | 
 |   OPENSSL_INLINE int sk_##name##_call_cmp_func(OPENSSL_sk_cmp_func cmp_func,  \ | 
 |                                                const void *const *a,          \ | 
 |                                                const void *const *b) {        \ | 
 |     /* The data is actually stored as |void*| pointers, so read the pointer   \ | 
 |      * as |void*| and then pass the corrected type into the caller-supplied   \ | 
 |      * function, which expects |constptrtype*|. */                            \ | 
 |     constptrtype a_ptr = (constptrtype)*a;                                    \ | 
 |     constptrtype b_ptr = (constptrtype)*b;                                    \ | 
 |     return ((sk_##name##_cmp_func)cmp_func)(&a_ptr, &b_ptr);                  \ | 
 |   }                                                                           \ | 
 |                                                                               \ | 
 |   OPENSSL_INLINE int sk_##name##_call_delete_if_func(                         \ | 
 |       OPENSSL_sk_delete_if_func func, void *obj, void *data) {                \ | 
 |     return ((sk_##name##_delete_if_func)func)((ptrtype)obj, data);            \ | 
 |   }                                                                           \ | 
 |                                                                               \ | 
 |   OPENSSL_INLINE STACK_OF(name) *sk_##name##_new(sk_##name##_cmp_func comp) { \ | 
 |     return (STACK_OF(name) *)sk_new((OPENSSL_sk_cmp_func)comp);               \ | 
 |   }                                                                           \ | 
 |                                                                               \ | 
 |   OPENSSL_INLINE STACK_OF(name) *sk_##name##_new_null(void) {                 \ | 
 |     return (STACK_OF(name) *)sk_new_null();                                   \ | 
 |   }                                                                           \ | 
 |                                                                               \ | 
 |   OPENSSL_INLINE size_t sk_##name##_num(const STACK_OF(name) *sk) {           \ | 
 |     return sk_num((const _STACK *)sk);                                        \ | 
 |   }                                                                           \ | 
 |                                                                               \ | 
 |   OPENSSL_INLINE void sk_##name##_zero(STACK_OF(name) *sk) {                  \ | 
 |     sk_zero((_STACK *)sk);                                                    \ | 
 |   }                                                                           \ | 
 |                                                                               \ | 
 |   OPENSSL_INLINE ptrtype sk_##name##_value(const STACK_OF(name) *sk,          \ | 
 |                                            size_t i) {                        \ | 
 |     return (ptrtype)sk_value((const _STACK *)sk, i);                          \ | 
 |   }                                                                           \ | 
 |                                                                               \ | 
 |   OPENSSL_INLINE ptrtype sk_##name##_set(STACK_OF(name) *sk, size_t i,        \ | 
 |                                          ptrtype p) {                         \ | 
 |     return (ptrtype)sk_set((_STACK *)sk, i, (void *)p);                       \ | 
 |   }                                                                           \ | 
 |                                                                               \ | 
 |   OPENSSL_INLINE void sk_##name##_free(STACK_OF(name) *sk) {                  \ | 
 |     sk_free((_STACK *)sk);                                                    \ | 
 |   }                                                                           \ | 
 |                                                                               \ | 
 |   OPENSSL_INLINE void sk_##name##_pop_free(STACK_OF(name) *sk,                \ | 
 |                                            sk_##name##_free_func free_func) { \ | 
 |     sk_pop_free_ex((_STACK *)sk, sk_##name##_call_free_func,                  \ | 
 |                    (OPENSSL_sk_free_func)free_func);                          \ | 
 |   }                                                                           \ | 
 |                                                                               \ | 
 |   OPENSSL_INLINE size_t sk_##name##_insert(STACK_OF(name) *sk, ptrtype p,     \ | 
 |                                            size_t where) {                    \ | 
 |     return sk_insert((_STACK *)sk, (void *)p, where);                         \ | 
 |   }                                                                           \ | 
 |                                                                               \ | 
 |   OPENSSL_INLINE ptrtype sk_##name##_delete(STACK_OF(name) *sk,               \ | 
 |                                             size_t where) {                   \ | 
 |     return (ptrtype)sk_delete((_STACK *)sk, where);                           \ | 
 |   }                                                                           \ | 
 |                                                                               \ | 
 |   OPENSSL_INLINE ptrtype sk_##name##_delete_ptr(STACK_OF(name) *sk,           \ | 
 |                                                 constptrtype p) {             \ | 
 |     return (ptrtype)sk_delete_ptr((_STACK *)sk, (const void *)p);             \ | 
 |   }                                                                           \ | 
 |                                                                               \ | 
 |   OPENSSL_INLINE void sk_##name##_delete_if(                                  \ | 
 |       STACK_OF(name) *sk, sk_##name##_delete_if_func func, void *data) {      \ | 
 |     sk_delete_if((_STACK *)sk, sk_##name##_call_delete_if_func,               \ | 
 |                  (OPENSSL_sk_delete_if_func)func, data);                      \ | 
 |   }                                                                           \ | 
 |                                                                               \ | 
 |   OPENSSL_INLINE int sk_##name##_find(const STACK_OF(name) *sk,               \ | 
 |                                       size_t *out_index, constptrtype p) {    \ | 
 |     return sk_find((const _STACK *)sk, out_index, (const void *)p,            \ | 
 |                    sk_##name##_call_cmp_func);                                \ | 
 |   }                                                                           \ | 
 |                                                                               \ | 
 |   OPENSSL_INLINE ptrtype sk_##name##_shift(STACK_OF(name) *sk) {              \ | 
 |     return (ptrtype)sk_shift((_STACK *)sk);                                   \ | 
 |   }                                                                           \ | 
 |                                                                               \ | 
 |   OPENSSL_INLINE size_t sk_##name##_push(STACK_OF(name) *sk, ptrtype p) {     \ | 
 |     return sk_push((_STACK *)sk, (void *)p);                                  \ | 
 |   }                                                                           \ | 
 |                                                                               \ | 
 |   OPENSSL_INLINE ptrtype sk_##name##_pop(STACK_OF(name) *sk) {                \ | 
 |     return (ptrtype)sk_pop((_STACK *)sk);                                     \ | 
 |   }                                                                           \ | 
 |                                                                               \ | 
 |   OPENSSL_INLINE STACK_OF(name) *sk_##name##_dup(const STACK_OF(name) *sk) {  \ | 
 |     return (STACK_OF(name) *)sk_dup((const _STACK *)sk);                      \ | 
 |   }                                                                           \ | 
 |                                                                               \ | 
 |   OPENSSL_INLINE void sk_##name##_sort(STACK_OF(name) *sk) {                  \ | 
 |     sk_sort((_STACK *)sk, sk_##name##_call_cmp_func);                         \ | 
 |   }                                                                           \ | 
 |                                                                               \ | 
 |   OPENSSL_INLINE int sk_##name##_is_sorted(const STACK_OF(name) *sk) {        \ | 
 |     return sk_is_sorted((const _STACK *)sk);                                  \ | 
 |   }                                                                           \ | 
 |                                                                               \ | 
 |   OPENSSL_INLINE sk_##name##_cmp_func sk_##name##_set_cmp_func(               \ | 
 |       STACK_OF(name) *sk, sk_##name##_cmp_func comp) {                        \ | 
 |     return (sk_##name##_cmp_func)sk_set_cmp_func((_STACK *)sk,                \ | 
 |                                                  (OPENSSL_sk_cmp_func)comp);  \ | 
 |   }                                                                           \ | 
 |                                                                               \ | 
 |   OPENSSL_INLINE STACK_OF(name) *sk_##name##_deep_copy(                       \ | 
 |       const STACK_OF(name) *sk, sk_##name##_copy_func copy_func,              \ | 
 |       sk_##name##_free_func free_func) {                                      \ | 
 |     return (STACK_OF(name) *)sk_deep_copy(                                    \ | 
 |         (const _STACK *)sk, sk_##name##_call_copy_func,                       \ | 
 |         (OPENSSL_sk_copy_func)copy_func, sk_##name##_call_free_func,          \ | 
 |         (OPENSSL_sk_free_func)free_func);                                     \ | 
 |   }                                                                           \ | 
 |                                                                               \ | 
 |   OPENSSL_MSVC_PRAGMA(warning(pop)) | 
 |  | 
 |  | 
 | // Built-in stacks. | 
 |  | 
 | typedef char *OPENSSL_STRING; | 
 |  | 
 | DEFINE_STACK_OF(void) | 
 | DEFINE_NAMED_STACK_OF(OPENSSL_STRING, char) | 
 |  | 
 |  | 
 | #if defined(__cplusplus) | 
 | }  // extern C | 
 | #endif | 
 |  | 
 | #if !defined(BORINGSSL_NO_CXX) | 
 | extern "C++" { | 
 |  | 
 | #include <type_traits> | 
 |  | 
 | BSSL_NAMESPACE_BEGIN | 
 |  | 
 | namespace internal { | 
 |  | 
 | // Stacks defined with |DEFINE_CONST_STACK_OF| are freed with |sk_free|. | 
 | template <typename Stack> | 
 | struct DeleterImpl<Stack, std::enable_if_t<StackTraits<Stack>::kIsConst>> { | 
 |   static void Free(Stack *sk) { sk_free(reinterpret_cast<_STACK *>(sk)); } | 
 | }; | 
 |  | 
 | // Stacks defined with |DEFINE_STACK_OF| are freed with |sk_pop_free| and the | 
 | // corresponding type's deleter. | 
 | template <typename Stack> | 
 | struct DeleterImpl<Stack, std::enable_if_t<!StackTraits<Stack>::kIsConst>> { | 
 |   static void Free(Stack *sk) { | 
 |     // sk_FOO_pop_free is defined by macros and bound by name, so we cannot | 
 |     // access it from C++ here. | 
 |     using Type = typename StackTraits<Stack>::Type; | 
 |     sk_pop_free_ex(reinterpret_cast<_STACK *>(sk), | 
 |                    [](OPENSSL_sk_free_func /* unused */, void *ptr) { | 
 |                      DeleterImpl<Type>::Free(reinterpret_cast<Type *>(ptr)); | 
 |                    }, | 
 |                    nullptr); | 
 |   } | 
 | }; | 
 |  | 
 | template <typename Stack> | 
 | class StackIteratorImpl { | 
 |  public: | 
 |   using Type = typename StackTraits<Stack>::Type; | 
 |   // Iterators must be default-constructable. | 
 |   StackIteratorImpl() : sk_(nullptr), idx_(0) {} | 
 |   StackIteratorImpl(const Stack *sk, size_t idx) : sk_(sk), idx_(idx) {} | 
 |  | 
 |   bool operator==(StackIteratorImpl other) const { | 
 |     return sk_ == other.sk_ && idx_ == other.idx_; | 
 |   } | 
 |   bool operator!=(StackIteratorImpl other) const { | 
 |     return !(*this == other); | 
 |   } | 
 |  | 
 |   Type *operator*() const { | 
 |     return reinterpret_cast<Type *>( | 
 |         sk_value(reinterpret_cast<const _STACK *>(sk_), idx_)); | 
 |   } | 
 |  | 
 |   StackIteratorImpl &operator++(/* prefix */) { | 
 |     idx_++; | 
 |     return *this; | 
 |   } | 
 |  | 
 |   StackIteratorImpl operator++(int /* postfix */) { | 
 |     StackIteratorImpl copy(*this); | 
 |     ++(*this); | 
 |     return copy; | 
 |   } | 
 |  | 
 |  private: | 
 |   const Stack *sk_; | 
 |   size_t idx_; | 
 | }; | 
 |  | 
 | template <typename Stack> | 
 | using StackIterator = | 
 |     std::enable_if_t<StackTraits<Stack>::kIsStack, StackIteratorImpl<Stack>>; | 
 |  | 
 | }  // namespace internal | 
 |  | 
 | // PushToStack pushes |elem| to |sk|. It returns true on success and false on | 
 | // allocation failure. | 
 | template <typename Stack> | 
 | inline std::enable_if_t<!internal::StackTraits<Stack>::kIsConst, bool> | 
 | PushToStack(Stack *sk, | 
 |             UniquePtr<typename internal::StackTraits<Stack>::Type> elem) { | 
 |   if (!sk_push(reinterpret_cast<_STACK *>(sk), elem.get())) { | 
 |     return false; | 
 |   } | 
 |   // sk_push takes ownership on success. | 
 |   elem.release(); | 
 |   return true; | 
 | } | 
 |  | 
 | BSSL_NAMESPACE_END | 
 |  | 
 | // Define begin() and end() for stack types so C++ range for loops work. | 
 | template <typename Stack> | 
 | inline bssl::internal::StackIterator<Stack> begin(const Stack *sk) { | 
 |   return bssl::internal::StackIterator<Stack>(sk, 0); | 
 | } | 
 |  | 
 | template <typename Stack> | 
 | inline bssl::internal::StackIterator<Stack> end(const Stack *sk) { | 
 |   return bssl::internal::StackIterator<Stack>( | 
 |       sk, sk_num(reinterpret_cast<const _STACK *>(sk))); | 
 | } | 
 |  | 
 | }  // extern C++ | 
 | #endif | 
 |  | 
 | #endif  // OPENSSL_HEADER_STACK_H |