当前位置:网站首页>c语言支持yaml配置文件通用方法
c语言支持yaml配置文件通用方法
2022-07-24 01:16:00 【llzhang_fly】
在go语言中使用viper之类的库很方便的处理yaml配置文件,但是在c语言中就比较麻烦,经过一番思索和借助强大的github,发现了一个libyaml c库,但是网上的例子都比较麻烦,而且比较繁琐,就想法作了一个相对比较容易配置的解析应用,可以简单地类似viper 的模式进行配置实现不同的配置文件读取。如你的配置文件很复杂请按格式修改KeyValue 全局变量,欢迎大家一起完善
库请自行下载 GitHub - yaml/libyaml: Canonical source repository for LibYAML
直接上代码
yaml示例文件
%YAML 1.1
---
mqtt:
subtopic: "Control/#"
pubtopic: "bbt"
qos: 1
serveraddress: "tcp://192.168.0.25:1883"
clientid: "kvm_test"
writelog: false
writetodisk: false
outputfile: "./receivedMessages.txt"
hearttime: 30
#ifndef __CONFIG_H__
#define __CONFIG_H__
#ifdef __cplusplus
extern "C" {
#endif
/************************/
/* Minimum YAML version */
/************************/
#define YAML_VERSION_MAJOR 1
#define YAML_VERSION_MINOR 1
#define STRUCT_TYPE_NAME 100
#define INT_TYPE_NAME 101
#define STRING_TYPE_NAME 102
#define BOOL_TYPE_NAME 103
#define FLOAT_TYPE_NAME 104
#define MAP_TYPE_NAME 105
#define LIST_TYPE_NAME 106
typedef struct{
char *key;
void *value;
int valuetype;
char *parent;
}KeyValue,*pKeyValue;
#ifdef __cplusplus
}
#endif
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#include <sys/stat.h>
#include <errno.h>
#include <yaml.h>
#include "config.h"
typedef struct {
char *SUBTOPIC; //string `yaml:"subtopic" mapstructure:"subtopic"` //"topic1"
char *PUBTOPIC; //string `yaml:"pubtopic" mapstructure:"pubtopic"`
int QOS; //byte `yaml:"qos" mapstructure:"qos"` //1
char *SERVERADDRESS; //string `yaml:"serveraddress" mapstructure:"serveraddress"` //= "tcp://mosquitto:1883"
char *CLIENTID; //string `yaml:"clientid" mapstructure:"clientid"` //= "mqtt_subscriber"
int HEARTTIME; //int `yaml:"hearttime" mapstructure:"hearttime"`
// CommandLocalPath string `yam:"commanlocalpath"`
}mqttSection,*pmqttSection;
typedef struct {
mqttSection Mqtt;// `yaml:"mqtt" mapstructure:"mqtt"`
// KVM kvmSection `yaml:"kvm" mapstructure:"kvm"`
}ConfigT;
ConfigT config;
static KeyValue webrtcconfig[]={
{"mqtt",&config,STRUCT_TYPE_NAME,NULL},
{"subtopic",&(config.Mqtt.SUBTOPIC),STRING_TYPE_NAME,"mqtt"},
{"pubtopic",&(config.Mqtt.PUBTOPIC),STRING_TYPE_NAME,"mqtt"},
{"qos",&(config.Mqtt.QOS),INT_TYPE_NAME,"mqtt"},
{"serveraddress",&(config.Mqtt.SERVERADDRESS),STRING_TYPE_NAME,"mqtt"},
{"clientid",&(config.Mqtt.CLIENTID),STRING_TYPE_NAME,"mqtt"},
{"hearttime",&(config.Mqtt.HEARTTIME),INT_TYPE_NAME,"mqtt"},
{NULL,NULL,0,NULL},
};
int printConfig(ConfigT * pconfig){
if(pconfig==NULL) return -1;
printf("mqtt:\r\n");
if(pconfig->Mqtt.SUBTOPIC!=NULL) {printf("subtopic: %s\r\n",pconfig->Mqtt.SUBTOPIC); }
if(pconfig->Mqtt.SUBTOPIC!=NULL) {printf("pubtopic: %s\r\n",pconfig->Mqtt.PUBTOPIC); }
printf("qos: %d\r\n",config.Mqtt.QOS);
if(pconfig->Mqtt.SERVERADDRESS!=NULL) {printf("serveraddress: %s\r\n",pconfig->Mqtt.SERVERADDRESS); }
if(pconfig->Mqtt.CLIENTID!=NULL) {printf("clientid: %s\r\n",pconfig->Mqtt.CLIENTID); }
printf("hearttime: %d\r\n",config.Mqtt.HEARTTIME);
}
int freeConfig(ConfigT * pconfig){
if(pconfig==NULL) return -1;
if(pconfig->Mqtt.SERVERADDRESS!=NULL) {free(pconfig->Mqtt.SERVERADDRESS); }
if(pconfig->Mqtt.CLIENTID!=NULL) {free(pconfig->Mqtt.CLIENTID); }
if(pconfig->Mqtt.SUBTOPIC!=NULL) {free(pconfig->Mqtt.SUBTOPIC); }
}
char currentkey[100];
void getvalue(yaml_event_t event,pKeyValue *ppconfigs){
char *value = (char *)event.data.scalar.value;
pKeyValue pconfig=*ppconfigs;
char *pstringname;
while(pconfig->key!=NULL){
if(currentkey[0]!=0){
if(!strcmp(currentkey,pconfig->key))
{
switch(pconfig->valuetype){
case STRING_TYPE_NAME:
pstringname=strdup(value);
printf("get string value %s\r\n",pstringname);
*((char**)pconfig->value)=pstringname;
memset(currentkey, 0, sizeof(currentkey));
break;
case INT_TYPE_NAME:
*((int*)(pconfig->value))=atoi(value);
memset(currentkey, 0, sizeof(currentkey));
break;
case BOOL_TYPE_NAME:
if(!strcmp(value,"true")) *((bool*)(pconfig->value))=true;
else *((bool*)(pconfig->value))=false;
memset(currentkey, 0, sizeof(currentkey));
break;
case FLOAT_TYPE_NAME:
*((float*)(pconfig->value))=atof(value);
memset(currentkey, 0, sizeof(currentkey));
break;
case STRUCT_TYPE_NAME:
case MAP_TYPE_NAME:
case LIST_TYPE_NAME:
memset(currentkey, 0, sizeof(currentkey));
strncpy(currentkey,value,strlen(value));
break;
default:
break;
}
break;
}
//continue;
}else{
if(!strcmp(value,pconfig->key)){
strncpy(currentkey,pconfig->key,strlen(pconfig->key));
break;
}
}
pconfig++;
}
}
int Load_YAML_Config( char *yaml_file, KeyValue *(configs[]) )
{
struct stat filecheck;
yaml_parser_t parser;
yaml_event_t event;
bool done = 0;
unsigned char type = 0;
unsigned char sub_type = 0;
if (stat(yaml_file, &filecheck) != false )
{
printf("[%s, line %d] Cannot open configuration file '%s'! %s", __FILE__, __LINE__, yaml_file, strerror(errno) );
return -1;
}
FILE *fh = fopen(yaml_file, "r");
if (!yaml_parser_initialize(&parser))
{
printf("[%s, line %d] Failed to initialize the libyaml parser. Abort!", __FILE__, __LINE__);
return -1;
}
if (fh == NULL)
{
printf("[%s, line %d] Failed to open the configuration file '%s' Abort!", __FILE__, __LINE__, yaml_file);
return -1;
}
memset(currentkey, 0, sizeof(currentkey));
/* Set input file */
yaml_parser_set_input_file(&parser, fh);
while(!done)
{
if (!yaml_parser_parse(&parser, &event))
{
/* Useful YAML vars: parser.context_mark.line+1, parser.context_mark.column+1, parser.problem, parser.problem_mark.line+1, parser.problem_mark.column+1 */
printf( "[%s, line %d] libyam parse error at line %ld in '%s'", __FILE__, __LINE__, parser.problem_mark.line+1, yaml_file);
}
if ( event.type == YAML_DOCUMENT_START_EVENT )
{
//yaml file first line is version
//%YAML 1.1
//---
yaml_version_directive_t *ver = event.data.document_start.version_directive;
if ( ver == NULL )
{
printf( "[%s, line %d] Invalid configuration file. Configuration must start with \"%%YAML 1.1\"", __FILE__, __LINE__);
}
int major = ver->major;
int minor = ver->minor;
if (! (major == YAML_VERSION_MAJOR && minor == YAML_VERSION_MINOR) )
{
printf( "[%s, line %d] Configuration has a invalid YAML version. Must be 1.1 or above", __FILE__, __LINE__);
return -1;
}
}
else if ( event.type == YAML_STREAM_END_EVENT )
{
done = true;
}
else if ( event.type == YAML_MAPPING_END_EVENT )
{
sub_type = 0;
}
else if ( event.type == YAML_SCALAR_EVENT )
{
getvalue(event,configs);
}
}
return 0;
}
int main(int argc, char *argv[]){
pKeyValue pconfig=&webrtcconfig[0];
Load_YAML_Config("../../etc/kvmagent.yml",&pconfig);
printConfig(&config);
freeConfig(&config);
}
————————————————
版权声明:本文为CSDN博主「superxxd」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/superxxd/article/details/125646097
边栏推荐
- 制作 .Img 镜像文件
- [QNX hypervisor 2.2 user manual]9 VM configuration reference
- High voltage technology learning summary
- Deep understanding of collaborative process
- High voltage technical examination questions with answers
- VLAN division, automatic allocation of IP to all hosts through DHCP, and communication accessible throughout the network
- Kubernets déploiement du tableau de bord (interface visuelle)
- Idea compiler sets the separation line between methods
- Tutorial on the principle and application of database system (048) -- MySQL query (x): self connection query
- Description of TCP packet sticking problem code
猜你喜欢

沃尔沃xc90的安全性如何?提供5座和7座可选

HCIP,OSPF综合实验

Programmeur de cheval noir - test d'interface - test d'interface d'apprentissage de quatre jours - jour 4 - Postman lit des fichiers de données externes, lit des données de fichiers de données, IHRM P

IDEA 热部署(热加载)

Solve the problem that MySQL inserts Chinese garbled code into the table

docker redis

Axure implements addition, deletion, modification and query

Dark horse programmer - interface test - four day learning interface test - day 4 - postman reads external data files, reads data files, IHRM project practice, employee management module, adds employe

爬虫请求库的使用2

Hcia-01 initial understanding of the Internet
随机推荐
Sublime text 3 Chinese + add common plug-ins
Use of crawler request library 2
C语言力扣第53题之最大子数组和。动态规划与分治
Sword *offer04 rebuild binary tree
Collation of key knowledge of high voltage technology
【FreeSwitch开发实践】专栏简介
GLIB-CRITICAL g_ file_ test:assertion ‘filename != null‘ failed
Scroll view realizes drop-down refresh (to avoid the drop-down problem triggered by the initial refresh triggered value of true when onload enters the page)
VLAN division, automatic allocation of IP to all hosts through DHCP, and communication accessible throughout the network
Dark horse programmer - interface test - four day learning interface test - day 4 - postman reads external data files, reads data files, IHRM project practice, employee management module, adds employe
J'ai choisi la mauvaise technologie au mauvais moment.
JS related knowledge
Tutorial on principles and applications of database system (042) -- MySQL query (4): using wildcards to construct query conditions
kubernetes 部署 dashboard(可視化界面)
Sublime text 3 汉化+添加常用插件
Axure implements addition, deletion, modification and query
Skywalking distributed system application performance monitoring tool - upper
URL query parameter encoding problem (golang)
scroll-view實現下拉刷新(避免onload進入頁面初始refresher-triggered為true觸發下拉問題)
【复盘】关于我在错误的时间选错了技术这件事