jaulib v1.4.1-14-g15926ba
Jau Support Library (C++, Java, ..)
Loading...
Searching...
No Matches
test_stringfmt_format.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 <string_view>
22
23#include <jau/basic_types.hpp>
24#include <jau/cpp_lang_util.hpp>
25#include <jau/cpp_pragma.hpp>
26#include <jau/float_types.hpp>
27#include <jau/int_types.hpp>
28#include <jau/string_cfmt.hpp>
30#include <jau/string_util.hpp>
31#include <jau/test/catch2_ext.hpp>
32#include <jau/type_concepts.hpp>
34
35#ifdef HAS_STD_FORMAT
36 #include <format>
37#endif
38
39using namespace std::literals;
40
41using namespace jau::float_literals;
42
43using namespace jau::int_literals;
44
45TEST_CASE("parse: width precision from format", "[jau][std::string][jau::cfmt]") {
46 using namespace jau::cfmt;
47
48 //
49 // Single feature: Width / Precision
50 //
51 {
52 std::string s;
53 jau::cfmt::Result r = jau::cfmt::formatR(s,"%" PRIi64, (int64_t)1);
54 std::cerr << "FormatResult " << r << "\n";
55 REQUIRE( true == r.success());
56 REQUIRE( 1 == r.argumentCount());
57 REQUIRE( flags_t::none == r.opts().flags);
58 REQUIRE( false == r.opts().width_set);
59 REQUIRE( 0 == r.opts().width);
60 REQUIRE( false == r.opts().precision_set);
61 REQUIRE( 0 == r.opts().precision);
63 }
64 {
65 std::string s;
66 jau::cfmt::Result r = jau::cfmt::formatR(s,"%23" PRIi64, (int64_t)1);
67 std::cerr << "FormatResult " << r << "\n";
68 REQUIRE( true == r.success());
69 REQUIRE( 1 == r.argumentCount());
70 REQUIRE( flags_t::none == r.opts().flags);
71 REQUIRE( true == r.opts().width_set);
72 REQUIRE( 23 == r.opts().width);
73 REQUIRE( false == r.opts().precision_set);
74 REQUIRE( 0 == r.opts().precision);
76 }
77 {
78 std::string s;
79 jau::cfmt::Result r = jau::cfmt::formatR(s,"%.12" PRIi64, (int64_t)1);
80 std::cerr << "FormatResult " << r << "\n";
81 REQUIRE( true == r.success());
82 REQUIRE( 1 == r.argumentCount());
83 REQUIRE( flags_t::none == r.opts().flags);
84 REQUIRE( false == r.opts().width_set);
85 REQUIRE( 0 == r.opts().width);
86 REQUIRE( true == r.opts().precision_set);
87 REQUIRE( 12 == r.opts().precision);
89 }
90 {
91 std::string s;
92 jau::cfmt::Result r = jau::cfmt::formatR(s,"%23.12" PRIi64, (int64_t)1);
93 std::cerr << "FormatResult " << r << "\n";
94 REQUIRE( true == r.success());
95 REQUIRE( 1 == r.argumentCount());
96 REQUIRE( flags_t::none == r.opts().flags);
97 REQUIRE( true == r.opts().width_set);
98 REQUIRE( 23 == r.opts().width);
99 REQUIRE( true == r.opts().precision_set);
100 REQUIRE( 12 == r.opts().precision);
101 REQUIRE( jau::cfmt::plength_t::l == r.opts().length_mod);
102 }
103 {
104 std::string s;
105 jau::cfmt::Result r = jau::cfmt::formatR(s,"%#-+0 23.12" PRIi64, (int64_t)1);
106 std::cerr << "FormatResult " << r << "\n";
107 REQUIRE( true == r.success());
108 REQUIRE( 1 == r.argumentCount());
109 REQUIRE( ( flags_t::left | flags_t::plus ) == r.opts().flags);
110 REQUIRE( true == r.opts().width_set);
111 REQUIRE( 23 == r.opts().width);
112 REQUIRE( true == r.opts().precision_set);
113 REQUIRE( 12 == r.opts().precision);
114 REQUIRE( jau::cfmt::plength_t::l == r.opts().length_mod);
115 }
116}
117
118TEST_CASE("parse: width precision from arg", "[jau][std::string][jau::cfmt]") {
119 using namespace jau::cfmt;
120
121 {
122 jau_string_check("%*" PRIi64, 21, (int64_t)1);
123 jau_string_checkLine("%*" PRIi64, 21, (int64_t)1);
124 std::string s;
125 jau::cfmt::Result r = jau::cfmt::formatR(s,"%*" PRIi64, 21, (int64_t)1);
126 std::cerr << "FormatResult " << r << "\n";
127 REQUIRE( true == r.success());
128 REQUIRE( 2 == r.argumentCount());
129 REQUIRE( flags_t::none == r.opts().flags);
130 REQUIRE( true == r.opts().width_set);
131 REQUIRE( 21 == r.opts().width);
132 REQUIRE( false == r.opts().precision_set);
133 REQUIRE( 0 == r.opts().precision);
134 REQUIRE( jau::cfmt::plength_t::l == r.opts().length_mod);
135 }
136 {
137 std::string s;
138 jau::cfmt::Result r = jau::cfmt::formatR(s,"%.*" PRIi64, 12, (int64_t)1);
139 std::cerr << "FormatResult " << r << "\n";
140 REQUIRE( true == r.success());
141 REQUIRE( 2 == r.argumentCount());
142 REQUIRE( flags_t::none == r.opts().flags);
143 REQUIRE( false == r.opts().width_set);
144 REQUIRE( 0 == r.opts().width);
145 REQUIRE( true == r.opts().precision_set);
146 REQUIRE( 12 == r.opts().precision);
147 REQUIRE( jau::cfmt::plength_t::l == r.opts().length_mod);
148 }
149 {
150 std::string s;
151 jau::cfmt::Result r = jau::cfmt::formatR(s,"%*.*" PRIi64, 23, 12, (int64_t)1);
152 std::cerr << "FormatResult " << r << "\n";
153 REQUIRE( true == r.success());
154 REQUIRE( 3 == r.argumentCount());
155 REQUIRE( flags_t::none == r.opts().flags);
156 REQUIRE( true == r.opts().width_set);
157 REQUIRE( 23 == r.opts().width);
158 REQUIRE( true == r.opts().precision_set);
159 REQUIRE( 12 == r.opts().precision);
160 REQUIRE( jau::cfmt::plength_t::l == r.opts().length_mod);
161 }
162
163 {
164 std::string s;
165 jau::cfmt::Result r = jau::cfmt::formatR(s,"%-*.12" PRIi64, 23, (int64_t)1);
166 std::cerr << "FormatResult " << r << "\n";
167 REQUIRE( true == r.success());
168 REQUIRE( 2 == r.argumentCount());
169 REQUIRE( flags_t::left == r.opts().flags);
170 REQUIRE( true == r.opts().width_set);
171 REQUIRE( 23 == r.opts().width);
172 REQUIRE( true == r.opts().precision_set);
173 REQUIRE( 12 == r.opts().precision);
174 REQUIRE( jau::cfmt::plength_t::l == r.opts().length_mod);
175 }
176 {
177 std::string s;
178 jau::cfmt::Result r = jau::cfmt::formatR(s,"%+.*" PRIi64, 12, (int64_t)1);
179 std::cerr << "FormatResult " << r << "\n";
180 REQUIRE( true == r.success());
181 REQUIRE( 2 == r.argumentCount());
182 REQUIRE( flags_t::plus == r.opts().flags);
183 REQUIRE( false == r.opts().width_set);
184 REQUIRE( 0 == r.opts().width);
185 REQUIRE( true == r.opts().precision_set);
186 REQUIRE( 12 == r.opts().precision);
187 REQUIRE( jau::cfmt::plength_t::l == r.opts().length_mod);
188 }
189}
190
191template <typename... Args>
192static void checkFormat(int line, const char *fmt, const Args &...args) {
193 std::string exp = jau::unsafe::format_string(fmt, args...);
194 // std::string has = jau::format_string(fmt, args...);
195 std::string has;
196 jau::cfmt::Result r = jau::cfmt::formatR(has, fmt, args...);
197 std::cerr << "FormatResult @ " << line << ": " << r << "\n";
198 std::cerr << "FormatResult @ " << line << ": exp `" << exp << "`, has `" << has << "`\n\n";
199 CHECK( true == r.success());
200 CHECK( sizeof...(args) == r.argumentCount());
201 CHECK(exp == has);
202}
203
204TEST_CASE("single_conversion", "[jau][std::string][jau::cfmt]") {
205 // type conversion
206 int32_t i32 = -1234;
207 int32_t i32_u = 1234;
208 uint32_t u32 = 1234;
209 float f32 = 123.45f; // 42.14f;
210 double f64 = 123.45; // 42.1456;
211 void *p1a = (void *)0xaabbccdd_u64; // NOLINT
212 void *p1b = (void *)0x11223344aabbccdd_u64; // NOLINT
213 void *p2a = (void *)0x112233aabbccdd_u64; // NOLINT
214 void *p2b = (void *)0xaabbcc_u64; // NOLINT
215 void *p3a = (void *)0x112233aabbccdd_u64; // NOLINT
216 void *p3b = (void *)0xaabbcc_u64; // NOLINT
217 const char sl1[] = "Hallo";
218 std::string s2 = "World";
219 std::string_view s2sv = s2;
220 const char *s2p = s2.c_str();
221
222 {
223 double value = 123.45;
224 const int expval = std::ilogb(value);
225 const double frac = value / std::scalbn(1.0, expval);
226 const uint64_t significand = jau::significand_raw(value);
227 fprintf(stderr, "JAU:10 v %f = %f * 2^%d -> 0x%0" PRIx64 "p%d\n", value, frac, expval, significand, expval);
228
229 const int32_t expval2 = jau::exponent_unbiased(value);
230 fprintf(stderr, "JAU:11 v %f = %f * 2^%d -> 0x%0" PRIx64 "p%d\n", value, frac, expval2, significand, expval2);
231 }
232 {
233 float value = 123.45f;
234 const int expval = std::ilogb(value);
235 const double frac = value / std::scalbn(1.0, expval);
236 const uint32_t significand = jau::significand_raw(value);
237 fprintf(stderr, "JAU:20 v %f = %f * 2^%d -> 0x%0" PRIx32 "p%d\n", value, frac, expval, significand, expval);
238
239 const int32_t expval2 = jau::exponent_unbiased(value);
240 fprintf(stderr, "JAU:21 v %f = %f * 2^%d -> 0x%0" PRIx32 "p%d\n", value, frac, expval2, significand, expval2);
241 }
242 {
243 float ivalue = 123.45f;
244 double value = ivalue;
245 const int expval = std::ilogb(value);
246 const double frac = value / std::scalbn(1.0, expval);
247 const uint64_t significand = jau::significand_raw(value) >> (32-4);
248 fprintf(stderr, "JAU:30 v %f = %f * 2^%d -> 0x%0" PRIx64 "p%d\n", value, frac, expval, significand, expval);
249
250 const int32_t expval2 = jau::exponent_unbiased(value);
251 fprintf(stderr, "JAU:31 v %f = %f * 2^%d -> 0x%0" PRIx64 "p%d\n", value, frac, expval2, significand, expval2);
252 }
253 checkFormat(__LINE__, "%%");
254
255 checkFormat(__LINE__, "%c", 'Z');
256 checkFormat(__LINE__, "%s", "Hello World");
257 checkFormat(__LINE__, "%s", sl1);
258 {
259 // impossible for vsnprintf (via jau::unsafe::format_string)
260 CHECK( 1 == jau::cfmt::check("%s", s2));
261 CHECK( "World" == jau::format_string("%s", s2));
262 CHECK( 1 == jau::cfmt::check("%s", s2sv));
263 CHECK( "World" == jau::format_string("%s", s2sv));
264 }
265 checkFormat(__LINE__, "%p", &i32);
266 checkFormat(__LINE__, "p1a %p %0p", p1a, p1a);
267 checkFormat(__LINE__, "p1b %p %0p", p1b, p1b);
268 checkFormat(__LINE__, "p2a %p %0p", p2a, p2a);
269 checkFormat(__LINE__, "p2b %p %0p", p2b, p2b);
270 checkFormat(__LINE__, "p3a %p %0p", p3a, p3a);
271 checkFormat(__LINE__, "p3b %p %0p", p3b, p3b);
272 checkFormat(__LINE__, "p3b %p %0p", &i32_u, &i32_u);
273 checkFormat(__LINE__, "p3b %p %0p", &sl1, &sl1);
274 checkFormat(__LINE__, "p3b %p %0p", s2p, s2p);
275 checkFormat(__LINE__, "%p", (void *)nullptr);
276 checkFormat(__LINE__, "%s", (char *)nullptr);
277
278 checkFormat(__LINE__, "%d", i32);
279
280 checkFormat(__LINE__, "%o", u32);
281 checkFormat(__LINE__, "%x", u32);
282 checkFormat(__LINE__, "%X", u32);
283 checkFormat(__LINE__, "%u", u32);
284 checkFormat(__LINE__, "%o", i32_u);
285 checkFormat(__LINE__, "%x", i32_u);
286 checkFormat(__LINE__, "%X", i32_u);
287 checkFormat(__LINE__, "%u", i32_u);
288
289 checkFormat(__LINE__, "%f", f64);
290 checkFormat(__LINE__, "%e", f64);
291 checkFormat(__LINE__, "%E", f64);
292 checkFormat(__LINE__, "%a", f64);
293 checkFormat(__LINE__, "%A", f64);
294 // checkFormat(__LINE__, "%g", f64);
295 // checkFormat(__LINE__, "%G", f64);
296
297 checkFormat(__LINE__, "%f", f32);
298 checkFormat(__LINE__, "%e", f32);
299 checkFormat(__LINE__, "%E", f32);
300 checkFormat(__LINE__, "%a", f32);
301 checkFormat(__LINE__, "%A", f32);
302 // checkFormat(__LINE__, "%g", f32);
303 // checkFormat(__LINE__, "%G", f32);
304
305 checkFormat(__LINE__, "%dZZZ", i32);
306 checkFormat(__LINE__, "%dZZ", i32);
307 checkFormat(__LINE__, "%dZ", i32);
308 checkFormat(__LINE__, "Z%dZ Z%dZ", i32, i32);
309 checkFormat(__LINE__, "Z%-6dZ Z%6dZ", i32, i32);
310
311 checkFormat(__LINE__, "%#020x", 305441741);
312 checkFormat(__LINE__, "%zd", 2147483647L);
313
314 static_assert(0 < jau::cfmt::checkLine("%zd", 2147483647UL)); // failed intentionally unsigned -> signed
315 checkFormat(__LINE__, "%zu", 2147483647UL);
316
317 static_assert(0 == jau::cfmt::checkLine("%s", (const char*)"Test"));
318 static_assert(0 == jau::cfmt::checkLine("%s", "Test"));
319 checkFormat(__LINE__, "%s", "Test");
320 {
321 const char *str = nullptr;
322 size_t str_len = 2;
323 const char limiter = '3';
324 const char *limiter_pos = nullptr;
325 char *endptr = nullptr;
326
327 jau_string_check("Value end not '%c' @ idx %zd, %p != %p, in: %p '%s' len %zu", limiter, endptr - str, endptr, limiter_pos, str, str, str_len);
328 jau_string_checkLine("Value end not '%c' @ idx %zd, %p != %p, in: %p '%s' len %zu", limiter, endptr - str, endptr, limiter_pos, str, str, str_len);
329 }
330 // bool
331 {
332 jau_string_check("%d", (bool)true);
333 jau_string_checkLine("%d", (bool)true);
334 jau_string_check("%u", (bool)true);
335 jau_string_checkLine("%u", (bool)true);
336 // jau_string_check("%s", (bool)true);
337 // jau_string_checkLine("%s", (bool)true);
338 }
339
340 // enums
341 {
342 enum enum1_unsigned_t { jau1_alpha, jau1_beta, jau1_gamma }; ///< unsigned
343 enum1_unsigned_t e1_u = jau1_alpha;
344
345 enum enum2_signed_t { jau2_alpha=-1, jau_beta, jau_gamma }; ///< signed
346 enum2_signed_t e2_s = jau2_alpha;
347
348 enum class enum3_signed_t { alpha=-1, beta, gamma }; ///< signed
349 enum3_signed_t e3_s = enum3_signed_t::alpha;
350
351 typedef enum { ///< unsigned
352 jau_CAP_CLEAR=0,
353 jau_CAP_SET=1
354 } enum4_unsigned_t;
355 enum4_unsigned_t e4_u = jau_CAP_CLEAR;
356
357 static_assert(true == std::is_enum_v<decltype(e1_u)>);
358 static_assert(true == std::is_unsigned_v<std::underlying_type_t<decltype(e1_u)>>);
359
360 static_assert(true == std::is_enum_v<decltype(e2_s)>);
361 static_assert(true == std::is_signed_v<std::underlying_type_t<decltype(e2_s)>>);
362
363 static_assert(true == std::is_enum_v<decltype(e3_s)>);
364 static_assert(true == std::is_signed_v<std::underlying_type_t<decltype(e3_s)>>);
365
366 static_assert(true == std::is_enum_v<decltype(e4_u)>);
367 static_assert(true == std::is_unsigned_v<std::underlying_type_t<decltype(e4_u)>>);
368
369 jau_format_string("Enum %u, %d, %d, %u\n", e1_u, e2_s, e3_s, e4_u);
370 jau_string_checkLine("%u, %d, %d, %u\n", e1_u, e2_s, e3_s, e4_u);
371
372 static_assert(4 == jau::cfmt::check("%u, %d, %d, %u\n", e1_u, e2_s, e3_s, e4_u));
373 static_assert(0 == jau::cfmt::checkLine("%u, %u, %d, %u\n", e1_u, e2_s, e3_s, e4_u));
374
375 static_assert(0 == jau::cfmt::checkLine("%u\n", e1_u)); // unsigned -> unsigned OK
376 static_assert(0 < jau::cfmt::checkLine("%d\n", e1_u)); // unsigned -> signed ERROR
377 static_assert(0 == jau::cfmt::checkLine("%u\n", e2_s)); // signed -> unsigned OK
378 }
379}
380
381TEST_CASE("thousands_flag", "[jau][std::string][jau::cfmt][flags]" ) {
382 //
383 // thousand flag ' or ,
384 //
385 jau_string_checkLine("%'d", 1);
386 jau_string_checkLine("%,d", 1);
387
388 CHECK("1" == jau::format_string("%'d", 1));
389 CHECK("10" == jau::format_string("%#'d", 10));
390 CHECK("100" == jau::format_string("%,d", 100));
391 CHECK("1'000" == jau::format_string("%'d", 1000));
392 CHECK("1'000'000" == jau::format_string("%,d", 1000000));
393 CHECK("+1'000'000" == jau::format_string("%'+d", 1000000));
394 CHECK("-1'000'000" == jau::format_string("%,d", -1000000));
395 CHECK("-1'000'000" == jau::format_string("%'d", -1000000));
396}
397
398TEST_CASE("binary", "[jau][std::string][jau::cfmt][flags]" ) {
399 jau_string_checkLine("%b", 1_u32);
400
401 CHECK("0b1" == jau::format_string("%#b", 1_u32));
402 CHECK("0b1010111111111110" == jau::format_string("%#b", 0xaffe_u32));
403 CHECK("1011111011101111" == jau::format_string("%b", 0xbeef_u32));
404}
405
406TEST_CASE("space_flag", "[jau][std::string][jau::cfmt][flags]" ) {
407 std::string buffer;
408
409 buffer = jau::format_string("% d", 42);
410 CHECK(buffer == " 42");
411
412 buffer = jau::format_string("% d", -42);
413 CHECK(buffer == "-42");
414
415 buffer = jau::format_string("% 5d", 42);
416 CHECK(buffer == " 42");
417
418 buffer = jau::format_string("% 5d", -42);
419 CHECK(buffer == " -42"); // "- 42" == " -42"
420
421 buffer = jau::format_string("% 15d", 42);
422 CHECK(buffer == " 42");
423
424 buffer = jau::format_string("% 15d", -42);
425 CHECK(buffer == " -42");
426
427 buffer = jau::format_string("% 15d", -42);
428 CHECK(buffer == " -42");
429
430 buffer = jau::format_string("% 15.3f", -42.987);
431 CHECK(buffer == " -42.987");
432
433 buffer = jau::format_string("% 15.3f", 42.987);
434 CHECK(buffer == " 42.987");
435
436 buffer = jau::format_string("% s", "Hello testing");
437 CHECK(buffer == "Hello testing");
438
439 buffer = jau::format_string("% d", 1024);
440 CHECK(buffer == " 1024");
441
442 buffer = jau::format_string("% d", -1024);
443 CHECK(buffer == "-1024");
444
445 buffer = jau::format_string("% i", 1024);
446 CHECK(buffer == " 1024");
447
448 buffer = jau::format_string("% i", -1024);
449 CHECK(buffer == "-1024");
450
451 buffer = jau::format_string("% u", 1024);
452 CHECK(buffer == "1024");
453
454 buffer = jau::format_string("% u", 4294966272U);
455 CHECK(buffer == "4294966272");
456
457 buffer = jau::format_string("% o", 511);
458 CHECK(buffer == "777");
459
460 buffer = jau::format_string("% o", 4294966785U);
461 CHECK(buffer == "37777777001");
462
463 buffer = jau::format_string("% x", 305441741);
464 CHECK(buffer == "1234abcd");
465
466 buffer = jau::format_string("% x", 3989525555U);
467 CHECK(buffer == "edcb5433");
468
469 buffer = jau::format_string("% X", 305441741);
470 CHECK(buffer == "1234ABCD");
471
472 buffer = jau::format_string("% X", 3989525555U);
473 CHECK(buffer == "EDCB5433");
474
475 buffer = jau::format_string("% c", 'x');
476 CHECK(buffer == "x");
477}
478
479TEST_CASE("plus_flag", "[jau][std::string][jau::cfmt][flags]" ) {
480 std::string buffer;
481
482 buffer = jau::format_string("%+d", 42);
483 CHECK(buffer == "+42");
484
485 buffer = jau::format_string("%+d", -42);
486 CHECK(buffer == "-42");
487
488 buffer = jau::format_string("%+5d", 42);
489 CHECK(buffer == " +42");
490
491 buffer = jau::format_string("%+5d", -42);
492 CHECK(buffer == " -42");
493
494 buffer = jau::format_string("%+15d", 42);
495 CHECK(buffer == " +42");
496
497 buffer = jau::format_string("%+15d", -42);
498 CHECK(buffer == " -42");
499
500 buffer = jau::format_string("%+s", "Hello testing");
501 CHECK(buffer == "Hello testing");
502
503 buffer = jau::format_string("%+d", 1024);
504 CHECK(buffer == "+1024");
505
506 buffer = jau::format_string("%+d", -1024);
507 CHECK(buffer == "-1024");
508
509 buffer = jau::format_string("%+i", 1024);
510 CHECK(buffer == "+1024");
511
512 buffer = jau::format_string("%+i", -1024);
513 CHECK(buffer == "-1024");
514
515 buffer = jau::format_string("%+u", 1024);
516 CHECK(buffer == "1024");
517
518 buffer = jau::format_string("%+u", 4294966272U);
519 CHECK(buffer == "4294966272");
520
521 buffer = jau::format_string("%+o", 511);
522 CHECK(buffer == "777");
523
524 buffer = jau::format_string("%+o", 4294966785U);
525 CHECK(buffer == "37777777001");
526
527 buffer = jau::format_string("%+x", 305441741);
528 CHECK(buffer == "1234abcd");
529
530 buffer = jau::format_string("%+x", 3989525555U);
531 CHECK(buffer == "edcb5433");
532
533 buffer = jau::format_string("%+X", 305441741);
534 CHECK(buffer == "1234ABCD");
535
536 buffer = jau::format_string("%+X", 3989525555U);
537 CHECK(buffer == "EDCB5433");
538
539 buffer = jau::format_string("%+c", 'x');
540 CHECK(buffer == "x");
541
542 buffer = jau::format_string("%+.0d", 0);
543 CHECK(buffer == "+");
544}
545
546
547TEST_CASE("zero_flag", "[jau][std::string][jau::cfmt][flags]" ) {
548 std::string buffer;
549
550 buffer = jau::format_string("%0d", 42);
551 CHECK(buffer == "42");
552
553 buffer = jau::format_string("%0ld", 42L);
554 CHECK(buffer == "42");
555
556 buffer = jau::format_string("%0d", -42);
557 CHECK(buffer == "-42");
558
559 buffer = jau::format_string("%05d", 42);
560 CHECK(buffer == "00042");
561
562 buffer = jau::format_string("%05d", -42);
563 CHECK(buffer == "-0042");
564
565 buffer = jau::format_string("%015d", 42);
566 CHECK(buffer == "000000000000042");
567
568 buffer = jau::format_string("%015d", -42);
569 CHECK(buffer == "-00000000000042");
570
571 buffer = jau::format_string("%015.2f", 42.1234);
572 CHECK(buffer == "000000000042.12");
573
574 buffer = jau::format_string("%015.3f", 42.9876);
575 CHECK(buffer == "00000000042.988");
576
577 buffer = jau::format_string("%015.5f", -42.9876);
578 CHECK(buffer == "-00000042.98760");
579}
580
581
582TEST_CASE("left_flag", "[jau][std::string][jau::cfmt][flags]" ) {
583 std::string buffer;
584
585 buffer = jau::format_string("%-d", 42);
586 CHECK(buffer == "42");
587
588 buffer = jau::format_string("%-d", -42);
589 CHECK(buffer == "-42");
590
591 buffer = jau::format_string("%-5d", 42);
592 CHECK(buffer == "42 ");
593
594 buffer = jau::format_string("%-5d", -42);
595 CHECK(buffer == "-42 ");
596
597 buffer = jau::format_string("%-15d", 42);
598 CHECK(buffer == "42 ");
599
600 buffer = jau::format_string("%-15d", -42);
601 CHECK(buffer == "-42 ");
602
603 buffer = jau::format_string("%-0d", 42);
604 CHECK(buffer == "42");
605
606 buffer = jau::format_string("%-0d", -42);
607 CHECK(buffer == "-42");
608
609 buffer = jau::format_string("%-05d", 42);
610 CHECK(buffer == "42 ");
611
612 buffer = jau::format_string("%-05d", -42);
613 CHECK(buffer == "-42 ");
614
615 buffer = jau::format_string("%-015d", 42);
616 CHECK(buffer == "42 ");
617
618 buffer = jau::format_string("%-015d", -42);
619 CHECK(buffer == "-42 ");
620
621 buffer = jau::format_string("%0-d", 42);
622 CHECK(buffer == "42");
623
624 buffer = jau::format_string("%0-d", -42);
625 CHECK(buffer == "-42");
626
627 buffer = jau::format_string("%0-5d", 42);
628 CHECK(buffer == "42 ");
629
630 buffer = jau::format_string("%0-5d", -42);
631 CHECK(buffer == "-42 ");
632
633 buffer = jau::format_string("%0-15d", 42);
634 CHECK(buffer == "42 ");
635
636 buffer = jau::format_string("%0-15d", -42);
637 CHECK(buffer == "-42 ");
638
639 buffer = jau::format_string("%0-15.3e", -42.);
640 CHECK(buffer == "-4.200e+01 ");
641
642 buffer = jau::format_string("%0-15.3g", -42.);
643 CHECK(buffer == "-42.0 ");
644}
645
646
647TEST_CASE("hash_flag", "[jau][std::string][jau::cfmt][flags]" ) {
648 std::string buffer;
649
650 buffer = jau::format_string("%#.0x", 0);
651 CHECK(buffer == "");
652 buffer = jau::format_string("%#.1x", 0);
653 CHECK(buffer == "0");
654 buffer = jau::format_string("%#.0llx", (long long)0);
655 CHECK(buffer == "");
656 buffer = jau::format_string("%#.8x", 0x614e);
657 CHECK(buffer == "0x0000614e");
658 buffer = jau::format_string("%#b", 6);
659 CHECK(buffer == "0b110");
660}
661
662
663TEST_CASE("specifier", "[jau][std::string][jau::cfmt][specifier]" ) {
664 std::string buffer;
665
666 buffer = jau::format_string("Hello testing");
667 CHECK(buffer == "Hello testing");
668
669 buffer = jau::format_string("%s", "Hello testing");
670 CHECK(buffer == "Hello testing");
671
672 buffer = jau::format_string("%d", 1024);
673 CHECK(buffer == "1024");
674
675 buffer = jau::format_string("%d", -1024);
676 CHECK(buffer == "-1024");
677
678 buffer = jau::format_string("%i", 1024);
679 CHECK(buffer == "1024");
680
681 buffer = jau::format_string("%i", -1024);
682 CHECK(buffer == "-1024");
683
684 buffer = jau::format_string("%u", 1024);
685 CHECK(buffer == "1024");
686
687 buffer = jau::format_string("%u", 4294966272U);
688 CHECK(buffer == "4294966272");
689
690 buffer = jau::format_string("%o", 511);
691 CHECK(buffer == "777");
692
693 buffer = jau::format_string("%o", 4294966785U);
694 CHECK(buffer == "37777777001");
695
696 buffer = jau::format_string("%x", 305441741);
697 CHECK(buffer == "1234abcd");
698
699 buffer = jau::format_string("%x", 3989525555U);
700 CHECK(buffer == "edcb5433");
701
702 buffer = jau::format_string("%X", 305441741);
703 CHECK(buffer == "1234ABCD");
704
705 buffer = jau::format_string("%X", 3989525555U);
706 CHECK(buffer == "EDCB5433");
707
708 buffer = jau::format_string("%%");
709 CHECK(buffer == "%");
710}
711
712
713TEST_CASE("width", "[jau][std::string][jau::cfmt][width]" ) {
714 std::string buffer;
715
716 buffer = jau::format_string("%1s", "Hello testing");
717 CHECK(buffer == "Hello testing");
718
719 buffer = jau::format_string("%1d", 1024);
720 CHECK(buffer == "1024");
721
722 buffer = jau::format_string("%1d", -1024);
723 CHECK(buffer == "-1024");
724
725 buffer = jau::format_string("%1i", 1024);
726 CHECK(buffer == "1024");
727
728 buffer = jau::format_string("%1i", -1024);
729 CHECK(buffer == "-1024");
730
731 buffer = jau::format_string("%1u", 1024);
732 CHECK(buffer == "1024");
733
734 buffer = jau::format_string("%1u", 4294966272U);
735 CHECK(buffer == "4294966272");
736
737 buffer = jau::format_string("%1o", 511);
738 CHECK(buffer == "777");
739
740 buffer = jau::format_string("%1o", 4294966785U);
741 CHECK(buffer == "37777777001");
742
743 buffer = jau::format_string("%1x", 305441741);
744 CHECK(buffer == "1234abcd");
745
746 buffer = jau::format_string("%1x", 3989525555U);
747 CHECK(buffer == "edcb5433");
748
749 buffer = jau::format_string("%1X", 305441741);
750 CHECK(buffer == "1234ABCD");
751
752 buffer = jau::format_string("%1X", 3989525555U);
753 CHECK(buffer == "EDCB5433");
754
755 buffer = jau::format_string("%1c", 'x');
756 CHECK(buffer == "x");
757}
758
759
760TEST_CASE("width_20", "[jau][std::string][jau::cfmt][width]" ) {
761 std::string buffer;
762
763 buffer = jau::format_string("%20s", "Hello");
764 CHECK(buffer == " Hello");
765
766 buffer = jau::format_string("%20d", 1024);
767 CHECK(buffer == " 1024");
768
769 buffer = jau::format_string("%20d", -1024);
770 CHECK(buffer == " -1024");
771
772 buffer = jau::format_string("%20i", 1024);
773 CHECK(buffer == " 1024");
774
775 buffer = jau::format_string("%20i", -1024);
776 CHECK(buffer == " -1024");
777
778 buffer = jau::format_string("%20u", 1024);
779 CHECK(buffer == " 1024");
780
781 buffer = jau::format_string("%20u", 4294966272U);
782 CHECK(buffer == " 4294966272");
783
784 buffer = jau::format_string("%20o", 511);
785 CHECK(buffer == " 777");
786
787 buffer = jau::format_string("%20o", 4294966785U);
788 CHECK(buffer == " 37777777001");
789
790 buffer = jau::format_string("%20x", 305441741);
791 CHECK(buffer == " 1234abcd");
792
793 buffer = jau::format_string("%20x", 3989525555U);
794 CHECK(buffer == " edcb5433");
795
796 buffer = jau::format_string("%20X", 305441741);
797 CHECK(buffer == " 1234ABCD");
798
799 buffer = jau::format_string("%20X", 3989525555U);
800 CHECK(buffer == " EDCB5433");
801
802 buffer = jau::format_string("%20c", 'x');
803 CHECK(buffer == " x");
804}
805
806
807TEST_CASE("width_star_20", "[jau][std::string][jau::cfmt][width]" ) {
808 std::string buffer;
809
810 buffer = jau::format_string("%*s", 20, "Hello");
811 CHECK(buffer == " Hello");
812
813 buffer = jau::format_string("%*d", 20, 1024);
814 CHECK(buffer == " 1024");
815
816 buffer = jau::format_string("%*d", 20, -1024);
817 CHECK(buffer == " -1024");
818
819 buffer = jau::format_string("%*i", 20, 1024);
820 CHECK(buffer == " 1024");
821
822 buffer = jau::format_string("%*i", 20, -1024);
823 CHECK(buffer == " -1024");
824
825 buffer = jau::format_string("%*u", 20, 1024);
826 CHECK(buffer == " 1024");
827
828 buffer = jau::format_string("%*u", 20, 4294966272U);
829 CHECK(buffer == " 4294966272");
830
831 buffer = jau::format_string("%*o", 20, 511);
832 CHECK(buffer == " 777");
833
834 buffer = jau::format_string("%*o", 20, 4294966785U);
835 CHECK(buffer == " 37777777001");
836
837 buffer = jau::format_string("%*x", 20, 305441741);
838 CHECK(buffer == " 1234abcd");
839
840 buffer = jau::format_string("%*x", 20, 3989525555U);
841 CHECK(buffer == " edcb5433");
842
843 buffer = jau::format_string("%*X", 20, 305441741);
844 CHECK(buffer == " 1234ABCD");
845
846 buffer = jau::format_string("%*X", 20, 3989525555U);
847 CHECK(buffer == " EDCB5433");
848
849 buffer = jau::format_string("%*c", 20,'x');
850 CHECK(buffer == " x");
851}
852
853
854TEST_CASE("width_left_20", "[jau][std::string][jau::cfmt][width]" ) {
855 std::string buffer;
856
857 buffer = jau::format_string("%-20s", "Hello");
858 CHECK(buffer == "Hello ");
859
860 buffer = jau::format_string("%-20d", 1024);
861 CHECK(buffer == "1024 ");
862
863 buffer = jau::format_string("%-20d", -1024);
864 CHECK(buffer == "-1024 ");
865
866 buffer = jau::format_string("%-20i", 1024);
867 CHECK(buffer == "1024 ");
868
869 buffer = jau::format_string("%-20i", -1024);
870 CHECK(buffer == "-1024 ");
871
872 buffer = jau::format_string("%-20u", 1024);
873 CHECK(buffer == "1024 ");
874
875 buffer = jau::format_string("%-20.4f", 1024.1234);
876 CHECK(buffer == "1024.1234 ");
877
878 buffer = jau::format_string("%-20u", 4294966272U);
879 CHECK(buffer == "4294966272 ");
880
881 buffer = jau::format_string("%-20o", 511);
882 CHECK(buffer == "777 ");
883
884 buffer = jau::format_string("%-20o", 4294966785U);
885 CHECK(buffer == "37777777001 ");
886
887 buffer = jau::format_string("%-20x", 305441741);
888 CHECK(buffer == "1234abcd ");
889
890 buffer = jau::format_string("%-20x", 3989525555U);
891 CHECK(buffer == "edcb5433 ");
892
893 buffer = jau::format_string("%-20X", 305441741);
894 CHECK(buffer == "1234ABCD ");
895
896 buffer = jau::format_string("%-20X", 3989525555U);
897 CHECK(buffer == "EDCB5433 ");
898
899 buffer = jau::format_string("%-20c", 'x');
900 CHECK(buffer == "x ");
901
902 buffer = jau::format_string("|%5d| |%-2d| |%5d|", 9, 9, 9);
903 CHECK(buffer == "| 9| |9 | | 9|");
904
905 buffer = jau::format_string("|%5d| |%-2d| |%5d|", 10, 10, 10);
906 CHECK(buffer == "| 10| |10| | 10|");
907
908 buffer = jau::format_string("|%5d| |%-12d| |%5d|", 9, 9, 9);
909 CHECK(buffer == "| 9| |9 | | 9|");
910
911 buffer = jau::format_string("|%5d| |%-12d| |%5d|", 10, 10, 10);
912 CHECK(buffer == "| 10| |10 | | 10|");
913}
914
915
916TEST_CASE("zero_width_left_20", "[jau][std::string][jau::cfmt][width]" ) {
917 std::string buffer;
918
919 buffer = jau::format_string("%0-20s", "Hello");
920 CHECK(buffer == "Hello ");
921
922 buffer = jau::format_string("%0-20d", 1024);
923 CHECK(buffer == "1024 ");
924
925 buffer = jau::format_string("%0-20d", -1024);
926 CHECK(buffer == "-1024 ");
927
928 buffer = jau::format_string("%0-20i", 1024);
929 CHECK(buffer == "1024 ");
930
931 buffer = jau::format_string("%0-20i", -1024);
932 CHECK(buffer == "-1024 ");
933
934 buffer = jau::format_string("%0-20u", 1024);
935 CHECK(buffer == "1024 ");
936
937 buffer = jau::format_string("%0-20u", 4294966272U);
938 CHECK(buffer == "4294966272 ");
939
940 buffer = jau::format_string("%0-20o", 511);
941 CHECK(buffer == "777 ");
942
943 buffer = jau::format_string("%0-20o", 4294966785U);
944 CHECK(buffer == "37777777001 ");
945
946 buffer = jau::format_string("%0-20x", 305441741);
947 CHECK(buffer == "1234abcd ");
948
949 buffer = jau::format_string("%0-20x", 3989525555U);
950 CHECK(buffer == "edcb5433 ");
951
952 buffer = jau::format_string("%0-20X", 305441741);
953 CHECK(buffer == "1234ABCD ");
954
955 buffer = jau::format_string("%0-20X", 3989525555U);
956 CHECK(buffer == "EDCB5433 ");
957
958 buffer = jau::format_string("%0-20c", 'x');
959 CHECK(buffer == "x ");
960}
961
962
963TEST_CASE("width_20", "[jau][std::string][jau::cfmt][padding]" ) {
964 std::string buffer;
965
966 buffer = jau::format_string("%020d", 1024);
967 CHECK(buffer == "00000000000000001024");
968
969 buffer = jau::format_string("%020d", -1024);
970 CHECK(buffer == "-0000000000000001024");
971
972 buffer = jau::format_string("%020i", 1024);
973 CHECK(buffer == "00000000000000001024");
974
975 buffer = jau::format_string("%020i", -1024);
976 CHECK(buffer == "-0000000000000001024");
977
978 buffer = jau::format_string("%020u", 1024);
979 CHECK(buffer == "00000000000000001024");
980
981 buffer = jau::format_string("%020u", 4294966272U);
982 CHECK(buffer == "00000000004294966272");
983
984 buffer = jau::format_string("%020o", 511);
985 CHECK(buffer == "00000000000000000777");
986
987 buffer = jau::format_string("%020o", 4294966785U);
988 CHECK(buffer == "00000000037777777001");
989
990 buffer = jau::format_string("%020x", 305441741);
991 CHECK(buffer == "0000000000001234abcd");
992
993 buffer = jau::format_string("%020x", 3989525555U);
994 CHECK(buffer == "000000000000edcb5433");
995
996 buffer = jau::format_string("%020X", 305441741);
997 CHECK(buffer == "0000000000001234ABCD");
998
999 buffer = jau::format_string("%020X", 3989525555U);
1000 CHECK(buffer == "000000000000EDCB5433");
1001}
1002
1003
1004TEST_CASE("precision_20", "[jau][std::string][jau::cfmt][padding]" ) {
1005 std::string buffer;
1006
1007 buffer = jau::format_string("%.20d", 1024);
1008 CHECK(buffer == "00000000000000001024");
1009
1010 buffer = jau::format_string("%.20d", -1024);
1011 CHECK(buffer == "-00000000000000001024");
1012
1013 buffer = jau::format_string("%.20i", 1024);
1014 CHECK(buffer == "00000000000000001024");
1015
1016 buffer = jau::format_string("%.20i", -1024);
1017 CHECK(buffer == "-00000000000000001024");
1018
1019 buffer = jau::format_string("%.20u", 1024);
1020 CHECK(buffer == "00000000000000001024");
1021
1022 buffer = jau::format_string("%.20u", 4294966272U);
1023 CHECK(buffer == "00000000004294966272");
1024
1025 buffer = jau::format_string("%.20o", 511);
1026 CHECK(buffer == "00000000000000000777");
1027
1028 buffer = jau::format_string("%.20o", 4294966785U);
1029 CHECK(buffer == "00000000037777777001");
1030
1031 buffer = jau::format_string("%.20x", 305441741);
1032 CHECK(buffer == "0000000000001234abcd");
1033
1034 buffer = jau::format_string("%.20x", 3989525555U);
1035 CHECK(buffer == "000000000000edcb5433");
1036
1037 buffer = jau::format_string("%.20X", 305441741);
1038 CHECK(buffer == "0000000000001234ABCD");
1039
1040 buffer = jau::format_string("%.20X", 3989525555U);
1041 CHECK(buffer == "000000000000EDCB5433");
1042}
1043
1044
1045TEST_CASE("hash_zero_width_20", "[jau][std::string][jau::cfmt][padding]" ) {
1046 std::string buffer;
1047
1048 buffer = jau::format_string("%#020d", 1024);
1049 CHECK(buffer == "00000000000000001024");
1050
1051 buffer = jau::format_string("%#020d", -1024);
1052 CHECK(buffer == "-0000000000000001024");
1053
1054 buffer = jau::format_string("%#020i", 1024);
1055 CHECK(buffer == "00000000000000001024");
1056
1057 buffer = jau::format_string("%#020i", -1024);
1058 CHECK(buffer == "-0000000000000001024");
1059
1060 buffer = jau::format_string("%#020u", 1024);
1061 CHECK(buffer == "00000000000000001024");
1062
1063 buffer = jau::format_string("%#020u", 4294966272U);
1064 CHECK(buffer == "00000000004294966272");
1065
1066 buffer = jau::format_string("%#020o", 511);
1067 CHECK(buffer == "00000000000000000777");
1068
1069 buffer = jau::format_string("%#020o", 4294966785U);
1070 CHECK(buffer == "00000000037777777001");
1071
1072 buffer = jau::format_string("%#020x", 305441741);
1073 CHECK(buffer == "0x00000000001234abcd");
1074
1075 buffer = jau::format_string("%#020x", 3989525555U);
1076 CHECK(buffer == "0x0000000000edcb5433");
1077
1078 buffer = jau::format_string("%#020X", 305441741);
1079 CHECK(buffer == "0X00000000001234ABCD");
1080
1081 buffer = jau::format_string("%#020X", 3989525555U);
1082 CHECK(buffer == "0X0000000000EDCB5433");
1083}
1084
1085
1086TEST_CASE("hash_width_20", "[jau][std::string][jau::cfmt][padding]" ) {
1087 std::string buffer;
1088
1089 buffer = jau::format_string("%#20d", 1024);
1090 CHECK(buffer == " 1024");
1091
1092 buffer = jau::format_string("%#20d", -1024);
1093 CHECK(buffer == " -1024");
1094
1095 buffer = jau::format_string("%#20i", 1024);
1096 CHECK(buffer == " 1024");
1097
1098 buffer = jau::format_string("%#20i", -1024);
1099 CHECK(buffer == " -1024");
1100
1101 buffer = jau::format_string("%#20u", 1024);
1102 CHECK(buffer == " 1024");
1103
1104 buffer = jau::format_string("%#20u", 4294966272U);
1105 CHECK(buffer == " 4294966272");
1106
1107 buffer = jau::format_string("%#20o", 511);
1108 CHECK(buffer == " 0777");
1109
1110 buffer = jau::format_string("%#20o", 4294966785U);
1111 CHECK(buffer == " 037777777001");
1112
1113 buffer = jau::format_string("%#20x", 305441741);
1114 CHECK(buffer == " 0x1234abcd");
1115
1116 buffer = jau::format_string("%#20x", 3989525555U);
1117 CHECK(buffer == " 0xedcb5433");
1118
1119 buffer = jau::format_string("%#20X", 305441741);
1120 CHECK(buffer == " 0X1234ABCD");
1121
1122 buffer = jau::format_string("%#20X", 3989525555U);
1123 CHECK(buffer == " 0XEDCB5433");
1124}
1125
1126
1127TEST_CASE("width_20_precision_5", "[jau][std::string][jau::cfmt][padding]" ) {
1128 std::string buffer;
1129
1130 buffer = jau::format_string("%20.5d", 1024);
1131 CHECK(buffer == " 01024");
1132
1133 buffer = jau::format_string("%20.5d", -1024);
1134 CHECK(buffer == " -01024");
1135
1136 buffer = jau::format_string("%20.5i", 1024);
1137 CHECK(buffer == " 01024");
1138
1139 buffer = jau::format_string("%20.5i", -1024);
1140 CHECK(buffer == " -01024");
1141
1142 buffer = jau::format_string("%20.5u", 1024);
1143 CHECK(buffer == " 01024");
1144
1145 buffer = jau::format_string("%20.5u", 4294966272U);
1146 CHECK(buffer == " 4294966272");
1147
1148 buffer = jau::format_string("%20.5o", 511);
1149 CHECK(buffer == " 00777");
1150
1151 buffer = jau::format_string("%20.5o", 4294966785U);
1152 CHECK(buffer == " 37777777001");
1153
1154 buffer = jau::format_string("%20.5x", 305441741);
1155 CHECK(buffer == " 1234abcd");
1156
1157 buffer = jau::format_string("%20.10x", 3989525555U);
1158 CHECK(buffer == " 00edcb5433");
1159
1160 buffer = jau::format_string("%20.5X", 305441741);
1161 CHECK(buffer == " 1234ABCD");
1162
1163 buffer = jau::format_string("%20.10X", 3989525555U);
1164 CHECK(buffer == " 00EDCB5433");
1165}
1166
1167
1168TEST_CASE("padding neg_numbers", "[jau][std::string][jau::cfmt][padding]" ) {
1169 std::string buffer;
1170
1171 // space padding
1172 buffer = jau::format_string("% 1d", -5);
1173 CHECK(buffer == "-5");
1174
1175 buffer = jau::format_string("% 2d", -5);
1176 CHECK(buffer == "-5");
1177
1178 buffer = jau::format_string("% 3d", -5);
1179 CHECK(buffer == " -5");
1180
1181 buffer = jau::format_string("% 4d", -5);
1182 CHECK(buffer == " -5");
1183
1184 // zero padding
1185 buffer = jau::format_string("%01d", -5);
1186 CHECK(buffer == "-5");
1187
1188 buffer = jau::format_string("%02d", -5);
1189 CHECK(buffer == "-5");
1190
1191 buffer = jau::format_string("%03d", -5);
1192 CHECK(buffer == "-05");
1193
1194 buffer = jau::format_string("%04d", -5);
1195 CHECK(buffer == "-005");
1196}
1197
1198
1199TEST_CASE("float padding_neg_numbers", "[jau][std::string][jau::cfmt][float]" ) {
1200 std::string buffer;
1201
1202 // space padding
1203 buffer = jau::format_string("% 3.1f", -5.);
1204 CHECK(buffer == "-5.0");
1205
1206 buffer = jau::format_string("% 4.1f", -5.);
1207 CHECK(buffer == "-5.0");
1208
1209 buffer = jau::format_string("% 5.1f", -5.);
1210 CHECK(buffer == " -5.0");
1211
1212 buffer = jau::format_string("% 6.1g", -5.);
1213 CHECK(buffer == " -5");
1214
1215 buffer = jau::format_string("% 6.1e", -5.);
1216 CHECK(buffer == "-5.0e+00");
1217
1218 buffer = jau::format_string("% 10.1e", -5.);
1219 CHECK(buffer == " -5.0e+00");
1220
1221 // zero padding
1222 buffer = jau::format_string("%03.1f", -5.);
1223 CHECK(buffer == "-5.0");
1224
1225 buffer = jau::format_string("%04.1f", -5.);
1226 CHECK(buffer == "-5.0");
1227
1228 buffer = jau::format_string("%05.1f", -5.);
1229 CHECK(buffer == "-05.0");
1230
1231 // zero padding no decimal point
1232 buffer = jau::format_string("%01.0f", -5.);
1233 CHECK(buffer == "-5");
1234
1235 buffer = jau::format_string("%02.0f", -5.);
1236 CHECK(buffer == "-5");
1237
1238 buffer = jau::format_string("%03.0f", -5.);
1239 CHECK(buffer == "-05");
1240
1241 buffer = jau::format_string("%010.1e", -5.);
1242 CHECK(buffer == "-005.0e+00");
1243
1244 buffer = jau::format_string("%07.0E", -5.);
1245 CHECK(buffer == "-05E+00");
1246
1247 buffer = jau::format_string("%03.0g", -5.);
1248 CHECK(buffer == "-05");
1249}
1250
1251TEST_CASE("length", "[jau][std::string][jau::cfmt][length]" ) {
1252 std::string buffer;
1253
1254 buffer = jau::format_string("%.0s", "Hello testing");
1255 CHECK(buffer == "");
1256
1257 buffer = jau::format_string("%20.0s", "Hello testing");
1258 CHECK(buffer == " ");
1259
1260 buffer = jau::format_string("%.s", "Hello testing");
1261 CHECK(buffer == "");
1262
1263 buffer = jau::format_string("%20.s", "Hello testing");
1264 CHECK(buffer == " ");
1265
1266 buffer = jau::format_string("%20.0d", 1024);
1267 CHECK(buffer == " 1024");
1268
1269 buffer = jau::format_string("%20.0d", -1024);
1270 CHECK(buffer == " -1024");
1271
1272 buffer = jau::format_string("%20.d", 0);
1273 CHECK(buffer == " ");
1274
1275 buffer = jau::format_string("%20.0i", 1024);
1276 CHECK(buffer == " 1024");
1277
1278 buffer = jau::format_string("%20.i", -1024);
1279 CHECK(buffer == " -1024");
1280
1281 buffer = jau::format_string("%20.i", 0);
1282 CHECK(buffer == " ");
1283
1284 buffer = jau::format_string("%20.u", 1024);
1285 CHECK(buffer == " 1024");
1286
1287 buffer = jau::format_string("%20.0u", 4294966272U);
1288 CHECK(buffer == " 4294966272");
1289
1290 buffer = jau::format_string("%20.u", 0U);
1291 CHECK(buffer == " ");
1292
1293 buffer = jau::format_string("%20.o", 511);
1294 CHECK(buffer == " 777");
1295
1296 buffer = jau::format_string("%20.0o", 4294966785U);
1297 CHECK(buffer == " 37777777001");
1298
1299 buffer = jau::format_string("%20.o", 0U);
1300 CHECK(buffer == " ");
1301
1302 buffer = jau::format_string("%20.x", 305441741);
1303 CHECK(buffer == " 1234abcd");
1304
1305 buffer = jau::format_string("%50.x", 305441741);
1306 CHECK(buffer == " 1234abcd");
1307
1308 buffer = jau::format_string("%50.x%10.u", 305441741, 12345);
1309 CHECK(buffer == " 1234abcd 12345");
1310
1311 buffer = jau::format_string("%20.0x", 3989525555U);
1312 CHECK(buffer == " edcb5433");
1313
1314 buffer = jau::format_string("%20.x", 0U);
1315 CHECK(buffer == " ");
1316
1317 buffer = jau::format_string("%20.X", 305441741);
1318 CHECK(buffer == " 1234ABCD");
1319
1320 buffer = jau::format_string("%20.0X", 3989525555U);
1321 CHECK(buffer == " EDCB5433");
1322
1323 buffer = jau::format_string("%20.X", 0U);
1324 CHECK(buffer == " ");
1325
1326 buffer = jau::format_string("%02.0u", 0U);
1327 CHECK(buffer == " ");
1328
1329 buffer = jau::format_string("%02.0d", 0);
1330 CHECK(buffer == " ");
1331}
1332
1333
1334TEST_CASE("float", "[jau][std::string][jau::cfmt][float]" ) {
1335 std::string buffer;
1336
1337 // test special-case floats using math.h macros
1338 buffer = jau::format_string("%8f", NAN);
1339 CHECK(buffer == " nan");
1340
1341 buffer = jau::format_string("%8f", INFINITY);
1342 CHECK(buffer == " inf");
1343
1344 buffer = jau::format_string("%-8f", -INFINITY);
1345 CHECK(buffer == "-inf ");
1346
1347 buffer = jau::format_string("%+8e", INFINITY);
1348 CHECK(buffer == " +inf");
1349
1350 buffer = jau::format_string("%.4f", 3.1415354); // NOLINT
1351 CHECK(buffer == "3.1415");
1352
1353 buffer = jau::format_string("%.3f", 30343.1415354);
1354 CHECK(buffer == "30343.142");
1355
1356 buffer = jau::format_string("%.0f", 34.1415354);
1357 CHECK(buffer == "34");
1358
1359 buffer = jau::format_string("%.0f", 1.3);
1360 CHECK(buffer == "1");
1361
1362 buffer = jau::format_string("%.0f", 1.55);
1363 CHECK(buffer == "2");
1364
1365 buffer = jau::format_string("%.1f", 1.64);
1366 CHECK(buffer == "1.6");
1367
1368 buffer = jau::format_string("%.2f", 42.8952);
1369 CHECK(buffer == "42.90");
1370
1371 buffer = jau::format_string("%.9f", 42.8952);
1372 CHECK(buffer == "42.895200000");
1373
1374 buffer = jau::format_string("%.10f", 42.895223);
1375 CHECK(buffer == "42.8952230000");
1376
1377 // assuming not being truncated to 9 digits. (19)
1378 buffer = jau::format_string("%.12f", 42.987654321098);
1379 CHECK(buffer == "42.987654321098");
1380
1381 // assuming not being truncated to 9 digits, but rounded
1382 buffer = jau::format_string("%.12f", 42.98765432109899);
1383 CHECK(buffer == "42.987654321099");
1384
1385 // 14
1386 buffer = jau::format_string("%.14f", 42.98765432109876);
1387 CHECK(buffer == "42.98765432109876");
1388 // 14 rounded
1389 buffer = jau::format_string("%.14f", 42.9876543210987699);
1390 CHECK(buffer == "42.98765432109877");
1391
1392 // 16 truncated to 14 (max precision)
1393 buffer = jau::format_string("%.16f", 42.9876543210987612);
1394 CHECK(buffer == "42.9876543210987600");
1395
1396 // 16 truncated to 14 (max precision) and rounded
1397 buffer = jau::format_string("%.16f", 42.9876543210987654);
1398 CHECK(buffer == "42.9876543210987700");
1399
1400 buffer = jau::format_string("%6.2f", 42.8952);
1401 CHECK(buffer == " 42.90");
1402
1403 buffer = jau::format_string("%+6.2f", 42.8952);
1404 CHECK(buffer == "+42.90");
1405
1406 buffer = jau::format_string("%+5.1f", 42.9252);
1407 CHECK(buffer == "+42.9");
1408
1409 buffer = jau::format_string("%f", 42.5);
1410 CHECK(buffer == "42.500000");
1411
1412 buffer = jau::format_string("%.1f", 42.5);
1413 CHECK(buffer == "42.5");
1414
1415 buffer = jau::format_string("%f", 42167.0);
1416 CHECK(buffer == "42167.000000");
1417
1418 buffer = jau::format_string("%.9f", -12345.987654321);
1419 CHECK(buffer == "-12345.987654321");
1420
1421 buffer = jau::format_string("%.1f", 3.999);
1422 CHECK(buffer == "4.0");
1423
1424 buffer = jau::format_string("%.0f", 3.5);
1425 CHECK(buffer == "4");
1426
1427 buffer = jau::format_string("%.0f", 4.5);
1428 CHECK(buffer == "4");
1429
1430 buffer = jau::format_string("%.0f", 3.49);
1431 CHECK(buffer == "3");
1432
1433 buffer = jau::format_string("%.1f", 3.49);
1434 CHECK(buffer == "3.5");
1435
1436 buffer = jau::format_string("a%-5.1f", 0.5);
1437 CHECK(buffer == "a0.5 ");
1438
1439 buffer = jau::format_string("a%-5.1fend", 0.5);
1440 CHECK(buffer == "a0.5 end");
1441
1442 buffer = jau::format_string("%G", 12345.678);
1443 CHECK(buffer == "12345.7");
1444
1445 buffer = jau::format_string("%.7G", 12345.678);
1446 CHECK(buffer == "12345.68");
1447
1448 buffer = jau::format_string("%.5G", 123456789.);
1449 CHECK(buffer == "1.2346E+08");
1450
1451 buffer = jau::format_string("%.6G", 12345.);
1452 CHECK(buffer == "12345.0");
1453
1454 buffer = jau::format_string("%+12.4g", 123456789.);
1455 CHECK(buffer == " +1.235e+08");
1456
1457 buffer = jau::format_string("%.2G", 0.001234);
1458 CHECK(buffer == "0.0012");
1459
1460 buffer = jau::format_string("%+10.4G", 0.001234);
1461 CHECK(buffer == " +0.001234");
1462
1463 buffer = jau::format_string("%+012.4g", 0.00001234);
1464 CHECK(buffer == "+001.234e-05");
1465
1466 buffer = jau::format_string("%.3g", -1.2345e-308);
1467 CHECK(buffer == "-1.23e-308");
1468
1469 buffer = jau::format_string("%+.3E", 1.23e+308);
1470 CHECK(buffer == "+1.230E+308");
1471
1472 // out of range for float: should switch to exp notation if supported, else empty
1473 buffer = jau::format_string("%.1f", 1E20);
1474 CHECK(buffer == "1.0e+20");
1475
1476 buffer = jau::format_string("%.5f", -1.12345);
1477 CHECK(buffer == "-1.12345");
1478
1479 buffer = jau::format_string("%.5f", -1.00000e20);
1480 CHECK(buffer == "-1.00000e+20");
1481
1482 // brute force float
1483 bool fail = false;
1484 std::stringstream str;
1485 str.precision(5);
1486 for (float i = -100000; i < 100000; i += 1) { // NOLINT
1487 buffer = jau::format_string("%.5f", i / 10000);
1488 str.str("");
1489 str << std::fixed << i / 10000;
1490 fail = fail || buffer != str.str();
1491 }
1492 CHECK(!fail);
1493
1494 // brute force exp
1495 fail = false;
1496 str.setf(std::ios::scientific, std::ios::floatfield);
1497 for (float i = -1e20; i < 1e20; i += 1e15) { // NOLINT
1498 buffer = jau::format_string("%.5f", i);
1499 buffer.shrink_to_fit();
1500 str.str("");
1501 str << i;
1502 REQUIRE(buffer == str.str());
1503 fail = fail || buffer != str.str();
1504 }
1505 CHECK(!fail);
1506}
1507
1508
1509TEST_CASE("types", "[jau][std::string][jau::cfmt][types]" ) {
1510 std::string buffer;
1511
1512 buffer = jau::format_string("%i", 0);
1513 CHECK(buffer == "0");
1514
1515 buffer = jau::format_string("%i", 1234);
1516 CHECK(buffer == "1234");
1517
1518 buffer = jau::format_string("%i", 32767);
1519 CHECK(buffer == "32767");
1520
1521 buffer = jau::format_string("%i", -32767);
1522 CHECK(buffer == "-32767");
1523
1524 buffer = jau::format_string("%li", 30L);
1525 CHECK(buffer == "30");
1526
1527 buffer = jau::format_string("%li", -2147483647L);
1528 CHECK(buffer == "-2147483647");
1529
1530 buffer = jau::format_string("%li", 2147483647L);
1531 CHECK(buffer == "2147483647");
1532
1533 buffer = jau::format_string("%lli", 30LL);
1534 CHECK(buffer == "30");
1535
1536 buffer = jau::format_string("%lli", -9223372036854775807LL);
1537 CHECK(buffer == "-9223372036854775807");
1538
1539 buffer = jau::format_string("%lli", 9223372036854775807LL);
1540 CHECK(buffer == "9223372036854775807");
1541
1542 buffer = jau::format_string("%lu", 100000L);
1543 CHECK(buffer == "100000");
1544
1545 buffer = jau::format_string("%lu", 0xFFFFFFFFL);
1546 CHECK(buffer == "4294967295");
1547
1548 buffer = jau::format_string("%llu", 281474976710656LLU);
1549 CHECK(buffer == "281474976710656");
1550
1551 buffer = jau::format_string("%llu", 18446744073709551615LLU);
1552 CHECK(buffer == "18446744073709551615");
1553
1554 buffer = jau::format_string("%zu", 2147483647UL);
1555 CHECK(buffer == "2147483647");
1556
1557 buffer = jau::format_string("%zd", 2147483647L);
1558 CHECK(buffer == "2147483647");
1559
1560 // failed intentionally unsigned -> signed
1561 static_assert(0 < jau::cfmt::checkLine("%zd", 2147483647UL));
1562 // buffer = jau::format_string("%zd", 2147483647UL);
1563 // CHECK(buffer == "2147483647");
1564
1565 if (sizeof(size_t) == sizeof(long)) {
1566 buffer = jau::format_string("%zi", -2147483647L);
1567 CHECK(buffer == "-2147483647");
1568 }
1569 else {
1570 buffer = jau::format_string("%zi", -2147483647LL);
1571 CHECK(buffer == "-2147483647");
1572 }
1573
1574 buffer = jau::format_string("%b", 60000);
1575 CHECK(buffer == "1110101001100000");
1576
1577 buffer = jau::format_string("%lb", 12345678L);
1578 CHECK(buffer == "101111000110000101001110");
1579
1580 buffer = jau::format_string("%o", 60000);
1581 CHECK(buffer == "165140");
1582
1583 buffer = jau::format_string("%lo", 12345678L);
1584 CHECK(buffer == "57060516");
1585
1586 buffer = jau::format_string("%lx", 0x12345678L);
1587 CHECK(buffer == "12345678");
1588
1589 buffer = jau::format_string("%llx", 0x1234567891234567LLU);
1590 CHECK(buffer == "1234567891234567");
1591
1592 buffer = jau::format_string("%lx", 0xabcdefabL);
1593 CHECK(buffer == "abcdefab");
1594
1595 buffer = jau::format_string("%lX", 0xabcdefabL);
1596 CHECK(buffer == "ABCDEFAB");
1597
1598 buffer = jau::format_string("%c", 'v');
1599 CHECK(buffer == "v");
1600
1601 buffer = jau::format_string("%cv", 'w');
1602 CHECK(buffer == "wv");
1603
1604 buffer = jau::format_string("%s", "A Test");
1605 CHECK(buffer == "A Test");
1606
1607 static_assert(0 < jau::cfmt::checkLine("%hhu", 0xFFU)); // size unsigned int > unsigned char (intentional failure)
1608 static_assert(0 == jau::cfmt::checkLine("%hhu", 0xFF_u8));
1609 buffer = jau::format_string("%hhu", 0xFF_u8);
1610 CHECK(buffer == "255");
1611
1612 // intentionally fails: given arg size > hh char
1613 static_assert(0 < jau::cfmt::checkLine("%hhu", 0xFFFFUL)); // size unsigned long > unsigned char (intentional failure)
1614 // buffer = jau::format_string("%hhu", 0xFFFFUL);
1615 // CHECK(buffer == "255");
1616
1617 static_assert(0 < jau::cfmt::checkLine("%hu", 0x123456UL)); // size unsigned long > unsigned short (intentional failure)
1618 static_assert(0 == jau::cfmt::checkLine("%hu", 0x1234_u16));
1619 buffer = jau::format_string("%hu", 0x1234_u16); // size unsigned long > unsigned short
1620 CHECK(buffer == "4660");
1621
1622 static_assert(0 < jau::cfmt::checkLine("%s%hhi %hu", "Test", 10000, 0xFFFFFFFF));
1623 static_assert(0 == jau::cfmt::checkLine("%s%hhi %hu", "Test", 16_i8, 0xFFFF_u16));
1624 buffer = jau::format_string("%s%hhi %hu", "Test", (char)16, (unsigned short)0xFFFF);
1625 CHECK(buffer == "Test16 65535");
1626
1627 buffer = jau::format_string("%tx", &buffer[10] - &buffer[0]);
1628 CHECK(buffer == "a");
1629
1630// TBD
1631 if (sizeof(intmax_t) == sizeof(long)) {
1632 buffer = jau::format_string("%ji", -2147483647L);
1633 CHECK(buffer == "-2147483647");
1634 }
1635 else {
1636 buffer = jau::format_string("%ji", -2147483647LL);
1637 CHECK(buffer == "-2147483647");
1638 }
1639}
1640
1641
1642TEST_CASE("pointer", "[jau][std::string][jau::cfmt][pointer]" ) {
1643 std::string buffer;
1644
1645#if 0
1646 buffer = jau::format_string("%p", (void*)0x1234U);
1647 if (sizeof(void*) == 4U) {
1648 CHECK(buffer == "00001234");
1649 }
1650 else {
1651 CHECK(buffer == "0000000000001234");
1652 }
1653
1654 buffer = jau::format_string("%p", (void*)0x12345678U);
1655 if (sizeof(void*) == 4U) {
1656 CHECK(buffer == "12345678");
1657 }
1658 else {
1659 CHECK(buffer == "0000000012345678");
1660 }
1661
1662 buffer = jau::format_string("%p-%p", (void*)0x12345678U, (void*)0x7EDCBA98U);
1663 if (sizeof(void*) == 4U) {
1664 CHECK(buffer == "12345678-7EDCBA98");
1665 }
1666 else {
1667 CHECK(buffer == "0000000012345678-000000007EDCBA98");
1668 }
1669
1670 if (sizeof(uintptr_t) == sizeof(uint64_t)) {
1671 buffer = jau::format_string("%p", (void*)(uintptr_t)0xFFFFFFFFU); // NOLINT
1672 CHECK(buffer == "00000000FFFFFFFF");
1673 }
1674 else {
1675 buffer = jau::format_string("%p", (void*)(uintptr_t)0xFFFFFFFFU); // NOLINT
1676 CHECK(buffer == "FFFFFFFF");
1677 }
1678#else
1679 // %#x or %#lx
1680 buffer = jau::format_string("%p", (void*)0x1234U);
1681 CHECK(buffer == "0x1234");
1682
1683 buffer = jau::format_string("%p", (void*)0x12345678U);
1684 CHECK(buffer == "0x12345678");
1685
1686 buffer = jau::format_string("%p-%p", (void*)0x12345678U, (void*)0x7EDCBA98U);
1687 CHECK(buffer == "0x12345678-0x7edcba98");
1688
1689 buffer = jau::format_string("%p", (void*)(uintptr_t)0xFFFFFFFFU); // NOLINT
1690 CHECK(buffer == "0xffffffff");
1691#endif
1692}
1693
1694
1695TEST_CASE("unknown flag", "[jau][std::string][jau::cfmt][error]" ) {
1696 std::string buffer;
1697
1698 // we inject an error message
1699 buffer = jau::format_string("%kmarco", 42, 37); // orig "kmarco"
1700 const size_t q = buffer.find("<E#", 0);
1701 CHECK( q != std::string::npos );
1702}
1703
1704
1705TEST_CASE("string length", "[jau][std::string][jau::cfmt][stringlen]" ) {
1706 std::string buffer;
1707
1708 buffer = jau::format_string("%.4s", "This is a test");
1709 CHECK(buffer == "This");
1710
1711 buffer = jau::format_string("%.4s", "test");
1712 CHECK(buffer == "test");
1713
1714 buffer = jau::format_string("%.7s", "123");
1715 CHECK(buffer == "123");
1716
1717 buffer = jau::format_string("%.7s", "");
1718 CHECK(buffer == "");
1719
1720 buffer = jau::format_string("%.4s%.2s", "123456", "abcdef");
1721 CHECK(buffer == "1234ab");
1722
1723 // we inject an error message
1724 buffer = jau::format_string("%.4.2s", "123456"); // orig ".2s"
1725 const size_t q = buffer.find("<E#", 0);
1726 CHECK( q != std::string::npos );
1727
1728 buffer = jau::format_string("%.*s", 3, "123456");
1729 CHECK(buffer == "123");
1730}
1731
1732TEST_CASE("misc", "[jau][std::string][jau::cfmt][misc]" ) {
1733 std::string buffer;
1734
1735 buffer = jau::format_string("%u%u%ctest%d %s", 5, 3000, 'a', -20, "bit");
1736 CHECK(buffer == "53000atest-20 bit");
1737
1738 buffer = jau::format_string("%.*f", 2, 0.33333333);
1739 CHECK(buffer == "0.33");
1740
1741 buffer = jau::format_string("%.*d", -1, 1);
1742 CHECK(buffer == "1");
1743
1744 buffer = jau::format_string("%.3s", "foobar");
1745 CHECK(buffer == "foo");
1746
1747 buffer = jau::format_string("% .0d", 0);
1748 CHECK(buffer == " ");
1749
1750 buffer = jau::format_string("%10.5d", 4);
1751 CHECK(buffer == " 00004");
1752
1753 buffer = jau::format_string("%*sx", -3, "hi");
1754 CHECK(buffer == "hi x");
1755
1756 buffer = jau::format_string("%.*g", 2, 0.33333333);
1757 CHECK(buffer == "0.33");
1758
1759 buffer = jau::format_string("%.*e", 2, 0.33333333);
1760 CHECK(buffer == "3.33e-01");
1761}
constexpr ssize_t argumentCount() const noexcept
Arguments processed.
constexpr const FormatOpts & opts() const noexcept
Last argument FormatOpts (error analysis)
constexpr bool success() const noexcept
true if operation was successful, otherwise indicates error
constexpr bool value(const Bool rhs) noexcept
constexpr int32_t exponent_unbiased(float32_t a) noexcept
Extracts the unbiased 8-bit exponent from the given IEEE 754 (IEC 559) float64_t and subtracts 127,...
constexpr uint32_t significand_raw(float32_t a) noexcept
Extracts the 23-bit significand (fraction, mantissa) from the given IEEE 754 (IEC 559) float32_t.
Result formatR(std::string &s, std::string_view fmt, const Targs &...args) noexcept
Strict format with type validation of arguments against the format string, appending to the given des...
#define jau_string_check(fmt,...)
Macro produces compile time validation using a static_assert against jau::cfmt::check2.
#define jau_string_checkLine(fmt,...)
Macro produces compile time validation using a static_assert against jau::cfmt::check2Line.
consteval_cxx20 int checkLine(std::string_view fmt, const Targs &...) noexcept
Strict type validation of arguments against the format string.
#define jau_format_string(fmt,...)
Macro, safely returns a (non-truncated) string according to snprintf() formatting rules using a reser...
consteval_cxx20 ssize_t check(std::string_view fmt, const Targs &...) noexcept
Strict type validation of arguments against the format string.
@ left
actual flag -, C99
@ plus
actual flag +, C99
Author: Sven Gothel sgothel@jausoft.com Copyright (c) 2021-2026 Gothel Software e....
std::string format_string(const char *format,...) noexcept
Returns a (non-truncated) string according to snprintf() formatting rules and variable number of argu...
std::string format_string(std::string_view format, const Args &...args) noexcept
Safely returns a (non-truncated) string according to snprintf() formatting rules using a reserved str...
TEST_CASE("parse: width precision from format", "[jau][std::string][jau::cfmt]")
static void checkFormat(int line, const char *fmt, const Args &...args)