31#ifndef ETL_FORMAT_INCLUDED
32#define ETL_FORMAT_INCLUDED
51#if ETL_USING_FORMAT_FLOATING_POINT
59 class format_exception :
public etl::exception
63 format_exception(string_type reason_, string_type file_name_, numeric_type line_number_)
64 : exception(reason_, file_name_, line_number_)
69 class bad_format_string_exception :
public etl::format_exception
73 bad_format_string_exception(string_type file_name_, numeric_type line_number_)
74 : etl::format_exception(ETL_ERROR_TEXT(
"format:bad", ETL_FORMAT_FILE_ID
"A"), file_name_, line_number_)
79 template <
class... Args>
80 ETL_CONSTEXPR14
bool check_f(
const char* fmt)
89 inline void please_note_this_is_error_message_1() noexcept {}
91 template <
class... Args>
92 struct basic_format_string
94 inline ETL_CONSTEVAL basic_format_string(
const char* fmt)
97 bool format_string_ok = check_f(fmt);
99 if (!format_string_ok)
108 ETL_ASSERT_FAIL_AND_RETURN(ETL_ERROR(bad_format_string_exception));
113 ETL_CONSTEXPR basic_format_string(
const basic_format_string& other) =
default;
114 ETL_CONSTEXPR14 basic_format_string& operator=(
const basic_format_string& other) =
default;
116 ETL_CONSTEXPR string_view
get()
const
126 template <
class... Args>
127 using format_string = basic_format_string<type_identity_t<Args>...>;
136 using supported_format_types = etl::variant<
etl::monostate, bool, char, int,
unsigned int,
long long int,
unsigned long long int,
137 #if ETL_USING_FORMAT_FLOATING_POINT
138 float, double,
long double,
140 const char*, etl::string_view,
const void*
144 template <
class CharT>
145 class basic_format_parse_context
149 using iterator = string_view::const_iterator;
150 using const_iterator = string_view::const_iterator;
151 using char_type = CharT;
153 basic_format_parse_context(etl::string_view fmt,
size_t n_args = 0)
157 , automatic_mode(false)
162 basic_format_parse_context<CharT>& operator=(
const basic_format_parse_context&) =
delete;
164 iterator
begin() const noexcept
166 return range.begin();
169 iterator
end() const noexcept
174 ETL_CONSTEXPR14
void advance_to(iterator pos)
176 range = etl::string_view(pos, range.end());
179 ETL_CONSTEXPR14
size_t next_arg_id()
182 ETL_ASSERT(manual_mode ==
false, ETL_ERROR(bad_format_string_exception));
183 automatic_mode =
true;
185 ETL_ASSERT(current < num_args, ETL_ERROR(bad_format_string_exception) );
189 ETL_CONSTEXPR14
void check_arg_id(
size_t id)
193 ETL_ASSERT(automatic_mode ==
false, ETL_ERROR(bad_format_string_exception));
195 ETL_ASSERT(
id < num_args, ETL_ERROR(bad_format_string_exception) );
200 etl::string_view range;
206 template <
class,
class>
207 friend struct formatter;
210 using format_parse_context = basic_format_parse_context<char>;
212 template <
class Context>
213 class basic_format_arg
221 void format(etl::basic_format_parse_context<char>& , Context& )
232 typedef void (*function_type)(etl::basic_format_parse_context<char>&, Context&,
const void*);
236 basic_format_arg() {}
238 basic_format_arg(
const bool v)
243 basic_format_arg(
const int v)
248 basic_format_arg(
const short v)
249 :
data(static_cast<int>(v))
253 basic_format_arg(
const unsigned short v)
254 :
data(static_cast<unsigned int>(v))
258 basic_format_arg(
const long int v)
259 :
data(static_cast<long long int>(v))
263 basic_format_arg(
const unsigned int v)
268 basic_format_arg(
const long long int v)
273 basic_format_arg(
const unsigned long long int v)
280 basic_format_arg(
const unsigned long v)
281 :
data(static_cast<unsigned long long int>(v))
285 basic_format_arg(
const char* v)
290 basic_format_arg(
char v)
295 basic_format_arg(
const signed char v)
296 :
data(static_cast<char>(v))
300 basic_format_arg(
const unsigned char v)
301 :
data(static_cast<char>(v))
305 #if ETL_USING_FORMAT_FLOATING_POINT
306 basic_format_arg(
const float v)
311 basic_format_arg(
const double v)
316 basic_format_arg(
const long double v)
322 basic_format_arg(
const etl::string_view v)
327 basic_format_arg(
const etl::ibasic_string<char>& v)
332 basic_format_arg(
const basic_format_arg& other)
337 basic_format_arg(
const void* v)
342 basic_format_arg& operator=(
const basic_format_arg& other)
348 explicit operator bool()
const
350 return !etl::holds_alternative<etl::monostate>(data);
353 template <
class R,
class Visitor>
354 R visit(Visitor&& vis)
356 return etl::visit(etl::forward<Visitor>(vis), data);
361 supported_format_types
data;
364 template <
class Context,
class... Args>
365 class format_arg_store
369 format_arg_store(Args&... args)
374 basic_format_arg<Context>
get(
size_t i)
const
379 etl::array_view<basic_format_arg<Context>>
get()
386 etl::array<basic_format_arg<Context>,
sizeof...(Args)> _args;
389 template <
class Context>
390 class basic_format_args
394 template <
class... Args>
395 basic_format_args(format_arg_store<Context, Args...>& store)
400 basic_format_args(
const basic_format_args<Context>& other)
405 basic_format_args& operator=(
const basic_format_args<Context>& other)
411 basic_format_arg<Context>
get(
size_t i)
const
424 etl::array_view<basic_format_arg<Context>> _args;
427 namespace private_format
429 using char_type = char;
431 enum class spec_align_t
439 enum class spec_sign_t
448 etl::optional<size_t> index{etl::nullopt_t()};
449 spec_align_t align{spec_align_t::NONE};
451 spec_sign_t sign{spec_sign_t::MINUS};
454 etl::optional<size_t> width{etl::nullopt_t()};
455 bool width_nested_replacement{
false};
456 etl::optional<size_t> precision{etl::nullopt_t()};
458 bool precision_nested_replacement{
false};
459 bool locale_specific{
false};
460 etl::optional<char> type{etl::nullopt_t()};
464 template <
class OutputIt,
class CharT>
465 class basic_format_context
469 using iterator = OutputIt;
470 using char_type = CharT;
472 basic_format_context(
const basic_format_context& other)
474 , _format_args(other._format_args)
478 basic_format_context(OutputIt it, basic_format_args<basic_format_context>& fmt_args)
480 , _format_args(fmt_args)
484 basic_format_context& operator=(
const basic_format_context&) =
delete;
486 basic_format_arg<basic_format_context> arg(
size_t id)
const
488 return _format_args.get(
id);
496 void advance_to(iterator it)
501 private_format::format_spec_t format_spec;
506 basic_format_args<basic_format_context>& _format_args;
509 template <
class OutputIt>
510 using format_context = basic_format_context<OutputIt, char>;
512 template <
class OutputIt>
513 using format_args = basic_format_args<format_context<OutputIt>>;
515 template <
class OutputIt>
516 using format_arg = basic_format_arg<format_context<OutputIt>>;
518 template <
class OutputIt,
class Context = format_context<OutputIt>,
class... Args>
519 format_arg_store<Context, Args...> make_format_args(Args&... args)
521 return format_arg_store<Context, Args...>(args...);
524 namespace private_format
526 inline bool is_digit(
const char c)
528 return c >=
'0' && c <=
'9';
531 inline void advance(format_parse_context& parse_ctx)
533 parse_ctx.advance_to(parse_ctx.begin() + 1);
536 inline etl::optional<size_t> parse_num(format_parse_context& parse_ctx)
538 etl::optional<size_t> result;
539 auto fmt_it = parse_ctx.begin();
540 while (fmt_it != parse_ctx.end())
542 const char c = *fmt_it;
545 size_t old_value = result.value_or(0);
546 size_t new_value = old_value * 10 +
static_cast<size_t>(c -
'0');
547 if (new_value < old_value)
550 ETL_ASSERT_FAIL(ETL_ERROR(bad_format_string_exception));
560 if (result.has_value())
562 parse_ctx.advance_to(fmt_it);
567 inline etl::optional<char> parse_any_of(format_parse_context& parse_ctx, etl::string_view chars)
569 etl::optional<char> result;
570 auto fmt_it = parse_ctx.
begin();
571 if (fmt_it != parse_ctx.end())
573 const char c = *fmt_it;
574 auto it = etl::find(chars.
cbegin(), chars.cend(), c);
575 if (it != chars.cend())
579 parse_ctx.advance_to(fmt_it);
585 inline bool parse_char(format_parse_context& parse_ctx,
char c)
587 auto fmt_it = parse_ctx.
begin();
588 if (fmt_it != parse_ctx.end())
590 char value = *fmt_it;
594 parse_ctx.advance_to(fmt_it);
601 inline bool parse_sequence(format_parse_context& parse_ctx, etl::string_view sequence)
603 auto fmt_it = parse_ctx.begin();
604 if (etl::equal(sequence.
cbegin(), sequence.cend(), fmt_it))
606 fmt_it += sequence.
size();
607 parse_ctx.advance_to(fmt_it);
613 inline bool is_align_character(
char c)
615 return c ==
'<' || c ==
'>' || c ==
'^';
618 inline spec_align_t align_from_char(
char c)
620 spec_align_t result = spec_align_t::NONE;
623 case '<': result = spec_align_t::START;
break;
624 case '>': result = spec_align_t::END;
break;
625 case '^': result = spec_align_t::CENTER;
break;
628 ETL_ASSERT_FAIL(ETL_ERROR(bad_format_string_exception));
633 inline spec_align_t parse_fill_and_align(format_parse_context& parse_ctx, char_type& fill)
635 spec_align_t result = spec_align_t::NONE;
638 auto fmt_it = parse_ctx.begin();
639 if (fmt_it != parse_ctx.end())
641 const char c = *fmt_it;
644 if (is_align_character(c))
646 result = align_from_char(c);
647 parse_ctx.advance_to(fmt_it);
649 else if (fmt_it != parse_ctx.end())
651 const char c2 = *fmt_it;
653 if (is_align_character(c2))
655 result = align_from_char(c2);
657 ETL_ERROR(bad_format_string_exception));
660 parse_ctx.advance_to(fmt_it);
671 inline spec_sign_t sign_from_char(
const char c)
673 spec_sign_t result = spec_sign_t::MINUS;
676 case '-': result = spec_sign_t::MINUS;
break;
677 case '+': result = spec_sign_t::PLUS;
break;
678 case ' ': result = spec_sign_t::SPACE;
break;
681 ETL_ASSERT_FAIL(ETL_ERROR(bad_format_string_exception));
686 inline bool parse_nested_replacement(format_parse_context& parse_ctx, etl::optional<size_t>& index)
688 bool start = parse_char(parse_ctx,
'{');
691 auto num = parse_num(parse_ctx);
696 parse_ctx.check_arg_id(*index);
697 bool end = parse_char(parse_ctx,
'}');
705 ETL_ASSERT_FAIL(ETL_ERROR(bad_format_string_exception));
710 bool end = parse_char(parse_ctx,
'}');
713 index = parse_ctx.next_arg_id();
719 ETL_ASSERT_FAIL(ETL_ERROR(bad_format_string_exception));
726 template <
class OutputIt>
727 void parse_format_spec(format_parse_context& parse_ctx, format_context<OutputIt>& fmt_context)
729 auto& format_spec = fmt_context.format_spec;
731 format_spec = format_spec_t();
733 format_spec.index = parse_num(parse_ctx);
735 bool colon = parse_char(parse_ctx,
':');
738 format_spec.align = parse_fill_and_align(parse_ctx, format_spec.
fill);
740 etl::optional<char> sign = parse_any_of(parse_ctx,
"+- ");
743 format_spec.sign = sign_from_char(*sign);
746 format_spec.hash = parse_char(parse_ctx,
'#');
747 format_spec.zero = parse_char(parse_ctx,
'0');
749 format_spec.
width = parse_num(parse_ctx);
750 if (!format_spec.
width)
753 format_spec.width_nested_replacement = parse_nested_replacement(parse_ctx, format_spec.
width);
756 if (parse_char(parse_ctx,
'.'))
758 format_spec.
precision = parse_num(parse_ctx);
762 format_spec.precision_nested_replacement = parse_nested_replacement(parse_ctx, format_spec.
precision);
766 format_spec.locale_specific = parse_char(parse_ctx,
'L');
768 format_spec.type = parse_any_of(parse_ctx,
"s?bBcdoxXaAeEfFgGpP");
773 template <
class T,
class CharT =
char>
776 using char_type = CharT;
782 format_parse_context::iterator parse(format_parse_context& parse_ctx)
784 return parse_ctx.end();
787 template <
class OutputIt>
788 typename format_context<OutputIt>::iterator format(
etl::monostate arg, format_context<OutputIt>& fmt_ctx)
791 return fmt_ctx.out();
795 namespace private_format
798 template <typename UnsignedT, typename = etl::enable_if_t<etl::is_unsigned<UnsignedT>::value>>
799 UnsignedT get_highest_digit(UnsignedT value,
size_t base = 10)
801 ETL_ASSERT(base > 1, ETL_ERROR(bad_format_string_exception));
802 UnsignedT result = 1;
804 while (result <= value)
811 template <
typename T>
812 T int_pow(T base, T exp)
825 template <
typename OutputIt,
typename T>
826 void format_sign(OutputIt& it, T value,
const format_spec_t& spec)
837 case spec_sign_t::MINUS:
840 case spec_sign_t::PLUS: c =
'+';
break;
841 case spec_sign_t::SPACE: c =
' ';
break;
844 ETL_ASSERT_FAIL(ETL_ERROR(bad_format_string_exception));
855 template <
typename OutputIt>
856 void format_sequence(OutputIt& out_it, etl::string_view value)
859 while (it != value.cend())
867 template <
typename OutputIt,
typename T>
868 void format_alternate_form(OutputIt& it,
const format_spec_t& spec)
870 if (spec.hash && spec.type.has_value())
872 switch (spec.type.value())
874 case 'b': format_sequence(it,
"0b");
break;
875 case 'B': format_sequence(it,
"0B");
break;
876 case 'o': format_sequence(it,
"0");
break;
877 case 'x': format_sequence(it,
"0x");
break;
879 format_sequence(it,
"0X");
886 template <
typename OutputIt>
887 void format_plain_char(OutputIt& it, char_type c)
893 template <
typename OutputIt>
894 void format_escaped_char(OutputIt& it, char_type c)
898 case '\t': format_sequence(it,
"\\t");
break;
899 case '\n': format_sequence(it,
"\\n");
break;
900 case '\r': format_sequence(it,
"\\r");
break;
901 case '"': format_sequence(it,
"\\\"");
break;
902 case '\'': format_sequence(it,
"\\'");
break;
903 case '\\': format_sequence(it,
"\\\\");
break;
904 default: *it = c; ++it;
908 template <
typename OutputIt>
909 void fill(OutputIt& it,
size_t size, char_type c)
919 template <
size_t default_base = 10>
920 inline size_t base_from_spec(
const format_spec_t& spec)
922 size_t base = default_base;
923 if (spec.type.has_value())
925 switch (spec.type.value())
928 case 'A': base = 16;
break;
930 case 'B': base = 2;
break;
931 case 'o': base = 8;
break;
944 inline bool is_uppercase(
const char c)
946 return c >=
'A' && c <=
'Z';
949 template <
typename OutputIt,
typename T>
950 void format_digit_char(OutputIt& it, T value,
const format_spec_t& spec)
954 *it =
static_cast<char_type
>(
'0' +
static_cast<typename etl::make_unsigned<T>::type
>(value));
958 if (spec.type.has_value() && is_uppercase(spec.type.value()))
960 *it =
static_cast<char_type
>(
'A' +
static_cast<typename etl::make_unsigned<T>::type
>(value - 10));
964 *it =
static_cast<char_type
>(
'a' +
static_cast<typename etl::make_unsigned<T>::type
>(value - 10));
970 inline void adjust_width_from_spec(
const format_spec_t& spec,
size_t& width)
972 if (spec.zero && spec.width.has_value())
974 width = etl::max(width, spec.width.value());
978 inline void check_precision(
const format_spec_t& spec)
980 if (spec.precision.has_value())
983 ETL_ASSERT_FAIL(ETL_ERROR(bad_format_string_exception));
990 template <
typename OutputIt,
typename T, T default_base = 10,
bool skip_last_zeros = false>
991 void format_plain_num(OutputIt& it, T value,
const format_spec_t& spec,
size_t width = 0)
993 using UnsignedT =
typename etl::make_unsigned<T>::type;
995 UnsignedT unsigned_value = etl::absolute_unsigned(value);
997 size_t base = base_from_spec<default_base>(spec);
998 UnsignedT highest_digit = get_highest_digit<UnsignedT>(unsigned_value, base);
1001 UnsignedT align_highest_digit = int_pow<UnsignedT>(base, width - 1);
1002 highest_digit = etl::max<UnsignedT>(align_highest_digit, highest_digit);
1006 while (highest_digit > 0)
1008 UnsignedT digit = unsigned_value / highest_digit;
1009 unsigned_value %= highest_digit;
1010 format_digit_char(it, digit, spec);
1012 if ETL_IF_CONSTEXPR (skip_last_zeros)
1014 if (unsigned_value == 0)
1020 highest_digit /= base;
1025 template <
typename OutputIt,
typename T,
bool skip_last_zeros = false>
1026 void format_num(OutputIt& it, T value,
const format_spec_t& spec)
1029 format_sign<OutputIt, T>(it, value, spec);
1030 format_alternate_form<OutputIt, T>(it, spec);
1031 adjust_width_from_spec(spec, width);
1032 check_precision(spec);
1033 format_plain_num(it, value, spec, width);
1036 #if ETL_USING_FORMAT_FLOATING_POINT
1037 template <
typename OutputIt,
typename T>
1038 void format_floating_default(OutputIt& it, T value,
const format_spec_t& spec)
1040 const size_t fractional_decimals = 6;
1043 T fractional = modf(value, &integral);
1045 unsigned long long int fractional_int;
1046 unsigned long long int integral_int;
1050 fractional_int =
static_cast<unsigned long long int>(-fractional * pow(10., fractional_decimals));
1051 integral_int =
static_cast<unsigned long long int>(-integral);
1056 fractional_int =
static_cast<unsigned long long int>(fractional * pow(10., fractional_decimals));
1057 integral_int =
static_cast<unsigned long long int>(integral);
1060 private_format::format_sign<OutputIt, int>(it, sign ? -1 : 0, spec);
1061 private_format::format_plain_num<OutputIt, unsigned long long int>(it, integral_int, spec);
1062 private_format::format_sequence<OutputIt>(it,
".");
1063 private_format::format_plain_num<OutputIt, unsigned long long int, 10, true>(it, fractional_int, spec, fractional_decimals);
1067 template <
typename OutputIt,
typename T>
1068 void format_floating_a(OutputIt& it, T value,
const format_spec_t& spec)
1070 static const size_t fractional_decimals = 10;
1071 static const size_t exponent_decimals = 1;
1072 long long int exponent_int = 0;
1075 unsigned long long int fractional_int;
1076 unsigned long long int integral_int;
1079 T fractional = modf(value, &integral);
1081 while (value >= 0x10 || value <= -0x10)
1085 fractional = modf(value, &integral);
1088 while ((value > 0.0000000000001 && value < 1) || (value < -0.0000000000001 && value > -1))
1092 fractional = modf(value, &integral);
1098 fractional_int =
static_cast<unsigned long long int>(-fractional * pow(
static_cast<T
>(0x10), fractional_decimals));
1099 integral_int =
static_cast<unsigned long long int>(-integral);
1104 fractional_int =
static_cast<unsigned long long int>(fractional * pow(
static_cast<T
>(0x10), fractional_decimals));
1105 integral_int =
static_cast<unsigned long long int>(integral);
1108 private_format::format_sign<OutputIt, int>(it, sign ? -1 : 0, spec);
1109 private_format::format_plain_char<OutputIt>(it,
'0');
1110 char hex_letter =
'x';
1111 if (is_uppercase(spec.type.value()))
1115 private_format::format_plain_char<OutputIt>(it, hex_letter);
1116 private_format::format_plain_num<OutputIt, unsigned long long int, 16>(it, integral_int, spec);
1117 private_format::format_plain_char<OutputIt>(it,
'.');
1118 private_format::format_plain_num<OutputIt, unsigned long long int, 16, true>(it, fractional_int, spec, fractional_decimals);
1120 if (is_uppercase(spec.type.value()))
1124 private_format::format_plain_char<OutputIt>(it, letter);
1125 private_format::format_plain_char<OutputIt>(it, (exponent_int < 0) ?
'-' :
'+');
1126 private_format::format_plain_num<OutputIt, long long int, 16>(it, exponent_int, spec, exponent_decimals);
1129 template <
typename OutputIt,
typename T>
1130 void format_floating_e(OutputIt& it, T value,
const format_spec_t& spec)
1132 static const size_t fractional_decimals = 6;
1133 static const size_t exponent_decimals = 2;
1134 long long int exponent_int = 0;
1137 unsigned long long int fractional_int;
1138 unsigned long long int integral_int;
1141 T fractional = modf(value, &integral);
1143 while (value >= 10 || value <= -10)
1147 fractional = modf(value, &integral);
1150 while ((value > 0.0000000000001 && value < 1) || (value < -0.0000000000001 && value > -1))
1154 fractional = modf(value, &integral);
1160 fractional_int =
static_cast<unsigned long long int>(-fractional * pow(10., fractional_decimals));
1161 integral_int =
static_cast<unsigned long long int>(-integral);
1166 fractional_int =
static_cast<unsigned long long int>(fractional * pow(10., fractional_decimals));
1167 integral_int =
static_cast<unsigned long long int>(integral);
1170 private_format::format_sign<OutputIt, int>(it, sign ? -1 : 0, spec);
1171 private_format::format_plain_num<OutputIt, unsigned long long int>(it, integral_int, spec);
1172 private_format::format_sequence<OutputIt>(it,
".");
1173 private_format::format_plain_num<OutputIt, unsigned long long int>(it, fractional_int, spec, fractional_decimals);
1175 if (is_uppercase(spec.type.value()))
1179 private_format::format_plain_char<OutputIt>(it, letter);
1180 private_format::format_plain_char<OutputIt>(it, (exponent_int < 0) ?
'-' :
'+');
1181 private_format::format_plain_num<OutputIt, long long int>(it, exponent_int, spec, exponent_decimals);
1184 template <
typename OutputIt,
typename T>
1185 void format_floating_f(OutputIt& it, T value,
const format_spec_t& spec)
1187 const size_t fractional_decimals = 6;
1190 T fractional = modf(value, &integral);
1192 unsigned long long int fractional_int;
1193 unsigned long long int integral_int;
1197 fractional_int =
static_cast<unsigned long long int>(-fractional * pow(10., fractional_decimals));
1198 integral_int =
static_cast<unsigned long long int>(-integral);
1203 fractional_int =
static_cast<unsigned long long int>(fractional * pow(10., fractional_decimals));
1204 integral_int =
static_cast<unsigned long long int>(integral);
1207 private_format::format_sign<OutputIt, int>(it, sign ? -1 : 0, spec);
1208 private_format::format_plain_num<OutputIt, unsigned long long int>(it, integral_int, spec);
1209 private_format::format_sequence<OutputIt>(it,
".");
1210 private_format::format_plain_num<OutputIt, unsigned long long int>(it, fractional_int, spec, fractional_decimals);
1214 class dummy_assign_to
1218 dummy_assign_to& operator=(char_type)
1224 template <
class OutputIt>
1225 class limit_assign_to
1229 limit_assign_to(OutputIt o,
bool is_active)
1235 limit_assign_to& operator=(char_type c)
1250 template <
class OutputIt>
1251 class limit_iterator
1255 limit_iterator(OutputIt& it,
size_t n)
1261 limit_iterator(
const limit_iterator& other) =
default;
1262 limit_iterator(limit_iterator&& other) =
default;
1263 limit_iterator& operator=(
const limit_iterator& other) =
default;
1264 limit_iterator& operator=(limit_iterator&& other) =
default;
1268 return limit_assign_to<OutputIt>(out, (limit > 0));
1271 limit_iterator& operator++()
1281 limit_iterator operator++(
int)
1283 limit_iterator temp = *
this;
1303 class counter_iterator
1312 counter_iterator(
const counter_iterator& other) =
default;
1313 counter_iterator& operator=(
const counter_iterator& other) =
default;
1317 return dummy_assign_to();
1320 counter_iterator& operator++()
1326 counter_iterator operator++(
int)
1328 counter_iterator temp = *
this;
1343 #if ETL_USING_FORMAT_FLOATING_POINT
1344 template <
typename OutputIt,
typename T>
1345 void format_floating_g(OutputIt& it, T value,
const format_spec_t& spec)
1347 private_format::counter_iterator counter_e, counter_f;
1349 format_floating_e(counter_e, value, spec);
1350 format_floating_f(counter_f, value, spec);
1352 if (counter_e.value() < counter_f.value())
1354 format_floating_e(it, value, spec);
1358 format_floating_f(it, value, spec);
1362 template <
typename OutputIt,
typename T>
1363 void format_floating(OutputIt& it, T value,
const format_spec_t& spec)
1367 if (spec.type.has_value() && (is_uppercase(spec.type.value())))
1369 format_sequence(it,
"NAN");
1373 format_sequence(it,
"nan");
1376 else if (isinf(value))
1378 if (spec.type.has_value() && (is_uppercase(spec.type.value())))
1380 format_sequence(it,
"INF");
1384 format_sequence(it,
"inf");
1387 else if (!spec.type.has_value())
1389 format_floating_default(it, value, spec);
1393 switch (spec.type.value())
1396 case 'A': format_floating_a(it, value, spec);
break;
1398 case 'E': format_floating_e(it, value, spec);
break;
1400 case 'F': format_floating_f(it, value, spec);
break;
1402 case 'G': format_floating_g(it, value, spec);
break;
1405 ETL_ASSERT_FAIL(ETL_ERROR(bad_format_string_exception));
1411 template <
class OutputIt>
1412 struct format_visitor
1414 using output_iterator = OutputIt;
1416 format_visitor(format_parse_context& parse_context, format_context<OutputIt>& f_ctx)
1417 : parse_ctx(parse_context)
1423 template <
typename T>
1424 void operator()(T value)
1427 format_parse_context::iterator it = f.parse(parse_ctx);
1428 parse_ctx.advance_to(it);
1429 OutputIt fit = f.format(value, fmt_ctx);
1430 fmt_ctx.advance_to(fit);
1433 format_parse_context& parse_ctx;
1434 format_context<OutputIt>& fmt_ctx;
1437 template <
class OutputIt>
1438 void output(format_context<OutputIt>& fmt_context,
char c)
1440 *fmt_context.out() = c;
1441 OutputIt tmp = fmt_context.out();
1443 fmt_context.advance_to(tmp);
1446 template <
typename OutputIt,
typename Int>
1447 typename format_context<OutputIt>::iterator format_aligned_int(Int arg, format_context<OutputIt>& fmt_ctx)
1449 size_t prefix_size = 0;
1450 size_t suffix_size = 0;
1452 if (fmt_ctx.format_spec.width)
1455 private_format::counter_iterator counter;
1456 private_format::format_num<private_format::counter_iterator, Int>(counter, arg, fmt_ctx.format_spec);
1458 if (counter.value() < fmt_ctx.format_spec.width.value())
1460 size_t pad = fmt_ctx.format_spec.width.value() - counter.value();
1461 switch (fmt_ctx.format_spec.align)
1463 case private_format::spec_align_t::START:
1467 case private_format::spec_align_t::CENTER:
1468 prefix_size =
pad / 2;
1469 suffix_size =
pad - prefix_size;
1471 case private_format::spec_align_t::NONE:
1472 case private_format::spec_align_t::END:
1478 ETL_ASSERT_FAIL(ETL_ERROR(bad_format_string_exception));
1484 OutputIt it = fmt_ctx.out();
1485 private_format::fill<OutputIt>(it, prefix_size, fmt_ctx.format_spec.fill);
1486 private_format::format_num<OutputIt, Int>(it, arg, fmt_ctx.format_spec);
1487 private_format::fill<OutputIt>(it, suffix_size, fmt_ctx.format_spec.fill);
1491 #if ETL_USING_FORMAT_FLOATING_POINT
1492 template <
typename OutputIt,
typename Float>
1493 typename format_context<OutputIt>::iterator format_aligned_floating(Float arg, format_context<OutputIt>& fmt_ctx)
1495 size_t prefix_size = 0;
1496 size_t suffix_size = 0;
1498 if (fmt_ctx.format_spec.width)
1501 private_format::counter_iterator counter;
1502 private_format::format_floating<private_format::counter_iterator, Float>(counter, arg, fmt_ctx.format_spec);
1504 if (counter.value() < fmt_ctx.format_spec.width.value())
1506 size_t pad = fmt_ctx.format_spec.width.value() - counter.value();
1507 switch (fmt_ctx.format_spec.align)
1509 case private_format::spec_align_t::START:
1513 case private_format::spec_align_t::CENTER:
1514 prefix_size =
pad / 2;
1515 suffix_size =
pad - prefix_size;
1517 case private_format::spec_align_t::NONE:
1518 case private_format::spec_align_t::END:
1524 ETL_ASSERT_FAIL(ETL_ERROR(bad_format_string_exception));
1530 OutputIt it = fmt_ctx.out();
1531 private_format::fill<OutputIt>(it, prefix_size, fmt_ctx.format_spec.fill);
1532 private_format::format_floating<OutputIt, Float>(it, arg, fmt_ctx.format_spec);
1533 private_format::fill<OutputIt>(it, suffix_size, fmt_ctx.format_spec.fill);
1538 template <
typename OutputIt>
1539 void format_string_view(OutputIt& it, etl::string_view arg,
const format_spec_t& spec)
1541 bool escaped =
false;
1542 if (spec.type.has_value())
1544 switch (spec.type.value())
1555 ETL_ASSERT_FAIL(ETL_ERROR(bad_format_string_exception));
1558 size_t limit = etl::numeric_limits<size_t>::max();
1559 if (spec.precision.has_value())
1561 limit = spec.precision.value();
1566 format_plain_char(it,
'"');
1568 etl::string_view::const_iterator arg_it = arg.
begin();
1569 while (arg_it != arg.cend() && limit > 0)
1573 format_escaped_char(it, *arg_it);
1577 format_plain_char(it, *arg_it);
1584 format_plain_char(it,
'"');
1588 template <
typename OutputIt>
1589 typename format_context<OutputIt>::iterator format_aligned_string_view(etl::string_view arg, format_context<OutputIt>& fmt_ctx)
1591 size_t prefix_size = 0;
1592 size_t suffix_size = 0;
1594 if (fmt_ctx.format_spec.width)
1597 private_format::counter_iterator counter;
1598 private_format::format_string_view<private_format::counter_iterator>(counter, arg, fmt_ctx.format_spec);
1600 if (counter.value() < fmt_ctx.format_spec.width.value())
1602 size_t pad = fmt_ctx.format_spec.width.value() - counter.value();
1603 switch (fmt_ctx.format_spec.align)
1605 case private_format::spec_align_t::NONE:
1606 case private_format::spec_align_t::START:
1610 case private_format::spec_align_t::CENTER:
1611 prefix_size =
pad / 2;
1612 suffix_size =
pad - prefix_size;
1614 case private_format::spec_align_t::END:
1620 ETL_ASSERT_FAIL(ETL_ERROR(bad_format_string_exception));
1626 OutputIt it = fmt_ctx.out();
1627 private_format::fill<OutputIt>(it, prefix_size, fmt_ctx.format_spec.fill);
1628 private_format::format_string_view<OutputIt>(it, arg, fmt_ctx.format_spec);
1629 private_format::fill<OutputIt>(it, suffix_size, fmt_ctx.format_spec.fill);
1633 template <
typename OutputIt>
1634 void format_chars(OutputIt& it,
const char* arg,
const format_spec_t& spec)
1636 bool escaped =
false;
1637 if (spec.type.has_value())
1639 switch (spec.type.value())
1650 ETL_ASSERT_FAIL(ETL_ERROR(bad_format_string_exception));
1653 size_t limit = etl::numeric_limits<size_t>::max();
1654 if (spec.precision.has_value())
1656 limit = spec.precision.value();
1661 format_plain_char(it,
'"');
1663 const char_type* arg_it = arg;
1664 while (*arg_it !=
'\0' && limit > 0)
1668 format_escaped_char(it, *arg_it);
1672 format_plain_char(it, *arg_it);
1679 format_plain_char(it,
'"');
1683 template <
typename OutputIt>
1684 typename format_context<OutputIt>::iterator format_aligned_chars(
const char* arg, format_context<OutputIt>& fmt_ctx)
1686 size_t prefix_size = 0;
1687 size_t suffix_size = 0;
1689 if (fmt_ctx.format_spec.width)
1692 private_format::counter_iterator counter;
1693 private_format::format_chars<private_format::counter_iterator>(counter, arg, fmt_ctx.format_spec);
1695 if (counter.value() < fmt_ctx.format_spec.width.value())
1697 size_t pad = fmt_ctx.format_spec.width.value() - counter.value();
1698 switch (fmt_ctx.format_spec.align)
1700 case private_format::spec_align_t::NONE:
1701 case private_format::spec_align_t::START:
1705 case private_format::spec_align_t::CENTER:
1706 prefix_size =
pad / 2;
1707 suffix_size =
pad - prefix_size;
1709 case private_format::spec_align_t::END:
1715 ETL_ASSERT_FAIL(ETL_ERROR(bad_format_string_exception));
1721 OutputIt it = fmt_ctx.out();
1722 private_format::fill<OutputIt>(it, prefix_size, fmt_ctx.format_spec.fill);
1723 private_format::format_chars<OutputIt>(it, arg, fmt_ctx.format_spec);
1724 private_format::fill<OutputIt>(it, suffix_size, fmt_ctx.format_spec.fill);
1728 inline void check_char_spec(
const format_spec_t& spec)
1730 if ((!spec.type.has_value() || spec.type.value() ==
'c' || spec.type.value() ==
'?')
1731 && (spec.sign != spec_sign_t::MINUS || spec.zero || spec.hash || spec.precision))
1733 ETL_ASSERT_FAIL(ETL_ERROR(bad_format_string_exception));
1737 template <
typename OutputIt>
1738 void format_char(OutputIt& it, char_type c,
const format_spec_t& spec)
1740 check_char_spec(spec);
1741 if (spec.type.has_value())
1743 switch (spec.type.value())
1747 format_plain_char(it, c);
1751 format_plain_char(it,
'\'');
1752 format_escaped_char(it, c);
1753 format_plain_char(it,
'\'');
1760 case 'X': private_format::format_num<OutputIt, unsigned int>(it,
static_cast<unsigned int>(
static_cast<unsigned char>(c)), spec);
break;
1763 ETL_ASSERT_FAIL(ETL_ERROR(bad_format_string_exception));
1768 format_plain_char(it, c);
1772 template <
typename OutputIt>
1773 typename format_context<OutputIt>::iterator format_aligned_char(char_type arg, format_context<OutputIt>& fmt_ctx)
1775 size_t prefix_size = 0;
1776 size_t suffix_size = 0;
1778 if (fmt_ctx.format_spec.width)
1781 private_format::counter_iterator counter;
1782 private_format::format_char<private_format::counter_iterator>(counter, arg, fmt_ctx.format_spec);
1784 if (counter.value() < fmt_ctx.format_spec.width.value())
1786 size_t pad = fmt_ctx.format_spec.width.value() - counter.value();
1787 switch (fmt_ctx.format_spec.align)
1789 case private_format::spec_align_t::NONE:
1790 if (!fmt_ctx.format_spec.type.has_value() || fmt_ctx.format_spec.type.value() ==
'c' || fmt_ctx.format_spec.type.value() ==
'?')
1801 case private_format::spec_align_t::START:
1805 case private_format::spec_align_t::CENTER:
1806 prefix_size =
pad / 2;
1807 suffix_size =
pad - prefix_size;
1809 case private_format::spec_align_t::END:
1815 ETL_ASSERT_FAIL(ETL_ERROR(bad_format_string_exception));
1821 OutputIt it = fmt_ctx.out();
1822 private_format::fill<OutputIt>(it, prefix_size, fmt_ctx.format_spec.fill);
1823 private_format::format_char<OutputIt>(it, arg, fmt_ctx.format_spec);
1824 private_format::fill<OutputIt>(it, suffix_size, fmt_ctx.format_spec.fill);
1828 template <
typename OutputIt>
1829 void format_bool(OutputIt& it,
bool value,
const format_spec_t& spec)
1831 if (spec.type.has_value())
1833 switch (spec.type.value())
1837 format_sequence(it, value ?
"true" :
"false");
1844 case 'X': private_format::format_num<OutputIt, unsigned int>(it,
static_cast<unsigned int>(
static_cast<unsigned char>(value)), spec);
break;
1847 ETL_ASSERT_FAIL(ETL_ERROR(bad_format_string_exception));
1852 format_sequence(it, value ?
"true" :
"false");
1856 template <
typename OutputIt>
1857 typename format_context<OutputIt>::iterator format_aligned_bool(
bool arg, format_context<OutputIt>& fmt_ctx)
1859 size_t prefix_size = 0;
1860 size_t suffix_size = 0;
1862 if (fmt_ctx.format_spec.width)
1865 private_format::counter_iterator counter;
1866 private_format::format_bool<private_format::counter_iterator>(counter, arg, fmt_ctx.format_spec);
1868 if (counter.value() < fmt_ctx.format_spec.width.value())
1870 size_t pad = fmt_ctx.format_spec.width.value() - counter.value();
1871 switch (fmt_ctx.format_spec.align)
1873 case private_format::spec_align_t::START:
1877 case private_format::spec_align_t::CENTER:
1878 prefix_size =
pad / 2;
1879 suffix_size =
pad - prefix_size;
1881 case private_format::spec_align_t::NONE:
1882 case private_format::spec_align_t::END:
1888 ETL_ASSERT_FAIL(ETL_ERROR(bad_format_string_exception));
1894 OutputIt it = fmt_ctx.out();
1895 private_format::fill<OutputIt>(it, prefix_size, fmt_ctx.format_spec.fill);
1896 private_format::format_bool<OutputIt>(it, arg, fmt_ctx.format_spec);
1897 private_format::fill<OutputIt>(it, suffix_size, fmt_ctx.format_spec.fill);
1901 template <
typename OutputIt>
1902 void format_pointer(OutputIt& it,
const void* value,
const format_spec_t& spec)
1904 if (spec.type.has_value())
1906 switch (spec.type.value())
1910 format_sequence(it, spec.type.value() ==
'p' ?
"0x" :
"0X");
1911 format_plain_num<OutputIt, uintptr_t>(it,
reinterpret_cast<uintptr_t
>(value), spec);
1915 ETL_ASSERT_FAIL(ETL_ERROR(bad_format_string_exception));
1920 format_sequence(it,
"0x");
1921 format_plain_num<OutputIt, uintptr_t>(it,
reinterpret_cast<uintptr_t
>(value), spec);
1925 template <
typename OutputIt>
1926 typename format_context<OutputIt>::iterator format_aligned_pointer(
const void* arg, format_context<OutputIt>& fmt_ctx)
1928 size_t prefix_size = 0;
1929 size_t suffix_size = 0;
1931 if (fmt_ctx.format_spec.width)
1934 private_format::counter_iterator counter;
1935 private_format::format_pointer<private_format::counter_iterator>(counter, arg, fmt_ctx.format_spec);
1937 if (counter.value() < fmt_ctx.format_spec.width.value())
1939 size_t pad = fmt_ctx.format_spec.width.value() - counter.value();
1940 switch (fmt_ctx.format_spec.align)
1942 case private_format::spec_align_t::START:
1946 case private_format::spec_align_t::CENTER:
1947 prefix_size =
pad / 2;
1948 suffix_size =
pad - prefix_size;
1950 case private_format::spec_align_t::NONE:
1951 case private_format::spec_align_t::END:
1957 ETL_ASSERT_FAIL(ETL_ERROR(bad_format_string_exception));
1963 OutputIt it = fmt_ctx.out();
1964 private_format::fill<OutputIt>(it, prefix_size, fmt_ctx.format_spec.fill);
1965 private_format::format_pointer<OutputIt>(it, arg, fmt_ctx.format_spec);
1966 private_format::fill<OutputIt>(it, suffix_size, fmt_ctx.format_spec.fill);
1972 struct formatter<int>
1974 format_parse_context::iterator parse(format_parse_context& parse_ctx)
1977 return parse_ctx.begin();
1980 template <
class OutputIt>
1981 typename format_context<OutputIt>::iterator format(
int arg, format_context<OutputIt>& fmt_ctx)
1983 if (fmt_ctx.format_spec.type.has_value() && fmt_ctx.format_spec.type.value() ==
'c')
1985 return private_format::format_aligned_char<OutputIt>(
static_cast<private_format::char_type
>(arg), fmt_ctx);
1987 return private_format::format_aligned_int<OutputIt, int>(arg, fmt_ctx);
1992 struct formatter<unsigned int>
1994 format_parse_context::iterator parse(format_parse_context& parse_ctx)
1997 return parse_ctx.begin();
2000 template <
class OutputIt>
2001 typename format_context<OutputIt>::iterator format(
unsigned int arg, format_context<OutputIt>& fmt_ctx)
2003 if (fmt_ctx.format_spec.type.has_value() && fmt_ctx.format_spec.type.value() ==
'c')
2005 return private_format::format_aligned_char<OutputIt>(
static_cast<private_format::char_type
>(arg), fmt_ctx);
2007 return private_format::format_aligned_int<OutputIt, unsigned int>(arg, fmt_ctx);
2012 struct formatter<long long int>
2014 format_parse_context::iterator parse(format_parse_context& parse_ctx)
2017 return parse_ctx.begin();
2020 template <
class OutputIt>
2021 typename format_context<OutputIt>::iterator format(
long long int arg, format_context<OutputIt>& fmt_ctx)
2023 if (fmt_ctx.format_spec.type.has_value() && fmt_ctx.format_spec.type.value() ==
'c')
2025 return private_format::format_aligned_char<OutputIt>(
static_cast<private_format::char_type
>(arg), fmt_ctx);
2027 return private_format::format_aligned_int<OutputIt, long long int>(arg, fmt_ctx);
2032 struct formatter<unsigned long long int>
2034 format_parse_context::iterator parse(format_parse_context& parse_ctx)
2037 return parse_ctx.begin();
2040 template <
class OutputIt>
2041 typename format_context<OutputIt>::iterator format(
unsigned long long int arg, format_context<OutputIt>& fmt_ctx)
2043 if (fmt_ctx.format_spec.type.has_value() && fmt_ctx.format_spec.type.value() ==
'c')
2045 return private_format::format_aligned_char<OutputIt>(
static_cast<private_format::char_type
>(arg), fmt_ctx);
2047 return private_format::format_aligned_int<OutputIt, unsigned long long int>(arg, fmt_ctx);
2052 struct formatter<char>
2054 format_parse_context::iterator parse(format_parse_context& parse_ctx)
2057 return parse_ctx.begin();
2060 template <
class OutputIt>
2061 typename format_context<OutputIt>::iterator format(private_format::char_type arg, format_context<OutputIt>& fmt_ctx)
2063 return private_format::format_aligned_char<OutputIt>(arg, fmt_ctx);
2067 #if ETL_USING_FORMAT_FLOATING_POINT
2069 struct formatter<float>
2071 format_parse_context::iterator parse(format_parse_context& parse_ctx)
2074 return parse_ctx.begin();
2077 template <
class OutputIt>
2078 typename format_context<OutputIt>::iterator format(
float arg, format_context<OutputIt>& fmt_ctx)
2080 return private_format::format_aligned_floating<OutputIt, float>(arg, fmt_ctx);
2085 struct formatter<double>
2087 format_parse_context::iterator parse(format_parse_context& parse_ctx)
2090 return parse_ctx.begin();
2093 template <
class OutputIt>
2094 typename format_context<OutputIt>::iterator format(
double arg, format_context<OutputIt>& fmt_ctx)
2096 return private_format::format_aligned_floating<OutputIt, double>(arg, fmt_ctx);
2101 struct formatter<long double>
2103 format_parse_context::iterator parse(format_parse_context& parse_ctx)
2106 return parse_ctx.begin();
2109 template <
class OutputIt>
2110 typename format_context<OutputIt>::iterator format(
long double arg, format_context<OutputIt>& fmt_ctx)
2112 return private_format::format_aligned_floating<OutputIt, long double>(arg, fmt_ctx);
2118 struct formatter<etl::string_view>
2120 format_parse_context::iterator parse(format_parse_context& parse_ctx)
2123 return parse_ctx.begin();
2126 template <
class OutputIt>
2127 typename format_context<OutputIt>::iterator format(etl::string_view arg, format_context<OutputIt>& fmt_ctx)
2129 return private_format::format_aligned_string_view<OutputIt>(arg, fmt_ctx);
2135 struct formatter<const char*>
2137 format_parse_context::iterator parse(format_parse_context& parse_ctx)
2140 return parse_ctx.begin();
2143 template <
class OutputIt>
2144 typename format_context<OutputIt>::iterator format(
const char* arg, format_context<OutputIt>& fmt_ctx)
2146 return private_format::format_aligned_chars<OutputIt>(arg, fmt_ctx);
2151 struct formatter<bool>
2153 format_parse_context::iterator parse(format_parse_context& parse_ctx)
2156 return parse_ctx.begin();
2159 template <
class OutputIt>
2160 typename format_context<OutputIt>::iterator format(
bool arg, format_context<OutputIt>& fmt_ctx)
2162 return private_format::format_aligned_bool<OutputIt>(arg, fmt_ctx);
2167 struct formatter<const void*>
2169 format_parse_context::iterator parse(format_parse_context& parse_ctx)
2172 return parse_ctx.begin();
2175 template <
class OutputIt>
2176 typename format_context<OutputIt>::iterator format(
const void* arg, format_context<OutputIt>& fmt_ctx)
2178 return private_format::format_aligned_pointer<OutputIt>(arg, fmt_ctx);
2182 template <
class OutputIt>
2183 OutputIt vformat_to(OutputIt out, etl::string_view fmt, format_args<OutputIt> args)
2185 format_parse_context parse_context(fmt, args.size());
2186 format_context<OutputIt> fmt_context(out, args);
2187 private_format::format_visitor<OutputIt> v(parse_context, fmt_context);
2189 while (parse_context.begin() != parse_context.end())
2191 const char c = *parse_context.begin();
2192 private_format::advance(parse_context);
2195 if (*parse_context.begin() ==
'{')
2198 private_format::output<OutputIt>(fmt_context, c);
2199 private_format::advance(parse_context);
2203 private_format::parse_format_spec<OutputIt>(parse_context, fmt_context);
2204 etl::optional<size_t> index = fmt_context.format_spec.index;
2205 if (index.has_value())
2207 parse_context.check_arg_id(*index);
2211 index = parse_context.next_arg_id();
2213 format_arg<OutputIt> arg = args.get(*index);
2214 arg.template visit<void>(v);
2216 ETL_ASSERT(*parse_context.begin() ==
'}', ETL_ERROR(bad_format_string_exception) );
2217 if (parse_context.begin() != parse_context.end())
2219 private_format::advance(parse_context);
2225 ETL_ASSERT(*parse_context.begin() ==
'}', ETL_ERROR(bad_format_string_exception) );
2227 private_format::output<OutputIt>(fmt_context, c);
2228 private_format::advance(parse_context);
2232 private_format::output<OutputIt>(fmt_context, c);
2236 return fmt_context.out();
2239 template <typename OutputIt, typename = etl::enable_if_t< !etl::is_base_of< etl::remove_reference<etl::istring>::type, OutputIt>::value>,
2241 OutputIt format_to(OutputIt out, format_string<Args...> fmt, Args&&... args)
2243 auto the_args{make_format_args<OutputIt>(args...)};
2244 return vformat_to(etl::move(out), fmt.get(), format_args<OutputIt>(the_args));
2247 template <
typename OutputIt,
class WrapperIt = private_format::limit_iterator<OutputIt>,
class... Args>
2248 OutputIt format_to_n(OutputIt out,
size_t n, format_string<Args...> fmt, Args&&... args)
2250 auto the_args{make_format_args<WrapperIt>(args...)};
2251 return vformat_to(WrapperIt(out, n), fmt.get(), format_args<WrapperIt>(the_args)).get();
2255 template <
class... Args>
2256 etl::istring::iterator format_to(etl::istring& out, format_string<Args...> fmt, Args&&... args)
2258 etl::istring::iterator result = format_to_n(out.
begin(), out.
max_size(), fmt, etl::forward<Args>(args)...);
2263 template <
class... Args>
2264 size_t formatted_size(format_string<Args...> fmt, Args&&... args)
2266 private_format::counter_iterator it;
2267 it = format_to(it, fmt, etl::forward<Args>(args)...);
ETL_CONSTEXPR const_iterator cbegin() const ETL_NOEXCEPT
Returns a const iterator to the beginning of the array.
Definition string_view.h:239
ETL_CONSTEXPR size_t size() const ETL_NOEXCEPT
Returns the size of the array.
Definition string_view.h:307
ETL_CONSTEXPR const_iterator begin() const ETL_NOEXCEPT
Returns a const iterator to the beginning of the array.
Definition string_view.h:231
iterator begin()
Definition basic_string.h:371
void uninitialized_resize(size_type new_size)
Definition basic_string.h:538
ETL_CONSTEXPR20_STL iterator begin() ETL_NOEXCEPT
Returns an iterator to the beginning of the optional.
Definition optional.h:1605
size_type max_size() const
Definition basic_string.h:238
#define ETL_ASSERT(b, e)
Definition error_handler.h:511
etl::monostate monostate
Definition variant_legacy.h:80
bitset_ext
Definition absolute.h:40
ETL_CONSTEXPR TContainer::pointer data(TContainer &container)
Definition iterator.h:1228
void pad(TIString &s, typename TIString::size_type required_size, string_pad_direction pad_direction, typename TIString::value_type pad_char)
pad
Definition string_utilities.h:831
ETL_CONSTEXPR TContainer::size_type size(const TContainer &container)
Definition iterator.h:1192
ETL_CONSTEXPR TContainer::iterator begin(TContainer &container)
Definition iterator.h:967
ETL_CONSTEXPR14 enable_if<!etl::is_specialization< TRep2, etl::chrono::duration >::value, etl::chrono::duration< typenameetl::common_type< TRep1, TRep2 >::type, TPeriod1 > >::type operator*(const etl::chrono::duration< TRep1, TPeriod1 > &lhs, const TRep2 &rhs) ETL_NOEXCEPT
Operator *.
Definition duration.h:541
T & get(array< T, Size > &a)
Definition array.h:1161
ETL_CONSTEXPR TContainer::iterator end(TContainer &container)
Definition iterator.h:997
A 'no-value' placeholder.
Definition monostate.h:42