1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
|
libnvxx is a lightweight C++ wrapper around FreeBSD's libnv. it allows you to
interoperate with C code that uses libnv, which is becoming fairly common on
FreeBSD.
priority is given to a clean and idiomatic C++ API for the library. this means
in some cases the API is less efficient than it could be; for example, it
sometimes requires data copies which are, strictly speaking, not necessary.
this is not considered a problem in practice, since the overhead is still very
low, and using libnv in a tight loop would be fairly unusual.
to build and install the library:
% make
% su
# make install
# kyua test --kyuafile /usr/local/tests/nvxx/Kyuafile
to use the library:
#include <nvxx.h> and link with -lnvxx. if you link statically, you also need
to link with -lnv.
the basic API is very similar to the C libnv API:
auto nvl = bsd::nv_list();
nvl.add_number("the answer", 42);
assert(nvl.exists_number("the answer"));
std::print("{0}\n", nvl.get_number("the answer"));
iterator interface:
for (auto [name, value] : nvl) {
std::print("key = {0}\n", name);
// do something with value...
}
serialization interface:
struct object {
std::uint64_t int_value{};
std::string string_value{};
std::vector<std::uint64_t> array_value;
};
template<> struct bsd::nv_schema<object> {
auto get() {
return bsd::nv_field("int value", &object::int_value)
>> bsd::nv_field("string value", &object::string_value)
>> bsd::nv_field("array value", &object::array_value);
}
};
// ...
object obj{};
nv_list nvl = bsd::nv_serialize(obj);
object obj2 = bsd::nv_deserialize<object>(nvl);
infrequently asked questions:
Q: what version of FreeBSD does libnvxx require?
A: libnvxx is developed and tested on FreeBSD 15.0-CURRENT. it will probably
work on earlier versions, as long as the C++ compiler is sufficiently
capable.
Q: what version of C++ does libnvxx require?
A: libnvxx requires C++23 (or later).
Q: but isn't FreeBSD's implementation of C++23 rather incomplete?
A: yes. however, libnvxx only uses the parts which are implemented in the
version of LLVM that FreeBSD ships in base.
Q: doesn't the public API only require C++20?
A: this may be the case, i haven't verified it. if so, patches to support
C++20 for the public API would probably be accepted.
Q: why is the type called bsd::nv_list instead of bsd::nvlist?
A: because <sys/nv_namespace.h> does "#define nvlist FreeBSD_nvlist", which
would cause issues with symbol names in the ABI.
Q: i found a bug and i have a patch that fixes it.
A: that's not a question.
Q: i found a bug and i have a patch that fixes it?
A: please open a pull request on the GitHub repository.
Q: what if i found a bug but i don't have a patch?
A: in that case please open an issue on the GitHub repository, preferably with
a minimal test case.
Q: why wrap libnv instead of creating a C++ version from scratch?
A: the primary use-case of libnv in C++ is to interoperate with existing C APIs
and protocols which use libnv. this requires using libnv in order to, for
example, pass nvlists between C and C++ code.
unlike in C, there is little reason to use libnv in C++ native code for data
storage, since we already have a rich template library for that.
Q: why does the library abort on invalid operations instead of throwing an
exception?
A: because this is how libnv works and there's no way to override it.
Q: do you intend to submit this for inclusion in the FreeBSD base system?
A: eventually, yes, but not until there are some actual users of it to justify
importing it.
Q: is this why you're using <bsd.lib.mk> instead of something more sensible
like CMake?
A: precisely!
|