Compare commits

...

4 Commits

Author SHA1 Message Date
36942cca18 [nostalgia,olympic] Replace SpanView with Span<const T>
All checks were successful
Build / build (push) Successful in 2m36s
2024-12-01 08:41:20 -06:00
b14f1d5000 [ox] Replace SpanView with Span<const T> 2024-12-01 08:41:08 -06:00
1bf4f246c2 [applib] Make run take args as a SpanView 2024-11-28 00:51:42 -06:00
edda8e010e [ox/clargs] Add constructor that takes a SpanView 2024-11-28 00:51:02 -06:00
21 changed files with 115 additions and 176 deletions

View File

@ -11,18 +11,19 @@
namespace ox { namespace ox {
ClArgs::ClArgs(int argc, const char **args) noexcept { ClArgs::ClArgs(int argc, const char **args) noexcept: ClArgs({args, static_cast<size_t>(argc)}) {}
auto const argv = ox::SpanView{args, static_cast<size_t>(argc)};
for (auto i = 0u; i < static_cast<unsigned>(argc); ++i) { ClArgs::ClArgs(ox::SpanView<const char*> args) noexcept {
auto arg = StringView(argv[i]); for (auto i = 0u; i < args.size(); ++i) {
auto arg = StringView(args[i]);
if (arg[0] == '-') { if (arg[0] == '-') {
while (arg[0] == '-' && arg.len()) { while (arg[0] == '-' && arg.len()) {
arg = substr(arg, 1); arg = substr(arg, 1);
} }
m_bools[arg] = true; m_bools[arg] = true;
// parse additional arguments // parse additional arguments
if (i < static_cast<unsigned>(argc) && argv[i + 1]) { if (i < args.size() && args[i + 1]) {
auto val = String(argv[i + 1]); auto val = String(args[i + 1]);
if (val.len() && val[i] != '-') { if (val.len() && val[i] != '-') {
if (val == "false") { if (val == "false") {
m_bools[arg] = false; m_bools[arg] = false;

View File

@ -9,6 +9,7 @@
#pragma once #pragma once
#include <ox/std/hashmap.hpp> #include <ox/std/hashmap.hpp>
#include <ox/std/span.hpp>
#include <ox/std/string.hpp> #include <ox/std/string.hpp>
namespace ox { namespace ox {
@ -22,6 +23,8 @@ class ClArgs {
public: public:
ClArgs(int argc, const char **args) noexcept; ClArgs(int argc, const char **args) noexcept;
ClArgs(ox::SpanView<const char*> args) noexcept;
[[nodiscard]] [[nodiscard]]
bool getBool(ox::StringViewCR arg, bool defaultValue) const noexcept; bool getBool(ox::StringViewCR arg, bool defaultValue) const noexcept;

View File

@ -231,7 +231,7 @@ int main(int argc, const char **argv) {
oxError("Must specify test to run"); oxError("Must specify test to run");
return -1; return -1;
} }
auto const args = ox::SpanView{argv, static_cast<size_t>(argc)}; auto const args = ox::Span{argv, static_cast<size_t>(argc)};
ox::StringView const testName = args[1]; ox::StringView const testName = args[1];
ox::StringView const testArg = argc >= 3 ? args[2] : nullptr; ox::StringView const testArg = argc >= 3 ? args[2] : nullptr;
auto const func = tests.find(testName); auto const func = tests.find(testName);

View File

@ -39,7 +39,7 @@ static ox::Result<ox::UniquePtr<ox::FileSystem>> loadFs(const char *path) noexce
return {ox::make_unique<ox::FileSystem32>(buff.data, buff.size)}; return {ox::make_unique<ox::FileSystem32>(buff.data, buff.size)};
} }
static ox::Error runLs(ox::FileSystem *fs, ox::SpanView<const char*> args) noexcept { static ox::Error runLs(ox::FileSystem *fs, ox::Span<const char*> args) noexcept {
if (args.size() < 2) { if (args.size() < 2) {
oxErr("Must provide a directory to ls\n"); oxErr("Must provide a directory to ls\n");
return OxError(1); return OxError(1);
@ -51,7 +51,7 @@ static ox::Error runLs(ox::FileSystem *fs, ox::SpanView<const char*> args) noexc
return OxError(0); return OxError(0);
} }
static ox::Error runRead(ox::FileSystem *fs, ox::SpanView<const char*> args) noexcept { static ox::Error runRead(ox::FileSystem *fs, ox::Span<const char*> args) noexcept {
if (args.size() < 2) { if (args.size() < 2) {
oxErr("Must provide a path to a file to read\n"); oxErr("Must provide a path to a file to read\n");
return OxError(1); return OxError(1);
@ -66,7 +66,7 @@ static ox::Error run(int argc, const char **argv) noexcept {
oxErr("OxFS file and subcommand arguments are required\n"); oxErr("OxFS file and subcommand arguments are required\n");
return OxError(1); return OxError(1);
} }
auto const args = ox::SpanView{argv, static_cast<size_t>(argc)}; auto const args = ox::Span{argv, static_cast<size_t>(argc)};
auto const fsPath = args[1]; auto const fsPath = args[1];
ox::String subCmd(args[2]); ox::String subCmd(args[2]);
oxRequire(fs, loadFs(fsPath)); oxRequire(fs, loadFs(fsPath));

View File

@ -21,7 +21,7 @@ namespace ox {
extern template class Vector<char>; extern template class Vector<char>;
using Buffer = Vector<char>; using Buffer = Vector<char>;
using BufferView = SpanView<char>; using BufferView = Span<const char>;
class BufferWriter { class BufferWriter {
private: private:

View File

@ -18,126 +18,6 @@ OX_CLANG_NOWARN_BEGIN(-Wunsafe-buffer-usage)
namespace ox { namespace ox {
template<typename T>
class SpanView {
private:
T const*m_items{};
std::size_t m_size{};
public:
using value_type = T;
using size_type = std::size_t;
template<typename RefType = T const&, typename PtrType = T const*, bool reverse = false>
using iterator = SpanIterator<T, RefType, PtrType, reverse>;
constexpr SpanView() noexcept {}
template<std::size_t sz>
constexpr SpanView(ox::Array<T, sz> const&a) noexcept:
m_items(a.data()),
m_size(a.size()) {
}
template<std::size_t sz, typename Allocator>
constexpr SpanView(ox::Vector<T, sz, Allocator> const&v) noexcept:
m_items(v.data()),
m_size(v.size()) {
}
template<std::size_t sz>
constexpr SpanView(const T (&a)[sz]) noexcept:
m_items(a),
m_size(sz) {
}
constexpr SpanView(const T *a, std::size_t sz) noexcept:
m_items(a),
m_size(sz) {
}
constexpr iterator<> begin() noexcept {
return iterator<>(m_items, 0, m_size);
}
constexpr iterator<> end() noexcept {
return iterator<>(m_items, m_size, m_size);
}
[[nodiscard]]
constexpr iterator<const T&, const T*> begin() const noexcept {
return iterator<const T&, const T*>(m_items, 0, m_size);
}
[[nodiscard]]
constexpr iterator<const T&, const T*> end() const noexcept {
return iterator<const T&, const T*>(m_items, m_size, m_size);
}
[[nodiscard]]
constexpr iterator<const T&, const T*> cbegin() const noexcept {
return iterator<const T&, const T*>(m_items, 0, m_size);
}
[[nodiscard]]
constexpr iterator<const T&, const T*> cend() const noexcept {
return iterator<const T&, const T*>(m_items, m_size, m_size);
}
[[nodiscard]]
constexpr iterator<const T&, const T*, true> crbegin() const noexcept {
return iterator<const T&, const T*, true>(m_items, m_size - 1, m_size);
}
[[nodiscard]]
constexpr iterator<const T&, const T*, true> crend() const noexcept {
return iterator<const T&, const T*, true>(m_items, MaxValue<size_type>, m_size);
}
[[nodiscard]]
constexpr iterator<const T&, const T*, true> rbegin() const noexcept {
return iterator<const T&, const T*, true>(m_items, m_size - 1, m_size);
}
[[nodiscard]]
constexpr iterator<const T&, const T*, true> rend() const noexcept {
return iterator<const T&, const T*, true>(m_items, MaxValue<size_type>, m_size);
}
constexpr const T &operator[](std::size_t i) const noexcept {
ox::primitiveAssert(__FILE__, __LINE__, i < size(), "Span access overflow");
return m_items[i];
}
constexpr SpanView operator+(size_t i) const noexcept {
ox::primitiveAssert(__FILE__, __LINE__, i < size(), "Span access overflow");
return {m_items + i, m_size - i};
}
constexpr SpanView operator+=(size_t i) noexcept {
ox::primitiveAssert(__FILE__, __LINE__, i < size(), "Span access overflow");
m_items += i;
m_size -= i;
return *this;
}
[[nodiscard]]
constexpr T const*data() const noexcept {
return m_items;
}
[[nodiscard]]
constexpr std::size_t size() const noexcept {
return m_size;
}
[[nodiscard]]
constexpr bool empty() const noexcept {
return m_size == 0;
}
};
template<typename T> template<typename T>
class Span { class Span {
@ -153,18 +33,32 @@ class Span {
template<typename RefType = T&, typename PtrType = T*, bool reverse = false> template<typename RefType = T&, typename PtrType = T*, bool reverse = false>
using iterator = SpanIterator<T, RefType, PtrType, reverse>; using iterator = SpanIterator<T, RefType, PtrType, reverse>;
constexpr Span() noexcept = default;
template<std::size_t sz> template<std::size_t sz>
constexpr Span(ox::Array<T, sz> &a) noexcept: constexpr Span(ox::Array<T, sz> &a) noexcept:
m_items(a.data()), m_items(a.data()),
m_size(a.size()) { m_size(a.size()) {
} }
template<std::size_t sz>
constexpr Span(ox::Array<ox::remove_const_t<T>, sz> const&a) noexcept:
m_items(a.data()),
m_size(a.size()) {
}
template<std::size_t sz, typename Allocator> template<std::size_t sz, typename Allocator>
constexpr Span(ox::Vector<T, sz, Allocator> &v) noexcept: constexpr Span(ox::Vector<T, sz, Allocator> &v) noexcept:
m_items(v.data()), m_items(v.data()),
m_size(v.size()) { m_size(v.size()) {
} }
template<std::size_t sz, typename Allocator>
constexpr Span(ox::Vector<ox::remove_const_t<T>, sz, Allocator> const&v) noexcept:
m_items(v.data()),
m_size(v.size()) {
}
template<std::size_t sz> template<std::size_t sz>
constexpr Span(T (&a)[sz]) noexcept: constexpr Span(T (&a)[sz]) noexcept:
m_items(a), m_items(a),
@ -273,6 +167,9 @@ class Span {
}; };
template<typename T>
using SpanView = Span<const T>;
} }
OX_CLANG_NOWARN_END OX_CLANG_NOWARN_END

View File

@ -477,7 +477,7 @@ int main(int argc, const char **argv) {
oxError("Must specify test to run"); oxError("Must specify test to run");
return -1; return -1;
} }
auto const args = ox::SpanView{argv, static_cast<size_t>(argc)}; auto const args = ox::Span{argv, static_cast<size_t>(argc)};
auto const testName = args[1]; auto const testName = args[1];
auto const func = tests.find(testName); auto const func = tests.find(testName);
if (func != tests.end()) { if (func != tests.end()) {

View File

@ -269,6 +269,41 @@ template<class T>
constexpr bool is_move_constructible_v = detail::is_move_constructible<T>(0); constexpr bool is_move_constructible_v = detail::is_move_constructible<T>(0);
template<typename T>
struct remove_cv {
using type = T;
};
template<typename T>
struct remove_cv<const T> {
using type = T;
};
template<typename T>
struct remove_cv<volatile T> {
using type = T;
};
template<typename T>
struct remove_cv<const volatile T> {
using type = T;
};
template<typename T>
struct remove_const {
using type = T;
};
template<typename T>
struct remove_const<const T> {
using type = T;
};
template<typename T>
using remove_const_t = typename remove_const<T>::type;
// is String? // is String?
template<std::size_t SmallStringSize> template<std::size_t SmallStringSize>

View File

@ -20,7 +20,7 @@
#include "types.hpp" #include "types.hpp"
#include "utility.hpp" #include "utility.hpp"
OX_CLANG_NOWARN_BEGIN(-Wunsafe-buffer-usage) OX_ALLOW_UNSAFE_BUFFERS_BEGIN
namespace ox { namespace ox {
@ -712,4 +712,4 @@ constexpr auto alignOf(const Vector<T>&) noexcept {
} }
OX_CLANG_NOWARN_END OX_ALLOW_UNSAFE_BUFFERS_END

View File

@ -2,6 +2,8 @@
* Copyright 2016 - 2024 Gary Talent (gary@drinkingtea.net). All rights reserved. * Copyright 2016 - 2024 Gary Talent (gary@drinkingtea.net). All rights reserved.
*/ */
#include <ox/std/algorithm.hpp>
#include "deletetilescommand.hpp" #include "deletetilescommand.hpp"
namespace nostalgia::core { namespace nostalgia::core {
@ -20,11 +22,9 @@ core::DeleteTilesCommand::DeleteTilesCommand(
// copy pixels to be erased // copy pixels to be erased
{ {
auto &s = getSubSheet(m_img, m_idx); auto &s = getSubSheet(m_img, m_idx);
auto &p = s.pixels; auto dst = m_deletedPixels.begin();
auto dst = m_deletedPixels.data(); auto src = s.pixels.begin() + m_deletePos;
auto src = &p[m_deletePos]; ox::copy_n(src, m_deleteSz, dst);
const auto sz = m_deleteSz * sizeof(decltype(p[0]));
ox::memcpy(dst, src, sz);
} }
} }
@ -32,9 +32,9 @@ ox::Error core::DeleteTilesCommand::redo() noexcept {
auto &s = getSubSheet(m_img, m_idx); auto &s = getSubSheet(m_img, m_idx);
auto &p = s.pixels; auto &p = s.pixels;
auto srcPos = m_deletePos + m_deleteSz; auto srcPos = m_deletePos + m_deleteSz;
const auto src = &p[srcPos]; auto const src = &p[srcPos];
const auto dst1 = &p[m_deletePos]; auto const dst1 = &p[m_deletePos];
const auto dst2 = &p[(p.size() - m_deleteSz)]; auto const dst2 = &p[(p.size() - m_deleteSz)];
ox::memmove(dst1, src, p.size() - srcPos); ox::memmove(dst1, src, p.size() - srcPos);
ox::memset(dst2, 0, m_deleteSz * sizeof(decltype(p[0]))); ox::memset(dst2, 0, m_deleteSz * sizeof(decltype(p[0])));
return {}; return {};
@ -43,10 +43,10 @@ ox::Error core::DeleteTilesCommand::redo() noexcept {
ox::Error DeleteTilesCommand::undo() noexcept { ox::Error DeleteTilesCommand::undo() noexcept {
auto &s = getSubSheet(m_img, m_idx); auto &s = getSubSheet(m_img, m_idx);
auto &p = s.pixels; auto &p = s.pixels;
const auto src = &p[m_deletePos]; auto const src = &p[m_deletePos];
const auto dst1 = &p[m_deletePos + m_deleteSz]; auto const dst1 = &p[m_deletePos + m_deleteSz];
const auto dst2 = src; auto const dst2 = src;
const auto sz = p.size() - m_deletePos - m_deleteSz; auto const sz = p.size() - m_deletePos - m_deleteSz;
ox::memmove(dst1, src, sz); ox::memmove(dst1, src, sz);
ox::memcpy(dst2, m_deletedPixels.data(), m_deletedPixels.size()); ox::memcpy(dst2, m_deletedPixels.data(), m_deletedPixels.size());
return {}; return {};

View File

@ -21,10 +21,9 @@ core::InsertTilesCommand::InsertTilesCommand(
{ {
auto &s = getSubSheet(m_img, m_idx); auto &s = getSubSheet(m_img, m_idx);
auto &p = s.pixels; auto &p = s.pixels;
auto dst = m_deletedPixels.data(); auto dst = m_deletedPixels.begin();
auto src = &p[p.size() - m_insertCnt]; auto src = p.begin() + p.size() - m_insertCnt;
const auto sz = m_insertCnt * sizeof(decltype(p[0])); ox::copy_n(src, m_insertCnt, dst);
ox::memcpy(dst, src, sz);
} }
} }

View File

@ -27,7 +27,7 @@ static std::map<ox::StringView, ox::Error(*)()> tests = {
int main(int argc, const char **argv) { int main(int argc, const char **argv) {
int retval = -1; int retval = -1;
if (argc > 0) { if (argc > 0) {
auto const args = ox::SpanView{argv, static_cast<size_t>(argc)}; auto const args = ox::Span{argv, static_cast<size_t>(argc)};
auto const testName = ox::StringView(args[1]); auto const testName = ox::StringView(args[1]);
if (tests.find(testName) != tests.end()) { if (tests.find(testName) != tests.end()) {
retval = static_cast<int>(tests[testName]()); retval = static_cast<int>(tests[testName]());

View File

@ -41,8 +41,7 @@ ox::Error run(
ox::StringView project, ox::StringView project,
ox::StringView appName, ox::StringView appName,
ox::StringView projectDataDir, ox::StringView projectDataDir,
int argc, ox::SpanView<char const*> argv) noexcept;
char const**argv) noexcept;
} }
@ -65,7 +64,11 @@ int main(int argc, char const**argv) {
#if OLYMPIC_LOAD_STUDIO_MODULES #if OLYMPIC_LOAD_STUDIO_MODULES
OLYMPIC_PROJECT_NAMESPACE::registerStudioModules(); OLYMPIC_PROJECT_NAMESPACE::registerStudioModules();
#endif #endif
auto const err = olympic::run(OLYMPIC_PROJECT_NAME, OLYMPIC_APP_NAME, OLYMPIC_PROJECT_DATADIR, argc, argv); auto const err = olympic::run(
OLYMPIC_PROJECT_NAME,
OLYMPIC_APP_NAME,
OLYMPIC_PROJECT_DATADIR,
{argv, static_cast<size_t>(argc)});
oxAssert(err, "Something went wrong..."); oxAssert(err, "Something went wrong...");
if (err) { if (err) {
oxErrf("Failure: {}\n", toStr(err)); oxErrf("Failure: {}\n", toStr(err));

View File

@ -9,7 +9,9 @@ namespace keel {
static ox::Vector<Module const*> mods; static ox::Vector<Module const*> mods;
void registerModule(Module const*mod) noexcept { void registerModule(Module const*mod) noexcept {
mods.emplace_back(mod); if (mod) {
mods.emplace_back(mod);
}
} }
[[nodiscard]] [[nodiscard]]

View File

@ -81,8 +81,8 @@ static ox::Error pack(
return {}; return {};
} }
static ox::Error run(int argc, char const**argv, ox::StringView projectDataDir) noexcept { static ox::Error run(ox::SpanView<char const*> argv, ox::StringView projectDataDir) noexcept {
ox::ClArgs const args(argc, argv); ox::ClArgs const args(argv);
auto const argSrc = args.getString("src", ""); auto const argSrc = args.getString("src", "");
auto const argRomBin = args.getString("rom-bin", ""); auto const argRomBin = args.getString("rom-bin", "");
auto const argManifest = args.getString("manifest", ""); auto const argManifest = args.getString("manifest", "");
@ -103,9 +103,8 @@ ox::Error run(
[[maybe_unused]] ox::StringView project, [[maybe_unused]] ox::StringView project,
[[maybe_unused]] ox::StringView appName, [[maybe_unused]] ox::StringView appName,
ox::StringView projectDataDir, ox::StringView projectDataDir,
int argc, ox::SpanView<char const*> argv) noexcept {
char const**argv) noexcept { return ::run(argv, projectDataDir);
return ::run(argc, argv, projectDataDir);
} }
} }

View File

@ -28,7 +28,7 @@ static std::map<ox::StringView, ox::Error(*)()> tests = {
int main(int argc, const char **argv) { int main(int argc, const char **argv) {
int retval = -1; int retval = -1;
if (argc > 0) { if (argc > 0) {
auto const args = ox::SpanView{argv, static_cast<size_t>(argc)}; auto const args = ox::Span{argv, static_cast<size_t>(argc)};
auto testName = args[1]; auto testName = args[1];
if (tests.find(testName) != tests.end()) { if (tests.find(testName) != tests.end()) {
retval = static_cast<int>(tests[testName]()); retval = static_cast<int>(tests[testName]());

View File

@ -52,8 +52,7 @@ static ox::Error runApp(
static ox::Error run( static ox::Error run(
ox::StringViewCR appName, ox::StringViewCR appName,
ox::StringViewCR projectDataDir, ox::StringViewCR projectDataDir,
int, ox::SpanView<const char*>) {
char const**) {
// seed UUID generator // seed UUID generator
auto const time = std::time(nullptr); auto const time = std::time(nullptr);
ox::UUID::seedGenerator({ ox::UUID::seedGenerator({
@ -74,9 +73,8 @@ ox::Error run(
ox::StringView project, ox::StringView project,
ox::StringView appName, ox::StringView appName,
ox::StringView projectDataDir, ox::StringView projectDataDir,
int argc, ox::SpanView<char const*> args) noexcept {
char const**argv) noexcept { return studio::run(ox::sfmt("{} {}", project, appName), projectDataDir, args);
return studio::run(ox::sfmt("{} {}", project, appName), projectDataDir, argc, argv);
} }
} }

View File

@ -21,7 +21,9 @@ namespace studio {
static ox::Vector<studio::Module const*> modules; static ox::Vector<studio::Module const*> modules;
void registerModule(studio::Module const*mod) noexcept { void registerModule(studio::Module const*mod) noexcept {
modules.emplace_back(mod); if (mod) {
modules.emplace_back(mod);
}
} }
@ -238,18 +240,18 @@ void StudioUI::loadEditorMaker(studio::EditorMaker const&editorMaker) noexcept {
} }
} }
void StudioUI::loadModule(studio::Module const*mod) noexcept { void StudioUI::loadModule(studio::Module const&mod) noexcept {
for (auto const&editorMaker : mod->editors(m_sctx)) { for (auto const&editorMaker : mod.editors(m_sctx)) {
loadEditorMaker(editorMaker); loadEditorMaker(editorMaker);
} }
for (auto &im : mod->itemMakers(m_sctx)) { for (auto &im : mod.itemMakers(m_sctx)) {
m_newMenu.addItemMaker(std::move(im)); m_newMenu.addItemMaker(std::move(im));
} }
} }
void StudioUI::loadModules() noexcept { void StudioUI::loadModules() noexcept {
for (auto const mod : modules) { for (auto const mod : modules) {
loadModule(mod); loadModule(*mod);
} }
} }

View File

@ -69,7 +69,7 @@ class StudioUI: public ox::SignalHandler {
void loadEditorMaker(studio::EditorMaker const&editorMaker) noexcept; void loadEditorMaker(studio::EditorMaker const&editorMaker) noexcept;
void loadModule(studio::Module const*mod) noexcept; void loadModule(studio::Module const&mod) noexcept;
void loadModules() noexcept; void loadModules() noexcept;

View File

@ -189,7 +189,7 @@ bool BeginPopup(turbine::Context &ctx, ox::CStringView popupName, bool &show, Im
* @param selectedIdx * @param selectedIdx
* @return true if new value selected, false otherwise * @return true if new value selected, false otherwise
*/ */
bool ComboBox(ox::CStringView lbl, ox::SpanView<ox::String> list, size_t &selectedIdx) noexcept; bool ComboBox(ox::CStringView lbl, ox::Span<const ox::String> list, size_t &selectedIdx) noexcept;
/** /**
* *
@ -223,7 +223,7 @@ bool ListBox(
* @param selIdx * @param selIdx
* @return true if new value selected, false otherwise * @return true if new value selected, false otherwise
*/ */
bool ListBox(ox::CStringView name, ox::SpanView<ox::String> const&list, size_t &selIdx) noexcept; bool ListBox(ox::CStringView name, ox::Span<const ox::String> const&list, size_t &selIdx) noexcept;
class FilePicker { class FilePicker {
private: private:

View File

@ -87,7 +87,7 @@ bool BeginPopup(turbine::Context &ctx, ox::CStringView popupName, bool &show, Im
bool ComboBox( bool ComboBox(
ox::CStringView lbl, ox::CStringView lbl,
ox::SpanView<ox::String> list, ox::Span<const ox::String> list,
size_t &selectedIdx) noexcept { size_t &selectedIdx) noexcept {
bool out{}; bool out{};
auto const first = selectedIdx < list.size() ? list[selectedIdx].c_str() : ""; auto const first = selectedIdx < list.size() ? list[selectedIdx].c_str() : "";
@ -155,7 +155,7 @@ bool ListBox(
return out; return out;
} }
bool ListBox(ox::CStringView name, ox::SpanView<ox::String> const&list, size_t &selIdx) noexcept { bool ListBox(ox::CStringView name, ox::Span<const ox::String> const&list, size_t &selIdx) noexcept {
return ListBox(name, [list](size_t i) -> ox::CStringView { return ListBox(name, [list](size_t i) -> ox::CStringView {
return list[i]; return list[i];
}, list.size(), selIdx); }, list.size(), selIdx);