Skip to content

Commit

Permalink
Allow compile time CRC calculation (#1016)
Browse files Browse the repository at this point in the history
* Making crc constexpr for c++14. Allows compile time CRC computation.

* Fix syntax when using c++03 or `ETL_FORCE_NO_ADVANCED_CPP`

* Remove use of `ETL_FORCE_NO_ADVANCED_CPP` option since it is no longer used.

---------

Co-authored-by: Zach O'Brien <[email protected]>
Co-authored-by: John Wellbelove <[email protected]>
  • Loading branch information
3 people authored Jan 24, 2025
1 parent 778351a commit 14b50c6
Show file tree
Hide file tree
Showing 50 changed files with 1,610 additions and 21 deletions.
16 changes: 8 additions & 8 deletions include/etl/frame_check_sequence.h
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ namespace etl
//*************************************************************************
/// Default constructor.
//*************************************************************************
frame_check_sequence()
ETL_CONSTEXPR14 frame_check_sequence() : frame_check()
{
reset();
}
Expand All @@ -118,7 +118,7 @@ namespace etl
/// \param end End of the range.
//*************************************************************************
template<typename TIterator>
frame_check_sequence(TIterator begin, const TIterator end)
ETL_CONSTEXPR14 frame_check_sequence(TIterator begin, const TIterator end) : frame_check()
{
ETL_STATIC_ASSERT(sizeof(typename etl::iterator_traits<TIterator>::value_type) == 1, "Type not supported");

Expand All @@ -129,7 +129,7 @@ namespace etl
//*************************************************************************
/// Resets the FCS to the initial state.
//*************************************************************************
void reset()
ETL_CONSTEXPR14 void reset()
{
frame_check = policy.initial();
}
Expand All @@ -140,7 +140,7 @@ namespace etl
/// \param end
//*************************************************************************
template<typename TIterator>
void add(TIterator begin, const TIterator end)
ETL_CONSTEXPR14 void add(TIterator begin, const TIterator end)
{
ETL_STATIC_ASSERT(sizeof(typename etl::iterator_traits<TIterator>::value_type) == 1, "Type not supported");

Expand All @@ -154,31 +154,31 @@ namespace etl
//*************************************************************************
/// \param value The uint8_t to add to the FCS.
//*************************************************************************
void add(uint8_t value_)
ETL_CONSTEXPR14 void add(uint8_t value_)
{
frame_check = policy.add(frame_check, value_);
}

//*************************************************************************
/// Gets the FCS value.
//*************************************************************************
value_type value() const
ETL_CONSTEXPR14 value_type value() const
{
return policy.final(frame_check);
}

//*************************************************************************
/// Conversion operator to value_type.
//*************************************************************************
operator value_type () const
ETL_CONSTEXPR14 operator value_type () const
{
return policy.final(frame_check);
}

//*************************************************************************
/// Gets an add_insert_iterator for input.
//*************************************************************************
add_insert_iterator input()
ETL_CONSTEXPR14 add_insert_iterator input()
{
return add_insert_iterator(*this);
}
Expand Down
53 changes: 40 additions & 13 deletions include/etl/private/crc_implementation.h
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@ namespace etl
// Accumulator_Bits > Chunk_Bits
// Not Reflected
template <typename TAccumulator, size_t Accumulator_Bits, size_t Chunk_Bits, uint8_t Chunk_Mask, bool Reflect>
static
static ETL_CONSTEXPR14
typename etl::enable_if<(Accumulator_Bits > Chunk_Bits) && !Reflect, TAccumulator>::type
crc_update_chunk(TAccumulator crc, uint8_t value, const TAccumulator table[])
{
Expand All @@ -181,7 +181,7 @@ namespace etl
// Accumulator_Bits > Chunk_Bits
// Reflected
template <typename TAccumulator, size_t Accumulator_Bits, size_t Chunk_Bits, uint8_t Chunk_Mask, bool Reflect>
static
static ETL_CONSTEXPR14
typename etl::enable_if<(Accumulator_Bits > Chunk_Bits) && Reflect, TAccumulator>::type
crc_update_chunk(TAccumulator crc, uint8_t value, const TAccumulator table[])
{
Expand All @@ -199,7 +199,7 @@ namespace etl
// Accumulator_Bits == Chunk_Bits
// Not Reflected
template <typename TAccumulator, size_t Accumulator_Bits, size_t Chunk_Bits, uint8_t Chunk_Mask, bool Reflect>
static
static ETL_CONSTEXPR14
typename etl::enable_if<(Accumulator_Bits == Chunk_Bits) && !Reflect, TAccumulator>::type
crc_update_chunk(TAccumulator crc, uint8_t value, const TAccumulator table[])
{
Expand All @@ -216,7 +216,7 @@ namespace etl
// Accumulator_Bits == Chunk_Bits
// Reflected
template <typename TAccumulator, size_t Accumulator_Bits, size_t Chunk_Bits, uint8_t Chunk_Mask, bool Reflect>
static
static ETL_CONSTEXPR14
typename etl::enable_if<(Accumulator_Bits == Chunk_Bits) && Reflect, TAccumulator>::type
crc_update_chunk(TAccumulator crc, uint8_t value, const TAccumulator table[])
{
Expand All @@ -241,16 +241,21 @@ namespace etl
struct crc_table<TAccumulator, Accumulator_Bits, Chunk_Bits, Chunk_Mask, Polynomial, Reflect, 4U>
{
//*************************************************************************
#if !ETL_USING_CPP11
TAccumulator add(TAccumulator crc, uint8_t value) const
{
#endif
static ETL_CONSTANT TAccumulator table[4U] =
{
crc_table_entry<TAccumulator, Accumulator_Bits, Polynomial, Reflect, 0U, Chunk_Bits>::value,
crc_table_entry<TAccumulator, Accumulator_Bits, Polynomial, Reflect, 1U, Chunk_Bits>::value,
crc_table_entry<TAccumulator, Accumulator_Bits, Polynomial, Reflect, 2U, Chunk_Bits>::value,
crc_table_entry<TAccumulator, Accumulator_Bits, Polynomial, Reflect, 3U, Chunk_Bits>::value
};

#if ETL_USING_CPP11
ETL_CONSTEXPR14 TAccumulator add(TAccumulator crc, uint8_t value) const
{
#endif
if ETL_IF_CONSTEXPR(Reflect)
{
crc = crc_update_chunk<TAccumulator, Accumulator_Bits, Chunk_Bits, Chunk_Mask, Reflect>(crc, value, table);
Expand All @@ -269,15 +274,21 @@ namespace etl
return crc;
}
};
#if ETL_USING_CPP11
template <typename TAccumulator, size_t Accumulator_Bits, size_t Chunk_Bits, uint8_t Chunk_Mask, TAccumulator Polynomial, bool Reflect>
ETL_CONSTANT TAccumulator crc_table<TAccumulator, Accumulator_Bits, Chunk_Bits, Chunk_Mask, Polynomial, Reflect, 4U>::table[4U];
#endif

//*********************************
// Table size of 16.
template <typename TAccumulator, size_t Accumulator_Bits, size_t Chunk_Bits, uint8_t Chunk_Mask, TAccumulator Polynomial, bool Reflect>
struct crc_table<TAccumulator, Accumulator_Bits, Chunk_Bits, Chunk_Mask, Polynomial, Reflect, 16U>
{
//*************************************************************************
#if !ETL_USING_CPP11
TAccumulator add(TAccumulator crc, uint8_t value) const
{
#endif
static ETL_CONSTANT TAccumulator table[16U] =
{
crc_table_entry<TAccumulator, Accumulator_Bits, Polynomial, Reflect, 0U, Chunk_Bits>::value,
Expand All @@ -297,7 +308,10 @@ namespace etl
crc_table_entry<TAccumulator, Accumulator_Bits, Polynomial, Reflect, 14U, Chunk_Bits>::value,
crc_table_entry<TAccumulator, Accumulator_Bits, Polynomial, Reflect, 15U, Chunk_Bits>::value
};

#if ETL_USING_CPP11
ETL_CONSTEXPR14 TAccumulator add(TAccumulator crc, uint8_t value) const
{
#endif
if ETL_IF_CONSTEXPR(Reflect)
{
crc = crc_update_chunk<TAccumulator, Accumulator_Bits, Chunk_Bits, Chunk_Mask, Reflect>(crc, value, table);
Expand All @@ -312,16 +326,22 @@ namespace etl
return crc;
}
};
#if ETL_USING_CPP11
template <typename TAccumulator, size_t Accumulator_Bits, size_t Chunk_Bits, uint8_t Chunk_Mask, TAccumulator Polynomial, bool Reflect>
ETL_CONSTANT TAccumulator crc_table<TAccumulator, Accumulator_Bits, Chunk_Bits, Chunk_Mask, Polynomial, Reflect, 16U>::table[16U];
#endif

//*********************************
// Table size of 256.
template <typename TAccumulator, size_t Accumulator_Bits, size_t Chunk_Bits, uint8_t Chunk_Mask, TAccumulator Polynomial, bool Reflect>
struct crc_table<TAccumulator, Accumulator_Bits, Chunk_Bits, Chunk_Mask, Polynomial, Reflect, 256U>
{
//*************************************************************************
#if !ETL_USING_CPP11
TAccumulator add(TAccumulator crc, uint8_t value) const
{
static ETL_CONSTANT TAccumulator table[256U] =
#endif
static ETL_CONSTANT TAccumulator table[256U]=
{
crc_table_entry<TAccumulator, Accumulator_Bits, Polynomial, Reflect, 0U, Chunk_Bits>::value,
crc_table_entry<TAccumulator, Accumulator_Bits, Polynomial, Reflect, 1U, Chunk_Bits>::value,
Expand Down Expand Up @@ -580,13 +600,20 @@ namespace etl
crc_table_entry<TAccumulator, Accumulator_Bits, Polynomial, Reflect, 254U, Chunk_Bits>::value,
crc_table_entry<TAccumulator, Accumulator_Bits, Polynomial, Reflect, 255U, Chunk_Bits>::value
};
#if ETL_USING_CPP11
ETL_CONSTEXPR14 TAccumulator add(TAccumulator crc, uint8_t value) const
{
#endif

crc = crc_update_chunk<TAccumulator, Accumulator_Bits, Chunk_Bits, Chunk_Mask, Reflect>(crc, value, table);

return crc;
}
};

#if ETL_USING_CPP11
template <typename TAccumulator, size_t Accumulator_Bits, size_t Chunk_Bits, uint8_t Chunk_Mask, TAccumulator Polynomial, bool Reflect>
ETL_CONSTANT TAccumulator crc_table<TAccumulator, Accumulator_Bits, Chunk_Bits, Chunk_Mask, Polynomial, Reflect, 256U>::table[256U];
#endif
//*****************************************************************************
// CRC Policies.
//*****************************************************************************
Expand Down Expand Up @@ -615,7 +642,7 @@ namespace etl
}

//*************************************************************************
accumulator_type final(accumulator_type crc) const
ETL_CONSTEXPR accumulator_type final(accumulator_type crc) const
{
return crc ^ TCrcParameters::Xor_Out;
}
Expand Down Expand Up @@ -643,7 +670,7 @@ namespace etl
}

//*************************************************************************
accumulator_type final(accumulator_type crc) const
ETL_CONSTEXPR accumulator_type final(accumulator_type crc) const
{
return crc ^ TCrcParameters::Xor_Out;
}
Expand Down Expand Up @@ -671,7 +698,7 @@ namespace etl
}

//*************************************************************************
accumulator_type final(accumulator_type crc) const
ETL_CONSTEXPR accumulator_type final(accumulator_type crc) const
{
return crc ^ TCrcParameters::Xor_Out;
}
Expand All @@ -691,7 +718,7 @@ namespace etl
//*************************************************************************
/// Default constructor.
//*************************************************************************
crc_type()
ETL_CONSTEXPR14 crc_type()
{
this->reset();
}
Expand All @@ -702,7 +729,7 @@ namespace etl
/// \param end End of the range.
//*************************************************************************
template<typename TIterator>
crc_type(TIterator begin, const TIterator end)
ETL_CONSTEXPR14 crc_type(TIterator begin, const TIterator end)
{
this->reset();
this->add(begin, end);
Expand Down
22 changes: 22 additions & 0 deletions test/test_crc16.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,17 @@ namespace
CHECK_EQUAL(0xBB3DU, crc);
}

#if ETL_USING_CPP14
//*************************************************************************
TEST(test_crc16_16_constexpr)
{
constexpr char data[] = "123456789";
constexpr uint16_t crc = etl::crc16_t16(data, data + 9);

CHECK_EQUAL(0xBB3DU, crc);
}
#endif

//*************************************************************************
TEST(test_crc16_16_add_values)
{
Expand Down Expand Up @@ -199,6 +210,17 @@ namespace
CHECK_EQUAL(0xBB3DU, crc);
}

#if ETL_USING_CPP14
//*************************************************************************
TEST(test_crc16_4_constexpr)
{
constexpr char data[] = "123456789";
constexpr uint16_t crc = etl::crc16_t4(data, data + 9);

CHECK_EQUAL(0xBB3DU, crc);
}
#endif

//*************************************************************************
TEST(test_crc16_4_add_values)
{
Expand Down
33 changes: 33 additions & 0 deletions test/test_crc16_a.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,17 @@ namespace
CHECK_EQUAL(0xBF05U, crc);
}

#if ETL_USING_CPP14
//*************************************************************************
TEST(test_crc16_a_constexpr)
{
constexpr char data[] = "123456789";
constexpr uint16_t crc = etl::crc16_a(data, data + 9);

CHECK_EQUAL(0xBF05U, crc);
}
#endif

//*************************************************************************
TEST(test_crc16_a_add_values)
{
Expand Down Expand Up @@ -127,6 +138,17 @@ namespace
CHECK_EQUAL(0xBF05U, crc);
}

#if ETL_USING_CPP14
//*************************************************************************
TEST(test_crc16_a_16_constexpr)
{
constexpr char data[] = "123456789";
constexpr uint16_t crc = etl::crc16_a_t16(data, data + 9);

CHECK_EQUAL(0xBF05U, crc);
}
#endif

//*************************************************************************
TEST(test_crc16_a_16_add_values)
{
Expand Down Expand Up @@ -199,6 +221,17 @@ namespace
CHECK_EQUAL(0xBF05U, crc);
}

#if ETL_USING_CPP14
//*************************************************************************
TEST(test_crc16_a_4_constexpr)
{
constexpr char data[] = "123456789";
constexpr uint16_t crc = etl::crc16_a_t4(data, data + 9);

CHECK_EQUAL(0xBF05U, crc);
}
#endif

//*************************************************************************
TEST(test_crc16_a_4_add_values)
{
Expand Down
33 changes: 33 additions & 0 deletions test/test_crc16_arc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,17 @@ namespace
CHECK_EQUAL(0xBB3DU, crc);
}

#if ETL_USING_CPP14
//*************************************************************************
TEST(test_crc16_arc_constexpr)
{
constexpr char data[] = "123456789";
constexpr uint16_t crc = etl::crc16_arc(data, data + 9);

CHECK_EQUAL(0xBB3DU, crc);
}
#endif

//*************************************************************************
TEST(test_crc16_arc_add_values)
{
Expand Down Expand Up @@ -127,6 +138,17 @@ namespace
CHECK_EQUAL(0xBB3DU, crc);
}

#if ETL_USING_CPP14
//*************************************************************************
TEST(test_crc16_arc_16_constexpr)
{
constexpr char data[] = "123456789";
constexpr uint16_t crc = etl::crc16_arc_t16(data, data + 9);

CHECK_EQUAL(0xBB3DU, crc);
}
#endif

//*************************************************************************
TEST(test_crc16_arc_16_add_values)
{
Expand Down Expand Up @@ -199,6 +221,17 @@ namespace
CHECK_EQUAL(0xBB3DU, crc);
}

#if ETL_USING_CPP14
//*************************************************************************
TEST(test_crc16_arc_4_constexpr)
{
constexpr char data[] = "123456789";
constexpr uint16_t crc = etl::crc16_arc_t4(data, data + 9);

CHECK_EQUAL(0xBB3DU, crc);
}
#endif

//*************************************************************************
TEST(test_crc16_arc_4_add_values)
{
Expand Down
Loading

0 comments on commit 14b50c6

Please sign in to comment.