【10】Strongswan collections —— array

news2025/3/31 20:06:02

//array 代码解释与测试

#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#include <stdarg.h>

#define INIT(this, ...) ({ (this) = malloc(sizeof(*(this))); \
                           *(this) = (typeof(*(this))){ __VA_ARGS__ }; (this); })

#define TRUE true
#define FALSE false

#define METHOD(iface, name, ret, this, ...) \
    static ret name(union {iface *_public; this;} \
    __attribute__((transparent_union)), ##__VA_ARGS__); \
    static typeof(name) *_##name = (typeof(name)*)name; \
    static ret name(this, ##__VA_ARGS__)

/** 清理前未使用的头部/尾部元素的最大数量 */
#define ARRAY_MAX_UNUSED 32


/**
 * This macro allows counting the number of arguments passed to a macro.
 * Combined with the VA_ARGS_DISPATCH() macro this can be used to implement
 * macro overloading based on the number of arguments.
 * 0 to 10 arguments are currently supported.
 */
#define VA_ARGS_NUM(...) _VA_ARGS_NUM(0,##__VA_ARGS__,10,9,8,7,6,5,4,3,2,1,0)
#define _VA_ARGS_NUM(_0,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,NUM,...) NUM

/**
 * This macro can be used to dispatch a macro call based on the number of given
 * arguments, for instance:
 *
 * @code
 * #define MY_MACRO(...) VA_ARGS_DISPATCH(MY_MACRO, __VA_ARGS__)(__VA_ARGS__)
 * #define MY_MACRO1(arg) one_arg(arg)
 * #define MY_MACRO2(arg1,arg2) two_args(arg1,arg2)
 * @endcode
 *
 * MY_MACRO() can now be called with either one or two arguments, which will
 * resolve to one_arg(arg) or two_args(arg1,arg2), respectively.
 */
#define VA_ARGS_DISPATCH(func, ...) _VA_ARGS_DISPATCH(func, VA_ARGS_NUM(__VA_ARGS__))
#define _VA_ARGS_DISPATCH(func, num) __VA_ARGS_DISPATCH(func, num)
#define __VA_ARGS_DISPATCH(func, num) func ## num

/**
 * Assign variadic arguments to the given variables.
 *
 * @note The order and types of the variables are significant and must match the
 * variadic arguments passed to the function that calls this macro exactly.
 *
 * @param last		the last argument before ... in the function that calls this
 * @param ...		variable names
 */
#define VA_ARGS_GET(last, ...) ({ \
    va_list _va_args_get_ap; \
    va_start(_va_args_get_ap, last); \
    _VA_ARGS_GET_ASGN(__VA_ARGS__) \
    va_end(_va_args_get_ap); \
})

/**
 * Assign variadic arguments from a va_list to the given variables.
 *
 * @note The order and types of the variables are significant and must match the
 * variadic arguments passed to the function that calls this macro exactly.
 *
 * @param list		the va_list variable in the function that calls this
 * @param ...		variable names
 */
#define VA_ARGS_VGET(list, ...) ({ \
    va_list _va_args_get_ap; \
    va_copy(_va_args_get_ap, list); \
    _VA_ARGS_GET_ASGN(__VA_ARGS__) \
    va_end(_va_args_get_ap); \
})

#define _VA_ARGS_GET_ASGN(...) VA_ARGS_DISPATCH(_VA_ARGS_GET_ASGN, __VA_ARGS__)(__VA_ARGS__)
#define _VA_ARGS_GET_ASGN1(v1) __VA_ARGS_GET_ASGN(v1)
#define _VA_ARGS_GET_ASGN2(v1,v2) __VA_ARGS_GET_ASGN(v1) __VA_ARGS_GET_ASGN(v2)
#define _VA_ARGS_GET_ASGN3(v1,v2,v3) __VA_ARGS_GET_ASGN(v1) __VA_ARGS_GET_ASGN(v2) \
    __VA_ARGS_GET_ASGN(v3)
#define _VA_ARGS_GET_ASGN4(v1,v2,v3,v4) __VA_ARGS_GET_ASGN(v1) __VA_ARGS_GET_ASGN(v2) \
    __VA_ARGS_GET_ASGN(v3) __VA_ARGS_GET_ASGN(v4)
#define _VA_ARGS_GET_ASGN5(v1,v2,v3,v4,v5) __VA_ARGS_GET_ASGN(v1) __VA_ARGS_GET_ASGN(v2) \
    __VA_ARGS_GET_ASGN(v3) __VA_ARGS_GET_ASGN(v4) __VA_ARGS_GET_ASGN(v5)
#define __VA_ARGS_GET_ASGN(v) v = va_arg(_va_args_get_ap, typeof(v));


typedef struct array_t array_t;

/**
 * Special array index values for insert/remove.
 */
enum array_idx_t {
    ARRAY_HEAD = 0,
    ARRAY_TAIL = -1,
};


/**
 * 数据是一个已分配的数据块,可能有未使用的头部和尾部:
 *
 *   "esize" each (or sizeof(void*) if esize = 0)
 *  /-\ /-\ /-\ /-\ /-\ /-\
 *
 * +---------------+-------------------------------+---------------+
 * | h | e | a | d | e | l | e | m | e | n | t | s | t | a | i | l |
 * +---------------+-------------------------------+---------------+
 *
 * \--------------/ \-----------------------------/ \-------------/
 *      unused                    used                   unused
 *      "head"                   "count"                 "tail"
 *
 */
struct array_t {
    /** 数组中当前元素的个数(不包括头尾元素) */
    uint32_t count;
    /** 每个元素的大小,指针式数组元素大小为 0 */
    uint16_t esize;
    /** 数组前部已分配但未使用的元素个数 */
    uint8_t head;
    /** 数组末尾已分配但未使用的元素个数 */
    uint8_t tail;
    /** 数值元素 */
    void *data;
};

/**
 * 获取数组若干元素的实际大小
 */
static size_t get_size(array_t *array, uint32_t num)
{
    if (array->esize)
    {
        return (size_t)array->esize * num;
    }
    return sizeof(void*) * num;
}

/**
 * 增加tail个空间到room个数字节的空间
 */
static void make_tail_room(array_t *array, uint8_t room)
{
    if (array->tail < room)
    {
        array->data = realloc(array->data,
                        get_size(array, array->count + array->head + room));
        array->tail = room;
    }
}

/**
 * 增加head个空间到room个数的字节数
 */
static void make_head_room(array_t *array, uint8_t room)
{
    if (array->head < room)
    {
        uint8_t increase = room - array->head;

        array->data = realloc(array->data,
                        get_size(array, array->count + array->tail + room));
        memmove(array->data + get_size(array, increase), array->data,
                get_size(array, array->count + array->tail + array->head));
        array->head = room;
    }
}

/**
 * 向count区插入一个数据,插入位置之后数据向后move,占用tail区一个空间
 */
static void insert_tail(array_t *array, int idx)
{
    make_tail_room(array, 1);
    memmove(array->data + get_size(array, array->head + idx + 1),
            array->data + get_size(array, array->head + idx),
            get_size(array, array->count - idx));

    array->tail--;
    array->count++;
}

/**
 * head区减少1个空间当作count区空间,count区数据整体向head区移动一个空间
 */
static void insert_head(array_t *array, int idx)
{
    make_head_room(array, 1);
    /* move down all elements before idx by one */
    memmove(array->data + get_size(array, array->head - 1),
            array->data + get_size(array, array->head),
            get_size(array, idx));

    array->head--;
    array->count++;
}

/**
 * count区移走一个,移走区之后数据前移一个
 */
static void remove_tail(array_t *array, int idx)
{
    /* move all items after idx one down */
    memmove(array->data + get_size(array, idx + array->head),
            array->data + get_size(array, idx + array->head + 1),
            get_size(array, array->count - 1 - idx));
    array->count--;
    array->tail++;
}

/**
 * head区多1,count区少1
 */
static void remove_head(array_t *array, int idx)
{
    /* move all items before idx one up */
    memmove(array->data + get_size(array, array->head + 1),
            array->data + get_size(array, array->head), get_size(array, idx));
    array->count--;
    array->head++;
}

array_t *array_create(u_int esize, uint8_t reserve)
{
    array_t *array;

    INIT(array,
        .esize = esize,
        .tail = reserve,
    );
    if (array->tail)
    {
        //初始分配tail个空间
        array->data = malloc(get_size(array, array->tail));
    }
    return array;
}

int array_count(array_t *array)
{
    if (array)
    {
        return array->count;
    }
    return 0;
}

void array_compress(array_t *array)
{
    if (array)
    {
        uint32_t tail;

        tail = array->tail;
        //去头
        if (array->head)
        {
            memmove(array->data, array->data + get_size(array, array->head),
                    get_size(array, array->count + array->tail));
            tail += array->head;
            array->head = 0;
        }
        //丢弃tail数据,保留count数据
        if (tail)
        {
            size_t size = get_size(array, array->count);

            if (size)
            {
                array->data = realloc(array->data, size);
            }
            else
            {
                free(array->data);
                array->data = NULL;
            }
            array->tail = 0;
        }
    }
}


typedef struct enumerator_t enumerator_t;

/**
 * Enumerator interface, allows enumeration over collections.
 */
struct enumerator_t {
    bool (*enumerate)(enumerator_t *this, ...);
    bool (*venumerate)(enumerator_t *this, va_list args);
    void (*destroy)(enumerator_t *this);
};

bool enumerator_enumerate_default(enumerator_t *enumerator, ...)
{
    va_list args;
    bool result;

    if (!enumerator->venumerate)
    {
        return FALSE;
    }
    va_start(args, enumerator);
    result = enumerator->venumerate(enumerator, args);
    va_end(args);
    return result;
}

METHOD(enumerator_t, enumerate_empty, bool,
    enumerator_t *enumerator, va_list args)
{
    return FALSE;
}



typedef struct {
    /** public enumerator interface */
    enumerator_t public;
    /** enumerated array */
    array_t *array;
    /** current index +1, initialized at 0 */
    int idx;
} array_enumerator_t;

METHOD(enumerator_t, enumerate, bool,
    array_enumerator_t *this, va_list args)
{
    void *pos, **out;

    VA_ARGS_VGET(args, out);

    //idx在count范围内移动,下标从0开始
    if (this->idx >= this->array->count)
    {
        return FALSE;
    }

    //偏移   + this->array->head到count区,this->idx +到偏移位置
    pos = this->array->data +
          get_size(this->array, this->idx + this->array->head);
    if (this->array->esize)
    {
        //返回位置指针
        *out = pos;
    }
    else
    {
        //指针数组则,返回数组中保存的指针
        *out = *(void**)pos;
    }
    //为枚举下一个做准备
    this->idx++;
    return TRUE;
}

enumerator_t* enumerator_create_empty()
{
    enumerator_t *this;

    INIT(this,
        .enumerate = enumerator_enumerate_default,
        .venumerate = _enumerate_empty,
        .destroy = (void*)free,
    );
    return this;
}

enumerator_t* array_create_enumerator(array_t *array)
{
    array_enumerator_t *enumerator;

    if (!array)
    {
        return enumerator_create_empty();
    }

    INIT(enumerator,
        .public = {
            .enumerate = enumerator_enumerate_default,
            .venumerate = _enumerate,
            .destroy = (void*)free,
        },
        .array = array,
    );
    return &enumerator->public;
}

void array_insert(array_t *array, int idx, void *data)
{
    if (idx < 0 || idx <= array_count(array))
    {
        void *pos;

        if (idx < 0)
        {
            idx = array_count(array);
        }

        if (array->head && !array->tail)
        {
            insert_head(array, idx);
        }
        else if (array->tail && !array->head)
        {
            insert_tail(array, idx);
        }
        else if (idx > array_count(array) / 2)
        {
            insert_tail(array, idx);
        }
        else
        {
            insert_head(array, idx);
        }

        pos = array->data + get_size(array, array->head + idx);
        if (array->esize)
        {
            memcpy(pos, data, get_size(array, 1));
        }
        else
        {
            /* pointer based array, copy pointer value */
            *(void**)pos = data;
        }
    }
}

bool array_get(array_t *array, int idx, void *data)
{
    if (!array)
    {
        return FALSE;
    }
    if (idx >= 0 && idx >= array_count(array))
    {
        return FALSE;
    }
    if (idx < 0)
    {
        if (array_count(array) == 0)
        {
            return FALSE;
        }
        idx = array_count(array) - 1;
    }
    if (data)
    {
        memcpy(data, array->data + get_size(array, array->head + idx),
               get_size(array, 1));
    }
    return TRUE;
}

bool array_remove(array_t *array, int idx, void *data)
{
    if (!array_get(array, idx, data))
    {
        return FALSE;
    }
    if (idx < 0)
    {
        idx = array_count(array) - 1;
    }
    if (idx > array_count(array) / 2)
    {
        remove_tail(array, idx);
    }
    else
    {
        remove_head(array, idx);
    }
    if (array->head + array->tail > ARRAY_MAX_UNUSED)
    {
        array_compress(array);
    }
    return TRUE;
}


void array_remove_at(array_t *array, enumerator_t *public)
{
    array_enumerator_t *enumerator = (array_enumerator_t*)public;

    if (enumerator->idx)
    {
        array_remove(array, --enumerator->idx, NULL);
    }
}

void array_insert_create(array_t **array, int idx, void *ptr)
{
    if (*array == NULL)
    {
        *array = array_create(0, 0);
    }
    array_insert(*array, idx, ptr);
}

void array_insert_create_value(array_t **array, u_int esize,
                               int idx, void *val)
{
    if (*array == NULL)
    {
        *array = array_create(esize, 0);
    }
    array_insert(*array, idx, val);
}

void array_insert_enumerator(array_t *array, int idx, enumerator_t *enumerator)
{
    void *ptr;

    while (enumerator->enumerate(enumerator, &ptr))
    {
        array_insert(array, idx, ptr);
    }
    enumerator->destroy(enumerator);
}


int main()
{
    int *data = malloc(sizeof (int));
    *data = 1;
    int *iter;

    array_t *at;
    at = array_create(0, 0);
    array_insert(at, ARRAY_TAIL, data);
    array_insert(at, ARRAY_TAIL, data);

    enumerator_t *enumerator;
    enumerator = array_create_enumerator(at);
    while (enumerator->enumerate(enumerator, &iter)){
        printf("iter: %d\n", *iter);
    }

    return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2323639.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

ESP32S3 WIFI 实现TCP服务器和静态IP

一、 TCP服务器代码 代码由station_example_main的官方例程修改 /* WiFi station ExampleThis example code is in the Public Domain (or CC0 licensed, at your option.)Unless required by applicable law or agreed to in writing, thissoftware is distributed on an &q…

docker中安装 python

ubuntu 1、安装源码编译所需依赖 apt-get install -y gcc g make cmake libsqlite3-dev zlib1g-dev libssl-dev libffi-dev 2、下载python安装包 python-release安装包下载_开源镜像站-阿里云 3、解压安装 tar -zxvf Python-3.7.5.tgz cd Python-3.7.5 ./configure --prefix…

数据库----单表、多表

数据库 create database 数据库名称;---创建数据库create database 数据库名称 default charsetutf8mb4;---创建数据库&#xff0c;同时指定编码show databases;---查看当前数据库管理下存在多少数据库show databases like "db_%";---查询以db_开头的数据库select d…

ubuntu 22.04 一键安装 lxd

LXD系列 LXD是一个现代、安全且功能强大的系统容器和虚拟机管理器。 它为在容器或虚拟机中运行和管理完整的 Linux 系统提供了统一的体验。LXD 支持大量 Linux 发行版的映像(官方 Ubuntu 映像和社区提供的映像),并且围绕

HO与OH差异之Navigation三

在上一篇内容中我们介绍了HO与OH差异之Navigator&#xff0c;我们也了解了Navigator的基本概念和大致了解了一下他的基础用法&#xff0c;既然谈到差异肯定就不止这两种差异&#xff0c;今天就让我们来了解第三种差异NavRouter&#xff0c;其中在HO中我们并没有这种路由方式但是…

模型压缩与迁移:基于蒸馏技术的实战教程

1.前言 模型蒸馏&#xff08;Model Distillation&#xff09;&#xff0c;又称为知识蒸馏&#xff08;Knowledge Distillation&#xff09;&#xff0c;是一种将大型、复杂的模型&#xff08;通常称为教师模型&#xff0c;Teacher Model&#xff09;的知识转移到小型、简单模型…

XSS通关技巧

目录 第一关&#xff1a; 第二关&#xff1a; 第三关&#xff1a; 第四关&#xff1a; 第五关&#xff1a; 第六关&#xff1a; 第七关&#xff1a; 第八关&#xff1a; 第九关&#xff1a; 第十关&#xff1a; 第十一关&#xff1a; 第十二关&#xff1a; 第十三关&#xff1a…

el-tree树多选,将选中的树对象中某个字段值改为true,并过滤出所有为true的对象,组成新的数组

功能实现&#xff1a; el-tree树多选&#xff0c;将选中的树对象中某个字段值改为true,并过滤出所有为true的对象&#xff0c;组成新的数组提交给后端 <template><div><!-- 树形菜单 --><el-tree:data"stageList"show-checkboxdefault-expand-…

大文件版本管理git-lfs

1. 安装 Git Large File Storage (LFS) 是一个 开源的 Git 扩展&#xff0c;用于替换 Git 仓库中的大文件&#xff0c;用指针文件替代实际的大文件&#xff0c;可以在保持仓库轻量级的同时&#xff0c;有效地管理大型文件。 如果install提示失败&#xff0c;多试几次&#xf…

融合YOLO11与行为树的人机协作智能框架:动态工效学优化与自适应安全决策

人工智能技术要真正发挥其价值&#xff0c;必须与生产生活深度融合&#xff0c;为产业发展和人类生活带来实际效益。近年来&#xff0c;基于深度学习的机器视觉技术在工业自动化领域取得了显著进展&#xff0c;其中YOLO&#xff08;You Only Look Once&#xff09;算法作为一种…

Postgresql源码(142)子查询提升pull_up_sublinks

1 案例 drop table t_fun01; create table t_fun01 (image_id numeric primary key, content_id varchar(50), file_code varchar(20)); create index idx3 on t_fun01(content_id); create index idx4 on t_fun01(file_code); insert into t_fun01 select t.i, t.i%10, t.i%1…

23种设计模式-桥接(Bridge)设计模式

桥接设计模式 &#x1f6a9;什么是桥接设计模式&#xff1f;&#x1f6a9;桥接设计模式的特点&#x1f6a9;桥接设计模式的结构&#x1f6a9;桥接设计模式的优缺点&#x1f6a9;桥接设计模式的Java实现&#x1f6a9;代码总结&#x1f6a9;总结 &#x1f6a9;什么是桥接设计模式…

【黑皮书】 AVL树

目录 前言 一 AVL树的介绍 二 单旋转 二 双旋转 总结 前言 AVL树的学习 一 AVL树的介绍 AVL树是带有平衡条件的二叉查找树&#xff0c;这个平衡条件要持续保持&#xff0c;而且必须保证树的深度为O(log(N))最简单的想法就是要求左右子树具有相同的高度 一棵AVL树是…

【机器学习】什么是决策树?

什么是决策树&#xff1f; 决策树是一种用于分类和回归问题的模型。它通过一系列的“决策”将数据逐步分裂&#xff0c;最终得出预测结果。可以把它看作是一个“树”&#xff0c;每个节点表示一个特征的判断&#xff0c;而每个分支代表了可能的判断结果&#xff0c;最终的叶子…

使用独立服务器的最佳方式指南

在寻找合适的主机服务方案时&#xff0c;可以考虑独立服务器&#xff0c;因为它拥有管理员权限以及更高的性能配置。在本指南中&#xff0c;我们将介绍独立服务器的多种用途&#xff0c;并分析为什么选择独立服务器可能是处理高性能、资源密集型应用和大流量网站的最佳方案。 搭…

【HTML 基础教程】HTML 属性

HTML 属性 属性是 HTML 元素提供的附加信息。 属性通常出现在 HTML 标签的开始标签中&#xff0c;用于定义元素的行为、样式、内容或其他特性。 属性总是以 name"value" 的形式写在标签内&#xff0c;name 是属性的名称&#xff0c;value 是属性的值。 HTML 属性 …

爬虫问题整理(2025.3.27)

此时此刻&#xff0c;困扰我一天的两个问题终于得到了解决&#xff0c;在此分享给大家。 问题1&#xff1a;使用anaconda prompt无法进行pip安装&#xff0c;这里只是一个示例&#xff0c;实际安装任何模块都会出现类似报错。 解决办法&#xff1a;关掉梯子......没错&#xf…

短信验证码安全需求设计

背景&#xff1a; 近期发现部分系统再短信充值频繁&#xff0c;发现存在恶意消耗短信额度现象&#xff0c;数据库表排查&#xff0c;发现大量非合法用户非法调用短信接口API导致额度耗尽。由于系统当初设计存在安全缺陷&#xff0c;故被不法分子进行利用&#xff0c;造成损失。…

若依专题——基础应用篇

若依搭建 搭建后端项目 ① Git 克隆并初始化项目 ② MySQL 导入与配置 ③ 启动 Redis 搭建后端项目注意事项&#xff1f; ① 项目初始化慢&#xff0c;执行clean、package ② MySQL导入后&#xff0c;修改application-druid.yml ③ Redis有密码&#xff0c;修改ap…

AI for CFD入门指南(传承版)

AI for CFD入门指南 前言适用对象核心目标基础准备传承机制 AI for CFDLibtorch的介绍与使用方法PytorchAutogluon MakefileVscodeOpenFOAMParaviewGambit 前言 适用对象 新加入课题组的硕士/博士研究生对AICFD交叉领域感兴趣的本科生实习生需要快速上手组内研究工具的合作研…