/* * 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 #include #include #include #include #include /** * @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 static T* allocate_clone(T const& v) { return new T(v); } template static void deallocate_clone(T* p) { #ifdef EFL_EINA_CXX11 std::default_delete()(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(p)); } }; /** * This allocator allows users to create custom allocation schemes by * overloading the new_clone(T const& v) and * delete_clone(T* p) functions. */ struct heap_clone_allocator { template static T* allocate_clone(T const& v) { return new_clone(v); } template 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 static T* allocate_clone(T const& v) { return const_cast(&v); } template 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 static void deallocate_clone(T* p) { #ifdef EFL_EINA_CXX11 std::default_delete()(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 * standard-layout. */ struct malloc_clone_allocator { template static T* allocate_clone(T const& v) { static_assert(std::is_pod::value, "malloc_clone_allocator can only be used with POD types"); T* p = static_cast(std::malloc(sizeof(T))); std::memcpy(p, &v, sizeof(T)); return p; } template static void deallocate_clone(T const* p) { static_assert(std::is_pod::value || std::is_void::value , "malloc_clone_allocator can only be used with POD types"); std::free(const_cast(p)); } }; /** * @internal */ template struct clone_allocator_deleter { template void operator()(T* object) const { A::deallocate_clone(object); } }; /** * @} */ } } /** * @} */ #endif