Files
foobar2000-sdk/pfc/other.h
2021-12-14 00:28:25 -07:00

290 lines
7.6 KiB
C++

#pragma once
namespace pfc {
template<class T>
class vartoggle_t {
T oldval; T & var;
public:
vartoggle_t(T & p_var,const T & val) : var(p_var) {
oldval = var;
var = val;
}
~vartoggle_t() {var = oldval;}
};
template<class T>
class vartoggle_volatile_t {
T oldval; volatile T & var;
public:
vartoggle_volatile_t(volatile T & p_var,const T & val) : var(p_var) {
oldval = var;
var = val;
}
~vartoggle_volatile_t() {var = oldval;}
};
typedef vartoggle_t<bool> booltoggle;
};
#ifdef _MSC_VER
class fpu_control
{
unsigned old_val;
unsigned mask;
public:
inline fpu_control(unsigned p_mask,unsigned p_val)
{
mask = p_mask;
_controlfp_s(&old_val,p_val,mask);
}
inline ~fpu_control()
{
unsigned dummy;
_controlfp_s(&dummy,old_val,mask);
}
};
class fpu_control_roundnearest : private fpu_control
{
public:
fpu_control_roundnearest() : fpu_control(_MCW_RC,_RC_NEAR) {}
};
class fpu_control_flushdenormal : private fpu_control
{
public:
fpu_control_flushdenormal() : fpu_control(_MCW_DN,_DN_FLUSH) {}
};
class fpu_control_default : private fpu_control
{
public:
fpu_control_default() : fpu_control(_MCW_DN|_MCW_RC,_DN_FLUSH|_RC_NEAR) {}
};
#ifdef _M_IX86
class sse_control {
public:
sse_control(unsigned p_mask,unsigned p_val) : m_mask(p_mask) {
__control87_2(p_val,p_mask,NULL,&m_oldval);
}
~sse_control() {
__control87_2(m_oldval,m_mask,NULL,&m_oldval);
}
private:
unsigned m_mask,m_oldval;
};
class sse_control_flushdenormal : private sse_control {
public:
sse_control_flushdenormal() : sse_control(_MCW_DN,_DN_FLUSH) {}
};
#endif
#endif
namespace pfc {
class releaser_delete {
public:
template<typename T> static void release(T* p_ptr) {delete p_ptr;}
};
class releaser_delete_array {
public:
template<typename T> static void release(T* p_ptr) {delete[] p_ptr;}
};
class releaser_free {
public:
static void release(void * p_ptr) {free(p_ptr);}
};
//! Assumes t_freefunc to never throw exceptions.
template<typename T,typename t_releaser = releaser_delete >
class ptrholder_t {
private:
typedef ptrholder_t<T,t_releaser> t_self;
public:
inline ptrholder_t(T* p_ptr) : m_ptr(p_ptr) {}
inline ptrholder_t() : m_ptr(NULL) {}
inline ~ptrholder_t() {t_releaser::release(m_ptr);}
inline bool is_valid() const {return m_ptr != NULL;}
inline bool is_empty() const {return m_ptr == NULL;}
inline T* operator->() const {return m_ptr;}
inline T* get_ptr() const {return m_ptr;}
inline void release() {t_releaser::release(replace_null_t(m_ptr));;}
inline void attach(T * p_ptr) {release(); m_ptr = p_ptr;}
inline const t_self & operator=(T * p_ptr) {set(p_ptr);return *this;}
inline T* detach() {return pfc::replace_null_t(m_ptr);}
inline T& operator*() const {return *m_ptr;}
inline t_self & operator<<(t_self & p_source) {attach(p_source.detach());return *this;}
inline t_self & operator>>(t_self & p_dest) {p_dest.attach(detach());return *this;}
//deprecated
inline void set(T * p_ptr) {attach(p_ptr);}
ptrholder_t(t_self&& other) { m_ptr = other.detach(); }
const t_self& operator=(t_self&& other) { attach(other.detach()); return this; }
private:
ptrholder_t(const t_self &) {throw pfc::exception_not_implemented();}
const t_self & operator=(const t_self & ) {throw pfc::exception_not_implemented();}
T* m_ptr;
};
//avoid "void&" breakage
template<typename t_releaser>
class ptrholder_t<void,t_releaser> {
private:
typedef void T;
typedef ptrholder_t<T,t_releaser> t_self;
public:
inline ptrholder_t(T* p_ptr) : m_ptr(p_ptr) {}
inline ptrholder_t() : m_ptr(NULL) {}
inline ~ptrholder_t() {t_releaser::release(m_ptr);}
inline bool is_valid() const {return m_ptr != NULL;}
inline bool is_empty() const {return m_ptr == NULL;}
inline T* operator->() const {return m_ptr;}
inline T* get_ptr() const {return m_ptr;}
inline void release() {t_releaser::release(replace_null_t(m_ptr));;}
inline void attach(T * p_ptr) {release(); m_ptr = p_ptr;}
inline const t_self & operator=(T * p_ptr) {set(p_ptr);return *this;}
inline T* detach() {return pfc::replace_null_t(m_ptr);}
inline t_self & operator<<(t_self & p_source) {attach(p_source.detach());return *this;}
inline t_self & operator>>(t_self & p_dest) {p_dest.attach(detach());return *this;}
//deprecated
inline void set(T * p_ptr) {attach(p_ptr);}
private:
ptrholder_t(const t_self &) {throw pfc::exception_not_implemented();}
const t_self & operator=(const t_self & ) {throw pfc::exception_not_implemented();}
T* m_ptr;
};
PFC_NORETURN void crash();
void outputDebugLine(const char * msg);
class debugLog : public string_formatter {
public:
~debugLog() { outputDebugLine(this->get_ptr()); }
};
#define PFC_DEBUGLOG ::pfc::debugLog()._formatter()
template<typename t_type,t_type p_initval>
class int_container_helper {
public:
int_container_helper() : m_val(p_initval) {}
t_type m_val;
};
//warning: not multi-thread-safe
template<typename t_base>
class instanceTracker : public t_base {
private:
typedef instanceTracker<t_base> t_self;
public:
TEMPLATE_CONSTRUCTOR_FORWARD_FLOOD_WITH_INITIALIZER(instanceTracker,t_base,{g_list += this;});
instanceTracker(const t_self & p_other) : t_base( (const t_base &)p_other) {g_list += this;}
~instanceTracker() {g_list -= this;}
typedef pfc::avltree_t<t_self*> t_list;
static const t_list & instanceList() {return g_list;}
template<typename t_callback> static void forEach(t_callback & p_callback) {instanceList().enumerate(p_callback);}
private:
static t_list g_list;
};
template<typename t_base>
typename instanceTracker<t_base>::t_list instanceTracker<t_base>::g_list;
//warning: not multi-thread-safe
template<typename TClass>
class instanceTrackerV2 {
private:
typedef instanceTrackerV2<TClass> t_self;
public:
instanceTrackerV2(const t_self & p_other) {g_list += static_cast<TClass*>(this);}
instanceTrackerV2() {g_list += static_cast<TClass*>(this);}
~instanceTrackerV2() {g_list -= static_cast<TClass*>(this);}
typedef pfc::avltree_t<TClass*> t_instanceList;
static const t_instanceList & instanceList() {return g_list;}
template<typename t_callback> static void forEach(t_callback & p_callback) {instanceList().enumerate(p_callback);}
private:
static t_instanceList g_list;
};
template<typename TClass>
typename instanceTrackerV2<TClass>::t_instanceList instanceTrackerV2<TClass>::g_list;
struct objDestructNotifyData {
bool m_flag;
objDestructNotifyData * m_next;
};
class objDestructNotify {
public:
objDestructNotify() : m_data() {}
~objDestructNotify() {
set();
}
void set() {
objDestructNotifyData * w = m_data;
while(w) {
w->m_flag = true; w = w->m_next;
}
}
objDestructNotifyData * m_data;
};
class objDestructNotifyScope : private objDestructNotifyData {
public:
objDestructNotifyScope(objDestructNotify &obj) : m_obj(&obj) {
m_next = m_obj->m_data;
m_obj->m_data = this;
}
~objDestructNotifyScope() {
if (!m_flag) m_obj->m_data = m_next;
}
bool get() const {return m_flag;}
PFC_CLASS_NOT_COPYABLE_EX(objDestructNotifyScope)
private:
objDestructNotify * m_obj;
};
class bigmem {
public:
enum {slice = 1024*1024};
bigmem() : m_size() {}
~bigmem() {clear();}
void resize(size_t newSize);
size_t size() const {return m_size;}
void clear();
void read(void * ptrOut, size_t bytes, size_t offset);
void write(const void * ptrIn, size_t bytes, size_t offset);
uint8_t * _slicePtr(size_t which);
size_t _sliceCount();
size_t _sliceSize(size_t which);
private:
array_t<uint8_t*> m_data;
size_t m_size;
PFC_CLASS_NOT_COPYABLE_EX(bigmem)
};
double exp_int( double base, int exp );
}