mirror of
				https://github.com/RGBCube/serenity
				synced 2025-10-31 00:12:44 +00:00 
			
		
		
		
	 f96a3c002a
			
		
	
	
		f96a3c002a
		
	
	
	
	
		
			
			Note that this still keeps the old behaviour of putting things in std by default on serenity so the tools can be happy, but if USING_AK_GLOBALLY is unset, AK behaves like a good citizen and doesn't try to put things in the ::std namespace. std::nothrow_t and its friends get to stay because I'm being told that compilers assume things about them and I can't yeet them into a different namespace...for now.
		
			
				
	
	
		
			87 lines
		
	
	
	
		
			2 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			87 lines
		
	
	
	
		
			2 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| /*
 | |
|  * Copyright (c) 2020, the SerenityOS developers.
 | |
|  *
 | |
|  * SPDX-License-Identifier: BSD-2-Clause
 | |
|  */
 | |
| 
 | |
| #pragma once
 | |
| 
 | |
| #include <AK/Traits.h>
 | |
| 
 | |
| namespace AK {
 | |
| 
 | |
| template<typename T>
 | |
| class TypedTransfer {
 | |
| public:
 | |
|     static void move(T* destination, T* source, size_t count)
 | |
|     {
 | |
|         if (count == 0)
 | |
|             return;
 | |
| 
 | |
|         if constexpr (Traits<T>::is_trivial()) {
 | |
|             __builtin_memmove(destination, source, count * sizeof(T));
 | |
|             return;
 | |
|         }
 | |
| 
 | |
|         for (size_t i = 0; i < count; ++i) {
 | |
|             if (destination <= source)
 | |
|                 new (&destination[i]) T(AK::move(source[i]));
 | |
|             else
 | |
|                 new (&destination[count - i - 1]) T(AK::move(source[count - i - 1]));
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     static size_t copy(T* destination, T const* source, size_t count)
 | |
|     {
 | |
|         if (count == 0)
 | |
|             return 0;
 | |
| 
 | |
|         if constexpr (Traits<T>::is_trivial()) {
 | |
|             if (count == 1)
 | |
|                 *destination = *source;
 | |
|             else
 | |
|                 __builtin_memmove(destination, source, count * sizeof(T));
 | |
|             return count;
 | |
|         }
 | |
| 
 | |
|         for (size_t i = 0; i < count; ++i) {
 | |
|             if (destination <= source)
 | |
|                 new (&destination[i]) T(source[i]);
 | |
|             else
 | |
|                 new (&destination[count - i - 1]) T(source[count - i - 1]);
 | |
|         }
 | |
| 
 | |
|         return count;
 | |
|     }
 | |
| 
 | |
|     static bool compare(T const* a, T const* b, size_t count)
 | |
|     {
 | |
|         if (count == 0)
 | |
|             return true;
 | |
| 
 | |
|         if constexpr (Traits<T>::is_trivial())
 | |
|             return !__builtin_memcmp(a, b, count * sizeof(T));
 | |
| 
 | |
|         for (size_t i = 0; i < count; ++i) {
 | |
|             if (a[i] != b[i])
 | |
|                 return false;
 | |
|         }
 | |
| 
 | |
|         return true;
 | |
|     }
 | |
| 
 | |
|     static void delete_(T* ptr, size_t count)
 | |
|     {
 | |
|         if (count == 0)
 | |
|             return;
 | |
| 
 | |
|         if constexpr (Traits<T>::is_trivial()) {
 | |
|             return;
 | |
|         }
 | |
| 
 | |
|         for (size_t i = 0; i < count; ++i)
 | |
|             ptr[i].~T();
 | |
|     }
 | |
| };
 | |
| 
 | |
| }
 |