使用C对TOML文件的解析


TOML是前GitHub CEO, Tom Preston-Werner,于2013年创建的语言,其目标是成为一个小规模的易于使用的语义化配置文件格式。TOML被设计为可以无二义性的转换为一个哈希表(Hash table)。

toml书写语法

参考这里

解析toml文件

这里使用tomlc99

#下载库
git clone https://github.com/cktan/tomlc99.git
cd tomlc99
#创建test.c文件
vi test.c

将以下代码复制到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;

/*设置输出颜色*/
#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 数组名或者是表名
 */
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);
		/*如果是表中数组或者KV型数组*/
	} else if (0 != (arr = toml_array_in(curtab, key))) {
    
    
		/*[[key]]数组或者KV型数组*/
	    if (toml_array_kind(arr) == 't') {
    
    
	    	printf(red_color"如果是[[key]]数组\n"color_suffix);
		print_array_of_tables(arr, key);
	    }
	    else {
    
    
			/*KV型数组*/
			printf(red_color"如果是KV型数组\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 打印标表中数组
 * 
 * @param arr 数组指针
 * @param key 数组名
 */
static void print_array_of_tables(toml_array_t* arr, const char* key)
{
    
    
    int i;
    toml_table_t* tab;
    printf("\n");
	/*轮询表中数组*/
	printf(red_color"轮询表中数组\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 打印数组
 * 
 * @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
#增加执行权限
sudo chmod +x test
#运行解析
./test sample.toml

测试输出内容如下

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/weixin_42892101/article/details/109748325
今日推荐