Monado OpenXR Runtime
u_string_list.hpp
Go to the documentation of this file.
1// Copyright 2021, Collabora, Ltd.
2// SPDX-License-Identifier: BSL-1.0
3/*!
4 * @file
5 * @brief A collection of strings, like a list of extensions to enable
6 *
7 * @author Rylie Pavlik <rylie.pavlik@collabora.com>
8 * @ingroup aux_util
9 *
10 */
11
12#pragma once
13
14#include "u_string_list.h"
15
16#include <memory>
17#include <vector>
18#include <limits>
19#include <stdexcept>
20#include <string>
21#include <algorithm>
22
23namespace xrt::auxiliary::util {
24
25/*!
26 * @brief A collection of strings (const char *), like a list of extensions to enable.
27 *
28 * This version is only for use with strings that will outlive this object, preferably string literals.
29 *
30 * Size is limited to one less than the max value of uint32_t which shouldn't be a problem,
31 * the size really should be much smaller (especially if you use push_back_unique()).
32 */
34{
35public:
36 /// Construct a string list.
37 StringList() = default;
38 /// Construct a string list with the given capacity.
39 StringList(uint32_t capacity) : vec(capacity, nullptr)
40 {
41 // best way I know to create with capacity
42 vec.clear();
43 }
44 StringList(StringList &&) = default;
45 StringList(StringList const &) = default;
46
48 operator=(StringList &&) = default;
50 operator=(StringList const &) = default;
51
52 /// Construct a string list with the given items
53 template <uint32_t N> StringList(const char *(&arr)[N]) : StringList(N)
54 {
55 for (auto &&elt : arr) {
56 push_back(elt);
57 }
58 }
59
60 /*!
61 * @brief Get the size of the array (the number of strings)
62 */
63 uint32_t
64 size() const noexcept
65 {
66 return static_cast<uint32_t>(vec.size());
67 }
68
69 /*!
70 * @brief Get the data pointer of the array
71 */
72 const char *const *
73 data() const noexcept
74 {
75 return vec.data();
76 }
77
78 /*!
79 * @brief Append a new string to the list.
80 *
81 * @param str a non-null, null-terminated string that must live at least as long as the list,
82 * preferably a string literal.
83 *
84 * @throws std::out_of_range if you have a ridiculous number of strings in your list already,
85 * std::invalid_argument if you pass a null pointer.
86 */
87 void
88 push_back(const char *str)
89 {
90
91 if (vec.size() > (std::numeric_limits<uint32_t>::max)() - 1) {
92 throw std::out_of_range("Size limit reached");
93 }
94 if (str == nullptr) {
95 throw std::invalid_argument("Cannot pass a null pointer");
96 }
97 vec.push_back(str);
98 }
99
100 /// Add all given items
101 /// @throws the same as what push_back() throws
102 template <uint32_t N>
103 void
104 push_back_all(const char *(&arr)[N])
105 {
106 for (auto &&elt : arr) {
107 push_back(elt);
108 }
109 }
110
111 /*!
112 * @brief Check if the string is in the list.
113 *
114 * (Comparing string contents, not pointers)
115 *
116 * @param str a non-null, null-terminated string.
117 *
118 * @return true if the string is in the list.
119 */
120 bool
121 contains(const char *str)
122 {
123 if (str == nullptr) {
124 throw std::invalid_argument("Cannot pass a null pointer");
125 }
126 std::string needle{str};
127 auto it = std::find_if(vec.begin(), vec.end(), [needle](const char *elt) { return needle == elt; });
128 return it != vec.end();
129 }
130
131 /*!
132 * @brief Append a new string to the list if it doesn't match any existing string.
133 *
134 * (Comparing string contents, not pointers)
135 *
136 * This does a simple linear search, because it is assumed that the size of this list is fairly small.
137 *
138 * @param str a non-null, null-terminated string that must live at least as long as the list,
139 * preferably a string literal.
140 *
141 * @return true if we added it
142 *
143 * @throws std::out_of_range if you have a ridiculous number of strings in your list already,
144 * std::invalid_argument if you pass a null pointer.
145 */
146 bool
147 push_back_unique(const char *str)
148 {
149 if (vec.size() > (std::numeric_limits<uint32_t>::max)() - 1) {
150 throw std::out_of_range("Size limit reached");
151 }
152 if (str == nullptr) {
153 throw std::invalid_argument("Cannot pass a null pointer");
154 }
155 std::string needle{str};
156 auto it = std::find_if(vec.begin(), vec.end(), [needle](const char *elt) { return needle == elt; });
157 if (it != vec.end()) {
158 // already have it
159 return false;
160 }
161 vec.push_back(str);
162 return true;
163 }
164
165private:
166 std::vector<const char *> vec;
167};
168
169} // namespace xrt::auxiliary::util
A collection of strings (const char *), like a list of extensions to enable.
Definition: u_string_list.hpp:34
void push_back_all(const char *(&arr)[N])
Add all given items.
Definition: u_string_list.hpp:104
StringList()=default
Construct a string list.
void push_back(const char *str)
Append a new string to the list.
Definition: u_string_list.hpp:88
StringList(const char *(&arr)[N])
Construct a string list with the given items.
Definition: u_string_list.hpp:53
bool push_back_unique(const char *str)
Append a new string to the list if it doesn't match any existing string.
Definition: u_string_list.hpp:147
const char *const * data() const noexcept
Get the data pointer of the array.
Definition: u_string_list.hpp:73
bool contains(const char *str)
Check if the string is in the list.
Definition: u_string_list.hpp:121
StringList(uint32_t capacity)
Construct a string list with the given capacity.
Definition: u_string_list.hpp:39
uint32_t size() const noexcept
Get the size of the array (the number of strings)
Definition: u_string_list.hpp:64
A collection of strings, like a list of extensions to enable.