适用于 C++ 嵌入式项目的轻量级、线程安全属性类
适用于 Linux 嵌入式/应用程序的 C++ 的 INI 风格属性
引言
嵌入式和简单应用程序需要一个方便的存储属性的地方,而 INI 风格的文件非常适合此目的。
背景
这是嵌入式应用程序中的一个常见问题;有许多方法可以存储应用程序的离散配置信息,但我一直担心代码碎片化。在编写了几个需要非系统特定方法来存储应用程序配置信息的项目后,我选择了 INI 文件;那些易于在记事本中编辑和配置的旧版 Windows 3.1 文件。就像那些旧的 ini 文件一样,我也想让框架能够保留这些文件中的注释。
注释很重要,我无需详细说明这一点。并且文件本身的格式不应被更改。此外,框架没有理由变得复杂。除了线程安全和 STL 之外,确实没有理由使用额外的库、第三方工具等。所有这些只需要项目采用 C++ 11 和 STL。这在某些情况下可能是一个问题,并非所有嵌入式项目都使用 C++,而更倾向于纯 C,但在 C++ 适用的情况下,我在很多项目中都使用 C++,这个类可能是一个不错的选择。
Using the Code
我通常从属性文件开始,我在其中放入了我想要看到的信息;我的应用程序到底需要什么?这是一个示例。
# a comment
; also a comment
entry1=value
entry2="a string"
random=1234
详细来说,我们有几个字符前缀(# 和 ;)表示后面的内容是注释,对于现有的属性文件,应保留但忽略它们,包括分隔的换行符。然后是三对键-值对。一种是简单的 `string`,没有空格。然后是一个带有空格的 `string`,为了使类保持简单,我决定带有空格的 `string` 需要用引号括起来。我认为这对于集成商来说不应构成太大麻烦。然后是一个数字值,也可以是浮点值。这基本上涵盖了该类所需的数据。文件可以包含任意数量的换行符、注释、值。但这个类适用于小型配置,理论上兆字节大小的文件也能正常工作,但我会考虑一个比这个更强大的解决方案。
注释可以“嵌套”,为了更好的表达,你也可以肯定地添加像这样的注释字符分隔线
########################################################
……如果喜欢的话。
获取和设置键-值对
现在我们来看代码。在检查文件是否存在并(在代码示例中已涵盖)创建它之后,我们可以像这样查找键
float f;
try {
unique_ptr<properties> p(new Properties(MODE::PRP_READWRITE));
// the next statement, if enabled, would throw a "Key doesn't exist" exception
// because we didn't specify a properties file. No file, no properties db.
// cout << "The value of pi is approximately " << p->Get("p1", 4.0) << endl;
p->OpenPropFile(PRPFILE);
// now we can look for a key in the file
f = p->Get("pi", static_cast<float>(4.0));
首先(使用 C++ 11 智能指针),我们实例化类,传递一个 `read` / `write` 参数。该类可以以读/写模式实例化,对于进程内的某些情况,只读模式可能很有用。接下来,我们使用纯文件系统语义打开文件。
我还包含了一个特定于此类库的自定义异常类,再次,有关详细信息,请参阅实现。可能遇到的异常包括找不到属性文件、键值对格式错误、重复键,只是此类中可能遇到的问题。
然后我们查找一个键,在本例中是一个 `float`。这里需要注意的一点是,我喜欢在找不到键时提供默认值,在本例中,键存在,因此我们得到了预期的输出
The value of pi is approximately 3.14159
有关详细信息,请参阅驱动程序类(*main.cc*)。所有值都表示为纯文本,因此我们使用一个类型转换模板来设置数据类型。
设置值很简单
p->Set("anewvalue", static_cast<unsigned int>(4049860985));
p->dump();
那个 `dump` 函数只是将所有键及其值回显到 `stdout`,这对于调试很方便。
最后,几点说明:Makefile 包含了类生成的具体细节。`std=c++11` 是必需的,如果您正在将该类集成到多线程应用程序中,请务必将“`_REENTRANT` 宏传递给编译器(Makefile 中也显示了这一点)。关于 Makefile,这是一个递归的 Makefile,我在开发新代码时总是使用这种 Makefile 模式,我肯定不建议在生产项目中使用它。由于这绝不是一个独立的应用程序,所以我认为无妨。您一定会在自己的应用程序中使用传统的 autoconf 工具链或 cmake。
我还会做的另一件事是让库更具重入性,通过添加对哈希表的直接方法访问,直接访问表并简单地用锁围绕它可能不是一个好的方法。