comparison foosdk/sdk/foobar2000/helpers/cfg_objList.h @ 1:20d02a178406 default tip

*: check in everything else yay
author Paper <paper@tflc.us>
date Mon, 05 Jan 2026 02:15:46 -0500
parents
children
comparison
equal deleted inserted replaced
0:e9bb126753e7 1:20d02a178406
1 #pragma once
2
3 #include <SDK/cfg_var.h>
4
5 #if FOOBAR2020
6 #include <SDK/configStore.h>
7 namespace cfg_var_modern {
8 template<typename obj_t>
9 class cfg_objList : private cfg_var_common {
10 public:
11 cfg_objList(const GUID& guid) : cfg_var_common(guid) { }
12 template<typename source_t, unsigned source_count> cfg_objList(const GUID& guid, const source_t(&source)[source_count]) : cfg_var_common(guid) {
13 m_defaults.resize(source_count);
14 for( unsigned walk = 0; walk < source_count; ++ walk) m_defaults[walk] = source[walk];
15 }
16
17 void clear() { set(std::vector<obj_t>()); }
18 void remove_all() { clear(); }
19 size_t remove_mask(pfc::bit_array const& arg) {
20 init();
21 PFC_INSYNC_WRITE(m_listGuard);
22 size_t gone = pfc::remove_mask_t(m_list, arg);
23 if (gone > 0) save();
24 return gone;
25 }
26 //! Returns number of items removed.
27 template<typename pred_t> size_t remove_if(pred_t&& p) {
28 init();
29 PFC_INSYNC_WRITE(m_listGuard);
30 const auto nBefore = m_list.size();
31 const size_t nAfter = pfc::remove_if_t(m_list, std::forward<pred_t>(p));
32 const auto gone = nAfter - nBefore;
33 if (gone > 0) save();
34 return gone;
35 }
36 bool remove_item(obj_t const& v) {
37 return remove_if([&v](const obj_t& arg) { return v == arg; }) != 0;
38 }
39 size_t size() { init(); PFC_INSYNC_READ(m_listGuard);return m_list.size(); }
40 size_t get_count() { return size(); }
41 size_t get_size() { return size(); }
42
43 obj_t get(size_t idx) { init(); PFC_INSYNC_READ(m_listGuard); return m_list[idx]; }
44
45 obj_t operator[] (size_t idx) { return get(idx); }
46
47 template<typename arg_t>
48 void set(size_t idx, arg_t&& v) {
49 init();
50 PFC_INSYNC_WRITE(m_listGuard); m_list[idx] = std::forward<arg_t>(v); save();
51 }
52 bool have_item(obj_t const& arg) {
53 return find_item(arg) != SIZE_MAX;
54 }
55 size_t find_item(obj_t const& arg) {
56 init();
57 PFC_INSYNC_READ(m_listGuard);
58 for (size_t idx = 0; idx < m_list.size(); ++idx) {
59 if (m_list[idx] == arg) return idx;
60 }
61 return SIZE_MAX;
62 }
63 template<typename arg_t>
64 void insert_item(size_t idx, arg_t&& arg) {
65 init();
66 PFC_INSYNC_WRITE(m_listGuard);
67 m_list.insert(m_list.begin() + idx, std::forward<arg_t>(arg));
68 save();
69 }
70 template<typename arg_t>
71 void set_items(arg_t&& arg) {
72 init();
73 PFC_INSYNC_WRITE(m_listGuard);
74 m_list.clear();
75 for (auto& item : arg) m_list.push_back(item);
76 save();
77 }
78 template<typename arg_t>
79 void insert_items(arg_t&& arg, size_t at) {
80 init();
81 PFC_INSYNC_WRITE(m_listGuard);
82 m_list.insert(m_list.begin() + at, arg.begin(), arg.end());
83 save();
84 }
85 template<typename arg_t>
86 void add_items(arg_t&& arg) {
87 init();
88 PFC_INSYNC_WRITE(m_listGuard);
89
90 m_list.insert(m_list.end(), arg.begin(), arg.end());
91 save();
92 }
93 template<typename arg_t>
94 void add_item(arg_t&& arg) {
95 init();
96 PFC_INSYNC_WRITE(m_listGuard);
97 m_list.push_back(std::forward<arg_t>(arg));
98 save();
99 }
100 template<typename arg_t>
101 void set(arg_t&& arg) {
102 init();
103 set_(std::forward<arg_t>(arg));
104 }
105 std::vector<obj_t> get() {
106 init();
107 PFC_INSYNC_READ(m_listGuard);
108 return m_list;
109 }
110
111
112 private:
113 void init() {
114 std::call_once(m_init, [this] {
115 auto blob = fb2k::configStore::get()->getConfigBlob(formatName(), nullptr);
116 if (blob.is_valid()) try {
117 stream_reader_formatter_simple<> reader(blob->data(), blob->size());
118 std::vector<obj_t> data;
119 uint32_t count; reader >> count; data.resize(count);
120 for (auto& v : data) reader >> v;
121 set_(std::move(data), false);
122 return;
123 } catch(...) {} // fall through, set defaults
124 set_(m_defaults, false);
125 });
126 }
127 template<typename arg_t>
128 void set_(arg_t&& arg, bool bSave = true) {
129 PFC_INSYNC_WRITE(m_listGuard);
130 m_list = std::forward<arg_t>(arg);
131 if (bSave) save();
132 }
133 void save() {
134 // assumes write sync
135 stream_writer_formatter_simple<> out;
136 out << (uint32_t)m_list.size();
137 for (auto& v : m_list) out << v;
138 fb2k::configStore::get()->setConfigBlob(formatName(), out.m_buffer.get_ptr(), out.m_buffer.get_size());
139 }
140 #ifdef FOOBAR2000_HAVE_CFG_VAR_LEGACY
141 void set_data_raw(stream_reader* p_stream, t_size p_sizehint, abort_callback& p_abort) override {
142 stream_reader_formatter<> reader(*p_stream, p_abort);
143 std::vector<obj_t> data;
144 uint32_t count; reader >> count; data.resize(count);
145 for (auto& v : data) reader >> v;
146 set(std::move(data));
147 }
148 #endif
149
150 std::vector<obj_t> m_list;
151 pfc::readWriteLock m_listGuard;
152
153 std::once_flag m_init;
154
155 std::vector<obj_t> m_defaults;
156 };
157
158 }
159 #endif // FOOBAR2020
160