Compare commits

...

152 Commits

Author SHA1 Message Date
Akkadius 2d7267cb4e Add file export to lua-api.md 2018-07-02 01:15:00 -05:00
Akkadius 3443d8eb25 Upload lua-doc-parser.pl 2018-07-02 01:03:02 -05:00
Akkadius 1c5f0fba4f embparser_api.cpp formatting 2018-07-01 21:48:18 -05:00
Akkadius 5b6f9d3bfb Add --quest to perl-doc-parser.pl and update usage doc in embparser_api.cpp for quest:: 2018-07-01 21:47:34 -05:00
Akkadius 595138679d add --questitem to perl-doc-parser.pl - format and add usage doc to perl_questitem.cpp 2018-07-01 20:52:56 -05:00
Akkadius 9e03d76211 perl-doc-parser.pl fix --all option 2018-07-01 20:45:24 -05:00
Akkadius 94aa271a84 perl_raids.cpp formatting 2018-07-01 20:39:21 -05:00
Akkadius 57c1cd0be4 Add --raid to perl-doc-parser.pl and update usage docs for perl_raids.cpp 2018-07-01 20:39:07 -05:00
Akkadius d331114f71 Format perl_object.cpp 2018-07-01 20:29:44 -05:00
Akkadius 5b05987e27 perl_object.cpp formatting 2018-07-01 20:29:09 -05:00
Akkadius ed37715993 Add --objet to perl-doc-parser.pl and update usage doc for perl_object.cpp 2018-07-01 20:29:00 -05:00
Akkadius d079feeb66 perl_npc.cpp formatting 2018-07-01 20:20:40 -05:00
Akkadius 880285afa6 Add --npc to perl-doc-parser.pl and update usage docs in perl_npc.cpp 2018-07-01 20:20:09 -05:00
Akkadius 6faaff31be Add --hateentry to perl-doc-parser.pl - format perl_hateentry.cpp 2018-07-01 20:04:53 -05:00
Akkadius 465071c2cf More perl_groups.cpp formatting 2018-07-01 20:02:53 -05:00
Akkadius cf6a9d6b2a perl_groups.cpp formatting 2018-07-01 20:01:03 -05:00
Akkadius 782c5ebc75 Add group to perl-doc-parser.pl - update usage docs for perl_groups.cpp 2018-07-01 20:00:52 -05:00
Akkadius ef39395580 Add Doors to perl-doc-parser.pl 2018-07-01 19:56:11 -05:00
Akkadius 86c9b6b079 perl_doors.cpp formatting 2018-07-01 19:56:02 -05:00
Akkadius 4a036116dd Update perl_doors.cpp usage doc 2018-07-01 19:55:50 -05:00
Akkadius 2bab945c34 perl_entity.cpp formatting 2018-07-01 19:50:56 -05:00
Akkadius 26ed80bdda Add --entity to perl-doc-parser.pl 2018-07-01 19:49:52 -05:00
Akkadius a6c1314e3e perl_entity.cpp formatting 2018-07-01 19:49:31 -05:00
Akkadius 979e54daa7 Update usage croak docs perl_entity.cpp 2018-07-01 19:49:21 -05:00
Akkadius b87e355db3 Add corpse to perl-doc-parser.pl 2018-07-01 19:36:57 -05:00
Akkadius 88ed2e64bb perl_player_corpse.cpp formatting 2018-07-01 19:36:47 -05:00
Akkadius 2010d1ba83 Update usage docs for perl_player_corpse 2018-07-01 19:36:35 -05:00
Akkadius 332a3d6c6a Add "mob" to perl-doc-parser.pl 2018-07-01 19:30:52 -05:00
Akkadius 214503617e perl_mob.cpp formatting 2018-07-01 19:28:01 -05:00
Akkadius 1a1cce859a Update perl_mob.cpp croak usage blocks 2018-07-01 19:26:50 -05:00
Akkadius 0786b1158a Add initial perl-doc-parser.pl for Client 2018-07-01 18:16:23 -05:00
Akkadius 4d87216ec6 Format perl_client.cpp 2018-07-01 18:16:04 -05:00
Akkadius 7dbf24b95d Cleanup perl_client.cpp Usage types 2018-07-01 18:14:31 -05:00
KimLS e7cf687d2b Don't set c++ vers 2018-06-29 22:12:11 -07:00
KimLS 5544fd0ae5 Merge branch 'master' of github.com:EQEmu/Server 2018-06-28 21:03:48 -07:00
KimLS 842a40f76d lower cmake version 2018-06-28 21:03:32 -07:00
Michael Cook (mackal) 70f55179b6 Switch netcode to steady_clock 2018-06-28 22:16:25 -04:00
Alex a2e12667b4 Update README.md 2018-06-28 13:25:50 -07:00
KimLS 213a496efb Add cmake prefix path [skip-ci] 2018-06-28 13:21:46 -07:00
KimLS b0336302ee Merge branch 'build_improvements' 2018-06-28 13:17:48 -07:00
KimLS 58725b061e Add appveyor yml [skip-ci] 2018-06-28 13:17:11 -07:00
KimLS 90c18c1dc9 Change travis 2018-06-27 23:05:12 -07:00
KimLS 97ee8e59a1 Travis test 2018-06-27 22:50:08 -07:00
KimLS 50eededd9f Some build fixes and changes 2018-06-27 19:54:33 -07:00
Michael Cook (mackal) ee95a2a0c8 Remove uneeded DumpPacket in Handle_OP_ItemLinkClick 2018-06-27 21:22:39 -04:00
KimLS 254764c1e6 Fix for failed build due to lb changes 2018-06-26 23:00:20 -07:00
KimLS 352e70cf28 Fix for duplicate luabind 2018-06-26 22:50:44 -07:00
Michael Cook (mackal) 0558b1bc48 Merge pull request #739 from noudess/master
Changes to make Harmony work.
2018-06-24 14:38:33 -04:00
Paul Coene 2b38dbf1fb Changes to make Harmony work. 2018-06-24 12:13:09 -04:00
Michael Cook (mackal) bce92c5e02 Add support for innate self targeted spells
Currently this just includes checking SpellType_InCombatBuffs
2018-06-20 14:18:39 -04:00
Michael Cook (mackal) 653824ae9e More task comments .. 2018-06-07 18:14:09 -04:00
Michael Cook (mackal) b61f612fbe More comments 2018-06-05 22:39:48 -04:00
Michael Cook (mackal) 028dbc4bda Add ActivityCollect (unimplemented) and more comments 2018-06-05 22:16:53 -04:00
Michael Cook (mackal) 49b90eae76 More comments to task system 2018-06-05 13:12:29 -04:00
Michael Cook (mackal) 65acefc6b1 Comment task selection packet some 2018-06-04 23:54:57 -04:00
KimLS c985307057 Patch detour to avoid a crash if an invalid ref is returned 2018-05-31 19:24:26 -07:00
Uleat b475f66014 Fix for bot-enabled compile (cursory seems to be ok) 2018-05-30 22:05:27 -04:00
Akkadius eae7183de2 Word better 2018-05-28 03:33:44 -05:00
Akkadius 1d088a1ac1 Merge branch 'master' of https://github.com/EQEmu/Server 2018-05-28 01:47:06 -05:00
Akkadius 7d0b7560bc Fix for map download 2018-05-28 01:46:50 -05:00
Akkadius 7e86337b80 Update notes 2018-05-28 01:13:57 -05:00
Akkadius ac25d49a62 Patch notes - navmesh merge 2018-05-28 00:59:02 -05:00
Akkadius 8a911682bf Use GetRaceGenderDefaultHeight in GetDefaultRaceSize constant 2018-05-28 00:41:32 -05:00
Akkadius a87bf5681f Merge branch 'master' into wp_master 2018-05-28 00:33:05 -05:00
Akkadius b84b98dd7c Merge branch 'master' into wp_master 2018-05-28 00:32:39 -05:00
Michael Cook (mackal) c487acbf1a Off by 1 error in size check 2018-05-28 01:30:32 -04:00
Michael Cook (mackal) 72349ddbb6 Fix condition to set default heights
Was off by 1, if the height > 0 they don't get default height
2018-05-28 01:23:35 -04:00
Akkadius c8389103e3 Few tweaks to rules loading code - broadcast all zones that have loaded when #reloadallrules is used 2018-05-27 23:44:09 -05:00
Akkadius 7a7069959f Fix issue where size 0 NPC's would hop in and out of the ground because FixZ calculates the offset wrong by adding a default race size 2018-05-27 23:14:32 -05:00
Akkadius a20615ea11 Add an up to date easy to read race defines list 2018-05-27 23:13:43 -05:00
Akkadius 0e8672562a Fix issue where some perl calls were unintentionally renamed 2018-05-26 17:39:57 -05:00
Akkadius 05ae8c8219 Add rule Aggro:NPCAggroMaxDistanceEnabled - enabled by default
If enabled, NPC's will drop aggro beyond 600 units or what is defined at the zone level
2018-05-25 22:41:46 -05:00
KimLS add0c4de47 Added ignore flag for navmesh 2018-05-24 22:25:00 -07:00
JJ 510d8083b3 Merge pull request #734 from noudess/master
Kerran illusion spell uses 562 not 23.
2018-05-22 17:33:39 +03:00
Chris Miles d0e960e64b Ubuntu Server 18 LTS compile fix 2018-05-21 19:30:51 -05:00
Paul Coene b8a844b9dc Kerran illusion spell uses 562 not 23. 2018-05-21 18:40:22 -04:00
KimLS f46e4f9aa4 Some tweaks so its harder to get npcs intentionally stuck 2018-05-20 17:24:00 -07:00
Michael Cook (mackal) a828443b46 Add OP_TaskRequestTimer to patch files
This is the lockout timer before you can request a task again

Currently unimplemented
2018-05-15 22:12:18 -04:00
Natedog2012 e28ddcff25 Fix size of AltCurrencySelectItem_Struct in RoF2 2018-05-14 01:11:37 -07:00
KimLS 80c7643396 Fix for spaces instead of tabs 2018-05-12 22:30:07 -07:00
KimLS 66aaa92bd1 Changes to stuck handling that should result in fewer actually stuck npcs 2018-05-12 22:16:50 -07:00
Akkadius eb463eef97 Tweaks to zone shutdown code 2018-05-12 03:31:47 -05:00
Akkadius d43273fd1b Fix some of the Fix Z logic - Boats no longer snap Z - Even though we checked for water, chances are boats pathing was above water and would snap Z to the floor of the water 2018-05-11 00:43:49 -05:00
Akkadius 2c91d1db6e Make sure NPC's don't open keyed or lockpick enabled doors - also make sure we are opening doors and not platforms above or below 2018-05-11 00:14:24 -05:00
Akkadius d504397593 Change map loading paths - maps/base/*.map - maps/water/*.wtr - maps/nav/*.nav 2018-05-10 04:19:43 -05:00
Akkadius 95043d637c Implement NPC's opening doors and clean up door code a bit 2018-05-10 03:54:49 -05:00
KimLS 51a006654a Merge branch 'master' into wp_master 2018-05-02 18:24:19 -07:00
KimLS dde3f603be Change distance to within 100.0 dist instead of within 1.0 dist for checking stuck code. The actual instances where you're within 100.0 with a partial path and legit not stuck is going to be uncommon enough to put up with the visual oddities 2018-05-02 18:23:28 -07:00
Michael Cook (mackal) 4fe6836cf0 Fix compiling with libc++ 2018-04-27 21:41:52 -04:00
Michael Cook (mackal) fdcd39398c Merge pull request #730 from regneq/master
Added pause, resume, and ispause to lua.
2018-04-27 20:05:58 -04:00
regneq f7fe10fc98 Implemented lua methods eq.pause_timer("timername") and eq.resume_tim…
…er("timername"). This allows developers to pause and resume the given timer on the current NPC.

Added lua method eq.is_paused_timer("timername") to check to see if y…

…ou have a paused timer or not. Example usage:

if(eq.is_paused_timer("test"))then
     e.self:Say("You have a paused timer.");
else
     e.self:Say("You do not have a paused timer.");
end

(credit goes to Cavedude)
2018-04-27 16:31:35 -07:00
regneq 7d99becca9 Merge pull request #11 from EQEmu/master
eqemu update
2018-04-27 11:51:59 -07:00
KimLS a53f65d86b Merge and compile fixes (non-bot, will do bots later) 2018-04-16 14:15:08 -07:00
Uleat fb7362c092 Added bot command 'BotStopMeleeLevel' 2018-04-12 20:14:02 -04:00
Uleat 714f8172ec Added CanDoCombat() checks to certain actions 2018-04-11 18:49:49 -04:00
Michael Cook (mackal) 9344896238 /pet attack is range limited 2018-04-08 18:38:34 -04:00
Michael Cook (mackal) 3081f7b24f Pets/NPCs don't use bane damage
Adds rule NPC:UseBaneDamage (defaults to false)
2018-04-08 18:26:25 -04:00
Michael Cook (mackal) e594b7eac6 Fix NPC chance on fishing (100 = 100% chance now) 2018-03-29 18:28:36 -04:00
KayenEQ 0f3fbc3883 Add Change Log message 2018-03-28 17:07:15 -04:00
KayenEQ 2d20d5858e Fix for a few of the Cast on Fade effects to make sure the trigger spell
hits the correct target type.
2018-03-28 16:06:45 -04:00
Uleat fe57e4d924 Merge branch 'master' of https://github.com/EQEmu/Server 2018-03-26 03:38:33 -04:00
Uleat e4e40505b6 Removal of test code 2018-03-26 03:38:08 -04:00
Kinglykrab 5b5c3a08e6 Fix TryMoveAlong() in Perl.
- Didn't have 4th option accounted for (my bad).
2018-03-25 14:33:38 -04:00
Michael Cook (mackal) 137d2d723d Initialize AISpellVar 2018-03-25 01:16:06 -04:00
Michael Cook (mackal) aff481bd37 Fix invalid read in con 2018-03-25 01:12:42 -04:00
Kinglykrab a5a660b828 Fix quest::set_proximity(). 2018-03-24 21:06:56 -04:00
Kinglykrab d08b7dafa4 Export TryMoveAlong() to Perl. 2018-03-24 18:52:20 -04:00
Michael Cook (mackal) 3e1b86a7c3 Fix lua/perl set_proximity to accept flag for say prox
This will fix proximity say to always work
2018-03-24 15:24:54 -04:00
regneq fe68c7bc14 Merge pull request #10 from EQEmu/master
merge updates
2018-03-21 16:00:01 -07:00
Michael Cook (mackal) 4ee35d7e56 Add default size function 2018-03-20 14:35:52 -04:00
Uleat dbdad80960 Fix gcc error - report is non-critical portion of test 2018-03-19 22:00:12 -04:00
Uleat 72940b2511 Merge branch 'master' of https://github.com/EQEmu/Server 2018-03-19 20:58:40 -04:00
Uleat 70922975cf Test code for tracing zone crashes (stage 2) 2018-03-19 20:58:13 -04:00
Michael Cook (mackal) 135cfd7617 Revert "Revert changes to melee push until the generic push processing is better"
This reverts commit 49089f7537.
2018-03-19 00:13:57 -04:00
Uleat d58e88a2f7 Merge branch 'master' of https://github.com/EQEmu/Server 2018-03-17 20:19:15 -04:00
Michael Cook (mackal) c29bdd4b1d Add a sanity check to prevent mobs climbing steep walls
Ex. in OMM's room in anguish
2018-03-17 14:29:11 -04:00
Michael Cook (mackal) 0643bf9783 Remove z offset mod in push, wasn't needed 2018-03-17 13:43:27 -04:00
Uleat 386261181e Rework of command #peekinv 2018-03-17 07:54:39 -04:00
Michael Cook (mackal) d8b704ef7d Adjust z offset down 2018-03-17 02:05:36 -04:00
Michael Cook (mackal) e46e2952e6 Use 8 points to check in push code 2018-03-15 16:20:00 -04:00
Michael Cook (mackal) a339d0d41d Don't rotate the box, it works better 2018-03-15 15:48:34 -04:00
Michael Cook (mackal) d62f2d41fc Bug fixes to push, shouldn't get stuck anymore 2018-03-15 15:39:36 -04:00
Michael Cook (mackal) 339e921f17 Add a #push command, only works on NPCs for now 2018-03-14 16:10:14 -04:00
Uleat 5e963c05af Added client message for test code 2018-03-12 20:49:48 -04:00
KimLS cbbfae0cfc Merge master compile fixes 2017-09-17 13:34:35 -07:00
KimLS fc7623b690 Merge fix 2017-09-17 13:20:48 -07:00
KimLS 9dd4002337 Move stuck code out of main pathing function so we can add logging easily later 2017-09-09 14:01:39 -07:00
KimLS ccdebf0116 Add custom feature, cross-class skill trainer, fix up stuck detection and added a better solution to it. 2017-09-09 00:24:30 -07:00
KimLS 1a4aa1692a Remove partial warp for now 2017-09-05 22:50:08 -07:00
KimLS 6a79694fa1 Merge branch 'master' of github.com:EQEmu/Server into wp 2017-08-31 17:47:33 -07:00
KimLS c52ff4249a Pathing stuck detection, and logic to go with it 2017-08-30 19:55:35 -07:00
KimLS 0ba9b3fedc Fix for bug in pathing stuck detection 2017-08-29 22:03:22 -07:00
KimLS 46561b9cf5 Factor in size to actor offset 2017-08-28 23:48:05 -07:00
KimLS 545ac6b420 Some pathing tweaks, removed old quest functions that dealt with the old pathing code. Fixes to best z under new system 2017-08-28 22:01:08 -07:00
KimLS 0e8f6a32b1 Explicit RTreeValue decl because gcc didnt like it implicitly here 2017-08-20 17:40:37 -07:00
KimLS 17544d4577 Some tweaks to GCC errors, still think there's a couple 2017-08-20 15:37:46 -07:00
KimLS 563878f20e Compile fixes and some debugging messages in find path code. 2017-08-19 12:49:06 -07:00
KimLS ffbee0ad1a Merge 2017-08-09 10:42:07 -07:00
KimLS 575ba28b62 Bug fixes with fear points and teleport jumps 2017-08-06 20:48:39 -07:00
KimLS 3afee1f841 Work on making the paths work well when being z corrected esp for nav meshes 2017-08-05 20:54:43 -07:00
KimLS 832c31a41a work on navmesh loading 2017-07-29 15:05:56 -07:00
KimLS ff13f162ce Forgot to git add so missed a bunch of stuff 2017-07-29 00:12:21 -07:00
KimLS 80f1c65e1c Update fmt lib, add recast, wip on recast pathfinder interface (broken atm) 2017-07-29 00:11:57 -07:00
KimLS 7d3f35d48b Support for v3 path files, removed the movement log stuff, fix for a crash or two 2017-07-27 23:21:45 -07:00
KimLS 69c6879ac9 Merge fix 2017-07-22 14:20:40 -07:00
KimLS bdc90ac3a7 Command changes and code cleanup 2017-07-21 20:22:33 -07:00
KimLS ab33148f81 Some tweaks to wp, basically works 2017-07-20 00:34:58 -07:00
KimLS c2766db89d Working on waypoint code, using boost graph libs 2017-07-19 19:54:26 -07:00
KimLS 5f1063acb9 Add pathfinding interfaces, still heavily wip 2017-07-18 00:01:59 -07:00
KimLS 596e3b28b5 Actually add the interface files 2017-07-16 22:30:19 -07:00
KimLS 077ba02004 Merge branch 'master' of github.com:EQEmu/Server into wp 2017-07-16 22:30:03 -07:00
KimLS 75ee3b30e2 Support for races up to waypoint node race, wip on interface for pathfinding to support both kinds. 2017-07-16 22:29:52 -07:00
323 changed files with 44710 additions and 32769 deletions
+3
View File
@@ -37,3 +37,6 @@ x64/
x86/
log/
logs/
vcpkg/
.idea/*
+20 -25
View File
@@ -1,32 +1,27 @@
language: cpp
compiler: gcc
sudo: false
addons:
apt:
sources:
- ubuntu-toolchain-r-test
packages:
- gcc-4.8
- g++-4.8
- libmysqlclient-dev
- libperl-dev
- libboost-dev
- liblua5.1-0-dev
- zlib1g-dev
- uuid-dev
- libssl-dev
dist: trusty
before_install:
- sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test
- sudo apt-get update -qq
- mkdir $HOME/usr
- export PATH="$HOME/usr/bin:$PATH"
- wget https://cmake.org/files/v3.11/cmake-3.11.2-Linux-x86_64.sh
- chmod +x cmake-3.11.2-Linux-x86_64.sh
- ./cmake-3.11.2-Linux-x86_64.sh --prefix=$HOME/usr --exclude-subdir --skip-license
install:
- if [ "$CXX" = "g++" ]; then export CXX="g++-4.8" CC="gcc-4.8"; fi
- sudo apt-get install -qq g++-7
- sudo update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-7 90
- sudo apt-get install libmysqlclient-dev
- sudo apt-get install libperl-dev
- sudo apt-get install libboost-dev
- sudo apt-get install liblua5.1-0-dev
- sudo apt-get install zlib1g-dev
- sudo apt-get install uuid-dev
- sudo apt-get install libssl-dev
script:
- cmake -G "Unix Makefiles" -DEQEMU_BUILD_TESTS=ON -DEQEMU_ENABLE_BOTS=ON -DEQEMU_BUILD_LOGIN=ON
- make -j2
- ./bin/tests
branches:
only:
- master
- stable
notifications:
email: false
irc:
channels: "irc.eqemulator.net#eqemucoders"
os: linux
+6 -50
View File
@@ -27,8 +27,6 @@
#EQEMU_USE_MAP_MMFS
#EQEMU_MAP_DIR
#We set a fairly new version (as of 2013) because I found finding perl was a bit... buggy on older ones
#Can change this if you really want but you should upgrade!
CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
#FindMySQL is located here so lets make it so CMake can find it
@@ -42,6 +40,8 @@ IF(NOT CMAKE_BUILD_TYPE)
SET(CMAKE_BUILD_TYPE RelWithDebInfo CACHE STRING "Choose the type of build." FORCE)
ENDIF(NOT CMAKE_BUILD_TYPE)
SET(CMAKE_PREFIX_PATH "${CMAKE_CURRENT_SOURCE_DIR}/dependencies" "${CMAKE_PREFIX_PATH}")
#Add our various windows definitions
IF(MSVC OR MINGW)
ADD_DEFINITIONS(-D_WINDOWS)
@@ -53,35 +53,6 @@ IF(MSVC OR MINGW)
ENDIF(MSVC OR MINGW)
IF(MSVC)
#Set our default locations for zlib/mysql based on x86/x64
IF(CMAKE_CL_64)
SET(ZLIB_ROOT "${CMAKE_CURRENT_SOURCE_DIR}/dependencies/zlib_x64")
SET(MYSQL_ROOT "${CMAKE_CURRENT_SOURCE_DIR}/dependencies/mysql_x64")
SET(LUA_ROOT "${CMAKE_CURRENT_SOURCE_DIR}/dependencies/luaj_x64")
SET(OPENSSL_ROOT_DIR "${CMAKE_CURRENT_SOURCE_DIR}/dependencies/openssl_x64")
SET(SODIUM_INCLUDE_HINTS "${CMAKE_CURRENT_SOURCE_DIR}/dependencies/libsodium/include")
IF(MSVC_VERSION GREATER 1800)
SET(SODIUM_LIBRARY_HINTS "${CMAKE_CURRENT_SOURCE_DIR}/dependencies/libsodium/x64/Release/v140/dynamic")
ELSEIF(MSVC_VERSION EQUAL 1800)
SET(SODIUM_LIBRARY_HINTS "${CMAKE_CURRENT_SOURCE_DIR}/dependencies/libsodium/x64/Release/v120/dynamic")
ELSE()
SET(SODIUM_LIBRARY_HINTS "${CMAKE_CURRENT_SOURCE_DIR}/dependencies/libsodium/x64/Release/v110/dynamic")
ENDIF()
ELSE(CMAKE_CL_64)
SET(ZLIB_ROOT "${CMAKE_CURRENT_SOURCE_DIR}/dependencies/zlib_x86")
SET(MYSQL_ROOT "${CMAKE_CURRENT_SOURCE_DIR}/dependencies/mysql_x86")
SET(LUA_ROOT "${CMAKE_CURRENT_SOURCE_DIR}/dependencies/luaj_x86")
SET(SODIUM_INCLUDE_HINTS "${CMAKE_CURRENT_SOURCE_DIR}/dependencies/libsodium/include")
SET(OPENSSL_ROOT_DIR "${CMAKE_CURRENT_SOURCE_DIR}/dependencies/openssl_x86")
IF(MSVC_VERSION GREATER 1800)
SET(SODIUM_LIBRARY_HINTS "${CMAKE_CURRENT_SOURCE_DIR}/dependencies/libsodium/Win32/Release/v140/dynamic")
ELSEIF(MSVC_VERSION EQUAL 1800)
SET(SODIUM_LIBRARY_HINTS "${CMAKE_CURRENT_SOURCE_DIR}/dependencies/libsodium/Win32/Release/v120/dynamic")
ELSE()
SET(SODIUM_LIBRARY_HINTS "${CMAKE_CURRENT_SOURCE_DIR}/dependencies/libsodium/Win32/Release/v110/dynamic")
ENDIF()
ENDIF(CMAKE_CL_64)
#disable CRT warnings on windows cause they're annoying as shit and we use C functions everywhere
OPTION(EQEMU_DISABLE_CRT_SECURE_WARNINGS "Disable Secure CRT Warnings" ON)
IF(EQEMU_DISABLE_CRT_SECURE_WARNINGS)
@@ -100,23 +71,6 @@ IF(MSVC)
ADD_DEFINITIONS(-DCRASH_LOGGING)
ENDIF(EQEMU_ENABLE_CRASH_LOGGING)
#Disable safe SEH or not?
OPTION(EQEMU_DISABLE_SAFESEH "Disable Safe SEH (Needed for Strawberry Perl)" OFF)
IF(EQEMU_DISABLE_SAFESEH)
SET(CMAKE_EXE_LINKER_FLAGS_DEBUG "${CMAKE_EXE_LINKER_FLAGS_DEBUG} /SAFESEH:NO")
SET(CMAKE_EXE_LINKER_FLAGS_MINSIZEREL "${CMAKE_EXE_LINKER_FLAGS_MINSIZEREL} /SAFESEH:NO")
SET(CMAKE_EXE_LINKER_FLAGS_RELEASE "${CMAKE_EXE_LINKER_FLAGS_RELEASE} /SAFESEH:NO")
SET(CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO "${CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO} /SAFESEH:NO")
SET(CMAKE_SHARED_LINKER_FLAGS_DEBUG "${CMAKE_SHARED_LINKER_FLAGS_DEBUG} /SAFESEH:NO")
SET(CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL "${CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL} /SAFESEH:NO")
SET(CMAKE_SHARED_LINKER_FLAGS_RELEASE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE} /SAFESEH:NO")
SET(CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO "${CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO} /SAFESEH:NO")
SET(CMAKE_MODULE_LINKER_FLAGS_DEBUG "${CMAKE_MODULE_LINKER_FLAGS_DEBUG} /SAFESEH:NO")
SET(CMAKE_MODULE_LINKER_FLAGS_MINSIZEREL "${CMAKE_MODULE_LINKER_FLAGS_MINSIZEREL} /SAFESEH:NO")
SET(CMAKE_MODULE_LINKER_FLAGS_RELEASE "${CMAKE_MODULE_LINKER_FLAGS_RELEASE} /SAFESEH:NO")
SET(CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO "${CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO} /SAFESEH:NO")
ENDIF(EQEMU_DISABLE_SAFESEH)
OPTION(EQEMU_BUILD_MSVC_MP "Enable build with multiple processes." ON)
IF(EQEMU_BUILD_MSVC_MP)
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /MP")
@@ -309,7 +263,7 @@ IF(EQEMU_BUILD_PERL)
INCLUDE_DIRECTORIES(SYSTEM "${PERL_INCLUDE_PATH}")
ENDIF(EQEMU_BUILD_PERL)
SET(SERVER_LIBS common debug ${MySQL_LIBRARY_DEBUG} optimized ${MySQL_LIBRARY_RELEASE} ${ZLIB_LIBRARY} libuv fmt)
SET(SERVER_LIBS common debug ${MySQL_LIBRARY_DEBUG} optimized ${MySQL_LIBRARY_RELEASE} ${ZLIB_LIBRARY} libuv fmt recast_navigation)
FIND_PACKAGE(Sodium REQUIRED)
IF(SODIUM_FOUND)
@@ -342,7 +296,7 @@ IF(EQEMU_BUILD_LUA)
FIND_PACKAGE(Boost REQUIRED)
INCLUDE_DIRECTORIES(SYSTEM "${LUA_INCLUDE_DIR}" "${Boost_INCLUDE_DIRS}")
INCLUDE_DIRECTORIES(SYSTEM "${CMAKE_CURRENT_SOURCE_DIR}/luabind")
INCLUDE_DIRECTORIES(SYSTEM "${CMAKE_CURRENT_SOURCE_DIR}/libs/luabind")
OPTION(EQEMU_SANITIZE_LUA_LIBS "Sanitize Lua Libraries (Remove OS and IO standard libraries from being able to run)." ON)
IF(EQEMU_SANITIZE_LUA_LIBS)
@@ -357,6 +311,8 @@ INCLUDE_DIRECTORIES(SYSTEM "${CMAKE_CURRENT_SOURCE_DIR}/libs/cereal")
INCLUDE_DIRECTORIES(SYSTEM "${CMAKE_CURRENT_SOURCE_DIR}/libs/libuv/include" )
INCLUDE_DIRECTORIES(SYSTEM "${CMAKE_CURRENT_SOURCE_DIR}/libs/libuv/src")
INCLUDE_DIRECTORIES(SYSTEM "${CMAKE_CURRENT_SOURCE_DIR}/libs/format")
INCLUDE_DIRECTORIES(SYSTEM "${CMAKE_CURRENT_SOURCE_DIR}/libs/recast/detour/include")
INCLUDE_DIRECTORIES(SYSTEM "${CMAKE_CURRENT_SOURCE_DIR}/libs/recast/recast/include")
IF(EQEMU_BUILD_SERVER OR EQEMU_BUILD_LOGIN OR EQEMU_BUILD_TESTS OR EQEMU_BUILD_HC)
ADD_SUBDIRECTORY(common)
+3 -3
View File
@@ -1,7 +1,7 @@
# EQEmulator Core Server
|Travis CI (Linux)|Appveyor (Windows) |
|:---:|:---:|
|[![Linux CI](https://travis-ci.org/EQEmu/Server.svg?branch=master)](https://travis-ci.org/EQEmu/Server) |[![Windows CI](https://ci.appveyor.com/api/projects/status/d0cvokm7u732v8vl/branch/master?svg=true)](https://ci.appveyor.com/project/KimLS/server/branch/master) |
|Travis CI (Linux)|Appveyor w/ Bots (Windows) |Appveyor w/o Bots (Windows) |
|:---:|:---:|:---:|
|[![Linux CI](https://travis-ci.org/EQEmu/Server.svg?branch=master)](https://travis-ci.org/EQEmu/Server) |[![Build status](https://ci.appveyor.com/api/projects/status/scr25kmntx36c1ub/branch/master?svg=true)](https://ci.appveyor.com/project/KimLS/server-87crp/branch/master) |[![Build status](https://ci.appveyor.com/api/projects/status/mdwbr4o9l6mxqofj/branch/master?svg=true)](https://ci.appveyor.com/project/KimLS/server-w0pq2/branch/master) |
***
+39
View File
@@ -0,0 +1,39 @@
version: 1.0.{build}
branches:
only:
- master
image: Visual Studio 2017
configuration: RelWithDebInfo
clone_folder: c:\projects\eqemu
init:
- ps: git config --global core.autocrlf input
before_build:
- ps: >-
$wc = New-Object System.Net.WebClient
$wc.DownloadFile("https://github.com/EQEmu/eqemu.github.com/blob/master/downloads/appveyor/vcpkg-export.7z?raw=true", "c:\projects\eqemu\vcpkg-export.7z")
$wc.DownloadFile("http://strawberryperl.com/download/5.26.2.1/strawberry-perl-5.26.2.1-64bit-portable.zip", "c:\projects\eqemu\strawberry-perl-5.26.2.1-64bit-portable.zip")
cd c:\projects\eqemu
7z x c:/projects/eqemu/vcpkg-export.7z -oc:/projects/eqemu/vcpkg -y
7z x c:/projects/eqemu/strawberry-perl-5.26.2.1-64bit-portable.zip -oc:/projects/eqemu/strawberry-perl-portable -y
(Get-Content C:/projects/eqemu/strawberry-perl-portable/perl/lib/CORE/config.h).replace('#define PERL_STATIC_INLINE static __inline__', '#define PERL_STATIC_INLINE static __inline') | Set-Content C:/projects/eqemu/strawberry-perl-portable/perl/lib/CORE/config.h
mkdir build
cd build
cmake -G "Visual Studio 15 2017 Win64" -DEQEMU_BUILD_TESTS=ON -DEQEMU_BUILD_LOGIN=ON -EQEMU_ENABLE_BOTS=ON -DPERL_EXECUTABLE="C:/projects/eqemu/strawberry-perl-portable/perl/bin/perl.exe" -DPERL_INCLUDE_PATH="C:/projects/eqemu/strawberry-perl-portable/perl/lib/CORE" -DPERL_LIBRARY="C:/projects/eqemu/strawberry-perl-portable/perl/lib/CORE/libperl526.a" -DCMAKE_TOOLCHAIN_FILE="C:/projects/eqemu/vcpkg/vcpkg-export-20180627-133249/scripts/buildsystems/vcpkg.cmake" ..
build:
project: C:\projects\eqemu\build\EQEmu.sln
parallel: true
verbosity: minimal
after_build:
- cmd: >-
7z a build_x64-bots.zip C:\projects\eqemu\build\bin\RelWithDebInfo\*.exe C:\projects\eqemu\build\bin\RelWithDebInfo\*.dll C:\projects\eqemu\build\bin\RelWithDebInfo\*.pdb
appveyor PushArtifact build_x64-bots.zip
+39
View File
@@ -0,0 +1,39 @@
version: 1.0.{build}
branches:
only:
- master
image: Visual Studio 2017
configuration: RelWithDebInfo
clone_folder: c:\projects\eqemu
init:
- ps: git config --global core.autocrlf input
before_build:
- ps: >-
$wc = New-Object System.Net.WebClient
$wc.DownloadFile("https://github.com/EQEmu/eqemu.github.com/blob/master/downloads/appveyor/vcpkg-export.7z?raw=true", "c:\projects\eqemu\vcpkg-export.7z")
$wc.DownloadFile("http://strawberryperl.com/download/5.26.2.1/strawberry-perl-5.26.2.1-64bit-portable.zip", "c:\projects\eqemu\strawberry-perl-5.26.2.1-64bit-portable.zip")
cd c:\projects\eqemu
7z x c:/projects/eqemu/vcpkg-export.7z -oc:/projects/eqemu/vcpkg -y
7z x c:/projects/eqemu/strawberry-perl-5.26.2.1-64bit-portable.zip -oc:/projects/eqemu/strawberry-perl-portable -y
(Get-Content C:/projects/eqemu/strawberry-perl-portable/perl/lib/CORE/config.h).replace('#define PERL_STATIC_INLINE static __inline__', '#define PERL_STATIC_INLINE static __inline') | Set-Content C:/projects/eqemu/strawberry-perl-portable/perl/lib/CORE/config.h
mkdir build
cd build
cmake -G "Visual Studio 15 2017 Win64" -DEQEMU_BUILD_TESTS=ON -DEQEMU_BUILD_LOGIN=ON -EQEMU_ENABLE_BOTS=OFF -DPERL_EXECUTABLE="C:/projects/eqemu/strawberry-perl-portable/perl/bin/perl.exe" -DPERL_INCLUDE_PATH="C:/projects/eqemu/strawberry-perl-portable/perl/lib/CORE" -DPERL_LIBRARY="C:/projects/eqemu/strawberry-perl-portable/perl/lib/CORE/libperl526.a" -DCMAKE_TOOLCHAIN_FILE="C:/projects/eqemu/vcpkg/vcpkg-export-20180627-133249/scripts/buildsystems/vcpkg.cmake" ..
build:
project: C:\projects\eqemu\build\EQEmu.sln
parallel: true
verbosity: minimal
after_build:
- cmd: >-
7z a build_x64-no-bots.zip C:\projects\eqemu\build\bin\RelWithDebInfo\*.exe C:\projects\eqemu\build\bin\RelWithDebInfo\*.dll C:\projects\eqemu\build\bin\RelWithDebInfo\*.pdb
appveyor PushArtifact build_x64-no-bots.zip
+22
View File
@@ -1,5 +1,27 @@
EQEMu Changelog (Started on Sept 24, 2003 15:50)
-------------------------------------------------------
== 05/28/2018 ==
Akkadius: Fixed an issue where size 0 NPC's hop in and out of the ground at idle
Akkadius: NPC's now open doors within proximity given the door doesn't have locked requirements
Akkadius: #reloadallrules will now display zones that have had their rules reloaded to GM's
Akkadius: Zones should now respect "shutdowndelay" in the zones table at all times
Akkadius: Fixed an issue where boats would snap to the bed of the body of water
Akkadius: Added rule Aggro:NPCAggroMaxDistanceEnabled - defaults to true
Akkadius: Changed map directory load structure
- maps/base/*.map
- maps/nav/*.nav
- maps/water/*.wtr
- maps/path/*.path
KLS: Implemented navigation mesh
- All up to date maps and navs can be found https://github.com/Akkadius/EQEmuMaps
- To update maps either check out the maps found in the above repository or use the maintenance command:
perl eqemu_server.pl maps
== 03/28/2018 ==
Kayen: SE_CastOnFadeEffect, SE_CastOnFadeEffectNPC, SE_CastOnFadeEffectAlway triggered spell will now hit
the correct targets.
== 03/07/2018 ==
Uleat: Added command '#ucs' to force a reconnect to UCS server.
- Works in place of client auto-reconnect packet in zones where feature is unsupported
+2
View File
@@ -3,6 +3,7 @@ CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
SET(common_sources
base_packet.cpp
classes.cpp
compression.cpp
condition.cpp
crash.cpp
crc16.cpp
@@ -113,6 +114,7 @@ SET(common_headers
base_data.h
bodytypes.h
classes.h
compression.h
condition.h
crash.h
crc16.h
+82
View File
@@ -0,0 +1,82 @@
#include "global_define.h"
#include "types.h"
#include <string.h>
#include <zlib.h>
namespace EQEmu
{
uint32 EstimateDeflateBuffer(uint32 len) {
z_stream zstream;
memset(&zstream, 0, sizeof(zstream));
zstream.zalloc = Z_NULL;
zstream.zfree = Z_NULL;
zstream.opaque = Z_NULL;
if (deflateInit(&zstream, Z_FINISH) != Z_OK)
return 0;
return deflateBound(&zstream, len);
}
uint32 DeflateData(const char *buffer, uint32 len, char *out_buffer, uint32 out_len_max) {
z_stream zstream;
memset(&zstream, 0, sizeof(zstream));
int zerror;
zstream.next_in = const_cast<unsigned char*>(reinterpret_cast<const unsigned char*>(buffer));
zstream.avail_in = len;
zstream.zalloc = Z_NULL;
zstream.zfree = Z_NULL;
zstream.opaque = Z_NULL;
deflateInit(&zstream, Z_FINISH);
zstream.next_out = reinterpret_cast<unsigned char*>(out_buffer);
zstream.avail_out = out_len_max;
zerror = deflate(&zstream, Z_FINISH);
if (zerror == Z_STREAM_END)
{
deflateEnd(&zstream);
return (uint32)zstream.total_out;
}
else
{
zerror = deflateEnd(&zstream);
return 0;
}
}
uint32 InflateData(const char* buffer, uint32 len, char* out_buffer, uint32 out_len_max) {
z_stream zstream;
int zerror = 0;
int i;
zstream.next_in = const_cast<unsigned char*>(reinterpret_cast<const unsigned char*>(buffer));
zstream.avail_in = len;
zstream.next_out = reinterpret_cast<unsigned char*>(out_buffer);;
zstream.avail_out = out_len_max;
zstream.zalloc = Z_NULL;
zstream.zfree = Z_NULL;
zstream.opaque = Z_NULL;
i = inflateInit2(&zstream, 15);
if (i != Z_OK) {
return 0;
}
zerror = inflate(&zstream, Z_FINISH);
if (zerror == Z_STREAM_END) {
inflateEnd(&zstream);
return zstream.total_out;
}
else {
if (zerror == -4 && zstream.msg == 0)
{
return 0;
}
zerror = inflateEnd(&zstream);
return 0;
}
}
}
+8
View File
@@ -0,0 +1,8 @@
#pragma once
namespace EQEmu
{
uint32 EstimateDeflateBuffer(uint32 len);
uint32 DeflateData(const char *buffer, uint32 len, char *out_buffer, uint32 out_len_max);
uint32 InflateData(const char* buffer, uint32 len, char* out_buffer, uint32 out_len_max);
}
+7 -4
View File
@@ -1,32 +1,35 @@
#pragma once
#include <functional>
#include "../any.h"
#include "event_loop.h"
namespace EQ {
class BackgroundTask
{
public:
typedef std::function<void(void)> BackgroundTaskFunction;
typedef std::function<void(EQEmu::Any&)> BackgroundTaskFunction;
struct BackgroundTaskBaton
{
BackgroundTaskFunction fn;
BackgroundTaskFunction on_finish;
EQEmu::Any data;
};
BackgroundTask(BackgroundTaskFunction fn, BackgroundTaskFunction on_finish) {
BackgroundTask(BackgroundTaskFunction fn, BackgroundTaskFunction on_finish, EQEmu::Any data) {
uv_work_t *m_work = new uv_work_t;
memset(m_work, 0, sizeof(uv_work_t));
BackgroundTaskBaton *baton = new BackgroundTaskBaton();
baton->fn = fn;
baton->on_finish = on_finish;
baton->data = data;
m_work->data = baton;
uv_queue_work(EventLoop::Get().Handle(), m_work, [](uv_work_t* req) {
BackgroundTaskBaton *baton = (BackgroundTaskBaton*)req->data;
baton->fn();
baton->fn(baton->data);
}, [](uv_work_t* req, int status) {
BackgroundTaskBaton *baton = (BackgroundTaskBaton*)req->data;
baton->on_finish();
baton->on_finish(baton->data);
delete baton;
delete req;
});
-1
View File
@@ -1,5 +1,4 @@
#include "event_sub.h"
#include <string.h>
void EventSubscriptionWatcher::Subscribe(const std::string &event_name)
{
+1
View File
@@ -1,6 +1,7 @@
#pragma once
#include <unordered_map>
#include <string>
class EventSubscriptionWatcher
{
+1
View File
@@ -154,6 +154,7 @@ enum { //timer settings, all in milliseconds
AIscanarea_delay = 6000,
AIfeignremember_delay = 500,
AItarget_check_duration = 500,
AI_scan_door_open_interval = 1000,
// AIClientScanarea_delay = 750, //used in REVERSE_AGGRO
AIassistcheck_delay = 3000, //now often a fighting NPC will yell for help
AI_check_signal_timer_delay = 500, // How often EVENT_SIGNAL checks are processed
+1
View File
@@ -6,6 +6,7 @@
#include <windows.h>
#endif
#include <string>
#include <mysql.h>
#include "types.h"
#include "mysql_request_row.h"
+5 -5
View File
@@ -1,9 +1,9 @@
#include "console_server.h"
#include "../common/util/uuid.h"
#include "../common/net/packet.h"
#include "../common/eqemu_logsys.h"
#include "../common/servertalk.h"
#include "../common/rulesys.h"
#include "../util/uuid.h"
#include "../net/packet.h"
#include "../eqemu_logsys.h"
#include "../servertalk.h"
#include "../rulesys.h"
EQ::Net::ConsoleServerConnection::ConsoleServerConnection(ConsoleServer *parent, std::shared_ptr<TCPConnection> connection)
{
+1 -1
View File
@@ -747,7 +747,7 @@ void EQ::Net::DaybreakConnection::ProcessDecodedPacket(const Packet &p)
response.zero = 0;
response.opcode = OP_SessionStatResponse;
response.timestamp = request.timestamp;
response.our_timestamp = EQ::Net::HostToNetwork(std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::high_resolution_clock::now().time_since_epoch()).count());
response.our_timestamp = EQ::Net::HostToNetwork(std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now().time_since_epoch()).count());
response.client_sent = request.packets_sent;
response.client_recv = request.packets_recv;
response.server_sent = EQ::Net::HostToNetwork(m_stats.sent_packets);
+3 -3
View File
@@ -68,8 +68,8 @@ namespace EQ
SequencePast
};
typedef std::chrono::high_resolution_clock::time_point Timestamp;
typedef std::chrono::high_resolution_clock Clock;
typedef std::chrono::steady_clock::time_point Timestamp;
typedef std::chrono::steady_clock Clock;
struct DaybreakConnectionStats
{
@@ -282,4 +282,4 @@ namespace EQ
friend class DaybreakConnection;
};
}
}
}
-1
View File
@@ -2346,7 +2346,6 @@ struct AltCurrencySelectItem_Struct
/*064*/ uint32 unknown064;
/*068*/ uint32 unknown068;
/*072*/ uint32 unknown072;
/*076*/ uint32 unknown076;
};
//Server -> Client
+2 -2
View File
@@ -28,9 +28,9 @@
typedef const char Const_char;
#ifdef EMBPERL
#include "../common/global_define.h"
#include "../common/useperl.h"
#include "global_define.h"
#include "eqdb.h"
#include "useperl.h"
#ifdef THIS /* this macro seems to leak out on some systems */
#undef THIS
+2 -2
View File
@@ -28,9 +28,9 @@
typedef const char Const_char;
#ifdef EMBPERL
#include "../common/global_define.h"
#include "../common/useperl.h"
#include "global_define.h"
#include "eqdb_res.h"
#include "useperl.h"
XS(XS_EQDBRes_num_rows); /* prototype to pass -Wmissing-prototypes */
+200 -87
View File
@@ -1349,102 +1349,99 @@ const char* GetPlayerRaceName(uint32 player_race_value)
return GetRaceIDName(GetRaceIDFromPlayerRaceValue(player_race_value));
}
uint32 GetPlayerRaceValue(uint16 race_id)
{
uint32 GetPlayerRaceValue(uint16 race_id) {
switch (race_id) {
case HUMAN:
case BARBARIAN:
case ERUDITE:
case WOOD_ELF:
case HIGH_ELF:
case DARK_ELF:
case HALF_ELF:
case DWARF:
case TROLL:
case OGRE:
case HALFLING:
case GNOME:
return race_id;
case IKSAR:
return PLAYER_RACE_IKSAR;
case VAHSHIR:
return PLAYER_RACE_VAHSHIR;
case FROGLOK:
case FROGLOK2:
return PLAYER_RACE_FROGLOK;
case DRAKKIN:
return PLAYER_RACE_DRAKKIN;
default:
return PLAYER_RACE_UNKNOWN; // watch
case HUMAN:
case BARBARIAN:
case ERUDITE:
case WOOD_ELF:
case HIGH_ELF:
case DARK_ELF:
case HALF_ELF:
case DWARF:
case TROLL:
case OGRE:
case HALFLING:
case GNOME:
return race_id;
case IKSAR:
return PLAYER_RACE_IKSAR;
case VAHSHIR:
return PLAYER_RACE_VAHSHIR;
case FROGLOK:
case FROGLOK2:
return PLAYER_RACE_FROGLOK;
case DRAKKIN:
return PLAYER_RACE_DRAKKIN;
default:
return PLAYER_RACE_UNKNOWN; // watch
}
}
uint32 GetPlayerRaceBit(uint16 race_id)
{
uint32 GetPlayerRaceBit(uint16 race_id) {
switch (race_id) {
case HUMAN:
return PLAYER_RACE_HUMAN_BIT;
case BARBARIAN:
return PLAYER_RACE_BARBARIAN_BIT;
case ERUDITE:
return PLAYER_RACE_ERUDITE_BIT;
case WOOD_ELF:
return PLAYER_RACE_WOOD_ELF_BIT;
case HIGH_ELF:
return PLAYER_RACE_HIGH_ELF_BIT;
case DARK_ELF:
return PLAYER_RACE_DARK_ELF_BIT;
case HALF_ELF:
return PLAYER_RACE_HALF_ELF_BIT;
case DWARF:
return PLAYER_RACE_DWARF_BIT;
case TROLL:
return PLAYER_RACE_TROLL_BIT;
case OGRE:
return PLAYER_RACE_OGRE_BIT;
case HALFLING:
return PLAYER_RACE_HALFLING_BIT;
case GNOME:
return PLAYER_RACE_GNOME_BIT;
case IKSAR:
return PLAYER_RACE_IKSAR_BIT;
case VAHSHIR:
return PLAYER_RACE_VAHSHIR_BIT;
case FROGLOK:
return PLAYER_RACE_FROGLOK_BIT;
case DRAKKIN:
return PLAYER_RACE_DRAKKIN_BIT;
default:
return PLAYER_RACE_UNKNOWN_BIT;
case HUMAN:
return PLAYER_RACE_HUMAN_BIT;
case BARBARIAN:
return PLAYER_RACE_BARBARIAN_BIT;
case ERUDITE:
return PLAYER_RACE_ERUDITE_BIT;
case WOOD_ELF:
return PLAYER_RACE_WOOD_ELF_BIT;
case HIGH_ELF:
return PLAYER_RACE_HIGH_ELF_BIT;
case DARK_ELF:
return PLAYER_RACE_DARK_ELF_BIT;
case HALF_ELF:
return PLAYER_RACE_HALF_ELF_BIT;
case DWARF:
return PLAYER_RACE_DWARF_BIT;
case TROLL:
return PLAYER_RACE_TROLL_BIT;
case OGRE:
return PLAYER_RACE_OGRE_BIT;
case HALFLING:
return PLAYER_RACE_HALFLING_BIT;
case GNOME:
return PLAYER_RACE_GNOME_BIT;
case IKSAR:
return PLAYER_RACE_IKSAR_BIT;
case VAHSHIR:
return PLAYER_RACE_VAHSHIR_BIT;
case FROGLOK:
return PLAYER_RACE_FROGLOK_BIT;
case DRAKKIN:
return PLAYER_RACE_DRAKKIN_BIT;
default:
return PLAYER_RACE_UNKNOWN_BIT;
}
}
uint16 GetRaceIDFromPlayerRaceValue(uint32 player_race_value)
{
uint16 GetRaceIDFromPlayerRaceValue(uint32 player_race_value) {
switch (player_race_value) {
case PLAYER_RACE_HUMAN:
case PLAYER_RACE_BARBARIAN:
case PLAYER_RACE_ERUDITE:
case PLAYER_RACE_WOOD_ELF:
case PLAYER_RACE_HIGH_ELF:
case PLAYER_RACE_DARK_ELF:
case PLAYER_RACE_HALF_ELF:
case PLAYER_RACE_DWARF:
case PLAYER_RACE_TROLL:
case PLAYER_RACE_OGRE:
case PLAYER_RACE_HALFLING:
case PLAYER_RACE_GNOME:
return player_race_value;
case PLAYER_RACE_IKSAR:
return IKSAR;
case PLAYER_RACE_VAHSHIR:
return VAHSHIR;
case PLAYER_RACE_FROGLOK:
return FROGLOK;
case PLAYER_RACE_DRAKKIN:
return DRAKKIN;
default:
return PLAYER_RACE_UNKNOWN; // watch
case PLAYER_RACE_HUMAN:
case PLAYER_RACE_BARBARIAN:
case PLAYER_RACE_ERUDITE:
case PLAYER_RACE_WOOD_ELF:
case PLAYER_RACE_HIGH_ELF:
case PLAYER_RACE_DARK_ELF:
case PLAYER_RACE_HALF_ELF:
case PLAYER_RACE_DWARF:
case PLAYER_RACE_TROLL:
case PLAYER_RACE_OGRE:
case PLAYER_RACE_HALFLING:
case PLAYER_RACE_GNOME:
return player_race_value;
case PLAYER_RACE_IKSAR:
return IKSAR;
case PLAYER_RACE_VAHSHIR:
return VAHSHIR;
case PLAYER_RACE_FROGLOK:
return FROGLOK;
case PLAYER_RACE_DRAKKIN:
return DRAKKIN;
default:
return PLAYER_RACE_UNKNOWN; // watch
}
}
@@ -1488,6 +1485,122 @@ uint16 GetRaceIDFromPlayerRaceBit(uint32 player_race_bit)
}
}
float GetRaceGenderDefaultHeight(int race, int gender)
{
static float male_height[] = {
6.0f, 6.0f, 7.0f, 6.0f, 5.0f, 6.0f, 5.0f, 5.5f, 4.0f, 8.0f, 9.0f, 3.5f, 3.0f, 6.0f, 6.0f,
2.0f, 8.5f, 8.0f, 21.0f, 20.0f, 6.0f, 6.0f, 3.5f, 3.0f, 6.0f, 2.0f, 5.0f, 5.0f, 6.0f, 6.0f,
6.0f, 7.5f, 6.0f, 6.0f, 6.0f, 6.0f, 6.0f, 6.0f, 5.0f, 6.0f, 6.0f, 7.0f, 4.0f, 4.7f, 6.0f,
8.0f, 3.0f, 12.0f, 5.0f, 21.0f, 6.0f, 6.0f, 3.0f, 9.0f, 6.0f, 6.0f, 2.0f, 6.0f, 3.0f, 6.0f,
4.0f, 20.0f, 5.0f, 5.0f, 6.0f, 9.0f, 25.0f, 6.0f, 6.0f, 10.0f, 6.0f, 6.0f, 6.0f, 6.0f, 2.5f,
7.0f, 6.0f, 5.0f, 6.0f, 1.5f, 1.0f, 3.5f, 7.0f, 6.0f, 6.0f, 6.0f, 6.0f, 7.0f, 3.0f, 3.0f,
7.0f, 12.0f, 8.0f, 9.0f, 4.0f, 11.5f, 8.0f, 6.0f, 6.0f, 12.0f, 6.0f, 6.0f, 6.0f, 20.0f, 10.0f,
6.5f, 6.0f, 17.0f, 1.0f, 4.0f, 6.0f, 8.0f, 5.0f, 1.0f, 6.0f, 6.0f, 5.0f, 5.0f, 5.0f, 9.0f,
3.0f, 8.0f, 2.0f, 24.0f, 6.0f, 10.0f, 6.0f, 6.0f, 6.0f, 3.0f, 7.0f, 9.0f, 6.0f, 11.0f, 2.5f,
14.0f, 8.0f, 7.0f, 12.0f, 6.0f, 27.0f, 6.0f, 6.0f, 6.0f, 6.0f, 2.0f, 9.0f, 9.0f, 6.0f, 9.0f,
3.0f, 3.0f, 6.0f, 6.0f, 10.0f, 6.0f, 6.0f, 15.0f, 15.0f, 9.0f, 7.0f, 6.0f, 6.0f, 7.0f, 8.0f,
3.0f, 3.0f, 6.0f, 7.0f, 13.0f, 6.0f, 6.0f, 9.0f, 5.0f, 7.0f, 9.0f, 6.0f, 6.0f, 8.0f, 6.0f,
6.0f, 5.5f, 6.0f, 4.0f, 25.0f, 6.0f, 6.0f, 6.0f, 22.0f, 20.0f, 6.0f, 10.0f, 13.5f, 12.0f, 3.0f,
30.0f, 6.0f, 6.0f, 35.0f, 1.5f, 8.0f, 3.0f, 6.0f, 2.0f, 6.0f, 6.0f, 5.0f, 2.0f, 7.0f, 6.0f,
6.0f, 6.0f, 6.0f, 4.0f, 6.0f, 6.0f, 6.0f, 8.0f, 8.0f, 7.0f, 8.0f, 6.0f, 7.0f, 6.0f, 7.0f,
6.0f, 10.0f, 3.0f, 6.0f, 8.0f, 9.0f, 15.0f, 5.0f, 10.0f, 7.0f, 6.0f, 7.0f, 6.0f, 7.0f, 7.0f,
12.0f, 6.0f, 4.0f, 6.0f, 5.0f, 3.0f, 30.0f, 30.0f, 15.0f, 20.0f, 6.0f, 10.0f, 6.0f, 14.0f, 14.0f,
16.0f, 15.0f, 30.0f, 15.0f, 7.5f, 5.0f, 4.0f, 6.0f, 15.0f, 6.5f, 3.0f, 12.0f, 10.0f, 10.5f, 10.0f,
7.5f, 6.0f, 6.0f, 12.5f, 9.0f, 20.0f, 2.0f, 10.0f, 25.0f, 8.0f, 6.0f, 6.0f, 10.0f, 18.0f, 45.0f,
13.0f, 15.0f, 8.0f, 30.0f, 25.0f, 25.0f, 10.0f, 13.0f, 5.0f, 3.5f, 15.0f, 35.0f, 11.0f, 15.0f, 50.0f,
13.0f, 6.0f, 7.0f, 6.0f, 60.0f, 6.0f, 22.0f, 22.0f, 21.0f, 22.0f, 15.0f, 25.0f, 23.0f, 8.0f, 15.0f,
10.0f, 6.0f, 7.0f, 6.0f, 12.0f, 9.5f, 6.0f, 12.0f, 12.0f, 12.0f, 15.0f, 4.0f, 5.0f, 105.0f, 20.0f,
5.0f, 10.0f, 10.0f, 10.0f, 20.0f, 13.5f, 8.0f, 10.0f, 3.0f, 5.0f, 9.0f, 6.0f, 6.0f, 6.0f, 10.0f,
8.0f, 8.0f, 8.0f, 6.0f, 6.0f, 5.0f, 5.0f, 5.0f, 9.0f, 9.0f, 9.0f, 6.0f, 8.5f, 6.0f, 7.0f,
8.0f, 7.0f, 11.0f, 6.0f, 7.0f, 9.0f, 8.0f, 6.0f, 8.0f, 6.0f, 6.0f, 6.0f, 6.0f, 9.0f, 10.0f,
6.0f, 3.0f, 4.0f, 3.0f, 3.0f, 4.0f, 10.0f, 10.0f, 2.0f, 8.0f, 6.0f, 6.0f, 14.0f, 7.0f, 5.0f,
9.0f, 7.0f, 7.0f, 10.0f, 10.0f, 12.0f, 9.0f, 7.0f, 12.0f, 13.0f, 16.0f, 6.0f, 9.0f, 6.0f, 6.0f,
10.0f, 25.0f, 15.0f, 6.0f, 25.0f, 6.0f, 6.0f, 8.0f, 11.0f, 6.0f, 9.0f, 2.0f, 6.0f, 5.0f, 4.0f,
8.5f, 6.0f, 6.0f, 6.0f, 4.0f, 6.0f, 15.0f, 1.0f, 2.0f, 6.0f, 40.0f, 8.0f, 12.0f, 3.0f, 8.0f,
99.0f, 9.0f, 100.0f, 100.0f, 10.0f, 6.0f, 27.5f, 20.0f, 6.0f, 6.0f, 5.0f, 6.0f, 8.0f, 5.0f, 3.0f,
11.5f, 25.0f, 80.0f, 20.0f, 9.0f, 8.0f, 5.0f, 4.0f, 7.0f, 10.0f, 6.0f, 11.0f, 8.0f, 5.0f, 6.0f,
6.0f, 30.0f, 7.0f, 15.0f, 9.0f, 6.0f, 9.0f, 6.0f, 3.0f, 32.5f, 15.0f, 7.5f, 10.0f, 10.0f, 6.0f,
6.0f, 6.0f, 6.0f, 6.0f, 6.0f, 9.0f, 20.0f, 6.0f, 6.0f, 6.0f, 25.0f, 12.0f, 6.0f, 8.0f, 6.0f,
6.0f, 20.0f, 10.0f, 8.0f, 12.0f, 8.0f, 2.0f, 6.0f, 3.0f, 6.0f, 7.0f, 1.5f, 6.0f, 3.0f, 3.0f,
3.0f, 3.0f, 2.0f, 3.0f, 3.0f, 6.0f, 6.0f, 6.0f, 4.5f, 7.0f, 6.0f, 7.0f, 6.0f, 22.0f, 8.0f,
15.0f, 22.0f, 8.0f, 15.0f, 6.0f, 80.0f, 150.0f, 7.0f, 6.0f, 6.0f, 6.0f, 12.0f, 6.0f, 6.0f, 6.0f,
6.0f, 6.0f, 6.0f, 6.0f, 6.0f, 6.0f, 6.0f, 35.0f, 20.0f, 9.0f, 6.0f, 6.0f, 6.0f, 20.0f, 20.0f,
20.0f, 20.0f, 20.0f, 9.0f, 4.0f, 4.0f, 10.0f, 5.0f, 8.0f, 6.0f, 10.0f, 6.0f, 6.0f, 2.0f, 36.0f,
14.0f, 7.0f, 250.0f, 6.0f, 9.0f, 6.0f, 7.0f, 4.0f, 6.0f, 8.0f, 6.0f, 23.0f, 6.0f, 6.0f, 6.0f,
70.0f, 6.0f, 7.0f, 6.0f, 6.0f, 6.0f, 20.0f, 6.0f, 6.0f, 6.0f, 5.0f, 1.0f, 6.0f, 6.0f, 6.0f,
6.0f, 6.0f, 6.0f, 6.0f, 6.0f, 6.0f, 6.0f, 6.0f, 6.0f, 6.0f, 6.0f, 6.0f, 6.0f, 6.0f, 6.0f,
6.0f, 6.0f, 6.0f, 6.0f, 6.0f, 6.0f, 6.0f, 6.0f, 6.0f, 6.0f, 6.0f, 6.0f, 6.0f, 6.0f, 6.0f,
6.0f, 6.0f, 6.0f, 6.0f, 6.0f, 6.0f, 6.0f, 6.0f, 6.0f, 6.0f, 6.0f, 6.0f, 6.0f, 6.0f, 6.0f,
4.0f, 4.0f, 6.0f, 6.0f, 6.0f, 6.0f, 6.0f, 6.0f, 6.0f, 6.0f, 6.0f, 10.0f, 6.0f, 6.0f, 6.0f,
6.0f, 6.0f, 6.0f, 6.0f, 6.0f, 6.0f, 6.0f, 6.0f, 6.0f, 6.0f, 6.0f, 6.0f, 6.0f, 6.0f, 6.0f,
6.0f, 6.0f, 6.0f, 6.0f, 6.0f, 6.0f, 6.0f, 6.0f, 6.0f, 6.0f, 6.0f, 6.0f, 6.0f, 6.0f, 6.0f,
6.0f, 6.0f, 6.0f, 6.0f, 6.0f, 7.0f, 7.0f, 7.0f, 7.0f, 6.0f, 6.0f, 6.0f, 6.0f, 6.0f, 8.0f,
6.0f, 6.0f, 6.0f, 7.0f, 6.0f, 6.0f, 6.0f, 7.5f, 6.0f, 6.0f, 4.0f, 6.0f, 3.0f, 6.0f, 6.0f,
1.0f, 9.0f, 7.0f, 8.0f, 7.0f, 8.0f, 6.0f, 6.0f, 6.0f, 6.0f, 6.0f, 8.0f,
};
static float female_height[] = {
6.0f, 6.0f, 7.0f, 6.0f, 5.0f, 6.0f, 5.0f, 5.5f, 4.0f, 8.0f, 9.0f, 3.5f, 3.0f, 6.0f, 6.0f,
2.0f, 8.5f, 8.0f, 21.0f, 20.0f, 6.0f, 6.0f, 3.5f, 3.0f, 6.0f, 2.0f, 5.0f, 5.0f, 6.0f, 6.0f,
6.0f, 7.5f, 6.0f, 6.0f, 6.0f, 6.0f, 6.0f, 6.0f, 5.0f, 6.0f, 6.0f, 7.0f, 4.0f, 4.7f, 6.0f,
8.0f, 3.0f, 12.0f, 5.0f, 21.0f, 6.0f, 6.0f, 3.0f, 9.0f, 6.0f, 6.0f, 2.0f, 6.0f, 3.0f, 6.0f,
4.0f, 20.0f, 5.0f, 5.0f, 6.0f, 9.0f, 25.0f, 6.0f, 6.0f, 10.0f, 6.0f, 6.0f, 6.0f, 6.0f, 2.5f,
7.0f, 6.0f, 5.0f, 6.0f, 1.5f, 1.0f, 3.5f, 7.0f, 6.0f, 6.0f, 6.0f, 6.0f, 7.0f, 3.0f, 3.0f,
7.0f, 12.0f, 8.0f, 9.0f, 4.0f, 11.5f, 8.0f, 6.0f, 6.0f, 12.0f, 6.0f, 6.0f, 6.0f, 20.0f, 10.0f,
6.5f, 6.0f, 17.0f, 1.0f, 4.0f, 6.0f, 8.0f, 5.0f, 1.0f, 6.0f, 6.0f, 5.0f, 5.0f, 5.0f, 9.0f,
3.0f, 8.0f, 2.0f, 24.0f, 6.0f, 10.0f, 6.0f, 6.0f, 6.0f, 3.0f, 7.0f, 9.0f, 6.0f, 11.0f, 2.5f,
14.0f, 8.0f, 7.0f, 12.0f, 6.0f, 27.0f, 6.0f, 6.0f, 6.0f, 6.0f, 2.0f, 9.0f, 9.0f, 6.0f, 9.0f,
3.0f, 3.0f, 6.0f, 6.0f, 10.0f, 6.0f, 6.0f, 15.0f, 15.0f, 9.0f, 7.0f, 6.0f, 6.0f, 7.0f, 8.0f,
3.0f, 3.0f, 6.0f, 7.0f, 13.0f, 6.0f, 6.0f, 9.0f, 5.0f, 7.0f, 9.0f, 6.0f, 6.0f, 8.0f, 6.0f,
6.0f, 5.5f, 6.0f, 4.0f, 25.0f, 6.0f, 6.0f, 6.0f, 22.0f, 20.0f, 6.0f, 10.0f, 13.5f, 12.0f, 3.0f,
30.0f, 6.0f, 6.0f, 35.0f, 1.5f, 8.0f, 3.0f, 6.0f, 2.0f, 6.0f, 6.0f, 5.0f, 2.0f, 7.0f, 6.0f,
6.0f, 6.0f, 6.0f, 4.0f, 6.0f, 6.0f, 6.0f, 8.0f, 8.0f, 7.0f, 8.0f, 6.0f, 7.0f, 6.0f, 7.0f,
6.0f, 10.0f, 3.0f, 6.0f, 8.0f, 9.0f, 15.0f, 5.0f, 10.0f, 7.0f, 6.0f, 7.0f, 6.0f, 7.0f, 7.0f,
12.0f, 6.0f, 4.0f, 6.0f, 5.0f, 3.0f, 30.0f, 30.0f, 15.0f, 20.0f, 6.0f, 10.0f, 6.0f, 14.0f, 14.0f,
16.0f, 15.0f, 30.0f, 15.0f, 7.5f, 5.0f, 4.0f, 6.0f, 15.0f, 6.5f, 3.0f, 12.0f, 10.0f, 10.5f, 10.0f,
7.5f, 6.0f, 6.0f, 12.5f, 9.0f, 20.0f, 2.0f, 10.0f, 25.0f, 8.0f, 6.0f, 6.0f, 10.0f, 18.0f, 45.0f,
13.0f, 15.0f, 8.0f, 30.0f, 25.0f, 25.0f, 10.0f, 13.0f, 5.0f, 3.5f, 15.0f, 35.0f, 11.0f, 15.0f, 50.0f,
13.0f, 6.0f, 7.0f, 6.0f, 60.0f, 6.0f, 22.0f, 22.0f, 21.0f, 22.0f, 15.0f, 25.0f, 23.0f, 8.0f, 15.0f,
10.0f, 6.0f, 7.0f, 6.0f, 12.0f, 9.5f, 6.0f, 12.0f, 12.0f, 12.0f, 15.0f, 4.0f, 5.0f, 105.0f, 20.0f,
5.0f, 10.0f, 10.0f, 10.0f, 20.0f, 13.5f, 8.0f, 10.0f, 3.0f, 5.0f, 9.0f, 6.0f, 6.0f, 6.0f, 10.0f,
8.0f, 8.0f, 8.0f, 6.0f, 6.0f, 5.0f, 5.0f, 5.0f, 9.0f, 9.0f, 9.0f, 6.0f, 8.5f, 6.0f, 7.0f,
8.0f, 7.0f, 11.0f, 6.0f, 7.0f, 9.0f, 8.0f, 6.0f, 8.0f, 6.0f, 6.0f, 6.0f, 6.0f, 9.0f, 10.0f,
6.0f, 3.0f, 4.0f, 3.0f, 3.0f, 4.0f, 10.0f, 10.0f, 2.0f, 8.0f, 6.0f, 6.0f, 14.0f, 7.0f, 5.0f,
9.0f, 7.0f, 7.0f, 10.0f, 10.0f, 12.0f, 9.0f, 7.0f, 12.0f, 13.0f, 16.0f, 6.0f, 9.0f, 6.0f, 6.0f,
10.0f, 25.0f, 15.0f, 6.0f, 25.0f, 6.0f, 6.0f, 8.0f, 11.0f, 6.0f, 9.0f, 2.0f, 6.0f, 5.0f, 4.0f,
8.5f, 6.0f, 6.0f, 6.0f, 4.0f, 6.0f, 15.0f, 1.0f, 2.0f, 6.0f, 40.0f, 8.0f, 12.0f, 3.0f, 8.0f,
99.0f, 9.0f, 100.0f, 100.0f, 10.0f, 6.0f, 27.5f, 20.0f, 6.0f, 6.0f, 5.0f, 6.0f, 8.0f, 5.0f, 3.0f,
11.5f, 25.0f, 80.0f, 20.0f, 9.0f, 8.0f, 5.0f, 4.0f, 7.0f, 10.0f, 6.0f, 11.0f, 8.0f, 5.0f, 6.0f,
6.0f, 30.0f, 7.0f, 15.0f, 9.0f, 6.0f, 9.0f, 6.0f, 3.0f, 32.5f, 15.0f, 7.5f, 10.0f, 10.0f, 6.0f,
6.0f, 6.0f, 6.0f, 6.0f, 6.0f, 9.0f, 20.0f, 6.0f, 6.0f, 6.0f, 25.0f, 12.0f, 6.0f, 8.0f, 6.0f,
6.0f, 20.0f, 9.0f, 8.0f, 12.0f, 8.0f, 2.0f, 6.0f, 3.0f, 6.0f, 7.0f, 1.5f, 6.0f, 3.0f, 3.0f,
3.0f, 3.0f, 2.0f, 3.0f, 3.0f, 6.0f, 6.0f, 6.0f, 4.5f, 7.0f, 6.0f, 7.0f, 5.7f, 22.0f, 8.0f,
15.0f, 22.0f, 8.0f, 15.0f, 6.0f, 80.0f, 150.0f, 7.0f, 6.0f, 6.0f, 6.0f, 12.0f, 6.0f, 6.0f, 6.0f,
6.0f, 6.0f, 6.0f, 6.0f, 6.0f, 6.0f, 6.0f, 35.0f, 20.0f, 9.0f, 6.0f, 6.0f, 6.0f, 20.0f, 20.0f,
20.0f, 20.0f, 20.0f, 9.0f, 4.0f, 4.0f, 10.0f, 5.0f, 8.0f, 6.0f, 10.0f, 5.7f, 6.0f, 2.0f, 36.0f,
14.0f, 7.0f, 250.0f, 6.0f, 9.0f, 6.0f, 7.0f, 4.0f, 6.0f, 8.0f, 6.0f, 23.0f, 6.0f, 6.0f, 6.0f,
70.0f, 6.0f, 7.0f, 6.0f, 6.0f, 6.0f, 20.0f, 6.0f, 6.0f, 6.0f, 5.0f, 1.0f, 6.0f, 6.0f, 6.0f,
6.0f, 6.0f, 6.0f, 6.0f, 6.0f, 6.0f, 6.0f, 6.0f, 6.0f, 6.0f, 6.0f, 6.0f, 6.0f, 6.0f, 6.0f,
6.0f, 6.0f, 6.0f, 6.0f, 6.0f, 6.0f, 6.0f, 6.0f, 6.0f, 6.0f, 6.0f, 6.0f, 6.0f, 6.0f, 6.0f,
6.0f, 6.0f, 6.0f, 6.0f, 6.0f, 6.0f, 6.0f, 6.0f, 6.0f, 6.0f, 6.0f, 6.0f, 6.0f, 6.0f, 6.0f,
4.0f, 4.0f, 6.0f, 6.0f, 6.0f, 6.0f, 6.0f, 6.0f, 6.0f, 6.0f, 6.0f, 10.0f, 6.0f, 6.0f, 6.0f,
6.0f, 6.0f, 6.0f, 6.0f, 6.0f, 6.0f, 6.0f, 6.0f, 6.0f, 6.0f, 6.0f, 6.0f, 6.0f, 6.0f, 6.0f,
6.0f, 6.0f, 6.0f, 6.0f, 6.0f, 6.0f, 6.0f, 6.0f, 6.0f, 6.0f, 6.0f, 6.0f, 6.0f, 6.0f, 6.0f,
6.0f, 6.0f, 6.0f, 6.0f, 6.0f, 7.0f, 7.0f, 7.0f, 7.0f, 6.0f, 6.0f, 6.0f, 6.0f, 6.0f, 8.0f,
6.0f, 6.0f, 6.0f, 7.0f, 6.0f, 6.0f, 6.0f, 7.5f, 6.0f, 6.0f, 4.0f, 6.0f, 3.0f, 6.0f, 6.0f,
1.0f, 9.0f, 7.0f, 8.0f, 7.0f, 8.0f, 6.0f, 6.0f, 6.0f, 6.0f, 6.0f, 8.0f,
};
const auto size = sizeof(male_height) / sizeof(male_height[0]);
if (race >= size)
return 6.0f;
if (gender == 1)
return female_height[race];
return male_height[race];
}
// PlayerAppearance prep
#define HUMAN_MALE ((HUMAN << 8) | MALE)
+728 -409
View File
File diff suppressed because it is too large Load Diff
+32 -23
View File
@@ -236,46 +236,51 @@ void RuleManager::SaveRules(Database *database, const char *ruleset_name) {
}
bool RuleManager::LoadRules(Database *database, const char *ruleset_name) {
int ruleset_id = GetRulesetID(database, ruleset_name);
int ruleset_id = this->GetRulesetID(database, ruleset_name);
if (ruleset_id < 0) {
Log(Logs::Detail, Logs::Rules, "Failed to find ruleset '%s' for load operation. Canceling.", ruleset_name);
return(false);
return (false);
}
Log(Logs::Detail, Logs::Rules, "Loading rule set '%s' (%d)", ruleset_name, ruleset_id);
m_activeRuleset = ruleset_id;
m_activeName = ruleset_name;
m_activeName = ruleset_name;
/* Load default ruleset values first if we're loading something other than default */
if (strcasecmp(ruleset_name, "default") != 0){
if (strcasecmp(ruleset_name, "default") != 0) {
std::string default_ruleset_name = "default";
int default_ruleset_id = GetRulesetID(database, default_ruleset_name.c_str());
int default_ruleset_id = GetRulesetID(database, default_ruleset_name.c_str());
if (default_ruleset_id < 0) {
Log(Logs::Detail, Logs::Rules, "Failed to find default ruleset '%s' for load operation. Canceling.", default_ruleset_name.c_str());
return(false);
Log(Logs::Detail, Logs::Rules, "Failed to find default ruleset '%s' for load operation. Canceling.",
default_ruleset_name.c_str());
return (false);
}
Log(Logs::Detail, Logs::Rules, "Loading rule set '%s' (%d)", default_ruleset_name.c_str(), default_ruleset_id);
std::string query = StringFormat("SELECT rule_name, rule_value FROM rule_values WHERE ruleset_id = %d", default_ruleset_id);
std::string query = StringFormat(
"SELECT rule_name, rule_value FROM rule_values WHERE ruleset_id = %d",
default_ruleset_id
);
auto results = database->QueryDatabase(query);
if (!results.Success())
return false;
for (auto row = results.begin(); row != results.end(); ++row)
if (!SetRule(row[0], row[1], nullptr, false))
Log(Logs::Detail, Logs::Rules, "Unable to interpret rule record for %s", row[0]);
if (!SetRule(row[0], row[1], nullptr, false))
Log(Logs::Detail, Logs::Rules, "Unable to interpret rule record for %s", row[0]);
}
std::string query = StringFormat("SELECT rule_name, rule_value FROM rule_values WHERE ruleset_id=%d", ruleset_id);
auto results = database->QueryDatabase(query);
std::string query = StringFormat("SELECT rule_name, rule_value FROM rule_values WHERE ruleset_id=%d", ruleset_id);
auto results = database->QueryDatabase(query);
if (!results.Success())
return false;
for (auto row = results.begin(); row != results.end(); ++row)
if (!SetRule(row[0], row[1], nullptr, false))
Log(Logs::Detail, Logs::Rules, "Unable to interpret rule record for %s", row[0]);
if (!SetRule(row[0], row[1], nullptr, false))
Log(Logs::Detail, Logs::Rules, "Unable to interpret rule record for %s", row[0]);
return true;
}
@@ -283,7 +288,7 @@ bool RuleManager::LoadRules(Database *database, const char *ruleset_name) {
void RuleManager::_SaveRule(Database *database, RuleType type, uint16 index) {
char value_string[100];
switch(type) {
switch (type) {
case IntRule:
sprintf(value_string, "%d", m_RuleIntValues[index]);
break;
@@ -291,22 +296,26 @@ void RuleManager::_SaveRule(Database *database, RuleType type, uint16 index) {
sprintf(value_string, "%.13f", m_RuleRealValues[index]);
break;
case BoolRule:
sprintf(value_string, "%s", m_RuleBoolValues[index]?"true":"false");
sprintf(value_string, "%s", m_RuleBoolValues[index] ? "true" : "false");
break;
}
std::string query = StringFormat("REPLACE INTO rule_values "
"(ruleset_id, rule_name, rule_value) "
" VALUES(%d, '%s', '%s')",
m_activeRuleset, _GetRuleName(type, index), value_string);
auto results = database->QueryDatabase(query);
std::string query = StringFormat(
"REPLACE INTO rule_values "
"(ruleset_id, rule_name, rule_value) "
" VALUES(%d, '%s', '%s')",
m_activeRuleset,
_GetRuleName(type, index),
value_string
);
database->QueryDatabase(query);
}
int RuleManager::GetRulesetID(Database *database, const char *ruleset_name) {
uint32 len = strlen(ruleset_name);
uint32 len = static_cast<uint32>(strlen(ruleset_name));
auto rst = new char[2 * len + 1];
database->DoEscapeString(rst, ruleset_name, len);
+5 -1
View File
@@ -156,6 +156,7 @@ RULE_BOOL(Character, UseOldBindWound, false) // Uses the original bind wound beh
RULE_BOOL(Character, GrantHoTTOnCreate, false) // Grant Health of Target's Target leadership AA on character creation
RULE_BOOL(Character, UseOldConSystem, false) // Grant Health of Target's Target leadership AA on character creation
RULE_BOOL(Character, OPClientUpdateVisualDebug, false) // Shows a pulse and forward directional particle each time the client sends its position to server
RULE_BOOL(Character, AllowCrossClassTrainers, false)
RULE_BOOL(Character, PetsUseReagents, true) //Pets use reagent on spells
RULE_CATEGORY_END()
@@ -513,7 +514,8 @@ RULE_INT(NPC, MinorNPCCorpseDecayTimeMS, 450000) //level<55
RULE_INT(NPC, MajorNPCCorpseDecayTimeMS, 1500000) //level>=55
RULE_INT(NPC, CorpseUnlockTimer, 150000)
RULE_INT(NPC, EmptyNPCCorpseDecayTimeMS, 0)
RULE_BOOL (NPC, UseItemBonusesForNonPets, true)
RULE_BOOL(NPC, UseItemBonusesForNonPets, true)
RULE_BOOL(NPC, UseBaneDamage, false)
RULE_INT(NPC, SayPauseTimeInSec, 5)
RULE_INT(NPC, OOCRegen, 0)
RULE_BOOL(NPC, BuffFriends, false)
@@ -546,6 +548,8 @@ RULE_INT(Aggro, IntAggroThreshold, 75) // Int <= this will aggro regardless of l
RULE_BOOL(Aggro, AllowTickPulling, false) // tick pulling is an exploit in an NPC's call for help fixed sometime in 2006 on live
RULE_BOOL(Aggro, UseLevelAggro, true) // Level 18+ and Undead will aggro regardless of level difference. (this will disabled Rule:IntAggroThreshold if set to true)
RULE_INT(Aggro, ClientAggroCheckInterval, 6) // Interval in which clients actually check for aggro - in seconds
RULE_REAL(Aggro, PetAttackRange, 40000.0) // max squared range /pet attack works at default is 200
RULE_BOOL(Aggro, NPCAggroMaxDistanceEnabled, true) /* If enabled, NPC's will drop aggro beyond 600 units or what is defined at the zone level */
RULE_CATEGORY_END()
RULE_CATEGORY(TaskSystem)
+1 -2
View File
@@ -244,8 +244,7 @@ bool IsBeneficialSpell(uint16 spell_id)
} else {
// If the resisttype is not magic and spell is Bind Sight or Cast Sight
// It's not beneficial
if (sai == SAI_Dispell_Sight && spells[spell_id].skill == 18 &&
!IsEffectInSpell(spell_id, SE_VoiceGraft))
if ((sai == SAI_Calm && IsEffectInSpell(spell_id, SE_Harmony)) || (sai == SAI_Calm_Song && IsEffectInSpell(spell_id, SE_BindSight)) || (sai == SAI_Dispell_Sight && spells[spell_id].skill == 18 && !IsEffectInSpell(spell_id, SE_VoiceGraft)))
return false;
}
}
+2 -3
View File
@@ -131,12 +131,11 @@ void Timer::SetTimer(uint32 set_timer_time) {
uint32 Timer::GetRemainingTime() {
if (enabled) {
if (current_time-start_time > timer_time)
if (current_time - start_time > timer_time)
return 0;
else
return (start_time + timer_time) - current_time;
}
else {
} else {
return 0xFFFFFFFF;
}
}
+5 -1
View File
@@ -6,6 +6,10 @@
#include <EXTERN.h>
#define WIN32IO_IS_STDIO
// header to detect if libc++ is the std lib
// this doesn't do shit for C++ but libc++ and GCC 6.1+ use it to define some macros
#include <ciso646>
#ifndef WIN32
extern "C" { //the perl headers dont do this for us...
#endif
@@ -47,7 +51,7 @@ extern "C" { //the perl headers dont do this for us...
#endif
//These need to be cleaned up on FreeBSD
#ifdef __FreeBSD__
#if defined(__FreeBSD__) || defined(_LIBCPP_VERSION)
#ifdef do_open
#undef do_open
#endif
+1 -1
View File
@@ -32,7 +32,7 @@
#define CURRENT_BINARY_DATABASE_VERSION 9122
#ifdef BOTS
#define CURRENT_BINARY_BOTS_DATABASE_VERSION 9018
#define CURRENT_BINARY_BOTS_DATABASE_VERSION 9019
#else
#define CURRENT_BINARY_BOTS_DATABASE_VERSION 0 // must be 0
#endif
+2 -1
View File
@@ -3,4 +3,5 @@ IF(EQEMU_BUILD_LUA)
ENDIF(EQEMU_BUILD_LUA)
ADD_SUBDIRECTORY(libuv)
ADD_SUBDIRECTORY(format)
ADD_SUBDIRECTORY(format)
ADD_SUBDIRECTORY(recast)
+3
View File
@@ -0,0 +1,3 @@
<!---
Please make sure you've followed the guidelines outlined in the CONTRIBUTING.rst file.
--->
+19
View File
@@ -0,0 +1,19 @@
bin/
/_CPack_Packages
/doc/doxyxml
/doc/html
virtualenv
/Testing
/install_manifest.txt
*~
*.a
*.so*
*.zip
cmake_install.cmake
CPack*.cmake
fmt-*.cmake
CTestTestfile.cmake
CMakeCache.txt
CMakeFiles
Makefile
run-msbuild.bat
+1 -7
View File
@@ -1,4 +1,5 @@
language: cpp
dist: trusty
sudo: required # the doc target uses sudo to install dependencies
os:
@@ -22,12 +23,5 @@ matrix:
- os: osx
env: BUILD=Doc
addons:
apt:
sources:
- kubuntu-backports # cmake 2.8.12
packages:
- cmake
script:
- support/travis-build.py
+23 -9
View File
@@ -1,6 +1,6 @@
message(STATUS "CMake version: ${CMAKE_VERSION}")
cmake_minimum_required(VERSION 2.8)
cmake_minimum_required(VERSION 2.8.12)
# Determine if fmt is built as a subproject (using add_subdirectory)
# or if it is the master project.
@@ -9,12 +9,22 @@ if (CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_SOURCE_DIR)
set(MASTER_PROJECT ON)
endif ()
# Joins arguments and places the results in ${result_var}.
function(join result_var)
set(result )
foreach (arg ${ARGN})
set(result "${result}${arg}")
endforeach ()
set(${result_var} "${result}" PARENT_SCOPE)
endfunction()
# Set the default CMAKE_BUILD_TYPE to Release.
# This should be done before the project command since the latter can set
# CMAKE_BUILD_TYPE itself (it does so for nmake).
if (NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE Release CACHE STRING
"Choose the type of build, options are: None(CMAKE_CXX_FLAGS or CMAKE_C_FLAGS used) Debug Release RelWithDebInfo MinSizeRel.")
join(doc "Choose the type of build, options are: None(CMAKE_CXX_FLAGS or "
"CMAKE_C_FLAGS used) Debug Release RelWithDebInfo MinSizeRel.")
set(CMAKE_BUILD_TYPE Release CACHE STRING ${doc})
endif ()
option(FMT_PEDANTIC "Enable extra warnings and expensive tests." OFF)
@@ -28,13 +38,17 @@ option(FMT_USE_CPP11 "Enable the addition of C++11 compiler flags." ON)
project(FMT)
# Starting with cmake 3.0 VERSION is part of the project command.
set(FMT_VERSION 3.0.0)
if (NOT FMT_VERSION MATCHES "^([0-9]+).([0-9]+).([0-9]+)$")
message(FATAL_ERROR "Invalid version format ${FMT_VERSION}.")
file(READ fmt/format.h format_h)
if (NOT format_h MATCHES "FMT_VERSION ([0-9]+)([0-9][0-9])([0-9][0-9])")
message(FATAL_ERROR "Cannot get FMT_VERSION from format.h.")
endif ()
set(CPACK_PACKAGE_VERSION_MAJOR ${CMAKE_MATCH_1})
set(CPACK_PACKAGE_VERSION_MINOR ${CMAKE_MATCH_2})
set(CPACK_PACKAGE_VERSION_PATCH ${CMAKE_MATCH_3})
# Use math to skip leading zeros if any.
math(EXPR CPACK_PACKAGE_VERSION_MAJOR ${CMAKE_MATCH_1})
math(EXPR CPACK_PACKAGE_VERSION_MINOR ${CMAKE_MATCH_2})
math(EXPR CPACK_PACKAGE_VERSION_PATCH ${CMAKE_MATCH_3})
join(FMT_VERSION ${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}.
${CPACK_PACKAGE_VERSION_PATCH})
message(STATUS "Version: ${FMT_VERSION}")
message(STATUS "Build type: ${CMAKE_BUILD_TYPE}")
+11
View File
@@ -0,0 +1,11 @@
Contributing to fmt
===================
All C++ code must adhere to `Google C++ Style Guide
<https://google.github.io/styleguide/cppguide.html>`_ with the following
exceptions:
* Exceptions are permitted
* snake_case should be used instead of UpperCamelCase for function names
Thanks for contributing!
+110
View File
@@ -1,3 +1,113 @@
4.0.0 - 2017-06-27
------------------
* Removed old compatibility headers ``cppformat/*.h`` and CMake options (`#527 <https://github.com/pull/527>`_). Thanks `@maddinat0r (Alex Martin) <https://github.com/maddinat0r>`_.
* Added ``string.h`` containing ``fmt::to_string()`` as alternative to ``std::to_string()`` as well as other string writer functionality (`#326 <https://github.com/fmtlib/fmt/issues/326>`_ and `#441 <https://github.com/fmtlib/fmt/pull/441>`_):
.. code:: c++
#include "fmt/string.h"
std::string answer = fmt::to_string(42);
Thanks to `@glebov-andrey (Andrey Glebov) <https://github.com/glebov-andrey>`_.
* Moved ``fmt::printf()`` to new ``printf.h`` header and allowed ``%s`` as generic specifier (`#453 <https://github.com/fmtlib/fmt/pull/453>`_), made ``%.f`` more conformant to regular ``printf()`` (`#490 <https://github.com/fmtlib/fmt/pull/490>`_), added custom writer support (`#476 <https://github.com/fmtlib/fmt/issues/476>`_) and implemented missing custom argument formatting (`#339 <https://github.com/fmtlib/fmt/pull/339>`_ and `#340 <https://github.com/fmtlib/fmt/pull/340>`_):
.. code:: c++
#include "fmt/printf.h"
// %s format specifier can be used with any argument type.
fmt::printf("%s", 42);
Thanks `@mojoBrendan <https://github.com/mojoBrendan>`_, `@manylegged (Arthur Danskin) <https://github.com/manylegged>`_ and `@spacemoose (Glen Stark) <https://github.com/spacemoose>`_. See also `#360 <https://github.com/fmtlib/fmt/issues/360>`_, `#335 <https://github.com/fmtlib/fmt/issues/335>`_ and `#331 <https://github.com/fmtlib/fmt/issues/331>`_.
* Added ``container.h`` containing a ``BasicContainerWriter`` to write to containers like ``std::vector`` (`#450 <https://github.com/fmtlib/fmt/pull/450>`_). Thanks `@polyvertex (Jean-Charles Lefebvre) <https://github.com/polyvertex>`_.
* Added ``fmt::join()`` function that takes a range and formats its elements separated by a given string (`#466 <https://github.com/fmtlib/fmt/pull/466>`_):
.. code:: c++
#include "fmt/format.h"
std::vector<double> v = {1.2, 3.4, 5.6};
// Prints "(+01.20, +03.40, +05.60)".
fmt::print("({:+06.2f})", fmt::join(v.begin(), v.end(), ", "));
Thanks `@olivier80 <https://github.com/olivier80>`_.
* Added support for custom formatting specifications to simplify customization of built-in formatting (`#444 <https://github.com/fmtlib/fmt/pull/444>`_). Thanks `@polyvertex (Jean-Charles Lefebvre) <https://github.com/polyvertex>`_. See also `#439 <https://github.com/fmtlib/fmt/issues/439>`_.
* Added ``fmt::format_system_error()`` for error code formatting (`#323 <https://github.com/fmtlib/fmt/issues/323>`_ and `#526 <https://github.com/fmtlib/fmt/pull/526>`_). Thanks `@maddinat0r (Alex Martin) <https://github.com/maddinat0r>`_.
* Added thread-safe ``fmt::localtime()`` and ``fmt::gmtime()`` as replacement for the standard version to ``time.h`` (`#396 <https://github.com/fmtlib/fmt/pull/396>`_). Thanks `@codicodi <https://github.com/codicodi>`_.
* Internal improvements to ``NamedArg`` and ``ArgLists`` (`#389 <https://github.com/fmtlib/fmt/pull/389>`_ and `#390 <https://github.com/fmtlib/fmt/pull/390>`_). Thanks `@chronoxor <https://github.com/chronoxor>`_.
* Fixed crash due to bug in ``FormatBuf`` (`#493 <https://github.com/fmtlib/fmt/pull/493>`_). Thanks `@effzeh <https://github.com/effzeh>`_. See also `#480 <https://github.com/fmtlib/fmt/issues/480>`_ and `#491 <https://github.com/fmtlib/fmt/issues/491>`_.
* Fixed handling of wide strings in ``fmt::StringWriter``.
* Improved compiler error messages (`#357 <https://github.com/fmtlib/fmt/issues/357>`_).
* Fixed various warnings and issues with various compilers (`#494 <https://github.com/fmtlib/fmt/pull/494>`_, `#499 <https://github.com/fmtlib/fmt/pull/499>`_, `#483 <https://github.com/fmtlib/fmt/pull/483>`_, `#519 <https://github.com/fmtlib/fmt/pull/519>`_, `#485 <https://github.com/fmtlib/fmt/pull/485>`_, `#482 <https://github.com/fmtlib/fmt/pull/482>`_, `#475 <https://github.com/fmtlib/fmt/pull/475>`_, `#473 <https://github.com/fmtlib/fmt/pull/473>`_ and `#414 <https://github.com/fmtlib/fmt/pull/414>`_). Thanks `@chronoxor <https://github.com/chronoxor>`_, `@zhaohuaxishi <https://github.com/zhaohuaxishi>`_, `@pkestene (Pierre Kestener) <https://github.com/pkestene>`_, `@dschmidt (Dominik Schmidt) <https://github.com/dschmidt>`_ and `@0x414c (Alexey Gorishny) <https://github.com/0x414c>`_ .
* Improved CMake: targets are now namespaced (`#511 <https://github.com/fmtlib/fmt/pull/511>`_ and `#513 <https://github.com/fmtlib/fmt/pull/513>`_), supported header-only ``printf.h`` (`#354 <https://github.com/fmtlib/fmt/pull/354>`_), fixed issue with minimal supported library subset (`#418 <https://github.com/fmtlib/fmt/issues/418>`_, `#419 <https://github.com/fmtlib/fmt/pull/419>`_ and `#420 <https://github.com/fmtlib/fmt/pull/420>`_). Thanks `@bjoernthiel (Bjoern Thiel) <https://github.com/bjoernthiel>`_,
`@niosHD (Mario Werner) <https://github.com/niosHD>`_, `@LogicalKnight (Sean LK) <https://github.com/LogicalKnight>`_ and `@alabuzhev (Alex Alabuzhev) <https://github.com/alabuzhev>`_.
* Improved documentation. Thanks to `@pwm1234 (Phil) <https://github.com/pwm1234>`_ for `#393 <https://github.com/fmtlib/fmt/pull/393>`_.
3.0.2 - 2017-06-14
------------------
* Added ``FMT_VERSION`` macro (`#411 <https://github.com/fmtlib/fmt/issues/411>`_).
* Used ``FMT_NULL`` instead of literal ``0`` (`#409 <https://github.com/fmtlib/fmt/pull/409>`_). Thanks `@alabuzhev (Alex Alabuzhev) <https://github.com/alabuzhev>`_.
* Added extern templates for ``format_float`` (`#413 <https://github.com/fmtlib/fmt/issues/413>`_).
* Fixed implicit conversion issue (`#507 <https://github.com/fmtlib/fmt/issues/507>`_).
* Fixed signbit detection (`#423 <https://github.com/fmtlib/fmt/issues/423>`_).
* Fixed naming collision (`#425 <https://github.com/fmtlib/fmt/issues/425>`_).
* Fixed missing intrinsic for C++/CLI (`#457 <https://github.com/fmtlib/fmt/pull/457>`_). Thanks `@calumr (Calum Robinson) <https://github.com/calumr>`_
* Fixed Android detection (`#458 <https://github.com/fmtlib/fmt/pull/458>`_). Thanks `@Gachapen (Magnus Bjerke Vik) <https://github.com/Gachapen>`_.
* Use lean ``windows.h`` if not in header-only mode (`#503 <https://github.com/fmtlib/fmt/pull/503>`_). Thanks `@Quentin01 (Quentin Buathier) <https://github.com/Quentin01>`_.
* Fixed issue with CMake exporting C++11 flag (`#445 <https://github.com/fmtlib/fmt/pull/455>`_). Thanks `@EricWF (Eric) <https://github.com/EricWF>`_.
* Fixed issue with nvcc and MSVC compiler bug and MinGW (`#505 <https://github.com/fmtlib/fmt/issues/505>`_).
* Fixed DLL issues (`#469 <https://github.com/fmtlib/fmt/pull/469>`_ and `#502 <https://github.com/fmtlib/fmt/pull/502>`_). Thanks `@richardeakin (Richard Eakin) <https://github.com/richardeakin>`_ and `@AndreasSchoenle (Andreas Schönle) <https://github.com/AndreasSchoenle>`_.
* Fixed test compilation under FreeBSD (`#433 <https://github.com/fmtlib/fmt/issues/433>`_).
* Fixed various warnings (`#403 <https://github.com/fmtlib/fmt/pull/403>`_, `#410 <https://github.com/fmtlib/fmt/pull/410>`_ and `#510 <https://github.com/fmtlib/fmt/pull/510>`_). Thanks `@Lecetem <https://github.com/Lectem>`_, `@chenhayat (Chen Hayat) <https://github.com/chenhayat>`_ and `@trozen <https://github.com/trozen>`_.
* Removed redundant include (`#479 <https://github.com/fmtlib/fmt/issues/479>`_).
* Fixed documentation issues.
3.0.1 - 2016-11-01
------------------
* Fixed handling of thousands seperator (`#353 <https://github.com/fmtlib/fmt/issues/353>`_)
* Fixed handling of ``unsigned char`` strings (`#373 <https://github.com/fmtlib/fmt/issues/373>`_)
* Corrected buffer growth when formatting time (`#367 <https://github.com/fmtlib/fmt/issues/367>`_)
* Removed warnings under MSVC and clang (`#318 <https://github.com/fmtlib/fmt/issues/318>`_, `#250 <https://github.com/fmtlib/fmt/issues/250>`_, also merged `#385 <https://github.com/fmtlib/fmt/pull/385>`_ and `#361 <https://github.com/fmtlib/fmt/pull/361>`_). Thanks `@jcelerier (Jean-Michaël Celerier) <https://github.com/jcelerier>`_ and `@nmoehrle (Nils Moehrle) <https://github.com/nmoehrle>`_.
* Fixed compilation issues under Android (`#327 <https://github.com/fmtlib/fmt/pull/327>`_, `#345 <https://github.com/fmtlib/fmt/issues/345>`_ and `#381 <https://github.com/fmtlib/fmt/pull/381>`_), FreeBSD (`#358 <https://github.com/fmtlib/fmt/pull/358>`_), Cygwin (`#388 <https://github.com/fmtlib/fmt/issues/388>`_), MinGW (`#355 <https://github.com/fmtlib/fmt/issues/355>`_) as well as other issues (`#350 <https://github.com/fmtlib/fmt/issues/350>`_, `#366 <https://github.com/fmtlib/fmt/issues/355>`_, `#348 <https://github.com/fmtlib/fmt/pull/348>`_, `#402 <https://github.com/fmtlib/fmt/pull/402>`_, `#405 <https://github.com/fmtlib/fmt/pull/405>`_). Thanks to `@dpantele (Dmitry) <https://github.com/dpantele>`_, `@hghwng (Hugh Wang) <https://github.com/hghwng>`_, `@arvedarved (Tilman Keskinöz) <https://github.com/arvedarved>`_, `@LogicalKnight (Sean) <https://github.com/LogicalKnight>`_ and `@JanHellwig (Jan Hellwig) <https://github.com/janhellwig>`_.
* Fixed some documentation issues and extended specification (`#320 <https://github.com/fmtlib/fmt/issues/320>`_, `#333 <https://github.com/fmtlib/fmt/pull/333>`_, `#347 <https://github.com/fmtlib/fmt/issues/347>`_, `#362 <https://github.com/fmtlib/fmt/pull/362>`_). Thanks to `@smellman (Taro Matsuzawa aka. btm) <https://github.com/smellman>`_.
3.0.0 - 2016-05-07
------------------
+28 -5
View File
@@ -20,9 +20,11 @@ alternative to IOStreams.
Features
--------
* Two APIs: faster concatenation-based write API and slower (but still
very fast) replacement-based format API with positional arguments for
localization.
* Two APIs: faster concatenation-based `write API
<http://fmtlib.net/latest/api.html#write-api>`_ and slower,
but still very fast, replacement-based `format API
<http://fmtlib.net/latest/api.html#format-api>`_ with positional arguments
for localization.
* Write API similar to the one used by IOStreams but stateless allowing
faster implementation.
* Format API with `format string syntax
@@ -35,10 +37,10 @@ Features
* 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>`_
and better than performance of IOStreams. See `Speed tests`_ and
and better than the 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>`_.
* Small code size both in terms of source code (format consists of a single
* Small code size both in terms of source code (the core library consists of a single
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
@@ -89,6 +91,8 @@ An object of any user-defined type for which there is an overloaded
.. code:: c++
#include "fmt/ostream.h"
class Date {
int year_, month_, day_;
public:
@@ -132,6 +136,12 @@ Projects using this library
* `AMPL/MP <https://github.com/ampl/mp>`_:
An open-source library for mathematical programming
* `CUAUV <http://cuauv.org/>`_: Cornell University's autonomous underwater vehicle
* `Drake <http://drake.mit.edu/>`_: A planning, control, and analysis toolbox for nonlinear dynamical systems (MIT)
* `Envoy <https://lyft.github.io/envoy/>`_: C++ L7 proxy and communication bus (Lyft)
* `HarpyWar/pvpgn <https://github.com/pvpgn/pvpgn-server>`_:
Player vs Player Gaming Network with tweaks
@@ -139,6 +149,8 @@ Projects using this library
* `Keypirinha <http://keypirinha.com/>`_: A semantic launcher for Windows
* `Kodi <https://kodi.tv/>`_ (formerly xbmc): Home theater software
* `Lifeline <https://github.com/peter-clark/lifeline>`_: A 2D game
* `MongoDB Smasher <https://github.com/duckie/mongo_smasher>`_: A small tool to generate randomized datasets
@@ -158,6 +170,12 @@ Projects using this library
* `Salesforce Analytics Cloud <http://www.salesforce.com/analytics-cloud/overview/>`_:
Business intelligence software
* `Scylla <http://www.scylladb.com/>`_: A Cassandra-compatible NoSQL data store that can handle
1 million transactions per second on a single server
* `Seastar <http://www.seastar-project.org/>`_: An advanced, open-source C++ framework for
high-performance server applications on modern hardware
* `spdlog <https://github.com/gabime/spdlog>`_: Super fast C++ logging library
* `Stellar <https://www.stellar.org/>`_: Financial platform
@@ -390,6 +408,11 @@ It only applies if you distribute the documentation of fmt.
Acknowledgments
---------------
The fmt library is maintained by Victor Zverovich (`vitaut <https://github.com/vitaut>`_)
and Jonathan Müller (`foonathan <https://github.com/foonathan>`_) with contributions from many
other people. See `Contributors <https://github.com/fmtlib/fmt/graphs/contributors>`_ and `Releases <https://github.com/fmtlib/fmt/releases>`_ for some of the names. Let us know if your contribution
is not listed or mentioned incorrectly and we'll make it right.
The benchmark section of this readme file and the performance tests are taken
from the excellent `tinyformat <https://github.com/c42f/tinyformat>`_ library
written by Chris Foster. Boost Format library is acknowledged transitively
-2
View File
@@ -1,2 +0,0 @@
#include "../fmt/format.h"
#warning Including cppformat/format.h is deprecated. Include fmt/format.h instead.
-2
View File
@@ -1,2 +0,0 @@
#include "../fmt/posix.h"
#warning Including cppformat/posix.h is deprecated. Include fmt/posix.h instead.
+4 -2
View File
@@ -5,6 +5,8 @@ if (NOT DOXYGEN)
endif ()
add_custom_target(doc
COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/build.py ${FMT_VERSION})
COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/build.py ${FMT_VERSION}
SOURCES build.py conf.py _templates/layout.html)
install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/html/ DESTINATION share/doc/fmt)
install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/html/
DESTINATION share/doc/fmt OPTIONAL)
+28
View File
@@ -0,0 +1,28 @@
/* -- 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;
}
.github-btn {
border: 0;
overflow: hidden;
}
.jumbotron {
background-size: 100% 4px;
background-repeat: repeat-y;
color: white;
text-align: center;
}
+31 -20
View File
@@ -8,8 +8,9 @@
{# 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)
(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', 'fmtlib.net');
ga('send', 'pageview');
@@ -17,9 +18,11 @@
{% endblock %}
{%- macro searchform(classes, button) %}
<form class="{{classes}}" role="search" action="{{ pathto('search') }}" method="get">
<form class="{{classes}}" role="search" action="{{ pathto('search') }}"
method="get">
<div class="form-group">
<input type="text" name="q" class="form-control" {{ 'placeholder="Search"' if not button }} >
<input type="text" name="q" class="form-control"
{{ 'placeholder="Search"' if not button }} >
</div>
<input type="hidden" name="check_keywords" value="yes" />
<input type="hidden" name="area" value="default" />
@@ -36,7 +39,8 @@
<div class="navbar-content">
{# Brand and toggle get grouped for better mobile display #}
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target=".navbar-collapse">
<button type="button" class="navbar-toggle collapsed"
data-toggle="collapse" data-target=".navbar-collapse">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
@@ -49,18 +53,19 @@
<div class="collapse navbar-collapse">
<ul class="nav navbar-nav">
<li class="dropdown">
{# TODO: update versions automatically #}
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button"
aria-expanded="false">{{ version }} <span class="caret"></span></a>
<a href="#" class="dropdown-toggle" data-toggle="dropdown"
role="button" aria-expanded="false">{{ version }}
<span class="caret"></span></a>
<ul class="dropdown-menu" role="menu">
<li><a href="http://fmtlib.net/2.0.0/">2.0.0</a></li>
<li><a href="http://fmtlib.net/1.1.0/">1.1.0</a></li>
<li><a href="http://fmtlib.net/1.0.0/">1.0.0</a></li>
{% for v in versions.split(',') %}
<li><a href="http://fmtlib.net/{{v}}">{{v}}</a></li>
{% endfor %}
</ul>
</li>
{% for name in ['Contents', 'Usage', 'API', 'Syntax'] %}
{% if pagename == name.lower() %}
<li class="active"><a href="{{name.lower()}}.html">{{name}} <span class="sr-only">(current)</span></a></li>
<li class="active"><a href="{{name.lower()}}.html">{{name}}
<span class="sr-only">(current)</span></a></li>
{%else%}
<li><a href="{{name.lower()}}.html">{{name}}</a></li>
{%endif%}
@@ -75,20 +80,25 @@
</div> {# /.tb-container #}
</nav>
{% if pagename == "index" %}
{% set download_url = 'https://github.com/fmtlib/fmt/releases/download' %}
<div class="jumbotron">
<div class="tb-container">
<h1>{fmt}</h1>
<p class="lead">Small, safe and fast formatting library</p>
<div class="btn-group" role="group">
{% set name = 'fmt' if version.split('.')[0]|int >= 3 else 'cppformat' %}
<a class="btn btn-success"
href="https://github.com/fmtlib/fmt/releases/download/2.0.0/cppformat-2.0.0.zip">
<span class="glyphicon glyphicon-download"></span> Download
href="{{download_url}}/{{version}}/{{name}}-{{version}}.zip">
<span class="glyphicon glyphicon-download"></span> Download
</a>
<button type="button" class="btn btn-success dropdown-toggle" data-toggle="dropdown"><span class="caret"></span></button>
<button type="button" class="btn btn-success dropdown-toggle"
data-toggle="dropdown"><span class="caret"></span></button>
<ul class="dropdown-menu">
<li><a href="https://github.com/fmtlib/fmt/releases/download/2.0.0/cppformat-2.0.0.zip">Version 2.0.0</a></li>
<li><a href="https://github.com/fmtlib/fmt/releases/download/1.1.0/cppformat-1.1.0.zip">Version 1.1.0</a></li>
<li><a href="https://github.com/fmtlib/fmt/releases/download/1.0.0/cppformat-1.0.0.zip">Version 1.0.0</a></li>
{% for v in versions.split(',') %}
{% set name = 'fmt' if v.split('.')[0]|int >= 3 else 'cppformat' %}
<li><a href="{{download_url}}/{{v}}/{{name}}-{{v}}.zip">Version {{v}}
</a></li>
{% endfor %}
</ul>
</div>
</div>
@@ -105,14 +115,15 @@
{% block content %}
<div class="tb-container">
<div class="row">
{# TODO: integrate sidebar
{# Sidebar is currently disabled.
<div class="bs-sidebar">
<div class="sphinxsidebar" role="navigation" aria-label="main navigation">
<div class="sphinxsidebarwrapper">
{%- block sidebarlogo %}
{%- if logo %}
<p class="logo"><a href="{{ pathto(master_doc) }}">
<img class="logo" src="{{ pathto('_static/' + logo, 1) }}" alt="Logo"/>
<img class="logo" src="{{ pathto('_static/' + logo, 1) }}"
alt="Logo"/>
</a></p>
{%- endif %}
{%- endblock %}
+78 -12
View File
@@ -11,8 +11,8 @@ namespace is usually omitted in examples.
Format API
==========
The following functions use :ref:`format string syntax <syntax>` similar
to the one used by Python's `str.format
The following functions defined in ``fmt/format.h`` 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.
@@ -22,6 +22,11 @@ arguments in the resulting string.
*args* is an argument list representing arbitrary arguments.
The `performance of the format API
<https://github.com/fmtlib/fmt/blob/master/README.rst#speed-tests>`_ is close
to that of glibc's ``printf`` and better than the performance of IOStreams.
For even better speed use the `write API`_.
.. _format:
.. doxygenfunction:: format(CStringRef, ArgList)
@@ -40,8 +45,9 @@ arguments in the resulting string.
Date and time formatting
------------------------
The library supports `strftime <http://en.cppreference.com/w/cpp/chrono/c/strftime>`_-like
date and time formatting::
The library supports `strftime
<http://en.cppreference.com/w/cpp/chrono/c/strftime>`_-like date and time
formatting::
#include "fmt/time.h"
@@ -52,6 +58,36 @@ date and time formatting::
The format string syntax is described in the documentation of
`strftime <http://en.cppreference.com/w/cpp/chrono/c/strftime>`_.
Formatting user-defined types
-----------------------------
A custom ``format_arg`` function may be implemented and used to format any
user-defined type. That is how date and time formatting described in the
previous section is implemented in :file:`fmt/time.h`. The following example
shows how to implement custom formatting for a user-defined structure.
::
struct MyStruct { double a, b; };
void format_arg(fmt::BasicFormatter<char> &f,
const char *&format_str, const MyStruct &s) {
f.writer().write("[MyStruct: a={:.1f}, b={:.2f}]", s.a, s.b);
}
MyStruct m = { 1, 2 };
std::string s = fmt::format("m={}", n);
// s == "m=[MyStruct: a=1.0, b=2.00]"
Note in the example above the ``format_arg`` function ignores the contents of
``format_str`` so the type will always be formatted as specified. See
``format_arg`` in :file:`fmt/time.h` for an advanced example of how to use
the ``format_str`` argument to customize the formatted output.
This section shows how to define a custom format function for a user-defined
type. The next section describes how to get ``fmt`` to use a conventional stream
output ``operator<<`` when one is defined for a user-defined type.
``std::ostream`` support
------------------------
@@ -63,7 +99,7 @@ formatting of user-defined types that have overloaded ``operator<<``::
class Date {
int year_, month_, day_;
public:
Date(int year, int month, int day) : year_(year), month_(month), day_(day) {}
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_;
@@ -75,8 +111,6 @@ formatting of user-defined types that have overloaded ``operator<<``::
.. doxygenfunction:: print(std::ostream&, CStringRef, ArgList)
.. doxygenfunction:: fprintf(std::ostream&, CStringRef, ArgList)
Argument formatters
-------------------
@@ -86,7 +120,7 @@ custom argument formatter class::
// A custom argument formatter that formats negative integers as unsigned
// with the ``x`` format specifier.
class CustomArgFormatter :
public fmt::BasicArgFormatter<CustomArgFormatter, char> {
public fmt::BasicArgFormatter<CustomArgFormatter, char> {
public:
CustomArgFormatter(fmt::BasicFormatter<char, CustomArgFormatter> &f,
fmt::FormatSpec &s, const char *fmt)
@@ -120,22 +154,43 @@ custom argument formatter class::
.. doxygenclass:: fmt::ArgFormatter
:members:
Printf formatting functions
---------------------------
Printf formatting
-----------------
The header ``fmt/printf.h`` provides ``printf``-like formatting functionality.
The following functions use `printf format string syntax
<http://pubs.opengroup.org/onlinepubs/009695399/functions/fprintf.html>`_ with
a POSIX extension for positional arguments.
the POSIX extension for positional arguments. Unlike their standard
counterparts, the ``fmt`` functions are type-safe and throw an exception if an
argument type doesn't match its format specification.
.. doxygenfunction:: printf(CStringRef, ArgList)
.. doxygenfunction:: fprintf(std::FILE *, CStringRef, ArgList)
.. doxygenfunction:: fprintf(std::ostream&, CStringRef, ArgList)
.. doxygenfunction:: sprintf(CStringRef, ArgList)
.. doxygenclass:: fmt::PrintfFormatter
:members:
.. doxygenclass:: fmt::BasicPrintfArgFormatter
:members:
.. doxygenclass:: fmt::PrintfArgFormatter
:members:
Write API
=========
The write API provides classes for writing formatted data into character
streams. It is usually faster than the `format API`_ but, as IOStreams,
may result in larger compiled code size. The main writer class is
`~fmt::BasicMemoryWriter` which stores its output in a memory buffer and
provides direct access to it. It is possible to create custom writers that
store output elsewhere by subclassing `~fmt::BasicWriter`.
.. doxygenclass:: fmt::BasicWriter
:members:
@@ -145,6 +200,12 @@ Write API
.. doxygenclass:: fmt::BasicArrayWriter
:members:
.. doxygenclass:: fmt::BasicStringWriter
:members:
.. doxygenclass:: fmt::BasicContainerWriter
:members:
.. doxygenfunction:: bin(int)
.. doxygenfunction:: oct(int)
@@ -169,6 +230,8 @@ Utilities
.. doxygenclass:: fmt::ArgList
:members:
.. doxygenfunction:: fmt::to_string(const T&)
.. doxygenclass:: fmt::BasicStringRef
:members:
@@ -185,6 +248,8 @@ System errors
.. doxygenclass:: fmt::SystemError
:members:
.. doxygenfunction:: fmt::format_system_error
.. doxygenclass:: fmt::WindowsError
:members:
@@ -202,7 +267,8 @@ A custom allocator class can be specified as a template argument to
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;
typedef std::basic_string<char, std::char_traits<char>, CustomAllocator>
CustomString;
CustomString format(CustomAllocator alloc, fmt::CStringRef format_str,
fmt::ArgList args) {
+2 -1
View File
@@ -90,7 +90,8 @@
VERSION: '{{ release|e }}',
COLLAPSE_INDEX: false,
FILE_SUFFIX: '{{ '' if no_search_suffix else file_suffix }}',
HAS_SOURCE: {{ has_source|lower }}
HAS_SOURCE: {{ has_source|lower }},
SOURCELINK_SUFFIX: '{{ sourcelink_suffix }}'
};
</script>
{%- for scriptfile in script_files %}
+46 -28
View File
@@ -8,30 +8,35 @@ from distutils.version import LooseVersion
def pip_install(package, commit=None, **kwargs):
"Install package using pip."
min_version = kwargs.get('min_version')
if min_version:
from pkg_resources import get_distribution, DistributionNotFound
try:
installed_version = get_distribution(os.path.basename(package)).version
if LooseVersion(installed_version) >= min_version:
print('{} {} already installed'.format(package, min_version))
return
except DistributionNotFound:
pass
if commit:
check_version = kwargs.get('check_version', '')
#output = check_output(['pip', 'show', package.split('/')[1]])
#if check_version in output:
# print('{} already installed'.format(package))
# return
package = 'git+git://github.com/{0}.git@{1}'.format(package, commit)
print('Installing {}'.format(package))
check_call(['pip', 'install', '--upgrade', package])
package = 'git+https://github.com/{0}.git@{1}'.format(package, commit)
print('Installing {0}'.format(package))
check_call(['pip', 'install', package])
def build_docs(version='dev'):
def create_build_env(dirname='virtualenv'):
# Create virtualenv.
doc_dir = os.path.dirname(os.path.realpath(__file__))
virtualenv_dir = 'virtualenv'
check_call(['virtualenv', virtualenv_dir])
if not os.path.exists(dirname):
check_call(['virtualenv', dirname])
import sysconfig
scripts_dir = os.path.basename(sysconfig.get_path('scripts'))
activate_this_file = os.path.join(virtualenv_dir, scripts_dir,
'activate_this.py')
activate_this_file = os.path.join(dirname, scripts_dir, 'activate_this.py')
with open(activate_this_file) as f:
exec(f.read(), dict(__file__=activate_this_file))
# Import get_distribution after activating virtualenv to get info about
# the correct packages.
from pkg_resources import get_distribution, DistributionNotFound
# Upgrade pip because installation of sphinx with pip 1.1 available on Travis
# is broken (see #207) and it doesn't support the show command.
from pkg_resources import get_distribution, DistributionNotFound
pip_version = get_distribution('pip').version
if LooseVersion(pip_version) < LooseVersion('1.5.4'):
print("Updating pip")
@@ -46,27 +51,35 @@ def build_docs(version='dev'):
except DistributionNotFound:
pass
# Install Sphinx and Breathe.
pip_install('fmtlib/sphinx',
'12dde8afdb0a7bb5576e2656692c3478c69d8cc3',
check_version='1.4a0.dev-20151013')
pip_install('sphinx-doc/sphinx', '12b83372ac9316e8cbe86e7fed889296a4cc29ee',
min_version='1.4.1.dev20160531')
pip_install('michaeljones/breathe',
'1c9d7f80378a92cffa755084823a78bb38ee4acc')
'6b1c5bb7a1866f15fc328b8716258354b10c1daa',
min_version='4.2.0')
def build_docs(version='dev', **kwargs):
doc_dir = kwargs.get('doc_dir', os.path.dirname(os.path.realpath(__file__)))
work_dir = kwargs.get('work_dir', '.')
include_dir = kwargs.get('include_dir',
os.path.join(os.path.dirname(doc_dir), 'fmt'))
# Build docs.
cmd = ['doxygen', '-']
p = Popen(cmd, stdin=PIPE)
doxyxml_dir = os.path.join(work_dir, 'doxyxml')
p.communicate(input=r'''
PROJECT_NAME = fmt
GENERATE_LATEX = NO
GENERATE_MAN = NO
GENERATE_RTF = NO
CASE_SENSE_NAMES = NO
INPUT = {0}/format.h {0}/ostream.h
INPUT = {0}/container.h {0}/format.h {0}/ostream.h \
{0}/printf.h {0}/string.h
QUIET = YES
JAVADOC_AUTOBRIEF = YES
AUTOLINK_SUPPORT = NO
GENERATE_HTML = NO
GENERATE_XML = YES
XML_OUTPUT = doxyxml
XML_OUTPUT = {1}
ALIASES = "rst=\verbatim embed:rst"
ALIASES += "endrst=\endverbatim"
MACRO_EXPANSION = YES
@@ -76,24 +89,29 @@ def build_docs(version='dev'):
FMT_USE_USER_DEFINED_LITERALS=1 \
FMT_API=
EXCLUDE_SYMBOLS = fmt::internal::* StringValue write_str
'''.format(os.path.join(os.path.dirname(doc_dir), 'fmt')).encode('UTF-8'))
'''.format(include_dir, doxyxml_dir).encode('UTF-8'))
if p.returncode != 0:
raise CalledProcessError(p.returncode, cmd)
html_dir = os.path.join(work_dir, 'html')
versions = ['3.0.0', '2.0.0', '1.1.0']
check_call(['sphinx-build',
'-Dbreathe_projects.format=' + os.path.join(os.getcwd(), 'doxyxml'),
'-Dversion=' + version, '-Drelease=' + version, '-Aversion=' + version,
'-b', 'html', doc_dir, 'html'])
'-Dbreathe_projects.format=' + os.path.abspath(doxyxml_dir),
'-Dversion=' + version, '-Drelease=' + version,
'-Aversion=' + version, '-Aversions=' + ','.join(versions),
'-b', 'html', doc_dir, html_dir])
try:
check_call(['lessc', '--clean-css',
'--include-path=' + os.path.join(doc_dir, 'bootstrap'),
os.path.join(doc_dir, 'fmt.less'),
'html/_static/fmt.css'])
os.path.join(html_dir, '_static', 'fmt.css')])
except OSError as e:
if e.errno != errno.ENOENT:
raise
print('lessc not found; make sure that Less (http://lesscss.org/) is installed')
print('lessc not found; make sure that Less (http://lesscss.org/) ' +
'is installed')
sys.exit(1)
return 'html'
return html_dir
if __name__ == '__main__':
create_build_env()
build_docs(sys.argv[1])
+3 -4
View File
@@ -228,8 +228,7 @@ latex_documents = [
# One entry per manual page. List of tuples
# (source start file, name, description, authors, manual section).
man_pages = [
('index', 'format', u'format Documentation',
[u'Victor Zverovich'], 1)
('index', 'fmt', u'fmt documentation', [u'Victor Zverovich'], 1)
]
# If true, show URL addresses after external links.
@@ -242,8 +241,8 @@ man_pages = [
# (source start file, target name, title, author,
# dir menu entry, description, category)
texinfo_documents = [
('index', 'format', u'format Documentation',
u'Victor Zverovich', 'format', 'One line description of project.',
('index', 'fmt', u'fmt documentation',
u'Victor Zverovich', 'fmt', 'One line description of project.',
'Miscellaneous'),
]
+78 -12
View File
@@ -11,8 +11,8 @@ namespace is usually omitted in examples.
Format API
==========
The following functions use :ref:`format string syntax <syntax>` similar
to the one used by Python's `str.format
The following functions defined in ``fmt/format.h`` 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.
@@ -22,6 +22,11 @@ arguments in the resulting string.
*args* is an argument list representing arbitrary arguments.
The `performance of the format API
<https://github.com/fmtlib/fmt/blob/master/README.rst#speed-tests>`_ is close
to that of glibc's ``printf`` and better than the performance of IOStreams.
For even better speed use the `write API`_.
.. _format:
.. doxygenfunction:: format(CStringRef, ArgList)
@@ -40,8 +45,9 @@ arguments in the resulting string.
Date and time formatting
------------------------
The library supports `strftime <http://en.cppreference.com/w/cpp/chrono/c/strftime>`_-like
date and time formatting::
The library supports `strftime
<http://en.cppreference.com/w/cpp/chrono/c/strftime>`_-like date and time
formatting::
#include "fmt/time.h"
@@ -52,6 +58,36 @@ date and time formatting::
The format string syntax is described in the documentation of
`strftime <http://en.cppreference.com/w/cpp/chrono/c/strftime>`_.
Formatting user-defined types
-----------------------------
A custom ``format_arg`` function may be implemented and used to format any
user-defined type. That is how date and time formatting described in the
previous section is implemented in :file:`fmt/time.h`. The following example
shows how to implement custom formatting for a user-defined structure.
::
struct MyStruct { double a, b; };
void format_arg(fmt::BasicFormatter<char> &f,
const char *&format_str, const MyStruct &s) {
f.writer().write("[MyStruct: a={:.1f}, b={:.2f}]", s.a, s.b);
}
MyStruct m = { 1, 2 };
std::string s = fmt::format("m={}", n);
// s == "m=[MyStruct: a=1.0, b=2.00]"
Note in the example above the ``format_arg`` function ignores the contents of
``format_str`` so the type will always be formatted as specified. See
``format_arg`` in :file:`fmt/time.h` for an advanced example of how to use
the ``format_str`` argument to customize the formatted output.
This section shows how to define a custom format function for a user-defined
type. The next section describes how to get ``fmt`` to use a conventional stream
output ``operator<<`` when one is defined for a user-defined type.
``std::ostream`` support
------------------------
@@ -63,7 +99,7 @@ formatting of user-defined types that have overloaded ``operator<<``::
class Date {
int year_, month_, day_;
public:
Date(int year, int month, int day) : year_(year), month_(month), day_(day) {}
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_;
@@ -75,8 +111,6 @@ formatting of user-defined types that have overloaded ``operator<<``::
.. doxygenfunction:: print(std::ostream&, CStringRef, ArgList)
.. doxygenfunction:: fprintf(std::ostream&, CStringRef, ArgList)
Argument formatters
-------------------
@@ -86,7 +120,7 @@ custom argument formatter class::
// A custom argument formatter that formats negative integers as unsigned
// with the ``x`` format specifier.
class CustomArgFormatter :
public fmt::BasicArgFormatter<CustomArgFormatter, char> {
public fmt::BasicArgFormatter<CustomArgFormatter, char> {
public:
CustomArgFormatter(fmt::BasicFormatter<char, CustomArgFormatter> &f,
fmt::FormatSpec &s, const char *fmt)
@@ -120,22 +154,43 @@ custom argument formatter class::
.. doxygenclass:: fmt::ArgFormatter
:members:
Printf formatting functions
---------------------------
Printf formatting
-----------------
The header ``fmt/printf.h`` provides ``printf``-like formatting functionality.
The following functions use `printf format string syntax
<http://pubs.opengroup.org/onlinepubs/009695399/functions/fprintf.html>`_ with
a POSIX extension for positional arguments.
the POSIX extension for positional arguments. Unlike their standard
counterparts, the ``fmt`` functions are type-safe and throw an exception if an
argument type doesn't match its format specification.
.. doxygenfunction:: printf(CStringRef, ArgList)
.. doxygenfunction:: fprintf(std::FILE *, CStringRef, ArgList)
.. doxygenfunction:: fprintf(std::ostream&, CStringRef, ArgList)
.. doxygenfunction:: sprintf(CStringRef, ArgList)
.. doxygenclass:: fmt::PrintfFormatter
:members:
.. doxygenclass:: fmt::BasicPrintfArgFormatter
:members:
.. doxygenclass:: fmt::PrintfArgFormatter
:members:
Write API
=========
The write API provides classes for writing formatted data into character
streams. It is usually faster than the `format API`_ but, as IOStreams,
may result in larger compiled code size. The main writer class is
`~fmt::BasicMemoryWriter` which stores its output in a memory buffer and
provides direct access to it. It is possible to create custom writers that
store output elsewhere by subclassing `~fmt::BasicWriter`.
.. doxygenclass:: fmt::BasicWriter
:members:
@@ -145,6 +200,12 @@ Write API
.. doxygenclass:: fmt::BasicArrayWriter
:members:
.. doxygenclass:: fmt::BasicStringWriter
:members:
.. doxygenclass:: fmt::BasicContainerWriter
:members:
.. doxygenfunction:: bin(int)
.. doxygenfunction:: oct(int)
@@ -169,6 +230,8 @@ Utilities
.. doxygenclass:: fmt::ArgList
:members:
.. doxygenfunction:: fmt::to_string(const T&)
.. doxygenclass:: fmt::BasicStringRef
:members:
@@ -185,6 +248,8 @@ System errors
.. doxygenclass:: fmt::SystemError
:members:
.. doxygenfunction:: fmt::format_system_error
.. doxygenclass:: fmt::WindowsError
:members:
@@ -202,7 +267,8 @@ A custom allocator class can be specified as a template argument to
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;
typedef std::basic_string<char, std::char_traits<char>, CustomAllocator>
CustomString;
CustomString format(CustomAllocator alloc, fmt::CStringRef format_str,
fmt::ArgList args) {
+32 -29
View File
@@ -10,9 +10,9 @@ alternative to C++ IOStreams.
<div class="panel panel-default">
<div class="panel-heading">What users say:</div>
<div class="panel-body">
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.
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.
</div>
</div>
@@ -24,8 +24,8 @@ Format API
The replacement-based Format API provides a safe alternative to ``printf``,
``sprintf`` and friends with comparable or `better performance
<http://zverovich.net/2013/09/07/integer-to-string-conversion-in-cplusplus.html>`_.
The `format string syntax <doc/latest/index.html#format-string-syntax>`_ is similar
to the one used by `str.format <http://docs.python.org/2/library/stdtypes.html#str.format>`_
The `format string syntax <syntax.html>`_ is similar to the one used by
`str.format <http://docs.python.org/2/library/stdtypes.html#str.format>`_
in Python:
.. code:: c++
@@ -98,8 +98,8 @@ literal operators, they must be made visible with the directive
Write API
---------
The concatenation-based Write API (experimental) provides a
`fast <http://zverovich.net/2013/09/07/integer-to-string-conversion-in-cplusplus.html>`_
The concatenation-based Write API (experimental) provides a `fast
<http://zverovich.net/2013/09/07/integer-to-string-conversion-in-cplusplus.html>`_
stateless alternative to IOStreams:
.. code:: c++
@@ -112,8 +112,9 @@ stateless alternative to IOStreams:
Safety
------
The library is fully type safe, automatic memory management prevents buffer overflow,
errors in format strings are reported using exceptions. For example, the code
The library is fully type safe, automatic memory management prevents buffer
overflow, errors in format strings are reported using exceptions. For example,
the code
.. code:: c++
@@ -138,19 +139,21 @@ formatted into a narrow string. You can use a wide format string instead:
fmt::format(L"Cyrillic letter {}", L'\x42e');
For comparison, writing a wide character to ``std::ostream`` results in
its numeric value being written to the stream (i.e. 1070 instead of letter 'ю' which
is represented by ``L'\x42e'`` if we use Unicode) which is rarely what is needed.
its numeric value being written to the stream (i.e. 1070 instead of letter 'ю'
which is represented by ``L'\x42e'`` if we use Unicode) which is rarely what is
needed.
.. _portability:
Portability
-----------
The library is highly portable. Here is an incomplete list of operating systems and
compilers where it has been tested and known to work:
The library is highly portable. Here is an incomplete list of operating systems
and compilers where it has been tested and known to work:
* 64-bit (amd64) GNU/Linux with GCC 4.4.3, `4.6.3 <https://travis-ci.org/fmtlib/fmt>`_,
4.7.2, 4.8.1 and Intel C++ Compiler (ICC) 14.0.2
* 64-bit (amd64) GNU/Linux with GCC 4.4.3,
`4.6.3 <https://travis-ci.org/fmtlib/fmt>`_, 4.7.2, 4.8.1, and Intel C++
Compiler (ICC) 14.0.2
* 32-bit (i386) GNU/Linux with GCC 4.4.3, 4.6.3
@@ -161,21 +164,21 @@ compilers where it has been tested and known to work:
* 32-bit Windows with Visual C++ 2010
Although the library uses C++11 features when available, it also works with older
compilers and standard library implementations. The only thing to keep in mind
for C++98 portability:
Although the library uses C++11 features when available, it also works with
older compilers and standard library implementations. The only thing to keep in
mind for C++98 portability:
* Variadic templates: minimum GCC 4.4, Clang 2.9 or VS2013. This feature allows
the Format API to accept an unlimited number of arguments. With older compilers
the maximum is 15.
the Format API to accept an unlimited number of arguments. With older
compilers the maximum is 15.
* User-defined literals: minimum GCC 4.7, Clang 3.1 or VS2015. The suffixes
``_format`` and ``_a`` are functionally equivalent to the functions
* User-defined literals: minimum GCC 4.7, Clang 3.1 or VS2015. The suffixes
``_format`` and ``_a`` are functionally equivalent to the functions
``fmt::format`` and ``fmt::arg``.
The output of all formatting functions is consistent across platforms. In particular,
formatting a floating-point infinity always gives ``inf`` while the output
of ``printf`` is platform-dependent in this case. For example,
The output of all formatting functions is consistent across platforms. In
particular, formatting a floating-point infinity always gives ``inf`` while the
output of ``printf`` is platform-dependent in this case. For example,
.. code::
@@ -188,10 +191,10 @@ always prints ``inf``.
Ease of Use
-----------
fmt has a small self-contained code base consisting of a single header file
and a single source file and no external dependencies. A permissive BSD `license
<https://github.com/fmtlib/fmt#license>`_ allows using the library both
in open-source and commercial projects.
fmt has a small self-contained code base with the core library consisting of
a single header file and a single source file and no external dependencies.
A permissive BSD `license <https://github.com/fmtlib/fmt#license>`_ allows
using the library both in open-source and commercial projects.
.. raw:: html
+7 -9
View File
@@ -49,12 +49,10 @@ 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.
A *format_spec* field can also include nested replacement fields in certain
positions within it. These nested replacement fields can contain only an
argument id; format specifications are not allowed. This allows the
formatting of a value to be dynamically specified.
See the :ref:`formatexamples` section for some examples.
@@ -80,8 +78,8 @@ The general form of a *standard format specifier* is:
sign: "+" | "-" | " "
width: `integer` | "{" `arg_id` "}"
precision: `integer` | "{" `arg_id` "}"
type: `int_type` | "c" | "e" | "E" | "f" | "F" | "g" | "G" | "p" | "s"
int_type: "b" | "B" | "d" | "o" | "x" | "X"
type: `int_type` | "a" | "A" | "c" | "e" | "E" | "f" | "F" | "g" | "G" | "p" | "s"
int_type: "b" | "B" | "d" | "n" | "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
@@ -234,7 +232,7 @@ The available presentation types for floating-point values are:
+=========+==========================================================+
| ``'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. |
| | 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. |
+23 -2
View File
@@ -54,6 +54,23 @@ To build a `shared library`__ set the ``BUILD_SHARED_LIBS`` CMake variable to
__ http://en.wikipedia.org/wiki/Library_%28computing%29#Shared_libraries
Header-only usage with CMake
============================
In order to add ``fmtlib`` into an existing ``CMakeLists.txt`` file, you can add the ``fmt`` library directory into your main project, which will enable the ``fmt`` library::
add_subdirectory(fmt)
If you have a project called ``foo`` that you would like to link against the fmt library in a header-only fashion, you can enable with with::
target_link_libraries(foo PRIVATE fmt::fmt-header-only)
And then to ensure that the ``fmt`` library does not always get built, you can modify the call to ``add_subdirectory`` to read ::
add_subdirectory(fmt EXCLUDE_FROM_ALL)
This will ensure that the ``fmt`` library is exluded from calls to ``make``, ``make all``, or ``cmake --build .``.
Building the documentation
==========================
@@ -62,7 +79,11 @@ system:
* `Python <https://www.python.org/>`_ with pip and virtualenv
* `Doxygen <http://www.stack.nl/~dimitri/doxygen/>`_
* `Less <http://lesscss.org/>`_ with less-plugin-clean-css
* `Less <http://lesscss.org/>`_ with ``less-plugin-clean-css``.
Ubuntu doesn't package the ``clean-css`` plugin so you should use ``npm``
instead of ``apt`` to install both ``less`` and the plugin::
sudo npm install -g less less-plugin-clean-css.
First generate makefiles or project files using CMake as described in
the previous section. Then compile the ``doc`` target/project, for example::
@@ -87,4 +108,4 @@ Homebrew
fmt can be installed on OS X using `Homebrew <http://brew.sh/>`_::
brew install cppformat
brew install fmt
@@ -47,8 +47,10 @@
.highlight .mh { color: #208050 } /* Literal.Number.Hex */
.highlight .mi { color: #208050 } /* Literal.Number.Integer */
.highlight .mo { color: #208050 } /* Literal.Number.Oct */
.highlight .sa { color: #4070a0 } /* Literal.String.Affix */
.highlight .sb { color: #4070a0 } /* Literal.String.Backtick */
.highlight .sc { color: #4070a0 } /* Literal.String.Char */
.highlight .dl { color: #4070a0 } /* Literal.String.Delimiter */
.highlight .sd { color: #4070a0; font-style: italic } /* Literal.String.Doc */
.highlight .s2 { color: #4070a0 } /* Literal.String.Double */
.highlight .se { color: #4070a0; font-weight: bold } /* Literal.String.Escape */
@@ -59,7 +61,9 @@
.highlight .s1 { color: #4070a0 } /* Literal.String.Single */
.highlight .ss { color: #517918 } /* Literal.String.Symbol */
.highlight .bp { color: #007020 } /* Name.Builtin.Pseudo */
.highlight .fm { color: #06287e } /* Name.Function.Magic */
.highlight .vc { color: #bb60d5 } /* Name.Variable.Class */
.highlight .vg { color: #bb60d5 } /* Name.Variable.Global */
.highlight .vi { color: #bb60d5 } /* Name.Variable.Instance */
.highlight .vm { color: #bb60d5 } /* Name.Variable.Magic */
.highlight .il { color: #208050 } /* Literal.Number.Integer.Long */
+405 -132
View File
@@ -8,7 +8,7 @@
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>API Reference &mdash; fmt 3.0.0 documentation</title>
<title>API Reference &mdash; fmt 4.0.0 documentation</title>
<link rel="stylesheet" href="_static/basic.css" type="text/css" />
<link rel="stylesheet" href="_static/pygments.css" type="text/css" />
@@ -17,10 +17,11 @@
<script type="text/javascript">
var DOCUMENTATION_OPTIONS = {
URL_ROOT: './',
VERSION: '3.0.0',
VERSION: '4.0.0',
COLLAPSE_INDEX: false,
FILE_SUFFIX: '.html',
HAS_SOURCE: true
HAS_SOURCE: true,
SOURCELINK_SUFFIX: ''
};
</script>
<script type="text/javascript" src="_static/jquery.js"></script>
@@ -35,8 +36,9 @@
<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)
(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', 'fmtlib.net');
ga('send', 'pageview');
@@ -50,7 +52,8 @@
<div class="navbar-content">
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target=".navbar-collapse">
<button type="button" class="navbar-toggle collapsed"
data-toggle="collapse" data-target=".navbar-collapse">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
@@ -63,13 +66,17 @@
<div class="collapse navbar-collapse">
<ul class="nav navbar-nav">
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button"
aria-expanded="false">3.0.0 <span class="caret"></span></a>
<a href="#" class="dropdown-toggle" data-toggle="dropdown"
role="button" aria-expanded="false">4.0.0
<span class="caret"></span></a>
<ul class="dropdown-menu" role="menu">
<li><a href="http://fmtlib.net/2.0.0/">2.0.0</a></li>
<li><a href="http://fmtlib.net/1.1.0/">1.1.0</a></li>
<li><a href="http://fmtlib.net/1.0.0/">1.0.0</a></li>
<li><a href="http://fmtlib.net/3.0.0">3.0.0</a></li>
<li><a href="http://fmtlib.net/2.0.0">2.0.0</a></li>
<li><a href="http://fmtlib.net/1.1.0">1.1.0</a></li>
</ul>
</li>
@@ -82,7 +89,8 @@
<li class="active"><a href="api.html">API <span class="sr-only">(current)</span></a></li>
<li class="active"><a href="api.html">API
<span class="sr-only">(current)</span></a></li>
@@ -92,9 +100,11 @@
</ul>
<form class="navbar-form navbar-right" role="search" action="search.html" method="get">
<form class="navbar-form navbar-right" role="search" action="search.html"
method="get">
<div class="form-group">
<input type="text" name="q" class="form-control" placeholder="Search" >
<input type="text" name="q" class="form-control"
placeholder="Search" >
</div>
<input type="hidden" name="check_keywords" value="yes" />
<input type="hidden" name="area" value="default" />
@@ -122,13 +132,16 @@ in namespace <code class="docutils literal"><span class="pre">fmt</span></code>
namespace is usually omitted in examples.</p>
<div class="section" id="format-api">
<h2>Format API<a class="headerlink" href="#format-api" title="Permalink to this headline"></a></h2>
<p>The following functions use <a class="reference internal" href="syntax.html#syntax"><span class="std std-ref">format string syntax</span></a> similar
to the one used by Python&#8217;s <a class="reference external" href="http://docs.python.org/3/library/stdtypes.html#str.format">str.format</a> function.
<p>The following functions defined in <code class="docutils literal"><span class="pre">fmt/format.h</span></code> use <a class="reference internal" href="syntax.html#syntax"><span class="std std-ref">format string
syntax</span></a> similar to the one used by Python&#8217;s <a class="reference external" href="http://docs.python.org/3/library/stdtypes.html#str.format">str.format</a> function.
They take <em>format_str</em> and <em>args</em> as arguments.</p>
<p><em>format_str</em> is a format string that contains literal text and replacement
fields surrounded by braces <code class="docutils literal"><span class="pre">{}</span></code>. The fields are replaced with formatted
arguments in the resulting string.</p>
<p><em>args</em> is an argument list representing arbitrary arguments.</p>
<p>The <a class="reference external" href="https://github.com/fmtlib/fmt/blob/master/README.rst#speed-tests">performance of the format API</a> is close
to that of glibc&#8217;s <code class="docutils literal"><span class="pre">printf</span></code> and better than the performance of IOStreams.
For even better speed use the <a class="reference internal" href="#write-api">write API</a>.</p>
<span class="target" id="format"></span><dl class="function">
<dt id="_CPPv2N3fmt6formatE10CStringRef7ArgList">
<span id="fmt::format__CStringRef.ArgList"></span><span class="target" id="formatformat_8h_1a638f25c535b3bfa12dc1478b11885b6f"></span>std::string <code class="descclassname">fmt::</code><code class="descname">format</code><span class="sig-paren">(</span>CStringRef <em>format_str</em>, <a class="reference internal" href="#_CPPv2N3fmt7ArgListE" title="fmt::ArgList">ArgList</a> <em>args</em><span class="sig-paren">)</span><a class="headerlink" href="#_CPPv2N3fmt6formatE10CStringRef7ArgList" title="Permalink to this definition"></a></dt>
@@ -140,18 +153,10 @@ arguments in the resulting string.</p>
</p>
</dd></dl>
<dl class="function">
<dt id="_CPPv2N3fmt8literalsli7_formatEPKcNSt6size_tE">
<span class="target" id="formatformat_8h_1a8f568cdac4d075838347616fc4899417"></span>internal::UdlFormat&lt;char&gt; <code class="descclassname">fmt::literals::</code><code class="descname">operator&quot;&quot;_format</code><span class="sig-paren">(</span><em class="property">const</em> char *<em>s</em>, std::size_t<span class="sig-paren">)</span><a class="headerlink" href="#_CPPv2N3fmt8literalsli7_formatEPKcNSt6size_tE" title="Permalink to this definition"></a></dt>
<dd><p><p>C++11 literal equivalent of <a class="reference internal" href="#_CPPv2N3fmt6formatE10CStringRef7ArgList" title="fmt::format"><code class="xref cpp cpp-func docutils literal"><span class="pre">fmt::format()</span></code></a>.</p>
<p><strong>Example</strong>:</p>
<div class="highlight-c++"><div class="highlight"><pre><span></span><span class="k">using</span> <span class="k">namespace</span> <span class="n">fmt</span><span class="o">::</span><span class="n">literals</span><span class="p">;</span>
<span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">message</span> <span class="o">=</span> <span class="s">&quot;The answer is {}&quot;</span><span class="n">_format</span><span class="p">(</span><span class="mi">42</span><span class="p">);</span>
</pre></div>
<div class="admonition warning">
<p class="first admonition-title">Warning</p>
<p class="last">doxygenfunction: Cannot find function &#8220;operator&#8221;&#8220;_format&#8221; in doxygen xml output for project &#8220;format&#8221; from directory: /home/foonathan/Programming/fmt/build/doc/doxyxml</p>
</div>
</p>
</dd></dl>
<span class="target" id="print"></span><dl class="function">
<dt id="_CPPv2N3fmt5printE10CStringRef7ArgList">
<span id="fmt::print__CStringRef.ArgList"></span><span class="target" id="formatformat_8h_1a7cfad68e64995774f11072aaf5008e8a"></span>void <code class="descclassname">fmt::</code><code class="descname">print</code><span class="sig-paren">(</span>CStringRef <em>format_str</em>, <a class="reference internal" href="#_CPPv2N3fmt7ArgListE" title="fmt::ArgList">ArgList</a> <em>args</em><span class="sig-paren">)</span><a class="headerlink" href="#_CPPv2N3fmt5printE10CStringRef7ArgList" title="Permalink to this definition"></a></dt>
@@ -180,7 +185,8 @@ arguments in the resulting string.</p>
<dt id="_CPPv2N3fmt14BasicFormatterE">
<span id="fmt::BasicFormatter"></span><em class="property">class </em><code class="descclassname">fmt::</code><code class="descname">BasicFormatter</code><a class="headerlink" href="#_CPPv2N3fmt14BasicFormatterE" title="Permalink to this definition"></a></dt>
<dd><p>This template formats data and writes the output to a writer. </p>
<div class="breathe-sectiondef container">
<p>Inherits from fmt::internal::FormatterBase</p>
<div class="breathe-sectiondef docutils container">
<p class="breathe-sectiondef-title rubric">Public Types</p>
<dl class="type">
<dt id="_CPPv2N3fmt14BasicFormatter4CharE">
@@ -189,7 +195,7 @@ arguments in the resulting string.</p>
</dd></dl>
</div>
<div class="breathe-sectiondef container">
<div class="breathe-sectiondef docutils container">
<p class="breathe-sectiondef-title rubric">Public Functions</p>
<dl class="function">
<dt id="_CPPv2N3fmt14BasicFormatter14BasicFormatterERK7ArgListR11BasicWriterI4CharE">
@@ -217,8 +223,8 @@ appropriate lifetimes.</p>
<div class="section" id="date-and-time-formatting">
<h3>Date and time formatting<a class="headerlink" href="#date-and-time-formatting" title="Permalink to this headline"></a></h3>
<p>The library supports <a class="reference external" href="http://en.cppreference.com/w/cpp/chrono/c/strftime">strftime</a>-like
date and time formatting:</p>
<p>The library supports <a class="reference external" href="http://en.cppreference.com/w/cpp/chrono/c/strftime">strftime</a>-like date and time
formatting:</p>
<div class="highlight-c++"><div class="highlight"><pre><span></span><span class="cp">#include</span> <span class="cpf">&quot;fmt/time.h&quot;</span><span class="cp"></span>
<span class="n">std</span><span class="o">::</span><span class="kt">time_t</span> <span class="n">t</span> <span class="o">=</span> <span class="n">std</span><span class="o">::</span><span class="n">time</span><span class="p">(</span><span class="k">nullptr</span><span class="p">);</span>
@@ -229,6 +235,32 @@ date and time formatting:</p>
<p>The format string syntax is described in the documentation of
<a class="reference external" href="http://en.cppreference.com/w/cpp/chrono/c/strftime">strftime</a>.</p>
</div>
<div class="section" id="formatting-user-defined-types">
<h3>Formatting user-defined types<a class="headerlink" href="#formatting-user-defined-types" title="Permalink to this headline"></a></h3>
<p>A custom <code class="docutils literal"><span class="pre">format_arg</span></code> function may be implemented and used to format any
user-defined type. That is how date and time formatting described in the
previous section is implemented in <code class="file docutils literal"><span class="pre">fmt/time.h</span></code>. The following example
shows how to implement custom formatting for a user-defined structure.</p>
<div class="highlight-c++"><div class="highlight"><pre><span></span><span class="k">struct</span> <span class="n">MyStruct</span> <span class="p">{</span> <span class="kt">double</span> <span class="n">a</span><span class="p">,</span> <span class="n">b</span><span class="p">;</span> <span class="p">};</span>
<span class="kt">void</span> <span class="nf">format_arg</span><span class="p">(</span><span class="n">fmt</span><span class="o">::</span><span class="n">BasicFormatter</span><span class="o">&lt;</span><span class="kt">char</span><span class="o">&gt;</span> <span class="o">&amp;</span><span class="n">f</span><span class="p">,</span>
<span class="k">const</span> <span class="kt">char</span> <span class="o">*&amp;</span><span class="n">format_str</span><span class="p">,</span> <span class="k">const</span> <span class="n">MyStruct</span> <span class="o">&amp;</span><span class="n">s</span><span class="p">)</span> <span class="p">{</span>
<span class="n">f</span><span class="p">.</span><span class="n">writer</span><span class="p">().</span><span class="n">write</span><span class="p">(</span><span class="s">&quot;[MyStruct: a={:.1f}, b={:.2f}]&quot;</span><span class="p">,</span> <span class="n">s</span><span class="p">.</span><span class="n">a</span><span class="p">,</span> <span class="n">s</span><span class="p">.</span><span class="n">b</span><span class="p">);</span>
<span class="p">}</span>
<span class="n">MyStruct</span> <span class="n">m</span> <span class="o">=</span> <span class="p">{</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">2</span> <span class="p">};</span>
<span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">s</span> <span class="o">=</span> <span class="n">fmt</span><span class="o">::</span><span class="n">format</span><span class="p">(</span><span class="s">&quot;m={}&quot;</span><span class="p">,</span> <span class="n">n</span><span class="p">);</span>
<span class="c1">// s == &quot;m=[MyStruct: a=1.0, b=2.00]&quot;</span>
</pre></div>
</div>
<p>Note in the example above the <code class="docutils literal"><span class="pre">format_arg</span></code> function ignores the contents of
<code class="docutils literal"><span class="pre">format_str</span></code> so the type will always be formatted as specified. See
<code class="docutils literal"><span class="pre">format_arg</span></code> in <code class="file docutils literal"><span class="pre">fmt/time.h</span></code> for an advanced example of how to use
the <code class="docutils literal"><span class="pre">format_str</span></code> argument to customize the formatted output.</p>
<p>This section shows how to define a custom format function for a user-defined
type. The next section describes how to get <code class="docutils literal"><span class="pre">fmt</span></code> to use a conventional stream
output <code class="docutils literal"><span class="pre">operator&lt;&lt;</span></code> when one is defined for a user-defined type.</p>
</div>
<div class="section" id="std-ostream-support">
<h3><code class="docutils literal"><span class="pre">std::ostream</span></code> support<a class="headerlink" href="#std-ostream-support" title="Permalink to this headline"></a></h3>
<p>The header <code class="docutils literal"><span class="pre">fmt/ostream.h</span></code> provides <code class="docutils literal"><span class="pre">std::ostream</span></code> support including
@@ -238,7 +270,7 @@ formatting of user-defined types that have overloaded <code class="docutils lite
<span class="k">class</span> <span class="nc">Date</span> <span class="p">{</span>
<span class="kt">int</span> <span class="n">year_</span><span class="p">,</span> <span class="n">month_</span><span class="p">,</span> <span class="n">day_</span><span class="p">;</span>
<span class="k">public</span><span class="o">:</span>
<span class="n">Date</span><span class="p">(</span><span class="kt">int</span> <span class="n">year</span><span class="p">,</span> <span class="kt">int</span> <span class="n">month</span><span class="p">,</span> <span class="kt">int</span> <span class="n">day</span><span class="p">)</span> <span class="o">:</span> <span class="n">year_</span><span class="p">(</span><span class="n">year</span><span class="p">),</span> <span class="n">month_</span><span class="p">(</span><span class="n">month</span><span class="p">),</span> <span class="n">day_</span><span class="p">(</span><span class="n">day</span><span class="p">)</span> <span class="p">{}</span>
<span class="n">Date</span><span class="p">(</span><span class="kt">int</span> <span class="n">year</span><span class="p">,</span> <span class="kt">int</span> <span class="n">month</span><span class="p">,</span> <span class="kt">int</span> <span class="n">day</span><span class="p">)</span><span class="o">:</span> <span class="n">year_</span><span class="p">(</span><span class="n">year</span><span class="p">),</span> <span class="n">month_</span><span class="p">(</span><span class="n">month</span><span class="p">),</span> <span class="n">day_</span><span class="p">(</span><span class="n">day</span><span class="p">)</span> <span class="p">{}</span>
<span class="k">friend</span> <span class="n">std</span><span class="o">::</span><span class="n">ostream</span> <span class="o">&amp;</span><span class="k">operator</span><span class="o">&lt;&lt;</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">ostream</span> <span class="o">&amp;</span><span class="n">os</span><span class="p">,</span> <span class="k">const</span> <span class="n">Date</span> <span class="o">&amp;</span><span class="n">d</span><span class="p">)</span> <span class="p">{</span>
<span class="k">return</span> <span class="n">os</span> <span class="o">&lt;&lt;</span> <span class="n">d</span><span class="p">.</span><span class="n">year_</span> <span class="o">&lt;&lt;</span> <span class="sc">&#39;-&#39;</span> <span class="o">&lt;&lt;</span> <span class="n">d</span><span class="p">.</span><span class="n">month_</span> <span class="o">&lt;&lt;</span> <span class="sc">&#39;-&#39;</span> <span class="o">&lt;&lt;</span> <span class="n">d</span><span class="p">.</span><span class="n">day_</span><span class="p">;</span>
@@ -260,17 +292,6 @@ formatting of user-defined types that have overloaded <code class="docutils lite
</p>
</dd></dl>
<dl class="function">
<dt id="_CPPv2N3fmt7fprintfERNSt7ostreamE10CStringRef7ArgList">
<span id="fmt::fprintf__osR.CStringRef.ArgList"></span><span class="target" id="formatostream_8h_1adf9e00e4ddf5cad224a101333cfac9e8"></span>int <code class="descclassname">fmt::</code><code class="descname">fprintf</code><span class="sig-paren">(</span>std::ostream &amp;<em>os</em>, CStringRef <em>format_str</em>, <a class="reference internal" href="#_CPPv2N3fmt7ArgListE" title="fmt::ArgList">ArgList</a> <em>args</em><span class="sig-paren">)</span><a class="headerlink" href="#_CPPv2N3fmt7fprintfERNSt7ostreamE10CStringRef7ArgList" title="Permalink to this definition"></a></dt>
<dd><p><p>Prints formatted data to the stream <em>os</em>.</p>
<p><strong>Example</strong>:</p>
<div class="highlight-c++"><div class="highlight"><pre><span></span><span class="n">fprintf</span><span class="p">(</span><span class="n">cerr</span><span class="p">,</span> <span class="s">&quot;Don&#39;t %s!&quot;</span><span class="p">,</span> <span class="s">&quot;panic&quot;</span><span class="p">);</span>
</pre></div>
</div>
</p>
</dd></dl>
</div>
<div class="section" id="argument-formatters">
<h3>Argument formatters<a class="headerlink" href="#argument-formatters" title="Permalink to this headline"></a></h3>
@@ -279,7 +300,7 @@ custom argument formatter class:</p>
<div class="highlight-c++"><div class="highlight"><pre><span></span><span class="c1">// A custom argument formatter that formats negative integers as unsigned</span>
<span class="c1">// with the ``x`` format specifier.</span>
<span class="k">class</span> <span class="nc">CustomArgFormatter</span> <span class="o">:</span>
<span class="k">public</span> <span class="n">fmt</span><span class="o">::</span><span class="n">BasicArgFormatter</span><span class="o">&lt;</span><span class="n">CustomArgFormatter</span><span class="p">,</span> <span class="kt">char</span><span class="o">&gt;</span> <span class="p">{</span>
<span class="k">public</span> <span class="n">fmt</span><span class="o">::</span><span class="n">BasicArgFormatter</span><span class="o">&lt;</span><span class="n">CustomArgFormatter</span><span class="p">,</span> <span class="kt">char</span><span class="o">&gt;</span> <span class="p">{</span>
<span class="k">public</span><span class="o">:</span>
<span class="n">CustomArgFormatter</span><span class="p">(</span><span class="n">fmt</span><span class="o">::</span><span class="n">BasicFormatter</span><span class="o">&lt;</span><span class="kt">char</span><span class="p">,</span> <span class="n">CustomArgFormatter</span><span class="o">&gt;</span> <span class="o">&amp;</span><span class="n">f</span><span class="p">,</span>
<span class="n">fmt</span><span class="o">::</span><span class="n">FormatSpec</span> <span class="o">&amp;</span><span class="n">s</span><span class="p">,</span> <span class="k">const</span> <span class="kt">char</span> <span class="o">*</span><span class="n">fmt</span><span class="p">)</span>
@@ -329,7 +350,7 @@ then a corresponding method of <a class="reference internal" href="#_CPPv2N3fmt1
</pre></div>
</div>
</p>
<div class="breathe-sectiondef container">
<div class="breathe-sectiondef docutils container">
<p class="breathe-sectiondef-title rubric">Public Functions</p>
<dl class="function">
<dt id="_CPPv2N3fmt10ArgVisitor9visit_intEi">
@@ -440,7 +461,7 @@ called.</p>
<dl class="class">
<dt>
<span class="target" id="formatclassfmt_1_1_basic_arg_formatter"></span><em class="property">template </em>&lt;typename <em>Impl</em>, typename <em>Char</em>&gt;</dt>
<span class="target" id="formatclassfmt_1_1_basic_arg_formatter"></span><em class="property">template </em>&lt;typename <em>Impl</em>, typename <em>Char</em>, typename <em>Spec</em> = fmt::FormatSpec&gt;</dt>
<dt id="_CPPv2N3fmt17BasicArgFormatterE">
<span id="fmt::BasicArgFormatter"></span><em class="property">class </em><code class="descclassname">fmt::</code><code class="descname">BasicArgFormatter</code><a class="headerlink" href="#_CPPv2N3fmt17BasicArgFormatterE" title="Permalink to this definition"></a></dt>
<dd><p><p>An argument formatter based on the <a class="reference external" href="http://en.wikipedia.org/wiki/Curiously_recurring_template_pattern">curiously recurring template pattern</a>.</p>
@@ -455,11 +476,12 @@ will be called. If the subclass doesn&#8217;t contain a method with this signatu
then a corresponding method of <a class="reference internal" href="#_CPPv2N3fmt17BasicArgFormatterE" title="fmt::BasicArgFormatter"><code class="xref cpp cpp-any docutils literal"><span class="pre">BasicArgFormatter</span></code></a> or its superclass
will be called.</p>
</p>
<div class="breathe-sectiondef container">
<p>Inherits from fmt::internal::ArgFormatterBase&lt; Impl, Char, Spec &gt;</p>
<div class="breathe-sectiondef docutils container">
<p class="breathe-sectiondef-title rubric">Public Functions</p>
<dl class="function">
<dt id="_CPPv2N3fmt17BasicArgFormatter17BasicArgFormatterER14BasicFormatterI4Char4ImplER10FormatSpecPK4Char">
<span id="fmt::BasicArgFormatter::BasicArgFormatter__BasicFormatter:Char.Impl:R.FormatSpecR.CharCP"></span><span class="target" id="formatclassfmt_1_1_basic_arg_formatter_1a207b17b258c5e16cf61ebfc9b13211d3"></span><code class="descname">BasicArgFormatter</code><span class="sig-paren">(</span><a class="reference internal" href="#_CPPv2N3fmt14BasicFormatterE" title="fmt::BasicFormatter">BasicFormatter</a>&lt;Char, Impl&gt; &amp;<em>formatter</em>, FormatSpec &amp;<em>spec</em>, <em class="property">const</em> Char *<em>fmt</em><span class="sig-paren">)</span><a class="headerlink" href="#_CPPv2N3fmt17BasicArgFormatter17BasicArgFormatterER14BasicFormatterI4Char4ImplER10FormatSpecPK4Char" title="Permalink to this definition"></a></dt>
<dt id="_CPPv2N3fmt17BasicArgFormatter17BasicArgFormatterER14BasicFormatterI4Char4ImplER4SpecPK4Char">
<span id="fmt::BasicArgFormatter::BasicArgFormatter__BasicFormatter:Char.Impl:R.SpecR.CharCP"></span><span class="target" id="formatclassfmt_1_1_basic_arg_formatter_1a9fbfaaf573b6714ed03894326b0a5106"></span><code class="descname">BasicArgFormatter</code><span class="sig-paren">(</span><a class="reference internal" href="#_CPPv2N3fmt14BasicFormatterE" title="fmt::BasicFormatter">BasicFormatter</a>&lt;Char, Impl&gt; &amp;<em>formatter</em>, Spec &amp;<em>spec</em>, <em class="property">const</em> Char *<em>fmt</em><span class="sig-paren">)</span><a class="headerlink" href="#_CPPv2N3fmt17BasicArgFormatter17BasicArgFormatterER14BasicFormatterI4Char4ImplER4SpecPK4Char" title="Permalink to this definition"></a></dt>
<dd><p><p>Constructs an argument formatter object.
<em>formatter</em> is a reference to the main formatter object, <em>spec</em> contains
format specifier information for standard argument types, and <em>fmt</em> points
@@ -469,8 +491,8 @@ to the part of the format string being parsed for custom argument types.</p>
<dl class="function">
<dt id="_CPPv2N3fmt17BasicArgFormatter12visit_customEN8internal3Arg11CustomValueE">
<span id="fmt::BasicArgFormatter::visit_custom__internal::Arg::CustomValue"></span><span class="target" id="formatclassfmt_1_1_basic_arg_formatter_1ae0aab0f90c9c93e3513203fc84c2c4dc"></span>void <code class="descname">visit_custom</code><span class="sig-paren">(</span>internal::Arg::CustomValue <em>c</em><span class="sig-paren">)</span><a class="headerlink" href="#_CPPv2N3fmt17BasicArgFormatter12visit_customEN8internal3Arg11CustomValueE" title="Permalink to this definition"></a></dt>
<dd><p>Formats argument of a custom (user-defined) type. </p>
<span id="fmt::BasicArgFormatter::visit_custom__internal::Arg::CustomValue"></span><span class="target" id="formatclassfmt_1_1_basic_arg_formatter_1acc822e8efaa99b664deaf38b08950b88"></span>void <code class="descname">visit_custom</code><span class="sig-paren">(</span>internal::Arg::CustomValue <em>c</em><span class="sig-paren">)</span><a class="headerlink" href="#_CPPv2N3fmt17BasicArgFormatter12visit_customEN8internal3Arg11CustomValueE" title="Permalink to this definition"></a></dt>
<dd><p>Formats an argument of a custom (user-defined) type. </p>
</dd></dl>
</div>
@@ -482,7 +504,8 @@ to the part of the format string being parsed for custom argument types.</p>
<dt id="_CPPv2N3fmt12ArgFormatterE">
<span id="fmt::ArgFormatter"></span><em class="property">class </em><code class="descclassname">fmt::</code><code class="descname">ArgFormatter</code><a class="headerlink" href="#_CPPv2N3fmt12ArgFormatterE" title="Permalink to this definition"></a></dt>
<dd><p>The default argument formatter. </p>
<div class="breathe-sectiondef container">
<p>Inherits from <a class="reference internal" href="#formatclassfmt_1_1_basic_arg_formatter"><span class="std std-ref">fmt::BasicArgFormatter&lt; ArgFormatter&lt; Char &gt;, Char, FormatSpec &gt;</span></a></p>
<div class="breathe-sectiondef docutils container">
<p class="breathe-sectiondef-title rubric">Public Functions</p>
<dl class="function">
<dt id="_CPPv2N3fmt12ArgFormatter12ArgFormatterER14BasicFormatterI4CharER10FormatSpecPK4Char">
@@ -494,13 +517,16 @@ to the part of the format string being parsed for custom argument types.</p>
</dd></dl>
</div>
<div class="section" id="printf-formatting-functions">
<h3>Printf formatting functions<a class="headerlink" href="#printf-formatting-functions" title="Permalink to this headline"></a></h3>
<p>The following functions use <a class="reference external" href="http://pubs.opengroup.org/onlinepubs/009695399/functions/fprintf.html">printf format string syntax</a> with
a POSIX extension for positional arguments.</p>
<div class="section" id="printf-formatting">
<h3>Printf formatting<a class="headerlink" href="#printf-formatting" title="Permalink to this headline"></a></h3>
<p>The header <code class="docutils literal"><span class="pre">fmt/printf.h</span></code> provides <code class="docutils literal"><span class="pre">printf</span></code>-like formatting functionality.
The following functions use <a class="reference external" href="http://pubs.opengroup.org/onlinepubs/009695399/functions/fprintf.html">printf format string syntax</a> with
the POSIX extension for positional arguments. Unlike their standard
counterparts, the <code class="docutils literal"><span class="pre">fmt</span></code> functions are type-safe and throw an exception if an
argument type doesn&#8217;t match its format specification.</p>
<dl class="function">
<dt id="_CPPv2N3fmt6printfE10CStringRef7ArgList">
<span id="fmt::printf__CStringRef.ArgList"></span><span class="target" id="formatformat_8h_1aa936ffccf89f4609cd9fce18825f0b14"></span>int <code class="descclassname">fmt::</code><code class="descname">printf</code><span class="sig-paren">(</span>CStringRef <em>format</em>, <a class="reference internal" href="#_CPPv2N3fmt7ArgListE" title="fmt::ArgList">ArgList</a> <em>args</em><span class="sig-paren">)</span><a class="headerlink" href="#_CPPv2N3fmt6printfE10CStringRef7ArgList" title="Permalink to this definition"></a></dt>
<span id="fmt::printf__CStringRef.ArgList"></span><span class="target" id="formatprintf_8h_1aa936ffccf89f4609cd9fce18825f0b14"></span>int <code class="descclassname">fmt::</code><code class="descname">printf</code><span class="sig-paren">(</span>CStringRef <em>format</em>, <a class="reference internal" href="#_CPPv2N3fmt7ArgListE" title="fmt::ArgList">ArgList</a> <em>args</em><span class="sig-paren">)</span><a class="headerlink" href="#_CPPv2N3fmt6printfE10CStringRef7ArgList" title="Permalink to this definition"></a></dt>
<dd><p><p>Prints formatted data to <code class="docutils literal"><span class="pre">stdout</span></code>.</p>
<p><strong>Example</strong>:</p>
<div class="highlight-c++"><div class="highlight"><pre><span></span><span class="n">fmt</span><span class="o">::</span><span class="n">printf</span><span class="p">(</span><span class="s">&quot;Elapsed time: %.2f seconds&quot;</span><span class="p">,</span> <span class="mf">1.23</span><span class="p">);</span>
@@ -511,7 +537,7 @@ a POSIX extension for positional arguments.</p>
<dl class="function">
<dt id="_CPPv2N3fmt7fprintfEPNSt4FILEE10CStringRef7ArgList">
<span id="fmt::fprintf__std::FILEP.CStringRef.ArgList"></span><span class="target" id="formatformat_8h_1ae70c0a9615eef5e1e78450496d2a90e6"></span>int <code class="descclassname">fmt::</code><code class="descname">fprintf</code><span class="sig-paren">(</span>std::FILE *<em>f</em>, CStringRef <em>format</em>, <a class="reference internal" href="#_CPPv2N3fmt7ArgListE" title="fmt::ArgList">ArgList</a> <em>args</em><span class="sig-paren">)</span><a class="headerlink" href="#_CPPv2N3fmt7fprintfEPNSt4FILEE10CStringRef7ArgList" title="Permalink to this definition"></a></dt>
<span id="fmt::fprintf__std::FILEP.CStringRef.ArgList"></span><span class="target" id="formatprintf_8h_1ae70c0a9615eef5e1e78450496d2a90e6"></span>int <code class="descclassname">fmt::</code><code class="descname">fprintf</code><span class="sig-paren">(</span>std::FILE *<em>f</em>, CStringRef <em>format</em>, <a class="reference internal" href="#_CPPv2N3fmt7ArgListE" title="fmt::ArgList">ArgList</a> <em>args</em><span class="sig-paren">)</span><a class="headerlink" href="#_CPPv2N3fmt7fprintfEPNSt4FILEE10CStringRef7ArgList" title="Permalink to this definition"></a></dt>
<dd><p><p>Prints formatted data to the file <em>f</em>.</p>
<p><strong>Example</strong>:</p>
<div class="highlight-c++"><div class="highlight"><pre><span></span><span class="n">fmt</span><span class="o">::</span><span class="n">fprintf</span><span class="p">(</span><span class="n">stderr</span><span class="p">,</span> <span class="s">&quot;Don&#39;t %s!&quot;</span><span class="p">,</span> <span class="s">&quot;panic&quot;</span><span class="p">);</span>
@@ -520,9 +546,20 @@ a POSIX extension for positional arguments.</p>
</p>
</dd></dl>
<dl class="function">
<dt id="_CPPv2N3fmt7fprintfERNSt7ostreamE10CStringRef7ArgList">
<span id="fmt::fprintf__osR.CStringRef.ArgList"></span><span class="target" id="formatprintf_8h_1adf9e00e4ddf5cad224a101333cfac9e8"></span>int <code class="descclassname">fmt::</code><code class="descname">fprintf</code><span class="sig-paren">(</span>std::ostream &amp;<em>os</em>, CStringRef <em>format_str</em>, <a class="reference internal" href="#_CPPv2N3fmt7ArgListE" title="fmt::ArgList">ArgList</a> <em>args</em><span class="sig-paren">)</span><a class="headerlink" href="#_CPPv2N3fmt7fprintfERNSt7ostreamE10CStringRef7ArgList" title="Permalink to this definition"></a></dt>
<dd><p><p>Prints formatted data to the stream <em>os</em>.</p>
<p><strong>Example</strong>:</p>
<div class="highlight-c++"><div class="highlight"><pre><span></span><span class="n">fprintf</span><span class="p">(</span><span class="n">cerr</span><span class="p">,</span> <span class="s">&quot;Don&#39;t %s!&quot;</span><span class="p">,</span> <span class="s">&quot;panic&quot;</span><span class="p">);</span>
</pre></div>
</div>
</p>
</dd></dl>
<dl class="function">
<dt id="_CPPv2N3fmt7sprintfE10CStringRef7ArgList">
<span id="fmt::sprintf__CStringRef.ArgList"></span><span class="target" id="formatformat_8h_1a956d655d1291fb85203c58fadd4bba1a"></span>std::string <code class="descclassname">fmt::</code><code class="descname">sprintf</code><span class="sig-paren">(</span>CStringRef <em>format</em>, <a class="reference internal" href="#_CPPv2N3fmt7ArgListE" title="fmt::ArgList">ArgList</a> <em>args</em><span class="sig-paren">)</span><a class="headerlink" href="#_CPPv2N3fmt7sprintfE10CStringRef7ArgList" title="Permalink to this definition"></a></dt>
<span id="fmt::sprintf__CStringRef.ArgList"></span><span class="target" id="formatprintf_8h_1a956d655d1291fb85203c58fadd4bba1a"></span>std::string <code class="descclassname">fmt::</code><code class="descname">sprintf</code><span class="sig-paren">(</span>CStringRef <em>format</em>, <a class="reference internal" href="#_CPPv2N3fmt7ArgListE" title="fmt::ArgList">ArgList</a> <em>args</em><span class="sig-paren">)</span><a class="headerlink" href="#_CPPv2N3fmt7sprintfE10CStringRef7ArgList" title="Permalink to this definition"></a></dt>
<dd><p><p>Formats arguments and returns the result as a string.</p>
<p><strong>Example</strong>:</p>
<div class="highlight-c++"><div class="highlight"><pre><span></span><span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">message</span> <span class="o">=</span> <span class="n">fmt</span><span class="o">::</span><span class="n">sprintf</span><span class="p">(</span><span class="s">&quot;The answer is %d&quot;</span><span class="p">,</span> <span class="mi">42</span><span class="p">);</span>
@@ -531,10 +568,124 @@ a POSIX extension for positional arguments.</p>
</p>
</dd></dl>
<dl class="class">
<dt>
<span class="target" id="formatclassfmt_1_1_printf_formatter"></span><em class="property">template </em>&lt;typename <em>Char</em>, typename <em>ArgFormatter</em> = <a class="reference internal" href="#formatclassfmt_1_1_printf_arg_formatter"><span class="std std-ref">PrintfArgFormatter</span></a>&lt;Char&gt;&gt;</dt>
<dt id="_CPPv2N3fmt15PrintfFormatterE">
<span id="fmt::PrintfFormatter"></span><em class="property">class </em><code class="descclassname">fmt::</code><code class="descname">PrintfFormatter</code><a class="headerlink" href="#_CPPv2N3fmt15PrintfFormatterE" title="Permalink to this definition"></a></dt>
<dd><p>This template formats data and writes the output to a writer. </p>
<p>Inherits from fmt::internal::FormatterBase</p>
<div class="breathe-sectiondef docutils container">
<p class="breathe-sectiondef-title rubric">Public Functions</p>
<dl class="function">
<dt id="_CPPv2N3fmt15PrintfFormatter15PrintfFormatterERK7ArgListR11BasicWriterI4CharE">
<span id="fmt::PrintfFormatter::PrintfFormatter__ArgListCR.BasicWriter:Char:R"></span><span class="target" id="formatclassfmt_1_1_printf_formatter_1a9cb3cad9a8e4cd08445e9ff2338d40b0"></span><code class="descname">PrintfFormatter</code><span class="sig-paren">(</span><em class="property">const</em> <a class="reference internal" href="#_CPPv2N3fmt7ArgListE" title="fmt::ArgList">ArgList</a> &amp;<em>al</em>, <a class="reference internal" href="#_CPPv2N3fmt11BasicWriterE" title="fmt::BasicWriter">BasicWriter</a>&lt;Char&gt; &amp;<em>w</em><span class="sig-paren">)</span><a class="headerlink" href="#_CPPv2N3fmt15PrintfFormatter15PrintfFormatterERK7ArgListR11BasicWriterI4CharE" title="Permalink to this definition"></a></dt>
<dd><p><p>Constructs a <code class="docutils literal"><span class="pre">PrintfFormatter</span></code> object. References to the arguments and
the writer are stored in the formatter object so make sure they have
appropriate lifetimes.</p>
</p>
</dd></dl>
<dl class="function">
<dt id="_CPPv2N3fmt15PrintfFormatter6formatE15BasicCStringRefI4CharE">
<span id="fmt::PrintfFormatter::format__BasicCStringRef:Char:"></span><span class="target" id="formatclassfmt_1_1_printf_formatter_1a295c50e11b9a77720c8078f287040e5c"></span>void <code class="descname">format</code><span class="sig-paren">(</span><a class="reference internal" href="#_CPPv2N3fmt15BasicCStringRefE" title="fmt::BasicCStringRef">BasicCStringRef</a>&lt;Char&gt; <em>format_str</em><span class="sig-paren">)</span><a class="headerlink" href="#_CPPv2N3fmt15PrintfFormatter6formatE15BasicCStringRefI4CharE" title="Permalink to this definition"></a></dt>
<dd><p>Formats stored arguments and writes the output to the writer. </p>
</dd></dl>
</div>
</dd></dl>
<dl class="class">
<dt>
<span class="target" id="formatclassfmt_1_1_basic_printf_arg_formatter"></span><em class="property">template </em>&lt;typename <em>Impl</em>, typename <em>Char</em>, typename <em>Spec</em>&gt;</dt>
<dt id="_CPPv2N3fmt23BasicPrintfArgFormatterE">
<span id="fmt::BasicPrintfArgFormatter"></span><em class="property">class </em><code class="descclassname">fmt::</code><code class="descname">BasicPrintfArgFormatter</code><a class="headerlink" href="#_CPPv2N3fmt23BasicPrintfArgFormatterE" title="Permalink to this definition"></a></dt>
<dd><p><p>A <code class="docutils literal"><span class="pre">printf</span></code> argument formatter based on the <a class="reference external" href="http://en.wikipedia.org/wiki/Curiously_recurring_template_pattern">curiously recurring template
pattern</a>.</p>
<p>To use <a class="reference internal" href="#_CPPv2N3fmt23BasicPrintfArgFormatterE" title="fmt::BasicPrintfArgFormatter"><code class="xref cpp cpp-any docutils literal"><span class="pre">BasicPrintfArgFormatter</span></code></a> define a subclass that implements some
or all of the visit methods with the same signatures as the methods in
<a class="reference internal" href="#_CPPv2N3fmt10ArgVisitorE" title="fmt::ArgVisitor"><code class="xref cpp cpp-any docutils literal"><span class="pre">ArgVisitor</span></code></a>, for example, <a class="reference internal" href="#_CPPv2N3fmt10ArgVisitor9visit_intEi" title="fmt::ArgVisitor::visit_int"><code class="xref cpp cpp-any docutils literal"><span class="pre">visit_int()</span></code></a>.
Pass the subclass as the <em>Impl</em> template parameter. When a formatting
function processes an argument, it will dispatch to a visit method
specific to the argument type. For example, if the argument type is
<code class="docutils literal"><span class="pre">double</span></code> then the <a class="reference internal" href="#_CPPv2N3fmt10ArgVisitor12visit_doubleEd" title="fmt::ArgVisitor::visit_double"><code class="xref cpp cpp-any docutils literal"><span class="pre">visit_double()</span></code></a> method of a subclass
will be called. If the subclass doesn&#8217;t contain a method with this signature,
then a corresponding method of <a class="reference internal" href="#_CPPv2N3fmt23BasicPrintfArgFormatterE" title="fmt::BasicPrintfArgFormatter"><code class="xref cpp cpp-any docutils literal"><span class="pre">BasicPrintfArgFormatter</span></code></a> or its
superclass will be called.</p>
</p>
<p>Inherits from fmt::internal::ArgFormatterBase&lt; Impl, Char, Spec &gt;</p>
<div class="breathe-sectiondef docutils container">
<p class="breathe-sectiondef-title rubric">Public Functions</p>
<dl class="function">
<dt id="_CPPv2N3fmt23BasicPrintfArgFormatter23BasicPrintfArgFormatterER11BasicWriterI4CharER4Spec">
<span id="fmt::BasicPrintfArgFormatter::BasicPrintfArgFormatter__BasicWriter:Char:R.SpecR"></span><span class="target" id="formatclassfmt_1_1_basic_printf_arg_formatter_1a7027cf03f0a54f8d7e53563e948d9f54"></span><code class="descname">BasicPrintfArgFormatter</code><span class="sig-paren">(</span><a class="reference internal" href="#_CPPv2N3fmt11BasicWriterE" title="fmt::BasicWriter">BasicWriter</a>&lt;Char&gt; &amp;<em>w</em>, Spec &amp;<em>s</em><span class="sig-paren">)</span><a class="headerlink" href="#_CPPv2N3fmt23BasicPrintfArgFormatter23BasicPrintfArgFormatterER11BasicWriterI4CharER4Spec" title="Permalink to this definition"></a></dt>
<dd><p><p>Constructs an argument formatter object.
<em>writer</em> is a reference to the output writer and <em>spec</em> contains format
specifier information for standard argument types.</p>
</p>
</dd></dl>
<dl class="function">
<dt id="_CPPv2N3fmt23BasicPrintfArgFormatter10visit_boolEb">
<span id="fmt::BasicPrintfArgFormatter::visit_bool__b"></span><span class="target" id="formatclassfmt_1_1_basic_printf_arg_formatter_1a5a8896e3b7e60b678ad7ac1145d2d7db"></span>void <code class="descname">visit_bool</code><span class="sig-paren">(</span>bool <em>value</em><span class="sig-paren">)</span><a class="headerlink" href="#_CPPv2N3fmt23BasicPrintfArgFormatter10visit_boolEb" title="Permalink to this definition"></a></dt>
<dd><p>Formats an argument of type <code class="docutils literal"><span class="pre">bool</span></code>. </p>
</dd></dl>
<dl class="function">
<dt id="_CPPv2N3fmt23BasicPrintfArgFormatter10visit_charEi">
<span id="fmt::BasicPrintfArgFormatter::visit_char__i"></span><span class="target" id="formatclassfmt_1_1_basic_printf_arg_formatter_1a6d6a9710fe756a8682efa6e83eea8146"></span>void <code class="descname">visit_char</code><span class="sig-paren">(</span>int <em>value</em><span class="sig-paren">)</span><a class="headerlink" href="#_CPPv2N3fmt23BasicPrintfArgFormatter10visit_charEi" title="Permalink to this definition"></a></dt>
<dd><p>Formats a character. </p>
</dd></dl>
<dl class="function">
<dt id="_CPPv2N3fmt23BasicPrintfArgFormatter13visit_cstringEPKc">
<span id="fmt::BasicPrintfArgFormatter::visit_cstring__cCP"></span><span class="target" id="formatclassfmt_1_1_basic_printf_arg_formatter_1a202e5093c8d7ab388c05f58956e8f721"></span>void <code class="descname">visit_cstring</code><span class="sig-paren">(</span><em class="property">const</em> char *<em>value</em><span class="sig-paren">)</span><a class="headerlink" href="#_CPPv2N3fmt23BasicPrintfArgFormatter13visit_cstringEPKc" title="Permalink to this definition"></a></dt>
<dd><p>Formats a null-terminated C string. </p>
</dd></dl>
<dl class="function">
<dt id="_CPPv2N3fmt23BasicPrintfArgFormatter13visit_pointerEPKv">
<span id="fmt::BasicPrintfArgFormatter::visit_pointer__voidCP"></span><span class="target" id="formatclassfmt_1_1_basic_printf_arg_formatter_1a4184ac39a994f38d4b4850393e413a1c"></span>void <code class="descname">visit_pointer</code><span class="sig-paren">(</span><em class="property">const</em> void *<em>value</em><span class="sig-paren">)</span><a class="headerlink" href="#_CPPv2N3fmt23BasicPrintfArgFormatter13visit_pointerEPKv" title="Permalink to this definition"></a></dt>
<dd><p>Formats a pointer. </p>
</dd></dl>
<dl class="function">
<dt id="_CPPv2N3fmt23BasicPrintfArgFormatter12visit_customEN8internal3Arg11CustomValueE">
<span id="fmt::BasicPrintfArgFormatter::visit_custom__internal::Arg::CustomValue"></span><span class="target" id="formatclassfmt_1_1_basic_printf_arg_formatter_1a5ad1e99dfd69b88a6b7940c1bfc52d23"></span>void <code class="descname">visit_custom</code><span class="sig-paren">(</span>internal::Arg::CustomValue <em>c</em><span class="sig-paren">)</span><a class="headerlink" href="#_CPPv2N3fmt23BasicPrintfArgFormatter12visit_customEN8internal3Arg11CustomValueE" title="Permalink to this definition"></a></dt>
<dd><p>Formats an argument of a custom (user-defined) type. </p>
</dd></dl>
</div>
</dd></dl>
<dl class="class">
<dt>
<span class="target" id="formatclassfmt_1_1_printf_arg_formatter"></span><em class="property">template </em>&lt;<em class="property">typename</em> Char&gt;</dt>
<dt id="_CPPv2N3fmt18PrintfArgFormatterE">
<span id="fmt::PrintfArgFormatter"></span><em class="property">class </em><code class="descclassname">fmt::</code><code class="descname">PrintfArgFormatter</code><a class="headerlink" href="#_CPPv2N3fmt18PrintfArgFormatterE" title="Permalink to this definition"></a></dt>
<dd><p>The default printf argument formatter. </p>
<p>Inherits from <a class="reference internal" href="#formatclassfmt_1_1_basic_printf_arg_formatter"><span class="std std-ref">fmt::BasicPrintfArgFormatter&lt; PrintfArgFormatter&lt; Char &gt;, Char, FormatSpec &gt;</span></a></p>
<div class="breathe-sectiondef docutils container">
<p class="breathe-sectiondef-title rubric">Public Functions</p>
<dl class="function">
<dt id="_CPPv2N3fmt18PrintfArgFormatter18PrintfArgFormatterER11BasicWriterI4CharER10FormatSpec">
<span id="fmt::PrintfArgFormatter::PrintfArgFormatter__BasicWriter:Char:R.FormatSpecR"></span><span class="target" id="formatclassfmt_1_1_printf_arg_formatter_1aa4b9526d3c614205d607f63918c33245"></span><code class="descname">PrintfArgFormatter</code><span class="sig-paren">(</span><a class="reference internal" href="#_CPPv2N3fmt11BasicWriterE" title="fmt::BasicWriter">BasicWriter</a>&lt;Char&gt; &amp;<em>w</em>, FormatSpec &amp;<em>s</em><span class="sig-paren">)</span><a class="headerlink" href="#_CPPv2N3fmt18PrintfArgFormatter18PrintfArgFormatterER11BasicWriterI4CharER10FormatSpec" title="Permalink to this definition"></a></dt>
<dd><p>Constructs an argument formatter object. </p>
</dd></dl>
</div>
</dd></dl>
</div>
</div>
<div class="section" id="write-api">
<h2>Write API<a class="headerlink" href="#write-api" title="Permalink to this headline"></a></h2>
<p>The write API provides classes for writing formatted data into character
streams. It is usually faster than the <a class="reference internal" href="#format-api">format API</a> but, as IOStreams,
may result in larger compiled code size. The main writer class is
<a class="reference internal" href="#_CPPv2N3fmt17BasicMemoryWriterE" title="fmt::BasicMemoryWriter"><code class="xref cpp cpp-any docutils literal"><span class="pre">BasicMemoryWriter</span></code></a> which stores its output in a memory buffer and
provides direct access to it. It is possible to create custom writers that
store output elsewhere by subclassing <a class="reference internal" href="#_CPPv2N3fmt11BasicWriterE" title="fmt::BasicWriter"><code class="xref cpp cpp-any docutils literal"><span class="pre">BasicWriter</span></code></a>.</p>
<dl class="class">
<dt>
<span class="target" id="formatclassfmt_1_1_basic_writer"></span><em class="property">template </em>&lt;typename <em>Char</em>&gt;</dt>
@@ -564,37 +715,38 @@ such as <a class="reference internal" href="#_CPPv2N3fmt17BasicMemoryWriterE" ti
</tbody>
</table>
</p>
<div class="breathe-sectiondef container">
<p>Subclassed by <a class="reference internal" href="#formatclassfmt_1_1_basic_array_writer"><span class="std std-ref">fmt::BasicArrayWriter&lt; Char &gt;</span></a>, <a class="reference internal" href="#formatclassfmt_1_1_basic_memory_writer"><span class="std std-ref">fmt::BasicMemoryWriter&lt; Char, Allocator &gt;</span></a>, <a class="reference internal" href="#formatclassfmt_1_1_basic_string_writer"><span class="std std-ref">fmt::BasicStringWriter&lt; Char, Allocator &gt;</span></a></p>
<div class="breathe-sectiondef docutils container">
<p class="breathe-sectiondef-title rubric">Public Functions</p>
<dl class="function">
<dt id="_CPPv2N3fmt11BasicWriterD0Ev">
<span id="fmt::BasicWriter::~BasicWriter"></span>virtual <span class="target" id="formatclassfmt_1_1_basic_writer_1a25f6fc2e43d3bcfb3de9ac33afe6050d"></span><code class="descname">~BasicWriter</code><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#_CPPv2N3fmt11BasicWriterD0Ev" title="Permalink to this definition"></a></dt>
<span id="fmt::BasicWriter::~BasicWriter"></span><span class="target" id="formatclassfmt_1_1_basic_writer_1a25f6fc2e43d3bcfb3de9ac33afe6050d"></span><em class="property">virtual</em> <code class="descname">~BasicWriter</code><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#_CPPv2N3fmt11BasicWriterD0Ev" title="Permalink to this definition"></a></dt>
<dd><p><p>Destroys a <code class="docutils literal"><span class="pre">BasicWriter</span></code> object.</p>
</p>
</dd></dl>
<dl class="function">
<dt id="_CPPv2N3fmt11BasicWriter4sizeEv">
<span id="fmt::BasicWriter::size"></span><span class="target" id="formatclassfmt_1_1_basic_writer_1a1b6721b4ba4d3fa18ac781a36616cc2a"></span>std::size_t <code class="descname">size</code><span class="sig-paren">(</span><span class="sig-paren">)</span> const<a class="headerlink" href="#_CPPv2N3fmt11BasicWriter4sizeEv" title="Permalink to this definition"></a></dt>
<dt id="_CPPv2NK3fmt11BasicWriter4sizeEv">
<span id="fmt::BasicWriter::sizeC"></span><span class="target" id="formatclassfmt_1_1_basic_writer_1a8d4534eea273ef4a3dd9078b995d3d15"></span>std::size_t <code class="descname">size</code><span class="sig-paren">(</span><span class="sig-paren">)</span> <em class="property">const</em><a class="headerlink" href="#_CPPv2NK3fmt11BasicWriter4sizeEv" title="Permalink to this definition"></a></dt>
<dd><p>Returns the total number of characters written. </p>
</dd></dl>
<dl class="function">
<dt id="_CPPv2N3fmt11BasicWriter4dataEv">
<span id="fmt::BasicWriter::data"></span><span class="target" id="formatclassfmt_1_1_basic_writer_1a6f3f431fab4a937cd6844a5bda609391"></span><em class="property">const</em> Char *<code class="descname">data</code><span class="sig-paren">(</span><span class="sig-paren">)</span> const<a class="headerlink" href="#_CPPv2N3fmt11BasicWriter4dataEv" title="Permalink to this definition"></a></dt>
<dt id="_CPPv2NK3fmt11BasicWriter4dataEv">
<span id="fmt::BasicWriter::dataC"></span><span class="target" id="formatclassfmt_1_1_basic_writer_1a06ada257ca9ae580212d6fe0147fe2cc"></span><em class="property">const</em> Char *<code class="descname">data</code><span class="sig-paren">(</span><span class="sig-paren">)</span> <em class="property">const</em><a class="headerlink" href="#_CPPv2NK3fmt11BasicWriter4dataEv" title="Permalink to this definition"></a></dt>
<dd><p>Returns a pointer to the output buffer content. </p>
<p>No terminating null character is appended. </p>
</dd></dl>
<dl class="function">
<dt id="_CPPv2N3fmt11BasicWriter5c_strEv">
<span id="fmt::BasicWriter::c_str"></span><span class="target" id="formatclassfmt_1_1_basic_writer_1a8b68001f5c1c0ea851ddaef27dcbc691"></span><em class="property">const</em> Char *<code class="descname">c_str</code><span class="sig-paren">(</span><span class="sig-paren">)</span> const<a class="headerlink" href="#_CPPv2N3fmt11BasicWriter5c_strEv" title="Permalink to this definition"></a></dt>
<dt id="_CPPv2NK3fmt11BasicWriter5c_strEv">
<span id="fmt::BasicWriter::c_strC"></span><span class="target" id="formatclassfmt_1_1_basic_writer_1ab608044b16c838ed394cfe937e2ed8b9"></span><em class="property">const</em> Char *<code class="descname">c_str</code><span class="sig-paren">(</span><span class="sig-paren">)</span> <em class="property">const</em><a class="headerlink" href="#_CPPv2NK3fmt11BasicWriter5c_strEv" title="Permalink to this definition"></a></dt>
<dd><p>Returns a pointer to the output buffer content with terminating null character appended. </p>
</dd></dl>
<dl class="function">
<dt id="_CPPv2N3fmt11BasicWriter3strEv">
<span id="fmt::BasicWriter::str"></span><span class="target" id="formatclassfmt_1_1_basic_writer_1a91f06ced6e063ee77a99740e0e79faf6"></span>std::basic_string&lt;Char&gt; <code class="descname">str</code><span class="sig-paren">(</span><span class="sig-paren">)</span> const<a class="headerlink" href="#_CPPv2N3fmt11BasicWriter3strEv" title="Permalink to this definition"></a></dt>
<dt id="_CPPv2NK3fmt11BasicWriter3strEv">
<span id="fmt::BasicWriter::strC"></span><span class="target" id="formatclassfmt_1_1_basic_writer_1aac8dbeddff3d4e268d17a4f9c16264f6"></span>std::basic_string&lt;Char&gt; <code class="descname">str</code><span class="sig-paren">(</span><span class="sig-paren">)</span> <em class="property">const</em><a class="headerlink" href="#_CPPv2NK3fmt11BasicWriter3strEv" title="Permalink to this definition"></a></dt>
<dd><p><p>Returns the content of the output buffer as an <code class="xref cpp cpp-any docutils literal"><span class="pre">std::string</span></code>.</p>
</p>
</dd></dl>
@@ -695,11 +847,12 @@ and the standard allocator:</p>
<p>The output can be converted to an <code class="docutils literal"><span class="pre">std::string</span></code> with <code class="docutils literal"><span class="pre">out.str()</span></code> or
accessed as a C string with <code class="docutils literal"><span class="pre">out.c_str()</span></code>.</p>
</p>
<div class="breathe-sectiondef container">
<p>Inherits from <a class="reference internal" href="#formatclassfmt_1_1_basic_writer"><span class="std std-ref">fmt::BasicWriter&lt; Char &gt;</span></a></p>
<div class="breathe-sectiondef docutils container">
<p class="breathe-sectiondef-title rubric">Public Functions</p>
<dl class="function">
<dt id="_CPPv2N3fmt17BasicMemoryWriter17BasicMemoryWriterERR17BasicMemoryWriter">
<span id="fmt::BasicMemoryWriter::BasicMemoryWriter__BasicMemoryWriterRR"></span><span class="target" id="formatclassfmt_1_1_basic_memory_writer_1a245047763a93566d0a7c1f90e8901672"></span><code class="descname">BasicMemoryWriter</code><span class="sig-paren">(</span><a class="reference internal" href="#_CPPv2N3fmt17BasicMemoryWriterE" title="fmt::BasicMemoryWriter">BasicMemoryWriter</a> &amp;&amp;<em>other</em><span class="sig-paren">)</span><a class="headerlink" href="#_CPPv2N3fmt17BasicMemoryWriter17BasicMemoryWriterERR17BasicMemoryWriter" title="Permalink to this definition"></a></dt>
<span id="fmt::BasicMemoryWriter::BasicMemoryWriter__BasicMemoryWriterRR"></span><span class="target" id="formatclassfmt_1_1_basic_memory_writer_1a245047763a93566d0a7c1f90e8901672"></span><code class="descname">BasicMemoryWriter</code><span class="sig-paren">(</span><a class="reference internal" href="#_CPPv2N3fmt17BasicMemoryWriter17BasicMemoryWriterERR17BasicMemoryWriter" title="fmt::BasicMemoryWriter::BasicMemoryWriter">BasicMemoryWriter</a> &amp;&amp;<em>other</em><span class="sig-paren">)</span><a class="headerlink" href="#_CPPv2N3fmt17BasicMemoryWriter17BasicMemoryWriterERR17BasicMemoryWriter" title="Permalink to this definition"></a></dt>
<dd><p><p>Constructs a <a class="reference internal" href="#_CPPv2N3fmt17BasicMemoryWriterE" title="fmt::BasicMemoryWriter"><code class="xref cpp cpp-class docutils literal"><span class="pre">fmt::BasicMemoryWriter</span></code></a> object moving the content
of the other object to it.</p>
</p>
@@ -746,7 +899,8 @@ into the array.</p>
</tbody>
</table>
</p>
<div class="breathe-sectiondef container">
<p>Inherits from <a class="reference internal" href="#formatclassfmt_1_1_basic_writer"><span class="std std-ref">fmt::BasicWriter&lt; Char &gt;</span></a></p>
<div class="breathe-sectiondef docutils container">
<p class="breathe-sectiondef-title rubric">Public Functions</p>
<dl class="function">
<dt id="_CPPv2N3fmt16BasicArrayWriter16BasicArrayWriterEP4CharNSt6size_tE">
@@ -769,27 +923,118 @@ size known at compile time.</p>
</div>
</dd></dl>
<dl class="class">
<dt>
<span class="target" id="formatclassfmt_1_1_basic_string_writer"></span><em class="property">template </em>&lt;<em class="property">typename</em> Char, <em class="property">typename</em> Allocator = std::allocator&lt;Char&gt;&gt;</dt>
<dt id="_CPPv2N3fmt17BasicStringWriterE">
<span id="fmt::BasicStringWriter"></span><em class="property">class </em><code class="descclassname">fmt::</code><code class="descname">BasicStringWriter</code><a class="headerlink" href="#_CPPv2N3fmt17BasicStringWriterE" title="Permalink to this definition"></a></dt>
<dd><p><p>This class template provides operations for formatting and writing data
into a character stream. The output is stored in a <code class="docutils literal"><span class="pre">std::basic_string</span></code>
that grows dynamically.</p>
<p>You can use one of the following typedefs for common character types
and the standard allocator:</p>
<table border="1" class="docutils">
<colgroup>
<col width="35%" />
<col width="65%" />
</colgroup>
<thead valign="bottom">
<tr class="row-odd"><th class="head">Type</th>
<th class="head">Definition</th>
</tr>
</thead>
<tbody valign="top">
<tr class="row-even"><td>StringWriter</td>
<td>BasicStringWriter&lt;char&gt;</td>
</tr>
<tr class="row-odd"><td>WStringWriter</td>
<td>BasicStringWriter&lt;wchar_t&gt;</td>
</tr>
</tbody>
</table>
<p><strong>Example</strong>:</p>
<div class="highlight-c++"><div class="highlight"><pre><span></span><span class="n">StringWriter</span> <span class="n">out</span><span class="p">;</span>
<span class="n">out</span> <span class="o">&lt;&lt;</span> <span class="s">&quot;The answer is &quot;</span> <span class="o">&lt;&lt;</span> <span class="mi">42</span> <span class="o">&lt;&lt;</span> <span class="s">&quot;</span><span class="se">\n</span><span class="s">&quot;</span><span class="p">;</span>
</pre></div>
</div>
<p>This will write the following output to the <code class="docutils literal"><span class="pre">out</span></code> object:</p>
<div class="highlight-none"><div class="highlight"><pre><span></span>The answer is 42
</pre></div>
</div>
<p>The output can be moved to a <code class="docutils literal"><span class="pre">std::basic_string</span></code> with <code class="docutils literal"><span class="pre">out.move_to()</span></code>.</p>
</p>
<p>Inherits from <a class="reference internal" href="#formatclassfmt_1_1_basic_writer"><span class="std std-ref">fmt::BasicWriter&lt; Char &gt;</span></a></p>
<div class="breathe-sectiondef docutils container">
<p class="breathe-sectiondef-title rubric">Public Functions</p>
<dl class="function">
<dt id="_CPPv2N3fmt17BasicStringWriter17BasicStringWriterERK9Allocator">
<span id="fmt::BasicStringWriter::BasicStringWriter__AllocatorCR"></span><span class="target" id="formatclassfmt_1_1_basic_string_writer_1a39e60f775feda49e58964a9c540831fc"></span><code class="descname">BasicStringWriter</code><span class="sig-paren">(</span><em class="property">const</em> Allocator &amp;<em>allocator</em> = Allocator()<span class="sig-paren">)</span><a class="headerlink" href="#_CPPv2N3fmt17BasicStringWriter17BasicStringWriterERK9Allocator" title="Permalink to this definition"></a></dt>
<dd><p><p>Constructs a <a class="reference internal" href="#_CPPv2N3fmt17BasicStringWriterE" title="fmt::BasicStringWriter"><code class="xref cpp cpp-class docutils literal"><span class="pre">fmt::BasicStringWriter</span></code></a> object.</p>
</p>
</dd></dl>
<dl class="function">
<dt id="_CPPv2N3fmt17BasicStringWriter7move_toERNSt12basic_stringI4CharNSt11char_traitsI4CharEE9AllocatorEE">
<span id="fmt::BasicStringWriter::move_to__std::basic_string:Char.std::char_traits:Char:.Allocator:R"></span><span class="target" id="formatclassfmt_1_1_basic_string_writer_1af5eb54db9a51ef610d55ecb858257fb0"></span>void <code class="descname">move_to</code><span class="sig-paren">(</span>std::basic_string&lt;Char, std::char_traits&lt;Char&gt;, Allocator&gt; &amp;<em>str</em><span class="sig-paren">)</span><a class="headerlink" href="#_CPPv2N3fmt17BasicStringWriter7move_toERNSt12basic_stringI4CharNSt11char_traitsI4CharEE9AllocatorEE" title="Permalink to this definition"></a></dt>
<dd><p><p>Moves the buffer content to <em>str</em> clearing the buffer.</p>
</p>
</dd></dl>
</div>
</dd></dl>
<dl class="class">
<dt>
<span class="target" id="formatclassfmt_1_1_basic_container_writer"></span><em class="property">template </em>&lt;<em class="property">class</em> Container&gt;</dt>
<dt id="_CPPv2N3fmt20BasicContainerWriterE">
<span id="fmt::BasicContainerWriter"></span><em class="property">class </em><code class="descclassname">fmt::</code><code class="descname">BasicContainerWriter</code><a class="headerlink" href="#_CPPv2N3fmt20BasicContainerWriterE" title="Permalink to this definition"></a></dt>
<dd><p><p>This class template provides operations for formatting and appending data
to a standard <em>container</em> like <code class="docutils literal"><span class="pre">std::vector</span></code> or <code class="docutils literal"><span class="pre">std::basic_string</span></code>.</p>
<p><strong>Example</strong>:</p>
<div class="highlight-c++"><div class="highlight"><pre><span></span><span class="kt">void</span> <span class="nf">vecformat</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">char</span><span class="o">&gt;&amp;</span> <span class="n">dest</span><span class="p">,</span> <span class="n">fmt</span><span class="o">::</span><span class="n">BasicCStringRef</span><span class="o">&lt;</span><span class="kt">char</span><span class="o">&gt;</span> <span class="n">format</span><span class="p">,</span>
<span class="n">fmt</span><span class="o">::</span><span class="n">ArgList</span> <span class="n">args</span><span class="p">)</span> <span class="p">{</span>
<span class="n">fmt</span><span class="o">::</span><span class="n">BasicContainerWriter</span><span class="o">&lt;</span><span class="n">std</span><span class="o">::</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">char</span><span class="o">&gt;</span> <span class="o">&gt;</span> <span class="n">appender</span><span class="p">(</span><span class="n">dest</span><span class="p">);</span>
<span class="n">appender</span><span class="p">.</span><span class="n">write</span><span class="p">(</span><span class="n">format</span><span class="p">,</span> <span class="n">args</span><span class="p">);</span>
<span class="p">}</span>
<span class="n">FMT_VARIADIC</span><span class="p">(</span><span class="kt">void</span><span class="p">,</span> <span class="n">vecformat</span><span class="p">,</span> <span class="n">std</span><span class="o">::</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">char</span><span class="o">&gt;&amp;</span><span class="p">,</span>
<span class="n">fmt</span><span class="o">::</span><span class="n">BasicCStringRef</span><span class="o">&lt;</span><span class="kt">char</span><span class="o">&gt;</span><span class="p">);</span>
</pre></div>
</div>
</p>
<p>Inherits from <a class="reference internal" href="#formatclassfmt_1_1_basic_writer"><span class="std std-ref">fmt::BasicWriter&lt; Container::value_type &gt;</span></a></p>
<div class="breathe-sectiondef docutils container">
<p class="breathe-sectiondef-title rubric">Public Functions</p>
<dl class="function">
<dt id="_CPPv2N3fmt20BasicContainerWriter20BasicContainerWriterER9Container">
<span id="fmt::BasicContainerWriter::BasicContainerWriter__ContainerR"></span><span class="target" id="formatclassfmt_1_1_basic_container_writer_1a1c5f521af91a36bf07d580d3b5e8fde4"></span><code class="descname">BasicContainerWriter</code><span class="sig-paren">(</span>Container &amp;<em>dest</em><span class="sig-paren">)</span><a class="headerlink" href="#_CPPv2N3fmt20BasicContainerWriter20BasicContainerWriterER9Container" title="Permalink to this definition"></a></dt>
<dd><p><p>Constructs a <a class="reference internal" href="#_CPPv2N3fmt20BasicContainerWriterE" title="fmt::BasicContainerWriter"><code class="xref cpp cpp-class docutils literal"><span class="pre">fmt::BasicContainerWriter</span></code></a> object.</p>
</p>
</dd></dl>
</div>
</dd></dl>
<dl class="function">
<dt id="_CPPv2N3fmt3binEi">
<span id="fmt::bin__i"></span><span class="target" id="formatformat_8h_1aa3e8966d52b70224d46861fabd090e4b"></span>IntFormatSpec&lt;int, TypeSpec&lt;'b'&gt;&gt; <code class="descclassname">fmt::</code><code class="descname">bin</code><span class="sig-paren">(</span>int <em>value</em><span class="sig-paren">)</span><a class="headerlink" href="#_CPPv2N3fmt3binEi" title="Permalink to this definition"></a></dt>
<span id="fmt::bin__i"></span><span class="target" id="formatformat_8h_1a760fce6f0963895343b50eec787f80db"></span>IntFormatSpec&lt;int, TypeSpec&lt;'b'&gt;&gt; <code class="descclassname">fmt::</code><code class="descname">bin</code><span class="sig-paren">(</span>int <em>value</em><span class="sig-paren">)</span><a class="headerlink" href="#_CPPv2N3fmt3binEi" title="Permalink to this definition"></a></dt>
<dd><p>Returns an integer format specifier to format the value in base 2. </p>
</dd></dl>
<dl class="function">
<dt id="_CPPv2N3fmt3octEi">
<span id="fmt::oct__i"></span><span class="target" id="formatformat_8h_1a1d166c5b2242a6a0aefba5455c32a2b3"></span>IntFormatSpec&lt;int, TypeSpec&lt;'o'&gt;&gt; <code class="descclassname">fmt::</code><code class="descname">oct</code><span class="sig-paren">(</span>int <em>value</em><span class="sig-paren">)</span><a class="headerlink" href="#_CPPv2N3fmt3octEi" title="Permalink to this definition"></a></dt>
<span id="fmt::oct__i"></span><span class="target" id="formatformat_8h_1a49d07603108a758be5cc6157f456e32d"></span>IntFormatSpec&lt;int, TypeSpec&lt;'o'&gt;&gt; <code class="descclassname">fmt::</code><code class="descname">oct</code><span class="sig-paren">(</span>int <em>value</em><span class="sig-paren">)</span><a class="headerlink" href="#_CPPv2N3fmt3octEi" title="Permalink to this definition"></a></dt>
<dd><p>Returns an integer format specifier to format the value in base 8. </p>
</dd></dl>
<dl class="function">
<dt id="_CPPv2N3fmt3hexEi">
<span id="fmt::hex__i"></span><span class="target" id="formatformat_8h_1aaa926c5c42fbad5f5c98aaad84b9f66a"></span>IntFormatSpec&lt;int, TypeSpec&lt;'x'&gt;&gt; <code class="descclassname">fmt::</code><code class="descname">hex</code><span class="sig-paren">(</span>int <em>value</em><span class="sig-paren">)</span><a class="headerlink" href="#_CPPv2N3fmt3hexEi" title="Permalink to this definition"></a></dt>
<span id="fmt::hex__i"></span><span class="target" id="formatformat_8h_1a8451bad40c90c2ce2aa1a932851cf090"></span>IntFormatSpec&lt;int, TypeSpec&lt;'x'&gt;&gt; <code class="descclassname">fmt::</code><code class="descname">hex</code><span class="sig-paren">(</span>int <em>value</em><span class="sig-paren">)</span><a class="headerlink" href="#_CPPv2N3fmt3hexEi" title="Permalink to this definition"></a></dt>
<dd><p>Returns an integer format specifier to format the value in base 16 using lower-case letters for the digits above 9. </p>
</dd></dl>
<dl class="function">
<dt id="_CPPv2N3fmt4hexuEi">
<span id="fmt::hexu__i"></span><span class="target" id="formatformat_8h_1ac2fd8f73cfcd1321dfb6fb0302f23f66"></span>IntFormatSpec&lt;int, TypeSpec&lt;'X'&gt;&gt; <code class="descclassname">fmt::</code><code class="descname">hexu</code><span class="sig-paren">(</span>int <em>value</em><span class="sig-paren">)</span><a class="headerlink" href="#_CPPv2N3fmt4hexuEi" title="Permalink to this definition"></a></dt>
<span id="fmt::hexu__i"></span><span class="target" id="formatformat_8h_1ae08e783a599e0667dae7b5a63a265de4"></span>IntFormatSpec&lt;int, TypeSpec&lt;'X'&gt;&gt; <code class="descclassname">fmt::</code><code class="descname">hexu</code><span class="sig-paren">(</span>int <em>value</em><span class="sig-paren">)</span><a class="headerlink" href="#_CPPv2N3fmt4hexuEi" title="Permalink to this definition"></a></dt>
<dd><p>Returns an integer formatter format specifier to format in base 16 using upper-case letters for the digits above 9. </p>
</dd></dl>
@@ -797,7 +1042,7 @@ size known at compile time.</p>
<dt>
<em class="property">template </em>&lt;char <em>TYPE_CODE</em>, <em class="property">typename</em> Char&gt;</dt>
<dt id="_CPPv2N3fmt3padEij4Char">
<span id="fmt::pad__i.unsigned.Char"></span><span class="target" id="formatformat_8h_1a48d6010061d1710d807853ad9125d825"></span>IntFormatSpec&lt;int, AlignTypeSpec&lt;TYPE_CODE&gt;, Char&gt; <code class="descclassname">fmt::</code><code class="descname">pad</code><span class="sig-paren">(</span>int <em>value</em>, unsigned <em>width</em>, Char <em>fill</em><span class="sig-paren">)</span><a class="headerlink" href="#_CPPv2N3fmt3padEij4Char" title="Permalink to this definition"></a></dt>
<span id="fmt::pad__i.unsigned.Char"></span><span class="target" id="formatformat_8h_1aa6ebb90e2adc57f2c942e226fd708b24"></span>IntFormatSpec&lt;int, AlignTypeSpec&lt;TYPE_CODE&gt;, Char&gt; <code class="descclassname">fmt::</code><code class="descname">pad</code><span class="sig-paren">(</span>int <em>value</em>, unsigned <em>width</em>, Char <em>fill</em> = ' '<span class="sig-paren">)</span><a class="headerlink" href="#_CPPv2N3fmt3padEij4Char" title="Permalink to this definition"></a></dt>
<dd><p><p>Returns an integer format specifier to pad the formatted argument with the
fill character to the specified width using the default (right) numeric
alignment.</p>
@@ -817,7 +1062,7 @@ alignment.</p>
<dt>
<em class="property">template </em>&lt;<em class="property">typename</em> T&gt;</dt>
<dt id="_CPPv2N3fmt3argE9StringRefRK1T">
<span id="fmt::arg__StringRef.TCR"></span><span class="target" id="formatformat_8h_1a4649a895b3f769fe24b268e39a8cf152"></span>internal::NamedArg&lt;char&gt; <code class="descclassname">fmt::</code><code class="descname">arg</code><span class="sig-paren">(</span>StringRef <em>name</em>, <em class="property">const</em> T &amp;<em>arg</em><span class="sig-paren">)</span><a class="headerlink" href="#_CPPv2N3fmt3argE9StringRefRK1T" title="Permalink to this definition"></a></dt>
<span id="fmt::arg__StringRef.TCR"></span><span class="target" id="formatformat_8h_1a3ccc93714460459602dc6fc2b055ee6b"></span>internal::NamedArgWithType&lt;char, T&gt; <code class="descclassname">fmt::</code><code class="descname">arg</code><span class="sig-paren">(</span>StringRef <em>name</em>, <em class="property">const</em> T &amp;<em>arg</em><span class="sig-paren">)</span><a class="headerlink" href="#_CPPv2N3fmt3argE9StringRefRK1T" title="Permalink to this definition"></a></dt>
<dd><p><p>Returns a named argument for formatting functions.</p>
<p><strong>Example</strong>:</p>
<div class="highlight-c++"><div class="highlight"><pre><span></span><span class="n">print</span><span class="p">(</span><span class="s">&quot;Elapsed time: {s:.2f} seconds&quot;</span><span class="p">,</span> <span class="n">arg</span><span class="p">(</span><span class="s">&quot;s&quot;</span><span class="p">,</span> <span class="mf">1.23</span><span class="p">));</span>
@@ -826,18 +1071,10 @@ alignment.</p>
</p>
</dd></dl>
<dl class="function">
<dt id="_CPPv2N3fmt8literalsli2_aEPKcNSt6size_tE">
<span class="target" id="formatformat_8h_1a1f0ec67406a0e4937166e6481f481198"></span>internal::UdlArg&lt;char&gt; <code class="descclassname">fmt::literals::</code><code class="descname">operator&quot;&quot;_a</code><span class="sig-paren">(</span><em class="property">const</em> char *<em>s</em>, std::size_t<span class="sig-paren">)</span><a class="headerlink" href="#_CPPv2N3fmt8literalsli2_aEPKcNSt6size_tE" title="Permalink to this definition"></a></dt>
<dd><p><p>C++11 literal equivalent of <a class="reference internal" href="#_CPPv2N3fmt3argE9StringRefRK1T" title="fmt::arg"><code class="xref cpp cpp-func docutils literal"><span class="pre">fmt::arg()</span></code></a>.</p>
<p><strong>Example</strong>:</p>
<div class="highlight-c++"><div class="highlight"><pre><span></span><span class="k">using</span> <span class="k">namespace</span> <span class="n">fmt</span><span class="o">::</span><span class="n">literals</span><span class="p">;</span>
<span class="n">print</span><span class="p">(</span><span class="s">&quot;Elapsed time: {s:.2f} seconds&quot;</span><span class="p">,</span> <span class="s">&quot;s&quot;</span><span class="n">_a</span><span class="o">=</span><span class="mf">1.23</span><span class="p">);</span>
</pre></div>
<div class="admonition warning">
<p class="first admonition-title">Warning</p>
<p class="last">doxygenfunction: Cannot find function &#8220;operator&#8221;&#8220;_a&#8221; in doxygen xml output for project &#8220;format&#8221; from directory: /home/foonathan/Programming/fmt/build/doc/doxyxml</p>
</div>
</p>
</dd></dl>
<dl class="macro">
<dt id="c.FMT_CAPTURE">
<span class="target" id="formatformat_8h_1a3caa326fabdddb0e4fbcad7e5ec8bd37"></span><code class="descname">FMT_CAPTURE</code><span class="sig-paren">(</span>...<span class="sig-paren">)</span><a class="headerlink" href="#c.FMT_CAPTURE" title="Permalink to this definition"></a></dt>
@@ -886,23 +1123,39 @@ directly:</p>
<dt id="_CPPv2N3fmt7ArgListE">
<span id="fmt::ArgList"></span><span class="target" id="formatclassfmt_1_1_arg_list"></span><em class="property">class </em><code class="descclassname">fmt::</code><code class="descname">ArgList</code><a class="headerlink" href="#_CPPv2N3fmt7ArgListE" title="Permalink to this definition"></a></dt>
<dd><p>An argument list. </p>
<div class="breathe-sectiondef container">
<div class="breathe-sectiondef docutils container">
<p class="breathe-sectiondef-title rubric">Public Functions</p>
<dl class="function">
<dt id="_CPPv2N3fmt7ArgListixEj">
<span id="fmt::ArgList::subscript-operator__unsigned"></span><span class="target" id="formatclassfmt_1_1_arg_list_1ad2c2672388e003aa70d9c948ac8140cd"></span>internal::Arg <code class="descname">operator[]</code><span class="sig-paren">(</span>unsigned <em>index</em><span class="sig-paren">)</span> const<a class="headerlink" href="#_CPPv2N3fmt7ArgListixEj" title="Permalink to this definition"></a></dt>
<dt id="_CPPv2NK3fmt7ArgListixEj">
<span id="fmt::ArgList::subscript-operator__unsignedC"></span><span class="target" id="formatclassfmt_1_1_arg_list_1a9a717b2022170c8f2918141a80cc6eb2"></span>internal::Arg <code class="descname">operator[]</code><span class="sig-paren">(</span>unsigned <em>index</em><span class="sig-paren">)</span> <em class="property">const</em><a class="headerlink" href="#_CPPv2NK3fmt7ArgListixEj" title="Permalink to this definition"></a></dt>
<dd><p>Returns the argument at specified index. </p>
</dd></dl>
</div>
</dd></dl>
<dl class="function">
<dt>
<em class="property">template </em>&lt;<em class="property">typename</em> T&gt;</dt>
<dt id="_CPPv2N3fmt9to_stringERK1T">
<span id="fmt::to_string__TCR"></span><span class="target" id="formatstring_8h_1abfd84051cd3673d750be5851ee93b05f"></span>std::string <code class="descclassname">fmt::</code><code class="descname">to_string</code><span class="sig-paren">(</span><em class="property">const</em> T &amp;<em>value</em><span class="sig-paren">)</span><a class="headerlink" href="#_CPPv2N3fmt9to_stringERK1T" title="Permalink to this definition"></a></dt>
<dd><p><p>Converts <em>value</em> to <code class="docutils literal"><span class="pre">std::string</span></code> using the default format for type <em>T</em>.</p>
<p><strong>Example</strong>:</p>
<div class="highlight-c++"><div class="highlight"><pre><span></span><span class="cp">#include</span> <span class="cpf">&quot;fmt/string.h&quot;</span><span class="cp"></span>
<span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">answer</span> <span class="o">=</span> <span class="n">fmt</span><span class="o">::</span><span class="n">to_string</span><span class="p">(</span><span class="mi">42</span><span class="p">);</span>
</pre></div>
</div>
</p>
</dd></dl>
<dl class="class">
<dt>
<span class="target" id="formatclassfmt_1_1_basic_string_ref"></span><em class="property">template </em>&lt;typename <em>Char</em>&gt;</dt>
<dt id="_CPPv2N3fmt14BasicStringRefE">
<span id="fmt::BasicStringRef"></span><em class="property">class </em><code class="descclassname">fmt::</code><code class="descname">BasicStringRef</code><a class="headerlink" href="#_CPPv2N3fmt14BasicStringRefE" title="Permalink to this definition"></a></dt>
<dd><p><p>A string reference. It can be constructed from a C string or <code class="docutils literal"><span class="pre">std::string</span></code>.</p>
<dd><p><p>A string reference. It can be constructed from a C string or
<code class="docutils literal"><span class="pre">std::basic_string</span></code>.</p>
<p>You can use one of the following typedefs for common character types:</p>
<table border="1" class="docutils">
<colgroup>
@@ -933,7 +1186,7 @@ different types of strings to a function, for example:</p>
</pre></div>
</div>
</p>
<div class="breathe-sectiondef container">
<div class="breathe-sectiondef docutils container">
<p class="breathe-sectiondef-title rubric">Public Functions</p>
<dl class="function">
<dt id="_CPPv2N3fmt14BasicStringRef14BasicStringRefEPK4CharNSt6size_tE">
@@ -950,28 +1203,30 @@ the size with <code class="docutils literal"><span class="pre">std::char_traits&
</dd></dl>
<dl class="function">
<dt id="_CPPv2N3fmt14BasicStringRef14BasicStringRefERKNSt12basic_stringI4CharEE">
<span id="fmt::BasicStringRef::BasicStringRef__std::basic_string:Char:CR"></span><span class="target" id="formatclassfmt_1_1_basic_string_ref_1afd8ffd0c6d2ccac657f277a4faea3889"></span><code class="descname">BasicStringRef</code><span class="sig-paren">(</span><em class="property">const</em> std::basic_string&lt;Char&gt; &amp;<em>s</em><span class="sig-paren">)</span><a class="headerlink" href="#_CPPv2N3fmt14BasicStringRef14BasicStringRefERKNSt12basic_stringI4CharEE" title="Permalink to this definition"></a></dt>
<dd><p><p>Constructs a string reference from an <code class="docutils literal"><span class="pre">std::string</span></code> object.</p>
<dt>
<em class="property">template </em>&lt;<em class="property">typename</em> Allocator&gt;</dt>
<dt id="_CPPv2N3fmt14BasicStringRef14BasicStringRefERKNSt12basic_stringI4CharNSt11char_traitsI4CharEE9AllocatorEE">
<span id="fmt::BasicStringRef::BasicStringRef__std::basic_string:Char.std::char_traits:Char:.Allocator:CR"></span><span class="target" id="formatclassfmt_1_1_basic_string_ref_1a7c4c0c3bfc4768d7cb657f5756549863"></span><code class="descname">BasicStringRef</code><span class="sig-paren">(</span><em class="property">const</em> std::basic_string&lt;Char, std::char_traits&lt;Char&gt;, Allocator&gt; &amp;<em>s</em><span class="sig-paren">)</span><a class="headerlink" href="#_CPPv2N3fmt14BasicStringRef14BasicStringRefERKNSt12basic_stringI4CharNSt11char_traitsI4CharEE9AllocatorEE" title="Permalink to this definition"></a></dt>
<dd><p><p>Constructs a string reference from a <code class="docutils literal"><span class="pre">std::basic_string</span></code> object.</p>
</p>
</dd></dl>
<dl class="function">
<dt id="_CPPv2N3fmt14BasicStringRef9to_stringEv">
<span id="fmt::BasicStringRef::to_string"></span><span class="target" id="formatclassfmt_1_1_basic_string_ref_1a7340f48f53cf9188e9fea5e6e1556969"></span>std::basic_string&lt;Char&gt; <code class="descname">to_string</code><span class="sig-paren">(</span><span class="sig-paren">)</span> const<a class="headerlink" href="#_CPPv2N3fmt14BasicStringRef9to_stringEv" title="Permalink to this definition"></a></dt>
<dt id="_CPPv2NK3fmt14BasicStringRef9to_stringEv">
<span id="fmt::BasicStringRef::to_stringC"></span><span class="target" id="formatclassfmt_1_1_basic_string_ref_1a85503c30cd35cd6deff9e77da52857e6"></span>std::basic_string&lt;Char&gt; <code class="descname">to_string</code><span class="sig-paren">(</span><span class="sig-paren">)</span> <em class="property">const</em><a class="headerlink" href="#_CPPv2NK3fmt14BasicStringRef9to_stringEv" title="Permalink to this definition"></a></dt>
<dd><p><p>Converts a string reference to an <code class="docutils literal"><span class="pre">std::string</span></code> object.</p>
</p>
</dd></dl>
<dl class="function">
<dt id="_CPPv2N3fmt14BasicStringRef4dataEv">
<span id="fmt::BasicStringRef::data"></span><span class="target" id="formatclassfmt_1_1_basic_string_ref_1ae9c80502c527437215fe1c11dca8b475"></span><em class="property">const</em> Char *<code class="descname">data</code><span class="sig-paren">(</span><span class="sig-paren">)</span> const<a class="headerlink" href="#_CPPv2N3fmt14BasicStringRef4dataEv" title="Permalink to this definition"></a></dt>
<dt id="_CPPv2NK3fmt14BasicStringRef4dataEv">
<span id="fmt::BasicStringRef::dataC"></span><span class="target" id="formatclassfmt_1_1_basic_string_ref_1aeca62faae1111525b0ef2667e75187f7"></span><em class="property">const</em> Char *<code class="descname">data</code><span class="sig-paren">(</span><span class="sig-paren">)</span> <em class="property">const</em><a class="headerlink" href="#_CPPv2NK3fmt14BasicStringRef4dataEv" title="Permalink to this definition"></a></dt>
<dd><p>Returns a pointer to the string data. </p>
</dd></dl>
<dl class="function">
<dt id="_CPPv2N3fmt14BasicStringRef4sizeEv">
<span id="fmt::BasicStringRef::size"></span><span class="target" id="formatclassfmt_1_1_basic_string_ref_1ae38d9106dd5bec69488e5464aedc266a"></span>std::size_t <code class="descname">size</code><span class="sig-paren">(</span><span class="sig-paren">)</span> const<a class="headerlink" href="#_CPPv2N3fmt14BasicStringRef4sizeEv" title="Permalink to this definition"></a></dt>
<dt id="_CPPv2NK3fmt14BasicStringRef4sizeEv">
<span id="fmt::BasicStringRef::sizeC"></span><span class="target" id="formatclassfmt_1_1_basic_string_ref_1a765ddcb00e0a0a880a4a9458f9e68ea0"></span>std::size_t <code class="descname">size</code><span class="sig-paren">(</span><span class="sig-paren">)</span> <em class="property">const</em><a class="headerlink" href="#_CPPv2NK3fmt14BasicStringRef4sizeEv" title="Permalink to this definition"></a></dt>
<dd><p>Returns the string size. </p>
</dd></dl>
@@ -984,7 +1239,7 @@ the size with <code class="docutils literal"><span class="pre">std::char_traits&
<dt id="_CPPv2N3fmt15BasicCStringRefE">
<span id="fmt::BasicCStringRef"></span><em class="property">class </em><code class="descclassname">fmt::</code><code class="descname">BasicCStringRef</code><a class="headerlink" href="#_CPPv2N3fmt15BasicCStringRefE" title="Permalink to this definition"></a></dt>
<dd><p><p>A reference to a null terminated string. It can be constructed from a C
string or <code class="docutils literal"><span class="pre">std::string</span></code>.</p>
string or <code class="docutils literal"><span class="pre">std::basic_string</span></code>.</p>
<p>You can use one of the following typedefs for common character types:</p>
<table border="1" class="docutils">
<colgroup>
@@ -1015,7 +1270,7 @@ different types of strings to a function, for example:</p>
</pre></div>
</div>
</p>
<div class="breathe-sectiondef container">
<div class="breathe-sectiondef docutils container">
<p class="breathe-sectiondef-title rubric">Public Functions</p>
<dl class="function">
<dt id="_CPPv2N3fmt15BasicCStringRef15BasicCStringRefEPK4Char">
@@ -1024,15 +1279,17 @@ different types of strings to a function, for example:</p>
</dd></dl>
<dl class="function">
<dt id="_CPPv2N3fmt15BasicCStringRef15BasicCStringRefERKNSt12basic_stringI4CharEE">
<span id="fmt::BasicCStringRef::BasicCStringRef__std::basic_string:Char:CR"></span><span class="target" id="formatclassfmt_1_1_basic_c_string_ref_1ab460855d19c769773de532296f9f13f9"></span><code class="descname">BasicCStringRef</code><span class="sig-paren">(</span><em class="property">const</em> std::basic_string&lt;Char&gt; &amp;<em>s</em><span class="sig-paren">)</span><a class="headerlink" href="#_CPPv2N3fmt15BasicCStringRef15BasicCStringRefERKNSt12basic_stringI4CharEE" title="Permalink to this definition"></a></dt>
<dd><p><p>Constructs a string reference from an <code class="docutils literal"><span class="pre">std::string</span></code> object.</p>
<dt>
<em class="property">template </em>&lt;<em class="property">typename</em> Allocator&gt;</dt>
<dt id="_CPPv2N3fmt15BasicCStringRef15BasicCStringRefERKNSt12basic_stringI4CharNSt11char_traitsI4CharEE9AllocatorEE">
<span id="fmt::BasicCStringRef::BasicCStringRef__std::basic_string:Char.std::char_traits:Char:.Allocator:CR"></span><span class="target" id="formatclassfmt_1_1_basic_c_string_ref_1aa7caaa44a192e0184031d60c2a71bd12"></span><code class="descname">BasicCStringRef</code><span class="sig-paren">(</span><em class="property">const</em> std::basic_string&lt;Char, std::char_traits&lt;Char&gt;, Allocator&gt; &amp;<em>s</em><span class="sig-paren">)</span><a class="headerlink" href="#_CPPv2N3fmt15BasicCStringRef15BasicCStringRefERKNSt12basic_stringI4CharNSt11char_traitsI4CharEE9AllocatorEE" title="Permalink to this definition"></a></dt>
<dd><p><p>Constructs a string reference from a <code class="docutils literal"><span class="pre">std::basic_string</span></code> object.</p>
</p>
</dd></dl>
<dl class="function">
<dt id="_CPPv2N3fmt15BasicCStringRef5c_strEv">
<span id="fmt::BasicCStringRef::c_str"></span><span class="target" id="formatclassfmt_1_1_basic_c_string_ref_1ae3bafa845b53339b20c4f5edb4f635f9"></span><em class="property">const</em> Char *<code class="descname">c_str</code><span class="sig-paren">(</span><span class="sig-paren">)</span> const<a class="headerlink" href="#_CPPv2N3fmt15BasicCStringRef5c_strEv" title="Permalink to this definition"></a></dt>
<dt id="_CPPv2NK3fmt15BasicCStringRef5c_strEv">
<span id="fmt::BasicCStringRef::c_strC"></span><span class="target" id="formatclassfmt_1_1_basic_c_string_ref_1ac1064b18371a8762e3d89395d253d436"></span><em class="property">const</em> Char *<code class="descname">c_str</code><span class="sig-paren">(</span><span class="sig-paren">)</span> <em class="property">const</em><a class="headerlink" href="#_CPPv2NK3fmt15BasicCStringRef5c_strEv" title="Permalink to this definition"></a></dt>
<dd><p>Returns the pointer to a C string. </p>
</dd></dl>
@@ -1046,17 +1303,18 @@ different types of strings to a function, for example:</p>
<span id="fmt::Buffer"></span><em class="property">class </em><code class="descclassname">fmt::</code><code class="descname">Buffer</code><a class="headerlink" href="#_CPPv2N3fmt6BufferE" title="Permalink to this definition"></a></dt>
<dd><p><p>A buffer supporting a subset of <code class="docutils literal"><span class="pre">std::vector</span></code>&#8216;s operations.</p>
</p>
<div class="breathe-sectiondef container">
<p>Subclassed by fmt::internal::MemoryBuffer&lt; T, SIZE, Allocator &gt;</p>
<div class="breathe-sectiondef docutils container">
<p class="breathe-sectiondef-title rubric">Public Functions</p>
<dl class="function">
<dt id="_CPPv2N3fmt6Buffer4sizeEv">
<span id="fmt::Buffer::size"></span><span class="target" id="formatclassfmt_1_1_buffer_1a14fa72f0ddf584c14ffffb1446f598aa"></span>std::size_t <code class="descname">size</code><span class="sig-paren">(</span><span class="sig-paren">)</span> const<a class="headerlink" href="#_CPPv2N3fmt6Buffer4sizeEv" title="Permalink to this definition"></a></dt>
<dt id="_CPPv2NK3fmt6Buffer4sizeEv">
<span id="fmt::Buffer::sizeC"></span><span class="target" id="formatclassfmt_1_1_buffer_1a2489cffd9cdc6f846cdf17988d52f785"></span>std::size_t <code class="descname">size</code><span class="sig-paren">(</span><span class="sig-paren">)</span> <em class="property">const</em><a class="headerlink" href="#_CPPv2NK3fmt6Buffer4sizeEv" title="Permalink to this definition"></a></dt>
<dd><p>Returns the size of this buffer. </p>
</dd></dl>
<dl class="function">
<dt id="_CPPv2N3fmt6Buffer8capacityEv">
<span id="fmt::Buffer::capacity"></span><span class="target" id="formatclassfmt_1_1_buffer_1aaf54fe786de91157629f96380e0cb215"></span>std::size_t <code class="descname">capacity</code><span class="sig-paren">(</span><span class="sig-paren">)</span> const<a class="headerlink" href="#_CPPv2N3fmt6Buffer8capacityEv" title="Permalink to this definition"></a></dt>
<dt id="_CPPv2NK3fmt6Buffer8capacityEv">
<span id="fmt::Buffer::capacityC"></span><span class="target" id="formatclassfmt_1_1_buffer_1af38a0b9f1afac4901f24a73207f72e6f"></span>std::size_t <code class="descname">capacity</code><span class="sig-paren">(</span><span class="sig-paren">)</span> <em class="property">const</em><a class="headerlink" href="#_CPPv2NK3fmt6Buffer8capacityEv" title="Permalink to this definition"></a></dt>
<dd><p>Returns the capacity of this buffer. </p>
</dd></dl>
@@ -1083,11 +1341,11 @@ different types of strings to a function, for example:</p>
</dd></dl>
</div>
<div class="breathe-sectiondef container">
<div class="breathe-sectiondef docutils container">
<p class="breathe-sectiondef-title rubric">Protected Functions</p>
<dl class="function">
<dt id="_CPPv2N3fmt6Buffer4growENSt6size_tE">
<span id="fmt::Buffer::grow__std::s"></span>virtual <span class="target" id="formatclassfmt_1_1_buffer_1abdc7aaf5813aa07008b3d715969a7e19"></span>void <code class="descname">grow</code><span class="sig-paren">(</span>std::size_t <em>size</em><span class="sig-paren">)</span> = 0<a class="headerlink" href="#_CPPv2N3fmt6Buffer4growENSt6size_tE" title="Permalink to this definition"></a></dt>
<span id="fmt::Buffer::grow__std::s"></span><span class="target" id="formatclassfmt_1_1_buffer_1abdc7aaf5813aa07008b3d715969a7e19"></span><em class="property">virtual</em> void <code class="descname">grow</code><span class="sig-paren">(</span>std::size_t <em>size</em><span class="sig-paren">)</span> = 0<a class="headerlink" href="#_CPPv2N3fmt6Buffer4growENSt6size_tE" title="Permalink to this definition"></a></dt>
<dd><p><p>Increases the buffer capacity to hold at least <em>size</em> elements updating
<code class="docutils literal"><span class="pre">ptr_</span></code> and <code class="docutils literal"><span class="pre">capacity_</span></code>.</p>
</p>
@@ -1103,21 +1361,17 @@ different types of strings to a function, for example:</p>
<dt id="_CPPv2N3fmt11SystemErrorE">
<span id="fmt::SystemError"></span><span class="target" id="formatclassfmt_1_1_system_error"></span><em class="property">class </em><code class="descclassname">fmt::</code><code class="descname">SystemError</code><a class="headerlink" href="#_CPPv2N3fmt11SystemErrorE" title="Permalink to this definition"></a></dt>
<dd><p>An error returned by an operating system or a language runtime, for example a file opening error. </p>
<div class="breathe-sectiondef container">
<p>Inherits from fmt::internal::RuntimeError</p>
<p>Subclassed by <a class="reference internal" href="#formatclassfmt_1_1_windows_error"><span class="std std-ref">fmt::WindowsError</span></a></p>
<div class="breathe-sectiondef docutils container">
<p class="breathe-sectiondef-title rubric">Public Functions</p>
<dl class="function">
<dt id="_CPPv2N3fmt11SystemError11SystemErrorEi10CStringRef">
<span id="fmt::SystemError::SystemError__i.CStringRef"></span><span class="target" id="formatclassfmt_1_1_system_error_1a307c40b2542f53d7426b09319255d35c"></span><code class="descname">SystemError</code><span class="sig-paren">(</span>int <em>error_code</em>, CStringRef <em>message</em><span class="sig-paren">)</span><a class="headerlink" href="#_CPPv2N3fmt11SystemError11SystemErrorEi10CStringRef" title="Permalink to this definition"></a></dt>
<dd><p><p>Constructs a <a class="reference internal" href="#_CPPv2N3fmt11SystemErrorE" title="fmt::SystemError"><code class="xref cpp cpp-class docutils literal"><span class="pre">fmt::SystemError</span></code></a> object with the description
of the form</p>
<pre class="literal-block">
<em>&lt;message&gt;</em>: <em>&lt;system-message&gt;</em>
</pre>
<p>where <em>&lt;message&gt;</em> is the formatted message and <em>&lt;system-message&gt;</em> is
the system message corresponding to the error code.
<em>error_code</em> is a system error code as given by <code class="docutils literal"><span class="pre">errno</span></code>.
If <em>error_code</em> is not a valid error code such as -1, the system message
may look like &#8220;Unknown error -1&#8221; and is platform-dependent.</p>
<dd><p><p>Constructs a <a class="reference internal" href="#_CPPv2N3fmt11SystemErrorE" title="fmt::SystemError"><code class="xref cpp cpp-class docutils literal"><span class="pre">fmt::SystemError</span></code></a> object with a description
formatted with <a class="reference internal" href="#_CPPv2N3fmt19format_system_errorERN3fmt6WriterEiN3fmt9StringRefE" title="fmt::format_system_error"><code class="xref cpp cpp-any docutils literal"><span class="pre">fmt::format_system_error()</span></code></a>. <em>message</em> and additional
arguments passed into the constructor are formatted similarly to
<a class="reference internal" href="#_CPPv2N3fmt6formatE10CStringRef7ArgList" title="fmt::format"><code class="xref cpp cpp-any docutils literal"><span class="pre">fmt::format()</span></code></a>.</p>
<p><strong>Example</strong>:</p>
<div class="highlight-c++"><div class="highlight"><pre><span></span><span class="c1">// This throws a SystemError with the description</span>
<span class="c1">// cannot open file &#39;madeup&#39;: No such file or directory</span>
@@ -1134,11 +1388,29 @@ may look like &#8220;Unknown error -1&#8221; and is platform-dependent.</p>
</div>
</dd></dl>
<dl class="function">
<dt id="_CPPv2N3fmt19format_system_errorERN3fmt6WriterEiN3fmt9StringRefE">
<span id="fmt::format_system_error__fmt::WriterR.i.fmt::StringRef"></span><span class="target" id="formatformat_8h_1a3933879503d45e8cce0ef1e284f98402"></span>void <code class="descclassname">fmt::</code><code class="descname">format_system_error</code><span class="sig-paren">(</span>fmt::Writer &amp;<em>out</em>, int <em>error_code</em>, fmt::StringRef <em>message</em><span class="sig-paren">)</span><a class="headerlink" href="#_CPPv2N3fmt19format_system_errorERN3fmt6WriterEiN3fmt9StringRefE" title="Permalink to this definition"></a></dt>
<dd><p><p>Formats an error returned by an operating system or a language runtime,
for example a file opening error, and writes it to <em>out</em> in the following
form:</p>
<pre class="literal-block">
<em>&lt;message&gt;</em>: <em>&lt;system-message&gt;</em>
</pre>
<p>where <em>&lt;message&gt;</em> is the passed message and <em>&lt;system-message&gt;</em> is
the system message corresponding to the error code.
<em>error_code</em> is a system error code as given by <code class="docutils literal"><span class="pre">errno</span></code>.
If <em>error_code</em> is not a valid error code such as -1, the system message
may look like &#8220;Unknown error -1&#8221; and is platform-dependent.</p>
</p>
</dd></dl>
<dl class="class">
<dt id="_CPPv2N3fmt12WindowsErrorE">
<span id="fmt::WindowsError"></span><span class="target" id="formatclassfmt_1_1_windows_error"></span><em class="property">class </em><code class="descclassname">fmt::</code><code class="descname">WindowsError</code><a class="headerlink" href="#_CPPv2N3fmt12WindowsErrorE" title="Permalink to this definition"></a></dt>
<dd><p>A Windows error. </p>
<div class="breathe-sectiondef container">
<p>Inherits from <a class="reference internal" href="#formatclassfmt_1_1_system_error"><span class="std std-ref">fmt::SystemError</span></a></p>
<div class="breathe-sectiondef docutils container">
<p class="breathe-sectiondef-title rubric">Public Functions</p>
<dl class="function">
<dt id="_CPPv2N3fmt12WindowsError12WindowsErrorEi10CStringRef">
@@ -1183,7 +1455,8 @@ A custom allocator class can be specified as a template argument to
</div>
<p>It is also possible to write a formatting function that uses a custom
allocator:</p>
<div class="highlight-c++"><div class="highlight"><pre><span></span><span class="k">typedef</span> <span class="n">std</span><span class="o">::</span><span class="n">basic_string</span><span class="o">&lt;</span><span class="kt">char</span><span class="p">,</span> <span class="n">std</span><span class="o">::</span><span class="n">char_traits</span><span class="o">&lt;</span><span class="kt">char</span><span class="o">&gt;</span><span class="p">,</span> <span class="n">CustomAllocator</span><span class="o">&gt;</span> <span class="n">CustomString</span><span class="p">;</span>
<div class="highlight-c++"><div class="highlight"><pre><span></span><span class="k">typedef</span> <span class="n">std</span><span class="o">::</span><span class="n">basic_string</span><span class="o">&lt;</span><span class="kt">char</span><span class="p">,</span> <span class="n">std</span><span class="o">::</span><span class="n">char_traits</span><span class="o">&lt;</span><span class="kt">char</span><span class="o">&gt;</span><span class="p">,</span> <span class="n">CustomAllocator</span><span class="o">&gt;</span>
<span class="n">CustomString</span><span class="p">;</span>
<span class="n">CustomString</span> <span class="nf">format</span><span class="p">(</span><span class="n">CustomAllocator</span> <span class="n">alloc</span><span class="p">,</span> <span class="n">fmt</span><span class="o">::</span><span class="n">CStringRef</span> <span class="n">format_str</span><span class="p">,</span>
<span class="n">fmt</span><span class="o">::</span><span class="n">ArgList</span> <span class="n">args</span><span class="p">)</span> <span class="p">{</span>
@@ -1206,7 +1479,7 @@ allocator:</p>
<div class="footer" role="contentinfo">
&copy; Copyright 2012-2015, Victor Zverovich.
Created using <a href="http://sphinx-doc.org/">Sphinx</a> 1.4.1.
Created using <a href="http://sphinx-doc.org/">Sphinx</a> 1.4.1+.
</div>
<script src="_static/bootstrap.min.js"></script>
+27 -16
View File
@@ -8,7 +8,7 @@
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Contents &mdash; fmt 3.0.0 documentation</title>
<title>Contents &mdash; fmt 4.0.0 documentation</title>
<link rel="stylesheet" href="_static/basic.css" type="text/css" />
<link rel="stylesheet" href="_static/pygments.css" type="text/css" />
@@ -17,10 +17,11 @@
<script type="text/javascript">
var DOCUMENTATION_OPTIONS = {
URL_ROOT: './',
VERSION: '3.0.0',
VERSION: '4.0.0',
COLLAPSE_INDEX: false,
FILE_SUFFIX: '.html',
HAS_SOURCE: true
HAS_SOURCE: true,
SOURCELINK_SUFFIX: ''
};
</script>
<script type="text/javascript" src="_static/jquery.js"></script>
@@ -34,8 +35,9 @@
<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)
(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', 'fmtlib.net');
ga('send', 'pageview');
@@ -49,7 +51,8 @@
<div class="navbar-content">
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target=".navbar-collapse">
<button type="button" class="navbar-toggle collapsed"
data-toggle="collapse" data-target=".navbar-collapse">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
@@ -62,18 +65,23 @@
<div class="collapse navbar-collapse">
<ul class="nav navbar-nav">
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button"
aria-expanded="false">3.0.0 <span class="caret"></span></a>
<a href="#" class="dropdown-toggle" data-toggle="dropdown"
role="button" aria-expanded="false">4.0.0
<span class="caret"></span></a>
<ul class="dropdown-menu" role="menu">
<li><a href="http://fmtlib.net/2.0.0/">2.0.0</a></li>
<li><a href="http://fmtlib.net/1.1.0/">1.1.0</a></li>
<li><a href="http://fmtlib.net/1.0.0/">1.0.0</a></li>
<li><a href="http://fmtlib.net/3.0.0">3.0.0</a></li>
<li><a href="http://fmtlib.net/2.0.0">2.0.0</a></li>
<li><a href="http://fmtlib.net/1.1.0">1.1.0</a></li>
</ul>
</li>
<li class="active"><a href="contents.html">Contents <span class="sr-only">(current)</span></a></li>
<li class="active"><a href="contents.html">Contents
<span class="sr-only">(current)</span></a></li>
@@ -91,9 +99,11 @@
</ul>
<form class="navbar-form navbar-right" role="search" action="search.html" method="get">
<form class="navbar-form navbar-right" role="search" action="search.html"
method="get">
<div class="form-group">
<input type="text" name="q" class="form-control" placeholder="Search" >
<input type="text" name="q" class="form-control"
placeholder="Search" >
</div>
<input type="hidden" name="check_keywords" value="yes" />
<input type="hidden" name="area" value="default" />
@@ -120,6 +130,7 @@
<ul>
<li class="toctree-l1"><a class="reference internal" href="usage.html">Usage</a><ul>
<li class="toctree-l2"><a class="reference internal" href="usage.html#building-the-library">Building the library</a></li>
<li class="toctree-l2"><a class="reference internal" href="usage.html#header-only-usage-with-cmake">Header-only usage with CMake</a></li>
<li class="toctree-l2"><a class="reference internal" href="usage.html#building-the-documentation">Building the documentation</a></li>
<li class="toctree-l2"><a class="reference internal" href="usage.html#android-ndk">Android NDK</a></li>
<li class="toctree-l2"><a class="reference internal" href="usage.html#homebrew">Homebrew</a></li>
@@ -151,7 +162,7 @@
<div class="footer" role="contentinfo">
&copy; Copyright 2012-2015, Victor Zverovich.
Created using <a href="http://sphinx-doc.org/">Sphinx</a> 1.4.1.
Created using <a href="http://sphinx-doc.org/">Sphinx</a> 1.4.1+.
</div>
<script src="_static/bootstrap.min.js"></script>
+114 -37
View File
@@ -9,7 +9,7 @@
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Index &mdash; fmt 3.0.0 documentation</title>
<title>Index &mdash; fmt 4.0.0 documentation</title>
<link rel="stylesheet" href="_static/basic.css" type="text/css" />
<link rel="stylesheet" href="_static/pygments.css" type="text/css" />
@@ -18,10 +18,11 @@
<script type="text/javascript">
var DOCUMENTATION_OPTIONS = {
URL_ROOT: './',
VERSION: '3.0.0',
VERSION: '4.0.0',
COLLAPSE_INDEX: false,
FILE_SUFFIX: '.html',
HAS_SOURCE: true
HAS_SOURCE: true,
SOURCELINK_SUFFIX: ''
};
</script>
<script type="text/javascript" src="_static/jquery.js"></script>
@@ -34,8 +35,9 @@
<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)
(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', 'fmtlib.net');
ga('send', 'pageview');
@@ -49,7 +51,8 @@
<div class="navbar-content">
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target=".navbar-collapse">
<button type="button" class="navbar-toggle collapsed"
data-toggle="collapse" data-target=".navbar-collapse">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
@@ -62,13 +65,17 @@
<div class="collapse navbar-collapse">
<ul class="nav navbar-nav">
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button"
aria-expanded="false">3.0.0 <span class="caret"></span></a>
<a href="#" class="dropdown-toggle" data-toggle="dropdown"
role="button" aria-expanded="false">4.0.0
<span class="caret"></span></a>
<ul class="dropdown-menu" role="menu">
<li><a href="http://fmtlib.net/2.0.0/">2.0.0</a></li>
<li><a href="http://fmtlib.net/1.1.0/">1.1.0</a></li>
<li><a href="http://fmtlib.net/1.0.0/">1.0.0</a></li>
<li><a href="http://fmtlib.net/3.0.0">3.0.0</a></li>
<li><a href="http://fmtlib.net/2.0.0">2.0.0</a></li>
<li><a href="http://fmtlib.net/1.1.0">1.1.0</a></li>
</ul>
</li>
@@ -91,9 +98,11 @@
</ul>
<form class="navbar-form navbar-right" role="search" action="search.html" method="get">
<form class="navbar-form navbar-right" role="search" action="search.html"
method="get">
<div class="form-group">
<input type="text" name="q" class="form-control" placeholder="Search" >
<input type="text" name="q" class="form-control"
placeholder="Search" >
</div>
<input type="hidden" name="check_keywords" value="yes" />
<input type="hidden" name="area" value="default" />
@@ -141,7 +150,7 @@
</dt>
<dt><a href="api.html#_CPPv2N3fmt7ArgListixEj">fmt::ArgList::operator[] (C++ function)</a>
<dt><a href="api.html#_CPPv2NK3fmt7ArgListixEj">fmt::ArgList::operator[] (C++ function)</a>
</dt>
@@ -217,7 +226,7 @@
</dt>
<dt><a href="api.html#_CPPv2N3fmt17BasicArgFormatter17BasicArgFormatterER14BasicFormatterI4Char4ImplER10FormatSpecPK4Char">fmt::BasicArgFormatter::BasicArgFormatter (C++ function)</a>
<dt><a href="api.html#_CPPv2N3fmt17BasicArgFormatter17BasicArgFormatterER14BasicFormatterI4Char4ImplER4SpecPK4Char">fmt::BasicArgFormatter::BasicArgFormatter (C++ function)</a>
</dt>
@@ -233,15 +242,23 @@
</dt>
<dt><a href="api.html#_CPPv2N3fmt20BasicContainerWriterE">fmt::BasicContainerWriter (C++ class)</a>
</dt>
<dt><a href="api.html#_CPPv2N3fmt20BasicContainerWriter20BasicContainerWriterER9Container">fmt::BasicContainerWriter::BasicContainerWriter (C++ function)</a>
</dt>
<dt><a href="api.html#_CPPv2N3fmt15BasicCStringRefE">fmt::BasicCStringRef (C++ class)</a>
</dt>
<dt><a href="api.html#_CPPv2N3fmt15BasicCStringRef15BasicCStringRefEPK4Char">fmt::BasicCStringRef::BasicCStringRef (C++ function)</a>, <a href="api.html#_CPPv2N3fmt15BasicCStringRef15BasicCStringRefERKNSt12basic_stringI4CharEE">[1]</a>
<dt><a href="api.html#_CPPv2N3fmt15BasicCStringRef15BasicCStringRefEPK4Char">fmt::BasicCStringRef::BasicCStringRef (C++ function)</a>, <a href="api.html#_CPPv2N3fmt15BasicCStringRef15BasicCStringRefERKNSt12basic_stringI4CharNSt11char_traitsI4CharEE9AllocatorEE">[1]</a>
</dt>
<dt><a href="api.html#_CPPv2N3fmt15BasicCStringRef5c_strEv">fmt::BasicCStringRef::c_str (C++ function)</a>
<dt><a href="api.html#_CPPv2NK3fmt15BasicCStringRef5c_strEv">fmt::BasicCStringRef::c_str (C++ function)</a>
</dt>
@@ -276,6 +293,34 @@
<dt><a href="api.html#_CPPv2N3fmt17BasicMemoryWriteraSERR17BasicMemoryWriter">fmt::BasicMemoryWriter::operator= (C++ function)</a>
</dt>
<dt><a href="api.html#_CPPv2N3fmt23BasicPrintfArgFormatterE">fmt::BasicPrintfArgFormatter (C++ class)</a>
</dt>
<dt><a href="api.html#_CPPv2N3fmt23BasicPrintfArgFormatter23BasicPrintfArgFormatterER11BasicWriterI4CharER4Spec">fmt::BasicPrintfArgFormatter::BasicPrintfArgFormatter (C++ function)</a>
</dt>
<dt><a href="api.html#_CPPv2N3fmt23BasicPrintfArgFormatter10visit_boolEb">fmt::BasicPrintfArgFormatter::visit_bool (C++ function)</a>
</dt>
<dt><a href="api.html#_CPPv2N3fmt23BasicPrintfArgFormatter10visit_charEi">fmt::BasicPrintfArgFormatter::visit_char (C++ function)</a>
</dt>
<dt><a href="api.html#_CPPv2N3fmt23BasicPrintfArgFormatter13visit_cstringEPKc">fmt::BasicPrintfArgFormatter::visit_cstring (C++ function)</a>
</dt>
<dt><a href="api.html#_CPPv2N3fmt23BasicPrintfArgFormatter12visit_customEN8internal3Arg11CustomValueE">fmt::BasicPrintfArgFormatter::visit_custom (C++ function)</a>
</dt>
<dt><a href="api.html#_CPPv2N3fmt23BasicPrintfArgFormatter13visit_pointerEPKv">fmt::BasicPrintfArgFormatter::visit_pointer (C++ function)</a>
</dt>
</dl></td>
<td style="width: 33%" valign="top"><dl>
@@ -283,19 +328,31 @@
</dt>
<dt><a href="api.html#_CPPv2N3fmt14BasicStringRef14BasicStringRefEPK4Char">fmt::BasicStringRef::BasicStringRef (C++ function)</a>, <a href="api.html#_CPPv2N3fmt14BasicStringRef14BasicStringRefEPK4CharNSt6size_tE">[1]</a>, <a href="api.html#_CPPv2N3fmt14BasicStringRef14BasicStringRefERKNSt12basic_stringI4CharEE">[2]</a>
<dt><a href="api.html#_CPPv2N3fmt14BasicStringRef14BasicStringRefEPK4Char">fmt::BasicStringRef::BasicStringRef (C++ function)</a>, <a href="api.html#_CPPv2N3fmt14BasicStringRef14BasicStringRefEPK4CharNSt6size_tE">[1]</a>, <a href="api.html#_CPPv2N3fmt14BasicStringRef14BasicStringRefERKNSt12basic_stringI4CharNSt11char_traitsI4CharEE9AllocatorEE">[2]</a>
</dt>
<dt><a href="api.html#_CPPv2N3fmt14BasicStringRef4dataEv">fmt::BasicStringRef::data (C++ function)</a>
<dt><a href="api.html#_CPPv2NK3fmt14BasicStringRef4dataEv">fmt::BasicStringRef::data (C++ function)</a>
</dt>
<dt><a href="api.html#_CPPv2N3fmt14BasicStringRef4sizeEv">fmt::BasicStringRef::size (C++ function)</a>
<dt><a href="api.html#_CPPv2NK3fmt14BasicStringRef4sizeEv">fmt::BasicStringRef::size (C++ function)</a>
</dt>
<dt><a href="api.html#_CPPv2N3fmt14BasicStringRef9to_stringEv">fmt::BasicStringRef::to_string (C++ function)</a>
<dt><a href="api.html#_CPPv2NK3fmt14BasicStringRef9to_stringEv">fmt::BasicStringRef::to_string (C++ function)</a>
</dt>
<dt><a href="api.html#_CPPv2N3fmt17BasicStringWriterE">fmt::BasicStringWriter (C++ class)</a>
</dt>
<dt><a href="api.html#_CPPv2N3fmt17BasicStringWriter17BasicStringWriterERK9Allocator">fmt::BasicStringWriter::BasicStringWriter (C++ function)</a>
</dt>
<dt><a href="api.html#_CPPv2N3fmt17BasicStringWriter7move_toERNSt12basic_stringI4CharNSt11char_traitsI4CharEE9AllocatorEE">fmt::BasicStringWriter::move_to (C++ function)</a>
</dt>
@@ -303,11 +360,11 @@
</dt>
<dt><a href="api.html#_CPPv2N3fmt11BasicWriter5c_strEv">fmt::BasicWriter::c_str (C++ function)</a>
<dt><a href="api.html#_CPPv2NK3fmt11BasicWriter5c_strEv">fmt::BasicWriter::c_str (C++ function)</a>
</dt>
<dt><a href="api.html#_CPPv2N3fmt11BasicWriter4dataEv">fmt::BasicWriter::data (C++ function)</a>
<dt><a href="api.html#_CPPv2NK3fmt11BasicWriter4dataEv">fmt::BasicWriter::data (C++ function)</a>
</dt>
@@ -315,11 +372,11 @@
</dt>
<dt><a href="api.html#_CPPv2N3fmt11BasicWriter4sizeEv">fmt::BasicWriter::size (C++ function)</a>
<dt><a href="api.html#_CPPv2NK3fmt11BasicWriter4sizeEv">fmt::BasicWriter::size (C++ function)</a>
</dt>
<dt><a href="api.html#_CPPv2N3fmt11BasicWriter3strEv">fmt::BasicWriter::str (C++ function)</a>
<dt><a href="api.html#_CPPv2NK3fmt11BasicWriter3strEv">fmt::BasicWriter::str (C++ function)</a>
</dt>
@@ -343,7 +400,7 @@
</dt>
<dt><a href="api.html#_CPPv2N3fmt6Buffer8capacityEv">fmt::Buffer::capacity (C++ function)</a>
<dt><a href="api.html#_CPPv2NK3fmt6Buffer8capacityEv">fmt::Buffer::capacity (C++ function)</a>
</dt>
@@ -359,7 +416,7 @@
</dt>
<dt><a href="api.html#_CPPv2N3fmt6Buffer4sizeEv">fmt::Buffer::size (C++ function)</a>
<dt><a href="api.html#_CPPv2NK3fmt6Buffer4sizeEv">fmt::Buffer::size (C++ function)</a>
</dt>
@@ -367,6 +424,10 @@
</dt>
<dt><a href="api.html#_CPPv2N3fmt19format_system_errorERN3fmt6WriterEiN3fmt9StringRefE">fmt::format_system_error (C++ function)</a>
</dt>
<dt><a href="api.html#_CPPv2N3fmt7fprintfEPNSt4FILEE10CStringRef7ArgList">fmt::fprintf (C++ function)</a>, <a href="api.html#_CPPv2N3fmt7fprintfERNSt7ostreamE10CStringRef7ArgList">[1]</a>
</dt>
@@ -379,14 +440,6 @@
</dt>
<dt><a href="api.html#_CPPv2N3fmt8literalsli2_aEPKcNSt6size_tE">fmt::literals::operator&#34;&#34;_a (C++ function)</a>
</dt>
<dt><a href="api.html#_CPPv2N3fmt8literalsli7_formatEPKcNSt6size_tE">fmt::literals::operator&#34;&#34;_format (C++ function)</a>
</dt>
<dt><a href="api.html#_CPPv2N3fmt3octEi">fmt::oct (C++ function)</a>
</dt>
@@ -403,6 +456,26 @@
</dt>
<dt><a href="api.html#_CPPv2N3fmt18PrintfArgFormatterE">fmt::PrintfArgFormatter (C++ class)</a>
</dt>
<dt><a href="api.html#_CPPv2N3fmt18PrintfArgFormatter18PrintfArgFormatterER11BasicWriterI4CharER10FormatSpec">fmt::PrintfArgFormatter::PrintfArgFormatter (C++ function)</a>
</dt>
<dt><a href="api.html#_CPPv2N3fmt15PrintfFormatterE">fmt::PrintfFormatter (C++ class)</a>
</dt>
<dt><a href="api.html#_CPPv2N3fmt15PrintfFormatter6formatE15BasicCStringRefI4CharE">fmt::PrintfFormatter::format (C++ function)</a>
</dt>
<dt><a href="api.html#_CPPv2N3fmt15PrintfFormatter15PrintfFormatterERK7ArgListR11BasicWriterI4CharE">fmt::PrintfFormatter::PrintfFormatter (C++ function)</a>
</dt>
<dt><a href="api.html#_CPPv2N3fmt7sprintfE10CStringRef7ArgList">fmt::sprintf (C++ function)</a>
</dt>
@@ -415,6 +488,10 @@
</dt>
<dt><a href="api.html#_CPPv2N3fmt9to_stringERK1T">fmt::to_string (C++ function)</a>
</dt>
<dt><a href="api.html#_CPPv2N3fmt12WindowsErrorE">fmt::WindowsError (C++ class)</a>
</dt>
@@ -443,7 +520,7 @@
<div class="footer" role="contentinfo">
&copy; Copyright 2012-2015, Victor Zverovich.
Created using <a href="http://sphinx-doc.org/">Sphinx</a> 1.4.1.
Created using <a href="http://sphinx-doc.org/">Sphinx</a> 1.4.1+.
</div>
<script src="_static/bootstrap.min.js"></script>
+72 -47
View File
@@ -8,7 +8,7 @@
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Overview &mdash; fmt 3.0.0 documentation</title>
<title>Overview &mdash; fmt 4.0.0 documentation</title>
<link rel="stylesheet" href="_static/basic.css" type="text/css" />
<link rel="stylesheet" href="_static/pygments.css" type="text/css" />
@@ -17,10 +17,11 @@
<script type="text/javascript">
var DOCUMENTATION_OPTIONS = {
URL_ROOT: './',
VERSION: '3.0.0',
VERSION: '4.0.0',
COLLAPSE_INDEX: false,
FILE_SUFFIX: '.html',
HAS_SOURCE: true
HAS_SOURCE: true,
SOURCELINK_SUFFIX: ''
};
</script>
<script type="text/javascript" src="_static/jquery.js"></script>
@@ -33,8 +34,9 @@
<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)
(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', 'fmtlib.net');
ga('send', 'pageview');
@@ -48,7 +50,8 @@
<div class="navbar-content">
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target=".navbar-collapse">
<button type="button" class="navbar-toggle collapsed"
data-toggle="collapse" data-target=".navbar-collapse">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
@@ -61,13 +64,17 @@
<div class="collapse navbar-collapse">
<ul class="nav navbar-nav">
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button"
aria-expanded="false">3.0.0 <span class="caret"></span></a>
<a href="#" class="dropdown-toggle" data-toggle="dropdown"
role="button" aria-expanded="false">4.0.0
<span class="caret"></span></a>
<ul class="dropdown-menu" role="menu">
<li><a href="http://fmtlib.net/2.0.0/">2.0.0</a></li>
<li><a href="http://fmtlib.net/1.1.0/">1.1.0</a></li>
<li><a href="http://fmtlib.net/1.0.0/">1.0.0</a></li>
<li><a href="http://fmtlib.net/3.0.0">3.0.0</a></li>
<li><a href="http://fmtlib.net/2.0.0">2.0.0</a></li>
<li><a href="http://fmtlib.net/1.1.0">1.1.0</a></li>
</ul>
</li>
@@ -90,9 +97,11 @@
</ul>
<form class="navbar-form navbar-right" role="search" action="search.html" method="get">
<form class="navbar-form navbar-right" role="search" action="search.html"
method="get">
<div class="form-group">
<input type="text" name="q" class="form-control" placeholder="Search" >
<input type="text" name="q" class="form-control"
placeholder="Search" >
</div>
<input type="hidden" name="check_keywords" value="yes" />
<input type="hidden" name="area" value="default" />
@@ -105,20 +114,33 @@
</div>
</nav>
<div class="jumbotron">
<div class="tb-container">
<h1>{fmt}</h1>
<p class="lead">Small, safe and fast formatting library</p>
<div class="btn-group" role="group">
<a class="btn btn-success"
href="https://github.com/fmtlib/fmt/releases/download/2.0.0/cppformat-2.0.0.zip">
<span class="glyphicon glyphicon-download"></span> Download
href="https://github.com/fmtlib/fmt/releases/download/4.0.0/fmt-4.0.0.zip">
<span class="glyphicon glyphicon-download"></span> Download
</a>
<button type="button" class="btn btn-success dropdown-toggle" data-toggle="dropdown"><span class="caret"></span></button>
<button type="button" class="btn btn-success dropdown-toggle"
data-toggle="dropdown"><span class="caret"></span></button>
<ul class="dropdown-menu">
<li><a href="https://github.com/fmtlib/fmt/releases/download/2.0.0/cppformat-2.0.0.zip">Version 2.0.0</a></li>
<li><a href="https://github.com/fmtlib/fmt/releases/download/1.1.0/cppformat-1.1.0.zip">Version 1.1.0</a></li>
<li><a href="https://github.com/fmtlib/fmt/releases/download/1.0.0/cppformat-1.0.0.zip">Version 1.0.0</a></li>
<li><a href="https://github.com/fmtlib/fmt/releases/download/3.0.0/fmt-3.0.0.zip">Version 3.0.0
</a></li>
<li><a href="https://github.com/fmtlib/fmt/releases/download/2.0.0/cppformat-2.0.0.zip">Version 2.0.0
</a></li>
<li><a href="https://github.com/fmtlib/fmt/releases/download/1.1.0/cppformat-1.1.0.zip">Version 1.1.0
</a></li>
</ul>
</div>
</div>
@@ -140,16 +162,16 @@ alternative to C++ IOStreams.</p>
<div class="panel panel-default">
<div class="panel-heading">What users say:</div>
<div class="panel-body">
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.
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.
</div>
</div><div class="section" id="format-api">
<span id="id1"></span><h2>Format API<a class="headerlink" href="#format-api" title="Permalink to this headline"></a></h2>
<p>The replacement-based Format API provides a safe alternative to <code class="docutils literal"><span class="pre">printf</span></code>,
<code class="docutils literal"><span class="pre">sprintf</span></code> and friends with comparable or <a class="reference external" href="http://zverovich.net/2013/09/07/integer-to-string-conversion-in-cplusplus.html">better performance</a>.
The <a class="reference external" href="doc/latest/index.html#format-string-syntax">format string syntax</a> is similar
to the one used by <a class="reference external" href="http://docs.python.org/2/library/stdtypes.html#str.format">str.format</a>
The <a class="reference external" href="syntax.html">format string syntax</a> is similar to the one used by
<a class="reference external" href="http://docs.python.org/2/library/stdtypes.html#str.format">str.format</a>
in Python:</p>
<div class="code c++ highlight-c++"><div class="highlight"><pre><span></span><span class="n">fmt</span><span class="o">::</span><span class="n">format</span><span class="p">(</span><span class="s">&quot;The answer is {}&quot;</span><span class="p">,</span> <span class="mi">42</span><span class="p">);</span>
</pre></div>
@@ -202,8 +224,7 @@ literal operators, they must be made visible with the directive
</div>
<div class="section" id="write-api">
<span id="id2"></span><h2>Write API<a class="headerlink" href="#write-api" title="Permalink to this headline"></a></h2>
<p>The concatenation-based Write API (experimental) provides a
<a class="reference external" href="http://zverovich.net/2013/09/07/integer-to-string-conversion-in-cplusplus.html">fast</a>
<p>The concatenation-based Write API (experimental) provides a <a class="reference external" href="http://zverovich.net/2013/09/07/integer-to-string-conversion-in-cplusplus.html">fast</a>
stateless alternative to IOStreams:</p>
<div class="code c++ highlight-c++"><div class="highlight"><pre><span></span><span class="n">fmt</span><span class="o">::</span><span class="n">MemoryWriter</span> <span class="n">out</span><span class="p">;</span>
<span class="n">out</span> <span class="o">&lt;&lt;</span> <span class="s">&quot;The answer in hexadecimal is &quot;</span> <span class="o">&lt;&lt;</span> <span class="n">hex</span><span class="p">(</span><span class="mi">42</span><span class="p">);</span>
@@ -212,8 +233,9 @@ stateless alternative to IOStreams:</p>
</div>
<div class="section" id="safety">
<span id="id3"></span><h2>Safety<a class="headerlink" href="#safety" title="Permalink to this headline"></a></h2>
<p>The library is fully type safe, automatic memory management prevents buffer overflow,
errors in format strings are reported using exceptions. For example, the code</p>
<p>The library is fully type safe, automatic memory management prevents buffer
overflow, errors in format strings are reported using exceptions. For example,
the code</p>
<div class="code c++ highlight-c++"><div class="highlight"><pre><span></span><span class="n">fmt</span><span class="o">::</span><span class="n">format</span><span class="p">(</span><span class="s">&quot;The answer is {:d}&quot;</span><span class="p">,</span> <span class="s">&quot;forty-two&quot;</span><span class="p">);</span>
</pre></div>
</div>
@@ -231,36 +253,38 @@ formatted into a narrow string. You can use a wide format string instead:</p>
</pre></div>
</div>
<p>For comparison, writing a wide character to <code class="docutils literal"><span class="pre">std::ostream</span></code> results in
its numeric value being written to the stream (i.e. 1070 instead of letter &#8216;ю&#8217; which
is represented by <code class="docutils literal"><span class="pre">L'\x42e'</span></code> if we use Unicode) which is rarely what is needed.</p>
its numeric value being written to the stream (i.e. 1070 instead of letter &#8216;ю&#8217;
which is represented by <code class="docutils literal"><span class="pre">L'\x42e'</span></code> if we use Unicode) which is rarely what is
needed.</p>
</div>
<div class="section" id="portability">
<span id="id4"></span><h2>Portability<a class="headerlink" href="#portability" title="Permalink to this headline"></a></h2>
<p>The library is highly portable. Here is an incomplete list of operating systems and
compilers where it has been tested and known to work:</p>
<p>The library is highly portable. Here is an incomplete list of operating systems
and compilers where it has been tested and known to work:</p>
<ul class="simple">
<li>64-bit (amd64) GNU/Linux with GCC 4.4.3, <a class="reference external" href="https://travis-ci.org/fmtlib/fmt">4.6.3</a>,
4.7.2, 4.8.1 and Intel C++ Compiler (ICC) 14.0.2</li>
<li>64-bit (amd64) GNU/Linux with GCC 4.4.3,
<a class="reference external" href="https://travis-ci.org/fmtlib/fmt">4.6.3</a>, 4.7.2, 4.8.1, and Intel C++
Compiler (ICC) 14.0.2</li>
<li>32-bit (i386) GNU/Linux with GCC 4.4.3, 4.6.3</li>
<li>Mac OS X with GCC 4.2.1 and Clang 4.2, 5.1.0</li>
<li>64-bit Windows with Visual C++ 2010, 2013 and
<a class="reference external" href="https://ci.appveyor.com/project/vitaut/fmt">2015</a></li>
<li>32-bit Windows with Visual C++ 2010</li>
</ul>
<p>Although the library uses C++11 features when available, it also works with older
compilers and standard library implementations. The only thing to keep in mind
for C++98 portability:</p>
<p>Although the library uses C++11 features when available, it also works with
older compilers and standard library implementations. The only thing to keep in
mind for C++98 portability:</p>
<ul class="simple">
<li>Variadic templates: minimum GCC 4.4, Clang 2.9 or VS2013. This feature allows
the Format API to accept an unlimited number of arguments. With older compilers
the maximum is 15.</li>
the Format API to accept an unlimited number of arguments. With older
compilers the maximum is 15.</li>
<li>User-defined literals: minimum GCC 4.7, Clang 3.1 or VS2015. The suffixes
<code class="docutils literal"><span class="pre">_format</span></code> and <code class="docutils literal"><span class="pre">_a</span></code> are functionally equivalent to the functions
<code class="docutils literal"><span class="pre">fmt::format</span></code> and <code class="docutils literal"><span class="pre">fmt::arg</span></code>.</li>
</ul>
<p>The output of all formatting functions is consistent across platforms. In particular,
formatting a floating-point infinity always gives <code class="docutils literal"><span class="pre">inf</span></code> while the output
of <code class="docutils literal"><span class="pre">printf</span></code> is platform-dependent in this case. For example,</p>
<p>The output of all formatting functions is consistent across platforms. In
particular, formatting a floating-point infinity always gives <code class="docutils literal"><span class="pre">inf</span></code> while the
output of <code class="docutils literal"><span class="pre">printf</span></code> is platform-dependent in this case. For example,</p>
<div class="code highlight-c++"><div class="highlight"><pre><span></span><span class="n">fmt</span><span class="o">::</span><span class="n">print</span><span class="p">(</span><span class="s">&quot;{}&quot;</span><span class="p">,</span> <span class="n">std</span><span class="o">::</span><span class="n">numeric_limits</span><span class="o">&lt;</span><span class="kt">double</span><span class="o">&gt;::</span><span class="n">infinity</span><span class="p">());</span>
</pre></div>
</div>
@@ -268,9 +292,10 @@ of <code class="docutils literal"><span class="pre">printf</span></code> is plat
</div>
<div class="section" id="ease-of-use">
<span id="id7"></span><h2>Ease of Use<a class="headerlink" href="#ease-of-use" title="Permalink to this headline"></a></h2>
<p>fmt has a small self-contained code base consisting of a single header file
and a single source file and no external dependencies. A permissive BSD <a class="reference external" href="https://github.com/fmtlib/fmt#license">license</a> allows using the library both
in open-source and commercial projects.</p>
<p>fmt has a small self-contained code base with the core library consisting of
a single header file and a single source file and no external dependencies.
A permissive BSD <a class="reference external" href="https://github.com/fmtlib/fmt#license">license</a> allows
using the library both in open-source and commercial projects.</p>
<a class="btn btn-success" href="https://github.com/fmtlib/fmt">GitHub Repository</a>
<div class="section footer">
@@ -288,7 +313,7 @@ in open-source and commercial projects.</p>
<div class="footer" role="contentinfo">
&copy; Copyright 2012-2015, Victor Zverovich.
Created using <a href="http://sphinx-doc.org/">Sphinx</a> 1.4.1.
Created using <a href="http://sphinx-doc.org/">Sphinx</a> 1.4.1+.
</div>
<script src="_static/bootstrap.min.js"></script>
Binary file not shown.
+24 -15
View File
@@ -8,7 +8,7 @@
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Search &mdash; fmt 3.0.0 documentation</title>
<title>Search &mdash; fmt 4.0.0 documentation</title>
<link rel="stylesheet" href="_static/basic.css" type="text/css" />
<link rel="stylesheet" href="_static/pygments.css" type="text/css" />
@@ -17,10 +17,11 @@
<script type="text/javascript">
var DOCUMENTATION_OPTIONS = {
URL_ROOT: './',
VERSION: '3.0.0',
VERSION: '4.0.0',
COLLAPSE_INDEX: false,
FILE_SUFFIX: '.html',
HAS_SOURCE: true
HAS_SOURCE: true,
SOURCELINK_SUFFIX: ''
};
</script>
<script type="text/javascript" src="_static/jquery.js"></script>
@@ -40,8 +41,9 @@
<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)
(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', 'fmtlib.net');
ga('send', 'pageview');
@@ -56,7 +58,8 @@
<div class="navbar-content">
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target=".navbar-collapse">
<button type="button" class="navbar-toggle collapsed"
data-toggle="collapse" data-target=".navbar-collapse">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
@@ -69,13 +72,17 @@
<div class="collapse navbar-collapse">
<ul class="nav navbar-nav">
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button"
aria-expanded="false">3.0.0 <span class="caret"></span></a>
<a href="#" class="dropdown-toggle" data-toggle="dropdown"
role="button" aria-expanded="false">4.0.0
<span class="caret"></span></a>
<ul class="dropdown-menu" role="menu">
<li><a href="http://fmtlib.net/2.0.0/">2.0.0</a></li>
<li><a href="http://fmtlib.net/1.1.0/">1.1.0</a></li>
<li><a href="http://fmtlib.net/1.0.0/">1.0.0</a></li>
<li><a href="http://fmtlib.net/3.0.0">3.0.0</a></li>
<li><a href="http://fmtlib.net/2.0.0">2.0.0</a></li>
<li><a href="http://fmtlib.net/1.1.0">1.1.0</a></li>
</ul>
</li>
@@ -126,9 +133,11 @@
containing fewer words won't appear in the result list.
</p>
<form class="form-inline" role="search" action="#" method="get">
<form class="form-inline" role="search" action="#"
method="get">
<div class="form-group">
<input type="text" name="q" class="form-control" >
<input type="text" name="q" class="form-control"
>
</div>
<input type="hidden" name="check_keywords" value="yes" />
<input type="hidden" name="area" value="default" />
@@ -149,7 +158,7 @@
<div class="footer" role="contentinfo">
&copy; Copyright 2012-2015, Victor Zverovich.
Created using <a href="http://sphinx-doc.org/">Sphinx</a> 1.4.1.
Created using <a href="http://sphinx-doc.org/">Sphinx</a> 1.4.1+.
</div>
<script src="_static/bootstrap.min.js"></script>
File diff suppressed because one or more lines are too long
+33 -25
View File
@@ -8,7 +8,7 @@
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Format String Syntax &mdash; fmt 3.0.0 documentation</title>
<title>Format String Syntax &mdash; fmt 4.0.0 documentation</title>
<link rel="stylesheet" href="_static/basic.css" type="text/css" />
<link rel="stylesheet" href="_static/pygments.css" type="text/css" />
@@ -17,10 +17,11 @@
<script type="text/javascript">
var DOCUMENTATION_OPTIONS = {
URL_ROOT: './',
VERSION: '3.0.0',
VERSION: '4.0.0',
COLLAPSE_INDEX: false,
FILE_SUFFIX: '.html',
HAS_SOURCE: true
HAS_SOURCE: true,
SOURCELINK_SUFFIX: ''
};
</script>
<script type="text/javascript" src="_static/jquery.js"></script>
@@ -34,8 +35,9 @@
<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)
(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', 'fmtlib.net');
ga('send', 'pageview');
@@ -49,7 +51,8 @@
<div class="navbar-content">
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target=".navbar-collapse">
<button type="button" class="navbar-toggle collapsed"
data-toggle="collapse" data-target=".navbar-collapse">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
@@ -62,13 +65,17 @@
<div class="collapse navbar-collapse">
<ul class="nav navbar-nav">
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button"
aria-expanded="false">3.0.0 <span class="caret"></span></a>
<a href="#" class="dropdown-toggle" data-toggle="dropdown"
role="button" aria-expanded="false">4.0.0
<span class="caret"></span></a>
<ul class="dropdown-menu" role="menu">
<li><a href="http://fmtlib.net/2.0.0/">2.0.0</a></li>
<li><a href="http://fmtlib.net/1.1.0/">1.1.0</a></li>
<li><a href="http://fmtlib.net/1.0.0/">1.0.0</a></li>
<li><a href="http://fmtlib.net/3.0.0">3.0.0</a></li>
<li><a href="http://fmtlib.net/2.0.0">2.0.0</a></li>
<li><a href="http://fmtlib.net/1.1.0">1.1.0</a></li>
</ul>
</li>
@@ -85,15 +92,18 @@
<li class="active"><a href="syntax.html">Syntax <span class="sr-only">(current)</span></a></li>
<li class="active"><a href="syntax.html">Syntax
<span class="sr-only">(current)</span></a></li>
</ul>
<form class="navbar-form navbar-right" role="search" action="search.html" method="get">
<form class="navbar-form navbar-right" role="search" action="search.html"
method="get">
<div class="form-group">
<input type="text" name="q" class="form-control" placeholder="Search" >
<input type="text" name="q" class="form-control"
placeholder="Search" >
</div>
<input type="hidden" name="check_keywords" value="yes" />
<input type="hidden" name="area" value="default" />
@@ -153,12 +163,10 @@ precision and so on. Each value type can define its own &#8220;formatting
mini-language&#8221; or interpretation of the <em>format_spec</em>.</p>
<p>Most built-in types support a common formatting mini-language, which is
described in the next section.</p>
<p>A <em>format_spec</em> 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
<em>format_spec</em> string is interpreted. This allows the formatting of a value
to be dynamically specified.</p>
<p>A <em>format_spec</em> field can also include nested replacement fields in certain
positions within it. These nested replacement fields can contain only an
argument id; format specifications are not allowed. This allows the
formatting of a value to be dynamically specified.</p>
<p>See the <a class="reference internal" href="#formatexamples"><span class="std std-ref">Format examples</span></a> section for some examples.</p>
<div class="section" id="format-specification-mini-language">
<span id="formatspec"></span><h2>Format Specification Mini-Language<a class="headerlink" href="#format-specification-mini-language" title="Permalink to this headline"></a></h2>
@@ -176,8 +184,8 @@ although some of the formatting options are only supported by the numeric types.
<strong id="grammar-token-sign">sign </strong> ::= &quot;+&quot; | &quot;-&quot; | &quot; &quot;
<strong id="grammar-token-width">width </strong> ::= <a class="reference internal" href="#grammar-token-integer"><code class="xref docutils literal"><span class="pre">integer</span></code></a> | &quot;{&quot; <a class="reference internal" href="#grammar-token-arg_id"><code class="xref docutils literal"><span class="pre">arg_id</span></code></a> &quot;}&quot;
<strong id="grammar-token-precision">precision </strong> ::= <a class="reference internal" href="#grammar-token-integer"><code class="xref docutils literal"><span class="pre">integer</span></code></a> | &quot;{&quot; <a class="reference internal" href="#grammar-token-arg_id"><code class="xref docutils literal"><span class="pre">arg_id</span></code></a> &quot;}&quot;
<strong id="grammar-token-type">type </strong> ::= <a class="reference internal" href="#grammar-token-int_type"><code class="xref docutils literal"><span class="pre">int_type</span></code></a> | &quot;c&quot; | &quot;e&quot; | &quot;E&quot; | &quot;f&quot; | &quot;F&quot; | &quot;g&quot; | &quot;G&quot; | &quot;p&quot; | &quot;s&quot;
<strong id="grammar-token-int_type">int_type </strong> ::= &quot;b&quot; | &quot;B&quot; | &quot;d&quot; | &quot;o&quot; | &quot;x&quot; | &quot;X&quot;
<strong id="grammar-token-type">type </strong> ::= <a class="reference internal" href="#grammar-token-int_type"><code class="xref docutils literal"><span class="pre">int_type</span></code></a> | &quot;a&quot; | &quot;A&quot; | &quot;c&quot; | &quot;e&quot; | &quot;E&quot; | &quot;f&quot; | &quot;F&quot; | &quot;g&quot; | &quot;G&quot; | &quot;p&quot; | &quot;s&quot;
<strong id="grammar-token-int_type">int_type </strong> ::= &quot;b&quot; | &quot;B&quot; | &quot;d&quot; | &quot;n&quot; | &quot;o&quot; | &quot;x&quot; | &quot;X&quot;
</pre>
<p>The <em>fill</em> character can be any character other than &#8216;{&#8216; or &#8216;}&#8217;. The presence
of a fill character is signaled by the character following it, which must be
@@ -383,7 +391,7 @@ Boolean values are formatted using textual representation, either <code class="d
<tr class="row-even"><td><code class="docutils literal"><span class="pre">'a'</span></code></td>
<td>Hexadecimal floating point format. Prints the number in
base 16 with prefix <code class="docutils literal"><span class="pre">&quot;0x&quot;</span></code> and lower-case letters for
digits above 9. Uses &#8216;p&#8217; to indicate the exponent.</td>
digits above 9. Uses <code class="docutils literal"><span class="pre">'p'</span></code> to indicate the exponent.</td>
</tr>
<tr class="row-odd"><td><code class="docutils literal"><span class="pre">'A'</span></code></td>
<td>Same as <code class="docutils literal"><span class="pre">'a'</span></code> except it uses upper-case letters for
@@ -507,7 +515,7 @@ following examples.</p>
<div class="footer" role="contentinfo">
&copy; Copyright 2012-2015, Victor Zverovich.
Created using <a href="http://sphinx-doc.org/">Sphinx</a> 1.4.1.
Created using <a href="http://sphinx-doc.org/">Sphinx</a> 1.4.1+.
</div>
<script src="_static/bootstrap.min.js"></script>
+55 -21
View File
@@ -8,7 +8,7 @@
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Usage &mdash; fmt 3.0.0 documentation</title>
<title>Usage &mdash; fmt 4.0.0 documentation</title>
<link rel="stylesheet" href="_static/basic.css" type="text/css" />
<link rel="stylesheet" href="_static/pygments.css" type="text/css" />
@@ -17,10 +17,11 @@
<script type="text/javascript">
var DOCUMENTATION_OPTIONS = {
URL_ROOT: './',
VERSION: '3.0.0',
VERSION: '4.0.0',
COLLAPSE_INDEX: false,
FILE_SUFFIX: '.html',
HAS_SOURCE: true
HAS_SOURCE: true,
SOURCELINK_SUFFIX: ''
};
</script>
<script type="text/javascript" src="_static/jquery.js"></script>
@@ -35,8 +36,9 @@
<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)
(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', 'fmtlib.net');
ga('send', 'pageview');
@@ -50,7 +52,8 @@
<div class="navbar-content">
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target=".navbar-collapse">
<button type="button" class="navbar-toggle collapsed"
data-toggle="collapse" data-target=".navbar-collapse">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
@@ -63,13 +66,17 @@
<div class="collapse navbar-collapse">
<ul class="nav navbar-nav">
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button"
aria-expanded="false">3.0.0 <span class="caret"></span></a>
<a href="#" class="dropdown-toggle" data-toggle="dropdown"
role="button" aria-expanded="false">4.0.0
<span class="caret"></span></a>
<ul class="dropdown-menu" role="menu">
<li><a href="http://fmtlib.net/2.0.0/">2.0.0</a></li>
<li><a href="http://fmtlib.net/1.1.0/">1.1.0</a></li>
<li><a href="http://fmtlib.net/1.0.0/">1.0.0</a></li>
<li><a href="http://fmtlib.net/3.0.0">3.0.0</a></li>
<li><a href="http://fmtlib.net/2.0.0">2.0.0</a></li>
<li><a href="http://fmtlib.net/1.1.0">1.1.0</a></li>
</ul>
</li>
@@ -78,7 +85,8 @@
<li class="active"><a href="usage.html">Usage <span class="sr-only">(current)</span></a></li>
<li class="active"><a href="usage.html">Usage
<span class="sr-only">(current)</span></a></li>
@@ -92,9 +100,11 @@
</ul>
<form class="navbar-form navbar-right" role="search" action="search.html" method="get">
<form class="navbar-form navbar-right" role="search" action="search.html"
method="get">
<div class="form-group">
<input type="text" name="q" class="form-control" placeholder="Search" >
<input type="text" name="q" class="form-control"
placeholder="Search" >
</div>
<input type="hidden" name="check_keywords" value="yes" />
<input type="hidden" name="area" value="default" />
@@ -155,14 +165,38 @@ using Visual Studio or msbuild.</p>
</pre></div>
</div>
</div>
<div class="section" id="header-only-usage-with-cmake">
<h2>Header-only usage with CMake<a class="headerlink" href="#header-only-usage-with-cmake" title="Permalink to this headline"></a></h2>
<p>In order to add <code class="docutils literal"><span class="pre">fmtlib</span></code> into an existing <code class="docutils literal"><span class="pre">CMakeLists.txt</span></code> file, you can add the <code class="docutils literal"><span class="pre">fmt</span></code> library directory into your main project, which will enable the <code class="docutils literal"><span class="pre">fmt</span></code> library:</p>
<div class="highlight-c++"><div class="highlight"><pre><span></span><span class="n">add_subdirectory</span><span class="p">(</span><span class="n">fmt</span><span class="p">)</span>
</pre></div>
</div>
<p>If you have a project called <code class="docutils literal"><span class="pre">foo</span></code> that you would like to link against the fmt library in a header-only fashion, you can enable with with:</p>
<div class="highlight-c++"><div class="highlight"><pre><span></span><span class="n">target_link_libraries</span><span class="p">(</span><span class="n">foo</span> <span class="n">PRIVATE</span> <span class="n">fmt</span><span class="o">::</span><span class="n">fmt</span><span class="o">-</span><span class="n">header</span><span class="o">-</span><span class="n">only</span><span class="p">)</span>
</pre></div>
</div>
<p>And then to ensure that the <code class="docutils literal"><span class="pre">fmt</span></code> library does not always get built, you can modify the call to <code class="docutils literal"><span class="pre">add_subdirectory</span></code> to read</p>
<div class="highlight-c++"><div class="highlight"><pre><span></span><span class="n">add_subdirectory</span><span class="p">(</span><span class="n">fmt</span> <span class="n">EXCLUDE_FROM_ALL</span><span class="p">)</span>
</pre></div>
</div>
<p>This will ensure that the <code class="docutils literal"><span class="pre">fmt</span></code> library is exluded from calls to <code class="docutils literal"><span class="pre">make</span></code>, <code class="docutils literal"><span class="pre">make</span> <span class="pre">all</span></code>, or <code class="docutils literal"><span class="pre">cmake</span> <span class="pre">--build</span> <span class="pre">.</span></code>.</p>
</div>
<div class="section" id="building-the-documentation">
<h2>Building the documentation<a class="headerlink" href="#building-the-documentation" title="Permalink to this headline"></a></h2>
<p>To build the documentation you need the following software installed on your
system:</p>
<ul class="simple">
<li><a class="reference external" href="https://www.python.org/">Python</a> with pip and virtualenv</li>
<li><a class="reference external" href="http://www.stack.nl/~dimitri/doxygen/">Doxygen</a></li>
<li><a class="reference external" href="http://lesscss.org/">Less</a> with less-plugin-clean-css</li>
<ul>
<li><p class="first"><a class="reference external" href="https://www.python.org/">Python</a> with pip and virtualenv</p>
</li>
<li><p class="first"><a class="reference external" href="http://www.stack.nl/~dimitri/doxygen/">Doxygen</a></p>
</li>
<li><p class="first"><a class="reference external" href="http://lesscss.org/">Less</a> with <code class="docutils literal"><span class="pre">less-plugin-clean-css</span></code>.
Ubuntu doesn&#8217;t package the <code class="docutils literal"><span class="pre">clean-css</span></code> plugin so you should use <code class="docutils literal"><span class="pre">npm</span></code>
instead of <code class="docutils literal"><span class="pre">apt</span></code> to install both <code class="docutils literal"><span class="pre">less</span></code> and the plugin:</p>
<div class="highlight-c++"><div class="highlight"><pre><span></span><span class="n">sudo</span> <span class="n">npm</span> <span class="n">install</span> <span class="o">-</span><span class="n">g</span> <span class="n">less</span> <span class="n">less</span><span class="o">-</span><span class="n">plugin</span><span class="o">-</span><span class="n">clean</span><span class="o">-</span><span class="n">css</span><span class="p">.</span>
</pre></div>
</div>
</li>
</ul>
<p>First generate makefiles or project files using CMake as described in
the previous section. Then compile the <code class="docutils literal"><span class="pre">doc</span></code> target/project, for example:</p>
@@ -182,7 +216,7 @@ repository.</p>
<div class="section" id="homebrew">
<h2>Homebrew<a class="headerlink" href="#homebrew" title="Permalink to this headline"></a></h2>
<p>fmt can be installed on OS X using <a class="reference external" href="http://brew.sh/">Homebrew</a>:</p>
<div class="highlight-c++"><div class="highlight"><pre><span></span><span class="n">brew</span> <span class="n">install</span> <span class="n">cppformat</span>
<div class="highlight-c++"><div class="highlight"><pre><span></span><span class="n">brew</span> <span class="n">install</span> <span class="n">fmt</span>
</pre></div>
</div>
</div>
@@ -197,7 +231,7 @@ repository.</p>
<div class="footer" role="contentinfo">
&copy; Copyright 2012-2015, Victor Zverovich.
Created using <a href="http://sphinx-doc.org/">Sphinx</a> 1.4.1.
Created using <a href="http://sphinx-doc.org/">Sphinx</a> 1.4.1+.
</div>
<script src="_static/bootstrap.min.js"></script>
+32 -29
View File
@@ -10,9 +10,9 @@ alternative to C++ IOStreams.
<div class="panel panel-default">
<div class="panel-heading">What users say:</div>
<div class="panel-body">
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.
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.
</div>
</div>
@@ -24,8 +24,8 @@ Format API
The replacement-based Format API provides a safe alternative to ``printf``,
``sprintf`` and friends with comparable or `better performance
<http://zverovich.net/2013/09/07/integer-to-string-conversion-in-cplusplus.html>`_.
The `format string syntax <doc/latest/index.html#format-string-syntax>`_ is similar
to the one used by `str.format <http://docs.python.org/2/library/stdtypes.html#str.format>`_
The `format string syntax <syntax.html>`_ is similar to the one used by
`str.format <http://docs.python.org/2/library/stdtypes.html#str.format>`_
in Python:
.. code:: c++
@@ -98,8 +98,8 @@ literal operators, they must be made visible with the directive
Write API
---------
The concatenation-based Write API (experimental) provides a
`fast <http://zverovich.net/2013/09/07/integer-to-string-conversion-in-cplusplus.html>`_
The concatenation-based Write API (experimental) provides a `fast
<http://zverovich.net/2013/09/07/integer-to-string-conversion-in-cplusplus.html>`_
stateless alternative to IOStreams:
.. code:: c++
@@ -112,8 +112,9 @@ stateless alternative to IOStreams:
Safety
------
The library is fully type safe, automatic memory management prevents buffer overflow,
errors in format strings are reported using exceptions. For example, the code
The library is fully type safe, automatic memory management prevents buffer
overflow, errors in format strings are reported using exceptions. For example,
the code
.. code:: c++
@@ -138,19 +139,21 @@ formatted into a narrow string. You can use a wide format string instead:
fmt::format(L"Cyrillic letter {}", L'\x42e');
For comparison, writing a wide character to ``std::ostream`` results in
its numeric value being written to the stream (i.e. 1070 instead of letter 'ю' which
is represented by ``L'\x42e'`` if we use Unicode) which is rarely what is needed.
its numeric value being written to the stream (i.e. 1070 instead of letter 'ю'
which is represented by ``L'\x42e'`` if we use Unicode) which is rarely what is
needed.
.. _portability:
Portability
-----------
The library is highly portable. Here is an incomplete list of operating systems and
compilers where it has been tested and known to work:
The library is highly portable. Here is an incomplete list of operating systems
and compilers where it has been tested and known to work:
* 64-bit (amd64) GNU/Linux with GCC 4.4.3, `4.6.3 <https://travis-ci.org/fmtlib/fmt>`_,
4.7.2, 4.8.1 and Intel C++ Compiler (ICC) 14.0.2
* 64-bit (amd64) GNU/Linux with GCC 4.4.3,
`4.6.3 <https://travis-ci.org/fmtlib/fmt>`_, 4.7.2, 4.8.1, and Intel C++
Compiler (ICC) 14.0.2
* 32-bit (i386) GNU/Linux with GCC 4.4.3, 4.6.3
@@ -161,21 +164,21 @@ compilers where it has been tested and known to work:
* 32-bit Windows with Visual C++ 2010
Although the library uses C++11 features when available, it also works with older
compilers and standard library implementations. The only thing to keep in mind
for C++98 portability:
Although the library uses C++11 features when available, it also works with
older compilers and standard library implementations. The only thing to keep in
mind for C++98 portability:
* Variadic templates: minimum GCC 4.4, Clang 2.9 or VS2013. This feature allows
the Format API to accept an unlimited number of arguments. With older compilers
the maximum is 15.
the Format API to accept an unlimited number of arguments. With older
compilers the maximum is 15.
* User-defined literals: minimum GCC 4.7, Clang 3.1 or VS2015. The suffixes
``_format`` and ``_a`` are functionally equivalent to the functions
* User-defined literals: minimum GCC 4.7, Clang 3.1 or VS2015. The suffixes
``_format`` and ``_a`` are functionally equivalent to the functions
``fmt::format`` and ``fmt::arg``.
The output of all formatting functions is consistent across platforms. In particular,
formatting a floating-point infinity always gives ``inf`` while the output
of ``printf`` is platform-dependent in this case. For example,
The output of all formatting functions is consistent across platforms. In
particular, formatting a floating-point infinity always gives ``inf`` while the
output of ``printf`` is platform-dependent in this case. For example,
.. code::
@@ -188,10 +191,10 @@ always prints ``inf``.
Ease of Use
-----------
fmt has a small self-contained code base consisting of a single header file
and a single source file and no external dependencies. A permissive BSD `license
<https://github.com/fmtlib/fmt#license>`_ allows using the library both
in open-source and commercial projects.
fmt has a small self-contained code base with the core library consisting of
a single header file and a single source file and no external dependencies.
A permissive BSD `license <https://github.com/fmtlib/fmt#license>`_ allows
using the library both in open-source and commercial projects.
.. raw:: html
+7 -9
View File
@@ -49,12 +49,10 @@ 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.
A *format_spec* field can also include nested replacement fields in certain
positions within it. These nested replacement fields can contain only an
argument id; format specifications are not allowed. This allows the
formatting of a value to be dynamically specified.
See the :ref:`formatexamples` section for some examples.
@@ -80,8 +78,8 @@ The general form of a *standard format specifier* is:
sign: "+" | "-" | " "
width: `integer` | "{" `arg_id` "}"
precision: `integer` | "{" `arg_id` "}"
type: `int_type` | "c" | "e" | "E" | "f" | "F" | "g" | "G" | "p" | "s"
int_type: "b" | "B" | "d" | "o" | "x" | "X"
type: `int_type` | "a" | "A" | "c" | "e" | "E" | "f" | "F" | "g" | "G" | "p" | "s"
int_type: "b" | "B" | "d" | "n" | "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
@@ -234,7 +232,7 @@ The available presentation types for floating-point values are:
+=========+==========================================================+
| ``'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. |
| | 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. |
+23 -2
View File
@@ -54,6 +54,23 @@ To build a `shared library`__ set the ``BUILD_SHARED_LIBS`` CMake variable to
__ http://en.wikipedia.org/wiki/Library_%28computing%29#Shared_libraries
Header-only usage with CMake
============================
In order to add ``fmtlib`` into an existing ``CMakeLists.txt`` file, you can add the ``fmt`` library directory into your main project, which will enable the ``fmt`` library::
add_subdirectory(fmt)
If you have a project called ``foo`` that you would like to link against the fmt library in a header-only fashion, you can enable with with::
target_link_libraries(foo PRIVATE fmt::fmt-header-only)
And then to ensure that the ``fmt`` library does not always get built, you can modify the call to ``add_subdirectory`` to read ::
add_subdirectory(fmt EXCLUDE_FROM_ALL)
This will ensure that the ``fmt`` library is exluded from calls to ``make``, ``make all``, or ``cmake --build .``.
Building the documentation
==========================
@@ -62,7 +79,11 @@ system:
* `Python <https://www.python.org/>`_ with pip and virtualenv
* `Doxygen <http://www.stack.nl/~dimitri/doxygen/>`_
* `Less <http://lesscss.org/>`_ with less-plugin-clean-css
* `Less <http://lesscss.org/>`_ with ``less-plugin-clean-css``.
Ubuntu doesn't package the ``clean-css`` plugin so you should use ``npm``
instead of ``apt`` to install both ``less`` and the plugin::
sudo npm install -g less less-plugin-clean-css.
First generate makefiles or project files using CMake as described in
the previous section. Then compile the ``doc`` target/project, for example::
@@ -87,4 +108,4 @@ Homebrew
fmt can be installed on OS X using `Homebrew <http://brew.sh/>`_::
brew install cppformat
brew install fmt
+40 -14
View File
@@ -1,26 +1,52 @@
# Define the fmt library, its includes and the needed defines.
# format.cc is added to FMT_HEADERS for the header-only configuration.
set(FMT_HEADERS format.h format.cc ostream.h ostream.cc time.h)
# *.cc are added to FMT_HEADERS for the header-only configuration.
set(FMT_HEADERS container.h format.h format.cc ostream.h ostream.cc printf.h
printf.cc string.h time.h)
if (HAVE_OPEN)
set(FMT_HEADERS ${FMT_HEADERS} posix.h)
set(FMT_SOURCES ${FMT_SOURCES} posix.cc)
endif ()
add_library(fmt ${FMT_SOURCES} ${FMT_HEADERS} ../ChangeLog.rst)
add_library(fmt ${FMT_SOURCES} ${FMT_HEADERS} ../README.rst ../ChangeLog.rst)
add_library(fmt::fmt ALIAS fmt)
option(FMT_CPPFORMAT "Build cppformat library for backward compatibility." OFF)
if (FMT_CPPFORMAT)
message(WARNING "The cppformat library is deprecated, use fmt instead.")
add_library(cppformat ${FMT_SOURCES} ${FMT_HEADERS})
# Starting with cmake 3.1 the CXX_STANDARD property can be used instead.
# Note: Don't make -std=c++11 public or interface, since it breaks projects
# that use C++14.
target_compile_options(fmt PRIVATE ${CPP11_FLAG})
if (FMT_PEDANTIC)
target_compile_options(fmt PRIVATE ${PEDANTIC_COMPILE_FLAGS})
endif ()
include_directories(fmt INTERFACE
target_include_directories(fmt PUBLIC
$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}>
$<INSTALL_INTERFACE:include>)
set_target_properties(fmt PROPERTIES
VERSION ${FMT_VERSION} SOVERSION ${CPACK_PACKAGE_VERSION_MAJOR})
if (BUILD_SHARED_LIBS)
if (UNIX AND NOT APPLE)
# Fix rpmlint warning:
# unused-direct-shlib-dependency /usr/lib/libformat.so.1.1.0 /lib/libm.so.6.
target_link_libraries(fmt -Wl,--as-needed)
endif ()
target_compile_definitions(fmt PRIVATE FMT_EXPORT INTERFACE FMT_SHARED)
endif ()
#------------------------------------------------------------------------------
# additionally define a header only library when cmake is new enough
if (CMAKE_VERSION VERSION_GREATER 3.1.0 OR CMAKE_VERSION VERSION_EQUAL 3.1.0)
add_library(fmt-header-only INTERFACE)
add_library(fmt::fmt-header-only ALIAS fmt-header-only)
target_compile_definitions(fmt-header-only INTERFACE FMT_HEADER_ONLY=1)
target_include_directories(fmt-header-only INTERFACE
$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}>
$<INSTALL_INTERFACE:include>)
endif ()
# Install targets.
if (FMT_INSTALL)
include(CMakePackageConfigHelpers)
@@ -47,18 +73,18 @@ if (FMT_INSTALL)
${PROJECT_SOURCE_DIR}/support/cmake/fmt-config.cmake.in
${project_config}
INSTALL_DESTINATION ${FMT_CMAKE_DIR})
export(TARGETS ${INSTALL_TARGETS} FILE ${PROJECT_BINARY_DIR}/${targets_export_name}.cmake)
export(TARGETS ${INSTALL_TARGETS} NAMESPACE fmt::
FILE ${PROJECT_BINARY_DIR}/${targets_export_name}.cmake)
# Install version, config and target files.
install(
FILES ${project_config} ${version_config}
DESTINATION ${FMT_CMAKE_DIR})
install(EXPORT ${targets_export_name} DESTINATION ${FMT_CMAKE_DIR})
install(EXPORT ${targets_export_name} DESTINATION ${FMT_CMAKE_DIR}
NAMESPACE fmt::)
# Install the library and headers.
install(TARGETS ${INSTALL_TARGETS} EXPORT ${targets_export_name} DESTINATION ${FMT_LIB_DIR})
install(TARGETS ${INSTALL_TARGETS} EXPORT ${targets_export_name}
DESTINATION ${FMT_LIB_DIR})
install(FILES ${FMT_HEADERS} DESTINATION include/fmt)
if (FMT_CPPFORMAT)
install(TARGETS cppformat DESTINATION ${FMT_LIB_DIR})
endif ()
endif ()
+82
View File
@@ -0,0 +1,82 @@
/*
Formatting library for C++ - standard container utilities
Copyright (c) 2012 - 2016, Victor Zverovich
All rights reserved.
For the license information refer to format.h.
*/
#ifndef FMT_CONTAINER_H_
#define FMT_CONTAINER_H_
#include "format.h"
namespace fmt {
namespace internal {
/**
\rst
A "buffer" that appends data to a standard container (e.g. typically a
``std::vector`` or ``std::basic_string``).
\endrst
*/
template <typename Container>
class ContainerBuffer : public Buffer<typename Container::value_type> {
private:
Container& container_;
protected:
virtual void grow(std::size_t size) FMT_OVERRIDE {
container_.resize(size);
this->ptr_ = &container_[0];
this->capacity_ = size;
}
public:
explicit ContainerBuffer(Container& container) : container_(container) {
this->size_ = container_.size();
if (this->size_ > 0) {
this->ptr_ = &container_[0];
this->capacity_ = this->size_;
}
}
};
} // namespace internal
/**
\rst
This class template provides operations for formatting and appending data
to a standard *container* like ``std::vector`` or ``std::basic_string``.
**Example**::
void vecformat(std::vector<char>& dest, fmt::BasicCStringRef<char> format,
fmt::ArgList args) {
fmt::BasicContainerWriter<std::vector<char> > appender(dest);
appender.write(format, args);
}
FMT_VARIADIC(void, vecformat, std::vector<char>&,
fmt::BasicCStringRef<char>);
\endrst
*/
template <class Container>
class BasicContainerWriter
: public BasicWriter<typename Container::value_type> {
private:
internal::ContainerBuffer<Container> buffer_;
public:
/**
\rst
Constructs a :class:`fmt::BasicContainerWriter` object.
\endrst
*/
explicit BasicContainerWriter(Container& dest)
: BasicWriter<typename Container::value_type>(buffer_), buffer_(dest) {}
};
} // namespace fmt
#endif // FMT_CONTAINER_H_
+67 -467
View File
@@ -41,6 +41,9 @@
#endif
#if FMT_USE_WINDOWS_H
# if !defined(FMT_HEADER_ONLY) && !defined(WIN32_LEAN_AND_MEAN)
# define WIN32_LEAN_AND_MEAN
# endif
# if defined(NOMINMAX) || defined(FMT_WIN_MINMAX)
# include <windows.h>
# else
@@ -50,8 +53,6 @@
# endif
#endif
using fmt::internal::Arg;
#if FMT_EXCEPTIONS
# define FMT_TRY try
# define FMT_CATCH(x) catch (x)
@@ -79,6 +80,11 @@ static inline fmt::internal::Null<> strerror_s(char *, std::size_t, ...) {
}
namespace fmt {
FMT_FUNC internal::RuntimeError::~RuntimeError() FMT_DTOR_NOEXCEPT {}
FMT_FUNC FormatError::~FormatError() FMT_DTOR_NOEXCEPT {}
FMT_FUNC SystemError::~SystemError() FMT_DTOR_NOEXCEPT {}
namespace {
#ifndef _MSC_VER
@@ -100,27 +106,6 @@ inline int fmt_snprintf(char *buffer, size_t size, const char *format, ...) {
# define FMT_SWPRINTF swprintf
#endif // defined(_WIN32) && defined(__MINGW32__) && !defined(__NO_ISOCEXT)
// Checks if a value fits in int - used to avoid warnings about comparing
// signed and unsigned integers.
template <bool IsSigned>
struct IntChecker {
template <typename T>
static bool fits_in_int(T value) {
unsigned max = INT_MAX;
return value <= max;
}
static bool fits_in_int(bool) { return true; }
};
template <>
struct IntChecker<true> {
template <typename T>
static bool fits_in_int(T value) {
return value >= INT_MIN && value <= INT_MAX;
}
static bool fits_in_int(int) { return true; }
};
const char RESET_COLOR[] = "\x1b[0m";
typedef void (*FormatFunc)(Writer &, int, StringRef);
@@ -186,7 +171,8 @@ int safe_strerror(
: error_code_(err_code), buffer_(buf), buffer_size_(buf_size) {}
int run() {
strerror_r(0, 0, ""); // Suppress a warning about unused strerror_r.
// Suppress a warning about unused strerror_r.
strerror_r(0, FMT_NULL, "");
return handle(strerror_r(error_code_, buffer_, buffer_size_));
}
};
@@ -225,222 +211,19 @@ void report_error(FormatFunc func, int error_code,
std::fwrite(full_message.data(), full_message.size(), 1, stderr);
std::fputc('\n', stderr);
}
// IsZeroInt::visit(arg) returns true iff arg is a zero integer.
class IsZeroInt : public ArgVisitor<IsZeroInt, bool> {
public:
template <typename T>
bool visit_any_int(T value) { return value == 0; }
};
// Checks if an argument is a valid printf width specifier and sets
// left alignment if it is negative.
class WidthHandler : public ArgVisitor<WidthHandler, unsigned> {
private:
FormatSpec &spec_;
FMT_DISALLOW_COPY_AND_ASSIGN(WidthHandler);
public:
explicit WidthHandler(FormatSpec &spec) : spec_(spec) {}
void report_unhandled_arg() {
FMT_THROW(FormatError("width is not integer"));
}
template <typename T>
unsigned visit_any_int(T value) {
typedef typename internal::IntTraits<T>::MainType UnsignedType;
UnsignedType width = static_cast<UnsignedType>(value);
if (internal::is_negative(value)) {
spec_.align_ = ALIGN_LEFT;
width = 0 - width;
}
if (width > INT_MAX)
FMT_THROW(FormatError("number is too big"));
return static_cast<unsigned>(width);
}
};
class PrecisionHandler : public ArgVisitor<PrecisionHandler, int> {
public:
void report_unhandled_arg() {
FMT_THROW(FormatError("precision is not integer"));
}
template <typename T>
int visit_any_int(T value) {
if (!IntChecker<std::numeric_limits<T>::is_signed>::fits_in_int(value))
FMT_THROW(FormatError("number is too big"));
return static_cast<int>(value);
}
};
template <typename T, typename U>
struct is_same {
enum { value = 0 };
};
template <typename T>
struct is_same<T, T> {
enum { value = 1 };
};
// An argument visitor that converts an integer argument to T for printf,
// if T is an integral type. If T is void, the argument is converted to
// corresponding signed or unsigned type depending on the type specifier:
// 'd' and 'i' - signed, other - unsigned)
template <typename T = void>
class ArgConverter : public ArgVisitor<ArgConverter<T>, void> {
private:
internal::Arg &arg_;
wchar_t type_;
FMT_DISALLOW_COPY_AND_ASSIGN(ArgConverter);
public:
ArgConverter(internal::Arg &arg, wchar_t type)
: arg_(arg), type_(type) {}
void visit_bool(bool value) {
if (type_ != 's')
visit_any_int(value);
}
template <typename U>
void visit_any_int(U value) {
bool is_signed = type_ == 'd' || type_ == 'i';
using internal::Arg;
typedef typename internal::Conditional<
is_same<T, void>::value, U, T>::type TargetType;
if (sizeof(TargetType) <= sizeof(int)) {
// Extra casts are used to silence warnings.
if (is_signed) {
arg_.type = Arg::INT;
arg_.int_value = static_cast<int>(static_cast<TargetType>(value));
} else {
arg_.type = Arg::UINT;
typedef typename internal::MakeUnsigned<TargetType>::Type Unsigned;
arg_.uint_value = static_cast<unsigned>(static_cast<Unsigned>(value));
}
} else {
if (is_signed) {
arg_.type = Arg::LONG_LONG;
// glibc's printf doesn't sign extend arguments of smaller types:
// std::printf("%lld", -42); // prints "4294967254"
// but we don't have to do the same because it's a UB.
arg_.long_long_value = static_cast<LongLong>(value);
} else {
arg_.type = Arg::ULONG_LONG;
arg_.ulong_long_value =
static_cast<typename internal::MakeUnsigned<U>::Type>(value);
}
}
}
};
// Converts an integer argument to char for printf.
class CharConverter : public ArgVisitor<CharConverter, void> {
private:
internal::Arg &arg_;
FMT_DISALLOW_COPY_AND_ASSIGN(CharConverter);
public:
explicit CharConverter(internal::Arg &arg) : arg_(arg) {}
template <typename T>
void visit_any_int(T value) {
arg_.type = internal::Arg::CHAR;
arg_.int_value = static_cast<char>(value);
}
};
} // namespace
namespace internal {
template <typename Char>
class PrintfArgFormatter :
public ArgFormatterBase<PrintfArgFormatter<Char>, Char> {
void write_null_pointer() {
this->spec().type_ = 0;
this->write("(nil)");
}
typedef ArgFormatterBase<PrintfArgFormatter<Char>, Char> Base;
public:
PrintfArgFormatter(BasicWriter<Char> &w, FormatSpec &s)
: ArgFormatterBase<PrintfArgFormatter<Char>, Char>(w, s) {}
void visit_bool(bool value) {
FormatSpec &fmt_spec = this->spec();
if (fmt_spec.type_ != 's')
return this->visit_any_int(value);
fmt_spec.type_ = 0;
this->write(value);
}
void visit_char(int value) {
const FormatSpec &fmt_spec = this->spec();
BasicWriter<Char> &w = this->writer();
if (fmt_spec.type_ && fmt_spec.type_ != 'c')
w.write_int(value, fmt_spec);
typedef typename BasicWriter<Char>::CharPtr CharPtr;
CharPtr out = CharPtr();
if (fmt_spec.width_ > 1) {
Char fill = ' ';
out = w.grow_buffer(fmt_spec.width_);
if (fmt_spec.align_ != ALIGN_LEFT) {
std::fill_n(out, fmt_spec.width_ - 1, fill);
out += fmt_spec.width_ - 1;
} else {
std::fill_n(out + 1, fmt_spec.width_ - 1, fill);
}
} else {
out = w.grow_buffer(1);
}
*out = static_cast<Char>(value);
}
void visit_cstring(const char *value) {
if (value)
Base::visit_cstring(value);
else if (this->spec().type_ == 'p')
write_null_pointer();
else
this->write("(null)");
}
void visit_pointer(const void *value) {
if (value)
return Base::visit_pointer(value);
this->spec().type_ = 0;
write_null_pointer();
}
void visit_custom(Arg::CustomValue c) {
BasicFormatter<Char> formatter(ArgList(), this->writer());
const Char format_str[] = {'}', 0};
const Char *format = format_str;
c.format(&formatter, c.value, &format);
}
};
} // namespace internal
} // namespace fmt
FMT_FUNC void fmt::SystemError::init(
FMT_FUNC void SystemError::init(
int err_code, CStringRef format_str, ArgList args) {
error_code_ = err_code;
MemoryWriter w;
internal::format_system_error(w, err_code, format(format_str, args));
format_system_error(w, err_code, format(format_str, args));
std::runtime_error &base = *this;
base = std::runtime_error(w.str());
}
template <typename T>
int fmt::internal::CharTraits<char>::format_float(
int internal::CharTraits<char>::format_float(
char *buffer, std::size_t size, const char *format,
unsigned width, int precision, T value) {
if (width == 0) {
@@ -454,7 +237,7 @@ int fmt::internal::CharTraits<char>::format_float(
}
template <typename T>
int fmt::internal::CharTraits<wchar_t>::format_float(
int internal::CharTraits<wchar_t>::format_float(
wchar_t *buffer, std::size_t size, const wchar_t *format,
unsigned width, int precision, T value) {
if (width == 0) {
@@ -468,7 +251,7 @@ int fmt::internal::CharTraits<wchar_t>::format_float(
}
template <typename T>
const char fmt::internal::BasicData<T>::DIGITS[] =
const char internal::BasicData<T>::DIGITS[] =
"0001020304050607080910111213141516171819"
"2021222324252627282930313233343536373839"
"4041424344454647484950515253545556575859"
@@ -487,40 +270,40 @@ const char fmt::internal::BasicData<T>::DIGITS[] =
factor * 1000000000
template <typename T>
const uint32_t fmt::internal::BasicData<T>::POWERS_OF_10_32[] = {
const uint32_t internal::BasicData<T>::POWERS_OF_10_32[] = {
0, FMT_POWERS_OF_10(1)
};
template <typename T>
const uint64_t fmt::internal::BasicData<T>::POWERS_OF_10_64[] = {
const uint64_t internal::BasicData<T>::POWERS_OF_10_64[] = {
0,
FMT_POWERS_OF_10(1),
FMT_POWERS_OF_10(fmt::ULongLong(1000000000)),
FMT_POWERS_OF_10(ULongLong(1000000000)),
// Multiply several constants instead of using a single long long constant
// to avoid warnings about C++98 not supporting long long.
fmt::ULongLong(1000000000) * fmt::ULongLong(1000000000) * 10
ULongLong(1000000000) * ULongLong(1000000000) * 10
};
FMT_FUNC void fmt::internal::report_unknown_type(char code, const char *type) {
FMT_FUNC void internal::report_unknown_type(char code, const char *type) {
(void)type;
if (std::isprint(static_cast<unsigned char>(code))) {
FMT_THROW(fmt::FormatError(
fmt::format("unknown format code '{}' for {}", code, type)));
FMT_THROW(FormatError(
format("unknown format code '{}' for {}", code, type)));
}
FMT_THROW(fmt::FormatError(
fmt::format("unknown format code '\\x{:02x}' for {}",
FMT_THROW(FormatError(
format("unknown format code '\\x{:02x}' for {}",
static_cast<unsigned>(code), type)));
}
#if FMT_USE_WINDOWS_H
FMT_FUNC fmt::internal::UTF8ToUTF16::UTF8ToUTF16(fmt::StringRef s) {
FMT_FUNC internal::UTF8ToUTF16::UTF8ToUTF16(StringRef s) {
static const char ERROR_MSG[] = "cannot convert string from UTF-8 to UTF-16";
if (s.size() > INT_MAX)
FMT_THROW(WindowsError(ERROR_INVALID_PARAMETER, ERROR_MSG));
int s_size = static_cast<int>(s.size());
int length = MultiByteToWideChar(
CP_UTF8, MB_ERR_INVALID_CHARS, s.data(), s_size, 0, 0);
CP_UTF8, MB_ERR_INVALID_CHARS, s.data(), s_size, FMT_NULL, 0);
if (length == 0)
FMT_THROW(WindowsError(GetLastError(), ERROR_MSG));
buffer_.resize(length + 1);
@@ -531,30 +314,31 @@ FMT_FUNC fmt::internal::UTF8ToUTF16::UTF8ToUTF16(fmt::StringRef s) {
buffer_[length] = 0;
}
FMT_FUNC fmt::internal::UTF16ToUTF8::UTF16ToUTF8(fmt::WStringRef s) {
FMT_FUNC internal::UTF16ToUTF8::UTF16ToUTF8(WStringRef s) {
if (int error_code = convert(s)) {
FMT_THROW(WindowsError(error_code,
"cannot convert string from UTF-16 to UTF-8"));
}
}
FMT_FUNC int fmt::internal::UTF16ToUTF8::convert(fmt::WStringRef s) {
FMT_FUNC int internal::UTF16ToUTF8::convert(WStringRef s) {
if (s.size() > INT_MAX)
return ERROR_INVALID_PARAMETER;
int s_size = static_cast<int>(s.size());
int length = WideCharToMultiByte(CP_UTF8, 0, s.data(), s_size, 0, 0, 0, 0);
int length = WideCharToMultiByte(
CP_UTF8, 0, s.data(), s_size, FMT_NULL, 0, FMT_NULL, FMT_NULL);
if (length == 0)
return GetLastError();
buffer_.resize(length + 1);
length = WideCharToMultiByte(
CP_UTF8, 0, s.data(), s_size, &buffer_[0], length, 0, 0);
CP_UTF8, 0, s.data(), s_size, &buffer_[0], length, FMT_NULL, FMT_NULL);
if (length == 0)
return GetLastError();
buffer_[length] = 0;
return 0;
}
FMT_FUNC void fmt::WindowsError::init(
FMT_FUNC void WindowsError::init(
int err_code, CStringRef format_str, ArgList args) {
error_code_ = err_code;
MemoryWriter w;
@@ -563,17 +347,17 @@ FMT_FUNC void fmt::WindowsError::init(
base = std::runtime_error(w.str());
}
FMT_FUNC void fmt::internal::format_windows_error(
fmt::Writer &out, int error_code,
fmt::StringRef message) FMT_NOEXCEPT {
FMT_FUNC void internal::format_windows_error(
Writer &out, int error_code, StringRef message) FMT_NOEXCEPT {
FMT_TRY {
MemoryBuffer<wchar_t, INLINE_BUFFER_SIZE> buffer;
buffer.resize(INLINE_BUFFER_SIZE);
for (;;) {
wchar_t *system_message = &buffer[0];
int result = FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
0, error_code, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
system_message, static_cast<uint32_t>(buffer.size()), 0);
int result = FormatMessageW(
FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
FMT_NULL, error_code, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
system_message, static_cast<uint32_t>(buffer.size()), FMT_NULL);
if (result != 0) {
UTF16ToUTF8 utf8_message;
if (utf8_message.convert(system_message) == ERROR_SUCCESS) {
@@ -592,12 +376,11 @@ FMT_FUNC void fmt::internal::format_windows_error(
#endif // FMT_USE_WINDOWS_H
FMT_FUNC void fmt::internal::format_system_error(
fmt::Writer &out, int error_code,
fmt::StringRef message) FMT_NOEXCEPT {
FMT_FUNC void format_system_error(
Writer &out, int error_code, StringRef message) FMT_NOEXCEPT {
FMT_TRY {
MemoryBuffer<char, INLINE_BUFFER_SIZE> buffer;
buffer.resize(INLINE_BUFFER_SIZE);
internal::MemoryBuffer<char, internal::INLINE_BUFFER_SIZE> buffer;
buffer.resize(internal::INLINE_BUFFER_SIZE);
for (;;) {
char *system_message = &buffer[0];
int result = safe_strerror(error_code, system_message, buffer.size());
@@ -614,11 +397,11 @@ FMT_FUNC void fmt::internal::format_system_error(
}
template <typename Char>
void fmt::internal::ArgMap<Char>::init(const ArgList &args) {
void internal::ArgMap<Char>::init(const ArgList &args) {
if (!map_.empty())
return;
typedef internal::NamedArg<Char> NamedArg;
const NamedArg *named_arg = 0;
const NamedArg *named_arg = FMT_NULL;
bool use_values =
args.type(ArgList::MAX_PACKED_ARGS - 1) == internal::Arg::NONE;
if (use_values) {
@@ -659,18 +442,18 @@ void fmt::internal::ArgMap<Char>::init(const ArgList &args) {
}
template <typename Char>
void fmt::internal::FixedBuffer<Char>::grow(std::size_t) {
void internal::FixedBuffer<Char>::grow(std::size_t) {
FMT_THROW(std::runtime_error("buffer overflow"));
}
FMT_FUNC Arg fmt::internal::FormatterBase::do_get_arg(
FMT_FUNC internal::Arg internal::FormatterBase::do_get_arg(
unsigned arg_index, const char *&error) {
Arg arg = args_[arg_index];
internal::Arg arg = args_[arg_index];
switch (arg.type) {
case Arg::NONE:
case internal::Arg::NONE:
error = "argument index out of range";
break;
case Arg::NAMED_ARG:
case internal::Arg::NAMED_ARG:
arg = *static_cast<const internal::Arg*>(arg.pointer);
break;
default:
@@ -679,203 +462,31 @@ FMT_FUNC Arg fmt::internal::FormatterBase::do_get_arg(
return arg;
}
template <typename Char>
void fmt::internal::PrintfFormatter<Char>::parse_flags(
FormatSpec &spec, const Char *&s) {
for (;;) {
switch (*s++) {
case '-':
spec.align_ = ALIGN_LEFT;
break;
case '+':
spec.flags_ |= SIGN_FLAG | PLUS_FLAG;
break;
case '0':
spec.fill_ = '0';
break;
case ' ':
spec.flags_ |= SIGN_FLAG;
break;
case '#':
spec.flags_ |= HASH_FLAG;
break;
default:
--s;
return;
}
}
}
template <typename Char>
Arg fmt::internal::PrintfFormatter<Char>::get_arg(
const Char *s, unsigned arg_index) {
(void)s;
const char *error = 0;
Arg arg = arg_index == UINT_MAX ?
next_arg(error) : FormatterBase::get_arg(arg_index - 1, error);
if (error)
FMT_THROW(FormatError(!*s ? "invalid format string" : error));
return arg;
}
template <typename Char>
unsigned fmt::internal::PrintfFormatter<Char>::parse_header(
const Char *&s, FormatSpec &spec) {
unsigned arg_index = UINT_MAX;
Char c = *s;
if (c >= '0' && c <= '9') {
// Parse an argument index (if followed by '$') or a width possibly
// preceded with '0' flag(s).
unsigned value = parse_nonnegative_int(s);
if (*s == '$') { // value is an argument index
++s;
arg_index = value;
} else {
if (c == '0')
spec.fill_ = '0';
if (value != 0) {
// Nonzero value means that we parsed width and don't need to
// parse it or flags again, so return now.
spec.width_ = value;
return arg_index;
}
}
}
parse_flags(spec, s);
// Parse width.
if (*s >= '0' && *s <= '9') {
spec.width_ = parse_nonnegative_int(s);
} else if (*s == '*') {
++s;
spec.width_ = WidthHandler(spec).visit(get_arg(s));
}
return arg_index;
}
template <typename Char>
void fmt::internal::PrintfFormatter<Char>::format(
BasicWriter<Char> &writer, BasicCStringRef<Char> format_str) {
const Char *start = format_str.c_str();
const Char *s = start;
while (*s) {
Char c = *s++;
if (c != '%') continue;
if (*s == c) {
write(writer, start, s);
start = ++s;
continue;
}
write(writer, start, s - 1);
FormatSpec spec;
spec.align_ = ALIGN_RIGHT;
// Parse argument index, flags and width.
unsigned arg_index = parse_header(s, spec);
// Parse precision.
if (*s == '.') {
++s;
if ('0' <= *s && *s <= '9') {
spec.precision_ = static_cast<int>(parse_nonnegative_int(s));
} else if (*s == '*') {
++s;
spec.precision_ = PrecisionHandler().visit(get_arg(s));
}
}
Arg arg = get_arg(s, arg_index);
if (spec.flag(HASH_FLAG) && IsZeroInt().visit(arg))
spec.flags_ &= ~to_unsigned<int>(HASH_FLAG);
if (spec.fill_ == '0') {
if (arg.type <= Arg::LAST_NUMERIC_TYPE)
spec.align_ = ALIGN_NUMERIC;
else
spec.fill_ = ' '; // Ignore '0' flag for non-numeric types.
}
// Parse length and convert the argument to the required type.
switch (*s++) {
case 'h':
if (*s == 'h')
ArgConverter<signed char>(arg, *++s).visit(arg);
else
ArgConverter<short>(arg, *s).visit(arg);
break;
case 'l':
if (*s == 'l')
ArgConverter<fmt::LongLong>(arg, *++s).visit(arg);
else
ArgConverter<long>(arg, *s).visit(arg);
break;
case 'j':
ArgConverter<intmax_t>(arg, *s).visit(arg);
break;
case 'z':
ArgConverter<std::size_t>(arg, *s).visit(arg);
break;
case 't':
ArgConverter<std::ptrdiff_t>(arg, *s).visit(arg);
break;
case 'L':
// printf produces garbage when 'L' is omitted for long double, no
// need to do the same.
break;
default:
--s;
ArgConverter<void>(arg, *s).visit(arg);
}
// Parse type.
if (!*s)
FMT_THROW(FormatError("invalid format string"));
spec.type_ = static_cast<char>(*s++);
if (arg.type <= Arg::LAST_INTEGER_TYPE) {
// Normalize type.
switch (spec.type_) {
case 'i': case 'u':
spec.type_ = 'd';
break;
case 'c':
// TODO: handle wchar_t
CharConverter(arg).visit(arg);
break;
}
}
start = s;
// Format argument.
internal::PrintfArgFormatter<Char>(writer, spec).visit(arg);
}
write(writer, start, s);
}
FMT_FUNC void fmt::report_system_error(
FMT_FUNC void report_system_error(
int error_code, fmt::StringRef message) FMT_NOEXCEPT {
// 'fmt::' is for bcc32.
fmt::report_error(internal::format_system_error, error_code, message);
report_error(format_system_error, error_code, message);
}
#if FMT_USE_WINDOWS_H
FMT_FUNC void fmt::report_windows_error(
FMT_FUNC void report_windows_error(
int error_code, fmt::StringRef message) FMT_NOEXCEPT {
// 'fmt::' is for bcc32.
fmt::report_error(internal::format_windows_error, error_code, message);
report_error(internal::format_windows_error, error_code, message);
}
#endif
FMT_FUNC void fmt::print(std::FILE *f, CStringRef format_str, ArgList args) {
FMT_FUNC void print(std::FILE *f, CStringRef format_str, ArgList args) {
MemoryWriter w;
w.write(format_str, args);
std::fwrite(w.data(), 1, w.size(), f);
}
FMT_FUNC void fmt::print(CStringRef format_str, ArgList args) {
FMT_FUNC void print(CStringRef format_str, ArgList args) {
print(stdout, format_str, args);
}
FMT_FUNC void fmt::print_colored(Color c, CStringRef format, ArgList args) {
FMT_FUNC void print_colored(Color c, CStringRef format, ArgList args) {
char escape[] = "\x1b[30m";
escape[3] = static_cast<char>('0' + c);
std::fputs(escape, stdout);
@@ -883,53 +494,42 @@ FMT_FUNC void fmt::print_colored(Color c, CStringRef format, ArgList args) {
std::fputs(RESET_COLOR, stdout);
}
FMT_FUNC int fmt::fprintf(std::FILE *f, CStringRef format, ArgList args) {
MemoryWriter w;
printf(w, format, args);
std::size_t size = w.size();
return std::fwrite(w.data(), 1, size, f) < size ? -1 : static_cast<int>(size);
}
#ifndef FMT_HEADER_ONLY
template struct fmt::internal::BasicData<void>;
template struct internal::BasicData<void>;
// Explicit instantiations for char.
template void fmt::internal::FixedBuffer<char>::grow(std::size_t);
template void internal::FixedBuffer<char>::grow(std::size_t);
template void fmt::internal::ArgMap<char>::init(const fmt::ArgList &args);
template void internal::ArgMap<char>::init(const ArgList &args);
template void fmt::internal::PrintfFormatter<char>::format(
BasicWriter<char> &writer, CStringRef format);
template int fmt::internal::CharTraits<char>::format_float(
template FMT_API int internal::CharTraits<char>::format_float(
char *buffer, std::size_t size, const char *format,
unsigned width, int precision, double value);
template int fmt::internal::CharTraits<char>::format_float(
template FMT_API int internal::CharTraits<char>::format_float(
char *buffer, std::size_t size, const char *format,
unsigned width, int precision, long double value);
// Explicit instantiations for wchar_t.
template void fmt::internal::FixedBuffer<wchar_t>::grow(std::size_t);
template void internal::FixedBuffer<wchar_t>::grow(std::size_t);
template void fmt::internal::ArgMap<wchar_t>::init(const fmt::ArgList &args);
template void internal::ArgMap<wchar_t>::init(const ArgList &args);
template void fmt::internal::PrintfFormatter<wchar_t>::format(
BasicWriter<wchar_t> &writer, WCStringRef format);
template int fmt::internal::CharTraits<wchar_t>::format_float(
template FMT_API int internal::CharTraits<wchar_t>::format_float(
wchar_t *buffer, std::size_t size, const wchar_t *format,
unsigned width, int precision, double value);
template int fmt::internal::CharTraits<wchar_t>::format_float(
template FMT_API int internal::CharTraits<wchar_t>::format_float(
wchar_t *buffer, std::size_t size, const wchar_t *format,
unsigned width, int precision, long double value);
#endif // FMT_HEADER_ONLY
} // namespace fmt
#ifdef _MSC_VER
# pragma warning(pop)
#endif
+409 -229
View File
File diff suppressed because it is too large Load Diff
+4 -30
View File
@@ -4,34 +4,15 @@
Copyright (c) 2012 - 2016, 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.
For the license information refer to format.h.
*/
#include "ostream.h"
namespace fmt {
namespace {
// Write the content of w to os.
void write(std::ostream &os, Writer &w) {
namespace internal {
FMT_FUNC void write(std::ostream &os, Writer &w) {
const char *data = w.data();
typedef internal::MakeUnsigned<std::streamsize>::Type UnsignedStreamSize;
UnsignedStreamSize size = w.size();
@@ -49,13 +30,6 @@ void write(std::ostream &os, Writer &w) {
FMT_FUNC void print(std::ostream &os, CStringRef format_str, ArgList args) {
MemoryWriter w;
w.write(format_str, args);
write(os, w);
}
FMT_FUNC int fprintf(std::ostream &os, CStringRef format, ArgList args) {
MemoryWriter w;
printf(w, format, args);
write(os, w);
return static_cast<int>(w.size());
internal::write(os, w);
}
} // namespace fmt
+22 -50
View File
@@ -4,25 +4,7 @@
Copyright (c) 2012 - 2016, 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.
For the license information refer to format.h.
*/
#ifndef FMT_OSTREAM_H_
@@ -42,28 +24,27 @@ class FormatBuf : public std::basic_streambuf<Char> {
typedef typename std::basic_streambuf<Char>::traits_type traits_type;
Buffer<Char> &buffer_;
Char *start_;
public:
FormatBuf(Buffer<Char> &buffer) : buffer_(buffer), start_(&buffer[0]) {
this->setp(start_, start_ + buffer_.capacity());
}
FormatBuf(Buffer<Char> &buffer) : buffer_(buffer) {}
int_type overflow(int_type ch = traits_type::eof()) {
if (!traits_type::eq_int_type(ch, traits_type::eof())) {
size_t buf_size = size();
buffer_.resize(buf_size);
buffer_.reserve(buf_size * 2);
protected:
// The put-area is actually always empty. This makes the implementation
// simpler and has the advantage that the streambuf and the buffer are always
// in sync and sputc never writes into uninitialized memory. The obvious
// disadvantage is that each call to sputc always results in a (virtual) call
// to overflow. There is no disadvantage here for sputn since this always
// results in a call to xsputn.
start_ = &buffer_[0];
start_[buf_size] = traits_type::to_char_type(ch);
this->setp(start_+ buf_size + 1, start_ + buf_size * 2);
}
int_type overflow(int_type ch = traits_type::eof()) FMT_OVERRIDE {
if (!traits_type::eq_int_type(ch, traits_type::eof()))
buffer_.push_back(static_cast<Char>(ch));
return ch;
}
size_t size() const {
return to_unsigned(this->pptr() - start_);
std::streamsize xsputn(const Char *s, std::streamsize count) FMT_OVERRIDE {
buffer_.append(s, s + count);
return count;
}
};
@@ -84,19 +65,22 @@ struct ConvertToIntImpl<T, true> {
value = sizeof(convert(get<DummyStream>() << get<T>())) == sizeof(No)
};
};
// Write the content of w to os.
FMT_API void write(std::ostream &os, Writer &w);
} // namespace internal
// Formats a value.
template <typename Char, typename ArgFormatter, typename T>
void format(BasicFormatter<Char, ArgFormatter> &f,
const Char *&format_str, const T &value) {
template <typename Char, typename ArgFormatter_, typename T>
void format_arg(BasicFormatter<Char, ArgFormatter_> &f,
const Char *&format_str, const T &value) {
internal::MemoryBuffer<Char, internal::INLINE_BUFFER_SIZE> buffer;
internal::FormatBuf<Char> format_buf(buffer);
std::basic_ostream<Char> output(&format_buf);
output << value;
BasicStringRef<Char> str(&buffer[0], format_buf.size());
BasicStringRef<Char> str(&buffer[0], buffer.size());
typedef internal::MakeArg< BasicFormatter<Char> > MakeArg;
format_str = f.format(format_str, MakeArg(str));
}
@@ -112,18 +96,6 @@ void format(BasicFormatter<Char, ArgFormatter> &f,
*/
FMT_API void print(std::ostream &os, CStringRef format_str, ArgList args);
FMT_VARIADIC(void, print, std::ostream &, CStringRef)
/**
\rst
Prints formatted data to the stream *os*.
**Example**::
fprintf(cerr, "Don't %s!", "panic");
\endrst
*/
FMT_API int fprintf(std::ostream &os, CStringRef format_str, ArgList args);
FMT_VARIADIC(int, fprintf, std::ostream &, CStringRef)
} // namespace fmt
#ifdef FMT_HEADER_ONLY
+21 -36
View File
@@ -1,28 +1,10 @@
/*
A C++ interface to POSIX functions.
Copyright (c) 2014 - 2016, Victor Zverovich
Copyright (c) 2012 - 2016, 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.
For the license information refer to format.h.
*/
// Disable bogus MSVC warnings.
@@ -39,6 +21,9 @@
#ifndef _WIN32
# include <unistd.h>
#else
# ifndef WIN32_LEAN_AND_MEAN
# define WIN32_LEAN_AND_MEAN
# endif
# include <windows.h>
# include <io.h>
@@ -90,16 +75,16 @@ fmt::BufferedFile::BufferedFile(
fmt::CStringRef filename, fmt::CStringRef mode) {
FMT_RETRY_VAL(file_, FMT_SYSTEM(fopen(filename.c_str(), mode.c_str())), 0);
if (!file_)
throw SystemError(errno, "cannot open file {}", filename);
FMT_THROW(SystemError(errno, "cannot open file {}", filename));
}
void fmt::BufferedFile::close() {
if (!file_)
return;
int result = FMT_SYSTEM(fclose(file_));
file_ = 0;
file_ = FMT_NULL;
if (result != 0)
throw SystemError(errno, "cannot close file");
FMT_THROW(SystemError(errno, "cannot close file"));
}
// A macro used to prevent expansion of fileno on broken versions of MinGW.
@@ -108,7 +93,7 @@ void fmt::BufferedFile::close() {
int fmt::BufferedFile::fileno() const {
int fd = FMT_POSIX_CALL(fileno FMT_ARGS(file_));
if (fd == -1)
throw SystemError(errno, "cannot get file descriptor");
FMT_THROW(SystemError(errno, "cannot get file descriptor"));
return fd;
}
@@ -121,7 +106,7 @@ fmt::File::File(fmt::CStringRef path, int oflag) {
FMT_RETRY(fd_, FMT_POSIX_CALL(open(path.c_str(), oflag, mode)));
#endif
if (fd_ == -1)
throw SystemError(errno, "cannot open file {}", path);
FMT_THROW(SystemError(errno, "cannot open file {}", path));
}
fmt::File::~File() FMT_NOEXCEPT {
@@ -139,7 +124,7 @@ void fmt::File::close() {
int result = FMT_POSIX_CALL(close(fd_));
fd_ = -1;
if (result != 0)
throw SystemError(errno, "cannot close file");
FMT_THROW(SystemError(errno, "cannot close file"));
}
fmt::LongLong fmt::File::size() const {
@@ -153,7 +138,7 @@ fmt::LongLong fmt::File::size() const {
if (size_lower == INVALID_FILE_SIZE) {
DWORD error = GetLastError();
if (error != NO_ERROR)
throw WindowsError(GetLastError(), "cannot get file size");
FMT_THROW(WindowsError(GetLastError(), "cannot get file size"));
}
fmt::ULongLong long_size = size_upper;
return (long_size << sizeof(DWORD) * CHAR_BIT) | size_lower;
@@ -161,7 +146,7 @@ fmt::LongLong fmt::File::size() const {
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_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;
@@ -172,7 +157,7 @@ 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");
FMT_THROW(SystemError(errno, "cannot read from file"));
return internal::to_unsigned(result);
}
@@ -180,7 +165,7 @@ 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");
FMT_THROW(SystemError(errno, "cannot write to file"));
return internal::to_unsigned(result);
}
@@ -189,7 +174,7 @@ fmt::File fmt::File::dup(int fd) {
// 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);
FMT_THROW(SystemError(errno, "cannot duplicate file descriptor {}", fd));
return File(new_fd);
}
@@ -197,8 +182,8 @@ 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);
FMT_THROW(SystemError(errno,
"cannot duplicate file descriptor {} to {}", fd_, fd));
}
}
@@ -225,7 +210,7 @@ void fmt::File::pipe(File &read_end, File &write_end) {
int result = FMT_POSIX_CALL(pipe(fds));
#endif
if (result != 0)
throw SystemError(errno, "cannot create pipe");
FMT_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]);
@@ -236,7 +221,7 @@ 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");
FMT_THROW(SystemError(errno, "cannot associate stream with file descriptor"));
BufferedFile file(f);
fd_ = -1;
return file;
@@ -250,7 +235,7 @@ long fmt::getpagesize() {
#else
long size = FMT_POSIX_CALL(sysconf(_SC_PAGESIZE));
if (size < 0)
throw SystemError(errno, "cannot get memory page size");
FMT_THROW(SystemError(errno, "cannot get memory page size"));
return size;
#endif
}
+30 -66
View File
@@ -1,34 +1,16 @@
/*
A C++ interface to POSIX functions.
Copyright (c) 2014 - 2016, Victor Zverovich
Copyright (c) 2012 - 2016, 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.
For the license information refer to format.h.
*/
#ifndef FMT_POSIX_H_
#define FMT_POSIX_H_
#ifdef __MINGW32__
#if defined(__MINGW32__) || defined(__CYGWIN__)
// Workaround MinGW bug https://sourceforge.net/p/mingw/bugs/2024/.
# undef __STRICT_ANSI__
#endif
@@ -41,7 +23,7 @@
#include <cstddef>
#ifdef __APPLE__
#if defined __APPLE__ || defined(__FreeBSD__)
# include <xlocale.h> // for LC_NUMERIC_MASK on OS X
#endif
@@ -69,25 +51,6 @@
# endif
#endif
#if FMT_GCC_VERSION >= 407
# define FMT_UNUSED __attribute__((unused))
#else
# define FMT_UNUSED
#endif
#ifndef FMT_USE_STATIC_ASSERT
# define FMT_USE_STATIC_ASSERT 0
#endif
#if FMT_USE_STATIC_ASSERT || FMT_HAS_FEATURE(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
@@ -125,10 +88,10 @@ class BufferedFile {
public:
// Constructs a BufferedFile object which doesn't represent any file.
BufferedFile() FMT_NOEXCEPT : file_(0) {}
BufferedFile() FMT_NOEXCEPT : file_(FMT_NULL) {}
// Destroys the object closing the file it represents if any.
~BufferedFile() FMT_NOEXCEPT;
FMT_API ~BufferedFile() FMT_NOEXCEPT;
#if !FMT_USE_RVALUE_REFERENCES
// Emulate a move constructor and a move assignment operator if rvalue
@@ -147,7 +110,7 @@ public:
// A "move constructor" for moving from an lvalue.
BufferedFile(BufferedFile &f) FMT_NOEXCEPT : file_(f.file_) {
f.file_ = 0;
f.file_ = FMT_NULL;
}
// A "move assignment operator" for moving from a temporary.
@@ -161,7 +124,7 @@ public:
BufferedFile &operator=(BufferedFile &other) {
close();
file_ = other.file_;
other.file_ = 0;
other.file_ = FMT_NULL;
return *this;
}
@@ -169,7 +132,7 @@ public:
// BufferedFile file = BufferedFile(...);
operator Proxy() FMT_NOEXCEPT {
Proxy p = {file_};
file_ = 0;
file_ = FMT_NULL;
return p;
}
@@ -179,29 +142,29 @@ public:
public:
BufferedFile(BufferedFile &&other) FMT_NOEXCEPT : file_(other.file_) {
other.file_ = 0;
other.file_ = FMT_NULL;
}
BufferedFile& operator=(BufferedFile &&other) {
close();
file_ = other.file_;
other.file_ = 0;
other.file_ = FMT_NULL;
return *this;
}
#endif
// Opens a file.
BufferedFile(CStringRef filename, CStringRef mode);
FMT_API BufferedFile(CStringRef filename, CStringRef mode);
// Closes the file.
void close();
FMT_API void close();
// Returns the pointer to a FILE object representing this file.
FILE *get() const FMT_NOEXCEPT { return file_; }
// We place parentheses around fileno to workaround a bug in some versions
// of MinGW that define fileno as a macro.
int (fileno)() const;
FMT_API int (fileno)() const;
void print(CStringRef format_str, const ArgList &args) {
fmt::print(file_, format_str, args);
@@ -234,7 +197,7 @@ class File {
File() FMT_NOEXCEPT : fd_(-1) {}
// Opens a file and constructs a File object representing this file.
File(CStringRef path, int oflag);
FMT_API File(CStringRef path, int oflag);
#if !FMT_USE_RVALUE_REFERENCES
// Emulate a move constructor and a move assignment operator if rvalue
@@ -297,49 +260,50 @@ class File {
#endif
// Destroys the object closing the file it represents if any.
~File() FMT_NOEXCEPT;
FMT_API ~File() FMT_NOEXCEPT;
// Returns the file descriptor.
int descriptor() const FMT_NOEXCEPT { return fd_; }
// Closes the file.
void close();
FMT_API void close();
// Returns the file size. The size has signed type for consistency with
// stat::st_size.
LongLong size() const;
FMT_API 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);
FMT_API 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);
FMT_API 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);
FMT_API static File dup(int fd);
// Makes fd be the copy of this file descriptor, closing fd first if
// necessary.
void dup2(int fd);
FMT_API 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;
FMT_API 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);
FMT_API 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);
FMT_API BufferedFile fdopen(const char *mode);
};
// Returns the memory page size.
long getpagesize();
#if defined(LC_NUMERIC_MASK) || defined(_MSC_VER)
#if (defined(LC_NUMERIC_MASK) || defined(_MSC_VER)) && \
!defined(__ANDROID__) && !defined(__CYGWIN__)
# define FMT_LOCALE
#endif
@@ -372,9 +336,9 @@ class Locale {
public:
typedef locale_t Type;
Locale() : locale_(newlocale(LC_NUMERIC_MASK, "C", NULL)) {
Locale() : locale_(newlocale(LC_NUMERIC_MASK, "C", FMT_NULL)) {
if (!locale_)
throw fmt::SystemError(errno, "cannot create locale");
FMT_THROW(fmt::SystemError(errno, "cannot create locale"));
}
~Locale() { freelocale(locale_); }
@@ -383,7 +347,7 @@ class Locale {
// Converts string to floating-point number and advances str past the end
// of the parsed input.
double strtod(const char *&str) const {
char *end = 0;
char *end = FMT_NULL;
double result = strtod_l(str, &end, locale_);
str = end;
return result;
+32
View File
@@ -0,0 +1,32 @@
/*
Formatting library for C++
Copyright (c) 2012 - 2016, Victor Zverovich
All rights reserved.
For the license information refer to format.h.
*/
#include "format.h"
#include "printf.h"
namespace fmt {
template <typename Char>
void printf(BasicWriter<Char> &w, BasicCStringRef<Char> format, ArgList args);
FMT_FUNC int fprintf(std::FILE *f, CStringRef format, ArgList args) {
MemoryWriter w;
printf(w, format, args);
std::size_t size = w.size();
return std::fwrite(w.data(), 1, size, f) < size ? -1 : static_cast<int>(size);
}
#ifndef FMT_HEADER_ONLY
template void PrintfFormatter<char>::format(CStringRef format);
template void PrintfFormatter<wchar_t>::format(WCStringRef format);
#endif // FMT_HEADER_ONLY
} // namespace fmt
+603
View File
@@ -0,0 +1,603 @@
/*
Formatting library for C++
Copyright (c) 2012 - 2016, Victor Zverovich
All rights reserved.
For the license information refer to format.h.
*/
#ifndef FMT_PRINTF_H_
#define FMT_PRINTF_H_
#include <algorithm> // std::fill_n
#include <limits> // std::numeric_limits
#include "ostream.h"
namespace fmt {
namespace internal {
// Checks if a value fits in int - used to avoid warnings about comparing
// signed and unsigned integers.
template <bool IsSigned>
struct IntChecker {
template <typename T>
static bool fits_in_int(T value) {
unsigned max = std::numeric_limits<int>::max();
return value <= max;
}
static bool fits_in_int(bool) { return true; }
};
template <>
struct IntChecker<true> {
template <typename T>
static bool fits_in_int(T value) {
return value >= std::numeric_limits<int>::min() &&
value <= std::numeric_limits<int>::max();
}
static bool fits_in_int(int) { return true; }
};
class PrecisionHandler : public ArgVisitor<PrecisionHandler, int> {
public:
void report_unhandled_arg() {
FMT_THROW(FormatError("precision is not integer"));
}
template <typename T>
int visit_any_int(T value) {
if (!IntChecker<std::numeric_limits<T>::is_signed>::fits_in_int(value))
FMT_THROW(FormatError("number is too big"));
return static_cast<int>(value);
}
};
// IsZeroInt::visit(arg) returns true iff arg is a zero integer.
class IsZeroInt : public ArgVisitor<IsZeroInt, bool> {
public:
template <typename T>
bool visit_any_int(T value) { return value == 0; }
};
// returns the default type for format specific "%s"
class DefaultType : public ArgVisitor<DefaultType, char> {
public:
char visit_char(int) { return 'c'; }
char visit_bool(bool) { return 's'; }
char visit_pointer(const void *) { return 'p'; }
template <typename T>
char visit_any_int(T) { return 'd'; }
template <typename T>
char visit_any_double(T) { return 'g'; }
char visit_unhandled_arg() { return 's'; }
};
template <typename T, typename U>
struct is_same {
enum { value = 0 };
};
template <typename T>
struct is_same<T, T> {
enum { value = 1 };
};
// An argument visitor that converts an integer argument to T for printf,
// if T is an integral type. If T is void, the argument is converted to
// corresponding signed or unsigned type depending on the type specifier:
// 'd' and 'i' - signed, other - unsigned)
template <typename T = void>
class ArgConverter : public ArgVisitor<ArgConverter<T>, void> {
private:
internal::Arg &arg_;
wchar_t type_;
FMT_DISALLOW_COPY_AND_ASSIGN(ArgConverter);
public:
ArgConverter(internal::Arg &arg, wchar_t type)
: arg_(arg), type_(type) {}
void visit_bool(bool value) {
if (type_ != 's')
visit_any_int(value);
}
void visit_char(char value) {
if (type_ != 's')
visit_any_int(value);
}
template <typename U>
void visit_any_int(U value) {
bool is_signed = type_ == 'd' || type_ == 'i';
if (type_ == 's') {
is_signed = std::numeric_limits<U>::is_signed;
}
using internal::Arg;
typedef typename internal::Conditional<
is_same<T, void>::value, U, T>::type TargetType;
if (sizeof(TargetType) <= sizeof(int)) {
// Extra casts are used to silence warnings.
if (is_signed) {
arg_.type = Arg::INT;
arg_.int_value = static_cast<int>(static_cast<TargetType>(value));
} else {
arg_.type = Arg::UINT;
typedef typename internal::MakeUnsigned<TargetType>::Type Unsigned;
arg_.uint_value = static_cast<unsigned>(static_cast<Unsigned>(value));
}
} else {
if (is_signed) {
arg_.type = Arg::LONG_LONG;
// glibc's printf doesn't sign extend arguments of smaller types:
// std::printf("%lld", -42); // prints "4294967254"
// but we don't have to do the same because it's a UB.
arg_.long_long_value = static_cast<LongLong>(value);
} else {
arg_.type = Arg::ULONG_LONG;
arg_.ulong_long_value =
static_cast<typename internal::MakeUnsigned<U>::Type>(value);
}
}
}
};
// Converts an integer argument to char for printf.
class CharConverter : public ArgVisitor<CharConverter, void> {
private:
internal::Arg &arg_;
FMT_DISALLOW_COPY_AND_ASSIGN(CharConverter);
public:
explicit CharConverter(internal::Arg &arg) : arg_(arg) {}
template <typename T>
void visit_any_int(T value) {
arg_.type = internal::Arg::CHAR;
arg_.int_value = static_cast<char>(value);
}
};
// Checks if an argument is a valid printf width specifier and sets
// left alignment if it is negative.
class WidthHandler : public ArgVisitor<WidthHandler, unsigned> {
private:
FormatSpec &spec_;
FMT_DISALLOW_COPY_AND_ASSIGN(WidthHandler);
public:
explicit WidthHandler(FormatSpec &spec) : spec_(spec) {}
void report_unhandled_arg() {
FMT_THROW(FormatError("width is not integer"));
}
template <typename T>
unsigned visit_any_int(T value) {
typedef typename internal::IntTraits<T>::MainType UnsignedType;
UnsignedType width = static_cast<UnsignedType>(value);
if (internal::is_negative(value)) {
spec_.align_ = ALIGN_LEFT;
width = 0 - width;
}
unsigned int_max = std::numeric_limits<int>::max();
if (width > int_max)
FMT_THROW(FormatError("number is too big"));
return static_cast<unsigned>(width);
}
};
} // namespace internal
/**
\rst
A ``printf`` argument formatter based on the `curiously recurring template
pattern <http://en.wikipedia.org/wiki/Curiously_recurring_template_pattern>`_.
To use `~fmt::BasicPrintfArgFormatter` define a subclass that implements some
or all of the visit methods with the same signatures as the methods in
`~fmt::ArgVisitor`, for example, `~fmt::ArgVisitor::visit_int()`.
Pass the subclass as the *Impl* template parameter. When a formatting
function processes an argument, it will dispatch to a visit method
specific to the argument type. For example, if the argument type is
``double`` then the `~fmt::ArgVisitor::visit_double()` method of a subclass
will be called. If the subclass doesn't contain a method with this signature,
then a corresponding method of `~fmt::BasicPrintfArgFormatter` or its
superclass will be called.
\endrst
*/
template <typename Impl, typename Char, typename Spec>
class BasicPrintfArgFormatter :
public internal::ArgFormatterBase<Impl, Char, Spec> {
private:
void write_null_pointer() {
this->spec().type_ = 0;
this->write("(nil)");
}
typedef internal::ArgFormatterBase<Impl, Char, Spec> Base;
public:
/**
\rst
Constructs an argument formatter object.
*writer* is a reference to the output writer and *spec* contains format
specifier information for standard argument types.
\endrst
*/
BasicPrintfArgFormatter(BasicWriter<Char> &w, Spec &s)
: internal::ArgFormatterBase<Impl, Char, Spec>(w, s) {}
/** Formats an argument of type ``bool``. */
void visit_bool(bool value) {
Spec &fmt_spec = this->spec();
if (fmt_spec.type_ != 's')
return this->visit_any_int(value);
fmt_spec.type_ = 0;
this->write(value);
}
/** Formats a character. */
void visit_char(int value) {
const Spec &fmt_spec = this->spec();
BasicWriter<Char> &w = this->writer();
if (fmt_spec.type_ && fmt_spec.type_ != 'c')
w.write_int(value, fmt_spec);
typedef typename BasicWriter<Char>::CharPtr CharPtr;
CharPtr out = CharPtr();
if (fmt_spec.width_ > 1) {
Char fill = ' ';
out = w.grow_buffer(fmt_spec.width_);
if (fmt_spec.align_ != ALIGN_LEFT) {
std::fill_n(out, fmt_spec.width_ - 1, fill);
out += fmt_spec.width_ - 1;
} else {
std::fill_n(out + 1, fmt_spec.width_ - 1, fill);
}
} else {
out = w.grow_buffer(1);
}
*out = static_cast<Char>(value);
}
/** Formats a null-terminated C string. */
void visit_cstring(const char *value) {
if (value)
Base::visit_cstring(value);
else if (this->spec().type_ == 'p')
write_null_pointer();
else
this->write("(null)");
}
/** Formats a pointer. */
void visit_pointer(const void *value) {
if (value)
return Base::visit_pointer(value);
this->spec().type_ = 0;
write_null_pointer();
}
/** Formats an argument of a custom (user-defined) type. */
void visit_custom(internal::Arg::CustomValue c) {
BasicFormatter<Char> formatter(ArgList(), this->writer());
const Char format_str[] = {'}', 0};
const Char *format = format_str;
c.format(&formatter, c.value, &format);
}
};
/** The default printf argument formatter. */
template <typename Char>
class PrintfArgFormatter :
public BasicPrintfArgFormatter<PrintfArgFormatter<Char>, Char, FormatSpec> {
public:
/** Constructs an argument formatter object. */
PrintfArgFormatter(BasicWriter<Char> &w, FormatSpec &s)
: BasicPrintfArgFormatter<PrintfArgFormatter<Char>, Char, FormatSpec>(w, s) {}
};
/** This template formats data and writes the output to a writer. */
template <typename Char, typename ArgFormatter = PrintfArgFormatter<Char> >
class PrintfFormatter : private internal::FormatterBase {
private:
BasicWriter<Char> &writer_;
void parse_flags(FormatSpec &spec, const Char *&s);
// Returns the argument with specified index or, if arg_index is equal
// to the maximum unsigned value, the next argument.
internal::Arg get_arg(
const Char *s,
unsigned arg_index = (std::numeric_limits<unsigned>::max)());
// Parses argument index, flags and width and returns the argument index.
unsigned parse_header(const Char *&s, FormatSpec &spec);
public:
/**
\rst
Constructs a ``PrintfFormatter`` object. References to the arguments and
the writer are stored in the formatter object so make sure they have
appropriate lifetimes.
\endrst
*/
explicit PrintfFormatter(const ArgList &al, BasicWriter<Char> &w)
: FormatterBase(al), writer_(w) {}
/** Formats stored arguments and writes the output to the writer. */
void format(BasicCStringRef<Char> format_str);
};
template <typename Char, typename AF>
void PrintfFormatter<Char, AF>::parse_flags(FormatSpec &spec, const Char *&s) {
for (;;) {
switch (*s++) {
case '-':
spec.align_ = ALIGN_LEFT;
break;
case '+':
spec.flags_ |= SIGN_FLAG | PLUS_FLAG;
break;
case '0':
spec.fill_ = '0';
break;
case ' ':
spec.flags_ |= SIGN_FLAG;
break;
case '#':
spec.flags_ |= HASH_FLAG;
break;
default:
--s;
return;
}
}
}
template <typename Char, typename AF>
internal::Arg PrintfFormatter<Char, AF>::get_arg(const Char *s,
unsigned arg_index) {
(void)s;
const char *error = FMT_NULL;
internal::Arg arg = arg_index == std::numeric_limits<unsigned>::max() ?
next_arg(error) : FormatterBase::get_arg(arg_index - 1, error);
if (error)
FMT_THROW(FormatError(!*s ? "invalid format string" : error));
return arg;
}
template <typename Char, typename AF>
unsigned PrintfFormatter<Char, AF>::parse_header(
const Char *&s, FormatSpec &spec) {
unsigned arg_index = std::numeric_limits<unsigned>::max();
Char c = *s;
if (c >= '0' && c <= '9') {
// Parse an argument index (if followed by '$') or a width possibly
// preceded with '0' flag(s).
unsigned value = internal::parse_nonnegative_int(s);
if (*s == '$') { // value is an argument index
++s;
arg_index = value;
} else {
if (c == '0')
spec.fill_ = '0';
if (value != 0) {
// Nonzero value means that we parsed width and don't need to
// parse it or flags again, so return now.
spec.width_ = value;
return arg_index;
}
}
}
parse_flags(spec, s);
// Parse width.
if (*s >= '0' && *s <= '9') {
spec.width_ = internal::parse_nonnegative_int(s);
} else if (*s == '*') {
++s;
spec.width_ = internal::WidthHandler(spec).visit(get_arg(s));
}
return arg_index;
}
template <typename Char, typename AF>
void PrintfFormatter<Char, AF>::format(BasicCStringRef<Char> format_str) {
const Char *start = format_str.c_str();
const Char *s = start;
while (*s) {
Char c = *s++;
if (c != '%') continue;
if (*s == c) {
write(writer_, start, s);
start = ++s;
continue;
}
write(writer_, start, s - 1);
FormatSpec spec;
spec.align_ = ALIGN_RIGHT;
// Parse argument index, flags and width.
unsigned arg_index = parse_header(s, spec);
// Parse precision.
if (*s == '.') {
++s;
if ('0' <= *s && *s <= '9') {
spec.precision_ = static_cast<int>(internal::parse_nonnegative_int(s));
} else if (*s == '*') {
++s;
spec.precision_ = internal::PrecisionHandler().visit(get_arg(s));
} else {
spec.precision_ = 0;
}
}
using internal::Arg;
Arg arg = get_arg(s, arg_index);
if (spec.flag(HASH_FLAG) && internal::IsZeroInt().visit(arg))
spec.flags_ &= ~internal::to_unsigned<int>(HASH_FLAG);
if (spec.fill_ == '0') {
if (arg.type <= Arg::LAST_NUMERIC_TYPE)
spec.align_ = ALIGN_NUMERIC;
else
spec.fill_ = ' '; // Ignore '0' flag for non-numeric types.
}
// Parse length and convert the argument to the required type.
using internal::ArgConverter;
switch (*s++) {
case 'h':
if (*s == 'h')
ArgConverter<signed char>(arg, *++s).visit(arg);
else
ArgConverter<short>(arg, *s).visit(arg);
break;
case 'l':
if (*s == 'l')
ArgConverter<fmt::LongLong>(arg, *++s).visit(arg);
else
ArgConverter<long>(arg, *s).visit(arg);
break;
case 'j':
ArgConverter<intmax_t>(arg, *s).visit(arg);
break;
case 'z':
ArgConverter<std::size_t>(arg, *s).visit(arg);
break;
case 't':
ArgConverter<std::ptrdiff_t>(arg, *s).visit(arg);
break;
case 'L':
// printf produces garbage when 'L' is omitted for long double, no
// need to do the same.
break;
default:
--s;
ArgConverter<void>(arg, *s).visit(arg);
}
// Parse type.
if (!*s)
FMT_THROW(FormatError("invalid format string"));
spec.type_ = static_cast<char>(*s++);
if (spec.type_ == 's') {
// set the format type to the default if 's' is specified
spec.type_ = internal::DefaultType().visit(arg);
}
if (arg.type <= Arg::LAST_INTEGER_TYPE) {
// Normalize type.
switch (spec.type_) {
case 'i': case 'u':
spec.type_ = 'd';
break;
case 'c':
// TODO: handle wchar_t
internal::CharConverter(arg).visit(arg);
break;
}
}
start = s;
// Format argument.
AF(writer_, spec).visit(arg);
}
write(writer_, start, s);
}
inline void printf(Writer &w, CStringRef format, ArgList args) {
PrintfFormatter<char>(args, w).format(format);
}
FMT_VARIADIC(void, printf, Writer &, CStringRef)
inline void printf(WWriter &w, WCStringRef format, ArgList args) {
PrintfFormatter<wchar_t>(args, w).format(format);
}
FMT_VARIADIC(void, printf, WWriter &, WCStringRef)
/**
\rst
Formats arguments and returns the result as a string.
**Example**::
std::string message = fmt::sprintf("The answer is %d", 42);
\endrst
*/
inline std::string sprintf(CStringRef format, ArgList args) {
MemoryWriter w;
printf(w, format, args);
return w.str();
}
FMT_VARIADIC(std::string, sprintf, CStringRef)
inline std::wstring sprintf(WCStringRef format, ArgList args) {
WMemoryWriter w;
printf(w, format, args);
return w.str();
}
FMT_VARIADIC_W(std::wstring, sprintf, WCStringRef)
/**
\rst
Prints formatted data to the file *f*.
**Example**::
fmt::fprintf(stderr, "Don't %s!", "panic");
\endrst
*/
FMT_API int fprintf(std::FILE *f, CStringRef format, ArgList args);
FMT_VARIADIC(int, fprintf, std::FILE *, CStringRef)
/**
\rst
Prints formatted data to ``stdout``.
**Example**::
fmt::printf("Elapsed time: %.2f seconds", 1.23);
\endrst
*/
inline int printf(CStringRef format, ArgList args) {
return fprintf(stdout, format, args);
}
FMT_VARIADIC(int, printf, CStringRef)
/**
\rst
Prints formatted data to the stream *os*.
**Example**::
fprintf(cerr, "Don't %s!", "panic");
\endrst
*/
inline int fprintf(std::ostream &os, CStringRef format_str, ArgList args) {
MemoryWriter w;
printf(w, format_str, args);
internal::write(os, w);
return static_cast<int>(w.size());
}
FMT_VARIADIC(int, fprintf, std::ostream &, CStringRef)
} // namespace fmt
#ifdef FMT_HEADER_ONLY
# include "printf.cc"
#endif
#endif // FMT_PRINTF_H_
+126
View File
@@ -0,0 +1,126 @@
/*
Formatting library for C++ - string utilities
Copyright (c) 2012 - 2016, Victor Zverovich
All rights reserved.
For the license information refer to format.h.
*/
#ifndef FMT_STRING_H_
#define FMT_STRING_H_
#include "format.h"
namespace fmt {
namespace internal {
// A buffer that stores data in ``std::basic_string``.
template <typename Char, typename Allocator = std::allocator<Char> >
class StringBuffer : public Buffer<Char> {
public:
typedef std::basic_string<Char, std::char_traits<Char>, Allocator> StringType;
private:
StringType data_;
protected:
virtual void grow(std::size_t size) FMT_OVERRIDE {
data_.resize(size);
this->ptr_ = &data_[0];
this->capacity_ = size;
}
public:
explicit StringBuffer(const Allocator &allocator = Allocator())
: data_(allocator) {}
// Moves the data to ``str`` clearing the buffer.
void move_to(StringType &str) {
data_.resize(this->size_);
str.swap(data_);
this->capacity_ = this->size_ = 0;
this->ptr_ = FMT_NULL;
}
};
} // namespace internal
/**
\rst
This class template provides operations for formatting and writing data
into a character stream. The output is stored in a ``std::basic_string``
that grows dynamically.
You can use one of the following typedefs for common character types
and the standard allocator:
+---------------+----------------------------+
| Type | Definition |
+===============+============================+
| StringWriter | BasicStringWriter<char> |
+---------------+----------------------------+
| WStringWriter | BasicStringWriter<wchar_t> |
+---------------+----------------------------+
**Example**::
StringWriter out;
out << "The answer is " << 42 << "\n";
This will write the following output to the ``out`` object:
.. code-block:: none
The answer is 42
The output can be moved to a ``std::basic_string`` with ``out.move_to()``.
\endrst
*/
template <typename Char, typename Allocator = std::allocator<Char> >
class BasicStringWriter : public BasicWriter<Char> {
private:
internal::StringBuffer<Char, Allocator> buffer_;
public:
/**
\rst
Constructs a :class:`fmt::BasicStringWriter` object.
\endrst
*/
explicit BasicStringWriter(const Allocator &allocator = Allocator())
: BasicWriter<Char>(buffer_), buffer_(allocator) {}
/**
\rst
Moves the buffer content to *str* clearing the buffer.
\endrst
*/
void move_to(std::basic_string<Char, std::char_traits<Char>, Allocator> &str) {
buffer_.move_to(str);
}
};
typedef BasicStringWriter<char> StringWriter;
typedef BasicStringWriter<wchar_t> WStringWriter;
/**
\rst
Converts *value* to ``std::string`` using the default format for type *T*.
**Example**::
#include "fmt/string.h"
std::string answer = fmt::to_string(42);
\endrst
*/
template <typename T>
std::string to_string(const T &value) {
fmt::MemoryWriter w;
w << value;
return w.str();
}
}
#endif // FMT_STRING_H_
+102 -23
View File
@@ -4,37 +4,25 @@
Copyright (c) 2012 - 2016, 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.
For the license information refer to format.h.
*/
#ifndef FMT_TIME_H_
#define FMT_TIME_H_
#include "fmt/format.h"
#include "format.h"
#include <ctime>
#ifdef _MSC_VER
# pragma warning(push)
# pragma warning(disable: 4702) // unreachable code
# pragma warning(disable: 4996) // "deprecated" functions
#endif
namespace fmt {
template <typename ArgFormatter>
void format(BasicFormatter<char, ArgFormatter> &f,
const char *&format_str, const std::tm &tm) {
void format_arg(BasicFormatter<char, ArgFormatter> &f,
const char *&format_str, const std::tm &tm) {
if (*format_str == ':')
++format_str;
const char *end = format_str;
@@ -54,11 +42,102 @@ void format(BasicFormatter<char, ArgFormatter> &f,
buffer.resize(start + count);
break;
}
if (size >= format.size() * 256) {
// If the buffer is 256 times larger than the format string, assume
// that `strftime` gives an empty result. There doesn't seem to be a
// better way to distinguish the two cases:
// https://github.com/fmtlib/fmt/issues/367
break;
}
const std::size_t MIN_GROWTH = 10;
buffer.reserve(buffer.capacity() + size > MIN_GROWTH ? size : MIN_GROWTH);
buffer.reserve(buffer.capacity() + (size > MIN_GROWTH ? size : MIN_GROWTH));
}
format_str = end + 1;
}
namespace internal{
inline Null<> localtime_r(...) { return Null<>(); }
inline Null<> localtime_s(...) { return Null<>(); }
inline Null<> gmtime_r(...) { return Null<>(); }
inline Null<> gmtime_s(...) { return Null<>(); }
}
// Thread-safe replacement for std::localtime
inline std::tm localtime(std::time_t time) {
struct LocalTime {
std::time_t time_;
std::tm tm_;
LocalTime(std::time_t t): time_(t) {}
bool run() {
using namespace fmt::internal;
return handle(localtime_r(&time_, &tm_));
}
bool handle(std::tm *tm) { return tm != FMT_NULL; }
bool handle(internal::Null<>) {
using namespace fmt::internal;
return fallback(localtime_s(&tm_, &time_));
}
bool fallback(int res) { return res == 0; }
bool fallback(internal::Null<>) {
using namespace fmt::internal;
std::tm *tm = std::localtime(&time_);
if (tm) tm_ = *tm;
return tm != FMT_NULL;
}
};
LocalTime lt(time);
if (lt.run())
return lt.tm_;
// Too big time values may be unsupported.
FMT_THROW(fmt::FormatError("time_t value out of range"));
return std::tm();
}
// Thread-safe replacement for std::gmtime
inline std::tm gmtime(std::time_t time) {
struct GMTime {
std::time_t time_;
std::tm tm_;
GMTime(std::time_t t): time_(t) {}
bool run() {
using namespace fmt::internal;
return handle(gmtime_r(&time_, &tm_));
}
bool handle(std::tm *tm) { return tm != FMT_NULL; }
bool handle(internal::Null<>) {
using namespace fmt::internal;
return fallback(gmtime_s(&tm_, &time_));
}
bool fallback(int res) { return res == 0; }
bool fallback(internal::Null<>) {
std::tm *tm = std::gmtime(&time_);
if (tm != FMT_NULL) tm_ = *tm;
return tm != FMT_NULL;
}
};
GMTime gt(time);
if (gt.run())
return gt.tm_;
// Too big time values may be unsupported.
FMT_THROW(fmt::FormatError("time_t value out of range"));
return std::tm();
}
} //namespace fmt
#ifdef _MSC_VER
# pragma warning(pop)
#endif
#endif // FMT_TIME_H_
+16 -15
View File
@@ -10,22 +10,23 @@ platform = os.environ.get('PLATFORM')
path = os.environ['PATH']
cmake_command = ['cmake', '-DFMT_PEDANTIC=ON', '-DCMAKE_BUILD_TYPE=' + config]
if build == 'mingw':
cmake_command.append('-GMinGW Makefiles')
build_command = ['mingw32-make', '-j4']
test_command = ['mingw32-make', 'test']
# Remove the path to Git bin directory from $PATH because it breaks MinGW config.
path = path.replace(r'C:\Program Files (x86)\Git\bin', '')
os.environ['PATH'] = r'C:\MinGW\bin;' + path
cmake_command.append('-GMinGW Makefiles')
build_command = ['mingw32-make', '-j4']
test_command = ['mingw32-make', 'test']
# Remove the path to Git bin directory from $PATH because it breaks
# MinGW config.
path = path.replace(r'C:\Program Files (x86)\Git\bin', '')
os.environ['PATH'] = r'C:\MinGW\bin;' + path
else:
# Add MSBuild 14.0 to PATH as described in
# http://help.appveyor.com/discussions/problems/2229-v140-not-found-on-vs2105rc.
os.environ['PATH'] = r'C:\Program Files (x86)\MSBuild\14.0\Bin;' + path
generator = 'Visual Studio 14 2015'
if platform == 'x64':
generator += ' Win64'
cmake_command.append('-G' + generator)
build_command = ['cmake', '--build', '.', '--config', config, '--', '/m:4']
test_command = ['ctest', '-C', config]
# Add MSBuild 14.0 to PATH as described in
# http://help.appveyor.com/discussions/problems/2229-v140-not-found-on-vs2105rc.
os.environ['PATH'] = r'C:\Program Files (x86)\MSBuild\14.0\Bin;' + path
generator = 'Visual Studio 14 2015'
if platform == 'x64':
generator += ' Win64'
cmake_command.append('-G' + generator)
build_command = ['cmake', '--build', '.', '--config', config, '--', '/m:4']
test_command = ['ctest', '-C', config]
check_call(cmake_command)
check_call(build_command)
+4
View File
@@ -20,3 +20,7 @@ build_script:
on_failure:
- appveyor PushArtifact Testing/Temporary/LastTest.log
- appveyor AddTest test
# Uncomment this to debug AppVeyor failures.
#on_finish:
# - ps: $blockRdp = $true; iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/appveyor/ci/master/scripts/enable-rdp.ps1'))
+13 -1
View File
@@ -20,7 +20,14 @@ if (FMT_USE_CPP11)
check_cxx_source_compiles("
#include <unistd.h>
int main() {}" FMT_CPP11_UNISTD_H)
if (FMT_CPP11_CMATH AND FMT_CPP11_UNISTD_H)
# Check if snprintf works with -std=c++11. It may not in MinGW.
check_cxx_source_compiles("
#include <stdio.h>
int main() {
char buffer[10];
snprintf(buffer, 10, \"foo\");
}" FMT_CPP11_SNPRINTF)
if (FMT_CPP11_CMATH AND FMT_CPP11_UNISTD_H AND FMT_CPP11_SNPRINTF)
set(CPP11_FLAG -std=c++11)
else ()
check_cxx_compiler_flag(-std=gnu++11 HAVE_STD_GNUPP11_FLAG)
@@ -37,6 +44,11 @@ if (FMT_USE_CPP11)
endif ()
endif ()
if (CMAKE_CXX_STANDARD)
# Don't use -std compiler flag if CMAKE_CXX_STANDARD is specified.
set(CPP11_FLAG )
endif ()
set(CMAKE_REQUIRED_FLAGS ${CPP11_FLAG})
# Check if variadic templates are working and not affected by GCC bug 39653:
+235
View File
@@ -0,0 +1,235 @@
#!/usr/bin/env python
"""Manage site and releases.
Usage:
manage.py release [<branch>]
manage.py site
"""
from __future__ import print_function
import datetime, docopt, fileinput, json, os
import re, requests, shutil, sys, tempfile
from contextlib import contextmanager
from distutils.version import LooseVersion
from subprocess import check_call
class Git:
def __init__(self, dir):
self.dir = dir
def call(self, method, args, **kwargs):
return check_call(['git', method] + list(args), **kwargs)
def add(self, *args):
return self.call('add', args, cwd=self.dir)
def checkout(self, *args):
return self.call('checkout', args, cwd=self.dir)
def clean(self, *args):
return self.call('clean', args, cwd=self.dir)
def clone(self, *args):
return self.call('clone', list(args) + [self.dir])
def commit(self, *args):
return self.call('commit', args, cwd=self.dir)
def pull(self, *args):
return self.call('pull', args, cwd=self.dir)
def push(self, *args):
return self.call('push', args, cwd=self.dir)
def reset(self, *args):
return self.call('reset', args, cwd=self.dir)
def update(self, *args):
clone = not os.path.exists(self.dir)
if clone:
self.clone(*args)
return clone
def clean_checkout(repo, branch):
repo.clean('-f', '-d')
repo.reset('--hard')
repo.checkout(branch)
class Runner:
def __init__(self, cwd):
self.cwd = cwd
def __call__(self, *args, **kwargs):
kwargs['cwd'] = kwargs.get('cwd', self.cwd)
check_call(args, **kwargs)
def create_build_env():
"""Create a build environment."""
class Env:
pass
env = Env()
# Import the documentation build module.
env.fmt_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
sys.path.insert(0, os.path.join(env.fmt_dir, 'doc'))
import build
env.build_dir = 'build'
# Virtualenv and repos are cached to speed up builds.
build.create_build_env(os.path.join(env.build_dir, 'virtualenv'))
env.fmt_repo = Git(os.path.join(env.build_dir, 'fmt'))
return env
@contextmanager
def rewrite(filename):
class Buffer:
pass
buffer = Buffer()
if not os.path.exists(filename):
buffer.data = ''
yield buffer
return
with open(filename) as f:
buffer.data = f.read()
yield buffer
with open(filename, 'w') as f:
f.write(buffer.data)
fmt_repo_url = 'git@github.com:fmtlib/fmt'
def update_site(env):
env.fmt_repo.update(fmt_repo_url)
doc_repo = Git(os.path.join(env.build_dir, 'fmtlib.github.io'))
doc_repo.update('git@github.com:fmtlib/fmtlib.github.io')
for version in ['1.0.0', '1.1.0', '2.0.0', '3.0.0']:
clean_checkout(env.fmt_repo, version)
target_doc_dir = os.path.join(env.fmt_repo.dir, 'doc')
# Remove the old theme.
for entry in os.listdir(target_doc_dir):
path = os.path.join(target_doc_dir, entry)
if os.path.isdir(path):
shutil.rmtree(path)
# Copy the new theme.
for entry in ['_static', '_templates', 'basic-bootstrap', 'bootstrap',
'conf.py', 'fmt.less']:
src = os.path.join(env.fmt_dir, 'doc', entry)
dst = os.path.join(target_doc_dir, entry)
copy = shutil.copytree if os.path.isdir(src) else shutil.copyfile
copy(src, dst)
# Rename index to contents.
contents = os.path.join(target_doc_dir, 'contents.rst')
if not os.path.exists(contents):
os.rename(os.path.join(target_doc_dir, 'index.rst'), contents)
# Fix issues in reference.rst/api.rst.
for filename in ['reference.rst', 'api.rst']:
pattern = re.compile('doxygenfunction.. (bin|oct|hexu|hex)$', re.M)
with rewrite(os.path.join(target_doc_dir, filename)) as b:
b.data = b.data.replace('std::ostream &', 'std::ostream&')
b.data = re.sub(pattern, r'doxygenfunction:: \1(int)', b.data)
b.data = b.data.replace('std::FILE*', 'std::FILE *')
b.data = b.data.replace('unsigned int', 'unsigned')
# Fix a broken link in index.rst.
index = os.path.join(target_doc_dir, 'index.rst')
with rewrite(index) as b:
b.data = b.data.replace(
'doc/latest/index.html#format-string-syntax', 'syntax.html')
# Build the docs.
html_dir = os.path.join(env.build_dir, 'html')
if os.path.exists(html_dir):
shutil.rmtree(html_dir)
include_dir = env.fmt_repo.dir
if LooseVersion(version) >= LooseVersion('3.0.0'):
include_dir = os.path.join(include_dir, 'fmt')
import build
build.build_docs(version, doc_dir=target_doc_dir,
include_dir=include_dir, work_dir=env.build_dir)
shutil.rmtree(os.path.join(html_dir, '.doctrees'))
# Create symlinks for older versions.
for link, target in {'index': 'contents', 'api': 'reference'}.items():
link = os.path.join(html_dir, link) + '.html'
target += '.html'
if os.path.exists(os.path.join(html_dir, target)) and \
not os.path.exists(link):
os.symlink(target, link)
# Copy docs to the website.
version_doc_dir = os.path.join(doc_repo.dir, version)
shutil.rmtree(version_doc_dir)
shutil.move(html_dir, version_doc_dir)
def release(args):
env = create_build_env()
fmt_repo = env.fmt_repo
branch = args.get('<branch>')
if branch is None:
branch = 'master'
if not fmt_repo.update('-b', branch, fmt_repo_url):
clean_checkout(fmt_repo, branch)
# Convert changelog from RST to GitHub-flavored Markdown and get the
# version.
changelog = 'ChangeLog.rst'
changelog_path = os.path.join(fmt_repo.dir, changelog)
import rst2md
changes, version = rst2md.convert(changelog_path)
cmakelists = 'CMakeLists.txt'
for line in fileinput.input(os.path.join(fmt_repo.dir, cmakelists),
inplace=True):
prefix = 'set(FMT_VERSION '
if line.startswith(prefix):
line = prefix + version + ')\n'
sys.stdout.write(line)
# Update the version in the changelog.
title_len = 0
for line in fileinput.input(changelog_path, inplace=True):
if line.decode('utf-8').startswith(version + ' - TBD'):
line = version + ' - ' + datetime.date.today().isoformat()
title_len = len(line)
line += '\n'
elif title_len:
line = '-' * title_len + '\n'
title_len = 0
sys.stdout.write(line)
# TODO: add new version to manage.py
fmt_repo.checkout('-B', 'release')
fmt_repo.add(changelog, cmakelists)
fmt_repo.commit('-m', 'Update version')
# Build the docs and package.
run = Runner(fmt_repo.dir)
run('cmake', '.')
run('make', 'doc', 'package_source')
update_site(env)
# Create a release on GitHub.
fmt_repo.push('origin', 'release')
r = requests.post('https://api.github.com/repos/fmtlib/fmt/releases',
params={'access_token': os.getenv('FMT_TOKEN')},
data=json.dumps({'tag_name': version,
'target_commitish': 'release',
'body': changes, 'draft': True}))
if r.status_code != 201:
raise Exception('Failed to create a release ' + str(r))
if __name__ == '__main__':
args = docopt.docopt(__doc__)
if args.get('release'):
release(args)
elif args.get('site'):
update_site(create_build_env())
+127
View File
@@ -0,0 +1,127 @@
# reStructuredText (RST) to GitHub-flavored Markdown converter
import re
from docutils import core, nodes, writers
def is_github_ref(node):
return re.match('https://github.com/.*/(issues|pull)/.*', node['refuri'])
class Translator(nodes.NodeVisitor):
def __init__(self, document):
nodes.NodeVisitor.__init__(self, document)
self.output = ''
self.indent = 0
self.preserve_newlines = False
def write(self, text):
self.output += text.replace('\n', '\n' + ' ' * self.indent)
def visit_document(self, node):
pass
def depart_document(self, node):
pass
def visit_section(self, node):
pass
def depart_section(self, node):
# Skip all sections except the first one.
raise nodes.StopTraversal
def visit_title(self, node):
self.version = re.match(r'(\d+\.\d+\.\d+).*', node.children[0]).group(1)
raise nodes.SkipChildren
def depart_title(self, node):
pass
def visit_Text(self, node):
if not self.preserve_newlines:
node = node.replace('\n', ' ')
self.write(node)
def depart_Text(self, node):
pass
def visit_bullet_list(self, node):
pass
def depart_bullet_list(self, node):
pass
def visit_list_item(self, node):
self.write('* ')
self.indent += 2
def depart_list_item(self, node):
self.indent -= 2
self.write('\n\n')
def visit_paragraph(self, node):
pass
def depart_paragraph(self, node):
pass
def visit_reference(self, node):
if not is_github_ref(node):
self.write('[')
def depart_reference(self, node):
if not is_github_ref(node):
self.write('](' + node['refuri'] + ')')
def visit_target(self, node):
pass
def depart_target(self, node):
pass
def visit_literal(self, node):
self.write('`')
def depart_literal(self, node):
self.write('`')
def visit_literal_block(self, node):
self.write('\n\n```')
if 'c++' in node['classes']:
self.write('c++')
self.write('\n')
self.preserve_newlines = True
def depart_literal_block(self, node):
self.write('\n```\n')
self.preserve_newlines = False
def visit_inline(self, node):
pass
def depart_inline(self, node):
pass
def visit_image(self, node):
self.write('![](' + node['uri'] + ')')
def depart_image(self, node):
pass
class MDWriter(writers.Writer):
"""GitHub-flavored markdown writer"""
supported = ('md',)
"""Formats this writer supports."""
def translate(self):
translator = Translator(self.document)
self.document.walkabout(translator)
self.output = (translator.output, translator.version)
def convert(rst_path):
"""Converts RST file to Markdown."""
return core.publish_file(source_path=rst_path, writer=MDWriter())
+65 -60
View File
@@ -6,34 +6,28 @@ import errno, os, re, shutil, sys, tempfile, urllib
from subprocess import call, check_call, check_output, Popen, PIPE, STDOUT
def rmtree_if_exists(dir):
try:
shutil.rmtree(dir)
except OSError as e:
if e.errno == errno.ENOENT:
pass
try:
shutil.rmtree(dir)
except OSError as e:
if e.errno == errno.ENOENT:
pass
def makedirs_if_not_exist(dir):
try:
os.makedirs(dir)
except OSError as e:
if e.errno != errno.EEXIST:
raise
try:
os.makedirs(dir)
except OSError as e:
if e.errno != errno.EEXIST:
raise
fmt_dir = os.path.dirname(os.path.dirname(os.path.realpath(__file__)))
build = os.environ['BUILD']
if build == 'Doc':
travis = 'TRAVIS' in os.environ
# Install dependencies.
if travis:
def install_dependencies():
branch = os.environ['TRAVIS_BRANCH']
if branch != 'master':
print('Branch: ' + branch)
exit(0) # Ignore non-master branches
check_call('curl -s https://deb.nodesource.com/gpgkey/nodesource.gpg.key | ' +
'sudo apt-key add -', shell=True)
check_call('echo "deb https://deb.nodesource.com/node_0.10 precise main" | ' +
'sudo tee /etc/apt/sources.list.d/nodesource.list', shell=True)
print('Branch: ' + branch)
exit(0) # Ignore non-master branches
check_call('curl -s https://deb.nodesource.com/gpgkey/nodesource.gpg.key ' +
'| sudo apt-key add -', shell=True)
check_call('echo "deb https://deb.nodesource.com/node_0.10 precise main" ' +
'| sudo tee /etc/apt/sources.list.d/nodesource.list', shell=True)
check_call(['sudo', 'apt-get', 'update'])
check_call(['sudo', 'apt-get', 'install', 'python-virtualenv', 'nodejs'])
check_call(['npm', 'install', '-g', 'less', 'less-plugin-clean-css'])
@@ -41,39 +35,48 @@ if build == 'Doc':
urllib.urlretrieve('http://mirrors.kernel.org/ubuntu/pool/main/d/doxygen/' +
deb_file, deb_file)
check_call(['sudo', 'dpkg', '-i', deb_file])
sys.path.insert(0, os.path.join(fmt_dir, 'doc'))
import build
html_dir = build.build_docs()
repo = 'fmtlib.github.io'
if travis and 'KEY' not in os.environ:
# Don't update the repo if building on Travis from an account that doesn't
# have push access.
print('Skipping update of ' + repo)
exit(0)
# Clone the fmtlib.github.io repo.
rmtree_if_exists(repo)
git_url = 'https://github.com/' if travis else 'git@github.com:'
check_call(['git', 'clone', git_url + 'fmtlib/{}.git'.format(repo)])
# Copy docs to the repo.
target_dir = os.path.join(repo, 'dev')
rmtree_if_exists(target_dir)
shutil.copytree(html_dir, target_dir, ignore=shutil.ignore_patterns('.*'))
if travis:
check_call(['git', 'config', '--global', 'user.name', 'amplbot'])
check_call(['git', 'config', '--global', 'user.email', 'viz@ampl.com'])
# Push docs to GitHub pages.
check_call(['git', 'add', '--all'], cwd=repo)
if call(['git', 'diff-index', '--quiet', 'HEAD'], cwd=repo):
check_call(['git', 'commit', '-m', 'Update documentation'], cwd=repo)
cmd = 'git push'
fmt_dir = os.path.dirname(os.path.dirname(os.path.realpath(__file__)))
build = os.environ['BUILD']
if build == 'Doc':
travis = 'TRAVIS' in os.environ
if travis:
cmd += ' https://$KEY@github.com/fmtlib/fmtlib.github.io.git master'
p = Popen(cmd, shell=True, stdout=PIPE, stderr=STDOUT, cwd=repo)
# Print the output without the key.
print(p.communicate()[0].replace(os.environ['KEY'], '$KEY'))
if p.returncode != 0:
raise CalledProcessError(p.returncode, cmd)
exit(0)
install_dependencies()
sys.path.insert(0, os.path.join(fmt_dir, 'doc'))
import build
build.create_build_env()
html_dir = build.build_docs()
repo = 'fmtlib.github.io'
if travis and 'KEY' not in os.environ:
# Don't update the repo if building on Travis from an account that
# doesn't have push access.
print('Skipping update of ' + repo)
exit(0)
# Clone the fmtlib.github.io repo.
rmtree_if_exists(repo)
git_url = 'https://github.com/' if travis else 'git@github.com:'
check_call(['git', 'clone', git_url + 'fmtlib/{}.git'.format(repo)])
# Copy docs to the repo.
target_dir = os.path.join(repo, 'dev')
rmtree_if_exists(target_dir)
shutil.copytree(html_dir, target_dir, ignore=shutil.ignore_patterns('.*'))
if travis:
check_call(['git', 'config', '--global', 'user.name', 'amplbot'])
check_call(['git', 'config', '--global', 'user.email', 'viz@ampl.com'])
# Push docs to GitHub pages.
check_call(['git', 'add', '--all'], cwd=repo)
if call(['git', 'diff-index', '--quiet', 'HEAD'], cwd=repo):
check_call(['git', 'commit', '-m', 'Update documentation'], cwd=repo)
cmd = 'git push'
if travis:
cmd += ' https://$KEY@github.com/fmtlib/fmtlib.github.io.git master'
p = Popen(cmd, shell=True, stdout=PIPE, stderr=STDOUT, cwd=repo)
# Print the output without the key.
print(p.communicate()[0].replace(os.environ['KEY'], '$KEY'))
if p.returncode != 0:
raise CalledProcessError(p.returncode, cmd)
exit(0)
standard = os.environ['STANDARD']
install_dir = os.path.join(fmt_dir, "_install")
@@ -83,11 +86,13 @@ test_build_dir = os.path.join(fmt_dir, "_build_test")
# Configure library.
makedirs_if_not_exist(build_dir)
common_cmake_flags = [
'-DCMAKE_INSTALL_PREFIX=' + install_dir, '-DCMAKE_BUILD_TYPE=' + build
'-DCMAKE_INSTALL_PREFIX=' + install_dir, '-DCMAKE_BUILD_TYPE=' + build
]
extra_cmake_flags = []
if standard != '0x':
extra_cmake_flags = ['-DCMAKE_CXX_FLAGS=-std=c++' + standard, '-DFMT_USE_CPP11=OFF']
extra_cmake_flags = [
'-DCMAKE_CXX_FLAGS=-std=c++' + standard, '-DFMT_USE_CPP11=OFF'
]
check_call(['cmake', '-DFMT_DOC=OFF', '-DFMT_PEDANTIC=ON', fmt_dir] +
common_cmake_flags + extra_cmake_flags, cwd=build_dir)
@@ -98,9 +103,9 @@ check_call(['make', '-j4'], cwd=build_dir)
env = os.environ.copy()
env['CTEST_OUTPUT_ON_FAILURE'] = '1'
if call(['make', 'test'], env=env, cwd=build_dir):
with open('Testing/Temporary/LastTest.log', 'r') as f:
print(f.read())
sys.exit(-1)
with open('Testing/Temporary/LastTest.log', 'r') as f:
print(f.read())
sys.exit(-1)
# Install library.
check_call(['make', 'install'], cwd=build_dir)
+15 -15
View File
@@ -8,23 +8,23 @@ import shutil, tempfile
from subprocess import check_output, STDOUT
class Git:
def __init__(self, dir):
self.dir = dir
def __init__(self, dir):
self.dir = dir
def __call__(self, *args):
output = check_output(['git'] + list(args), cwd=self.dir, stderr=STDOUT)
print(output)
return output
def __call__(self, *args):
output = check_output(['git'] + list(args), cwd=self.dir, stderr=STDOUT)
print(output)
return output
dir = tempfile.mkdtemp()
try:
git = Git(dir)
git('clone', '-b', 'coverity', 'git@github.com:fmtlib/fmt.git', dir)
output = git('merge', '-X', 'theirs', '--no-commit', 'origin/master')
if 'Fast-forward' not in output:
git('reset', 'HEAD', '.travis.yml')
git('checkout', '--', '.travis.yml')
git('commit', '-m', 'Update coverity branch')
git('push')
git = Git(dir)
git('clone', '-b', 'coverity', 'git@github.com:fmtlib/fmt.git', dir)
output = git('merge', '-X', 'theirs', '--no-commit', 'origin/master')
if 'Fast-forward' not in output:
git('reset', 'HEAD', '.travis.yml')
git('checkout', '--', '.travis.yml')
git('commit', '-m', 'Update coverity branch')
git('push')
finally:
shutil.rmtree(dir)
shutil.rmtree(dir)
+19 -4
View File
@@ -56,11 +56,19 @@ if (CMAKE_COMPILER_IS_GNUCXX OR (CMAKE_CXX_COMPILER_ID MATCHES "Clang"))
set(PEDANTIC_COMPILE_FLAGS -Wall -Wextra -Wno-long-long -Wno-variadic-macros)
endif ()
function(add_fmt_executable name)
add_executable(${name} ${ARGN})
if (MINGW)
target_link_libraries(${name} -static-libgcc -static-libstdc++)
endif ()
endfunction()
# Adds a test.
# Usage: add_fmt_test(name srcs...)
function(add_fmt_test name)
add_executable(${name} ${name}.cc ${ARGN})
add_fmt_executable(${name} ${name}.cc ${ARGN})
target_link_libraries(${name} test-main)
# define if certain c++ features can be used
target_compile_definitions(${name} PRIVATE
FMT_USE_TYPE_TRAITS=$<BOOL:${SUPPORTS_TYPE_TRAITS}>
@@ -72,13 +80,17 @@ function(add_fmt_test name)
endfunction()
add_fmt_test(assert-test)
add_fmt_test(container-test)
add_fmt_test(gtest-extra-test)
add_fmt_test(format-test)
add_fmt_test(format-impl-test)
add_fmt_test(ostream-test)
add_fmt_test(printf-test)
add_fmt_test(string-test)
add_fmt_test(time-test)
add_fmt_test(util-test mock-allocator.h)
add_fmt_test(macro-test)
add_fmt_test(custom-formatter-test)
# Enable stricter options for one test to make sure that the header is free of
# warnings.
@@ -87,7 +99,8 @@ if (FMT_PEDANTIC AND MSVC)
endif ()
if (HAVE_OPEN)
add_executable(posix-mock-test posix-mock-test.cc ../fmt/format.cc ${TEST_MAIN_SRC})
add_fmt_executable(posix-mock-test
posix-mock-test.cc ../fmt/format.cc ../fmt/printf.cc ${TEST_MAIN_SRC})
target_include_directories(posix-mock-test PRIVATE ${PROJECT_SOURCE_DIR})
target_compile_definitions(posix-mock-test PRIVATE FMT_USE_FILE_DESCRIPTORS=1)
target_link_libraries(posix-mock-test gmock)
@@ -95,7 +108,7 @@ if (HAVE_OPEN)
add_fmt_test(posix-test)
endif ()
add_executable(header-only-test
add_fmt_executable(header-only-test
header-only-test.cc header-only-test2.cc test-main.cc)
target_link_libraries(header-only-test gmock)
if (TARGET fmt-header-only)
@@ -109,6 +122,7 @@ endif ()
check_cxx_compiler_flag(-fno-exceptions HAVE_FNO_EXCEPTIONS_FLAG)
if (HAVE_FNO_EXCEPTIONS_FLAG)
add_library(noexception-test ../fmt/format.cc)
target_include_directories(noexception-test PRIVATE ${PROJECT_SOURCE_DIR})
target_compile_options(noexception-test PRIVATE -fno-exceptions)
endif ()
@@ -116,6 +130,7 @@ if (FMT_PEDANTIC)
# Test that the library compiles without windows.h.
if (CMAKE_SYSTEM_NAME STREQUAL "Windows")
add_library(no-windows-h-test ../fmt/format.cc)
target_include_directories(no-windows-h-test PRIVATE ${PROJECT_SOURCE_DIR})
target_compile_definitions(no-windows-h-test PRIVATE FMT_USE_WINDOWS_H=0)
endif ()
@@ -125,7 +140,7 @@ if (FMT_PEDANTIC)
"${CMAKE_CURRENT_BINARY_DIR}/compile-test"
--build-generator ${CMAKE_GENERATOR}
--build-makeprogram ${CMAKE_MAKE_PROGRAM}
--build-options
--build-options
"-DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER}"
"-DCPP11_FLAG=${CPP11_FLAG}"
"-DSUPPORTS_USER_DEFINED_LITERALS=${SUPPORTS_USER_DEFINED_LITERALS}")
@@ -5,9 +5,9 @@ project(fmt-test)
add_subdirectory(../.. fmt)
add_executable(library-test "main.cc")
target_link_libraries(library-test fmt)
target_link_libraries(library-test fmt::fmt)
if (TARGET fmt-header-only)
if (TARGET fmt::fmt-header-only)
add_executable(header-only-test "main.cc")
target_link_libraries(header-only-test fmt-header-only)
target_link_libraries(header-only-test fmt::fmt-header-only)
endif ()
+94
View File
@@ -0,0 +1,94 @@
/*
Tests of container utilities
Copyright (c) 2012 - 2016, Victor Zverovich
All rights reserved.
For the license information refer to format.h.
*/
#include "fmt/container.h"
#include "gtest/gtest.h"
using fmt::internal::ContainerBuffer;
TEST(ContainerBufferTest, Empty) {
std::string data;
ContainerBuffer<std::string> buffer(data);
EXPECT_EQ(0u, buffer.size());
EXPECT_EQ(0u, buffer.capacity());
}
TEST(ContainerBufferTest, Reserve) {
std::string data;
ContainerBuffer<std::string> buffer(data);
std::size_t capacity = std::string().capacity() + 10;
buffer.reserve(capacity);
EXPECT_EQ(0u, buffer.size());
EXPECT_EQ(capacity, buffer.capacity());
}
TEST(ContainerBufferTest, Resize) {
std::string data;
ContainerBuffer<std::string> buffer(data);
std::size_t size = std::string().capacity() + 10;
buffer.resize(size);
EXPECT_EQ(size, buffer.size());
EXPECT_EQ(size, buffer.capacity());
}
TEST(ContainerBufferTest, Append) {
std::string data("Why so");
const std::string serious(" serious");
ContainerBuffer<std::string> buffer(data);
buffer.append(serious.c_str(), serious.c_str() + serious.length());
EXPECT_EQ("Why so serious", data);
EXPECT_EQ(data.length(), buffer.size());
}
TEST(BasicContainerWriterTest, String) {
std::string data;
fmt::BasicContainerWriter<std::string> out(data);
out << "The answer is " << 42 << "\n";
EXPECT_EQ("The answer is 42\n", data);
EXPECT_EQ(17u, out.size());
}
TEST(BasicContainerWriterTest, WString) {
std::wstring data;
fmt::BasicContainerWriter<std::wstring> out(data);
out << "The answer is " << 42 << "\n";
EXPECT_EQ(L"The answer is 42\n", data);
EXPECT_EQ(17u, out.size());
}
TEST(BasicContainerWriterTest, Vector) {
std::vector<char> data;
fmt::BasicContainerWriter<std::vector<char> > out(data);
out << "The answer is " << 42 << "\n";
EXPECT_EQ(17u, data.size());
EXPECT_EQ(out.size(), data.size());
}
TEST(BasicContainerWriterTest, StringAppend) {
std::string data("The");
fmt::BasicContainerWriter<std::string> out(data);
EXPECT_EQ(3u, data.size());
EXPECT_EQ(3u, out.size());
out << " answer is " << 42 << "\n";
EXPECT_EQ("The answer is 42\n", data);
EXPECT_EQ(17u, out.size());
}
TEST(BasicContainerWriterTest, VectorAppend) {
std::vector<char> data;
data.push_back('T');
data.push_back('h');
data.push_back('e');
fmt::BasicContainerWriter<std::vector<char> > out(data);
EXPECT_EQ(3u, data.size());
EXPECT_EQ(3u, out.size());
out << " answer is " << 42 << "\n";
EXPECT_EQ(17u, data.size());
EXPECT_EQ(17u, out.size());
}
+68
View File
@@ -0,0 +1,68 @@
/*
Custom argument formatter tests
Copyright (c) 2016, Victor Zverovich
All rights reserved.
For the license information refer to format.h.
*/
#include "fmt/printf.h"
#include "gtest-extra.h"
using fmt::BasicPrintfArgFormatter;
// A custom argument formatter that doesn't print `-` for floating-point values
// rounded to 0.
class CustomArgFormatter
: public fmt::BasicArgFormatter<CustomArgFormatter, char> {
public:
CustomArgFormatter(fmt::BasicFormatter<char, CustomArgFormatter> &f,
fmt::FormatSpec &s, const char *fmt)
: fmt::BasicArgFormatter<CustomArgFormatter, char>(f, s, fmt) {}
void visit_double(double value) {
if (round(value * pow(10, spec().precision())) == 0)
value = 0;
fmt::BasicArgFormatter<CustomArgFormatter, char>::visit_double(value);
}
};
// A custom argument formatter that doesn't print `-` for floating-point values
// rounded to 0.
class CustomPrintfArgFormatter :
public BasicPrintfArgFormatter<CustomPrintfArgFormatter, char> {
public:
typedef BasicPrintfArgFormatter<CustomPrintfArgFormatter, char> Base;
CustomPrintfArgFormatter(fmt::BasicWriter<char> &w, fmt::FormatSpec &spec)
: Base(w, spec) {}
void visit_double(double value) {
if (round(value * pow(10, spec().precision())) == 0)
value = 0;
Base::visit_double(value);
}
};
std::string custom_format(const char *format_str, fmt::ArgList args) {
fmt::MemoryWriter writer;
// Pass custom argument formatter as a template arg to BasicFormatter.
fmt::BasicFormatter<char, CustomArgFormatter> formatter(args, writer);
formatter.format(format_str);
return writer.str();
}
FMT_VARIADIC(std::string, custom_format, const char *)
std::string custom_sprintf(const char* format_str, fmt::ArgList args){
fmt::MemoryWriter writer;
fmt::PrintfFormatter<char, CustomPrintfArgFormatter> formatter(args, writer);
formatter.format(format_str);
return writer.str();
}
FMT_VARIADIC(std::string, custom_sprintf, const char*);
TEST(CustomFormatterTest, Format) {
EXPECT_EQ("0.00", custom_format("{:.2f}", -.00001));
EXPECT_EQ("0.00", custom_sprintf("%.2f", -.00001));
}
@@ -5,9 +5,9 @@ project(fmt-test)
find_package(FMT REQUIRED)
add_executable(library-test main.cc)
target_link_libraries(library-test fmt)
target_link_libraries(library-test fmt::fmt)
if (TARGET fmt-header-only)
if (TARGET fmt::fmt-header-only)
add_executable(header-only-test main.cc)
target_link_libraries(header-only-test fmt-header-only)
target_link_libraries(header-only-test fmt::fmt-header-only)
endif ()
+4 -2
View File
@@ -26,10 +26,12 @@
*/
#define FMT_NOEXCEPT
#undef FMT_SHARED
#include "test-assert.h"
// Include format.cc instead of format.h to test implementation-specific stuff.
// Include *.cc instead of *.h to test implementation-specific stuff.
#include "fmt/format.cc"
#include "fmt/printf.cc"
#include <algorithm>
#include <cstring>
@@ -46,7 +48,7 @@ TEST(FormatTest, ArgConverter) {
Arg arg = Arg();
arg.type = Arg::LONG_LONG;
arg.long_long_value = std::numeric_limits<fmt::LongLong>::max();
fmt::ArgConverter<fmt::LongLong>(arg, 'd').visit(arg);
fmt::internal::ArgConverter<fmt::LongLong>(arg, 'd').visit(arg);
EXPECT_EQ(Arg::LONG_LONG, arg.type);
}
+67 -20
View File
@@ -43,8 +43,23 @@
// Test that the library compiles if None is defined to 0 as done by xlib.h.
#define None 0
struct LocaleMock {
static LocaleMock *instance;
MOCK_METHOD0(localeconv, lconv *());
} *LocaleMock::instance;
namespace fmt {
namespace std {
using namespace ::std;
lconv *localeconv() {
return LocaleMock::instance ?
LocaleMock::instance->localeconv() : ::std::localeconv();
}
}
}
#include "fmt/format.h"
#include "fmt/time.h"
#include "util.h"
#include "mock-allocator.h"
@@ -235,7 +250,7 @@ TEST(WriterTest, Allocator) {
std::size_t size =
static_cast<std::size_t>(1.5 * fmt::internal::INLINE_BUFFER_SIZE);
std::vector<char> mem(size);
EXPECT_CALL(alloc, allocate(size)).WillOnce(testing::Return(&mem[0]));
EXPECT_CALL(alloc, allocate(size, 0)).WillOnce(testing::Return(&mem[0]));
for (int i = 0; i < fmt::internal::INLINE_BUFFER_SIZE + 1; ++i)
w << '*';
EXPECT_CALL(alloc, deallocate(&mem[0], size));
@@ -917,7 +932,7 @@ TEST(FormatterTest, RuntimeWidth) {
FormatError, "number is too big");
EXPECT_THROW_MSG(format("{0:{1}}", 0, -1l),
FormatError, "negative width");
if (fmt::internal::check(sizeof(long) > sizeof(int))) {
if (fmt::internal::const_check(sizeof(long) > sizeof(int))) {
long value = INT_MAX;
EXPECT_THROW_MSG(format("{0:{1}}", 0, (value + 1)),
FormatError, "number is too big");
@@ -1036,7 +1051,7 @@ TEST(FormatterTest, RuntimePrecision) {
FormatError, "number is too big");
EXPECT_THROW_MSG(format("{0:.{1}}", 0, -1l),
FormatError, "negative precision");
if (fmt::internal::check(sizeof(long) > sizeof(int))) {
if (fmt::internal::const_check(sizeof(long) > sizeof(int))) {
long value = INT_MAX;
EXPECT_THROW_MSG(format("{0:.{1}}", 0, (value + 1)),
FormatError, "number is too big");
@@ -1209,13 +1224,24 @@ TEST(FormatterTest, FormatOct) {
}
TEST(FormatterTest, FormatIntLocale) {
#ifndef _WIN32
const char *locale = "en_US.utf-8";
#else
const char *locale = "English_United States";
#endif
std::setlocale(LC_ALL, locale);
EXPECT_EQ("1,234,567", format("{:n}", 1234567));
ScopedMock<LocaleMock> mock;
lconv lc = lconv();
char sep[] = "--";
lc.thousands_sep = sep;
EXPECT_CALL(mock, localeconv()).Times(3).WillRepeatedly(testing::Return(&lc));
EXPECT_EQ("123", format("{:n}", 123));
EXPECT_EQ("1--234", format("{:n}", 1234));
EXPECT_EQ("1--234--567", format("{:n}", 1234567));
}
struct ConvertibleToLongLong {
operator fmt::LongLong() const {
return fmt::LongLong(1) << 32;
}
};
TEST(FormatterTest, FormatConvertibleToLongLong) {
EXPECT_EQ("100000000", format("{:x}", ConvertibleToLongLong()));
}
TEST(FormatterTest, FormatFloat) {
@@ -1327,6 +1353,8 @@ TEST(FormatterTest, FormatUCharString) {
EXPECT_EQ("test", format("{0:s}", str));
const unsigned char *const_str = str;
EXPECT_EQ("test", format("{0:s}", const_str));
unsigned char *ptr = str;
EXPECT_EQ("test", format("{0:s}", ptr));
}
TEST(FormatterTest, FormatPointer) {
@@ -1350,7 +1378,7 @@ TEST(FormatterTest, FormatCStringRef) {
EXPECT_EQ("test", format("{0}", CStringRef("test")));
}
void format(fmt::BasicFormatter<char> &f, const char *, const Date &d) {
void format_arg(fmt::BasicFormatter<char> &f, const char *, const Date &d) {
f.writer() << d.year() << '-' << d.month() << '-' << d.day();
}
@@ -1363,7 +1391,7 @@ TEST(FormatterTest, FormatCustom) {
class Answer {};
template <typename Char>
void format(fmt::BasicFormatter<Char> &f, const Char *, Answer) {
void format_arg(fmt::BasicFormatter<Char> &f, const Char *, Answer) {
f.writer() << "42";
}
@@ -1534,13 +1562,25 @@ TEST(FormatTest, Variadic) {
EXPECT_EQ(L"abc1", format(L"{}c{}", L"ab", 1));
}
TEST(FormatTest, Time) {
std::tm tm = std::tm();
tm.tm_year = 116;
tm.tm_mon = 3;
tm.tm_mday = 25;
EXPECT_EQ("The date is 2016-04-25.",
fmt::format("The date is {:%Y-%m-%d}.", tm));
TEST(FormatTest, JoinArg) {
using fmt::join;
int v1[3] = { 1, 2, 3 };
std::vector<float> v2;
v2.push_back(1.2f);
v2.push_back(3.4f);
EXPECT_EQ("(1, 2, 3)", format("({})", join(v1 + 0, v1 + 3, ", ")));
EXPECT_EQ("(1)", format("({})", join(v1 + 0, v1 + 1, ", ")));
EXPECT_EQ("()", format("({})", join(v1 + 0, v1 + 0, ", ")));
EXPECT_EQ("(001, 002, 003)", format("({:03})", join(v1 + 0, v1 + 3, ", ")));
EXPECT_EQ("(+01.20, +03.40)", format("({:+06.2f})", join(v2.begin(), v2.end(), ", ")));
EXPECT_EQ(L"(1, 2, 3)", format(L"({})", join(v1 + 0, v1 + 3, L", ")));
#if FMT_HAS_GXX_CXX11
EXPECT_EQ("(1, 2, 3)", format("({})", join(v1, ", ")));
EXPECT_EQ("(+01.20, +03.40)", format("({:+06.2f})", join(v2, ", ")));
#endif
}
template <typename T>
@@ -1644,3 +1684,10 @@ FMT_VARIADIC(void, custom_format, const char *)
TEST(FormatTest, CustomArgFormatter) {
custom_format("{}", 42);
}
void convert(int);
// Check if there is no collision with convert function in the global namespace.
TEST(FormatTest, ConvertCollision) {
fmt::format("{}", 42);
}
+3 -2
View File
@@ -10090,8 +10090,9 @@ class FunctionMockerBase : public UntypedFunctionMockerBase {
// threads concurrently.
Result InvokeWith(const ArgumentTuple& args)
GTEST_LOCK_EXCLUDED_(g_gmock_mutex) {
return static_cast<const ResultHolder*>(
this->UntypedInvokeWith(&args))->GetValueAndDelete();
const ResultHolder *rh = static_cast<const ResultHolder*>(
this->UntypedInvokeWith(&args));
return rh ? rh->GetValueAndDelete() : Result();
}
// Adds and returns a default action spec for this mock function.
+1 -1
View File
@@ -320,7 +320,7 @@ TEST(StreamingAssertionsTest, EXPECT_WRITE) {
TEST(UtilTest, FormatSystemError) {
fmt::MemoryWriter out;
fmt::internal::format_system_error(out, EDOM, "test message");
fmt::format_system_error(out, EDOM, "test message");
EXPECT_EQ(out.str(), format_system_error(EDOM, "test message"));
}
+1 -1
View File
@@ -105,6 +105,6 @@ std::string read(File &f, std::size_t count) {
std::string format_system_error(int error_code, fmt::StringRef message) {
fmt::MemoryWriter out;
fmt::internal::format_system_error(out, error_code, message);
fmt::format_system_error(out, error_code, message);
return out.str();
}
+7 -1
View File
@@ -29,7 +29,7 @@
#define FMT_GTEST_EXTRA_H_
#include <string>
#include <gtest/gtest.h>
#include <gmock/gmock.h>
#include "fmt/format.h"
@@ -172,4 +172,10 @@ std::string read(fmt::File &f, std::size_t count);
#endif // FMT_USE_FILE_DESCRIPTORS
template <typename Mock>
struct ScopedMock : testing::StrictMock<Mock> {
ScopedMock() { Mock::instance = this; }
~ScopedMock() { Mock::instance = 0; }
};
#endif // FMT_GTEST_EXTRA_H_
+5 -1
View File
@@ -2823,7 +2823,11 @@ inline int IsATTY(int /* fd */) { return 0; }
inline int IsATTY(int fd) { return _isatty(fd); }
# endif // GTEST_OS_WINDOWS_MOBILE
inline int StrCaseCmp(const char* s1, const char* s2) {
return _stricmp(s1, s2);
# if _EMULATE_GLIBC
return strcasecmp(s1, s2);
# else
return _stricmp(s1, s2);
# endif
}
inline char* StrDup(const char* src) { return _strdup(src); }
# endif // __BORLANDC__
+6 -4
View File
@@ -36,8 +36,8 @@ class MockAllocator {
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));
MOCK_METHOD2_T(allocate, T *(std::size_t n, const T *h));
MOCK_METHOD2_T(deallocate, void (T *p, std::size_t n));
};
template <typename Allocator>
@@ -78,8 +78,10 @@ class AllocatorRef {
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); }
value_type *allocate(std::size_t n, const value_type *h) {
return alloc_->allocate(n, h);
}
void deallocate(value_type *p, std::size_t n) { alloc_->deallocate(p, n); }
};
#endif // FMT_MOCK_ALLOCATOR_H_
+3 -21
View File
@@ -25,7 +25,7 @@
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "fmt/ostream.cc"
#include "fmt/ostream.h"
#include <sstream>
#include "gmock/gmock.h"
@@ -35,13 +35,6 @@
using fmt::format;
using fmt::FormatError;
template <typename Char>
std::basic_ostream<Char> &operator<<(
std::basic_ostream<Char> &os, const BasicTestString<Char> &s) {
os << s.value();
return os;
}
std::ostream &operator<<(std::ostream &os, const Date &d) {
os << d.year() << '-' << d.month() << '-' << d.day();
return os;
@@ -128,22 +121,11 @@ TEST(OStreamTest, Print) {
EXPECT_EQ("Don't panic!", os.str());
}
TEST(OStreamTest, PrintfCustom) {
EXPECT_EQ("abc", fmt::sprintf("%s", TestString("abc")));
}
TEST(OStreamTest, FPrintf) {
std::ostringstream os;
int ret = fmt::fprintf(os, "Don't %s!", "panic");
EXPECT_EQ("Don't panic!", os.str());
EXPECT_EQ(12, ret);
}
TEST(OStreamTest, WriteToOStream) {
std::ostringstream os;
fmt::MemoryWriter w;
w << "foo";
fmt::write(os, w);
fmt::internal::write(os, w);
EXPECT_EQ("foo", os.str());
}
@@ -188,5 +170,5 @@ TEST(OStreamTest, WriteToOStreamMaxSize) {
data += n;
size -= static_cast<std::size_t>(n);
} while (size != 0);
fmt::write(os, w);
fmt::internal::write(os, w);
}
+1 -7
View File
@@ -453,12 +453,6 @@ TEST(BufferedFileTest, FilenoNoRetry) {
fileno_count = 0;
}
template <typename Mock>
struct ScopedMock : testing::StrictMock<Mock> {
ScopedMock() { Mock::instance = this; }
~ScopedMock() { Mock::instance = 0; }
};
struct TestMock {
static TestMock *instance;
} *TestMock::instance;
@@ -508,7 +502,7 @@ LocaleType newlocale(int category_mask, const char *locale, LocaleType base) {
return LocaleMock::instance->newlocale(category_mask, locale, base);
}
#ifdef __APPLE__
#if defined(__APPLE__) || defined(__FreeBSD__)
typedef int FreeLocaleResult;
#else
typedef void FreeLocaleResult;
+1 -1
View File
@@ -232,7 +232,7 @@ TEST(FileTest, MoveAssignmentClosesFile) {
File OpenBufferedFile(int &fd) {
File f = open_file();
fd = f.descriptor();
return std::move(f);
return f;
}
TEST(FileTest, MoveFromTemporaryInCtor) {
+36 -4
View File
@@ -29,6 +29,7 @@
#include <climits>
#include <cstring>
#include "fmt/printf.h"
#include "fmt/format.h"
#include "gtest-extra.h"
#include "util.h"
@@ -201,6 +202,8 @@ TEST(PrintfTest, HashFlag) {
TEST(PrintfTest, Width) {
EXPECT_PRINTF(" abc", "%5s", "abc");
EXPECT_PRINTF(" -42", "%5s", "-42");
EXPECT_PRINTF(" 0.123456", "%10s", 0.123456);
// Width cannot be specified twice.
EXPECT_THROW_MSG(fmt::sprintf("%5-5d", 42), FormatError,
@@ -295,12 +298,13 @@ void TestLength(const char *length_spec, U value) {
fmt::LongLong signed_value = 0;
fmt::ULongLong unsigned_value = 0;
// Apply integer promotion to the argument.
fmt::ULongLong max = std::numeric_limits<U>::max();
using fmt::internal::check;
if (check(max <= static_cast<unsigned>(std::numeric_limits<int>::max()))) {
using std::numeric_limits;
fmt::ULongLong max = numeric_limits<U>::max();
using fmt::internal::const_check;
if (const_check(max <= static_cast<unsigned>(numeric_limits<int>::max()))) {
signed_value = static_cast<int>(value);
unsigned_value = static_cast<unsigned>(value);
} else if (check(max <= std::numeric_limits<unsigned>::max())) {
} else if (const_check(max <= numeric_limits<unsigned>::max())) {
signed_value = static_cast<unsigned>(value);
unsigned_value = static_cast<unsigned>(value);
}
@@ -379,11 +383,13 @@ TEST(PrintfTest, Bool) {
TEST(PrintfTest, Int) {
EXPECT_PRINTF("-42", "%d", -42);
EXPECT_PRINTF("-42", "%i", -42);
EXPECT_PRINTF("-42", "%s", -42);
unsigned u = 0 - 42u;
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);
EXPECT_PRINTF(fmt::format("{}", u), "%s", u);
}
TEST(PrintfTest, LongLong) {
@@ -395,7 +401,11 @@ TEST(PrintfTest, LongLong) {
TEST(PrintfTest, Float) {
EXPECT_PRINTF("392.650000", "%f", 392.65);
EXPECT_PRINTF("392.65", "%.2f", 392.65);
EXPECT_PRINTF("392.6", "%.1f", 392.65);
EXPECT_PRINTF("393", "%.f", 392.65);
EXPECT_PRINTF("392.650000", "%F", 392.65);
EXPECT_PRINTF("392.65", "%s", 392.65);
char buffer[BUFFER_SIZE];
safe_sprintf(buffer, "%e", 392.65);
EXPECT_PRINTF(buffer, "%e", 392.65);
@@ -420,6 +430,7 @@ TEST(PrintfTest, Inf) {
TEST(PrintfTest, Char) {
EXPECT_PRINTF("x", "%c", 'x');
EXPECT_PRINTF("x", "%s", 'x');
int max = std::numeric_limits<int>::max();
EXPECT_PRINTF(fmt::format("{}", static_cast<char>(max)), "%c", max);
//EXPECT_PRINTF("x", "%lc", L'x');
@@ -438,13 +449,17 @@ TEST(PrintfTest, Pointer) {
int n;
void *p = &n;
EXPECT_PRINTF(fmt::format("{}", p), "%p", p);
EXPECT_PRINTF(fmt::format("{}", p), "%s", p);
p = 0;
EXPECT_PRINTF("(nil)", "%p", p);
EXPECT_PRINTF(" (nil)", "%10p", p);
EXPECT_PRINTF("(nil)", "%s", p);
EXPECT_PRINTF(" (nil)", "%10s", p);
const char *s = "test";
EXPECT_PRINTF(fmt::format("{:p}", s), "%p", s);
const char *null_str = 0;
EXPECT_PRINTF("(nil)", "%p", null_str);
EXPECT_PRINTF("(null)", "%s", null_str);
}
TEST(PrintfTest, Location) {
@@ -477,3 +492,20 @@ TEST(PrintfTest, PrintfError) {
TEST(PrintfTest, WideString) {
EXPECT_EQ(L"abc", fmt::sprintf(L"%s", L"abc"));
}
TEST(PrintfTest, PrintfCustom) {
EXPECT_EQ("abc", fmt::sprintf("%s", TestString("abc")));
}
TEST(PrintfTest, OStream) {
std::ostringstream os;
int ret = fmt::fprintf(os, "Don't %s!", "panic");
EXPECT_EQ("Don't panic!", os.str());
EXPECT_EQ(12, ret);
}
TEST(PrintfTest, Writer) {
fmt::MemoryWriter writer;
printf(writer, "%d", 42);
EXPECT_EQ("42", writer.str());
}
+80
View File
@@ -0,0 +1,80 @@
/*
Tests of string utilities
Copyright (c) 2012 - 2016, Victor Zverovich
All rights reserved.
For the license information refer to format.h.
*/
#include "fmt/string.h"
#include "gtest/gtest.h"
using fmt::internal::StringBuffer;
TEST(StringBufferTest, Empty) {
StringBuffer<char> buffer;
EXPECT_EQ(0u, buffer.size());
EXPECT_EQ(0u, buffer.capacity());
std::string data;
// std::string may have initial capacity.
std::size_t capacity = data.capacity();
buffer.move_to(data);
EXPECT_EQ("", data);
EXPECT_EQ(capacity, data.capacity());
}
TEST(StringBufferTest, Reserve) {
StringBuffer<char> buffer;
std::size_t capacity = std::string().capacity() + 10;
buffer.reserve(capacity);
EXPECT_EQ(0u, buffer.size());
EXPECT_EQ(capacity, buffer.capacity());
std::string data;
buffer.move_to(data);
EXPECT_EQ("", data);
}
TEST(StringBufferTest, Resize) {
StringBuffer<char> buffer;
std::size_t size = std::string().capacity() + 10;
buffer.resize(size);
EXPECT_EQ(size, buffer.size());
EXPECT_EQ(size, buffer.capacity());
std::string data;
buffer.move_to(data);
EXPECT_EQ(size, data.size());
}
TEST(StringBufferTest, MoveTo) {
StringBuffer<char> buffer;
std::size_t size = std::string().capacity() + 10;
buffer.resize(size);
const char *p = &buffer[0];
std::string data;
buffer.move_to(data);
EXPECT_EQ(p, &data[0]);
EXPECT_EQ(0u, buffer.size());
EXPECT_EQ(0u, buffer.capacity());
}
TEST(StringWriterTest, MoveTo) {
fmt::StringWriter out;
out << "The answer is " << 42 << "\n";
std::string s;
out.move_to(s);
EXPECT_EQ("The answer is 42\n", s);
EXPECT_EQ(0u, out.size());
}
TEST(StringWriterTest, WString) {
fmt::WStringWriter out;
out << "The answer is " << 42 << "\n";
std::wstring s;
out.move_to(s);
EXPECT_EQ(L"The answer is 42\n", s);
}
TEST(StringTest, ToString) {
EXPECT_EQ("42", fmt::to_string(42));
}

Some files were not shown because too many files have changed in this diff Show More