堆栈介绍
- 堆栈是一种先进后出的数据结构
- openssl 大量采用堆栈来存放数据。它实现了一 个通用的堆栈,可以方便的存储任意数据
- 它实现了许多基本的堆栈操作,主要有:堆栈拷贝(sk_dup)、构建新堆栈(sk_new_null,sk_new)、插入数据(sk_insert)、删除数据(sk_delete)、查找数据(sk_find,sk_find_ex)、入栈(sk_push)、出栈(sk_pop)、获取堆栈元素个数(sk_num)、获取堆栈值(sk_value)、设置堆栈值(sk_set)和堆栈排序(sk_sort)
数据结构
- openssl 堆栈数据结构在 stack.h 中
- stack.h 位于 include/openssl文件夹下
- 定义位于crypto/stack文件夹下的stack.c文件内,具体内容如下:
stack.h
/** Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.** Licensed under the OpenSSL license (the "License"). You may not use* this file except in compliance with the License. You can obtain a copy* in the file LICENSE in the source distribution or at* https://www.openssl.org/source/license.html*/#ifndef HEADER_STACK_H
# define HEADER_STACK_H#ifdef __cplusplus
extern "C" {
#endiftypedef struct stack_st OPENSSL_STACK; /* Use STACK_OF(...) instead */typedef int (*OPENSSL_sk_compfunc)(const void *, const void *);
typedef void (*OPENSSL_sk_freefunc)(void *);
typedef void *(*OPENSSL_sk_copyfunc)(const void *);int OPENSSL_sk_num(const OPENSSL_STACK *);
void *OPENSSL_sk_value(const OPENSSL_STACK *, int);void *OPENSSL_sk_set(OPENSSL_STACK *st, int i, const void *data);OPENSSL_STACK *OPENSSL_sk_new(OPENSSL_sk_compfunc cmp);
OPENSSL_STACK *OPENSSL_sk_new_null(void);
void OPENSSL_sk_free(OPENSSL_STACK *);
void OPENSSL_sk_pop_free(OPENSSL_STACK *st, void (*func) (void *));
OPENSSL_STACK *OPENSSL_sk_deep_copy(const OPENSSL_STACK *, OPENSSL_sk_copyfunc c, OPENSSL_sk_freefunc f);
int OPENSSL_sk_insert(OPENSSL_STACK *sk, const void *data, int where);
void *OPENSSL_sk_delete(OPENSSL_STACK *st, int loc);
void *OPENSSL_sk_delete_ptr(OPENSSL_STACK *st, const void *p);
int OPENSSL_sk_find(OPENSSL_STACK *st, const void *data);
int OPENSSL_sk_find_ex(OPENSSL_STACK *st, const void *data);
int OPENSSL_sk_push(OPENSSL_STACK *st, const void *data);
int OPENSSL_sk_unshift(OPENSSL_STACK *st, const void *data);
void *OPENSSL_sk_shift(OPENSSL_STACK *st);
void *OPENSSL_sk_pop(OPENSSL_STACK *st);
void OPENSSL_sk_zero(OPENSSL_STACK *st);
OPENSSL_sk_compfunc OPENSSL_sk_set_cmp_func(OPENSSL_STACK *sk, OPENSSL_sk_compfunc cmp);
OPENSSL_STACK *OPENSSL_sk_dup(const OPENSSL_STACK *st);
void OPENSSL_sk_sort(OPENSSL_STACK *st);
int OPENSSL_sk_is_sorted(const OPENSSL_STACK *st);# if OPENSSL_API_COMPAT < 0x10100000L
# define _STACK OPENSSL_STACK
# define sk_num OPENSSL_sk_num
# define sk_value OPENSSL_sk_value
# define sk_set OPENSSL_sk_set
# define sk_new OPENSSL_sk_new
# define sk_new_null OPENSSL_sk_new_null
# define sk_free OPENSSL_sk_free
# define sk_pop_free OPENSSL_sk_pop_free
# define sk_deep_copy OPENSSL_sk_deep_copy
# define sk_insert OPENSSL_sk_insert
# define sk_delete OPENSSL_sk_delete
# define sk_delete_ptr OPENSSL_sk_delete_ptr
# define sk_find OPENSSL_sk_find
# define sk_find_ex OPENSSL_sk_find_ex
# define sk_push OPENSSL_sk_push
# define sk_unshift OPENSSL_sk_unshift
# define sk_shift OPENSSL_sk_shift
# define sk_pop OPENSSL_sk_pop
# define sk_zero OPENSSL_sk_zero
# define sk_set_cmp_func OPENSSL_sk_set_cmp_func
# define sk_dup OPENSSL_sk_dup
# define sk_sort OPENSSL_sk_sort
# define sk_is_sorted OPENSSL_sk_is_sorted
# endif#ifdef __cplusplus
}
#endif#endif
stack.cpp
/** Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.** Licensed under the OpenSSL license (the "License"). You may not use* this file except in compliance with the License. You can obtain a copy* in the file LICENSE in the source distribution or at* https://www.openssl.org/source/license.html*/#include <stdio.h>
#include "internal/cryptlib.h"
#include "internal/numbers.h"
#include <openssl/stack.h>
#include <openssl/objects.h>struct stack_st {int num;const char **data;int sorted;size_t num_alloc;OPENSSL_sk_compfunc comp;
};#undef MIN_NODES
#define MIN_NODES 4#include <errno.h>OPENSSL_sk_compfunc OPENSSL_sk_set_cmp_func(OPENSSL_STACK *sk, OPENSSL_sk_compfunc c)
{OPENSSL_sk_compfunc old = sk->comp;if (sk->comp != c)sk->sorted = 0;sk->comp = c;return old;
}OPENSSL_STACK *OPENSSL_sk_dup(const OPENSSL_STACK *sk)
{OPENSSL_STACK *ret;if (sk->num < 0)return NULL;if ((ret = OPENSSL_malloc(sizeof(*ret))) == NULL)return NULL;/* direct structure assignment */*ret = *sk;if ((ret->data = OPENSSL_malloc(sizeof(*ret->data) * sk->num_alloc)) == NULL)goto err;memcpy(ret->data, sk->data, sizeof(char *) * sk->num);return ret;err:OPENSSL_sk_free(ret);return NULL;
}OPENSSL_STACK *OPENSSL_sk_deep_copy(const OPENSSL_STACK *sk,OPENSSL_sk_copyfunc copy_func,OPENSSL_sk_freefunc free_func)
{OPENSSL_STACK *ret;int i;if (sk->num < 0)return NULL;if ((ret = OPENSSL_malloc(sizeof(*ret))) == NULL)return NULL;/* direct structure assignment */*ret = *sk;ret->num_alloc = sk->num > MIN_NODES ? (size_t)sk->num : MIN_NODES;ret->data = OPENSSL_zalloc(sizeof(*ret->data) * ret->num_alloc);if (ret->data == NULL) {OPENSSL_free(ret);return NULL;}for (i = 0; i < ret->num; ++i) {if (sk->data[i] == NULL)continue;if ((ret->data[i] = copy_func(sk->data[i])) == NULL) {while (--i >= 0)if (ret->data[i] != NULL)free_func((void *)ret->data[i]);OPENSSL_sk_free(ret);return NULL;}}return ret;
}OPENSSL_STACK *OPENSSL_sk_new_null(void)
{return OPENSSL_sk_new((OPENSSL_sk_compfunc)NULL);
}OPENSSL_STACK *OPENSSL_sk_new(OPENSSL_sk_compfunc c)
{OPENSSL_STACK *ret;if ((ret = OPENSSL_zalloc(sizeof(*ret))) == NULL)goto err;if ((ret->data = OPENSSL_zalloc(sizeof(*ret->data) * MIN_NODES)) == NULL)goto err;ret->comp = c;ret->num_alloc = MIN_NODES;return (ret);err:OPENSSL_free(ret);return (NULL);
}int OPENSSL_sk_insert(OPENSSL_STACK *st, const void *data, int loc)
{if (st == NULL || st->num < 0 || st->num == INT_MAX) {return 0;}if (st->num_alloc <= (size_t)(st->num + 1)) {size_t doub_num_alloc = st->num_alloc * 2;const char **tmpdata;/* Overflow checks */if (doub_num_alloc < st->num_alloc)return 0;/* Avoid overflow due to multiplication by sizeof(char *) */if (doub_num_alloc > SIZE_MAX / sizeof(char *))return 0;tmpdata = OPENSSL_realloc((char *)st->data,sizeof(char *) * doub_num_alloc);if (tmpdata == NULL)return 0;st->data = tmpdata;st->num_alloc = doub_num_alloc;}if ((loc >= st->num) || (loc < 0)) {st->data[st->num] = data;} else {memmove(&st->data[loc + 1], &st->data[loc],sizeof(st->data[0]) * (st->num - loc));st->data[loc] = data;}st->num++;st->sorted = 0;return st->num;
}void *OPENSSL_sk_delete_ptr(OPENSSL_STACK *st, const void *p)
{int i;for (i = 0; i < st->num; i++)if (st->data[i] == p)return OPENSSL_sk_delete(st, i);return NULL;
}void *OPENSSL_sk_delete(OPENSSL_STACK *st, int loc)
{const char *ret;if (st == NULL || loc < 0 || loc >= st->num)return NULL;ret = st->data[loc];if (loc != st->num - 1)memmove(&st->data[loc], &st->data[loc + 1],sizeof(st->data[0]) * (st->num - loc - 1));st->num--;return (void *)ret;
}static int internal_find(OPENSSL_STACK *st, const void *data,int ret_val_options)
{const void *r;int i;if (st == NULL)return -1;if (st->comp == NULL) {for (i = 0; i < st->num; i++)if (st->data[i] == data)return (i);return (-1);}OPENSSL_sk_sort(st);if (data == NULL)return (-1);r = OBJ_bsearch_ex_(&data, st->data, st->num, sizeof(void *), st->comp,ret_val_options);if (r == NULL)return (-1);return (int)((const char **)r - st->data);
}int OPENSSL_sk_find(OPENSSL_STACK *st, const void *data)
{return internal_find(st, data, OBJ_BSEARCH_FIRST_VALUE_ON_MATCH);
}int OPENSSL_sk_find_ex(OPENSSL_STACK *st, const void *data)
{return internal_find(st, data, OBJ_BSEARCH_VALUE_ON_NOMATCH);
}int OPENSSL_sk_push(OPENSSL_STACK *st, const void *data)
{return (OPENSSL_sk_insert(st, data, st->num));
}int OPENSSL_sk_unshift(OPENSSL_STACK *st, const void *data)
{return (OPENSSL_sk_insert(st, data, 0));
}void *OPENSSL_sk_shift(OPENSSL_STACK *st)
{if (st == NULL)return (NULL);if (st->num <= 0)return (NULL);return (OPENSSL_sk_delete(st, 0));
}void *OPENSSL_sk_pop(OPENSSL_STACK *st)
{if (st == NULL)return (NULL);if (st->num <= 0)return (NULL);return (OPENSSL_sk_delete(st, st->num - 1));
}void OPENSSL_sk_zero(OPENSSL_STACK *st)
{if (st == NULL)return;if (st->num <= 0)return;memset(st->data, 0, sizeof(*st->data) * st->num);st->num = 0;
}void OPENSSL_sk_pop_free(OPENSSL_STACK *st, OPENSSL_sk_freefunc func)
{int i;if (st == NULL)return;for (i = 0; i < st->num; i++)if (st->data[i] != NULL)func((char *)st->data[i]);OPENSSL_sk_free(st);
}void OPENSSL_sk_free(OPENSSL_STACK *st)
{if (st == NULL)return;OPENSSL_free(st->data);OPENSSL_free(st);
}int OPENSSL_sk_num(const OPENSSL_STACK *st)
{if (st == NULL)return -1;return st->num;
}void *OPENSSL_sk_value(const OPENSSL_STACK *st, int i)
{if (st == NULL || i < 0 || i >= st->num)return NULL;return (void *)st->data[i];
}void *OPENSSL_sk_set(OPENSSL_STACK *st, int i, const void *data)
{if (st == NULL || i < 0 || i >= st->num)return NULL;st->data[i] = data;return (void *)st->data[i];
}void OPENSSL_sk_sort(OPENSSL_STACK *st)
{if (st && !st->sorted && st->comp != NULL) {qsort(st->data, st->num, sizeof(char *), st->comp);st->sorted = 1;}
}int OPENSSL_sk_is_sorted(const OPENSSL_STACK *st)
{if (st == NULL)return 1;return st->sorted;
}
数据结构
struct stack_st {int num;const char **data;int sorted;size_t num_alloc;OPENSSL_sk_compfunc comp;
};
- 各项意义如下:
- num: 堆栈中存放数据的个数。
- data: 用于存放数据地址,每个数据地址存放在 data[0]到 data[num-1]中。
- sorted: 堆栈是否已排序,如果排序则值为 1,否则为 0,堆栈数据一般是无序的,只有当用户调用了 sk_sort 操作,其值才为 1。
- comp: 堆栈内存放数据的比较函数地址,此函数用于排序和查找操作;当用户生成一 个新堆栈时,可以指定comp为用户实现的一个比较函数;或当堆栈已经存在 时通过调用 sk_set_cmp_func 函数来重新指定比较函数。
- 注意,用户不需要调用底层的堆栈函数(sk_sort、sk_set_cmp_func 等),而是调用他通过 宏实现的各个函数。
函数介绍
- openssl 堆栈实现源码位于 crypto/stack 目录下。下面分析了部分函数。
- sk_set_cmp_func
- 此函数用于设置堆栈存放数据的比较函数。由于堆栈不知道用户存放的是什么数据,所以,比较函数必须由用户自己实现。
OPENSSL_sk_compfunc OPENSSL_sk_set_cmp_func(OPENSSL_STACK *sk, OPENSSL_sk_compfunc c)
{OPENSSL_sk_compfunc old = sk->comp;if (sk->comp != c)sk->sorted = 0;sk->comp = c;return old;
}
- OPENSSL_sk_dup 堆栈拷贝
- 使用OPSNSSL_malloc进行内存的分配,其实质是调用CRYPTO_malloc进行内存的分配
OPENSSL_STACK *OPENSSL_sk_dup(const OPENSSL_STACK *sk)
{OPENSSL_STACK *ret;if ((ret = OPENSSL_malloc(sizeof(*ret))) == NULL)goto err;if (sk == NULL) {ret->num = 0;ret->sorted = 0;ret->comp = NULL;} else {/* direct structure assignment */*ret = *sk;}if (sk == NULL || sk->num == 0) {/* postpone |ret->data| allocation */ret->data = NULL;ret->num_alloc = 0;return ret;}/* duplicate |sk->data| content */if ((ret->data = OPENSSL_malloc(sizeof(*ret->data) * sk->num_alloc)) == NULL)goto err;memcpy(ret->data, sk->data, sizeof(void *) * sk->num);return ret;err:ERR_raise(ERR_LIB_CRYPTO, ERR_R_MALLOC_FAILURE);OPENSSL_sk_free(ret);return NULL;
}
- C++版本
OPENSSL_STACK *OPENSSL_sk_dup(const OPENSSL_STACK *sk){OPENSSL_STACK *ret;if((ret = reinterpret_cast<OPENSSL_STACK *>(OPENSSL_malloc(sizeof (*ret)))) == nullptr){goto err;}if (sk == nullptr){ret->num = 0;ret->sorted = 0;ret->comp = nullptr;} else{//直接结构赋值*ret = *sk;}if (sk == nullptr || sk->num == 0){//推迟|ret->data|分配ret->data = nullptr;ret->num_alloc = 0;return ret;}// 重复|sk->data|内容if ((ret->data = static_cast<const void **>(OPENSSL_malloc(sizeof((*ret).data) * sk->num_alloc))) == nullptr)goto err;memcpy(ret->data,sk->data,sizeof (void*)*sk->num);return ret;err:ERR_raise(ERR_LIB_CRYPTO,ERR_R_MALLOC_FAILURE);OPENSSL_sk_free(ret);return nullptr;
}
# define OPENSSL_malloc(num) \CRYPTO_malloc(num, OPENSSL_FILE, OPENSSL_LINE)
- *根据配置制作我们自己的__FILE__和__LINE__变体
/** Make our own variants of __FILE__ and __LINE__, depending on configuration*/# ifndef OPENSSL_FILE
# ifdef OPENSSL_NO_FILENAMES
# define OPENSSL_FILE ""
# define OPENSSL_LINE 0
# else
# define OPENSSL_FILE __FILE__
# define OPENSSL_LINE __LINE__
# endif
# endif
- CRYPTO_malloc
- # define INCREMENT(x) /* empty */
void *CRYPTO_malloc(size_t num, const char *file, int line)
{INCREMENT(malloc_count);if (malloc_impl != CRYPTO_malloc)return malloc_impl(num, file, line);if (num == 0)return NULL;FAILTEST();if (allow_customize) {/** Disallow customization after the first allocation. We only set this* if necessary to avoid a store to the same cache line on every* allocation.*/allow_customize = 0;}return malloc(num);
}
- malloc_count 全局静态变量,在openssl里面出现了三次
- 定义位于 mem.c 文件中
- 只要设置了“allow_customize”,就可以更改以下指针
/** the following pointers may be changed as long as 'allow_customize' is set*/static CRYPTO_malloc_fn malloc_impl = CRYPTO_malloc;
- INCREMENT 和 FAILTEST
# define FAILTEST() if (shouldfail()) return NULL#else# define INCREMENT(x) /* empty */
# define FAILTEST() /* empty */
#endif
- *allow_customize 禁止在第一次分配后进行自定义。我们仅在必要时设置此值,以避免在每次分配时将存储存储到相同的缓存行。
OPENSSL_sk_deep_copy 深拷贝
OPENSSL_STACK *OPENSSL_sk_deep_copy(const OPENSSL_STACK *sk,OPENSSL_sk_copyfunc copy_func,OPENSSL_sk_freefunc free_func)
{OPENSSL_STACK *ret;int i;if ((ret = OPENSSL_malloc(sizeof(*ret))) == NULL)goto err;if (sk == NULL) {ret->num = 0;ret->sorted = 0;ret->comp = NULL;} else {/* direct structure assignment */*ret = *sk;}if (sk == NULL || sk->num == 0) {/* postpone |ret| data allocation */ret->data = NULL;ret->num_alloc = 0;return ret;}ret->num_alloc = sk->num > min_nodes ? sk->num : min_nodes;ret->data = OPENSSL_zalloc(sizeof(*ret->data) * ret->num_alloc);if (ret->data == NULL)goto err;for (i = 0; i < ret->num; ++i) {if (sk->data[i] == NULL)continue;if ((ret->data[i] = copy_func(sk->data[i])) == NULL) {while (--i >= 0)if (ret->data[i] != NULL)free_func((void *)ret->data[i]);goto err;}}return ret;err:ERR_raise(ERR_LIB_CRYPTO, ERR_R_MALLOC_FAILURE);OPENSSL_sk_free(ret);return NULL;
}
OPENSSL_STACK *OPENSSL_sk_deep_copy(const OPENSSL_STACK *sk,OPENSSL_sk_copyfunc copy_func,OPENSSL_sk_freefunc free_func)
{OPENSSL_STACK *ret;int j;if ((ret = reinterpret_cast<OPENSSL_STACK *>(OPENSSL_malloc(sizeof (*ret))))== nullptr)goto err;if (sk == nullptr){ret->num = 0;ret->sorted = 0;ret->comp = nullptr;} else{//直接结构赋值*ret = *sk;}if (sk == nullptr || sk->num == 0){//推迟|ret->data|分配ret->data = nullptr;ret->num_alloc = 0;return ret;}ret->num_alloc = sk->num > min_nodes ? sk->num : min_nodes;ret->data = static_cast<const void **>(OPENSSL_zalloc(sizeof(*ret->data) * ret->num_alloc));if (ret->data == nullptr)goto err;for (j = 0; j < ret->num; ++j) {if (sk->data[j] == nullptr)continue;if ((ret->data[j] = copy_func(sk->data[j]))== nullptr){while (--j >= 0)if (ret->data[j]!= nullptr)free_func((void *)ret->data[j]);goto err;}}return ret;err:ERR_raise(ERR_LIB_CRYPTO,ERR_R_MALLOC_FAILURE);OPENSSL_sk_free(ret);return nullptr;
}
# define OPENSSL_zalloc(num) \CRYPTO_zalloc(num, OPENSSL_FILE, OPENSSL_LINE)
- CRYPTO_zalloc 内存分配,内部调用 CRYPTO_malloc
void *CRYPTO_zalloc(size_t num, const char *file, int line)
{void *ret;ret = CRYPTO_malloc(num, file, line);FAILTEST();if (ret != NULL)memset(ret, 0, num);return ret;
}
typedef void *(*OPENSSL_sk_copyfunc)(const void *);
typedef void (*OPENSSL_sk_freefunc)(void *);
/* Main error raising functions */
# define ERR_raise(lib, reason) ERR_raise_data((lib),(reason),NULL)
# define ERR_raise_data \(ERR_new(), \ERR_set_debug(OPENSSL_FILE,OPENSSL_LINE,OPENSSL_FUNC), \ERR_set_error)
void ERR_new(void)
{c_new_error(NULL);
}void ERR_set_debug(const char *file, int line, const char *func)
{c_set_error_debug(NULL, file, line, func);
}void ERR_set_error(int lib, int reason, const char *fmt, ...)
{va_list args;va_start(args, fmt);c_vset_error(NULL, ERR_PACK(lib, 0, reason), fmt, args);va_end(args);
}
void OPENSSL_sk_free(OPENSSL_STACK *st)
{if (st == NULL)return;OPENSSL_free(st->data);OPENSSL_free(st);
}
OPENSSL_sk_new_reserve
OPENSSL_STACK *OPENSSL_sk_new_null(void)
{return OPENSSL_sk_new_reserve(NULL, 0);
}
OPENSSL_sk_new
OPENSSL_STACK *OPENSSL_sk_new(OPENSSL_sk_compfunc c)
{return OPENSSL_sk_new_reserve(c, 0);
}
OPENSSL_sk_new_reserve
OPENSSL_STACK *OPENSSL_sk_new_reserve(OPENSSL_sk_compfunc c, int n)
{OPENSSL_STACK *st = reinterpret_cast<OPENSSL_STACK *>(OPENSSL_zalloc(sizeof(OPENSSL_STACK)));if (st == NULL)return NULL;st->comp = c;if (n <= 0)return st;if (!sk_reserve(st, n, 1)) {OPENSSL_sk_free(st);return NULL;}return st;
}
sk_reserve
/* internal STACK storage allocation */
static int sk_reserve(OPENSSL_STACK *st, int n, int exact)
{const void **tmpdata;int num_alloc;//检查预订是否超过硬限制if (n > max_nodes - st->num){return 0;}//指出新的大小num_alloc = st->num + n;if (num_alloc < min_nodes){num_alloc = min_nodes;}//如果 |st->data| 分配被推迟if (st->data == nullptr){//此时,|st->num_alloc| 和 |st->num| 是 0//所以 |num_alloc| 值为 |n| 或 |min_nodes| 如果大于 |n|if((st->data = static_cast<const void **>(OPENSSL_zalloc(sizeof (void *)*num_alloc)))== nullptr){ERR_raise(ERR_LIB_CRYPTO,ERR_R_MALLOC_FAILURE);return 0;}st->num_alloc = num_alloc;return 1;}if (!exact){if (num_alloc <= st->num_alloc)return 1;num_alloc = compute_growth(num_alloc,st->num_alloc);if (num_alloc == 0)return 0;} else if (num_alloc == st->num_alloc){return 1;}tmpdata = static_cast<const void **>(OPENSSL_realloc((void *)st->data, sizeof(void *) * num_alloc));if (tmpdata == NULL)return 0;st->data = tmpdata;st->num_alloc = num_alloc;return 1;
}
compute_growth
/** 根据目标大小计算数组增长。** 增长分数是有理数,由分子和分母定义。 根据 Andrew Koenig 在他的论文“为什么向量是有效的?”中的说法。 从 JOOP 11(5) 1998 开始,这个因子应该小于黄金比例 (1.618...)。** 我们使用 3/2 = 1.5 来简化计算和溢出检查。另一个选项 8/5 = 1.6 允许稍微更快的增长,尽管安全计算更加困难。** 避免溢出的限制是正确的。 模三校正项确保限制是在不超过硬限制的情况下可以通过增长因子扩展的最大数。** 不要用 |current| 调用它 小于2,否则会无限循环。*/
static ossl_inline int compute_growth(int target,int current){const int limit = (max_nodes / 3)*2 + (max_nodes % 3 ? 1: 0);while(current < target){//检查我们是否处于硬限制if (current >= max_nodes)return 0;//如果在范围内,则将大小扩大 3/2 倍current = current < limit ? current + current / 2 : max_nodes;}return current;
}
OPENSSL_sk_reserve
int OPENSSL_sk_reserve(OPENSSL_STACK *st, int n)
{if (st == NULL)return 0;if (n < 0)return 1;return sk_reserve(st, n, 1);
}
OPENSSL_sk_insert
- C 库函数 – memmove() | 菜鸟教程
int OPENSSL_sk_insert(OPENSSL_STACK *st,const void *data,int loc)
{if (st == nullptr || st->num == max_nodes){return 0;}if (!sk_reserve(st,1,0))return 0;if ((loc >= st->num) || (loc < 0)){st->data[st->num] = data;} else{memmove(&st->data[loc+1],&st->data[loc],sizeof(st->data[0]) * (st->num - loc));st->data[loc] = data;}st->num++;st->sorted = 0;return st->num;
}
internal_delete
static ossl_inline void * internal_delete(OPENSSL_STACK *st,int loc){const void *ret = st->data[loc];if (loc != st->num-1){memmove(&st->data[loc],&st->data[loc+1],sizeof (st->data[0]) * (st->num - loc -1));}st->num--;return (void*)ret;
}
OPENSSL_sk_delete_ptr
void* OPENSSL_sk_delete_ptr(OPENSSL_STACK *st,const void *p){for (int j = 0; j < st->num; ++j) {if (st->data[j]==p)return internal_delete(st,j);}return nullptr;
}
OPENSSL_sk_delete
void *OPENSSL_sk_delete(OPENSSL_STACK *st,int loc)
{if (st == nullptr || loc < 0 || loc >= st->num){return nullptr;}return internal_delete(st,loc);
}
internal_find
- 根据数据地址来查找它在堆栈中的位置。当堆栈设置了比较函数时,它首先对堆栈进行排序,然后通过二分法进行查找。
- 如果堆栈没有设置比较函数,它只是简单的比较数据地址来查找
static int internal_find(OPENSSL_STACK *st,const void *data,int ret_val_options,int *pnum)
{const void *r = nullptr;if (st == nullptr || st->num == 0){return -1;}//未排序 采用循环遍历的方式进行查找if (st->comp == nullptr){for (int i = 0; i < st->num; ++i) {if (st->data[i] == data){if (pnum != nullptr)*pnum = 1;return i;}if (pnum != nullptr){*pnum = 0;}return -1;}}//根据comp比较函数进行快速排序if (!st->sorted){if (st->num > 1)qsort(st->data,st->num,sizeof (void*),st->comp);st->sorted = 1; //空或单元素堆栈被视为已排序}if (data == nullptr)return -1;if (pnum != nullptr)ret_val_options |= OSSL_BSEARCH_FIRST_VALUE_ON_MATCH;r = ossl_bsearch(&data,st->data,st->num,sizeof(void*),st->comp,ret_val_options);if (pnum != nullptr){*pnum = 0;if (r != nullptr){const void **p = (const void **)r;while (p < st->data + st->num){if (st->comp(&data,p) != 0)break;++*pnum;++p;}}}return r == nullptr ? -1 : (int)((const void **)r - st->data);
}
ossl_bsearch
- C 库函数 – bsearch() | 菜鸟教程
#include <stddef.h>
#include "internal/cryptlib.h"const void *ossl_bsearch(const void *key, const void *base, int num,int size, int (*cmp) (const void *, const void *),int flags)
{const char *base_ = base;int l, h, i = 0, c = 0;const char *p = NULL;if (num == 0)return NULL;l = 0;h = num;while (l < h) {i = (l + h) / 2;p = &(base_[i * size]);c = (*cmp) (key, p);if (c < 0)h = i;else if (c > 0)l = i + 1;elsebreak;}if (c != 0 && !(flags & OSSL_BSEARCH_VALUE_ON_NOMATCH))p = NULL;else if (c == 0 && (flags & OSSL_BSEARCH_FIRST_VALUE_ON_MATCH)) {while (i > 0 && (*cmp) (key, &(base_[(i - 1) * size])) == 0)i--;p = &(base_[i * size]);}return p;
}
/* Function for simple binary search *//* Flags */
# define OSSL_BSEARCH_VALUE_ON_NOMATCH 0x01
# define OSSL_BSEARCH_FIRST_VALUE_ON_MATCH 0x02
OPENSSL_sk_find
int OPENSSL_sk_find(OPENSSL_STACK *st, const void *data)
{return internal_find(st, data, OSSL_BSEARCH_FIRST_VALUE_ON_MATCH, NULL);
}
OPENSSL_sk_find_ex
int OPENSSL_sk_find_ex(OPENSSL_STACK *st, const void *data)
{return internal_find(st, data, OSSL_BSEARCH_VALUE_ON_NOMATCH, NULL);
}
OPENSSL_sk_find_all
int OPENSSL_sk_find_all(OPENSSL_STACK *st, const void *data, int *pnum)
{return internal_find(st, data, OSSL_BSEARCH_FIRST_VALUE_ON_MATCH, pnum);
}
OPENSSL_sk_push
int OPENSSL_sk_push(OPENSSL_STACK *st, const void *data)
{if (st == NULL)return -1;return OPENSSL_sk_insert(st, data, st->num);
}
OPENSSL_sk_unshift
int OPENSSL_sk_unshift(OPENSSL_STACK *st, const void *data)
{return OPENSSL_sk_insert(st, data, 0);
}
OPENSSL_sk_shift
void *OPENSSL_sk_shift(OPENSSL_STACK *st)
{if (st == NULL || st->num == 0)return NULL;return internal_delete(st, 0);
}
OPENSSL_sk_pop
void *OPENSSL_sk_pop(OPENSSL_STACK *st)
{if (st == NULL || st->num == 0)return NULL;return internal_delete(st, st->num - 1);
}
OPENSSL_sk_zero
void OPENSSL_sk_zero(OPENSSL_STACK *st)
{if (st == NULL || st->num == 0)return;memset(st->data, 0, sizeof(*st->data) * st->num);st->num = 0;
}
OPENSSL_sk_pop_free
- 释放data和结构体
void OPENSSL_sk_pop_free(OPENSSL_STACK *st, OPENSSL_sk_freefunc func)
{int i;if (st == NULL)return;for (i = 0; i < st->num; i++)if (st->data[i] != NULL)func((char *)st->data[i]);OPENSSL_sk_free(st);
}
OPENSSL_sk_free
void OPENSSL_sk_free(OPENSSL_STACK *st)
{if (st == NULL)return;OPENSSL_free(st->data);OPENSSL_free(st);
}
OPENSSL_sk_num
int OPENSSL_sk_num(const OPENSSL_STACK *st)
{return st == NULL ? -1 : st->num;
}
OPENSSL_sk_value
void *OPENSSL_sk_value(const OPENSSL_STACK *st, int i)
{if (st == NULL || i < 0 || i >= st->num)return NULL;return (void *)st->data[i];
}
OPENSSL_sk_set
void *OPENSSL_sk_set(OPENSSL_STACK *st, int i, const void *data)
{if (st == NULL || i < 0 || i >= st->num)return NULL;st->data[i] = data;st->sorted = 0;return (void *)st->data[i];
}
OPENSSL_sk_sort
- 本函数对堆栈数据排序。它首先根据sorted来判断是否已经排序,如果未排序 则调用了标准C 函数qsort 进行快速排序。
void OPENSSL_sk_sort(OPENSSL_STACK *st)
{if (st != NULL && !st->sorted && st->comp != NULL) {if (st->num > 1)qsort(st->data, st->num, sizeof(void *), st->comp);st->sorted = 1; /* empty or single-element stack is considered sorted */}
}
OPENSSL_sk_is_sorted
int OPENSSL_sk_is_sorted(const OPENSSL_STACK *st)
{return st == NULL ? 1 : st->sorted;
}