32#include <jau/test/catch2_ext.hpp>
41using namespace std::literals;
47template <
typename... Args>
48constexpr static std::string
format_string000(
const std::size_t maxStrLen,
const std::string& format,
const Args &...args) {
50 str.reserve(maxStrLen + 1);
51 str.resize(maxStrLen);
57 const size_t nchars = std::snprintf(&str[0], maxStrLen + 1, format.data(), args...);
59 if( nchars < maxStrLen + 1 ) {
70 const size_t bsz = 1024;
74 nchars = std::snprintf(&str[0], bsz,
75 "format_000a: %f, %f, %zu, %" PRIu64
", %" PRIu64
", %" PRIx64
", %06" PRIu64
", %06" PRIx64
", %d\n",
76 fa + 1.0_f32, fb + 1.0_f32, sz1 + 1,
77 a_u64 + 1_u64, a_u64 + 1_u64, a_u64 + 1_u64, a_u64 + 1_u64, a_u64 + 1_u64,
91 return jau::format_string(
"format_010a: %f, %f, %zu, %" PRIu64
", %" PRIu64
", %" PRIx64
", %06" PRIu64
", %06" PRIx64
", %d\n",
92 fa + 1.0_f32, fb + 1.0_f32, sz1 + 1,
93 a_u64 + 1_u64, a_u64 + 1_u64, a_u64 + 1_u64, a_u64 + 1_u64, a_u64 + 1_u64,
98 return jau::format_string_n(1023,
"format_020a: %f, %f, %zu, %" PRIu64
", %" PRIu64
", %" PRIx64
", %06" PRIu64
", %06" PRIx64
", %d\n",
99 fa + 1.0_f32, fb + 1.0_f32, sz1 + 1,
100 a_u64 + 1_u64, a_u64 + 1_u64, a_u64 + 1_u64, a_u64 + 1_u64, a_u64 + 1_u64,
105 std::ostringstream ss1;
106 ss1 <<
"format_030a: "
107 << fa + 1.0_f32 <<
", "
108 << fb + 1.0_f32 <<
", "
110 << a_u64 + 1_u64 <<
", "
116std::string format_040a_stdformat(
float fa,
float fb,
size_t sz1, uint64_t a_u64,
int i) {
117 return std::format(
"format_040a: {0}, {1}, {3}, {4}, {5}\n",
118 fa + 1.0_f32, fb + 1.0_f32, sz1 + 1, a_u64 + 1_u64, i + 1);
126 const size_t bsz = 1024;
130 nchars = std::snprintf(&str[0], bsz,
131 "format_000b: %.2f, %2.2f, %zu, %" PRIu64
", %" PRIu64
", %" PRIx64
", %06" PRIu64
", %06" PRIx64
", %03d\n",
132 fa + 1.0_f32, fb + 1.0_f32, sz1 + 1,
133 a_u64 + 1_u64, a_u64 + 1_u64, a_u64 + 1_u64, a_u64 + 1_u64, a_u64 + 1_u64,
146 return jau::format_string(
"format_010b: %.2f, %2.2f, %zu, %" PRIu64
", %" PRIu64
", %" PRIx64
", %06" PRIu64
", %06" PRIx64
", %03d\n",
147 fa + 1.0_f32, fb + 1.0_f32, sz1 + 1,
148 a_u64 + 1_u64, a_u64 + 1_u64, a_u64 + 1_u64, a_u64 + 1_u64, a_u64 + 1_u64,
153 return jau::format_string_n(1023,
"format_020b: %.2f, %2.2f, %zu, %" PRIu64
", %" PRIu64
", %" PRIx64
", %06" PRIu64
", %06" PRIx64
", %03d\n",
154 fa + 1.0_f32, fb + 1.0_f32, sz1 + 1,
155 a_u64 + 1_u64, a_u64 + 1_u64, a_u64 + 1_u64, a_u64 + 1_u64, a_u64 + 1_u64,
160 std::ostringstream ss1;
162 ss1 <<
"format_030b: "
163 << fa + 1.0_f32 <<
", ";
165 ss1 << fb + 1.0_f32 <<
", "
167 << a_u64 + 1_u64 <<
", ";
169 ss1 << i + 1 <<
"\n";
174std::string format_040b_stdformat(
float fa,
float fb,
size_t sz1, uint64_t a_u64,
int i) {
175 return std::format(
"format_040b: {0:.2f}, {1:2.2f}, {3}, {4}, {5:03d}\n",
176 fa + 1.0_f32, fb + 1.0_f32, sz1 + 1, a_u64 + 1_u64, i + 1);
180template <
typename Func>
182 constexpr float fa = 1.1f, fb = 2.2f;
183 constexpr size_t sz1 = 1;
184 constexpr uint64_t sz2 = 2;
187 const std::string s =
func(fa, fb, sz1, sz2, i);
188 volatile size_t l = s.length();
218template <
typename... Args>
229template <
typename... Targs>
234template <
typename... Targs>
246TEST_CASE(
"jau::cfmt_00",
"[jau][std::string][jau::cfmt]") {
248 constexpr float fa = 1.123456f, fb = 2.2f;
249 constexpr size_t sz1 = 1;
250 constexpr int64_t v_i64 = 2;
251 constexpr uint64_t v_u64 = 3;
253 const float *pf = &fa;
257 std::cerr <<
"XXX: " << __LINE__ <<
": " << pr << std::endl;
258 static_assert( 0 <= pr.
argCount() );
262 fa, fb, sz1, v_i64, v_i64, v_i64, v_u64, v_u64, i);
263 std::cerr <<
"XXX: " << __LINE__ <<
": " << pc << std::endl;
269 std::cerr <<
"XXX: " << __LINE__ <<
": " << pr << std::endl;
282 std::cerr <<
"XXX: " << __LINE__ <<
": " << pr1 << std::endl;
283 static_assert( 0 <= pr1.
argCount() );
286 std::cerr <<
"XXX: " << __LINE__ <<
": " << s3 << std::endl;
287 REQUIRE( s3.length() > 0 );
297 static_assert(
false == std::is_signed_v<const float*>);
298 static_assert(
false == std::is_unsigned_v<const float*>);
300 static_assert(
true == std::is_signed_v<float>);
301 static_assert(
false == std::is_unsigned_v<float>);
305 using T =
unsigned int;
307 using U =
typename std::conditional_t<std::is_unsigned_v<T>, std::make_signed<T>, std::type_identity<T>>
::type;
308 static_assert( std::is_same_v<T, T> );
309 static_assert( std::is_same_v<E, U> );
315 using U =
typename std::conditional_t<std::is_unsigned_v<T>, std::make_signed<T>, std::type_identity<T>>
::type;
316 static_assert( std::is_same_v<T, T> );
317 static_assert( std::is_same_v<E, U> );
322 static_assert(
true ==
jau::cfmt::check(
"unsigned int -> int %d", (
unsigned int)1));
323 static_assert(
true ==
jau::cfmt::check(
"unsigned int -> unsigned int %u", (
unsigned int)1));
325 static_assert(
true ==
jau::cfmt::check(
" uint64_t -> int64_t %" PRIi64, (uint64_t)1));
326 static_assert(
true ==
jau::cfmt::check(
" int64_t -> uint64_t %" PRIu64, (int64_t)1));
331 printf(
"XXX: sizeof(long) %zu, %s\n",
sizeof(
long), res.
toString().c_str());
333 if constexpr (
sizeof(long) <= 4 ) {
343 static_assert(
true ==
jau::cfmt::check(
" %" PRIi64
", %" PRIi64
", %08" PRIi64
".", (int64_t)1, (int64_t)1, (int64_t)1));
344 static_assert(
true ==
jau::cfmt::check(
" %" PRIi64
", %" PRIi64
", %08" PRIi64
".", v_i64, v_i64, v_i64));
359 static_assert(4 ==
jau::cfmt::checkR(
"Hello 1 %.2f, 2 %2.2f, 3 %zu, 4 %" PRIi64
" - end", fa, fb, sz1, v_i64).
argCount());
360 static_assert(5 ==
jau::cfmt::checkR(
"Hello 1 %.2f, 2 %2.2f, 3 %zu, 4 %" PRIi64
", 5 %03d - end", fa, fb, sz1, v_i64, i).
argCount());
362 static_assert(5 ==
jau::cfmt::checkR(
"Hello %" PRIu64
", %" PRIu64
", %" PRIx64
", %06" PRIu64
", %06" PRIx64
"",
363 v_i64, v_i64, v_i64, v_i64, v_i64).
argCount());
372 if constexpr (
sizeof(long) <= 4 ) {
377 static_assert(-6 ==
jau::cfmt::checkR(
"Hello 1 %.2f, 2 %2.2f, 3 %zu, 4 %" PRIi64
", 5 %03d, 6 %p - end",
378 fa, fb, sz1, v_i64, i, i).
argCount());
379 static_assert(
false ==
jau::cfmt::check(
"Hello 1 %.2f, 2 %2.2f, 3 %zu, 4 %" PRIi64
", 5 %03d, 6 %p - end",
380 fa, fb, sz1, v_i64, i, i));
384 fa + 1.0_f32, fb + 1.0_f32, sz1 + 1, v_i64 + 1_u64, i + 1);
385 REQUIRE( s.size() > 0 );
389 REQUIRE( s0.size() > 0 );
395 constexpr bool b1 = std::is_nothrow_assignable_v<int&, uint64_t>;
396 static_assert( b1,
"Not Assignable" );
397 constexpr bool b2 = std::is_nothrow_assignable_v<unsigned int&, long double>;
398 static_assert( b2,
"Not Assignable" );
410 std::cerr <<
"XXX: " << __LINE__ <<
": " << c1 << std::endl;
411 REQUIRE(
false == c1.
error());
415 REQUIRE(
false == c1.
error());
419 REQUIRE(
false == c3.
error());
421 REQUIRE(9 == std::snprintf(buf,
sizeof(buf),
"Hello 1 %d", i));
429 std::cerr <<
"XXX: " << __LINE__ <<
": " << pc << std::endl;
430 REQUIRE(2 ==
jau::cfmt::checkR(
"Hello 1 %.2f, 2 %2.2f - end", fa, fb).argCount());
434 std::cerr <<
"XXX: " << __LINE__ <<
": " << pc << std::endl;
435 REQUIRE(3 ==
jau::cfmt::checkR(
"Hello 1 %.2f, 2 %2.2f, 3 %zu - end", fa, fb, sz1).argCount());
437 REQUIRE(4 ==
jau::cfmt::checkR(
"Hello 1 %.2f, 2 %2.2f, 3 %zu, 4 %" PRIi64
" - end", fa, fb, sz1, v_i64).argCount());
438 REQUIRE(5 ==
jau::cfmt::checkR(
"Hello 1 %.2f, 2 %2.2f, 3 %zu, 4 %" PRIi64
", 5 %03d - end", fa, fb, sz1, v_i64, i).argCount());
439 REQUIRE(6 ==
jau::cfmt::checkR(
"Hello 1 %.2f, 2 %2.2f, 3 %zu, 4 %" PRIi64
", 5 %03d, 6 %p - end", fa, fb, sz1, v_i64, i, pf).argCount());
445 if constexpr (
sizeof(long) <= 4 ) {
450 REQUIRE(-6 ==
jau::cfmt::checkR(
"Hello 1 %.2f, 2 %2.2f, 3 %zu, 4 %" PRIi64
", 5 %03d, 6 %p - end",
451 fa, fb, sz1, v_i64, i, i).argCount());
455TEST_CASE(
"jau::cfmt_01",
"[jau][std::string][format_string]") {
461TEST_CASE(
"jau::cfmt_10",
"[benchmark][jau][std::string][format_string]") {
462 const size_t loops = 1000;
463 WARN(
"Benchmark with " + std::to_string(
loops) +
" loops");
466 BENCHMARK(
"fmt__checkR bench") {
467 volatile size_t res = 0;
468 for(
size_t i = 0; i <
loops; ++i ) {
469 float fa = 1.1f, fb = 2.2f;
474 size_t r =
jau::cfmt::checkR(
"format_check: %.2f, %2.2f, %zu, %" PRIu64
", %03d\n",
481 BENCHMARK(
"fmt__checkR2 bench") {
482 constexpr static std::string_view format =
"format_check: %.2f, %2.2f, %zu, %" PRIu64
", %03d\n";
483 volatile size_t res = 0;
484 for(
size_t i = 0; i <
loops; ++i ) {
491 BENCHMARK(
"fmt__checkR2 cnstexpr bench") {
492 constexpr static std::string_view format =
"format_check: %.2f, %2.2f, %zu, %" PRIu64
", %03d\n";
493 volatile size_t res = 0;
494 for(
size_t i = 0; i <
loops; ++i ) {
501 BENCHMARK(
"fmt__check cnstexpr bench") {
502 volatile size_t res = 0;
503 for(
size_t i = 0; i <
loops; ++i ) {
504 constexpr float fa = 1.1f, fb = 2.2f;
505 constexpr size_t sz1 = 1;
506 constexpr uint64_t sz2 = 2;
507 constexpr int i1 = 3;
510 fa, fb, sz1, sz2, i1);
517 BENCHMARK(
"fmt__check cnstexp2 bench") {
518 volatile size_t res = 0;
519 for(
size_t i = 0; i <
loops; ++i ) {
520 constexpr float fa = 1.1f, fb = 2.2f;
521 constexpr size_t sz1 = 1;
522 constexpr uint64_t sz2 = 2;
523 constexpr int i1 = 3;
526 fa, fb, sz1, sz2, i1);
533 BENCHMARK(
"format_000a_vsnprintf bench") {
534 volatile size_t res = 0;
535 for(
size_t i = 0; i <
loops; ++i ) {
540 BENCHMARK(
"format_010a_jaufmtstr bench") {
541 volatile size_t res = 0;
542 for(
size_t i = 0; i <
loops; ++i ) {
547 BENCHMARK(
"format_020a jau macro bench") {
548 volatile size_t res = 0;
549 for(
size_t i = 0; i <
loops; ++i ) {
551 constexpr float fa = 1.1f, fb = 2.2f;
552 constexpr size_t sz1 = 1;
553 constexpr uint64_t a_u64 = 2;
556 fa + 1.0_f32, fb + 1.0_f32, sz1 + 1, a_u64 + 1_u64, j + 1);
557 res = res + s.length();
562 BENCHMARK(
"fmt__020a cnstexpr-in bench") {
563 volatile size_t res = 0;
564 for(
size_t i = 0; i <
loops; ++i ) {
566 constexpr float fa = 1.1f, fb = 2.2f;
567 constexpr size_t sz1 = 1;
568 constexpr uint64_t a_u64 = 2;
570 if constexpr(
jau::cfmt::check(
"format_020a: %f, %f, %zu, %" PRIu64
", %d\n",
571 fa + 1.0_f32, fb + 1.0_f32, sz1 + 1, a_u64 + 1_u64, j + 1) ) {
580 const size_t nchars = std::snprintf(&s[0], 1023 + 1,
"format_020a: %f, %f, %zu, %" PRIu64
", %d\n",
581 fa + 1.0_f32, fb + 1.0_f32, sz1 + 1, a_u64 + 1_u64, j + 1);
583 if( nchars < 1023 + 1 ) {
587 res = res + s.length();
593 BENCHMARK(
"fmt__020a_jaufmtstr_n bench") {
594 volatile size_t res = 0;
595 for(
size_t i = 0; i <
loops; ++i ) {
600 BENCHMARK(
"format_030a_strstream bench") {
601 volatile size_t res = 0;
602 for(
size_t i = 0; i <
loops; ++i ) {
608 BENCHMARK(
"format_040a_stdformat bench") {
609 volatile size_t res = 0;
610 for(
size_t i = 0; i < iterations; ++i ) {
611 res = res +
test_format(format_040a_stdformat,
false);
617 BENCHMARK(
"format_000b_vsnprintf__ bench") {
618 volatile size_t res = 0;
619 for(
size_t i = 0; i <
loops; ++i ) {
624 BENCHMARK(
"format_010b_jaufmtstr__ bench") {
625 volatile size_t res = 0;
626 for(
size_t i = 0; i <
loops; ++i ) {
631 BENCHMARK(
"format_020b_jaufmtstr_n bench") {
632 volatile size_t res = 0;
633 for(
size_t i = 0; i <
loops; ++i ) {
638 BENCHMARK(
"format_030b_strstream__ bench") {
639 volatile size_t res = 0;
640 for(
size_t i = 0; i <
loops; ++i ) {
646 BENCHMARK(
"format_040b_stdformat bench") {
647 volatile size_t res = 0;
648 for(
size_t i = 0; i < iterations; ++i ) {
649 res = res +
test_format(format_040b_stdformat,
false);
#define PRAGMA_DISABLE_WARNING_PUSH
#define PRAGMA_DISABLE_WARNING_POP
#define PRAGMA_DISABLE_WARNING_FORMAT_NONLITERAL
constexpr const PResult checkR(const std::string_view fmt, const Targs &...) noexcept
Strict type validation of arguments against the format string.
constexpr PResult checkR2(const std::string_view fmt) noexcept
Strict type validation of arguments against the format string.
constexpr bool check(const std::string_view fmt, const Targs &...) noexcept
Strict type validation of arguments against the format string.
constexpr std::string format_string_n(const std::size_t maxStrLen, const std::string_view &format, const Args &...args)
Safely returns a (potentially truncated) string according to snprintf() formatting rules and variable...
constexpr std::string format_string(const std::string_view format, const Args &...args)
Safely returns a (non-truncated) string according to snprintf() formatting rules using an initially s...
constexpr bool check2(const std::string_view fmt) noexcept
Strict type validation of arguments against the format string.
constexpr PResult checkR(const std::string_view fmt, const Targs &...) noexcept
Strict type validation of arguments against the format string.
constexpr bool check3(StrView fmt) noexcept
constexpr const PResult checkRec(const PResult ctx) noexcept
#define jau_format_string_static(...)
constexpr ssize_t argCount() const noexcept
constexpr bool error() const noexcept
constexpr ssize_t argCount() const noexcept
std::string toString() const
int printf(const char *format,...)
Operating Systems predefined macros.
static constexpr std::string format_string000(const std::size_t maxStrLen, const std::string &format, const Args &...args)
static size_t test_format(const Func func, bool output)
static constexpr std::string format_string_static2(const std::string_view fmt, const Args &...)
static constexpr jau::cfmt2::PResult check(const std::string_view fmt, const Targs &...) noexcept
static std::string format_000a_vsnprintf(float fa, float fb, size_t sz1, uint64_t a_u64, int i)
static std::string format_020b_jaufmtstr_n(float fa, float fb, size_t sz1, uint64_t a_u64, int i)
static constexpr std::string format_string_static3(const std::string_view format, const Targs &...args)
static std::string format_010a_jaufmtstr(float fa, float fb, size_t sz1, uint64_t a_u64, int i)
static std::string format_000b_vsnprintf(float fa, float fb, size_t sz1, uint64_t a_u64, int i)
static std::string format_030a_strstream(float fa, float fb, size_t sz1, uint64_t a_u64, int i)
static std::string format_030b_strstream(float fa, float fb, size_t sz1, uint64_t a_u64, int i)
static std::string format_010b_jaufmtstr(float fa, float fb, size_t sz1, uint64_t a_u64, int i)
TEST_CASE("jau::cfmt_00", "[jau][std::string][jau::cfmt]")
static constexpr std::string format_020a_jaufmtstr_n(float fa, float fb, size_t sz1, uint64_t a_u64, int i)