Mercurial > foo_out_sdl
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; } |
