【9】Strongswan collections —— enumerator

//以目录枚举为例子,说明enumerator,从源码剥离可运行

#include <stdio.h>
#include <stdbool.h>
#include <dirent.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdint.h>
#include <stddef.h>
#include <sys/time.h>
#include <stdarg.h>/*** 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));#ifndef FALSE
# define FALSE false
#endif /* FALSE */
#ifndef TRUE
# define TRUE  true
#endif /* TRUE */typedef struct enumerator_t enumerator_t;struct enumerator_t {/*** 枚举集合。** enumerate() 方法接受可变数量的指针参数(枚举到的值被写入这些参数)**通常只需分配调用枚举器的 venumerate() 方法的通用 enumerator_enumerate_default() 函数就足够了。 ...** @param ...	枚举项的变量列表,取决于实现* @return		TRUE if pointers returned*/bool (*enumerate)(enumerator_t *this, ...);/*** 枚举集合。** venumerate() 方法采用一个变量参数列表,其中包含将枚举值写入的指针。** @param args	枚举项的变量列表,取决于实现* @return		TRUE if pointers returned*/bool (*venumerate)(enumerator_t *this, va_list args);/*** Destroy an enumerator_t instance.*/void (*destroy)(enumerator_t *this);
};/*** Enumerator implementation for directory enumerator*/
typedef struct {/** implements enumerator_t */enumerator_t public;/** directory handle */DIR *dir;/** absolute path of current file */char full[PATH_MAX];/** where directory part of full ends and relative file gets written *///完整路径中的目录部分结束以及相对文件将被写入的位置char *full_end;
} dir_enum_t;
/*** Helper function that compares two strings for equality*/
static inline bool streq(const char *x, const char *y)
{return (x == y) || (x && y && strcmp(x, y) == 0);
}bool enumerate_dir_enum(dir_enum_t *this, va_list args){//读取目录中的条目,依靠此函数特性实现枚举struct dirent *entry = readdir(this->dir);struct stat *st = NULL;size_t remaining;char **relative = NULL, **absolute = NULL;;int len;//对应enumerate输入的变参... &relative, &file, NULL 下面写入这些值相当于写入那些值VA_ARGS_VGET(args, relative, absolute, st);if (!entry){return FALSE;}if (streq(entry->d_name, ".") || streq(entry->d_name, "..")){return this->public.enumerate(&this->public, relative, absolute, st);}if (relative){//条目名称*relative = entry->d_name;}if (absolute || st){//full是路径,relativeremaining = sizeof(this->full) - (this->full_end - this->full);len = snprintf(this->full_end, remaining, "%s", entry->d_name);if (len < 0 || len >= remaining){return FALSE;}if (absolute){*absolute = this->full;}if (st && stat(this->full, st)){/* try lstat() e.g. if a symlink is not valid anymore */if ((errno != ENOENT && errno != ENOTDIR) || lstat(this->full, st)){return FALSE;}}}return TRUE;
}# define DIRECTORY_SEPARATOR "/"
static inline bool path_is_separator(char c)
{return c == DIRECTORY_SEPARATOR[0];
}/*** Object allocation/initialization macro, using designated initializer.*/
#define INIT(this, ...) ({ (this) = malloc(sizeof(*(this))); \*(this) = (typeof(*(this))){ __VA_ARGS__ }; (this); })bool enumerator_enumerate_default(enumerator_t *enumerator, ...)
{va_list args;bool result;if (!enumerator->venumerate){return FALSE;}//va_start用于获取函数参数列表...中可变参数的首指针//输出参数args保存函数参数列表中可变参数的首指针(即,可变参数列表)//输入参数enumerator为函数参数列表中最后一个固定参数(...之前)va_start(args, enumerator);result = enumerator->venumerate(enumerator, args);va_end(args);return result;
}void destroy_dir_enum(dir_enum_t *this){closedir(this->dir);free(this);
}enumerator_t* enumerator_create_directory(const char *path)
{dir_enum_t *this;int len;//实例化INIT(this,.public = {.enumerate = enumerator_enumerate_default,.venumerate = enumerate_dir_enum,.destroy = destroy_dir_enum,},);if (*path == '\0'){path = "./";}len = snprintf(this->full, sizeof(this->full)-1, "%s", path);if (len < 0 || len >= sizeof(this->full)-1){free(this);return NULL;}/* append a '/' if not already done */if (!path_is_separator(this->full[len-1])){this->full[len++] = DIRECTORY_SEPARATOR[0];this->full[len] = '\0';}this->full_end = &this->full[len];//打开目录this->dir = opendir(path);if (!this->dir){free(this);return NULL;}return &this->public;
}int main()
{char *file;char *relative;char *st;char *path = "/root/open/strongswan-6.0.0";enumerator_t *enumerator;enumerator = enumerator_create_directory(path);if (enumerator){while (enumerator->enumerate(enumerator, &relative, &file, NULL)){printf("file: %s | relative: %s | size:%s\n", file, relative, NULL);}enumerator->destroy(enumerator);}return 0;
}

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

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

相关文章

谈谈对spring IOC的理解,原理和实现

一、IoC 核心概念 1. 控制反转&#xff08;Inversion of Control&#xff09; 传统编程中对象自行管理依赖&#xff08;主动创建&#xff09;&#xff0c;而IoC将控制权转移给容器&#xff0c;由容器负责对象的创建、装配和管理&#xff0c;实现依赖关系的反向控制。 2. 依赖…

【Hugging Face 开源库】Diffusers 库 —— 扩散模型

Diffusers 的三个主要组件1. DiffusionPipeline&#xff1a;端到端推理工具__call__ 函数callback_on_step_end 管道回调函数 2. 预训练模型架构和模块UNetVAE&#xff08;Variational AutoEncoder&#xff09;图像尺寸与 UNet 和 VAE 的关系EMA&#xff08;Exponential Moving…

甘肃旅游服务平台+论文源码视频演示

4 系统设计 4.1系统概要设计 甘肃旅游服务平台并没有使用C/S结构&#xff0c;而是基于网络浏览器的方式去访问服务器&#xff0c;进而获取需要的数据信息&#xff0c;这种依靠浏览器进行数据访问的模式就是现在用得比较广泛的适用于广域网并且没有网速限制要求的小程序结构&am…

路由选型终极对决:直连/静态/动态三大类型+华为华三思科配置差异,一张表彻底讲透!

路由选型终极对决&#xff1a;直连/静态/动态三大类型华为华三思科配置差异&#xff0c;一张表彻底讲透&#xff01; 一、路由&#xff1a;互联网世界的导航系统二、路由类型深度解析三者的本质区别 三、 解密路由表——网络设备的GPS华为&#xff08;Huawei&#xff09;华三&a…

【RAG综述系列】之 RAG 相关背景和基本原理

系列文章&#xff1a; 【RAG综述系列】之 RAG 相关背景和基本原理 【RAG综述系列】之 RAG 特点与挑战以及方法与评估 【RAG综述系列】之 RAG 先进方法与综合评估 【RAG综述系列】之 RAG 应用和未来方向 正文&#xff1a; 检索增强生成&#xff08;Retrieval-Augmented Gen…

CMake 构建的Qt 项目中的构建套件的配置

在Qt 框架中&#xff0c;使用CMake 构建工具时&#xff0c;需要自己给构建套件添加相关配置&#xff0c;否则已经添加的构建套件将不可选择使用。 创建CMake 项目后&#xff0c;如果打开项目配置时&#xff0c;出现如下构建套件不可选的情况&#xff0c; 需要先确认是否安装…

本地化智能运维助手:基于 LangChain 数据增强 和 DeepSeek-R1 的K8s运维文档检索与问答系统 Demo

写在前面 博文内容为基于 LangChain 数据增强 和 Ollams 本地部署 DeepSeek-R1实现 K8s运维文档检索与问答系统 Demo通过 Demo 对 LEDVR 工作流&#xff0c; 语义检索有基本认知理解不足小伙伴帮忙指正 &#x1f603;,生活加油 我看远山&#xff0c;远山悲悯 持续分享技术干货…

Kotlin when 表达式完全指南:从基础到高级的12种实战用法

掌握 when 的灵活运用&#xff0c;告别繁琐的 if-else 链 以下是 Kotlin 中 when 表达式的 12种核心用法 的全面总结&#xff0c;涵盖基础到高级场景&#xff0c;并附带实用示例&#xff1a; 一、基础用法 1. 替代 Java 的 switch-case when (x) {1 -> println("一&qu…

新加坡 PSB 认证:安全标准、证书特点及申请注意事项

目录 什么是PSB认证&#xff1f; 涉及产品范围 强制性认证产品类别 自愿性认证产品 认证项目与测试标准 1. 安全测试 2. 电磁兼容性&#xff08;EMC&#xff09;测试 3. 能效测试&#xff08;特定产品&#xff09; 认证流程详解 第一步&#xff1a;准备阶段 第二步&a…

UE4学习笔记 FPS游戏制作26 UE中的UI

文章目录 几个概念创建一个UI蓝图添加UI获取UI的引用 切换设计器和UI蓝图将UI添加到游戏场景锚点轴点slotSizeToContent三种UI数据更新方式函数绑定属性绑定事件绑定 九宫格分割图片 几个概念 UMG&#xff1a;UE的UI编辑器 slate UI: UE的UI的编辑语言 创建一个UI蓝图 右键用…

HttpRunner v4.x 远程调用实践指南

一、基于 SSH 的远程执行方案 1. 环境准备流程 在目标服务器部署 HttpRunner 运行时环境&#xff1a; # 远程服务器执行&#xff08;需 Golang 1.18 和 Python 3.8&#xff09; curl -ksSL https://httprunner.com/script/install.sh | bash配置免密登录&#xff08;本地机器…

头条项目的文章延迟发布功能

最近做的头条项目其中有个功能是创作者发表的文章可以设置在未来某个时间发表&#xff0c;在实现这个功能的时候就在想该怎么实现呢&#xff1f;刚开始想的是利用Spring的定时任务定时的去数据库中查询&#xff0c;可以这个查询频率该怎么设置&#xff0c;每次从数据库中需要查…

Celery 全面指南:Python 分布式任务队列详解

Celery 全面指南&#xff1a;Python 分布式任务队列详解 Celery 是一个强大的分布式任务队列/异步任务队列系统&#xff0c;基于分布式消息传递&#xff0c;专注于实时处理&#xff0c;同时也支持任务调度。本文将全面介绍 Celery 的核心功能、应用场景&#xff0c;并通过丰富…

OpenHarmony NativeC++应用开发speexdsp噪声消除案例

随着5.0的版本的迭代升级&#xff0c;笔者感受到了开源鸿蒙前所未有大的版本更替速度。5.0出现了越来越多的C API可以调用&#xff0c;极大的方便了native c应用的开发。笔者先将speexdsp噪声消除的案例分享&#xff0c;老规矩&#xff0c;还是开源&#xff01;&#xff01;&am…

nuxt3 seo优化

在 Nuxt3 中&#xff0c;通过 nuxtjs/seo、nuxtjs/sitemap 和 nuxtjs/robots 模块可以生成包含动态链接的站点地图&#xff08;sitemap.xml&#xff09;&#xff0c;但具体是“实时生成”还是“部署时生成”&#xff0c;取决于你的配置方式和数据更新频率。以下是具体分析&…

es6的100个问题

基础概念 解释 let、const 和 var 的区别。什么是块级作用域&#xff1f;ES6 如何实现它&#xff1f;箭头函数和普通函数的主要区别是什么&#xff1f;解释模板字符串&#xff08;Template Literals&#xff09;的用途&#xff0c;并举例嵌套变量的写法。解构赋值的语法是什么…

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

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

Java面试黄金宝典15

1. 请找出增序排列中一个数字第一次和最后一次出现的数组下标 定义 由于数组是增序排列的&#xff0c;我们可以利用二分查找的特性来高效地定位目标数字。对于查找第一次出现的位置&#xff0c;当中间元素等于目标数字时&#xff0c;我们需要继续向左搜索&#xff0c;以确保找…

CentOS 7安装 mysql

CentOS 7安装 mysql 1. yum 安装 mysql 配置mysql源 yum -y install mysql57-community-release-el7-10.noarch.rpm安装MySQL服务器 yum -y install mysql-community-server启动MySQL systemctl start mysqld.service查看MySQL运行状态&#xff0c;运行状态如图&#xff…

科软25机试

题目: 2025科软复试上机题&#xff08;回忆版&#xff09;题解_哔哩哔哩_bilibili 1. 字符串反转 #include<bits/stdc.h> using namespace std;void solve(string& a, int CurN) {if (!(CurN % 2)) {int right a.size() - 1;int left 0;while (left < right)…