介绍说明

最近自己基于 XR872 在做一个小作品练习练习,具备可以配置的功能,选择了使用 ini 作为配置文件。我调研了网上常见的 ini 解析库,几乎都涉及到了 fopen()/fgets().. 以及 malloc()。

说明这些开源库都仅适用于支持完整 C语言标准库的系统,并不适用于 RTOS 或裸跑的单片机。因为前者虽是 C 语言的标准文件操作函数,但在单片机中基本上使用的都是简化版的 fatfs 接口,要想引入单片机使用,意味着需要对该接口库进行修改。后者更是涉及到内存管理,ram 的占用会随着 ini 配置文件的内容而变化,意味着 ram 的使用不可控,极易受外部因素影响,这对 ram 资源极为稀有的单片机来说,是不可接受的。

本着学习的态度,就自己设计了一个非常简单的 ini 配置文件解析库(libinimini),具有以下几种特点:

1. 内存空间占用可控,libinimini 只使用用户指定的一段内存空间进行解析和返回结果。
2. 不关心数据的来源,libinimini 会通过回调用户的接口来获取每一行文本,不关心文本来自于文件还是其它通信接口。
3. 使用方便简单易上手,用户只需要实现以行为单位的文本数据的回调接口,之后只需要等待 libinimini 解析结果即可。

注意:接口本身会将键值作为字符串传递出来,如果需要转换为数字,调用类似 atoi() 的函数转换即可。

源码仓库位置:

https://github.com/lovemengx/libinimini

https://gitee.com/lovemengx/libinimini

示例代码

sys_config.ini(部分内容)

单片机版本(xr872@FreeRtos)

/**
******************************************************************************
* @文件 main.c
* @版本 V1.0.0
* @日期
* @概要 用于举例说明 libinimini 如何在单片机中应用
* @作者 lmx
******************************************************************************
* @注意
******************************************************************************
*/ #include <stdio.h>
#include <string.h>
#include "fs/fatfs/ff.h"
#include "kernel/os/os.h"
#include "../src/libinimini.h"
#include "common/framework/fs_ctrl.h"
#include "common/framework/platform_init.h" // 由 libinimini 回调,用于将解析的结果返回
// 返回值: LIB_INIMINI_STOP:停止解析 LIB_INIMINI_KEEP:继续解析
static int inimini_result_cb(libinimini_data_t* data, void* context)
{
printf("section:%-20s keyname:%-30s strval:%-30s\n", data->section, data->keyname, data->strval);
if (strcmp(data->section, "compass_para") == 0 && strcmp(data->keyname, "compass_int") == 0) {
printf("-------------------------------------------------\n");
printf("[%s]\n", data->section);
printf("%s = %s\n", data->keyname, data->strval);
printf("-------------------------------------------------\n");
return LIB_INIMINI_STOP;
}
return LIB_INIMINI_KEEP;
} // 由 libinimini 回调,用于获取每一行的原始文本数据
// 返回值: 0: 已无数据可以提供 >0: 字符串数据的长度
static unsigned int inimini_getline_cb(char* buf, unsigned int size, void* context)
{
FIL* fp = (FIL*)context;
if (f_gets(buf, size, fp) == NULL) {
return LIB_INIMINI_STOP;
}
return (unsigned int)strlen(buf);
} int main(void)
{
FIL file;
static char cache[512] = { 0 };
libinimini_parameter_t para; platform_init(); if(fs_ctrl_mount(FS_MNT_DEV_TYPE_SDCARD, 0) != FS_MNT_STATUS_MOUNT_OK){
printf("fs mount failed\n");
while(1) OS_Sleep(1);
} if(f_open(&file, "sys_config.ini", FA_READ | FA_OPEN_EXISTING) != FR_OK){
printf("open file failed\n");
while(1) OS_Sleep(1);
} memset(&para, 0x00, sizeof(libinimini_parameter_t));
para.contex = &file;
para.result = inimini_result_cb;
para.ops.getline_cb = inimini_getline_cb;
libinimini_foreach(&para, cache, sizeof(cache));
f_close(&file); printf("libinimini_foreach done...\n");
while(1) OS_Sleep(1);
return 0;
}

Windows/Linux 版本

#include <stdio.h>
#include <string.h>
#include "libinimini.h" // 由 libinimini 回调,用于将解析的结果返回
// 返回值: LIB_INIMINI_STOP:停止解析 LIB_INIMINI_KEEP:继续解析
static int inimini_result_cb(libinimini_data_t* data, void* context)
{
printf("section:%-20s keyname:%-30s strval:%-30s\n", data->section, data->keyname, data->strval);
if (strcmp(data->section, "compass_para") == 0 && strcmp(data->keyname, "compass_int") == 0) {
printf("-------------------------------------------------\n");
printf("[%s]\n", data->section);
printf("%s = %s\n", data->keyname, data->strval);
printf("-------------------------------------------------\n");
return LIB_INIMINI_STOP;
}
return LIB_INIMINI_KEEP;
} // 由 libinimini 回调,用于获取每一行的原始文本数据
// 返回值: 0: 已无数据可以提供 >0: 字符串数据的长度
static unsigned int inimini_getline_cb(char* buf, unsigned int size, void* contex)
{
FILE* fp = (FILE*)contex;
if (fgets(buf, size, fp) == NULL) {
return LIB_INIMINI_STOP;
}
return strlen(buf);
} int main(void)
{
char inimini_cache[1024] = { 0 };
libinimini_parameter_t para; FILE* fp = fopen("F:/sys_config.ini", "r");
if (NULL == fp) {
printf("open file failed\n");
return 0;
} memset(&para, 0x00, sizeof(libinimini_parameter_t));
para.contex = fp;
para.result = inimini_result_cb;
para.ops.getline_cb = inimini_getline_cb;
int cnt = libinimini_foreach(&para, inimini_cache, sizeof(inimini_cache));
fclose(fp); printf("libinimini_foreach done...\n");
return 0;
}

【开源】libinimini:适用于单片机的极简 ini 解析库的更多相关文章

  1. .NET开源项目 QuarkDoc 一款自带极简主义属性的文档管理系统

    有些话说在前头 因为公司产品业务重构且功能拆分组件化,往后会有很多的接口文档需要留存,所以急需一款文档管理系统.当时选型要求3点: 1.不能是云平台上的Saas服务,整个系统都要在自己公司部署维护(数 ...

  2. itest(爱测试) 开源一站式敏捷测试管理平台&极简项目管理,重大升级(接口测试)6.0.0 发布

    itest 简介 itest 开源敏捷测试管理,testOps 践行者,极简的任务管理,测试管理,缺陷管理,测试环境管理,接口测试5合1,又有丰富的统计分析.可按测试包分配测试用例执行,也可建测试迭代 ...

  3. 极简实用的Asp.NetCore模块化框架新增CMS模块

    简介 关于这个框架的背景,在前面我已经交代过了.不清楚的可以查看这个链接 极简实用的Asp.NetCore模块化框架决定免费开源了 在最近一段时间内,对这个框架新增了以下功能: 1.新增了CMS模块, ...

  4. ServiceFabric极简文档-0. ServiceFabric简介

    前言: 最近ServiceFabric开源了,大家热情都比较高,官方文档大而全,但快速入手不容易找到头绪.发几篇极简的文档,跟大家分享一下,顺便为Ray的ServiceFabric部署做一下铺垫.因为 ...

  5. .NET Core实战项目之CMS 第八章 设计篇-内容管理极简设计全过程

    写在前面 上一篇文章中我带着大家进行了权限部分的极简设计,也仅仅是一个基本的权限设计.不过你完全可以基于这套权限系统设计你的更复杂的权限系统,当然更复杂的权限系统要根据你的业务来进行,因为任何脱离实际 ...

  6. [深度学习工具]·极简安装Dlib人脸识别库

    [深度学习工具]·极简安装Dlib人脸识别库 Dlib介绍 Dlib是一个现代化的C ++工具箱,其中包含用于在C ++中创建复杂软件以解决实际问题的机器学习算法和工具.它广泛应用于工业界和学术界,包 ...

  7. 树莓派(Raspberry Pi)使用Shell编写的极简Service

    树莓派(Raspberry Pi)运行的系统是基于Debian的,不仅可以运行Shell,还支持systemd和docker,可以编写一个简单的服务,让其在启动时运行,执行一些自动化的操作.这里在Ra ...

  8. 首发:极简的Centos主机监控方法,分分钟即可使用【转】

    需求天天有,今年事更多.硬盘测试刚刚完成,就又来了性能监控的需求.一般我们生产就用zabbix了,用起来还行,就是蛮多脚本要写.开发和测试都是分散的,经常还要重装系统,用zabbix就算了,开发和测试 ...

  9. Asky极简教程:零基础1小时学编程,已更新前8节

    Asky极简架构 开源Asky极简架构.超轻量级.高并发.水平扩展.微服务架构 <Asky极简教程:零基础1小时学编程>开源教程 零基础入门,从零开始全程演示,如何开发一个大型互联网系统, ...

  10. [开发技巧]·Python极简实现滑动平均滤波(基于Numpy.convolve)

    [开发技巧]·Python极简实现滑动平均滤波(基于Numpy.convolve) ​ 1.滑动平均概念 滑动平均滤波法(又称递推平均滤波法),时把连续取N个采样值看成一个队列 ,队列的长度固定为N ...

随机推荐

  1. CSS 动画一站式指南

    CSS 动画一站式指南 目录 CSS 动画一站式指南 1. CSS 动画 1.1 变换 1.1.1 变换属性介绍 1.1.2 变换动画实践 1.2 过渡 1.2.1 过渡属性介绍 1.2.2 过渡动画 ...

  2. golang中的错误处理

    0.1.索引 https://waterflow.link/articles/1666716727236 1.panic 当我们执行panic的时候会结束下面的流程: package main imp ...

  3. 一、Redis的Java客户端

    模糊的目标,要不断去解释它们,把他们转化成一个更具体的内容,这样才能够找到途径. 常用客户端介绍 Jedis客户端 基本使用(直连) 引入对应依赖 <dependency> <gro ...

  4. hyperworks2021位安装教程

    hyperworks2021位安装教程:1.先使用"百度网盘客户端"下载hw21_EN_x64软件安装包到电脑磁盘英文路径文件夹下,并鼠标右击进行解压缩,然后在文件夹内找到hwDe ...

  5. PGL图学习之图神经网络GraphSAGE、GIN图采样算法[系列七]

    0. PGL图学习之图神经网络GraphSAGE.GIN图采样算法[系列七] 本项目链接:https://aistudio.baidu.com/aistudio/projectdetail/50619 ...

  6. 快速构建页面结构的 3D Visualization

    对 Chrome 扩展功能熟悉的小伙伴,可能都有用过 Chrome 的 3D 展示页面层级关系这个功能. 可以通过 控制台 --> 右边的三个小点 --> More Tools --> ...

  7. ArcObjects SDK开发 008 从mxd地图文件说起

    1.Mxd文件介绍 ArcGIS的地图文件为.mxd扩展名.Mxd文件的是有版本的,和ArcGIS的版本对应.可以在ArcMap中的File-Save A Copy,保存一个地图拷贝的时候选择Mxd文 ...

  8. 模拟Promise的功能

    模拟Promise的功能,  按照下面的步骤,一步一步 1. 新建是个构造函数 2. 传入一个可执行函数 函数的入参第一个为 fullFill函数 第二个为 reject函数: 函数立即执行, 参数函 ...

  9. JavaScript入门②-函数(1)基础{浅出}

    01.JS函数基础 1.1.函数定义 函数(方法)就是一段定义好的逻辑代码,函数本身也是一个object引用对象.三种函数构造方式: ① 函数申明:function 函数名(参数){代码},申明函数有 ...

  10. 详记apache-poi的使用,将word,excel,ppt转换为html

    原文:https://blog.51cto.com/yunyaniu/5210961 java:Java的jar包之POI的简介.安装.使用方法(基于POI的转换-Word.Excel.Ppt等转ht ...