|
1
|
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
|