Compare commits

..

973 Commits
0.8.0 ... 1.1.0

Author SHA1 Message Date
Victor Zverovich
0b097da31e Set release date 2015-03-06 08:33:25 -08:00
Victor Zverovich
f9e98c2007 Merge branch 'master' of github.com:cppformat/cppformat 2015-03-06 08:30:38 -08:00
Victor Zverovich
2d80bcc1cb Bump version 2015-03-06 08:30:30 -08:00
Victor Zverovich
fa5b35e539 Update ChangeLog.rst 2015-03-06 08:17:13 -08:00
Victor Zverovich
549b61e958 Update ChangeLog.rst 2015-03-06 08:15:11 -08:00
Victor Zverovich
2d200e3caa Update ChangeLog.rst 2015-03-06 08:14:19 -08:00
Victor Zverovich
3252eead94 Update ChangeLog.rst 2015-03-06 08:03:34 -08:00
Victor Zverovich
d82b6c7e62 Update ChangeLog.rst 2015-03-06 08:03:11 -08:00
Victor Zverovich
55ba812d12 Update ChangeLog.rst 2015-03-06 07:52:51 -08:00
Victor Zverovich
5463a62d43 Update ChangeLog.rst 2015-03-06 07:52:06 -08:00
Victor Zverovich
9350328086 Update ChangeLog.rst 2015-03-06 07:32:28 -08:00
Victor Zverovich
9d1fc0ecd5 Update ChangeLog.rst 2015-03-06 07:18:44 -08:00
Victor Zverovich
9c006520bd Break long lines 2015-03-05 08:15:26 -08:00
Victor Zverovich
8ad6f93428 Update changelog 2015-03-05 08:04:27 -08:00
Victor Zverovich
72c97ab4ab Add missing '>' 2015-03-05 07:31:27 -08:00
Victor Zverovich
bcc2fd1dbe Fix markup 2015-03-05 07:30:50 -08:00
Victor Zverovich
a89f578c14 Update changelog 2015-03-05 07:29:54 -08:00
Victor Zverovich
6005907db6 Fix markup 2015-03-05 07:27:14 -08:00
Victor Zverovich
53dd7d1583 Update changelog 2015-03-05 07:26:44 -08:00
Victor Zverovich
65a8a7f85e Fix markup 2015-03-04 19:03:56 -08:00
Victor Zverovich
89e0684da6 Update changelog 2015-03-04 19:02:59 -08:00
Victor Zverovich
a5c6975118 Use issue numbers instead of links 2015-03-04 18:50:46 -08:00
Victor Zverovich
ec7b006fab Update changelog 2015-03-04 18:49:23 -08:00
Victor Zverovich
c1f8274701 Copy info from releases to changelog 2015-03-04 18:30:00 -08:00
Victor Zverovich
91d9497911 Fix markup 2015-03-04 18:16:26 -08:00
Victor Zverovich
3453df6d65 Add a changelog 2015-03-04 18:10:08 -08:00
Victor Zverovich
648c730bd2 CMake should be now preinstalled on OS X
https://github.com/travis-ci/travis-ci/issues/2408
2015-03-04 15:15:31 -08:00
Victor Zverovich
8abc15f85e Fix a reference 2015-03-04 14:04:10 -08:00
Victor Zverovich
4ff6ab396c Fix biicode build script 2015-03-04 09:24:54 -08:00
Victor Zverovich
14d1fb561f Don't run biicode on Travis 2015-03-04 09:22:52 -08:00
Victor Zverovich
7ae6dfbcba Fix cmake command 2015-03-04 08:57:56 -08:00
Victor Zverovich
bdada10c2c Only run biicode-build on Linux and print cmake version 2015-03-04 08:53:51 -08:00
Victor Zverovich
65cf5414c9 Temporarily disable biicode build 2015-03-04 08:33:13 -08:00
Victor Zverovich
cb40e7c60b Fix biicode-build script 2015-03-04 08:24:35 -08:00
Victor Zverovich
3a9b7ad8b6 Pass env to bii 2015-03-04 08:07:26 -08:00
Victor Zverovich
38b5f573dd Set CMAKE_ROOT 2015-03-04 08:01:56 -08:00
Victor Zverovich
5ad6c6bd7f Use correct path to CMake bin directory, take 2 2015-03-04 07:51:09 -08:00
Victor Zverovich
85ef48cb6d Use correct path to CMake bin directory 2015-03-04 07:36:30 -08:00
Victor Zverovich
a6864a7264 Fix CMake installation and enable biicode build 2015-03-04 07:07:13 -08:00
Victor Zverovich
0dd1f19281 Temporarily disable biicode build 2015-03-03 22:24:34 -08:00
Victor Zverovich
7c8f915f0b Sudo make me a sandwich 2015-03-03 22:19:56 -08:00
Victor Zverovich
e1b62a5d39 Install CMake in system dirs 2015-03-03 22:12:37 -08:00
Victor Zverovich
4d208ae86f Install newer version of cmake 2015-03-03 22:07:20 -08:00
Victor Zverovich
29451ea8e2 Update travis config 2015-03-03 21:49:33 -08:00
Victor Zverovich
e6113fb9f5 Rewrite biicode build script in Python and simplify 2015-03-03 21:45:47 -08:00
Victor Zverovich
7c0a23329e Update copyright notices 2015-03-03 21:04:45 -08:00
Victor Zverovich
f1e77e41a5 Update breathe 2015-03-02 08:34:22 -08:00
Victor Zverovich
267d4542bb Remove unnecessary stuff from biicode-build.sh 2015-03-02 07:54:13 -08:00
Victor Zverovich
ee5443e920 Move biicode files to support/biicode 2015-03-02 07:48:57 -08:00
Victor Zverovich
103530d407 Fix formatting 2015-03-01 20:58:45 -08:00
Victor Zverovich
efc42fbd4e Temporary exclude fancy ctor from the docs 2015-03-01 18:25:40 -08:00
Victor Zverovich
7c0d5756ff Fix clang build 2015-03-01 18:19:56 -08:00
Victor Zverovich
91a7ee6c20 Add BasicArrayWriter to docs 2015-03-01 18:10:09 -08:00
Victor Zverovich
74512aa282 Ignore bin directory 2015-03-01 18:09:03 -08:00
Victor Zverovich
beaf6f7436 Add a fixed-size array writer 2015-03-01 18:08:24 -08:00
Victor Zverovich
63b4f0ae1a build.py -> appveyor-build.py 2015-03-01 17:20:22 -08:00
Victor Zverovich
5bea8a649b Move biicode C++ Format sample to support/biicode/sample.cc 2015-03-01 17:12:14 -08:00
Victor Zverovich
2e3423b053 Update compile-test 2015-03-01 17:03:44 -08:00
Victor Zverovich
1244f3d58f Move biicode.cmake to support/cmake 2015-03-01 17:00:53 -08:00
Victor Zverovich
656f0895ed Add readme 2015-03-01 16:48:08 -08:00
Victor Zverovich
5a51aac85e Move biicode build script to support/biicode-build.sh 2015-03-01 16:46:44 -08:00
Victor Zverovich
c3e845ab7e Only enable doc target if breathe is available 2015-03-01 16:35:29 -08:00
Victor Zverovich
ce4d3e175c Fix biicode build 2015-03-01 16:23:47 -08:00
Victor Zverovich
fb86e4f6fa Remove conf.py from .gitignore 2015-03-01 16:16:18 -08:00
Victor Zverovich
da6ac7fb26 Fix tests 2015-03-01 16:12:26 -08:00
Victor Zverovich
07754c047c Place executables in the bin dir 2015-03-01 16:07:18 -08:00
Victor Zverovich
67089022bf Run test commands during CI builds 2015-03-01 15:21:33 -08:00
Victor Zverovich
4df5d10e3c Check if initializer lists are supported 2015-03-01 14:14:06 -08:00
Victor Zverovich
8a915b9b8d Update compile-test 2015-03-01 14:13:45 -08:00
Victor Zverovich
8f1e5df672 Merge branch 'master' of github.com:cppformat/cppformat 2015-03-01 09:43:44 -08:00
Victor Zverovich
c09c42f9a7 Don't do explicit instantiation in the header-only mode 2015-03-01 09:43:33 -08:00
Victor Zverovich
86a7d856fa Update README.rst 2015-02-26 09:05:20 -08:00
Victor Zverovich
391d6430e5 Update README.rst 2015-02-26 08:10:36 -08:00
Victor Zverovich
a8a7534f78 Reorder function declarations
Obey your inner OCD
2015-02-26 06:54:12 -08:00
Victor Zverovich
110d4c0ab0 Replace CharTraits::UnsupportedStrType with WCharHelper::Unsupported 2015-02-26 06:32:00 -08:00
Victor Zverovich
17b9e4db8c Improve error reporting when trying to write wchar_t with a char writer 2015-02-26 06:21:54 -08:00
Victor Zverovich
52f44bf114 Fix clang warning
warning: unknown warning group '-Wdocumentation-unknown-command',
ignored [-Wunknown-pragmas]
2015-02-25 17:32:32 -08:00
Victor Zverovich
fede517b22 Don't define _CRT_SECURE_NO_WARNINGS if it is already defined
This is done to avoid warnings.
2015-02-25 17:20:26 -08:00
Victor Zverovich
c746122623 Remove extra whitespace 2015-02-25 16:23:11 -08:00
Victor Zverovich
ed490145d8 Improve error reporting when trying to format wide char into narrow string 2015-02-25 16:03:00 -08:00
Victor Zverovich
f3fe82415d Merge branch 'master' of github.com:cppformat/cppformat 2015-02-25 09:50:53 -08:00
Victor Zverovich
d5602d9fb6 Remove unnecessary call to convert 2015-02-25 09:50:39 -08:00
Victor Zverovich
7716157bdb Update README.rst 2015-02-25 09:00:31 -08:00
Victor Zverovich
e70af5b99e Merge branch 'better-errors' 2015-02-25 08:00:46 -08:00
Victor Zverovich
f014d32147 Improve error reporting when formatting wide into narrow strings 2015-02-25 07:58:49 -08:00
Victor Zverovich
bf14b2c41b Try improving error reporting
when formatting wide strings into narrow.
2015-02-25 07:43:47 -08:00
Victor Zverovich
f6cffb5eeb Indent 2015-02-25 06:17:12 -08:00
Victor Zverovich
c634a5bf2b Merge branch 'master' of github.com:cppformat/cppformat 2015-02-25 06:16:08 -08:00
Victor Zverovich
f8fd34ac30 Merge pull request #121 from objectx/VC2013
Avoid error C2156 under VC++2013
2015-02-25 06:15:09 -08:00
Masashi Fujita
c2bcb31354 Avoid error C2156 under VC++2013 2015-02-25 20:40:28 +09:00
Victor Zverovich
7215c3446b Break long lines 2015-02-24 16:44:01 -08:00
Victor Zverovich
642b72cd91 Fix StringRef test 2015-02-24 09:52:16 -08:00
Victor Zverovich
89fed501d4 Merge branch 'master' of github.com:cppformat/cppformat 2015-02-24 08:32:12 -08:00
Victor Zverovich
28fd7fb159 Fix formatting (-Gangnam- Google style) 2015-02-24 08:31:56 -08:00
Victor Zverovich
85833c90ee Merge pull request #119 from TrentHouliston/master
Add an install command to the cmake file (to allow make install)
2015-02-24 05:55:46 -08:00
Trent Houliston
4da1fa391e Add an install command to the cmake file (to allow make install) 2015-02-24 17:31:30 +11:00
Victor Zverovich
de92f5d8a7 Update README.rst 2015-02-22 11:46:58 -08:00
Victor Zverovich
d06ff7a7e8 Fix internal::clzll on Win64 2015-02-22 06:31:55 -08:00
Victor Zverovich
a81baf2904 Merge branch 'master' of github.com:cppformat/cppformat 2015-02-22 06:29:33 -08:00
Victor Zverovich
810c734c3f Merge pull request #118 from CarterLi/master
Emulate _BitScanForward64 on WIN32
2015-02-22 06:29:19 -08:00
Carter Li
524222f094 Win32 doesn't have _BitScanForward64 so emulate it with two 32 bit calls.
Implementation used: http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/support/win32/support.h?view=markup#l135
2015-02-22 17:48:19 +08:00
Victor Zverovich
016adee06c Simplify sample 2015-02-21 16:15:47 -08:00
Victor Zverovich
2b35c9e8e7 Move CMake files to support 2015-02-21 16:02:44 -08:00
Victor Zverovich
cbc46d9e78 Use __builtin_clz whenever it is available 2015-02-21 06:21:29 -08:00
Victor Zverovich
e87a24633b Don't use builtin_ in function names as they are not builtins 2015-02-21 06:16:49 -08:00
Victor Zverovich
14eae59c6a Correct FMT_BUILTIN_CLZ definition 2015-02-20 08:58:16 -08:00
Victor Zverovich
2418a84f02 Cleanup 2015-02-20 08:51:01 -08:00
Victor Zverovich
27e0bf72c0 Use correct intrinsics for count_digits 2015-02-20 08:49:06 -08:00
Victor Zverovich
939193be21 Merge pull request #116 from CarterLi/master
Use MSVC intrinsics for better performance
2015-02-20 08:22:06 -08:00
Carter Li
00e3ae508e Use MSVC intrinsics for better performance 2015-02-20 11:19:01 +08:00
Victor Zverovich
bc33d17ce3 Update README.rst 2015-02-19 08:40:40 -08:00
Victor Zverovich
65cd4835cd Update README.rst 2015-02-19 08:26:03 -08:00
Victor Zverovich
53010624a0 Move Windows implementation of print_colored to a separate branch
as it needs further testing.
2015-02-19 07:54:59 -08:00
Victor Zverovich
a92205be9c Remove unused policy setting 2015-02-17 14:42:11 -08:00
Victor Zverovich
a16ca84346 Use mirror 2015-02-17 09:19:49 -08:00
Victor Zverovich
f40f790159 Merge branch 'master' of github.com:cppformat/cppformat 2015-02-17 09:17:21 -08:00
Victor Zverovich
88835f8468 Fix mingw download URL 2015-02-17 09:16:50 -08:00
Victor Zverovich
5b0a9bbe85 Improve StringRef test 2015-02-17 06:45:45 -08:00
Victor Zverovich
6a52fc164a Merge pull request #114 from CarterLi/master
Silence warnings on Windows
2015-02-17 06:39:21 -08:00
Victor Zverovich
b4df6cb2fa Add libstdc++ version 2015-02-17 06:24:40 -08:00
Victor Zverovich
932eb9777e Fix formatting, take 2 2015-02-17 06:15:44 -08:00
Victor Zverovich
4a1974577f Fix formatting 2015-02-17 06:14:32 -08:00
Victor Zverovich
dfad5f1d39 Update README.rst 2015-02-17 06:12:44 -08:00
Carter Li
3f574c1611 Silence warnings on Windows 2015-02-17 10:11:42 +08:00
Victor Zverovich
8d07db0e0e Break long line 2015-02-16 14:33:04 -08:00
Victor Zverovich
bd133382f0 Fix BasicWriter::write without formatting arguments on C++11 (#109) 2015-02-16 14:32:38 -08:00
Victor Zverovich
040b8e7e06 Link to Android NDK 2015-02-16 07:25:45 -08:00
Victor Zverovich
d9ef0e0a44 Minor correction 2015-02-16 07:11:57 -08:00
Victor Zverovich
6c656663f3 Merge branch 'master' of github.com:cppformat/cppformat 2015-02-16 07:09:33 -08:00
Victor Zverovich
291e43abac Add Android NDK section 2015-02-16 07:09:25 -08:00
Victor Zverovich
a85d5e962b Update README.rst 2015-02-15 09:32:13 -08:00
Victor Zverovich
11fab458c4 Merge pull request #107 from newnon/master
Android.mk
2015-02-15 09:12:49 -08:00
Victor Zverovich
829cd70cd2 Merge pull request #112 from CarterLi/master
Detect static assertion support
2015-02-15 08:43:59 -08:00
Sergey
1d49443405 fix android.mk 2015-02-15 19:21:32 +03:00
root
9fd566412d Refine 2015-02-15 15:25:56 +08:00
carterl
9331533309 Use __GXX_EXPERIMENTAL_CXX0X__ for better C++11 detection 2015-02-15 04:16:23 +01:00
carterl
43b9fefbd2 Use static_assert more actively 2015-02-15 03:55:21 +01:00
Victor Zverovich
0fc15d48f3 Merge pull request #111 from CarterLi/master
Use explicitly deleted functions to make types non-copyable
2015-02-14 08:33:37 -08:00
Carter Li
2eef573656 Use explicitly deleted functions to make types non-copyable 2015-02-14 23:22:14 +08:00
Victor Zverovich
f77350f8fa Disable unnecessary CMake check and comment 2015-02-14 06:18:19 -08:00
Victor Zverovich
5282bebbd7 Merge pull request #110 from CarterLi/master
Use throw() when noexcept is not supported
2015-02-14 06:10:11 -08:00
Carter Li
e2583ab5f3 Use throw() when noexcept is not supported 2015-02-14 09:58:29 +08:00
Victor Zverovich
950e6b9753 Fix downloader 2015-02-12 21:34:36 -08:00
Victor Zverovich
c110f7b8d3 Move the code from appveyor config to a Python script
No more PowerShell rubbish, yay!
2015-02-12 17:53:39 -08:00
Victor Zverovich
86fee707fb Update MinGW URL 2015-02-12 16:48:17 -08:00
Victor Zverovich
c643fdae53 Fix CMake warning 2015-02-12 15:55:21 -08:00
Victor Zverovich
609f33c94a Fix appveyor script 2015-02-12 15:41:30 -08:00
Victor Zverovich
2f05eaa07d Correct filename in Biicode config 2015-02-12 15:39:06 -08:00
Victor Zverovich
2ced92529d Move logic from travis.yml to a Python script 2015-02-12 15:34:38 -08:00
Victor Zverovich
dd2e8b98de Fix RST markup 2015-02-12 12:46:28 -08:00
Sergey Perepelitsa
f79c88c190 Android.mk 2015-02-12 23:34:56 +03:00
Victor Zverovich
4f51033aa9 Workaround PowerShell idiocy 2015-02-12 12:27:32 -08:00
Victor Zverovich
503e87f153 Report CMake version for debugging 2015-02-12 11:41:45 -08:00
Victor Zverovich
3822241d99 Use policy check instead of CMake version check 2015-02-12 11:27:55 -08:00
Victor Zverovich
e392eea160 Fix CMake warning 2015-02-12 10:12:26 -08:00
Victor Zverovich
8273855067 Remove extra newline mostly to check for linguist updates 2015-02-12 06:23:58 -08:00
Victor Zverovich
8bd1953094 Minor changes to follow C++ Format's coding conventions 2015-02-11 14:16:22 -08:00
Victor Zverovich
33f85efb55 Merge pull request #104 from franramirez688/master
Adapted to biicode via biicode.conf, ignore.bii and CMakeLists.txt
2015-02-11 14:02:27 -08:00
franchuti688
7b77eb61b5 adapted to biicode via biicode.conf, ignore.bii and CMakeLists.txt; mixed Travis
(original and biicode building)
2015-02-11 22:52:00 +01:00
Victor Zverovich
50151ff804 Update README.rst 2015-02-10 19:37:54 -08:00
Victor Zverovich
4a11f70408 Update README.rst
D'oh.
2015-02-10 19:36:29 -08:00
Victor Zverovich
01b00e6dfb Update README.rst 2015-02-10 19:34:03 -08:00
Victor Zverovich
a32f9148fc Update README.rst 2015-02-10 19:32:33 -08:00
Victor Zverovich
a95b3f7ee1 Update README.rst 2015-02-10 19:31:22 -08:00
Victor Zverovich
04a21bbb2e Merge branch 'fallthrough' of github.com:cppformat/cppformat 2015-02-09 08:02:14 -08:00
Victor Zverovich
618dd9d6af Remove the fallthrough attribute detection 2015-02-09 07:54:03 -08:00
Victor Zverovich
a92c179a6d Fix warnings on clang 2015-02-09 07:37:26 -08:00
Victor Zverovich
267382af39 Revert the experimental fix for print_colored that didn't work 2015-02-09 06:53:05 -08:00
Victor Zverovich
cfd476bb8b Temporarily disable the test as the fix didn't work. 2015-02-08 20:41:13 -08:00
Victor Zverovich
e875e3145f Fix print_colored on Windows 2015-02-08 20:24:07 -08:00
Victor Zverovich
9368b6a4ee Fix error handling in print_colored 2015-02-08 20:06:45 -08:00
Victor Zverovich
7004d1edf6 Update the contributed code to the used coding conventions 2015-02-08 19:54:39 -08:00
Victor Zverovich
d5ab6ba728 Merge pull request #102 from Ryuuke/master
added color support for windows
2015-02-08 18:25:31 -08:00
Ryuuke
bc78ca42a9 remove global variables 2015-02-08 23:10:13 +00:00
Ryuuke
4806f75469 remove unused define 2015-02-08 16:14:46 +00:00
Ryuuke
5a9dc8f991 windows cli colors revision and test case 2015-02-08 16:08:29 +00:00
viz
26c151c5e4 Detect [[clang::fallthrough]] even __has_cpp_attribute is not supported 2015-02-08 07:57:05 -08:00
Ryuuke
bce73e2bd8 remove forward enum declaration 2015-02-07 22:47:42 +00:00
Ryuuke
51ceef3dee added color support for windows 2015-02-07 22:39:08 +00:00
Victor Zverovich
326ade7698 Document what happens if you pass an invalid error code
to SystemError or WindowsError
2015-02-07 09:46:42 -08:00
Victor Zverovich
502d2ede8a Bump version 2015-02-07 08:53:30 -08:00
Victor Zverovich
81dc04dd48 Update README.rst
Add POL to the list of projects using cppformat
2015-02-07 08:31:17 -08:00
Victor Zverovich
fe2b5351be Merge pull request #101 from cppformat/fallthrough
Try detecting clang::fallthrough using __has_cpp_attribute
2015-02-07 06:57:20 -08:00
Victor Zverovich
d7fea1ba0c Try detecting clang::fallthrough using __has_cpp_attribute
and use it to silence one of the warnings in #96.
2015-02-07 06:51:47 -08:00
Victor Zverovich
37ad436068 Fix by @dixlorenz for clang warnings "'return' will never be executed" (#96) 2015-02-06 21:27:31 -08:00
Victor Zverovich
45d70b71ec Fix by @dixlorenz for clang warning about unknown Doxygen tags 2015-02-06 21:25:30 -08:00
Victor Zverovich
d930f6956f Update README.rst
Add a link to GitHub search for projects using the library
2015-02-06 14:03:44 -08:00
Victor Zverovich
38a7406318 Update README.rst
Add 0 A.D. to the list of projects using C++ Format and reorder projects lexicographically
2015-02-06 13:46:19 -08:00
Victor Zverovich
83f5085551 Remove RTD theme 2015-02-06 09:01:49 -08:00
Victor Zverovich
554abb12f1 Fix formatting 2015-02-06 08:45:43 -08:00
Victor Zverovich
f2c16957f7 Provide examples of using SystemError and WindowsError (#54) 2015-02-06 08:43:02 -08:00
Victor Zverovich
48e6df117a Merge branch 'master' of github.com:cppformat/cppformat 2015-02-06 07:27:29 -08:00
Victor Zverovich
59254410da Fix a warning (#95) 2015-02-06 07:27:19 -08:00
Victor Zverovich
58a300c82a Merge pull request #98 from MariadeAnton/master
Update README.rst
2015-02-06 07:07:14 -08:00
MariadeAnton
710817befb Update README.rst
Added biicode badge
2015-02-06 15:19:30 +01:00
Victor Zverovich
ba17cca432 Fix link 2015-02-05 11:18:16 -08:00
Victor Zverovich
f82f4bd79b Merge branch 'master' of github.com:cppformat/cppformat 2015-02-05 11:16:47 -08:00
Victor Zverovich
589b73f646 Update links 2015-02-05 11:16:39 -08:00
Victor Zverovich
afba2422ae Fix packaging 2015-02-05 08:50:47 -08:00
Victor Zverovich
58683f5376 Version 1.0 🎆 2015-02-05 08:42:25 -08:00
Victor Zverovich
bc6fcd90cf Fix CSS 2015-02-05 08:41:19 -08:00
Victor Zverovich
402f5f3178 Documentation fixes 2015-02-05 08:36:46 -08:00
Victor Zverovich
bdeffc3fdc Fix build on Android NDK
where XSI-compliant version of strerror_r is used violating the docs at
http://linux.die.net/man/3/strerror_r
2015-02-05 07:04:22 -08:00
Victor Zverovich
b4eef59100 Only add the doc target if doxygen and sphinx-build are available 2015-01-30 12:53:52 -08:00
Victor Zverovich
90bc8dd3ed Don't track the dependencies of the doc target as Sphinx does it itself 2015-01-30 08:49:48 -08:00
Victor Zverovich
237eaa53e1 Replace exclude_trees with exclude_patterns
exclude_trees was removed in Sphinx 1.3b1
2015-01-30 07:15:00 -08:00
Victor Zverovich
531ee615af Switch to the main breathe repo 2015-01-21 14:46:29 -08:00
Victor Zverovich
fae27d262c Switch to the main breathe repo 2015-01-21 14:44:05 -08:00
Victor Zverovich
0bd32f3f29 Merge branch 'master' of github.com:cppformat/cppformat 2015-01-08 07:56:19 -08:00
Victor Zverovich
43aebf51d6 Allow precision specifier for non-float arguments 2015-01-08 07:56:08 -08:00
Victor Zverovich
757a523195 Merge pull request #89 from mparaniak/master
Add format linking to tests
2015-01-06 09:12:37 -08:00
Mikolaj Paraniak
7f706171a9 Add format linking to tests 2015-01-06 16:57:07 +01:00
Victor Zverovich
cd828a8691 Add a test for https://github.com/cppformat/cppformat/issues/86 2015-01-05 07:16:26 -08:00
Victor Zverovich
6080108802 Merge pull request #87 from aruhan/issue/86
Fix format using wostream produces wrong results
2015-01-05 07:13:04 -08:00
aruhan
e8febf7f4b Fix format using wostream produces wrong results 2015-01-05 22:33:18 +09:00
Victor Zverovich
130bccbcbf Update README.rst 2014-12-19 07:50:41 -08:00
Victor Zverovich
01414ac6ec Update README.rst 2014-12-19 07:49:54 -08:00
Victor Zverovich
3cb004d0d3 Update README.rst 2014-12-19 07:48:38 -08:00
Victor Zverovich
a7d7e0daec Restore bootstrap theme 2014-12-19 07:42:46 -08:00
Victor Zverovich
67e196eac4 Make test libraries static 2014-12-19 07:39:13 -08:00
Victor Zverovich
fdecd5b40f Remove FMT_SHARED in favor of BUILD_SHARED_LIBS 2014-12-19 07:37:49 -08:00
Victor Zverovich
a8b1769803 Use default namespace 2014-12-18 08:46:25 -08:00
Victor Zverovich
8d89e56d2c Set primary domain to cpp 2014-12-18 08:36:53 -08:00
Victor Zverovich
fb12cfd196 Suppress more bogus warnings 2014-12-17 06:53:32 -08:00
Victor Zverovich
ecd2b80e8f Get rid of using declarations for header-only config 2014-12-17 06:42:26 -08:00
Victor Zverovich
c95908bd8c Disable bogus MSVC warnings 2014-12-17 06:41:21 -08:00
Victor Zverovich
c630d1f236 Disable "secure" warnings in posix. 2014-12-16 07:07:09 -08:00
Victor Zverovich
0d1eb8b1ea Don't undefine "secure" warnings 2014-12-16 07:02:59 -08:00
Victor Zverovich
dff2137405 Don't define/undefine macros without FMT_ prefix 2014-12-16 07:01:01 -08:00
Victor Zverovich
2523f3b939 Fix more -Wshadow warnings 2014-12-10 07:24:05 -08:00
Victor Zverovich
f9fc8fd09d Fix -Wshadow warnings 2014-12-09 07:45:54 -08:00
Victor Zverovich
b49a1b4a52 Fix linkage errors on Windows in header-only config 2014-12-09 06:32:07 -08:00
Victor Zverovich
df580969f7 Add a test for header-only configuration 2014-12-09 06:22:55 -08:00
Victor Zverovich
f9c3ff244d Merge branch 'header-only' of github.com:cppformat/cppformat 2014-12-09 06:14:04 -08:00
Victor Zverovich
6e3d7d9a6a Update README.rst
Add spdlog
2014-12-08 06:15:31 -08:00
Victor Zverovich
54f19ff7b2 Simplify append_float_length 2014-12-03 06:33:31 -08:00
Victor Zverovich
f3bd9d4241 Remove extra space 2014-12-03 06:20:12 -08:00
Victor Zverovich
6f3c095ed6 Use FMT_DISALLOW_COPY_AND_ASSIGN instead of undefined assignment operators 2014-12-03 06:16:52 -08:00
Victor Zverovich
0fea89ec8f Merge pull request #81 from Queueless/master
Fixed Level 4 warnings on Windows
2014-12-03 06:04:06 -08:00
Victor Zverovich
7706e1054d Update README.rst
Fix formatting
2014-12-02 12:55:13 -08:00
Victor Zverovich
a23fbbb9a3 Update README.rst
Add Analytics Cloud to the list of projects using C++ Format.
Source: https://help.salesforce.com/servlet/servlet.FileDownload?file=015300000035w3yAAA
2014-12-02 12:54:12 -08:00
Daniel.Perry
838dc1e189 move append_float_length specialization to the header 2014-12-02 10:20:27 -05:00
Victor Zverovich
820c03a473 Update README.rst
Add readpe to projects using cppformat
2014-12-02 06:39:16 -08:00
Victor Zverovich
311251eb91 Complete header-only configuration support 2014-11-29 06:58:00 -08:00
Victor Zverovich
c2a6903e19 Define FMT_FUNC to nothing if FMT_HEADER_ONLY is not defined 2014-11-28 15:30:03 -08:00
Victor Zverovich
d9c605c61f Initial support for header-only configuration 2014-11-28 06:40:57 -08:00
Daniel.Perry
334fc54b5d removed unused code 2014-11-25 18:03:54 -05:00
Daniel.Perry
bd0067ee76 made code compile under windows with level 4 warnings 2014-11-25 18:01:09 -05:00
Victor Zverovich
4c59aa8780 Link to stable docs 2014-11-24 16:20:07 -08:00
Victor Zverovich
aca49379a5 Fix a few minor issues detected by CppCheck
Thanks to Dmitry Andriyankov for reporting.
2014-11-24 07:38:26 -08:00
Victor Zverovich
615c1eef6b Fix error handling in fmt::fprintf. 2014-11-14 09:40:01 -08:00
Victor Zverovich
8ea9f068c7 Convert tabs to spaces 2014-11-07 07:58:49 -08:00
Victor Zverovich
97ea39cf79 Remove no longer needed highlight directives 2014-11-07 07:26:04 -08:00
Victor Zverovich
43d3c0a110 Set highlight language to c++ in config 2014-11-07 07:24:51 -08:00
Victor Zverovich
f02e4100db Undo highlight since it's not working and simplify markup 2014-11-07 07:04:03 -08:00
Victor Zverovich
e41ca7b951 Try setting highlight to c++ 2014-11-07 06:56:53 -08:00
Victor Zverovich
6527551d43 Simplify markup 2014-11-05 07:39:34 -08:00
Victor Zverovich
9cbb25e43f Simplify markup 2014-11-05 07:36:55 -08:00
Victor Zverovich
10698cc44d Update theme 2014-11-04 08:31:07 -08:00
Victor Zverovich
aa78f6155b Add theme alias 2014-11-04 08:17:59 -08:00
Victor Zverovich
6bcfb377b2 Link to docs 2014-11-04 07:44:07 -08:00
Victor Zverovich
bbd7681a33 Add ReadTheDocs badge 2014-11-04 07:42:56 -08:00
Victor Zverovich
8f93e84a1a Switch to ReadTheDocs theme 2014-11-04 07:37:25 -08:00
Victor Zverovich
ed92af29b3 Add missing ')' 2014-10-30 13:58:16 -07:00
Victor Zverovich
14984acd27 Fix UTF conversion tests 2014-10-30 13:00:44 -07:00
Victor Zverovich
daca48cb15 Fix MSVC build 2014-10-30 12:20:08 -07:00
Victor Zverovich
cabe5bddb4 Fix util-test 2014-10-30 08:07:28 -07:00
Victor Zverovich
5a5870d3ca n -> size 2014-10-30 07:10:43 -07:00
Victor Zverovich
5c4b6678e4 Compute StringRef size in ctor 2014-10-30 07:05:42 -07:00
Victor Zverovich
10d83aaa52 Test that StringRef size computation 2014-10-30 06:27:44 -07:00
Victor Zverovich
d5a6316d5c Update breathe 2014-10-25 10:27:49 -07:00
Victor Zverovich
9501ca0e68 Update theme 2014-10-24 07:43:53 -07:00
Victor Zverovich
06ae9a6de0 Update breathe 2014-10-24 07:09:56 -07:00
Victor Zverovich
c50e7781fc Remove old bootstrap theme 2014-10-24 07:09:46 -07:00
Victor Zverovich
e3263a341e Update theme 2014-10-23 07:25:54 -07:00
Victor Zverovich
adca25913c Indent descriptions of macros 2014-10-23 07:22:37 -07:00
Victor Zverovich
99ff512b32 Use sphinx bootstrap theme from subproject 2014-10-23 07:17:56 -07:00
Victor Zverovich
0019793786 Add bootstrap theme as a module 2014-10-21 08:28:27 -07:00
Victor Zverovich
e640e458c1 Align navbar content with the main content 2014-10-20 08:56:27 -07:00
Victor Zverovich
fb6ed7590b Align footer with the main content 2014-10-17 09:39:43 -07:00
Victor Zverovich
e9bf788bd5 Add side margins if screen is too wide 2014-10-17 09:20:21 -07:00
Victor Zverovich
4a818ac785 Move CSS override to theme because RTD ignores layout.html
RTD bug: https://github.com/rtfd/readthedocs.org/issues/152
2014-10-17 09:15:47 -07:00
Victor Zverovich
c90c6805a2 Add side margins if screen is too wide 2014-10-17 07:53:56 -07:00
Victor Zverovich
7d2c3ac0f2 Add styles 2014-10-17 07:24:49 -07:00
Victor Zverovich
32392597aa Move Usage section to a separate file 2014-10-16 07:12:43 -07:00
Victor Zverovich
2b17d47372 Merge branch 'master' of github.com:cppformat/cppformat 2014-10-16 06:51:04 -07:00
Victor Zverovich
ca94e4d27f Update breathe 2014-10-16 06:50:48 -07:00
Victor Zverovich
c752b6d489 Merge pull request #78 from amorozov/issue/76
sign-compare warnings fixes
2014-10-14 06:46:20 -07:00
Alexey Morozov
4d3126c567 sign-compare warnings fixes 2014-10-14 03:28:47 +07:00
Victor Zverovich
755ecb0311 Fix warnings 2014-10-13 08:39:38 -07:00
Victor Zverovich
d707adce5c Fix warning in clang 2014-10-13 06:59:18 -07:00
Victor Zverovich
0d732cf5d3 Merge branch 'master' of github.com:cppformat/cppformat 2014-10-13 06:46:17 -07:00
Victor Zverovich
5189274797 Fix warnings 2014-10-13 06:46:07 -07:00
Victor Zverovich
73ec6504c7 Update README.rst 2014-10-12 14:18:17 -07:00
Victor Zverovich
88f3f53870 Fix Sphinx config 2014-10-10 08:47:36 -07:00
Victor Zverovich
709465197a Switch to bootstrap theme 2014-10-10 08:40:35 -07:00
Victor Zverovich
76a2ea56ce Add bootstrap Sphinx theme 2014-10-10 08:39:54 -07:00
Victor Zverovich
a7520f164a Restore theme 2014-10-10 06:18:50 -07:00
Victor Zverovich
bb1926753d Try using the default theme 2014-10-10 06:10:52 -07:00
Victor Zverovich
f05e856017 Fix example 2014-10-09 11:25:39 -07:00
Victor Zverovich
4865950649 Update links 2014-10-09 09:10:12 -07:00
Victor Zverovich
8cab5909e0 Improve PDF output 2014-10-09 07:57:26 -07:00
Victor Zverovich
80f5cbb9e5 Add missing quote 2014-10-09 07:57:03 -07:00
Victor Zverovich
833fd47f83 Change the next version number to 0.12.0 2014-10-06 08:49:33 -07:00
Victor Zverovich
8b76e97062 Support compilation with exceptions disabled 2014-10-06 08:30:55 -07:00
Victor Zverovich
55c61d1abd Update project name 2014-10-06 08:27:42 -07:00
Victor Zverovich
b6afd93879 Split long line 2014-10-06 08:20:52 -07:00
Victor Zverovich
1e63fc7ca0 Comment 2014-10-05 09:34:46 -07:00
Victor Zverovich
32c5dca733 Update breathe 2014-10-03 07:14:56 -07:00
Victor Zverovich
43b389f358 Update README.rst 2014-10-02 06:44:34 -07:00
Victor Zverovich
fae3ae67b9 Fix util-test 2014-10-01 09:32:31 -07:00
Victor Zverovich
ae413ebf7a Add a section on custom allocators 2014-10-01 08:49:20 -07:00
Victor Zverovich
04d38a8b14 Update docs 2014-10-01 08:32:01 -07:00
Victor Zverovich
03f7f99f4c Fix build on pre-C++11 compilers 2014-10-01 08:24:47 -07:00
Victor Zverovich
8b9a6e03f6 Test buffer 2014-10-01 08:12:10 -07:00
Victor Zverovich
74dc571ba0 Support signed char and unsigned char strings 2014-09-30 08:15:56 -07:00
Victor Zverovich
98a25ec7cb Test Buffer 2014-09-30 07:30:27 -07:00
Victor Zverovich
313b259891 Use type_traits to test if copyable/assignable
Replace compile tests that check if types are copy constructible and copy assignable with normal tests that use type_traits (if available).
2014-09-30 07:30:05 -07:00
Victor Zverovich
d00f689c40 Fix type_traits check 2014-09-29 11:03:18 -07:00
Victor Zverovich
b79d06a5da Escape quotes 2014-09-29 10:44:48 -07:00
Victor Zverovich
2846a9eb38 Check if is_copy_assignable is working
is_copy_assignable is broken in MSVC.
2014-09-29 10:42:16 -07:00
Victor Zverovich
810f42c0c7 Fix util-test on Windows, take 2 2014-09-29 09:59:49 -07:00
Victor Zverovich
55a16eaec7 Fix util-test on Windows 2014-09-29 09:37:33 -07:00
Victor Zverovich
a309c4bbed Fix posix-test on Windows 2014-09-29 09:28:44 -07:00
Victor Zverovich
e1c046c984 Fix open check 2014-09-29 09:27:32 -07:00
Victor Zverovich
8c4db5081b Fix Windows build 2014-09-29 09:17:02 -07:00
Victor Zverovich
dd90129066 Check if type_traits actually work. 2014-09-29 09:15:41 -07:00
Victor Zverovich
d1ded569ff Separate memory management and formatting
Array is split into an abstract Buffer class and a concrete MemoryBuffer class. BasicWriter now does all memory allocation through a Buffer object. Subclasses of BasicWriter may use different buffer types. The new BasicMemoryBuffer class uses the default MemoryBuffer.
2014-09-29 08:48:16 -07:00
Victor Zverovich
5ca3d00e26 Mind the lifetime 2014-09-25 12:15:16 -07:00
Victor Zverovich
a9da3d3852 Fix ArgList::operator[] 2014-09-25 09:31:36 -07:00
Victor Zverovich
b2bd63d2d9 Test ArgList 2014-09-25 09:11:51 -07:00
Victor Zverovich
65cb43a484 Store type info in uint64_t instead of ULongLong 2014-09-25 07:42:29 -07:00
Victor Zverovich
c2f02df2f5 Fix warning in clang 2014-09-25 07:38:16 -07:00
Victor Zverovich
f43caef311 Fix linkage 2014-09-25 07:21:48 -07:00
Victor Zverovich
098a8fdef8 Simplify make_type 2014-09-25 07:14:08 -07:00
Victor Zverovich
75a2ea03a7 Reduce code bloat
Special case C strings because there is no need to handle size for them. Add support for pre-C++11 compilers to make_type.
2014-09-25 07:10:44 -07:00
Victor Zverovich
163178eee1 Make print non-inline 2014-09-25 07:08:25 -07:00
Victor Zverovich
ae8bc36e57 MakeArg -> MakeValue 2014-09-24 08:07:50 -07:00
Victor Zverovich
93b314d3ab Comments 2014-09-24 07:59:23 -07:00
Victor Zverovich
ec1aea34e6 Refactor type processing 2014-09-24 07:48:45 -07:00
Victor Zverovich
ab6e759291 pointer_value -> pointer 2014-09-23 08:21:58 -07:00
Victor Zverovich
d2973766ea ArgBase -> Value 2014-09-23 08:11:03 -07:00
Victor Zverovich
beb00edf73 Store types in ArgList instead of Arg 2014-09-23 07:59:43 -07:00
Victor Zverovich
49222dc0c7 Improve allocator test 2014-09-23 07:58:23 -07:00
Victor Zverovich
13bbb0db7a Update docs 2014-09-21 14:12:21 -07:00
Victor Zverovich
eac25ad1c7 Update readme 2014-09-21 08:13:35 -07:00
Victor Zverovich
1d4640415d Pass ArgList by value
This improve bloat test results:
Old stripped size: 67680 (optimized)
New stripped size: 59488 (optimized)
2014-09-21 08:08:52 -07:00
Victor Zverovich
14f2577569 Fix linkage 2014-09-19 08:45:05 -07:00
Victor Zverovich
b9a568b1dd Add support for custom memory allocator to BasicWriter 2014-09-19 07:51:42 -07:00
Victor Zverovich
70205edd6e Fix build with ancient CMake 2014-09-18 09:29:51 -07:00
Victor Zverovich
a734f67978 Check if variadic templates are working 2014-09-18 09:18:18 -07:00
Victor Zverovich
6a98f42336 Add support for custom allocators 2014-09-18 09:07:40 -07:00
Victor Zverovich
a4998accf6 Fix travis build 2014-09-17 08:26:07 -07:00
Victor Zverovich
c76b22405d Replace GTest with GMock (includes GTest) 2014-09-17 08:01:42 -07:00
Victor Zverovich
2938a92d64 Add KBEngine to projects that use cppformat 2014-09-13 08:44:49 -07:00
Victor Zverovich
b54d6e7124 Fix posix-test, take 3. 2014-09-12 18:22:45 -07:00
Victor Zverovich
94daf27c9d Fix posix-test, take 2. 2014-09-12 17:41:04 -07:00
Victor Zverovich
886ad20a9d Remove unused size argument from Array's ctor. 2014-09-12 17:20:36 -07:00
Victor Zverovich
434e83a192 Fix posix-test. 2014-09-12 17:16:22 -07:00
Victor Zverovich
ddd95965e1 Fix MaxSize test. 2014-09-12 16:52:15 -07:00
Victor Zverovich
a3062f6647 Disambiguate a call 2014-09-12 16:18:04 -07:00
Victor Zverovich
352b6ae496 Workaround more Windows crap. 2014-09-12 15:18:11 -07:00
Victor Zverovich
74169e4b5d Add a portable getpagesize() implementation 2014-09-12 13:53:52 -07:00
Victor Zverovich
1e9ca17b9d Workaround Windows crap. 2014-09-12 13:42:22 -07:00
Victor Zverovich
225b757b50 Handy fix for handling of handles. 2014-09-12 12:37:32 -07:00
Victor Zverovich
cb7caa540f Move FMT_STATIC_ASSERT to header and test. 2014-09-12 12:05:32 -07:00
Victor Zverovich
ea9989b254 Add missing include. 2014-09-12 11:57:33 -07:00
Victor Zverovich
949c3c5df4 Test if File::size can handle maximum file size. 2014-09-12 11:12:22 -07:00
Victor Zverovich
e34e9fa0c7 Add File::size and make File's ctor take StringRef. 2014-09-12 10:50:16 -07:00
Victor Zverovich
f175591923 Return size_t instead of streamsize in File::read and File::write
File::read and File::write throw exception on error, so they don't need to return a negative value to indicate error.
2014-09-12 09:38:37 -07:00
Victor Zverovich
6cd9be2c06 Bump version. 2014-09-12 08:29:38 -07:00
Victor Zverovich
3269fce2dc Fix https://github.com/cppformat/cppformat/issues/61 2014-09-12 08:27:23 -07:00
Victor Zverovich
d59fbdcd4a Increase the maximum number of formatting arguments on compilers without variadic templates to 15. 2014-09-11 21:18:36 -07:00
Victor Zverovich
445663fade Fix windows build. 2014-09-05 10:56:00 -07:00
Victor Zverovich
f2c9df8e9f Move safe_strerror to anonymous namespace. 2014-09-05 08:44:41 -07:00
Victor Zverovich
b33d2aa825 Workaround Windows braindamage. 2014-09-05 08:06:07 -07:00
Victor Zverovich
88e0db8486 Test format_error_code. 2014-09-05 08:04:26 -07:00
Victor Zverovich
d4916d9271 Add missing file. 2014-09-05 07:35:00 -07:00
Victor Zverovich
fe9888a1e2 Move implementation tests to format-impl-test. 2014-09-05 07:12:20 -07:00
Victor Zverovich
93bcad6d8e Fix Windows build. 2014-09-03 08:10:20 -07:00
Victor Zverovich
22f75d8b6d Don't throw exceptions from error formatting functions. Gracefully fallback to a less descriptive message instead. 2014-09-03 08:03:05 -07:00
Victor Zverovich
82d4d11c11 format -> cppformat 2014-08-29 09:18:53 -07:00
Victor Zverovich
5debb2aa86 Refactor error reporting to reduce duplication. 2014-08-29 08:16:10 -07:00
Victor Zverovich
605d2600f8 Improve error reporting. 2014-08-29 07:45:55 -07:00
Victor Zverovich
271fa8c908 Improve handling of format strings in custom arguments. 2014-08-29 07:23:54 -07:00
Victor Zverovich
3947a7a98c Move check_sign to anonymous namespace. 2014-08-29 06:57:53 -07:00
Victor Zverovich
ab35af53c5 Check result of fread. 2014-08-29 06:57:26 -07:00
Victor Zverovich
e62354a190 Fix build. 2014-08-28 14:51:01 -07:00
Victor Zverovich
eab0b577f8 Report filename in exception. 2014-08-28 13:42:07 -07:00
Victor Zverovich
e44619707e Fix Windows build. 2014-08-28 12:46:30 -07:00
Victor Zverovich
2dad1690c8 Fix BufferefFile test on Windows. 2014-08-28 12:13:03 -07:00
Victor Zverovich
564da25932 Add ctor & print method to BufferedFile. 2014-08-28 11:53:05 -07:00
Victor Zverovich
108cd1d1a0 Fix anchor. 2014-08-28 10:18:13 -07:00
Victor Zverovich
32344d9b14 Comment 2014-08-28 08:11:21 -07:00
Victor Zverovich
c57d7a506f Factor out argument processing logic common between format and printf to FormatterBase::{next_arg,get_arg}. 2014-08-28 08:05:47 -07:00
Victor Zverovich
56fc525e98 Get rid of FormatterBase::error_. 2014-08-28 07:48:55 -07:00
Victor Zverovich
279c7a6e6a Change "number is too big in format" to "number is too big" because the error can occur not only in the format function. 2014-08-28 06:50:52 -07:00
Victor Zverovich
526b7fc91d Throw exception in parse_nonnegative_int if the number is too big. 2014-08-28 06:42:59 -07:00
Victor Zverovich
9646e38c3b Don't use error_ in parse_arg_index. 2014-08-27 09:13:42 -07:00
Victor Zverovich
da0f7c0a51 Improve error reporting in parse_arg_index. 2014-08-27 09:04:51 -07:00
Victor Zverovich
42de4f1f7d Get rid of FormatErrorReporter. 2014-08-27 08:24:31 -07:00
Victor Zverovich
8cc0d21124 Move the Crash Reporter fix to Google Test where it belongs. 2014-08-23 10:25:21 -07:00
Victor Zverovich
59a462c67d Make sure that Crash Reporter is not invoked on death tests. 2014-08-23 10:04:06 -07:00
Victor Zverovich
45397e5046 Add dependency from CMakeLists.txt since it is used to get version. 2014-08-21 08:51:45 -07:00
Victor Zverovich
034aedb6d4 Bump version. 2014-08-21 08:49:58 -07:00
Victor Zverovich
dd4323f31c Add fprintf and write docs. 2014-08-21 08:49:13 -07:00
Victor Zverovich
f9561671cf Write docs. 2014-08-21 07:30:00 -07:00
Victor Zverovich
da0293c4dd Add missing include. 2014-08-21 07:29:23 -07:00
Victor Zverovich
03cdf1235a Test printf. 2014-08-21 07:14:02 -07:00
Victor Zverovich
f1ac0a19e9 Test float. 2014-08-20 08:21:06 -07:00
Victor Zverovich
be00d8b272 Convert integer argument like printf does. 2014-08-19 08:49:10 -07:00
Victor Zverovich
406c6123fb Cleanup 2014-08-19 08:47:38 -07:00
Victor Zverovich
c4a4a05d12 Improve handling of char in printf. 2014-08-19 08:14:21 -07:00
Victor Zverovich
f2be7851cc Fix a warning. 2014-08-19 07:29:30 -07:00
Victor Zverovich
e0f92d675e Fix a warning. 2014-08-19 07:14:25 -07:00
Victor Zverovich
39ac84f01e Comment. 2014-08-18 07:03:22 -07:00
Victor Zverovich
186734cf8b Fix warnings. 2014-08-18 07:03:12 -07:00
Victor Zverovich
61857356ea Fix appveyor config. 2014-08-17 08:01:00 -07:00
Victor Zverovich
2462c61d05 Enable output for test failures. 2014-08-17 07:56:48 -07:00
Victor Zverovich
adce0245dc Fix a warning. 2014-08-17 07:53:55 -07:00
Victor Zverovich
366e852f00 Fix a warning. 2014-08-15 16:35:41 -07:00
Victor Zverovich
bb01633d19 Fix a warning. 2014-08-15 09:03:59 -07:00
Victor Zverovich
c978d88183 Test ArgConverter. 2014-08-15 08:40:13 -07:00
Victor Zverovich
fb32161fa4 Move implementation specific stuff from format.h to format.cc. 2014-08-15 08:40:03 -07:00
Victor Zverovich
c7cfa7d4e7 More tests. 2014-08-15 06:58:24 -07:00
Victor Zverovich
d4412a01f0 Simplify isinfinity. 2014-08-13 08:01:51 -07:00
Victor Zverovich
1a0c76a81a Fix formatting of long double. 2014-08-13 07:51:02 -07:00
Victor Zverovich
18f1e08685 Test 'll' specifier. 2014-08-13 06:59:29 -07:00
Victor Zverovich
e488a28601 Fix a warning. 2014-08-13 06:53:43 -07:00
Victor Zverovich
ddd087d8d1 Test more length specifiers. 2014-08-13 06:42:15 -07:00
Victor Zverovich
d3a7039e31 Implement 'll' specifier. 2014-08-12 08:36:19 -07:00
Victor Zverovich
5614295aa1 Test 'l' specifier. 2014-08-12 08:15:39 -07:00
Victor Zverovich
7c14431211 Enable 'h' speciffier tests. 2014-08-12 06:49:27 -07:00
Victor Zverovich
adbf3f8b86 Rewrite length specifier tests without using printf to workaround broken MSVC implementation. 2014-08-11 08:34:17 -07:00
Victor Zverovich
137153b9f0 Take integer promotion into account. 2014-08-11 06:54:58 -07:00
Victor Zverovich
910dec5ed3 Fix 'l' specifier test. 2014-08-11 06:33:40 -07:00
Victor Zverovich
028d12dacd Disable 'l' specifier tests. 2014-08-09 10:12:36 -07:00
Victor Zverovich
316ae7e244 Implement more printf length specifiers. 2014-08-09 10:04:35 -07:00
Victor Zverovich
6a8becb5bf Rearrange tests to simplify inclusion in other projects, part 2. 2014-08-09 09:07:15 -07:00
Victor Zverovich
56fb75c2ec Rearrange tests to simplify inclusion in other projects. 2014-08-09 09:04:38 -07:00
Victor Zverovich
bdbacde659 Test 'h' specifier. 2014-08-09 08:53:14 -07:00
Victor Zverovich
3465d056e7 Test hh specifier with unsigned char. 2014-08-08 06:59:17 -07:00
Victor Zverovich
e22d657202 Fix MSVC warnings. 2014-08-08 06:51:09 -07:00
Victor Zverovich
44e23c39f1 Implement GetThreadCount on Linux. 2014-08-07 09:30:46 -07:00
Victor Zverovich
431b556951 Add FMT_ prefix to SPECIALIZE_MAKE_UNSIGNED. 2014-08-07 07:42:55 -07:00
Victor Zverovich
6a37965710 Replace gtest with fused version. 2014-08-07 06:47:51 -07:00
Victor Zverovich
566061d1f1 Fix formatting of signed ints in test. 2014-08-06 08:21:12 -07:00
Victor Zverovich
6cd1563eac Add a size argument to Array ctor. 2014-08-06 07:17:03 -07:00
Victor Zverovich
e04b07921f Debug length specifier test. 2014-08-06 07:16:49 -07:00
Victor Zverovich
8b41b09add Test 'hh' and 'h' printf specifiers. 2014-08-06 07:00:04 -07:00
Victor Zverovich
86bbd3c238 Test hh length. 2014-08-05 08:21:47 -07:00
Victor Zverovich
b797d39dd1 Test printf length. 2014-08-05 07:52:59 -07:00
Victor Zverovich
fc10d10b6b Disable hh specifier tests for now because broken MSVC's printf causes test failures. 2014-08-01 08:50:09 -07:00
Victor Zverovich
58dfe5c9f7 Make format_decimal inline. 2014-08-01 08:49:16 -07:00
Victor Zverovich
3390a9510e Markup 2014-08-01 07:36:08 -07:00
Victor Zverovich
5ccbc9bb53 Acknowledge Boris Kaul. 2014-08-01 07:35:02 -07:00
Victor Zverovich
a259c941e2 Implement 'l' length specifier. 2014-08-01 07:15:27 -07:00
Victor Zverovich
be9356b651 Specialize MakeUnsigned for all signed integer types. 2014-07-31 21:23:49 -07:00
Victor Zverovich
d81fafc295 Fix tests on MSVC, take 2. 2014-07-31 07:43:14 -07:00
Victor Zverovich
3f444fe3e2 Fix tests on MSVC. 2014-07-31 06:47:24 -07:00
Victor Zverovich
e2f0408b69 Print format string on failure. 2014-07-30 10:59:23 -07:00
Victor Zverovich
f4156b57f0 Implement 'hh' length specifier in printf. 2014-07-30 08:39:07 -07:00
Victor Zverovich
39b0930aee Improve handling of 'h' length specifier in printf. 2014-07-30 08:08:08 -07:00
Victor Zverovich
eeca22357b Handle 'h' length specifier in printf. 2014-07-30 07:37:16 -07:00
Victor Zverovich
e4c4e4e944 Improve handling of dynamic precision in printf. 2014-07-30 06:51:35 -07:00
Victor Zverovich
be785a8a43 Fix MSVC build. 2014-07-29 09:14:07 -07:00
Victor Zverovich
d346a4120d FormatDec -> format_decimal 2014-07-29 08:45:29 -07:00
Victor Zverovich
bf5b246717 fmt_isinf -> isinfinity 2014-07-29 08:22:52 -07:00
Victor Zverovich
138c3dccdc Fix tests. 2014-07-29 08:11:49 -07:00
Victor Zverovich
8f8fd769ee Fix Fix https://github.com/cppformat/cppformat/issues/50 in tests too. 2014-07-29 07:50:05 -07:00
Victor Zverovich
24d6baa60f Fix Clang build. 2014-07-29 07:49:34 -07:00
Victor Zverovich
481c313df5 Fix the build. 2014-07-29 07:19:54 -07:00
Victor Zverovich
d8b9f413fe Fix https://github.com/cppformat/cppformat/issues/50. 2014-07-29 06:38:05 -07:00
Victor Zverovich
ad9c830282 format -> format_str to avoid confusion with function name. 2014-07-29 06:26:44 -07:00
Victor Zverovich
7a83dcd23e Mind the lifetime. 2014-07-28 13:30:09 -07:00
Victor Zverovich
7e40ca6a9c Fix a warning. 2014-07-28 09:08:21 -07:00
Victor Zverovich
4d049cf598 More fixes for https://github.com/cppformat/cppformat/issues/50. 2014-07-28 08:41:50 -07:00
Victor Zverovich
75b5eb4b9d More fixes for https://github.com/cppformat/cppformat/issues/50. 2014-07-27 15:09:05 -07:00
Victor Zverovich
5d4803a567 More fixes for https://github.com/cppformat/cppformat/issues/50. 2014-07-27 12:53:42 -07:00
Victor Zverovich
4c563de76f Use stock version of sphinx build. 2014-07-27 10:07:20 -07:00
Victor Zverovich
82652f4ee2 Experiment with appveyor. 2014-07-27 09:24:22 -07:00
Victor Zverovich
b9c40c6af5 Experiment with appveyor. 2014-07-27 09:03:59 -07:00
Victor Zverovich
7b44b0113b Remove sphinx submodule. 2014-07-27 08:51:33 -07:00
Victor Zverovich
8e0bfb5714 Debug appveyor config. 2014-07-27 08:42:03 -07:00
Victor Zverovich
2ebfa7b53d Fix appveyor config, take 2. 2014-07-27 08:30:37 -07:00
Victor Zverovich
721d95adf2 Fix appveyor config. 2014-07-27 08:13:39 -07:00
Victor Zverovich
af90b08b76 Remove sphinx submodule as we can now use the stock version. 2014-07-27 08:08:16 -07:00
Victor Zverovich
d658c835d4 Update breathe. 2014-07-26 21:34:50 -07:00
Victor Zverovich
a8cef1d987 FormatDecimal -> format_decimal (https://github.com/cppformat/cppformat/issues/50) 2014-07-26 21:31:40 -07:00
Victor Zverovich
1a6cdb53ac Use custom version of breathe. 2014-07-26 21:30:36 -07:00
Victor Zverovich
33cde15334 Fix version. 2014-07-26 21:23:50 -07:00
Victor Zverovich
533b9cf24f Add missing import. 2014-07-26 21:14:40 -07:00
Victor Zverovich
46b6e4b52c Run doxygen on ReadTheDocs. 2014-07-26 21:12:48 -07:00
Victor Zverovich
d91a66e1c5 Read version from CMakeLists.txt instead of using configure for compatibility with ReadTheDocs. 2014-07-26 21:05:42 -07:00
Victor Zverovich
2a1c0c9969 Obey line length limit. 2014-07-26 09:45:03 -07:00
Victor Zverovich
f634ccb344 ReportUnknownType -> report_unknown_type (https://github.com/cppformat/cppformat/issues/50) 2014-07-26 08:42:19 -07:00
Victor Zverovich
b498ba0bc5 FormatFloat -> format_float (https://github.com/cppformat/cppformat/issues/50) 2014-07-26 08:03:03 -07:00
Victor Zverovich
37356c3f5e Comment. 2014-07-26 07:26:04 -07:00
Victor Zverovich
aa6aa4207e Edit readme. 2014-07-26 07:25:31 -07:00
Victor Zverovich
2a747b19e0 CheckPtr -> make_ptr (https://github.com/cppformat/cppformat/issues/50) 2014-07-25 08:41:22 -07:00
Victor Zverovich
d142e3b55f Simplify handling of flags. 2014-07-25 08:29:06 -07:00
Victor Zverovich
d699c2a0d9 Don't duplicate integer format specifiers when formatting char as integer. 2014-07-25 08:24:27 -07:00
Victor Zverovich
a997de90eb Fix https://github.com/cppformat/cppformat/issues/57. 2014-07-25 07:10:33 -07:00
Victor Zverovich
89468c2a23 Update breathe. 2014-07-24 14:48:20 -07:00
Victor Zverovich
ee24839cbd Fix tests. 2014-07-24 09:07:43 -07:00
Victor Zverovich
ca0dcce2a6 CountDigits -> count_digits 2014-07-24 08:59:52 -07:00
Victor Zverovich
c1db293518 Don't use Writer's buffer directly in formatters. Unfriend BasicFormatter. 2014-07-24 08:53:27 -07:00
Victor Zverovich
a7d94f0c61 Fix https://github.com/cppformat/cppformat/issues/55. 2014-07-22 12:37:10 -07:00
Victor Zverovich
177715d8f9 Update breathe. 2014-07-21 12:27:52 -07:00
Victor Zverovich
f1dfd59a41 HandleArgIndex -> handle_arg_index. Use error_ instead of a local. 2014-07-16 08:49:23 -07:00
Victor Zverovich
f86c812e1a Remove unused SimpleErrorReporter. 2014-07-16 08:48:27 -07:00
Victor Zverovich
4edc88f609 Add FormatterBase. 2014-07-16 08:38:15 -07:00
Victor Zverovich
9144a8fbbe PrintfParser -> PrintfFormatter. 2014-07-16 07:59:45 -07:00
Victor Zverovich
e2a66c58e5 Simplify and test ArgVisitor. 2014-07-16 07:55:31 -07:00
Victor Zverovich
9d74f9542b IsNegative -> is_negative. Simplify WidthHandler and ArgFormatter. 2014-07-16 07:27:54 -07:00
Victor Zverovich
512e2ced93 Rewrite argument formatting using ArgVisitor. 2014-07-14 08:47:03 -07:00
Victor Zverovich
e3a2ac8725 Move StringValue to Arg & simplify StringTraits. 2014-07-14 08:04:17 -07:00
Victor Zverovich
8a66bb89b2 Complete ArgVisitor test. 2014-07-14 07:27:07 -07:00
Victor Zverovich
a7a18fac89 Fix util-test. 2014-07-14 07:17:58 -07:00
Victor Zverovich
591ad0a64a Add ArgVisitor. 2014-07-14 06:55:29 -07:00
Victor Zverovich
979561cc00 Clean appveyor config. 2014-07-10 11:23:06 -07:00
Victor Zverovich
4ecfdd50b6 Suppress error dialogs on assertion failures in MinGW. 2014-07-10 11:05:26 -07:00
Victor Zverovich
c3a6e01f52 Try a fix for $env:Configuration not expanding. 2014-07-10 10:43:21 -07:00
Victor Zverovich
308ee8a7eb Clean appveyor config. 2014-07-10 09:34:26 -07:00
Victor Zverovich
eb04e9abd3 Report build type. 2014-07-10 09:14:24 -07:00
Victor Zverovich
c0d55e6308 Remove WriteArrayOfUnknownSize because it shouldn't compile according to standard. 2014-07-10 08:42:33 -07:00
Victor Zverovich
47f2e7aa02 Clean appveyor config. 2014-07-10 08:41:33 -07:00
Victor Zverovich
6eaee58679 Fix appveyor config. 2014-07-10 08:26:20 -07:00
Victor Zverovich
b119b9ad71 Debug appveyor config. 2014-07-10 08:18:24 -07:00
Victor Zverovich
59ed28274c Remove Git bin directory from the path because it breaks mingw config. 2014-07-10 07:58:42 -07:00
Victor Zverovich
f29a3fadbf Fix appveyor config, take 2. 2014-07-10 07:38:55 -07:00
Victor Zverovich
8cfe4e2266 Fix appveyor config. 2014-07-10 07:31:54 -07:00
Victor Zverovich
0a26914e42 Debug appveyor config. 2014-07-10 07:27:14 -07:00
Victor Zverovich
472e6107bb Fix appveyor config. 2014-07-10 07:02:59 -07:00
Victor Zverovich
307c207351 Split long line. 2014-07-10 07:00:26 -07:00
Victor Zverovich
dfadea8345 Fix 7z invocation. 2014-07-10 06:50:14 -07:00
Victor Zverovich
b1c89e37bf Add support for MinGW build. 2014-07-10 06:39:10 -07:00
Victor Zverovich
dac1aa0d23 Don't install MinGW for MSVC build. 2014-07-10 06:33:20 -07:00
Victor Zverovich
f7e0fb8a58 Try build matrix in appveyor. 2014-07-09 19:44:32 -07:00
Victor Zverovich
f739978fbb Clean appveyor config. 2014-07-09 17:32:32 -07:00
Victor Zverovich
cac3656b78 Suppress output from 7z. 2014-07-09 17:24:23 -07:00
Victor Zverovich
18b4abff0b Specify user agent when downloading from SF. 2014-07-09 17:13:27 -07:00
Victor Zverovich
2fb88aaa08 Debug appveyor config. 2014-07-09 17:06:05 -07:00
Victor Zverovich
bd8f8b5525 Try fixing download. 2014-07-09 15:16:24 -07:00
Victor Zverovich
5e42eaca0d Install mingw in appveyor. 2014-07-09 13:16:39 -07:00
Victor Zverovich
e839608dcf Try installing mingw in appveyor. 2014-07-09 12:07:24 -07:00
Victor Zverovich
83c2b37673 Check if 7zip installed in appveyor. 2014-07-09 11:16:28 -07:00
Victor Zverovich
16985f4764 Fix one more test failure on MinGW. 2014-07-09 10:13:44 -07:00
Victor Zverovich
d3a7a4c209 Fix StrError test. 2014-07-09 10:11:10 -07:00
Victor Zverovich
53a475ac94 Do fix a test. 2014-07-09 10:01:36 -07:00
Victor Zverovich
897397760c Fix a test. 2014-07-09 09:55:13 -07:00
Victor Zverovich
9c47f3e057 Fix MinGW issues, take 2. 2014-07-09 09:45:18 -07:00
Victor Zverovich
0ffcec0090 Fix MinGW issues. 2014-07-09 09:35:36 -07:00
Victor Zverovich
8321d0ecf9 Fix warnings on MinGW. 2014-07-09 08:39:01 -07:00
Victor Zverovich
e3a44c11f6 Add an overload of print that accepts std::ostream. 2014-07-09 06:56:36 -07:00
Victor Zverovich
ed421848b3 Test passing an array of unknown size as an argument. 2014-07-09 06:45:20 -07:00
Victor Zverovich
1d7bd5d073 Add c_str functions. 2014-07-08 16:44:24 -07:00
Victor Zverovich
b9a06bafd8 internal::FormatParser -> BasicFormatter. 2014-07-08 16:38:50 -07:00
Victor Zverovich
e825156add Move FormatParser to the internal namespace. 2014-07-08 16:20:33 -07:00
Victor Zverovich
f711266244 Test MakeArg. Clean the API. 2014-07-04 07:18:44 -07:00
Victor Zverovich
144e1fbb7c Disallow formatting of wide strings when using a narrow string formatter. 2014-07-04 06:56:19 -07:00
Victor Zverovich
270ed1cb92 Add printf example. 2014-07-03 09:40:34 -07:00
Victor Zverovich
4e260e8599 Test MakeArg and fix formatting. 2014-07-03 08:50:57 -07:00
Victor Zverovich
43a873f7ff Typo 2014-07-02 09:12:25 -07:00
Victor Zverovich
9fbdc32adc Test MakeArg and handle bool, signed char and unsigned char. 2014-07-02 08:38:31 -07:00
Victor Zverovich
6e5551e77a ArgInfo -> Arg 2014-07-02 06:33:25 -07:00
Victor Zverovich
c494c980b6 Clean. 2014-07-01 21:01:15 -07:00
Victor Zverovich
b827a97fd6 Correct example. 2014-07-01 16:59:25 -07:00
Victor Zverovich
5d15bdd5a5 Clean. 2014-07-01 16:23:50 -07:00
Victor Zverovich
530479bd07 Don't exclude PrepareBufferForInt to demonstrate an issue with docs. 2014-07-01 13:12:44 -07:00
Victor Zverovich
b8174bec30 Use Kill-o-Zap 2014-07-01 09:17:37 -07:00
Victor Zverovich
39166f9aa9 Remove more deprecated code. 2014-07-01 09:15:20 -07:00
Victor Zverovich
2dc108b31f Remove deprecated code 🎆 🎆 🎆 2014-07-01 09:10:43 -07:00
Victor Zverovich
ccf1dbb139 Bump version. 2014-07-01 07:19:42 -07:00
Victor Zverovich
cff1c79469 Fix another warning. 2014-07-01 06:27:15 -07:00
Victor Zverovich
537c6c4e18 Fix a warning. 2014-07-01 06:21:51 -07:00
Victor Zverovich
8e451911c9 Fix a warning. 2014-06-30 19:11:20 -07:00
Victor Zverovich
442c122c44 Fix warnings. 2014-06-30 18:38:45 -07:00
Victor Zverovich
536fedfe0f Fix build. 2014-06-30 18:26:46 -07:00
Victor Zverovich
35866bb2c2 Fix warnings. 2014-06-30 18:12:57 -07:00
Victor Zverovich
cea08c7abc Suppress more warnings. 2014-06-30 17:46:14 -07:00
Victor Zverovich
eb034a0589 Suppress warnings. 2014-06-30 17:40:53 -07:00
Victor Zverovich
f4208771a8 Replace ThrowWinError with WindowsError class. 2014-06-30 17:32:08 -07:00
Victor Zverovich
c6eb12d1d4 Fix one more Windows issue. 2014-06-30 17:17:48 -07:00
Victor Zverovich
182d8178fe Fix one more Windows issue. 2014-06-30 17:01:31 -07:00
Victor Zverovich
3c72e0c18b Fix Windows build, take 2. 2014-06-30 16:56:22 -07:00
Victor Zverovich
a318244a1c Fix Windows build. 2014-06-30 16:48:05 -07:00
Victor Zverovich
a2205739b1 Fix build. 2014-06-30 16:31:43 -07:00
Victor Zverovich
b939860d6e write -> write_str 2014-06-30 15:44:08 -07:00
Victor Zverovich
14e7ed76df Update excludes. 2014-06-30 15:43:46 -07:00
Victor Zverovich
53201033f2 Refactor error reporting API. 2014-06-30 14:26:29 -07:00
Victor Zverovich
d29e505568 Move PrintfParser from BasicWriter to the internal namespace. 2014-06-30 07:12:09 -07:00
Victor Zverovich
e63a0ff125 Deprecate c_str() and str(). 2014-06-30 06:43:53 -07:00
Victor Zverovich
90e6faffa0 Document ArgList. 2014-06-30 06:27:26 -07:00
Victor Zverovich
ba70b30d7e Move BasicArg & make_arg from BasicWriter to the internal namespace. 2014-06-30 06:19:20 -07:00
Victor Zverovich
21111cc954 MakeArg -> make_arg. Move printf out of Writer. 2014-06-29 19:52:26 -07:00
Victor Zverovich
f6d481f120 Improve example. 2014-06-29 14:22:53 -07:00
Victor Zverovich
afc760263e Update example. 2014-06-29 12:04:28 -07:00
Victor Zverovich
e882db900d Fix rendering. 2014-06-29 12:01:23 -07:00
Victor Zverovich
c673c84905 Fix rendering. 2014-06-29 12:00:14 -07:00
Victor Zverovich
5fe01fd096 Correct example. 2014-06-29 11:59:38 -07:00
Victor Zverovich
ba65bc1ec6 Update readme. 2014-06-29 11:58:21 -07:00
Victor Zverovich
7955dc479c Update readme. 2014-06-29 11:57:36 -07:00
Victor Zverovich
9d5905707a Update docs. 2014-06-29 11:51:27 -07:00
Victor Zverovich
a1264926a0 Writer::format -> Writer::write. Make fmt::format return string. 2014-06-29 11:51:10 -07:00
Victor Zverovich
d5b8196749 Update the API. 2014-06-28 21:56:40 -07:00
Victor Zverovich
856e129cc6 Don't use deprecated API. 2014-06-28 20:03:46 -07:00
Victor Zverovich
c649007ed8 Don't use deprecated API. 2014-06-28 19:59:44 -07:00
Victor Zverovich
0914c91284 Don't use deprecated API. 2014-06-28 19:53:15 -07:00
Victor Zverovich
421cb0ad18 Update test. 2014-06-28 19:47:41 -07:00
Victor Zverovich
2e03963e9e Add fmt::print. Undocument and deprecate old API. 2014-06-28 19:44:39 -07:00
Victor Zverovich
8dbfd723b6 Add another project using cppformat. 2014-06-28 19:17:13 -07:00
Victor Zverovich
ddbd50de4a Fix build. 2014-06-28 17:44:52 -07:00
Victor Zverovich
4d5b1e8a13 Update the API and tests. 2014-06-28 17:35:57 -07:00
Victor Zverovich
876a5d1f43 Update more tests. 2014-06-28 16:05:02 -07:00
Victor Zverovich
e06e9f885c Deprecate Format and update tests. 2014-06-28 15:58:02 -07:00
Victor Zverovich
09f40191f4 Fix build, take 2. 2014-06-28 14:57:06 -07:00
Victor Zverovich
c164cb6ecd Fix build. 2014-06-28 14:53:16 -07:00
Victor Zverovich
75e078748a Format -> format 2014-06-28 14:50:16 -07:00
Victor Zverovich
5edda531f6 Add fmt::format and deprecate fmt::Format. 2014-06-28 14:48:42 -07:00
Victor Zverovich
428d114766 Complete FMT_VARIADIC. 2014-06-28 13:31:44 -07:00
Victor Zverovich
9c8db26457 Fix build, take 2. 2014-06-28 13:06:49 -07:00
Victor Zverovich
3b3f76b809 Fix build. 2014-06-28 13:03:39 -07:00
Victor Zverovich
4f4e6c965f Fix MSVC build. FormatError -> FormatMessage to avoid ambiguity. 2014-06-28 12:49:51 -07:00
Victor Zverovich
5aa36285b1 Try another MSVC workaround. 2014-06-28 12:14:43 -07:00
Victor Zverovich
a0e2f52247 MSVC workaround. 2014-06-28 12:05:32 -07:00
Victor Zverovich
ce09e7e348 Simplify FMT_FOR_EACH. 2014-06-28 11:43:07 -07:00
Victor Zverovich
e4c2475318 MSVC workaround. 2014-06-28 11:36:49 -07:00
Victor Zverovich
3b18ecb24a FMT_FOR_EACH_NARG -> FMT_NARG. 2014-06-28 11:30:15 -07:00
Victor Zverovich
be7473b401 Test FMT_VARIADIC. 2014-06-28 11:20:04 -07:00
Victor Zverovich
2f6dddd6fd Simplify FMT_VARIADIC. 2014-06-28 11:07:43 -07:00
Victor Zverovich
360bfbdd50 Use 0-based indices. Test FMT_FOR_EACH*. 2014-06-28 10:32:37 -07:00
Victor Zverovich
bf25ef6455 FMT_TEMPLATE -> FMT_WRAP 2014-06-28 09:15:51 -07:00
Victor Zverovich
08e2dffa86 Add macro test. 2014-06-25 07:50:33 -07:00
Victor Zverovich
ef34eb6ec2 Emulate variadic functions on older compilers. 2014-06-25 07:50:16 -07:00
Victor Zverovich
2f752abe97 Add FMT_VARIADIC_VOID to emulate variadic functions on old compilers. 2014-06-24 19:27:26 -07:00
Victor Zverovich
8198df84f0 Suppress warnings about variadic macros. 2014-06-24 13:01:44 -07:00
Victor Zverovich
55f6640cae Fix test. 2014-06-24 11:13:18 -07:00
Victor Zverovich
a062f94ab0 Workaround a bug in VC++ variadic macro implementation. 2014-06-24 11:09:07 -07:00
Victor Zverovich
302b8f4406 Fix MSVC build, take 2. 2014-06-24 10:46:01 -07:00
Victor Zverovich
73fda2a8b1 Fix error on MSVC. 2014-06-24 10:30:37 -07:00
Victor Zverovich
0195f543d9 Initial support for variadic functions without C++11. 2014-06-24 10:14:50 -07:00
Victor Zverovich
ea99bfb902 Move ArgInfo to internal namespace and add ArgList. 2014-06-24 07:54:26 -07:00
Victor Zverovich
8d4535e76c Avoid unnecessary include. 2014-06-23 09:49:59 -07:00
Victor Zverovich
3e53ac2451 Fix warnings. 2014-06-23 08:48:42 -07:00
Victor Zverovich
d0587445cb Test negative precision. 2014-06-23 08:39:32 -07:00
Victor Zverovich
4099a1269b Add support for negative width. 2014-06-23 08:10:50 -07:00
Victor Zverovich
91e6bc8b97 Document 'a' and 'A' format specifiers. 2014-06-23 07:28:29 -07:00
Victor Zverovich
8a8be2267d More tests. 2014-06-23 07:17:58 -07:00
Victor Zverovich
1a75ed01cd Implement dynamic precision in printf. 2014-06-23 07:16:46 -07:00
Victor Zverovich
0552f5b809 Test precision. 2014-06-23 07:07:10 -07:00
Victor Zverovich
c538dd5033 Don't specify image dimensions as they have no effect. 2014-06-22 11:58:19 -07:00
Victor Zverovich
9c995a6b58 Don't use undefined _MSC_VER. 2014-06-21 09:47:37 -07:00
Victor Zverovich
5be9a8de3f Reduce the number of integer types that need to be handled. 2014-06-21 09:40:04 -07:00
Victor Zverovich
5e6f57ada1 Link to the latest release. 2014-06-21 09:11:19 -07:00
Victor Zverovich
680d88de68 Add Usage section. 2014-06-21 08:50:48 -07:00
Victor Zverovich
b1bbc90919 Use precision from FormatSpec. 2014-06-21 08:32:00 -07:00
Victor Zverovich
f8c058e99c Predefine _WIN32 for Windows-only parts of API. 2014-06-21 08:18:24 -07:00
Victor Zverovich
6238f2daa1 Make precision and alignment work together. 2014-06-21 08:18:05 -07:00
Victor Zverovich
f430516d3f Use stock version of breathe as it provides control over member visibility now. 2014-06-21 07:20:58 -07:00
Victor Zverovich
ca31c2b322 Fix handling of octal prefix. 2014-06-20 08:04:44 -07:00
Victor Zverovich
512ab9336b PrepareFilledBuffer -> PrepareBufferForInt 2014-06-20 08:01:58 -07:00
Victor Zverovich
c556926597 Implement precision + fill. 2014-06-20 07:59:23 -07:00
Victor Zverovich
879838a539 Implement integer precision. 2014-06-20 07:34:02 -07:00
Victor Zverovich
cb743c0249 Parse printf format specs. 2014-06-19 07:40:35 -07:00
Victor Zverovich
7d5da66db9 Clean 2014-06-17 06:54:08 -07:00
Victor Zverovich
1275923a68 Implement dynamic width in printf. 2014-06-17 06:53:48 -07:00
Victor Zverovich
8666ea82f7 Merge branch 'master' of github.com:cppformat/cppformat 2014-06-16 07:49:37 -07:00
Victor Zverovich
1f19b986a0 Implement printf specifications. 2014-06-16 07:49:30 -07:00
Victor Zverovich
da9457da61 Add a test case for https://github.com/cppformat/cppformat/pull/47 2014-06-16 07:48:57 -07:00
vitaut
7d8f3c261a Merge pull request #47 from Jopie64/master
Fix grow size during Array<>::append
2014-06-16 07:48:05 -07:00
Johan 't Hart
f4d47d7140 Fix grow size during Array<>::append
When the resulting array must grow during append, one must make sure
that the new elements _plus_ the current elements fit the new array
size.
2014-06-16 11:44:24 +02:00
Victor Zverovich
1aeac1b25a Unindent 2014-06-11 05:52:02 -07:00
vitaut
dc440dd19d Merge pull request #46 from amorozov/bug/45
GCC may have support for __has_feature but doesn't support __has_builtin
2014-06-11 05:49:26 -07:00
Alexey Morozov
08d4e5040f GCC may have support for __has_feature but doesn't support __has_builtin
So perform these checks separately
2014-06-11 15:47:46 +07:00
vitaut
f0bcc0b1c0 Merge pull request #44 from procedural/master
Changes for MinGW compiler
2014-06-10 16:13:34 -07:00
Constantine Tarasenkov
6aace693db Changes for MinGW compiler 2014-06-11 02:38:57 +04:00
Victor Zverovich
e2cbee77b8 Fix coding style issues. 2014-06-10 09:17:24 -07:00
Victor Zverovich
11f76fea94 Fix test, take 2. 2014-06-10 08:57:28 -07:00
Victor Zverovich
e1d4690566 Fix test. 2014-06-10 08:15:38 -07:00
Victor Zverovich
07095e85b2 Fix formatting and comment why fcntl.h is included. 2014-06-10 07:36:50 -07:00
Victor Zverovich
a2828412b6 Fix tests. 2014-06-10 07:36:23 -07:00
Victor Zverovich
03776dd988 Add support for hexadecimal floating point format specifiers a and A. 2014-06-10 07:03:49 -07:00
Victor Zverovich
546b62e74f More tests. 2014-06-10 06:21:41 -07:00
Victor Zverovich
ed19147441 Fix build, take 2. 2014-06-09 10:16:13 -07:00
Victor Zverovich
e7b6896c43 Fix tests. 2014-06-09 09:57:34 -07:00
Victor Zverovich
5222f59cc0 Fix build. 2014-06-09 09:35:12 -07:00
Victor Zverovich
eaa89e23d7 Put File, BufferedFile & ErrorCode in the fmt namespace. 2014-06-09 09:07:27 -07:00
Victor Zverovich
b692ab58b2 Move POSIX wrappers to separate files. 2014-06-09 08:33:48 -07:00
Victor Zverovich
b4dc0301f6 Disable test. 2014-06-09 08:17:14 -07:00
Victor Zverovich
f51fc08670 More tests. 2014-06-09 07:40:51 -07:00
Victor Zverovich
1b80148420 Implement '#' flag. 2014-06-07 08:57:55 -07:00
Victor Zverovich
bf790d2819 Ignore '0' flag for non-numeric types as printf does. 2014-06-07 07:31:25 -07:00
Victor Zverovich
80c99760fb Fix warnings. 2014-06-07 07:11:34 -07:00
Victor Zverovich
1ed23b9127 Warng about compilers mishandling negative NaN. 2014-06-06 18:54:45 -07:00
Victor Zverovich
acf94abffd Fix build. 2014-06-06 11:14:53 -07:00
Victor Zverovich
5b054ae7b8 Test signbit. 2014-06-06 11:04:27 -07:00
Victor Zverovich
34b5030239 Display test log on failure. 2014-06-06 09:18:57 -07:00
Victor Zverovich
39f812f040 Install CMake on OS X. 2014-06-06 09:07:08 -07:00
Victor Zverovich
533c8214d4 Avoid unnecessary check. 2014-06-06 08:54:37 -07:00
Victor Zverovich
8ed2243a3c Workaround windows brain damage. 2014-06-06 08:18:53 -07:00
Victor Zverovich
9a33891e97 Add missing include. 2014-06-06 08:07:05 -07:00
Victor Zverovich
ed8ff58019 Enable osx in travis-ci config. 2014-06-06 08:05:13 -07:00
Victor Zverovich
438eba1402 Fix parsing of flags. 2014-06-06 08:01:48 -07:00
Victor Zverovich
f16aff8033 Simplify tests. 2014-06-06 08:01:25 -07:00
Victor Zverovich
b88d261282 Fix an issue with allocation of a zero-size array. 2014-06-06 08:01:10 -07:00
Victor Zverovich
d9f5089a18 Remove unnecessary qualification. 2014-06-06 08:00:20 -07:00
Victor Zverovich
18316cb25f Fix windows build. 2014-06-06 07:29:57 -07:00
Victor Zverovich
9aba05b76a Parse '0' flag. 2014-06-06 07:07:57 -07:00
Victor Zverovich
bf8b29fbe7 Add initial support for printf format specifications. 2014-06-06 06:38:37 -07:00
Victor Zverovich
7042d14341 Disable extra tests unless FMT_EXTRA_TESTS is set. 2014-06-06 06:35:28 -07:00
Victor Zverovich
60cd838f1c Update benchmark results. 2014-05-23 08:58:28 -07:00
Victor Zverovich
23eb9b4f4c Move speed-test to benchmarks. 2014-05-23 07:24:23 -07:00
Victor Zverovich
19343ce274 Update readme. 2014-05-23 07:09:41 -07:00
Victor Zverovich
0a3806602a Fix script name. 2014-05-23 07:00:11 -07:00
Victor Zverovich
6be9a89eb6 Update readme. 2014-05-23 06:59:03 -07:00
Victor Zverovich
8d372eb30d Remove format-benchmark submodule. 2014-05-22 10:26:37 -07:00
Victor Zverovich
27c7216e01 Add an option to build cppformat as a shared library. 2014-05-22 08:45:30 -07:00
Victor Zverovich
7aa9eaea48 Update benchmarks. 2014-05-22 08:17:30 -07:00
Victor Zverovich
e3f11bab42 Add units. 2014-05-22 06:10:42 -07:00
Victor Zverovich
f561a7b0e8 Update benchmark results. 2014-05-22 06:08:50 -07:00
Victor Zverovich
3e4eded5b2 Update benchmarks. 2014-05-21 08:38:14 -07:00
Victor Zverovich
4fa1647c3a Fix module url. 2014-05-20 09:22:28 -07:00
Victor Zverovich
242ad5a120 Update readme. 2014-05-20 09:16:41 -07:00
Victor Zverovich
0e32544855 Update benchmark. 2014-05-20 07:10:46 -07:00
Victor Zverovich
e2670001bc Add updated format-benchmark repo. 2014-05-20 07:00:26 -07:00
Victor Zverovich
10e0c15534 Remove format-benchmark. 2014-05-20 06:56:00 -07:00
Victor Zverovich
b65c19012a Test write count conversion. 2014-05-19 08:37:28 -07:00
Victor Zverovich
49fac7666c Test read count conversion. 2014-05-19 08:25:08 -07:00
Victor Zverovich
ba176c3cb3 Fix handling of -std=c++11 flag. 2014-05-19 08:02:44 -07:00
Victor Zverovich
3159170383 Fix warnings. 2014-05-19 07:53:16 -07:00
Victor Zverovich
3c1bc74b04 Multiple build types in travis. 2014-05-19 07:53:02 -07:00
Victor Zverovich
cfa34cff2d Enable parallel build in appveyor. 2014-05-19 07:38:24 -07:00
Victor Zverovich
c123fc612f Enable parallel build in travis. 2014-05-19 07:35:18 -07:00
Victor Zverovich
f578bc3a4a More tests. Fix warnings. 2014-05-19 07:31:05 -07:00
Victor Zverovich
952fd7a756 Comment. 2014-05-19 07:30:32 -07:00
Victor Zverovich
5bd9efebda Fix Windows build, take 2. 2014-05-18 12:38:01 -07:00
Victor Zverovich
df991a0f46 Fix Windows build. 2014-05-18 11:09:37 -07:00
Victor Zverovich
f21fa23186 More posix tests. 2014-05-18 10:05:29 -07:00
Victor Zverovich
e654f56210 Test fdopen. 2014-05-18 10:04:49 -07:00
Victor Zverovich
13a5b2511b Document Print. 2014-05-18 10:04:36 -07:00
Victor Zverovich
e79bcfe5ab Enable parallel build in appveyor. 2014-05-18 10:03:48 -07:00
Victor Zverovich
1dd0e3046b Fix tests. 2014-05-18 10:03:28 -07:00
Victor Zverovich
bd205aea28 Fix test. 2014-05-16 09:16:29 -07:00
Victor Zverovich
ed2caaf265 No need for retry on Windows. 2014-05-16 09:09:54 -07:00
Victor Zverovich
5bc2b533ff Experiment with tests. 2014-05-16 08:59:54 -07:00
Victor Zverovich
e22665e528 Try different configurations. 2014-05-16 08:55:12 -07:00
Victor Zverovich
22240589fc Experiment with tests and multiple platforms. 2014-05-16 08:47:59 -07:00
Victor Zverovich
17cc8b0f23 Add test log to appveyor artifacts. 2014-05-16 08:37:46 -07:00
Victor Zverovich
f1eab158c5 Test retry on EINTR in read, write, dup & dup2. 2014-05-16 07:07:43 -07:00
Victor Zverovich
232e5c3a3b Test retry on EINTR in close. 2014-05-16 06:25:20 -07:00
Victor Zverovich
41895fdf42 Fix url. 2014-05-15 11:02:24 -07:00
Victor Zverovich
fb17316d77 Use stdio.h instead of cstdio for fdopen. Wrap all used POSIX functions for testing. 2014-05-15 08:58:10 -07:00
Victor Zverovich
d758dbb33a Add tests. 2014-05-15 07:45:44 -07:00
Victor Zverovich
e1ba41f0ce Update readme. 2014-05-14 19:17:20 -07:00
Victor Zverovich
34648f4019 Test EXPECT_SYSTEM_ERROR. 2014-05-14 09:01:16 -07:00
Victor Zverovich
5415b2a43b Fix example. 2014-05-14 08:20:20 -07:00
Victor Zverovich
c3b3c0fafe Fix warning. 2014-05-14 07:45:21 -07:00
Victor Zverovich
d2e7554f74 Write docs. 2014-05-14 07:29:47 -07:00
Victor Zverovich
3303708e94 Document ThrowSystemError and ThrowWinError. 2014-05-14 07:05:09 -07:00
Victor Zverovich
a59dc93764 Fix ReportSystemError and ReportWinError tests. 2014-05-14 06:58:13 -07:00
Victor Zverovich
bb93cf12a7 Add a test. 2014-05-14 06:45:39 -07:00
Victor Zverovich
cb389f9a09 Ignore generated files. 2014-05-13 09:28:53 -07:00
Victor Zverovich
191c2011f2 Don't include sphinx in the package. 2014-05-13 09:00:21 -07:00
Victor Zverovich
83920084f7 Update docs. 2014-05-13 08:55:13 -07:00
Victor Zverovich
891da2f474 Fix docs. 2014-05-13 07:39:18 -07:00
Victor Zverovich
089e54a09b Fix docs. 2014-05-13 07:35:46 -07:00
Victor Zverovich
660938fe4d Add sphinx and breathe at top level. 2014-05-13 07:32:28 -07:00
Victor Zverovich
b0728fed27 Remove sphinx submodule. 2014-05-13 07:30:04 -07:00
Victor Zverovich
4b31c28aea Fix an issue with permissions. 2014-05-13 06:56:17 -07:00
Victor Zverovich
39561f8a08 Add tests. 2014-05-13 06:51:17 -07:00
Victor Zverovich
734bb02904 More docs. 2014-05-13 06:43:43 -07:00
Victor Zverovich
1eb30e4288 Remove breathe. 2014-05-13 06:43:17 -07:00
Victor Zverovich
b9fbdadf75 Update names in the docs. 2014-05-13 06:15:43 -07:00
Victor Zverovich
6cb7f4638d Generate docs for variadic templates. 2014-05-13 06:15:33 -07:00
Victor Zverovich
76d9a103e1 Update dependencies. 2014-05-13 06:15:18 -07:00
Victor Zverovich
0c13c4483b Add custom version of sphinx and move breathe to doc. 2014-05-13 06:13:21 -07:00
Victor Zverovich
44afc0aed6 Update breathe. 2014-05-12 06:31:07 -07:00
Victor Zverovich
9c75b9eaa1 Fix warning. 2014-05-06 12:17:31 -07:00
Victor Zverovich
e283930566 Fix warnings. 2014-05-06 12:13:16 -07:00
Victor Zverovich
72ad3781a4 Don't use .travis.yml in tests. 2014-05-06 12:03:12 -07:00
Victor Zverovich
45c50a9f1a Fix warning. 2014-05-06 11:34:00 -07:00
Victor Zverovich
44b57bdf8b Fix warnings. 2014-05-06 11:29:07 -07:00
Victor Zverovich
aab84f67a4 Fix warnings. 2014-05-06 11:24:20 -07:00
Victor Zverovich
6bd3880cf1 Fix test. 2014-05-06 10:38:23 -07:00
Victor Zverovich
6a5f27bed2 Add test. 2014-05-06 09:17:53 -07:00
Victor Zverovich
eb09e58697 Fix warnings. 2014-05-06 08:13:28 -07:00
Victor Zverovich
5cf3b6dc7d Add a Print overload that writes to a file. 2014-05-06 08:05:51 -07:00
Victor Zverovich
2e50361a29 dup -> copy 2014-05-06 08:05:14 -07:00
Victor Zverovich
b322a1f58b Fix MSVC build. 2014-05-06 07:29:50 -07:00
Victor Zverovich
e1c86f0b5d Fix warnings. 2014-05-06 06:58:32 -07:00
Victor Zverovich
fb4ccac951 Add BufferedFile::fileno. 2014-05-06 06:45:53 -07:00
Victor Zverovich
d286efd3d2 Implement GetThreadCount on Linux. 2014-05-06 06:45:06 -07:00
Victor Zverovich
494f53421e Fix warnings. 2014-05-06 06:11:39 -07:00
Victor Zverovich
83e1658109 Test compilation without -std=c++11. 2014-05-05 17:39:01 -07:00
Victor Zverovich
e44a2be8b9 Make BufferedFile::close public. 2014-05-05 17:38:39 -07:00
Victor Zverovich
cada26d226 Suppress asserts locally. 2014-05-05 17:07:21 -07:00
Victor Zverovich
2ecce39ca9 More tests. 2014-05-05 12:52:16 -07:00
Victor Zverovich
0aacd0cf6d Replace EXPECT_STDOUT and EXPECT_STDERR with a single macro EXPECT_WRITE. 2014-05-05 08:35:59 -07:00
Victor Zverovich
098f8ac343 Evaluate EXPECT_STD* output argument once. 2014-05-05 08:20:01 -07:00
Victor Zverovich
758283f7d9 Fix tests. 2014-05-05 08:19:35 -07:00
Victor Zverovich
03ca48f3e7 Test calling RestoreAndRead twice. 2014-05-05 07:31:56 -07:00
Victor Zverovich
536e61386d Evaluate message argument passed to EXPECT_THROW_MSG once. 2014-05-05 07:31:38 -07:00
Victor Zverovich
368505ebe9 Fix tests. 2014-05-05 07:31:03 -07:00
Victor Zverovich
5434b0282c Don't die on Windows. 2014-05-05 07:11:54 -07:00
Victor Zverovich
3555341ab4 Fix test. 2014-05-04 18:23:06 -07:00
Victor Zverovich
a07350a0d4 More tests. 2014-05-04 10:08:29 -07:00
Victor Zverovich
6a4a9b773c More tests. 2014-05-04 09:01:18 -07:00
Victor Zverovich
02b185751f Add BufferedFile. OutputRedirector -> OutputRedirect. 2014-05-04 06:44:50 -07:00
Victor Zverovich
e4f8b069b5 Too young to die. 2014-05-03 20:49:42 -07:00
Victor Zverovich
590490f35f Try not to die. 2014-05-03 19:05:56 -07:00
Victor Zverovich
3e55391ea8 Fix test. 2014-05-03 18:48:20 -07:00
Victor Zverovich
527c4b312a Fix test. 2014-05-03 18:36:17 -07:00
Victor Zverovich
f4c5b37561 Fix test. 2014-05-03 18:27:23 -07:00
Victor Zverovich
58b762f965 Fix tests. 2014-05-03 18:13:16 -07:00
Victor Zverovich
ba89c6399c "Undo" delete. 2014-05-03 17:34:58 -07:00
Victor Zverovich
798c0fae71 Fix test, take 2. 2014-05-03 16:55:13 -07:00
Victor Zverovich
15f1f8510f Fix test. More comments. 2014-05-03 16:47:00 -07:00
Victor Zverovich
c880e31d9f Fix warnings. 2014-05-03 16:25:26 -07:00
Victor Zverovich
a2cf54fca2 Fix test. 2014-05-03 16:21:01 -07:00
Victor Zverovich
d13946bfb7 Fix warnings. 2014-05-03 15:50:22 -07:00
Victor Zverovich
1a6d365db5 Fix move assignment. 2014-05-03 15:46:11 -07:00
Victor Zverovich
823ce5fc3d More tests. 2014-05-03 15:26:44 -07:00
Victor Zverovich
c6f40e339f Fix MSVC build. 2014-05-03 15:16:52 -07:00
Victor Zverovich
ee793b35cf File::get -> File::descriptor. 2014-05-03 15:07:28 -07:00
Victor Zverovich
c6d83b1a3b Make File::close() public. 2014-05-03 15:04:14 -07:00
Victor Zverovich
f516fb9cba Fix tests. 2014-05-03 14:40:18 -07:00
Victor Zverovich
7b2568a3a9 Fix test. 2014-05-03 13:18:58 -07:00
Victor Zverovich
b808503bc1 More tests. 2014-05-03 13:14:15 -07:00
Victor Zverovich
9556d3714d Fix test. 2014-05-03 12:38:32 -07:00
Victor Zverovich
c5c2cd63bc FileDescriptor -> File 2014-05-03 12:28:02 -07:00
Victor Zverovich
98b6e59272 Add FileDescriptor::write. 2014-05-03 12:06:28 -07:00
Victor Zverovich
f3e123b304 Use streamsize instead of ssize_t for portability. 2014-05-03 12:06:04 -07:00
Victor Zverovich
cc6a772b89 Simplify tests. 2014-05-03 12:01:27 -07:00
Victor Zverovich
a297e272d1 Add FileDescriptor::read. 2014-05-03 11:26:46 -07:00
Victor Zverovich
90a3f0a620 Define ssize_t on Windows. 2014-05-03 11:03:04 -07:00
Victor Zverovich
e648d289bb Fix FileDescriptor::pipe. 2014-05-03 10:25:46 -07:00
Victor Zverovich
8214a5ef5e Fix MSVC build. 2014-05-03 10:10:50 -07:00
Victor Zverovich
1a2d7be3f5 Implement EXPECT_STDOUT and EXPECT_STDERR using pipes. 2014-05-03 09:48:54 -07:00
Victor Zverovich
dd0120c189 Use gtest's own tuple with clang. 2014-05-02 08:13:17 -07:00
Victor Zverovich
f9eb0b8ba5 format-test.h -> gtest-extra.h 2014-05-02 07:23:25 -07:00
Victor Zverovich
f912eace9e Move compile test to the end. 2014-05-02 07:15:55 -07:00
Victor Zverovich
62394e0ebd More assertion tests. 2014-05-02 07:07:55 -07:00
Victor Zverovich
61d5ebc0af Test EXPECT_THROW_MSG. 2014-05-02 06:33:21 -07:00
Victor Zverovich
79226fe703 Use DLL runtime for gtest. 2014-05-01 20:06:19 -07:00
Victor Zverovich
7bde2b3c25 Replace a fused version of gtest with a stripped down one. 2014-05-01 17:14:35 -07:00
Victor Zverovich
9cf43ccdad Move tests to the test dir. 2014-05-01 16:49:08 -07:00
Victor Zverovich
5c639eb4c4 Test system error reporting. 2014-05-01 08:43:36 -07:00
Victor Zverovich
6ec1389de2 Test SystemErrorSink. 2014-05-01 08:02:55 -07:00
Victor Zverovich
78209468a0 Test UTF16ToUTF8::Convert. 2014-05-01 07:27:29 -07:00
Victor Zverovich
9830c52816 Fix UTF8ToUTF16. 2014-05-01 07:20:38 -07:00
Victor Zverovich
73d98d5d17 Test error reporting in UTF8ToUTF16. 2014-05-01 07:13:42 -07:00
Victor Zverovich
dcd039df81 Define WIN32_LEAN_AND_MEAN. 2014-05-01 07:09:42 -07:00
Victor Zverovich
42764e54ae Fix UTF16ToUTF8. 2014-05-01 07:09:08 -07:00
Victor Zverovich
58a2f4f425 Test error reporting in UTF16ToUTF8. 2014-05-01 07:06:35 -07:00
Victor Zverovich
53b4c31afb Move Format*ErrorMessage to internal namespace. 2014-04-30 15:00:41 -07:00
Victor Zverovich
f3a86e83fe Fix test. 2014-04-30 13:34:52 -07:00
Victor Zverovich
d35411817e Fix test. 2014-04-30 13:28:05 -07:00
Victor Zverovich
d3b1783647 Fix test. 2014-04-30 13:02:53 -07:00
Victor Zverovich
0bece94257 Fix test. 2014-04-30 12:39:31 -07:00
Victor Zverovich
400812a905 CError -> WinError 2014-04-30 12:38:17 -07:00
Victor Zverovich
c7eba007cc Fix MSVC build. 2014-04-30 11:47:16 -07:00
Victor Zverovich
89a8aaf502 Fix UB. 2014-04-30 11:29:33 -07:00
Victor Zverovich
34712da2e7 Fix MSVC build. 2014-04-30 11:28:07 -07:00
Victor Zverovich
f68d329d24 Fix warning. 2014-04-30 11:22:20 -07:00
Victor Zverovich
99e6112fda Fix StrError, move Format*ErrorMessage to the implementation. 2014-04-30 11:20:41 -07:00
Victor Zverovich
a1a84df7a4 More tests. 2014-04-30 10:53:55 -07:00
Victor Zverovich
c8e2b474e8 Fix test. 2014-04-30 10:46:12 -07:00
Victor Zverovich
8f06746051 Implement GetThreadCount on Linux, fix warnings. 2014-04-30 10:45:58 -07:00
Victor Zverovich
25ce9e7153 Fix MSVC build. 2014-04-30 10:39:24 -07:00
Victor Zverovich
f79398699b Add ThrowCError to throw an exception on C library errors. 2014-04-30 10:18:11 -07:00
Victor Zverovich
2c6372d790 Add a portable thread-safe version of strerror. 2014-04-30 09:42:48 -07:00
Victor Zverovich
5019b6b0f4 Fix tests, take 2. 2014-04-30 07:46:16 -07:00
Victor Zverovich
ba571064e7 Fix tests. 2014-04-30 07:44:41 -07:00
Victor Zverovich
ed2bdbaeaf Fix Windows build. 2014-04-30 07:41:54 -07:00
Victor Zverovich
c16217bf9b Test UTF8ToUTF16 and UTF16ToUTF8. 2014-04-30 07:38:43 -07:00
Victor Zverovich
089974eb92 Fix compiler flags check. 2014-04-30 07:36:47 -07:00
Victor Zverovich
da9aeab810 Add UTF8ToUTF16 and UTF16ToUTF8. 2014-04-30 07:23:43 -07:00
Victor Zverovich
859a4975f6 Throw SystemError if fwrite fails. 2014-04-30 06:55:21 -07:00
Victor Zverovich
4e33311597 Get rid of FormatterProxy. 2014-04-29 09:32:25 -07:00
Victor Zverovich
063d0077b3 Test FileSink. Simplify tests. 2014-04-29 08:39:37 -07:00
Victor Zverovich
48be5c22a2 Test "move". 2014-04-29 07:58:20 -07:00
Victor Zverovich
e00409c517 Comment. 2014-04-29 07:49:46 -07:00
Victor Zverovich
2b64133287 Add test script to appveyor config. 2014-04-29 07:40:42 -07:00
Victor Zverovich
cfa7702409 Update benchmark. 2014-04-29 07:27:30 -07:00
Victor Zverovich
3c3c846908 Check for -std=c++0x flag if -std=c++11 is not available. 2014-04-29 07:12:06 -07:00
Victor Zverovich
3fe942c284 Update benchmarks. 2014-04-29 07:11:46 -07:00
Victor Zverovich
c1f947f4fb Add comments. 2014-04-29 06:54:46 -07:00
Victor Zverovich
6798c1704e Add tests. 2014-04-29 06:26:37 -07:00
Victor Zverovich
bfc8615d28 Update benchmarks. 2014-04-29 06:26:30 -07:00
Victor Zverovich
98e4447b46 Use locally defined open. 2014-04-29 06:10:58 -07:00
Victor Zverovich
710725ea9d Fix implementation of open on windows. 2014-04-29 06:00:01 -07:00
Victor Zverovich
60c92a7431 Get rid of MSB3644 warnings. 2014-04-29 05:56:47 -07:00
Victor Zverovich
7ad88eff13 Fix a warning. 2014-04-29 05:54:36 -07:00
Victor Zverovich
11b3b5128e Fix test when the output file exists. 2014-04-28 20:04:59 -07:00
Victor Zverovich
e3063a5902 Fix test. 2014-04-28 19:33:45 -07:00
Victor Zverovich
9514da06e7 Fix test. 2014-04-28 19:27:41 -07:00
Victor Zverovich
7e6dd376b1 Improve doc. 2014-04-28 19:27:29 -07:00
Victor Zverovich
46e26191f4 Remove unnecessary const refs. 2014-04-28 19:27:19 -07:00
Victor Zverovich
d9db89814f Refactor action classes, Action -> Sink, add comments. 2014-04-28 08:59:29 -07:00
Victor Zverovich
d2bf073334 Format. 2014-04-27 09:47:07 -07:00
Victor Zverovich
83a7b79c2d Add a macro to disallow the copy constructor and operator= functions. 2014-04-27 09:46:56 -07:00
Victor Zverovich
5dee290482 Fix warnings. 2014-04-27 07:16:17 -07:00
Victor Zverovich
8d28a2382b Fix MSVC build. 2014-04-27 07:09:53 -07:00
Victor Zverovich
8641461c98 More tests. 2014-04-27 06:56:12 -07:00
Victor Zverovich
0b307248a6 Fix warning. 2014-04-26 10:09:35 -07:00
Victor Zverovich
f6baab5c27 Fix warning. 2014-04-26 10:00:29 -07:00
Victor Zverovich
f153f6f4b5 Implement move assignment in BasicWriter. 2014-04-26 07:10:21 -07:00
Victor Zverovich
515fd5218a Test move assignment in Array. 2014-04-26 06:49:22 -07:00
Victor Zverovich
3bb9941e37 Fix warning. 2014-04-26 06:47:25 -07:00
Victor Zverovich
a9922a6df2 Try setting width. 2014-04-25 09:04:53 -07:00
Victor Zverovich
2266e93fce Resore RST. 2014-04-25 08:57:34 -07:00
Victor Zverovich
5746660183 Use HTML to set image size. 2014-04-25 08:34:41 -07:00
Victor Zverovich
38f285c477 Set image height. 2014-04-25 08:30:05 -07:00
Victor Zverovich
9b2e5b0c75 Add appveyor badge. 2014-04-25 08:21:26 -07:00
Victor Zverovich
26277c8ab3 Implement move assignment operator for Array. 2014-04-25 08:18:07 -07:00
Victor Zverovich
5adc272ee7 Add tests. 2014-04-25 07:44:35 -07:00
Victor Zverovich
08b0741fa7 Add move ctor to BasicWriter. 2014-04-25 07:40:37 -07:00
Victor Zverovich
259a307daf Fix version check, take 2. 2014-04-24 15:39:20 -07:00
Victor Zverovich
daaa314aac Fix version check. 2014-04-24 14:55:18 -07:00
Victor Zverovich
b61bb5d635 Don't use rvalue references when compiling with clang and an old libstdc++ as the latter doesn't provide std::move. 2014-04-24 14:18:37 -07:00
Victor Zverovich
9882a7cf33 Specify which project to build. 2014-04-24 12:58:45 -07:00
Victor Zverovich
9df02e2b97 Set path to find the correct version of msbuild. 2014-04-24 12:51:58 -07:00
Victor Zverovich
f28645f900 Fix includes. 2014-04-24 12:37:06 -07:00
Victor Zverovich
4c84eb18b6 Test Array's move ctor. 2014-04-24 08:15:32 -07:00
Victor Zverovich
71a5b7a126 Return Writer instead of std::string in variadic overloads of Format for performance & consistency with non-variadic versions. 2014-04-24 07:32:01 -07:00
Victor Zverovich
bc2cab2efe Format. 2014-04-24 07:30:47 -07:00
Victor Zverovich
b22493ce7e Add a move ctor to Array. 2014-04-24 07:30:39 -07:00
Victor Zverovich
81217a2cc0 Add a comment. 2014-04-24 07:30:06 -07:00
Victor Zverovich
47cbcf8b3a Correct dirname. 2014-04-24 06:16:53 -07:00
Victor Zverovich
f04cb531db Remove unused code. 2014-04-23 19:41:25 -07:00
Victor Zverovich
cfeba45c35 Let the buffer grow as it pleases. 2014-04-23 18:37:49 -07:00
Victor Zverovich
33baa8f382 Fix the error when formatting a float with a filled buffer on MSVC. 2014-04-23 18:37:08 -07:00
Victor Zverovich
cb316b13b1 Add header to the project. 2014-04-23 17:52:13 -07:00
Victor Zverovich
f2e0391800 Simplify. 2014-04-23 17:34:32 -07:00
Victor Zverovich
9bde82689f Use prefix FMT_ for all macros. 2014-04-23 17:33:50 -07:00
Victor Zverovich
269c3bab7e Generate a script that configures build environment and runs msbuild. 2014-04-23 17:21:18 -07:00
Victor Zverovich
8c423d9747 Add a script to configure build environment and run CMake when building with Microsoft SDK toolchain. 2014-04-23 16:50:04 -07:00
Victor Zverovich
cf2278d4c5 Detect msbuild. 2014-04-23 16:28:51 -07:00
Victor Zverovich
2ef85bf845 Escape backslashes and quote. 2014-04-23 16:11:41 -07:00
Victor Zverovich
96bcc1688b Quote command. 2014-04-23 15:21:25 -07:00
Victor Zverovich
83b23aeb44 Just try running msbuild. 2014-04-23 13:16:28 -07:00
Victor Zverovich
1e31452544 Fix build config, take 2. 2014-04-23 13:03:01 -07:00
Victor Zverovich
6b07e0d28f Fix build config. 2014-04-23 12:51:29 -07:00
Victor Zverovich
ac62d74d20 Use the absolut path to msbuild. 2014-04-23 12:46:58 -07:00
Victor Zverovich
0054010255 Try a different VS version. 2014-04-23 12:35:43 -07:00
Victor Zverovich
ca8b6f0b13 Specify Visual Studio version. 2014-04-23 12:31:10 -07:00
Victor Zverovich
e905a2870a Add appveyor config. 2014-04-23 12:18:53 -07:00
Victor Zverovich
01ab792f60 Decouple the action perform on argument's destruction from the argument. 2014-04-23 09:13:03 -07:00
Victor Zverovich
e78904b9b9 Move formatting functionality from BasicFormatter to BasicWriter & FormatPaser to simplify the implementation of standalone formatting methods. 2014-04-23 08:27:50 -07:00
Victor Zverovich
1104e73242 Don't use initializer lists. 2014-04-22 19:42:25 -07:00
Victor Zverovich
656a8378d1 Use ArgInfo instead of Arg where possible. 2014-04-22 08:58:54 -07:00
Victor Zverovich
5b8126f84d Factor POD part of Arg into ArgInfo to be able to store it in Array. 2014-04-22 08:19:10 -07:00
Victor Zverovich
028fb01f42 Make docs depend on layout. 2014-04-22 06:34:31 -07:00
Victor Zverovich
a27560ef8d Update breathe. 2014-04-21 11:43:25 -07:00
Victor Zverovich
656ca25177 Add example. 2014-04-20 08:46:24 -07:00
Victor Zverovich
03f68857e2 Replace BasicFormatter::Format with BasicWriter::FormatInt. 2014-04-20 08:46:09 -07:00
Victor Zverovich
cdfbd128ec Document namespace use. 2014-04-19 19:17:06 -07:00
Victor Zverovich
64005c04ac Move Portability section to the web site. 2014-04-18 08:26:23 -07:00
Victor Zverovich
395f7a9615 Update readme. 2014-04-18 07:21:39 -07:00
Victor Zverovich
aec95bcbba Add instructions on how to run the unit tests. 2014-04-17 21:28:00 -07:00
Victor Zverovich
23dd27873d Update instructions for running tests. 2014-04-17 21:25:04 -07:00
Victor Zverovich
da2a35de79 Update names and links. 2014-04-17 21:17:56 -07:00
Victor Zverovich
f4c31ccd59 Include gtest in the package and bump version. 2014-04-17 21:17:34 -07:00
Victor Zverovich
5e3e7fe7d3 Add a fused version of gtest. 2014-04-17 20:59:06 -07:00
Victor Zverovich
31f7a7479d Remove gtest submodule. 2014-04-17 20:50:21 -07:00
Victor Zverovich
107a184a81 Fix test. 2014-04-17 19:20:54 -07:00
Victor Zverovich
a07b51f7df Conditionally compile part of a test that uses C++11. 2014-04-17 19:18:11 -07:00
Victor Zverovich
7f622c118d Test example. 2014-04-17 18:28:45 -07:00
Victor Zverovich
c22c26ed3d Update project name, copyright and version. 2014-04-17 08:55:02 -07:00
Victor Zverovich
5ef5195c8f Add Google Analytics. 2014-04-16 12:24:35 -07:00
Victor Zverovich
265b40ec6e Disable GCC warning about "long long". 2014-04-16 09:19:31 -07:00
Victor Zverovich
2e8c75269a Update the package name. 2014-04-15 07:35:28 -07:00
60 changed files with 56027 additions and 3658 deletions

7
.gitignore vendored
View File

@@ -1,16 +1,15 @@
/bin
/_CPack_Packages
/doc/conf.py
/doc/doxyxml
/doc/html
/Testing
/*.cmake
/format-test
/install_manifest.txt
/tinyformat_speed_test
*~
*.a
*.zip
cmake_install.cmake
CPack*Config.cmake
CTestTestfile.cmake
CMakeCache.txt
CMakeFiles
Makefile

11
.gitmodules vendored
View File

@@ -1,9 +1,6 @@
[submodule "gtest"]
path = gtest
url = git://github.com/vitaut/gtest.git
[submodule "format-benchmark"]
path = format-benchmark
url = git://github.com/vitaut/format-benchmark.git
[submodule "breathe"]
path = breathe
url = git://github.com/vitaut/breathe.git
url = https://github.com/michaeljones/breathe.git
[submodule "doc/sphinx-bootstrap-theme"]
path = doc/sphinx-bootstrap-theme
url = https://github.com/cppformat/sphinx-bootstrap-theme.git

View File

@@ -1,9 +1,20 @@
language: cpp
os:
- linux
- osx
before_install:
- git submodule update --init
env:
- BUILD_TYPE=Debug
- BUILD_TYPE=Release
script:
- cmake .
- make
- make test
- cmake -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DFMT_EXTRA_TESTS=ON .
- make -j4
- CTEST_OUTPUT_ON_FAILURE=1 make test
after_failure:
- cat Testing/Temporary/LastTest.log

15
Android.mk Normal file
View File

@@ -0,0 +1,15 @@
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := cppformat_static
LOCAL_MODULE_FILENAME := libcppformat
LOCAL_SRC_FILES := format.cc
LOCAL_C_INCLUDES := $(LOCAL_PATH)
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)
LOCAL_CFLAGS += -std=c++11 -fexceptions
include $(BUILD_STATIC_LIBRARY)

View File

@@ -1,3 +1,5 @@
message(STATUS "CMake version: ${CMAKE_VERSION}")
cmake_minimum_required(VERSION 2.6)
# Set the default CMAKE_BUILD_TYPE to Release.
@@ -8,153 +10,165 @@ if (NOT CMAKE_BUILD_TYPE)
"Choose the type of build, options are: None(CMAKE_CXX_FLAGS or CMAKE_C_FLAGS used) Debug Release RelWithDebInfo MinSizeRel.")
endif ()
option(FMT_EXTRA_TESTS "Enable extra tests." OFF)
project(FORMAT)
message(STATUS "Build type: ${CMAKE_BUILD_TYPE}")
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
include(CheckCXXCompilerFlag)
check_cxx_compiler_flag(-std=c++11 HAVE_STD_CPP11_FLAG)
if (HAVE_STD_CPP11_FLAG)
set(CPP11_FLAG -std=c++11)
else ()
check_cxx_compiler_flag(-std=c++0x HAVE_STD_CPP0X_FLAG)
if (HAVE_STD_CPP0X_FLAG)
set(CPP11_FLAG -std=c++0x)
endif ()
endif ()
add_library(format format.cc)
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH}
"${CMAKE_CURRENT_SOURCE_DIR}/support/cmake")
if (CMAKE_GENERATOR MATCHES "Visual Studio")
# If Microsoft SDK is installed create script run-msbuild.bat that
# calls SetEnv.cmd to to set up build environment and runs msbuild.
# It is useful when building Visual Studio projects with the SDK
# toolchain rather than Visual Studio.
include(FindSetEnv)
if (WINSDK_SETENV)
set(MSBUILD_SETUP "call \"${WINSDK_SETENV}\"")
endif ()
# Set FrameworkPathOverride to get rid of MSB3644 warnings.
set(netfxpath "C:\\Program Files\\Reference Assemblies\\Microsoft\\Framework\\.NETFramework\\v4.0")
file(WRITE run-msbuild.bat "
${MSBUILD_SETUP}
${CMAKE_MAKE_PROGRAM} -p:FrameworkPathOverride=\"${netfxpath}\" %*")
endif ()
set(FMT_SOURCES format.cc format.h)
include(CheckSymbolExists)
if (WIN32)
check_symbol_exists(open io.h HAVE_OPEN)
else ()
check_symbol_exists(open fcntl.h HAVE_OPEN)
endif ()
if (HAVE_OPEN)
add_definitions(-DFMT_USE_FILE_DESCRIPTORS=1)
set(FMT_SOURCES ${FMT_SOURCES} posix.cc posix.h)
endif ()
if (CPP11_FLAG)
set(CMAKE_REQUIRED_FLAGS ${CPP11_FLAG})
endif ()
if (BIICODE)
include(support/cmake/biicode.cmake)
return()
endif ()
add_library(format ${FMT_SOURCES})
if (CMAKE_COMPILER_IS_GNUCXX)
set_target_properties(format PROPERTIES COMPILE_FLAGS
"-Wall -Wextra -pedantic")
"-Wall -Wextra -Wshadow -pedantic")
endif ()
if (HAVE_STD_CPP11_FLAG)
set_target_properties(format PROPERTIES COMPILE_FLAGS "-std=c++11")
if (CPP11_FLAG AND FMT_EXTRA_TESTS)
set_target_properties(format PROPERTIES COMPILE_FLAGS ${CPP11_FLAG})
# Test compilation with default flags.
add_library(testformat format.cc)
file(GLOB src RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} test/*.cc test/*.h)
add_library(testformat STATIC ${FMT_SOURCE_FILES} ${src})
endif ()
add_subdirectory(doc)
enable_testing()
add_test(compile-test ${CMAKE_CTEST_COMMAND}
--build-and-test
"${CMAKE_CURRENT_SOURCE_DIR}/test"
"${CMAKE_CURRENT_BINARY_DIR}/test"
--build-generator ${CMAKE_GENERATOR}
--build-makeprogram ${CMAKE_MAKE_PROGRAM})
include_directories(. gmock)
# We compile Google Test ourselves instead of using pre-compiled libraries.
# See the Google Test FAQ "Why is it not recommended to install a
# pre-compiled copy of Google Test (for example, into /usr/local)?"
# at http://code.google.com/p/googletest/wiki/FAQ for more details.
if (EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/gtest/CMakeLists.txt)
option(
gtest_force_shared_crt
"Use shared (DLL) run-time lib even when Google Test is built as static lib."
ON)
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
add_definitions(-DGTEST_USE_OWN_TR1_TUPLE=1)
endif ()
add_library(gmock STATIC gmock/gmock-gtest-all.cc)
find_package(Threads)
target_link_libraries(gmock ${CMAKE_THREAD_LIBS_INIT})
# Check if variadic templates are working and not affected by GCC bug 39653:
# https://gcc.gnu.org/bugzilla/show_bug.cgi?id=39653
check_cxx_source_compiles("
template <class T, class ...Types>
struct S { typedef typename S<Types...>::type type; };
int main() {}" FMT_VARIADIC_TEMPLATES)
# Check if initializer lists are supported.
check_cxx_source_compiles("
#include <initilizer_list>
int main() {}" FMT_INITIALIZER_LIST)
add_subdirectory(gtest)
include_directories(gtest/include)
link_directories(${CMAKE_CURRENT_BINARY_DIR}/gtest)
add_executable(format-test format-test.cc)
target_link_libraries(format-test format gtest)
if (CMAKE_COMPILER_IS_GNUCXX)
set_target_properties(format-test PROPERTIES COMPILE_FLAGS
"-Wall -Wextra -pedantic -Wno-long-long -Wno-variadic-macros")
endif ()
add_test(format-test format-test)
if (HAVE_STD_CPP11_FLAG)
set_target_properties(format-test PROPERTIES COMPILE_FLAGS "-std=c++11")
endif ()
if (NOT FMT_VARIADIC_TEMPLATES OR NOT FMT_INITIALIZER_LIST)
add_definitions(-DGTEST_LANG_CXX11=0)
endif ()
find_library(PROFILER_LIB profiler)
find_path(PROFILER_INCLUDE_DIR gperftools/profiler.h)
if (PROFILER_LIB AND PROFILER_INCLUDE_DIR)
include_directories(${PROFILER_INCLUDE_DIR})
set(HAVE_PROFILER TRUE)
# This is disabled at the moment because format is compiled without -std=c++11
# by default.
#check_cxx_source_compiles("
# void f() noexcept {}
# int main(){ f(); }" FMT_BASIC_NOEXCEPT_SUPPORT)
#if (FMT_BASIC_NOEXCEPT_SUPPORT)
# add_definitions(-DFMT_USE_NOEXCEPT=1)
#endif ()
#check_cxx_source_compiles("
# struct C{
# C()=delete;
# C(const C&)=delete;
# C& operator=(const C&)=delete;
# };
# int main(){}" FMT_DELETED_FUNCTIONS)
#if (FMT_DELETED_FUNCTIONS)
# add_definitions(-DFMT_USE_DELETED_FUNCTIONS=1)
#endif ()
#check_cxx_source_compiles("
# static_assert(true, \"\");
# int main(){}" FMT_STATIC_ASSERT)
#if (FMT_STATIC_ASSERT)
# add_definitions(-DFMT_USE_STATIC_ASSERT=1)
#endif ()
# GTest doesn't detect <tuple> with clang.
if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
target_compile_definitions(gmock PUBLIC GTEST_USE_OWN_TR1_TUPLE=1)
endif ()
find_package(Boost)
if (Boost_FOUND)
add_definitions(-DHAVE_BOOST)
include_directories(${Boost_INCLUDE_DIRS})
endif ()
if (EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/format-benchmark/tinyformat_test.cpp)
add_subdirectory(format-benchmark)
add_executable(tinyformat_speed_test format-benchmark/tinyformat_test.cpp)
target_link_libraries(tinyformat_speed_test format)
if (HAVE_PROFILER)
target_link_libraries(tinyformat_speed_test ${PROFILER_LIB})
set(PROFILE_DEFS ";FMT_PROFILE")
endif ()
set_target_properties(tinyformat_speed_test PROPERTIES COMPILE_DEFINITIONS
"SPEED_TEST;HAVE_FORMAT;_SCL_SECURE_NO_WARNINGS;${PROFILE_DEFS}")
if (HAVE_STD_CPP11_FLAG)
set_target_properties(tinyformat_speed_test PROPERTIES COMPILE_FLAGS "-std=c++11")
endif ()
add_custom_target(speed_test
COMMAND @echo running speed tests...
COMMAND @echo printf timings:
COMMAND @time -p ./tinyformat_speed_test printf > /dev/null
COMMAND @echo iostreams timings:
COMMAND @time -p ./tinyformat_speed_test iostreams > /dev/null
COMMAND @echo format timings:
COMMAND @time -p ./tinyformat_speed_test format > /dev/null
COMMAND @echo tinyformat timings:
COMMAND @time -p ./tinyformat_speed_test tinyformat > /dev/null
COMMAND @echo boost timings:
COMMAND @time -p ./tinyformat_speed_test boost > /dev/null
DEPENDS tinyformat_speed_test)
add_custom_target(bloat_test_debug
COMMAND echo running bloat tests...
COMMAND echo printf results:
COMMAND ./bloat_test.sh
COMMAND echo iostreams results:
COMMAND ./bloat_test.sh -DUSE_IOSTREAMS
COMMAND echo format results:
COMMAND ./bloat_test.sh -DUSE_FORMAT -L.. -lformat
COMMAND echo tinyformat results:
COMMAND ./bloat_test.sh -DUSE_TINYFORMAT
COMMAND echo boost results:
COMMAND ./bloat_test.sh -DUSE_BOOST
WORKING_DIRECTORY tinyformat
DEPENDS format)
add_custom_target(bloat_test_optimized
COMMAND echo running bloat tests...
COMMAND echo printf results:
COMMAND ./bloat_test.sh -O3
COMMAND echo iostreams results:
COMMAND ./bloat_test.sh -O3 -DUSE_IOSTREAMS
COMMAND echo format results:
COMMAND ./bloat_test.sh -O3 -DUSE_FORMAT -L.. -lformat
COMMAND echo tinyformat results:
COMMAND ./bloat_test.sh -O3 -DUSE_TINYFORMAT
COMMAND echo boost results:
COMMAND ./bloat_test.sh -O3 -DUSE_BOOST
WORKING_DIRECTORY tinyformat
DEPENDS format)
endif ()
enable_testing()
add_subdirectory(test)
if (EXISTS .gitignore)
# Get the list of ignored files from .gitignore.
file (STRINGS ".gitignore" lines)
LIST(REMOVE_ITEM lines /doc/html)
foreach (line ${lines})
string(REPLACE "." "[.]" line "${line}")
string(REPLACE "*" ".*" line "${line}")
set(ignored_files ${ignored_files} "${line}$" "${line}/")
endforeach ()
set(ignored_files ${ignored_files} /.git /breathe /format-benchmark /gtest)
set(ignored_files ${ignored_files} /.git /breathe /format-benchmark sphinx/)
set(CPACK_SOURCE_GENERATOR ZIP)
set(CPACK_SOURCE_IGNORE_FILES ${ignored_files})
set(CPACK_PACKAGE_VERSION_MAJOR 0)
set(CPACK_PACKAGE_VERSION_MINOR 8)
set(CPACK_PACKAGE_VERSION_MAJOR 1)
set(CPACK_PACKAGE_VERSION_MINOR 1)
set(CPACK_PACKAGE_VERSION_PATCH 0)
set(CPACK_SOURCE_PACKAGE_FILE_NAME
format-${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}.${CPACK_PACKAGE_VERSION_PATCH}-src)
set(CPPFORMAT_VERSION
${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}.${CPACK_PACKAGE_VERSION_PATCH})
set(CPACK_SOURCE_PACKAGE_FILE_NAME cppformat-${CPPFORMAT_VERSION})
set(CPACK_RESOURCE_FILE_README ${FORMAT_SOURCE_DIR}/README.rst)
include(CPack)
endif ()
configure_file(doc/conf.py.in doc/conf.py @ONLY)
# Install our targets
install(TARGETS format DESTINATION lib)
install(FILES format.h DESTINATION include)

335
ChangeLog.rst Normal file
View File

@@ -0,0 +1,335 @@
1.1.0 - 2015-03-06
------------------
* Added ``BasicArrayWriter``, a class template that provides operations for
formatting and writing data into a fixed-size array
(`#105 <https://github.com/cppformat/cppformat/issues/105>`_ and
`#122 <https://github.com/cppformat/cppformat/issues/122>`_):
.. code:: c++
char buffer[100];
fmt::ArrayWriter w(buffer);
w.write("The answer is {}", 42);
* Added `0 A.D. <http://play0ad.com/>`_ and `PenUltima Online (POL)
<http://www.polserver.com/>`_ to the list of notable projects using C++ Format.
* C++ Format now uses MSVC intrinsics for better formatting performance
(`#115 <https://github.com/cppformat/cppformat/pull/115>`_,
`#116 <https://github.com/cppformat/cppformat/pull/116>`_,
`#118 <https://github.com/cppformat/cppformat/pull/118>`_ and
`#121 <https://github.com/cppformat/cppformat/pull/121>`_).
Previously these optimizations where only used on GCC and Clang.
Thanks to `@CarterLi <https://github.com/CarterLi>`_ and
`@objectx <https://github.com/objectx>`_.
* CMake install target (`#119 <https://github.com/cppformat/cppformat/pull/119>`_).
Thanks to `@TrentHouliston <https://github.com/TrentHouliston>`_.
You can now install C++ Format with ``make install`` command.
* Improved `Biicode <http://www.biicode.com/>`_ support
(`#98 <https://github.com/cppformat/cppformat/pull/98>`_ and
`#104 <https://github.com/cppformat/cppformat/pull/104>`_). Thanks to
`@MariadeAnton <https://github.com/MariadeAnton>`_ and
`@franramirez688 <https://github.com/franramirez688>`_.
* Improved support for bulding with `Android NDK
<https://developer.android.com/tools/sdk/ndk/index.html>`_
(`#107 <https://github.com/cppformat/cppformat/pull/107>`_).
Thanks to `@newnon <https://github.com/newnon>`_.
The `android-ndk-example <https://github.com/cppformat/android-ndk-example>`_
repository provides and example of using C++ Format with Android NDK:
.. image:: https://raw.githubusercontent.com/cppformat/android-ndk-example/
master/screenshot.png
* Improved documentation of ``SystemError`` and ``WindowsError``
(`#54 <https://github.com/cppformat/cppformat/issues/54>`_).
* Various code improvements
(`#110 <https://github.com/cppformat/cppformat/pull/110>`_,
`#111 <https://github.com/cppformat/cppformat/pull/111>`_
`#112 <https://github.com/cppformat/cppformat/pull/112>`_).
Thanks to `@CarterLi <https://github.com/CarterLi>`_.
* Improved compile-time errors when formatting wide into narrow strings
(`#117 <https://github.com/cppformat/cppformat/issues/117>`_).
* Fixed ``BasicWriter::write`` without formatting arguments when C++11 support
is disabled (`#109 <https://github.com/cppformat/cppformat/issues/109>`_).
* Fixed header-only build on OS X with GCC 4.9
(`#124 <https://github.com/cppformat/cppformat/issues/124>`_).
* Fixed packaging issues (`#94 <https://github.com/cppformat/cppformat/issues/94>`_).
* Fixed warnings in GCC, MSVC and Xcode/Clang
(`#95 <https://github.com/cppformat/cppformat/issues/95>`_,
`#96 <https://github.com/cppformat/cppformat/issues/96>`_ and
`#114 <https://github.com/cppformat/cppformat/pull/114>`_).
* Added `changelog <https://github.com/cppformat/cppformat/edit/master/ChangeLog.rst>`_
(`#103 <https://github.com/cppformat/cppformat/issues/103>`_).
1.0.0 - 2015-02-05
------------------
* Add support for a header-only configuration when ``FMT_HEADER_ONLY`` is
defined before including ``format.h``:
.. code:: c++
#define FMT_HEADER_ONLY
#include "format.h"
* Compute string length in the constructor of ``BasicStringRef``
instead of the ``size`` method
(`#79 <https://github.com/cppformat/cppformat/issues/79>`_).
This eliminates size computation for string literals on reasonable optimizing
compilers.
* Fix formatting of types with overloaded ``operator <<`` for ``std::wostream``
(`#86 <https://github.com/cppformat/cppformat/issues/86>`_):
.. code:: c++
fmt::format(L"The date is {0}", Date(2012, 12, 9));
* Fix linkage of tests on Arch Linux
(`#89 <https://github.com/cppformat/cppformat/issues/89>`_).
* Allow precision specifier for non-float arguments
(`#90 <https://github.com/cppformat/cppformat/issues/90>`_):
.. code:: c++
fmt::print("{:.3}\n", "Carpet"); // prints "Car"
* Fix build on Android NDK
(`#93 <https://github.com/cppformat/cppformat/issues/93>`_)
* Improvements to documentation build procedure.
* Remove ``FMT_SHARED`` CMake variable in favor of standard `BUILD_SHARED_LIBS
<http://www.cmake.org/cmake/help/v3.0/variable/BUILD_SHARED_LIBS.html>`_.
* Fix error handling in ``fmt::fprintf``.
* Fix a number of warnings.
0.12.0 - 2014-10-25
-------------------
* [Breaking] Improved separation between formatting and buffer management.
``Writer`` is now a base class that cannot be instantiated directly.
The new ``MemoryWriter`` class implements the default buffer management
with small allocations done on stack. So ``fmt::Writer`` should be replaced
with ``fmt::MemoryWriter`` in variable declarations.
Old code:
.. code:: c++
fmt::Writer w;
New code:
.. code:: c++
fmt::MemoryWriter w;
If you pass ``fmt::Writer`` by reference, you can continue to do so:
.. code:: c++
void f(fmt::Writer &w);
This doesn't affect the formatting API.
* Support for custom memory allocators
(`#69 <https://github.com/cppformat/cppformat/issues/69>`_)
* Formatting functions now accept `signed char` and `unsigned char` strings as
arguments (`#73 <https://github.com/cppformat/cppformat/issues/73>`_):
.. code:: c++
auto s = format("GLSL version: {}", glGetString(GL_VERSION));
* Reduced code bloat. According to the new `benchmark results
<https://github.com/cppformat/cppformat#compile-time-and-code-bloat>`_,
cppformat is close to ``printf`` and by the order of magnitude better than
Boost Format in terms of compiled code size.
* Improved appearance of the documentation on mobile by using the `Sphinx
Bootstrap theme <http://ryan-roemer.github.io/sphinx-bootstrap-theme/>`_:
.. |old| image:: https://cloud.githubusercontent.com/assets/576385/4792130/
cd256436-5de3-11e4-9a62-c077d0c2b003.png
.. |new| image:: https://cloud.githubusercontent.com/assets/576385/4792131/
cd29896c-5de3-11e4-8f59-cac952942bf0.png
+-------+-------+
| Old | New |
+-------+-------+
| |old| | |new| |
+-------+-------+
0.11.0 - 2014-08-21
-------------------
* Safe printf implementation with a POSIX extension for positional arguments:
.. code:: c++
fmt::printf("Elapsed time: %.2f seconds", 1.23);
fmt::printf("%1$s, %3$d %2$s", weekday, month, day);
* Arguments of ``char`` type can now be formatted as integers
(Issue `#55 <https://github.com/cppformat/cppformat/issues/55>`_):
.. code:: c++
fmt::format("0x{0:02X}", 'a');
* Deprecated parts of the API removed.
* The library is now built and tested on MinGW with Appveyor in addition to
existing test platforms Linux/GCC, OS X/Clang, Windows/MSVC.
0.10.0 - 2014-07-01
-------------------
**Improved API**
* All formatting methods are now implemented as variadic functions instead
of using ``operator<<`` for feeding arbitrary arguments into a temporary
formatter object. This works both with C++11 where variadic templates are
used and with older standards where variadic functions are emulated by
providing lightweight wrapper functions defined with the ``FMT_VARIADIC``
macro. You can use this macro for defining your own portable variadic
functions:
.. code:: c++
void report_error(const char *format, const fmt::ArgList &args) {
fmt::print("Error: {}");
fmt::print(format, args);
}
FMT_VARIADIC(void, report_error, const char *)
report_error("file not found: {}", path);
Apart from a more natural syntax, this also improves performance as there
is no need to construct temporary formatter objects and control arguments'
lifetimes. Because the wrapper functions are very ligthweight, this doesn't
cause code bloat even in pre-C++11 mode.
* Simplified common case of formatting an ``std::string``. Now it requires a
single function call:
.. code:: c++
std::string s = format("The answer is {}.", 42);
Previously it required 2 function calls:
.. code:: c++
std::string s = str(Format("The answer is {}.") << 42);
Instead of unsafe ``c_str`` function, ``fmt::Writer`` should be used directly
to bypass creation of ``std::string``:
.. code:: c++
fmt::Writer w;
w.write("The answer is {}.", 42);
w.c_str(); // returns a C string
This doesn't do dynamic memory allocation for small strings and is less error
prone as the lifetime of the string is the same as for ``std::string::c_str``
which is well understood (hopefully).
* Improved consistency in naming functions that are a part of the public API.
Now all public functions are lowercase following the standard library
conventions. Previously it was a combination of lowercase and
CapitalizedWords.
Issue `#50 <https://github.com/cppformat/cppformat/issues/50>`_.
* Old functions are marked as deprecated and will be removed in the next
release.
**Other Changes**
* Experimental support for printf format specifications (work in progress):
.. code:: c++
fmt::printf("The answer is %d.", 42);
std::string s = fmt::sprintf("Look, a %s!", "string");
* Support for hexadecimal floating point format specifiers ``a`` and ``A``:
.. code:: c++
print("{:a}", -42.0); // Prints -0x1.5p+5
print("{:A}", -42.0); // Prints -0X1.5P+5
* CMake option ``FMT_SHARED`` that specifies whether to build format as a
shared library (off by default).
0.9.0 - 2014-05-13
------------------
* More efficient implementation of variadic formatting functions.
* ``Writer::Format`` now has a variadic overload:
.. code:: c++
Writer out;
out.Format("Look, I'm {}!", "variadic");
* For efficiency and consistency with other overloads, variadic overload of
the ``Format`` function now returns ``Writer`` instead of ``std::string``.
Use the ``str`` function to convert it to ``std::string``:
.. code:: c++
std::string s = str(Format("Look, I'm {}!", "variadic"));
* Replaced formatter actions with output sinks: ``NoAction`` -> ``NullSink``,
``Write`` -> ``FileSink``, ``ColorWriter`` -> ``ANSITerminalSink``.
This improves naming consistency and shouldn't affect client code unless
these classes are used directly which should be rarely needed.
* Added ``ThrowSystemError`` function that formats a message and throws
``SystemError`` containing the formatted message and system-specific error
description. For example, the following code
.. code:: c++
FILE *f = fopen(filename, "r");
if (!f)
ThrowSystemError(errno, "Failed to open file '{}'") << filename;
will throw ``SystemError`` exception with description
"Failed to open file '<filename>': No such file or directory" if file
doesn't exist.
* Support for AppVeyor continuous integration platform.
* ``Format`` now throws ``SystemError`` in case of I/O errors.
* Improve test infrastructure. Print functions are now tested by redirecting
the output to a pipe.
0.8.0 - 2014-04-14
------------------
* Initial release

View File

@@ -1,11 +1,21 @@
format
======
C++ Format
==========
.. image:: https://travis-ci.org/cppformat/format.png?branch=master
:target: https://travis-ci.org/cppformat/format
.. image:: https://travis-ci.org/cppformat/cppformat.png?branch=master
:target: https://travis-ci.org/cppformat/cppformat
Format is an open-source formatting library for C++.
It can be used as a type-safe alternative to printf or as a fast
.. image:: https://ci.appveyor.com/api/projects/status/qk0bhyhqp1ekpat8
:target: https://ci.appveyor.com/project/vitaut/cppformat
.. image:: https://readthedocs.org/projects/cppformat/badge/?version=stable
:target: http://cppformat.readthedocs.org/en/stable/
:alt: Documentation Status
.. image:: https://webapi.biicode.com/v1/badges/vitaut/vitaut/cppformat/master
:target: https://www.biicode.com/vitaut/cppformat
C++ Format is an open-source formatting library for C++.
It can be used as a safe alternative to printf or as a fast
alternative to IOStreams.
Features
@@ -14,15 +24,18 @@ Features
* Two APIs: faster concatenation-based write API and slower (but still
very fast) replacement-based format API with positional arguments for
localization.
* Write API similar to the one used by IOStreams but much faster and more
consistent.
* Write API similar to the one used by IOStreams but stateless allowing
faster implementation.
* Format API with `format string syntax
<http://cppformat.github.io/format#format-string-syntax>`__
<http://cppformat.readthedocs.org/en/latest/syntax.html>`_
similar to the one used by `str.format
<http://docs.python.org/2/library/stdtypes.html#str.format>`__ in Python.
<http://docs.python.org/2/library/stdtypes.html#str.format>`_ in Python.
* Safe `printf implementation
<http://cppformat.readthedocs.org/en/stable/reference.html#printf-formatting-functions>`_
including the POSIX extension for positional arguments.
* Support for user-defined types.
* High speed: performance of the format API is close to that of
glibc's `printf <http://en.cppreference.com/w/cpp/io/c/fprintf>`__
glibc's `printf <http://en.cppreference.com/w/cpp/io/c/fprintf>`_
and better than performance of IOStreams. See `Speed tests`_ and
`Fast integer to string conversion in C++
<http://zverovich.net/2013/09/07/integer-to-string-conversion-in-cplusplus.html>`_.
@@ -30,41 +43,43 @@ Features
header file and a single source file) and compiled code.
See `Compile time and code bloat`_.
* Reliability: the library has an extensive set of `unit tests
<https://github.com/cppformat/format/blob/master/format-test.cc>`__.
<https://github.com/cppformat/cppformat/tree/master/test>`_.
* Safety: the library is fully type safe, errors in format strings are
reported using exceptions, automatic memory management prevents buffer
overflow errors.
* Ease of use: small self-contained code base, no external dependencies,
permissive BSD `license`_.
* `Portability`_ with consistent output across platforms and support
for older compilers.
* `Portability <http://cppformat.github.io#portability>`_ with consistent output
across platforms and support for older compilers.
* Clean warning-free codebase even on high warning levels
(-Wall -Wextra -pedantic).
* Support for wide strings.
* Optional header-only configuration enabled with the ``FMT_HEADER_ONLY`` macro.
See the `documentation <http://cppformat.github.io/format/>`__ for more details.
See the `documentation <http://cppformat.readthedocs.org/en/stable/>`_ for more details.
Examples
--------
This prints ``Hello, world!`` to stdout:
.. code-block:: c++
.. code:: c++
fmt::Print("Hello, {}!") << "world";
fmt::print("Hello, {}!", "world"); // uses Python-like format string syntax
fmt::printf("Hello, %s!", "world"); // uses printf format string syntax
Arguments can be accessed by position and arguments' indices can be repeated:
.. code-block:: c++
.. code:: c++
std::string s = str(fmt::Format("{0}{1}{0}") << "abra" << "cad");
std::string s = fmt::format("{0}{1}{0}", "abra", "cad");
// s == "abracadabra"
Format can be used as a safe portable replacement for ``itoa``:
C++ Format can be used as a safe portable replacement for ``itoa``:
.. code-block:: c++
.. code:: c++
fmt::Writer w;
fmt::MemoryWriter w;
w << 42; // replaces itoa(42, buffer, 10)
w << fmt::hex(42); // replaces itoa(42, buffer, 16)
// access the string using w.str() or w.c_str()
@@ -72,7 +87,7 @@ Format can be used as a safe portable replacement for ``itoa``:
An object of any user-defined type for which there is an overloaded
:code:`std::ostream` insertion operator (``operator<<``) can be formatted:
.. code-block:: c++
.. code:: c++
class Date {
int year_, month_, day_;
@@ -84,44 +99,64 @@ An object of any user-defined type for which there is an overloaded
}
};
std::string s = str(fmt::Format("The date is {}") << Date(2012, 12, 9));
std::string s = fmt::format("The date is {}", Date(2012, 12, 9));
// s == "The date is 2012-12-9"
You can use `fmt::Formatter
<http://cppformat.github.io/format/#project0classfmt_1_1_formatter>`__
to create your own functions similar to `fmt::Format
<http://cppformat.github.io/format/#fmt::Format__StringRef>`__ and ``fmt::Print``
with an arbitrary action performed when formatting is complete:
You can use the `FMT_VARIADIC
<http://cppformat.readthedocs.org/en/latest/reference.html#utilities>`_
macro to create your own functions similar to `format
<http://cppformat.readthedocs.org/en/latest/reference.html#format>`_ and
`print <http://cppformat.readthedocs.org/en/latest/reference.html#print>`_
which take arbitrary arguments:
.. code-block:: c++
.. code:: c++
struct PrintError {
void operator()(const fmt::Writer &w) const {
std::cerr << "Error: " << w.str() << std::endl;
}
};
// Formats an error message and prints it to std::cerr.
fmt::Formatter<PrintError> ReportError(const char *format) {
fmt::Formatter<PrintError> f(format);
return f;
// Prints formatted error message.
void report_error(const char *format, fmt::ArgList args) {
fmt::print("Error: ");
fmt::print(format, args);
}
FMT_VARIADIC(void, report_error, const char *)
ReportError("File not found: {}") << path;
report_error("file not found: {}", path);
Note that you only need to define one function that takes ``fmt::ArgList``
argument. ``FMT_VARIADIC`` automatically defines necessary wrappers that
accept variable number of arguments.
Projects using this library
---------------------------
* `AMPL <https://github.com/ampl/ampl>`__:
Open-source AMPL solver interface, solver connections, table handlers
and examples
* `0 A.D. <http://play0ad.com/>`_: A free, open-source, cross-platform real-time strategy game
* `Saddy <https://code.google.com/p/saddy/>`__:
* `AMPL/MP <https://github.com/ampl/mp>`_:
An open-source library for mathematical programming
* `HarpyWar/pvpgn <https://github.com/HarpyWar/pvpgn>`_:
Player vs Player Gaming Network with tweaks
* `KBEngine <http://www.kbengine.org/>`_: An open-source MMOG server engine
* `Lifeline <https://github.com/peter-clark/lifeline>`_: A 2D game
* `PenUltima Online (POL) <http://www.polserver.com/>`_:
An MMO server, compatible with most Ultima Online clients
* `readpe <https://bitbucket.org/sys_dev/readpe>`_: Read Portable Executable
* `Saddy <https://code.google.com/p/saddy/>`_:
Small crossplatform 2D graphic engine
If you are aware of other projects using ``format``, please let me know
by `email <mailto:victor.zverovich@gmail.com>`__ or by submitting an
`issue <https://github.com/cppformat/format/issues>`__.
* `Salesforce Analytics Cloud <http://www.salesforce.com/analytics-cloud/overview/>`_:
Business intelligence software
* `spdlog <https://github.com/gabime/spdlog>`_: Super fast C++ logging library
`More... <https://github.com/search?q=cppformat&type=Code>`_
If you are aware of other projects using this library, please let me know
by `email <mailto:victor.zverovich@gmail.com>`_ or by submitting an
`issue <https://github.com/cppformat/cppformat/issues>`_.
Motivation
----------
@@ -138,12 +173,12 @@ Printf
~~~~~~
The good thing about printf is that it is very fast and readily available
being the part of the C standard library. The main drawback is that it
being a part of the C standard library. The main drawback is that it
doesn't support user-defined types. Printf also has safety issues although
they are mostly solved with `__attribute__ ((format (printf, ...))
<http://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html>`__ in GCC.
they are mostly solved with `_attribute__ ((format (printf, ...))
<http://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html>`_ in GCC.
There is a POSIX extension that adds positional arguments required for
`i18n <http://en.wikipedia.org/wiki/Internationalization_and_localization>`__
`i18n <http://en.wikipedia.org/wiki/Internationalization_and_localization>`_
to printf but it is not a part of C99 and may not be available on some
platforms.
@@ -152,13 +187,13 @@ IOStreams
The main issue with IOStreams is best illustrated with an example:
.. code-block:: c++
.. code:: c++
std::cout << std::setprecision(2) << std::fixed << 1.23456 << "\n";
which is a lot of typing compared to printf:
.. code-block:: c++
.. code:: c++
printf("%.2f\n", 1.23456);
@@ -207,9 +242,8 @@ Tinyformat
This library supports printf-like format strings and is very small and
fast. Unfortunately it doesn't support positional arguments and wrapping
it in C++98 is somewhat difficult. However if you only need a type-safe
printf replacement with support for user-defined types, I highly recommend
this library.
it in C++98 is somewhat difficult. Also its performance and code compactness
are limited by IOStreams.
Boost Spirit.Karma
~~~~~~~~~~~~~~~~~~
@@ -219,7 +253,16 @@ for completeness. As IOStreams it suffers from the problem of mixing
verbatim text with arguments. The library is pretty fast, but slower
on integer formatting than ``fmt::Writer`` on Karma's own benchmark,
see `Fast integer to string conversion in C++
<http://zverovich.net/2013/09/07/integer-to-string-conversion-in-cplusplus.html>`__.
<http://zverovich.net/2013/09/07/integer-to-string-conversion-in-cplusplus.html>`_.
What Users Say
--------------
Thanks for creating this library. Its been a hole in C++ for a long time.
Ive used both boost::format and loki::SPrintf, and neither felt like the
right answer. This does.
-- Kurt Haas
Benchmarks
----------
@@ -228,107 +271,105 @@ Speed tests
~~~~~~~~~~~
The following speed tests results were generated by building
``tinyformat_test.cpp`` on Ubuntu GNU/Linux 12.10 with
``g++-4.7.2 -O3 -DSPEED_TEST -DHAVE_FORMAT``, and taking the best of three
``tinyformat_test.cpp`` on Ubuntu GNU/Linux 14.04.1 with
``g++-4.8.2 -O3 -DSPEED_TEST -DHAVE_FORMAT``, and taking the best of three
runs. In the test, the format string ``"%0.10f:%04d:%+g:%s:%p:%c:%%\n"`` or
equivalent is filled 2000000 times with output sent to ``/dev/null``; for
further details see the `source
<https://github.com/cppformat/format-benchmark/blob/master/tinyformat_test.cpp>`__.
<https://github.com/cppformat/format-benchmark/blob/master/tinyformat_test.cpp>`_.
============== ========
test name run time
============== ========
libc printf 1.28s
std::ostream 2.09s
format 1.32s
tinyformat 2.55s
boost::format 10.42s
============== ========
================= ============= ===========
Library Method Run Time, s
================= ============= ===========
EGLIBC 2.19 printf 1.30
libstdc++ 4.8.2 std::ostream 1.85
C++ Format 1.0 fmt::print 1.42
tinyformat 2.0.1 tfm::printf 2.25
Boost Format 1.54 boost::format 9.94
================= ============= ===========
As you can see boost::format is much slower than the alternative methods; this
is confirmed by `other tests <http://accu.org/index.php/journals/1539>`__.
is confirmed by `other tests <http://accu.org/index.php/journals/1539>`_.
Tinyformat is quite good coming close to IOStreams. Unfortunately tinyformat
cannot be faster than the IOStreams because it uses them internally.
Performance of format is close to that of printf.
Performance of cppformat is close to that of printf, being `faster than printf on integer
formatting <http://zverovich.net/2013/09/07/integer-to-string-conversion-in-cplusplus.html>`_,
but slower on floating-point formatting which dominates this benchmark.
Compile time and code bloat
~~~~~~~~~~~~~~~~~~~~~~~~~~~
The script ``bloat_test.sh`` from the `tinyformat
<https://github.com/c42f/tinyformat>`__ repository tests compile time and
code bloat for nontrivial projects. It generates 100 translation units
and uses ``printf()`` or its alternative five times in each to simulate
a medium sized project. The resulting executable size and compile time
(g++-4.7.2, Ubuntu GNU/Linux 12.10, best of three) is shown in the following
tables.
**Non-optimized build**
====================== ================== ==========================
test name total compile time executable size (stripped)
====================== ================== ==========================
libc printf 2.8s 44K (32K)
std::ostream 12.9s 84K (60K)
format 16.0s 152K (128K)
tinyformat 20.6s 240K (200K)
boost::format 76.0s 888K (780K)
====================== ================== ==========================
The script `bloat-test.py
<https://github.com/cppformat/format-benchmark/blob/master/bloat-test.py>`_
from `format-benchmark <https://github.com/cppformat/format-benchmark>`_
tests compile time and code bloat for nontrivial projects.
It generates 100 translation units and uses ``printf()`` or its alternative
five times in each to simulate a medium sized project. The resulting
executable size and compile time (g++-4.8.1, Ubuntu GNU/Linux 13.10,
best of three) is shown in the following tables.
**Optimized build (-O3)**
====================== ================== ==========================
test name total compile time executable size (stripped)
====================== ================== ==========================
libc printf 3.5s 40K (28K)
std::ostream 14.1s 88K (64K)
format 25.1s 552K (536K)
tinyformat 56.3s 200K (164K)
boost::format 169.4s 1.7M (1.6M)
====================== ================== ==========================
============ =============== ==================== ==================
Method Compile Time, s Executable size, KiB Stripped size, KiB
============ =============== ==================== ==================
printf 2.6 41 30
IOStreams 19.4 92 70
C++ Format 46.8 46 34
tinyformat 64.6 418 386
Boost Format 222.8 990 923
============ =============== ==================== ==================
Printf and std::ostream win here which is not surprising considering
that they are included in the standard library. Tinyformat has somewhat
slower compilation times compared to format. Interestingly optimized
executable size is smaller with tinyformat then with format and for
non-optimized build its the other way around. Boost::format has by far
the largest overheads.
As you can see, C++ Format has 80% less overhead in terms of resulting
code size compared to IOStreams and comes pretty close to ``printf``.
Boost Format has by far the largest overheads.
**Non-optimized build**
============ =============== ==================== ==================
Method Compile Time, s Executable size, KiB Stripped size, KiB
============ =============== ==================== ==================
printf 2.1 41 30
IOStreams 19.7 86 62
C++ Format 47.9 108 86
tinyformat 27.7 234 190
Boost Format 122.6 884 763
============ =============== ==================== ==================
``libc``, ``libstdc++`` and ``libformat`` are all linked as shared
libraries to compare formatting function overhead only. Boost Format
and tinyformat are header-only libraries so they don't provide any
linkage options.
Running the tests
~~~~~~~~~~~~~~~~~
To run the tests you first need to get the format repository with submodules::
Please refer to `Building the library`__ for the instructions on how to build
the library and run the unit tests.
$ git clone --recursive git://github.com/cppformat/format.git
__ http://cppformat.readthedocs.org/en/latest/usage.html#building-the-library
Then go to the format directory and generate Makefiles with
`CMake <http://www.cmake.org/>`__::
Benchmarks reside in a separate repository,
`format-benchmarks <https://github.com/cppformat/format-benchmark>`_,
so to run the benchmarks you first need to clone this repository and
generate Makefiles with CMake::
$ cd format
$ git clone --recursive https://github.com/cppformat/format-benchmark.git
$ cd format-benchmark
$ cmake .
Next use the following commands to run the speed test::
Then you can run the speed test::
$ make speed_test
$ make speed-test
or the bloat test::
$ make bloat_test
Portability
-----------
The format library has been tested on the following systems and compilers:
* 64-bit (amd64) GNU/Linux with GCC 4.6.3, 4.7.2 and Intel C++ Compiler (ICC) 14.0.2
* 32-bit (i386) GNU/Linux with GCC 4.6.3
* Mac OS X with GCC 4.2.1 and Clang 4.2
* 64-bit Windows with Visual C++ 2010
* 32-bit Windows with Visual C++ 2010
$ make bloat-test
License
-------
Copyright (c) 2012, Victor Zverovich
Copyright (c) 2012 - 2015, Victor Zverovich
All rights reserved.
@@ -356,30 +397,31 @@ Documentation License
---------------------
The `Format String Syntax
<http://cppformat.github.io/format#format-string-syntax>`__
<http://cppformat.readthedocs.org/en/latest/syntax.html>`_
section in the documentation is based on the one from Python `string module
documentation <http://docs.python.org/3/library/string.html#module-string>`__
documentation <http://docs.python.org/3/library/string.html#module-string>`_
adapted for the current library. For this reason the documentation is
distributed under the Python Software Foundation license available in
`doc/LICENSE.python
<https://raw.github.com/cppformat/format/master/doc/LICENSE.python>`__.
<https://raw.github.com/cppformat/cppformat/master/doc/LICENSE.python>`_.
Acknowledgments
---------------
The benchmark section of this readme file and the performance tests are taken
from the excellent `tinyformat <https://github.com/c42f/tinyformat>`__ library
from the excellent `tinyformat <https://github.com/c42f/tinyformat>`_ library
written by Chris Foster. Boost Format library is acknowledged transitively
since it had some influence on tinyformat.
Some ideas used in the implementation are borrowed from `Loki
<http://loki-lib.sourceforge.net/>`__ SafeFormat and `Diagnostic API
<http://clang.llvm.org/doxygen/classclang_1_1Diagnostic.html>`__ in
`Clang <http://clang.llvm.org/>`__.
<http://loki-lib.sourceforge.net/>`_ SafeFormat and `Diagnostic API
<http://clang.llvm.org/doxygen/classclang_1_1Diagnostic.html>`_ in
`Clang <http://clang.llvm.org/>`_.
Format string syntax and the documentation are based on Python's `str.format
<http://docs.python.org/2/library/stdtypes.html#str.format>`__.
Thanks `Doug Turnbull <https://github.com/softwaredoug>`__ for his valuable
<http://docs.python.org/2/library/stdtypes.html#str.format>`_.
Thanks `Doug Turnbull <https://github.com/softwaredoug>`_ for his valuable
comments and contribution to the design of the type-safe API and
`Gregory Czajkowski <https://github.com/gcflymoto>`__ for implementing binary
formatting. Thanks `Ruslan Baratov <https://github.com/ruslo>`__ for comprehensive
`comparison of integer formatting algorithms <https://github.com/ruslo/int-dec-format-tests>`__
and useful comments regarding performance.
`Gregory Czajkowski <https://github.com/gcflymoto>`_ for implementing binary
formatting. Thanks `Ruslan Baratov <https://github.com/ruslo>`_ for comprehensive
`comparison of integer formatting algorithms <https://github.com/ruslo/int-dec-format-tests>`_
and useful comments regarding performance, `Boris Kaul <https://github.com/localvoid>`_ for
`C++ counting digits benchmark <https://github.com/localvoid/cxx-benchmark-count-digits>`_.

18
appveyor.yml Normal file
View File

@@ -0,0 +1,18 @@
environment:
CTEST_OUTPUT_ON_FAILURE: 1
matrix:
- BUILD: msvc
CONFIG: Debug
- BUILD: msvc
CONFIG: Release
- BUILD: mingw
CONFIG: Debug
- BUILD: mingw
CONFIG: Release
build_script:
- python support/appveyor-build.py
on_failure:
- appveyor PushArtifact Testing/Temporary/LastTest.log
- appveyor AddTest test

Submodule breathe updated: 1254e9510e...33a6cce142

View File

@@ -1,6 +1,16 @@
add_custom_command(OUTPUT html/index.html
COMMAND doxygen
COMMAND rm -rf html
COMMAND sphinx-build -b html . html
DEPENDS conf.py index.rst)
add_custom_target(doc DEPENDS html/index.html)
if (NOT EXISTS ${FORMAT_SOURCE_DIR}/breathe/breathe)
message(STATUS "Target 'doc' disabled (requires breathe module)")
return ()
endif ()
foreach (program doxygen sphinx-build)
find_program(${program} ${program})
if (NOT ${program})
message(STATUS "Target 'doc' disabled (requires ${program})")
return ()
endif ()
endforeach ()
add_custom_target(doc
COMMAND ${doxygen}
COMMAND ${sphinx-build} -b html . html)

View File

@@ -1,4 +1,4 @@
PROJECT_NAME = Format
PROJECT_NAME = C++ Format
GENERATE_LATEX = NO
GENERATE_MAN = NO
GENERATE_RTF = NO
@@ -12,3 +12,9 @@ GENERATE_XML = YES
XML_OUTPUT = doxyxml
ALIASES = "rst=\verbatim embed:rst"
ALIASES += "endrst=\endverbatim"
PREDEFINED = _WIN32=1 \
FMT_NO_DEPRECATED=1 \
FMT_USE_VARIADIC_TEMPLATES=1 \
FMT_USE_RVALUE_REFERENCES=1
EXCLUDE_SYMBOLS = fmt::internal::* BasicArg FormatParser StringValue \
write_str

16
doc/_static/breathe.css vendored Normal file
View File

@@ -0,0 +1,16 @@
/* -- breathe specific styles ----------------------------------------------- */
/* So enum value descriptions are displayed inline to the item */
.breatheenumvalues li tt + p {
display: inline;
}
/* So parameter descriptions are displayed inline to the item */
.breatheparameterlist li tt + p {
display: inline;
}
.container .breathe-sectiondef {
width: inherit;
}

7
doc/_static/cppformat.css vendored Normal file
View File

@@ -0,0 +1,7 @@
.class dd, .define dd, .function dd {
margin-left: 30px;
}
.public-func dd {
margin-left: 0px;
}

14
doc/_templates/layout.html vendored Normal file
View File

@@ -0,0 +1,14 @@
{% extends "!layout.html" %}
{% block footer %}
{{ super() }}
<!-- Google Analytics -->
<script>
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
ga('create', 'UA-20116650-4', 'cppformat.github.io');
ga('send', 'pageview');
</script>
{% endblock %}

View File

@@ -11,7 +11,7 @@
# All configuration values have a default; values that are commented out
# serve to show the default.
import sys, os
import sys, os, re, subprocess
# If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the
@@ -25,6 +25,9 @@ import sys, os
sys.path.append("../breathe")
if os.environ.get('READTHEDOCS', None) == 'True':
subprocess.call('doxygen')
# Add any Sphinx extension module names here, as strings. They can be extensions
# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
extensions = ['sphinx.ext.ifconfig', 'breathe']
@@ -46,15 +49,25 @@ source_suffix = '.rst'
master_doc = 'index'
# General information about the project.
project = u'format'
copyright = u'1990-2012, Python Software Foundation'
project = u'C++ Format'
copyright = u'2012-2014, Victor Zverovich'
# The version info for the project you're documenting, acts as replacement for
# |version| and |release|, also used in various other places throughout the
# built documents.
#
# The short X.Y version.
version = '@CPACK_PACKAGE_VERSION_MAJOR@.@CPACK_PACKAGE_VERSION_MINOR@'
# Get version from CMakeLists.txt.
version = {}
with open('../CMakeLists.txt') as f:
for line in f:
m = re.match(r'set\(CPACK_PACKAGE_VERSION_([A-Z]+) ([0-9]+)\)', line.strip())
if m:
kind, value = m.groups()
version[kind] = value
version = '{}.{}.{}'.format(version['MAJOR'], version['MINOR'], version['PATCH'])
# The full version, including alpha/beta/rc tags.
release = version
@@ -70,7 +83,7 @@ release = version
# List of patterns, relative to source directory, that match files and
# directories to ignore when looking for source files.
exclude_patterns = []
exclude_patterns = ['sphinx-bootstrap-theme/*']
# The reST default role (used for this markup: `text`) to use for all documents.
#default_role = None
@@ -89,6 +102,10 @@ exclude_patterns = []
# The name of the Pygments (syntax highlighting) style to use.
pygments_style = 'sphinx'
highlight_language = 'c++'
primary_domain = 'cpp'
# A list of ignored prefixes for module index sorting.
#modindex_common_prefix = []
@@ -97,15 +114,30 @@ pygments_style = 'sphinx'
# The theme to use for HTML and HTML Help pages. See the documentation for
# a list of builtin themes.
html_theme = 'sphinxdoc'
html_theme = 'bootstrap'
# Theme options are theme-specific and customize the look and feel of a theme
# further. For a list of options available for each theme, see the
# documentation.
#html_theme_options = {}
html_theme_options = {
# HTML navbar class (Default: "navbar") to attach to <div>.
# For black navbar, do "navbar navbar-inverse"
#'navbar_class': "navbar navbar-inverse",
# Fix navigation bar to top of page?
# Values: "true" (default) or "false"
'navbar_fixed_top': "true",
# Location of link to source.
# Options are "nav" (default), "footer".
'source_link_position': "footer",
# Render the next and previous page links in navbar. (Default: true)
'navbar_sidebarrel': False
}
# Add any paths that contain custom themes here, relative to this directory.
#html_theme_path = []
html_theme_path = ['sphinx-bootstrap-theme']
# The name for this set of Sphinx documents. If None, it defaults to
# "<project> v<release> documentation".
@@ -189,7 +221,7 @@ latex_elements = {
# Grouping the document tree into LaTeX files. List of tuples
# (source start file, target name, title, author, documentclass [howto/manual]).
latex_documents = [
('index', 'format.tex', u'format Documentation',
('index', 'format.tex', u'C++ Format Documentation',
u'Victor Zverovich', 'manual'),
]

View File

@@ -1,427 +1,10 @@
.. highlight:: c++
##########
C++ Format
##########
.. _string-formatting-api:
C++ Format Library API
----------------------
.. doxygenfunction:: fmt::Format(StringRef)
.. doxygenclass:: fmt::BasicWriter
:members:
.. doxygenclass:: fmt::Formatter
:members:
.. doxygenclass:: fmt::NoAction
:members:
.. doxygenclass:: fmt::Write
:members:
.. doxygenclass:: fmt::BasicStringRef
:members:
.. doxygenfunction:: fmt::str
.. doxygenfunction:: fmt::c_str
Write API
---------
.. doxygenfunction:: fmt::bin
.. doxygenfunction:: fmt::oct
.. doxygenfunction:: fmt::hex
.. doxygenfunction:: fmt::hexu
.. doxygenfunction:: fmt::pad
.. _formatstrings:
Format String Syntax
--------------------
The :cpp:func:`fmt::Format()` function and the :cpp:class:`fmt::Formatter`
class share the same syntax for format strings.
Format strings contain "replacement fields" surrounded by curly braces ``{}``.
Anything that is not contained in braces is considered literal text, which is
copied unchanged to the output. If you need to include a brace character in the
literal text, it can be escaped by doubling: ``{{`` and ``}}``.
The grammar for a replacement field is as follows:
.. productionlist:: sf
replacement_field: "{" [`arg_index`] [":" `format_spec`] "}"
arg_index: `integer`
In less formal terms, the replacement field can start with an *arg_index*
that specifies the argument whose value is to be formatted and inserted into
the output instead of the replacement field.
The *arg_index* is optionally followed by a *format_spec*, which is preceded
by a colon ``':'``. These specify a non-default format for the replacement value.
See also the :ref:`formatspec` section.
If the numerical arg_indexes in a format string are 0, 1, 2, ... in sequence,
they can all be omitted (not just some) and the numbers 0, 1, 2, ... will be
automatically inserted in that order.
Some simple format string examples::
"First, thou shalt count to {0}" // References the first argument
"Bring me a {}" // Implicitly references the first argument
"From {} to {}" // Same as "From {0} to {1}"
The *format_spec* field contains a specification of how the value should be
presented, including such details as field width, alignment, padding, decimal
precision and so on. Each value type can define its own "formatting
mini-language" or interpretation of the *format_spec*.
Most built-in types support a common formatting mini-language, which is
described in the next section.
A *format_spec* field can also include nested replacement fields within it.
These nested replacement fields can contain only an argument index;
format specifications are not allowed. Formatting is performed as if the
replacement fields within the format_spec are substituted before the
*format_spec* string is interpreted. This allows the formatting of a value
to be dynamically specified.
See the :ref:`formatexamples` section for some examples.
.. _formatspec:
Format Specification Mini-Language
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
"Format specifications" are used within replacement fields contained within a
format string to define how individual values are presented (see
:ref:`formatstrings`). They can also be passed directly to the
:func:`Format` function. Each formattable type may define how the format
specification is to be interpreted.
Most built-in types implement the following options for format specifications,
although some of the formatting options are only supported by the numeric types.
The general form of a *standard format specifier* is:
.. productionlist:: sf
format_spec: [[`fill`]`align`][`sign`]["#"]["0"][`width`]["." `precision`][`type`]
fill: <a character other than '{' or '}'>
align: "<" | ">" | "=" | "^"
sign: "+" | "-" | " "
width: `integer`
precision: `integer` | "{" `arg_index` "}"
type: `int_type` | "c" | "e" | "E" | "f" | "F" | "g" | "G" | "p" | s"
int_type: "b" | "B" | "d" | "o" | "x" | "X"
The *fill* character can be any character other than '{' or '}'. The presence
of a fill character is signaled by the character following it, which must be
one of the alignment options. If the second character of *format_spec* is not
a valid alignment option, then it is assumed that both the fill character and
the alignment option are absent.
The meaning of the various alignment options is as follows:
+---------+----------------------------------------------------------+
| Option | Meaning |
+=========+==========================================================+
| ``'<'`` | Forces the field to be left-aligned within the available |
| | space (this is the default for most objects). |
+---------+----------------------------------------------------------+
| ``'>'`` | Forces the field to be right-aligned within the |
| | available space (this is the default for numbers). |
+---------+----------------------------------------------------------+
| ``'='`` | Forces the padding to be placed after the sign (if any) |
| | but before the digits. This is used for printing fields |
| | in the form '+000000120'. This alignment option is only |
| | valid for numeric types. |
+---------+----------------------------------------------------------+
| ``'^'`` | Forces the field to be centered within the available |
| | space. |
+---------+----------------------------------------------------------+
Note that unless a minimum field width is defined, the field width will always
be the same size as the data to fill it, so that the alignment option has no
meaning in this case.
The *sign* option is only valid for number types, and can be one of the
following:
+---------+----------------------------------------------------------+
| Option | Meaning |
+=========+==========================================================+
| ``'+'`` | indicates that a sign should be used for both |
| | positive as well as negative numbers. |
+---------+----------------------------------------------------------+
| ``'-'`` | indicates that a sign should be used only for negative |
| | numbers (this is the default behavior). |
+---------+----------------------------------------------------------+
| space | indicates that a leading space should be used on |
| | positive numbers, and a minus sign on negative numbers. |
+---------+----------------------------------------------------------+
The ``'#'`` option causes the "alternate form" to be used for the
conversion. The alternate form is defined differently for different
types. This option is only valid for integer and floating-point types.
For integers, when binary, octal, or hexadecimal output is used, this
option adds the prefix respective ``"0b"`` (``"0B"``), ``"0"``, or
``"0x"`` (``"0X"``) to the output value. Whether the prefix is
lower-case or upper-case is determined by the case of the type
specifier, for example, the prefix ``"0x"`` is used for the type ``'x'``
and ``"0X"`` is used for ``'X'``. For floating-point numbers the
alternate form causes the result of the conversion to always contain a
decimal-point character, even if no digits follow it. Normally, a
decimal-point character appears in the result of these conversions
only if a digit follows it. In addition, for ``'g'`` and ``'G'``
conversions, trailing zeros are not removed from the result.
.. ifconfig:: False
The ``','`` option signals the use of a comma for a thousands separator.
For a locale aware separator, use the ``'n'`` integer presentation type
instead.
*width* is a decimal integer defining the minimum field width. If not
specified, then the field width will be determined by the content.
Preceding the *width* field by a zero (``'0'``) character enables
sign-aware zero-padding for numeric types. This is equivalent to a *fill*
character of ``'0'`` with an *alignment* type of ``'='``.
The *precision* is a decimal number indicating how many digits should be
displayed after the decimal point for a floating-point value formatted with
``'f'`` and ``'F'``, or before and after the decimal point for a floating-point
value formatted with ``'g'`` or ``'G'``. For non-number types the field
indicates the maximum field size - in other words, how many characters will be
used from the field content. The *precision* is not allowed for integer values.
Finally, the *type* determines how the data should be presented.
The available string presentation types are:
+---------+----------------------------------------------------------+
| Type | Meaning |
+=========+==========================================================+
| ``'s'`` | String format. This is the default type for strings and |
| | may be omitted. |
+---------+----------------------------------------------------------+
| none | The same as ``'s'``. |
+---------+----------------------------------------------------------+
The available character presentation types are:
+---------+----------------------------------------------------------+
| Type | Meaning |
+=========+==========================================================+
| ``'c'`` | Character format. This is the default type for |
| | characters and may be omitted. |
+---------+----------------------------------------------------------+
| none | The same as ``'c'``. |
+---------+----------------------------------------------------------+
The available integer presentation types are:
+---------+----------------------------------------------------------+
| Type | Meaning |
+=========+==========================================================+
| ``'b'`` | Binary format. Outputs the number in base 2. Using the |
| | ``'#'`` option with this type adds the prefix ``"0b"`` |
| | to the output value. |
+---------+----------------------------------------------------------+
| ``'B'`` | Binary format. Outputs the number in base 2. Using the |
| | ``'#'`` option with this type adds the prefix ``"0B"`` |
| | to the output value. |
+---------+----------------------------------------------------------+
| ``'d'`` | Decimal integer. Outputs the number in base 10. |
+---------+----------------------------------------------------------+
| ``'o'`` | Octal format. Outputs the number in base 8. |
+---------+----------------------------------------------------------+
| ``'x'`` | Hex format. Outputs the number in base 16, using |
| | lower-case letters for the digits above 9. Using the |
| | ``'#'`` option with this type adds the prefix ``"0x"`` |
| | to the output value. |
+---------+----------------------------------------------------------+
| ``'X'`` | Hex format. Outputs the number in base 16, using |
| | upper-case letters for the digits above 9. Using the |
| | ``'#'`` option with this type adds the prefix ``"0X"`` |
| | to the output value. |
+---------+----------------------------------------------------------+
| none | The same as ``'d'``. |
+---------+----------------------------------------------------------+
The available presentation types for floating-point values are:
+---------+----------------------------------------------------------+
| Type | Meaning |
+=========+==========================================================+
| ``'e'`` | Exponent notation. Prints the number in scientific |
| | notation using the letter 'e' to indicate the exponent. |
+---------+----------------------------------------------------------+
| ``'E'`` | Exponent notation. Same as ``'e'`` except it uses an |
| | upper case 'E' as the separator character. |
+---------+----------------------------------------------------------+
| ``'f'`` | Fixed point. Displays the number as a fixed-point |
| | number. |
+---------+----------------------------------------------------------+
| ``'F'`` | Fixed point. Same as ``'f'``, but converts ``nan`` to |
| | ``NAN`` and ``inf`` to ``INF``. |
+---------+----------------------------------------------------------+
| ``'g'`` | General format. For a given precision ``p >= 1``, |
| | this rounds the number to ``p`` significant digits and |
| | then formats the result in either fixed-point format |
| | or in scientific notation, depending on its magnitude. |
| | |
| | A precision of ``0`` is treated as equivalent to a |
| | precision of ``1``. |
+---------+----------------------------------------------------------+
| ``'G'`` | General format. Same as ``'g'`` except switches to |
| | ``'E'`` if the number gets too large. The |
| | representations of infinity and NaN are uppercased, too. |
+---------+----------------------------------------------------------+
| none | The same as ``'g'``. |
+---------+----------------------------------------------------------+
.. ifconfig:: False
+---------+----------------------------------------------------------+
| | The precise rules are as follows: suppose that the |
| | result formatted with presentation type ``'e'`` and |
| | precision ``p-1`` would have exponent ``exp``. Then |
| | if ``-4 <= exp < p``, the number is formatted |
| | with presentation type ``'f'`` and precision |
| | ``p-1-exp``. Otherwise, the number is formatted |
| | with presentation type ``'e'`` and precision ``p-1``. |
| | In both cases insignificant trailing zeros are removed |
| | from the significand, and the decimal point is also |
| | removed if there are no remaining digits following it. |
| | |
| | Positive and negative infinity, positive and negative |
| | zero, and nans, are formatted as ``inf``, ``-inf``, |
| | ``0``, ``-0`` and ``nan`` respectively, regardless of |
| | the precision. |
| | |
+---------+----------------------------------------------------------+
The available presentation types for pointers are:
+---------+----------------------------------------------------------+
| Type | Meaning |
+=========+==========================================================+
| ``'p'`` | Pointer format. This is the default type for |
| | pointers and may be omitted. |
+---------+----------------------------------------------------------+
| none | The same as ``'p'``. |
+---------+----------------------------------------------------------+
.. _formatexamples:
Format examples
^^^^^^^^^^^^^^^
This section contains examples of the format syntax and comparison with
the printf formatting.
In most of the cases the syntax is similar to the printf formatting, with the
addition of the ``{}`` and with ``:`` used instead of ``%``.
For example, ``"%03.2f"`` can be translated to ``"{:03.2f}"``.
The new format syntax also supports new and different options, shown in the
following examples.
Accessing arguments by position::
Format("{0}, {1}, {2}") << 'a' << 'b' << 'c';
// Result: "a, b, c"
Format("{}, {}, {}") << 'a' << 'b' << 'c';
// Result: "a, b, c"
Format("{2}, {1}, {0}") << 'a' << 'b' << 'c';
// Result: "c, b, a"
Format("{0}{1}{0}") << "abra" << "cad"; // arguments' indices can be repeated
// Result: "abracadabra"
Aligning the text and specifying a width::
Format("{:<30}") << "left aligned";
// Result: "left aligned "
Format("{:>30}") << "right aligned"
// Result: " right aligned"
Format("{:^30}") << "centered"
// Result: " centered "
Format("{:*^30}") << "centered" // use '*' as a fill char
// Result: "***********centered***********"
Replacing ``%+f``, ``%-f``, and ``% f`` and specifying a sign::
Format("{:+f}; {:+f}") << 3.14 << -3.14; // show it always
// Result: "+3.140000; -3.140000"
Format("{: f}; {: f}") << 3.14 << -3.14; // show a space for positive numbers
// Result: " 3.140000; -3.140000"
Format("{:-f}; {:-f}") << 3.14 << -3.14; // show only the minus -- same as '{:f}; {:f}'
// Result: "3.140000; -3.140000"
Replacing ``%x`` and ``%o`` and converting the value to different bases::
Format("int: {0:d}; hex: {0:x}; oct: {0:o}; bin: {0:b}") << 42;
// Result: "int: 42; hex: 2a; oct: 52; bin: 101010"
// with 0x or 0 or 0b as prefix:
Format("int: {0:d}; hex: {0:#x}; oct: {0:#o}; bin: {0:#b}") << 42;
// Result: "int: 42; hex: 0x2a; oct: 052; bin: 0b101010"
.. ifconfig:: False
Using the comma as a thousands separator::
Format("{:,}") << 1234567890)
'1,234,567,890'
Expressing a percentage::
>>> points = 19
>>> total = 22
Format("Correct answers: {:.2%}") << points/total)
'Correct answers: 86.36%'
Using type-specific formatting::
>>> import datetime
>>> d = datetime.datetime(2010, 7, 4, 12, 15, 58)
Format("{:%Y-%m-%d %H:%M:%S}") << d)
'2010-07-04 12:15:58'
Nesting arguments and more complex examples::
>>> for align, text in zip('<^>', ['left', 'center', 'right']):
... '{0:{fill}{align}16}") << text, fill=align, align=align)
...
'left<<<<<<<<<<<<'
'^^^^^center^^^^^'
'>>>>>>>>>>>right'
>>>
>>> octets = [192, 168, 0, 1]
Format("{:02X}{:02X}{:02X}{:02X}") << *octets)
'C0A80001'
>>> int(_, 16)
3232235521
>>>
>>> width = 5
>>> for num in range(5,12):
... for base in 'dXob':
... print('{0:{width}{base}}") << num, base=base, width=width), end=' ')
... print()
...
5 5 5 101
6 6 6 110
7 7 7 111
8 8 10 1000
9 9 11 1001
10 A 12 1010
11 B 13 1011
.. toctree::
:maxdepth: 2
usage
reference
syntax

116
doc/reference.rst Normal file
View File

@@ -0,0 +1,116 @@
.. cpp:namespace:: fmt
.. _string-formatting-api:
*************
API Reference
*************
All functions and classes provided by the C++ Format library reside
in namespace ``fmt`` and macros have prefix ``FMT_``. For brevity the
namespace is usually omitted in examples.
Formatting functions
====================
The following functions use :ref:`format string syntax <syntax>` similar
to the one used by Python's `str.format
<http://docs.python.org/3/library/stdtypes.html#str.format>`_ function.
They take *format_str* and *args* as arguments.
*format_str* is a format string that contains literal text and replacement
fields surrounded by braces ``{}``. The fields are replaced with formatted
arguments in the resulting string.
*args* is an argument list representing arbitrary arguments.
.. _format:
.. doxygenfunction:: format(StringRef, ArgList)
.. _print:
.. doxygenfunction:: print(StringRef, ArgList)
.. doxygenfunction:: print(std::FILE*, StringRef, ArgList)
.. doxygenfunction:: print(std::ostream&, StringRef, ArgList)
Printf formatting functions
===========================
The following functions use `printf format string syntax
<http://pubs.opengroup.org/onlinepubs/009695399/functions/fprintf.html>`_ with
a POSIX extension for positional arguments.
.. doxygenfunction:: printf(StringRef, ArgList)
.. doxygenfunction:: fprintf(std::FILE*, StringRef, ArgList)
.. doxygenfunction:: sprintf(StringRef, ArgList)
Write API
=========
.. doxygenclass:: fmt::BasicWriter
:members:
.. doxygenclass:: fmt::BasicMemoryWriter
:members:
.. doxygenclass:: fmt::BasicArrayWriter
:members:
.. doxygenfunction:: bin
.. doxygenfunction:: oct
.. doxygenfunction:: hex
.. doxygenfunction:: hexu
.. doxygenfunction:: pad(int, unsigned int, Char)
Utilities
=========
.. doxygendefine:: FMT_VARIADIC
.. doxygenclass:: fmt::ArgList
:members:
.. doxygenclass:: fmt::BasicStringRef
:members:
System Errors
=============
.. doxygenclass:: fmt::SystemError
:members:
.. doxygenclass:: fmt::WindowsError
:members:
.. _formatstrings:
Custom allocators
=================
The C++ Format library supports custom dynamic memory allocators.
A custom allocator class can be specified as a template argument to
:class:`fmt::BasicMemoryWriter`::
typedef fmt::BasicMemoryWriter<char, CustomAllocator> CustomMemoryWriter;
It is also possible to write a formatting function that uses a custom
allocator::
typedef std::basic_string<char, std::char_traits<char>, CustomAllocator> CustomString;
CustomString format(CustomAllocator alloc, fmt::StringRef format_str,
fmt::ArgList args) {
CustomMemoryWriter writer(alloc);
writer.write(format_str, args);
return CustomString(writer.data(), writer.size(), alloc);
}
FMT_VARIADIC(CustomString, format, CustomAllocator, fmt::StringRef)

391
doc/syntax.rst Normal file
View File

@@ -0,0 +1,391 @@
.. _syntax:
********************
Format String Syntax
********************
Formatting functions such as :ref:`fmt::format() <format>` and :ref:`fmt::print() <print>`
use the same format string syntax described in this section.
Format strings contain "replacement fields" surrounded by curly braces ``{}``.
Anything that is not contained in braces is considered literal text, which is
copied unchanged to the output. If you need to include a brace character in the
literal text, it can be escaped by doubling: ``{{`` and ``}}``.
The grammar for a replacement field is as follows:
.. productionlist:: sf
replacement_field: "{" [`arg_index`] [":" `format_spec`] "}"
arg_index: `integer`
In less formal terms, the replacement field can start with an *arg_index*
that specifies the argument whose value is to be formatted and inserted into
the output instead of the replacement field.
The *arg_index* is optionally followed by a *format_spec*, which is preceded
by a colon ``':'``. These specify a non-default format for the replacement value.
See also the :ref:`formatspec` section.
If the numerical arg_indexes in a format string are 0, 1, 2, ... in sequence,
they can all be omitted (not just some) and the numbers 0, 1, 2, ... will be
automatically inserted in that order.
Some simple format string examples::
"First, thou shalt count to {0}" // References the first argument
"Bring me a {}" // Implicitly references the first argument
"From {} to {}" // Same as "From {0} to {1}"
The *format_spec* field contains a specification of how the value should be
presented, including such details as field width, alignment, padding, decimal
precision and so on. Each value type can define its own "formatting
mini-language" or interpretation of the *format_spec*.
Most built-in types support a common formatting mini-language, which is
described in the next section.
A *format_spec* field can also include nested replacement fields within it.
These nested replacement fields can contain only an argument index;
format specifications are not allowed. Formatting is performed as if the
replacement fields within the format_spec are substituted before the
*format_spec* string is interpreted. This allows the formatting of a value
to be dynamically specified.
See the :ref:`formatexamples` section for some examples.
.. _formatspec:
Format Specification Mini-Language
==================================
"Format specifications" are used within replacement fields contained within a
format string to define how individual values are presented (see
:ref:`syntax`). Each formattable type may define how the format
specification is to be interpreted.
Most built-in types implement the following options for format specifications,
although some of the formatting options are only supported by the numeric types.
The general form of a *standard format specifier* is:
.. productionlist:: sf
format_spec: [[`fill`]`align`][`sign`]["#"]["0"][`width`]["." `precision`][`type`]
fill: <a character other than '{' or '}'>
align: "<" | ">" | "=" | "^"
sign: "+" | "-" | " "
width: `integer`
precision: `integer` | "{" `arg_index` "}"
type: `int_type` | "c" | "e" | "E" | "f" | "F" | "g" | "G" | "p" | "s"
int_type: "b" | "B" | "d" | "o" | "x" | "X"
The *fill* character can be any character other than '{' or '}'. The presence
of a fill character is signaled by the character following it, which must be
one of the alignment options. If the second character of *format_spec* is not
a valid alignment option, then it is assumed that both the fill character and
the alignment option are absent.
The meaning of the various alignment options is as follows:
+---------+----------------------------------------------------------+
| Option | Meaning |
+=========+==========================================================+
| ``'<'`` | Forces the field to be left-aligned within the available |
| | space (this is the default for most objects). |
+---------+----------------------------------------------------------+
| ``'>'`` | Forces the field to be right-aligned within the |
| | available space (this is the default for numbers). |
+---------+----------------------------------------------------------+
| ``'='`` | Forces the padding to be placed after the sign (if any) |
| | but before the digits. This is used for printing fields |
| | in the form '+000000120'. This alignment option is only |
| | valid for numeric types. |
+---------+----------------------------------------------------------+
| ``'^'`` | Forces the field to be centered within the available |
| | space. |
+---------+----------------------------------------------------------+
Note that unless a minimum field width is defined, the field width will always
be the same size as the data to fill it, so that the alignment option has no
meaning in this case.
The *sign* option is only valid for number types, and can be one of the
following:
+---------+----------------------------------------------------------+
| Option | Meaning |
+=========+==========================================================+
| ``'+'`` | indicates that a sign should be used for both |
| | positive as well as negative numbers. |
+---------+----------------------------------------------------------+
| ``'-'`` | indicates that a sign should be used only for negative |
| | numbers (this is the default behavior). |
+---------+----------------------------------------------------------+
| space | indicates that a leading space should be used on |
| | positive numbers, and a minus sign on negative numbers. |
+---------+----------------------------------------------------------+
The ``'#'`` option causes the "alternate form" to be used for the
conversion. The alternate form is defined differently for different
types. This option is only valid for integer and floating-point types.
For integers, when binary, octal, or hexadecimal output is used, this
option adds the prefix respective ``"0b"`` (``"0B"``), ``"0"``, or
``"0x"`` (``"0X"``) to the output value. Whether the prefix is
lower-case or upper-case is determined by the case of the type
specifier, for example, the prefix ``"0x"`` is used for the type ``'x'``
and ``"0X"`` is used for ``'X'``. For floating-point numbers the
alternate form causes the result of the conversion to always contain a
decimal-point character, even if no digits follow it. Normally, a
decimal-point character appears in the result of these conversions
only if a digit follows it. In addition, for ``'g'`` and ``'G'``
conversions, trailing zeros are not removed from the result.
.. ifconfig:: False
The ``','`` option signals the use of a comma for a thousands separator.
For a locale aware separator, use the ``'n'`` integer presentation type
instead.
*width* is a decimal integer defining the minimum field width. If not
specified, then the field width will be determined by the content.
Preceding the *width* field by a zero (``'0'``) character enables
sign-aware zero-padding for numeric types. This is equivalent to a *fill*
character of ``'0'`` with an *alignment* type of ``'='``.
The *precision* is a decimal number indicating how many digits should be
displayed after the decimal point for a floating-point value formatted with
``'f'`` and ``'F'``, or before and after the decimal point for a floating-point
value formatted with ``'g'`` or ``'G'``. For non-number types the field
indicates the maximum field size - in other words, how many characters will be
used from the field content. The *precision* is not allowed for integer values
or pointers.
Finally, the *type* determines how the data should be presented.
The available string presentation types are:
+---------+----------------------------------------------------------+
| Type | Meaning |
+=========+==========================================================+
| ``'s'`` | String format. This is the default type for strings and |
| | may be omitted. |
+---------+----------------------------------------------------------+
| none | The same as ``'s'``. |
+---------+----------------------------------------------------------+
The available character presentation types are:
+---------+----------------------------------------------------------+
| Type | Meaning |
+=========+==========================================================+
| ``'c'`` | Character format. This is the default type for |
| | characters and may be omitted. |
+---------+----------------------------------------------------------+
| none | The same as ``'c'``. |
+---------+----------------------------------------------------------+
The available integer presentation types are:
+---------+----------------------------------------------------------+
| Type | Meaning |
+=========+==========================================================+
| ``'b'`` | Binary format. Outputs the number in base 2. Using the |
| | ``'#'`` option with this type adds the prefix ``"0b"`` |
| | to the output value. |
+---------+----------------------------------------------------------+
| ``'B'`` | Binary format. Outputs the number in base 2. Using the |
| | ``'#'`` option with this type adds the prefix ``"0B"`` |
| | to the output value. |
+---------+----------------------------------------------------------+
| ``'d'`` | Decimal integer. Outputs the number in base 10. |
+---------+----------------------------------------------------------+
| ``'o'`` | Octal format. Outputs the number in base 8. |
+---------+----------------------------------------------------------+
| ``'x'`` | Hex format. Outputs the number in base 16, using |
| | lower-case letters for the digits above 9. Using the |
| | ``'#'`` option with this type adds the prefix ``"0x"`` |
| | to the output value. |
+---------+----------------------------------------------------------+
| ``'X'`` | Hex format. Outputs the number in base 16, using |
| | upper-case letters for the digits above 9. Using the |
| | ``'#'`` option with this type adds the prefix ``"0X"`` |
| | to the output value. |
+---------+----------------------------------------------------------+
| none | The same as ``'d'``. |
+---------+----------------------------------------------------------+
The available presentation types for floating-point values are:
+---------+----------------------------------------------------------+
| Type | Meaning |
+=========+==========================================================+
| ``'a'`` | Hexadecimal floating point format. Prints the number in |
| | base 16 with prefix ``"0x"`` and lower-case letters for |
| | digits above 9. Uses 'p' to indicate the exponent. |
+---------+----------------------------------------------------------+
| ``'A'`` | Same as ``'a'`` except it uses upper-case letters for |
| | the prefix, digits above 9 and to indicate the exponent. |
+---------+----------------------------------------------------------+
| ``'e'`` | Exponent notation. Prints the number in scientific |
| | notation using the letter 'e' to indicate the exponent. |
+---------+----------------------------------------------------------+
| ``'E'`` | Exponent notation. Same as ``'e'`` except it uses an |
| | upper-case 'E' as the separator character. |
+---------+----------------------------------------------------------+
| ``'f'`` | Fixed point. Displays the number as a fixed-point |
| | number. |
+---------+----------------------------------------------------------+
| ``'F'`` | Fixed point. Same as ``'f'``, but converts ``nan`` to |
| | ``NAN`` and ``inf`` to ``INF``. |
+---------+----------------------------------------------------------+
| ``'g'`` | General format. For a given precision ``p >= 1``, |
| | this rounds the number to ``p`` significant digits and |
| | then formats the result in either fixed-point format |
| | or in scientific notation, depending on its magnitude. |
| | |
| | A precision of ``0`` is treated as equivalent to a |
| | precision of ``1``. |
+---------+----------------------------------------------------------+
| ``'G'`` | General format. Same as ``'g'`` except switches to |
| | ``'E'`` if the number gets too large. The |
| | representations of infinity and NaN are uppercased, too. |
+---------+----------------------------------------------------------+
| none | The same as ``'g'``. |
+---------+----------------------------------------------------------+
.. ifconfig:: False
+---------+----------------------------------------------------------+
| | The precise rules are as follows: suppose that the |
| | result formatted with presentation type ``'e'`` and |
| | precision ``p-1`` would have exponent ``exp``. Then |
| | if ``-4 <= exp < p``, the number is formatted |
| | with presentation type ``'f'`` and precision |
| | ``p-1-exp``. Otherwise, the number is formatted |
| | with presentation type ``'e'`` and precision ``p-1``. |
| | In both cases insignificant trailing zeros are removed |
| | from the significand, and the decimal point is also |
| | removed if there are no remaining digits following it. |
| | |
| | Positive and negative infinity, positive and negative |
| | zero, and nans, are formatted as ``inf``, ``-inf``, |
| | ``0``, ``-0`` and ``nan`` respectively, regardless of |
| | the precision. |
| | |
+---------+----------------------------------------------------------+
The available presentation types for pointers are:
+---------+----------------------------------------------------------+
| Type | Meaning |
+=========+==========================================================+
| ``'p'`` | Pointer format. This is the default type for |
| | pointers and may be omitted. |
+---------+----------------------------------------------------------+
| none | The same as ``'p'``. |
+---------+----------------------------------------------------------+
.. _formatexamples:
Format examples
===============
This section contains examples of the format syntax and comparison with
the printf formatting.
In most of the cases the syntax is similar to the printf formatting, with the
addition of the ``{}`` and with ``:`` used instead of ``%``.
For example, ``"%03.2f"`` can be translated to ``"{:03.2f}"``.
The new format syntax also supports new and different options, shown in the
following examples.
Accessing arguments by position::
format("{0}, {1}, {2}", 'a', 'b', 'c');
// Result: "a, b, c"
format("{}, {}, {}", 'a', 'b', 'c');
// Result: "a, b, c"
format("{2}, {1}, {0}", 'a', 'b', 'c');
// Result: "c, b, a"
format("{0}{1}{0}", "abra", "cad"); // arguments' indices can be repeated
// Result: "abracadabra"
Aligning the text and specifying a width::
format("{:<30}", "left aligned");
// Result: "left aligned "
format("{:>30}", "right aligned");
// Result: " right aligned"
format("{:^30}", "centered");
// Result: " centered "
format("{:*^30}", "centered"); // use '*' as a fill char
// Result: "***********centered***********"
Replacing ``%+f``, ``%-f``, and ``% f`` and specifying a sign::
format("{:+f}; {:+f}", 3.14, -3.14); // show it always
// Result: "+3.140000; -3.140000"
format("{: f}; {: f}", 3.14, -3.14); // show a space for positive numbers
// Result: " 3.140000; -3.140000"
format("{:-f}; {:-f}", 3.14, -3.14); // show only the minus -- same as '{:f}; {:f}'
// Result: "3.140000; -3.140000"
Replacing ``%x`` and ``%o`` and converting the value to different bases::
format("int: {0:d}; hex: {0:x}; oct: {0:o}; bin: {0:b}", 42);
// Result: "int: 42; hex: 2a; oct: 52; bin: 101010"
// with 0x or 0 or 0b as prefix:
format("int: {0:d}; hex: {0:#x}; oct: {0:#o}; bin: {0:#b}", 42);
// Result: "int: 42; hex: 0x2a; oct: 052; bin: 0b101010"
.. ifconfig:: False
Using the comma as a thousands separator::
format("{:,}", 1234567890);
'1,234,567,890'
Expressing a percentage::
>>> points = 19
>>> total = 22
Format("Correct answers: {:.2%}") << points/total)
'Correct answers: 86.36%'
Using type-specific formatting::
>>> import datetime
>>> d = datetime.datetime(2010, 7, 4, 12, 15, 58)
Format("{:%Y-%m-%d %H:%M:%S}") << d)
'2010-07-04 12:15:58'
Nesting arguments and more complex examples::
>>> for align, text in zip('<^>', ['left', 'center', 'right']):
... '{0:{fill}{align}16}") << text, fill=align, align=align)
...
'left<<<<<<<<<<<<'
'^^^^^center^^^^^'
'>>>>>>>>>>>right'
>>>
>>> octets = [192, 168, 0, 1]
Format("{:02X}{:02X}{:02X}{:02X}") << *octets)
'C0A80001'
>>> int(_, 16)
3232235521
>>>
>>> width = 5
>>> for num in range(5,12):
... for base in 'dXob':
... print('{0:{width}{base}}") << num, base=base, width=width), end=' ')
... print()
...
5 5 5 101
6 6 6 110
7 7 7 111
8 8 10 1000
9 9 11 1001
10 A 12 1010
11 B 13 1011

66
doc/usage.rst Normal file
View File

@@ -0,0 +1,66 @@
*****
Usage
*****
To use the C++ Format library, add :file:`format.h` and :file:`format.cc` from
a `release archive <https://github.com/cppformat/cppformat/releases/latest>`_
or the `Git repository <https://github.com/cppformat/cppformat>`_ to your project.
Alternatively, you can :ref:`build the library with CMake <building>`.
If you are using Visual C++ with precompiled headers, you might need to add
the line ::
#include "stdafx.h"
before other includes in :file:`format.cc`.
.. _building:
Building the library
====================
The included `CMake build script`__ can be used to build the C++ Format
library on a wide range of platforms. CMake is freely available for
download from http://www.cmake.org/download/.
__ https://github.com/cppformat/cppformat/blob/master/CMakeLists.txt
CMake works by generating native makefiles or project files that can
be used in the compiler environment of your choice. The typical
workflow starts with::
mkdir build # Create a directory to hold the build output.
cd build
cmake <path/to/cppformat> # Generate native build scripts.
where :file:`{<path/to/cppformat>}` is a path to the ``cppformat`` repository.
If you are on a \*nix system, you should now see a Makefile in the
current directory. Now you can build C++ Format by running :command:`make`.
Once the library has been built you can invoke :command:`make test` to run
the tests.
If you use Windows and have Vistual Studio installed, a :file:`FORMAT.sln`
file and several :file:`.vcproj` files will be created. You can then build them
using Visual Studio or msbuild.
On Mac OS X with Xcode installed, an :file:`.xcodeproj` file will be generated.
To build a `shared library`__ set the ``BUILD_SHARED_LIBS`` CMake variable to
``TRUE``::
cmake -DBUILD_SHARED_LIBS=TRUE ...
__ http://en.wikipedia.org/wiki/Library_%28computing%29#Shared_libraries
Android NDK
===========
C++ Format provides `Android.mk file`__ that can be used to build the library
with `Android NDK <https://developer.android.com/tools/sdk/ndk/index.html>`_.
For an example of using C++ Format with Android NDK, see the
`android-ndk-example <https://github.com/cppformat/android-ndk-example>`_
repository.
__ https://github.com/cppformat/cppformat/blob/master/Android.mk

Submodule format-benchmark deleted from 1b2df8bc3d

File diff suppressed because it is too large Load Diff

1514
format.cc

File diff suppressed because it is too large Load Diff

2861
format.h

File diff suppressed because it is too large Load Diff

11443
gmock/gmock-gtest-all.cc Normal file

File diff suppressed because it is too large Load Diff

14198
gmock/gmock/gmock.h Normal file

File diff suppressed because it is too large Load Diff

232
gmock/gtest/gtest-spi.h Normal file
View File

@@ -0,0 +1,232 @@
// Copyright 2007, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Author: wan@google.com (Zhanyong Wan)
//
// Utilities for testing Google Test itself and code that uses Google Test
// (e.g. frameworks built on top of Google Test).
#ifndef GTEST_INCLUDE_GTEST_GTEST_SPI_H_
#define GTEST_INCLUDE_GTEST_GTEST_SPI_H_
#include "gtest/gtest.h"
namespace testing {
// This helper class can be used to mock out Google Test failure reporting
// so that we can test Google Test or code that builds on Google Test.
//
// An object of this class appends a TestPartResult object to the
// TestPartResultArray object given in the constructor whenever a Google Test
// failure is reported. It can either intercept only failures that are
// generated in the same thread that created this object or it can intercept
// all generated failures. The scope of this mock object can be controlled with
// the second argument to the two arguments constructor.
class GTEST_API_ ScopedFakeTestPartResultReporter
: public TestPartResultReporterInterface {
public:
// The two possible mocking modes of this object.
enum InterceptMode {
INTERCEPT_ONLY_CURRENT_THREAD, // Intercepts only thread local failures.
INTERCEPT_ALL_THREADS // Intercepts all failures.
};
// The c'tor sets this object as the test part result reporter used
// by Google Test. The 'result' parameter specifies where to report the
// results. This reporter will only catch failures generated in the current
// thread. DEPRECATED
explicit ScopedFakeTestPartResultReporter(TestPartResultArray* result);
// Same as above, but you can choose the interception scope of this object.
ScopedFakeTestPartResultReporter(InterceptMode intercept_mode,
TestPartResultArray* result);
// The d'tor restores the previous test part result reporter.
virtual ~ScopedFakeTestPartResultReporter();
// Appends the TestPartResult object to the TestPartResultArray
// received in the constructor.
//
// This method is from the TestPartResultReporterInterface
// interface.
virtual void ReportTestPartResult(const TestPartResult& result);
private:
void Init();
const InterceptMode intercept_mode_;
TestPartResultReporterInterface* old_reporter_;
TestPartResultArray* const result_;
GTEST_DISALLOW_COPY_AND_ASSIGN_(ScopedFakeTestPartResultReporter);
};
namespace internal {
// A helper class for implementing EXPECT_FATAL_FAILURE() and
// EXPECT_NONFATAL_FAILURE(). Its destructor verifies that the given
// TestPartResultArray contains exactly one failure that has the given
// type and contains the given substring. If that's not the case, a
// non-fatal failure will be generated.
class GTEST_API_ SingleFailureChecker {
public:
// The constructor remembers the arguments.
SingleFailureChecker(const TestPartResultArray* results,
TestPartResult::Type type,
const string& substr);
~SingleFailureChecker();
private:
const TestPartResultArray* const results_;
const TestPartResult::Type type_;
const string substr_;
GTEST_DISALLOW_COPY_AND_ASSIGN_(SingleFailureChecker);
};
} // namespace internal
} // namespace testing
// A set of macros for testing Google Test assertions or code that's expected
// to generate Google Test fatal failures. It verifies that the given
// statement will cause exactly one fatal Google Test failure with 'substr'
// being part of the failure message.
//
// There are two different versions of this macro. EXPECT_FATAL_FAILURE only
// affects and considers failures generated in the current thread and
// EXPECT_FATAL_FAILURE_ON_ALL_THREADS does the same but for all threads.
//
// The verification of the assertion is done correctly even when the statement
// throws an exception or aborts the current function.
//
// Known restrictions:
// - 'statement' cannot reference local non-static variables or
// non-static members of the current object.
// - 'statement' cannot return a value.
// - You cannot stream a failure message to this macro.
//
// Note that even though the implementations of the following two
// macros are much alike, we cannot refactor them to use a common
// helper macro, due to some peculiarity in how the preprocessor
// works. The AcceptsMacroThatExpandsToUnprotectedComma test in
// gtest_unittest.cc will fail to compile if we do that.
#define EXPECT_FATAL_FAILURE(statement, substr) \
do { \
class GTestExpectFatalFailureHelper {\
public:\
static void Execute() { statement; }\
};\
::testing::TestPartResultArray gtest_failures;\
::testing::internal::SingleFailureChecker gtest_checker(\
&gtest_failures, ::testing::TestPartResult::kFatalFailure, (substr));\
{\
::testing::ScopedFakeTestPartResultReporter gtest_reporter(\
::testing::ScopedFakeTestPartResultReporter:: \
INTERCEPT_ONLY_CURRENT_THREAD, &gtest_failures);\
GTestExpectFatalFailureHelper::Execute();\
}\
} while (::testing::internal::AlwaysFalse())
#define EXPECT_FATAL_FAILURE_ON_ALL_THREADS(statement, substr) \
do { \
class GTestExpectFatalFailureHelper {\
public:\
static void Execute() { statement; }\
};\
::testing::TestPartResultArray gtest_failures;\
::testing::internal::SingleFailureChecker gtest_checker(\
&gtest_failures, ::testing::TestPartResult::kFatalFailure, (substr));\
{\
::testing::ScopedFakeTestPartResultReporter gtest_reporter(\
::testing::ScopedFakeTestPartResultReporter:: \
INTERCEPT_ALL_THREADS, &gtest_failures);\
GTestExpectFatalFailureHelper::Execute();\
}\
} while (::testing::internal::AlwaysFalse())
// A macro for testing Google Test assertions or code that's expected to
// generate Google Test non-fatal failures. It asserts that the given
// statement will cause exactly one non-fatal Google Test failure with 'substr'
// being part of the failure message.
//
// There are two different versions of this macro. EXPECT_NONFATAL_FAILURE only
// affects and considers failures generated in the current thread and
// EXPECT_NONFATAL_FAILURE_ON_ALL_THREADS does the same but for all threads.
//
// 'statement' is allowed to reference local variables and members of
// the current object.
//
// The verification of the assertion is done correctly even when the statement
// throws an exception or aborts the current function.
//
// Known restrictions:
// - You cannot stream a failure message to this macro.
//
// Note that even though the implementations of the following two
// macros are much alike, we cannot refactor them to use a common
// helper macro, due to some peculiarity in how the preprocessor
// works. If we do that, the code won't compile when the user gives
// EXPECT_NONFATAL_FAILURE() a statement that contains a macro that
// expands to code containing an unprotected comma. The
// AcceptsMacroThatExpandsToUnprotectedComma test in gtest_unittest.cc
// catches that.
//
// For the same reason, we have to write
// if (::testing::internal::AlwaysTrue()) { statement; }
// instead of
// GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement)
// to avoid an MSVC warning on unreachable code.
#define EXPECT_NONFATAL_FAILURE(statement, substr) \
do {\
::testing::TestPartResultArray gtest_failures;\
::testing::internal::SingleFailureChecker gtest_checker(\
&gtest_failures, ::testing::TestPartResult::kNonFatalFailure, \
(substr));\
{\
::testing::ScopedFakeTestPartResultReporter gtest_reporter(\
::testing::ScopedFakeTestPartResultReporter:: \
INTERCEPT_ONLY_CURRENT_THREAD, &gtest_failures);\
if (::testing::internal::AlwaysTrue()) { statement; }\
}\
} while (::testing::internal::AlwaysFalse())
#define EXPECT_NONFATAL_FAILURE_ON_ALL_THREADS(statement, substr) \
do {\
::testing::TestPartResultArray gtest_failures;\
::testing::internal::SingleFailureChecker gtest_checker(\
&gtest_failures, ::testing::TestPartResult::kNonFatalFailure, \
(substr));\
{\
::testing::ScopedFakeTestPartResultReporter gtest_reporter(\
::testing::ScopedFakeTestPartResultReporter::INTERCEPT_ALL_THREADS, \
&gtest_failures);\
if (::testing::internal::AlwaysTrue()) { statement; }\
}\
} while (::testing::internal::AlwaysFalse())
#endif // GTEST_INCLUDE_GTEST_GTEST_SPI_H_

20061
gmock/gtest/gtest.h Normal file

File diff suppressed because it is too large Load Diff

1
gtest

Submodule gtest deleted from 9f357d549d

242
posix.cc Normal file
View File

@@ -0,0 +1,242 @@
/*
A C++ interface to POSIX functions.
Copyright (c) 2014 - 2015, Victor Zverovich
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
// Disable bogus MSVC warnings.
#ifndef _CRT_SECURE_NO_WARNINGS
# define _CRT_SECURE_NO_WARNINGS
#endif
#include "posix.h"
#include <limits.h>
#include <sys/types.h>
#include <sys/stat.h>
#ifndef _WIN32
# include <unistd.h>
#else
# include <windows.h>
# include <io.h>
# define O_CREAT _O_CREAT
# define O_TRUNC _O_TRUNC
#ifndef S_IRUSR
# define S_IRUSR _S_IREAD
#endif
#ifndef S_IWUSR
# define S_IWUSR _S_IWRITE
#endif
# ifdef __MINGW32__
# define _SH_DENYNO 0x40
# endif
#endif // _WIN32
namespace {
#ifdef _WIN32
// Return type of read and write functions.
typedef int RWResult;
// On Windows the count argument to read and write is unsigned, so convert
// it from size_t preventing integer overflow.
inline unsigned convert_rwcount(std::size_t count) {
return count <= UINT_MAX ? static_cast<unsigned>(count) : UINT_MAX;
}
#else
// Return type of read and write functions.
typedef ssize_t RWResult;
inline std::size_t convert_rwcount(std::size_t count) { return count; }
#endif
}
fmt::BufferedFile::~BufferedFile() FMT_NOEXCEPT {
if (file_ && FMT_SYSTEM(fclose(file_)) != 0)
fmt::report_system_error(errno, "cannot close file");
}
fmt::BufferedFile::BufferedFile(fmt::StringRef filename, fmt::StringRef mode) {
FMT_RETRY_VAL(file_, FMT_SYSTEM(fopen(filename.c_str(), mode.c_str())), 0);
if (!file_)
throw SystemError(errno, "cannot open file {}", filename);
}
void fmt::BufferedFile::close() {
if (!file_)
return;
int result = FMT_SYSTEM(fclose(file_));
file_ = 0;
if (result != 0)
throw SystemError(errno, "cannot close file");
}
int fmt::BufferedFile::fileno() const {
int fd = FMT_POSIX_CALL(fileno(file_));
if (fd == -1)
throw SystemError(errno, "cannot get file descriptor");
return fd;
}
fmt::File::File(fmt::StringRef path, int oflag) {
int mode = S_IRUSR | S_IWUSR;
#ifdef _WIN32
fd_ = -1;
FMT_POSIX_CALL(sopen_s(&fd_, path.c_str(), oflag, _SH_DENYNO, mode));
#else
FMT_RETRY(fd_, FMT_POSIX_CALL(open(path.c_str(), oflag, mode)));
#endif
if (fd_ == -1)
throw SystemError(errno, "cannot open file {}", path);
}
fmt::File::~File() FMT_NOEXCEPT {
// Don't retry close in case of EINTR!
// See http://linux.derkeiler.com/Mailing-Lists/Kernel/2005-09/3000.html
if (fd_ != -1 && FMT_POSIX_CALL(close(fd_)) != 0)
fmt::report_system_error(errno, "cannot close file");
}
void fmt::File::close() {
if (fd_ == -1)
return;
// Don't retry close in case of EINTR!
// See http://linux.derkeiler.com/Mailing-Lists/Kernel/2005-09/3000.html
int result = FMT_POSIX_CALL(close(fd_));
fd_ = -1;
if (result != 0)
throw SystemError(errno, "cannot close file");
}
fmt::LongLong fmt::File::size() const {
#ifdef _WIN32
LARGE_INTEGER filesize = {};
HANDLE handle = reinterpret_cast<HANDLE>(_get_osfhandle(fd_));
if (!FMT_SYSTEM(GetFileSizeEx(handle, &filesize)))
throw WindowsError(GetLastError(), "cannot get file size");
FMT_STATIC_ASSERT(sizeof(fmt::LongLong) >= sizeof(filesize.QuadPart),
"return type of File::size is not large enough");
return filesize.QuadPart;
#else
typedef struct stat Stat;
Stat file_stat = Stat();
if (FMT_POSIX_CALL(fstat(fd_, &file_stat)) == -1)
throw SystemError(errno, "cannot get file attributes");
FMT_STATIC_ASSERT(sizeof(fmt::LongLong) >= sizeof(file_stat.st_size),
"return type of File::size is not large enough");
return file_stat.st_size;
#endif
}
std::size_t fmt::File::read(void *buffer, std::size_t count) {
RWResult result = 0;
FMT_RETRY(result, FMT_POSIX_CALL(read(fd_, buffer, convert_rwcount(count))));
if (result < 0)
throw SystemError(errno, "cannot read from file");
return result;
}
std::size_t fmt::File::write(const void *buffer, std::size_t count) {
RWResult result = 0;
FMT_RETRY(result, FMT_POSIX_CALL(write(fd_, buffer, convert_rwcount(count))));
if (result < 0)
throw SystemError(errno, "cannot write to file");
return result;
}
fmt::File fmt::File::dup(int fd) {
// Don't retry as dup doesn't return EINTR.
// http://pubs.opengroup.org/onlinepubs/009695399/functions/dup.html
int new_fd = FMT_POSIX_CALL(dup(fd));
if (new_fd == -1)
throw SystemError(errno, "cannot duplicate file descriptor {}", fd);
return File(new_fd);
}
void fmt::File::dup2(int fd) {
int result = 0;
FMT_RETRY(result, FMT_POSIX_CALL(dup2(fd_, fd)));
if (result == -1) {
throw SystemError(errno,
"cannot duplicate file descriptor {} to {}", fd_, fd);
}
}
void fmt::File::dup2(int fd, ErrorCode &ec) FMT_NOEXCEPT {
int result = 0;
FMT_RETRY(result, FMT_POSIX_CALL(dup2(fd_, fd)));
if (result == -1)
ec = ErrorCode(errno);
}
void fmt::File::pipe(File &read_end, File &write_end) {
// Close the descriptors first to make sure that assignments don't throw
// and there are no leaks.
read_end.close();
write_end.close();
int fds[2] = {};
#ifdef _WIN32
// Make the default pipe capacity same as on Linux 2.6.11+.
enum { DEFAULT_CAPACITY = 65536 };
int result = FMT_POSIX_CALL(pipe(fds, DEFAULT_CAPACITY, _O_BINARY));
#else
// Don't retry as the pipe function doesn't return EINTR.
// http://pubs.opengroup.org/onlinepubs/009696799/functions/pipe.html
int result = FMT_POSIX_CALL(pipe(fds));
#endif
if (result != 0)
throw SystemError(errno, "cannot create pipe");
// The following assignments don't throw because read_fd and write_fd
// are closed.
read_end = File(fds[0]);
write_end = File(fds[1]);
}
fmt::BufferedFile fmt::File::fdopen(const char *mode) {
// Don't retry as fdopen doesn't return EINTR.
FILE *f = FMT_POSIX_CALL(fdopen(fd_, mode));
if (!f)
throw SystemError(errno, "cannot associate stream with file descriptor");
BufferedFile file(f);
fd_ = -1;
return file;
}
long fmt::getpagesize() {
#ifdef _WIN32
SYSTEM_INFO si;
GetSystemInfo(&si);
return si.dwPageSize;
#else
long size = FMT_POSIX_CALL(sysconf(_SC_PAGESIZE));
if (size < 0)
throw SystemError(errno, "cannot get memory page size");
return size;
#endif
}

337
posix.h Normal file
View File

@@ -0,0 +1,337 @@
/*
A C++ interface to POSIX functions.
Copyright (c) 2014 - 2015, Victor Zverovich
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef FMT_POSIX_H_
#define FMT_POSIX_H_
#include <errno.h>
#include <fcntl.h> // for O_RDONLY
#include <stdio.h>
#include <cstddef>
#include "format.h"
#ifdef FMT_INCLUDE_POSIX_TEST
# include "test/posix-test.h"
#endif
#ifndef FMT_POSIX
# ifdef _WIN32
// Fix warnings about deprecated symbols.
# define FMT_POSIX(call) _##call
# else
# define FMT_POSIX(call) call
# endif
#endif
// Calls to system functions are wrapped in FMT_SYSTEM for testability.
#ifdef FMT_SYSTEM
# define FMT_POSIX_CALL(call) FMT_SYSTEM(call)
#else
# define FMT_SYSTEM(call) call
# ifdef _WIN32
// Fix warnings about deprecated symbols.
# define FMT_POSIX_CALL(call) ::_##call
# else
# define FMT_POSIX_CALL(call) ::call
# endif
#endif
#if FMT_GCC_VERSION >= 407
# define FMT_UNUSED __attribute__((unused))
#else
# define FMT_UNUSED
#endif
#if FMT_USE_STATIC_ASSERT || FMT_HAS_CPP_ATTRIBUTE(cxx_static_assert) || \
(FMT_GCC_VERSION >= 403 && FMT_HAS_GXX_CXX11) || _MSC_VER >= 1600
# define FMT_STATIC_ASSERT(cond, message) static_assert(cond, message)
#else
# define FMT_CONCAT_(a, b) FMT_CONCAT(a, b)
# define FMT_STATIC_ASSERT(cond, message) \
typedef int FMT_CONCAT_(Assert, __LINE__)[(cond) ? 1 : -1] FMT_UNUSED
#endif
// Retries the expression while it evaluates to error_result and errno
// equals to EINTR.
#ifndef _WIN32
# define FMT_RETRY_VAL(result, expression, error_result) \
do { \
result = (expression); \
} while (result == error_result && errno == EINTR)
#else
# define FMT_RETRY_VAL(result, expression, error_result) result = (expression)
#endif
#define FMT_RETRY(result, expression) FMT_RETRY_VAL(result, expression, -1)
namespace fmt {
// An error code.
class ErrorCode {
private:
int value_;
public:
explicit ErrorCode(int value = 0) FMT_NOEXCEPT : value_(value) {}
int get() const FMT_NOEXCEPT { return value_; }
};
// A buffered file.
class BufferedFile {
private:
FILE *file_;
friend class File;
explicit BufferedFile(FILE *f) : file_(f) {}
public:
// Constructs a BufferedFile object which doesn't represent any file.
BufferedFile() FMT_NOEXCEPT : file_(0) {}
// Destroys the object closing the file it represents if any.
~BufferedFile() FMT_NOEXCEPT;
#if !FMT_USE_RVALUE_REFERENCES
// Emulate a move constructor and a move assignment operator if rvalue
// references are not supported.
private:
// A proxy object to emulate a move constructor.
// It is private to make it impossible call operator Proxy directly.
struct Proxy {
FILE *file;
};
public:
// A "move constructor" for moving from a temporary.
BufferedFile(Proxy p) FMT_NOEXCEPT : file_(p.file) {}
// A "move constructor" for for moving from an lvalue.
BufferedFile(BufferedFile &f) FMT_NOEXCEPT : file_(f.file_) {
f.file_ = 0;
}
// A "move assignment operator" for moving from a temporary.
BufferedFile &operator=(Proxy p) {
close();
file_ = p.file;
return *this;
}
// A "move assignment operator" for moving from an lvalue.
BufferedFile &operator=(BufferedFile &other) {
close();
file_ = other.file_;
other.file_ = 0;
return *this;
}
// Returns a proxy object for moving from a temporary:
// BufferedFile file = BufferedFile(...);
operator Proxy() FMT_NOEXCEPT {
Proxy p = {file_};
file_ = 0;
return p;
}
#else
private:
FMT_DISALLOW_COPY_AND_ASSIGN(BufferedFile);
public:
BufferedFile(BufferedFile &&other) FMT_NOEXCEPT : file_(other.file_) {
other.file_ = 0;
}
BufferedFile& operator=(BufferedFile &&other) {
close();
file_ = other.file_;
other.file_ = 0;
return *this;
}
#endif
// Opens a file.
BufferedFile(fmt::StringRef filename, fmt::StringRef mode);
// Closes the file.
void close();
// Returns the pointer to a FILE object representing this file.
FILE *get() const FMT_NOEXCEPT { return file_; }
int fileno() const;
void print(fmt::StringRef format_str, const ArgList &args) {
fmt::print(file_, format_str, args);
}
FMT_VARIADIC(void, print, fmt::StringRef)
};
// A file. Closed file is represented by a File object with descriptor -1.
// Methods that are not declared with FMT_NOEXCEPT may throw
// fmt::SystemError in case of failure. Note that some errors such as
// closing the file multiple times will cause a crash on Windows rather
// than an exception. You can get standard behavior by overriding the
// invalid parameter handler with _set_invalid_parameter_handler.
class File {
private:
int fd_; // File descriptor.
// Constructs a File object with a given descriptor.
explicit File(int fd) : fd_(fd) {}
public:
// Possible values for the oflag argument to the constructor.
enum {
RDONLY = FMT_POSIX(O_RDONLY), // Open for reading only.
WRONLY = FMT_POSIX(O_WRONLY), // Open for writing only.
RDWR = FMT_POSIX(O_RDWR) // Open for reading and writing.
};
// Constructs a File object which doesn't represent any file.
File() FMT_NOEXCEPT : fd_(-1) {}
// Opens a file and constructs a File object representing this file.
File(fmt::StringRef path, int oflag);
#if !FMT_USE_RVALUE_REFERENCES
// Emulate a move constructor and a move assignment operator if rvalue
// references are not supported.
private:
// A proxy object to emulate a move constructor.
// It is private to make it impossible call operator Proxy directly.
struct Proxy {
int fd;
};
public:
// A "move constructor" for moving from a temporary.
File(Proxy p) FMT_NOEXCEPT : fd_(p.fd) {}
// A "move constructor" for for moving from an lvalue.
File(File &other) FMT_NOEXCEPT : fd_(other.fd_) {
other.fd_ = -1;
}
// A "move assignment operator" for moving from a temporary.
File &operator=(Proxy p) {
close();
fd_ = p.fd;
return *this;
}
// A "move assignment operator" for moving from an lvalue.
File &operator=(File &other) {
close();
fd_ = other.fd_;
other.fd_ = -1;
return *this;
}
// Returns a proxy object for moving from a temporary:
// File file = File(...);
operator Proxy() FMT_NOEXCEPT {
Proxy p = {fd_};
fd_ = -1;
return p;
}
#else
private:
FMT_DISALLOW_COPY_AND_ASSIGN(File);
public:
File(File &&other) FMT_NOEXCEPT : fd_(other.fd_) {
other.fd_ = -1;
}
File& operator=(File &&other) {
close();
fd_ = other.fd_;
other.fd_ = -1;
return *this;
}
#endif
// Destroys the object closing the file it represents if any.
~File() FMT_NOEXCEPT;
// Returns the file descriptor.
int descriptor() const FMT_NOEXCEPT { return fd_; }
// Closes the file.
void close();
// Returns the file size.
fmt::LongLong size() const;
// Attempts to read count bytes from the file into the specified buffer.
std::size_t read(void *buffer, std::size_t count);
// Attempts to write count bytes from the specified buffer to the file.
std::size_t write(const void *buffer, std::size_t count);
// Duplicates a file descriptor with the dup function and returns
// the duplicate as a file object.
static File dup(int fd);
// Makes fd be the copy of this file descriptor, closing fd first if
// necessary.
void dup2(int fd);
// Makes fd be the copy of this file descriptor, closing fd first if
// necessary.
void dup2(int fd, ErrorCode &ec) FMT_NOEXCEPT;
// Creates a pipe setting up read_end and write_end file objects for reading
// and writing respectively.
static void pipe(File &read_end, File &write_end);
// Creates a BufferedFile object associated with this file and detaches
// this File object from the file.
BufferedFile fdopen(const char *mode);
};
// Returns the memory page size.
long getpagesize();
} // namespace fmt
#if !FMT_USE_RVALUE_REFERENCES
namespace std {
// For compatibility with C++98.
inline fmt::BufferedFile &move(fmt::BufferedFile &f) { return f; }
inline fmt::File &move(fmt::File &f) { return f; }
}
#endif
#endif // FMT_POSIX_H_

4
support/README Normal file
View File

@@ -0,0 +1,4 @@
This directory contains build support files such as
* CMake modules
* Build scripts

30
support/appveyor-build.py Executable file
View File

@@ -0,0 +1,30 @@
#!/usr/bin/env python
# Build the project on AppVeyor.
import os
from download import Downloader
from subprocess import check_call
build = os.environ['BUILD']
cmake_command = ['cmake', '-DFMT_EXTRA_TESTS=ON', '-DCMAKE_BUILD_TYPE=' + os.environ['CONFIG']]
build_command = ['msbuild', '/m:4', '/p:Config=' + os.environ['CONFIG'], 'FORMAT.sln']
test_command = ['msbuild', 'RUN_TESTS.vcxproj']
if build == 'mingw':
# Install MinGW.
mingw_url = 'http://ufpr.dl.sourceforge.net/project/mingw-w64/' + \
'Toolchains%20targetting%20Win64/Personal%20Builds/mingw-builds/' + \
'4.9.2/threads-win32/seh/x86_64-4.9.2-release-win32-seh-rt_v3-rev1.7z'
with Downloader().download(mingw_url) as f:
check_call(['7z', 'x', '-oC:\\', f])
# Remove path to Git bin directory from $PATH because it breaks MinGW config.
path = os.environ['PATH'].replace(r'C:\Program Files (x86)\Git\bin', '')
os.environ['PATH'] = r'C:\Program Files (x86)\MSBUILD\12.0\bin\;' + path + r';C:\mingw64\bin'
cmake_command.append('-GMinGW Makefiles')
build_command = ['mingw32-make', '-j4']
test_command = ['mingw32-make', 'test']
check_call(cmake_command)
check_call(build_command)
check_call(test_command)

13
support/biicode-build.py Executable file
View File

@@ -0,0 +1,13 @@
#!/usr/bin/env python
# Build the project with Biicode.
import glob, os, shutil
from subprocess import check_call
project_dir = 'biicode_project'
check_call(['bii', 'init', project_dir])
cppformat_dir = os.path.join(project_dir, 'blocks/vitaut/cppformat')
shutil.copytree('.', cppformat_dir, ignore=shutil.ignore_patterns(project_dir))
for f in glob.glob('support/biicode/*'):
shutil.copy(f, cppformat_dir)
check_call(['bii', 'cpp:build'], cwd=project_dir)

View File

@@ -0,0 +1,19 @@
# Biicode configuration file
[paths]
# Local directories to look for headers (within block)
/
[dependencies]
# Manual adjust file implicit dependencies, add (+), remove (-), or overwrite (=)
CMakeLists.txt + cmake/FindSetEnv.cmake
format.h = format.cc
format.cc - test/* posix.cc
support/biicode/sample.cc - test/*
[mains]
# Manual adjust of files that define an executable
!test/test-main.cc
[parent]
vitaut/cppformat: 0

View File

@@ -0,0 +1,3 @@
doc/*
breathe/*
gmock/*

17
support/biicode/sample.cc Normal file
View File

@@ -0,0 +1,17 @@
#include "vitaut/cppformat/format.h"
class Date {
int year_, month_, day_;
public:
Date(int year, int month, int day) : year_(year), month_(month), day_(day) {}
friend std::ostream &operator<<(std::ostream &os, const Date &d) {
return os << d.year_ << '-' << d.month_ << '-' << d.day_;
}
};
int main() {
std::string s = fmt::format("The date is {}", Date(2012, 12, 9));
fmt::print("Hello, {}!", "world"); // uses Python-like format string syntax
fmt::printf("\n%s", s); // uses printf format string syntax
}

View File

@@ -0,0 +1,7 @@
# A CMake script to find SetEnv.cmd.
find_program(WINSDK_SETENV NAMES SetEnv.cmd
PATHS "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Microsoft SDKs\\Windows;CurrentInstallFolder]/bin")
if (WINSDK_SETENV AND PRINT_PATH)
execute_process(COMMAND ${CMAKE_COMMAND} -E echo "${WINSDK_SETENV}")
endif ()

View File

@@ -0,0 +1,18 @@
# Initializes block variables
INIT_BIICODE_BLOCK()
# Actually create targets: EXEcutables and libraries.
ADD_BIICODE_TARGETS()
target_include_directories(${BII_BLOCK_TARGET} INTERFACE ${CMAKE_CURRENT_SOURCE_DIR})
if (HAVE_OPEN)
target_compile_definitions(${BII_BLOCK_TARGET} INTERFACE -DFMT_USE_FILE_DESCRIPTORS=1)
endif ()
if (CMAKE_COMPILER_IS_GNUCXX)
target_compile_options(${BII_BLOCK_TARGET} INTERFACE -Wall -Wextra -Wshadow -pedantic)
endif ()
if (CPP11_FLAG AND FMT_EXTRA_TESTS)
target_compile_options(${BII_BLOCK_TARGET} INTERFACE ${CPP11_FLAG})
endif ()

View File

@@ -0,0 +1,11 @@
@echo on
rem This scripts configures build environment and runs CMake.
rem Use it instead of running CMake directly when building with
rem the Microsoft SDK toolchain rather than Visual Studio.
rem It is used in the same way as cmake, for example:
rem
rem run-cmake -G "Visual Studio 10 Win64" .
for /F "delims=" %%i IN ('cmake "-DPRINT_PATH=1" -P %~dp0/FindSetEnv.cmake') DO set setenv=%%i
if NOT "%setenv%" == "" call "%setenv%"
cmake %*

46
support/download.py Normal file
View File

@@ -0,0 +1,46 @@
# A file downloader.
import contextlib, os, tempfile, timer, urllib2, urlparse
class Downloader:
def __init__(self, dir=None):
self.dir = dir
# Downloads a file and removes it when exiting a block.
# Usage:
# d = Downloader()
# with d.download(url) as f:
# use_file(f)
def download(self, url, cookie=None):
suffix = os.path.splitext(urlparse.urlsplit(url)[2])[1]
fd, filename = tempfile.mkstemp(suffix=suffix, dir=self.dir)
os.close(fd)
with timer.print_time('Downloading', url, 'to', filename):
opener = urllib2.build_opener()
if cookie:
opener.addheaders.append(('Cookie', cookie))
num_tries = 2
for i in range(num_tries):
try:
f = opener.open(url)
except urllib2.URLError, e:
print('Failed to open url', url)
continue
length = f.headers.get('content-length')
if not length:
print('Failed to get content-length')
continue
length = int(length)
with open(filename, 'wb') as out:
count = 0
while count < length:
data = f.read(1024 * 1024)
count += len(data)
out.write(data)
@contextlib.contextmanager
def remove(filename):
try:
yield filename
finally:
os.remove(filename)
return remove(filename)

35
support/timer.py Normal file
View File

@@ -0,0 +1,35 @@
# A with statement based timer.
from __future__ import print_function
from contextlib import contextmanager
import timeit
class Timer:
"""
A with statement based timer.
Usage:
t = Timer()
with t:
do_something()
time = t.time
"""
def __enter__(self):
self.start = timeit.default_timer()
def __exit__(self, type, value, traceback):
finish = timeit.default_timer()
self.time = finish - self.start
@contextmanager
def print_time(*args):
"""
Measures and prints the time taken to execute nested code.
args: Additional arguments to print.
"""
t = Timer()
print(*args)
with t:
yield
print(*args, end=' ')
print('finished in {0:.2f} second(s)'.format(t.time))

View File

@@ -1,27 +1,80 @@
# Test if compile errors are produced where necessary.
set(TEST_MAIN_SRC test-main.cc gtest-extra.cc gtest-extra.h util.cc)
add_library(test-main STATIC ${TEST_MAIN_SRC})
target_link_libraries(test-main format gmock)
cmake_minimum_required(VERSION 2.8)
include(CheckCXXSourceCompiles)
set(CMAKE_REQUIRED_INCLUDES ${CMAKE_CURRENT_SOURCE_DIR}/..)
function (expect_compile_error code)
check_cxx_source_compiles("
#include \"format.cc\"
int main() {
${code}
}
" compiles)
set (does_compile ${compiles})
# Unset the CMake cache variable compiles. Otherwise the compile test will
# just use cached information next time it runs.
unset(compiles CACHE)
if (does_compile)
message(FATAL_ERROR "No compile error for: ${code}")
# Adds a test.
# Usage: add_fmt_test(name [CUSTOM_LINK] srcs...)
function(add_fmt_test name)
cmake_parse_arguments(add_fmt_test CUSTOM_LINK "" "" ${ARGN})
add_executable(${name} ${name}.cc ${add_fmt_test_UNPARSED_ARGUMENTS})
target_link_libraries(${name} test-main)
if (NOT add_fmt_test_CUSTOM_LINK)
target_link_libraries(${name} format)
endif ()
endfunction ()
add_test(NAME ${name} COMMAND ${name})
endfunction()
# Writing a wide character to a character stream Writer is forbidden.
expect_compile_error("fmt::Writer() << L'a';")
expect_compile_error("fmt::Writer() << fmt::pad(\"abc\", 5, L' ');")
expect_compile_error("fmt::Writer() << fmt::pad(42, 5, L' ');")
add_fmt_test(gtest-extra-test)
add_fmt_test(format-test)
add_fmt_test(format-impl-test CUSTOM_LINK)
add_fmt_test(printf-test)
foreach (target format-test printf-test)
if (CMAKE_COMPILER_IS_GNUCXX)
set_target_properties(${target} PROPERTIES COMPILE_FLAGS
"-Wall -Wextra -pedantic -Wno-long-long -Wno-variadic-macros")
endif ()
if (CPP11_FLAG)
set_target_properties(${target} PROPERTIES COMPILE_FLAGS ${CPP11_FLAG})
endif ()
endforeach ()
add_fmt_test(util-test mock-allocator.h)
if (CPP11_FLAG)
set_target_properties(util-test PROPERTIES COMPILE_FLAGS ${CPP11_FLAG})
endif ()
foreach (src ${FMT_SOURCES})
set(FMT_TEST_SOURCES ${FMT_TEST_SOURCES} ../${src})
endforeach ()
check_cxx_source_compiles("
#include <type_traits>
class C { void operator=(const C&); };
int main() { static_assert(!std::is_copy_assignable<C>::value, \"\"); }"
HAVE_TYPE_TRAITS)
if (HAVE_TYPE_TRAITS)
add_definitions(-DFMT_USE_TYPE_TRAITS=1)
endif ()
add_executable(macro-test macro-test.cc ${FMT_TEST_SOURCES} ${TEST_MAIN_SRC})
set_target_properties(macro-test
PROPERTIES COMPILE_DEFINITIONS "FMT_USE_VARIADIC_TEMPLATES=0")
target_link_libraries(macro-test gmock)
if (HAVE_OPEN)
add_executable(posix-test posix-test.cc ${FMT_TEST_SOURCES} ${TEST_MAIN_SRC})
set_target_properties(posix-test
PROPERTIES COMPILE_DEFINITIONS "FMT_INCLUDE_POSIX_TEST=1")
target_link_libraries(posix-test gmock)
add_test(NAME posix-test COMMAND posix-test)
endif ()
add_executable(header-only-test
header-only-test.cc header-only-test2.cc test-main.cc)
set_target_properties(header-only-test
PROPERTIES COMPILE_DEFINITIONS "FMT_HEADER_ONLY=1")
target_link_libraries(header-only-test gmock)
# Test that the library can be compiled with exceptions disabled.
check_cxx_compiler_flag(-fno-exceptions HAVE_FNO_EXCEPTIONS_FLAG)
if (HAVE_FNO_EXCEPTIONS_FLAG)
add_library(noexception-test STATIC ../format.cc)
set_target_properties(noexception-test
PROPERTIES COMPILE_FLAGS -fno-exceptions)
endif ()
add_test(compile-test ${CMAKE_CTEST_COMMAND}
--build-and-test
"${CMAKE_CURRENT_SOURCE_DIR}/compile-test"
"${CMAKE_CURRENT_BINARY_DIR}/compile-test"
--build-generator ${CMAKE_GENERATOR}
--build-makeprogram ${CMAKE_MAKE_PROGRAM})

View File

@@ -0,0 +1,41 @@
# Test if compile errors are produced where necessary.
cmake_minimum_required(VERSION 2.8)
include(CheckCXXSourceCompiles)
set(CMAKE_REQUIRED_INCLUDES ${CMAKE_CURRENT_SOURCE_DIR}/../..)
function (expect_compile_error code)
check_cxx_source_compiles("
#include \"format.cc\"
#include \"posix.h\"
int main() {
${code}
}
" compiles)
set (does_compile ${compiles})
# Unset the CMake cache variable compiles. Otherwise the compile test will
# just use cached information next time it runs.
unset(compiles CACHE)
if (does_compile)
message(FATAL_ERROR "No compile error for: ${code}")
endif ()
endfunction ()
# MakeArg doesn't accept [const] volatile char *.
expect_compile_error("volatile char s[] = \"test\"; (fmt::internal::MakeArg<char>)(s);")
expect_compile_error("const volatile char s[] = \"test\"; (fmt::internal::MakeArg<char>)(s);")
# MakeArg<char> doesn't accept wchar_t.
expect_compile_error("fmt::internal::MakeValue<char>(L'a');")
expect_compile_error("fmt::internal::MakeValue<char>(L\"test\");")
# Writing a wide character to a character stream Writer is forbidden.
expect_compile_error("fmt::MemoryWriter() << L'a';")
expect_compile_error("fmt::MemoryWriter() << fmt::pad(\"abc\", 5, L' ');")
expect_compile_error("fmt::MemoryWriter() << fmt::pad(42, 5, L' ');")
# Formatting a wide character with a narrow format string is forbidden.
expect_compile_error("fmt::format(\"{}\", L'a';")
expect_compile_error("FMT_STATIC_ASSERT(0 > 1, \"oops\");")

112
test/format-impl-test.cc Normal file
View File

@@ -0,0 +1,112 @@
/*
Formatting library implementation tests.
Copyright (c) 2012-2014, Victor Zverovich
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
// Include format.cc instead of format.h to test implementation-specific stuff.
#include "format.cc"
#include <cstring>
#include "gtest-extra.h"
#include "util.h"
#undef max
TEST(FormatTest, ArgConverter) {
using fmt::internal::Arg;
Arg arg = Arg();
arg.type = Arg::LONG_LONG;
arg.long_long_value = std::numeric_limits<fmt::LongLong>::max();
ArgConverter<fmt::LongLong>(arg, 'd').visit(arg);
EXPECT_EQ(Arg::LONG_LONG, arg.type);
}
TEST(FormatTest, FormatNegativeNaN) {
double nan = std::numeric_limits<double>::quiet_NaN();
if (fmt::internal::getsign(-nan))
EXPECT_EQ("-nan", fmt::format("{}", -nan));
else
fmt::print("Warning: compiler doesn't handle negative NaN correctly");
}
TEST(FormatTest, StrError) {
char *message = 0;
char buffer[BUFFER_SIZE];
#ifndef NDEBUG
EXPECT_DEBUG_DEATH(safe_strerror(EDOM, message = 0, 0), "Assertion");
EXPECT_DEBUG_DEATH(safe_strerror(EDOM, message = buffer, 0), "Assertion");
#endif
buffer[0] = 'x';
#ifdef _GNU_SOURCE
// Use invalid error code to make sure that safe_strerror returns an error
// message in the buffer rather than a pointer to a static string.
int error_code = -1;
#else
int error_code = EDOM;
#endif
int result = safe_strerror(error_code, message = buffer, BUFFER_SIZE);
EXPECT_EQ(0, result);
std::size_t message_size = std::strlen(message);
EXPECT_GE(BUFFER_SIZE - 1u, message_size);
EXPECT_EQ(get_system_error(error_code), message);
// safe_strerror never uses buffer on MinGW.
#ifndef __MINGW32__
result = safe_strerror(error_code, message = buffer, message_size);
EXPECT_EQ(ERANGE, result);
result = safe_strerror(error_code, message = buffer, 1);
EXPECT_EQ(buffer, message); // Message should point to buffer.
EXPECT_EQ(ERANGE, result);
EXPECT_STREQ("", message);
#endif
}
TEST(FormatTest, FormatErrorCode) {
std::string msg = "error 42", sep = ": ";
{
fmt::MemoryWriter w;
w << "garbage";
format_error_code(w, 42, "test");
EXPECT_EQ("test: " + msg, w.str());
}
{
fmt::MemoryWriter w;
std::string prefix(
fmt::internal::INLINE_BUFFER_SIZE - msg.size() - sep.size() + 1, 'x');
format_error_code(w, 42, prefix);
EXPECT_EQ(msg, w.str());
}
{
fmt::MemoryWriter w;
std::string prefix(
fmt::internal::INLINE_BUFFER_SIZE - msg.size() - sep.size(), 'x');
format_error_code(w, 42, prefix);
EXPECT_EQ(prefix + sep + msg, w.str());
std::size_t size = fmt::internal::INLINE_BUFFER_SIZE;
EXPECT_EQ(size, w.size());
}
}

1465
test/format-test.cc Normal file

File diff suppressed because it is too large Load Diff

834
test/gtest-extra-test.cc Normal file
View File

@@ -0,0 +1,834 @@
/*
Tests of custom Google Test assertions.
Copyright (c) 2012-2014, Victor Zverovich
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "gtest-extra.h"
#include <cstring>
#include <algorithm>
#include <stdexcept>
#include <gtest/gtest-spi.h>
#if defined(_WIN32) && !defined(__MINGW32__)
# include <crtdbg.h> // for _CrtSetReportMode
#endif // _WIN32
namespace {
#if defined(_WIN32) && !defined(__MINGW32__)
// Suppresses Windows assertions on invalid file descriptors, making
// POSIX functions return proper error codes instead of crashing on Windows.
class SuppressAssert {
private:
_invalid_parameter_handler original_handler_;
int original_report_mode_;
static void handle_invalid_parameter(const wchar_t *,
const wchar_t *, const wchar_t *, unsigned , uintptr_t) {}
public:
SuppressAssert()
: original_handler_(_set_invalid_parameter_handler(handle_invalid_parameter)),
original_report_mode_(_CrtSetReportMode(_CRT_ASSERT, 0)) {
}
~SuppressAssert() {
_set_invalid_parameter_handler(original_handler_);
_CrtSetReportMode(_CRT_ASSERT, original_report_mode_);
}
};
# define SUPPRESS_ASSERT(statement) { SuppressAssert sa; statement; }
// Fix "secure" warning about using fopen without defining
// _CRT_SECURE_NO_WARNINGS.
FILE *safe_fopen(const char *filename, const char *mode) {
FILE *f = 0;
errno = fopen_s(&f, filename, mode);
return f;
}
#define fopen safe_fopen
#else
# define SUPPRESS_ASSERT(statement) statement
using std::fopen;
#endif // _WIN32
#define EXPECT_SYSTEM_ERROR_NOASSERT(statement, error_code, message) \
EXPECT_SYSTEM_ERROR(SUPPRESS_ASSERT(statement), error_code, message)
// Tests that assertion macros evaluate their arguments exactly once.
class SingleEvaluationTest : public ::testing::Test {
protected:
SingleEvaluationTest() {
p_ = s_;
a_ = 0;
b_ = 0;
}
static const char* const s_;
static const char* p_;
static int a_;
static int b_;
};
const char* const SingleEvaluationTest::s_ = "01234";
const char* SingleEvaluationTest::p_;
int SingleEvaluationTest::a_;
int SingleEvaluationTest::b_;
void do_nothing() {}
void throw_exception() {
throw std::runtime_error("test");
}
void throw_system_error() {
throw fmt::SystemError(EDOM, "test");
}
// Tests that when EXPECT_THROW_MSG fails, it evaluates its message argument
// exactly once.
TEST_F(SingleEvaluationTest, FailedEXPECT_THROW_MSG) {
EXPECT_NONFATAL_FAILURE(
EXPECT_THROW_MSG(throw_exception(), std::exception, p_++), "01234");
EXPECT_EQ(s_ + 1, p_);
}
// Tests that when EXPECT_SYSTEM_ERROR fails, it evaluates its message argument
// exactly once.
TEST_F(SingleEvaluationTest, FailedEXPECT_SYSTEM_ERROR) {
EXPECT_NONFATAL_FAILURE(
EXPECT_SYSTEM_ERROR(throw_system_error(), EDOM, p_++), "01234");
EXPECT_EQ(s_ + 1, p_);
}
// Tests that when EXPECT_WRITE fails, it evaluates its message argument
// exactly once.
TEST_F(SingleEvaluationTest, FailedEXPECT_WRITE) {
EXPECT_NONFATAL_FAILURE(
EXPECT_WRITE(stdout, std::printf("test"), p_++), "01234");
EXPECT_EQ(s_ + 1, p_);
}
// Tests that assertion arguments are evaluated exactly once.
TEST_F(SingleEvaluationTest, ExceptionTests) {
// successful EXPECT_THROW_MSG
EXPECT_THROW_MSG({ // NOLINT
a_++;
throw_exception();
}, std::exception, (b_++, "test"));
EXPECT_EQ(1, a_);
EXPECT_EQ(1, b_);
// failed EXPECT_THROW_MSG, throws different type
EXPECT_NONFATAL_FAILURE(EXPECT_THROW_MSG({ // NOLINT
a_++;
throw_exception();
}, std::logic_error, (b_++, "test")), "throws a different type");
EXPECT_EQ(2, a_);
EXPECT_EQ(2, b_);
// failed EXPECT_THROW_MSG, throws an exception with different message
EXPECT_NONFATAL_FAILURE(EXPECT_THROW_MSG({ // NOLINT
a_++;
throw_exception();
}, std::exception, (b_++, "other")),
"throws an exception with a different message");
EXPECT_EQ(3, a_);
EXPECT_EQ(3, b_);
// failed EXPECT_THROW_MSG, throws nothing
EXPECT_NONFATAL_FAILURE(
EXPECT_THROW_MSG(a_++, std::exception, (b_++, "test")), "throws nothing");
EXPECT_EQ(4, a_);
EXPECT_EQ(4, b_);
}
TEST_F(SingleEvaluationTest, SystemErrorTests) {
// successful EXPECT_SYSTEM_ERROR
EXPECT_SYSTEM_ERROR({ // NOLINT
a_++;
throw_system_error();
}, EDOM, (b_++, "test"));
EXPECT_EQ(1, a_);
EXPECT_EQ(1, b_);
// failed EXPECT_SYSTEM_ERROR, throws different type
EXPECT_NONFATAL_FAILURE(EXPECT_SYSTEM_ERROR({ // NOLINT
a_++;
throw_exception();
}, EDOM, (b_++, "test")), "throws a different type");
EXPECT_EQ(2, a_);
EXPECT_EQ(2, b_);
// failed EXPECT_SYSTEM_ERROR, throws an exception with different message
EXPECT_NONFATAL_FAILURE(EXPECT_SYSTEM_ERROR({ // NOLINT
a_++;
throw_system_error();
}, EDOM, (b_++, "other")),
"throws an exception with a different message");
EXPECT_EQ(3, a_);
EXPECT_EQ(3, b_);
// failed EXPECT_SYSTEM_ERROR, throws nothing
EXPECT_NONFATAL_FAILURE(
EXPECT_SYSTEM_ERROR(a_++, EDOM, (b_++, "test")), "throws nothing");
EXPECT_EQ(4, a_);
EXPECT_EQ(4, b_);
}
// Tests that assertion arguments are evaluated exactly once.
TEST_F(SingleEvaluationTest, WriteTests) {
// successful EXPECT_WRITE
EXPECT_WRITE(stdout, { // NOLINT
a_++;
std::printf("test");
}, (b_++, "test"));
EXPECT_EQ(1, a_);
EXPECT_EQ(1, b_);
// failed EXPECT_WRITE
EXPECT_NONFATAL_FAILURE(EXPECT_WRITE(stdout, { // NOLINT
a_++;
std::printf("test");
}, (b_++, "other")), "Actual: test");
EXPECT_EQ(2, a_);
EXPECT_EQ(2, b_);
}
// Tests that the compiler will not complain about unreachable code in the
// EXPECT_THROW_MSG macro.
TEST(ExpectThrowTest, DoesNotGenerateUnreachableCodeWarning) {
int n = 0;
using std::runtime_error;
EXPECT_THROW_MSG(throw runtime_error(""), runtime_error, "");
EXPECT_NONFATAL_FAILURE(EXPECT_THROW_MSG(n++, runtime_error, ""), "");
EXPECT_NONFATAL_FAILURE(EXPECT_THROW_MSG(throw 1, runtime_error, ""), "");
EXPECT_NONFATAL_FAILURE(EXPECT_THROW_MSG(
throw runtime_error("a"), runtime_error, "b"), "");
}
// Tests that the compiler will not complain about unreachable code in the
// EXPECT_SYSTEM_ERROR macro.
TEST(ExpectSystemErrorTest, DoesNotGenerateUnreachableCodeWarning) {
int n = 0;
EXPECT_SYSTEM_ERROR(throw fmt::SystemError(EDOM, "test"), EDOM, "test");
EXPECT_NONFATAL_FAILURE(EXPECT_SYSTEM_ERROR(n++, EDOM, ""), "");
EXPECT_NONFATAL_FAILURE(EXPECT_SYSTEM_ERROR(throw 1, EDOM, ""), "");
EXPECT_NONFATAL_FAILURE(EXPECT_SYSTEM_ERROR(
throw fmt::SystemError(EDOM, "aaa"), EDOM, "bbb"), "");
}
TEST(AssertionSyntaxTest, ExceptionAssertionBehavesLikeSingleStatement) {
if (::testing::internal::AlwaysFalse())
EXPECT_THROW_MSG(do_nothing(), std::exception, "");
if (::testing::internal::AlwaysTrue())
EXPECT_THROW_MSG(throw_exception(), std::exception, "test");
else
do_nothing();
}
TEST(AssertionSyntaxTest, SystemErrorAssertionBehavesLikeSingleStatement) {
if (::testing::internal::AlwaysFalse())
EXPECT_SYSTEM_ERROR(do_nothing(), EDOM, "");
if (::testing::internal::AlwaysTrue())
EXPECT_SYSTEM_ERROR(throw_system_error(), EDOM, "test");
else
do_nothing();
}
TEST(AssertionSyntaxTest, WriteAssertionBehavesLikeSingleStatement) {
if (::testing::internal::AlwaysFalse())
EXPECT_WRITE(stdout, std::printf("x"), "x");
if (::testing::internal::AlwaysTrue())
EXPECT_WRITE(stdout, std::printf("x"), "x");
else
do_nothing();
}
// Tests EXPECT_THROW_MSG.
TEST(ExpectTest, EXPECT_THROW_MSG) {
EXPECT_THROW_MSG(throw_exception(), std::exception, "test");
EXPECT_NONFATAL_FAILURE(
EXPECT_THROW_MSG(throw_exception(), std::logic_error, "test"),
"Expected: throw_exception() throws an exception of "
"type std::logic_error.\n Actual: it throws a different type.");
EXPECT_NONFATAL_FAILURE(
EXPECT_THROW_MSG(do_nothing(), std::exception, "test"),
"Expected: do_nothing() throws an exception of type std::exception.\n"
" Actual: it throws nothing.");
EXPECT_NONFATAL_FAILURE(
EXPECT_THROW_MSG(throw_exception(), std::exception, "other"),
"throw_exception() throws an exception with a different message.\n"
"Expected: other\n"
" Actual: test");
}
// Tests EXPECT_SYSTEM_ERROR.
TEST(ExpectTest, EXPECT_SYSTEM_ERROR) {
EXPECT_SYSTEM_ERROR(throw_system_error(), EDOM, "test");
EXPECT_NONFATAL_FAILURE(
EXPECT_SYSTEM_ERROR(throw_exception(), EDOM, "test"),
"Expected: throw_exception() throws an exception of "
"type fmt::SystemError.\n Actual: it throws a different type.");
EXPECT_NONFATAL_FAILURE(
EXPECT_SYSTEM_ERROR(do_nothing(), EDOM, "test"),
"Expected: do_nothing() throws an exception of type fmt::SystemError.\n"
" Actual: it throws nothing.");
EXPECT_NONFATAL_FAILURE(
EXPECT_SYSTEM_ERROR(throw_system_error(), EDOM, "other"),
fmt::format(
"throw_system_error() throws an exception with a different message.\n"
"Expected: {}\n"
" Actual: {}",
format_system_error(EDOM, "other"),
format_system_error(EDOM, "test")));
}
// Tests EXPECT_WRITE.
TEST(ExpectTest, EXPECT_WRITE) {
EXPECT_WRITE(stdout, do_nothing(), "");
EXPECT_WRITE(stdout, std::printf("test"), "test");
EXPECT_WRITE(stderr, std::fprintf(stderr, "test"), "test");
EXPECT_NONFATAL_FAILURE(
EXPECT_WRITE(stdout, std::printf("that"), "this"),
"Expected: this\n"
" Actual: that");
}
TEST(StreamingAssertionsTest, EXPECT_THROW_MSG) {
EXPECT_THROW_MSG(throw_exception(), std::exception, "test")
<< "unexpected failure";
EXPECT_NONFATAL_FAILURE(
EXPECT_THROW_MSG(throw_exception(), std::exception, "other")
<< "expected failure", "expected failure");
}
TEST(StreamingAssertionsTest, EXPECT_SYSTEM_ERROR) {
EXPECT_SYSTEM_ERROR(throw_system_error(), EDOM, "test")
<< "unexpected failure";
EXPECT_NONFATAL_FAILURE(
EXPECT_SYSTEM_ERROR(throw_system_error(), EDOM, "other")
<< "expected failure", "expected failure");
}
TEST(StreamingAssertionsTest, EXPECT_WRITE) {
EXPECT_WRITE(stdout, std::printf("test"), "test")
<< "unexpected failure";
EXPECT_NONFATAL_FAILURE(
EXPECT_WRITE(stdout, std::printf("test"), "other")
<< "expected failure", "expected failure");
}
TEST(UtilTest, FormatSystemError) {
fmt::MemoryWriter out;
fmt::internal::format_system_error(out, EDOM, "test message");
EXPECT_EQ(out.str(), format_system_error(EDOM, "test message"));
}
#if FMT_USE_FILE_DESCRIPTORS
using fmt::BufferedFile;
using fmt::ErrorCode;
using fmt::File;
// Checks if the file is open by reading one character from it.
bool isopen(int fd) {
char buffer;
return FMT_POSIX(read(fd, &buffer, 1)) == 1;
}
bool isclosed(int fd) {
char buffer;
std::streamsize result = 0;
SUPPRESS_ASSERT(result = FMT_POSIX(read(fd, &buffer, 1)));
return result == -1 && errno == EBADF;
}
// Attempts to read count characters from a file.
std::string read(File &f, std::size_t count) {
std::string buffer(count, '\0');
std::streamsize n = 0;
std::size_t offset = 0;
do {
n = f.read(&buffer[offset], count - offset);
// We can't read more than size_t bytes since count has type size_t.
offset += static_cast<std::size_t>(n);
} while (offset < count && n != 0);
buffer.resize(offset);
return buffer;
}
// Attempts to write a string to a file.
void write(File &f, fmt::StringRef s) {
std::size_t num_chars_left = s.size();
const char *ptr = s.c_str();
do {
std::streamsize count = f.write(ptr, num_chars_left);
ptr += count;
// We can't write more than size_t bytes since num_chars_left
// has type size_t.
num_chars_left -= static_cast<std::size_t>(count);
} while (num_chars_left != 0);
}
#define EXPECT_READ(file, expected_content) \
EXPECT_EQ(expected_content, read(file, std::strlen(expected_content)))
TEST(ErrorCodeTest, Ctor) {
EXPECT_EQ(0, ErrorCode().get());
EXPECT_EQ(42, ErrorCode(42).get());
}
const char FILE_CONTENT[] = "Don't panic!";
// Opens a file for reading.
File open_file() {
File read_end, write_end;
File::pipe(read_end, write_end);
write_end.write(FILE_CONTENT, sizeof(FILE_CONTENT) - 1);
write_end.close();
return read_end;
}
// Opens a buffered file for reading.
BufferedFile open_buffered_file(FILE **fp = 0) {
File read_end, write_end;
File::pipe(read_end, write_end);
write_end.write(FILE_CONTENT, sizeof(FILE_CONTENT) - 1);
write_end.close();
BufferedFile f = read_end.fdopen("r");
if (fp)
*fp = f.get();
return f;
}
TEST(BufferedFileTest, DefaultCtor) {
BufferedFile f;
EXPECT_TRUE(f.get() == 0);
}
TEST(BufferedFileTest, MoveCtor) {
BufferedFile bf = open_buffered_file();
FILE *fp = bf.get();
EXPECT_TRUE(fp != 0);
BufferedFile bf2(std::move(bf));
EXPECT_EQ(fp, bf2.get());
EXPECT_TRUE(bf.get() == 0);
}
TEST(BufferedFileTest, MoveAssignment) {
BufferedFile bf = open_buffered_file();
FILE *fp = bf.get();
EXPECT_TRUE(fp != 0);
BufferedFile bf2;
bf2 = std::move(bf);
EXPECT_EQ(fp, bf2.get());
EXPECT_TRUE(bf.get() == 0);
}
TEST(BufferedFileTest, MoveAssignmentClosesFile) {
BufferedFile bf = open_buffered_file();
BufferedFile bf2 = open_buffered_file();
int old_fd = bf2.fileno();
bf2 = std::move(bf);
EXPECT_TRUE(isclosed(old_fd));
}
TEST(BufferedFileTest, MoveFromTemporaryInCtor) {
FILE *fp = 0;
BufferedFile f(open_buffered_file(&fp));
EXPECT_EQ(fp, f.get());
}
TEST(BufferedFileTest, MoveFromTemporaryInAssignment) {
FILE *fp = 0;
BufferedFile f;
f = open_buffered_file(&fp);
EXPECT_EQ(fp, f.get());
}
TEST(BufferedFileTest, MoveFromTemporaryInAssignmentClosesFile) {
BufferedFile f = open_buffered_file();
int old_fd = f.fileno();
f = open_buffered_file();
EXPECT_TRUE(isclosed(old_fd));
}
TEST(BufferedFileTest, CloseFileInDtor) {
int fd = 0;
{
BufferedFile f = open_buffered_file();
fd = f.fileno();
}
EXPECT_TRUE(isclosed(fd));
}
TEST(BufferedFileTest, CloseErrorInDtor) {
BufferedFile *f = new BufferedFile(open_buffered_file());
EXPECT_WRITE(stderr, {
// The close function must be called inside EXPECT_WRITE, otherwise
// the system may recycle closed file descriptor when redirecting the
// output in EXPECT_STDERR and the second close will break output
// redirection.
FMT_POSIX(close(f->fileno()));
SUPPRESS_ASSERT(delete f);
}, format_system_error(EBADF, "cannot close file") + "\n");
}
TEST(BufferedFileTest, Close) {
BufferedFile f = open_buffered_file();
int fd = f.fileno();
f.close();
EXPECT_TRUE(f.get() == 0);
EXPECT_TRUE(isclosed(fd));
}
TEST(BufferedFileTest, CloseError) {
BufferedFile f = open_buffered_file();
FMT_POSIX(close(f.fileno()));
EXPECT_SYSTEM_ERROR_NOASSERT(f.close(), EBADF, "cannot close file");
EXPECT_TRUE(f.get() == 0);
}
TEST(BufferedFileTest, Fileno) {
BufferedFile f;
// fileno on a null FILE pointer either crashes or returns an error.
EXPECT_DEATH({
try {
f.fileno();
} catch (fmt::SystemError) {
std::exit(1);
}
}, "");
f = open_buffered_file();
EXPECT_TRUE(f.fileno() != -1);
File copy = File::dup(f.fileno());
EXPECT_READ(copy, FILE_CONTENT);
}
TEST(FileTest, DefaultCtor) {
File f;
EXPECT_EQ(-1, f.descriptor());
}
TEST(FileTest, OpenBufferedFileInCtor) {
FILE *fp = fopen("test-file", "w");
std::fputs(FILE_CONTENT, fp);
std::fclose(fp);
File f("test-file", File::RDONLY);
ASSERT_TRUE(isopen(f.descriptor()));
}
TEST(FileTest, OpenBufferedFileError) {
EXPECT_SYSTEM_ERROR(File("nonexistent", File::RDONLY),
ENOENT, "cannot open file nonexistent");
}
TEST(FileTest, MoveCtor) {
File f = open_file();
int fd = f.descriptor();
EXPECT_NE(-1, fd);
File f2(std::move(f));
EXPECT_EQ(fd, f2.descriptor());
EXPECT_EQ(-1, f.descriptor());
}
TEST(FileTest, MoveAssignment) {
File f = open_file();
int fd = f.descriptor();
EXPECT_NE(-1, fd);
File f2;
f2 = std::move(f);
EXPECT_EQ(fd, f2.descriptor());
EXPECT_EQ(-1, f.descriptor());
}
TEST(FileTest, MoveAssignmentClosesFile) {
File f = open_file();
File f2 = open_file();
int old_fd = f2.descriptor();
f2 = std::move(f);
EXPECT_TRUE(isclosed(old_fd));
}
File OpenBufferedFile(int &fd) {
File f = open_file();
fd = f.descriptor();
return std::move(f);
}
TEST(FileTest, MoveFromTemporaryInCtor) {
int fd = 0xdeadbeef;
File f(OpenBufferedFile(fd));
EXPECT_EQ(fd, f.descriptor());
}
TEST(FileTest, MoveFromTemporaryInAssignment) {
int fd = 0xdeadbeef;
File f;
f = OpenBufferedFile(fd);
EXPECT_EQ(fd, f.descriptor());
}
TEST(FileTest, MoveFromTemporaryInAssignmentClosesFile) {
int fd = 0xdeadbeef;
File f = open_file();
int old_fd = f.descriptor();
f = OpenBufferedFile(fd);
EXPECT_TRUE(isclosed(old_fd));
}
TEST(FileTest, CloseFileInDtor) {
int fd = 0;
{
File f = open_file();
fd = f.descriptor();
}
EXPECT_TRUE(isclosed(fd));
}
TEST(FileTest, CloseErrorInDtor) {
File *f = new File(open_file());
EXPECT_WRITE(stderr, {
// The close function must be called inside EXPECT_WRITE, otherwise
// the system may recycle closed file descriptor when redirecting the
// output in EXPECT_STDERR and the second close will break output
// redirection.
FMT_POSIX(close(f->descriptor()));
SUPPRESS_ASSERT(delete f);
}, format_system_error(EBADF, "cannot close file") + "\n");
}
TEST(FileTest, Close) {
File f = open_file();
int fd = f.descriptor();
f.close();
EXPECT_EQ(-1, f.descriptor());
EXPECT_TRUE(isclosed(fd));
}
TEST(FileTest, CloseError) {
File f = open_file();
FMT_POSIX(close(f.descriptor()));
EXPECT_SYSTEM_ERROR_NOASSERT(f.close(), EBADF, "cannot close file");
EXPECT_EQ(-1, f.descriptor());
}
TEST(FileTest, Read) {
File f = open_file();
EXPECT_READ(f, FILE_CONTENT);
}
TEST(FileTest, ReadError) {
File read_end, write_end;
File::pipe(read_end, write_end);
char buf;
// We intentionally read from write_end to cause error.
EXPECT_SYSTEM_ERROR(write_end.read(&buf, 1), EBADF, "cannot read from file");
}
TEST(FileTest, Write) {
File read_end, write_end;
File::pipe(read_end, write_end);
write(write_end, "test");
write_end.close();
EXPECT_READ(read_end, "test");
}
TEST(FileTest, WriteError) {
File read_end, write_end;
File::pipe(read_end, write_end);
// We intentionally write to read_end to cause error.
EXPECT_SYSTEM_ERROR(read_end.write(" ", 1), EBADF, "cannot write to file");
}
TEST(FileTest, Dup) {
File f = open_file();
File copy = File::dup(f.descriptor());
EXPECT_NE(f.descriptor(), copy.descriptor());
EXPECT_EQ(FILE_CONTENT, read(copy, sizeof(FILE_CONTENT) - 1));
}
TEST(FileTest, DupError) {
EXPECT_SYSTEM_ERROR_NOASSERT(File::dup(-1),
EBADF, "cannot duplicate file descriptor -1");
}
TEST(FileTest, Dup2) {
File f = open_file();
File copy = open_file();
f.dup2(copy.descriptor());
EXPECT_NE(f.descriptor(), copy.descriptor());
EXPECT_READ(copy, FILE_CONTENT);
}
TEST(FileTest, Dup2Error) {
File f = open_file();
EXPECT_SYSTEM_ERROR_NOASSERT(f.dup2(-1), EBADF,
fmt::format("cannot duplicate file descriptor {} to -1", f.descriptor()));
}
TEST(FileTest, Dup2NoExcept) {
File f = open_file();
File copy = open_file();
ErrorCode ec;
f.dup2(copy.descriptor(), ec);
EXPECT_EQ(0, ec.get());
EXPECT_NE(f.descriptor(), copy.descriptor());
EXPECT_READ(copy, FILE_CONTENT);
}
TEST(FileTest, Dup2NoExceptError) {
File f = open_file();
ErrorCode ec;
SUPPRESS_ASSERT(f.dup2(-1, ec));
EXPECT_EQ(EBADF, ec.get());
}
TEST(FileTest, Pipe) {
File read_end, write_end;
File::pipe(read_end, write_end);
EXPECT_NE(-1, read_end.descriptor());
EXPECT_NE(-1, write_end.descriptor());
write(write_end, "test");
EXPECT_READ(read_end, "test");
}
TEST(FileTest, Fdopen) {
File read_end, write_end;
File::pipe(read_end, write_end);
int read_fd = read_end.descriptor();
EXPECT_EQ(read_fd, FMT_POSIX(fileno(read_end.fdopen("r").get())));
}
TEST(FileTest, FdopenError) {
File f;
EXPECT_SYSTEM_ERROR_NOASSERT(
f.fdopen("r"), EBADF, "cannot associate stream with file descriptor");
}
TEST(OutputRedirectTest, ScopedRedirect) {
File read_end, write_end;
File::pipe(read_end, write_end);
{
BufferedFile file(write_end.fdopen("w"));
std::fprintf(file.get(), "[[[");
{
OutputRedirect redir(file.get());
std::fprintf(file.get(), "censored");
}
std::fprintf(file.get(), "]]]");
}
EXPECT_READ(read_end, "[[[]]]");
}
// Test that OutputRedirect handles errors in flush correctly.
TEST(OutputRedirectTest, FlushErrorInCtor) {
File read_end, write_end;
File::pipe(read_end, write_end);
int write_fd = write_end.descriptor();
File write_copy = write_end.dup(write_fd);
BufferedFile f = write_end.fdopen("w");
// Put a character in a file buffer.
EXPECT_EQ('x', fputc('x', f.get()));
FMT_POSIX(close(write_fd));
OutputRedirect *redir = 0;
EXPECT_SYSTEM_ERROR_NOASSERT(redir = new OutputRedirect(f.get()),
EBADF, "cannot flush stream");
delete redir;
write_copy.dup2(write_fd); // "undo" close or dtor will fail
}
TEST(OutputRedirectTest, DupErrorInCtor) {
BufferedFile f = open_buffered_file();
int fd = f.fileno();
File copy = File::dup(fd);
FMT_POSIX(close(fd));
OutputRedirect *redir = 0;
EXPECT_SYSTEM_ERROR_NOASSERT(redir = new OutputRedirect(f.get()),
EBADF, fmt::format("cannot duplicate file descriptor {}", fd));
copy.dup2(fd); // "undo" close or dtor will fail
delete redir;
}
TEST(OutputRedirectTest, RestoreAndRead) {
File read_end, write_end;
File::pipe(read_end, write_end);
BufferedFile file(write_end.fdopen("w"));
std::fprintf(file.get(), "[[[");
OutputRedirect redir(file.get());
std::fprintf(file.get(), "censored");
EXPECT_EQ("censored", redir.restore_and_read());
EXPECT_EQ("", redir.restore_and_read());
std::fprintf(file.get(), "]]]");
file = BufferedFile();
EXPECT_READ(read_end, "[[[]]]");
}
// Test that OutputRedirect handles errors in flush correctly.
TEST(OutputRedirectTest, FlushErrorInRestoreAndRead) {
File read_end, write_end;
File::pipe(read_end, write_end);
int write_fd = write_end.descriptor();
File write_copy = write_end.dup(write_fd);
BufferedFile f = write_end.fdopen("w");
OutputRedirect redir(f.get());
// Put a character in a file buffer.
EXPECT_EQ('x', fputc('x', f.get()));
FMT_POSIX(close(write_fd));
EXPECT_SYSTEM_ERROR_NOASSERT(redir.restore_and_read(),
EBADF, "cannot flush stream");
write_copy.dup2(write_fd); // "undo" close or dtor will fail
}
TEST(OutputRedirectTest, ErrorInDtor) {
File read_end, write_end;
File::pipe(read_end, write_end);
int write_fd = write_end.descriptor();
File write_copy = write_end.dup(write_fd);
BufferedFile f = write_end.fdopen("w");
OutputRedirect *redir = new OutputRedirect(f.get());
// Put a character in a file buffer.
EXPECT_EQ('x', fputc('x', f.get()));
EXPECT_WRITE(stderr, {
// The close function must be called inside EXPECT_WRITE, otherwise
// the system may recycle closed file descriptor when redirecting the
// output in EXPECT_STDERR and the second close will break output
// redirection.
FMT_POSIX(close(write_fd));
SUPPRESS_ASSERT(delete redir);
}, format_system_error(EBADF, "cannot flush stream"));
write_copy.dup2(write_fd); // "undo" close or dtor of BufferedFile will fail
}
#endif // FMT_USE_FILE_DESCRIPTORS
} // namespace

98
test/gtest-extra.cc Normal file
View File

@@ -0,0 +1,98 @@
/*
Custom Google Test assertions.
Copyright (c) 2012-2014, Victor Zverovich
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "gtest-extra.h"
#if FMT_USE_FILE_DESCRIPTORS
using fmt::File;
void OutputRedirect::flush() {
#if EOF != -1
# error "FMT_RETRY assumes return value of -1 indicating failure"
#endif
int result = 0;
FMT_RETRY(result, fflush(file_));
if (result != 0)
throw fmt::SystemError(errno, "cannot flush stream");
}
void OutputRedirect::restore() {
if (original_.descriptor() == -1)
return; // Already restored.
flush();
// Restore the original file.
original_.dup2(FMT_POSIX(fileno(file_)));
original_.close();
}
OutputRedirect::OutputRedirect(FILE *file) : file_(file) {
flush();
int fd = FMT_POSIX(fileno(file));
// Create a File object referring to the original file.
original_ = File::dup(fd);
// Create a pipe.
File write_end;
File::pipe(read_end_, write_end);
// Connect the passed FILE object to the write end of the pipe.
write_end.dup2(fd);
}
OutputRedirect::~OutputRedirect() FMT_NOEXCEPT {
try {
restore();
} catch (const std::exception &e) {
std::fputs(e.what(), stderr);
}
}
std::string OutputRedirect::restore_and_read() {
// Restore output.
restore();
// Read everything from the pipe.
std::string content;
if (read_end_.descriptor() == -1)
return content; // Already read.
enum { BUFFER_SIZE = 4096 };
char buffer[BUFFER_SIZE];
std::streamsize count = 0;
do {
count = read_end_.read(buffer, BUFFER_SIZE);
content.append(buffer, static_cast<std::size_t>(count));
} while (count != 0);
read_end_.close();
return content;
}
#endif // FMT_USE_FILE_DESCRIPTORS
std::string format_system_error(int error_code, fmt::StringRef message) {
fmt::MemoryWriter out;
fmt::internal::format_system_error(out, error_code, message);
return out.str();
}

138
test/gtest-extra.h Normal file
View File

@@ -0,0 +1,138 @@
/*
Custom Google Test assertions.
Copyright (c) 2012-2014, Victor Zverovich
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef FMT_GTEST_EXTRA_H_
#define FMT_GTEST_EXTRA_H_
#include <string>
#include <gtest/gtest.h>
#include "format.h"
#ifndef FMT_USE_FILE_DESCRIPTORS
# define FMT_USE_FILE_DESCRIPTORS 0
#endif
#if FMT_USE_FILE_DESCRIPTORS
# include "posix.h"
#endif
#define FMT_TEST_THROW_(statement, expected_exception, expected_message, fail) \
GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
if (::testing::AssertionResult gtest_ar = ::testing::AssertionSuccess()) { \
std::string gtest_expected_message = expected_message; \
bool gtest_caught_expected = false; \
try { \
GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \
} \
catch (expected_exception const& e) { \
if (gtest_expected_message != e.what()) { \
gtest_ar \
<< #statement " throws an exception with a different message.\n" \
<< "Expected: " << gtest_expected_message << "\n" \
<< " Actual: " << e.what(); \
goto GTEST_CONCAT_TOKEN_(gtest_label_testthrow_, __LINE__); \
} \
gtest_caught_expected = true; \
} \
catch (...) { \
gtest_ar << \
"Expected: " #statement " throws an exception of type " \
#expected_exception ".\n Actual: it throws a different type."; \
goto GTEST_CONCAT_TOKEN_(gtest_label_testthrow_, __LINE__); \
} \
if (!gtest_caught_expected) { \
gtest_ar << \
"Expected: " #statement " throws an exception of type " \
#expected_exception ".\n Actual: it throws nothing."; \
goto GTEST_CONCAT_TOKEN_(gtest_label_testthrow_, __LINE__); \
} \
} else \
GTEST_CONCAT_TOKEN_(gtest_label_testthrow_, __LINE__): \
fail(gtest_ar.failure_message())
// Tests that the statement throws the expected exception and the exception's
// what() method returns expected message.
#define EXPECT_THROW_MSG(statement, expected_exception, expected_message) \
FMT_TEST_THROW_(statement, expected_exception, \
expected_message, GTEST_NONFATAL_FAILURE_)
std::string format_system_error(int error_code, fmt::StringRef message);
#define EXPECT_SYSTEM_ERROR(statement, error_code, message) \
EXPECT_THROW_MSG(statement, fmt::SystemError, \
format_system_error(error_code, message))
#if FMT_USE_FILE_DESCRIPTORS
// Captures file output by redirecting it to a pipe.
// The output it can handle is limited by the pipe capacity.
class OutputRedirect {
private:
FILE *file_;
fmt::File original_; // Original file passed to redirector.
fmt::File read_end_; // Read end of the pipe where the output is redirected.
GTEST_DISALLOW_COPY_AND_ASSIGN_(OutputRedirect);
void flush();
void restore();
public:
explicit OutputRedirect(FILE *file);
~OutputRedirect() FMT_NOEXCEPT;
// Restores the original file, reads output from the pipe into a string
// and returns it.
std::string restore_and_read();
};
#define FMT_TEST_WRITE_(statement, expected_output, file, fail) \
GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
if (::testing::AssertionResult gtest_ar = ::testing::AssertionSuccess()) { \
std::string gtest_expected_output = expected_output; \
OutputRedirect gtest_redir(file); \
GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \
std::string gtest_output = gtest_redir.restore_and_read(); \
if (gtest_output != gtest_expected_output) { \
gtest_ar \
<< #statement " produces different output.\n" \
<< "Expected: " << gtest_expected_output << "\n" \
<< " Actual: " << gtest_output; \
goto GTEST_CONCAT_TOKEN_(gtest_label_testthrow_, __LINE__); \
} \
} else \
GTEST_CONCAT_TOKEN_(gtest_label_testthrow_, __LINE__): \
fail(gtest_ar.failure_message())
// Tests that the statement writes the expected output to file.
#define EXPECT_WRITE(file, statement, expected_output) \
FMT_TEST_WRITE_(statement, expected_output, file, GTEST_NONFATAL_FAILURE_)
#endif // FMT_USE_FILE_DESCRIPTORS
#endif // FMT_GTEST_EXTRA_H_

28
test/header-only-test.cc Normal file
View File

@@ -0,0 +1,28 @@
/*
Header-only configuration test
Copyright (c) 2014, Victor Zverovich
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "format.h"

28
test/header-only-test2.cc Normal file
View File

@@ -0,0 +1,28 @@
/*
Additional translation unit for the header-only configuration test
Copyright (c) 2014, Victor Zverovich
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "format.h"

113
test/macro-test.cc Normal file
View File

@@ -0,0 +1,113 @@
/*
Tests of variadic function emulation macros.
Copyright (c) 2012-2014, Victor Zverovich
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <utility>
#include <gtest/gtest.h>
#include "format.h"
#define IDENTITY(x) x
TEST(UtilTest, Gen) {
int values[] = {FMT_GEN(10, IDENTITY)};
for (int i = 0; i < 10; ++i)
EXPECT_EQ(i, values[i]);
}
#define MAKE_PAIR(x, y) std::make_pair(x, y)
TEST(UtilTest, ForEach) {
std::pair<char, int> values[] = {
FMT_FOR_EACH10(MAKE_PAIR, 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j')
};
for (int i = 0; i < 10; ++i) {
EXPECT_EQ('a' + i, values[i].first);
EXPECT_EQ(i, values[i].second);
}
}
TEST(UtilTest, NArg) {
EXPECT_EQ(1, FMT_NARG(a));
EXPECT_EQ(2, FMT_NARG(a, b));
EXPECT_EQ(3, FMT_NARG(a, b, c));
EXPECT_EQ(4, FMT_NARG(a, b, c, d));
EXPECT_EQ(5, FMT_NARG(a, b, c, d, e));
EXPECT_EQ(6, FMT_NARG(a, b, c, d, e, f));
EXPECT_EQ(7, FMT_NARG(a, b, c, d, e, f, g));
EXPECT_EQ(8, FMT_NARG(a, b, c, d, e, f, g, h));
EXPECT_EQ(9, FMT_NARG(a, b, c, d, e, f, g, h, i));
EXPECT_EQ(10, FMT_NARG(a, b, c, d, e, f, g, h, i, j));
}
int result;
#define MAKE_TEST(func) \
void func(const char *format, const fmt::ArgList &args) { \
result = 0; \
for (unsigned i = 0; args[i].type; ++i) \
result += args[i].int_value; \
}
MAKE_TEST(test_func)
typedef char Char;
FMT_WRAP1(test_func, const char *, 1)
TEST(UtilTest, Wrap1) {
result = 0;
test_func("", 42);
EXPECT_EQ(42, result);
}
MAKE_TEST(test_variadic_void)
FMT_VARIADIC_VOID(test_variadic_void, const char *)
TEST(UtilTest, VariadicVoid) {
result = 0;
test_variadic_void("", 10, 20, 30, 40, 50, 60, 70, 80, 90, 100);
EXPECT_EQ(550, result);
}
template <int>
struct S {};
#define GET_TYPE(n) S<n>
int test_variadic(FMT_GEN(10, GET_TYPE), const fmt::ArgList &args) { \
int result = 0; \
for (std::size_t i = 0; args[i].type; ++i) \
result += args[i].int_value; \
return result;
}
FMT_VARIADIC(int, test_variadic,
S<0>, S<1>, S<2>, S<3>, S<4>, S<5>, S<6>, S<7>, S<8>, S<9>)
#define MAKE_ARG(n) S<n>()
TEST(UtilTest, Variadic) {
EXPECT_EQ(550, test_variadic(FMT_GEN(10, MAKE_ARG),
10, 20, 30, 40, 50, 60, 70, 80, 90, 100));
}

85
test/mock-allocator.h Normal file
View File

@@ -0,0 +1,85 @@
/*
Mock allocator.
Copyright (c) 2014, Victor Zverovich
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef FMT_MOCK_ALLOCATOR_H_
#define FMT_MOCK_ALLOCATOR_H_
#include "gmock/gmock.h"
template <typename T>
class MockAllocator {
public:
MockAllocator() {}
MockAllocator(const MockAllocator &) {}
typedef T value_type;
MOCK_METHOD1_T(allocate, T* (std::size_t n));
MOCK_METHOD2_T(deallocate, void (T* p, std::size_t n));
};
template <typename Allocator>
class AllocatorRef {
private:
Allocator *alloc_;
public:
typedef typename Allocator::value_type value_type;
explicit AllocatorRef(Allocator *alloc = 0) : alloc_(alloc) {}
AllocatorRef(const AllocatorRef &other) : alloc_(other.alloc_) {}
AllocatorRef& operator=(const AllocatorRef &other) {
alloc_ = other.alloc_;
return *this;
}
#if FMT_USE_RVALUE_REFERENCES
private:
void move(AllocatorRef &other) {
alloc_ = other.alloc_;
other.alloc_ = 0;
}
public:
AllocatorRef(AllocatorRef &&other) {
move(other);
}
AllocatorRef& operator=(AllocatorRef &&other) {
assert(this != &other);
move(other);
return *this;
}
#endif
Allocator *get() const { return alloc_; }
value_type* allocate(std::size_t n) { return alloc_->allocate(n); }
void deallocate(value_type* p, std::size_t n) { alloc_->deallocate(p, n); }
};
#endif // FMT_MOCK_ALLOCATOR_H_

437
test/posix-test.cc Normal file
View File

@@ -0,0 +1,437 @@
/*
Test wrappers around POSIX functions.
Copyright (c) 2012-2014, Victor Zverovich
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
// Disable bogus MSVC warnings.
#define _CRT_SECURE_NO_WARNINGS
#include "posix-test.h"
#include <errno.h>
#include <fcntl.h>
#include <climits>
#ifdef _WIN32
# include <io.h>
# undef max
# undef ERROR
#endif
#include "gtest-extra.h"
using fmt::BufferedFile;
using fmt::ErrorCode;
using fmt::File;
namespace {
int open_count;
int close_count;
int dup_count;
int dup2_count;
int fdopen_count;
int read_count;
int write_count;
int pipe_count;
int fopen_count;
int fclose_count;
int fileno_count;
std::size_t read_nbyte;
std::size_t write_nbyte;
bool sysconf_error;
enum FStatSimulation { NONE, MAX_SIZE, ERROR } fstat_sim;
}
#define EMULATE_EINTR(func, error_result) \
if (func##_count != 0) { \
if (func##_count++ != 3) { \
errno = EINTR; \
return error_result; \
} \
}
#ifndef _WIN32
int test::open(const char *path, int oflag, int mode) {
EMULATE_EINTR(open, -1);
return ::open(path, oflag, mode);
}
static off_t max_file_size() { return std::numeric_limits<off_t>::max(); }
int test::fstat(int fd, struct stat *buf) {
int result = ::fstat(fd, buf);
if (fstat_sim == MAX_SIZE)
buf->st_size = max_file_size();
return result;
}
long test::sysconf(int name) {
long result = ::sysconf(name);
if (!sysconf_error)
return result;
// Simulate an error.
errno = EINVAL;
return -1;
}
#else
errno_t test::sopen_s(
int* pfh, const char *filename, int oflag, int shflag, int pmode) {
EMULATE_EINTR(open, EINTR);
return _sopen_s(pfh, filename, oflag, shflag, pmode);
}
static LONGLONG max_file_size() { return std::numeric_limits<LONGLONG>::max(); }
BOOL test::GetFileSizeEx(HANDLE hFile, PLARGE_INTEGER lpFileSize) {
if (fstat_sim == ERROR) {
SetLastError(ERROR_ACCESS_DENIED);
return FALSE;
}
BOOL result = ::GetFileSizeEx(hFile, lpFileSize);
if (fstat_sim == MAX_SIZE)
lpFileSize->QuadPart = max_file_size();
return result;
}
#endif
int test::close(int fildes) {
// Close the file first because close shouldn't be retried.
int result = ::FMT_POSIX(close(fildes));
EMULATE_EINTR(close, -1);
return result;
}
int test::dup(int fildes) {
EMULATE_EINTR(dup, -1);
return ::FMT_POSIX(dup(fildes));
}
int test::dup2(int fildes, int fildes2) {
EMULATE_EINTR(dup2, -1);
return ::FMT_POSIX(dup2(fildes, fildes2));
}
FILE *test::fdopen(int fildes, const char *mode) {
EMULATE_EINTR(fdopen, 0);
return ::FMT_POSIX(fdopen(fildes, mode));
}
test::ssize_t test::read(int fildes, void *buf, test::size_t nbyte) {
read_nbyte = nbyte;
EMULATE_EINTR(read, -1);
return ::FMT_POSIX(read(fildes, buf, nbyte));
}
test::ssize_t test::write(int fildes, const void *buf, test::size_t nbyte) {
write_nbyte = nbyte;
EMULATE_EINTR(write, -1);
return ::FMT_POSIX(write(fildes, buf, nbyte));
}
#ifndef _WIN32
int test::pipe(int fildes[2]) {
EMULATE_EINTR(pipe, -1);
return ::pipe(fildes);
}
#else
int test::pipe(int *pfds, unsigned psize, int textmode) {
EMULATE_EINTR(pipe, -1);
return _pipe(pfds, psize, textmode);
}
#endif
FILE *test::fopen(const char *filename, const char *mode) {
EMULATE_EINTR(fopen, 0);
return ::fopen(filename, mode);
}
int test::fclose(FILE *stream) {
EMULATE_EINTR(fclose, EOF);
return ::fclose(stream);
}
int test::fileno(FILE *stream) {
EMULATE_EINTR(fileno, -1);
return ::FMT_POSIX(fileno(stream));
}
#ifndef _WIN32
# define EXPECT_RETRY(statement, func, message) \
func##_count = 1; \
statement; \
EXPECT_EQ(4, func##_count); \
func##_count = 0;
# define EXPECT_EQ_POSIX(expected, actual) EXPECT_EQ(expected, actual)
#else
# define EXPECT_RETRY(statement, func, message) \
func##_count = 1; \
EXPECT_SYSTEM_ERROR(statement, EINTR, message); \
func##_count = 0;
# define EXPECT_EQ_POSIX(expected, actual)
#endif
void write_file(fmt::StringRef filename, fmt::StringRef content) {
fmt::BufferedFile f(filename, "w");
f.print("{}", content);
}
TEST(UtilTest, StaticAssert) {
FMT_STATIC_ASSERT(true, "success");
// Static assertion failure is tested in compile-test because it causes
// a compile-time error.
}
TEST(UtilTest, GetPageSize) {
#ifdef _WIN32
SYSTEM_INFO si = {};
GetSystemInfo(&si);
EXPECT_EQ(si.dwPageSize, fmt::getpagesize());
#else
EXPECT_EQ(sysconf(_SC_PAGESIZE), fmt::getpagesize());
sysconf_error = true;
EXPECT_SYSTEM_ERROR(
fmt::getpagesize(), EINVAL, "cannot get memory page size");
sysconf_error = false;
#endif
}
TEST(FileTest, OpenRetry) {
write_file("test", "there must be something here");
File *f = 0;
EXPECT_RETRY(f = new File("test", File::RDONLY),
open, "cannot open file test");
#ifndef _WIN32
char c = 0;
f->read(&c, 1);
#endif
delete f;
}
TEST(FileTest, CloseNoRetryInDtor) {
File read_end, write_end;
File::pipe(read_end, write_end);
File *f = new File(std::move(read_end));
int saved_close_count = 0;
EXPECT_WRITE(stderr, {
close_count = 1;
delete f;
saved_close_count = close_count;
close_count = 0;
}, format_system_error(EINTR, "cannot close file") + "\n");
EXPECT_EQ(2, saved_close_count);
}
TEST(FileTest, CloseNoRetry) {
File read_end, write_end;
File::pipe(read_end, write_end);
close_count = 1;
EXPECT_SYSTEM_ERROR(read_end.close(), EINTR, "cannot close file");
EXPECT_EQ(2, close_count);
close_count = 0;
}
TEST(FileTest, Size) {
std::string content = "top secret, destroy before reading";
write_file("test", content);
File f("test", File::RDONLY);
EXPECT_GE(f.size(), 0);
fmt::ULongLong file_size = f.size();
EXPECT_EQ(content.size(), file_size);
#ifdef _WIN32
fmt::MemoryWriter message;
fmt::internal::format_windows_error(
message, ERROR_ACCESS_DENIED, "cannot get file size");
fstat_sim = ERROR;
EXPECT_THROW_MSG(f.size(), fmt::WindowsError, message.str());
fstat_sim = NONE;
#else
f.close();
EXPECT_SYSTEM_ERROR(f.size(), EBADF, "cannot get file attributes");
#endif
}
TEST(FileTest, MaxSize) {
write_file("test", "");
File f("test", File::RDONLY);
fstat_sim = MAX_SIZE;
EXPECT_GE(f.size(), 0);
EXPECT_EQ(max_file_size(), f.size());
fstat_sim = NONE;
}
TEST(FileTest, ReadRetry) {
File read_end, write_end;
File::pipe(read_end, write_end);
enum { SIZE = 4 };
write_end.write("test", SIZE);
write_end.close();
char buffer[SIZE];
std::streamsize count = 0;
EXPECT_RETRY(count = read_end.read(buffer, SIZE),
read, "cannot read from file");
EXPECT_EQ_POSIX(static_cast<std::streamsize>(SIZE), count);
}
TEST(FileTest, WriteRetry) {
File read_end, write_end;
File::pipe(read_end, write_end);
enum { SIZE = 4 };
std::streamsize count = 0;
EXPECT_RETRY(count = write_end.write("test", SIZE),
write, "cannot write to file");
write_end.close();
#ifndef _WIN32
EXPECT_EQ(static_cast<std::streamsize>(SIZE), count);
char buffer[SIZE + 1];
read_end.read(buffer, SIZE);
buffer[SIZE] = '\0';
EXPECT_STREQ("test", buffer);
#endif
}
#ifdef _WIN32
TEST(FileTest, ConvertReadCount) {
File read_end, write_end;
File::pipe(read_end, write_end);
char c;
std::size_t size = UINT_MAX;
if (sizeof(unsigned) != sizeof(std::size_t))
++size;
read_count = 1;
read_nbyte = 0;
EXPECT_THROW(read_end.read(&c, size), fmt::SystemError);
read_count = 0;
EXPECT_EQ(UINT_MAX, read_nbyte);
}
TEST(FileTest, ConvertWriteCount) {
File read_end, write_end;
File::pipe(read_end, write_end);
char c;
std::size_t size = UINT_MAX;
if (sizeof(unsigned) != sizeof(std::size_t))
++size;
write_count = 1;
write_nbyte = 0;
EXPECT_THROW(write_end.write(&c, size), fmt::SystemError);
write_count = 0;
EXPECT_EQ(UINT_MAX, write_nbyte);
}
#endif
TEST(FileTest, DupNoRetry) {
int stdout_fd = FMT_POSIX(fileno(stdout));
dup_count = 1;
EXPECT_SYSTEM_ERROR(File::dup(stdout_fd), EINTR,
fmt::format("cannot duplicate file descriptor {}", stdout_fd));
dup_count = 0;
}
TEST(FileTest, Dup2Retry) {
int stdout_fd = FMT_POSIX(fileno(stdout));
File f1 = File::dup(stdout_fd), f2 = File::dup(stdout_fd);
EXPECT_RETRY(f1.dup2(f2.descriptor()), dup2,
fmt::format("cannot duplicate file descriptor {} to {}",
f1.descriptor(), f2.descriptor()));
}
TEST(FileTest, Dup2NoExceptRetry) {
int stdout_fd = FMT_POSIX(fileno(stdout));
File f1 = File::dup(stdout_fd), f2 = File::dup(stdout_fd);
ErrorCode ec;
dup2_count = 1;
f1.dup2(f2.descriptor(), ec);
#ifndef _WIN32
EXPECT_EQ(4, dup2_count);
#else
EXPECT_EQ(EINTR, ec.get());
#endif
dup2_count = 0;
}
TEST(FileTest, PipeNoRetry) {
File read_end, write_end;
pipe_count = 1;
EXPECT_SYSTEM_ERROR(
File::pipe(read_end, write_end), EINTR, "cannot create pipe");
pipe_count = 0;
}
TEST(FileTest, FdopenNoRetry) {
File read_end, write_end;
File::pipe(read_end, write_end);
fdopen_count = 1;
EXPECT_SYSTEM_ERROR(read_end.fdopen("r"),
EINTR, "cannot associate stream with file descriptor");
fdopen_count = 0;
}
TEST(BufferedFileTest, OpenRetry) {
write_file("test", "there must be something here");
BufferedFile *f = 0;
EXPECT_RETRY(f = new BufferedFile("test", "r"),
fopen, "cannot open file test");
#ifndef _WIN32
char c = 0;
if (fread(&c, 1, 1, f->get()) < 1)
throw fmt::SystemError(errno, "fread failed");
#endif
delete f;
}
TEST(BufferedFileTest, CloseNoRetryInDtor) {
File read_end, write_end;
File::pipe(read_end, write_end);
BufferedFile *f = new BufferedFile(read_end.fdopen("r"));
int saved_fclose_count = 0;
EXPECT_WRITE(stderr, {
fclose_count = 1;
delete f;
saved_fclose_count = fclose_count;
fclose_count = 0;
}, format_system_error(EINTR, "cannot close file") + "\n");
EXPECT_EQ(2, saved_fclose_count);
}
TEST(BufferedFileTest, CloseNoRetry) {
File read_end, write_end;
File::pipe(read_end, write_end);
BufferedFile f = read_end.fdopen("r");
fclose_count = 1;
EXPECT_SYSTEM_ERROR(f.close(), EINTR, "cannot close file");
EXPECT_EQ(2, fclose_count);
fclose_count = 0;
}
TEST(BufferedFileTest, FilenoNoRetry) {
File read_end, write_end;
File::pipe(read_end, write_end);
BufferedFile f = read_end.fdopen("r");
fileno_count = 1;
EXPECT_SYSTEM_ERROR(f.fileno(), EINTR, "cannot get file descriptor");
EXPECT_EQ(2, fileno_count);
fileno_count = 0;
}

81
test/posix-test.h Normal file
View File

@@ -0,0 +1,81 @@
/*
Test wrappers around POSIX functions.
Copyright (c) 2012-2014, Victor Zverovich
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef FMT_POSIX_TEST_H
#define FMT_POSIX_TEST_H
#include <errno.h>
#include <stdio.h>
#ifndef _WIN32
struct stat;
#else
# include <windows.h>
#endif
namespace test {
#ifndef _WIN32
// Size type for read and write.
typedef size_t size_t;
typedef ssize_t ssize_t;
int open(const char *path, int oflag, int mode);
int fstat(int fd, struct stat *buf);
long sysconf(int name);
#else
typedef unsigned size_t;
typedef int ssize_t;
errno_t sopen_s(
int* pfh, const char *filename, int oflag, int shflag, int pmode);
BOOL GetFileSizeEx(HANDLE hFile, PLARGE_INTEGER lpFileSize);
#endif
int close(int fildes);
int dup(int fildes);
int dup2(int fildes, int fildes2);
FILE *fdopen(int fildes, const char *mode);
ssize_t read(int fildes, void *buf, size_t nbyte);
ssize_t write(int fildes, const void *buf, size_t nbyte);
#ifndef _WIN32
int pipe(int fildes[2]);
#else
int pipe(int *pfds, unsigned psize, int textmode);
#endif
FILE *fopen(const char *filename, const char *mode);
int fclose(FILE *stream);
int fileno(FILE *stream);
} // namespace test
#define FMT_SYSTEM(call) test::call
#endif // FMT_POSIX_TEST_H

448
test/printf-test.cc Normal file
View File

@@ -0,0 +1,448 @@
/*
printf tests.
Copyright (c) 2012-2014, Victor Zverovich
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <cctype>
#include <climits>
#include <cstring>
#include "format.h"
#include "gtest-extra.h"
#include "util.h"
using fmt::format;
using fmt::FormatError;
const unsigned BIG_NUM = INT_MAX + 1u;
// Makes format string argument positional.
std::string make_positional(fmt::StringRef format) {
std::string s(format);
s.replace(s.find('%'), 1, "%1$");
return s;
}
#define EXPECT_PRINTF(expected_output, format, arg) \
EXPECT_EQ(expected_output, fmt::sprintf(format, arg)) \
<< "format: " << format; \
EXPECT_EQ(expected_output, fmt::sprintf(make_positional(format), arg))
TEST(PrintfTest, NoArgs) {
EXPECT_EQ("test", fmt::sprintf("test"));
}
TEST(PrintfTest, Escape) {
EXPECT_EQ("%", fmt::sprintf("%%"));
EXPECT_EQ("before %", fmt::sprintf("before %%"));
EXPECT_EQ("% after", fmt::sprintf("%% after"));
EXPECT_EQ("before % after", fmt::sprintf("before %% after"));
EXPECT_EQ("%s", fmt::sprintf("%%s"));
}
TEST(PrintfTest, PositionalArgs) {
EXPECT_EQ("42", fmt::sprintf("%1$d", 42));
EXPECT_EQ("before 42", fmt::sprintf("before %1$d", 42));
EXPECT_EQ("42 after", fmt::sprintf("%1$d after",42));
EXPECT_EQ("before 42 after", fmt::sprintf("before %1$d after", 42));
EXPECT_EQ("answer = 42", fmt::sprintf("%1$s = %2$d", "answer", 42));
EXPECT_EQ("42 is the answer",
fmt::sprintf("%2$d is the %1$s", "answer", 42));
EXPECT_EQ("abracadabra", fmt::sprintf("%1$s%2$s%1$s", "abra", "cad"));
}
TEST(PrintfTest, AutomaticArgIndexing) {
EXPECT_EQ("abc", fmt::sprintf("%c%c%c", 'a', 'b', 'c'));
}
TEST(PrintfTest, NumberIsTooBigInArgIndex) {
EXPECT_THROW_MSG(fmt::sprintf(format("%{}$", BIG_NUM)),
FormatError, "number is too big");
EXPECT_THROW_MSG(fmt::sprintf(format("%{}$d", BIG_NUM)),
FormatError, "number is too big");
}
TEST(PrintfTest, SwitchArgIndexing) {
EXPECT_THROW_MSG(fmt::sprintf("%1$d%", 1, 2),
FormatError, "invalid format string");
EXPECT_THROW_MSG(fmt::sprintf(format("%1$d%{}d", BIG_NUM), 1, 2),
FormatError, "number is too big");
EXPECT_THROW_MSG(fmt::sprintf("%1$d%d", 1, 2),
FormatError, "cannot switch from manual to automatic argument indexing");
EXPECT_THROW_MSG(fmt::sprintf("%d%1$", 1, 2),
FormatError, "invalid format string");
EXPECT_THROW_MSG(fmt::sprintf(format("%d%{}$d", BIG_NUM), 1, 2),
FormatError, "number is too big");
EXPECT_THROW_MSG(fmt::sprintf("%d%1$d", 1, 2),
FormatError, "cannot switch from automatic to manual argument indexing");
// Indexing errors override width errors.
EXPECT_THROW_MSG(fmt::sprintf(format("%d%1${}d", BIG_NUM), 1, 2),
FormatError, "number is too big");
EXPECT_THROW_MSG(fmt::sprintf(format("%1$d%{}d", BIG_NUM), 1, 2),
FormatError, "number is too big");
}
TEST(PrintfTest, InvalidArgIndex) {
EXPECT_THROW_MSG(fmt::sprintf("%0$d", 42), FormatError,
"argument index out of range");
EXPECT_THROW_MSG(fmt::sprintf("%2$d", 42), FormatError,
"argument index out of range");
EXPECT_THROW_MSG(fmt::sprintf(format("%{}$d", INT_MAX), 42),
FormatError, "argument index out of range");
EXPECT_THROW_MSG(fmt::sprintf("%2$", 42),
FormatError, "invalid format string");
EXPECT_THROW_MSG(fmt::sprintf(format("%{}$d", BIG_NUM), 42),
FormatError, "number is too big");
}
TEST(PrintfTest, DefaultAlignRight) {
EXPECT_PRINTF(" 42", "%5d", 42);
EXPECT_PRINTF(" abc", "%5s", "abc");
}
TEST(PrintfTest, ZeroFlag) {
EXPECT_PRINTF("00042", "%05d", 42);
EXPECT_PRINTF("-0042", "%05d", -42);
EXPECT_PRINTF("00042", "%05d", 42);
EXPECT_PRINTF("-0042", "%05d", -42);
EXPECT_PRINTF("-004.2", "%06g", -4.2);
EXPECT_PRINTF("+00042", "%00+6d", 42);
// '0' flag is ignored for non-numeric types.
EXPECT_PRINTF(" x", "%05c", 'x');
}
TEST(PrintfTest, PlusFlag) {
EXPECT_PRINTF("+42", "%+d", 42);
EXPECT_PRINTF("-42", "%+d", -42);
EXPECT_PRINTF("+0042", "%+05d", 42);
EXPECT_PRINTF("+0042", "%0++5d", 42);
// '+' flag is ignored for non-numeric types.
EXPECT_PRINTF("x", "%+c", 'x');
}
TEST(PrintfTest, MinusFlag) {
EXPECT_PRINTF("abc ", "%-5s", "abc");
EXPECT_PRINTF("abc ", "%0--5s", "abc");
}
TEST(PrintfTest, SpaceFlag) {
EXPECT_PRINTF(" 42", "% d", 42);
EXPECT_PRINTF("-42", "% d", -42);
EXPECT_PRINTF(" 0042", "% 05d", 42);
EXPECT_PRINTF(" 0042", "%0 5d", 42);
// ' ' flag is ignored for non-numeric types.
EXPECT_PRINTF("x", "% c", 'x');
}
TEST(PrintfTest, HashFlag) {
EXPECT_PRINTF("042", "%#o", 042);
EXPECT_PRINTF(fmt::format("0{:o}", static_cast<unsigned>(-042)), "%#o", -042);
EXPECT_PRINTF("0", "%#o", 0);
EXPECT_PRINTF("0x42", "%#x", 0x42);
EXPECT_PRINTF("0X42", "%#X", 0x42);
EXPECT_PRINTF(
fmt::format("0x{:x}", static_cast<unsigned>(-0x42)), "%#x", -0x42);
EXPECT_PRINTF("0", "%#x", 0);
EXPECT_PRINTF("0x0042", "%#06x", 0x42);
EXPECT_PRINTF("0x0042", "%0##6x", 0x42);
EXPECT_PRINTF("-42.000000", "%#f", -42.0);
EXPECT_PRINTF("-42.000000", "%#F", -42.0);
char buffer[BUFFER_SIZE];
safe_sprintf(buffer, "%#e", -42.0);
EXPECT_PRINTF(buffer, "%#e", -42.0);
safe_sprintf(buffer, "%#E", -42.0);
EXPECT_PRINTF(buffer, "%#E", -42.0);
EXPECT_PRINTF("-42.0000", "%#g", -42.0);
EXPECT_PRINTF("-42.0000", "%#G", -42.0);
safe_sprintf(buffer, "%#a", 16.0);
EXPECT_PRINTF(buffer, "%#a", 16.0);
safe_sprintf(buffer, "%#A", 16.0);
EXPECT_PRINTF(buffer, "%#A", 16.0);
// '#' flag is ignored for non-numeric types.
EXPECT_PRINTF("x", "%#c", 'x');
}
TEST(PrintfTest, Width) {
EXPECT_PRINTF(" abc", "%5s", "abc");
// Width cannot be specified twice.
EXPECT_THROW_MSG(fmt::sprintf("%5-5d", 42), FormatError,
"unknown format code '-' for integer");
EXPECT_THROW_MSG(fmt::sprintf(format("%{}d", BIG_NUM), 42),
FormatError, "number is too big");
EXPECT_THROW_MSG(fmt::sprintf(format("%1${}d", BIG_NUM), 42),
FormatError, "number is too big");
}
TEST(PrintfTest, DynamicWidth) {
EXPECT_EQ(" 42", fmt::sprintf("%*d", 5, 42));
EXPECT_EQ("42 ", fmt::sprintf("%*d", -5, 42));
EXPECT_THROW_MSG(fmt::sprintf("%*d", 5.0, 42), FormatError,
"width is not integer");
EXPECT_THROW_MSG(fmt::sprintf("%*d"), FormatError,
"argument index out of range");
EXPECT_THROW_MSG(fmt::sprintf("%*d", BIG_NUM, 42), FormatError,
"number is too big");
}
TEST(PrintfTest, IntPrecision) {
EXPECT_PRINTF("00042", "%.5d", 42);
EXPECT_PRINTF("-00042", "%.5d", -42);
EXPECT_PRINTF("00042", "%.5x", 0x42);
EXPECT_PRINTF("0x00042", "%#.5x", 0x42);
EXPECT_PRINTF("00042", "%.5o", 042);
EXPECT_PRINTF("00042", "%#.5o", 042);
EXPECT_PRINTF(" 00042", "%7.5d", 42);
EXPECT_PRINTF(" 00042", "%7.5x", 0x42);
EXPECT_PRINTF(" 0x00042", "%#10.5x", 0x42);
EXPECT_PRINTF(" 00042", "%7.5o", 042);
EXPECT_PRINTF(" 00042", "%#10.5o", 042);
EXPECT_PRINTF("00042 ", "%-7.5d", 42);
EXPECT_PRINTF("00042 ", "%-7.5x", 0x42);
EXPECT_PRINTF("0x00042 ", "%-#10.5x", 0x42);
EXPECT_PRINTF("00042 ", "%-7.5o", 042);
EXPECT_PRINTF("00042 ", "%-#10.5o", 042);
}
TEST(PrintfTest, FloatPrecision) {
char buffer[BUFFER_SIZE];
safe_sprintf(buffer, "%.3e", 1234.5678);
EXPECT_PRINTF(buffer, "%.3e", 1234.5678);
EXPECT_PRINTF("1234.568", "%.3f", 1234.5678);
safe_sprintf(buffer, "%.3g", 1234.5678);
EXPECT_PRINTF(buffer, "%.3g", 1234.5678);
safe_sprintf(buffer, "%.3a", 1234.5678);
EXPECT_PRINTF(buffer, "%.3a", 1234.5678);
}
TEST(PrintfTest, IgnorePrecisionForNonNumericArg) {
EXPECT_PRINTF("abc", "%.5s", "abc");
}
TEST(PrintfTest, DynamicPrecision) {
EXPECT_EQ("00042", fmt::sprintf("%.*d", 5, 42));
EXPECT_EQ("42", fmt::sprintf("%.*d", -5, 42));
EXPECT_THROW_MSG(fmt::sprintf("%.*d", 5.0, 42), FormatError,
"precision is not integer");
EXPECT_THROW_MSG(fmt::sprintf("%.*d"), FormatError,
"argument index out of range");
EXPECT_THROW_MSG(fmt::sprintf("%.*d", BIG_NUM, 42), FormatError,
"number is too big");
if (sizeof(fmt::LongLong) != sizeof(int)) {
fmt::LongLong prec = static_cast<fmt::LongLong>(INT_MIN) - 1;
EXPECT_THROW_MSG(fmt::sprintf("%.*d", prec, 42), FormatError,
"number is too big");
}
}
template <typename T>
struct MakeSigned { typedef T Type; };
#define SPECIALIZE_MAKE_SIGNED(T, S) \
template <> \
struct MakeSigned<T> { typedef S Type; }
SPECIALIZE_MAKE_SIGNED(char, signed char);
SPECIALIZE_MAKE_SIGNED(unsigned char, signed char);
SPECIALIZE_MAKE_SIGNED(unsigned short, short);
SPECIALIZE_MAKE_SIGNED(unsigned, int);
SPECIALIZE_MAKE_SIGNED(unsigned long, long);
SPECIALIZE_MAKE_SIGNED(fmt::ULongLong, fmt::LongLong);
template <typename T, typename U>
void TestLength(const char *length_spec, U value) {
fmt::LongLong signed_value = value;
fmt::ULongLong unsigned_value = value;
// Apply integer promotion to the argument.
fmt::ULongLong max = std::numeric_limits<U>::max();
if (max <= static_cast<unsigned>(std::numeric_limits<int>::max())) {
signed_value = static_cast<int>(value);
unsigned_value = static_cast<int>(value);
} else if (max <= std::numeric_limits<unsigned>::max()) {
signed_value = static_cast<unsigned>(value);
unsigned_value = static_cast<unsigned>(value);
}
using fmt::internal::MakeUnsigned;
if (sizeof(U) <= sizeof(int) && sizeof(int) < sizeof(T)) {
signed_value = unsigned_value =
static_cast<typename MakeUnsigned<unsigned>::Type>(value);
} else {
signed_value = static_cast<typename MakeSigned<T>::Type>(value);
unsigned_value = static_cast<typename MakeUnsigned<T>::Type>(value);
}
std::ostringstream os;
os << signed_value;
EXPECT_PRINTF(os.str(), fmt::format("%{}d", length_spec), value);
EXPECT_PRINTF(os.str(), fmt::format("%{}i", length_spec), value);
os.str("");
os << unsigned_value;
EXPECT_PRINTF(os.str(), fmt::format("%{}u", length_spec), value);
os.str("");
os << std::oct << unsigned_value;
EXPECT_PRINTF(os.str(), fmt::format("%{}o", length_spec), value);
os.str("");
os << std::hex << unsigned_value;
EXPECT_PRINTF(os.str(), fmt::format("%{}x", length_spec), value);
os.str("");
os << std::hex << std::uppercase << unsigned_value;
EXPECT_PRINTF(os.str(), fmt::format("%{}X", length_spec), value);
}
template <typename T>
void TestLength(const char *length_spec) {
T min = std::numeric_limits<T>::min(), max = std::numeric_limits<T>::max();
TestLength<T>(length_spec, 42);
TestLength<T>(length_spec, -42);
TestLength<T>(length_spec, min);
TestLength<T>(length_spec, max);
if (min >= 0 || static_cast<fmt::LongLong>(min) >
std::numeric_limits<fmt::LongLong>::min()) {
TestLength<T>(length_spec, fmt::LongLong(min) - 1);
}
fmt::ULongLong long_long_max = std::numeric_limits<fmt::LongLong>::max();
if (max < 0 || static_cast<fmt::ULongLong>(max) < long_long_max)
TestLength<T>(length_spec, fmt::LongLong(max) + 1);
TestLength<T>(length_spec, std::numeric_limits<short>::min());
TestLength<T>(length_spec, std::numeric_limits<unsigned short>::max());
TestLength<T>(length_spec, std::numeric_limits<int>::min());
TestLength<T>(length_spec, std::numeric_limits<int>::max());
TestLength<T>(length_spec, std::numeric_limits<unsigned>::min());
TestLength<T>(length_spec, std::numeric_limits<unsigned>::max());
TestLength<T>(length_spec, std::numeric_limits<fmt::LongLong>::min());
TestLength<T>(length_spec, std::numeric_limits<fmt::LongLong>::max());
TestLength<T>(length_spec, std::numeric_limits<fmt::ULongLong>::min());
TestLength<T>(length_spec, std::numeric_limits<fmt::ULongLong>::max());
}
TEST(PrintfTest, Length) {
TestLength<char>("hh");
TestLength<signed char>("hh");
TestLength<unsigned char>("hh");
TestLength<short>("h");
TestLength<unsigned short>("h");
TestLength<long>("l");
TestLength<unsigned long>("l");
TestLength<fmt::LongLong>("ll");
TestLength<fmt::ULongLong>("ll");
TestLength<intmax_t>("j");
TestLength<std::size_t>("z");
TestLength<std::ptrdiff_t>("t");
long double max = std::numeric_limits<long double>::max();
EXPECT_PRINTF(fmt::format("{}", max), "%g", max);
EXPECT_PRINTF(fmt::format("{}", max), "%Lg", max);
}
TEST(PrintfTest, Int) {
EXPECT_PRINTF("-42", "%d", -42);
EXPECT_PRINTF("-42", "%i", -42);
unsigned u = -42;
EXPECT_PRINTF(fmt::format("{}", u), "%u", -42);
EXPECT_PRINTF(fmt::format("{:o}", u), "%o", -42);
EXPECT_PRINTF(fmt::format("{:x}", u), "%x", -42);
EXPECT_PRINTF(fmt::format("{:X}", u), "%X", -42);
}
TEST(PrintfTest, Float) {
EXPECT_PRINTF("392.650000", "%f", 392.65);
EXPECT_PRINTF("392.650000", "%F", 392.65);
char buffer[BUFFER_SIZE];
safe_sprintf(buffer, "%e", 392.65);
EXPECT_PRINTF(buffer, "%e", 392.65);
safe_sprintf(buffer, "%E", 392.65);
EXPECT_PRINTF(buffer, "%E", 392.65);
EXPECT_PRINTF("392.65", "%g", 392.65);
EXPECT_PRINTF("392.65", "%G", 392.65);
safe_sprintf(buffer, "%a", -392.65);
EXPECT_EQ(buffer, format("{:a}", -392.65));
safe_sprintf(buffer, "%A", -392.65);
EXPECT_EQ(buffer, format("{:A}", -392.65));
}
TEST(PrintfTest, Inf) {
double inf = std::numeric_limits<double>::infinity();
for (const char* type = "fega"; *type; ++type) {
EXPECT_PRINTF("inf", fmt::format("%{}", *type), inf);
char upper = std::toupper(*type);
EXPECT_PRINTF("INF", fmt::format("%{}", upper), inf);
}
}
TEST(PrintfTest, Char) {
EXPECT_PRINTF("x", "%c", 'x');
int max = std::numeric_limits<int>::max();
EXPECT_PRINTF(fmt::format("{}", static_cast<char>(max)), "%c", max);
//EXPECT_PRINTF("x", "%lc", L'x');
// TODO: test wchar_t
}
TEST(PrintfTest, String) {
EXPECT_PRINTF("abc", "%s", "abc");
// TODO: wide string
}
TEST(PrintfTest, Pointer) {
int n;
void *p = &n;
EXPECT_PRINTF(fmt::format("{}", p), "%p", p);
}
TEST(PrintfTest, Location) {
// TODO: test %n
}
#if FMT_USE_FILE_DESCRIPTORS
TEST(PrintfTest, Examples) {
const char *weekday = "Thursday";
const char *month = "August";
int day = 21;
EXPECT_WRITE(stdout, fmt::printf("%1$s, %3$d %2$s", weekday, month, day),
"Thursday, 21 August");
}
TEST(PrintfTest, PrintfError) {
fmt::File read_end, write_end;
fmt::File::pipe(read_end, write_end);
int result = fmt::fprintf(read_end.fdopen("r").get(), "test");
EXPECT_LT(result, 0);
}
#endif

50
test/test-main.cc Normal file
View File

@@ -0,0 +1,50 @@
/*
Tests of additional gtest macros.
Copyright (c) 2012-2014, Victor Zverovich
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <gtest/gtest.h>
#ifdef _WIN32
# include <windows.h>
# include <crtdbg.h>
#endif
int main(int argc, char **argv) {
#ifdef _WIN32
// Don't display any error dialogs. This also suppresses message boxes
// on assertion failures in MinGW where _set_error_mode/CrtSetReportMode
// doesn't help.
SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX |
SEM_NOOPENFILEERRORBOX);
// Disable message boxes on assertion failures.
_CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG);
_CrtSetReportFile(_CRT_ERROR, _CRTDBG_FILE_STDERR);
_CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG);
_CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR);
#endif
testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}

834
test/util-test.cc Normal file
View File

@@ -0,0 +1,834 @@
/*
Utility tests.
Copyright (c) 2012-2014, Victor Zverovich
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <cfloat>
#include <climits>
#include <cstring>
#include <limits>
#if FMT_USE_TYPE_TRAITS
# include <type_traits>
#endif
#include "gmock/gmock.h"
#include "gtest-extra.h"
#include "mock-allocator.h"
#include "util.h"
// Check if format.h compiles with windows.h included.
#ifdef _WIN32
# include <windows.h>
#endif
#include "format.h"
#undef max
using fmt::StringRef;
using fmt::internal::Arg;
using fmt::internal::Value;
using fmt::internal::Buffer;
using fmt::internal::MemoryBuffer;
using testing::Return;
using testing::StrictMock;
namespace {
struct Test {};
template <typename Char>
std::basic_ostream<Char> &operator<<(std::basic_ostream<Char> &os, Test) {
return os << "test";
}
template <typename Char, typename T>
Arg make_arg(const T &value) {
Arg arg = Arg();
Value &arg_value = arg;
arg_value = fmt::internal::MakeValue<Char>(value);
arg.type = static_cast<Arg::Type>(
fmt::internal::MakeValue<Char>::type(value));
return arg;
}
} // namespace
void CheckForwarding(
MockAllocator<int> &alloc, AllocatorRef< MockAllocator<int> > &ref) {
int mem;
// Check if value_type is properly defined.
AllocatorRef< MockAllocator<int> >::value_type *ptr = &mem;
// Check forwarding.
EXPECT_CALL(alloc, allocate(42)).WillOnce(Return(ptr));
ref.allocate(42);
EXPECT_CALL(alloc, deallocate(ptr, 42));
ref.deallocate(ptr, 42);
}
TEST(AllocatorTest, AllocatorRef) {
StrictMock< MockAllocator<int> > alloc;
typedef AllocatorRef< MockAllocator<int> > TestAllocatorRef;
TestAllocatorRef ref(&alloc);
// Check if AllocatorRef forwards to the underlying allocator.
CheckForwarding(alloc, ref);
TestAllocatorRef ref2(ref);
CheckForwarding(alloc, ref2);
TestAllocatorRef ref3;
EXPECT_EQ(0, ref3.get());
ref3 = ref;
CheckForwarding(alloc, ref3);
}
#if FMT_USE_TYPE_TRAITS
TEST(BufferTest, Noncopyable) {
EXPECT_FALSE(std::is_copy_constructible<Buffer<char> >::value);
EXPECT_FALSE(std::is_copy_assignable<Buffer<char> >::value);
}
TEST(BufferTest, Nonmoveable) {
EXPECT_FALSE(std::is_move_constructible<Buffer<char> >::value);
EXPECT_FALSE(std::is_move_assignable<Buffer<char> >::value);
}
#endif
// A test buffer with a dummy grow method.
template <typename T>
struct TestBuffer : Buffer<T> {
void grow(std::size_t size) { this->capacity_ = size; }
};
template <typename T>
struct MockBuffer : Buffer<T> {
MOCK_METHOD1(do_grow, void (std::size_t size));
void grow(std::size_t size) {
this->capacity_ = size;
do_grow(size);
}
MockBuffer() {}
MockBuffer(T *ptr) : Buffer<T>(ptr) {}
MockBuffer(T *ptr, std::size_t capacity) : Buffer<T>(ptr, capacity) {}
};
TEST(BufferTest, Ctor) {
{
MockBuffer<int> buffer;
EXPECT_EQ(0, &buffer[0]);
EXPECT_EQ(0u, buffer.size());
EXPECT_EQ(0u, buffer.capacity());
}
{
int dummy;
MockBuffer<int> buffer(&dummy);
EXPECT_EQ(&dummy, &buffer[0]);
EXPECT_EQ(0u, buffer.size());
EXPECT_EQ(0u, buffer.capacity());
}
{
int dummy;
std::size_t capacity = std::numeric_limits<std::size_t>::max();
MockBuffer<int> buffer(&dummy, capacity);
EXPECT_EQ(&dummy, &buffer[0]);
EXPECT_EQ(0u, buffer.size());
EXPECT_EQ(capacity, buffer.capacity());
}
}
struct DyingBuffer : TestBuffer<int> {
MOCK_METHOD0(die, void());
~DyingBuffer() { die(); }
};
TEST(BufferTest, VirtualDtor) {
typedef StrictMock<DyingBuffer> StictMockBuffer;
StictMockBuffer *mock_buffer = new StictMockBuffer();
EXPECT_CALL(*mock_buffer, die());
Buffer<int> *buffer = mock_buffer;
delete buffer;
}
TEST(BufferTest, Access) {
char data[10];
MockBuffer<char> buffer(data, sizeof(data));
buffer[0] = 11;
EXPECT_EQ(11, buffer[0]);
buffer[3] = 42;
EXPECT_EQ(42, *(&buffer[0] + 3));
const Buffer<char> &const_buffer = buffer;
EXPECT_EQ(42, const_buffer[3]);
}
TEST(BufferTest, Resize) {
char data[123];
MockBuffer<char> buffer(data, sizeof(data));
buffer[10] = 42;
EXPECT_EQ(42, buffer[10]);
buffer.resize(20);
EXPECT_EQ(20u, buffer.size());
EXPECT_EQ(123u, buffer.capacity());
EXPECT_EQ(42, buffer[10]);
buffer.resize(5);
EXPECT_EQ(5u, buffer.size());
EXPECT_EQ(123u, buffer.capacity());
EXPECT_EQ(42, buffer[10]);
// Check if resize calls grow.
EXPECT_CALL(buffer, do_grow(124));
buffer.resize(124);
EXPECT_CALL(buffer, do_grow(200));
buffer.resize(200);
}
TEST(BufferTest, Clear) {
TestBuffer<char> buffer;
buffer.resize(20);
buffer.clear();
EXPECT_EQ(0u, buffer.size());
EXPECT_EQ(20u, buffer.capacity());
}
TEST(BufferTest, PushBack) {
int data[15];
MockBuffer<int> buffer(data, 10);
buffer.push_back(11);
EXPECT_EQ(11, buffer[0]);
EXPECT_EQ(1u, buffer.size());
buffer.resize(10);
EXPECT_CALL(buffer, do_grow(11));
buffer.push_back(22);
EXPECT_EQ(22, buffer[10]);
EXPECT_EQ(11u, buffer.size());
}
TEST(BufferTest, Append) {
char data[15];
MockBuffer<char> buffer(data, 10);
const char *test = "test";
buffer.append(test, test + 5);
EXPECT_STREQ(test, &buffer[0]);
EXPECT_EQ(5u, buffer.size());
buffer.resize(10);
EXPECT_CALL(buffer, do_grow(12));
buffer.append(test, test + 2);
EXPECT_EQ('t', buffer[10]);
EXPECT_EQ('e', buffer[11]);
EXPECT_EQ(12u, buffer.size());
}
TEST(BufferTest, AppendAllocatesEnoughStorage) {
char data[19];
MockBuffer<char> buffer(data, 10);
const char *test = "abcdefgh";
buffer.resize(10);
EXPECT_CALL(buffer, do_grow(19));
buffer.append(test, test + 9);
}
TEST(MemoryBufferTest, Ctor) {
MemoryBuffer<char, 123> buffer;
EXPECT_EQ(0u, buffer.size());
EXPECT_EQ(123u, buffer.capacity());
}
#if FMT_USE_RVALUE_REFERENCES
typedef AllocatorRef< std::allocator<char> > TestAllocator;
void check_move_buffer(const char *str,
MemoryBuffer<char, 5, TestAllocator> &buffer) {
std::allocator<char> *alloc = buffer.get_allocator().get();
MemoryBuffer<char, 5, TestAllocator> buffer2(std::move(buffer));
// Move shouldn't destroy the inline content of the first buffer.
EXPECT_EQ(str, std::string(&buffer[0], buffer.size()));
EXPECT_EQ(str, std::string(&buffer2[0], buffer2.size()));
EXPECT_EQ(5u, buffer2.capacity());
// Move should transfer allocator.
EXPECT_EQ(0, buffer.get_allocator().get());
EXPECT_EQ(alloc, buffer2.get_allocator().get());
}
TEST(MemoryBufferTest, MoveCtor) {
std::allocator<char> alloc;
MemoryBuffer<char, 5, TestAllocator> buffer((TestAllocator(&alloc)));
const char test[] = "test";
buffer.append(test, test + 4);
check_move_buffer("test", buffer);
// Adding one more character fills the inline buffer, but doesn't cause
// dynamic allocation.
buffer.push_back('a');
check_move_buffer("testa", buffer);
const char *inline_buffer_ptr = &buffer[0];
// Adding one more character causes the content to move from the inline to
// a dynamically allocated buffer.
buffer.push_back('b');
MemoryBuffer<char, 5, TestAllocator> buffer2(std::move(buffer));
// Move should rip the guts of the first buffer.
EXPECT_EQ(inline_buffer_ptr, &buffer[0]);
EXPECT_EQ("testab", std::string(&buffer2[0], buffer2.size()));
EXPECT_GT(buffer2.capacity(), 5u);
}
void check_move_assign_buffer(const char *str, MemoryBuffer<char, 5> &buffer) {
MemoryBuffer<char, 5> buffer2;
buffer2 = std::move(buffer);
// Move shouldn't destroy the inline content of the first buffer.
EXPECT_EQ(str, std::string(&buffer[0], buffer.size()));
EXPECT_EQ(str, std::string(&buffer2[0], buffer2.size()));
EXPECT_EQ(5u, buffer2.capacity());
}
TEST(MemoryBufferTest, MoveAssignment) {
MemoryBuffer<char, 5> buffer;
const char test[] = "test";
buffer.append(test, test + 4);
check_move_assign_buffer("test", buffer);
// Adding one more character fills the inline buffer, but doesn't cause
// dynamic allocation.
buffer.push_back('a');
check_move_assign_buffer("testa", buffer);
const char *inline_buffer_ptr = &buffer[0];
// Adding one more character causes the content to move from the inline to
// a dynamically allocated buffer.
buffer.push_back('b');
MemoryBuffer<char, 5> buffer2;
buffer2 = std::move(buffer);
// Move should rip the guts of the first buffer.
EXPECT_EQ(inline_buffer_ptr, &buffer[0]);
EXPECT_EQ("testab", std::string(&buffer2[0], buffer2.size()));
EXPECT_GT(buffer2.capacity(), 5u);
}
#endif // FMT_USE_RVALUE_REFERENCES
TEST(MemoryBufferTest, Grow) {
typedef AllocatorRef< MockAllocator<int> > Allocator;
typedef MemoryBuffer<int, 10, Allocator> Base;
MockAllocator<int> alloc;
struct TestMemoryBuffer : Base {
TestMemoryBuffer(Allocator alloc) : Base(alloc) {}
void grow(std::size_t size) { Base::grow(size); }
} buffer((Allocator(&alloc)));
buffer.resize(7);
for (int i = 0; i < 7; ++i)
buffer[i] = i * i;
EXPECT_EQ(10u, buffer.capacity());
int mem[20];
mem[7] = 0xdead;
EXPECT_CALL(alloc, allocate(20)).WillOnce(Return(mem));
buffer.grow(20);
EXPECT_EQ(20u, buffer.capacity());
// Check if size elements have been copied
for (int i = 0; i < 7; ++i)
EXPECT_EQ(i * i, buffer[i]);
// and no more than that.
EXPECT_EQ(0xdead, buffer[7]);
EXPECT_CALL(alloc, deallocate(mem, 20));
}
TEST(MemoryBufferTest, Allocator) {
typedef AllocatorRef< MockAllocator<char> > TestAllocator;
MemoryBuffer<char, 10, TestAllocator> buffer;
EXPECT_EQ(0, buffer.get_allocator().get());
StrictMock< MockAllocator<char> > alloc;
char mem;
{
MemoryBuffer<char, 10, TestAllocator> buffer2((TestAllocator(&alloc)));
EXPECT_EQ(&alloc, buffer2.get_allocator().get());
std::size_t size = 2 * fmt::internal::INLINE_BUFFER_SIZE;
EXPECT_CALL(alloc, allocate(size)).WillOnce(Return(&mem));
buffer2.reserve(size);
EXPECT_CALL(alloc, deallocate(&mem, size));
}
}
TEST(MemoryBufferTest, ExceptionInDeallocate) {
typedef AllocatorRef< MockAllocator<char> > TestAllocator;
StrictMock< MockAllocator<char> > alloc;
MemoryBuffer<char, 10, TestAllocator> buffer((TestAllocator(&alloc)));
std::size_t size = 2 * fmt::internal::INLINE_BUFFER_SIZE;
std::vector<char> mem(size);
{
EXPECT_CALL(alloc, allocate(size)).WillOnce(Return(&mem[0]));
buffer.resize(size);
std::fill(&buffer[0], &buffer[0] + size, 'x');
}
std::vector<char> mem2(2 * size);
{
EXPECT_CALL(alloc, allocate(2 * size)).WillOnce(Return(&mem2[0]));
std::exception e;
EXPECT_CALL(alloc, deallocate(&mem[0], size)).WillOnce(testing::Throw(e));
EXPECT_THROW(buffer.reserve(2 * size), std::exception);
EXPECT_EQ(&mem2[0], &buffer[0]);
// Check that the data has been copied.
for (std::size_t i = 0; i < size; ++i)
EXPECT_EQ('x', buffer[i]);
}
EXPECT_CALL(alloc, deallocate(&mem2[0], 2 * size));
}
TEST(UtilTest, Increment) {
char s[10] = "123";
increment(s);
EXPECT_STREQ("124", s);
s[2] = '8';
increment(s);
EXPECT_STREQ("129", s);
increment(s);
EXPECT_STREQ("130", s);
s[1] = s[2] = '9';
increment(s);
EXPECT_STREQ("200", s);
}
template <Arg::Type>
struct ArgInfo;
#define ARG_INFO(type_code, Type, field) \
template <> \
struct ArgInfo<Arg::type_code> { \
static Type get(const Value &value) { return value.field; } \
};
ARG_INFO(INT, int, int_value);
ARG_INFO(UINT, unsigned, uint_value);
ARG_INFO(LONG_LONG, fmt::LongLong, long_long_value);
ARG_INFO(ULONG_LONG, fmt::ULongLong, ulong_long_value);
ARG_INFO(DOUBLE, double, double_value);
ARG_INFO(LONG_DOUBLE, long double, long_double_value);
ARG_INFO(CHAR, int, int_value);
ARG_INFO(CSTRING, const char *, string.value);
ARG_INFO(STRING, const char *, string.value);
ARG_INFO(WSTRING, const wchar_t *, wstring.value);
ARG_INFO(POINTER, const void *, pointer);
ARG_INFO(CUSTOM, Arg::CustomValue, custom);
#define CHECK_ARG_INFO(Type, field, value) { \
Value arg_value = {}; \
arg_value.field = value; \
EXPECT_EQ(value, ArgInfo<Arg::Type>::get(arg_value)); \
}
TEST(ArgTest, ArgInfo) {
CHECK_ARG_INFO(INT, int_value, 42);
CHECK_ARG_INFO(UINT, uint_value, 42u);
CHECK_ARG_INFO(LONG_LONG, long_long_value, 42);
CHECK_ARG_INFO(ULONG_LONG, ulong_long_value, 42u);
CHECK_ARG_INFO(DOUBLE, double_value, 4.2);
CHECK_ARG_INFO(LONG_DOUBLE, long_double_value, 4.2);
CHECK_ARG_INFO(CHAR, int_value, 'x');
const char STR[] = "abc";
CHECK_ARG_INFO(CSTRING, string.value, STR);
const wchar_t WSTR[] = L"abc";
CHECK_ARG_INFO(WSTRING, wstring.value, WSTR);
int p = 0;
CHECK_ARG_INFO(POINTER, pointer, &p);
Value value = {};
value.custom.value = &p;
EXPECT_EQ(&p, ArgInfo<Arg::CUSTOM>::get(value).value);
}
#define EXPECT_ARG_(Char, type_code, MakeArgType, ExpectedType, value) { \
MakeArgType input = static_cast<MakeArgType>(value); \
Arg arg = make_arg<Char>(input); \
EXPECT_EQ(Arg::type_code, arg.type); \
ExpectedType expected_value = static_cast<ExpectedType>(value); \
EXPECT_EQ(expected_value, ArgInfo<Arg::type_code>::get(arg)); \
}
#define EXPECT_ARG(type_code, Type, value) \
EXPECT_ARG_(char, type_code, Type, Type, value)
#define EXPECT_ARGW(type_code, Type, value) \
EXPECT_ARG_(wchar_t, type_code, Type, Type, value)
TEST(ArgTest, MakeArg) {
// Test bool.
EXPECT_ARG_(char, INT, bool, int, true);
EXPECT_ARG_(wchar_t, INT, bool, int, true);
// Test char.
EXPECT_ARG(CHAR, signed char, 'a');
EXPECT_ARG(CHAR, signed char, SCHAR_MIN);
EXPECT_ARG(CHAR, signed char, SCHAR_MAX);
EXPECT_ARG(CHAR, unsigned char, 'a');
EXPECT_ARG(CHAR, unsigned char, UCHAR_MAX );
EXPECT_ARG(CHAR, char, 'a');
EXPECT_ARG(CHAR, char, CHAR_MIN);
EXPECT_ARG(CHAR, char, CHAR_MAX);
// Test wchar_t.
EXPECT_ARGW(CHAR, wchar_t, L'a');
EXPECT_ARGW(CHAR, wchar_t, WCHAR_MIN);
EXPECT_ARGW(CHAR, wchar_t, WCHAR_MAX);
// Test short.
EXPECT_ARG(INT, short, 42);
EXPECT_ARG(INT, short, SHRT_MIN);
EXPECT_ARG(INT, short, SHRT_MAX);
EXPECT_ARG(UINT, unsigned short, 42);
EXPECT_ARG(UINT, unsigned short, USHRT_MAX);
// Test int.
EXPECT_ARG(INT, int, 42);
EXPECT_ARG(INT, int, INT_MIN);
EXPECT_ARG(INT, int, INT_MAX);
EXPECT_ARG(UINT, unsigned, 42);
EXPECT_ARG(UINT, unsigned, UINT_MAX);
// Test long.
#if LONG_MAX == INT_MAX
# define LONG INT
# define ULONG UINT
# define long_value int_value
# define ulong_value uint_value
#else
# define LONG LONG_LONG
# define ULONG ULONG_LONG
# define long_value long_long_value
# define ulong_value ulong_long_value
#endif
EXPECT_ARG(LONG, long, 42);
EXPECT_ARG(LONG, long, LONG_MIN);
EXPECT_ARG(LONG, long, LONG_MAX);
EXPECT_ARG(ULONG, unsigned long, 42);
EXPECT_ARG(ULONG, unsigned long, ULONG_MAX);
// Test long long.
EXPECT_ARG(LONG_LONG, fmt::LongLong, 42);
EXPECT_ARG(LONG_LONG, fmt::LongLong, LLONG_MIN);
EXPECT_ARG(LONG_LONG, fmt::LongLong, LLONG_MAX);
EXPECT_ARG(ULONG_LONG, fmt::ULongLong, 42);
EXPECT_ARG(ULONG_LONG, fmt::ULongLong, ULLONG_MAX);
// Test float.
EXPECT_ARG(DOUBLE, float, 4.2);
EXPECT_ARG(DOUBLE, float, FLT_MIN);
EXPECT_ARG(DOUBLE, float, FLT_MAX);
// Test double.
EXPECT_ARG(DOUBLE, double, 4.2);
EXPECT_ARG(DOUBLE, double, DBL_MIN);
EXPECT_ARG(DOUBLE, double, DBL_MAX);
// Test long double.
EXPECT_ARG(LONG_DOUBLE, long double, 4.2);
EXPECT_ARG(LONG_DOUBLE, long double, LDBL_MIN);
EXPECT_ARG(LONG_DOUBLE, long double, LDBL_MAX);
// Test string.
char STR[] = "test";
EXPECT_ARG(CSTRING, char*, STR);
EXPECT_ARG(CSTRING, const char*, STR);
EXPECT_ARG(STRING, std::string, STR);
EXPECT_ARG(STRING, fmt::StringRef, STR);
// Test wide string.
wchar_t WSTR[] = L"test";
EXPECT_ARGW(WSTRING, wchar_t*, WSTR);
EXPECT_ARGW(WSTRING, const wchar_t*, WSTR);
EXPECT_ARGW(WSTRING, std::wstring, WSTR);
EXPECT_ARGW(WSTRING, fmt::WStringRef, WSTR);
int n = 42;
EXPECT_ARG(POINTER, void*, &n);
EXPECT_ARG(POINTER, const void*, &n);
::Test t;
Arg arg = make_arg<char>(t);
EXPECT_EQ(fmt::internal::Arg::CUSTOM, arg.type);
EXPECT_EQ(&t, arg.custom.value);
fmt::MemoryWriter w;
fmt::BasicFormatter<char> formatter(w);
const char *s = "}";
arg.custom.format(&formatter, &t, &s);
EXPECT_EQ("test", w.str());
}
TEST(UtilTest, ArgList) {
fmt::ArgList args;
EXPECT_EQ(Arg::NONE, args[fmt::ArgList::MAX_ARGS].type);
}
struct Result {
Arg arg;
Result() : arg(make_arg<char>(0xdeadbeef)) {}
template <typename T>
Result(const T& value) : arg(make_arg<char>(value)) {}
Result(const wchar_t *s) : arg(make_arg<wchar_t>(s)) {}
};
struct TestVisitor : fmt::internal::ArgVisitor<TestVisitor, Result> {
Result visit_int(int value) { return value; }
Result visit_uint(unsigned value) { return value; }
Result visit_long_long(fmt::LongLong value) { return value; }
Result visit_ulong_long(fmt::ULongLong value) { return value; }
Result visit_double(double value) { return value; }
Result visit_long_double(long double value) { return value; }
Result visit_char(int value) { return static_cast<char>(value); }
Result visit_string(Arg::StringValue<char> s) { return s.value; }
Result visit_wstring(Arg::StringValue<wchar_t> s) { return s.value; }
Result visit_pointer(const void *p) { return p; }
Result visit_custom(Arg::CustomValue c) {
return *static_cast<const ::Test*>(c.value);
}
};
#define EXPECT_RESULT_(Char, type_code, value) { \
Arg arg = make_arg<Char>(value); \
Result result = TestVisitor().visit(arg); \
EXPECT_EQ(Arg::type_code, result.arg.type); \
EXPECT_EQ(value, ArgInfo<Arg::type_code>::get(result.arg)); \
}
#define EXPECT_RESULT(type_code, value) \
EXPECT_RESULT_(char, type_code, value)
#define EXPECT_RESULTW(type_code, value) \
EXPECT_RESULT_(wchar_t, type_code, value)
TEST(ArgVisitorTest, VisitAll) {
EXPECT_RESULT(INT, 42);
EXPECT_RESULT(UINT, 42u);
EXPECT_RESULT(LONG_LONG, 42ll);
EXPECT_RESULT(ULONG_LONG, 42ull);
EXPECT_RESULT(DOUBLE, 4.2);
EXPECT_RESULT(LONG_DOUBLE, 4.2l);
EXPECT_RESULT(CHAR, 'x');
const char STR[] = "abc";
EXPECT_RESULT(CSTRING, STR);
const wchar_t WSTR[] = L"abc";
EXPECT_RESULTW(WSTRING, WSTR);
const void *p = STR;
EXPECT_RESULT(POINTER, p);
::Test t;
Result result = TestVisitor().visit(make_arg<char>(t));
EXPECT_EQ(Arg::CUSTOM, result.arg.type);
EXPECT_EQ(&t, result.arg.custom.value);
}
struct TestAnyVisitor : fmt::internal::ArgVisitor<TestAnyVisitor, Result> {
template <typename T>
Result visit_any_int(T value) { return value; }
template <typename T>
Result visit_any_double(T value) { return value; }
};
#undef EXPECT_RESULT
#define EXPECT_RESULT(type_code, value) { \
Result result = TestAnyVisitor().visit(make_arg<char>(value)); \
EXPECT_EQ(Arg::type_code, result.arg.type); \
EXPECT_EQ(value, ArgInfo<Arg::type_code>::get(result.arg)); \
}
TEST(ArgVisitorTest, VisitAny) {
EXPECT_RESULT(INT, 42);
EXPECT_RESULT(UINT, 42u);
EXPECT_RESULT(LONG_LONG, 42ll);
EXPECT_RESULT(ULONG_LONG, 42ull);
EXPECT_RESULT(DOUBLE, 4.2);
EXPECT_RESULT(LONG_DOUBLE, 4.2l);
}
struct TestUnhandledVisitor :
fmt::internal::ArgVisitor<TestUnhandledVisitor, const char *> {
const char *visit_unhandled_arg() { return "test"; }
};
#define EXPECT_UNHANDLED(value) \
EXPECT_STREQ("test", TestUnhandledVisitor().visit(make_arg<wchar_t>(value)));
TEST(ArgVisitorTest, VisitUnhandledArg) {
EXPECT_UNHANDLED(42);
EXPECT_UNHANDLED(42u);
EXPECT_UNHANDLED(42ll);
EXPECT_UNHANDLED(42ull);
EXPECT_UNHANDLED(4.2);
EXPECT_UNHANDLED(4.2l);
EXPECT_UNHANDLED('x');
const char STR[] = "abc";
EXPECT_UNHANDLED(STR);
const wchar_t WSTR[] = L"abc";
EXPECT_UNHANDLED(WSTR);
const void *p = STR;
EXPECT_UNHANDLED(p);
EXPECT_UNHANDLED(::Test());
}
TEST(ArgVisitorTest, VisitInvalidArg) {
Arg arg = Arg();
arg.type = static_cast<Arg::Type>(Arg::CUSTOM + 1);
EXPECT_DEBUG_DEATH(TestVisitor().visit(arg), "Assertion");
}
// Tests fmt::internal::count_digits for integer type Int.
template <typename Int>
void test_count_digits() {
for (Int i = 0; i < 10; ++i)
EXPECT_EQ(1u, fmt::internal::count_digits(i));
for (Int i = 1, n = 1,
end = std::numeric_limits<Int>::max() / 10; n <= end; ++i) {
n *= 10;
EXPECT_EQ(i, fmt::internal::count_digits(n - 1));
EXPECT_EQ(i + 1, fmt::internal::count_digits(n));
}
}
TEST(UtilTest, StringRef) {
// Test that StringRef::size() returns string length, not buffer size.
char str[100] = "some string";
EXPECT_EQ(std::strlen(str), StringRef(str).size());
EXPECT_LT(std::strlen(str), sizeof(str));
}
TEST(UtilTest, CountDigits) {
test_count_digits<uint32_t>();
test_count_digits<uint64_t>();
}
#ifdef _WIN32
TEST(UtilTest, UTF16ToUTF8) {
std::string s = "ёжик";
fmt::internal::UTF16ToUTF8 u(L"\x0451\x0436\x0438\x043A");
EXPECT_EQ(s, u.str());
EXPECT_EQ(s.size(), u.size());
}
TEST(UtilTest, UTF8ToUTF16) {
std::string s = "лошадка";
fmt::internal::UTF8ToUTF16 u(s.c_str());
EXPECT_EQ(L"\x043B\x043E\x0448\x0430\x0434\x043A\x0430", u.str());
EXPECT_EQ(7, u.size());
}
template <typename Converter, typename Char>
void check_utf_conversion_error(const char *message) {
fmt::MemoryWriter out;
fmt::internal::format_windows_error(out, ERROR_INVALID_PARAMETER, message);
fmt::SystemError error(0, "");
try {
Converter(fmt::BasicStringRef<Char>(0, 0));
} catch (const fmt::SystemError &e) {
error = e;
}
EXPECT_EQ(ERROR_INVALID_PARAMETER, error.error_code());
EXPECT_EQ(out.str(), error.what());
}
TEST(UtilTest, UTF16ToUTF8Error) {
check_utf_conversion_error<fmt::internal::UTF16ToUTF8, wchar_t>(
"cannot convert string from UTF-16 to UTF-8");
}
TEST(UtilTest, UTF8ToUTF16Error) {
check_utf_conversion_error<fmt::internal::UTF8ToUTF16, char>(
"cannot convert string from UTF-8 to UTF-16");
}
TEST(UtilTest, UTF16ToUTF8Convert) {
fmt::internal::UTF16ToUTF8 u;
EXPECT_EQ(ERROR_INVALID_PARAMETER, u.convert(fmt::WStringRef(0, 0)));
}
#endif // _WIN32
typedef void (*FormatErrorMessage)(
fmt::Writer &out, int error_code, StringRef message);
template <typename Error>
void check_throw_error(int error_code, FormatErrorMessage format) {
fmt::SystemError error(0, "");
try {
throw Error(error_code, "test {}", "error");
} catch (const fmt::SystemError &e) {
error = e;
}
fmt::MemoryWriter message;
format(message, error_code, "test error");
EXPECT_EQ(message.str(), error.what());
EXPECT_EQ(error_code, error.error_code());
}
TEST(UtilTest, FormatSystemError) {
fmt::MemoryWriter message;
fmt::internal::format_system_error(message, EDOM, "test");
EXPECT_EQ(fmt::format("test: {}", get_system_error(EDOM)), message.str());
message.clear();
fmt::internal::format_system_error(
message, EDOM, fmt::StringRef("x", std::numeric_limits<size_t>::max()));
EXPECT_EQ(fmt::format("error {}", EDOM), message.str());
}
TEST(UtilTest, SystemError) {
fmt::SystemError e(EDOM, "test");
EXPECT_EQ(fmt::format("test: {}", get_system_error(EDOM)), e.what());
EXPECT_EQ(EDOM, e.error_code());
check_throw_error<fmt::SystemError>(EDOM, fmt::internal::format_system_error);
}
TEST(UtilTest, ReportSystemError) {
fmt::MemoryWriter out;
fmt::internal::format_system_error(out, EDOM, "test error");
out << '\n';
EXPECT_WRITE(stderr, fmt::report_system_error(EDOM, "test error"), out.str());
}
#ifdef _WIN32
TEST(UtilTest, FormatWindowsError) {
LPWSTR message = 0;
FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, 0,
ERROR_FILE_EXISTS, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
reinterpret_cast<LPWSTR>(&message), 0, 0);
fmt::internal::UTF16ToUTF8 utf8_message(message);
LocalFree(message);
fmt::MemoryWriter actual_message;
fmt::internal::format_windows_error(
actual_message, ERROR_FILE_EXISTS, "test");
EXPECT_EQ(fmt::format("test: {}", utf8_message.str()),
actual_message.str());
actual_message.clear();
fmt::internal::format_windows_error(
actual_message, ERROR_FILE_EXISTS,
fmt::StringRef("x", std::numeric_limits<size_t>::max()));
EXPECT_EQ(fmt::format("error {}", ERROR_FILE_EXISTS), actual_message.str());
}
TEST(UtilTest, WindowsError) {
check_throw_error<fmt::WindowsError>(
ERROR_FILE_EXISTS, fmt::internal::format_windows_error);
}
TEST(UtilTest, ReportWindowsError) {
fmt::MemoryWriter out;
fmt::internal::format_windows_error(out, ERROR_FILE_EXISTS, "test error");
out << '\n';
EXPECT_WRITE(stderr,
fmt::report_windows_error(ERROR_FILE_EXISTS, "test error"), out.str());
}
#endif // _WIN32

51
test/util.cc Normal file
View File

@@ -0,0 +1,51 @@
/*
Test utilities.
Copyright (c) 2012-2014, Victor Zverovich
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "util.h"
#include <cstring>
void increment(char *s) {
for (int i = static_cast<int>(std::strlen(s)) - 1; i >= 0; --i) {
if (s[i] != '9') {
++s[i];
break;
}
s[i] = '0';
}
}
std::string get_system_error(int error_code) {
#if defined(__MINGW32__) || !defined(_WIN32)
return strerror(error_code);
#else
enum { BUFFER_SIZE = 200 };
char buffer[BUFFER_SIZE];
if (strerror_s(buffer, BUFFER_SIZE, error_code))
throw std::exception("strerror_s failed");
return buffer;
#endif
}

51
test/util.h Normal file
View File

@@ -0,0 +1,51 @@
/*
Test utilities.
Copyright (c) 2012-2014, Victor Zverovich
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <cstdarg>
#include <cstdio>
#include <string>
enum {BUFFER_SIZE = 256};
#ifdef _MSC_VER
# define FMT_VSNPRINTF vsprintf_s
#else
# define FMT_VSNPRINTF vsnprintf
#endif
template <std::size_t SIZE>
void safe_sprintf(char (&buffer)[SIZE], const char *format, ...) {
std::va_list args;
va_start(args, format);
FMT_VSNPRINTF(buffer, SIZE, format, args);
va_end(args);
}
// Increment a number in a string.
void increment(char *s);
std::string get_system_error(int error_code);