mirror of
https://gitlab.freedesktop.org/monado/monado.git
synced 2025-02-03 12:28:07 +00:00
a/util: Add utility for lists of strings, like extension lists.
This commit is contained in:
parent
ea38309c86
commit
27a8ec675b
src/xrt/auxiliary
|
@ -183,6 +183,9 @@ add_library(
|
|||
util/u_sink_queue.c
|
||||
util/u_sink_quirk.c
|
||||
util/u_sink_split.c
|
||||
util/u_string_list.cpp
|
||||
util/u_string_list.h
|
||||
util/u_string_list.hpp
|
||||
util/u_template_historybuf.hpp
|
||||
util/u_time.cpp
|
||||
util/u_time.h
|
||||
|
|
113
src/xrt/auxiliary/util/u_string_list.cpp
Normal file
113
src/xrt/auxiliary/util/u_string_list.cpp
Normal file
|
@ -0,0 +1,113 @@
|
|||
// Copyright 2021, Collabora, Ltd.
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
/*!
|
||||
* @file
|
||||
* @brief A collection of strings, like a list of extensions to enable
|
||||
*
|
||||
* @author Ryan Pavlik <ryan.pavlik@collabora.com>
|
||||
* @ingroup aux_util
|
||||
*
|
||||
*/
|
||||
|
||||
#include "u_string_list.h"
|
||||
#include "u_string_list.hpp"
|
||||
|
||||
using xrt::auxiliary::util::StringList;
|
||||
|
||||
|
||||
struct u_string_list
|
||||
{
|
||||
u_string_list() = default;
|
||||
u_string_list(StringList &&sl) : list(std::move(sl)) {}
|
||||
|
||||
StringList list;
|
||||
};
|
||||
|
||||
struct u_string_list *
|
||||
u_string_list_create()
|
||||
{
|
||||
try {
|
||||
auto ret = std::make_unique<u_string_list>();
|
||||
return ret.release();
|
||||
} catch (std::exception const &) {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
struct u_string_list *
|
||||
u_string_list_create_with_capacity(uint32_t capacity)
|
||||
{
|
||||
|
||||
try {
|
||||
auto ret = std::make_unique<u_string_list>(xrt::auxiliary::util::StringList{capacity});
|
||||
return ret.release();
|
||||
} catch (std::exception const &) {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
uint32_t
|
||||
u_string_list_get_size(const struct u_string_list *usl)
|
||||
{
|
||||
|
||||
if (usl == nullptr) {
|
||||
return 0;
|
||||
}
|
||||
return usl->list.size();
|
||||
}
|
||||
|
||||
|
||||
const char *const *
|
||||
u_string_list_get_data(const struct u_string_list *usl)
|
||||
{
|
||||
|
||||
if (usl == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
return usl->list.data();
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
u_string_list_append(struct u_string_list *usl, const char *str)
|
||||
{
|
||||
if (usl == nullptr) {
|
||||
return -1;
|
||||
}
|
||||
try {
|
||||
usl->list.push_back(str);
|
||||
return 1;
|
||||
} catch (std::exception const &) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
u_string_list_append_unique(struct u_string_list *usl, const char *str)
|
||||
{
|
||||
if (usl == nullptr) {
|
||||
return -1;
|
||||
}
|
||||
try {
|
||||
auto added = usl->list.push_back_unique(str);
|
||||
return added ? 1 : 0;
|
||||
} catch (std::exception const &) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
u_string_list_destroy(struct u_string_list **list_ptr)
|
||||
{
|
||||
if (list_ptr == nullptr) {
|
||||
return;
|
||||
}
|
||||
u_string_list *list = *list_ptr;
|
||||
if (list == nullptr) {
|
||||
return;
|
||||
}
|
||||
delete list;
|
||||
*list_ptr = nullptr;
|
||||
}
|
99
src/xrt/auxiliary/util/u_string_list.h
Normal file
99
src/xrt/auxiliary/util/u_string_list.h
Normal file
|
@ -0,0 +1,99 @@
|
|||
// Copyright 2021, Collabora, Ltd.
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
/*!
|
||||
* @file
|
||||
* @brief A collection of strings, like a list of extensions to enable
|
||||
*
|
||||
* @author Ryan Pavlik <ryan.pavlik@collabora.com>
|
||||
* @ingroup aux_util
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
/*!
|
||||
* @brief A collection of string literals (const char *), such as used for extension name lists.
|
||||
*
|
||||
* @see xrt::auxiliary::util::StringList
|
||||
*/
|
||||
struct u_string_list;
|
||||
|
||||
/*!
|
||||
* @brief Create a string list with room for at least the given number of strings.
|
||||
*
|
||||
* @public @memberof u_string_list
|
||||
*/
|
||||
struct u_string_list *
|
||||
u_string_list_create(void);
|
||||
|
||||
/*!
|
||||
* @brief Create a string list with room for at least the given number of strings.
|
||||
*
|
||||
* @public @memberof u_string_list
|
||||
*/
|
||||
struct u_string_list *
|
||||
u_string_list_create_with_capacity(uint32_t capacity);
|
||||
|
||||
/*!
|
||||
* @brief Retrieve the number of elements in the list
|
||||
*
|
||||
* @public @memberof u_string_list
|
||||
*/
|
||||
uint32_t
|
||||
u_string_list_get_size(const struct u_string_list *usl);
|
||||
|
||||
/*!
|
||||
* @brief Retrieve the data pointer of the list
|
||||
*
|
||||
* @public @memberof u_string_list
|
||||
*/
|
||||
const char *const *
|
||||
u_string_list_get_data(const struct u_string_list *usl);
|
||||
|
||||
/*!
|
||||
* @brief Append a new string literal to the list.
|
||||
*
|
||||
* @param usl self pointer
|
||||
* @param str a non-null, null-terminated string that must live at least as long as the list, preferably a string
|
||||
* literal.
|
||||
* @return 1 if successfully added, negative for errors.
|
||||
*
|
||||
* @public @memberof u_string_list
|
||||
*/
|
||||
int
|
||||
u_string_list_append(struct u_string_list *usl, const char *str);
|
||||
|
||||
/*!
|
||||
* @brief Append a new string literal to the list, if it's not the same as a string already in the list.
|
||||
*
|
||||
* (Comparing string contents, not just pointers)
|
||||
*
|
||||
* @param usl self pointer
|
||||
* @param str a non-null, null-terminated string that must live at least as long as the list, preferably a string
|
||||
* literal.
|
||||
* @return 1 if successfully added, 0 if already existing so not added, negative for errors.
|
||||
*
|
||||
* @public @memberof u_string_list
|
||||
*/
|
||||
int
|
||||
u_string_list_append_unique(struct u_string_list *usl, const char *str);
|
||||
|
||||
/*!
|
||||
* @brief Destroy a string list.
|
||||
*
|
||||
* Performs null checks and sets your pointer to zero.
|
||||
*
|
||||
* @public @memberof u_string_list
|
||||
*/
|
||||
void
|
||||
u_string_list_destroy(struct u_string_list **list_ptr);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
148
src/xrt/auxiliary/util/u_string_list.hpp
Normal file
148
src/xrt/auxiliary/util/u_string_list.hpp
Normal file
|
@ -0,0 +1,148 @@
|
|||
// Copyright 2021, Collabora, Ltd.
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
/*!
|
||||
* @file
|
||||
* @brief A collection of strings, like a list of extensions to enable
|
||||
*
|
||||
* @author Ryan Pavlik <ryan.pavlik@collabora.com>
|
||||
* @ingroup aux_util
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "u_string_list.h"
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
#include <limits>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <algorithm>
|
||||
|
||||
namespace xrt::auxiliary::util {
|
||||
|
||||
/*!
|
||||
* @brief A collection of strings (const char *), like a list of extensions to enable.
|
||||
*
|
||||
* This version is only for use with strings that will outlive this object, preferably string literals.
|
||||
*
|
||||
* Size is limited to one less than the max value of uint32_t which shouldn't be a problem,
|
||||
* the size really should be much smaller (especially if you use push_back_unique()).
|
||||
*/
|
||||
class StringList
|
||||
{
|
||||
public:
|
||||
/// Construct a string list.
|
||||
StringList() = default;
|
||||
/// Construct a string list with the given capacity.
|
||||
StringList(uint32_t capacity) : vec(capacity, nullptr)
|
||||
{
|
||||
// best way I know to create with capacity
|
||||
vec.clear();
|
||||
}
|
||||
StringList(StringList &&) = default;
|
||||
StringList(StringList const &) = default;
|
||||
|
||||
StringList &
|
||||
operator=(StringList &&) = default;
|
||||
StringList &
|
||||
operator=(StringList const &) = default;
|
||||
|
||||
/// Construct a string list with the given items
|
||||
template <uint32_t N> StringList(const char *(&arr)[N]) : StringList(N)
|
||||
{
|
||||
for (auto &&elt : arr) {
|
||||
push_back(elt);
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Get the size of the array (the number of strings)
|
||||
*/
|
||||
uint32_t
|
||||
size() const noexcept
|
||||
{
|
||||
return static_cast<uint32_t>(vec.size());
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Get the data pointer of the array
|
||||
*/
|
||||
const char *const *
|
||||
data() const noexcept
|
||||
{
|
||||
return vec.data();
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Append a new string to the list.
|
||||
*
|
||||
* @param str a non-null, null-terminated string that must live at least as long as the list,
|
||||
* preferably a string literal.
|
||||
*
|
||||
* @throws std::out_of_range if you have a ridiculous number of strings in your list already,
|
||||
* std::invalid_argument if you pass a null pointer.
|
||||
*/
|
||||
void
|
||||
push_back(const char *str)
|
||||
{
|
||||
|
||||
if (vec.size() > std::numeric_limits<uint32_t>::max() - 1) {
|
||||
throw std::out_of_range("Size limit reached");
|
||||
}
|
||||
if (str == nullptr) {
|
||||
throw std::invalid_argument("Cannot pass a null pointer");
|
||||
}
|
||||
vec.push_back(str);
|
||||
}
|
||||
|
||||
/// Add all given items
|
||||
/// @throws the same as what push_back() throws
|
||||
template <uint32_t N>
|
||||
void
|
||||
push_back_all(const char *(&arr)[N])
|
||||
{
|
||||
for (auto &&elt : arr) {
|
||||
push_back(elt);
|
||||
}
|
||||
}
|
||||
/*!
|
||||
* @brief Append a new string to the list if it doesn't match any existing string.
|
||||
*
|
||||
* (Comparing string contents, not just pointers)
|
||||
*
|
||||
* This does a simple linear search, because it is assumed that the size of this list is fairly small.
|
||||
*
|
||||
* @param str a non-null, null-terminated string that must live at least as long as the list,
|
||||
* preferably a string literal.
|
||||
*
|
||||
* @return true if we added it
|
||||
*
|
||||
* @throws std::out_of_range if you have a ridiculous number of strings in your list already,
|
||||
* std::invalid_argument if you pass a null pointer.
|
||||
*/
|
||||
bool
|
||||
push_back_unique(const char *str)
|
||||
{
|
||||
if (vec.size() > std::numeric_limits<uint32_t>::max() - 1) {
|
||||
throw std::out_of_range("Size limit reached");
|
||||
}
|
||||
if (str == nullptr) {
|
||||
throw std::invalid_argument("Cannot pass a null pointer");
|
||||
}
|
||||
std::string needle{str};
|
||||
auto it = std::find_if(vec.begin(), vec.end(), [needle](const char *elt) { return needle == elt; });
|
||||
if (it != vec.end()) {
|
||||
// already have it
|
||||
return false;
|
||||
}
|
||||
vec.push_back(str);
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
std::vector<const char *> vec;
|
||||
};
|
||||
|
||||
} // namespace xrt::auxiliary::util
|
Loading…
Reference in a new issue