Making DALi public API typesafe using guaranteed types; uint8_t, uint32_t
[platform/core/uifw/dali-core.git] / dali / public-api / common / dali-vector.cpp
index 2b5e42d..31fad54 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -19,8 +19,7 @@
 #include <dali/public-api/common/dali-vector.h>
 
 // EXTERNAL INCLUDES
-#include <stdlib.h>
-#include <memory.h>
+#include <cstring> // for memcpy & memmove
 
 namespace Dali
 {
@@ -36,11 +35,11 @@ VectorBase::~VectorBase()
 
 VectorBase::SizeType VectorBase::Capacity() const
 {
-  SizeType capacity = 0;
+  SizeType capacity = 0u;
   if( mData )
   {
     SizeType* metadata = reinterpret_cast< SizeType* >( mData );
-    capacity = *(metadata - 2);
+    capacity = *(metadata - 2u);
   }
   return capacity;
 }
@@ -52,20 +51,19 @@ void VectorBase::Release()
   {
     // adjust pointer to real beginning
     SizeType* metadata = reinterpret_cast< SizeType* >( mData );
-    // TODO would be nice to memset to a bitpattern to catch illegal use of container after release
-    // but that would require knowledge of the itemsize
-    free( metadata - 2 );
-    mData = 0;
+
+    delete [] ( metadata - 2u );
+    mData = 0u;
   }
 }
 
 void VectorBase::SetCount( SizeType count )
 {
-  // someone can call Resize( 0 ) before ever populating the vector
+  // someone can call Resize( 0u ) before ever populating the vector
   if( mData )
   {
     SizeType* metadata = reinterpret_cast< SizeType* >( mData );
-    *(metadata - 1) = count;
+    *(metadata - 1u) = count;
   }
 }
 
@@ -75,8 +73,10 @@ void VectorBase::Reserve( SizeType capacity, SizeType elementSize )
   SizeType oldCount = Count();
   if( capacity > oldCapacity )
   {
-    const SizeType wholeAllocation = sizeof(SizeType) * 2 + capacity * elementSize;
-    void* wholeData = (void*)malloc( wholeAllocation );
+    const SizeType wholeAllocation = sizeof(SizeType) * 2u + capacity * elementSize;
+    void* wholeData = reinterpret_cast< void* >( new uint8_t[ wholeAllocation ] );
+    DALI_ASSERT_ALWAYS( wholeData && "VectorBase::Reserve - Memory allocation failed" );
+
 #if defined( DEBUG_ENABLED )
     // in debug build this will help identify a vector of uninitialized data
     memset( wholeData, 0xaa, wholeAllocation );
@@ -97,19 +97,16 @@ void VectorBase::Reserve( SizeType capacity, SizeType elementSize )
 
 void VectorBase::Copy( const VectorBase& vector, SizeType elementSize )
 {
-  if( this != &vector )
-  {
-    // release old data
-    Release();
-    // reserve space based on source capacity
-    const SizeType capacity = vector.Capacity();
-    Reserve( capacity, elementSize );
-    // copy over whole data
-    const SizeType wholeAllocation = sizeof(SizeType) * 2 + capacity * elementSize;
-    SizeType* srcData = reinterpret_cast< SizeType* >( vector.mData );
-    SizeType* dstData = reinterpret_cast< SizeType* >( mData );
-    memcpy( dstData - 2, srcData - 2, wholeAllocation );
-  }
+  // release old data
+  Release();
+  // reserve space based on source capacity
+  const SizeType capacity = vector.Capacity();
+  Reserve( capacity, elementSize );
+  // copy over whole data
+  const SizeType wholeAllocation = sizeof(SizeType) * 2u + capacity * elementSize;
+  SizeType* srcData = reinterpret_cast< SizeType* >( vector.mData );
+  SizeType* dstData = reinterpret_cast< SizeType* >( mData );
+  memcpy( dstData - 2u, srcData - 2u, wholeAllocation );
 }
 
 void VectorBase::Swap( VectorBase& vector )
@@ -120,12 +117,50 @@ void VectorBase::Swap( VectorBase& vector )
 
 void VectorBase::Erase( char* address, SizeType elementSize )
 {
-  char* startAddress = address + elementSize;
-  const char* endAddress = reinterpret_cast< char* >( mData ) + Count() * elementSize;
-  SizeType numberOfBytes = endAddress - startAddress;
-  // addresses overlap so use memmove
-  memmove( address, startAddress, numberOfBytes );
-  SetCount( Count() - 1 );
+  // erase can be called on an unallocated vector
+  if( mData )
+  {
+    char* startAddress = address + elementSize;
+    const char* endAddress = reinterpret_cast< char* >( mData ) + Count() * elementSize;
+    SizeType numberOfBytes = endAddress - startAddress;
+    // addresses overlap so use memmove
+    memmove( address, startAddress, numberOfBytes );
+    SetCount( Count() - 1u );
+  }
+}
+
+char* VectorBase::Erase( char* first, char* last, SizeType elementSize )
+{
+  char* next = NULL;
+
+  if( mData )
+  {
+    char* startAddress = last;
+    const char* endAddress = reinterpret_cast< char* >( mData ) + Count() * elementSize;
+    SizeType numberOfBytes = endAddress - startAddress;
+    // addresses overlap so use memmove
+    memmove( first, startAddress, numberOfBytes );
+    SetCount( Count() - ( last - first ) / elementSize );
+
+    next = first;
+  }
+
+  return next;
+}
+
+void VectorBase::CopyMemory( char* destination, const char* source, size_t numberOfBytes )
+{
+  if( ( ( source < destination ) && ( source + numberOfBytes > destination ) ) ||
+      ( ( destination < source ) && ( destination + numberOfBytes > source ) ) )
+  {
+    // If there is overlap, use memmove.
+    memmove( destination, source, numberOfBytes );
+  }
+  else
+  {
+    // It's safe to use memcpy if there isn't overlap.
+    memcpy( destination, source, numberOfBytes );
+  }
 }
 
 } // namespace Dali