From 71fee969260bf0bff572c030e00bec67455f06a4 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Emmanuel=20Beno=C3=AEt?= <tseeker@nocternity.net>
Date: Sat, 15 Dec 2018 20:42:39 +0100
Subject: [PATCH] Utilities - Array helpers

A bunch of utility functions to move array data around, based on the
array elements' types.
---
 include/ebcl/Utilities.hh        |  29 +++++++++
 include/ebcl/inline/Utilities.hh | 108 +++++++++++++++++++++++++++++++
 2 files changed, 137 insertions(+)

diff --git a/include/ebcl/Utilities.hh b/include/ebcl/Utilities.hh
index eba08c0..62b6518 100644
--- a/include/ebcl/Utilities.hh
+++ b/include/ebcl/Utilities.hh
@@ -371,6 +371,35 @@ struct T_BigEndian
 };
 
 
+/*= ARRAY COPYING AND MOVING =================================================*/
+
+template<
+	typename Type ,
+	bool IsTrivial = !std::is_class< Type >( )
+> struct T_ArrayHelpers
+{
+	// Default-initialise items in an array
+	static void init( Type* dest , const uint32_t size );
+	// Copy-initialise items in an array
+	static void init( Type* dest , const uint32_t size , Type const& value );
+
+	// Delete items in an array
+	static void destroy( Type* dest , const uint32_t size );
+
+	// Copy array items using copy constructors
+	static void copyNew( Type const* source , Type* dest , const uint32_t size );
+	// Copy array items using assignment operators
+	static void copyAssign( Type const* source , Type* dest , const uint32_t size );
+
+	// Initialise destination items using move constructors
+	static void moveNew( Type* source , Type* dest , const uint32_t size );
+	// Move items using assignments
+	static void moveAssign( Type* source , Type* dest , const uint32_t size );
+	// Move items using move constructors and delete source items
+	static void move( Type* source , Type* dest , const uint32_t size );
+};
+
+
 /*= COMPARATORS AND SORTING ==================================================*/
 
 // F_Comparator< T > - T_Comparator function type
diff --git a/include/ebcl/inline/Utilities.hh b/include/ebcl/inline/Utilities.hh
index e007559..08d8c37 100644
--- a/include/ebcl/inline/Utilities.hh
+++ b/include/ebcl/inline/Utilities.hh
@@ -152,6 +152,114 @@ struct T_BigEndian< T , E_Endian::BIG >
 };
 
 
+/*= ARRAY COPYING AND MOVING =================================================*/
+
+// Array helpers for trivial types
+template< typename T >
+struct T_ArrayHelpers< T , true >
+{
+	static void init( T* dest , const uint32_t size )
+		{ memset( dest , 0 , size * sizeof( T ) ); }
+
+	static void init( T* dest , const uint32_t size , T const& value )
+	{
+		for ( uint32_t i = 0 ; i < size ; i ++ ) {
+			::new ( reinterpret_cast< char* >( &dest[ i ] ) ) T( value );
+		}
+	}
+
+	static void destroy( T* dest , const uint32_t size )
+		{ M_UNUSED( dest ); M_UNUSED( size ); }
+
+	static void copyNew( T const* source , T* dest , const uint32_t size )
+		{ memmove( dest , source , sizeof( T ) * size ); }
+
+	static void copyAssign( T const* source , T* dest , const uint32_t size )
+		{ memmove( dest , source , sizeof( T ) * size ); }
+
+	static void moveNew( T* source , T* dest , const uint32_t size )
+		{ memmove( dest , source , sizeof( T ) * size ); }
+
+	static void moveAssign( T* source , T* dest , const uint32_t size )
+		{ memmove( dest , source , sizeof( T ) * size ); }
+
+	static void move( T* source , T* dest , const uint32_t size )
+		{ memmove( dest , source , sizeof( T ) * size ); }
+};
+
+/*----------------------------------------------------------------------------*/
+
+// Array helpers for non-trivial types
+template< typename T >
+struct T_ArrayHelpers< T , false >
+{
+	static void init( T* dest , const uint32_t size )
+	{
+		for ( uint32_t i = 0 ; i < size ; i ++ ) {
+			::new ( reinterpret_cast< char* >( &dest[ i ] ) ) T( );
+		}
+	}
+
+	static void init( T* dest , const uint32_t size , T const& value )
+	{
+		for ( uint32_t i = 0 ; i < size ; i ++ ) {
+			::new ( reinterpret_cast< char* >( &dest[ i ] ) ) T( value );
+		}
+	}
+
+	// ---------------------------------------------------------------------
+
+	static void destroy( T* dest , const uint32_t size )
+	{
+		for ( uint32_t i = 0 ; i < size ; i ++ ) {
+			dest[ i ].~T( );
+		}
+	}
+
+	// ---------------------------------------------------------------------
+
+	static void copyNew( T const* source , T* dest , const uint32_t size )
+	{
+		for ( uint32_t i = 0 ; i < size ; i ++ ) {
+			::new ( ( char* ) &( dest[ i ] ) ) T( source[ i ] );
+		}
+	}
+
+	static void copyAssign( T const* source , T* dest , const uint32_t size )
+	{
+		for ( uint32_t i = 0 ; i < size ; i ++ ) {
+			dest[ i ] = source[ i ];
+		}
+	}
+
+	// ---------------------------------------------------------------------
+
+	static void moveNew( T* source , T* dest , const uint32_t size )
+	{
+		for ( uint32_t i = 0 ; i < size ; i ++ ) {
+			::new ( reinterpret_cast< char* >( &( dest[ i ] ) ) )
+				T( std::move( source[ i ] ) );
+		}
+	}
+
+	static void moveAssign( T* source , T* dest , const uint32_t size )
+	{
+		for ( uint32_t i = 0 ; i < size ; i ++ ) {
+			dest[ i ] = std::move( source[ i ] );
+		}
+	}
+
+	static void move( T* source , T* dest , const uint32_t size )
+	{
+		for ( uint32_t i = 0 ; i < size ; i ++ ) {
+			::new ( reinterpret_cast< char* >( &( dest[ i ] ) ) )
+				T( std::move( source[ i ] ) );
+			source[ i ].~T( );
+		}
+	}
+};
+
+
 /*= COMPARATORS AND SORTING ==================================================*/
 
 template< typename T >