【10】Strongswan collections —— array
//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;
}相关文章:
【10】Strongswan collections —— array
//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…...
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…...
VSCode Flutter 快捷键
扩展安装: Flutter Widget Snippets Flutter Flutter Files 1.StatelessWidget切换StatefulWidget快捷键 1.1 将光标放在 StatelessWidget 上。 1.2 按下快捷键: Windows/Linux: Ctrl . macOS: Cmd . 1.3 在弹出的菜单中选择 "Convert to Stat…...
Java面试黄金宝典18
1. 如何找到一条单链表的中间结点 定义 单链表是一种常见的数据结构,每个节点包含数据和指向下一个节点的指针。找到单链表的中间结点,即找出链表中位于中间位置的节点。可借助快慢指针法达成,快指针每次移动两步,慢指针每次移动…...
设计秒杀系统(高并发的分布式系统)
学海无涯,志当存远。燃心砺志,奋进不辍。 愿诸君得此鸡汤,如沐春风,事业有成。 若觉此言甚善,烦请赐赞一枚,共励学途,同铸辉煌! 思路 处理高并发 流量削峰:限流…...
【面试题】利用Promise实现Websocket阻塞式await wsRequest() 请求
逻辑实现过程 1. 目标与基础设计 目标:实现一个类似 HTTP 请求的阻塞式调用接口(如 await wsRequest(...)),让开发者无需手动处理 WebSocket 的事件回调,而是通过 Promise 和 async/await 获得同步体验。 基础设计&a…...
数据库----单表、多表
数据库 create database 数据库名称;---创建数据库create database 数据库名称 default charsetutf8mb4;---创建数据库,同时指定编码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,我们也了解了Navigator的基本概念和大致了解了一下他的基础用法,既然谈到差异肯定就不止这两种差异,今天就让我们来了解第三种差异NavRouter,其中在HO中我们并没有这种路由方式但是…...
Zookeeper运维指南:服务端与客户端常用命令详解
#作者:任少近 文章目录 1 Zookeeper服务端常用命令2 Zookeeper客户端常用命令2.1Ls命令2.2创建节点create2.3Get命令2.4删除命令2.5修改命令 1 Zookeeper服务端常用命令 启动ZK服务: bin/zkServer.sh start # ./zkServer.sh startZooKeeper JMX enabled by defau…...
linux scp复制多层级文件夹到另一服务器免密及脚本配置
文章目录 生成 SSH 密钥对将公钥复制到目标服务器验证免密登录scp 多级文件夹复制脚本 生成 SSH 密钥对 在本地机器上,使用 ssh-keygen 命令生成 SSH 密钥对。打开终端并执行以下命令: ssh-keygen -t rsa 按提示连续按回车键,默认会在 ~/.ss…...
模型压缩与迁移:基于蒸馏技术的实战教程
1.前言 模型蒸馏(Model Distillation),又称为知识蒸馏(Knowledge Distillation),是一种将大型、复杂的模型(通常称为教师模型,Teacher Model)的知识转移到小型、简单模型…...
XSS通关技巧
目录 第一关: 第二关: 第三关: 第四关: 第五关: 第六关: 第七关: 第八关: 第九关: 第十关: 第十一关: 第十二关: 第十三关:…...
el-tree树多选,将选中的树对象中某个字段值改为true,并过滤出所有为true的对象,组成新的数组
功能实现: el-tree树多选,将选中的树对象中某个字段值改为true,并过滤出所有为true的对象,组成新的数组提交给后端 <template><div><!-- 树形菜单 --><el-tree:data"stageList"show-checkboxdefault-expand-…...
大文件版本管理git-lfs
1. 安装 Git Large File Storage (LFS) 是一个 开源的 Git 扩展,用于替换 Git 仓库中的大文件,用指针文件替代实际的大文件,可以在保持仓库轻量级的同时,有效地管理大型文件。 如果install提示失败,多试几次…...
Android RemoteViews:跨进程 UI 更新的奥秘与实践
目录 一、RemoteViews 的舞台:使用场景 (一)通知栏:动态交互的窗口 (二)桌面小部件:桌面上的动态名片 二、RemoteViews 的本质:定义与架构 (一)什么是 RemoteViews? (二)架构设计:层次分明的协作 (三)操作限制:能力边界在哪里? 三、RemoteViews 的引擎…...
es 3期 第27节-运用Script脚本实现复杂需求
#### 1.Elasticsearch是数据库,不是普通的Java应用程序,传统数据库需要的硬件资源同样需要,提升性能最有效的就是升级硬件。 #### 2.Elasticsearch是文档型数据库,不是关系型数据库,不具备严格的ACID事务特性ÿ…...
玩转python: 掌握Python常用库之数据分析pandas
pandas是Python中最强大的数据处理和分析库之一,它提供了高效、灵活且易于使用的数据结构,使数据清洗、转换和分析变得简单直观。 1、pandas库简介 pandas由Wes McKinney于2008年开发,名称来源于"panel data"(面板数据…...
融合YOLO11与行为树的人机协作智能框架:动态工效学优化与自适应安全决策
人工智能技术要真正发挥其价值,必须与生产生活深度融合,为产业发展和人类生活带来实际效益。近年来,基于深度学习的机器视觉技术在工业自动化领域取得了显著进展,其中YOLO(You Only Look Once)算法作为一种…...
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…...
通过 ECNWP 洋流、海浪可视化开发的方法和架构
第一篇:ECNWP 洋流、海浪可视化开发方法 1. 数据获取与预处理 ECNWP(Eastern Central North Pacific)区域的洋流和海浪数据通常来源于 NOAA、EMC 等权威机构。数据包括流速、流向、波高、波向、周期等。 代码示例:数据下载与预处理 import pandas as pd import numpy as…...
如何 编译 px4
DeepSeek-R1满血版 回答完成 深度思考完成 用时27秒,搜索全网29篇资料 以下是详细的PX4固件编译教程,综合多平台及常见问题解决方案: 一、环境准备 系统要求 Ubuntu 20.04/22.04(推荐)或 MacOS 12 Windo…...
23种设计模式-桥接(Bridge)设计模式
桥接设计模式 🚩什么是桥接设计模式?🚩桥接设计模式的特点🚩桥接设计模式的结构🚩桥接设计模式的优缺点🚩桥接设计模式的Java实现🚩代码总结🚩总结 🚩什么是桥接设计模式…...
【黑皮书】 AVL树
目录 前言 一 AVL树的介绍 二 单旋转 二 双旋转 总结 前言 AVL树的学习 一 AVL树的介绍 AVL树是带有平衡条件的二叉查找树,这个平衡条件要持续保持,而且必须保证树的深度为O(log(N))最简单的想法就是要求左右子树具有相同的高度 一棵AVL树是…...
【机器学习】什么是决策树?
什么是决策树? 决策树是一种用于分类和回归问题的模型。它通过一系列的“决策”将数据逐步分裂,最终得出预测结果。可以把它看作是一个“树”,每个节点表示一个特征的判断,而每个分支代表了可能的判断结果,最终的叶子…...
【商城实战(74)】数据采集与整理,夯实电商运营基石
【商城实战】专栏重磅来袭!这是一份专为开发者与电商从业者打造的超详细指南。从项目基础搭建,运用 uniapp、Element Plus、SpringBoot 搭建商城框架,到用户、商品、订单等核心模块开发,再到性能优化、安全加固、多端适配…...
使用独立服务器的最佳方式指南
在寻找合适的主机服务方案时,可以考虑独立服务器,因为它拥有管理员权限以及更高的性能配置。在本指南中,我们将介绍独立服务器的多种用途,并分析为什么选择独立服务器可能是处理高性能、资源密集型应用和大流量网站的最佳方案。 搭…...
视频格式转换:畅享多平台无缝视频体验
视频格式转换:畅享多平台无缝视频体验 视频已成为我们日常生活中不可或缺的一部分,不论是工作中展示方案的演示,还是生活里记录美好瞬间的短片,视频的存在无处不在。然而,面对各类设备、平台对视频格式的不同要求&…...
【HTML 基础教程】HTML 属性
HTML 属性 属性是 HTML 元素提供的附加信息。 属性通常出现在 HTML 标签的开始标签中,用于定义元素的行为、样式、内容或其他特性。 属性总是以 name"value" 的形式写在标签内,name 是属性的名称,value 是属性的值。 HTML 属性 …...
