@@ -110,6 +110,8 @@ int unitTests()
110110 // up the tests. Turn this off for consistency:
111111 _set_output_format (_TWO_DIGIT_EXPONENT);
112112# endif
113+
114+ // ------------------------------------------------------------
113115 // Test various basic format specs against results of sprintf
114116 CHECK_EQUAL (tfm::format (" %s" , " asdf" ), " asdf" );
115117 CHECK_EQUAL (tfm::format (" %d" , 1234 ), " 1234" );
@@ -135,36 +137,43 @@ int unitTests()
135137 CHECK_EQUAL (tfm::format (" %hc" , (short )65 ), " A" );
136138 CHECK_EQUAL (tfm::format (" %lc" , (long )65 ), " A" );
137139 CHECK_EQUAL (tfm::format (" %s" , " asdf_123098" ), " asdf_123098" );
140+ // Test "%%" - (note plain "%%" format gives warning with gcc printf)
141+ CHECK_EQUAL (tfm::format (" %%%s" , " asdf" ), " %asdf" );
142+ // Check that 0-argument formatting is printf-compatible
143+ CHECK_EQUAL (tfm::format (" 100%%" ), " 100%" );
138144
139145 // Test printing of pointers. Note that there's no standard numerical
140146 // representation so this is platform and OS dependent.
147+ //
148+ // Also test special case when %p is used with `char*` pointer types. In
149+ // this case the implementation needs to take care to cast to void*
150+ // before invoking `operator<<`; it must not dereference the pointer and
151+ // print as a string.
141152# ifdef _MSC_VER
142153# ifdef _WIN64
143- CHECK_EQUAL (tfm::format (" %p" , (void *)0x12345 ), " 0000000000012345" );
154+ CHECK_EQUAL (tfm::format (" %p" , (void *)0x12345 ), " 0000000000012345" );
155+ CHECK_EQUAL (tfm::format (" %p" , (const char *)0x10 ), " 0000000000000010" );
144156# else
145157 CHECK_EQUAL (tfm::format (" %p" , (void *)0x12345 ), " 00012345" );
158+ CHECK_EQUAL (tfm::format (" %p" , (const char *)0x10 ), " 00000010" );
146159# endif // _WIN64
147160# else
148161 CHECK_EQUAL (tfm::format (" %p" , (void *)0x12345 ), " 0x12345" );
149- # endif // _MSC_VER
150- CHECK_EQUAL (tfm::format (" %%%s" , " asdf" ), " %asdf" ); // note: plain "%%" format gives warning with gcc
162+ CHECK_EQUAL (tfm::format (" %p" , (const char *)0x10 ), " 0x10" );
163+ CHECK_EQUAL (tfm::format (" %p" , (char *)0x10 ), " 0x10" );
164+ CHECK_EQUAL (tfm::format (" %p" , (signed char *)0x10 ), " 0x10" );
165+ CHECK_EQUAL (tfm::format (" %p" , (unsigned char *)0x10 ), " 0x10" );
166+ # endif // !_MSC_VER
167+
151168 // chars with int format specs are printed as ints:
152169 CHECK_EQUAL (tfm::format (" %hhd" , (char )65 ), " 65" );
153170 CHECK_EQUAL (tfm::format (" %hhu" , (unsigned char )65 ), " 65" );
154171 CHECK_EQUAL (tfm::format (" %hhd" , (signed char )65 ), " 65" );
155- # ifdef _MSC_VER
156- # ifdef _WIN64
157- CHECK_EQUAL (tfm::format (" %p" , (const char *)0x10 ), " 0000000000000010" );
158- # else
159- CHECK_EQUAL (tfm::format (" %p" , (const char *)0x10 ), " 00000010" );
160- # endif // _WIN64
161- # else
162- CHECK_EQUAL (tfm::format (" %p" , (const char *)0x10 ), " 0x10" ); // should print address, not string.
163- # endif // _MSC_VER
164- // bools with string format spec are printed as "true" or "false"
172+ // Bools with string format spec are printed as "true" or "false".
165173 CHECK_EQUAL (tfm::format (" %s" , true ), " true" );
166174 CHECK_EQUAL (tfm::format (" %d" , true ), " 1" );
167175
176+ // ------------------------------------------------------------
168177 // Test precision & width
169178 CHECK_EQUAL (tfm::format (" %10d" , -10 ), " -10" );
170179 CHECK_EQUAL (tfm::format (" %.4d" , 10 ), " 0010" );
@@ -194,6 +203,7 @@ int unitTests()
194203 CHECK_EQUAL (tfm::format (" %1$*3$.*2$f" , 1234.1234567890 , 4 , 10 ), " 1234.1235" );
195204 CHECK_EQUAL (tfm::format (" %1$*2$.*3$f" , 1234.1234567890 , -10 , 4 ), " 1234.1235 " );
196205
206+ // ------------------------------------------------------------
197207 // Test flags
198208 CHECK_EQUAL (tfm::format (" %#x" , 0x271828 ), " 0x271828" );
199209 CHECK_EQUAL (tfm::format (" %#o" , 0x271828 ), " 011614050" );
@@ -215,6 +225,7 @@ int unitTests()
215225 CHECK_EQUAL (tfm::format (" %-010d" , 10 ), " 10 " ); // '-' overrides '0'
216226 CHECK_EQUAL (tfm::format (" %0-10d" , 10 ), " 10 " );
217227
228+ // ------------------------------------------------------------
218229 // Check that length modifiers are ignored
219230 CHECK_EQUAL (tfm::format (" %hd" , (short )1000 ), " 1000" );
220231 CHECK_EQUAL (tfm::format (" %ld" , (long )100000 ), " 100000" );
@@ -223,13 +234,11 @@ int unitTests()
223234 CHECK_EQUAL (tfm::format (" %td" , (ptrdiff_t )100000 ), " 100000" );
224235 CHECK_EQUAL (tfm::format (" %jd" , 100000 ), " 100000" );
225236
226- // Check that 0-argument formatting is printf-compatible
227- CHECK_EQUAL (tfm::format (" 100%%" ), " 100%" );
228-
229237 // printf incompatibilities:
230238 // compareSprintf("%6.4x", 10); // precision & width can't be supported independently
231239 // compareSprintf("%.4d", -10); // negative numbers + precision don't quite work.
232240
241+ // ------------------------------------------------------------
233242 // General "complicated" format spec test
234243 CHECK_EQUAL (tfm::format (" %0.10f:%04d:%+g:%s:%#X:%c:%%:%%asdf" ,
235244 1.234 , 42 , 3.13 , " str" , 0XDEAD , (int )' X' ),
@@ -239,6 +248,8 @@ int unitTests()
239248 3.13 , 1.234 , 42 , 4 , 0XDEAD , " str" , (int )' X' ),
240249 " 1.2340000000:0042:+3.13:str:0XDEAD:X:%:%asdf" );
241250
251+ // ------------------------------------------------------------
252+ // Error handling
242253 // Test wrong number of args
243254 EXPECT_ERROR ( tfm::format (" %d" , 5 , 10 ) )
244255 EXPECT_ERROR ( tfm::format (" %d %d" , 1 ) )
@@ -263,6 +274,8 @@ int unitTests()
263274 // Unhandled C99 format spec
264275 EXPECT_ERROR ( tfm::format (" %n" , 10 ) )
265276
277+ // ------------------------------------------------------------
278+ // Misc
266279#ifdef TEST_WCHAR_T_COMPILE
267280 // Test wchar_t handling - should fail to compile!
268281 tfm::format (" %ls" , L" blah" );
0 commit comments