Add ref-qualifiers to basic_format_spec (#1292)

* Remove AppVeyor build status badge

Removed AppVeyor build status badge from README.

* Update README.md

* Update CONTRIBUTING.md

Updated the instructions for contributing.

* Fix for issue 1276 "Data corruption in the etl::bip_buffer_spsc_atomic" (#1277)

* Reproduce data corruption bug in the `etl::bip_buffer_spsc_atomic`.

* Fix data corruption bug in the `etl::bip_buffer_spsc_atomic`.

* feat: use ref-qualifiers for basic_format_spec

Converted the l-value methods to ref-qualified and also added r-value ref-qualified methods.

---------

Co-authored-by: John Wellbelove <jwellbelove@users.noreply.github.com>
Co-authored-by: Sergei <sergej.shirokov@gmail.com>
This commit is contained in:
Drew Rife 2026-02-06 04:32:54 -05:00 committed by GitHub
parent 21a1f58299
commit 2a79845dd5
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 232 additions and 34 deletions

View File

@ -36,6 +36,7 @@ SOFTWARE.
#include "platform.h"
#include "type_traits.h"
#include "static_assert.h"
#include "utility.h"
namespace etl
{
@ -206,7 +207,7 @@ namespace etl
//***************************************************************************
/// Default constructor.
//***************************************************************************
ETL_CONSTEXPR basic_format_spec()
ETL_CONSTEXPR basic_format_spec() ETL_NOEXCEPT
: base_(10U)
, width_(0U)
, precision_(0U)
@ -228,7 +229,7 @@ namespace etl
bool left_justified__,
bool boolalpha__,
bool show_base__,
typename TString::value_type fill__)
typename TString::value_type fill__) ETL_NOEXCEPT
: base_(base__)
, width_(width__)
, precision_(precision__)
@ -243,7 +244,7 @@ namespace etl
//***************************************************************************
/// Clears the format spec back to default.
//***************************************************************************
ETL_CONSTEXPR14 void clear()
ETL_CONSTEXPR14 void clear() ETL_NOEXCEPT
{
base_ = 10U;
width_ = 0U;
@ -259,56 +260,93 @@ namespace etl
/// Sets the base.
/// \return A reference to the basic_format_spec.
//***************************************************************************
ETL_CONSTEXPR14 basic_format_spec& base(uint32_t b)
ETL_CONSTEXPR14 basic_format_spec& base(uint32_t b) ETL_LVALUE_REF_QUALIFIER ETL_NOEXCEPT
{
base_ = static_cast<uint_least8_t>(b);
return *this;
}
#if ETL_USING_CPP11
/// @overload
ETL_CONSTEXPR14 basic_format_spec&& base(uint32_t b) ETL_RVALUE_REF_QUALIFIER ETL_NOEXCEPT
{
base_ = static_cast<uint_least8_t>(b);
return etl::move(*this);
}
#endif
//***************************************************************************
/// Sets the base to binary.
/// \return A reference to the basic_format_spec.
//***************************************************************************
ETL_CONSTEXPR14 basic_format_spec& binary()
ETL_CONSTEXPR14 basic_format_spec& binary() ETL_LVALUE_REF_QUALIFIER ETL_NOEXCEPT
{
base(2);
return *this;
return base(2);
}
#if ETL_USING_CPP11
/// @overload
ETL_CONSTEXPR14 basic_format_spec&& binary() ETL_RVALUE_REF_QUALIFIER ETL_NOEXCEPT
{
return etl::move(base(2));
}
#endif
//***************************************************************************
/// Sets the base to octal.
/// \return A reference to the basic_format_spec.
//***************************************************************************
ETL_CONSTEXPR14 basic_format_spec& octal()
ETL_CONSTEXPR14 basic_format_spec& octal() ETL_LVALUE_REF_QUALIFIER ETL_NOEXCEPT
{
base(8);
return *this;
return base(8);
}
#if ETL_USING_CPP11
/// @overload
ETL_CONSTEXPR14 basic_format_spec&& octal() ETL_RVALUE_REF_QUALIFIER ETL_NOEXCEPT
{
return etl::move(base(8));
}
#endif
//***************************************************************************
/// Sets the base to decimal.
/// \return A reference to the basic_format_spec.
//***************************************************************************
ETL_CONSTEXPR14 basic_format_spec& decimal()
ETL_CONSTEXPR14 basic_format_spec& decimal() ETL_LVALUE_REF_QUALIFIER ETL_NOEXCEPT
{
base(10);
return *this;
return base(10);
}
#if ETL_USING_CPP11
/// @overload
ETL_CONSTEXPR14 basic_format_spec&& decimal() ETL_RVALUE_REF_QUALIFIER ETL_NOEXCEPT
{
return etl::move(base(10));
}
#endif
//***************************************************************************
/// Sets the base to hex.
/// \return A reference to the basic_format_spec.
//***************************************************************************
ETL_CONSTEXPR14 basic_format_spec& hex()
ETL_CONSTEXPR14 basic_format_spec& hex() ETL_LVALUE_REF_QUALIFIER ETL_NOEXCEPT
{
base(16);
return *this;
return base(16);
}
#if ETL_USING_CPP11
/// @overload
ETL_CONSTEXPR14 basic_format_spec&& hex() ETL_RVALUE_REF_QUALIFIER ETL_NOEXCEPT
{
return etl::move(base(16));
}
#endif
//***************************************************************************
/// Gets the base.
//***************************************************************************
ETL_CONSTEXPR uint32_t get_base() const
ETL_CONSTEXPR uint32_t get_base() const ETL_NOEXCEPT
{
return base_;
}
@ -317,16 +355,25 @@ namespace etl
/// Sets the show base flag.
/// \return A reference to the basic_format_spec.
//***************************************************************************
ETL_CONSTEXPR14 basic_format_spec& show_base(bool b)
ETL_CONSTEXPR14 basic_format_spec& show_base(bool b) ETL_LVALUE_REF_QUALIFIER ETL_NOEXCEPT
{
show_base_ = b;
return *this;
}
#if ETL_USING_CPP11
/// @overload
ETL_CONSTEXPR14 basic_format_spec&& show_base(bool b) ETL_RVALUE_REF_QUALIFIER ETL_NOEXCEPT
{
show_base_ = b;
return etl::move(*this);
}
#endif
//***************************************************************************
/// Gets the show base flag.
//***************************************************************************
ETL_CONSTEXPR bool is_show_base() const
ETL_CONSTEXPR bool is_show_base() const ETL_NOEXCEPT
{
return show_base_;
}
@ -335,16 +382,25 @@ namespace etl
/// Sets the width.
/// \return A reference to the basic_format_spec.
//***************************************************************************
ETL_CONSTEXPR14 basic_format_spec& width(uint32_t w)
ETL_CONSTEXPR14 basic_format_spec& width(uint32_t w) ETL_LVALUE_REF_QUALIFIER ETL_NOEXCEPT
{
width_ = static_cast<uint_least8_t>(w);
return *this;
}
#if ETL_USING_CPP11
/// @overload
ETL_CONSTEXPR14 basic_format_spec&& width(uint32_t w) ETL_RVALUE_REF_QUALIFIER ETL_NOEXCEPT
{
width_ = static_cast<uint_least8_t>(w);
return etl::move(*this);
}
#endif
//***************************************************************************
/// Gets the width.
//***************************************************************************
ETL_CONSTEXPR uint32_t get_width() const
ETL_CONSTEXPR uint32_t get_width() const ETL_NOEXCEPT
{
return width_;
}
@ -353,16 +409,25 @@ namespace etl
/// Sets the precision.
/// \return A reference to the basic_format_spec.
//***************************************************************************
ETL_CONSTEXPR14 basic_format_spec& precision(uint32_t p)
ETL_CONSTEXPR14 basic_format_spec& precision(uint32_t p) ETL_LVALUE_REF_QUALIFIER ETL_NOEXCEPT
{
precision_ = static_cast<uint_least8_t>(p);
return *this;
}
#if ETL_USING_CPP11
/// @overload
ETL_CONSTEXPR14 basic_format_spec&& precision(uint32_t p) ETL_RVALUE_REF_QUALIFIER ETL_NOEXCEPT
{
precision_ = static_cast<uint_least8_t>(p);
return etl::move(*this);
}
#endif
//***************************************************************************
/// Gets the precision.
//***************************************************************************
ETL_CONSTEXPR uint32_t get_precision() const
ETL_CONSTEXPR uint32_t get_precision() const ETL_NOEXCEPT
{
return precision_;
}
@ -371,16 +436,25 @@ namespace etl
/// Sets the upper case flag.
/// \return A reference to the basic_format_spec.
//***************************************************************************
ETL_CONSTEXPR14 basic_format_spec& upper_case(bool u)
ETL_CONSTEXPR14 basic_format_spec& upper_case(bool u) ETL_LVALUE_REF_QUALIFIER ETL_NOEXCEPT
{
upper_case_ = u;
return *this;
}
#if ETL_USING_CPP11
/// @overload
ETL_CONSTEXPR14 basic_format_spec&& upper_case(bool u) ETL_RVALUE_REF_QUALIFIER ETL_NOEXCEPT
{
upper_case_ = u;
return etl::move(*this);
}
#endif
//***************************************************************************
/// Gets the upper case flag.
//***************************************************************************
ETL_CONSTEXPR bool is_upper_case() const
ETL_CONSTEXPR bool is_upper_case() const ETL_NOEXCEPT
{
return upper_case_;
}
@ -389,16 +463,25 @@ namespace etl
/// Sets the fill character.
/// \return A reference to the basic_format_spec.
//***************************************************************************
ETL_CONSTEXPR14 basic_format_spec& fill(typename TString::value_type c)
ETL_CONSTEXPR14 basic_format_spec& fill(typename TString::value_type c) ETL_LVALUE_REF_QUALIFIER ETL_NOEXCEPT
{
fill_ = c;
return *this;
}
#if ETL_USING_CPP11
/// @overload
ETL_CONSTEXPR14 basic_format_spec&& fill(typename TString::value_type c) ETL_RVALUE_REF_QUALIFIER ETL_NOEXCEPT
{
fill_ = c;
return etl::move(*this);
}
#endif
//***************************************************************************
/// Gets the fill character.
//***************************************************************************
ETL_CONSTEXPR typename TString::value_type get_fill() const
ETL_CONSTEXPR typename TString::value_type get_fill() const ETL_NOEXCEPT
{
return fill_;
}
@ -407,16 +490,25 @@ namespace etl
/// Sets the left justify flag.
/// \return A reference to the basic_format_spec.
//***************************************************************************
ETL_CONSTEXPR14 basic_format_spec& left()
ETL_CONSTEXPR14 basic_format_spec& left() ETL_LVALUE_REF_QUALIFIER ETL_NOEXCEPT
{
left_justified_ = true;
return *this;
}
#if ETL_USING_CPP11
/// @overload
ETL_CONSTEXPR14 basic_format_spec&& left() ETL_RVALUE_REF_QUALIFIER ETL_NOEXCEPT
{
left_justified_ = true;
return etl::move(*this);
}
#endif
//***************************************************************************
/// Gets the left justify flag.
//***************************************************************************
ETL_CONSTEXPR bool is_left() const
ETL_CONSTEXPR bool is_left() const ETL_NOEXCEPT
{
return left_justified_;
}
@ -425,16 +517,25 @@ namespace etl
/// Sets the right justify flag.
/// \return A reference to the basic_format_spec.
//***************************************************************************
ETL_CONSTEXPR14 basic_format_spec& right()
ETL_CONSTEXPR14 basic_format_spec& right() ETL_LVALUE_REF_QUALIFIER ETL_NOEXCEPT
{
left_justified_ = false;
return *this;
}
#if ETL_USING_CPP11
/// @overload
ETL_CONSTEXPR14 basic_format_spec&& right() ETL_RVALUE_REF_QUALIFIER ETL_NOEXCEPT
{
left_justified_ = false;
return etl::move(*this);
}
#endif
//***************************************************************************
/// Gets the right justify flag.
//***************************************************************************
ETL_CONSTEXPR bool is_right() const
ETL_CONSTEXPR bool is_right() const ETL_NOEXCEPT
{
return !left_justified_;
}
@ -443,16 +544,25 @@ namespace etl
/// Sets the bool alpha flag.
/// \return A reference to the basic_format_spec.
//***************************************************************************
ETL_CONSTEXPR14 basic_format_spec& boolalpha(bool b)
ETL_CONSTEXPR14 basic_format_spec& boolalpha(bool b) ETL_LVALUE_REF_QUALIFIER ETL_NOEXCEPT
{
boolalpha_ = b;
return *this;
}
#if ETL_USING_CPP11
/// @overload
ETL_CONSTEXPR14 basic_format_spec&& boolalpha(bool b) ETL_RVALUE_REF_QUALIFIER ETL_NOEXCEPT
{
boolalpha_ = b;
return etl::move(*this);
}
#endif
//***************************************************************************
/// Gets the boolalpha flag.
//***************************************************************************
ETL_CONSTEXPR bool is_boolalpha() const
ETL_CONSTEXPR bool is_boolalpha() const ETL_NOEXCEPT
{
return boolalpha_;
}
@ -481,7 +591,6 @@ namespace etl
}
private:
uint_least8_t base_;
uint_least8_t width_;
uint_least8_t precision_;

View File

@ -368,6 +368,7 @@ SOFTWARE.
#define ETL_ENUM_CLASS(name) enum class name
#define ETL_ENUM_CLASS_TYPE(name, type) enum class name : type
#define ETL_LVALUE_REF_QUALIFIER &
#define ETL_RVALUE_REF_QUALIFIER &&
#if ETL_USING_EXCEPTIONS
#define ETL_NOEXCEPT noexcept
#define ETL_NOEXCEPT_EXPR(...) noexcept(__VA_ARGS__)
@ -393,6 +394,7 @@ SOFTWARE.
#define ETL_ENUM_CLASS(name) enum name
#define ETL_ENUM_CLASS_TYPE(name, type) enum name
#define ETL_LVALUE_REF_QUALIFIER
#define ETL_RVALUE_REF_QUALIFIER
#endif
//*************************************

View File

@ -91,6 +91,93 @@ namespace
CHECK_EQUAL(true, format.is_upper_case());
}
//*************************************************************************
#if ETL_USING_CPP11
TEST(test_format_rvalue_ref_qualifiers)
{
// Test chaining on temporary (rvalue)
auto format = etl::format_spec()
.base(16)
.boolalpha(true)
.fill('*')
.left()
.precision(3)
.show_base(true)
.upper_case(true)
.width(8);
CHECK_EQUAL(16, format.get_base());
CHECK_EQUAL('*', format.get_fill());
CHECK_EQUAL(3, format.get_precision());
CHECK_EQUAL(8, format.get_width());
CHECK_EQUAL(true, format.is_boolalpha());
CHECK_EQUAL(true, format.is_left());
CHECK_EQUAL(false, format.is_right());
CHECK_EQUAL(true, format.is_show_base());
CHECK_EQUAL(true, format.is_upper_case());
}
//*************************************************************************
TEST(test_format_lvalue_ref_qualifiers)
{
// Test chaining on lvalue
etl::format_spec format;
format.hex().boolalpha(true).fill('#').right().precision(5).show_base(false).upper_case(false).width(12);
CHECK_EQUAL(16, format.get_base());
CHECK_EQUAL('#', format.get_fill());
CHECK_EQUAL(5, format.get_precision());
CHECK_EQUAL(12, format.get_width());
CHECK_EQUAL(true, format.is_boolalpha());
CHECK_EQUAL(false, format.is_left());
CHECK_EQUAL(true, format.is_right());
CHECK_EQUAL(false, format.is_show_base());
CHECK_EQUAL(false, format.is_upper_case());
}
//*************************************************************************
TEST(test_format_base_methods)
{
// Test binary
auto format_bin = etl::format_spec().binary().width(8).fill('0');
CHECK_EQUAL(2, format_bin.get_base());
CHECK_EQUAL(8, format_bin.get_width());
CHECK_EQUAL('0', format_bin.get_fill());
// Test octal
auto format_oct = etl::format_spec().octal().width(6);
CHECK_EQUAL(8, format_oct.get_base());
CHECK_EQUAL(6, format_oct.get_width());
// Test decimal
auto format_dec = etl::format_spec().decimal().precision(2);
CHECK_EQUAL(10, format_dec.get_base());
CHECK_EQUAL(2, format_dec.get_precision());
// Test hex
auto format_hex = etl::format_spec().hex().upper_case(true);
CHECK_EQUAL(16, format_hex.get_base());
CHECK_EQUAL(true, format_hex.is_upper_case());
}
//*************************************************************************
TEST(test_format_mixed_lvalue_rvalue)
{
// Create as rvalue, then use as lvalue
auto format = etl::format_spec().hex().width(8);
// Continue chaining on lvalue
format.fill('0').upper_case(true).show_base(true);
CHECK_EQUAL(16, format.get_base());
CHECK_EQUAL('0', format.get_fill());
CHECK_EQUAL(8, format.get_width());
CHECK_EQUAL(true, format.is_upper_case());
CHECK_EQUAL(true, format.is_show_base());
}
#endif
//*************************************************************************
#if ETL_USING_CPP14
TEST(test_format_constexpr)