读取yaml文件数组内容到glist链表

读取yaml文件数组内容到glist链表

config.yaml内容:

servers:
  - name: server1
    ip: 192.168.1.1
    roles:
      - web
      - database
  - name: server2
    ip: 192.168.1.2
    roles:
      - web
  - name: server3
    ip: 192.168.1.3
    roles:
      - database

测试代码:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <yaml.h>
#include <glib.h>

#define MAX_ROLES 10
#define MAX_NAME_LEN 256
#define MAX_IP_LEN 16

typedef struct {
    char name[MAX_NAME_LEN];
    char ip[MAX_IP_LEN];
    char roles[MAX_ROLES][MAX_NAME_LEN];
    int role_count;
} server_t;

void print_event(yaml_event_t *event) {
    switch (event->type) {
        case YAML_NO_EVENT: puts("No event!"); break;
        case YAML_STREAM_START_EVENT: puts("STREAM START"); break;
        case YAML_STREAM_END_EVENT: puts("STREAM END"); break;
        case YAML_DOCUMENT_START_EVENT: puts("Start Document"); break;
        case YAML_DOCUMENT_END_EVENT: puts("End Document"); break;
        case YAML_SEQUENCE_START_EVENT: puts("Start Sequence"); break;
        case YAML_SEQUENCE_END_EVENT: puts("End Sequence"); break;
        case YAML_MAPPING_START_EVENT: puts("Start Mapping"); break;
        case YAML_MAPPING_END_EVENT: puts("End Mapping"); break;
        case YAML_ALIAS_EVENT: printf("Alias: %s\n", event->data.alias.anchor); break;
        case YAML_SCALAR_EVENT: printf("Scalar: %s\n", event->data.scalar.value); break;
    }
}

GList* get_array_config_yaml(const char *file_path) {
    FILE *fh = fopen(file_path, "r");
    if (!fh) {
        perror("Failed to open file");
        return NULL;
    }

    yaml_parser_t parser;
    yaml_event_t event;

    if (!yaml_parser_initialize(&parser)) {
        fputs("Failed to initialize parser\n", stderr);
        fclose(fh);
        return NULL;
    }
    yaml_parser_set_input_file(&parser, fh);

    GList *server_list = NULL;
    server_t *current_server = NULL;

    int in_servers = 0; // Are we parsing the 'servers' section?
    int in_roles = 0;   // Are we parsing the 'roles' section of a server?
    char current_key[MAX_NAME_LEN] = ""; // Current key being parsed

    while (1) {
        if (!yaml_parser_parse(&parser, &event)) {
            fprintf(stderr, "Parser error %d\n", parser.error);
            goto cleanup;
        }

        print_event(&event);

        if (event.type == YAML_STREAM_END_EVENT) {
            yaml_event_delete(&event);
            break;
        }

        switch (event.type) {
            case YAML_MAPPING_START_EVENT:
                if (in_servers && !current_server) {
                    // Starting a new server object
                    current_server = g_new0(server_t, 1);
                }
                break;

            case YAML_MAPPING_END_EVENT:
                if (current_server) {
                    // Finished parsing a server object
                    server_list = g_list_append(server_list, current_server);
                    current_server = NULL;
                }
                break;

            case YAML_SCALAR_EVENT:
                if (!in_servers) {
                    // We are at the root level expecting the 'servers' key
                    if (strcmp((char *)event.data.scalar.value, "servers") == 0) {
                        in_servers = 1;
                    }
                } else if (current_server && !in_roles) {
                    // Not in roles, this must be a key or value for the server
                    if (strlen(current_key) == 0) {
                        // This is a key
                        strncpy(current_key, (char *)event.data.scalar.value, MAX_NAME_LEN);
                    } else {
                        // This is a value
                        if (strcmp(current_key, "name") == 0) {
                            strncpy(current_server->name, (char *)event.data.scalar.value, MAX_NAME_LEN);
                        } else if (strcmp(current_key, "ip") == 0) {
                            strncpy(current_server->ip, (char *)event.data.scalar.value, MAX_IP_LEN);
                        }
                        current_key[0] = '\0'; // Reset current_key after usage
                    }
                } else if (current_server && in_roles) {
                    // In roles sequence, add this role to the current server
                    if (current_server->role_count < MAX_ROLES) {
                        strncpy(current_server->roles[current_server->role_count], (char *)event.data.scalar.value, MAX_NAME_LEN);
                        current_server->role_count++;
                    }
                }
                break;

            case YAML_SEQUENCE_START_EVENT:
                if (current_server && strcmp(current_key, "roles") == 0) {
                    in_roles = 1; // Start of roles sequence
                    current_key[0] = '\0'; // Reset current_key after usage
                }
                break;

            case YAML_SEQUENCE_END_EVENT:
                if (in_roles) {
                    in_roles = 0; // End of roles sequence
                }
                break;

            default:
                break;
        }

        yaml_event_delete(&event);
    }

cleanup:
    yaml_parser_delete(&parser);
    fclose(fh);

    return server_list;
}

int main(void) {
    GList *server_list = get_array_config_yaml("config.yaml");

    // Print the parsed data
    for (GList *iter = server_list; iter != NULL; iter = g_list_next(iter)) {
        server_t *server = (server_t *)iter->data;
        printf("Server Name: %s\n", server->name);
        printf("IP Address: %s\n", server->ip);
        printf("Roles: ");
        for (int j = 0; j < server->role_count; ++j) {
            printf("%s ", server->roles[j]);
        }
        printf("\n");
    }

    // Free the server list memory
    for (GList *iter = server_list; iter != NULL; iter = g_list_next(iter)) {
        server_t *server = (server_t *)iter->data;
        g_free(server);
    }
    g_list_free(server_list);

    return 0;
}

编译:

gcc -o parse_yaml main.c -I/usr/local/eyou/gateway/ebaselib/include/ -L/usr/local/eyou/gateway/ebaselib/lib/ -lyaml $(pkg-config --cflags --libs glib-2.0)

执行

./parse_yaml

结果:

STREAM START
Start Document
Start Mapping
Scalar: servers
Start Sequence
Start Mapping
Scalar: name
Scalar: server1
Scalar: ip
Scalar: 192.168.1.1
Scalar: roles
Start Sequence
Scalar: web
Scalar: database
End Sequence
End Mapping
Start Mapping
Scalar: name
Scalar: server2
Scalar: ip
Scalar: 192.168.1.2
Scalar: roles
Start Sequence
Scalar: web
End Sequence
End Mapping
Start Mapping
Scalar: name
Scalar: server3
Scalar: ip
Scalar: 192.168.1.3
Scalar: roles
Start Sequence
Scalar: database
End Sequence
End Mapping
End Sequence
End Mapping
End Document
STREAM END
Server Name: server1
IP Address: 192.168.1.1
Roles: web database 
Server Name: server2
IP Address: 192.168.1.2
Roles: web 
Server Name: server3
IP Address: 192.168.1.3
Roles: database
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值