Files
2026-08-16 18:24:52 +07:00

555 lines
16 KiB
C++

// This file is part of VSTGUI. It is subject to the license terms
// in the LICENSE file found in the top-level directory of this
// distribution and at http://github.com/steinbergmedia/vstgui/LICENSE
#pragma once
#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <utility>
//-----------------------------------------------------------------------------
// VSTGUI Version
//-----------------------------------------------------------------------------
#define VSTGUI_VERSION_MAJOR 4
#define VSTGUI_VERSION_MINOR 15
#define VSTGUI_VERSION_PATCHLEVEL 0
//-----------------------------------------------------------------------------
// Platform definitions
//-----------------------------------------------------------------------------
#if __APPLE_CC__
#ifndef __ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES
#define __ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES 0
#endif
#include <stdint.h>
#include <AvailabilityMacros.h>
#include <TargetConditionals.h>
#if TARGET_OS_IPHONE
#ifndef MAC
#define MAC 1
#endif
#ifndef MAC_COCOA
#define MAC_COCOA 1
#endif
#define VSTGUI_OPENGL_SUPPORT 0 // there's an implementation, but not yet tested, so this is zero
#define VSTGUI_TOUCH_EVENT_HANDLING 1
#else
#ifndef MAC_OS_X_VERSION_10_9
#error you need at least OSX SDK 10.9 to build vstgui
#endif
#ifndef MAC_COCOA
#define MAC_COCOA 1
#endif
#ifndef MAC
#define MAC 1
#endif
#endif
#ifndef __has_feature
#error compiler not supported
#endif
#if __has_feature (cxx_rvalue_references) == 0
#error need cxx_rvalue_references support from compiler
#endif
#if __has_feature (cxx_range_for) == 0
#error need cxx_range_for support from compiler
#endif
#include <type_traits>
#if defined (__clang__) && __clang_major__ > 4
#if defined (VSTGUI_WARN_EVERYTHING) && VSTGUI_WARN_EVERYTHING == 1
#pragma clang diagnostic warning "-Weverything"
#pragma clang diagnostic warning "-Wconversion"
#pragma clang diagnostic ignored "-Wreorder"
#else
#pragma clang diagnostic warning "-Wunreachable-code"
#if __clang_major__ > 7
#pragma clang diagnostic warning "-Wshadow"
#endif
#endif
#endif
#elif WIN32 || WINDOWS || defined(_WIN32)
#ifndef NOMINMAX
#define NOMINMAX
#endif
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#include <sdkddkver.h>
#if _WIN32_WINNT < 0x601
#error unsupported Platform SDK you need at least the Windows 7 Platform SDK to compile VSTGUI
#endif
#ifdef __GNUC__
#if __cplusplus < 201103L
#error compiler not supported
#endif
#elif _MSC_VER <= 1800
#error Visual Studio 2015 or newer needed
#endif
#include <type_traits>
#include <cstdint>
#ifndef WINDOWS
#define WINDOWS 1
#endif
#if (defined(_M_ARM64) || defined(_M_ARM))
#if defined(VSTGUI_OPENGL_SUPPORT)
#undef VSTGUI_OPENGL_SUPPORT
#endif
#define VSTGUI_OPENGL_SUPPORT 0
#endif
#ifdef _MSC_VER
#pragma warning(3 : 4189) // local variable is initialized but not referenced
#pragma warning(3 : 4702) // unreachable code
#pragma warning(3 : 4995) // deprecated
#pragma warning(3 : 4431) // missing type specifier - int assumed. Note: C no longer supports default-int
#pragma warning(3 : 4254) // conversion from 'type1' to 'type2', possible loss of data
#pragma warning(3 : 4388) // signed/unsigned mismatch
#pragma warning(disable : 4250) // class1' : inherits 'class2::member' via dominance
#endif
#if defined (__clang__) && __clang__
#if defined (VSTGUI_WARN_EVERYTHING) && VSTGUI_WARN_EVERYTHING == 1
#pragma clang diagnostic warning "-Wconversion"
#pragma clang diagnostic ignored "-Wreorder"
#else
#pragma clang diagnostic warning "-Wunreachable-code"
#endif
#endif
#include <algorithm>
using std::min;
using std::max;
#elif defined(__linux__)
#include <cstdint>
#include <type_traits>
#include <algorithm>
#include <climits>
using std::min;
using std::max;
#ifndef LINUX
#define LINUX 1
#endif
#else
#error unsupported system/compiler
#endif
#include <atomic>
#include <utility>
#ifdef UNICODE
#undef UNICODE
#endif
#define UNICODE 1
//----------------------------------------------------
// Deprecation setting
//----------------------------------------------------
#ifndef VSTGUI_ENABLE_DEPRECATED_METHODS
#define VSTGUI_ENABLE_DEPRECATED_METHODS 1
#endif
#if VSTGUI_ENABLE_DEPRECATED_METHODS
#define VSTGUI_DEPRECATED(x) [[deprecated]] x
#define VSTGUI_DEPRECATED_MSG(x, msg) [[deprecated(msg)]] x
#else
#define VSTGUI_DEPRECATED(x)
#define VSTGUI_DEPRECATED_MSG(x, msg)
#endif
//----------------------------------------------------
// Feature setting
//----------------------------------------------------
#ifndef VSTGUI_OPENGL_SUPPORT
#define VSTGUI_OPENGL_SUPPORT 1
#endif
#ifndef VSTGUI_TOUCH_EVENT_HANDLING
#define VSTGUI_TOUCH_EVENT_HANDLING 0
#endif
#ifndef VSTGUI_ENABLE_XML_PARSER
#define VSTGUI_ENABLE_XML_PARSER 1
#endif
#if VSTGUI_ENABLE_DEPRECATED_METHODS
#define VSTGUI_OVERRIDE_VMETHOD override
#define VSTGUI_FINAL_VMETHOD final
#else
#define VSTGUI_OVERRIDE_VMETHOD static_assert (false, "VSTGUI_OVERRIDE_VMETHOD is deprecated, just use override!");
#define VSTGUI_FINAL_VMETHOD static_assert (false, "VSTGUI_FINAL_VMETHOD is deprecated, just use final!");
#endif
//----------------------------------------------------
// Helper makros
//----------------------------------------------------
#define VSTGUI_MAKE_STRING_PRIVATE_DONT_USE(x) # x
#define VSTGUI_MAKE_STRING(x) VSTGUI_MAKE_STRING_PRIVATE_DONT_USE(x)
//----------------------------------------------------
#if DEVELOPMENT
#ifndef DEBUG
#define DEBUG 1
#endif
#else
#if !defined(NDEBUG) && !defined(DEBUG)
#define NDEBUG 1
#endif
#endif
//----------------------------------------------------
#define CLASS_METHODS(name, parent) CBaseObject* newCopy () const override { return new name (*this); }
#define CLASS_METHODS_NOCOPY(name, parent) CBaseObject* newCopy () const override { return nullptr; }
#define CLASS_METHODS_VIRTUAL(name, parent) CBaseObject* newCopy () const override = 0;
//----------------------------------------------------
namespace VSTGUI {
/** coordinate type */
using CCoord = double;
/** ID String pointer */
using IdStringPtr = const char*;
/** UTF8 String pointer */
using UTF8StringPtr = const char*;
/** UTF8 String buffer pointer */
using UTF8StringBuffer = char*;
//-----------------------------------------------------------------------------
// @brief Byte Order
//-----------------------------------------------------------------------------
enum ByteOrder
{
kBigEndianByteOrder = 0,
kLittleEndianByteOrder,
#if WINDOWS || defined(__LITTLE_ENDIAN__) || defined(__LITTLE_ENDIAN)
kNativeByteOrder = kLittleEndianByteOrder
#else
kNativeByteOrder = kBigEndianByteOrder
#endif
};
//-----------------------------------------------------------------------------
// @brief Message Results
//-----------------------------------------------------------------------------
enum CMessageResult
{
kMessageUnknown = 0,
kMessageNotified = 1
};
//-----------------------------------------------------------------------------
class IReference
{
public:
/** decrease refcount and delete object if refcount == 0 */
virtual void forget () = 0;
/** increase refcount */
virtual void remember () = 0;
};
//-----------------------------------------------------------------------------
template <typename T>
class ReferenceCounted : virtual public IReference
{
public:
ReferenceCounted () = default;
virtual ~ReferenceCounted () noexcept = default;
ReferenceCounted (const ReferenceCounted&) {}
ReferenceCounted& operator= (const ReferenceCounted&) { return *this; }
//-----------------------------------------------------------------------------
/// @name Reference Counting Methods
//-----------------------------------------------------------------------------
//@{
void forget () override { if (--nbReference == 0) { beforeDelete (); delete this; } }
void remember () override { nbReference++; }
/** get refcount */
virtual int32_t getNbReference () const { return nbReference; }
//@}
private:
virtual void beforeDelete () {}
T nbReference {1};
};
using AtomicReferenceCounted = ReferenceCounted<std::atomic<int32_t>>;
using NonAtomicReferenceCounted = ReferenceCounted<int32_t>;
//-----------------------------------------------------------------------------
// CBaseObject Declaration
//! @brief Base Object with reference counter
//-----------------------------------------------------------------------------
class CBaseObject : public NonAtomicReferenceCounted
{
public:
CBaseObject () = default;
~CBaseObject () noexcept override = default;
CBaseObject (const CBaseObject&) {}
CBaseObject& operator= (const CBaseObject&) { return *this; }
//-----------------------------------------------------------------------------
/// @name Message Methods
//-----------------------------------------------------------------------------
//@{
virtual CMessageResult notify ([[maybe_unused]] CBaseObject* sender,
[[maybe_unused]] IdStringPtr message)
{
return kMessageUnknown;
}
//@}
/// @cond ignore
virtual CBaseObject* newCopy () const { return nullptr; }
/// @endcond
};
//------------------------------------------------------------------------
template <class I>
class SharedPointer
{
public:
//------------------------------------------------------------------------
inline SharedPointer (I* ptr, bool remember = true) noexcept;
inline SharedPointer (const SharedPointer&) noexcept;
inline SharedPointer () noexcept;
inline ~SharedPointer () noexcept;
inline I* operator=(I* ptr) noexcept;
inline SharedPointer<I>& operator=(const SharedPointer<I>& ) noexcept;
inline operator I* () const noexcept { return ptr; } // act as I*
inline I* operator->() const noexcept { return ptr; } // act as I*
inline I* get () const noexcept { return ptr; }
template<class T> T* cast () const { return dynamic_cast<T*> (ptr); }
inline SharedPointer (SharedPointer<I>&& mp) noexcept;
inline SharedPointer<I>& operator=(SharedPointer<I>&& mp) noexcept;
template<typename T>
inline SharedPointer (const SharedPointer<T>& op) noexcept
{
*this = static_cast<I*> (op.get ());
}
template<typename T>
inline SharedPointer& operator= (const SharedPointer<T>& op) noexcept
{
*this = static_cast<I*> (op.get ());
return *this;
}
template<typename T>
inline SharedPointer (SharedPointer<T>&& op) noexcept
{
*this = std::move (op);
}
template<typename T>
inline SharedPointer& operator= (SharedPointer<T>&& op) noexcept
{
if (ptr)
ptr->forget ();
ptr = op.ptr;
op.ptr = nullptr;
return *this;
}
//------------------------------------------------------------------------
protected:
template<typename T>
friend class SharedPointer;
I* ptr {nullptr};
};
//-----------------------------------------------------------------------------
class CBaseObjectGuard
{
public:
explicit CBaseObjectGuard (CBaseObject* _obj) : obj (_obj) {}
protected:
SharedPointer<CBaseObject> obj;
};
//------------------------------------------------------------------------
template <class I>
inline SharedPointer<I>::SharedPointer (I* _ptr, bool remember) noexcept
: ptr (_ptr)
{
if (ptr && remember)
ptr->remember ();
}
//------------------------------------------------------------------------
template <class I>
inline SharedPointer<I>::SharedPointer (const SharedPointer<I>& other) noexcept
: ptr (other.ptr)
{
if (ptr)
ptr->remember ();
}
//------------------------------------------------------------------------
template <class I>
inline SharedPointer<I>::SharedPointer () noexcept
: ptr (nullptr)
{}
//------------------------------------------------------------------------
template <class I>
inline SharedPointer<I>::~SharedPointer () noexcept
{
if (ptr)
ptr->forget ();
}
//------------------------------------------------------------------------
template <class I>
inline SharedPointer<I>::SharedPointer (SharedPointer<I>&& mp) noexcept
: ptr (nullptr)
{
*this = std::move (mp);
}
//------------------------------------------------------------------------
template <class I>
inline SharedPointer<I>& SharedPointer<I>::operator=(SharedPointer<I>&& mp) noexcept
{
if (ptr)
ptr->forget ();
ptr = mp.ptr;
mp.ptr = nullptr;
return *this;
}
//------------------------------------------------------------------------
template <class I>
inline I* SharedPointer<I>::operator=(I* _ptr) noexcept
{
if (_ptr != ptr)
{
if (ptr)
ptr->forget ();
ptr = _ptr;
if (ptr)
ptr->remember ();
}
return ptr;
}
//------------------------------------------------------------------------
template <class I>
inline SharedPointer<I>& SharedPointer<I>::operator=(const SharedPointer<I>& _ptr) noexcept
{
operator= (_ptr.ptr);
return *this;
}
//------------------------------------------------------------------------
template <class I>
inline SharedPointer<I> owned (I* p) noexcept { return SharedPointer<I> (p, false); }
//------------------------------------------------------------------------
template <class I>
inline SharedPointer<I> shared (I* p) noexcept { return SharedPointer<I> (p, true); }
//------------------------------------------------------------------------
template <class I, typename ...Args>
inline SharedPointer<I> makeOwned (Args&& ...args)
{
return SharedPointer<I> (new I (std::forward<Args>(args)...), false);
}
#if VSTGUI_ENABLE_DEPRECATED_METHODS
//------------------------------------------------------------------------
/** An owning pointer. \deprecated
*
* This class is now deprecated. Please change your code from
* @code{.cpp} OwningPointer<MyClass> obj = new MyClass () @endcode
* to
* @code{.cpp} SharedPointer<MyClass> obj = makeOwned<MyClass> (); @endcode
*/
template <class I>
class OwningPointer : public SharedPointer<I>
{
public:
//------------------------------------------------------------------------
inline OwningPointer (I* p) : SharedPointer<I> (p, false) {}
inline OwningPointer (const SharedPointer<I>& p) : SharedPointer<I> (p) {}
inline OwningPointer (const OwningPointer<I>& p) : SharedPointer<I> (p) {}
inline OwningPointer () : SharedPointer<I> () {}
inline I* operator=(I* _ptr)
{
if (_ptr != this->ptr)
{
if (this->ptr)
this->ptr->forget ();
this->ptr = _ptr;
}
return this->ptr;
}
};
#endif
//------------------------------------------------------------------------
template <typename T, typename B>
inline void setBit (T& storage, B bit, bool state)
{
static_assert (std::is_integral<T>::value, "only works for integral types");
static_assert (sizeof (T) >= sizeof (B), "bit type is too big");
if (state)
storage |= static_cast<T> (bit);
else
storage &= ~(static_cast<T> (bit));
}
//------------------------------------------------------------------------
template <typename T, typename B>
inline constexpr bool hasBit (T storage, B bit)
{
static_assert (std::is_integral<T>::value, "only works for integral types");
static_assert (sizeof (T) >= sizeof (B), "bit type is too big");
return (storage & static_cast<T> (bit)) ? true : false;
}
//-----------------------------------------------------------------------------
template <typename T, typename B>
struct BitScopeToggleT
{
BitScopeToggleT (T& storage, B bit) : storage (storage), bit (bit) { toggle (); }
~BitScopeToggleT () noexcept { toggle (); }
private:
void toggle ()
{
bool state = hasBit (storage, bit);
setBit (storage, bit, !state);
}
T& storage;
B bit;
};
//-----------------------------------------------------------------------------
#define VSTGUI_NEWER_THAN(major, minor) \
(VSTGUI_VERSION > major || (VSTGUI_VERSION_MAJOR == major && VSTGUI_VERSION_MINOR > minor))
#define VSTGUI_NEWER_THAN_4_10 VSTGUI_NEWER_THAN (4, 10)
#define VSTGUI_NEWER_THAN_4_11 VSTGUI_NEWER_THAN (4, 11)
#define VSTGUI_NEWER_THAN_4_12 VSTGUI_NEWER_THAN (4, 12)
#define VSTGUI_NEWER_THAN_4_13 VSTGUI_NEWER_THAN (4, 13)
} // VSTGUI
//-----------------------------------------------------------------------------
#include "vstguidebug.h"