Mercurial > foo_out_sdl
view foosdk/sdk/foobar2000/SDK/commonObjects.cpp @ 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 |
line wrap: on
line source
#include "foobar2000-sdk-pch.h" #include <pfc/sort.h> #include <pfc/bit_array_impl.h> #include <pfc/string_conv.h> #ifdef FOOBAR2000_MOBILE #include "browseTree.h" #endif #include <mutex> namespace { class arrayImpl : public fb2k::array { public: arrayImpl() {} arrayImpl(std::initializer_list<fb2k::objRef> const& arg) { m_content.set_size_discard(arg.size()); size_t walk = 0; for (auto& obj : arg) m_content[walk++] = obj; } arrayImpl( array::ptr in ) { const size_t count = in->count(); m_content.set_size_discard( count ); for(size_t w = 0; w < count; ++w) m_content[w] = in->itemAt(w); } arrayImpl( array::ptr in, size_t const * order, size_t count ) { if (count != in->count()) uBugCheck(); m_content.set_size_discard(count); for(size_t w = 0; w < count; ++w) m_content[w] = in->itemAt( order[w] ); } arrayImpl( fb2k::objRef in ) { m_content.set_size_discard( 1 ) ; m_content[0] = in; } arrayImpl( fb2k::objRef const * in, size_t inCount) { m_content.set_data_fromptr( in, inCount ); } size_t count() const { return m_content.get_size(); } service_ptr itemAt(size_t idx) const { return m_content[idx]; } private: pfc::array_staticsize_t< service_ptr > m_content; }; class arrayMutableImpl : public fb2k::arrayMutable { public: arrayMutableImpl() {} arrayMutableImpl( array::ptr in ) { const size_t count = in->count(); m_content.set_size_discard( count ); for(size_t w = 0; w < count; ++w) { m_content[w] = in->itemAt( w ); } } arrayMutableImpl( fb2k::objRef in ) { m_content.set_size_discard( 1 ); m_content[0] = in; } size_t count() const { return m_content.get_size(); } fb2k::objRef itemAt( size_t idx ) const { return m_content[idx]; } void remove( pfc::bit_array const & mask ) { pfc::remove_mask_t( m_content, mask ); } void insert( fb2k::objRef obj, size_t at ) { pfc::insert_t( m_content, obj, at ); } void insertFrom( array::ptr objects, size_t at ) { if (objects.get_ptr() == this) { objects = arrayWithArray( objects ); } pfc::insert_multi_t( m_content, *objects, objects->count(), at ); } void reorder( const size_t * order, size_t count ) { if (count != m_content.get_size()) uBugCheck(); pfc::reorder_t( m_content, order, count ); } void resize( size_t newSize ) { m_content.set_size( newSize ); } void setItem( fb2k::objRef obj, size_t atIndex ) { if (atIndex > m_content.get_size()) uBugCheck(); m_content[atIndex] = obj; } void prealloc(size_t capacity) { m_content.prealloc(capacity); } private: pfc::array_t< fb2k::objRef, pfc::alloc_fast > m_content; }; class stringImpl : public fb2k::string { public: stringImpl( const wchar_t * str, size_t len = pfc_infinite ) { size_t n = pfc::stringcvt::estimate_wide_to_utf8( str, len ); m_str = (char*) malloc( n ); pfc::stringcvt::convert_wide_to_utf8( m_str, n, str, len ); } stringImpl( const char * str ) { m_str = pfc::strDup(str); if (m_str == nullptr) throw std::bad_alloc(); } stringImpl( const char * str, size_t len ) { len = pfc::strlen_max( str, len ); m_str = (char*)malloc( len + 1 ); if (m_str == nullptr) throw std::bad_alloc(); memcpy (m_str, str, len ); m_str[len] = 0; } ~stringImpl() { free(m_str); } const char * c_str() const {return m_str;} private: char * m_str; }; class memBlockImpl : public fb2k::memBlock { public: memBlockImpl( const void * inData, size_t inDataSize ) { m_data.set_data_fromptr( (const uint8_t*) inData, inDataSize ); } const void * data() const { return m_data.get_ptr(); } size_t size() const { return m_data.get_size(); } private: pfc::array_staticsize_t< uint8_t > m_data; }; class memBlockImpl_takeOwnership : public fb2k::memBlock { public: memBlockImpl_takeOwnership(void * data, size_t size) : m_data(data), m_size(size) {} ~memBlockImpl_takeOwnership() { free(m_data); } const void * data() const { return m_data; } size_t size() const { return m_size; } private: void * const m_data; const size_t m_size; }; class memBlockMutableImpl : public fb2k::memBlockMutable { public: memBlockMutableImpl( size_t initSize ) { m_data.set_size_discard( initSize ); } memBlockMutableImpl( const void * inData, size_t inSize) { m_data.set_data_fromptr( (const uint8_t*) inData, inSize ); } memBlockMutableImpl() {} const void * data() const { return m_data.get_ptr(); } void * dataMutable() { return m_data.get_ptr(); } size_t size() const { return m_data.get_size(); } void resize( size_t size ) { m_data.set_size( size ); } void resizeDiscard( size_t size ) { m_data.set_size_discard( size ); } private: pfc::array_t< uint8_t > m_data; }; } namespace fb2k { FOOGUIDDECL const GUID array::class_guid = { 0x3f2c5273, 0x6cea, 0x427d, { 0x8c, 0x74, 0x34, 0x79, 0xc7, 0x22, 0x6a, 0x1 } }; FOOGUIDDECL const GUID arrayMutable::class_guid = { 0x142709d1, 0x9cef, 0x42c4, { 0xb5, 0x63, 0xbc, 0x3a, 0xee, 0x8, 0xdc, 0xe3 } }; FOOGUIDDECL const GUID string::class_guid = { 0xb3572de3, 0xdc77, 0x4494, { 0xa3, 0x90, 0xb1, 0xff, 0xd9, 0x17, 0x38, 0x77 } }; // ! Old GUID of album_art_data ! FOOGUIDDECL const GUID memBlock::class_guid = { 0x9ddce05c, 0xaa3f, 0x4565, { 0xb3, 0x3a, 0xbd, 0x6a, 0xdc, 0xdd, 0x90, 0x37 } }; FOOGUIDDECL const GUID memBlockMutable::class_guid = { 0x481ab64c, 0xa28, 0x435b, { 0x85, 0xdc, 0x9e, 0x20, 0xfe, 0x92, 0x15, 0x61 } }; FOOGUIDDECL const GUID objReceiver::class_guid = { 0x1b60d9fa, 0xcb9d, 0x45a4, { 0x90, 0x4e, 0xa, 0xa8, 0xaa, 0xe7, 0x99, 0x7c } }; array::ptr array::arrayReordered( size_t const * order, size_t count ) { return new service_impl_t< arrayImpl > ( this, order, count ); } array::ptr array::copy() const { return arrayWithArray( const_cast<array*>( this ) ); } array::ptr array::empty() { return new service_impl_t< arrayImpl >(); } array::ptr array::arrayWithArray( array::ptr source ) { return new service_impl_t< arrayImpl > ( source ); } array::ptr array::arrayWithObject( objRef source ) { return new service_impl_t< arrayImpl > ( source ); } array::ptr array::arrayWithObjects( objRef const * source, size_t count ) { return new service_impl_t<arrayImpl>( source, count ); } array::ptr array::arrayWithObjects(std::initializer_list< objRef > const& arg) { return new service_impl_t<arrayImpl>(arg); } arrayMutable::ptr arrayMutable::arrayWithCapacity(size_t capacity) { auto ret = fb2k::service_new< arrayMutableImpl >(); ret->prealloc(capacity); return ret; } arrayMutable::ptr arrayMutable::empty() { return new service_impl_t< arrayMutableImpl > (); } arrayMutable::ptr arrayMutable::arrayWithArray( array::ptr source ) { return new service_impl_t< arrayMutableImpl > ( source ); } arrayMutable::ptr arrayMutable::arrayWithObject( objRef source ) { return new service_impl_t< arrayMutableImpl > ( source ); } arrayMutable::ptr arrayMutable::copy() const { return arrayWithArray( const_cast<arrayMutable*>(this) ); } array::ptr array::makeConst() const { arrayMutableRef mut; if (mut &= const_cast<array*>(this)) return mut->copyConst(); return const_cast<array*>(this); } array::ptr arrayMutable::copyConst() const { return array::arrayWithArray( const_cast<arrayMutable*>(this) ); } string::ptr string::stringWithString( const char * str ) { return new service_impl_t< stringImpl > (str); } string::ptr string::stringWithString( const char * str, size_t len ) { return new service_impl_t< stringImpl > (str, len); } string::ptr string::stringWithString( string::ptr str ) { return new service_impl_t< stringImpl > (str->c_str() ); } bool string::equalsNullSafe( string::ptr v1, string::ptr v2 ) { if (v1.is_empty() && v2.is_empty()) return true; if (v1.is_empty() || v2.is_empty()) return false; return v1->equals( v2 ); } memBlock::ptr memBlock::empty() { return blockWithData(NULL, 0); } memBlock::ptr memBlock::blockWithDataTakeOwnership(void * inData, size_t inSize) { return new service_impl_t< memBlockImpl_takeOwnership >(inData, inSize); } memBlock::ptr memBlock::blockWithData( const void * inData, size_t inSize) { return new service_impl_t< memBlockImpl > ( inData, inSize ); } memBlock::ptr memBlock::blockWithData(pfc::mem_block const& b) { return blockWithData(b.ptr(), b.size()); } memBlock::ptr memBlock::blockWithData(pfc::mem_block&& b) { auto ret = blockWithDataTakeOwnership(b.ptr(), b.size()); b.detach(); return ret; } memBlock::ptr memBlock::copy() const { return blockWithBlock( const_cast<memBlock*>( this ) ); } memBlockMutable::ptr memBlockMutable::copy() const { return blockWithBlock( const_cast<memBlockMutable*>( this ) ); } memBlock::ptr memBlockMutable::copyConst() const { return memBlock::blockWithBlock( const_cast<memBlockMutable*>(this) ); } memBlockMutableRef memBlockMutable::empty() { return new service_impl_t< memBlockMutableImpl >; } memBlockMutableRef memBlockMutable::blockWithSize(size_t initSize) { return new service_impl_t< memBlockMutableImpl >( initSize ); } memBlockRef memBlock::blockWithBlock(memBlock::ptr block) { return blockWithData( block->data(), block->size() ); } memBlockMutableRef memBlockMutable::blockWithData( const void * inData, size_t inSize ) { return new service_impl_t< memBlockMutableImpl >( inData, inSize ); } memBlockMutableRef memBlockMutable::blockWithBlock(memBlock::ptr block) { return blockWithData( block->data(), block->size() ); } void describe( objRef obj, pfc::string_formatter & output, unsigned indent) { output.add_chars( ' ', indent * 2 ); { stringRef str; if (obj->cast(str)) { output << "string: " << str->c_str() << "\n"; return; } } { arrayRef arr; if (obj->cast(arr)) { arrayMutableRef mut; if (obj->cast(mut)) { output << "arrayMutable"; } else { output << "array"; } const size_t count = arr->count(); output << " (" << count << " items):\n"; for(size_t w = 0; w < count; ++w) { describe( arr->itemAt(w), output, indent + 1); } return; } } { memBlockRef block; if (obj->cast(block)) { memBlockMutableRef mut; if (obj->cast(mut)) { output << "memBlockMutable"; } else { output << "memBlock"; } output << " (" << block->size() << " bytes)\n"; return; } } #ifdef FOOBAR2000_MOBILE { browseTreeItem::ptr item; if (obj->cast(item)) { output << "browseTreeItem\n"; return; } } #endif output << "[unknown]\n"; } void describeDebug( objRef obj ) { console::formatter temp; describe( obj, temp, 0 ); } void arrayMutable::removeAt( size_t idx ) { remove(pfc::bit_array_one (idx) ) ; } stringRef makeString( const wchar_t * str ) { return new service_impl_t<stringImpl>(str); } stringRef makeString( const wchar_t * str, size_t len ) { return new service_impl_t<stringImpl>(str, len); } } namespace { using namespace fb2k; class objReceiverImpl : public objReceiver { public: objReceiverImpl( const objReceiverFunc_t & f ) : m_func(f) {} void receiveObj(objRef obj) { m_func(obj); } objReceiverFunc_t m_func; }; class callOnReleaseImpl : public service_base { public: callOnReleaseImpl( std::function<void () > f_) : f(f_) {} std::function<void ()> f; ~callOnReleaseImpl () { try { f(); } catch(...) {} } }; class arrayDeferred : public array { public: arrayDeferred( std::function<arrayRef () > f ) : m_func(f) {} size_t count() const { init(); return m_chain->count(); } objRef itemAt( size_t index ) const { init(); return m_chain->itemAt( index ); } private: mutable std::once_flag m_once; mutable std::function< arrayRef () > m_func; mutable arrayRef m_chain; void init() const { std::call_once( m_once, [this] { m_chain = m_func(); } ); } }; } namespace fb2k { objReceiverRef makeObjReceiver( objReceiverFunc_t f ) { return new service_impl_t< objReceiverImpl > ( f ); } objRef callOnRelease( std::function< void () > f) { return new service_impl_t< callOnReleaseImpl > (f); } objRef callOnReleaseInMainThread( std::function< void () > f) { return callOnRelease( [f] { fb2k::inMainThread2( f ); }); } arrayRef makeArrayDeferred( std::function< arrayRef () > f ) { return new service_impl_t<arrayDeferred> ( f ); } } namespace fb2k { objRef array::firstItem() const { size_t n = this->count(); if ( n == 0 ) return nullptr; return this->itemAt( 0 ); } objRef array::lastItem() const { size_t n = this->count(); if ( n == 0 ) return nullptr; return this->itemAt( n - 1 ); } size_t array::indexOfItem(objRef item) { const size_t m = this->count(); for( size_t n = 0; n < m; ++n ) { auto obj = this->itemAt( n ); if ( obj == item ) return n; } return SIZE_MAX; } array::ptr array::subset( pfc::bit_array const & mask ) const { auto out = arrayMutable::empty(); mask.walk( this->size(), [=] ( size_t w ) { out->add( this->itemAt( w ) ); } ); return out->makeConst(); } array::ptr array::subsetExcluding(const pfc::bit_array & mask) const { return subset(pfc::bit_array_not(mask) ); } array::ptr array::subsetExcludingSingle( size_t index ) const { return subsetExcluding(pfc::bit_array_one(index ) ); } }
