使用C對TOML文件的解析

@TOC
TOML是前GitHub CEO, Tom Preston-Werner,于2013年創(chuàng)建的語言,其目標(biāo)是成為一個(gè)小規(guī)模的易于使用的語義化配置文件格式。TOML被設(shè)計(jì)為可以無二義性的轉(zhuǎn)換為一個(gè)哈希表(Hash table)。

toml書寫語法

參考這里

解析toml文件

這里使用tomlc99

#下載庫
git clone https://github.com/cktan/tomlc99.git
cd tomlc99
#創(chuàng)建test.c文件
vi test.c

將以下代碼復(fù)制到test.c文件中

#ifdef NDEBUG
#undef NDEBUG
#endif

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <stdint.h>
#include <assert.h>
#include "toml.h"

typedef struct node_t node_t;
struct node_t {
    const char*   key;
    toml_table_t* tab;
};

node_t stack[20];
int stacktop = 0;

/*設(shè)置輸出顏色*/
#define red_color "\E[1;31m"
#define color_suffix "\E[0m"

static void print_array_of_tables(toml_array_t* arr, const char* key);
static void print_array(toml_array_t* arr);

/**
 * @brief 打印表名
 * 
 * @param arrname 數(shù)組名或者是表名
 */
static void print_table_title(const char* arrname)
{
    int i;
    printf("%s", arrname ? "[[" : "[");
    /*打印上級*/
    printf(red_color"開始打印上級:"color_suffix);
    for (i = 1; i < stacktop; i++) {
    printf("%s", stack[i].key);
    if (i + 1 < stacktop)
        printf(".");
    }
    /*打印尾部*/
    printf(red_color"打印尾部:"color_suffix);
    if (arrname)
    printf(".%s]]\n", arrname);
    else
    printf("]\n");
}

/**
 * @brief 打印表
 * 
 * @param curtab 
 */
static void print_table(toml_table_t* curtab)
{
    int i;
    const char* key;
    const char* raw;
    toml_array_t* arr;
    toml_table_t* tab;

    /*輪詢KEY*/
    for (i = 0; 0 != (key = toml_key_in(curtab, i)); i++) {
        /*如果是KV則打印*/
    if (0 != (raw = toml_raw_in(curtab, key))) {
        printf(red_color"如果是KV則打印\n"color_suffix);
        printf("%s = %s\n", key, raw);
        /*如果是表中數(shù)組或者KV型數(shù)組*/
    } else if (0 != (arr = toml_array_in(curtab, key))) {
        /*[[key]]數(shù)組或者KV型數(shù)組*/
        if (toml_array_kind(arr) == 't') {
            printf(red_color"如果是[[key]]數(shù)組\n"color_suffix);
        print_array_of_tables(arr, key);
        }
        else {
            /*KV型數(shù)組*/
            printf(red_color"如果是KV型數(shù)組\n"color_suffix);
        printf("%s = [\n", key);/*xx = [ss,sss]*/
        print_array(arr);
        printf("    ]\n");
        }
    } else if (0 != (tab = toml_table_in(curtab, key))) {
        /*如果是[tab.tab]嵌套則分解*/
        printf(red_color"如果是[tab.tab]嵌套則分解打印\n"color_suffix);
        stack[stacktop].key = key;
        stack[stacktop].tab = tab;
        stacktop++;
        print_table_title(0);
        print_table(tab);
        stacktop--;
    } else {
        abort();
    }
    }
}

/**
 * @brief 打印標(biāo)表中數(shù)組
 * 
 * @param arr 數(shù)組指針
 * @param key 數(shù)組名
 */
static void print_array_of_tables(toml_array_t* arr, const char* key)
{
    int i;
    toml_table_t* tab;
    printf("\n");
    /*輪詢表中數(shù)組*/
    printf(red_color"輪詢表中數(shù)組\n"color_suffix);
    for (i = 0; 0 != (tab = toml_table_at(arr, i)); i++) {
    print_table_title(key);//[[key]]
    print_table(tab);
    printf("\n");
    }
}

/**
 * @brief 打印數(shù)組
 * 
 * @param curarr 
 */
static void print_array(toml_array_t* curarr)
{
    toml_array_t* arr;
    const char* raw;
    toml_table_t* tab;
    int i;

    switch (toml_array_kind(curarr)) {
/*
[
    0: yyy,
    1: xxx,
    2: xxx,
]
*/
    case 'v': 
    for (i = 0; 0 != (raw = toml_raw_at(curarr, i)); i++) {
        printf("  %d: %s,\n", i, raw);
    }
    break;
/*
[
    0:
        0:
            0:xxx
            1:xxx
        1:
            0:xxx
            1:xxx
    1:
        0:
            0:xxx
            1:xxx
        1:
            0:xxx
            1:xxx   
]
*/
    case 'a': 
    for (i = 0; 0 != (arr = toml_array_at(curarr, i)); i++) {
        printf("  %d: \n", i);
        print_array(arr);
    }
    break;
        
    case 't': 
    for (i = 0; 0 != (tab = toml_table_at(curarr, i)); i++) {
        print_table(tab);
    }
    printf("\n");
    break;
    
    case '\0':
    break;

    default:
    abort();
    }
}

/**
 * @brief 解析打印toml文件
 * 
 * @param fp 
 */
static void cat(FILE* fp)
{
    char  errbuf[200];
    
    toml_table_t* tab = toml_parse_file(fp, errbuf, sizeof(errbuf));
    if (!tab) {
    fprintf(stderr, "ERROR: %s\n", errbuf);
    return;
    }

    stack[stacktop].tab = tab;
    stack[stacktop].key = "";
    stacktop++;
    print_table(tab);
    stacktop--;

    toml_free(tab);
}

int main(int argc, const char* argv[])
{
    int i;
    if (argc == 1) {
    cat(stdin);
    } else {
    for (i = 1; i < argc; i++) {
        
        FILE* fp = fopen(argv[i], "r");
        if (!fp) {
        fprintf(stderr, "ERROR: cannot open %s: %s\n",
            argv[i], strerror(errno));
        exit(1);
        }
        cat(fp);
        fclose(fp);
    }
    }
    return 0;
}

準(zhǔn)備測試的toml文件,寫入到同級目錄的sample.toml文件中

[Service]
  Port = 50000
  Timeout = 5000
  ConnectRetries = 10
  Labels = [ 'MQTT_Protocol' ,'MODBUS_Protocol' ]
  StartupMsg = 'mqtt modbus device service started'
  CheckInterval = '10s'

[Clients]
  [Clients.Data]
    Host = 'localhost'
    Port = 48080

  [Clients.Metadata]
    Host = 'localhost'
    Port = 48081

[Device]
  DataTransform = false
  Discovery = false
  MaxCmdOps = 128
  MaxCmdResultLen = 256

[Logging]
  LogLevel = 'DEBUG'

[[DeviceList]]
  Name = 'modbus-01_hangzhou-temperature_device-1'
  Profile = 'modbus_temperature_device_profile_common'
  Description = 'An temperature device'
  [DeviceList.Protocols]
    [DeviceList.Protocols.modbus-rtu]
      Address = '/tmp/slave'
      BaudRate = 9600
      DataBits = 8
      StopBits = 1
      Parity = 'N'
      UnitID = 1
  [[DeviceList.AutoEvents]]
    Resource = 'temperature'
    OnChange = false
    Frequency = '10s'
  [[DeviceList.AutoEvents]]
    Resource = 'humidity'
    OnChange = true
    Frequency = '15000ms'

[[DeviceList]]
  Name = 'modbus-01_hangzhou-temperature_device-2'
  Profile = 'modbus_temperature_device_profile_common'
  Description = 'An temperature device'
  [DeviceList.Protocols]
    [DeviceList.Protocols.modbus-rtu]
      Address = '/tmp/slave'
      BaudRate = 9600
      DataBits = 8
      StopBits = 1
      Parity = 'N'
      UnitID = 2
  [[DeviceList.AutoEvents]]
    Resource = 'temperature'
    OnChange = false
    Frequency = '10s'
  [[DeviceList.AutoEvents]]
    Resource = 'humidity'
    OnChange = true
    Frequency = '15000ms'
gcc toml.c test.c -o test
#增加執(zhí)行權(quán)限
sudo chmod +x test
#運(yùn)行解析
./test sample.toml

測試輸出內(nèi)容如下

在這里插入圖片描述
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容