/* SPDX-FileCopyrightText: 2023 Blender Authors * * SPDX-License-Identifier: GPL-2.0-or-later */ /** \file * \ingroup DNA * * Group generic defines for all DNA headers may use in this file. */ #pragma once /* `makesdna` ignores. */ #ifdef DNA_DEPRECATED_ALLOW /* allow use of deprecated items */ # define DNA_DEPRECATED #else # if defined(__GNUC__) || defined(__clang__) || defined(_MSC_VER) # define DNA_DEPRECATED [[deprecated]] # else # define DNA_DEPRECATED # endif #endif /* GCC considers default member initialization in constructors deprecated. * This macro helps silence that while still warning in other cases */ #if defined(__GNUC__) || defined(__clang__) /* clang-format off */ # define DNA_DEPRECATED_IGNORE(statement) \ _Pragma("GCC diagnostic push") \ _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"") \ statement \ _Pragma("GCC diagnostic pop") /* clang-format on */ #else # define DNA_DEPRECATED_IGNORE(statement) statement #endif #ifdef __GNUC__ # define DNA_PRIVATE_ATTR __attribute__((deprecated)) #else # define DNA_PRIVATE_ATTR #endif /* poison pragma */ #ifdef DNA_DEPRECATED_ALLOW # define DNA_DEPRECATED_GCC_POISON 0 #else /* enable the pragma if we can */ # ifdef __GNUC__ # define DNA_DEPRECATED_GCC_POISON 1 # else # define DNA_DEPRECATED_GCC_POISON 0 # endif #endif /* hrmf, we need a better include then this */ #include "../blenlib/BLI_sys_types.h" /* needed for int64_t only! */ namespace blender { /* non-id name variables should use this length */ #define MAX_NAME 64 /* #DNA_DEFINE_CXX_METHODS is used to define C++ methods which are needed for proper/safe resource * management, making unsafe (from an ownership perspective: i.e. pointers which sometimes needs to * be set to nullptr on copy, sometimes needs to be dupalloc-ed) operations explicit, and taking * care of compiler specific warnings when dealing with members marked with DNA_DEPRECATED. * * The `class_name` argument is to match the structure name the macro is used from. * * Typical usage example: * * struct Object { * DNA_DEFINE_CXX_METHODS(Object) * }; */ /* Forward-declared here since there is no simple header file to be pulled for this functionality. * Avoids pulling `string.h` from this header to get access to #memcpy. */ void _DNA_internal_memcpy(void *dst, const void *src, size_t size); void _DNA_internal_memzero(void *dst, size_t size); void _DNA_internal_swap(void *a, void *b, size_t size); namespace dna::internal { template class ShallowDataConstRef { public: constexpr explicit ShallowDataConstRef(const T &ref) : ref_(ref) {} const T *get_pointer() const { return &ref_; } private: const T &ref_; }; class ShallowZeroInitializeTag {}; } // namespace dna::internal #define DNA_DEFINE_CXX_METHODS(class_name) \ DNA_DEPRECATED_IGNORE(class_name() = default;) \ ~class_name() = default; \ /* Delete copy and assignment, which are not safe for resource ownership. */ \ class_name(const class_name &other) = delete; \ class_name(class_name &&other) noexcept = delete; \ class_name &operator=(const class_name &other) = delete; \ class_name &operator=(class_name &&other) = delete; \ /* Support for shallow copy. */ \ /* NOTE: Calling the default constructor works-around deprecated warning generated by GCC. */ \ class_name(const dna::internal::ShallowDataConstRef ref) : class_name() \ { \ _DNA_internal_memcpy(this, ref.get_pointer(), sizeof(class_name)); \ } \ class_name &operator=(const dna::internal::ShallowDataConstRef ref) \ { \ if (this != ref.get_pointer()) { \ _DNA_internal_memcpy(this, ref.get_pointer(), sizeof(class_name)); \ } \ return *this; \ } \ /* Create object which memory is filled with zeros. */ \ class_name(const dna::internal::ShallowZeroInitializeTag /*tag*/) : class_name() \ { \ _DNA_internal_memzero(this, sizeof(class_name)); \ } \ class_name &operator=(const dna::internal::ShallowZeroInitializeTag /*tag*/) \ { \ _DNA_internal_memzero(this, sizeof(class_name)); \ return *this; \ } namespace dna { /* Creates shallow copy of the given object. * The entire object is copied as-is using memory copy. * * Typical usage: * Object temp_object = dna::shallow_copy(*input_object); * * From the implementation detail go via copy constructor/assign operator defined in the structure. */ template [[nodiscard]] inline internal::ShallowDataConstRef shallow_copy(const T &other) { return internal::ShallowDataConstRef(other); } template inline void shallow_copy_array(T *dst, const T *src, const int64_t size) { _DNA_internal_memcpy(dst, src, sizeof(T) * size_t(size)); } /* DNA object initializer which leads to an object which underlying memory is filled with zeroes. */ [[nodiscard]] inline internal::ShallowZeroInitializeTag shallow_zero_initialize() { return internal::ShallowZeroInitializeTag(); } template inline void shallow_swap(T &a, T &b) { _DNA_internal_swap(&a, &b, sizeof(T)); } } // namespace dna } // namespace blender