31#include <jau/test/catch2_ext.hpp>
40using namespace std::literals;
46template <
typename... Args>
47constexpr std::string
format_string000(
const std::size_t maxStrLen,
const std::string_view format,
const Args &...args) {
49 str.reserve(maxStrLen + 1);
50 str.resize(maxStrLen);
56 const size_t nchars = std::snprintf(&str[0], maxStrLen + 1, format.data(), args...);
58 if( nchars < maxStrLen + 1 ) {
69 const size_t bsz = 1024;
73 nchars = std::snprintf(&str[0], bsz,
74 "format_000a: %f, %f, %zu, %" PRIu64
", %d\n",
75 fa + 1.0_f32, fb + 1.0_f32, sz1 + 1, a_u64 + 1_u64, i + 1);
89 fa + 1.0_f32, fb + 1.0_f32, sz1 + 1, a_u64 + 1_u64, i + 1);
94 fa + 1.0_f32, fb + 1.0_f32, sz1 + 1, a_u64 + 1_u64, i + 1);
98 std::ostringstream ss1;
99 ss1 <<
"format_030a: "
100 << fa + 1.0_f32 <<
", "
101 << fb + 1.0_f32 <<
", "
103 << a_u64 + 1_u64 <<
", "
109std::string format_040a_stdformat(
float fa,
float fb,
size_t sz1, uint64_t a_u64,
int i) {
110 return std::format(
"format_040a: {0}, {1}, {3}, {4}, {5}\n",
111 fa + 1.0_f32, fb + 1.0_f32, sz1 + 1, a_u64 + 1_u64, i + 1);
119 const size_t bsz = 1024;
123 nchars = std::snprintf(&str[0], bsz,
124 "format_000b: %.2f, %2.2f, %zu, %" PRIu64
", %03d\n",
125 fa + 1.0_f32, fb + 1.0_f32, sz1 + 1, a_u64 + 1_u64, i + 1);
138 fa + 1.0_f32, fb + 1.0_f32, sz1 + 1, a_u64 + 1_u64, i + 1);
143 fa + 1.0_f32, fb + 1.0_f32, sz1 + 1, a_u64 + 1_u64, i + 1);
147 std::ostringstream ss1;
149 ss1 <<
"format_030b: "
150 << fa + 1.0_f32 <<
", ";
152 ss1 << fb + 1.0_f32 <<
", "
154 << a_u64 + 1_u64 <<
", ";
156 ss1 << i + 1 <<
"\n";
161std::string format_040b_stdformat(
float fa,
float fb,
size_t sz1, uint64_t a_u64,
int i) {
162 return std::format(
"format_040b: {0:.2f}, {1:2.2f}, {3}, {4}, {5:03d}\n",
163 fa + 1.0_f32, fb + 1.0_f32, sz1 + 1, a_u64 + 1_u64, i + 1);
167template <
typename Func>
169 constexpr float fa = 1.1f, fb = 2.2f;
170 constexpr size_t sz1 = 1;
171 constexpr uint64_t sz2 = 2;
174 const std::string s =
func(fa, fb, sz1, sz2, i);
175 volatile size_t l = s.length();
205template <
typename... Args>
216template <
typename... Targs>
221template <
typename... Targs>
233TEST_CASE(
"jau::cfmt_00",
"[jau][std::string][jau::cfmt]") {
235 constexpr float fa = 1.123456f, fb = 2.2f;
236 constexpr size_t sz1 = 1;
237 constexpr int64_t sz2 = 2;
239 const float *pf = &fa;
243 std::cerr <<
"XXX: " << __LINE__ <<
": " << pr << std::endl;
244 static_assert( 0 <= pr.
argCount() );
248 fa, fb, sz1, sz2, i);
249 std::cerr <<
"XXX: " << __LINE__ <<
": " << pc << std::endl;
255 std::cerr <<
"XXX: " << __LINE__ <<
": " << pr << std::endl;
268 std::cerr <<
"XXX: " << __LINE__ <<
": " << pr1 << std::endl;
269 static_assert( 0 <= pr1.
argCount() );
272 std::cerr <<
"XXX: " << __LINE__ <<
": " << s3 << std::endl;
273 REQUIRE( s3.length() > 0 );
283 static_assert(
false == std::is_signed_v<const float*>);
284 static_assert(
false == std::is_unsigned_v<const float*>);
286 static_assert(
true == std::is_signed_v<float>);
287 static_assert(
false == std::is_unsigned_v<float>);
291 using T =
unsigned int;
293 using U =
typename std::conditional_t<std::is_unsigned_v<T>, std::make_signed<T>, std::type_identity<T>>
::type;
294 static_assert( std::is_same_v<T, T> );
295 static_assert( std::is_same_v<E, U> );
301 using U =
typename std::conditional_t<std::is_unsigned_v<T>, std::make_signed<T>, std::type_identity<T>>
::type;
302 static_assert( std::is_same_v<T, T> );
303 static_assert( std::is_same_v<E, U> );
308 static_assert(
true ==
jau::cfmt::check(
"unsigned int -> int %d", (
unsigned int)1));
309 static_assert(
true ==
jau::cfmt::check(
"unsigned int -> unsigned int %u", (
unsigned int)1));
315 printf(
"XXX: sizeof(long) %zu, %s\n",
sizeof(
long), res.
toString().c_str());
317 if constexpr (
sizeof(long) <= 4 ) {
343 static_assert(5 ==
jau::cfmt::checkR(
"Hello 1 %.2f, 2 %2.2f, 3 %zu, 4 %" PRIi64
", 5 %03d - end", fa, fb, sz1, sz2, i).
argCount());
350 if constexpr (
sizeof(long) <= 4 ) {
355 static_assert(-6 ==
jau::cfmt::checkR(
"Hello 1 %.2f, 2 %2.2f, 3 %zu, 4 %" PRIi64
", 5 %03d, 6 %p - end",
356 fa, fb, sz1, sz2, i, i).
argCount());
357 static_assert(
false ==
jau::cfmt::check(
"Hello 1 %.2f, 2 %2.2f, 3 %zu, 4 %" PRIi64
", 5 %03d, 6 %p - end",
358 fa, fb, sz1, sz2, i, i));
361 fa + 1.0_f32, fb + 1.0_f32, sz1 + 1, sz2 + 1_u64, i + 1);
365 constexpr bool b1 = std::is_nothrow_assignable_v<int&, uint64_t>;
366 static_assert( b1,
"Not Assignable" );
367 constexpr bool b2 = std::is_nothrow_assignable_v<unsigned int&, long double>;
368 static_assert( b2,
"Not Assignable" );
380 std::cerr <<
"XXX: " << __LINE__ <<
": " << c1 << std::endl;
381 REQUIRE(
false == c1.
error());
385 REQUIRE(
false == c1.
error());
389 REQUIRE(
false == c3.
error());
391 REQUIRE(9 == std::snprintf(buf,
sizeof(buf),
"Hello 1 %d", i));
399 std::cerr <<
"XXX: " << __LINE__ <<
": " << pc << std::endl;
400 REQUIRE(2 ==
jau::cfmt::checkR(
"Hello 1 %.2f, 2 %2.2f - end", fa, fb).argCount());
404 std::cerr <<
"XXX: " << __LINE__ <<
": " << pc << std::endl;
405 REQUIRE(3 ==
jau::cfmt::checkR(
"Hello 1 %.2f, 2 %2.2f, 3 %zu - end", fa, fb, sz1).argCount());
407 REQUIRE(4 ==
jau::cfmt::checkR(
"Hello 1 %.2f, 2 %2.2f, 3 %zu, 4 %" PRIi64
" - end", fa, fb, sz1, sz2).argCount());
408 REQUIRE(5 ==
jau::cfmt::checkR(
"Hello 1 %.2f, 2 %2.2f, 3 %zu, 4 %" PRIi64
", 5 %03d - end", fa, fb, sz1, sz2, i).argCount());
409 REQUIRE(6 ==
jau::cfmt::checkR(
"Hello 1 %.2f, 2 %2.2f, 3 %zu, 4 %" PRIi64
", 5 %03d, 6 %p - end", fa, fb, sz1, sz2, i, pf).argCount());
415 if constexpr (
sizeof(long) <= 4 ) {
420 REQUIRE(-6 ==
jau::cfmt::checkR(
"Hello 1 %.2f, 2 %2.2f, 3 %zu, 4 %" PRIi64
", 5 %03d, 6 %p - end",
421 fa, fb, sz1, sz2, i, i).argCount());
425TEST_CASE(
"jau::cfmt_01",
"[jau][std::string][format_string]") {
431TEST_CASE(
"jau::cfmt_10",
"[benchmark][jau][std::string][format_string]") {
432 const size_t loops = 1000;
433 WARN(
"Benchmark with " + std::to_string(
loops) +
" loops");
436 BENCHMARK(
"fmt__check bench") {
437 volatile size_t res = 0;
438 for(
size_t i = 0; i <
loops; ++i ) {
439 float fa = 1.1f, fb = 2.2f;
444 size_t r =
jau::cfmt::checkR(
"format_check: %.2f, %2.2f, %zu, %" PRIu64
", %03d\n",
451 BENCHMARK(
"fmt__check cnstexpr bench") {
452 volatile size_t res = 0;
453 for(
size_t i = 0; i <
loops; ++i ) {
454 constexpr float fa = 1.1f, fb = 2.2f;
455 constexpr size_t sz1 = 1;
456 constexpr uint64_t sz2 = 2;
457 constexpr int i1 = 3;
460 fa, fb, sz1, sz2, i1);
467 BENCHMARK(
"fmt__check cnstexp2 bench") {
468 volatile size_t res = 0;
469 for(
size_t i = 0; i <
loops; ++i ) {
470 constexpr float fa = 1.1f, fb = 2.2f;
471 constexpr size_t sz1 = 1;
472 constexpr uint64_t sz2 = 2;
473 constexpr int i1 = 3;
476 fa, fb, sz1, sz2, i1);
483 BENCHMARK(
"format_000a_vsnprintf bench") {
484 volatile size_t res = 0;
485 for(
size_t i = 0; i <
loops; ++i ) {
490 BENCHMARK(
"format_010a_vsnprintf bench") {
491 volatile size_t res = 0;
492 for(
size_t i = 0; i <
loops; ++i ) {
497 BENCHMARK(
"fmt__020a macro bench") {
498 volatile size_t res = 0;
499 for(
size_t i = 0; i <
loops; ++i ) {
501 constexpr float fa = 1.1f, fb = 2.2f;
502 constexpr size_t sz1 = 1;
503 constexpr uint64_t a_u64 = 2;
506 fa + 1.0_f32, fb + 1.0_f32, sz1 + 1, a_u64 + 1_u64, j + 1);
507 res = res + s.length();
512 BENCHMARK(
"fmt__020a cnstexpr-in bench") {
513 volatile size_t res = 0;
514 for(
size_t i = 0; i <
loops; ++i ) {
516 constexpr float fa = 1.1f, fb = 2.2f;
517 constexpr size_t sz1 = 1;
518 constexpr uint64_t a_u64 = 2;
520 if constexpr(
jau::cfmt::check(
"format_020a: %f, %f, %zu, %" PRIu64
", %d\n",
521 fa + 1.0_f32, fb + 1.0_f32, sz1 + 1, a_u64 + 1_u64, j + 1) ) {
530 const size_t nchars = std::snprintf(&s[0], 1023 + 1,
"format_020a: %f, %f, %zu, %" PRIu64
", %d\n",
531 fa + 1.0_f32, fb + 1.0_f32, sz1 + 1, a_u64 + 1_u64, j + 1);
533 if( nchars < 1023 + 1 ) {
537 res = res + s.length();
543 BENCHMARK(
"fmt__020a_tsnprintf bench") {
544 volatile size_t res = 0;
545 for(
size_t i = 0; i <
loops; ++i ) {
550 BENCHMARK(
"format_030a_strstream bench") {
551 volatile size_t res = 0;
552 for(
size_t i = 0; i <
loops; ++i ) {
558 BENCHMARK(
"format_040a_stdformat bench") {
559 volatile size_t res = 0;
560 for(
size_t i = 0; i < iterations; ++i ) {
561 res = res +
test_format(format_040a_stdformat,
false);
567 BENCHMARK(
"format_000b_vsnprintf bench") {
568 volatile size_t res = 0;
569 for(
size_t i = 0; i <
loops; ++i ) {
574 BENCHMARK(
"format_010b_vsnprintf bench") {
575 volatile size_t res = 0;
576 for(
size_t i = 0; i <
loops; ++i ) {
581 BENCHMARK(
"format_020b__snprintf bench") {
582 volatile size_t res = 0;
583 for(
size_t i = 0; i <
loops; ++i ) {
588 BENCHMARK(
"format_030b_strstream bench") {
589 volatile size_t res = 0;
590 for(
size_t i = 0; i <
loops; ++i ) {
596 BENCHMARK(
"format_040b_stdformat bench") {
597 volatile size_t res = 0;
598 for(
size_t i = 0; i < iterations; ++i ) {
599 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 std::string format_string_v(const std::size_t maxStrLen, const std::string_view format, const Args &...args)
Safely returns a string according to printf() formatting rules and variable number of arguments follo...
constexpr const PResult checkR(const std::string_view fmt, const Targs &...) 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 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.
std::string format_string(const char *format,...)
Returns a string according to printf() formatting rules and variable number of arguments following th...
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.
std::string format_020b_tsnprintf(float fa, float fb, size_t sz1, uint64_t a_u64, int i)
std::string format_030b_strstream(float fa, float fb, size_t sz1, uint64_t a_u64, int i)
constexpr jau::cfmt2::PResult check(const std::string_view fmt, const Targs &...) noexcept
std::string format_010a_vsnprintf(float fa, float fb, size_t sz1, uint64_t a_u64, int i)
std::string format_030a_strstream(float fa, float fb, size_t sz1, uint64_t a_u64, int i)
std::string format_010b_vsnprintf(float fa, float fb, size_t sz1, uint64_t a_u64, int i)
constexpr std::string format_string000(const std::size_t maxStrLen, const std::string_view format, const Args &...args)
size_t test_format(const Func func, bool output)
constexpr std::string format_string_static3(const std::string_view format, const Targs &...args)
constexpr std::string format_string_static2(const std::string_view fmt, const Args &...)
std::string format_000b_vsnprintf(float fa, float fb, size_t sz1, uint64_t a_u64, int i)
std::string format_000a_vsnprintf(float fa, float fb, size_t sz1, uint64_t a_u64, int i)
TEST_CASE("jau::cfmt_00", "[jau][std::string][jau::cfmt]")
constexpr std::string format_020a_tsnprintf(float fa, float fb, size_t sz1, uint64_t a_u64, int i)