diff --git a/include/etl/memory.h b/include/etl/memory.h index d7cf6d87..fea4904e 100644 --- a/include/etl/memory.h +++ b/include/etl/memory.h @@ -2286,12 +2286,15 @@ namespace etl /// \return A pointer to the destination. //*************************************************************************** template - typename etl::enable_if::value_type>::value, T*>::type - mem_copy(const T* sb, const T* se, T* db) ETL_NOEXCEPT + T* mem_copy(const T* sb, const T* se, T* db) ETL_NOEXCEPT { - return reinterpret_cast(memcpy(reinterpret_cast(db), - reinterpret_cast(sb), - sizeof(typename etl::iterator_traits::value_type) * static_cast(se - sb))); + ETL_STATIC_ASSERT(etl::is_trivially_copyable::value, "Cannot mem_copy a non trivially copyable type"); + + memcpy(reinterpret_cast(db), + reinterpret_cast(sb), + sizeof(typename etl::iterator_traits::value_type) * static_cast(se - sb)); + + return db; } //*************************************************************************** @@ -2302,12 +2305,15 @@ namespace etl /// \param destination begin //*************************************************************************** template - typename etl::enable_if::value_type>::value, T*>::type - mem_copy(const T* sb, size_t n, T* db) ETL_NOEXCEPT + T* mem_copy(const T* sb, size_t n, T* db) ETL_NOEXCEPT { - return reinterpret_cast(memcpy(reinterpret_cast(db), - reinterpret_cast(sb), - sizeof(typename etl::iterator_traits::value_type) * n)); + ETL_STATIC_ASSERT(etl::is_trivially_copyable::value, "Cannot mem_copy a non trivially copyable type"); + + memcpy(reinterpret_cast(db), + reinterpret_cast(sb), + sizeof(typename etl::iterator_traits::value_type) * n); + + return db; } //*************************************************************************** @@ -2318,12 +2324,15 @@ namespace etl /// \param destination begin //*************************************************************************** template - typename etl::enable_if::value_type>::value, T*>::type - mem_move(const T* sb, const T* se, T* db) ETL_NOEXCEPT + T* mem_move(const T* sb, const T* se, T* db) ETL_NOEXCEPT { - return reinterpret_cast(memmove(reinterpret_cast(db), - reinterpret_cast(sb), - sizeof(typename etl::iterator_traits::value_type) * static_cast(se - sb))); + ETL_STATIC_ASSERT(etl::is_trivially_copyable::value, "Cannot mem_move a non trivially copyable type"); + + memmove(reinterpret_cast(db), + reinterpret_cast(sb), + sizeof(T) * static_cast(se - sb)); + + return db; } //*************************************************************************** @@ -2334,12 +2343,15 @@ namespace etl /// \param destination begin //*************************************************************************** template - typename etl::enable_if::value_type>::value, T*>::type - mem_move(const T* sb, size_t n, T* db) ETL_NOEXCEPT + T* mem_move(const T* sb, size_t n, T* db) ETL_NOEXCEPT { - return reinterpret_cast(memmove(reinterpret_cast(db), - reinterpret_cast(sb), - sizeof(typename etl::iterator_traits::value_type) * n)); + ETL_STATIC_ASSERT(etl::is_trivially_copyable::value, "Cannot mem_move a non trivially copyable type"); + + memmove(reinterpret_cast(db), + reinterpret_cast(sb), + sizeof(typename etl::iterator_traits::value_type) * n); + + return db; } //*************************************************************************** @@ -2348,17 +2360,18 @@ namespace etl /// \param se Source end /// \param db Destination begin /// \return < 0 The first byte that does not match in both memory blocks has a lower value in 'sb' than in 'db' when evaluated as unsigned char values. - /// 0 The contents of both memory blocks are equal - /// > 0 The first byte that does not match in both memory blocks has a greater value in 'sb' than in 'db' when evaluated as unsigned char values. + /// 0 The contents of both memory blocks are equal + /// > 0 The first byte that does not match in both memory blocks has a greater value in 'sb' than in 'db' when evaluated as unsigned char values. //*************************************************************************** template ETL_NODISCARD - typename etl::enable_if::value_type>::value, int>::type - mem_compare(const T* sb, const T* se, const T* db) ETL_NOEXCEPT + int mem_compare(const T* sb, const T* se, const T* db) ETL_NOEXCEPT { + ETL_STATIC_ASSERT(etl::is_trivially_copyable::value, "Cannot mem_compare a non trivially copyable type"); + return memcmp(reinterpret_cast(db), reinterpret_cast(sb), - sizeof(typename etl::iterator_traits::value_type) * static_cast(se - sb)); + sizeof(T) * static_cast(se - sb)); } //*************************************************************************** @@ -2367,49 +2380,64 @@ namespace etl /// \param n Source length /// \param db Destination begin /// \return < 0 The first byte that does not match in both memory blocks has a lower value in 'sb' than in 'db' when evaluated as unsigned char values. - /// 0 The contents of both memory blocks are equal - /// > 0 The first byte that does not match in both memory blocks has a greater value in 'sb' than in 'db' when evaluated as unsigned char values. + /// 0 The contents of both memory blocks are equal + /// > 0 The first byte that does not match in both memory blocks has a greater value in 'sb' than in 'db' when evaluated as unsigned char values. //*************************************************************************** template ETL_NODISCARD - typename etl::enable_if::value_type>::value, int>::type - mem_compare(const T* sb, size_t n, const T* db) ETL_NOEXCEPT + int mem_compare(const T* sb, size_t n, const T* db) ETL_NOEXCEPT { + ETL_STATIC_ASSERT(etl::is_trivially_copyable::value, "Cannot mem_compare a non trivially copyable type"); + return memcmp(reinterpret_cast(db), reinterpret_cast(sb), - sizeof(typename etl::iterator_traits::value_type) * n); + sizeof(T) * n); } //*************************************************************************** /// Template wrapper for memset. /// \param db Destination begin. /// \param de Destination end. - /// \param value The value to set each character of the memory region. + /// \param value The value to set each byte of the memory region. /// \return The destination //*************************************************************************** template - typename etl::enable_if::value_type>::value, TPointer>::type + typename etl::enable_if::value && + !etl::is_const::value && + etl::is_integral::value && + sizeof(T) == 1, TPointer>::type mem_set(TPointer db, const TPointer de, T value) ETL_NOEXCEPT { - return reinterpret_cast(memset(reinterpret_cast(db), - static_cast(value), - sizeof(typename etl::iterator_traits::value_type) * static_cast(de - db))); + ETL_STATIC_ASSERT(etl::is_trivially_copyable::value_type>::value, "Cannot mem_set a non trivially copyable type"); + + memset(reinterpret_cast(db), + static_cast(value), + sizeof(typename etl::iterator_traits::value_type) * static_cast(de - db)); + + return db; } //*************************************************************************** /// Template wrapper for memset. /// \param db Destination begin. /// \param n Destination length. - /// \param value The value to set each character of the memory region. + /// \param value The value to set each byte of the memory region. /// \return The destination //*************************************************************************** template - typename etl::enable_if::value_type>::value, TPointer>::type + typename etl::enable_if::value && + !etl::is_const::value && + etl::is_integral::value && + sizeof(T) == 1, TPointer>::type mem_set(TPointer db, size_t n, T value) ETL_NOEXCEPT { - return reinterpret_cast(memset(reinterpret_cast(db), - static_cast(value), - sizeof(typename etl::iterator_traits::value_type) * n)); + ETL_STATIC_ASSERT(etl::is_trivially_copyable::value_type>::value, "Cannot mem_set a non trivially copyable type"); + + memset(reinterpret_cast(db), + static_cast(value), + sizeof(typename etl::iterator_traits::value_type) * n); + + return db; } //*************************************************************************** @@ -2421,7 +2449,10 @@ namespace etl //*************************************************************************** template ETL_NODISCARD - typename etl::enable_if::value && !etl::is_const::type>::value, char*>::type + typename etl::enable_if::value && + !etl::is_const::type>::value && + etl::is_integral::value && + sizeof(T) == 1, char*>::type mem_char(TPointer sb, TPointer se, T value) ETL_NOEXCEPT { void* result = memchr(reinterpret_cast(sb), @@ -2440,7 +2471,10 @@ namespace etl //*************************************************************************** template ETL_NODISCARD - typename etl::enable_if::value && etl::is_const::type>::value, const char*>::type + typename etl::enable_if::value && + etl::is_const::type>::value && + etl::is_integral::value && + sizeof(T) == 1, const char*>::type mem_char(TPointer sb, TPointer se, T value) ETL_NOEXCEPT { const void* result = memchr(reinterpret_cast(sb), @@ -2459,7 +2493,10 @@ namespace etl //*************************************************************************** template ETL_NODISCARD - typename etl::enable_if::value && !etl::is_const::type>::value, char*>::type + typename etl::enable_if::value && + !etl::is_const::type>::value && + etl::is_integral::value && + sizeof(T) == 1, char*>::type mem_char(TPointer sb, size_t n, T value) ETL_NOEXCEPT { void* result = memchr(reinterpret_cast(sb), @@ -2478,7 +2515,10 @@ namespace etl //*************************************************************************** template ETL_NODISCARD - typename etl::enable_if::value && etl::is_const::type>::value, const char*>::type + typename etl::enable_if::value && + etl::is_const::type>::value && + etl::is_integral::value && + sizeof(T) == 1, const char*>::type mem_char(TPointer sb, size_t n, T value) ETL_NOEXCEPT { const void* result = memchr(reinterpret_cast(sb), diff --git a/test/test_memory.cpp b/test/test_memory.cpp index 9546afef..33bad7e9 100644 --- a/test/test_memory.cpp +++ b/test/test_memory.cpp @@ -1176,9 +1176,9 @@ namespace uint32_t src[8] = { 0x12345678, 0x76543210, 0x01452367, 0x23670145, 0x67234501, 0x45016723, 0x01324576, 0x76453201 }; uint32_t dst[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; - etl::mem_copy(src, src + 8, dst); - + uint32_t* result = etl::mem_copy(src, src + 8, dst); CHECK(std::equal(src, src + 8, dst)); + CHECK(result == dst); } //************************************************************************* @@ -1187,9 +1187,9 @@ namespace const uint32_t src[8] = { 0x12345678, 0x76543210, 0x01452367, 0x23670145, 0x67234501, 0x45016723, 0x01324576, 0x76453201 }; uint32_t dst[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; - etl::mem_copy(src, src + 8, dst); - + uint32_t* result = etl::mem_copy(src, src + 8, dst); CHECK(std::equal(src, src + 8, dst)); + CHECK(result == dst); } //************************************************************************* @@ -1198,8 +1198,9 @@ namespace uint32_t src[8] = { 0x12345678, 0x76543210, 0x01452367, 0x23670145, 0x67234501, 0x45016723, 0x01324576, 0x76453201 }; uint32_t dst[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; - etl::mem_copy(src, 8, dst); + uint32_t* result = etl::mem_copy(src, 8, dst); CHECK(std::equal(src, src + 8, dst)); + CHECK(result == dst); } //************************************************************************* @@ -1208,8 +1209,9 @@ namespace const uint32_t src[8] = { 0x12345678, 0x76543210, 0x01452367, 0x23670145, 0x67234501, 0x45016723, 0x01324576, 0x76453201 }; uint32_t dst[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; - etl::mem_copy(src, 8, dst); + uint32_t* result = etl::mem_copy(src, 8, dst); CHECK(std::equal(src, src + 8, dst)); + CHECK(result == dst); } //************************************************************************* @@ -1218,9 +1220,9 @@ namespace uint32_t expected[8] = { 0x12345678, 0x76543210, 0x01452367, 0x23670145, 0x67234501, 0x45016723, 0x01324576, 0x76453201 }; uint32_t data[12] = { 0x12345678, 0x76543210, 0x01452367, 0x23670145, 0x67234501, 0x45016723, 0x01324576, 0x76453201, 0, 0, 0, 0 }; - etl::mem_move(data, data + 8, data + 4); - + uint32_t* result = etl::mem_move(data, data + 8, data + 4); CHECK(std::equal(expected, expected + 8, data + 4)); + CHECK(result == data + 4); } //************************************************************************* @@ -1231,9 +1233,9 @@ namespace const uint32_t* data_begin = &data[0]; const uint32_t* data_end = &data[8]; - etl::mem_move(data_begin, data_end, data + 4); - + uint32_t* result = etl::mem_move(data_begin, data_end, data + 4); CHECK(std::equal(expected, expected + 8, data + 4)); + CHECK(result == data + 4); } //************************************************************************* @@ -1242,9 +1244,9 @@ namespace uint32_t expected[8] = { 0x12345678, 0x76543210, 0x01452367, 0x23670145, 0x67234501, 0x45016723, 0x01324576, 0x76453201 }; uint32_t data[12] = { 0x12345678, 0x76543210, 0x01452367, 0x23670145, 0x67234501, 0x45016723, 0x01324576, 0x76453201, 0, 0, 0, 0 }; - etl::mem_move(data, 8, data + 4); - + uint32_t* result = etl::mem_move(data, 8, data + 4); CHECK(std::equal(expected, expected + 8, data + 4)); + CHECK(result == data + 4); } //************************************************************************* @@ -1253,9 +1255,10 @@ namespace uint32_t expected[8] = { 0x12345678, 0x76543210, 0x01452367, 0x23670145, 0x67234501, 0x45016723, 0x01324576, 0x76453201 }; uint32_t data[12] = { 0x12345678, 0x76543210, 0x01452367, 0x23670145, 0x67234501, 0x45016723, 0x01324576, 0x76453201, 0, 0, 0, 0 }; const uint32_t* data_begin = &data[0]; - etl::mem_move(data_begin, 8, data + 4); - + + uint32_t* result = etl::mem_move(data_begin, 8, data + 4); CHECK(std::equal(expected, expected + 8, data + 4)); + CHECK(result == data + 4); } //************************************************************************* @@ -1342,7 +1345,7 @@ namespace uint32_t data[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; uint32_t expected[8] = { 0, 0x5A5A5A5A, 0x5A5A5A5A, 0x5A5A5A5A, 0x5A5A5A5A, 0, 0, 0 }; - etl::mem_set(data + 1, data + 5, 0x5A); + etl::mem_set(data + 1, data + 5, (char)0x5A); CHECK(std::equal(expected, expected + 8, data)); } @@ -1353,7 +1356,7 @@ namespace uint32_t data[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; uint32_t expected[8] = { 0, 0x5A5A5A5A, 0x5A5A5A5A, 0x5A5A5A5A, 0x5A5A5A5A, 0, 0, 0 }; - etl::mem_set(data + 1, 4, 0x5A); + etl::mem_set(data + 1, 4, (char)0x5A); CHECK(std::equal(expected, expected + 8, data)); } @@ -1363,8 +1366,8 @@ namespace { uint32_t data[8] = { 0x12345678, 0x76543210, 0x01452367, 0x23670145, 0x67294501, 0x45016723, 0x01324576, 0x76453201 }; - char *p1 = etl::mem_char(data, data + 8, 0x29); - char* p2 = etl::mem_char(data, data + 8, 0x99); + char *p1 = etl::mem_char(data, data + 8, (char)0x29); + char* p2 = etl::mem_char(data, data + 8, (char)0x99); CHECK_EQUAL(uint32_t(0x29), uint32_t(*p1)); CHECK((reinterpret_cast(data) + 18) == p1); @@ -1376,8 +1379,8 @@ namespace { const uint32_t data[8] = { 0x12345678, 0x76543210, 0x01452367, 0x23670145, 0x67294501, 0x45016723, 0x01324576, 0x76453201 }; - const char* p1 = etl::mem_char(data, data + 8, 0x29); - const char* p2 = etl::mem_char(data, data + 8, 0x99); + const char* p1 = etl::mem_char(data, data + 8, (char)0x29); + const char* p2 = etl::mem_char(data, data + 8, (char)0x99); CHECK_EQUAL(uint32_t(0x29), uint32_t(*p1)); CHECK((reinterpret_cast(data) + 18) == p1); @@ -1389,8 +1392,8 @@ namespace { uint32_t data[8] = { 0x12345678, 0x76543210, 0x01452367, 0x23670145, 0x67294501, 0x45016723, 0x01324576, 0x76453201 }; - char* p1 = etl::mem_char(data, 8, 0x29); - char* p2 = etl::mem_char(data, 8, 0x99); + char* p1 = etl::mem_char(data, 8, (char)0x29); + char* p2 = etl::mem_char(data, 8, (char)0x99); CHECK_EQUAL(uint32_t(0x29), uint32_t(*p1)); CHECK((reinterpret_cast(data) + 18) == p1); @@ -1402,8 +1405,8 @@ namespace { const uint32_t data[8] = { 0x12345678, 0x76543210, 0x01452367, 0x23670145, 0x67294501, 0x45016723, 0x01324576, 0x76453201 }; - const char* p1 = etl::mem_char(data, 8, 0x29); - const char* p2 = etl::mem_char(data, 8, 0x99); + const char* p1 = etl::mem_char(data, 8, (char)0x29); + const char* p2 = etl::mem_char(data, 8, (char)0x99); CHECK_EQUAL(uint32_t(0x29), uint32_t(*p1)); CHECK((reinterpret_cast(data) + 18) == p1);