Mercurial > hg > pub > prymula > com
diff DPF-Prymula-audioplugins/dpf/distrho/extra/ScopedPointer.hpp @ 3:84e66ea83026
DPF-Prymula-audioplugins-0.231015-2
author | prymula <prymula76@outlook.com> |
---|---|
date | Mon, 16 Oct 2023 21:53:34 +0200 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DPF-Prymula-audioplugins/dpf/distrho/extra/ScopedPointer.hpp Mon Oct 16 21:53:34 2023 +0200 @@ -0,0 +1,251 @@ +/* + * DISTRHO Plugin Framework (DPF) + * Copyright (C) 2012-2016 Filipe Coelho <falktx@falktx.com> + * + * Permission to use, copy, modify, and/or distribute this software for any purpose with + * or without fee is hereby granted, provided that the above copyright notice and this + * permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD + * TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER + * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef DISTRHO_SCOPED_POINTER_HPP_INCLUDED +#define DISTRHO_SCOPED_POINTER_HPP_INCLUDED + +#include "../DistrhoUtils.hpp" + +#include <algorithm> + +START_NAMESPACE_DISTRHO + +// ----------------------------------------------------------------------- +// The following code was based from juce-core ScopedPointer class + +/** + Copyright (C) 2013 Raw Material Software Ltd. + + Permission is granted to use this software under the terms of the ISC license + http://www.isc.org/downloads/software-support-policy/isc-license/ + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH REGARD + TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND + FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, + OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF + USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + OF THIS SOFTWARE. +*/ + +//============================================================================== +/** + This class holds a pointer which is automatically deleted when this object goes + out of scope. + + Once a pointer has been passed to a ScopedPointer, it will make sure that the pointer + gets deleted when the ScopedPointer is deleted. Using the ScopedPointer on the stack or + as member variables is a good way to use RAII to avoid accidentally leaking dynamically + created objects. + + A ScopedPointer can be used in pretty much the same way that you'd use a normal pointer + to an object. If you use the assignment operator to assign a different object to a + ScopedPointer, the old one will be automatically deleted. + + A const ScopedPointer is guaranteed not to lose ownership of its object or change the + object to which it points during its lifetime. This means that making a copy of a const + ScopedPointer is impossible, as that would involve the new copy taking ownership from the + old one. + + If you need to get a pointer out of a ScopedPointer without it being deleted, you + can use the release() method. + + Something to note is the main difference between this class and the std::auto_ptr class, + which is that ScopedPointer provides a cast-to-object operator, wheras std::auto_ptr + requires that you always call get() to retrieve the pointer. The advantages of providing + the cast is that you don't need to call get(), so can use the ScopedPointer in pretty much + exactly the same way as a raw pointer. The disadvantage is that the compiler is free to + use the cast in unexpected and sometimes dangerous ways - in particular, it becomes difficult + to return a ScopedPointer as the result of a function. To avoid this causing errors, + ScopedPointer contains an overloaded constructor that should cause a syntax error in these + circumstances, but it does mean that instead of returning a ScopedPointer from a function, + you'd need to return a raw pointer (or use a std::auto_ptr instead). +*/ +template<class ObjectType> +class ScopedPointer +{ +public: + //============================================================================== + /** Creates a ScopedPointer containing a null pointer. */ + ScopedPointer() noexcept + : object(nullptr) {} + + /** Creates a ScopedPointer that owns the specified object. */ + ScopedPointer(ObjectType* const objectToTakePossessionOf) noexcept + : object(objectToTakePossessionOf) {} + + /** Creates a ScopedPointer that takes its pointer from another ScopedPointer. + + Because a pointer can only belong to one ScopedPointer, this transfers + the pointer from the other object to this one, and the other object is reset to + be a null pointer. + */ + ScopedPointer(ScopedPointer& objectToTransferFrom) noexcept + : object(objectToTransferFrom.object) + { + objectToTransferFrom.object = nullptr; + } + + /** Destructor. + This will delete the object that this ScopedPointer currently refers to. + */ + ~ScopedPointer() + { + delete object; + } + + /** Changes this ScopedPointer to point to a new object. + + Because a pointer can only belong to one ScopedPointer, this transfers + the pointer from the other object to this one, and the other object is reset to + be a null pointer. + + If this ScopedPointer already points to an object, that object + will first be deleted. + */ + ScopedPointer& operator=(ScopedPointer& objectToTransferFrom) + { + if (this != objectToTransferFrom.getAddress()) + { + // Two ScopedPointers should never be able to refer to the same object - if + // this happens, you must have done something dodgy! + DISTRHO_SAFE_ASSERT_RETURN(object == nullptr || object != objectToTransferFrom.object, *this); + + ObjectType* const oldObject = object; + object = objectToTransferFrom.object; + objectToTransferFrom.object = nullptr; + delete oldObject; + } + + return *this; + } + + /** Changes this ScopedPointer to point to a new object. + + If this ScopedPointer already points to an object, that object + will first be deleted. + + The pointer that you pass in may be a nullptr. + */ + ScopedPointer& operator=(ObjectType* const newObjectToTakePossessionOf) + { + if (object != newObjectToTakePossessionOf) + { + ObjectType* const oldObject = object; + object = newObjectToTakePossessionOf; + delete oldObject; + } + + return *this; + } + + //============================================================================== + /** Returns the object that this ScopedPointer refers to. */ + operator ObjectType*() const noexcept { return object; } + + /** Returns the object that this ScopedPointer refers to. */ + ObjectType* get() const noexcept { return object; } + + /** Returns the object that this ScopedPointer refers to. */ + ObjectType& getObject() const noexcept { return *object; } + + /** Returns the object that this ScopedPointer refers to. */ + ObjectType& operator*() const noexcept { return *object; } + + /** Lets you access methods and properties of the object that this ScopedPointer refers to. */ + ObjectType* operator->() const noexcept { return object; } + + //============================================================================== + /** Removes the current object from this ScopedPointer without deleting it. + This will return the current object, and set the ScopedPointer to a null pointer. + */ + ObjectType* release() noexcept { ObjectType* const o = object; object = nullptr; return o; } + + //============================================================================== + /** Swaps this object with that of another ScopedPointer. + The two objects simply exchange their pointers. + */ + void swapWith(ScopedPointer<ObjectType>& other) noexcept + { + // Two ScopedPointers should never be able to refer to the same object - if + // this happens, you must have done something dodgy! + DISTRHO_SAFE_ASSERT_RETURN(object != other.object || this == other.getAddress() || object == nullptr,); + + std::swap(object, other.object); + } + +private: + //============================================================================== + ObjectType* object; + + // (Required as an alternative to the overloaded & operator). + const ScopedPointer* getAddress() const noexcept { return this; } + +#ifndef _MSC_VER // (MSVC can't deal with multiple copy constructors) + /* The copy constructors are private to stop people accidentally copying a const ScopedPointer + (the compiler would let you do so by implicitly casting the source to its raw object pointer). + + A side effect of this is that in a compiler that doesn't support C++11, you may hit an + error when you write something like this: + + ScopedPointer<MyClass> m = new MyClass(); // Compile error: copy constructor is private. + + Even though the compiler would normally ignore the assignment here, it can't do so when the + copy constructor is private. It's very easy to fix though - just write it like this: + + ScopedPointer<MyClass> m (new MyClass()); // Compiles OK + + It's probably best to use the latter form when writing your object declarations anyway, as + this is a better representation of the code that you actually want the compiler to produce. + */ +# ifdef DISTRHO_PROPER_CPP11_SUPPORT + ScopedPointer(const ScopedPointer&) = delete; + ScopedPointer& operator=(const ScopedPointer&) = delete; +# else + ScopedPointer(const ScopedPointer&); + ScopedPointer& operator=(const ScopedPointer&); +# endif +#endif +}; + +//============================================================================== +/** Compares a ScopedPointer with another pointer. + This can be handy for checking whether this is a null pointer. +*/ +template<class ObjectType> +bool operator==(const ScopedPointer<ObjectType>& pointer1, ObjectType* const pointer2) noexcept +{ + return static_cast<ObjectType*>(pointer1) == pointer2; +} + +/** Compares a ScopedPointer with another pointer. + This can be handy for checking whether this is a null pointer. +*/ +template<class ObjectType> +bool operator!=(const ScopedPointer<ObjectType>& pointer1, ObjectType* const pointer2) noexcept +{ + return static_cast<ObjectType*>(pointer1) != pointer2; +} + +// ----------------------------------------------------------------------- + +END_NAMESPACE_DISTRHO + +#endif // DISTRHO_SCOPED_POINTER_HPP_INCLUDED