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 ) );
+    }
+}