efl/src/bindings/cxx/eina_cxx/eina_clone_allocators.hh

216 lines
5.0 KiB
C++

/*
* Copyright 2019 by its authors. See AUTHORS.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef EINA_CLONE_ALLOCATORS_HH_
#define EINA_CLONE_ALLOCATORS_HH_
#include <eina_workarounds.hh>
#include <Eo.h>
#include <memory>
#include <cstring>
#include <cstdlib>
#include <type_traits>
/**
* @addtogroup Eina_Cxx_Containers_Group
*
* @{
*/
namespace efl { namespace eina {
/**
* @defgroup Eina_Cxx_Clone_Allocators_Group Clone Allocators
* @ingroup Eina_Cxx_Containers_Group
*
* Clone allocators is a formalized way to pointer containers control
* the memory of the stored objects, allowing users to apply custom
* allocators/deallocators for the cloned objects.
*
* @{
*/
/*
* @internal
*/
struct default_clone_allocator_placeholder;
/**
* This allocator creates copies of objects on the heap, calling their
* copy constructor to make then equivalent to the given reference.
*
* The created objects are released with the default delete.
*/
struct heap_copy_allocator
{
template <typename T>
static T* allocate_clone(T const& v)
{
return new T(v);
}
template <typename T>
static void deallocate_clone(T* p)
{
#ifdef EFL_EINA_CXX11
std::default_delete<T>()(p);
#else
delete p;
#endif
}
};
/**
* This allocator creates copies of Eo classes through eo_ref
*
* The created objects are released using eo_unref
*/
struct eo_clone_allocator
{
static Eo* allocate_clone(Eo const& v)
{
return ::efl_ref(&v);
}
static void deallocate_clone(Eo const* p)
{
::efl_unref(const_cast<Eo*>(p));
}
};
/**
* This allocator allows users to create custom allocation schemes by
* overloading the <tt>new_clone(T const& v)</tt> and
* <tt>delete_clone(T* p)</tt> functions.
*/
struct heap_clone_allocator
{
template <typename T>
static T* allocate_clone(T const& v)
{
return new_clone(v);
}
template <typename T>
static void deallocate_clone(T* p)
{
delete_clone(p);
}
};
/**
* This allocator does not allocate or deallocate anything. It simple
* gets non-const-qualified pointers for objects, which allow
* containers to hold elements without having ownership on them.
*
* It is commonly used to create a pointer container that is a view into
* another existing container.
*/
struct view_clone_allocator
{
template <typename T>
static T* allocate_clone(T const& v)
{
return const_cast<T*>(&v);
}
template <typename T>
static void deallocate_clone(T*)
{
}
};
/**
* This allocator does not define an @c allocate_clone member function,
* so it should be used to disable operations that require elements to
* be cloned.
*/
struct heap_no_copy_allocator
{
static void deallocate_clone(_Elm_Calendar_Mark const volatile*) {}
static void deallocate_clone(_Elm_Calendar_Mark volatile*) {}
static void deallocate_clone(_Elm_Calendar_Mark const*) {}
static void deallocate_clone(_Elm_Calendar_Mark*) {}
static void deallocate_clone(Elm_Gen_Item const volatile*) {}
static void deallocate_clone(Elm_Gen_Item volatile*) {}
static void deallocate_clone(Elm_Gen_Item const*) {}
static void deallocate_clone(Elm_Gen_Item*) {}
static void deallocate_clone(_Elm_Map_Overlay const volatile*) {}
static void deallocate_clone(_Elm_Map_Overlay volatile*) {}
static void deallocate_clone(_Elm_Map_Overlay const*) {}
static void deallocate_clone(_Elm_Map_Overlay*) {}
template <typename T>
static void deallocate_clone(T* p)
{
#ifdef EFL_EINA_CXX11
std::default_delete<T>()(p);
#else
delete p;
#endif
}
};
/**
* Manages allocation and deallocation of memory using the function
* @c malloc and @c free. This allocator does not calls constructors,
* the content of the newly allocated objects are assigned using
* @c memcpy, so it has to be used with types that have
* <em>standard-layout</em>.
*/
struct malloc_clone_allocator
{
template <typename T>
static T* allocate_clone(T const& v)
{
static_assert(std::is_pod<T>::value, "malloc_clone_allocator can only be used with POD types");
T* p = static_cast<T*>(std::malloc(sizeof(T)));
std::memcpy(p, &v, sizeof(T));
return p;
}
template <typename T>
static void deallocate_clone(T const* p)
{
static_assert(std::is_pod<T>::value || std::is_void<T>::value
, "malloc_clone_allocator can only be used with POD types");
std::free(const_cast<T*>(p));
}
};
/**
* @internal
*/
template <typename A>
struct clone_allocator_deleter
{
template <typename T>
void operator()(T* object) const
{
A::deallocate_clone(object);
}
};
/**
* @}
*/
} }
/**
* @}
*/
#endif