Skip to content

Commit

Permalink
Merge branch 'pull-request/#989-Packed-unaligned_type' into development
Browse files Browse the repository at this point in the history
# Conflicts:
#	.gitignore
  • Loading branch information
jwellbelove committed Dec 26, 2024
2 parents 56c95b4 + 4f38779 commit 3b54c4e
Show file tree
Hide file tree
Showing 5 changed files with 111 additions and 9 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -391,3 +391,4 @@ test/test_file_list.txt
examples/QueuedMessageRouter/vs2022/.vs/QueuedMessageRouter/CopilotIndices
examples/QueuedMessageRouter/vs2022/.vs/QueuedMessageRouter/FileContentIndex
examples/QueuedMessageRouter/vs2022/.vs/QueuedMessageRouter/v17
test/etl_error_handler/assert_function/build-make
2 changes: 1 addition & 1 deletion include/etl/file_error_numbers.h
Original file line number Diff line number Diff line change
Expand Up @@ -103,5 +103,5 @@ SOFTWARE.
#define ETL_EXPECTED_FILE_ID "70"
#define ETL_ALIGNMENT_FILE_ID "71"
#define ETL_BASE64_FILE_ID "72"

#define ETL_UNALIGNED_TYPE_FILE_ID "73"
#endif
10 changes: 7 additions & 3 deletions include/etl/platform.h
Original file line number Diff line number Diff line change
Expand Up @@ -463,15 +463,19 @@ SOFTWARE.
//*************************************
// Determine if the ETL should use __attribute__((packed).
#if defined(ETL_COMPILER_CLANG) || defined(ETL_COMPILER_GCC) || defined(ETL_COMPILER_INTEL) || defined(ETL_COMPILER_ARM6)
#define ETL_PACKED __attribute__((packed))
#define ETL_PACKED_CLASS(class_type) class __attribute__((packed)) class_type
#define ETL_PACKED_STRUCT(struct_type) struct __attribute__((packed)) struct_type
#define ETL_END_PACKED
#define ETL_HAS_PACKED 1
#elif defined(ETL_COMPILER_MICROSOFT)
#define ETL_PACKED __pragma(pack(push, 1))
#define ETL_PACKED_CLASS(class_type) __pragma(pack(push, 1)) class class_type
#define ETL_PACKED_STRUCT(struct_type) __pragma(pack(push, 1)) struct struct_type
#define ETL_PACKED
#define ETL_END_PACKED __pragma(pack(pop))
#define ETL_HAS_PACKED 1
#else
#define ETL_PACKED
#define ETL_PACKED_CLASS(class_type) class class_type
#define ETL_PACKED_STRUCT(struct_type) struct struct_type
#define ETL_END_PACKED
#define ETL_HAS_PACKED 0
#endif
Expand Down
105 changes: 101 additions & 4 deletions include/etl/unaligned_type.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,19 +41,48 @@ SOFTWARE.
#include "iterator.h"
#include "algorithm.h"
#include "bit.h"
#include "array.h"
#include "exception.h"
#include "file_error_numbers.h"

#include <bit>

#include <string.h>

namespace etl
{
struct unaligned_type_exception : public etl::exception
{
public:

unaligned_type_exception(string_type reason_, string_type file_name_, numeric_type line_number_)
: exception(reason_, file_name_, line_number_)
{
}
};

//***************************************************************************
/// Buffer size exception.
//***************************************************************************
class unaligned_type_buffer_size : public unaligned_type_exception
{
public:

unaligned_type_buffer_size(string_type file_name_, numeric_type line_number_)
: unaligned_type_exception(ETL_ERROR_TEXT("unaligned_type:buffer size", ETL_UNALIGNED_TYPE_FILE_ID"A"), file_name_, line_number_)
{
}
};

namespace private_unaligned_type
{
//*************************************************************************
/// unaligned_type_common
/// Contains all functionality that doesn't require the type.
/// ETL_PACKED ensures that GCC does not complain when used in a packed object.
//*************************************************************************
template <size_t Size_>
class ETL_PACKED unaligned_type_common
ETL_PACKED_CLASS(unaligned_type_common)
{
public:

Expand Down Expand Up @@ -227,7 +256,7 @@ namespace etl
///\tparam Endian The endianness of the arithmetic type.
//*************************************************************************
template <typename T, int Endian_>
class ETL_PACKED unaligned_type : public private_unaligned_type::unaligned_type_common<sizeof(T)>
ETL_PACKED_CLASS(unaligned_type) : public private_unaligned_type::unaligned_type_common<sizeof(T)>
{
public:

Expand All @@ -243,8 +272,8 @@ namespace etl
typedef typename private_unaligned_type::unaligned_type_common<sizeof(T)>::reverse_iterator reverse_iterator;
typedef typename private_unaligned_type::unaligned_type_common<sizeof(T)>::const_reverse_iterator const_reverse_iterator;

static ETL_CONSTANT int Endian = Endian_;
static ETL_CONSTANT size_t Size = private_unaligned_type::unaligned_type_common<sizeof(T)>::Size;
static ETL_CONSTANT int Endian = Endian_;
static ETL_CONSTANT size_t Size = private_unaligned_type::unaligned_type_common<sizeof(T)>::Size;

//*************************************************************************
/// Default constructor
Expand All @@ -261,6 +290,24 @@ namespace etl
unaligned_copy<T>::copy(value, this->storage);
}

//*************************************************************************
/// Construct from an address.
//*************************************************************************
ETL_CONSTEXPR14 unaligned_type(const void* address)
{
etl::copy_n(reinterpret_cast<const char*>(address), sizeof(T), this->storage);
}

//*************************************************************************
/// Construct from an address and size.
//*************************************************************************
ETL_CONSTEXPR14 unaligned_type(const void* address, size_t buffer_size)
{
ETL_ASSERT(sizeof(T) <= buffer_size, ETL_ERROR(etl::unaligned_type_buffer_size));

etl::copy_n(reinterpret_cast<const char*>(address), sizeof(T), this->storage);
}

//*************************************************************************
/// Copy constructor
//*************************************************************************
Expand Down Expand Up @@ -315,6 +362,56 @@ namespace etl
return value;
}

// For run time pointer
static unaligned_type<T, Endian_>& at_address(void* address)
{
//auto p = (::new(address) unaligned_type<T, Endian_>());

//return *p;

return *reinterpret_cast<unaligned_type<T, Endian_>*>(address);
}

// For const run time pointer
static const unaligned_type<T, Endian_>& at_address(const void* address)
{
return *reinterpret_cast<const unaligned_type<T, Endian_>*>(address);
}

// For run time pointer and size
static unaligned_type<T, Endian_>& at_address(void* address, size_t buffer_size)
{
ETL_ASSERT(sizeof(T) <= buffer_size, ETL_ERROR(etl::unaligned_type_buffer_size));

return *reinterpret_cast<unaligned_type<T, Endian_>*>(address);
}

// For const run time pointer and size
static const unaligned_type<T, Endian_>& at_address(const void* address, size_t buffer_size)
{
ETL_ASSERT(sizeof(T) <= buffer_size, ETL_ERROR(etl::unaligned_type_buffer_size));

return *reinterpret_cast<const unaligned_type<T, Endian_>*>(address);
}

// For run time pointer and compile time size
template <size_t Size>
static unaligned_type<T, Endian_>& at_address(void* address)
{
ETL_STATIC_ASSERT(sizeof(T) <= Size, "Buffer size to small for type");

return *reinterpret_cast<unaligned_type<T, Endian_>*>(address);
}

// For const run time pointer and compile time size
template <size_t Size>
static unaligned_type<T, Endian_>& at_address(const void* address)
{
ETL_STATIC_ASSERT(sizeof(T) <= Size, "Buffer size to small for type");

return *reinterpret_cast<const unaligned_type<T, Endian_>*>(address);
}

//*************************************************************************
/// Unaligned copy
//*************************************************************************
Expand Down
2 changes: 1 addition & 1 deletion test/test_utility.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -730,7 +730,7 @@ namespace
uint32_t c = 0x87654321;
};

struct ETL_PACKED Packed
ETL_PACKED_STRUCT(Packed)
{
uint32_t a = 0x12345678;
uint8_t b = 0x9A;
Expand Down

0 comments on commit 3b54c4e

Please sign in to comment.