亚欧色一区w666天堂,色情一区二区三区免费看,少妇特黄A片一区二区三区,亚洲人成网站999久久久综合,国产av熟女一区二区三区

  • 發布文章
  • 消息中心
點贊
收藏
評論
分享
原(yuan)創

使用libcyaml實現YAML解析和序列化

2023-11-27 09:33:25
307
0

前言

 YAML(Yet Another Markup Language)是一種人類可讀的(de)(de)(de)數據(ju)序列(lie)化格(ge)式,常用于(yu)(如K8S及Ansible)配置文件和數據(ju)交換(huan)。在C語言(yan)中,我們可以使用libyaml來(lai)解(jie)析和處(chu)理YAML格(ge)式的(de)(de)(de)數據(ju), libcyaml 是基于(yu)libyaml 封裝的(de)(de)(de)基于(yu)schema的(de)(de)(de)YAML解(jie)析和序列(lie)化工具, 基于(yu)ISC協議開源(yuan),用戶能(neng)夠方便集成到業務(wu)代(dai)碼(ma)。本文將介紹如何使用libcayml實(shi)現解(jie)析YAML到結構體(ti)。

前置準備

1.    安裝依賴包
libcayml 基于libyaml作為底層的YAML讀(du)寫庫,因此需(xu)要安裝libyaml及其(qi)開(kai)發庫,否則在編譯時將出(chu)現錯誤(wu)。

$ yum install -y libyaml libyaml-devel

2.    下載(zai)代碼

git clone github.com/tlsa/libcyaml.git lib
cd lib
git clone v1.4.1 -b v1.4.1

項目集成

1.    打開調試開關
在項目中,通常需要(yao)打開調試(shi)便于后期(qi)問題(ti)定位,因此修改Makefile打開編譯調試(shi)開關

diff --git a/Makefile b/Makefile
index 77f2fb3..01c7355 100644
--- a/Makefile
+++ b/Makefile
@@ -18,7 +18,7 @@ VERSION_DEVEL = 0
 VERSION_STR = $(VERSION_MAJOR).$(VERSION_MINOR).$(VERSION_PATCH)

 # Default variant depends on whether it's a development build.
-ifeq ($(VERSION_DEVEL), 1)
+ifneq ($(ENVTYPE),release)
        VARIANT = debug
 else
        VARIANT = release
@@ -80,7 +80,7 @@ else ifeq ($(VARIANT), san)
        CFLAGS += -O0 -g -fsanitize=address -fsanitize=undefined -fno-sanitize-recover
        LDFLAGS += -fsanitize=address -fsanitize=undefined -fno-sanitize-recover
 else
-       CFLAGS += -O2 -DNDEBUG
+       CFLAGS += -g -O2 -DNDEBUG
 endif

 ifneq ($(filter coverage,$(MAKECMDGOALS)),)
--
2.27.0

2.    代碼開發
參考代碼倉庫中examples/planner/main.c 進行代碼開發:
定義結構體

struct task {
    const char *name;
    enum task_flags flags;
    struct duration estimate;

    const char **depends;
    unsigned depends_count;

    const char **people;
    unsigned n_people;
};

定義結構(gou)體對應的schema:

static const cyaml_schema_field_t task_fields_schema[] = {
    CYAML_FIELD_STRING_PTR(
            "name", CYAML_FLAG_POINTER,
            struct task, name, 0, CYAML_UNLIMITED),
    CYAML_FIELD_FLAGS(
            "flags", CYAML_FLAG_OPTIONAL | CYAML_FLAG_STRICT,
            struct task, flags, task_flags_strings,
            CYAML_ARRAY_LEN(task_flags_strings)),
    CYAML_FIELD_MAPPING(
            "estimate", CYAML_FLAG_DEFAULT,
            struct task, estimate, duration_fields_schema),
    CYAML_FIELD_SEQUENCE(
            "depends", CYAML_FLAG_POINTER | CYAML_FLAG_OPTIONAL,
            struct task, depends,
            &string_ptr_schema, 0, CYAML_UNLIMITED),
    CYAML_FIELD_SEQUENCE_COUNT(
            "people", CYAML_FLAG_POINTER | CYAML_FLAG_OPTIONAL,
            struct task, people, n_people,
            &string_ptr_schema, 0, CYAML_UNLIMITED),
    CYAML_FIELD_END
};

static const cyaml_schema_value_t task_schema = {
    CYAML_VALUE_MAPPING(CYAML_FLAG_DEFAULT,
            struct task, task_fields_schema),
};


如果結(jie)構(gou)體作為另外一(yi)個結(jie)構(gou)體的成員, 可以參考plan的相關定(ding)義:

struct plan {
    …
    struct task *tasks;
    uint64_t tasks_count;
};

 
Schema定義:

static const cyaml_schema_field_t plan_fields_schema[] = {
   …
   CYAML_FIELD_SEQUENCE(
            "tasks", CYAML_FLAG_POINTER,
            struct plan, tasks,
            &task_schema, 0, CYAML_UNLIMITED),
   …
};


YAML 配置

static const cyaml_config_t config = {
    .log_fn = cyaml_log,
    .mem_fn = cyaml_mem,
    .log_level = CYAML_LOG_INFO,
};

這里使用默認的日志及內存分配函數,如有需要可實現自定義的方法。
解析yaml文件到結構體

    err = cyaml_load_file(argv[ARG_PATH_IN], &config,
            &plan_schema, (void **) &plan, NULL);

序(xu)列化(hua)結(jie)構體(ti)并寫(xie)到文(wen)件:

   err = cyaml_save_file(argv[ARG_PATH_OUT], &config,
            &plan_schema, plan, 0);

最后,別記得釋放內存:

    cyaml_free(&config, &plan_schema, plan, 0);

編譯libcayml到源碼(ma)

CFLAGS += -I lib/include

LIBS = -lyaml -Llib -lcyaml

OBJS = main.o

all: libs $(TARGET)

libs:
    make ENVTYPE=$(ENVTYPE) -C lib
    install -m 0644 lib/build/$(VARIANT)/libcyaml.a lib/

$(TARGET): $(OBJS)
    -mkdir -p ./build/
    gcc $(CFLAGS) -o $@ $^ $(LIBS)

執(zhi)行make命(ming)令即(ji)能(neng)完成代碼編譯。

總結


YAML是一(yi)種方便人類(lei)閱讀和編寫(xie)的數(shu)據序列化格式,在(zai)C語(yu)言中(zhong)可以(yi)(yi)使用(yong)libyaml庫來解析和處(chu)理YAML格式的數(shu)據。本文介紹了如何使用(yong)基于libyaml封裝的開源libcyaml庫,以(yi)(yi)及如何使用(yong)libcyaml庫來加載、解析和處(chu)理YAML文件(jian)。

0條評論
0 / 1000
l****n
6文章(zhang)數(shu)
0粉絲數
l****n
6 文章 | 0 粉絲
原創

使用libcyaml實現YAML解析和序列化

2023-11-27 09:33:25
307
0

前言

 YAML(Yet Another Markup Language)是(shi)一種人類可讀的(de)數(shu)據序(xu)列化格(ge)式,常用(yong)于(yu)(如(ru)K8S及Ansible)配置文件(jian)和(he)(he)數(shu)據交換。在C語言(yan)中,我們可以(yi)使(shi)用(yong)libyaml來解析和(he)(he)處理YAML格(ge)式的(de)數(shu)據, libcyaml 是(shi)基(ji)于(yu)libyaml 封裝的(de)基(ji)于(yu)schema的(de)YAML解析和(he)(he)序(xu)列化工具, 基(ji)于(yu)ISC協(xie)議開源,用(yong)戶能(neng)夠方便(bian)集成到業務代碼。本文將介紹如(ru)何使(shi)用(yong)libcayml實現解析YAML到結構(gou)體。

前置準備

1.    安裝依賴包
libcayml 基于libyaml作為底層的YAML讀寫庫,因此需要安裝libyaml及其開發庫,否則在編譯時將出現錯誤(wu)。

$ yum install -y libyaml libyaml-devel

2.    下(xia)載代碼

git clone github.com/tlsa/libcyaml.git lib
cd lib
git clone v1.4.1 -b v1.4.1

項目集成

1.    打開調試開關
在項目(mu)中(zhong),通常需要打開(kai)(kai)(kai)調試(shi)便于(yu)后期問題定位(wei),因(yin)此(ci)修(xiu)改Makefile打開(kai)(kai)(kai)編譯調試(shi)開(kai)(kai)(kai)關

diff --git a/Makefile b/Makefile
index 77f2fb3..01c7355 100644
--- a/Makefile
+++ b/Makefile
@@ -18,7 +18,7 @@ VERSION_DEVEL = 0
 VERSION_STR = $(VERSION_MAJOR).$(VERSION_MINOR).$(VERSION_PATCH)

 # Default variant depends on whether it's a development build.
-ifeq ($(VERSION_DEVEL), 1)
+ifneq ($(ENVTYPE),release)
        VARIANT = debug
 else
        VARIANT = release
@@ -80,7 +80,7 @@ else ifeq ($(VARIANT), san)
        CFLAGS += -O0 -g -fsanitize=address -fsanitize=undefined -fno-sanitize-recover
        LDFLAGS += -fsanitize=address -fsanitize=undefined -fno-sanitize-recover
 else
-       CFLAGS += -O2 -DNDEBUG
+       CFLAGS += -g -O2 -DNDEBUG
 endif

 ifneq ($(filter coverage,$(MAKECMDGOALS)),)
--
2.27.0

2.    代碼開發
參考代碼倉庫中examples/planner/main.c 進行代碼開發:
定義結構體

struct task {
    const char *name;
    enum task_flags flags;
    struct duration estimate;

    const char **depends;
    unsigned depends_count;

    const char **people;
    unsigned n_people;
};

定(ding)義(yi)結(jie)構(gou)體對(dui)應的schema:

static const cyaml_schema_field_t task_fields_schema[] = {
    CYAML_FIELD_STRING_PTR(
            "name", CYAML_FLAG_POINTER,
            struct task, name, 0, CYAML_UNLIMITED),
    CYAML_FIELD_FLAGS(
            "flags", CYAML_FLAG_OPTIONAL | CYAML_FLAG_STRICT,
            struct task, flags, task_flags_strings,
            CYAML_ARRAY_LEN(task_flags_strings)),
    CYAML_FIELD_MAPPING(
            "estimate", CYAML_FLAG_DEFAULT,
            struct task, estimate, duration_fields_schema),
    CYAML_FIELD_SEQUENCE(
            "depends", CYAML_FLAG_POINTER | CYAML_FLAG_OPTIONAL,
            struct task, depends,
            &string_ptr_schema, 0, CYAML_UNLIMITED),
    CYAML_FIELD_SEQUENCE_COUNT(
            "people", CYAML_FLAG_POINTER | CYAML_FLAG_OPTIONAL,
            struct task, people, n_people,
            &string_ptr_schema, 0, CYAML_UNLIMITED),
    CYAML_FIELD_END
};

static const cyaml_schema_value_t task_schema = {
    CYAML_VALUE_MAPPING(CYAML_FLAG_DEFAULT,
            struct task, task_fields_schema),
};


如果結構體作(zuo)為另外一個結構體的成員, 可以參考plan的相關定(ding)義:

struct plan {
    …
    struct task *tasks;
    uint64_t tasks_count;
};

 
Schema定義:

static const cyaml_schema_field_t plan_fields_schema[] = {
   …
   CYAML_FIELD_SEQUENCE(
            "tasks", CYAML_FLAG_POINTER,
            struct plan, tasks,
            &task_schema, 0, CYAML_UNLIMITED),
   …
};


YAML 配置

static const cyaml_config_t config = {
    .log_fn = cyaml_log,
    .mem_fn = cyaml_mem,
    .log_level = CYAML_LOG_INFO,
};

這里使用默認的日志及內存分配函數,如有需要可實現自定義的方法。
解(jie)析yaml文件到結(jie)構體(ti)

    err = cyaml_load_file(argv[ARG_PATH_IN], &config,
            &plan_schema, (void **) &plan, NULL);

序列化結構體并(bing)寫到文件(jian):

   err = cyaml_save_file(argv[ARG_PATH_OUT], &config,
            &plan_schema, plan, 0);

最后,別記得釋放內(nei)存:

    cyaml_free(&config, &plan_schema, plan, 0);

編(bian)譯libcayml到源碼

CFLAGS += -I lib/include

LIBS = -lyaml -Llib -lcyaml

OBJS = main.o

all: libs $(TARGET)

libs:
    make ENVTYPE=$(ENVTYPE) -C lib
    install -m 0644 lib/build/$(VARIANT)/libcyaml.a lib/

$(TARGET): $(OBJS)
    -mkdir -p ./build/
    gcc $(CFLAGS) -o $@ $^ $(LIBS)

執行(xing)make命令即能(neng)完成代碼(ma)編(bian)譯。

總結


YAML是(shi)一種方(fang)便人類(lei)閱讀和編寫的數據序列化格式,在C語言中可(ke)以使(shi)用(yong)libyaml庫(ku)來解析和處理YAML格式的數據。本文介(jie)紹了如(ru)何使(shi)用(yong)基(ji)于libyaml封裝的開(kai)源(yuan)libcyaml庫(ku),以及(ji)如(ru)何使(shi)用(yong)libcyaml庫(ku)來加載、解析和處理YAML文件。

文章來自個人專欄
文(wen)章 | 訂閱(yue)
0條評論
0 / 1000
請輸入你的評論
0
0