comparison foosdk/sdk/foobar2000/SDK/commonObjects.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 <functional>
4 #include <initializer_list>
5 #include <pfc/list.h>
6 #include "completion_notify.h"
7
8 namespace fb2k {
9 typedef service_ptr objRef;
10
11 template<typename interface_t> class array_typed;
12 template<typename interface_t> class array_soft_typed;
13
14 class NOVTABLE array : public service_base, public pfc::list_base_const_t<service_ptr> {
15 FB2K_MAKE_SERVICE_INTERFACE( array, service_base );
16 public:
17 virtual size_t count() const = 0;
18 size_t size() const {return count();}
19 virtual objRef itemAt( size_t index ) const = 0;
20
21 objRef firstItem( ) const;
22 objRef lastItem( ) const;
23
24 objRef operator[] (size_t idx) const {return itemAt(idx);}
25
26 array::ptr arrayReordered( size_t const * order, size_t count );
27
28 array::ptr copy() const;
29 //! If this is a mutable array, creates a const copy of it. \n
30 //! Otherwise returns this object.
31 array::ptr makeConst() const;
32
33 static array::ptr empty();
34 static array::ptr arrayWithArray( array::ptr source );
35 static array::ptr arrayWithObject( objRef source );
36 static array::ptr arrayWithObjects( objRef const * source, size_t count );
37 static array::ptr arrayWithObjects(std::initializer_list< objRef > const&);
38
39 size_t indexOfItem( objRef item );
40
41 array::ptr subset( pfc::bit_array const & mask ) const;
42 array::ptr subsetExcluding( pfc::bit_array const & mask ) const;
43 array::ptr subsetExcludingSingle( size_t index ) const;
44
45 // UNSAFE CAST HELPER
46 // Use only when documented as allowed
47 template<typename interface_t>
48 const pfc::list_base_const_t< service_ptr_t< interface_t > >& as_list_of() const {
49 const pfc::list_base_const_t<service_ptr> * temp = this;
50 return *reinterpret_cast<const pfc::list_base_const_t< service_ptr_t< interface_t > > * > (temp);
51 }
52
53 // TYPED ARRAY HELPER
54 // Usage: for( auto obj : myArray->typed<interface>() ) { ... }
55 // Expects ALL objects in the array to implement the interface - causes runtime bugcheck if they don't
56 template<typename interface_t>
57 const array_typed<interface_t>& typed() const { return *reinterpret_cast< const array_typed<interface_t> * > (this); }
58
59 // SOFT TYPED ARRAY HELPER
60 // Usage: for( auto obj : myArray->softTyped<interface>() ) { ... }
61 // Skips objects not implementing the interface.
62 template<typename interface_t>
63 const array_soft_typed<interface_t>& softTyped() const { return *reinterpret_cast<const array_soft_typed<interface_t> *> (this); }
64
65
66 // pfc::list_base_const_t<>
67 t_size get_count() const override {return this->count();}
68 void get_item_ex(service_ptr& p_out, t_size n) const override { p_out = this->itemAt(n); }
69 };
70
71 template<typename interface_t> class array_typed : public array {
72 public:
73 typedef service_ptr_t<interface_t> ptr_t;
74 class iterator {
75 public:
76 static iterator _make(const array* arr, size_t index) { iterator ret; ret.m_arr = arr; ret.m_index = index; return ret; }
77 void operator++() { ++m_index; }
78 bool operator==(const iterator& other) const { PFC_ASSERT(m_arr == other.m_arr); return m_index == other.m_index; }
79 bool operator!=(const iterator& other) const { PFC_ASSERT(m_arr == other.m_arr); return m_index != other.m_index; }
80
81 ptr_t operator*() const {
82 ptr_t ret;
83 ret ^= m_arr->itemAt(m_index);
84 return ret;
85 }
86 private:
87 const array* m_arr;
88 size_t m_index;
89 };
90 typedef iterator const_iterator;
91 iterator begin() const { return iterator::_make(this, 0); }
92 iterator end() const { return iterator::_make(this, this->count()); }
93 };
94
95 template<typename interface_t> class array_soft_typed : public array {
96 public:
97 typedef service_ptr_t<interface_t> ptr_t;
98 class iterator {
99 public:
100 static iterator _make(const array* arr, size_t index) {
101 iterator ret;
102 ret.m_arr = arr; ret.m_index = index;
103 ret.m_max = arr->count();
104 ret.fetch();
105 return ret;
106 }
107 void operator++() { ++m_index; fetch(); }
108 bool operator==(const iterator& other) const { PFC_ASSERT(m_arr == other.m_arr); return m_index == other.m_index; }
109 bool operator!=(const iterator& other) const { PFC_ASSERT(m_arr == other.m_arr); return m_index != other.m_index; }
110
111 ptr_t operator*() const {
112 PFC_ASSERT(m_ptr.is_valid());
113 return m_ptr;
114 }
115 private:
116 void fetch() {
117 m_ptr.reset();
118 while (m_index < m_max) {
119 if (m_ptr &= m_arr->itemAt(m_index)) break;
120 ++m_index;
121 }
122 }
123 const array* m_arr;
124 size_t m_index, m_max;
125 ptr_t m_ptr;
126 };
127 typedef iterator const_iterator;
128 iterator begin() const { return iterator::_make(this, 0); }
129 iterator end() const { return iterator::_make(this, this->count()); }
130 };
131
132 class NOVTABLE arrayMutable : public array {
133 FB2K_MAKE_SERVICE_INTERFACE( arrayMutable, array );
134 public:
135 virtual void remove( pfc::bit_array const & mask ) = 0;
136 virtual void insert( objRef obj, size_t at ) = 0;
137 virtual void insertFrom( array::ptr objects, size_t at ) = 0;
138 virtual void reorder( const size_t * order, size_t count ) = 0;
139
140 virtual void resize( size_t newSize ) = 0;
141 virtual void setItem( objRef obj, size_t atIndex ) = 0;
142
143 arrayMutable::ptr copy() const;
144 array::ptr copyConst() const;
145
146 void removeAt( size_t idx );
147 void add( objRef obj ) {insert( obj, (size_t)(-1) ) ; }
148 void addFrom( array::ptr obj ) {insertFrom( obj, (size_t)(-1) ) ; }
149 static arrayMutable::ptr empty();
150 static arrayMutable::ptr arrayWithArray( array::ptr source );
151 static arrayMutable::ptr arrayWithObject( objRef source );
152 static arrayMutable::ptr arrayWithCapacity(size_t capacity);
153 };
154
155 class NOVTABLE string : public service_base {
156 FB2K_MAKE_SERVICE_INTERFACE( string, service_base );
157 public:
158 virtual const char * c_str() const = 0;
159
160 size_t length() const { return strlen(c_str()); }
161 bool isEmpty() const { return *c_str() == 0; }
162 bool equals( const char * other ) const { return strcmp(c_str(), other) == 0; }
163 bool equals( string::ptr other ) const { return equals(other->c_str()); }
164
165 static string::ptr stringWithString( const char * str );
166 static string::ptr stringWithString( string::ptr str );
167 static string::ptr stringWithString( const char * str, size_t len );
168 static bool equalsNullSafe( string::ptr v1, string::ptr v2 );
169 };
170
171 class NOVTABLE memBlock : public service_base {
172 FB2K_MAKE_SERVICE_INTERFACE( memBlock, service_base );
173 public:
174 virtual const void * data() const = 0;
175 virtual size_t size() const = 0;
176
177 const uint8_t * begin() const { return (const uint8_t*) data(); }
178 const uint8_t * end() const { return begin() + size(); }
179
180 //! Album_art_data compatibility
181 size_t get_size() { return size(); }
182 //! Album_art_data compatibility
183 const void * get_ptr() { return data(); }
184
185 memBlock::ptr copy() const;
186
187 static memBlock::ptr empty();
188 static memBlock::ptr blockWithData( const void * inData, size_t inSize);
189 static memBlock::ptr blockWithBlock( memBlock::ptr block );
190 template<typename vec_t>
191 static memBlock::ptr blockWithVector(const vec_t & vec) {
192 auto size = vec.size();
193 if (size == 0) return empty();
194 return blockWithData(&vec[0], size * sizeof(vec[0]));
195 }
196
197 //! Create an object that takes ownership of this memory, without copying it; will call free() when done.
198 static memBlock::ptr blockWithDataTakeOwnership(void * inData, size_t inSize);
199 static memBlock::ptr blockWithData(pfc::mem_block const &);
200 static memBlock::ptr blockWithData(pfc::mem_block && );
201
202 //! Determine whether two memBlock objects store the same content.
203 static bool equals(memBlock const & v1, memBlock const & v2) {
204 const t_size s = v1.size();
205 if (s != v2.size()) return false;
206 return memcmp(v1.data(), v2.data(),s) == 0;
207 }
208 static bool equals(ptr const& v1, ptr const& v2) {
209 if (v1.is_valid() != v2.is_valid()) return false;
210 if (v1.is_empty() && v2.is_empty()) return true;
211 return equals(*v1, *v2);
212 }
213
214 bool operator==(const memBlock & other) const {return equals(*this,other);}
215 bool operator!=(const memBlock & other) const {return !equals(*this,other);}
216
217 };
218
219 class NOVTABLE memBlockMutable : public memBlock {
220 FB2K_MAKE_SERVICE_INTERFACE( memBlockMutable, memBlock );
221 public:
222 virtual void * dataMutable() = 0;
223
224 //! Resizes preserving content. When expanding, contents of newly allocated area are undefined.
225 virtual void resize( size_t size ) = 0;
226 //! Resizes without preserving content. Contents undefined afterwards.
227 virtual void resizeDiscard( size_t size ) { resize( size ); }
228
229 memBlockMutable::ptr copy() const;
230 memBlock::ptr copyConst() const;
231 static memBlockMutable::ptr empty();
232 static memBlockMutable::ptr blockWithSize( size_t initSize );
233 static memBlockMutable::ptr blockWithData( const void * inData, size_t inSize );
234 static memBlockMutable::ptr blockWithBlock( memBlock::ptr block );
235
236 bool operator==(const memBlockMutable & other) const {return equals(*this,other);}
237 bool operator!=(const memBlockMutable & other) const {return !equals(*this,other);}
238 };
239
240
241 //! Asynchronous object return helper. \n
242 //! If the operation has failed for some reason, receiveObj() will be called with null object.
243 class objReceiver : public service_base {
244 FB2K_MAKE_SERVICE_INTERFACE( objReceiver, service_base );
245 public:
246 virtual void receiveObj( objRef obj ) = 0;
247 };
248
249 typedef objReceiver::ptr objReceiverRef;
250
251
252 typedef ::completion_notify completionNotify;
253 typedef completionNotify::ptr completionNotifyRef;
254 typedef array::ptr arrayRef;
255 typedef arrayMutable::ptr arrayMutableRef;
256 typedef string::ptr stringRef;
257 typedef memBlock::ptr memBlockRef;
258 typedef memBlockMutable::ptr memBlockMutableRef;
259
260 stringRef makeString( const wchar_t * str );
261 stringRef makeString( const wchar_t * str, size_t len );
262
263 inline stringRef makeString( const char * str ) {
264 return string::stringWithString ( str );
265 }
266 inline stringRef makeString( const char * str, size_t len) {
267 return string::stringWithString ( str, len );
268 }
269 inline arrayRef makeArray( std::initializer_list<objRef> const & arg ) {
270 return array::arrayWithObjects( arg );
271 }
272 inline memBlockRef makeMemBlock( const void * data, size_t size ) {
273 return memBlock::blockWithData( data, size );
274 }
275
276 void describe( objRef obj, pfc::string_formatter & output, unsigned indent);
277 void describeDebug( objRef obj );
278
279
280 typedef std::function< void (objRef) > objReceiverFunc_t;
281
282 objReceiverRef makeObjReceiver( objReceiverFunc_t );
283
284 template<typename class_t> objReceiverRef makeObjReceiverTyped(std::function< void(service_ptr_t<class_t>) > func) {
285 return makeObjReceiver([=](objRef obj) {
286 if (obj.is_empty()) func(nullptr);
287 else {
288 service_ptr_t<class_t> temp; temp ^= obj; func(temp);
289 }
290 });
291 }
292
293 objRef callOnRelease( std::function< void () > );
294 objRef callOnReleaseInMainThread( std::function< void () > );
295
296 arrayRef makeArrayDeferred( std::function< arrayRef () > f );
297 }
298 inline pfc::string_base & operator<<(pfc::string_base & p_fmt, fb2k::stringRef str) { p_fmt.add_string(str->c_str()); return p_fmt; }