Mercurial > foo_out_sdl
diff 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 diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/foosdk/sdk/foobar2000/SDK/commonObjects.cpp Mon Jan 05 02:15:46 2026 -0500 @@ -0,0 +1,456 @@ +#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 ) ); + } +}
