使用C语言和libcyaml库解析yaml配置文件

本文介绍了C语言中使用libcyaml库来读写YAML文件的方法。通过一个实例展示了如何编译libcyaml库,并提供了代码示例,演示了如何解析和打印YAML文件中的数据结构。主要涉及libyaml-dev的安装、libcyaml的编译以及YAML数据结构的定义和解析。
摘要由CSDN通过智能技术生成

C语言的yaml库有 libyaml 和 libcyaml (The Official YAML Web Site

个人觉得libcyaml比较好用,libcyaml项目地址:GitHub - tlsa/libcyaml: C library for reading and writing YAML.

libcyaml编译没有难度,按照说明编译即可,需要注意的是提前安装libyaml-dev:

sudo apt install libyaml-dev

下面直接上例子:

~/test
    -include
        -cyaml
            cyaml.h
    -lib
        libcyaml.a
    1.yaml
    main.c
    Makefile

1.yaml

# slave 1
Name: "drive_1"
Pos: 1
Vendor_ID: 0x00000A1E
Product_ID: 0x00000305
Sdo:
  - Description: "To disable [AL. 090.1], set [Pr. PC41.0 [AL. 090.1 Homing incomplete] detection selection] to '1' (disabled)."
    Index: 0x2129
    SubIndex: 0x00
    BitLen: 32
    Value: 1
  - Description: "Pr. PD01.2_Input signal automatic ON selection"
    Index: 0x2181
    SubIndex: 0x00
    BitLen: 32
    Value: 0x00000C00
  - Description: "Reset alarm. Writing '1EA5h' resets an alarm."
    Index: 0x2A46
    SubIndex: 0x00
    BitLen: 16
    Value: 0x1EA5

main.c

/*
 * SPDX-License-Identifier: ISC
 *
 * Copyright (C) 2018 Michael Drake <tlsa@netsurf-browser.org>
 */

#include <stdlib.h>
#include <stdio.h>

#include <cyaml/cyaml.h>

/******************************************************************************
 * C data structure for storing a project plan.
 *
 * This is what we want to load the YAML into.
 ******************************************************************************/

/* Structure for storing a sdo item */
struct sdo {
	char *description;
	int *index;
	int *subindex;
	int *bitlen;
	int *value;
};

/* Structure for storing a slave */
struct slave {
	char *name;
	int *pos;
	int *vendor_id;
	int *product_id;
	struct sdo *sdos;
	unsigned sdos_count;
};

/******************************************************************************
 * CYAML schema to tell libcyaml about both expected YAML and data structure.
 *
 * (Our CYAML schema is just a bunch of static const data.)
 ******************************************************************************/

/* The sdo mapping's field definitions schema is an array.
 *
 * All the field entries will refer to their parent mapping's structure,
 * in this case, `struct task`.
 */
static const cyaml_schema_field_t sdo_fields_schema[] = {
	/* The first field in the mapping is description.
	 *
	 * YAML key: "Description".
	 * C structure member for this key: "description".
	 *
	 * Its CYAML type is string pointer, and we have no minimum or maximum
	 * string length constraints.
	 */
	CYAML_FIELD_STRING_PTR(
			"Description", CYAML_FLAG_POINTER,
			struct sdo, description, 0, CYAML_UNLIMITED),

	CYAML_FIELD_UINT("Index", CYAML_FLAG_DEFAULT, struct sdo, index),
	CYAML_FIELD_UINT("SubIndex", CYAML_FLAG_DEFAULT, struct sdo, subindex),
	CYAML_FIELD_UINT("BitLen", CYAML_FLAG_DEFAULT, struct sdo, bitlen),
	CYAML_FIELD_UINT("Value", CYAML_FLAG_DEFAULT, struct sdo, value),
	
	

	/* The field array must be terminated by an entry with a NULL key.
	 * Here we use the CYAML_FIELD_END macro for that. */
	CYAML_FIELD_END
};

/* The value for a sdo is a mapping.
 *
 * Its fields are defined in sdo_fields_schema.
 */
static const cyaml_schema_value_t sdo_schema = {
	CYAML_VALUE_MAPPING(CYAML_FLAG_DEFAULT,
			struct sdo, sdo_fields_schema),
};


/* The plan mapping's field definitions schema is an array.
 *
 * All the field entries will refer to their parent mapping's structure,
 * in this case, `struct plan`.
 */
static const cyaml_schema_field_t slave_fields_schema[] = {

	CYAML_FIELD_STRING_PTR(
			"Name", CYAML_FLAG_POINTER,
			struct slave, name, 0, CYAML_UNLIMITED),

	CYAML_FIELD_UINT(
			"Pos", CYAML_FLAG_DEFAULT, 
			struct slave, pos),

	CYAML_FIELD_UINT(
			"Vendor_ID", CYAML_FLAG_DEFAULT, 
			struct slave, vendor_id),

	CYAML_FIELD_UINT(
			"Product_ID", CYAML_FLAG_DEFAULT, 
			struct slave, product_id),


	CYAML_FIELD_SEQUENCE(
			"Sdo", CYAML_FLAG_POINTER,
			struct slave, sdos,
			&sdo_schema, 0, CYAML_UNLIMITED),

	/* The field array must be terminated by an entry with a NULL key.
	 * Here we use the CYAML_FIELD_END macro for that. */
	CYAML_FIELD_END
};


/* Top-level schema.  The top level value for the plan is a mapping.
 *
 * Its fields are defined in plan_fields_schema.
 */
static const cyaml_schema_value_t slave_schema = {
	CYAML_VALUE_MAPPING(CYAML_FLAG_POINTER,
			struct slave, slave_fields_schema),
};



/******************************************************************************
 * Actual code to load and save YAML doc using libcyaml.
 ******************************************************************************/

/* Our CYAML config.
 *
 * If you want to change it between calls, don't make it const.
 *
 * Here we have a very basic config.
 */
static const cyaml_config_t config = {
	.log_fn = cyaml_log,            /* Use the default logging function. */
	.mem_fn = cyaml_mem,            /* Use the default memory allocator. */
	.log_level = CYAML_LOG_WARNING, /* Logging errors and warnings only. */
};

/* Main entry point from OS. */
int main(int argc, char *argv[])
{
	cyaml_err_t err;
	struct slave *slave;
	enum {
		ARG_PROG_NAME,
		ARG_PATH_IN,
		ARG_PATH_OUT,
		ARG__COUNT,
	};

	// /* Handle args */
	// if (argc != ARG__COUNT) {
	// 	fprintf(stderr, "Usage:\n");
	// 	fprintf(stderr, "  %s <INPUT> <OUTPUT>\n", argv[ARG_PROG_NAME]);
	// 	return EXIT_FAILURE;
	// }

	/* Load input file. */
	err = cyaml_load_file(argv[ARG_PATH_IN], &config,
			&slave_schema, (void **) &slave, NULL);
	if (err != CYAML_OK) {
		fprintf(stderr, "ERROR: %s\n", cyaml_strerror(err));
		return EXIT_FAILURE;
	}

	/* Use the data. */
	printf("Project: %s\n", slave->name);
	for (unsigned i = 0; i < slave->sdos_count; i++) {
		printf("%u. Description: %s\n", i + 1, slave->sdos[i].description);
		printf("Index: 0x%x\n", slave->sdos[i].index);
		printf("SubIndex: %d\n", slave->sdos[i].subindex);
		printf("BitLen: %d\n", slave->sdos[i].bitlen);
		printf("Value: 0x%x\n", slave->sdos[i].value);
	}

	// /* Modify the data */
	// plan->tasks[0].estimate.days += 3;
	// plan->tasks[0].estimate.weeks += 1;

	// /* Save data to new YAML file. */
	// err = cyaml_save_file(argv[ARG_PATH_OUT], &config,
	// 		&plan_schema, plan, 0);
	// if (err != CYAML_OK) {
	// 	fprintf(stderr, "ERROR: %s\n", cyaml_strerror(err));
	// 	cyaml_free(&config, &plan_schema, plan, 0);
	// 	return EXIT_FAILURE;
	// }

	/* Free the data */
	cyaml_free(&config, &slave_schema, slave, 0);

	return EXIT_SUCCESS;
}

Makefile

INCLUDE = -I include
CFLAGS += $(INCLUDE)
CFLAGS += -std=c11 -Wall -Wextra -pedantic \
		-Wconversion -Wwrite-strings -Wcast-align -Wpointer-arith \
		-Winit-self -Wshadow -Wstrict-prototypes -Wmissing-prototypes \
		-Wredundant-decls -Wundef -Wvla -Wdeclaration-after-statement
LDFLAGS += -lyaml -Llib -lcyaml

all: main

main: main.c
	$(CC) $(CPPFLAGS) $(CFLAGS) -o $@ $^ $(LDFLAGS)

  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

liu_jiankang

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值