使用C對TOML文件的解析

@TOC
TOML是前GitHub CEO端壳, Tom Preston-Werner,于2013年創(chuàng)建的語言枪蘑,其目標是成為一個小規(guī)模的易于使用的語義化配置文件格式损谦。TOML被設(shè)計為可以無二義性的轉(zhuǎn)換為一個哈希表(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 打印標表中數(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;
}

準備測試的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
#運行解析
./test sample.toml

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

在這里插入圖片描述
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末照捡,一起剝皮案震驚了整個濱河市颅湘,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌栗精,老刑警劉巖闯参,帶你破解...
    沈念sama閱讀 219,110評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異悲立,居然都是意外死亡鹿寨,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,443評論 3 395
  • 文/潘曉璐 我一進店門级历,熙熙樓的掌柜王于貴愁眉苦臉地迎上來释移,“玉大人,你說我怎么就攤上這事寥殖⊥婊洌” “怎么了?”我有些...
    開封第一講書人閱讀 165,474評論 0 356
  • 文/不壞的土叔 我叫張陵嚼贡,是天一觀的道長熏纯。 經(jīng)常有香客問我,道長粤策,這世上最難降的妖魔是什么樟澜? 我笑而不...
    開封第一講書人閱讀 58,881評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮叮盘,結(jié)果婚禮上秩贰,老公的妹妹穿的比我還像新娘。我一直安慰自己柔吼,他們只是感情好毒费,可當我...
    茶點故事閱讀 67,902評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著愈魏,像睡著了一般觅玻。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上培漏,一...
    開封第一講書人閱讀 51,698評論 1 305
  • 那天溪厘,我揣著相機與錄音,去河邊找鬼牌柄。 笑死畸悬,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的珊佣。 我是一名探鬼主播蹋宦,決...
    沈念sama閱讀 40,418評論 3 419
  • 文/蒼蘭香墨 我猛地睜開眼闺骚,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了妆档?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,332評論 0 276
  • 序言:老撾萬榮一對情侶失蹤虫碉,失蹤者是張志新(化名)和其女友劉穎贾惦,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體敦捧,經(jīng)...
    沈念sama閱讀 45,796評論 1 316
  • 正文 獨居荒郊野嶺守林人離奇死亡须板,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,968評論 3 337
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了兢卵。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片习瑰。...
    茶點故事閱讀 40,110評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖秽荤,靈堂內(nèi)的尸體忽然破棺而出甜奄,到底是詐尸還是另有隱情,我是刑警寧澤窃款,帶...
    沈念sama閱讀 35,792評論 5 346
  • 正文 年R本政府宣布课兄,位于F島的核電站,受9級特大地震影響晨继,放射性物質(zhì)發(fā)生泄漏烟阐。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,455評論 3 331
  • 文/蒙蒙 一紊扬、第九天 我趴在偏房一處隱蔽的房頂上張望蜒茄。 院中可真熱鬧,春花似錦餐屎、人聲如沸檀葛。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,003評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽驻谆。三九已至,卻和暖如春庆聘,著一層夾襖步出監(jiān)牢的瞬間胜臊,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,130評論 1 272
  • 我被黑心中介騙來泰國打工伙判, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留象对,地道東北人。 一個月前我還...
    沈念sama閱讀 48,348評論 3 373
  • 正文 我出身青樓宴抚,卻偏偏與公主長得像勒魔,于是被迫代替她去往敵國和親甫煞。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 45,047評論 2 355

推薦閱讀更多精彩內(nèi)容