gnunet-android

GNUnet for Android
Log | Files | Refs | README

stack.h (31966B)


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