2 * Carla Scope-related classes and tools (pointer and setter taken from JUCE v4)
3 * Copyright (C) 2013 Raw Material Software Ltd.
4 * Copyright (c) 2016 ROLI Ltd.
5 * Copyright (C) 2013-2020 Filipe Coelho <falktx@falktx.com>
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License as
9 * published by the Free Software Foundation; either version 2 of
10 * the License, or any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * For a full copy of the GNU General Public License see the doc/GPL.txt file.
20 #ifndef CARLA_SCOPE_UTILS_HPP_INCLUDED
21 #define CARLA_SCOPE_UTILS_HPP_INCLUDED
23 #include "CarlaUtils.hpp"
28 #if ! (defined(CARLA_OS_HAIKU) || defined(CARLA_OS_MAC) || defined(CARLA_OS_WIN))
29 # define CARLA_USE_NEWLOCALE
32 #if defined(CARLA_OS_WIN) && __MINGW64_VERSION_MAJOR >= 5
33 # define CARLA_USE_CONFIGTHREADLOCALE
36 // -----------------------------------------------------------------------
37 // CarlaScopedEnvVar class
39 class CarlaScopedEnvVar
{
41 CarlaScopedEnvVar(const char* const envVar
, const char* const valueOrNull
) noexcept
45 CARLA_SAFE_ASSERT_RETURN(envVar
!= nullptr && envVar
[0] != '\0',);
47 key
= carla_strdup_safe(envVar
);
48 CARLA_SAFE_ASSERT_RETURN(key
!= nullptr,);
50 if (const char* const envVarValue
= std::getenv(key
))
52 origValue
= carla_strdup_safe(envVarValue
);
53 CARLA_SAFE_ASSERT_RETURN(origValue
!= nullptr,);
56 // change env var if requested
57 if (valueOrNull
!= nullptr)
58 carla_setenv(key
, valueOrNull
);
59 // if null, unset. but only if there is in an active env var value
60 else if (origValue
!= nullptr)
64 ~CarlaScopedEnvVar() noexcept
66 bool hasOrigValue
= false;
68 if (origValue
!= nullptr)
72 carla_setenv(key
, origValue
);
90 const char* origValue
;
92 CARLA_DECLARE_NON_COPYABLE(CarlaScopedEnvVar
)
93 CARLA_PREVENT_HEAP_ALLOCATION
96 // -----------------------------------------------------------------------
97 // CarlaScopedLocale class
99 class CarlaScopedLocale
{
100 #ifdef CARLA_USE_NEWLOCALE
101 static constexpr locale_t kNullLocale
= (locale_t
)nullptr;
105 CarlaScopedLocale() noexcept
106 #ifdef CARLA_USE_NEWLOCALE
107 : newloc(::newlocale(LC_NUMERIC_MASK
, "C", kNullLocale
)),
108 oldloc(newloc
!= kNullLocale
? ::uselocale(newloc
) : kNullLocale
) {}
110 # ifdef CARLA_USE_CONFIGTHREADLOCALE
111 : oldthreadloc(_configthreadlocale(_ENABLE_PER_THREAD_LOCALE
)),
115 oldloc(carla_strdup_safe(::setlocale(LC_NUMERIC
, nullptr)))
117 ::setlocale(LC_NUMERIC
, "C");
121 ~CarlaScopedLocale() noexcept
123 #ifdef CARLA_USE_NEWLOCALE
124 if (oldloc
!= kNullLocale
)
126 if (newloc
!= kNullLocale
)
127 ::freelocale(newloc
);
128 #else // CARLA_USE_NEWLOCALE
129 if (oldloc
!= nullptr)
131 ::setlocale(LC_NUMERIC
, oldloc
);
135 # ifdef CARLA_USE_CONFIGTHREADLOCALE
136 if (oldthreadloc
!= -1)
137 _configthreadlocale(oldthreadloc
);
139 #endif // CARLA_USE_NEWLOCALE
143 #ifdef CARLA_USE_NEWLOCALE
144 locale_t newloc
, oldloc
;
146 # ifdef CARLA_USE_CONFIGTHREADLOCALE
147 const int oldthreadloc
;
149 const char* const oldloc
;
152 CARLA_DECLARE_NON_COPYABLE(CarlaScopedLocale
)
153 CARLA_PREVENT_HEAP_ALLOCATION
156 //=====================================================================================================================
158 This class holds a pointer which is automatically deleted when this object goes
161 Once a pointer has been passed to a CarlaScopedPointer, it will make sure that the pointer
162 gets deleted when the CarlaScopedPointer is deleted. Using the CarlaScopedPointer on the stack or
163 as member variables is a good way to use RAII to avoid accidentally leaking dynamically
166 A CarlaScopedPointer can be used in pretty much the same way that you'd use a normal pointer
167 to an object. If you use the assignment operator to assign a different object to a
168 CarlaScopedPointer, the old one will be automatically deleted.
170 A const CarlaScopedPointer is guaranteed not to lose ownership of its object or change the
171 object to which it points during its lifetime. This means that making a copy of a const
172 CarlaScopedPointer is impossible, as that would involve the new copy taking ownership from the
175 If you need to get a pointer out of a CarlaScopedPointer without it being deleted, you
176 can use the release() method.
178 Something to note is the main difference between this class and the std::auto_ptr class,
179 which is that CarlaScopedPointer provides a cast-to-object operator, whereas std::auto_ptr
180 requires that you always call get() to retrieve the pointer. The advantages of providing
181 the cast is that you don't need to call get(), so can use the CarlaScopedPointer in pretty much
182 exactly the same way as a raw pointer. The disadvantage is that the compiler is free to
183 use the cast in unexpected and sometimes dangerous ways - in particular, it becomes difficult
184 to return a CarlaScopedPointer as the result of a function. To avoid this causing errors,
185 CarlaScopedPointer contains an overloaded constructor that should cause a syntax error in these
186 circumstances, but it does mean that instead of returning a CarlaScopedPointer from a function,
187 you'd need to return a raw pointer (or use a std::auto_ptr instead).
189 template<class ObjectType
>
190 class CarlaScopedPointer
193 //=================================================================================================================
194 /** Creates a CarlaScopedPointer containing a null pointer. */
195 CarlaScopedPointer() noexcept
198 /** Creates a CarlaScopedPointer that owns the specified object. */
199 CarlaScopedPointer(ObjectType
* const objectToTakePossessionOf
) noexcept
200 : object(objectToTakePossessionOf
) {}
202 /** Creates a CarlaScopedPointer that takes its pointer from another CarlaScopedPointer.
204 Because a pointer can only belong to one CarlaScopedPointer, this transfers
205 the pointer from the other object to this one, and the other object is reset to
208 CarlaScopedPointer(CarlaScopedPointer
& objectToTransferFrom
) noexcept
209 : object(objectToTransferFrom
.object
)
211 objectToTransferFrom
.object
= nullptr;
215 This will delete the object that this CarlaScopedPointer currently refers to.
217 ~CarlaScopedPointer()
222 /** Changes this CarlaScopedPointer to point to a new object.
224 Because a pointer can only belong to one CarlaScopedPointer, this transfers
225 the pointer from the other object to this one, and the other object is reset to
228 If this CarlaScopedPointer already points to an object, that object
229 will first be deleted.
231 CarlaScopedPointer
& operator=(CarlaScopedPointer
& objectToTransferFrom
)
233 if (this != objectToTransferFrom
.getAddress())
235 // Two CarlaScopedPointers should never be able to refer to the same object - if
236 // this happens, you must have done something dodgy!
237 CARLA_SAFE_ASSERT_RETURN(object
== nullptr || object
!= objectToTransferFrom
.object
, *this);
239 ObjectType
* const oldObject
= object
;
240 object
= objectToTransferFrom
.object
;
241 objectToTransferFrom
.object
= nullptr;
248 /** Changes this CarlaScopedPointer to point to a new object.
250 If this CarlaScopedPointer already points to an object, that object
251 will first be deleted.
253 The pointer that you pass in may be a nullptr.
255 CarlaScopedPointer
& operator=(ObjectType
* const newObjectToTakePossessionOf
)
257 if (object
!= newObjectToTakePossessionOf
)
259 ObjectType
* const oldObject
= object
;
260 object
= newObjectToTakePossessionOf
;
267 //=================================================================================================================
268 /** Returns the object that this CarlaScopedPointer refers to. */
269 operator ObjectType
*() const noexcept
{ return object
; }
271 /** Returns the object that this CarlaScopedPointer refers to. */
272 ObjectType
* get() const noexcept
{ return object
; }
274 /** Returns the object that this CarlaScopedPointer refers to. */
275 ObjectType
& operator*() const noexcept
{ return *object
; }
277 /** Lets you access methods and properties of the object that this CarlaScopedPointer refers to. */
278 ObjectType
* operator->() const noexcept
{ return object
; }
280 //=================================================================================================================
281 /** Removes the current object from this CarlaScopedPointer without deleting it.
282 This will return the current object, and set the CarlaScopedPointer to a null pointer.
284 ObjectType
* release() noexcept
{ ObjectType
* const o
= object
; object
= nullptr; return o
; }
286 //=================================================================================================================
287 /** Swaps this object with that of another CarlaScopedPointer.
288 The two objects simply exchange their pointers.
290 void swapWith(CarlaScopedPointer
<ObjectType
>& other
) noexcept
292 // Two CarlaScopedPointers should never be able to refer to the same object - if
293 // this happens, you must have done something dodgy!
294 CARLA_SAFE_ASSERT_RETURN(object
!= other
.object
|| this == other
.getAddress() || object
== nullptr,);
296 std::swap(object
, other
.object
);
300 //=================================================================================================================
303 // (Required as an alternative to the overloaded & operator).
304 const CarlaScopedPointer
* getAddress() const noexcept
{ return this; }
306 #ifdef CARLA_PROPER_CPP11_SUPPORT
307 CarlaScopedPointer(const CarlaScopedPointer
&) = delete;
308 CarlaScopedPointer
& operator=(const CarlaScopedPointer
&) = delete;
310 CarlaScopedPointer(const CarlaScopedPointer
&);
311 CarlaScopedPointer
& operator=(const CarlaScopedPointer
&);
315 //=====================================================================================================================
316 /** Compares a CarlaScopedPointer with another pointer.
317 This can be handy for checking whether this is a null pointer.
319 template<class ObjectType
>
320 bool operator==(const CarlaScopedPointer
<ObjectType
>& pointer1
, ObjectType
* const pointer2
) noexcept
322 return static_cast<ObjectType
*>(pointer1
) == pointer2
;
325 /** Compares a CarlaScopedPointer with another pointer.
326 This can be handy for checking whether this is a null pointer.
328 template<class ObjectType
>
329 bool operator!=(const CarlaScopedPointer
<ObjectType
>& pointer1
, ObjectType
* const pointer2
) noexcept
331 return static_cast<ObjectType
*>(pointer1
) != pointer2
;
334 //=====================================================================================================================
336 Helper class providing an RAII-based mechanism for temporarily setting and
337 then re-setting a value.
343 CarlaScopedValueSetter setter (x, 2);
351 CarlaScopedValueSetter setter (x, 3, 4);
359 template <typename ValueType
>
360 class CarlaScopedValueSetter
363 /** Creates a CarlaScopedValueSetter that will immediately change the specified value to the
364 given new value, and will then reset it to its original value when this object is deleted.
365 Must be used only for 'noexcept' compatible types.
367 CarlaScopedValueSetter(ValueType
& valueToSet
, ValueType newValue
) noexcept
369 originalValue(valueToSet
)
371 valueToSet
= newValue
;
374 /** Creates a CarlaScopedValueSetter that will immediately change the specified value to the
375 given new value, and will then reset it to be valueWhenDeleted when this object is deleted.
377 CarlaScopedValueSetter(ValueType
& valueToSet
, ValueType newValue
, ValueType valueWhenDeleted
) noexcept
379 originalValue(valueWhenDeleted
)
381 valueToSet
= newValue
;
384 ~CarlaScopedValueSetter() noexcept
386 value
= originalValue
;
390 //=================================================================================================================
392 const ValueType originalValue
;
394 CARLA_DECLARE_NON_COPYABLE(CarlaScopedValueSetter
)
395 CARLA_PREVENT_HEAP_ALLOCATION
398 // -----------------------------------------------------------------------
400 #endif // CARLA_SCOPE_UTILS_HPP_INCLUDED