|
1
|
1 #include "foobar2000-sdk-pch.h"
|
|
|
2 #include "config_object_impl.h"
|
|
|
3 #include "configStore.h"
|
|
|
4
|
|
|
5 void config_object_notify_manager::g_on_changed(const service_ptr_t<config_object> & p_object)
|
|
|
6 {
|
|
|
7 if (core_api::assert_main_thread())
|
|
|
8 {
|
|
|
9 for (auto ptr : enumerate()) {
|
|
|
10 ptr->on_changed(p_object);
|
|
|
11 }
|
|
|
12 }
|
|
|
13 }
|
|
|
14
|
|
|
15 bool config_object::g_find(service_ptr_t<config_object> & p_out,const GUID & p_guid)
|
|
|
16 {
|
|
|
17 for (auto ptr : enumerate()) {
|
|
|
18 if (ptr->get_guid() == p_guid) {
|
|
|
19 p_out = ptr;
|
|
|
20 return true;
|
|
|
21 }
|
|
|
22 }
|
|
|
23 return false;
|
|
|
24 }
|
|
|
25
|
|
|
26 void config_object::g_get_data_string(const GUID & p_guid,pfc::string_base & p_out)
|
|
|
27 {
|
|
|
28 service_ptr_t<config_object> ptr;
|
|
|
29 if (!g_find(ptr,p_guid)) throw exception_service_not_found();
|
|
|
30 ptr->get_data_string(p_out);
|
|
|
31 }
|
|
|
32
|
|
|
33 void config_object::g_set_data_string(const GUID & p_guid,const char * p_data,t_size p_length)
|
|
|
34 {
|
|
|
35 service_ptr_t<config_object> ptr;
|
|
|
36 if (!g_find(ptr,p_guid)) throw exception_service_not_found();
|
|
|
37 ptr->set_data_string(p_data,p_length);
|
|
|
38 }
|
|
|
39
|
|
|
40 void config_object::get_data_int32(t_int32 & p_out)
|
|
|
41 {
|
|
|
42 t_int32 temp;
|
|
|
43 get_data_struct_t<t_int32>(temp);
|
|
|
44 byte_order::order_le_to_native_t(temp);
|
|
|
45 p_out = temp;
|
|
|
46 }
|
|
|
47
|
|
|
48 void config_object::set_data_int32(t_int32 p_val)
|
|
|
49 {
|
|
|
50 t_int32 temp = p_val;
|
|
|
51 byte_order::order_native_to_le_t(temp);
|
|
|
52 set_data_struct_t<t_int32>(temp);
|
|
|
53 }
|
|
|
54
|
|
|
55 bool config_object::get_data_bool_simple(bool p_default) {
|
|
|
56 try {
|
|
|
57 bool ret = p_default;
|
|
|
58 get_data_bool(ret);
|
|
|
59 return ret;
|
|
|
60 } catch(...) {return p_default;}
|
|
|
61 }
|
|
|
62
|
|
|
63 t_int32 config_object::get_data_int32_simple(t_int32 p_default) {
|
|
|
64 try {
|
|
|
65 t_int32 ret = p_default;
|
|
|
66 get_data_int32(ret);
|
|
|
67 return ret;
|
|
|
68 } catch(...) {return p_default;}
|
|
|
69 }
|
|
|
70
|
|
|
71 void config_object::g_get_data_int32(const GUID & p_guid,t_int32 & p_out) {
|
|
|
72 service_ptr_t<config_object> ptr;
|
|
|
73 if (!g_find(ptr,p_guid)) throw exception_service_not_found();
|
|
|
74 ptr->get_data_int32(p_out);
|
|
|
75 }
|
|
|
76
|
|
|
77 void config_object::g_set_data_int32(const GUID & p_guid,t_int32 p_val) {
|
|
|
78 service_ptr_t<config_object> ptr;
|
|
|
79 if (!g_find(ptr,p_guid)) throw exception_service_not_found();
|
|
|
80 ptr->set_data_int32(p_val);
|
|
|
81 }
|
|
|
82
|
|
|
83 bool config_object::g_get_data_bool_simple(const GUID & p_guid,bool p_default)
|
|
|
84 {
|
|
|
85 service_ptr_t<config_object> ptr;
|
|
|
86 if (!g_find(ptr,p_guid)) throw exception_service_not_found();
|
|
|
87 return ptr->get_data_bool_simple(p_default);
|
|
|
88 }
|
|
|
89
|
|
|
90 t_int32 config_object::g_get_data_int32_simple(const GUID & p_guid,t_int32 p_default)
|
|
|
91 {
|
|
|
92 service_ptr_t<config_object> ptr;
|
|
|
93 if (!g_find(ptr,p_guid)) throw exception_service_not_found();
|
|
|
94 return ptr->get_data_int32_simple(p_default);
|
|
|
95 }
|
|
|
96
|
|
|
97 void config_object::get_data_bool(bool & p_out) {get_data_struct_t<bool>(p_out);}
|
|
|
98 void config_object::set_data_bool(bool p_val) {set_data_struct_t<bool>(p_val);}
|
|
|
99
|
|
|
100 void config_object::g_get_data_bool(const GUID & p_guid,bool & p_out) {g_get_data_struct_t<bool>(p_guid,p_out);}
|
|
|
101 void config_object::g_set_data_bool(const GUID & p_guid,bool p_val) {g_set_data_struct_t<bool>(p_guid,p_val);}
|
|
|
102
|
|
|
103 namespace {
|
|
|
104 class stream_writer_string : public stream_writer {
|
|
|
105 public:
|
|
|
106 void write(const void * p_buffer,t_size p_bytes,abort_callback & p_abort) {
|
|
|
107 p_abort.check();
|
|
|
108 m_out.add_string((const char*)p_buffer,p_bytes);
|
|
|
109 }
|
|
|
110 stream_writer_string(pfc::string_base & p_out) : m_out(p_out) {m_out.reset();}
|
|
|
111 private:
|
|
|
112 pfc::string_base & m_out;
|
|
|
113 };
|
|
|
114
|
|
|
115 class stream_writer_fixedbuffer : public stream_writer {
|
|
|
116 public:
|
|
|
117 void write(const void * p_buffer,t_size p_bytes,abort_callback & p_abort) {
|
|
|
118 p_abort.check();
|
|
|
119 if (p_bytes > 0) {
|
|
|
120 if (p_bytes > m_bytes - m_bytes_read) throw pfc::exception_overflow();
|
|
|
121 memcpy((t_uint8*)m_out,p_buffer,p_bytes);
|
|
|
122 m_bytes_read += p_bytes;
|
|
|
123 }
|
|
|
124 }
|
|
|
125 stream_writer_fixedbuffer(void * p_out,t_size p_bytes,t_size & p_bytes_read) : m_out(p_out), m_bytes(p_bytes), m_bytes_read(p_bytes_read) {m_bytes_read = 0;}
|
|
|
126 private:
|
|
|
127 void * m_out;
|
|
|
128 t_size m_bytes;
|
|
|
129 t_size & m_bytes_read;
|
|
|
130 };
|
|
|
131
|
|
|
132
|
|
|
133
|
|
|
134 class stream_writer_get_length : public stream_writer {
|
|
|
135 public:
|
|
|
136 void write(const void * ,t_size p_bytes,abort_callback & p_abort) override {
|
|
|
137 p_abort.check();
|
|
|
138 m_length += p_bytes;
|
|
|
139 }
|
|
|
140 stream_writer_get_length(t_size & p_length) : m_length(p_length) {m_length = 0;}
|
|
|
141 private:
|
|
|
142 t_size & m_length;
|
|
|
143 };
|
|
|
144 };
|
|
|
145
|
|
|
146 t_size config_object::get_data_raw(void * p_out,t_size p_bytes) {
|
|
|
147 t_size ret = 0;
|
|
|
148 stream_writer_fixedbuffer stream(p_out,p_bytes,ret);
|
|
|
149 get_data(&stream,fb2k::noAbort);
|
|
|
150 return ret;
|
|
|
151 }
|
|
|
152
|
|
|
153 t_size config_object::get_data_raw_length() {
|
|
|
154 t_size ret = 0;
|
|
|
155 stream_writer_get_length stream(ret);
|
|
|
156 get_data(&stream,fb2k::noAbort);
|
|
|
157 return ret;
|
|
|
158 }
|
|
|
159
|
|
|
160 void config_object::set_data_raw(const void * p_data,t_size p_bytes, bool p_notify) {
|
|
|
161 stream_reader_memblock_ref stream(p_data,p_bytes);
|
|
|
162 set_data(&stream,fb2k::noAbort,p_notify);
|
|
|
163 }
|
|
|
164
|
|
|
165 void config_object::set_data_string(const char * p_data,t_size p_length) {
|
|
|
166 set_data_raw(p_data,pfc::strlen_max(p_data,p_length));
|
|
|
167 }
|
|
|
168
|
|
|
169 void config_object::get_data_string(pfc::string_base & p_out) {
|
|
|
170 stream_writer_string stream(p_out);
|
|
|
171 get_data(&stream,fb2k::noAbort);
|
|
|
172 }
|
|
|
173
|
|
|
174
|
|
|
175 //config_object_impl stuff
|
|
|
176
|
|
|
177 #if FOOBAR2020
|
|
|
178 pfc::string8 config_object_impl::formatName() const {
|
|
|
179 return pfc::format("config_object.", pfc::print_guid(get_guid()));
|
|
|
180 }
|
|
|
181
|
|
|
182 void config_object_impl::get_data(stream_writer * p_stream,abort_callback & p_abort) const {
|
|
|
183 auto blob = fb2k::configStore::get()->getConfigBlob(formatName(), m_initial);
|
|
|
184 if (blob.is_valid()) p_stream->write(blob->data(), blob->size(), p_abort);
|
|
|
185 }
|
|
|
186
|
|
|
187 void config_object_impl::set_data(stream_reader * p_stream,abort_callback & p_abort,bool p_notify) {
|
|
|
188 core_api::ensure_main_thread();
|
|
|
189
|
|
|
190 {
|
|
|
191 pfc::mem_block data;
|
|
|
192 enum {delta = 1024};
|
|
|
193 t_uint8 buffer[delta];
|
|
|
194 for(;;)
|
|
|
195 {
|
|
|
196 t_size delta_done = p_stream->read(buffer,delta,p_abort);
|
|
|
197
|
|
|
198 if (delta_done > 0)
|
|
|
199 {
|
|
|
200 data.append_fromptr(buffer,delta_done);
|
|
|
201 }
|
|
|
202
|
|
|
203 if (delta_done != delta) break;
|
|
|
204 }
|
|
|
205
|
|
|
206 auto blob = fb2k::memBlock::blockWithData(std::move(data));
|
|
|
207 fb2k::configStore::get()->setConfigBlob(formatName(), blob);
|
|
|
208 }
|
|
|
209
|
|
|
210 if (p_notify) config_object_notify_manager::g_on_changed(this);
|
|
|
211 }
|
|
|
212
|
|
|
213 config_object_impl::config_object_impl(const GUID & p_guid,const void * p_data,t_size p_bytes) : cfg_var_reader(p_guid)
|
|
|
214 {
|
|
|
215 if (p_bytes > 0) m_initial = fb2k::makeMemBlock(p_data, p_bytes);
|
|
|
216 }
|
|
|
217 #else // FOOBAR2020
|
|
|
218 void config_object_impl::get_data(stream_writer* p_stream, abort_callback& p_abort) const {
|
|
|
219 inReadSync(m_sync);
|
|
|
220 p_stream->write_object(m_data.get_ptr(), m_data.get_size(), p_abort);
|
|
|
221 }
|
|
|
222
|
|
|
223 void config_object_impl::set_data(stream_reader* p_stream, abort_callback& p_abort, bool p_notify) {
|
|
|
224 core_api::ensure_main_thread();
|
|
|
225
|
|
|
226 {
|
|
|
227 inWriteSync(m_sync);
|
|
|
228 m_data.set_size(0);
|
|
|
229 enum { delta = 1024 };
|
|
|
230 t_uint8 buffer[delta];
|
|
|
231 for (;;)
|
|
|
232 {
|
|
|
233 t_size delta_done = p_stream->read(buffer, delta, p_abort);
|
|
|
234
|
|
|
235 if (delta_done > 0)
|
|
|
236 {
|
|
|
237 m_data.append_fromptr(buffer, delta_done);
|
|
|
238 }
|
|
|
239
|
|
|
240 if (delta_done != delta) break;
|
|
|
241 }
|
|
|
242 }
|
|
|
243
|
|
|
244 if (p_notify) config_object_notify_manager::g_on_changed(this);
|
|
|
245 }
|
|
|
246
|
|
|
247 config_object_impl::config_object_impl(const GUID& p_guid, const void* p_data, t_size p_bytes) : cfg_var(p_guid)
|
|
|
248 {
|
|
|
249 m_data.set_data_fromptr((const t_uint8*)p_data, p_bytes);
|
|
|
250 }
|
|
|
251 #endif
|