diff options
| author | Lexi Winter <lexi@hemlock.eden.le-fay.org> | 2025-03-24 22:39:22 +0000 |
|---|---|---|
| committer | Lexi Winter <lexi@hemlock.eden.le-fay.org> | 2025-03-24 22:39:22 +0000 |
| commit | 10881c992810727ca7a1be7de864f400f160b50f (patch) | |
| tree | 52fbe9fa7d0bf382df48b080bc660ab99c7f27ee | |
| parent | bbaa28af2733188e7466ae7bd3ef8f8f64003bf9 (diff) | |
| download | libnvxx-10881c992810727ca7a1be7de864f400f160b50f.tar.gz libnvxx-10881c992810727ca7a1be7de864f400f160b50f.tar.bz2 | |
add iterator support for basic types
| -rw-r--r-- | .gitignore | 1 | ||||
| -rw-r--r-- | libnvxx/Makefile | 2 | ||||
| -rw-r--r-- | libnvxx/nvxx.h | 1 | ||||
| -rw-r--r-- | libnvxx/nvxx_iterator.cc | 157 | ||||
| -rw-r--r-- | libnvxx/nvxx_iterator.h | 99 | ||||
| -rw-r--r-- | libnvxx/tests/Makefile | 2 | ||||
| -rw-r--r-- | libnvxx/tests/nvxx_iterator.cc | 78 |
7 files changed, 338 insertions, 2 deletions
@@ -10,3 +10,4 @@ .depend* Kyuafile /libnvxx/tests/nvxx_basic +/libnvxx/tests/nvxx_iterator diff --git a/libnvxx/Makefile b/libnvxx/Makefile index d201992..966b4db 100644 --- a/libnvxx/Makefile +++ b/libnvxx/Makefile @@ -26,7 +26,7 @@ LIBDIR= ${PREFIX}/lib INCLUDEDIR= ${PREFIX}/include SHLIB_MAJOR= 1 INCS= nvxx.h nvxx_base.h -SRCS= nvxx.cc +SRCS= nvxx.cc nvxx_iterator.cc CXXSTD= c++23 CXXFLAGS+= -W -Wall -Wextra -Werror LDADD= -lnv diff --git a/libnvxx/nvxx.h b/libnvxx/nvxx.h index 7c938ce..85eb684 100644 --- a/libnvxx/nvxx.h +++ b/libnvxx/nvxx.h @@ -28,5 +28,6 @@ */ #include "nvxx_base.h" +#include "nvxx_iterator.h" #endif /* !_NVXX_H_INCLUDED */ diff --git a/libnvxx/nvxx_iterator.cc b/libnvxx/nvxx_iterator.cc new file mode 100644 index 0000000..5a8f04f --- /dev/null +++ b/libnvxx/nvxx_iterator.cc @@ -0,0 +1,157 @@ +/* + * This is free and unencumbered software released into the public domain. + * + * Anyone is free to copy, modify, publish, use, compile, sell, or distribute + * this software, either in source code form or as a compiled binary, for any + * purpose, commercial or non-commercial, and by any means. + * + * In jurisdictions that recognize copyright laws, the author or authors of + * this software dedicate any and all copyright interest in the software to the + * public domain. We make this dedication for the benefit of the public at + * large and to the detriment of our heirs and successors. We intend this + * dedication to be an overt act of relinquishment in perpetuity of all present + * and future rights to this software under copyright law. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include <sys/cnv.h> + +#include "nvxx.h" + +namespace bsd { + +nv_list_iterator +begin(const_nv_list const &nvl) +{ + return nv_list_iterator(nvl); +} + +nv_list_iterator +begin(nv_list const &nvl) +{ + return nv_list_iterator(nvl); +} + +std::default_sentinel_t +end(const_nv_list const &) +{ + return {}; +} + +std::default_sentinel_t +end(nv_list const &) +{ + return {}; +} + +nv_list_iterator::nv_list_iterator() +{ +} + +nv_list_iterator::nv_list_iterator(const_nv_list const &nvl) + : __nvlist(nvl.ptr()) +{ + __advance(); +} + +nv_list_iterator::nv_list_iterator(nv_list const &nvl) + : __nvlist(nvl.ptr()) +{ + __advance(); +} + +nv_list_iterator & +nv_list_iterator::operator++() +{ + __advance(); + return *this; +} + +nv_list_iterator +nv_list_iterator::operator++(int) +{ + nv_list_iterator tmp = *this; + ++(*this); + return tmp; +} + +bool +nv_list_iterator::operator==(nv_list_iterator const &other) const +{ + return (__nvlist == other.__nvlist) + && (__cookie == other.__cookie); +} + +bool +nv_list_iterator::operator==(std::default_sentinel_t) const +{ + return __cookie == nullptr; +} + +nv_list_iterator::const_reference +nv_list_iterator::operator*() const +{ + return __current; +} + +nv_list_iterator::const_pointer +nv_list_iterator::operator->() const +{ + return &__current; +} + +void +nv_list_iterator::__advance() +{ + auto type = int{}; + auto const *namep = ::nvlist_next(__nvlist, &type, &__cookie); + + if (namep == nullptr) { + __cookie = nullptr; + return; + } + + auto name = std::string_view(namep); + + switch (type) { + case NV_TYPE_NULL: + __current = std::make_pair(name, nullptr); + break; + case NV_TYPE_BOOL: + __current = std::make_pair(name, cnvlist_get_bool(__cookie)); + break; + case NV_TYPE_NUMBER: + __current = std::make_pair(name, cnvlist_get_number(__cookie)); + break; + case NV_TYPE_STRING: + __current = std::make_pair(name, + std::string_view( + cnvlist_get_string(__cookie))); + break; + case NV_TYPE_NVLIST: + __current = std::make_pair(name, + const_nv_list(cnvlist_get_nvlist(__cookie))); + break; + case NV_TYPE_DESCRIPTOR: + __current = std::make_pair(name, + cnvlist_get_descriptor(__cookie)); + break; + case NV_TYPE_BINARY: { + auto nitems = std::size_t{}; + auto ptr = cnvlist_get_binary(__cookie, &nitems); + auto span = std::span{static_cast<std::byte const *>(ptr), nitems}; + __current = std::make_pair(name, span); + break; + } + default: + std::abort(); + } +} + +} diff --git a/libnvxx/nvxx_iterator.h b/libnvxx/nvxx_iterator.h new file mode 100644 index 0000000..d626bfd --- /dev/null +++ b/libnvxx/nvxx_iterator.h @@ -0,0 +1,99 @@ +/* + * This is free and unencumbered software released into the public domain. + * + * Anyone is free to copy, modify, publish, use, compile, sell, or distribute + * this software, either in source code form or as a compiled binary, for any + * purpose, commercial or non-commercial, and by any means. + * + * In jurisdictions that recognize copyright laws, the author or authors of + * this software dedicate any and all copyright interest in the software to the + * public domain. We make this dedication for the benefit of the public at + * large and to the detriment of our heirs and successors. We intend this + * dedication to be an overt act of relinquishment in perpetuity of all present + * and future rights to this software under copyright law. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef _NVXX_ITERATOR_H_INCLUDED +#define _NVXX_ITERATOR_H_INCLUDED + +#include <variant> +#include <iterator> +#include <concepts> + +/* + * iterator support for libnvxx. this exposes a const_nv_list as an iterable + * container or range. + */ + +namespace bsd { + +// the key type of an nvlist value +using nv_list_key_t = std::string_view; + +// the value type of an nvlist value +using nv_list_value_t = std::variant< + nullptr_t, /* null */ + bool, /* bool */ + std::uint64_t, /* number */ + std::string_view, /* string */ + const_nv_list, /* nvlist */ + int, /* descriptor */ + std::span<std::byte const> /* binary */ +>; + +// the iterator value type +using nv_list_pair_t = std::pair<nv_list_key_t, nv_list_value_t>; + +/* + * The nvlist iterator type. This is never an 'end' iterator, because we use + * a sentinel for that. + */ +struct nv_list_iterator { + using iterator_category = std::forward_iterator_tag; + using difference_type = std::ptrdiff_t; + using value_type = nv_list_pair_t; + using pointer = value_type *; + using const_pointer = value_type const *; + using reference = value_type &; + using const_reference = value_type const &; + using sentinel = std::default_sentinel_t; + + nv_list_iterator(); + explicit nv_list_iterator(const_nv_list const &nvl); + explicit nv_list_iterator(nv_list const &nvl); + + nv_list_iterator &operator++(); + nv_list_iterator operator++(int); + + bool operator==(nv_list_iterator const &other) const; + bool operator==(std::default_sentinel_t) const; + + const_reference operator*() const; + const_pointer operator->() const; + +private: + ::nvlist_t const *__nvlist = nullptr; + void *__cookie = nullptr; + nv_list_pair_t __current; + + void __advance(); +}; + +static_assert(std::forward_iterator<nv_list_iterator>); +static_assert(std::sentinel_for<std::default_sentinel_t, nv_list_iterator>); + +nv_list_iterator begin(const_nv_list const &nvl); +nv_list_iterator begin(nv_list const &nvl); +std::default_sentinel_t end(const_nv_list const &); +std::default_sentinel_t end(nv_list const &); + +}; + +#endif /* !_NVXX_ITERATOR_H_INCLUDED */ diff --git a/libnvxx/tests/Makefile b/libnvxx/tests/Makefile index 29d0351..db4b538 100644 --- a/libnvxx/tests/Makefile +++ b/libnvxx/tests/Makefile @@ -20,7 +20,7 @@ PREFIX?= /usr/local TESTSDIR?= ${PREFIX}/tests/nvxx -ATF_TESTS_CXX= nvxx_basic +ATF_TESTS_CXX= nvxx_basic nvxx_iterator CXXSTD= c++23 # Note that we can't use -Werror here because it breaks ATF. CXXFLAGS+= -W -Wall -Wextra diff --git a/libnvxx/tests/nvxx_iterator.cc b/libnvxx/tests/nvxx_iterator.cc new file mode 100644 index 0000000..df78bdf --- /dev/null +++ b/libnvxx/tests/nvxx_iterator.cc @@ -0,0 +1,78 @@ +/* + * This is free and unencumbered software released into the public domain. + * + * Anyone is free to copy, modify, publish, use, compile, sell, or distribute + * this software, either in source code form or as a compiled binary, for any + * purpose, commercial or non-commercial, and by any means. + * + * In jurisdictions that recognize copyright laws, the author or authors of + * this software dedicate any and all copyright interest in the software to the + * public domain. We make this dedication for the benefit of the public at + * large and to the detriment of our heirs and successors. We intend this + * dedication to be an overt act of relinquishment in perpetuity of all present + * and future rights to this software under copyright law. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include <algorithm> +#include <ranges> +#include <list> +#include <vector> +#include <span> +#include <string> +#include <string_view> + +#include <atf-c++.hpp> + +#include "nvxx.h" + +#define TEST_CASE(name) \ + ATF_TEST_CASE_WITHOUT_HEAD(name) \ + ATF_TEST_CASE_BODY(name) + +TEST_CASE(nvxx_basic_iterate) +{ + using namespace std::literals; + auto nvl = bsd::nv_list(); + + nvl.add_number("a number", 42); + nvl.add_string("a string", "a test string"); + nvl.add_bool("a bool", true); + + auto begin = std::ranges::begin(nvl); + auto end = std::ranges::end(nvl); + + auto i = 0u; + while (begin != end) { + auto name = begin->first; + auto const &value = begin->second; + + if (std::holds_alternative<std::uint64_t>(value)) { + ATF_REQUIRE_EQ("a number"sv, name); + ATF_REQUIRE_EQ(42, std::get<std::uint64_t>(value)); + } else if (std::holds_alternative<std::string_view>(value)) { + ATF_REQUIRE_EQ("a string"sv, name); + ATF_REQUIRE_EQ("a test string", + std::get<std::string_view>(value)); + } else if (std::holds_alternative<bool>(value)) { + ATF_REQUIRE_EQ("a bool"sv, name); + ATF_REQUIRE_EQ(true, std::get<bool>(value)); + } else + ATF_REQUIRE_EQ(true, false); + + ++i; + ++begin; + } + ATF_REQUIRE_EQ(3, i); +} + +ATF_INIT_TEST_CASES(tcs) +{ + ATF_ADD_TEST_CASE(tcs, nvxx_basic_iterate); +} |
