jaulib v1.4.1
Jau Support Library (C++, Java, ..)
Loading...
Searching...
No Matches
test_stringfmt01.cpp
Go to the documentation of this file.
1/**
2 * Author: Sven Gothel <sgothel@jausoft.com>
3 * Copyright (c) 2024 Gothel Software e.K.
4 *
5 * ***
6 *
7 * SPDX-License-Identifier: MIT
8 *
9 * This Source Code Form is subject to the terms of the MIT License
10 * If a copy of the MIT was not distributed with this
11 * file, You can obtain one at https://opensource.org/license/mit/.
12 *
13 */
14#include <sys/types.h>
15#include <cassert>
16#include <cinttypes>
17#include <cstdint>
18#include <cstdio>
19#include <cstring>
20#include <iostream>
21#include <sstream>
22#include <string_view>
23#include <type_traits>
24
25#include <jau/basic_types.hpp>
26#include <jau/cpp_lang_util.hpp>
27#include <jau/cpp_pragma.hpp>
28#include <jau/float_types.hpp>
29#include <jau/int_types.hpp>
30#include <jau/string_cfmt.hpp>
31#include <jau/string_util.hpp>
32#include <jau/test/catch2_ext.hpp>
34
35#include "string_cfmt2.hpp"
36
37#ifdef HAS_STD_FORMAT
38 #include <format>
39#endif
40
41using namespace std::literals;
42
43using namespace jau::float_literals;
44
45using namespace jau::int_literals;
46
47template <typename... Args>
48constexpr static std::string format_string000(const std::size_t maxStrLen, const std::string& format, const Args &...args) {
49 std::string str;
50 str.reserve(maxStrLen + 1); // incl. EOS
51 str.resize(maxStrLen); // excl. EOS
52
53 // -Wformat=2 -> -Wformat -Wformat-nonliteral -Wformat-security -Wformat-y2k
54 // -Wformat=2 -Wformat-overflow=2 -Wformat-signedness
57 const size_t nchars = std::snprintf(&str[0], maxStrLen + 1, format.data(), args...);
59 if( nchars < maxStrLen + 1 ) {
60 str.resize(nchars);
61 str.shrink_to_fit();
62 } // else truncated w/ nchars > MaxStrLen
63 return str;
64}
65
66static std::string format_000a_vsnprintf(float fa, float fb, size_t sz1, uint64_t a_u64, int i) {
67 size_t nchars;
68 std::string str;
69 {
70 const size_t bsz = 1024; // including EOS
71 str.reserve(bsz); // incl. EOS
72 str.resize(bsz - 1); // excl. EOS
73
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,
78 i + 1);
79
80 if( nchars < bsz ) {
81 str.resize(nchars);
82 str.shrink_to_fit();
83 return str;
84 }
85 }
86 str.clear(); // error
87 return str;
88}
89
90static std::string format_010a_jaufmtstr(float fa, float fb, size_t sz1, uint64_t a_u64, int i) {
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,
94 i + 1);
95}
96
97static constexpr std::string format_020a_jaufmtstr_n(float fa, float fb, size_t sz1, uint64_t a_u64, int i) {
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,
101 i + 1);
102}
103
104static std::string format_030a_strstream(float fa, float fb, size_t sz1, uint64_t a_u64, int i) {
105 std::ostringstream ss1;
106 ss1 << "format_030a: "
107 << fa + 1.0_f32 << ", "
108 << fb + 1.0_f32 << ", "
109 << sz1 + 1 << ", "
110 << a_u64 + 1_u64 << ", "
111 << i + 1 << "\n";
112 return ss1.str();
113}
114
115#ifdef HAS_STD_FORMAT
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);
119}
120#endif
121
122static std::string format_000b_vsnprintf(float fa, float fb, size_t sz1, uint64_t a_u64, int i) {
123 size_t nchars;
124 std::string str;
125 {
126 const size_t bsz = 1024; // including EOS
127 str.reserve(bsz); // incl. EOS
128 str.resize(bsz - 1); // excl. EOS
129
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,
134 i + 1);
135
136 if( nchars < bsz ) {
137 str.resize(nchars);
138 str.shrink_to_fit();
139 return str;
140 }
141 }
142 str.clear(); // error
143 return str;
144}
145static std::string format_010b_jaufmtstr(float fa, float fb, size_t sz1, uint64_t a_u64, int i) {
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,
149 i + 1);
150}
151
152static std::string format_020b_jaufmtstr_n(float fa, float fb, size_t sz1, uint64_t a_u64, int i) {
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,
156 i + 1);
157}
158
159static std::string format_030b_strstream(float fa, float fb, size_t sz1, uint64_t a_u64, int i) {
160 std::ostringstream ss1;
161 ss1.precision(3);
162 ss1 << "format_030b: "
163 << fa + 1.0_f32 << ", ";
164 ss1.width(3);
165 ss1 << fb + 1.0_f32 << ", "
166 << sz1 + 1 << ", "
167 << a_u64 + 1_u64 << ", ";
168 ss1.width(3);
169 ss1 << i + 1 << "\n";
170 return ss1.str();
171}
172
173#ifdef HAS_STD_FORMAT
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);
177}
178#endif
179
180template <typename Func>
181static size_t test_format(const Func func, bool output) {
182 constexpr float fa = 1.1f, fb = 2.2f;
183 constexpr size_t sz1 = 1;
184 constexpr uint64_t sz2 = 2;
185 constexpr int i = 3;
186
187 const std::string s = func(fa, fb, sz1, sz2, i);
188 volatile size_t l = s.length();
189 if( output ) {
190 std::cout << s;
191 }
192 REQUIRE(0 < l);
193 REQUIRE(l < 1024);
194 return l;
195}
196
197static void format_0a() {
202
203#ifdef HAS_STD_FORMAT
204 test_format(format_040a_stdformat, true);
205#endif
206}
207static void format_0b() {
212
213#ifdef HAS_STD_FORMAT
214 test_format(format_040b_stdformat, true);
215#endif
216}
217
218template <typename... Args>
219static constexpr std::string format_string_static2(const std::string_view fmt, const Args &...) {
220 // constexpr const std::string format2(format);
221 // constexpr const bool b = jau::cfmt::check2<Args...>("Haus"sv);
222 constexpr const bool b = jau::cfmt::check3<Args...>(fmt);
223 static_assert( b );
224 (void)b;
225 return ""; // jau::format_string_v(1024, format, args...);
226}
227
228
229template <typename... Targs>
230static constexpr jau::cfmt2::PResult check(const std::string_view fmt, const Targs &...) noexcept {
231 return jau::cfmt2::impl::checkRec<Targs...>( jau::cfmt2::PResult(fmt) );
232}
233
234template <typename... Targs>
235static constexpr std::string format_string_static3(const std::string_view format, const Targs &...args) {
236 // constexpr const jau::cfmt2::PResult ctx2 = jau::cfmt2::impl::checkRec<Targs...>( jau::cfmt2::PResult(format) );
237 // static_assert( 0 <= jau::cfmt2::impl::checkRec<Targs...>( jau::cfmt2::PResult(format)).argCount() );
238 if( 0 <= jau::cfmt2::impl::checkRec<Targs...>( jau::cfmt2::PResult(format)).argCount() ) {
239 return jau::format_string_n(1024, format, args...);
240 } else {
241 return "";
242 }
243}
244
245
246TEST_CASE("jau::cfmt_00", "[jau][std::string][jau::cfmt]") {
247 char buf[1024];
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;
252 constexpr int i = 3;
253 const float *pf = &fa;
254
255 {
256 constexpr jau::cfmt2::PResult pr = jau::cfmt2::checkR("lala %d", 2);
257 std::cerr << "XXX: " << __LINE__ << ": " << pr << std::endl;
258 static_assert( 0 <= pr.argCount() );
259 }
260 { // 'format_check: %.2f, %2.2f, %zu, %lu, %03d'
261 constexpr jau::cfmt2::PResult pc = jau::cfmt2::checkR("format_check: %.2f, %2.2f, %zu, %" PRIi64 ", %" PRIi64 "d, %" PRIi64 "X, %06" PRIu64 "d, %06" PRIu64 "X, %03d\n",
262 fa, fb, sz1, v_i64, v_i64, v_i64, v_u64, v_u64, i);
263 std::cerr << "XXX: " << __LINE__ << ": " << pc << std::endl;
264 // static_assert( 5 == pc.argCount() );
265 REQUIRE(9 == pc.argCount());
266 }
267 {
268 constexpr jau::cfmt2::PResult pr = jau::cfmt2::checkR("lala %d - end", 2);
269 std::cerr << "XXX: " << __LINE__ << ": " << pr << std::endl;
270 // static_assert( 0 <= pr.argCount() );
271 REQUIRE(0 <= pr.argCount());
272 }
273 {
274 constexpr const bool b1 = jau::cfmt::check("lala %d", 2);
275 static_assert( b1 );
276
277 constexpr const bool b2 = jau::cfmt::check2<int>("lala %d");
278 static_assert( b2 );
279
280 // constexpr jau::cfmt2::PResult pr1 = check(fmt3, 2);
281 constexpr jau::cfmt2::PResult pr1 = check("Hello %d", 2);
282 std::cerr << "XXX: " << __LINE__ << ": " << pr1 << std::endl;
283 static_assert( 0 <= pr1.argCount() );
284
285 std::string s3 = format_string_static3("Hello %d", 2);
286 std::cerr << "XXX: " << __LINE__ << ": " << s3 << std::endl;
287 REQUIRE( s3.length() > 0 );
288
289 // constexpr const std::string f2 = "Hello %d"s;
290 // constexpr const std::string_view f2v = "Hello %d"sv;
291 // format_string_static2(f2v, (int)2);
292 // constexpr const std::string_view f3 = "Hello %d"sv;
293 // constexpr const char f3[] = "Hello %d";
294 // format_string_static2("Hello %d"sv, (int)2);
295 }
296 {
297 static_assert(false == std::is_signed_v<const float*>);
298 static_assert(false == std::is_unsigned_v<const float*>);
299
300 static_assert(true == std::is_signed_v<float>);
301 static_assert(false == std::is_unsigned_v<float>);
302 }
303 {
304 using E = int;
305 using T = unsigned int;
306 // using U = std::conditional_t<std::is_unsigned_v<T>, std::make_signed_t<T>, T>; // triggers the instantiating the 'other' case and hence fails
307 using U = typename std::conditional_t<std::is_unsigned_v<T>, std::make_signed<T>, std::type_identity<T>>::type; // NOLINT
308 static_assert( std::is_same_v<T, T> );
309 static_assert( std::is_same_v<E, U> );
310 }
311 {
312 using E = float;
313 using T = float;
314 // using U = std::conditional_t<std::is_unsigned_v<T>, std::make_signed_t<T>, T>; // triggers the instantiating the 'other' case and hence fails
315 using U = typename std::conditional_t<std::is_unsigned_v<T>, std::make_signed<T>, std::type_identity<T>>::type; // NOLINT
316 static_assert( std::is_same_v<T, T> );
317 static_assert( std::is_same_v<E, U> );
318 }
319 {
320 // we shall ignore signedness like snprintf
321 static_assert(true == jau::cfmt::check(" int -> int %d", 1));
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));
324 static_assert(true == jau::cfmt::check(" int -> unsigned int %u", 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));
327 static_assert(true == jau::cfmt::check(" char -> int %d", (char)1)); // integral target type > given type
328 {
329 jau::cfmt::PResult res = jau::cfmt::checkR(" error long -> int %d", (long)1);
330 // if( res.error() ) {
331 printf("XXX: sizeof(long) %zu, %s\n", sizeof(long), res.toString().c_str());
332 }
333 if constexpr ( sizeof(long) <= 4 ) {
334 assert(true == jau::cfmt::check(" OK long(4) -> int %d", (long)1)); // NOLINT(misc-static-assert)
335 } else {
336 assert(false == jau::cfmt::check(" error long(8) -> int %d", (long)1)); // NOLINT(misc-static-assert); error: integral target type < given type
337 }
338
339 static_assert(true == jau::cfmt::check(" %d", i));
340 static_assert(true == jau::cfmt::check(" %f", fa));
341 static_assert(true == jau::cfmt::check(" %zd", (ssize_t)1));
342 static_assert(true == jau::cfmt::check(" %zu", (size_t)1));
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));
345 static_assert(true == jau::cfmt::check(" %p", pf));
346 // static_assert(true == jau::cfmt::check(" %s", "lala"));
347
348 static_assert(0 == jau::cfmt::checkR("Hello World").argCount());
349 static_assert(1 == jau::cfmt::checkR("Hello World %d", 1).argCount());
350 static_assert(1 == jau::cfmt::checkR("Hello 1 %d", i).argCount());
351 static_assert(true == jau::cfmt::check("Hello World"));
352 static_assert(true == jau::cfmt::check("Hello World %d", 1));
353 static_assert(true == jau::cfmt::check("Hello 1 %d", i));
354
355 static_assert(1 == jau::cfmt::checkR("Hello 1 %.2f", fa).argCount());
356 static_assert(1 == jau::cfmt::checkR("Hello 1 %.2f - end", fa).argCount());
357 static_assert(2 == jau::cfmt::checkR("Hello 1 %.2f, 2 %2.2f - end", fa, fb).argCount());
358 static_assert(3 == jau::cfmt::checkR("Hello 1 %.2f , 2 %2.2f, 3 %zu - end", fa, fb, sz1).argCount());
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());
361
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());
364
365 // static_assert(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());
366 // static_assert(1 == jau::cfmt::checkR(" %s", "lala").argCount());
367
368 static_assert(false == jau::cfmt::check("Hello World %"));
369 static_assert(0 > jau::cfmt::checkR("Hello World %").argCount());
370 static_assert(0 > jau::cfmt::checkR("Hello 1 %d").argCount());
371 static_assert(-1 == jau::cfmt::checkR("Hello 1 %d", fa).argCount());
372 if constexpr ( sizeof(long) <= 4 ) {
373 assert( 1 == jau::cfmt::checkR("Hello 1 %d", sz1).argCount()); // NOLINT(misc-static-assert)
374 } else {
375 assert(-1 == jau::cfmt::checkR("Hello 1 %d", sz1).argCount()); // NOLINT(misc-static-assert)
376 }
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));
381
382 {
383 const std::string s = jau_format_string_static("format_020a: %f, %f, %zu, %" PRIu64 ", %d\n",
384 fa + 1.0_f32, fb + 1.0_f32, sz1 + 1, v_i64 + 1_u64, i + 1);
385 REQUIRE( s.size() > 0 );
386 }
387 {
388 std::string s0 = jau::format_string("Hello %d", 1);
389 REQUIRE( s0.size() > 0 );
390 // const std::string s1 = jau::format_string<"Hello %d">(1);
391 REQUIRE_THROWS_AS( s0 = jau::format_string("Hello %d", 1.0f), jau::IllegalArgumentError);
392 }
393 }
394 {
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" );
400 jau_format_string_static("Hello %d", (int)2);
401 jau_format_string_static("Hello %d", (unsigned int)2);
402 jau_format_string_static("Hello %u", (unsigned int)2);
403 jau_format_string_static("Hello %u", (int)2);
404
405 // constexpr std::string_view fmt2 = "Hello %d"sv;
406 // format_string_static2("Hello %d"sv, (int)2);
407 // format_string_static2("Hello %d"s, (int)2);
408
409 constexpr jau::cfmt::PResult c1 = jau::cfmt::checkR("Hello %u", (unsigned int)1);
410 std::cerr << "XXX: " << __LINE__ << ": " << c1 << std::endl;
411 REQUIRE(false == c1.error());
412 }
413 {
414 constexpr jau::cfmt::PResult c1 = jau::cfmt::checkR("Hello World");
415 REQUIRE(false == c1.error());
416 REQUIRE(0 == c1.argCount());
417 REQUIRE(0 == jau::cfmt::checkR("Hello World").argCount());
418 constexpr jau::cfmt::PResult c3 = jau::cfmt::checkR("Hello 1 %d", i);
419 REQUIRE(false == c3.error());
420 REQUIRE(1 == c3.argCount());
421 REQUIRE(9 == std::snprintf(buf, sizeof(buf), "Hello 1 %d", i));
422
423 // `Hello 1 %.2f, 2 %2.2f, 3 %zu, 4 %li, 5 %03d, 6 %p - end`
424 REQUIRE(1 == jau::cfmt::checkR("Hello 1 %.2f", fa).argCount());
425 REQUIRE(1 == jau::cfmt::checkR("Hello 1 %.2f - end", fa).argCount());
426
427 // 'Hello 1 %.2f, 2 %2.2f - end'
428 jau::cfmt::PResult pc = jau::cfmt::checkR("Hello 1 %.2f, 2 %2.2f - end", fa, fb);
429 std::cerr << "XXX: " << __LINE__ << ": " << pc << std::endl;
430 REQUIRE(2 == jau::cfmt::checkR("Hello 1 %.2f, 2 %2.2f - end", fa, fb).argCount());
431
432 // `Hello 1 %.2f, 2 %2.2f, 3 %zu - end`
433 pc = jau::cfmt::checkR("Hello 1 %.2f, 2 %2.2f, 3 %zu - end", fa, fb, sz1);
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());
436
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());
440
441 // REQUIRE(13 == std::snprintf(buf, sizeof(buf), "Hello World %").argCount());
442 REQUIRE(0 > jau::cfmt::checkR("Hello World %").argCount());
443 REQUIRE(0 > jau::cfmt::checkR("Hello 1 %d").argCount());
444 REQUIRE(-1 == jau::cfmt::checkR("Hello 1 %d", fa).argCount());
445 if constexpr ( sizeof(long) <= 4 ) {
446 REQUIRE( 1 == jau::cfmt::checkR("Hello 1 %d", sz1).argCount());
447 } else {
448 REQUIRE(-1 == jau::cfmt::checkR("Hello 1 %d", sz1).argCount());
449 }
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());
452 }
453}
454
455TEST_CASE("jau::cfmt_01", "[jau][std::string][format_string]") {
456 format_0a();
457 format_0b();
458}
459
460/// Execute with `test_stringfmt --perf_analysis`
461TEST_CASE("jau::cfmt_10", "[benchmark][jau][std::string][format_string]") {
462 const size_t loops = 1000; // catch_auto_run ? 1000 : 1000;
463 WARN("Benchmark with " + std::to_string(loops) + " loops");
464 CHECK(true);
465
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;
470 size_t sz1 = 1;
471 uint64_t sz2 = 2;
472 int i1 = 3;
473
474 size_t r = jau::cfmt::checkR("format_check: %.2f, %2.2f, %zu, %" PRIu64 ", %03d\n",
475 fa, fb, sz1, sz2, i1).argCount();
476 REQUIRE(5 == r);
477 res = res + r;
478 }
479 return res;
480 };
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 ) {
486 REQUIRE(5 == r);
487 res = res + r;
488 }
489 return res;
490 };
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 ) {
496 REQUIRE(5 == r);
497 res = res + r;
498 }
499 return res;
500 };
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;
508
509 constexpr jau::cfmt::PResult pc = jau::cfmt::checkR("format_check: %.2f, %2.2f, %zu, %" PRIu64 ", %03d\n",
510 fa, fb, sz1, sz2, i1);
511 constexpr size_t r = pc.argCount();
512 REQUIRE(5 == r);
513 res = res + r;
514 }
515 return res;
516 };
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;
524
525 constexpr jau::cfmt2::PResult pc = jau::cfmt2::checkR("format_check: %.2f, %2.2f, %zu, %" PRIu64 ", %03d\n",
526 fa, fb, sz1, sz2, i1);
527 constexpr size_t r = pc.argCount();
528 REQUIRE(5 == r);
529 res = res + r;
530 }
531 return res;
532 };
533 BENCHMARK("format_000a_vsnprintf bench") {
534 volatile size_t res = 0;
535 for( size_t i = 0; i < loops; ++i ) {
536 res = res + test_format(format_000a_vsnprintf, false);
537 }
538 return res;
539 };
540 BENCHMARK("format_010a_jaufmtstr bench") {
541 volatile size_t res = 0;
542 for( size_t i = 0; i < loops; ++i ) {
543 res = res + test_format(format_010a_jaufmtstr, false);
544 }
545 return res;
546 };
547 BENCHMARK("format_020a jau macro bench") {
548 volatile size_t res = 0;
549 for( size_t i = 0; i < loops; ++i ) {
550 {
551 constexpr float fa = 1.1f, fb = 2.2f;
552 constexpr size_t sz1 = 1;
553 constexpr uint64_t a_u64 = 2;
554 constexpr int j = 3;
555 const std::string s = jau_format_string_static("format_020a: %f, %f, %zu, %" PRIu64 ", %d\n",
556 fa + 1.0_f32, fb + 1.0_f32, sz1 + 1, a_u64 + 1_u64, j + 1);
557 res = res + s.length();
558 }
559 }
560 return res;
561 };
562 BENCHMARK("fmt__020a cnstexpr-in bench") {
563 volatile size_t res = 0;
564 for( size_t i = 0; i < loops; ++i ) {
565 {
566 constexpr float fa = 1.1f, fb = 2.2f;
567 constexpr size_t sz1 = 1;
568 constexpr uint64_t a_u64 = 2;
569 constexpr int j = 3;
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) ) {
572 std::string s;
573 s.reserve(1023 + 1); // incl. EOS
574 s.resize(1023); // excl. EOS
575
576 // -Wformat=2 -> -Wformat -Wformat-nonliteral -Wformat-security -Wformat-y2k
577 // -Wformat=2 -Wformat-overflow=2 -Wformat-signedness
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 ) {
584 s.resize(nchars);
585 s.shrink_to_fit();
586 } // else truncated w/ nchars > MaxStrLen
587 res = res + s.length();
588 }
589 }
590 }
591 return res;
592 };
593 BENCHMARK("fmt__020a_jaufmtstr_n bench") {
594 volatile size_t res = 0;
595 for( size_t i = 0; i < loops; ++i ) {
596 res = res + test_format(format_020a_jaufmtstr_n, false);
597 }
598 return res;
599 };
600 BENCHMARK("format_030a_strstream bench") {
601 volatile size_t res = 0;
602 for( size_t i = 0; i < loops; ++i ) {
603 res = res + test_format(format_030a_strstream, false);
604 }
605 return res;
606 };
607#ifdef HAS_STD_FORMAT
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);
612 }
613 return res;
614 };
615#endif
616
617 BENCHMARK("format_000b_vsnprintf__ bench") {
618 volatile size_t res = 0;
619 for( size_t i = 0; i < loops; ++i ) {
620 res = res + test_format(format_000b_vsnprintf, false);
621 }
622 return res;
623 };
624 BENCHMARK("format_010b_jaufmtstr__ bench") {
625 volatile size_t res = 0;
626 for( size_t i = 0; i < loops; ++i ) {
627 res = res + test_format(format_010b_jaufmtstr, false);
628 }
629 return res;
630 };
631 BENCHMARK("format_020b_jaufmtstr_n bench") {
632 volatile size_t res = 0;
633 for( size_t i = 0; i < loops; ++i ) {
634 res = res + test_format(format_020b_jaufmtstr_n, false);
635 }
636 return res;
637 };
638 BENCHMARK("format_030b_strstream__ bench") {
639 volatile size_t res = 0;
640 for( size_t i = 0; i < loops; ++i ) {
641 res = res + test_format(format_030b_strstream, false);
642 }
643 return res;
644 };
645#ifdef HAS_STD_FORMAT
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);
650 }
651 return res;
652 };
653#endif
654}
#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
static int loops
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 void format_0b()
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 void format_0a()
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)