mirror of
https://github.com/EQEmu/Server.git
synced 2026-06-13 15:08:22 +00:00
Compare commits
230 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 79caacd8a3 | |||
| 6a79694fa1 | |||
| c52ff4249a | |||
| 4e7870c634 | |||
| 487dcc4459 | |||
| 0ba9b3fedc | |||
| 46561b9cf5 | |||
| 545ac6b420 | |||
| 2146489740 | |||
| 3746128014 | |||
| ca32e35ef6 | |||
| c37e83e235 | |||
| 00604722bb | |||
| 808654743c | |||
| bb2d8f6a4d | |||
| 7a263c032d | |||
| ad7dfc31a9 | |||
| 0663e9cb6f | |||
| b0a3e9205f | |||
| 0e8f6a32b1 | |||
| 17544d4577 | |||
| b22a88eccc | |||
| 563878f20e | |||
| 4d3dda23f8 | |||
| 718a2c2205 | |||
| ffbee0ad1a | |||
| bb8c6da0b4 | |||
| 575ba28b62 | |||
| 3afee1f841 | |||
| d5699fb68d | |||
| 28fca1f8dc | |||
| 935dc7d8fb | |||
| 771c3b175e | |||
| b468945eb7 | |||
| 3554211233 | |||
| 0fc72875b2 | |||
| 2286203123 | |||
| 210655ddc7 | |||
| 034ebab064 | |||
| e32b6c55e4 | |||
| 4f016de277 | |||
| 832c31a41a | |||
| 02b7e3fafb | |||
| ff13f162ce | |||
| 80f1c65e1c | |||
| 7d3f35d48b | |||
| 0b11340c4e | |||
| f6f3060c9d | |||
| 6bf2cf8cb8 | |||
| a0140ff943 | |||
| df1e486df6 | |||
| a0cfba5b3e | |||
| 3b1c663e58 | |||
| 0624667572 | |||
| 07c80f9560 | |||
| 947341a5ee | |||
| 44eef6482c | |||
| f534e69a90 | |||
| 03399fe3fd | |||
| 51c9cec35a | |||
| da660b461f | |||
| 69c6879ac9 | |||
| a1ff12d9ab | |||
| 24ab98be4b | |||
| 49d0c308e8 | |||
| edf1cfefd3 | |||
| 601e495da7 | |||
| e84799e15b | |||
| bdc90ac3a7 | |||
| dfdd775519 | |||
| a36b37b1ea | |||
| ceb0fe22f1 | |||
| aa8a2ea41b | |||
| 159fb62898 | |||
| d8bbd85abb | |||
| 57d260f30a | |||
| ef74205503 | |||
| 89bbf05b63 | |||
| 7d5089f5e8 | |||
| ab33148f81 | |||
| c2766db89d | |||
| f97693f8e1 | |||
| 034c076882 | |||
| 12bed1462f | |||
| 79ff4dd944 | |||
| ec77e3a6fd | |||
| 35977b02ed | |||
| 20b6c2f556 | |||
| 7cda4aaa2c | |||
| 07bdb3a632 | |||
| fe8c55ac63 | |||
| a83edb83ba | |||
| 5f1063acb9 | |||
| f917a38e1a | |||
| accc8aee57 | |||
| 596e3b28b5 | |||
| 077ba02004 | |||
| 75ee3b30e2 | |||
| 78d95cab89 | |||
| 7881d6609a | |||
| 84b3cff936 | |||
| e265f7713c | |||
| 3312d8c05b | |||
| 8b5389e719 | |||
| 6f2de7d31b | |||
| fb208657ea | |||
| eab6bb8314 | |||
| 0b489bc507 | |||
| b2b447516d | |||
| f7cc23d415 | |||
| 6fcd39b4f8 | |||
| 70a74d6615 | |||
| 55c557f227 | |||
| ab5fe1e518 | |||
| 10325fed8b | |||
| 58970282da | |||
| ff005a22a3 | |||
| 92031bbd70 | |||
| f9480f2518 | |||
| 56c570fd19 | |||
| 0b647c7ae5 | |||
| 91589eae34 | |||
| 89a5a45d7e | |||
| 06b91a6e01 | |||
| 19bee763bd | |||
| b0710ff8d1 | |||
| 2342caff32 | |||
| e05a45f6c7 | |||
| c7e33eb6b9 | |||
| 6c1efd74cb | |||
| 43204e52f8 | |||
| 2a7a88ff47 | |||
| 6580aad173 | |||
| 574a5e303c | |||
| 5c75a68715 | |||
| ee618f70ab | |||
| 94038ebb75 | |||
| be0374d197 | |||
| c8b20ecb1a | |||
| 45b29aedf3 | |||
| 855796448c | |||
| 0153726755 | |||
| d47daa2857 | |||
| d9a1cf8c7b | |||
| 59a2f0cdde | |||
| ec00daa5be | |||
| dceb79ad69 | |||
| a41c690a62 | |||
| 62e4169e50 | |||
| 122e71f4a3 | |||
| c6c6d00bad | |||
| ccdeb4d385 | |||
| b7338d5bf0 | |||
| 127f51e758 | |||
| aae1d2f049 | |||
| 9c88dda251 | |||
| 900a5f83da | |||
| 0c532236a5 | |||
| bebab942cc | |||
| 58c15b0287 | |||
| bfae4273c2 | |||
| 7300776a85 | |||
| 3878bd0c76 | |||
| 786e03b0ac | |||
| f8b5637112 | |||
| 2f4944ca21 | |||
| a7c0e82c9e | |||
| 5542107f02 | |||
| 94b5684b42 | |||
| 4a84c311b2 | |||
| 49505a7a45 | |||
| 10b01e62df | |||
| eff8000196 | |||
| c6bb4a6470 | |||
| 3dcc2edceb | |||
| cfd2f8776e | |||
| d11e2410bf | |||
| 83605831ec | |||
| aed1959dbe | |||
| c3c60b331a | |||
| 15606a99fc | |||
| eddc9c9baf | |||
| 7bbc4a6a44 | |||
| 1f39a0cb3e | |||
| 8d680b2222 | |||
| 21ef83bcbe | |||
| 6253162166 | |||
| 1110b284d8 | |||
| 5c6f684808 | |||
| 9b1a449fba | |||
| e4f337edb6 | |||
| 5a9744b429 | |||
| e0237ce526 | |||
| 4d2825d817 | |||
| 09ccd23d0b | |||
| cbbd01b391 | |||
| 539fa8b262 | |||
| 592bbd3180 | |||
| b09792812a | |||
| 9154938827 | |||
| 4f7b8e0934 | |||
| c0f53647b8 | |||
| 3e1b75b814 | |||
| 497170c453 | |||
| 6773412e40 | |||
| 1c8dea909e | |||
| d6ac686a54 | |||
| 5fac13075b | |||
| 6cc774faf4 | |||
| 8f4ec1b960 | |||
| 357be65a69 | |||
| f164833b00 | |||
| 627859ba73 | |||
| a7c239b801 | |||
| 1cabb091e7 | |||
| d0e612b5ff | |||
| 0a8b21d4ab | |||
| 27fd6316f1 | |||
| 4e15364d42 | |||
| 35c194e2eb | |||
| 0c5c6587e5 | |||
| b5a81fbd07 | |||
| 0a0d4fbb70 | |||
| c1669299aa | |||
| d62219d0ad | |||
| 59ddf507e6 | |||
| 4d94d5fe17 | |||
| d64f2e40c5 | |||
| 75d7c40098 | |||
| 7c377e8904 |
+10
-3
@@ -259,6 +259,7 @@ ENDIF(EQEMU_ENABLE_BOTS)
|
|||||||
OPTION(EQEMU_BUILD_SERVER "Build the game server." ON)
|
OPTION(EQEMU_BUILD_SERVER "Build the game server." ON)
|
||||||
OPTION(EQEMU_BUILD_LOGIN "Build the login server." OFF)
|
OPTION(EQEMU_BUILD_LOGIN "Build the login server." OFF)
|
||||||
OPTION(EQEMU_BUILD_HC "Build the headless client." OFF)
|
OPTION(EQEMU_BUILD_HC "Build the headless client." OFF)
|
||||||
|
OPTION(EQEMU_BUILD_LP "Build the login lookup proxy." OFF)
|
||||||
OPTION(EQEMU_BUILD_TESTS "Build utility tests." OFF)
|
OPTION(EQEMU_BUILD_TESTS "Build utility tests." OFF)
|
||||||
OPTION(EQEMU_BUILD_PERL "Build Perl parser." ON)
|
OPTION(EQEMU_BUILD_PERL "Build Perl parser." ON)
|
||||||
OPTION(EQEMU_BUILD_LUA "Build Lua parser." ON)
|
OPTION(EQEMU_BUILD_LUA "Build Lua parser." ON)
|
||||||
@@ -309,7 +310,7 @@ IF(EQEMU_BUILD_PERL)
|
|||||||
INCLUDE_DIRECTORIES(SYSTEM "${PERL_INCLUDE_PATH}")
|
INCLUDE_DIRECTORIES(SYSTEM "${PERL_INCLUDE_PATH}")
|
||||||
ENDIF(EQEMU_BUILD_PERL)
|
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)
|
FIND_PACKAGE(Sodium REQUIRED)
|
||||||
IF(SODIUM_FOUND)
|
IF(SODIUM_FOUND)
|
||||||
@@ -357,11 +358,13 @@ 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/include" )
|
||||||
INCLUDE_DIRECTORIES(SYSTEM "${CMAKE_CURRENT_SOURCE_DIR}/libs/libuv/src")
|
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/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)
|
IF(EQEMU_BUILD_SERVER OR EQEMU_BUILD_LOGIN OR EQEMU_BUILD_TESTS OR EQEMU_BUILD_HC OR EQEMU_BUILD_LP)
|
||||||
ADD_SUBDIRECTORY(common)
|
ADD_SUBDIRECTORY(common)
|
||||||
ADD_SUBDIRECTORY(libs)
|
ADD_SUBDIRECTORY(libs)
|
||||||
ENDIF(EQEMU_BUILD_SERVER OR EQEMU_BUILD_LOGIN OR EQEMU_BUILD_TESTS OR EQEMU_BUILD_HC)
|
ENDIF(EQEMU_BUILD_SERVER OR EQEMU_BUILD_LOGIN OR EQEMU_BUILD_TESTS OR EQEMU_BUILD_HC OR EQEMU_BUILD_LP)
|
||||||
IF(EQEMU_BUILD_SERVER)
|
IF(EQEMU_BUILD_SERVER)
|
||||||
ADD_SUBDIRECTORY(shared_memory)
|
ADD_SUBDIRECTORY(shared_memory)
|
||||||
ADD_SUBDIRECTORY(world)
|
ADD_SUBDIRECTORY(world)
|
||||||
@@ -378,6 +381,10 @@ IF(EQEMU_BUILD_HC)
|
|||||||
ADD_SUBDIRECTORY(hc)
|
ADD_SUBDIRECTORY(hc)
|
||||||
ENDIF(EQEMU_BUILD_HC)
|
ENDIF(EQEMU_BUILD_HC)
|
||||||
|
|
||||||
|
IF(EQEMU_BUILD_LP)
|
||||||
|
ADD_SUBDIRECTORY(lp)
|
||||||
|
ENDIF(EQEMU_BUILD_LP)
|
||||||
|
|
||||||
IF(EQEMU_BUILD_TESTS)
|
IF(EQEMU_BUILD_TESTS)
|
||||||
ADD_SUBDIRECTORY(tests)
|
ADD_SUBDIRECTORY(tests)
|
||||||
ENDIF(EQEMU_BUILD_TESTS)
|
ENDIF(EQEMU_BUILD_TESTS)
|
||||||
|
|||||||
+63
-17
@@ -1,25 +1,71 @@
|
|||||||
EQEMu Changelog (Started on Sept 24, 2003 15:50)
|
EQEMu Changelog (Started on Sept 24, 2003 15:50)
|
||||||
-------------------------------------------------------
|
-------------------------------------------------------
|
||||||
|
|
||||||
|
== 7/14/2017 ==
|
||||||
|
Akkadius: HP Update tuning - HP Updates are now forced when a client is targeted
|
||||||
|
Akkadius: Client position updates should be smoother (granted the client has a good connection)
|
||||||
|
- Clients should also no longer randomly disappear
|
||||||
|
|
||||||
|
== 7/11/2017 ==
|
||||||
|
Akkadius: Raid/Group/XTarget HP/Mana/Endurance updates now only send when percentage changes
|
||||||
|
Akkadius: Raid/Group Mana/Endurance updates should now update real-time once again
|
||||||
|
Akkadius: Fixed an issue with clients looking like they are 'skipping' when they are moving in view of another client
|
||||||
|
Akkadius: Fixed an issue with NPC's who are ghosted in plain view of a client when they are not really there
|
||||||
|
|
||||||
|
== 7/9/2017 ==
|
||||||
|
Akkadius: Fix HP update issues, rework logic for more accurate HP updates
|
||||||
|
Akkadius: Massive reductions in unnecessary network traffic especially during high spam combat fights
|
||||||
|
- HP Updates now only send to others when HP percentage changes (0-100%)
|
||||||
|
- HP Updates were sending excessively even during idle zones when HP wasn't changing at all
|
||||||
|
- Attack animations now only send once per second versus up to a hundred times a second per Mob/Client
|
||||||
|
- 17,000 OP_ClientUpdate packets per second have been observed in combat scenarios, some of the major culprits have been
|
||||||
|
throttled without affecting what the client should see
|
||||||
|
- Before and After packet differences under similar load/tests (Packets per second)
|
||||||
|
- 7,000 - 8,000 OP_Animation pps After: 600-800 pps
|
||||||
|
- 13,0000 - 17,000 OP_MobHealth pps After: 1-10 pps
|
||||||
|
- 15,0000 - 20,000 OP_ClientUpdate pps After: 500-1,000 pps
|
||||||
|
- Packet reports from a 46 client test here:
|
||||||
|
https://gist.github.com/Akkadius/28b7ad2fdd82bdd15ea737c68f404346
|
||||||
|
- Servers who use Marquee HP updates will also recieve far less packet spam as they will only be sent when HP changes
|
||||||
|
|
||||||
|
== 7/1/2017 ==
|
||||||
|
Akkadius: Resolve issues with NPC's hopping to the ceiling in small corridors
|
||||||
|
Akkadius: Improved grounding issues with NPC's during combat
|
||||||
|
Akkadius: Improved scenarios where NPC's need to be dragged out of the ground - they should correct themselves far more consistently
|
||||||
|
- Scenarios where an NPC is coming up from the bottom floor, or from the top floor, they will correct much better
|
||||||
|
- A video of these tests can be found here: https://www.youtube.com/watch?v=HtC7bVNM7ZQ&feature=youtu.be
|
||||||
|
|
||||||
|
== 6/28/2017 ==
|
||||||
|
Akkadius: Fixed issues with Z correctness when NPCs are pathing on normal grids
|
||||||
|
Akkadius: Fixed issues with Z correctness when NPCs are engaged with players following
|
||||||
|
Akkadius: NPC corpses should fall into the ground far less
|
||||||
|
|
||||||
|
== 6/25/2017 ==
|
||||||
|
Akkadius: New rules made by developers are now automatically created when world boots up, this keeps
|
||||||
|
from having to issue schema SQL updates every time rules are added.
|
||||||
|
- Whenever a rule isn't present in the database, it will be automatically created
|
||||||
|
Akkadius: Sped up saylink retrieval x1000 helpful for dialogues, plugins with many saylinks
|
||||||
|
|
||||||
== 4/16/2017 ==
|
== 4/16/2017 ==
|
||||||
KLS: Merge eqstream branch
|
KLS: Merge eqstream branch
|
||||||
-UDP client stack completely rewritten should both have better throughput and recover better (peq has had far fewer reports of desyncs).
|
- UDP client stack completely rewritten should both have better throughput and recover better (peq has had far fewer reports of desyncs).
|
||||||
-TCP Server to Server connection stack completely rewritten.
|
- TCP Server to Server connection stack completely rewritten.
|
||||||
-Server connections reconnect much more reliably and quickly now.
|
- Server connections reconnect much more reliably and quickly now.
|
||||||
-Now supports optional packet encryption via libsodium (https://download.libsodium.org/doc/).
|
- Now supports optional packet encryption via libsodium (https://download.libsodium.org/doc/).
|
||||||
-Protocol behind the tcp connections has changed (see breaking changes section).
|
- Protocol behind the tcp connections has changed (see breaking changes section).
|
||||||
-API significantly changed and should be easier to write new servers or handlers for.
|
- API significantly changed and should be easier to write new servers or handlers for.
|
||||||
-Telnet console connection has been separated out from the current port (see breaking changes section).
|
- Telnet console connection has been separated out from the current port (see breaking changes section).
|
||||||
-Because of changes to the TCP stack, lsreconnect and echo have been disabled.
|
- Because of changes to the TCP stack, lsreconnect and echo have been disabled.
|
||||||
-The server tic rate has been changed to be approx 30 fps from 500+ fps.
|
- The server tic rate has been changed to be approx 30 fps from 500+ fps.
|
||||||
-Changed how missiles and movement were calculated slightly to account for this (Missiles in particular are not perfect but close enough).
|
- Changed how missiles and movement were calculated slightly to account for this (Missiles in particular are not perfect but close enough).
|
||||||
|
|
||||||
-Breaking changes:
|
- Breaking changes:
|
||||||
-Users who use the cmake install feature should be aware that the install directory is now %cmake_install_dir%/bin instead of just %cmake_install_dir%/
|
- Users who use the cmake install feature should be aware that the install directory is now %cmake_install_dir%/bin instead of just %cmake_install_dir%/
|
||||||
-To support new features such as encryption the underlying protocol had to change... however some servers such as the public login server will be slow to change so we've included a compatibility layer for legacy login connections:
|
- To support new features such as encryption the underlying protocol had to change... however some servers such as the public login server will be slow to change so we've included a compatibility layer for legacy login connections:
|
||||||
-You should add <legacy>1</legacy> to the login section of your configuration file when connecting to a server that is using the old protocol.
|
- You should add <legacy>1</legacy> to the login section of your configuration file when connecting to a server that is using the old protocol.
|
||||||
-The central eqemu login server uses the old protocol and probably will for the forseeable future so if your server is connecting to it be sure to add that tag to your configuration file in that section.
|
- The central eqemu login server uses the old protocol and probably will for the forseeable future so if your server is connecting to it be sure to add that tag to your configuration file in that section.
|
||||||
-Telnet no longer uses the same port as the Server to Server connection and because of this the tcp tag no longer has any effect on telnet connections.
|
- Telnet no longer uses the same port as the Server to Server connection and because of this the tcp tag no longer has any effect on telnet connections.
|
||||||
-To enable telnet you need to add a telnet tag in the world section of configuration such as:
|
- To enable telnet you need to add a telnet tag in the world section of configuration such as:
|
||||||
<telnet ip="0.0.0.0" port="9001" enabled="true"/>
|
<telnet ip="0.0.0.0" port="9001" enabled="true"/>
|
||||||
|
|
||||||
== 4/1/2017 ==
|
== 4/1/2017 ==
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
|
|||||||
SET(common_sources
|
SET(common_sources
|
||||||
base_packet.cpp
|
base_packet.cpp
|
||||||
classes.cpp
|
classes.cpp
|
||||||
|
compression.cpp
|
||||||
condition.cpp
|
condition.cpp
|
||||||
crash.cpp
|
crash.cpp
|
||||||
crc16.cpp
|
crc16.cpp
|
||||||
@@ -113,6 +114,7 @@ SET(common_headers
|
|||||||
base_data.h
|
base_data.h
|
||||||
bodytypes.h
|
bodytypes.h
|
||||||
classes.h
|
classes.h
|
||||||
|
compression.h
|
||||||
condition.h
|
condition.h
|
||||||
crash.h
|
crash.h
|
||||||
crc16.h
|
crc16.h
|
||||||
|
|||||||
@@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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);
|
||||||
|
}
|
||||||
@@ -408,6 +408,7 @@ N(OP_ReloadUI),
|
|||||||
N(OP_RemoveAllDoors),
|
N(OP_RemoveAllDoors),
|
||||||
N(OP_RemoveBlockedBuffs),
|
N(OP_RemoveBlockedBuffs),
|
||||||
N(OP_RemoveNimbusEffect),
|
N(OP_RemoveNimbusEffect),
|
||||||
|
N(OP_RemoveTrap),
|
||||||
N(OP_Report),
|
N(OP_Report),
|
||||||
N(OP_ReqClientSpawn),
|
N(OP_ReqClientSpawn),
|
||||||
N(OP_ReqNewZone),
|
N(OP_ReqNewZone),
|
||||||
@@ -523,6 +524,7 @@ N(OP_TributeToggle),
|
|||||||
N(OP_TributeUpdate),
|
N(OP_TributeUpdate),
|
||||||
N(OP_Untargetable),
|
N(OP_Untargetable),
|
||||||
N(OP_UpdateAA),
|
N(OP_UpdateAA),
|
||||||
|
N(OP_UpdateAura),
|
||||||
N(OP_UpdateLeadershipAA),
|
N(OP_UpdateLeadershipAA),
|
||||||
N(OP_VetClaimReply),
|
N(OP_VetClaimReply),
|
||||||
N(OP_VetClaimRequest),
|
N(OP_VetClaimRequest),
|
||||||
|
|||||||
+22
-18
@@ -27,7 +27,7 @@
|
|||||||
//SpawnAppearance types: (compared two clients for server-originating types: SoF & RoF2)
|
//SpawnAppearance types: (compared two clients for server-originating types: SoF & RoF2)
|
||||||
#define AT_Die 0 // this causes the client to keel over and zone to bind point (default action)
|
#define AT_Die 0 // this causes the client to keel over and zone to bind point (default action)
|
||||||
#define AT_WhoLevel 1 // the level that shows up on /who
|
#define AT_WhoLevel 1 // the level that shows up on /who
|
||||||
//#define AT_2 2 // unknown
|
#define AT_HPMax 2 // idk
|
||||||
#define AT_Invis 3 // 0 = visible, 1 = invisible
|
#define AT_Invis 3 // 0 = visible, 1 = invisible
|
||||||
#define AT_PVP 4 // 0 = blue, 1 = pvp (red)
|
#define AT_PVP 4 // 0 = blue, 1 = pvp (red)
|
||||||
#define AT_Light 5 // light type emitted by player (lightstone, shiny shield)
|
#define AT_Light 5 // light type emitted by player (lightstone, shiny shield)
|
||||||
@@ -36,33 +36,37 @@
|
|||||||
#define AT_SpawnID 16 // server to client, sets player spawn id
|
#define AT_SpawnID 16 // server to client, sets player spawn id
|
||||||
#define AT_HP 17 // Client->Server, my HP has changed (like regen tic)
|
#define AT_HP 17 // Client->Server, my HP has changed (like regen tic)
|
||||||
#define AT_Linkdead 18 // 0 = normal, 1 = linkdead
|
#define AT_Linkdead 18 // 0 = normal, 1 = linkdead
|
||||||
#define AT_Levitate 19 // 0=off, 1=flymode, 2=levitate
|
#define AT_Levitate 19 // 0=off, 1=flymode, 2=levitate max 5, see GravityBehavior enum
|
||||||
#define AT_GM 20 // 0 = normal, 1 = GM - all odd numbers seem to make it GM
|
#define AT_GM 20 // 0 = normal, 1 = GM - all odd numbers seem to make it GM
|
||||||
#define AT_Anon 21 // 0 = normal, 1 = anon, 2 = roleplay
|
#define AT_Anon 21 // 0 = normal, 1 = anon, 2 = roleplay
|
||||||
#define AT_GuildID 22
|
#define AT_GuildID 22
|
||||||
#define AT_GuildRank 23 // 0=member, 1=officer, 2=leader
|
#define AT_GuildRank 23 // 0=member, 1=officer, 2=leader
|
||||||
#define AT_AFK 24 // 0 = normal, 1 = afk
|
#define AT_AFK 24 // 0 = normal, 1 = afk
|
||||||
#define AT_Pet 25 // Param is EntityID of owner, or 0 for when charm breaks
|
#define AT_Pet 25 // Param is EntityID of owner, or 0 for when charm breaks
|
||||||
//#define AT_27 27 // unknown
|
#define AT_Summoned 27 // Unsure
|
||||||
#define AT_Split 28 // 0 = normal, 1 = autosplit on (not showing in SoF+) (client-to-server only)
|
#define AT_Split 28 // 0 = normal, 1 = autosplit on (not showing in SoF+) (client-to-server only)
|
||||||
#define AT_Size 29 // spawn's size (present: SoF, absent: RoF2)
|
#define AT_Size 29 // spawn's size (present: SoF, absent: RoF2)
|
||||||
//#define AT_30 30 // unknown
|
#define AT_SetType 30 // 0 = PC, 1 = NPC, 2 <= = corpse
|
||||||
#define AT_NPCName 31 // change PC's name's color to NPC color 0 = normal, 1 = npc name
|
#define AT_NPCName 31 // change PC's name's color to NPC color 0 = normal, 1 = npc name, Trader on RoF2?
|
||||||
//#define AT_32 32 // unknown
|
#define AT_AARank 32 // AA Rank Title ID thingy, does is this the title in /who?
|
||||||
//#define AT_33 33 // unknown
|
#define AT_CancelSneakHide 33 // Turns off Hide and Sneak
|
||||||
//#define AT_34 34 // unknown (present: SoF, absent: RoF2)
|
//#define AT_34 34 // unknown (present: SoF, absent: RoF2)
|
||||||
//#define AT_35 35 // unknown
|
#define AT_AreaHPRegen 35 // guild hall regen pool sets to value * 0.001
|
||||||
//#define AT_36 36 // unknown
|
#define AT_AreaManaRegen 36 // guild hall regen pool sets to value * 0.001
|
||||||
//#define AT_37 37 // unknown
|
#define AT_AreaEndRegen 37 // guild hall regen pool sets to value * 0.001
|
||||||
//#define AT_38 38 // unknown
|
#define AT_FreezeBuffs 38 // Freezes beneficial buff timers
|
||||||
//#define AT_39 39 // unknown
|
#define AT_NpcTintIndex 39 // not 100% sure
|
||||||
|
#define AT_GroupConsent 40 // auto consent group
|
||||||
|
#define AT_RaidConsent 41 // auto consent raid
|
||||||
|
#define AT_GuildConsent 42 // auto consent guild
|
||||||
#define AT_ShowHelm 43 // 0 = hide graphic, 1 = show graphic
|
#define AT_ShowHelm 43 // 0 = hide graphic, 1 = show graphic
|
||||||
#define AT_DamageState 44 // The damage state of a destructible object (0 through 4)
|
#define AT_DamageState 44 // The damage state of a destructible object (0 through 10) plays soundids most only have 2 or 4 states though
|
||||||
//#define AT_46 46 // unknown
|
#define AT_EQPlayers 45 // /eqplayersupdate
|
||||||
//#define AT_48 48 // unknown
|
#define AT_FindBits 46 // set FindBits, whatever those are!
|
||||||
//#define AT_49 49 // unknown
|
#define AT_TextureType 48 // TextureType
|
||||||
//#define AT_52 52 // (absent: SoF, present: RoF2) (not a replacement for RoF absent 29 or 34)
|
#define AT_FacePick 49 // Turns off face pick window? maybe ...
|
||||||
//#define AT_53 53 // (absent: SoF, present: RoF2) (not a replacement for RoF absent 29 or 34)
|
#define AT_GuildShow 52 // this is what MQ2 call sit, not sure
|
||||||
|
#define AT_Offline 53 // Offline mode
|
||||||
|
|
||||||
//#define AT_Trader 300 // Bazaar Trader Mode (not present in SoF or RoF2)
|
//#define AT_Trader 300 // Bazaar Trader Mode (not present in SoF or RoF2)
|
||||||
|
|
||||||
|
|||||||
@@ -305,6 +305,7 @@ union
|
|||||||
uint8 DestructibleUnk8;
|
uint8 DestructibleUnk8;
|
||||||
uint32 DestructibleUnk9;
|
uint32 DestructibleUnk9;
|
||||||
bool targetable_with_hotkey;
|
bool targetable_with_hotkey;
|
||||||
|
bool show_name;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -5332,6 +5333,24 @@ struct fling_struct {
|
|||||||
/* 28 */
|
/* 28 */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// used when action == 0
|
||||||
|
struct AuraCreate_Struct {
|
||||||
|
/* 00 */ uint32 action; // 0 = add, 1 = delete, 2 = reset
|
||||||
|
/* 04 */ uint32 type; // unsure -- normal auras show 1 clicky (ex. Circle of Power) show 0
|
||||||
|
/* 08 */ char aura_name[64];
|
||||||
|
/* 72 */ uint32 entity_id;
|
||||||
|
/* 76 */ uint32 icon;
|
||||||
|
/* 80 */
|
||||||
|
};
|
||||||
|
|
||||||
|
// used when action == 1
|
||||||
|
struct AuraDestory_Struct {
|
||||||
|
/* 00 */ uint32 action; // 0 = add, 1 = delete, 2 = reset
|
||||||
|
/* 04 */ uint32 entity_id;
|
||||||
|
/* 08 */
|
||||||
|
};
|
||||||
|
// I think we can assume it's just action for 2, client doesn't seem to do anything with the rest of the data in that case
|
||||||
|
|
||||||
// Restore structure packing to default
|
// Restore structure packing to default
|
||||||
#pragma pack()
|
#pragma pack()
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,8 @@
|
|||||||
#include "global_define.h"
|
#include "global_define.h"
|
||||||
#include "eq_stream_proxy.h"
|
#include "eq_stream_proxy.h"
|
||||||
#include "struct_strategy.h"
|
#include "struct_strategy.h"
|
||||||
|
#include "eqemu_logsys.h"
|
||||||
|
#include "opcodemgr.h"
|
||||||
|
|
||||||
|
|
||||||
EQStreamProxy::EQStreamProxy(std::shared_ptr<EQStreamInterface> &stream, const StructStrategy *structs, OpcodeManager **opcodes)
|
EQStreamProxy::EQStreamProxy(std::shared_ptr<EQStreamInterface> &stream, const StructStrategy *structs, OpcodeManager **opcodes)
|
||||||
@@ -39,6 +41,11 @@ void EQStreamProxy::QueuePacket(const EQApplicationPacket *p, bool ack_req) {
|
|||||||
if(p == nullptr)
|
if(p == nullptr)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if (p->GetOpcode() != OP_SpecialMesg) {
|
||||||
|
Log(Logs::General, Logs::Server_Client_Packet, "[%s - 0x%04x] [Size: %u]", OpcodeManager::EmuToName(p->GetOpcode()), p->GetOpcode(), p->Size());
|
||||||
|
Log(Logs::General, Logs::Server_Client_Packet_With_Dump, "[%s - 0x%04x] [Size: %u] %s", OpcodeManager::EmuToName(p->GetOpcode()), p->GetOpcode(), p->Size(), DumpPacketToString(p).c_str());
|
||||||
|
}
|
||||||
|
|
||||||
EQApplicationPacket *newp = p->Copy();
|
EQApplicationPacket *newp = p->Copy();
|
||||||
FastQueuePacket(&newp, ack_req);
|
FastQueuePacket(&newp, ack_req);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -86,6 +86,8 @@ enum LogCategory {
|
|||||||
Login_Server,
|
Login_Server,
|
||||||
Client_Login,
|
Client_Login,
|
||||||
Headless_Client,
|
Headless_Client,
|
||||||
|
HP_Update,
|
||||||
|
FixZ,
|
||||||
MaxCategoryID /* Don't Remove this*/
|
MaxCategoryID /* Don't Remove this*/
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -135,7 +137,10 @@ static const char* LogCategoryName[LogCategory::MaxCategoryID] = {
|
|||||||
"Packet :: Server -> Client (Dump)",
|
"Packet :: Server -> Client (Dump)",
|
||||||
"Packet :: Client -> Server (Dump)",
|
"Packet :: Client -> Server (Dump)",
|
||||||
"Login Server",
|
"Login Server",
|
||||||
"Client Login"
|
"Client Login",
|
||||||
|
"Headless Client",
|
||||||
|
"HP Update",
|
||||||
|
"FixZ"
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,32 +1,35 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
#include "../any.h"
|
||||||
#include "event_loop.h"
|
#include "event_loop.h"
|
||||||
|
|
||||||
namespace EQ {
|
namespace EQ {
|
||||||
class BackgroundTask
|
class BackgroundTask
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
typedef std::function<void(void)> BackgroundTaskFunction;
|
typedef std::function<void(EQEmu::Any&)> BackgroundTaskFunction;
|
||||||
struct BackgroundTaskBaton
|
struct BackgroundTaskBaton
|
||||||
{
|
{
|
||||||
BackgroundTaskFunction fn;
|
BackgroundTaskFunction fn;
|
||||||
BackgroundTaskFunction on_finish;
|
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;
|
uv_work_t *m_work = new uv_work_t;
|
||||||
memset(m_work, 0, sizeof(uv_work_t));
|
memset(m_work, 0, sizeof(uv_work_t));
|
||||||
BackgroundTaskBaton *baton = new BackgroundTaskBaton();
|
BackgroundTaskBaton *baton = new BackgroundTaskBaton();
|
||||||
baton->fn = fn;
|
baton->fn = fn;
|
||||||
baton->on_finish = on_finish;
|
baton->on_finish = on_finish;
|
||||||
|
baton->data = data;
|
||||||
|
|
||||||
m_work->data = baton;
|
m_work->data = baton;
|
||||||
uv_queue_work(EventLoop::Get().Handle(), m_work, [](uv_work_t* req) {
|
uv_queue_work(EventLoop::Get().Handle(), m_work, [](uv_work_t* req) {
|
||||||
BackgroundTaskBaton *baton = (BackgroundTaskBaton*)req->data;
|
BackgroundTaskBaton *baton = (BackgroundTaskBaton*)req->data;
|
||||||
baton->fn();
|
baton->fn(baton->data);
|
||||||
}, [](uv_work_t* req, int status) {
|
}, [](uv_work_t* req, int status) {
|
||||||
BackgroundTaskBaton *baton = (BackgroundTaskBaton*)req->data;
|
BackgroundTaskBaton *baton = (BackgroundTaskBaton*)req->data;
|
||||||
baton->on_finish();
|
baton->on_finish(baton->data);
|
||||||
delete baton;
|
delete baton;
|
||||||
delete req;
|
delete req;
|
||||||
});
|
});
|
||||||
|
|||||||
+319
-318
@@ -135,26 +135,26 @@ void EQ::Net::DaybreakConnectionManager::Process()
|
|||||||
|
|
||||||
switch (status)
|
switch (status)
|
||||||
{
|
{
|
||||||
case StatusConnecting: {
|
case StatusConnecting: {
|
||||||
auto time_since_last_send = std::chrono::duration_cast<std::chrono::milliseconds>(now - connection->m_last_send);
|
|
||||||
if ((size_t)time_since_last_send.count() > m_options.connect_delay_ms) {
|
|
||||||
connection->SendConnect();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case StatusConnected: {
|
|
||||||
if (m_options.keepalive_delay_ms != 0) {
|
|
||||||
auto time_since_last_send = std::chrono::duration_cast<std::chrono::milliseconds>(now - connection->m_last_send);
|
auto time_since_last_send = std::chrono::duration_cast<std::chrono::milliseconds>(now - connection->m_last_send);
|
||||||
if ((size_t)time_since_last_send.count() > m_options.keepalive_delay_ms) {
|
if ((size_t)time_since_last_send.count() > m_options.connect_delay_ms) {
|
||||||
connection->SendKeepAlive();
|
connection->SendConnect();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case StatusConnected: {
|
||||||
|
if (m_options.keepalive_delay_ms != 0) {
|
||||||
|
auto time_since_last_send = std::chrono::duration_cast<std::chrono::milliseconds>(now - connection->m_last_send);
|
||||||
|
if ((size_t)time_since_last_send.count() > m_options.keepalive_delay_ms) {
|
||||||
|
connection->SendKeepAlive();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
case StatusDisconnecting:
|
||||||
case StatusDisconnecting:
|
connection->Process();
|
||||||
connection->Process();
|
break;
|
||||||
break;
|
default:
|
||||||
default:
|
break;
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
iter++;
|
iter++;
|
||||||
@@ -170,12 +170,12 @@ void EQ::Net::DaybreakConnectionManager::ProcessResend()
|
|||||||
|
|
||||||
switch (status)
|
switch (status)
|
||||||
{
|
{
|
||||||
case StatusConnected:
|
case StatusConnected:
|
||||||
case StatusDisconnecting:
|
case StatusDisconnecting:
|
||||||
connection->ProcessResend();
|
connection->ProcessResend();
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
iter++;
|
iter++;
|
||||||
@@ -277,7 +277,7 @@ EQ::Net::DaybreakConnection::DaybreakConnection(DaybreakConnectionManager *owner
|
|||||||
m_encode_passes[1] = owner->m_options.encode_passes[1];
|
m_encode_passes[1] = owner->m_options.encode_passes[1];
|
||||||
m_hold_time = Clock::now();
|
m_hold_time = Clock::now();
|
||||||
m_buffered_packets_length = 0;
|
m_buffered_packets_length = 0;
|
||||||
m_rolling_ping = 900;
|
m_rolling_ping = 500;
|
||||||
m_resend_delay = (m_rolling_ping * m_owner->m_options.resend_delay_factor) + m_owner->m_options.resend_delay_ms;
|
m_resend_delay = (m_rolling_ping * m_owner->m_options.resend_delay_factor) + m_owner->m_options.resend_delay_ms;
|
||||||
m_combined.reset(new char[512]);
|
m_combined.reset(new char[512]);
|
||||||
m_combined[0] = 0;
|
m_combined[0] = 0;
|
||||||
@@ -300,7 +300,7 @@ EQ::Net::DaybreakConnection::DaybreakConnection(DaybreakConnectionManager *owner
|
|||||||
m_crc_bytes = 0;
|
m_crc_bytes = 0;
|
||||||
m_hold_time = Clock::now();
|
m_hold_time = Clock::now();
|
||||||
m_buffered_packets_length = 0;
|
m_buffered_packets_length = 0;
|
||||||
m_rolling_ping = 900;
|
m_rolling_ping = 500;
|
||||||
m_resend_delay = (m_rolling_ping * m_owner->m_options.resend_delay_factor) + m_owner->m_options.resend_delay_ms;
|
m_resend_delay = (m_rolling_ping * m_owner->m_options.resend_delay_factor) + m_owner->m_options.resend_delay_ms;
|
||||||
m_combined.reset(new char[512]);
|
m_combined.reset(new char[512]);
|
||||||
m_combined[0] = 0;
|
m_combined[0] = 0;
|
||||||
@@ -382,13 +382,8 @@ void EQ::Net::DaybreakConnection::ProcessPacket(Packet &p)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (p.GetInt8(0) != 0) {
|
|
||||||
LogF(Logs::Detail, Logs::Netcode, "Error parsing packet, did not start with a 0 frame, not a valid protocol packet.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto opcode = p.GetInt8(1);
|
auto opcode = p.GetInt8(1);
|
||||||
if (opcode == OP_KeepAlive || opcode == OP_OutboundPing) {
|
if (p.GetInt8(0) == 0 && (opcode == OP_KeepAlive || opcode == OP_OutboundPing)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -406,14 +401,20 @@ void EQ::Net::DaybreakConnection::ProcessPacket(Packet &p)
|
|||||||
|
|
||||||
for (int i = 1; i >= 0; --i) {
|
for (int i = 1; i >= 0; --i) {
|
||||||
switch (m_encode_passes[i]) {
|
switch (m_encode_passes[i]) {
|
||||||
case EncodeCompression:
|
case EncodeCompression:
|
||||||
Decompress(temp, DaybreakHeader::size(), temp.Length() - DaybreakHeader::size());
|
if(temp.GetInt8(0) == 0)
|
||||||
break;
|
Decompress(temp, DaybreakHeader::size(), temp.Length() - DaybreakHeader::size());
|
||||||
case EncodeXOR:
|
else
|
||||||
Decode(temp, DaybreakHeader::size(), temp.Length() - DaybreakHeader::size());
|
Decompress(temp, 1, temp.Length() - 1);
|
||||||
break;
|
break;
|
||||||
default:
|
case EncodeXOR:
|
||||||
break;
|
if (temp.GetInt8(0) == 0)
|
||||||
|
Decode(temp, DaybreakHeader::size(), temp.Length() - DaybreakHeader::size());
|
||||||
|
else
|
||||||
|
Decode(temp, 1, temp.Length() - 1);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -424,11 +425,14 @@ void EQ::Net::DaybreakConnection::ProcessPacket(Packet &p)
|
|||||||
|
|
||||||
for (int i = 1; i >= 0; --i) {
|
for (int i = 1; i >= 0; --i) {
|
||||||
switch (m_encode_passes[i]) {
|
switch (m_encode_passes[i]) {
|
||||||
case EncodeXOR:
|
case EncodeXOR:
|
||||||
Decode(temp, DaybreakHeader::size(), temp.Length() - DaybreakHeader::size());
|
if (temp.GetInt8(0) == 0)
|
||||||
break;
|
Decode(temp, DaybreakHeader::size(), temp.Length() - DaybreakHeader::size());
|
||||||
default:
|
else
|
||||||
break;
|
Decode(temp, 1, temp.Length() - 1);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -490,274 +494,274 @@ void EQ::Net::DaybreakConnection::ProcessDecodedPacket(const Packet &p)
|
|||||||
}
|
}
|
||||||
|
|
||||||
switch (p.GetInt8(1)) {
|
switch (p.GetInt8(1)) {
|
||||||
case OP_Combined: {
|
case OP_Combined: {
|
||||||
if (m_status == StatusDisconnecting) {
|
if (m_status == StatusDisconnecting) {
|
||||||
SendDisconnect();
|
SendDisconnect();
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
char *current = (char*)p.Data() + 2;
|
|
||||||
char *end = (char*)p.Data() + p.Length();
|
|
||||||
while (current < end) {
|
|
||||||
uint8_t subpacket_length = *(uint8_t*)current;
|
|
||||||
current += 1;
|
|
||||||
|
|
||||||
if (end < current + subpacket_length) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ProcessDecodedPacket(StaticPacket(current, subpacket_length));
|
char *current = (char*)p.Data() + 2;
|
||||||
current += subpacket_length;
|
char *end = (char*)p.Data() + p.Length();
|
||||||
}
|
while (current < end) {
|
||||||
break;
|
uint8_t subpacket_length = *(uint8_t*)current;
|
||||||
}
|
current += 1;
|
||||||
|
|
||||||
case OP_AppCombined:
|
if (end < current + subpacket_length) {
|
||||||
{
|
return;
|
||||||
if (m_status == StatusDisconnecting) {
|
|
||||||
SendDisconnect();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t *current = (uint8_t*)p.Data() + 2;
|
|
||||||
uint8_t *end = (uint8_t*)p.Data() + p.Length();
|
|
||||||
|
|
||||||
while (current < end) {
|
|
||||||
uint32_t subpacket_length = 0;
|
|
||||||
if (*current == 0xFF)
|
|
||||||
{
|
|
||||||
if (end < current + 3) {
|
|
||||||
throw std::out_of_range("Error in OP_AppCombined, end < current + 3");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (*(current + 1) == 0xFF && *(current + 2) == 0xFF) {
|
ProcessDecodedPacket(StaticPacket(current, subpacket_length));
|
||||||
if (end < current + 7) {
|
current += subpacket_length;
|
||||||
throw std::out_of_range("Error in OP_AppCombined, end < current + 7");
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case OP_AppCombined:
|
||||||
|
{
|
||||||
|
if (m_status == StatusDisconnecting) {
|
||||||
|
SendDisconnect();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t *current = (uint8_t*)p.Data() + 2;
|
||||||
|
uint8_t *end = (uint8_t*)p.Data() + p.Length();
|
||||||
|
|
||||||
|
while (current < end) {
|
||||||
|
uint32_t subpacket_length = 0;
|
||||||
|
if (*current == 0xFF)
|
||||||
|
{
|
||||||
|
if (end < current + 3) {
|
||||||
|
throw std::out_of_range("Error in OP_AppCombined, end < current + 3");
|
||||||
}
|
}
|
||||||
|
|
||||||
subpacket_length = (uint32_t)(
|
if (*(current + 1) == 0xFF && *(current + 2) == 0xFF) {
|
||||||
(*(current + 3) << 24) |
|
if (end < current + 7) {
|
||||||
(*(current + 4) << 16) |
|
throw std::out_of_range("Error in OP_AppCombined, end < current + 7");
|
||||||
(*(current + 5) << 8) |
|
}
|
||||||
(*(current + 6))
|
|
||||||
);
|
subpacket_length = (uint32_t)(
|
||||||
current += 7;
|
(*(current + 3) << 24) |
|
||||||
|
(*(current + 4) << 16) |
|
||||||
|
(*(current + 5) << 8) |
|
||||||
|
(*(current + 6))
|
||||||
|
);
|
||||||
|
current += 7;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
subpacket_length = (uint32_t)(
|
||||||
|
(*(current + 1) << 8) |
|
||||||
|
(*(current + 2))
|
||||||
|
);
|
||||||
|
current += 3;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
subpacket_length = (uint32_t)(
|
subpacket_length = (uint32_t)((*(current + 0)));
|
||||||
(*(current + 1) << 8) |
|
current += 1;
|
||||||
(*(current + 2))
|
}
|
||||||
);
|
|
||||||
current += 3;
|
ProcessDecodedPacket(StaticPacket(current, subpacket_length));
|
||||||
|
current += subpacket_length;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
case OP_SessionRequest:
|
||||||
|
{
|
||||||
|
if (m_status == StatusConnected) {
|
||||||
|
auto request = p.GetSerialize<DaybreakConnect>(0);
|
||||||
|
|
||||||
|
if (NetworkToHost(request.connect_code) != m_connect_code) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
DaybreakConnectReply reply;
|
||||||
|
reply.zero = 0;
|
||||||
|
reply.opcode = OP_SessionResponse;
|
||||||
|
reply.connect_code = HostToNetwork(m_connect_code);
|
||||||
|
reply.encode_key = HostToNetwork(m_encode_key);
|
||||||
|
reply.crc_bytes = m_crc_bytes;
|
||||||
|
reply.max_packet_size = HostToNetwork(m_max_packet_size);
|
||||||
|
reply.encode_pass1 = m_encode_passes[0];
|
||||||
|
reply.encode_pass2 = m_encode_passes[1];
|
||||||
|
DynamicPacket p;
|
||||||
|
p.PutSerialize(0, reply);
|
||||||
|
InternalSend(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case OP_SessionResponse:
|
||||||
|
{
|
||||||
|
if (m_status == StatusConnecting) {
|
||||||
|
auto reply = p.GetSerialize<DaybreakConnectReply>(0);
|
||||||
|
|
||||||
|
if (m_connect_code == reply.connect_code) {
|
||||||
|
m_encode_key = reply.encode_key;
|
||||||
|
m_crc_bytes = reply.crc_bytes;
|
||||||
|
m_encode_passes[0] = (DaybreakEncodeType)reply.encode_pass1;
|
||||||
|
m_encode_passes[1] = (DaybreakEncodeType)reply.encode_pass2;
|
||||||
|
m_max_packet_size = reply.max_packet_size;
|
||||||
|
ChangeStatus(StatusConnected);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
break;
|
||||||
subpacket_length = (uint32_t)((*(current + 0)));
|
|
||||||
current += 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
ProcessDecodedPacket(StaticPacket(current, subpacket_length));
|
|
||||||
current += subpacket_length;
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
case OP_SessionRequest:
|
case OP_Packet:
|
||||||
{
|
case OP_Packet2:
|
||||||
if (m_status == StatusConnected) {
|
case OP_Packet3:
|
||||||
auto request = p.GetSerialize<DaybreakConnect>(0);
|
case OP_Packet4:
|
||||||
|
{
|
||||||
if (NetworkToHost(request.connect_code) != m_connect_code) {
|
if (m_status == StatusDisconnecting) {
|
||||||
|
SendDisconnect();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
DaybreakConnectReply reply;
|
auto header = p.GetSerialize<DaybreakReliableHeader>(0);
|
||||||
reply.zero = 0;
|
auto sequence = NetworkToHost(header.sequence);
|
||||||
reply.opcode = OP_SessionResponse;
|
auto stream_id = header.opcode - OP_Packet;
|
||||||
reply.connect_code = HostToNetwork(m_connect_code);
|
auto stream = &m_streams[stream_id];
|
||||||
reply.encode_key = HostToNetwork(m_encode_key);
|
|
||||||
reply.crc_bytes = m_crc_bytes;
|
|
||||||
reply.max_packet_size = HostToNetwork(m_max_packet_size);
|
|
||||||
reply.encode_pass1 = m_encode_passes[0];
|
|
||||||
reply.encode_pass2 = m_encode_passes[1];
|
|
||||||
DynamicPacket p;
|
|
||||||
p.PutSerialize(0, reply);
|
|
||||||
InternalSend(p);
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
auto order = CompareSequence(stream->sequence_in, sequence);
|
||||||
}
|
if (order == SequenceFuture) {
|
||||||
|
SendOutOfOrderAck(stream_id, sequence);
|
||||||
case OP_SessionResponse:
|
AddToQueue(stream_id, sequence, p);
|
||||||
{
|
|
||||||
if (m_status == StatusConnecting) {
|
|
||||||
auto reply = p.GetSerialize<DaybreakConnectReply>(0);
|
|
||||||
|
|
||||||
if (m_connect_code == reply.connect_code) {
|
|
||||||
m_encode_key = reply.encode_key;
|
|
||||||
m_crc_bytes = reply.crc_bytes;
|
|
||||||
m_encode_passes[0] = (DaybreakEncodeType)reply.encode_pass1;
|
|
||||||
m_encode_passes[1] = (DaybreakEncodeType)reply.encode_pass2;
|
|
||||||
m_max_packet_size = reply.max_packet_size;
|
|
||||||
ChangeStatus(StatusConnected);
|
|
||||||
}
|
}
|
||||||
}
|
else if (order == SequencePast) {
|
||||||
break;
|
SendAck(stream_id, stream->sequence_in - 1);
|
||||||
}
|
|
||||||
|
|
||||||
case OP_Packet:
|
|
||||||
case OP_Packet2:
|
|
||||||
case OP_Packet3:
|
|
||||||
case OP_Packet4:
|
|
||||||
{
|
|
||||||
if (m_status == StatusDisconnecting) {
|
|
||||||
SendDisconnect();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto header = p.GetSerialize<DaybreakReliableHeader>(0);
|
|
||||||
auto sequence = NetworkToHost(header.sequence);
|
|
||||||
auto stream_id = header.opcode - OP_Packet;
|
|
||||||
auto stream = &m_streams[stream_id];
|
|
||||||
|
|
||||||
auto order = CompareSequence(stream->sequence_in, sequence);
|
|
||||||
if (order == SequenceFuture) {
|
|
||||||
SendOutOfOrderAck(stream_id, sequence);
|
|
||||||
AddToQueue(stream_id, sequence, p);
|
|
||||||
}
|
|
||||||
else if (order == SequencePast) {
|
|
||||||
SendAck(stream_id, stream->sequence_in - 1);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
RemoveFromQueue(stream_id, sequence);
|
|
||||||
SendAck(stream_id, stream->sequence_in);
|
|
||||||
stream->sequence_in++;
|
|
||||||
StaticPacket next((char*)p.Data() + DaybreakReliableHeader::size(), p.Length() - DaybreakReliableHeader::size());
|
|
||||||
ProcessDecodedPacket(next);
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case OP_Fragment:
|
|
||||||
case OP_Fragment2:
|
|
||||||
case OP_Fragment3:
|
|
||||||
case OP_Fragment4:
|
|
||||||
{
|
|
||||||
auto header = p.GetSerialize<DaybreakReliableHeader>(0);
|
|
||||||
auto sequence = NetworkToHost(header.sequence);
|
|
||||||
auto stream_id = header.opcode - OP_Fragment;
|
|
||||||
auto stream = &m_streams[stream_id];
|
|
||||||
|
|
||||||
auto order = CompareSequence(stream->sequence_in, sequence);
|
|
||||||
|
|
||||||
if (order == SequenceFuture) {
|
|
||||||
SendOutOfOrderAck(stream_id, sequence);
|
|
||||||
AddToQueue(stream_id, sequence, p);
|
|
||||||
}
|
|
||||||
else if (order == SequencePast) {
|
|
||||||
SendAck(stream_id, stream->sequence_in - 1);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
RemoveFromQueue(stream_id, sequence);
|
|
||||||
SendAck(stream_id, stream->sequence_in);
|
|
||||||
stream->sequence_in++;
|
|
||||||
|
|
||||||
if (stream->fragment_total_bytes == 0) {
|
|
||||||
auto fragheader = p.GetSerialize<DaybreakReliableFragmentHeader>(0);
|
|
||||||
stream->fragment_total_bytes = NetworkToHost(fragheader.total_size);
|
|
||||||
stream->fragment_current_bytes = 0;
|
|
||||||
stream->fragment_packet.Reserve(stream->fragment_total_bytes);
|
|
||||||
stream->fragment_packet.PutData(
|
|
||||||
stream->fragment_current_bytes,
|
|
||||||
(char*)p.Data() + DaybreakReliableFragmentHeader::size(), p.Length() - DaybreakReliableFragmentHeader::size());
|
|
||||||
|
|
||||||
stream->fragment_current_bytes += (uint32_t)(p.Length() - DaybreakReliableFragmentHeader::size());
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
stream->fragment_packet.PutData(
|
RemoveFromQueue(stream_id, sequence);
|
||||||
stream->fragment_current_bytes,
|
SendAck(stream_id, stream->sequence_in);
|
||||||
(char*)p.Data() + DaybreakReliableHeader::size(), p.Length() - DaybreakReliableHeader::size());
|
stream->sequence_in++;
|
||||||
|
StaticPacket next((char*)p.Data() + DaybreakReliableHeader::size(), p.Length() - DaybreakReliableHeader::size());
|
||||||
|
ProcessDecodedPacket(next);
|
||||||
|
}
|
||||||
|
|
||||||
stream->fragment_current_bytes += (uint32_t)(p.Length() - DaybreakReliableHeader::size());
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
if (stream->fragment_current_bytes >= stream->fragment_total_bytes) {
|
case OP_Fragment:
|
||||||
ProcessDecodedPacket(stream->fragment_packet);
|
case OP_Fragment2:
|
||||||
stream->fragment_packet.Clear();
|
case OP_Fragment3:
|
||||||
stream->fragment_total_bytes = 0;
|
case OP_Fragment4:
|
||||||
|
{
|
||||||
|
auto header = p.GetSerialize<DaybreakReliableHeader>(0);
|
||||||
|
auto sequence = NetworkToHost(header.sequence);
|
||||||
|
auto stream_id = header.opcode - OP_Fragment;
|
||||||
|
auto stream = &m_streams[stream_id];
|
||||||
|
|
||||||
|
auto order = CompareSequence(stream->sequence_in, sequence);
|
||||||
|
|
||||||
|
if (order == SequenceFuture) {
|
||||||
|
SendOutOfOrderAck(stream_id, sequence);
|
||||||
|
AddToQueue(stream_id, sequence, p);
|
||||||
|
}
|
||||||
|
else if (order == SequencePast) {
|
||||||
|
SendAck(stream_id, stream->sequence_in - 1);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
RemoveFromQueue(stream_id, sequence);
|
||||||
|
SendAck(stream_id, stream->sequence_in);
|
||||||
|
stream->sequence_in++;
|
||||||
|
|
||||||
|
if (stream->fragment_total_bytes == 0) {
|
||||||
|
auto fragheader = p.GetSerialize<DaybreakReliableFragmentHeader>(0);
|
||||||
|
stream->fragment_total_bytes = NetworkToHost(fragheader.total_size);
|
||||||
stream->fragment_current_bytes = 0;
|
stream->fragment_current_bytes = 0;
|
||||||
|
stream->fragment_packet.Reserve(stream->fragment_total_bytes);
|
||||||
|
stream->fragment_packet.PutData(
|
||||||
|
stream->fragment_current_bytes,
|
||||||
|
(char*)p.Data() + DaybreakReliableFragmentHeader::size(), p.Length() - DaybreakReliableFragmentHeader::size());
|
||||||
|
|
||||||
|
stream->fragment_current_bytes += (uint32_t)(p.Length() - DaybreakReliableFragmentHeader::size());
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
stream->fragment_packet.PutData(
|
||||||
|
stream->fragment_current_bytes,
|
||||||
|
(char*)p.Data() + DaybreakReliableHeader::size(), p.Length() - DaybreakReliableHeader::size());
|
||||||
|
|
||||||
|
stream->fragment_current_bytes += (uint32_t)(p.Length() - DaybreakReliableHeader::size());
|
||||||
|
|
||||||
|
if (stream->fragment_current_bytes >= stream->fragment_total_bytes) {
|
||||||
|
ProcessDecodedPacket(stream->fragment_packet);
|
||||||
|
stream->fragment_packet.Clear();
|
||||||
|
stream->fragment_total_bytes = 0;
|
||||||
|
stream->fragment_current_bytes = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
case OP_Ack:
|
||||||
}
|
case OP_Ack2:
|
||||||
|
case OP_Ack3:
|
||||||
case OP_Ack:
|
case OP_Ack4:
|
||||||
case OP_Ack2:
|
{
|
||||||
case OP_Ack3:
|
auto header = p.GetSerialize<DaybreakReliableHeader>(0);
|
||||||
case OP_Ack4:
|
auto sequence = NetworkToHost(header.sequence);
|
||||||
{
|
auto stream_id = header.opcode - OP_Ack;
|
||||||
auto header = p.GetSerialize<DaybreakReliableHeader>(0);
|
Ack(stream_id, sequence);
|
||||||
auto sequence = NetworkToHost(header.sequence);
|
break;
|
||||||
auto stream_id = header.opcode - OP_Ack;
|
|
||||||
Ack(stream_id, sequence);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case OP_OutOfOrderAck:
|
|
||||||
case OP_OutOfOrderAck2:
|
|
||||||
case OP_OutOfOrderAck3:
|
|
||||||
case OP_OutOfOrderAck4:
|
|
||||||
{
|
|
||||||
auto header = p.GetSerialize<DaybreakReliableHeader>(0);
|
|
||||||
auto sequence = NetworkToHost(header.sequence);
|
|
||||||
auto stream_id = header.opcode - OP_OutOfOrderAck;
|
|
||||||
OutOfOrderAck(stream_id, sequence);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case OP_SessionDisconnect:
|
|
||||||
{
|
|
||||||
if (m_status == StatusConnected || m_status == StatusDisconnecting) {
|
|
||||||
FlushBuffer();
|
|
||||||
SendDisconnect();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ChangeStatus(StatusDisconnecting);
|
case OP_OutOfOrderAck:
|
||||||
break;
|
case OP_OutOfOrderAck2:
|
||||||
}
|
case OP_OutOfOrderAck3:
|
||||||
|
case OP_OutOfOrderAck4:
|
||||||
case OP_Padding:
|
{
|
||||||
{
|
auto header = p.GetSerialize<DaybreakReliableHeader>(0);
|
||||||
auto self = m_self.lock();
|
auto sequence = NetworkToHost(header.sequence);
|
||||||
if (m_owner->m_on_packet_recv && self) {
|
auto stream_id = header.opcode - OP_OutOfOrderAck;
|
||||||
m_owner->m_on_packet_recv(self, StaticPacket((char*)p.Data() + 1, p.Length() - 1));
|
OutOfOrderAck(stream_id, sequence);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
}
|
|
||||||
case OP_SessionStatRequest:
|
|
||||||
{
|
|
||||||
auto request = p.GetSerialize<DaybreakSessionStatRequest>(0);
|
|
||||||
|
|
||||||
DaybreakSessionStatResponse response;
|
case OP_SessionDisconnect:
|
||||||
response.zero = 0;
|
{
|
||||||
response.opcode = OP_SessionStatResponse;
|
if (m_status == StatusConnected || m_status == StatusDisconnecting) {
|
||||||
response.timestamp = request.timestamp;
|
FlushBuffer();
|
||||||
response.our_timestamp = EQ::Net::HostToNetwork(std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::high_resolution_clock::now().time_since_epoch()).count());
|
SendDisconnect();
|
||||||
response.client_sent = request.packets_sent;
|
}
|
||||||
response.client_recv = request.packets_recv;
|
|
||||||
response.server_sent = EQ::Net::HostToNetwork(m_stats.sent_packets);
|
ChangeStatus(StatusDisconnecting);
|
||||||
response.server_recv = EQ::Net::HostToNetwork(m_stats.recv_packets);
|
break;
|
||||||
DynamicPacket out;
|
}
|
||||||
out.PutSerialize(0, response);
|
|
||||||
InternalSend(out);
|
case OP_Padding:
|
||||||
break;
|
{
|
||||||
}
|
auto self = m_self.lock();
|
||||||
case OP_SessionStatResponse:
|
if (m_owner->m_on_packet_recv && self) {
|
||||||
break;
|
m_owner->m_on_packet_recv(self, StaticPacket((char*)p.Data() + 1, p.Length() - 1));
|
||||||
default:
|
}
|
||||||
LogF(Logs::Detail, Logs::Netcode, "Unhandled opcode {0:#x}", p.GetInt8(1));
|
break;
|
||||||
break;
|
}
|
||||||
|
case OP_SessionStatRequest:
|
||||||
|
{
|
||||||
|
auto request = p.GetSerialize<DaybreakSessionStatRequest>(0);
|
||||||
|
|
||||||
|
DaybreakSessionStatResponse response;
|
||||||
|
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.client_sent = request.packets_sent;
|
||||||
|
response.client_recv = request.packets_recv;
|
||||||
|
response.server_sent = EQ::Net::HostToNetwork(m_stats.sent_packets);
|
||||||
|
response.server_recv = EQ::Net::HostToNetwork(m_stats.recv_packets);
|
||||||
|
DynamicPacket out;
|
||||||
|
out.PutSerialize(0, response);
|
||||||
|
InternalSend(out);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case OP_SessionStatResponse:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
LogF(Logs::Detail, Logs::Netcode, "Unhandled opcode {0:#x}", p.GetInt8(1));
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -782,16 +786,16 @@ bool EQ::Net::DaybreakConnection::ValidateCRC(Packet &p)
|
|||||||
int calculated = 0;
|
int calculated = 0;
|
||||||
int actual = 0;
|
int actual = 0;
|
||||||
switch (m_crc_bytes) {
|
switch (m_crc_bytes) {
|
||||||
case 2:
|
case 2:
|
||||||
actual = NetworkToHost(*(int16_t*)&data[p.Length() - (size_t)m_crc_bytes]) & 0xffff;
|
actual = NetworkToHost(*(int16_t*)&data[p.Length() - (size_t)m_crc_bytes]) & 0xffff;
|
||||||
calculated = Crc32(data, (int)(p.Length() - (size_t)m_crc_bytes), m_encode_key) & 0xffff;
|
calculated = Crc32(data, (int)(p.Length() - (size_t)m_crc_bytes), m_encode_key) & 0xffff;
|
||||||
break;
|
break;
|
||||||
case 4:
|
case 4:
|
||||||
actual = NetworkToHost(*(int32_t*)&data[p.Length() - (size_t)m_crc_bytes]);
|
actual = NetworkToHost(*(int32_t*)&data[p.Length() - (size_t)m_crc_bytes]);
|
||||||
calculated = Crc32(data, (int)(p.Length() - (size_t)m_crc_bytes), m_encode_key);
|
calculated = Crc32(data, (int)(p.Length() - (size_t)m_crc_bytes), m_encode_key);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (actual == calculated) {
|
if (actual == calculated) {
|
||||||
@@ -809,14 +813,14 @@ void EQ::Net::DaybreakConnection::AppendCRC(Packet &p)
|
|||||||
|
|
||||||
int calculated = 0;
|
int calculated = 0;
|
||||||
switch (m_crc_bytes) {
|
switch (m_crc_bytes) {
|
||||||
case 2:
|
case 2:
|
||||||
calculated = Crc32(p.Data(), (int)p.Length(), m_encode_key) & 0xffff;
|
calculated = Crc32(p.Data(), (int)p.Length(), m_encode_key) & 0xffff;
|
||||||
p.PutInt16(p.Length(), EQ::Net::HostToNetwork((int16_t)calculated));
|
p.PutInt16(p.Length(), EQ::Net::HostToNetwork((int16_t)calculated));
|
||||||
break;
|
break;
|
||||||
case 4:
|
case 4:
|
||||||
calculated = Crc32(p.Data(), (int)p.Length(), m_encode_key);
|
calculated = Crc32(p.Data(), (int)p.Length(), m_encode_key);
|
||||||
p.PutInt32(p.Length(), EQ::Net::HostToNetwork(calculated));
|
p.PutInt32(p.Length(), EQ::Net::HostToNetwork(calculated));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1026,7 +1030,7 @@ void EQ::Net::DaybreakConnection::ProcessResend(int stream)
|
|||||||
InternalBufferedSend(entry.second.packet);
|
InternalBufferedSend(entry.second.packet);
|
||||||
entry.second.last_sent = now;
|
entry.second.last_sent = now;
|
||||||
entry.second.times_resent++;
|
entry.second.times_resent++;
|
||||||
m_rolling_ping += 300;
|
m_rolling_ping += 100;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -1040,7 +1044,7 @@ void EQ::Net::DaybreakConnection::ProcessResend(int stream)
|
|||||||
InternalBufferedSend(entry.second.packet);
|
InternalBufferedSend(entry.second.packet);
|
||||||
entry.second.last_sent = now;
|
entry.second.last_sent = now;
|
||||||
entry.second.times_resent++;
|
entry.second.times_resent++;
|
||||||
m_rolling_ping += 300;
|
m_rolling_ping += 100;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1187,27 +1191,24 @@ void EQ::Net::DaybreakConnection::InternalSend(Packet &p)
|
|||||||
|
|
||||||
if (PacketCanBeEncoded(p)) {
|
if (PacketCanBeEncoded(p)) {
|
||||||
DynamicPacket out;
|
DynamicPacket out;
|
||||||
|
out.PutPacket(0, p);
|
||||||
if (p.GetUInt8(0) != 0) {
|
|
||||||
out.PutUInt8(0, 0);
|
|
||||||
out.PutUInt8(1, OP_Combined);
|
|
||||||
out.PutUInt8(2, p.Length());
|
|
||||||
out.PutPacket(3, p);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
out.PutPacket(0, p);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 0; i < 2; ++i) {
|
for (int i = 0; i < 2; ++i) {
|
||||||
switch (m_encode_passes[i]) {
|
switch (m_encode_passes[i]) {
|
||||||
case EncodeCompression:
|
case EncodeCompression:
|
||||||
Compress(out, DaybreakHeader::size(), out.Length() - DaybreakHeader::size());
|
if(out.GetInt8(0) == 0)
|
||||||
break;
|
Compress(out, DaybreakHeader::size(), out.Length() - DaybreakHeader::size());
|
||||||
case EncodeXOR:
|
else
|
||||||
Encode(out, DaybreakHeader::size(), out.Length() - DaybreakHeader::size());
|
Compress(out, 1, out.Length() - 1);
|
||||||
break;
|
break;
|
||||||
default:
|
case EncodeXOR:
|
||||||
break;
|
if (out.GetInt8(0) == 0)
|
||||||
|
Encode(out, DaybreakHeader::size(), out.Length() - DaybreakHeader::size());
|
||||||
|
else
|
||||||
|
Encode(out, 1, out.Length() - 1);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -8,7 +8,6 @@
|
|||||||
#include <functional>
|
#include <functional>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <unordered_map>
|
|
||||||
#include <queue>
|
#include <queue>
|
||||||
#include <list>
|
#include <list>
|
||||||
|
|
||||||
@@ -156,13 +155,13 @@ namespace EQ
|
|||||||
|
|
||||||
uint16_t sequence_in;
|
uint16_t sequence_in;
|
||||||
uint16_t sequence_out;
|
uint16_t sequence_out;
|
||||||
std::unordered_map<uint16_t, Packet*> packet_queue;
|
std::map<uint16_t, Packet*> packet_queue;
|
||||||
|
|
||||||
DynamicPacket fragment_packet;
|
DynamicPacket fragment_packet;
|
||||||
uint32_t fragment_current_bytes;
|
uint32_t fragment_current_bytes;
|
||||||
uint32_t fragment_total_bytes;
|
uint32_t fragment_total_bytes;
|
||||||
|
|
||||||
std::unordered_map<uint16_t, DaybreakSentPacket> sent_packets;
|
std::map<uint16_t, DaybreakSentPacket> sent_packets;
|
||||||
};
|
};
|
||||||
|
|
||||||
DaybreakStream m_streams[4];
|
DaybreakStream m_streams[4];
|
||||||
@@ -206,10 +205,10 @@ namespace EQ
|
|||||||
DaybreakConnectionManagerOptions() {
|
DaybreakConnectionManagerOptions() {
|
||||||
max_connection_count = 0;
|
max_connection_count = 0;
|
||||||
keepalive_delay_ms = 9000;
|
keepalive_delay_ms = 9000;
|
||||||
resend_delay_ms = 300;
|
resend_delay_ms = 150;
|
||||||
resend_delay_factor = 1.5;
|
resend_delay_factor = 1.5;
|
||||||
resend_delay_min = 350;
|
resend_delay_min = 150;
|
||||||
resend_delay_max = 8000;
|
resend_delay_max = 1000;
|
||||||
connect_delay_ms = 500;
|
connect_delay_ms = 500;
|
||||||
stale_connection_ms = 90000;
|
stale_connection_ms = 90000;
|
||||||
connect_stale_ms = 5000;
|
connect_stale_ms = 5000;
|
||||||
@@ -219,7 +218,7 @@ namespace EQ
|
|||||||
encode_passes[1] = DaybreakEncodeType::EncodeNone;
|
encode_passes[1] = DaybreakEncodeType::EncodeNone;
|
||||||
port = 0;
|
port = 0;
|
||||||
hold_size = 448;
|
hold_size = 448;
|
||||||
hold_length_ms = 10;
|
hold_length_ms = 50;
|
||||||
simulated_in_packet_loss = 0;
|
simulated_in_packet_loss = 0;
|
||||||
simulated_out_packet_loss = 0;
|
simulated_out_packet_loss = 0;
|
||||||
tic_rate_hertz = 60.0;
|
tic_rate_hertz = 60.0;
|
||||||
|
|||||||
@@ -81,7 +81,12 @@ void EQ::Net::EQStream::QueuePacket(const EQApplicationPacket *p, bool ack_req)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_connection->QueuePacket(out);
|
if (ack_req) {
|
||||||
|
m_connection->QueuePacket(out);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
m_connection->QueuePacket(out, 0, false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3930,7 +3930,7 @@ namespace RoF
|
|||||||
if (strlen(emu->suffix))
|
if (strlen(emu->suffix))
|
||||||
PacketSize += strlen(emu->suffix) + 1;
|
PacketSize += strlen(emu->suffix) + 1;
|
||||||
|
|
||||||
bool ShowName = 1;
|
bool ShowName = emu->show_name;
|
||||||
if (emu->bodytype >= 66)
|
if (emu->bodytype >= 66)
|
||||||
{
|
{
|
||||||
emu->race = 127;
|
emu->race = 127;
|
||||||
|
|||||||
+55
-45
@@ -1883,35 +1883,34 @@ namespace RoF2
|
|||||||
eq->FogDensity = emu->fog_density;
|
eq->FogDensity = emu->fog_density;
|
||||||
|
|
||||||
/*fill in some unknowns with observed values, hopefully it will help */
|
/*fill in some unknowns with observed values, hopefully it will help */
|
||||||
eq->unknown569 = 0;
|
eq->ZoneTimeZone = 0;
|
||||||
eq->unknown571 = 0;
|
eq->unknown571 = 0;
|
||||||
eq->unknown572 = 4;
|
eq->WaterMidi = 4;
|
||||||
eq->unknown576 = 2;
|
eq->DayMidi = 2;
|
||||||
eq->unknown580 = 0;
|
eq->NightMidi = 0;
|
||||||
|
|
||||||
eq->unknown800 = -1;
|
eq->SkyRelated2 = -1;
|
||||||
eq->unknown844 = 600;
|
eq->NPCAggroMaxDist = 600;
|
||||||
eq->unknown848 = 2008; // Guild Lobby observed value
|
eq->FilterID = 2008; // Guild Lobby observed value
|
||||||
eq->unknown880 = 50;
|
eq->LavaDamage = 50;
|
||||||
eq->unknown884 = 10;
|
eq->MinLavaDamage = 10;
|
||||||
eq->unknown888 = 1;
|
eq->bDisallowManaStone = 1;
|
||||||
eq->unknown889 = 0;
|
eq->bNoBind = 0;
|
||||||
eq->unknown890 = 1;
|
eq->bNoAttack = 0;
|
||||||
eq->unknown891 = 0;
|
eq->bNoCallOfHero = 0;
|
||||||
eq->unknown892 = 0;
|
eq->bNoFlux = 0;
|
||||||
eq->unknown893 = 0;
|
eq->bNoFear = 0;
|
||||||
eq->fall_damage = 0; // 0 = Fall Damage on, 1 = Fall Damage off
|
eq->fall_damage = 0; // 0 = Fall Damage on, 1 = Fall Damage off
|
||||||
eq->unknown895 = 0;
|
eq->unknown895 = 0;
|
||||||
eq->unknown896 = 180;
|
eq->FastRegenHP = 180;
|
||||||
eq->unknown900 = 180;
|
eq->FastRegenMana = 180;
|
||||||
eq->unknown904 = 180;
|
eq->FastRegenEndurance = 180;
|
||||||
eq->unknown908 = 2;
|
eq->CanPlaceCampsite = 2;
|
||||||
eq->unknown912 = 2;
|
eq->CanPlaceGuildBanner = 2;
|
||||||
eq->unknown932 = -1; // Set from PoK Example
|
eq->FishingRelated = -1; // Set from PoK Example
|
||||||
eq->unknown936 = -1; // Set from PoK Example
|
eq->ForageRelated = -1; // Set from PoK Example
|
||||||
eq->unknown944 = 1.0; // Set from PoK Example
|
eq->bNoLevitate = 0;
|
||||||
eq->unknown948 = 0; // New on Live as of Dec 15 2014
|
eq->Blooming = 1.0; // Set from PoK Example
|
||||||
eq->unknown952 = 100; // New on Live as of Dec 15 2014
|
|
||||||
|
|
||||||
FINISH_ENCODE();
|
FINISH_ENCODE();
|
||||||
}
|
}
|
||||||
@@ -4086,7 +4085,7 @@ namespace RoF2
|
|||||||
PacketSize += strlen(emu->DestructibleString) + 1;
|
PacketSize += strlen(emu->DestructibleString) + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ShowName = 1;
|
bool ShowName = emu->show_name;
|
||||||
if (emu->bodytype >= 66)
|
if (emu->bodytype >= 66)
|
||||||
{
|
{
|
||||||
emu->race = 127;
|
emu->race = 127;
|
||||||
@@ -4120,6 +4119,7 @@ namespace RoF2
|
|||||||
VARSTRUCT_ENCODE_STRING(Buffer, emu->name);
|
VARSTRUCT_ENCODE_STRING(Buffer, emu->name);
|
||||||
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->spawnId);
|
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->spawnId);
|
||||||
VARSTRUCT_ENCODE_TYPE(uint8, Buffer, emu->level);
|
VARSTRUCT_ENCODE_TYPE(uint8, Buffer, emu->level);
|
||||||
|
// actually melee range variable, this probably screws the shit out of melee ranges :D
|
||||||
if (emu->DestructibleObject)
|
if (emu->DestructibleObject)
|
||||||
{
|
{
|
||||||
VARSTRUCT_ENCODE_TYPE(float, Buffer, 10); // was int and 0x41200000
|
VARSTRUCT_ENCODE_TYPE(float, Buffer, 10); // was int and 0x41200000
|
||||||
@@ -4128,7 +4128,7 @@ namespace RoF2
|
|||||||
{
|
{
|
||||||
VARSTRUCT_ENCODE_TYPE(float, Buffer, SpawnSize - 0.7); // Eye Height?
|
VARSTRUCT_ENCODE_TYPE(float, Buffer, SpawnSize - 0.7); // Eye Height?
|
||||||
}
|
}
|
||||||
VARSTRUCT_ENCODE_TYPE(uint8, Buffer, emu->NPC);
|
VARSTRUCT_ENCODE_TYPE(uint8, Buffer, emu->NPC); // 0 PC, 1 NPC etc
|
||||||
|
|
||||||
structs::Spawn_Struct_Bitfields *Bitfields = (structs::Spawn_Struct_Bitfields*)Buffer;
|
structs::Spawn_Struct_Bitfields *Bitfields = (structs::Spawn_Struct_Bitfields*)Buffer;
|
||||||
|
|
||||||
@@ -4159,6 +4159,7 @@ namespace RoF2
|
|||||||
|
|
||||||
Buffer += sizeof(structs::Spawn_Struct_Bitfields);
|
Buffer += sizeof(structs::Spawn_Struct_Bitfields);
|
||||||
|
|
||||||
|
// actually part of bitfields
|
||||||
uint8 OtherData = 0;
|
uint8 OtherData = 0;
|
||||||
|
|
||||||
if (emu->class_ == 62) //LDoN Chest
|
if (emu->class_ == 62) //LDoN Chest
|
||||||
@@ -4174,6 +4175,7 @@ namespace RoF2
|
|||||||
OtherData = OtherData | 0xe1; // Live has 0xe1 for OtherData
|
OtherData = OtherData | 0xe1; // Live has 0xe1 for OtherData
|
||||||
|
|
||||||
VARSTRUCT_ENCODE_TYPE(uint8, Buffer, OtherData);
|
VARSTRUCT_ENCODE_TYPE(uint8, Buffer, OtherData);
|
||||||
|
// float EmitterScalingRadius
|
||||||
|
|
||||||
if (emu->DestructibleObject)
|
if (emu->DestructibleObject)
|
||||||
{
|
{
|
||||||
@@ -4183,6 +4185,7 @@ namespace RoF2
|
|||||||
{
|
{
|
||||||
VARSTRUCT_ENCODE_TYPE(float, Buffer, -1); // unknown3
|
VARSTRUCT_ENCODE_TYPE(float, Buffer, -1); // unknown3
|
||||||
}
|
}
|
||||||
|
// int DefaultEmitterID
|
||||||
VARSTRUCT_ENCODE_TYPE(float, Buffer, 0); // unknown4
|
VARSTRUCT_ENCODE_TYPE(float, Buffer, 0); // unknown4
|
||||||
|
|
||||||
if (emu->DestructibleObject || emu->class_ == 62)
|
if (emu->DestructibleObject || emu->class_ == 62)
|
||||||
@@ -4192,8 +4195,9 @@ namespace RoF2
|
|||||||
VARSTRUCT_ENCODE_STRING(Buffer, emu->DestructibleString);
|
VARSTRUCT_ENCODE_STRING(Buffer, emu->DestructibleString);
|
||||||
|
|
||||||
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->DestructibleAppearance);
|
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->DestructibleAppearance);
|
||||||
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->DestructibleUnk1);
|
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->DestructibleUnk1); // ObjectAnimationID
|
||||||
|
|
||||||
|
// these 10 are SoundIDs
|
||||||
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->DestructibleID1);
|
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->DestructibleID1);
|
||||||
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->DestructibleID2);
|
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->DestructibleID2);
|
||||||
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->DestructibleID3);
|
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->DestructibleID3);
|
||||||
@@ -4205,8 +4209,8 @@ namespace RoF2
|
|||||||
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->DestructibleUnk5);
|
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->DestructibleUnk5);
|
||||||
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->DestructibleUnk6);
|
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->DestructibleUnk6);
|
||||||
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->DestructibleUnk7);
|
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->DestructibleUnk7);
|
||||||
VARSTRUCT_ENCODE_TYPE(uint8, Buffer, emu->DestructibleUnk8);
|
VARSTRUCT_ENCODE_TYPE(uint8, Buffer, emu->DestructibleUnk8); // bInteractiveObjectCollidable
|
||||||
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->DestructibleUnk9);
|
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->DestructibleUnk9); // IteractiveObjectType
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -4214,6 +4218,7 @@ namespace RoF2
|
|||||||
{
|
{
|
||||||
// Setting this next field to zero will cause a crash. Looking at ShowEQ, if it is zero, the bodytype field is not
|
// Setting this next field to zero will cause a crash. Looking at ShowEQ, if it is zero, the bodytype field is not
|
||||||
// present. Will sort that out later.
|
// present. Will sort that out later.
|
||||||
|
// This is the CharacterPropertyHash, it can have multiple fields
|
||||||
VARSTRUCT_ENCODE_TYPE(uint8, Buffer, 1); // This is a properties count field
|
VARSTRUCT_ENCODE_TYPE(uint8, Buffer, 1); // This is a properties count field
|
||||||
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->bodytype);
|
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->bodytype);
|
||||||
}
|
}
|
||||||
@@ -4233,10 +4238,10 @@ namespace RoF2
|
|||||||
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->drakkin_tattoo);
|
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->drakkin_tattoo);
|
||||||
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->drakkin_details);
|
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->drakkin_details);
|
||||||
|
|
||||||
VARSTRUCT_ENCODE_TYPE(uint8, Buffer, emu->equip_chest2);
|
VARSTRUCT_ENCODE_TYPE(uint8, Buffer, emu->equip_chest2); // InNonPCRaceIllusion
|
||||||
VARSTRUCT_ENCODE_TYPE(uint8, Buffer, 0); // unknown9
|
VARSTRUCT_ENCODE_TYPE(uint8, Buffer, 0); // material
|
||||||
VARSTRUCT_ENCODE_TYPE(uint8, Buffer, 0); // unknown10
|
VARSTRUCT_ENCODE_TYPE(uint8, Buffer, 0); // variation
|
||||||
VARSTRUCT_ENCODE_TYPE(uint8, Buffer, emu->helm); // unknown11
|
VARSTRUCT_ENCODE_TYPE(uint8, Buffer, emu->helm); // headtype
|
||||||
|
|
||||||
VARSTRUCT_ENCODE_TYPE(float, Buffer, emu->size);
|
VARSTRUCT_ENCODE_TYPE(float, Buffer, emu->size);
|
||||||
VARSTRUCT_ENCODE_TYPE(uint8, Buffer, emu->face);
|
VARSTRUCT_ENCODE_TYPE(uint8, Buffer, emu->face);
|
||||||
@@ -4244,6 +4249,7 @@ namespace RoF2
|
|||||||
VARSTRUCT_ENCODE_TYPE(float, Buffer, emu->runspeed);
|
VARSTRUCT_ENCODE_TYPE(float, Buffer, emu->runspeed);
|
||||||
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->race);
|
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->race);
|
||||||
|
|
||||||
|
// From MQ2: todo: create enum for this byte. Holding: Nothing=0 A RightHand Weapon=1 A Shield=2 Dual Wielding Two Weapons=3 A Spear=4 A LeftHand Weapon=5 A Two Handed Weapon=6 A bow=7
|
||||||
VARSTRUCT_ENCODE_TYPE(uint8, Buffer, 0); // ShowEQ calls this 'Holding'
|
VARSTRUCT_ENCODE_TYPE(uint8, Buffer, 0); // ShowEQ calls this 'Holding'
|
||||||
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->deity);
|
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->deity);
|
||||||
if (emu->NPC)
|
if (emu->NPC)
|
||||||
@@ -4276,19 +4282,19 @@ namespace RoF2
|
|||||||
|
|
||||||
VARSTRUCT_ENCODE_STRING(Buffer, emu->lastName);
|
VARSTRUCT_ENCODE_STRING(Buffer, emu->lastName);
|
||||||
|
|
||||||
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); // aatitle ??
|
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); // aatitle
|
||||||
VARSTRUCT_ENCODE_TYPE(uint8, Buffer, emu->NPC ? 0 : 1); // unknown - Must be 1 for guild name to be shown abover players head.
|
VARSTRUCT_ENCODE_TYPE(uint8, Buffer, emu->NPC ? 0 : 1); // unknown - Must be 1 for guild name to be shown abover players head.
|
||||||
VARSTRUCT_ENCODE_TYPE(uint8, Buffer, 0); // unknown
|
VARSTRUCT_ENCODE_TYPE(uint8, Buffer, 0); // TempPet
|
||||||
|
|
||||||
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->petOwnerId);
|
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->petOwnerId);
|
||||||
|
|
||||||
VARSTRUCT_ENCODE_TYPE(uint8, Buffer, 0); // unknown13
|
VARSTRUCT_ENCODE_TYPE(uint8, Buffer, 0); // FindBits MQ2 name
|
||||||
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->PlayerState);
|
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->PlayerState);
|
||||||
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); // unknown15
|
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); // NpcTintIndex
|
||||||
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); // unknown16
|
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); // PrimaryTintIndex
|
||||||
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); // unknown17
|
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); // SecondaryTintIndex
|
||||||
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0xffffffff); // unknown18
|
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0xffffffff); // These do something with OP_WeaponEquip1
|
||||||
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0xffffffff); // unknown19
|
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0xffffffff); // ^
|
||||||
|
|
||||||
if ((emu->NPC == 0) || (emu->race <= 12) || (emu->race == 128) || (emu->race == 130) || (emu->race == 330) || (emu->race == 522))
|
if ((emu->NPC == 0) || (emu->race <= 12) || (emu->race == 128) || (emu->race == 130) || (emu->race == 330) || (emu->race == 522))
|
||||||
{
|
{
|
||||||
@@ -4356,12 +4362,16 @@ namespace RoF2
|
|||||||
VARSTRUCT_ENCODE_STRING(Buffer, emu->suffix);
|
VARSTRUCT_ENCODE_STRING(Buffer, emu->suffix);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// skipping two ints
|
||||||
|
// unknown, maybe some sort of spawn ID
|
||||||
|
// SplineID -- no idea
|
||||||
Buffer += 8;
|
Buffer += 8;
|
||||||
VARSTRUCT_ENCODE_TYPE(uint8, Buffer, emu->IsMercenary);
|
VARSTRUCT_ENCODE_TYPE(uint8, Buffer, emu->IsMercenary);
|
||||||
VARSTRUCT_ENCODE_STRING(Buffer, "0000000000000000");
|
VARSTRUCT_ENCODE_STRING(Buffer, "0000000000000000"); // RealEstateItemGuid
|
||||||
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0xffffffff);
|
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0xffffffff); // RealEstateID
|
||||||
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0xffffffff);
|
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0xffffffff); // RealEstateItemID
|
||||||
// 29 zero bytes follow
|
// 29 zero bytes follow
|
||||||
|
// PhysicsEffects follow here ... unsure what they are but it's a count followed by a struct like {spellid, casterid, effectid, baseeffect}
|
||||||
Buffer += 29;
|
Buffer += 29;
|
||||||
if (Buffer != (BufferStart + PacketSize))
|
if (Buffer != (BufferStart + PacketSize))
|
||||||
{
|
{
|
||||||
|
|||||||
+103
-72
@@ -328,38 +328,43 @@ showeq -> eqemu
|
|||||||
sed -e 's/_t//g' -e 's/seto_0xFF/set_to_0xFF/g'
|
sed -e 's/_t//g' -e 's/seto_0xFF/set_to_0xFF/g'
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
// I think this is actually 5 bytes
|
||||||
|
// IDA's pseudocode reads this as 5 bytes pulled into 2 DWORDs
|
||||||
struct Spawn_Struct_Bitfields
|
struct Spawn_Struct_Bitfields
|
||||||
{
|
{
|
||||||
|
// byte 1
|
||||||
/*00*/ unsigned gender:2; // Gender (0=male, 1=female, 2=monster)
|
/*00*/ unsigned gender:2; // Gender (0=male, 1=female, 2=monster)
|
||||||
/*02*/ unsigned ispet:1; // Guessed based on observing live spawns
|
/*02*/ unsigned ispet:1; // Guessed based on observing live spawns
|
||||||
/*03*/ unsigned afk:1; // 0=no, 1=afk
|
/*03*/ unsigned afk:1; // 0=no, 1=afk
|
||||||
/*04*/ unsigned anon:2; // 0=normal, 1=anon, 2=roleplay
|
/*04*/ unsigned anon:2; // 0=normal, 1=anon, 2=roleplay
|
||||||
/*06*/ unsigned gm:1;
|
/*06*/ unsigned gm:1;
|
||||||
/*06*/ unsigned sneak:1;
|
/*07*/ unsigned sneak:1;
|
||||||
|
// byte 2
|
||||||
/*08*/ unsigned lfg:1;
|
/*08*/ unsigned lfg:1;
|
||||||
/*09*/ unsigned unknown09:1;
|
/*09*/ unsigned betabuffed:1;
|
||||||
/*10*/ unsigned invis:1; // May have invis & sneak the wrong way around ... not sure how to tell which is which
|
/*10*/ unsigned invis:12; // there are 3000 different (non-GM) invis levels
|
||||||
/*11*/ unsigned invis1:1; // GM Invis? Can only be seen with #gm on - same for the below
|
|
||||||
/*12*/ unsigned invis2:1; // This one also make the NPC/PC invis
|
|
||||||
/*13*/ unsigned invis3:1; // This one also make the NPC/PC invis
|
|
||||||
/*14*/ unsigned invis4:1; // This one also make the NPC/PC invis
|
|
||||||
/*15*/ unsigned invis6:1; // This one also make the NPC/PC invis
|
|
||||||
/*16*/ unsigned invis7:1; // This one also make the NPC/PC invis
|
|
||||||
/*17*/ unsigned invis8:1; // This one also make the NPC/PC invis
|
|
||||||
/*18*/ unsigned invis9:1; // This one also make the NPC/PC invis
|
|
||||||
/*19*/ unsigned invis10:1; // This one also make the NPC/PC invis
|
|
||||||
/*20*/ unsigned invis11:1; // This one also make the NPC/PC invis
|
|
||||||
/*21*/ unsigned invis12:1; // This one also make the NPC/PC invis
|
|
||||||
/*22*/ unsigned linkdead:1; // 1 Toggles LD on or off after name. Correct for RoF2
|
/*22*/ unsigned linkdead:1; // 1 Toggles LD on or off after name. Correct for RoF2
|
||||||
/*23*/ unsigned showhelm:1;
|
/*23*/ unsigned showhelm:1;
|
||||||
|
// byte 4
|
||||||
/*24*/ unsigned unknown24:1; // Prefixes name with !
|
/*24*/ unsigned unknown24:1; // Prefixes name with !
|
||||||
/*25*/ unsigned trader:1;
|
/*25*/ unsigned trader:1;
|
||||||
/*26*/ unsigned unknown26:1;
|
/*26*/ unsigned animationonpop:1;
|
||||||
/*27*/ unsigned targetable:1;
|
/*27*/ unsigned targetable:1;
|
||||||
/*28*/ unsigned targetable_with_hotkey:1;
|
/*28*/ unsigned targetable_with_hotkey:1;
|
||||||
/*29*/ unsigned showname:1;
|
/*29*/ unsigned showname:1;
|
||||||
/*30*/ unsigned unknown30:1;
|
/*30*/ unsigned idleanimationsoff:1; // what we called statue?
|
||||||
/*30*/ unsigned untargetable:1; // Untargetable with mouse
|
/*31*/ unsigned untargetable:1; // bClickThrough
|
||||||
|
/* do these later
|
||||||
|
32 unsigned buyer:1;
|
||||||
|
33 unsigned offline:1;
|
||||||
|
34 unsigned interactiveobject:1;
|
||||||
|
35 unsigned flung:1; // hmm this vfunc appears to do stuff with leve and flung variables
|
||||||
|
36 unsigned title:1;
|
||||||
|
37 unsigned suffix:1;
|
||||||
|
38 unsigned padding1:1;
|
||||||
|
39 unsigned padding2:1;
|
||||||
|
40 unsinged padding3:1;
|
||||||
|
*/
|
||||||
/*
|
/*
|
||||||
// Unknown in RoF2
|
// Unknown in RoF2
|
||||||
unsigned betabuffed:1;
|
unsigned betabuffed:1;
|
||||||
@@ -498,7 +503,7 @@ struct Spawn_Struct
|
|||||||
|
|
||||||
/*0000*/ //char title[0]; // only read if(hasTitleOrSuffix & 4)
|
/*0000*/ //char title[0]; // only read if(hasTitleOrSuffix & 4)
|
||||||
/*0000*/ //char suffix[0]; // only read if(hasTitleOrSuffix & 8)
|
/*0000*/ //char suffix[0]; // only read if(hasTitleOrSuffix & 8)
|
||||||
char unknown20[8];
|
char unknown20[8]; // 2 ints, first unknown, 2nd SplineID
|
||||||
uint8 IsMercenary; // If NPC == 1 and this == 1, then the NPC name is Orange.
|
uint8 IsMercenary; // If NPC == 1 and this == 1, then the NPC name is Orange.
|
||||||
/*0000*/ char unknown21[55];
|
/*0000*/ char unknown21[55];
|
||||||
};
|
};
|
||||||
@@ -556,74 +561,100 @@ struct ServerZoneEntry_Struct //Adjusted from SEQ Everquest.h Struct
|
|||||||
//New Zone Struct - Size: 948
|
//New Zone Struct - Size: 948
|
||||||
struct NewZone_Struct {
|
struct NewZone_Struct {
|
||||||
/*0000*/ char char_name[64]; // Character Name
|
/*0000*/ char char_name[64]; // Character Name
|
||||||
/*0064*/ char zone_short_name[32]; // Zone Short Name
|
/*0064*/ char zone_short_name[128]; // Zone Short Name
|
||||||
/*0096*/ char unknown0096[96];
|
/*0192*/ char zone_long_name[128]; // Zone Long Name
|
||||||
/*0192*/ char zone_long_name[278]; // Zone Long Name
|
/*0320*/ char zone_desc[5][30]; // mostly just empty strings
|
||||||
/*0470*/ uint8 ztype; // Zone type (usually FF)
|
/*0470*/ uint8 ztype; // Zone type (usually FF) FogOnOff
|
||||||
/*0471*/ uint8 fog_red[4]; // Zone fog (red)
|
/*0471*/ uint8 fog_red[4]; // Zone fog (red) ARGBCOLOR
|
||||||
/*0475*/ uint8 fog_green[4]; // Zone fog (green)
|
/*0475*/ uint8 fog_green[4]; // Zone fog (green) ARGBCOLOR
|
||||||
/*0479*/ uint8 fog_blue[4]; // Zone fog (blue)
|
/*0479*/ uint8 fog_blue[4]; // Zone fog (blue) ARGBCOLO
|
||||||
/*0483*/ uint8 unknown323;
|
/*0483*/ uint8 unknown323; // padding?
|
||||||
/*0484*/ float fog_minclip[4];
|
/*0484*/ float fog_minclip[4]; // MQ2 has this starting at this offset, must be padding above
|
||||||
/*0500*/ float fog_maxclip[4];
|
/*0500*/ float fog_maxclip[4];
|
||||||
/*0516*/ float gravity;
|
/*0516*/ float gravity;
|
||||||
/*0520*/ uint8 time_type;
|
/*0520*/ uint8 time_type; // OutDoor flag 0 = IndoorDungeon, 1 = OUtdoor, 2 = OutdoorCity, 3 = DungeonCity, 4 = IndoorCity, 5 = OutdoorDungeon
|
||||||
/*0521*/ uint8 rain_chance[4];
|
/*0521*/ uint8 rain_chance[4];
|
||||||
/*0525*/ uint8 rain_duration[4];
|
/*0525*/ uint8 rain_duration[4];
|
||||||
/*0529*/ uint8 snow_chance[4];
|
/*0529*/ uint8 snow_chance[4];
|
||||||
/*0533*/ uint8 snow_duration[4];
|
/*0533*/ uint8 snow_duration[4];
|
||||||
/*0537*/ uint8 unknown537[32]; // Seen all 0xff
|
/*0537*/ uint8 unknown537[32]; // this is removed on live, specialdates and specialcodes probably macro'd out
|
||||||
/*0569*/ uint8 unknown569; // Unknown - Seen 0
|
/*0569*/ uint8 ZoneTimeZone; // MQ2 "in hours from worldserver, can be negative"
|
||||||
/*0570*/ uint8 sky; // Sky Type
|
/*0570*/ uint8 sky; // Sky Type
|
||||||
/*0571*/ uint8 unknown571; // Unknown - Seen 0
|
/*0571*/ uint8 unknown571; // Padding I think
|
||||||
/*0572*/ uint32 unknown572; // Unknown - Seen 4 in Guild Lobby
|
/*0572*/ uint32 WaterMidi; // Unknown - Seen 4 in Guild Lobby
|
||||||
/*0576*/ uint32 unknown576; // Unknown - Seen 2 in Guild Lobby
|
/*0576*/ uint32 DayMidi; // Unknown - Seen 2 in Guild Lobby
|
||||||
/*0580*/ uint32 unknown580; // Unknown - Seen 0 in Guild Lobby
|
/*0580*/ uint32 NightMidi; // Unknown - Seen 0 in Guild Lobby
|
||||||
/*0584*/ float zone_exp_multiplier; // Experience Multiplier
|
/*0584*/ float zone_exp_multiplier; // Experience Multiplier
|
||||||
/*0588*/ float safe_y; // Zone Safe Y
|
/*0588*/ float safe_y; // Zone Safe Y
|
||||||
/*0592*/ float safe_x; // Zone Safe X
|
/*0592*/ float safe_x; // Zone Safe X
|
||||||
/*0596*/ float safe_z; // Zone Safe Z
|
/*0596*/ float safe_z; // Zone Safe Z
|
||||||
/*0600*/ float min_z; // Guessed - NEW - Seen 0
|
/*0600*/ float min_z; // This isn't safe heading like live -- could be default heading rather than succor heading
|
||||||
/*0604*/ float max_z; // Guessed
|
/*0604*/ float max_z; // Ceiling
|
||||||
/*0608*/ float underworld; // Underworld, min z (Not Sure?)
|
/*0608*/ float underworld; // Underworld, min z (Not Sure?) Floor
|
||||||
/*0612*/ float minclip; // Minimum View Distance
|
/*0612*/ float minclip; // Minimum View Distance
|
||||||
/*0616*/ float maxclip; // Maximum View DIstance
|
/*0616*/ float maxclip; // Maximum View DIstance
|
||||||
/*0620*/ uint8 unknown620[84]; // ***Placeholder
|
/*0620*/ uint32 ForageLow; // Forage loot table ID?
|
||||||
/*0704*/ char zone_short_name2[96]; //zone file name? excludes instance number which can be in previous version.
|
/*0624*/ uint32 ForageMedium; // Forage loot table ID?
|
||||||
/*0800*/ int32 unknown800; //seen -1
|
/*0628*/ uint32 ForageHigh; // Forage loot table ID?
|
||||||
/*0804*/ char unknown804[40]; //
|
/*0632*/ uint32 FishingLow; // Fishing loot table ID?
|
||||||
/*0844*/ int32 unknown844; //seen 600
|
/*0636*/ uint32 FishingMedium; // Fishing loot table ID?
|
||||||
/*0848*/ int32 unknown848; //seen 2008
|
/*0640*/ uint32 FishingHigh; // Fishing loot table ID?
|
||||||
/*0852*/ uint16 zone_id;
|
/*0644*/ uint32 sky_lock; // MQ2 skyrelated
|
||||||
|
/*0648*/ uint32 graveyard_timer; // minutes until corpse pop to graveyard
|
||||||
|
/*0652*/ uint32 scriptIDHour; // These are IDs of scripts
|
||||||
|
/*0656*/ uint32 scriptIDMinute; // These are IDs of scripts
|
||||||
|
/*0660*/ uint32 scriptIDTick; // These are IDs of scripts
|
||||||
|
/*0664*/ uint32 scriptIDOnPlayerDeath; // These are IDs of scripts
|
||||||
|
/*0668*/ uint32 scriptIDOnNPCDeath; // These are IDs of scripts
|
||||||
|
/*0672*/ uint32 scriptIDPlayerEnteringZone; // These are IDs of scripts
|
||||||
|
/*0676*/ uint32 scriptIDOnZonePop; // These are IDs of scripts
|
||||||
|
/*0680*/ uint32 scriptIDNPCLoot; // These are IDs of scripts
|
||||||
|
/*0684*/ uint32 scriptIDAdventureFailed; // These are IDs of scripts
|
||||||
|
/*0688*/ uint32 CanExploreTasks;
|
||||||
|
/*0692*/ uint32 UnknownFlag; // not sure, neither is MQ2!
|
||||||
|
/*0696*/ uint32 scriptIDOnFishing; // THese are IDs of scripts
|
||||||
|
/*0700*/ uint32 scriptIDOnForage; // THese are IDs of scripts
|
||||||
|
/*0704*/ char zone_short_name2[32]; //zone file name? excludes instance number which can be in previous version.
|
||||||
|
/*0736*/ char WeatherString[32];
|
||||||
|
/*0768*/ char SkyString2[32];
|
||||||
|
/*0800*/ int32 SkyRelated2; //seen -1 -- maybe some default sky time?
|
||||||
|
/*0804*/ char WeatherString2[32]; //
|
||||||
|
/*0836*/ float WeatherChangeTime; // not sure :P
|
||||||
|
/*0840*/ uint32 Climate;
|
||||||
|
/*0844*/ int32 NPCAggroMaxDist; //seen 600
|
||||||
|
/*0848*/ int32 FilterID; //seen 2008 -- maybe zone guide related?
|
||||||
|
/*0852*/ uint16 zone_id; // this might just be instance ID got 1736 for time
|
||||||
/*0854*/ uint16 zone_instance;
|
/*0854*/ uint16 zone_instance;
|
||||||
/*0856*/ char unknown856[20];
|
/*0856*/ uint32 scriptNPCReceivedanItem;
|
||||||
/*0876*/ uint32 SuspendBuffs;
|
/*0860*/ uint32 bCheck; // padded bool
|
||||||
/*0880*/ uint32 unknown880; // Seen 50
|
/*0864*/ uint32 scriptIDSomething;
|
||||||
/*0884*/ uint32 unknown884; // Seen 10
|
/*0868*/ uint32 scriptIDSomething2;
|
||||||
/*0888*/ uint8 unknown888; // Seen 1
|
/*0872*/ uint32 scriptIDSomething3;
|
||||||
/*0889*/ uint8 unknown889; // Seen 0 (POK) or 1 (rujj)
|
/*0876*/ uint32 SuspendBuffs; // padded bool
|
||||||
/*0890*/ uint8 unknown890; // Seen 1
|
/*0880*/ uint32 LavaDamage; // LavaDamage value
|
||||||
/*0891*/ uint8 unknown891; // Seen 0
|
/*0884*/ uint32 MinLavaDamage; // min cap after resist calcs
|
||||||
/*0892*/ uint8 unknown892; // Seen 0
|
/*0888*/ uint8 bDisallowManaStone; // can't use manastone in this zone
|
||||||
/*0893*/ uint8 unknown893; // Seen 0 - 00
|
/*0889*/ uint8 bNoBind; // can't bind even if outdoor says we can!
|
||||||
/*0894*/ uint8 fall_damage; // 0 = Fall Damage on, 1 = Fall Damage off
|
/*0890*/ uint8 bNoAttack; // non-attack zone
|
||||||
/*0895*/ uint8 unknown895; // Seen 0 - 00
|
/*0891*/ uint8 bNoCallOfHero; // coth line disabled
|
||||||
/*0896*/ uint32 unknown896; // Seen 180
|
/*0892*/ uint8 bNoFlux; // gflux no worky
|
||||||
/*0900*/ uint32 unknown900; // Seen 180
|
/*0893*/ uint8 bNoFear; // fear spells no worky
|
||||||
/*0904*/ uint32 unknown904; // Seen 180
|
/*0894*/ uint8 fall_damage; // 0 = Fall Damage on, 1 = Fall Damage off MQ2 calls bNoEncumber
|
||||||
/*0908*/ uint32 unknown908; // Seen 2
|
/*0895*/ uint8 unknown895; // padding
|
||||||
/*0912*/ uint32 unknown912; // Seen 2
|
/*0896*/ uint32 FastRegenHP; // percentage I think?
|
||||||
/*0916*/ float FogDensity; // Most zones have this set to 0.33 Blightfire had 0.16
|
/*0900*/ uint32 FastRegenMana; // percentage I think?
|
||||||
/*0920*/ uint32 unknown920; // Seen 0
|
/*0904*/ uint32 FastRegenEndurance; // percentage I think?
|
||||||
/*0924*/ uint32 unknown924; // Seen 0
|
/*0908*/ uint32 CanPlaceCampsite; // 0 = no, 1 = can place, 2 = place and goto
|
||||||
/*0928*/ uint32 unknown928; // Seen 0
|
/*0912*/ uint32 CanPlaceGuildBanner; // ^
|
||||||
/*0932*/ int32 unknown932; // Seen -1
|
/*0916*/ float FogDensity; // Most zones have this set to 0.33 Blightfire had 0.16
|
||||||
/*0936*/ int32 unknown936; // Seen -1
|
/*0920*/ uint32 bAdjustGamma; // padded bool
|
||||||
/*0940*/ uint32 unknown940; // Seen 0
|
/*0924*/ uint32 TimeStringID; // Seen 0
|
||||||
/*0944*/ float unknown944; // Seen 1.0 in PoK, and 0.25 in Guild Lobby
|
/*0928*/ uint32 bNoMercenaries; // padded bool
|
||||||
/*0948*/ uint32 unknown948; // Seen 0 - New on Live as of Dec 15 2014
|
/*0932*/ int32 FishingRelated; // Seen -1 idk
|
||||||
/*0952*/ uint32 unknown952; // Seen 100 - New on Live as of Dec 15 2014
|
/*0936*/ int32 ForageRelated; // Seen -1 idk
|
||||||
/*0956*/
|
/*0940*/ uint32 bNoLevitate; // padded bool
|
||||||
|
/*0944*/ float Blooming; // Seen 1.0 in PoK, and 0.25 in Guild Lobby
|
||||||
|
/*0948*/
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
@@ -339,18 +339,7 @@ struct Spawn_Struct_Bitfields
|
|||||||
/*06*/ unsigned sneak:1;
|
/*06*/ unsigned sneak:1;
|
||||||
/*08*/ unsigned lfg:1;
|
/*08*/ unsigned lfg:1;
|
||||||
/*09*/ unsigned unknown09:1;
|
/*09*/ unsigned unknown09:1;
|
||||||
/*10*/ unsigned invis:1; // May have invis & sneak the wrong way around ... not sure how to tell which is which
|
/*10*/ unsigned invis:12; // there are 3000 different (non-GM) invis levels
|
||||||
/*11*/ unsigned invis1:1; // GM Invis? Can only be seen with #gm on - same for the below
|
|
||||||
/*12*/ unsigned invis2:1; // This one also make the NPC/PC invis
|
|
||||||
/*13*/ unsigned invis3:1; // This one also make the NPC/PC invis
|
|
||||||
/*14*/ unsigned invis4:1; // This one also make the NPC/PC invis
|
|
||||||
/*15*/ unsigned invis6:1; // This one also make the NPC/PC invis
|
|
||||||
/*16*/ unsigned invis7:1; // This one also make the NPC/PC invis
|
|
||||||
/*17*/ unsigned invis8:1; // This one also make the NPC/PC invis
|
|
||||||
/*18*/ unsigned invis9:1; // This one also make the NPC/PC invis
|
|
||||||
/*19*/ unsigned invis10:1; // This one also make the NPC/PC invis
|
|
||||||
/*20*/ unsigned invis11:1; // This one also make the NPC/PC invis
|
|
||||||
/*21*/ unsigned invis12:1; // This one also make the NPC/PC invis
|
|
||||||
/*22*/ unsigned linkdead:1; // 1 Toggles LD on or off after name. Correct for RoF
|
/*22*/ unsigned linkdead:1; // 1 Toggles LD on or off after name. Correct for RoF
|
||||||
/*23*/ unsigned showhelm:1;
|
/*23*/ unsigned showhelm:1;
|
||||||
/*24*/ unsigned unknown24:1; // Prefixes name with !
|
/*24*/ unsigned unknown24:1; // Prefixes name with !
|
||||||
|
|||||||
@@ -2560,7 +2560,7 @@ namespace SoD
|
|||||||
PacketSize += strlen(emu->DestructibleString) + 1;
|
PacketSize += strlen(emu->DestructibleString) + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ShowName = 1;
|
bool ShowName = emu->show_name;
|
||||||
if (emu->bodytype >= 66)
|
if (emu->bodytype >= 66)
|
||||||
{
|
{
|
||||||
emu->race = 127;
|
emu->race = 127;
|
||||||
|
|||||||
@@ -250,8 +250,7 @@ struct Spawn_Struct_Bitfields
|
|||||||
unsigned sneak:1;
|
unsigned sneak:1;
|
||||||
unsigned lfg:1;
|
unsigned lfg:1;
|
||||||
unsigned padding5:1;
|
unsigned padding5:1;
|
||||||
unsigned invis:1; // 0 = visible, 1 = invis/sneaking
|
unsigned invis:12; // there are 3000 different (non-GM) invis levels
|
||||||
unsigned padding7:11;
|
|
||||||
unsigned gm:1;
|
unsigned gm:1;
|
||||||
unsigned anon:2; // 0=normal, 1=anon, 2=roleplay
|
unsigned anon:2; // 0=normal, 1=anon, 2=roleplay
|
||||||
unsigned gender:2; // Gender (0=male, 1=female, 2=monster)
|
unsigned gender:2; // Gender (0=male, 1=female, 2=monster)
|
||||||
|
|||||||
@@ -2097,7 +2097,7 @@ namespace SoF
|
|||||||
int k;
|
int k;
|
||||||
for (r = 0; r < entrycount; r++, eq++, emu++) {
|
for (r = 0; r < entrycount; r++, eq++, emu++) {
|
||||||
|
|
||||||
eq->showname = 1; //New Field - Toggles Name Display on or off - 0 = off, 1 = on
|
eq->showname = emu->show_name ? 1 : 0; //New Field - Toggles Name Display on or off - 0 = off, 1 = on
|
||||||
eq->linkdead = 0; //New Field - Toggles LD on or off after name - 0 = off, 1 = on
|
eq->linkdead = 0; //New Field - Toggles LD on or off after name - 0 = off, 1 = on
|
||||||
eq->statue = 0; //New Field - 1 freezes animation
|
eq->statue = 0; //New Field - 1 freezes animation
|
||||||
eq->showhelm = emu->showhelm;
|
eq->showhelm = emu->showhelm;
|
||||||
@@ -2136,10 +2136,10 @@ namespace SoF
|
|||||||
eq->findable = emu->findable;
|
eq->findable = emu->findable;
|
||||||
if (emu->bodytype >= 66)
|
if (emu->bodytype >= 66)
|
||||||
{
|
{
|
||||||
eq->bodytype = 11; //non-targetable
|
eq->bodytype = 11; //non-targetable
|
||||||
eq->showname = 0; //no visible name
|
eq->showname = 0; //no visible name
|
||||||
eq->race = 127; //invisible man
|
eq->race = 127; //invisible man
|
||||||
eq->gender = 0; //invisible men are gender 0
|
eq->gender = 0; //invisible men are gender 0
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -2844,7 +2844,7 @@ namespace UF
|
|||||||
PacketSize += strlen(emu->DestructibleString) + 1;
|
PacketSize += strlen(emu->DestructibleString) + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ShowName = 1;
|
bool ShowName = emu->show_name;
|
||||||
if (emu->bodytype >= 66)
|
if (emu->bodytype >= 66)
|
||||||
{
|
{
|
||||||
emu->race = 127;
|
emu->race = 127;
|
||||||
|
|||||||
@@ -250,8 +250,7 @@ struct Spawn_Struct_Bitfields
|
|||||||
unsigned sneak:1;
|
unsigned sneak:1;
|
||||||
unsigned lfg:1;
|
unsigned lfg:1;
|
||||||
unsigned padding5:1;
|
unsigned padding5:1;
|
||||||
unsigned invis:1; // 0 = visible, 1 = invis/sneaking
|
unsigned invis:12; // there are 3000 different (non-GM) invis levels
|
||||||
unsigned padding7:11;
|
|
||||||
unsigned gm:1;
|
unsigned gm:1;
|
||||||
unsigned anon:2; // 0=normal, 1=anon, 2=roleplay
|
unsigned anon:2; // 0=normal, 1=anon, 2=roleplay
|
||||||
unsigned gender:2; // Gender (0=male, 1=female, 2=monster)
|
unsigned gender:2; // Gender (0=male, 1=female, 2=monster)
|
||||||
|
|||||||
@@ -28,9 +28,9 @@
|
|||||||
typedef const char Const_char;
|
typedef const char Const_char;
|
||||||
|
|
||||||
#ifdef EMBPERL
|
#ifdef EMBPERL
|
||||||
#include "../common/global_define.h"
|
#include "global_define.h"
|
||||||
#include "../common/useperl.h"
|
|
||||||
#include "eqdb.h"
|
#include "eqdb.h"
|
||||||
|
#include "useperl.h"
|
||||||
|
|
||||||
#ifdef THIS /* this macro seems to leak out on some systems */
|
#ifdef THIS /* this macro seems to leak out on some systems */
|
||||||
#undef THIS
|
#undef THIS
|
||||||
|
|||||||
@@ -28,9 +28,9 @@
|
|||||||
typedef const char Const_char;
|
typedef const char Const_char;
|
||||||
|
|
||||||
#ifdef EMBPERL
|
#ifdef EMBPERL
|
||||||
#include "../common/global_define.h"
|
#include "global_define.h"
|
||||||
#include "../common/useperl.h"
|
|
||||||
#include "eqdb_res.h"
|
#include "eqdb_res.h"
|
||||||
|
#include "useperl.h"
|
||||||
|
|
||||||
|
|
||||||
XS(XS_EQDBRes_num_rows); /* prototype to pass -Wmissing-prototypes */
|
XS(XS_EQDBRes_num_rows); /* prototype to pass -Wmissing-prototypes */
|
||||||
|
|||||||
+8
-3
@@ -134,7 +134,6 @@ RULE_INT(Character, TradeskillUpMakePoison, 2) // Make Poison skillup rate adjus
|
|||||||
RULE_INT(Character, TradeskillUpPottery, 4) // Pottery skillup rate adjust. Lower is faster.
|
RULE_INT(Character, TradeskillUpPottery, 4) // Pottery skillup rate adjust. Lower is faster.
|
||||||
RULE_INT(Character, TradeskillUpResearch, 1) // Research skillup rate adjust. Lower is faster.
|
RULE_INT(Character, TradeskillUpResearch, 1) // Research skillup rate adjust. Lower is faster.
|
||||||
RULE_INT(Character, TradeskillUpTinkering, 2) // Tinkering skillup rate adjust. Lower is faster.
|
RULE_INT(Character, TradeskillUpTinkering, 2) // Tinkering skillup rate adjust. Lower is faster.
|
||||||
RULE_BOOL(Character, SpamHPUpdates, false) // if your server has stupid amounts of HP that causes client display issues, turn this on!
|
|
||||||
RULE_BOOL(Character, MarqueeHPUpdates, false) // Will show Health % in center of screen < 100%
|
RULE_BOOL(Character, MarqueeHPUpdates, false) // Will show Health % in center of screen < 100%
|
||||||
RULE_INT(Character, IksarCommonTongue, 95) // 95 By default (live-like?)
|
RULE_INT(Character, IksarCommonTongue, 95) // 95 By default (live-like?)
|
||||||
RULE_INT(Character, OgreCommonTongue, 95) // 95 By default (live-like?)
|
RULE_INT(Character, OgreCommonTongue, 95) // 95 By default (live-like?)
|
||||||
@@ -151,6 +150,7 @@ RULE_BOOL(Character, AllowMQTarget, false) // Disables putting players in the 'h
|
|||||||
RULE_BOOL(Character, UseOldBindWound, false) // Uses the original bind wound behavior
|
RULE_BOOL(Character, UseOldBindWound, false) // Uses the original bind wound behavior
|
||||||
RULE_BOOL(Character, GrantHoTTOnCreate, false) // Grant Health of Target's Target leadership AA on character creation
|
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, 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_CATEGORY_END()
|
RULE_CATEGORY_END()
|
||||||
|
|
||||||
RULE_CATEGORY(Mercs)
|
RULE_CATEGORY(Mercs)
|
||||||
@@ -235,7 +235,6 @@ RULE_BOOL(World, StartZoneSameAsBindOnCreation, true) //Should the start zone AL
|
|||||||
RULE_CATEGORY_END()
|
RULE_CATEGORY_END()
|
||||||
|
|
||||||
RULE_CATEGORY(Zone)
|
RULE_CATEGORY(Zone)
|
||||||
RULE_INT(Zone, NPCPositonUpdateTicCount, 32) //ms between intervals of sending a position update to the entire zone.
|
|
||||||
RULE_INT(Zone, ClientLinkdeadMS, 180000) //the time a client remains link dead on the server after a sudden disconnection
|
RULE_INT(Zone, ClientLinkdeadMS, 180000) //the time a client remains link dead on the server after a sudden disconnection
|
||||||
RULE_INT(Zone, GraveyardTimeMS, 1200000) //ms time until a player corpse is moved to a zone's graveyard, if one is specified for the zone
|
RULE_INT(Zone, GraveyardTimeMS, 1200000) //ms time until a player corpse is moved to a zone's graveyard, if one is specified for the zone
|
||||||
RULE_BOOL(Zone, EnableShadowrest, 1) // enables or disables the shadowrest zone feature for player corpses. Default is turned on.
|
RULE_BOOL(Zone, EnableShadowrest, 1) // enables or disables the shadowrest zone feature for player corpses. Default is turned on.
|
||||||
@@ -274,6 +273,8 @@ RULE_BOOL(Map, FixPathingZWhenLoading, true) //increases zone boot times a bit
|
|||||||
RULE_BOOL(Map, FixPathingZAtWaypoints, false) //alternative to `WhenLoading`, accomplishes the same thing but does it at each waypoint instead of once at boot time.
|
RULE_BOOL(Map, FixPathingZAtWaypoints, false) //alternative to `WhenLoading`, accomplishes the same thing but does it at each waypoint instead of once at boot time.
|
||||||
RULE_BOOL(Map, FixPathingZWhenMoving, false) //very CPU intensive, but helps hopping with widely spaced waypoints.
|
RULE_BOOL(Map, FixPathingZWhenMoving, false) //very CPU intensive, but helps hopping with widely spaced waypoints.
|
||||||
RULE_BOOL(Map, FixPathingZOnSendTo, false) //try to repair Z coords in the SendTo routine as well.
|
RULE_BOOL(Map, FixPathingZOnSendTo, false) //try to repair Z coords in the SendTo routine as well.
|
||||||
|
RULE_BOOL(Map, FixZWhenMoving, true) // Automatically fix NPC Z coordinates when moving/pathing/engaged (Far less CPU intensive than its predecessor)
|
||||||
|
RULE_BOOL(Map, MobZVisualDebug, false) // Displays spell effects determining whether or not NPC is hitting Best Z calcs (blue for hit, red for miss)
|
||||||
RULE_REAL(Map, FixPathingZMaxDeltaMoving, 20) //at runtime while pathing: max change in Z to allow the BestZ code to apply.
|
RULE_REAL(Map, FixPathingZMaxDeltaMoving, 20) //at runtime while pathing: max change in Z to allow the BestZ code to apply.
|
||||||
RULE_REAL(Map, FixPathingZMaxDeltaWaypoint, 20) //at runtime at each waypoint: max change in Z to allow the BestZ code to apply.
|
RULE_REAL(Map, FixPathingZMaxDeltaWaypoint, 20) //at runtime at each waypoint: max change in Z to allow the BestZ code to apply.
|
||||||
RULE_REAL(Map, FixPathingZMaxDeltaSendTo, 20) //at runtime in SendTo: max change in Z to allow the BestZ code to apply.
|
RULE_REAL(Map, FixPathingZMaxDeltaSendTo, 20) //at runtime in SendTo: max change in Z to allow the BestZ code to apply.
|
||||||
@@ -289,7 +290,7 @@ RULE_BOOL(Pathing, AggroReturnToGrid, true) // Enable pathing for aggroed roamin
|
|||||||
RULE_BOOL(Pathing, Guard, true) // Enable pathing for mobs moving to their guard point.
|
RULE_BOOL(Pathing, Guard, true) // Enable pathing for mobs moving to their guard point.
|
||||||
RULE_BOOL(Pathing, Find, true) // Enable pathing for FindPerson requests from the client.
|
RULE_BOOL(Pathing, Find, true) // Enable pathing for FindPerson requests from the client.
|
||||||
RULE_BOOL(Pathing, Fear, true) // Enable pathing for fear
|
RULE_BOOL(Pathing, Fear, true) // Enable pathing for fear
|
||||||
RULE_REAL(Pathing, ZDiffThreshold, 10) // If a mob las LOS to it's target, it will run to it if the Z difference is < this.
|
RULE_REAL(Pathing, ZDiffThresholdNew, 80) // If a mob las LOS to it's target, it will run to it if the Z difference is < this.
|
||||||
RULE_INT(Pathing, LOSCheckFrequency, 1000) // A mob will check for LOS to it's target this often (milliseconds).
|
RULE_INT(Pathing, LOSCheckFrequency, 1000) // A mob will check for LOS to it's target this often (milliseconds).
|
||||||
RULE_INT(Pathing, RouteUpdateFrequencyShort, 1000) // How often a new route will be calculated if the target has moved.
|
RULE_INT(Pathing, RouteUpdateFrequencyShort, 1000) // How often a new route will be calculated if the target has moved.
|
||||||
RULE_INT(Pathing, RouteUpdateFrequencyLong, 5000) // How often a new route will be calculated if the target has moved.
|
RULE_INT(Pathing, RouteUpdateFrequencyLong, 5000) // How often a new route will be calculated if the target has moved.
|
||||||
@@ -348,6 +349,7 @@ RULE_INT(Spells, MaxTotalSlotsNPC, 60) // default to Tit's limit
|
|||||||
RULE_INT(Spells, MaxTotalSlotsPET, 30) // default to Tit's limit
|
RULE_INT(Spells, MaxTotalSlotsPET, 30) // default to Tit's limit
|
||||||
RULE_BOOL (Spells, EnableBlockedBuffs, true)
|
RULE_BOOL (Spells, EnableBlockedBuffs, true)
|
||||||
RULE_INT(Spells, ReflectType, 3) //0 = disabled, 1 = single target player spells only, 2 = all player spells, 3 = all single target spells, 4 = all spells
|
RULE_INT(Spells, ReflectType, 3) //0 = disabled, 1 = single target player spells only, 2 = all player spells, 3 = all single target spells, 4 = all spells
|
||||||
|
RULE_BOOL(Spells, ReflectMessagesClose, true) // Live functionality is for Reflect messages to show to players within close proximity, false shows just player reflecting
|
||||||
RULE_INT(Spells, VirusSpreadDistance, 30) // The distance a viral spell will jump to its next victim
|
RULE_INT(Spells, VirusSpreadDistance, 30) // The distance a viral spell will jump to its next victim
|
||||||
RULE_BOOL(Spells, LiveLikeFocusEffects, true) // Determines whether specific healing, dmg and mana reduction focuses are randomized
|
RULE_BOOL(Spells, LiveLikeFocusEffects, true) // Determines whether specific healing, dmg and mana reduction focuses are randomized
|
||||||
RULE_INT(Spells, BaseImmunityLevel, 55) // The level that targets start to be immune to stun, fear and mez spells with a max level of 0.
|
RULE_INT(Spells, BaseImmunityLevel, 55) // The level that targets start to be immune to stun, fear and mez spells with a max level of 0.
|
||||||
@@ -397,6 +399,7 @@ RULE_BOOL(Spells, FlatItemExtraSpellAmt, false) // allow SpellDmg stat to affect
|
|||||||
RULE_BOOL(Spells, IgnoreSpellDmgLvlRestriction, false) // ignore the 5 level spread on applying SpellDmg
|
RULE_BOOL(Spells, IgnoreSpellDmgLvlRestriction, false) // ignore the 5 level spread on applying SpellDmg
|
||||||
RULE_BOOL(Spells, AllowItemTGB, false) // TGB doesn't work with items on live, custom servers want it though
|
RULE_BOOL(Spells, AllowItemTGB, false) // TGB doesn't work with items on live, custom servers want it though
|
||||||
RULE_BOOL(Spells, NPCInnateProcOverride, true) // NPC innate procs override the target type to single target.
|
RULE_BOOL(Spells, NPCInnateProcOverride, true) // NPC innate procs override the target type to single target.
|
||||||
|
RULE_BOOL(Spells, OldRainTargets, false) // use old incorrectly implemented max targets for rains
|
||||||
RULE_CATEGORY_END()
|
RULE_CATEGORY_END()
|
||||||
|
|
||||||
RULE_CATEGORY(Combat)
|
RULE_CATEGORY(Combat)
|
||||||
@@ -560,6 +563,8 @@ RULE_INT(Range, DamageMessages, 50)
|
|||||||
RULE_INT(Range, SpellMessages, 75)
|
RULE_INT(Range, SpellMessages, 75)
|
||||||
RULE_INT(Range, SongMessages, 75)
|
RULE_INT(Range, SongMessages, 75)
|
||||||
RULE_INT(Range, MobPositionUpdates, 600)
|
RULE_INT(Range, MobPositionUpdates, 600)
|
||||||
|
RULE_INT(Range, ClientPositionUpdates, 300)
|
||||||
|
RULE_INT(Range, ClientForceSpawnUpdateRange, 1000)
|
||||||
RULE_INT(Range, CriticalDamage, 80)
|
RULE_INT(Range, CriticalDamage, 80)
|
||||||
RULE_INT(Range, ClientNPCScan, 300)
|
RULE_INT(Range, ClientNPCScan, 300)
|
||||||
RULE_CATEGORY_END()
|
RULE_CATEGORY_END()
|
||||||
|
|||||||
@@ -189,6 +189,7 @@
|
|||||||
#define ServerOP_ReloadWorld 0x4009
|
#define ServerOP_ReloadWorld 0x4009
|
||||||
#define ServerOP_ReloadLogs 0x4010
|
#define ServerOP_ReloadLogs 0x4010
|
||||||
#define ServerOP_ReloadPerlExportSettings 0x4011
|
#define ServerOP_ReloadPerlExportSettings 0x4011
|
||||||
|
#define ServerOP_CZSetEntityVariableByClientName 0x4012
|
||||||
/* Query Server OP Codes */
|
/* Query Server OP Codes */
|
||||||
#define ServerOP_QSPlayerLogTrades 0x5010
|
#define ServerOP_QSPlayerLogTrades 0x5010
|
||||||
#define ServerOP_QSPlayerLogHandins 0x5011
|
#define ServerOP_QSPlayerLogHandins 0x5011
|
||||||
@@ -1263,6 +1264,12 @@ struct CZSetEntVarByNPCTypeID_Struct {
|
|||||||
char m_var[256];
|
char m_var[256];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct CZSetEntVarByClientName_Struct {
|
||||||
|
char CharName[64];
|
||||||
|
char id[256];
|
||||||
|
char m_var[256];
|
||||||
|
};
|
||||||
|
|
||||||
struct ReloadWorld_Struct{
|
struct ReloadWorld_Struct{
|
||||||
uint32 Option;
|
uint32 Option;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1674,6 +1674,7 @@ void SharedDatabase::LoadSpells(void *data, int max_spells) {
|
|||||||
for (y = 0; y < 16; y++)
|
for (y = 0; y < 16; y++)
|
||||||
sp[tempid].deities[y]=atoi(row[126+y]);
|
sp[tempid].deities[y]=atoi(row[126+y]);
|
||||||
|
|
||||||
|
sp[tempid].new_icon=atoi(row[144]);
|
||||||
sp[tempid].uninterruptable=atoi(row[146]) != 0;
|
sp[tempid].uninterruptable=atoi(row[146]) != 0;
|
||||||
sp[tempid].ResistDiff=atoi(row[147]);
|
sp[tempid].ResistDiff=atoi(row[147]);
|
||||||
sp[tempid].dot_stacking_exempt = atoi(row[148]) != 0;
|
sp[tempid].dot_stacking_exempt = atoi(row[148]) != 0;
|
||||||
|
|||||||
+4
-4
@@ -562,9 +562,9 @@ typedef enum {
|
|||||||
#define SE_LimitManaMin 348 // implemented
|
#define SE_LimitManaMin 348 // implemented
|
||||||
#define SE_ShieldEquipDmgMod 349 // implemented[AA] Increase melee base damage (indirectly increasing hate) when wearing a shield.
|
#define SE_ShieldEquipDmgMod 349 // implemented[AA] Increase melee base damage (indirectly increasing hate) when wearing a shield.
|
||||||
#define SE_ManaBurn 350 // implemented - Drains mana for damage/heal at a defined ratio up to a defined maximum amount of mana.
|
#define SE_ManaBurn 350 // implemented - Drains mana for damage/heal at a defined ratio up to a defined maximum amount of mana.
|
||||||
//#define SE_PersistentEffect 351 // *not implemented. creates a trap/totem that casts a spell (spell id + base1?) when anything comes near it. can probably make a beacon for this
|
#define SE_PersistentEffect 351 // *not implemented. creates a trap/totem that casts a spell (spell id + base1?) when anything comes near it. can probably make a beacon for this
|
||||||
//#define SE_IncreaseTrapCount 352 // *not implemented - looks to be some type of invulnerability? Test ITC (8755)
|
#define SE_IncreaseTrapCount 352 // *not implemented - looks to be some type of invulnerability? Test ITC (8755)
|
||||||
//#define SE_AdditionalAura 353 // *not implemented - allows use of more than 1 aura, aa effect
|
#define SE_AdditionalAura 353 // *not implemented - allows use of more than 1 aura, aa effect
|
||||||
//#define SE_DeactivateAllTraps 354 // *not implemented - looks to be some type of invulnerability? Test DAT (8757)
|
//#define SE_DeactivateAllTraps 354 // *not implemented - looks to be some type of invulnerability? Test DAT (8757)
|
||||||
//#define SE_LearnTrap 355 // *not implemented - looks to be some type of invulnerability? Test LT (8758)
|
//#define SE_LearnTrap 355 // *not implemented - looks to be some type of invulnerability? Test LT (8758)
|
||||||
//#define SE_ChangeTriggerType 356 // not used
|
//#define SE_ChangeTriggerType 356 // not used
|
||||||
@@ -757,7 +757,7 @@ struct SPDat_Spell_Struct
|
|||||||
// -- DIETY_BERTOXXULOUS ... DIETY_VEESHAN
|
// -- DIETY_BERTOXXULOUS ... DIETY_VEESHAN
|
||||||
/* 142 */ //int8 npc_no_cast; // 142: between 0 & 100 -- NPC_NO_CAST
|
/* 142 */ //int8 npc_no_cast; // 142: between 0 & 100 -- NPC_NO_CAST
|
||||||
/* 143 */ //int ai_pt_bonus; // 143: always set to 0, client doesn't save this -- AI_PT_BONUS
|
/* 143 */ //int ai_pt_bonus; // 143: always set to 0, client doesn't save this -- AI_PT_BONUS
|
||||||
/* 144 */ //int16 new_icon // Spell icon used by the client in uifiles/default/spells??.tga, both for spell gems & buff window. Looks to depreciate icon & memicon -- NEW_ICON
|
/* 144 */ int16 new_icon; // Spell icon used by the client in uifiles/default/spells??.tga, both for spell gems & buff window. Looks to depreciate icon & memicon -- NEW_ICON
|
||||||
/* 145 */ //int16 spellanim; // Doesn't look like it's the same as #doanim, so not sure what this is, particles I think -- SPELL_EFFECT_INDEX
|
/* 145 */ //int16 spellanim; // Doesn't look like it's the same as #doanim, so not sure what this is, particles I think -- SPELL_EFFECT_INDEX
|
||||||
/* 146 */ bool uninterruptable; // Looks like anything != 0 is uninterruptable. Values are mostly -1, 0, & 1 (Fetid Breath = 90?) -- NO_INTERRUPT
|
/* 146 */ bool uninterruptable; // Looks like anything != 0 is uninterruptable. Values are mostly -1, 0, & 1 (Fetid Breath = 90?) -- NO_INTERRUPT
|
||||||
/* 147 */ int16 ResistDiff; // -- RESIST_MOD
|
/* 147 */ int16 ResistDiff; // -- RESIST_MOD
|
||||||
|
|||||||
+1
-1
@@ -30,7 +30,7 @@
|
|||||||
Manifest: https://github.com/EQEmu/Server/blob/master/utils/sql/db_update_manifest.txt
|
Manifest: https://github.com/EQEmu/Server/blob/master/utils/sql/db_update_manifest.txt
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define CURRENT_BINARY_DATABASE_VERSION 9110
|
#define CURRENT_BINARY_DATABASE_VERSION 9114
|
||||||
#ifdef BOTS
|
#ifdef BOTS
|
||||||
#define CURRENT_BINARY_BOTS_DATABASE_VERSION 9017
|
#define CURRENT_BINARY_BOTS_DATABASE_VERSION 9017
|
||||||
#else
|
#else
|
||||||
|
|||||||
@@ -4,3 +4,4 @@ ENDIF(EQEMU_BUILD_LUA)
|
|||||||
|
|
||||||
ADD_SUBDIRECTORY(libuv)
|
ADD_SUBDIRECTORY(libuv)
|
||||||
ADD_SUBDIRECTORY(format)
|
ADD_SUBDIRECTORY(format)
|
||||||
|
ADD_SUBDIRECTORY(recast)
|
||||||
+3
@@ -0,0 +1,3 @@
|
|||||||
|
<!---
|
||||||
|
Please make sure you've followed the guidelines outlined in the CONTRIBUTING.rst 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,4 +1,5 @@
|
|||||||
language: cpp
|
language: cpp
|
||||||
|
dist: trusty
|
||||||
sudo: required # the doc target uses sudo to install dependencies
|
sudo: required # the doc target uses sudo to install dependencies
|
||||||
|
|
||||||
os:
|
os:
|
||||||
@@ -22,12 +23,5 @@ matrix:
|
|||||||
- os: osx
|
- os: osx
|
||||||
env: BUILD=Doc
|
env: BUILD=Doc
|
||||||
|
|
||||||
addons:
|
|
||||||
apt:
|
|
||||||
sources:
|
|
||||||
- kubuntu-backports # cmake 2.8.12
|
|
||||||
packages:
|
|
||||||
- cmake
|
|
||||||
|
|
||||||
script:
|
script:
|
||||||
- support/travis-build.py
|
- support/travis-build.py
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
message(STATUS "CMake version: ${CMAKE_VERSION}")
|
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)
|
# Determine if fmt is built as a subproject (using add_subdirectory)
|
||||||
# or if it is the master project.
|
# or if it is the master project.
|
||||||
@@ -9,12 +9,22 @@ if (CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_SOURCE_DIR)
|
|||||||
set(MASTER_PROJECT ON)
|
set(MASTER_PROJECT ON)
|
||||||
endif ()
|
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.
|
# Set the default CMAKE_BUILD_TYPE to Release.
|
||||||
# This should be done before the project command since the latter can set
|
# This should be done before the project command since the latter can set
|
||||||
# CMAKE_BUILD_TYPE itself (it does so for nmake).
|
# CMAKE_BUILD_TYPE itself (it does so for nmake).
|
||||||
if (NOT CMAKE_BUILD_TYPE)
|
if (NOT CMAKE_BUILD_TYPE)
|
||||||
set(CMAKE_BUILD_TYPE Release CACHE STRING
|
join(doc "Choose the type of build, options are: None(CMAKE_CXX_FLAGS or "
|
||||||
"Choose the type of build, options are: None(CMAKE_CXX_FLAGS or CMAKE_C_FLAGS used) Debug Release RelWithDebInfo MinSizeRel.")
|
"CMAKE_C_FLAGS used) Debug Release RelWithDebInfo MinSizeRel.")
|
||||||
|
set(CMAKE_BUILD_TYPE Release CACHE STRING ${doc})
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
option(FMT_PEDANTIC "Enable extra warnings and expensive tests." OFF)
|
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)
|
project(FMT)
|
||||||
|
|
||||||
# Starting with cmake 3.0 VERSION is part of the project command.
|
# Starting with cmake 3.0 VERSION is part of the project command.
|
||||||
set(FMT_VERSION 3.0.0)
|
file(READ fmt/format.h format_h)
|
||||||
if (NOT FMT_VERSION MATCHES "^([0-9]+).([0-9]+).([0-9]+)$")
|
if (NOT format_h MATCHES "FMT_VERSION ([0-9]+)([0-9][0-9])([0-9][0-9])")
|
||||||
message(FATAL_ERROR "Invalid version format ${FMT_VERSION}.")
|
message(FATAL_ERROR "Cannot get FMT_VERSION from format.h.")
|
||||||
endif ()
|
endif ()
|
||||||
set(CPACK_PACKAGE_VERSION_MAJOR ${CMAKE_MATCH_1})
|
# Use math to skip leading zeros if any.
|
||||||
set(CPACK_PACKAGE_VERSION_MINOR ${CMAKE_MATCH_2})
|
math(EXPR CPACK_PACKAGE_VERSION_MAJOR ${CMAKE_MATCH_1})
|
||||||
set(CPACK_PACKAGE_VERSION_PATCH ${CMAKE_MATCH_3})
|
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}")
|
message(STATUS "Build type: ${CMAKE_BUILD_TYPE}")
|
||||||
|
|
||||||
|
|||||||
@@ -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!
|
||||||
@@ -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
|
3.0.0 - 2016-05-07
|
||||||
------------------
|
------------------
|
||||||
|
|
||||||
|
|||||||
+28
-5
@@ -20,9 +20,11 @@ alternative to IOStreams.
|
|||||||
Features
|
Features
|
||||||
--------
|
--------
|
||||||
|
|
||||||
* Two APIs: faster concatenation-based write API and slower (but still
|
* Two APIs: faster concatenation-based `write API
|
||||||
very fast) replacement-based format API with positional arguments for
|
<http://fmtlib.net/latest/api.html#write-api>`_ and slower,
|
||||||
localization.
|
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
|
* Write API similar to the one used by IOStreams but stateless allowing
|
||||||
faster implementation.
|
faster implementation.
|
||||||
* Format API with `format string syntax
|
* Format API with `format string syntax
|
||||||
@@ -35,10 +37,10 @@ Features
|
|||||||
* Support for user-defined types.
|
* Support for user-defined types.
|
||||||
* High speed: performance of the format API is close to that of
|
* High speed: performance of the format API is close to that of
|
||||||
glibc's `printf <http://en.cppreference.com/w/cpp/io/c/fprintf>`_
|
glibc's `printf <http://en.cppreference.com/w/cpp/io/c/fprintf>`_
|
||||||
and better than performance of IOStreams. See `Speed tests`_ and
|
and better than the performance of IOStreams. See `Speed tests`_ and
|
||||||
`Fast integer to string conversion in C++
|
`Fast integer to string conversion in C++
|
||||||
<http://zverovich.net/2013/09/07/integer-to-string-conversion-in-cplusplus.html>`_.
|
<http://zverovich.net/2013/09/07/integer-to-string-conversion-in-cplusplus.html>`_.
|
||||||
* 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.
|
header file and a single source file) and compiled code.
|
||||||
See `Compile time and code bloat`_.
|
See `Compile time and code bloat`_.
|
||||||
* Reliability: the library has an extensive set of `unit tests
|
* 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++
|
.. code:: c++
|
||||||
|
|
||||||
|
#include "fmt/ostream.h"
|
||||||
|
|
||||||
class Date {
|
class Date {
|
||||||
int year_, month_, day_;
|
int year_, month_, day_;
|
||||||
public:
|
public:
|
||||||
@@ -132,6 +136,12 @@ Projects using this library
|
|||||||
* `AMPL/MP <https://github.com/ampl/mp>`_:
|
* `AMPL/MP <https://github.com/ampl/mp>`_:
|
||||||
An open-source library for mathematical programming
|
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>`_:
|
* `HarpyWar/pvpgn <https://github.com/pvpgn/pvpgn-server>`_:
|
||||||
Player vs Player Gaming Network with tweaks
|
Player vs Player Gaming Network with tweaks
|
||||||
|
|
||||||
@@ -139,6 +149,8 @@ Projects using this library
|
|||||||
|
|
||||||
* `Keypirinha <http://keypirinha.com/>`_: A semantic launcher for Windows
|
* `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
|
* `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
|
* `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/>`_:
|
* `Salesforce Analytics Cloud <http://www.salesforce.com/analytics-cloud/overview/>`_:
|
||||||
Business intelligence software
|
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
|
* `spdlog <https://github.com/gabime/spdlog>`_: Super fast C++ logging library
|
||||||
|
|
||||||
* `Stellar <https://www.stellar.org/>`_: Financial platform
|
* `Stellar <https://www.stellar.org/>`_: Financial platform
|
||||||
@@ -390,6 +408,11 @@ It only applies if you distribute the documentation of fmt.
|
|||||||
Acknowledgments
|
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
|
The benchmark section of this readme file and the performance tests are taken
|
||||||
from the excellent `tinyformat <https://github.com/c42f/tinyformat>`_ library
|
from the excellent `tinyformat <https://github.com/c42f/tinyformat>`_ library
|
||||||
written by Chris Foster. Boost Format library is acknowledged transitively
|
written by Chris Foster. Boost Format library is acknowledged transitively
|
||||||
|
|||||||
@@ -1,2 +0,0 @@
|
|||||||
#include "../fmt/format.h"
|
|
||||||
#warning Including cppformat/format.h is deprecated. Include fmt/format.h instead.
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
#include "../fmt/posix.h"
|
|
||||||
#warning Including cppformat/posix.h is deprecated. Include fmt/posix.h instead.
|
|
||||||
@@ -5,6 +5,8 @@ if (NOT DOXYGEN)
|
|||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
add_custom_target(doc
|
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)
|
||||||
|
|||||||
Vendored
+28
@@ -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
@@ -8,8 +8,9 @@
|
|||||||
{# Google Analytics #}
|
{# Google Analytics #}
|
||||||
<script>
|
<script>
|
||||||
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
|
(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),
|
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();
|
||||||
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
|
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');
|
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
|
||||||
ga('create', 'UA-20116650-4', 'fmtlib.net');
|
ga('create', 'UA-20116650-4', 'fmtlib.net');
|
||||||
ga('send', 'pageview');
|
ga('send', 'pageview');
|
||||||
@@ -17,9 +18,11 @@
|
|||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{%- macro searchform(classes, button) %}
|
{%- 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">
|
<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>
|
</div>
|
||||||
<input type="hidden" name="check_keywords" value="yes" />
|
<input type="hidden" name="check_keywords" value="yes" />
|
||||||
<input type="hidden" name="area" value="default" />
|
<input type="hidden" name="area" value="default" />
|
||||||
@@ -36,7 +39,8 @@
|
|||||||
<div class="navbar-content">
|
<div class="navbar-content">
|
||||||
{# Brand and toggle get grouped for better mobile display #}
|
{# Brand and toggle get grouped for better mobile display #}
|
||||||
<div class="navbar-header">
|
<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="sr-only">Toggle navigation</span>
|
||||||
<span class="icon-bar"></span>
|
<span class="icon-bar"></span>
|
||||||
<span class="icon-bar"></span>
|
<span class="icon-bar"></span>
|
||||||
@@ -49,18 +53,19 @@
|
|||||||
<div class="collapse navbar-collapse">
|
<div class="collapse navbar-collapse">
|
||||||
<ul class="nav navbar-nav">
|
<ul class="nav navbar-nav">
|
||||||
<li class="dropdown">
|
<li class="dropdown">
|
||||||
{# TODO: update versions automatically #}
|
<a href="#" class="dropdown-toggle" data-toggle="dropdown"
|
||||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button"
|
role="button" aria-expanded="false">{{ version }}
|
||||||
aria-expanded="false">{{ version }} <span class="caret"></span></a>
|
<span class="caret"></span></a>
|
||||||
<ul class="dropdown-menu" role="menu">
|
<ul class="dropdown-menu" role="menu">
|
||||||
<li><a href="http://fmtlib.net/2.0.0/">2.0.0</a></li>
|
{% for v in versions.split(',') %}
|
||||||
<li><a href="http://fmtlib.net/1.1.0/">1.1.0</a></li>
|
<li><a href="http://fmtlib.net/{{v}}">{{v}}</a></li>
|
||||||
<li><a href="http://fmtlib.net/1.0.0/">1.0.0</a></li>
|
{% endfor %}
|
||||||
</ul>
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
{% for name in ['Contents', 'Usage', 'API', 'Syntax'] %}
|
{% for name in ['Contents', 'Usage', 'API', 'Syntax'] %}
|
||||||
{% if pagename == name.lower() %}
|
{% 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%}
|
{%else%}
|
||||||
<li><a href="{{name.lower()}}.html">{{name}}</a></li>
|
<li><a href="{{name.lower()}}.html">{{name}}</a></li>
|
||||||
{%endif%}
|
{%endif%}
|
||||||
@@ -75,20 +80,25 @@
|
|||||||
</div> {# /.tb-container #}
|
</div> {# /.tb-container #}
|
||||||
</nav>
|
</nav>
|
||||||
{% if pagename == "index" %}
|
{% if pagename == "index" %}
|
||||||
|
{% set download_url = 'https://github.com/fmtlib/fmt/releases/download' %}
|
||||||
<div class="jumbotron">
|
<div class="jumbotron">
|
||||||
<div class="tb-container">
|
<div class="tb-container">
|
||||||
<h1>{fmt}</h1>
|
<h1>{fmt}</h1>
|
||||||
<p class="lead">Small, safe and fast formatting library</p>
|
<p class="lead">Small, safe and fast formatting library</p>
|
||||||
<div class="btn-group" role="group">
|
<div class="btn-group" role="group">
|
||||||
|
{% set name = 'fmt' if version.split('.')[0]|int >= 3 else 'cppformat' %}
|
||||||
<a class="btn btn-success"
|
<a class="btn btn-success"
|
||||||
href="https://github.com/fmtlib/fmt/releases/download/2.0.0/cppformat-2.0.0.zip">
|
href="{{download_url}}/{{version}}/{{name}}-{{version}}.zip">
|
||||||
<span class="glyphicon glyphicon-download"></span> Download
|
<span class="glyphicon glyphicon-download"></span> Download
|
||||||
</a>
|
</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">
|
<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>
|
{% for v in versions.split(',') %}
|
||||||
<li><a href="https://github.com/fmtlib/fmt/releases/download/1.1.0/cppformat-1.1.0.zip">Version 1.1.0</a></li>
|
{% set name = 'fmt' if v.split('.')[0]|int >= 3 else 'cppformat' %}
|
||||||
<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="{{download_url}}/{{v}}/{{name}}-{{v}}.zip">Version {{v}}
|
||||||
|
</a></li>
|
||||||
|
{% endfor %}
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -105,14 +115,15 @@
|
|||||||
{% block content %}
|
{% block content %}
|
||||||
<div class="tb-container">
|
<div class="tb-container">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
{# TODO: integrate sidebar
|
{# Sidebar is currently disabled.
|
||||||
<div class="bs-sidebar">
|
<div class="bs-sidebar">
|
||||||
<div class="sphinxsidebar" role="navigation" aria-label="main navigation">
|
<div class="sphinxsidebar" role="navigation" aria-label="main navigation">
|
||||||
<div class="sphinxsidebarwrapper">
|
<div class="sphinxsidebarwrapper">
|
||||||
{%- block sidebarlogo %}
|
{%- block sidebarlogo %}
|
||||||
{%- if logo %}
|
{%- if logo %}
|
||||||
<p class="logo"><a href="{{ pathto(master_doc) }}">
|
<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>
|
</a></p>
|
||||||
{%- endif %}
|
{%- endif %}
|
||||||
{%- endblock %}
|
{%- endblock %}
|
||||||
|
|||||||
+78
-12
@@ -11,8 +11,8 @@ namespace is usually omitted in examples.
|
|||||||
Format API
|
Format API
|
||||||
==========
|
==========
|
||||||
|
|
||||||
The following functions use :ref:`format string syntax <syntax>` similar
|
The following functions defined in ``fmt/format.h`` use :ref:`format string
|
||||||
to the one used by Python's `str.format
|
syntax <syntax>` similar to the one used by Python's `str.format
|
||||||
<http://docs.python.org/3/library/stdtypes.html#str.format>`_ function.
|
<http://docs.python.org/3/library/stdtypes.html#str.format>`_ function.
|
||||||
They take *format_str* and *args* as arguments.
|
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.
|
*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:
|
.. _format:
|
||||||
|
|
||||||
.. doxygenfunction:: format(CStringRef, ArgList)
|
.. doxygenfunction:: format(CStringRef, ArgList)
|
||||||
@@ -40,8 +45,9 @@ arguments in the resulting string.
|
|||||||
Date and time formatting
|
Date and time formatting
|
||||||
------------------------
|
------------------------
|
||||||
|
|
||||||
The library supports `strftime <http://en.cppreference.com/w/cpp/chrono/c/strftime>`_-like
|
The library supports `strftime
|
||||||
date and time formatting::
|
<http://en.cppreference.com/w/cpp/chrono/c/strftime>`_-like date and time
|
||||||
|
formatting::
|
||||||
|
|
||||||
#include "fmt/time.h"
|
#include "fmt/time.h"
|
||||||
|
|
||||||
@@ -52,6 +58,36 @@ date and time formatting::
|
|||||||
The format string syntax is described in the documentation of
|
The format string syntax is described in the documentation of
|
||||||
`strftime <http://en.cppreference.com/w/cpp/chrono/c/strftime>`_.
|
`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
|
``std::ostream`` support
|
||||||
------------------------
|
------------------------
|
||||||
|
|
||||||
@@ -63,7 +99,7 @@ formatting of user-defined types that have overloaded ``operator<<``::
|
|||||||
class Date {
|
class Date {
|
||||||
int year_, month_, day_;
|
int year_, month_, day_;
|
||||||
public:
|
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) {
|
friend std::ostream &operator<<(std::ostream &os, const Date &d) {
|
||||||
return os << d.year_ << '-' << d.month_ << '-' << d.day_;
|
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:: print(std::ostream&, CStringRef, ArgList)
|
||||||
|
|
||||||
.. doxygenfunction:: fprintf(std::ostream&, CStringRef, ArgList)
|
|
||||||
|
|
||||||
Argument formatters
|
Argument formatters
|
||||||
-------------------
|
-------------------
|
||||||
|
|
||||||
@@ -86,7 +120,7 @@ custom argument formatter class::
|
|||||||
// A custom argument formatter that formats negative integers as unsigned
|
// A custom argument formatter that formats negative integers as unsigned
|
||||||
// with the ``x`` format specifier.
|
// with the ``x`` format specifier.
|
||||||
class CustomArgFormatter :
|
class CustomArgFormatter :
|
||||||
public fmt::BasicArgFormatter<CustomArgFormatter, char> {
|
public fmt::BasicArgFormatter<CustomArgFormatter, char> {
|
||||||
public:
|
public:
|
||||||
CustomArgFormatter(fmt::BasicFormatter<char, CustomArgFormatter> &f,
|
CustomArgFormatter(fmt::BasicFormatter<char, CustomArgFormatter> &f,
|
||||||
fmt::FormatSpec &s, const char *fmt)
|
fmt::FormatSpec &s, const char *fmt)
|
||||||
@@ -120,22 +154,43 @@ custom argument formatter class::
|
|||||||
.. doxygenclass:: fmt::ArgFormatter
|
.. doxygenclass:: fmt::ArgFormatter
|
||||||
:members:
|
:members:
|
||||||
|
|
||||||
Printf formatting functions
|
Printf formatting
|
||||||
---------------------------
|
-----------------
|
||||||
|
|
||||||
|
The header ``fmt/printf.h`` provides ``printf``-like formatting functionality.
|
||||||
The following functions use `printf format string syntax
|
The following functions use `printf format string syntax
|
||||||
<http://pubs.opengroup.org/onlinepubs/009695399/functions/fprintf.html>`_ with
|
<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:: printf(CStringRef, ArgList)
|
||||||
|
|
||||||
.. doxygenfunction:: fprintf(std::FILE *, CStringRef, ArgList)
|
.. doxygenfunction:: fprintf(std::FILE *, CStringRef, ArgList)
|
||||||
|
|
||||||
|
.. doxygenfunction:: fprintf(std::ostream&, CStringRef, ArgList)
|
||||||
|
|
||||||
.. doxygenfunction:: sprintf(CStringRef, ArgList)
|
.. doxygenfunction:: sprintf(CStringRef, ArgList)
|
||||||
|
|
||||||
|
.. doxygenclass:: fmt::PrintfFormatter
|
||||||
|
:members:
|
||||||
|
|
||||||
|
.. doxygenclass:: fmt::BasicPrintfArgFormatter
|
||||||
|
:members:
|
||||||
|
|
||||||
|
.. doxygenclass:: fmt::PrintfArgFormatter
|
||||||
|
:members:
|
||||||
|
|
||||||
Write API
|
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
|
.. doxygenclass:: fmt::BasicWriter
|
||||||
:members:
|
:members:
|
||||||
|
|
||||||
@@ -145,6 +200,12 @@ Write API
|
|||||||
.. doxygenclass:: fmt::BasicArrayWriter
|
.. doxygenclass:: fmt::BasicArrayWriter
|
||||||
:members:
|
:members:
|
||||||
|
|
||||||
|
.. doxygenclass:: fmt::BasicStringWriter
|
||||||
|
:members:
|
||||||
|
|
||||||
|
.. doxygenclass:: fmt::BasicContainerWriter
|
||||||
|
:members:
|
||||||
|
|
||||||
.. doxygenfunction:: bin(int)
|
.. doxygenfunction:: bin(int)
|
||||||
|
|
||||||
.. doxygenfunction:: oct(int)
|
.. doxygenfunction:: oct(int)
|
||||||
@@ -169,6 +230,8 @@ Utilities
|
|||||||
.. doxygenclass:: fmt::ArgList
|
.. doxygenclass:: fmt::ArgList
|
||||||
:members:
|
:members:
|
||||||
|
|
||||||
|
.. doxygenfunction:: fmt::to_string(const T&)
|
||||||
|
|
||||||
.. doxygenclass:: fmt::BasicStringRef
|
.. doxygenclass:: fmt::BasicStringRef
|
||||||
:members:
|
:members:
|
||||||
|
|
||||||
@@ -185,6 +248,8 @@ System errors
|
|||||||
.. doxygenclass:: fmt::SystemError
|
.. doxygenclass:: fmt::SystemError
|
||||||
:members:
|
:members:
|
||||||
|
|
||||||
|
.. doxygenfunction:: fmt::format_system_error
|
||||||
|
|
||||||
.. doxygenclass:: fmt::WindowsError
|
.. doxygenclass:: fmt::WindowsError
|
||||||
:members:
|
: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
|
It is also possible to write a formatting function that uses a custom
|
||||||
allocator::
|
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,
|
CustomString format(CustomAllocator alloc, fmt::CStringRef format_str,
|
||||||
fmt::ArgList args) {
|
fmt::ArgList args) {
|
||||||
|
|||||||
@@ -90,7 +90,8 @@
|
|||||||
VERSION: '{{ release|e }}',
|
VERSION: '{{ release|e }}',
|
||||||
COLLAPSE_INDEX: false,
|
COLLAPSE_INDEX: false,
|
||||||
FILE_SUFFIX: '{{ '' if no_search_suffix else file_suffix }}',
|
FILE_SUFFIX: '{{ '' if no_search_suffix else file_suffix }}',
|
||||||
HAS_SOURCE: {{ has_source|lower }}
|
HAS_SOURCE: {{ has_source|lower }},
|
||||||
|
SOURCELINK_SUFFIX: '{{ sourcelink_suffix }}'
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
{%- for scriptfile in script_files %}
|
{%- for scriptfile in script_files %}
|
||||||
|
|||||||
+46
-28
@@ -8,30 +8,35 @@ from distutils.version import LooseVersion
|
|||||||
|
|
||||||
def pip_install(package, commit=None, **kwargs):
|
def pip_install(package, commit=None, **kwargs):
|
||||||
"Install package using pip."
|
"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:
|
if commit:
|
||||||
check_version = kwargs.get('check_version', '')
|
package = 'git+https://github.com/{0}.git@{1}'.format(package, commit)
|
||||||
#output = check_output(['pip', 'show', package.split('/')[1]])
|
print('Installing {0}'.format(package))
|
||||||
#if check_version in output:
|
check_call(['pip', 'install', package])
|
||||||
# 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])
|
|
||||||
|
|
||||||
def build_docs(version='dev'):
|
def create_build_env(dirname='virtualenv'):
|
||||||
# Create virtualenv.
|
# Create virtualenv.
|
||||||
doc_dir = os.path.dirname(os.path.realpath(__file__))
|
if not os.path.exists(dirname):
|
||||||
virtualenv_dir = 'virtualenv'
|
check_call(['virtualenv', dirname])
|
||||||
check_call(['virtualenv', virtualenv_dir])
|
|
||||||
import sysconfig
|
import sysconfig
|
||||||
scripts_dir = os.path.basename(sysconfig.get_path('scripts'))
|
scripts_dir = os.path.basename(sysconfig.get_path('scripts'))
|
||||||
activate_this_file = os.path.join(virtualenv_dir, scripts_dir,
|
activate_this_file = os.path.join(dirname, scripts_dir, 'activate_this.py')
|
||||||
'activate_this.py')
|
|
||||||
with open(activate_this_file) as f:
|
with open(activate_this_file) as f:
|
||||||
exec(f.read(), dict(__file__=activate_this_file))
|
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
|
# 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.
|
# 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
|
pip_version = get_distribution('pip').version
|
||||||
if LooseVersion(pip_version) < LooseVersion('1.5.4'):
|
if LooseVersion(pip_version) < LooseVersion('1.5.4'):
|
||||||
print("Updating pip")
|
print("Updating pip")
|
||||||
@@ -46,27 +51,35 @@ def build_docs(version='dev'):
|
|||||||
except DistributionNotFound:
|
except DistributionNotFound:
|
||||||
pass
|
pass
|
||||||
# Install Sphinx and Breathe.
|
# Install Sphinx and Breathe.
|
||||||
pip_install('fmtlib/sphinx',
|
pip_install('sphinx-doc/sphinx', '12b83372ac9316e8cbe86e7fed889296a4cc29ee',
|
||||||
'12dde8afdb0a7bb5576e2656692c3478c69d8cc3',
|
min_version='1.4.1.dev20160531')
|
||||||
check_version='1.4a0.dev-20151013')
|
|
||||||
pip_install('michaeljones/breathe',
|
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.
|
# Build docs.
|
||||||
cmd = ['doxygen', '-']
|
cmd = ['doxygen', '-']
|
||||||
p = Popen(cmd, stdin=PIPE)
|
p = Popen(cmd, stdin=PIPE)
|
||||||
|
doxyxml_dir = os.path.join(work_dir, 'doxyxml')
|
||||||
p.communicate(input=r'''
|
p.communicate(input=r'''
|
||||||
PROJECT_NAME = fmt
|
PROJECT_NAME = fmt
|
||||||
GENERATE_LATEX = NO
|
GENERATE_LATEX = NO
|
||||||
GENERATE_MAN = NO
|
GENERATE_MAN = NO
|
||||||
GENERATE_RTF = NO
|
GENERATE_RTF = NO
|
||||||
CASE_SENSE_NAMES = 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
|
QUIET = YES
|
||||||
JAVADOC_AUTOBRIEF = YES
|
JAVADOC_AUTOBRIEF = YES
|
||||||
AUTOLINK_SUPPORT = NO
|
AUTOLINK_SUPPORT = NO
|
||||||
GENERATE_HTML = NO
|
GENERATE_HTML = NO
|
||||||
GENERATE_XML = YES
|
GENERATE_XML = YES
|
||||||
XML_OUTPUT = doxyxml
|
XML_OUTPUT = {1}
|
||||||
ALIASES = "rst=\verbatim embed:rst"
|
ALIASES = "rst=\verbatim embed:rst"
|
||||||
ALIASES += "endrst=\endverbatim"
|
ALIASES += "endrst=\endverbatim"
|
||||||
MACRO_EXPANSION = YES
|
MACRO_EXPANSION = YES
|
||||||
@@ -76,24 +89,29 @@ def build_docs(version='dev'):
|
|||||||
FMT_USE_USER_DEFINED_LITERALS=1 \
|
FMT_USE_USER_DEFINED_LITERALS=1 \
|
||||||
FMT_API=
|
FMT_API=
|
||||||
EXCLUDE_SYMBOLS = fmt::internal::* StringValue write_str
|
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:
|
if p.returncode != 0:
|
||||||
raise CalledProcessError(p.returncode, cmd)
|
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',
|
check_call(['sphinx-build',
|
||||||
'-Dbreathe_projects.format=' + os.path.join(os.getcwd(), 'doxyxml'),
|
'-Dbreathe_projects.format=' + os.path.abspath(doxyxml_dir),
|
||||||
'-Dversion=' + version, '-Drelease=' + version, '-Aversion=' + version,
|
'-Dversion=' + version, '-Drelease=' + version,
|
||||||
'-b', 'html', doc_dir, 'html'])
|
'-Aversion=' + version, '-Aversions=' + ','.join(versions),
|
||||||
|
'-b', 'html', doc_dir, html_dir])
|
||||||
try:
|
try:
|
||||||
check_call(['lessc', '--clean-css',
|
check_call(['lessc', '--clean-css',
|
||||||
'--include-path=' + os.path.join(doc_dir, 'bootstrap'),
|
'--include-path=' + os.path.join(doc_dir, 'bootstrap'),
|
||||||
os.path.join(doc_dir, 'fmt.less'),
|
os.path.join(doc_dir, 'fmt.less'),
|
||||||
'html/_static/fmt.css'])
|
os.path.join(html_dir, '_static', 'fmt.css')])
|
||||||
except OSError as e:
|
except OSError as e:
|
||||||
if e.errno != errno.ENOENT:
|
if e.errno != errno.ENOENT:
|
||||||
raise
|
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)
|
sys.exit(1)
|
||||||
return 'html'
|
return html_dir
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
create_build_env()
|
||||||
build_docs(sys.argv[1])
|
build_docs(sys.argv[1])
|
||||||
|
|||||||
@@ -228,8 +228,7 @@ latex_documents = [
|
|||||||
# One entry per manual page. List of tuples
|
# One entry per manual page. List of tuples
|
||||||
# (source start file, name, description, authors, manual section).
|
# (source start file, name, description, authors, manual section).
|
||||||
man_pages = [
|
man_pages = [
|
||||||
('index', 'format', u'format Documentation',
|
('index', 'fmt', u'fmt documentation', [u'Victor Zverovich'], 1)
|
||||||
[u'Victor Zverovich'], 1)
|
|
||||||
]
|
]
|
||||||
|
|
||||||
# If true, show URL addresses after external links.
|
# If true, show URL addresses after external links.
|
||||||
@@ -242,8 +241,8 @@ man_pages = [
|
|||||||
# (source start file, target name, title, author,
|
# (source start file, target name, title, author,
|
||||||
# dir menu entry, description, category)
|
# dir menu entry, description, category)
|
||||||
texinfo_documents = [
|
texinfo_documents = [
|
||||||
('index', 'format', u'format Documentation',
|
('index', 'fmt', u'fmt documentation',
|
||||||
u'Victor Zverovich', 'format', 'One line description of project.',
|
u'Victor Zverovich', 'fmt', 'One line description of project.',
|
||||||
'Miscellaneous'),
|
'Miscellaneous'),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|||||||
@@ -11,8 +11,8 @@ namespace is usually omitted in examples.
|
|||||||
Format API
|
Format API
|
||||||
==========
|
==========
|
||||||
|
|
||||||
The following functions use :ref:`format string syntax <syntax>` similar
|
The following functions defined in ``fmt/format.h`` use :ref:`format string
|
||||||
to the one used by Python's `str.format
|
syntax <syntax>` similar to the one used by Python's `str.format
|
||||||
<http://docs.python.org/3/library/stdtypes.html#str.format>`_ function.
|
<http://docs.python.org/3/library/stdtypes.html#str.format>`_ function.
|
||||||
They take *format_str* and *args* as arguments.
|
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.
|
*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:
|
.. _format:
|
||||||
|
|
||||||
.. doxygenfunction:: format(CStringRef, ArgList)
|
.. doxygenfunction:: format(CStringRef, ArgList)
|
||||||
@@ -40,8 +45,9 @@ arguments in the resulting string.
|
|||||||
Date and time formatting
|
Date and time formatting
|
||||||
------------------------
|
------------------------
|
||||||
|
|
||||||
The library supports `strftime <http://en.cppreference.com/w/cpp/chrono/c/strftime>`_-like
|
The library supports `strftime
|
||||||
date and time formatting::
|
<http://en.cppreference.com/w/cpp/chrono/c/strftime>`_-like date and time
|
||||||
|
formatting::
|
||||||
|
|
||||||
#include "fmt/time.h"
|
#include "fmt/time.h"
|
||||||
|
|
||||||
@@ -52,6 +58,36 @@ date and time formatting::
|
|||||||
The format string syntax is described in the documentation of
|
The format string syntax is described in the documentation of
|
||||||
`strftime <http://en.cppreference.com/w/cpp/chrono/c/strftime>`_.
|
`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
|
``std::ostream`` support
|
||||||
------------------------
|
------------------------
|
||||||
|
|
||||||
@@ -63,7 +99,7 @@ formatting of user-defined types that have overloaded ``operator<<``::
|
|||||||
class Date {
|
class Date {
|
||||||
int year_, month_, day_;
|
int year_, month_, day_;
|
||||||
public:
|
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) {
|
friend std::ostream &operator<<(std::ostream &os, const Date &d) {
|
||||||
return os << d.year_ << '-' << d.month_ << '-' << d.day_;
|
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:: print(std::ostream&, CStringRef, ArgList)
|
||||||
|
|
||||||
.. doxygenfunction:: fprintf(std::ostream&, CStringRef, ArgList)
|
|
||||||
|
|
||||||
Argument formatters
|
Argument formatters
|
||||||
-------------------
|
-------------------
|
||||||
|
|
||||||
@@ -86,7 +120,7 @@ custom argument formatter class::
|
|||||||
// A custom argument formatter that formats negative integers as unsigned
|
// A custom argument formatter that formats negative integers as unsigned
|
||||||
// with the ``x`` format specifier.
|
// with the ``x`` format specifier.
|
||||||
class CustomArgFormatter :
|
class CustomArgFormatter :
|
||||||
public fmt::BasicArgFormatter<CustomArgFormatter, char> {
|
public fmt::BasicArgFormatter<CustomArgFormatter, char> {
|
||||||
public:
|
public:
|
||||||
CustomArgFormatter(fmt::BasicFormatter<char, CustomArgFormatter> &f,
|
CustomArgFormatter(fmt::BasicFormatter<char, CustomArgFormatter> &f,
|
||||||
fmt::FormatSpec &s, const char *fmt)
|
fmt::FormatSpec &s, const char *fmt)
|
||||||
@@ -120,22 +154,43 @@ custom argument formatter class::
|
|||||||
.. doxygenclass:: fmt::ArgFormatter
|
.. doxygenclass:: fmt::ArgFormatter
|
||||||
:members:
|
:members:
|
||||||
|
|
||||||
Printf formatting functions
|
Printf formatting
|
||||||
---------------------------
|
-----------------
|
||||||
|
|
||||||
|
The header ``fmt/printf.h`` provides ``printf``-like formatting functionality.
|
||||||
The following functions use `printf format string syntax
|
The following functions use `printf format string syntax
|
||||||
<http://pubs.opengroup.org/onlinepubs/009695399/functions/fprintf.html>`_ with
|
<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:: printf(CStringRef, ArgList)
|
||||||
|
|
||||||
.. doxygenfunction:: fprintf(std::FILE *, CStringRef, ArgList)
|
.. doxygenfunction:: fprintf(std::FILE *, CStringRef, ArgList)
|
||||||
|
|
||||||
|
.. doxygenfunction:: fprintf(std::ostream&, CStringRef, ArgList)
|
||||||
|
|
||||||
.. doxygenfunction:: sprintf(CStringRef, ArgList)
|
.. doxygenfunction:: sprintf(CStringRef, ArgList)
|
||||||
|
|
||||||
|
.. doxygenclass:: fmt::PrintfFormatter
|
||||||
|
:members:
|
||||||
|
|
||||||
|
.. doxygenclass:: fmt::BasicPrintfArgFormatter
|
||||||
|
:members:
|
||||||
|
|
||||||
|
.. doxygenclass:: fmt::PrintfArgFormatter
|
||||||
|
:members:
|
||||||
|
|
||||||
Write API
|
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
|
.. doxygenclass:: fmt::BasicWriter
|
||||||
:members:
|
:members:
|
||||||
|
|
||||||
@@ -145,6 +200,12 @@ Write API
|
|||||||
.. doxygenclass:: fmt::BasicArrayWriter
|
.. doxygenclass:: fmt::BasicArrayWriter
|
||||||
:members:
|
:members:
|
||||||
|
|
||||||
|
.. doxygenclass:: fmt::BasicStringWriter
|
||||||
|
:members:
|
||||||
|
|
||||||
|
.. doxygenclass:: fmt::BasicContainerWriter
|
||||||
|
:members:
|
||||||
|
|
||||||
.. doxygenfunction:: bin(int)
|
.. doxygenfunction:: bin(int)
|
||||||
|
|
||||||
.. doxygenfunction:: oct(int)
|
.. doxygenfunction:: oct(int)
|
||||||
@@ -169,6 +230,8 @@ Utilities
|
|||||||
.. doxygenclass:: fmt::ArgList
|
.. doxygenclass:: fmt::ArgList
|
||||||
:members:
|
:members:
|
||||||
|
|
||||||
|
.. doxygenfunction:: fmt::to_string(const T&)
|
||||||
|
|
||||||
.. doxygenclass:: fmt::BasicStringRef
|
.. doxygenclass:: fmt::BasicStringRef
|
||||||
:members:
|
:members:
|
||||||
|
|
||||||
@@ -185,6 +248,8 @@ System errors
|
|||||||
.. doxygenclass:: fmt::SystemError
|
.. doxygenclass:: fmt::SystemError
|
||||||
:members:
|
:members:
|
||||||
|
|
||||||
|
.. doxygenfunction:: fmt::format_system_error
|
||||||
|
|
||||||
.. doxygenclass:: fmt::WindowsError
|
.. doxygenclass:: fmt::WindowsError
|
||||||
:members:
|
: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
|
It is also possible to write a formatting function that uses a custom
|
||||||
allocator::
|
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,
|
CustomString format(CustomAllocator alloc, fmt::CStringRef format_str,
|
||||||
fmt::ArgList args) {
|
fmt::ArgList args) {
|
||||||
|
|||||||
@@ -10,9 +10,9 @@ alternative to C++ IOStreams.
|
|||||||
<div class="panel panel-default">
|
<div class="panel panel-default">
|
||||||
<div class="panel-heading">What users say:</div>
|
<div class="panel-heading">What users say:</div>
|
||||||
<div class="panel-body">
|
<div class="panel-body">
|
||||||
Thanks for creating this library. It’s been a hole in C++ for a long time.
|
Thanks for creating this library. It’s been a hole in C++ for a long
|
||||||
I’ve used both boost::format and loki::SPrintf, and neither felt like the
|
time. I’ve used both boost::format and loki::SPrintf, and neither felt
|
||||||
right answer. This does.
|
like the right answer. This does.
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -24,8 +24,8 @@ Format API
|
|||||||
The replacement-based Format API provides a safe alternative to ``printf``,
|
The replacement-based Format API provides a safe alternative to ``printf``,
|
||||||
``sprintf`` and friends with comparable or `better performance
|
``sprintf`` and friends with comparable or `better performance
|
||||||
<http://zverovich.net/2013/09/07/integer-to-string-conversion-in-cplusplus.html>`_.
|
<http://zverovich.net/2013/09/07/integer-to-string-conversion-in-cplusplus.html>`_.
|
||||||
The `format string syntax <doc/latest/index.html#format-string-syntax>`_ is similar
|
The `format string syntax <syntax.html>`_ is similar to the one used by
|
||||||
to the one used by `str.format <http://docs.python.org/2/library/stdtypes.html#str.format>`_
|
`str.format <http://docs.python.org/2/library/stdtypes.html#str.format>`_
|
||||||
in Python:
|
in Python:
|
||||||
|
|
||||||
.. code:: c++
|
.. code:: c++
|
||||||
@@ -98,8 +98,8 @@ literal operators, they must be made visible with the directive
|
|||||||
Write API
|
Write API
|
||||||
---------
|
---------
|
||||||
|
|
||||||
The concatenation-based Write API (experimental) provides a
|
The concatenation-based Write API (experimental) provides a `fast
|
||||||
`fast <http://zverovich.net/2013/09/07/integer-to-string-conversion-in-cplusplus.html>`_
|
<http://zverovich.net/2013/09/07/integer-to-string-conversion-in-cplusplus.html>`_
|
||||||
stateless alternative to IOStreams:
|
stateless alternative to IOStreams:
|
||||||
|
|
||||||
.. code:: c++
|
.. code:: c++
|
||||||
@@ -112,8 +112,9 @@ stateless alternative to IOStreams:
|
|||||||
Safety
|
Safety
|
||||||
------
|
------
|
||||||
|
|
||||||
The library is fully type safe, automatic memory management prevents buffer overflow,
|
The library is fully type safe, automatic memory management prevents buffer
|
||||||
errors in format strings are reported using exceptions. For example, the code
|
overflow, errors in format strings are reported using exceptions. For example,
|
||||||
|
the code
|
||||||
|
|
||||||
.. code:: c++
|
.. 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');
|
fmt::format(L"Cyrillic letter {}", L'\x42e');
|
||||||
|
|
||||||
For comparison, writing a wide character to ``std::ostream`` results in
|
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
|
its numeric value being written to the stream (i.e. 1070 instead of letter 'ю'
|
||||||
is represented by ``L'\x42e'`` if we use Unicode) which is rarely what is needed.
|
which is represented by ``L'\x42e'`` if we use Unicode) which is rarely what is
|
||||||
|
needed.
|
||||||
|
|
||||||
.. _portability:
|
.. _portability:
|
||||||
|
|
||||||
Portability
|
Portability
|
||||||
-----------
|
-----------
|
||||||
|
|
||||||
The library is highly portable. Here is an incomplete list of operating systems and
|
The library is highly portable. Here is an incomplete list of operating systems
|
||||||
compilers where it has been tested and known to work:
|
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>`_,
|
* 64-bit (amd64) GNU/Linux with GCC 4.4.3,
|
||||||
4.7.2, 4.8.1 and Intel C++ Compiler (ICC) 14.0.2
|
`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
|
* 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
|
* 32-bit Windows with Visual C++ 2010
|
||||||
|
|
||||||
Although the library uses C++11 features when available, it also works with older
|
Although the library uses C++11 features when available, it also works with
|
||||||
compilers and standard library implementations. The only thing to keep in mind
|
older compilers and standard library implementations. The only thing to keep in
|
||||||
for C++98 portability:
|
mind for C++98 portability:
|
||||||
|
|
||||||
* Variadic templates: minimum GCC 4.4, Clang 2.9 or VS2013. This feature allows
|
* 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 Format API to accept an unlimited number of arguments. With older
|
||||||
the maximum is 15.
|
compilers the maximum is 15.
|
||||||
|
|
||||||
* User-defined literals: minimum GCC 4.7, Clang 3.1 or VS2015. The suffixes
|
* User-defined literals: minimum GCC 4.7, Clang 3.1 or VS2015. The suffixes
|
||||||
``_format`` and ``_a`` are functionally equivalent to the functions
|
``_format`` and ``_a`` are functionally equivalent to the functions
|
||||||
``fmt::format`` and ``fmt::arg``.
|
``fmt::format`` and ``fmt::arg``.
|
||||||
|
|
||||||
The output of all formatting functions is consistent across platforms. In particular,
|
The output of all formatting functions is consistent across platforms. In
|
||||||
formatting a floating-point infinity always gives ``inf`` while the output
|
particular, formatting a floating-point infinity always gives ``inf`` while the
|
||||||
of ``printf`` is platform-dependent in this case. For example,
|
output of ``printf`` is platform-dependent in this case. For example,
|
||||||
|
|
||||||
.. code::
|
.. code::
|
||||||
|
|
||||||
@@ -188,10 +191,10 @@ always prints ``inf``.
|
|||||||
Ease of Use
|
Ease of Use
|
||||||
-----------
|
-----------
|
||||||
|
|
||||||
fmt has a small self-contained code base consisting of a single header file
|
fmt has a small self-contained code base with the core library consisting of
|
||||||
and a single source file and no external dependencies. A permissive BSD `license
|
a single header file and a single source file and no external dependencies.
|
||||||
<https://github.com/fmtlib/fmt#license>`_ allows using the library both
|
A permissive BSD `license <https://github.com/fmtlib/fmt#license>`_ allows
|
||||||
in open-source and commercial projects.
|
using the library both in open-source and commercial projects.
|
||||||
|
|
||||||
.. raw:: html
|
.. raw:: html
|
||||||
|
|
||||||
|
|||||||
@@ -49,12 +49,10 @@ mini-language" or interpretation of the *format_spec*.
|
|||||||
Most built-in types support a common formatting mini-language, which is
|
Most built-in types support a common formatting mini-language, which is
|
||||||
described in the next section.
|
described in the next section.
|
||||||
|
|
||||||
A *format_spec* field can also include nested replacement fields within it.
|
A *format_spec* field can also include nested replacement fields in certain
|
||||||
These nested replacement fields can contain only an argument index;
|
positions within it. These nested replacement fields can contain only an
|
||||||
format specifications are not allowed. Formatting is performed as if the
|
argument id; format specifications are not allowed. This allows the
|
||||||
replacement fields within the format_spec are substituted before the
|
formatting of a value to be dynamically specified.
|
||||||
*format_spec* string is interpreted. This allows the formatting of a value
|
|
||||||
to be dynamically specified.
|
|
||||||
|
|
||||||
See the :ref:`formatexamples` section for some examples.
|
See the :ref:`formatexamples` section for some examples.
|
||||||
|
|
||||||
@@ -80,8 +78,8 @@ The general form of a *standard format specifier* is:
|
|||||||
sign: "+" | "-" | " "
|
sign: "+" | "-" | " "
|
||||||
width: `integer` | "{" `arg_id` "}"
|
width: `integer` | "{" `arg_id` "}"
|
||||||
precision: `integer` | "{" `arg_id` "}"
|
precision: `integer` | "{" `arg_id` "}"
|
||||||
type: `int_type` | "c" | "e" | "E" | "f" | "F" | "g" | "G" | "p" | "s"
|
type: `int_type` | "a" | "A" | "c" | "e" | "E" | "f" | "F" | "g" | "G" | "p" | "s"
|
||||||
int_type: "b" | "B" | "d" | "o" | "x" | "X"
|
int_type: "b" | "B" | "d" | "n" | "o" | "x" | "X"
|
||||||
|
|
||||||
The *fill* character can be any character other than '{' or '}'. The presence
|
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
|
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 |
|
| ``'a'`` | Hexadecimal floating point format. Prints the number in |
|
||||||
| | base 16 with prefix ``"0x"`` and lower-case letters for |
|
| | 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 |
|
| ``'A'`` | Same as ``'a'`` except it uses upper-case letters for |
|
||||||
| | the prefix, digits above 9 and to indicate the exponent. |
|
| | the prefix, digits above 9 and to indicate the exponent. |
|
||||||
|
|||||||
@@ -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
|
__ 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
|
Building the documentation
|
||||||
==========================
|
==========================
|
||||||
|
|
||||||
@@ -62,7 +79,11 @@ system:
|
|||||||
|
|
||||||
* `Python <https://www.python.org/>`_ with pip and virtualenv
|
* `Python <https://www.python.org/>`_ with pip and virtualenv
|
||||||
* `Doxygen <http://www.stack.nl/~dimitri/doxygen/>`_
|
* `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
|
First generate makefiles or project files using CMake as described in
|
||||||
the previous section. Then compile the ``doc`` target/project, for example::
|
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/>`_::
|
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 .mh { color: #208050 } /* Literal.Number.Hex */
|
||||||
.highlight .mi { color: #208050 } /* Literal.Number.Integer */
|
.highlight .mi { color: #208050 } /* Literal.Number.Integer */
|
||||||
.highlight .mo { color: #208050 } /* Literal.Number.Oct */
|
.highlight .mo { color: #208050 } /* Literal.Number.Oct */
|
||||||
|
.highlight .sa { color: #4070a0 } /* Literal.String.Affix */
|
||||||
.highlight .sb { color: #4070a0 } /* Literal.String.Backtick */
|
.highlight .sb { color: #4070a0 } /* Literal.String.Backtick */
|
||||||
.highlight .sc { color: #4070a0 } /* Literal.String.Char */
|
.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 .sd { color: #4070a0; font-style: italic } /* Literal.String.Doc */
|
||||||
.highlight .s2 { color: #4070a0 } /* Literal.String.Double */
|
.highlight .s2 { color: #4070a0 } /* Literal.String.Double */
|
||||||
.highlight .se { color: #4070a0; font-weight: bold } /* Literal.String.Escape */
|
.highlight .se { color: #4070a0; font-weight: bold } /* Literal.String.Escape */
|
||||||
@@ -59,7 +61,9 @@
|
|||||||
.highlight .s1 { color: #4070a0 } /* Literal.String.Single */
|
.highlight .s1 { color: #4070a0 } /* Literal.String.Single */
|
||||||
.highlight .ss { color: #517918 } /* Literal.String.Symbol */
|
.highlight .ss { color: #517918 } /* Literal.String.Symbol */
|
||||||
.highlight .bp { color: #007020 } /* Name.Builtin.Pseudo */
|
.highlight .bp { color: #007020 } /* Name.Builtin.Pseudo */
|
||||||
|
.highlight .fm { color: #06287e } /* Name.Function.Magic */
|
||||||
.highlight .vc { color: #bb60d5 } /* Name.Variable.Class */
|
.highlight .vc { color: #bb60d5 } /* Name.Variable.Class */
|
||||||
.highlight .vg { color: #bb60d5 } /* Name.Variable.Global */
|
.highlight .vg { color: #bb60d5 } /* Name.Variable.Global */
|
||||||
.highlight .vi { color: #bb60d5 } /* Name.Variable.Instance */
|
.highlight .vi { color: #bb60d5 } /* Name.Variable.Instance */
|
||||||
|
.highlight .vm { color: #bb60d5 } /* Name.Variable.Magic */
|
||||||
.highlight .il { color: #208050 } /* Literal.Number.Integer.Long */
|
.highlight .il { color: #208050 } /* Literal.Number.Integer.Long */
|
||||||
+405
-132
@@ -8,7 +8,7 @@
|
|||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
|
||||||
|
|
||||||
<title>API Reference — fmt 3.0.0 documentation</title>
|
<title>API Reference — fmt 4.0.0 documentation</title>
|
||||||
|
|
||||||
<link rel="stylesheet" href="_static/basic.css" type="text/css" />
|
<link rel="stylesheet" href="_static/basic.css" type="text/css" />
|
||||||
<link rel="stylesheet" href="_static/pygments.css" type="text/css" />
|
<link rel="stylesheet" href="_static/pygments.css" type="text/css" />
|
||||||
@@ -17,10 +17,11 @@
|
|||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
var DOCUMENTATION_OPTIONS = {
|
var DOCUMENTATION_OPTIONS = {
|
||||||
URL_ROOT: './',
|
URL_ROOT: './',
|
||||||
VERSION: '3.0.0',
|
VERSION: '4.0.0',
|
||||||
COLLAPSE_INDEX: false,
|
COLLAPSE_INDEX: false,
|
||||||
FILE_SUFFIX: '.html',
|
FILE_SUFFIX: '.html',
|
||||||
HAS_SOURCE: true
|
HAS_SOURCE: true,
|
||||||
|
SOURCELINK_SUFFIX: ''
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
<script type="text/javascript" src="_static/jquery.js"></script>
|
<script type="text/javascript" src="_static/jquery.js"></script>
|
||||||
@@ -35,8 +36,9 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
|
(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),
|
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();
|
||||||
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
|
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');
|
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
|
||||||
ga('create', 'UA-20116650-4', 'fmtlib.net');
|
ga('create', 'UA-20116650-4', 'fmtlib.net');
|
||||||
ga('send', 'pageview');
|
ga('send', 'pageview');
|
||||||
@@ -50,7 +52,8 @@
|
|||||||
<div class="navbar-content">
|
<div class="navbar-content">
|
||||||
|
|
||||||
<div class="navbar-header">
|
<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="sr-only">Toggle navigation</span>
|
||||||
<span class="icon-bar"></span>
|
<span class="icon-bar"></span>
|
||||||
<span class="icon-bar"></span>
|
<span class="icon-bar"></span>
|
||||||
@@ -63,13 +66,17 @@
|
|||||||
<div class="collapse navbar-collapse">
|
<div class="collapse navbar-collapse">
|
||||||
<ul class="nav navbar-nav">
|
<ul class="nav navbar-nav">
|
||||||
<li class="dropdown">
|
<li class="dropdown">
|
||||||
|
<a href="#" class="dropdown-toggle" data-toggle="dropdown"
|
||||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button"
|
role="button" aria-expanded="false">4.0.0
|
||||||
aria-expanded="false">3.0.0 <span class="caret"></span></a>
|
<span class="caret"></span></a>
|
||||||
<ul class="dropdown-menu" role="menu">
|
<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/3.0.0">3.0.0</a></li>
|
||||||
<li><a href="http://fmtlib.net/1.0.0/">1.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>
|
</ul>
|
||||||
</li>
|
</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>
|
</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">
|
<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>
|
</div>
|
||||||
<input type="hidden" name="check_keywords" value="yes" />
|
<input type="hidden" name="check_keywords" value="yes" />
|
||||||
<input type="hidden" name="area" value="default" />
|
<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>
|
namespace is usually omitted in examples.</p>
|
||||||
<div class="section" id="format-api">
|
<div class="section" id="format-api">
|
||||||
<h2>Format API<a class="headerlink" href="#format-api" title="Permalink to this headline">¶</a></h2>
|
<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
|
<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
|
||||||
to the one used by Python’s <a class="reference external" href="http://docs.python.org/3/library/stdtypes.html#str.format">str.format</a> function.
|
syntax</span></a> similar to the one used by Python’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>
|
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
|
<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
|
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>
|
arguments in the resulting string.</p>
|
||||||
<p><em>args</em> is an argument list representing arbitrary arguments.</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’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">
|
<span class="target" id="format"></span><dl class="function">
|
||||||
<dt id="_CPPv2N3fmt6formatE10CStringRef7ArgList">
|
<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>
|
<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>
|
</p>
|
||||||
</dd></dl>
|
</dd></dl>
|
||||||
|
|
||||||
<dl class="function">
|
<div class="admonition warning">
|
||||||
<dt id="_CPPv2N3fmt8literalsli7_formatEPKcNSt6size_tE">
|
<p class="first admonition-title">Warning</p>
|
||||||
<span class="target" id="formatformat_8h_1a8f568cdac4d075838347616fc4899417"></span>internal::UdlFormat<char> <code class="descclassname">fmt::literals::</code><code class="descname">operator""_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>
|
<p class="last">doxygenfunction: Cannot find function “operator”“_format” in doxygen xml output for project “format” from directory: /home/foonathan/Programming/fmt/build/doc/doxyxml</p>
|
||||||
<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">"The answer is {}"</span><span class="n">_format</span><span class="p">(</span><span class="mi">42</span><span class="p">);</span>
|
|
||||||
</pre></div>
|
|
||||||
</div>
|
</div>
|
||||||
</p>
|
|
||||||
</dd></dl>
|
|
||||||
|
|
||||||
<span class="target" id="print"></span><dl class="function">
|
<span class="target" id="print"></span><dl class="function">
|
||||||
<dt id="_CPPv2N3fmt5printE10CStringRef7ArgList">
|
<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>
|
<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">
|
<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>
|
<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>
|
<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>
|
<p class="breathe-sectiondef-title rubric">Public Types</p>
|
||||||
<dl class="type">
|
<dl class="type">
|
||||||
<dt id="_CPPv2N3fmt14BasicFormatter4CharE">
|
<dt id="_CPPv2N3fmt14BasicFormatter4CharE">
|
||||||
@@ -189,7 +195,7 @@ arguments in the resulting string.</p>
|
|||||||
</dd></dl>
|
</dd></dl>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<div class="breathe-sectiondef container">
|
<div class="breathe-sectiondef docutils container">
|
||||||
<p class="breathe-sectiondef-title rubric">Public Functions</p>
|
<p class="breathe-sectiondef-title rubric">Public Functions</p>
|
||||||
<dl class="function">
|
<dl class="function">
|
||||||
<dt id="_CPPv2N3fmt14BasicFormatter14BasicFormatterERK7ArgListR11BasicWriterI4CharE">
|
<dt id="_CPPv2N3fmt14BasicFormatter14BasicFormatterERK7ArgListR11BasicWriterI4CharE">
|
||||||
@@ -217,8 +223,8 @@ appropriate lifetimes.</p>
|
|||||||
|
|
||||||
<div class="section" id="date-and-time-formatting">
|
<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>
|
<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
|
<p>The library supports <a class="reference external" href="http://en.cppreference.com/w/cpp/chrono/c/strftime">strftime</a>-like date and time
|
||||||
date and time formatting:</p>
|
formatting:</p>
|
||||||
<div class="highlight-c++"><div class="highlight"><pre><span></span><span class="cp">#include</span> <span class="cpf">"fmt/time.h"</span><span class="cp"></span>
|
<div class="highlight-c++"><div class="highlight"><pre><span></span><span class="cp">#include</span> <span class="cpf">"fmt/time.h"</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>
|
<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
|
<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>
|
<a class="reference external" href="http://en.cppreference.com/w/cpp/chrono/c/strftime">strftime</a>.</p>
|
||||||
</div>
|
</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"><</span><span class="kt">char</span><span class="o">></span> <span class="o">&</span><span class="n">f</span><span class="p">,</span>
|
||||||
|
<span class="k">const</span> <span class="kt">char</span> <span class="o">*&</span><span class="n">format_str</span><span class="p">,</span> <span class="k">const</span> <span class="n">MyStruct</span> <span class="o">&</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">"[MyStruct: a={:.1f}, b={:.2f}]"</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">"m={}"</span><span class="p">,</span> <span class="n">n</span><span class="p">);</span>
|
||||||
|
<span class="c1">// s == "m=[MyStruct: a=1.0, b=2.00]"</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<<</span></code> when one is defined for a user-defined type.</p>
|
||||||
|
</div>
|
||||||
<div class="section" id="std-ostream-support">
|
<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>
|
<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
|
<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="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="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="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">&</span><span class="k">operator</span><span class="o"><<</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">ostream</span> <span class="o">&</span><span class="n">os</span><span class="p">,</span> <span class="k">const</span> <span class="n">Date</span> <span class="o">&</span><span class="n">d</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">&</span><span class="k">operator</span><span class="o"><<</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">ostream</span> <span class="o">&</span><span class="n">os</span><span class="p">,</span> <span class="k">const</span> <span class="n">Date</span> <span class="o">&</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"><<</span> <span class="n">d</span><span class="p">.</span><span class="n">year_</span> <span class="o"><<</span> <span class="sc">'-'</span> <span class="o"><<</span> <span class="n">d</span><span class="p">.</span><span class="n">month_</span> <span class="o"><<</span> <span class="sc">'-'</span> <span class="o"><<</span> <span class="n">d</span><span class="p">.</span><span class="n">day_</span><span class="p">;</span>
|
<span class="k">return</span> <span class="n">os</span> <span class="o"><<</span> <span class="n">d</span><span class="p">.</span><span class="n">year_</span> <span class="o"><<</span> <span class="sc">'-'</span> <span class="o"><<</span> <span class="n">d</span><span class="p">.</span><span class="n">month_</span> <span class="o"><<</span> <span class="sc">'-'</span> <span class="o"><<</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>
|
</p>
|
||||||
</dd></dl>
|
</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 &<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">"Don't %s!"</span><span class="p">,</span> <span class="s">"panic"</span><span class="p">);</span>
|
|
||||||
</pre></div>
|
|
||||||
</div>
|
|
||||||
</p>
|
|
||||||
</dd></dl>
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<div class="section" id="argument-formatters">
|
<div class="section" id="argument-formatters">
|
||||||
<h3>Argument formatters<a class="headerlink" href="#argument-formatters" title="Permalink to this headline">¶</a></h3>
|
<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>
|
<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="c1">// with the ``x`` format specifier.</span>
|
||||||
<span class="k">class</span> <span class="nc">CustomArgFormatter</span> <span class="o">:</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"><</span><span class="n">CustomArgFormatter</span><span class="p">,</span> <span class="kt">char</span><span class="o">></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"><</span><span class="n">CustomArgFormatter</span><span class="p">,</span> <span class="kt">char</span><span class="o">></span> <span class="p">{</span>
|
||||||
<span class="k">public</span><span class="o">:</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"><</span><span class="kt">char</span><span class="p">,</span> <span class="n">CustomArgFormatter</span><span class="o">></span> <span class="o">&</span><span class="n">f</span><span class="p">,</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"><</span><span class="kt">char</span><span class="p">,</span> <span class="n">CustomArgFormatter</span><span class="o">></span> <span class="o">&</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">&</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>
|
<span class="n">fmt</span><span class="o">::</span><span class="n">FormatSpec</span> <span class="o">&</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>
|
</pre></div>
|
||||||
</div>
|
</div>
|
||||||
</p>
|
</p>
|
||||||
<div class="breathe-sectiondef container">
|
<div class="breathe-sectiondef docutils container">
|
||||||
<p class="breathe-sectiondef-title rubric">Public Functions</p>
|
<p class="breathe-sectiondef-title rubric">Public Functions</p>
|
||||||
<dl class="function">
|
<dl class="function">
|
||||||
<dt id="_CPPv2N3fmt10ArgVisitor9visit_intEi">
|
<dt id="_CPPv2N3fmt10ArgVisitor9visit_intEi">
|
||||||
@@ -440,7 +461,7 @@ called.</p>
|
|||||||
|
|
||||||
<dl class="class">
|
<dl class="class">
|
||||||
<dt>
|
<dt>
|
||||||
<span class="target" id="formatclassfmt_1_1_basic_arg_formatter"></span><em class="property">template </em><typename <em>Impl</em>, typename <em>Char</em>></dt>
|
<span class="target" id="formatclassfmt_1_1_basic_arg_formatter"></span><em class="property">template </em><typename <em>Impl</em>, typename <em>Char</em>, typename <em>Spec</em> = fmt::FormatSpec></dt>
|
||||||
<dt id="_CPPv2N3fmt17BasicArgFormatterE">
|
<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>
|
<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>
|
<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’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
|
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>
|
will be called.</p>
|
||||||
</p>
|
</p>
|
||||||
<div class="breathe-sectiondef container">
|
<p>Inherits from fmt::internal::ArgFormatterBase< Impl, Char, Spec ></p>
|
||||||
|
<div class="breathe-sectiondef docutils container">
|
||||||
<p class="breathe-sectiondef-title rubric">Public Functions</p>
|
<p class="breathe-sectiondef-title rubric">Public Functions</p>
|
||||||
<dl class="function">
|
<dl class="function">
|
||||||
<dt id="_CPPv2N3fmt17BasicArgFormatter17BasicArgFormatterER14BasicFormatterI4Char4ImplER10FormatSpecPK4Char">
|
<dt id="_CPPv2N3fmt17BasicArgFormatter17BasicArgFormatterER14BasicFormatterI4Char4ImplER4SpecPK4Char">
|
||||||
<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><Char, Impl> &<em>formatter</em>, FormatSpec &<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>
|
<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><Char, Impl> &<em>formatter</em>, Spec &<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.
|
<dd><p><p>Constructs an argument formatter object.
|
||||||
<em>formatter</em> is a reference to the main formatter object, <em>spec</em> contains
|
<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
|
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">
|
<dl class="function">
|
||||||
<dt id="_CPPv2N3fmt17BasicArgFormatter12visit_customEN8internal3Arg11CustomValueE">
|
<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>
|
<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 argument of a custom (user-defined) type. </p>
|
<dd><p>Formats an argument of a custom (user-defined) type. </p>
|
||||||
</dd></dl>
|
</dd></dl>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
@@ -482,7 +504,8 @@ to the part of the format string being parsed for custom argument types.</p>
|
|||||||
<dt id="_CPPv2N3fmt12ArgFormatterE">
|
<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>
|
<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>
|
<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< ArgFormatter< Char >, Char, FormatSpec ></span></a></p>
|
||||||
|
<div class="breathe-sectiondef docutils container">
|
||||||
<p class="breathe-sectiondef-title rubric">Public Functions</p>
|
<p class="breathe-sectiondef-title rubric">Public Functions</p>
|
||||||
<dl class="function">
|
<dl class="function">
|
||||||
<dt id="_CPPv2N3fmt12ArgFormatter12ArgFormatterER14BasicFormatterI4CharER10FormatSpecPK4Char">
|
<dt id="_CPPv2N3fmt12ArgFormatter12ArgFormatterER14BasicFormatterI4CharER10FormatSpecPK4Char">
|
||||||
@@ -494,13 +517,16 @@ to the part of the format string being parsed for custom argument types.</p>
|
|||||||
</dd></dl>
|
</dd></dl>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<div class="section" id="printf-formatting-functions">
|
<div class="section" id="printf-formatting">
|
||||||
<h3>Printf formatting functions<a class="headerlink" href="#printf-formatting-functions" title="Permalink to this headline">¶</a></h3>
|
<h3>Printf formatting<a class="headerlink" href="#printf-formatting" 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
|
<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.
|
||||||
a POSIX extension for positional arguments.</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
|
||||||
|
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’t match its format specification.</p>
|
||||||
<dl class="function">
|
<dl class="function">
|
||||||
<dt id="_CPPv2N3fmt6printfE10CStringRef7ArgList">
|
<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>
|
<dd><p><p>Prints formatted data to <code class="docutils literal"><span class="pre">stdout</span></code>.</p>
|
||||||
<p><strong>Example</strong>:</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">"Elapsed time: %.2f seconds"</span><span class="p">,</span> <span class="mf">1.23</span><span class="p">);</span>
|
<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">"Elapsed time: %.2f seconds"</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">
|
<dl class="function">
|
||||||
<dt id="_CPPv2N3fmt7fprintfEPNSt4FILEE10CStringRef7ArgList">
|
<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>
|
<dd><p><p>Prints formatted data to the file <em>f</em>.</p>
|
||||||
<p><strong>Example</strong>:</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">"Don't %s!"</span><span class="p">,</span> <span class="s">"panic"</span><span class="p">);</span>
|
<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">"Don't %s!"</span><span class="p">,</span> <span class="s">"panic"</span><span class="p">);</span>
|
||||||
@@ -520,9 +546,20 @@ a POSIX extension for positional arguments.</p>
|
|||||||
</p>
|
</p>
|
||||||
</dd></dl>
|
</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 &<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">"Don't %s!"</span><span class="p">,</span> <span class="s">"panic"</span><span class="p">);</span>
|
||||||
|
</pre></div>
|
||||||
|
</div>
|
||||||
|
</p>
|
||||||
|
</dd></dl>
|
||||||
|
|
||||||
<dl class="function">
|
<dl class="function">
|
||||||
<dt id="_CPPv2N3fmt7sprintfE10CStringRef7ArgList">
|
<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>
|
<dd><p><p>Formats arguments and returns the result as a string.</p>
|
||||||
<p><strong>Example</strong>:</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">"The answer is %d"</span><span class="p">,</span> <span class="mi">42</span><span class="p">);</span>
|
<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">"The answer is %d"</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>
|
</p>
|
||||||
</dd></dl>
|
</dd></dl>
|
||||||
|
|
||||||
|
<dl class="class">
|
||||||
|
<dt>
|
||||||
|
<span class="target" id="formatclassfmt_1_1_printf_formatter"></span><em class="property">template </em><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><Char>></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> &<em>al</em>, <a class="reference internal" href="#_CPPv2N3fmt11BasicWriterE" title="fmt::BasicWriter">BasicWriter</a><Char> &<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><Char> <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><typename <em>Impl</em>, typename <em>Char</em>, typename <em>Spec</em>></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’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< Impl, Char, Spec ></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><Char> &<em>w</em>, Spec &<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><<em class="property">typename</em> Char></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< PrintfArgFormatter< Char >, Char, FormatSpec ></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><Char> &<em>w</em>, FormatSpec &<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>
|
</div>
|
||||||
<div class="section" id="write-api">
|
<div class="section" id="write-api">
|
||||||
<h2>Write API<a class="headerlink" href="#write-api" title="Permalink to this headline">¶</a></h2>
|
<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">
|
<dl class="class">
|
||||||
<dt>
|
<dt>
|
||||||
<span class="target" id="formatclassfmt_1_1_basic_writer"></span><em class="property">template </em><typename <em>Char</em>></dt>
|
<span class="target" id="formatclassfmt_1_1_basic_writer"></span><em class="property">template </em><typename <em>Char</em>></dt>
|
||||||
@@ -564,37 +715,38 @@ such as <a class="reference internal" href="#_CPPv2N3fmt17BasicMemoryWriterE" ti
|
|||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
</p>
|
</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< Char ></span></a>, <a class="reference internal" href="#formatclassfmt_1_1_basic_memory_writer"><span class="std std-ref">fmt::BasicMemoryWriter< Char, Allocator ></span></a>, <a class="reference internal" href="#formatclassfmt_1_1_basic_string_writer"><span class="std std-ref">fmt::BasicStringWriter< Char, Allocator ></span></a></p>
|
||||||
|
<div class="breathe-sectiondef docutils container">
|
||||||
<p class="breathe-sectiondef-title rubric">Public Functions</p>
|
<p class="breathe-sectiondef-title rubric">Public Functions</p>
|
||||||
<dl class="function">
|
<dl class="function">
|
||||||
<dt id="_CPPv2N3fmt11BasicWriterD0Ev">
|
<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>
|
<dd><p><p>Destroys a <code class="docutils literal"><span class="pre">BasicWriter</span></code> object.</p>
|
||||||
</p>
|
</p>
|
||||||
</dd></dl>
|
</dd></dl>
|
||||||
|
|
||||||
<dl class="function">
|
<dl class="function">
|
||||||
<dt id="_CPPv2N3fmt11BasicWriter4sizeEv">
|
<dt id="_CPPv2NK3fmt11BasicWriter4sizeEv">
|
||||||
<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>
|
<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><p>Returns the total number of characters written. </p>
|
||||||
</dd></dl>
|
</dd></dl>
|
||||||
|
|
||||||
<dl class="function">
|
<dl class="function">
|
||||||
<dt id="_CPPv2N3fmt11BasicWriter4dataEv">
|
<dt id="_CPPv2NK3fmt11BasicWriter4dataEv">
|
||||||
<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>
|
<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>
|
<dd><p>Returns a pointer to the output buffer content. </p>
|
||||||
<p>No terminating null character is appended. </p>
|
<p>No terminating null character is appended. </p>
|
||||||
</dd></dl>
|
</dd></dl>
|
||||||
|
|
||||||
<dl class="function">
|
<dl class="function">
|
||||||
<dt id="_CPPv2N3fmt11BasicWriter5c_strEv">
|
<dt id="_CPPv2NK3fmt11BasicWriter5c_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>
|
<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><p>Returns a pointer to the output buffer content with terminating null character appended. </p>
|
||||||
</dd></dl>
|
</dd></dl>
|
||||||
|
|
||||||
<dl class="function">
|
<dl class="function">
|
||||||
<dt id="_CPPv2N3fmt11BasicWriter3strEv">
|
<dt id="_CPPv2NK3fmt11BasicWriter3strEv">
|
||||||
<span id="fmt::BasicWriter::str"></span><span class="target" id="formatclassfmt_1_1_basic_writer_1a91f06ced6e063ee77a99740e0e79faf6"></span>std::basic_string<Char> <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>
|
<span id="fmt::BasicWriter::strC"></span><span class="target" id="formatclassfmt_1_1_basic_writer_1aac8dbeddff3d4e268d17a4f9c16264f6"></span>std::basic_string<Char> <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>
|
<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>
|
</p>
|
||||||
</dd></dl>
|
</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
|
<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>
|
accessed as a C string with <code class="docutils literal"><span class="pre">out.c_str()</span></code>.</p>
|
||||||
</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< Char ></span></a></p>
|
||||||
|
<div class="breathe-sectiondef docutils container">
|
||||||
<p class="breathe-sectiondef-title rubric">Public Functions</p>
|
<p class="breathe-sectiondef-title rubric">Public Functions</p>
|
||||||
<dl class="function">
|
<dl class="function">
|
||||||
<dt id="_CPPv2N3fmt17BasicMemoryWriter17BasicMemoryWriterERR17BasicMemoryWriter">
|
<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> &&<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> &&<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
|
<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>
|
of the other object to it.</p>
|
||||||
</p>
|
</p>
|
||||||
@@ -746,7 +899,8 @@ into the array.</p>
|
|||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
</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< Char ></span></a></p>
|
||||||
|
<div class="breathe-sectiondef docutils container">
|
||||||
<p class="breathe-sectiondef-title rubric">Public Functions</p>
|
<p class="breathe-sectiondef-title rubric">Public Functions</p>
|
||||||
<dl class="function">
|
<dl class="function">
|
||||||
<dt id="_CPPv2N3fmt16BasicArrayWriter16BasicArrayWriterEP4CharNSt6size_tE">
|
<dt id="_CPPv2N3fmt16BasicArrayWriter16BasicArrayWriterEP4CharNSt6size_tE">
|
||||||
@@ -769,27 +923,118 @@ size known at compile time.</p>
|
|||||||
</div>
|
</div>
|
||||||
</dd></dl>
|
</dd></dl>
|
||||||
|
|
||||||
|
<dl class="class">
|
||||||
|
<dt>
|
||||||
|
<span class="target" id="formatclassfmt_1_1_basic_string_writer"></span><em class="property">template </em><<em class="property">typename</em> Char, <em class="property">typename</em> Allocator = std::allocator<Char>></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<char></td>
|
||||||
|
</tr>
|
||||||
|
<tr class="row-odd"><td>WStringWriter</td>
|
||||||
|
<td>BasicStringWriter<wchar_t></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"><<</span> <span class="s">"The answer is "</span> <span class="o"><<</span> <span class="mi">42</span> <span class="o"><<</span> <span class="s">"</span><span class="se">\n</span><span class="s">"</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< Char ></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 &<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<Char, std::char_traits<Char>, Allocator> &<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><<em class="property">class</em> Container></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"><</span><span class="kt">char</span><span class="o">>&</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"><</span><span class="kt">char</span><span class="o">></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"><</span><span class="n">std</span><span class="o">::</span><span class="n">vector</span><span class="o"><</span><span class="kt">char</span><span class="o">></span> <span class="o">></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"><</span><span class="kt">char</span><span class="o">>&</span><span class="p">,</span>
|
||||||
|
<span class="n">fmt</span><span class="o">::</span><span class="n">BasicCStringRef</span><span class="o"><</span><span class="kt">char</span><span class="o">></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< Container::value_type ></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 &<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">
|
<dl class="function">
|
||||||
<dt id="_CPPv2N3fmt3binEi">
|
<dt id="_CPPv2N3fmt3binEi">
|
||||||
<span id="fmt::bin__i"></span><span class="target" id="formatformat_8h_1aa3e8966d52b70224d46861fabd090e4b"></span>IntFormatSpec<int, TypeSpec<'b'>> <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<int, TypeSpec<'b'>> <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><p>Returns an integer format specifier to format the value in base 2. </p>
|
||||||
</dd></dl>
|
</dd></dl>
|
||||||
|
|
||||||
<dl class="function">
|
<dl class="function">
|
||||||
<dt id="_CPPv2N3fmt3octEi">
|
<dt id="_CPPv2N3fmt3octEi">
|
||||||
<span id="fmt::oct__i"></span><span class="target" id="formatformat_8h_1a1d166c5b2242a6a0aefba5455c32a2b3"></span>IntFormatSpec<int, TypeSpec<'o'>> <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<int, TypeSpec<'o'>> <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><p>Returns an integer format specifier to format the value in base 8. </p>
|
||||||
</dd></dl>
|
</dd></dl>
|
||||||
|
|
||||||
<dl class="function">
|
<dl class="function">
|
||||||
<dt id="_CPPv2N3fmt3hexEi">
|
<dt id="_CPPv2N3fmt3hexEi">
|
||||||
<span id="fmt::hex__i"></span><span class="target" id="formatformat_8h_1aaa926c5c42fbad5f5c98aaad84b9f66a"></span>IntFormatSpec<int, TypeSpec<'x'>> <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<int, TypeSpec<'x'>> <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><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>
|
</dd></dl>
|
||||||
|
|
||||||
<dl class="function">
|
<dl class="function">
|
||||||
<dt id="_CPPv2N3fmt4hexuEi">
|
<dt id="_CPPv2N3fmt4hexuEi">
|
||||||
<span id="fmt::hexu__i"></span><span class="target" id="formatformat_8h_1ac2fd8f73cfcd1321dfb6fb0302f23f66"></span>IntFormatSpec<int, TypeSpec<'X'>> <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<int, TypeSpec<'X'>> <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><p>Returns an integer formatter format specifier to format in base 16 using upper-case letters for the digits above 9. </p>
|
||||||
</dd></dl>
|
</dd></dl>
|
||||||
|
|
||||||
@@ -797,7 +1042,7 @@ size known at compile time.</p>
|
|||||||
<dt>
|
<dt>
|
||||||
<em class="property">template </em><char <em>TYPE_CODE</em>, <em class="property">typename</em> Char></dt>
|
<em class="property">template </em><char <em>TYPE_CODE</em>, <em class="property">typename</em> Char></dt>
|
||||||
<dt id="_CPPv2N3fmt3padEij4Char">
|
<dt id="_CPPv2N3fmt3padEij4Char">
|
||||||
<span id="fmt::pad__i.unsigned.Char"></span><span class="target" id="formatformat_8h_1a48d6010061d1710d807853ad9125d825"></span>IntFormatSpec<int, AlignTypeSpec<TYPE_CODE>, Char> <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<int, AlignTypeSpec<TYPE_CODE>, Char> <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
|
<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
|
fill character to the specified width using the default (right) numeric
|
||||||
alignment.</p>
|
alignment.</p>
|
||||||
@@ -817,7 +1062,7 @@ alignment.</p>
|
|||||||
<dt>
|
<dt>
|
||||||
<em class="property">template </em><<em class="property">typename</em> T></dt>
|
<em class="property">template </em><<em class="property">typename</em> T></dt>
|
||||||
<dt id="_CPPv2N3fmt3argE9StringRefRK1T">
|
<dt id="_CPPv2N3fmt3argE9StringRefRK1T">
|
||||||
<span id="fmt::arg__StringRef.TCR"></span><span class="target" id="formatformat_8h_1a4649a895b3f769fe24b268e39a8cf152"></span>internal::NamedArg<char> <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 &<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<char, T> <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 &<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>
|
<dd><p><p>Returns a named argument for formatting functions.</p>
|
||||||
<p><strong>Example</strong>:</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">"Elapsed time: {s:.2f} seconds"</span><span class="p">,</span> <span class="n">arg</span><span class="p">(</span><span class="s">"s"</span><span class="p">,</span> <span class="mf">1.23</span><span class="p">));</span>
|
<div class="highlight-c++"><div class="highlight"><pre><span></span><span class="n">print</span><span class="p">(</span><span class="s">"Elapsed time: {s:.2f} seconds"</span><span class="p">,</span> <span class="n">arg</span><span class="p">(</span><span class="s">"s"</span><span class="p">,</span> <span class="mf">1.23</span><span class="p">));</span>
|
||||||
@@ -826,18 +1071,10 @@ alignment.</p>
|
|||||||
</p>
|
</p>
|
||||||
</dd></dl>
|
</dd></dl>
|
||||||
|
|
||||||
<dl class="function">
|
<div class="admonition warning">
|
||||||
<dt id="_CPPv2N3fmt8literalsli2_aEPKcNSt6size_tE">
|
<p class="first admonition-title">Warning</p>
|
||||||
<span class="target" id="formatformat_8h_1a1f0ec67406a0e4937166e6481f481198"></span>internal::UdlArg<char> <code class="descclassname">fmt::literals::</code><code class="descname">operator""_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>
|
<p class="last">doxygenfunction: Cannot find function “operator”“_a” in doxygen xml output for project “format” from directory: /home/foonathan/Programming/fmt/build/doc/doxyxml</p>
|
||||||
<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">"Elapsed time: {s:.2f} seconds"</span><span class="p">,</span> <span class="s">"s"</span><span class="n">_a</span><span class="o">=</span><span class="mf">1.23</span><span class="p">);</span>
|
|
||||||
</pre></div>
|
|
||||||
</div>
|
</div>
|
||||||
</p>
|
|
||||||
</dd></dl>
|
|
||||||
|
|
||||||
<dl class="macro">
|
<dl class="macro">
|
||||||
<dt id="c.FMT_CAPTURE">
|
<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>
|
<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">
|
<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>
|
<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>
|
<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>
|
<p class="breathe-sectiondef-title rubric">Public Functions</p>
|
||||||
<dl class="function">
|
<dl class="function">
|
||||||
<dt id="_CPPv2N3fmt7ArgListixEj">
|
<dt id="_CPPv2NK3fmt7ArgListixEj">
|
||||||
<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>
|
<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><p>Returns the argument at specified index. </p>
|
||||||
</dd></dl>
|
</dd></dl>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</dd></dl>
|
</dd></dl>
|
||||||
|
|
||||||
|
<dl class="function">
|
||||||
|
<dt>
|
||||||
|
<em class="property">template </em><<em class="property">typename</em> T></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 &<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">"fmt/string.h"</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">
|
<dl class="class">
|
||||||
<dt>
|
<dt>
|
||||||
<span class="target" id="formatclassfmt_1_1_basic_string_ref"></span><em class="property">template </em><typename <em>Char</em>></dt>
|
<span class="target" id="formatclassfmt_1_1_basic_string_ref"></span><em class="property">template </em><typename <em>Char</em>></dt>
|
||||||
<dt id="_CPPv2N3fmt14BasicStringRefE">
|
<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>
|
<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>
|
<p>You can use one of the following typedefs for common character types:</p>
|
||||||
<table border="1" class="docutils">
|
<table border="1" class="docutils">
|
||||||
<colgroup>
|
<colgroup>
|
||||||
@@ -933,7 +1186,7 @@ different types of strings to a function, for example:</p>
|
|||||||
</pre></div>
|
</pre></div>
|
||||||
</div>
|
</div>
|
||||||
</p>
|
</p>
|
||||||
<div class="breathe-sectiondef container">
|
<div class="breathe-sectiondef docutils container">
|
||||||
<p class="breathe-sectiondef-title rubric">Public Functions</p>
|
<p class="breathe-sectiondef-title rubric">Public Functions</p>
|
||||||
<dl class="function">
|
<dl class="function">
|
||||||
<dt id="_CPPv2N3fmt14BasicStringRef14BasicStringRefEPK4CharNSt6size_tE">
|
<dt id="_CPPv2N3fmt14BasicStringRef14BasicStringRefEPK4CharNSt6size_tE">
|
||||||
@@ -950,28 +1203,30 @@ the size with <code class="docutils literal"><span class="pre">std::char_traits&
|
|||||||
</dd></dl>
|
</dd></dl>
|
||||||
|
|
||||||
<dl class="function">
|
<dl class="function">
|
||||||
<dt id="_CPPv2N3fmt14BasicStringRef14BasicStringRefERKNSt12basic_stringI4CharEE">
|
<dt>
|
||||||
<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<Char> &<em>s</em><span class="sig-paren">)</span><a class="headerlink" href="#_CPPv2N3fmt14BasicStringRef14BasicStringRefERKNSt12basic_stringI4CharEE" title="Permalink to this definition">¶</a></dt>
|
<em class="property">template </em><<em class="property">typename</em> Allocator></dt>
|
||||||
<dd><p><p>Constructs a string reference from an <code class="docutils literal"><span class="pre">std::string</span></code> object.</p>
|
<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<Char, std::char_traits<Char>, Allocator> &<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>
|
</p>
|
||||||
</dd></dl>
|
</dd></dl>
|
||||||
|
|
||||||
<dl class="function">
|
<dl class="function">
|
||||||
<dt id="_CPPv2N3fmt14BasicStringRef9to_stringEv">
|
<dt id="_CPPv2NK3fmt14BasicStringRef9to_stringEv">
|
||||||
<span id="fmt::BasicStringRef::to_string"></span><span class="target" id="formatclassfmt_1_1_basic_string_ref_1a7340f48f53cf9188e9fea5e6e1556969"></span>std::basic_string<Char> <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>
|
<span id="fmt::BasicStringRef::to_stringC"></span><span class="target" id="formatclassfmt_1_1_basic_string_ref_1a85503c30cd35cd6deff9e77da52857e6"></span>std::basic_string<Char> <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>
|
<dd><p><p>Converts a string reference to an <code class="docutils literal"><span class="pre">std::string</span></code> object.</p>
|
||||||
</p>
|
</p>
|
||||||
</dd></dl>
|
</dd></dl>
|
||||||
|
|
||||||
<dl class="function">
|
<dl class="function">
|
||||||
<dt id="_CPPv2N3fmt14BasicStringRef4dataEv">
|
<dt id="_CPPv2NK3fmt14BasicStringRef4dataEv">
|
||||||
<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>
|
<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><p>Returns a pointer to the string data. </p>
|
||||||
</dd></dl>
|
</dd></dl>
|
||||||
|
|
||||||
<dl class="function">
|
<dl class="function">
|
||||||
<dt id="_CPPv2N3fmt14BasicStringRef4sizeEv">
|
<dt id="_CPPv2NK3fmt14BasicStringRef4sizeEv">
|
||||||
<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>
|
<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><p>Returns the string size. </p>
|
||||||
</dd></dl>
|
</dd></dl>
|
||||||
|
|
||||||
@@ -984,7 +1239,7 @@ the size with <code class="docutils literal"><span class="pre">std::char_traits&
|
|||||||
<dt id="_CPPv2N3fmt15BasicCStringRefE">
|
<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>
|
<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
|
<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>
|
<p>You can use one of the following typedefs for common character types:</p>
|
||||||
<table border="1" class="docutils">
|
<table border="1" class="docutils">
|
||||||
<colgroup>
|
<colgroup>
|
||||||
@@ -1015,7 +1270,7 @@ different types of strings to a function, for example:</p>
|
|||||||
</pre></div>
|
</pre></div>
|
||||||
</div>
|
</div>
|
||||||
</p>
|
</p>
|
||||||
<div class="breathe-sectiondef container">
|
<div class="breathe-sectiondef docutils container">
|
||||||
<p class="breathe-sectiondef-title rubric">Public Functions</p>
|
<p class="breathe-sectiondef-title rubric">Public Functions</p>
|
||||||
<dl class="function">
|
<dl class="function">
|
||||||
<dt id="_CPPv2N3fmt15BasicCStringRef15BasicCStringRefEPK4Char">
|
<dt id="_CPPv2N3fmt15BasicCStringRef15BasicCStringRefEPK4Char">
|
||||||
@@ -1024,15 +1279,17 @@ different types of strings to a function, for example:</p>
|
|||||||
</dd></dl>
|
</dd></dl>
|
||||||
|
|
||||||
<dl class="function">
|
<dl class="function">
|
||||||
<dt id="_CPPv2N3fmt15BasicCStringRef15BasicCStringRefERKNSt12basic_stringI4CharEE">
|
<dt>
|
||||||
<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<Char> &<em>s</em><span class="sig-paren">)</span><a class="headerlink" href="#_CPPv2N3fmt15BasicCStringRef15BasicCStringRefERKNSt12basic_stringI4CharEE" title="Permalink to this definition">¶</a></dt>
|
<em class="property">template </em><<em class="property">typename</em> Allocator></dt>
|
||||||
<dd><p><p>Constructs a string reference from an <code class="docutils literal"><span class="pre">std::string</span></code> object.</p>
|
<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<Char, std::char_traits<Char>, Allocator> &<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>
|
</p>
|
||||||
</dd></dl>
|
</dd></dl>
|
||||||
|
|
||||||
<dl class="function">
|
<dl class="function">
|
||||||
<dt id="_CPPv2N3fmt15BasicCStringRef5c_strEv">
|
<dt id="_CPPv2NK3fmt15BasicCStringRef5c_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>
|
<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><p>Returns the pointer to a C string. </p>
|
||||||
</dd></dl>
|
</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>
|
<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>‘s operations.</p>
|
<dd><p><p>A buffer supporting a subset of <code class="docutils literal"><span class="pre">std::vector</span></code>‘s operations.</p>
|
||||||
</p>
|
</p>
|
||||||
<div class="breathe-sectiondef container">
|
<p>Subclassed by fmt::internal::MemoryBuffer< T, SIZE, Allocator ></p>
|
||||||
|
<div class="breathe-sectiondef docutils container">
|
||||||
<p class="breathe-sectiondef-title rubric">Public Functions</p>
|
<p class="breathe-sectiondef-title rubric">Public Functions</p>
|
||||||
<dl class="function">
|
<dl class="function">
|
||||||
<dt id="_CPPv2N3fmt6Buffer4sizeEv">
|
<dt id="_CPPv2NK3fmt6Buffer4sizeEv">
|
||||||
<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>
|
<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><p>Returns the size of this buffer. </p>
|
||||||
</dd></dl>
|
</dd></dl>
|
||||||
|
|
||||||
<dl class="function">
|
<dl class="function">
|
||||||
<dt id="_CPPv2N3fmt6Buffer8capacityEv">
|
<dt id="_CPPv2NK3fmt6Buffer8capacityEv">
|
||||||
<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>
|
<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><p>Returns the capacity of this buffer. </p>
|
||||||
</dd></dl>
|
</dd></dl>
|
||||||
|
|
||||||
@@ -1083,11 +1341,11 @@ different types of strings to a function, for example:</p>
|
|||||||
</dd></dl>
|
</dd></dl>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<div class="breathe-sectiondef container">
|
<div class="breathe-sectiondef docutils container">
|
||||||
<p class="breathe-sectiondef-title rubric">Protected Functions</p>
|
<p class="breathe-sectiondef-title rubric">Protected Functions</p>
|
||||||
<dl class="function">
|
<dl class="function">
|
||||||
<dt id="_CPPv2N3fmt6Buffer4growENSt6size_tE">
|
<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
|
<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>
|
<code class="docutils literal"><span class="pre">ptr_</span></code> and <code class="docutils literal"><span class="pre">capacity_</span></code>.</p>
|
||||||
</p>
|
</p>
|
||||||
@@ -1103,21 +1361,17 @@ different types of strings to a function, for example:</p>
|
|||||||
<dt id="_CPPv2N3fmt11SystemErrorE">
|
<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>
|
<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>
|
<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>
|
<p class="breathe-sectiondef-title rubric">Public Functions</p>
|
||||||
<dl class="function">
|
<dl class="function">
|
||||||
<dt id="_CPPv2N3fmt11SystemError11SystemErrorEi10CStringRef">
|
<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>
|
<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
|
<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
|
||||||
of the form</p>
|
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
|
||||||
<pre class="literal-block">
|
arguments passed into the constructor are formatted similarly to
|
||||||
<em><message></em>: <em><system-message></em>
|
<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>
|
||||||
</pre>
|
|
||||||
<p>where <em><message></em> is the formatted message and <em><system-message></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 “Unknown error -1” and is platform-dependent.</p>
|
|
||||||
<p><strong>Example</strong>:</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>
|
<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 'madeup': No such file or directory</span>
|
<span class="c1">// cannot open file 'madeup': No such file or directory</span>
|
||||||
@@ -1134,11 +1388,29 @@ may look like “Unknown error -1” and is platform-dependent.</p>
|
|||||||
</div>
|
</div>
|
||||||
</dd></dl>
|
</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 &<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><message></em>: <em><system-message></em>
|
||||||
|
</pre>
|
||||||
|
<p>where <em><message></em> is the passed message and <em><system-message></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 “Unknown error -1” and is platform-dependent.</p>
|
||||||
|
</p>
|
||||||
|
</dd></dl>
|
||||||
|
|
||||||
<dl class="class">
|
<dl class="class">
|
||||||
<dt id="_CPPv2N3fmt12WindowsErrorE">
|
<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>
|
<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>
|
<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>
|
<p class="breathe-sectiondef-title rubric">Public Functions</p>
|
||||||
<dl class="function">
|
<dl class="function">
|
||||||
<dt id="_CPPv2N3fmt12WindowsError12WindowsErrorEi10CStringRef">
|
<dt id="_CPPv2N3fmt12WindowsError12WindowsErrorEi10CStringRef">
|
||||||
@@ -1183,7 +1455,8 @@ A custom allocator class can be specified as a template argument to
|
|||||||
</div>
|
</div>
|
||||||
<p>It is also possible to write a formatting function that uses a custom
|
<p>It is also possible to write a formatting function that uses a custom
|
||||||
allocator:</p>
|
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"><</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"><</span><span class="kt">char</span><span class="o">></span><span class="p">,</span> <span class="n">CustomAllocator</span><span class="o">></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"><</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"><</span><span class="kt">char</span><span class="o">></span><span class="p">,</span> <span class="n">CustomAllocator</span><span class="o">></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">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>
|
<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">
|
<div class="footer" role="contentinfo">
|
||||||
© Copyright 2012-2015, Victor Zverovich.
|
© 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>
|
</div>
|
||||||
|
|
||||||
<script src="_static/bootstrap.min.js"></script>
|
<script src="_static/bootstrap.min.js"></script>
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
|
||||||
|
|
||||||
<title>Contents — fmt 3.0.0 documentation</title>
|
<title>Contents — fmt 4.0.0 documentation</title>
|
||||||
|
|
||||||
<link rel="stylesheet" href="_static/basic.css" type="text/css" />
|
<link rel="stylesheet" href="_static/basic.css" type="text/css" />
|
||||||
<link rel="stylesheet" href="_static/pygments.css" type="text/css" />
|
<link rel="stylesheet" href="_static/pygments.css" type="text/css" />
|
||||||
@@ -17,10 +17,11 @@
|
|||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
var DOCUMENTATION_OPTIONS = {
|
var DOCUMENTATION_OPTIONS = {
|
||||||
URL_ROOT: './',
|
URL_ROOT: './',
|
||||||
VERSION: '3.0.0',
|
VERSION: '4.0.0',
|
||||||
COLLAPSE_INDEX: false,
|
COLLAPSE_INDEX: false,
|
||||||
FILE_SUFFIX: '.html',
|
FILE_SUFFIX: '.html',
|
||||||
HAS_SOURCE: true
|
HAS_SOURCE: true,
|
||||||
|
SOURCELINK_SUFFIX: ''
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
<script type="text/javascript" src="_static/jquery.js"></script>
|
<script type="text/javascript" src="_static/jquery.js"></script>
|
||||||
@@ -34,8 +35,9 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
|
(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),
|
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();
|
||||||
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
|
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');
|
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
|
||||||
ga('create', 'UA-20116650-4', 'fmtlib.net');
|
ga('create', 'UA-20116650-4', 'fmtlib.net');
|
||||||
ga('send', 'pageview');
|
ga('send', 'pageview');
|
||||||
@@ -49,7 +51,8 @@
|
|||||||
<div class="navbar-content">
|
<div class="navbar-content">
|
||||||
|
|
||||||
<div class="navbar-header">
|
<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="sr-only">Toggle navigation</span>
|
||||||
<span class="icon-bar"></span>
|
<span class="icon-bar"></span>
|
||||||
<span class="icon-bar"></span>
|
<span class="icon-bar"></span>
|
||||||
@@ -62,18 +65,23 @@
|
|||||||
<div class="collapse navbar-collapse">
|
<div class="collapse navbar-collapse">
|
||||||
<ul class="nav navbar-nav">
|
<ul class="nav navbar-nav">
|
||||||
<li class="dropdown">
|
<li class="dropdown">
|
||||||
|
<a href="#" class="dropdown-toggle" data-toggle="dropdown"
|
||||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button"
|
role="button" aria-expanded="false">4.0.0
|
||||||
aria-expanded="false">3.0.0 <span class="caret"></span></a>
|
<span class="caret"></span></a>
|
||||||
<ul class="dropdown-menu" role="menu">
|
<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/3.0.0">3.0.0</a></li>
|
||||||
<li><a href="http://fmtlib.net/1.0.0/">1.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>
|
</ul>
|
||||||
</li>
|
</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>
|
</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">
|
<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>
|
</div>
|
||||||
<input type="hidden" name="check_keywords" value="yes" />
|
<input type="hidden" name="check_keywords" value="yes" />
|
||||||
<input type="hidden" name="area" value="default" />
|
<input type="hidden" name="area" value="default" />
|
||||||
@@ -120,6 +130,7 @@
|
|||||||
<ul>
|
<ul>
|
||||||
<li class="toctree-l1"><a class="reference internal" href="usage.html">Usage</a><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#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#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#android-ndk">Android NDK</a></li>
|
||||||
<li class="toctree-l2"><a class="reference internal" href="usage.html#homebrew">Homebrew</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">
|
<div class="footer" role="contentinfo">
|
||||||
© Copyright 2012-2015, Victor Zverovich.
|
© 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>
|
</div>
|
||||||
|
|
||||||
<script src="_static/bootstrap.min.js"></script>
|
<script src="_static/bootstrap.min.js"></script>
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
|
||||||
|
|
||||||
<title>Index — fmt 3.0.0 documentation</title>
|
<title>Index — fmt 4.0.0 documentation</title>
|
||||||
|
|
||||||
<link rel="stylesheet" href="_static/basic.css" type="text/css" />
|
<link rel="stylesheet" href="_static/basic.css" type="text/css" />
|
||||||
<link rel="stylesheet" href="_static/pygments.css" type="text/css" />
|
<link rel="stylesheet" href="_static/pygments.css" type="text/css" />
|
||||||
@@ -18,10 +18,11 @@
|
|||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
var DOCUMENTATION_OPTIONS = {
|
var DOCUMENTATION_OPTIONS = {
|
||||||
URL_ROOT: './',
|
URL_ROOT: './',
|
||||||
VERSION: '3.0.0',
|
VERSION: '4.0.0',
|
||||||
COLLAPSE_INDEX: false,
|
COLLAPSE_INDEX: false,
|
||||||
FILE_SUFFIX: '.html',
|
FILE_SUFFIX: '.html',
|
||||||
HAS_SOURCE: true
|
HAS_SOURCE: true,
|
||||||
|
SOURCELINK_SUFFIX: ''
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
<script type="text/javascript" src="_static/jquery.js"></script>
|
<script type="text/javascript" src="_static/jquery.js"></script>
|
||||||
@@ -34,8 +35,9 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
|
(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),
|
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();
|
||||||
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
|
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');
|
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
|
||||||
ga('create', 'UA-20116650-4', 'fmtlib.net');
|
ga('create', 'UA-20116650-4', 'fmtlib.net');
|
||||||
ga('send', 'pageview');
|
ga('send', 'pageview');
|
||||||
@@ -49,7 +51,8 @@
|
|||||||
<div class="navbar-content">
|
<div class="navbar-content">
|
||||||
|
|
||||||
<div class="navbar-header">
|
<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="sr-only">Toggle navigation</span>
|
||||||
<span class="icon-bar"></span>
|
<span class="icon-bar"></span>
|
||||||
<span class="icon-bar"></span>
|
<span class="icon-bar"></span>
|
||||||
@@ -62,13 +65,17 @@
|
|||||||
<div class="collapse navbar-collapse">
|
<div class="collapse navbar-collapse">
|
||||||
<ul class="nav navbar-nav">
|
<ul class="nav navbar-nav">
|
||||||
<li class="dropdown">
|
<li class="dropdown">
|
||||||
|
<a href="#" class="dropdown-toggle" data-toggle="dropdown"
|
||||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button"
|
role="button" aria-expanded="false">4.0.0
|
||||||
aria-expanded="false">3.0.0 <span class="caret"></span></a>
|
<span class="caret"></span></a>
|
||||||
<ul class="dropdown-menu" role="menu">
|
<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/3.0.0">3.0.0</a></li>
|
||||||
<li><a href="http://fmtlib.net/1.0.0/">1.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>
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
@@ -91,9 +98,11 @@
|
|||||||
</ul>
|
</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">
|
<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>
|
</div>
|
||||||
<input type="hidden" name="check_keywords" value="yes" />
|
<input type="hidden" name="check_keywords" value="yes" />
|
||||||
<input type="hidden" name="area" value="default" />
|
<input type="hidden" name="area" value="default" />
|
||||||
@@ -141,7 +150,7 @@
|
|||||||
</dt>
|
</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>
|
</dt>
|
||||||
|
|
||||||
|
|
||||||
@@ -217,7 +226,7 @@
|
|||||||
</dt>
|
</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>
|
</dt>
|
||||||
|
|
||||||
|
|
||||||
@@ -233,15 +242,23 @@
|
|||||||
</dt>
|
</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><a href="api.html#_CPPv2N3fmt15BasicCStringRefE">fmt::BasicCStringRef (C++ class)</a>
|
||||||
</dt>
|
</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>
|
||||||
|
|
||||||
|
|
||||||
<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>
|
</dt>
|
||||||
|
|
||||||
|
|
||||||
@@ -276,6 +293,34 @@
|
|||||||
<dt><a href="api.html#_CPPv2N3fmt17BasicMemoryWriteraSERR17BasicMemoryWriter">fmt::BasicMemoryWriter::operator= (C++ function)</a>
|
<dt><a href="api.html#_CPPv2N3fmt17BasicMemoryWriteraSERR17BasicMemoryWriter">fmt::BasicMemoryWriter::operator= (C++ function)</a>
|
||||||
</dt>
|
</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>
|
</dl></td>
|
||||||
<td style="width: 33%" valign="top"><dl>
|
<td style="width: 33%" valign="top"><dl>
|
||||||
|
|
||||||
@@ -283,19 +328,31 @@
|
|||||||
</dt>
|
</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>
|
||||||
|
|
||||||
|
|
||||||
<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>
|
||||||
|
|
||||||
|
|
||||||
<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>
|
||||||
|
|
||||||
|
|
||||||
<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>
|
</dt>
|
||||||
|
|
||||||
|
|
||||||
@@ -303,11 +360,11 @@
|
|||||||
</dt>
|
</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>
|
||||||
|
|
||||||
|
|
||||||
<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>
|
</dt>
|
||||||
|
|
||||||
|
|
||||||
@@ -315,11 +372,11 @@
|
|||||||
</dt>
|
</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>
|
||||||
|
|
||||||
|
|
||||||
<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>
|
</dt>
|
||||||
|
|
||||||
|
|
||||||
@@ -343,7 +400,7 @@
|
|||||||
</dt>
|
</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>
|
</dt>
|
||||||
|
|
||||||
|
|
||||||
@@ -359,7 +416,7 @@
|
|||||||
</dt>
|
</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>
|
</dt>
|
||||||
|
|
||||||
|
|
||||||
@@ -367,6 +424,10 @@
|
|||||||
</dt>
|
</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><a href="api.html#_CPPv2N3fmt7fprintfEPNSt4FILEE10CStringRef7ArgList">fmt::fprintf (C++ function)</a>, <a href="api.html#_CPPv2N3fmt7fprintfERNSt7ostreamE10CStringRef7ArgList">[1]</a>
|
||||||
</dt>
|
</dt>
|
||||||
|
|
||||||
@@ -379,14 +440,6 @@
|
|||||||
</dt>
|
</dt>
|
||||||
|
|
||||||
|
|
||||||
<dt><a href="api.html#_CPPv2N3fmt8literalsli2_aEPKcNSt6size_tE">fmt::literals::operator""_a (C++ function)</a>
|
|
||||||
</dt>
|
|
||||||
|
|
||||||
|
|
||||||
<dt><a href="api.html#_CPPv2N3fmt8literalsli7_formatEPKcNSt6size_tE">fmt::literals::operator""_format (C++ function)</a>
|
|
||||||
</dt>
|
|
||||||
|
|
||||||
|
|
||||||
<dt><a href="api.html#_CPPv2N3fmt3octEi">fmt::oct (C++ function)</a>
|
<dt><a href="api.html#_CPPv2N3fmt3octEi">fmt::oct (C++ function)</a>
|
||||||
</dt>
|
</dt>
|
||||||
|
|
||||||
@@ -403,6 +456,26 @@
|
|||||||
</dt>
|
</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><a href="api.html#_CPPv2N3fmt7sprintfE10CStringRef7ArgList">fmt::sprintf (C++ function)</a>
|
||||||
</dt>
|
</dt>
|
||||||
|
|
||||||
@@ -415,6 +488,10 @@
|
|||||||
</dt>
|
</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><a href="api.html#_CPPv2N3fmt12WindowsErrorE">fmt::WindowsError (C++ class)</a>
|
||||||
</dt>
|
</dt>
|
||||||
|
|
||||||
@@ -443,7 +520,7 @@
|
|||||||
|
|
||||||
<div class="footer" role="contentinfo">
|
<div class="footer" role="contentinfo">
|
||||||
© Copyright 2012-2015, Victor Zverovich.
|
© 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>
|
</div>
|
||||||
|
|
||||||
<script src="_static/bootstrap.min.js"></script>
|
<script src="_static/bootstrap.min.js"></script>
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
|
||||||
|
|
||||||
<title>Overview — fmt 3.0.0 documentation</title>
|
<title>Overview — fmt 4.0.0 documentation</title>
|
||||||
|
|
||||||
<link rel="stylesheet" href="_static/basic.css" type="text/css" />
|
<link rel="stylesheet" href="_static/basic.css" type="text/css" />
|
||||||
<link rel="stylesheet" href="_static/pygments.css" type="text/css" />
|
<link rel="stylesheet" href="_static/pygments.css" type="text/css" />
|
||||||
@@ -17,10 +17,11 @@
|
|||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
var DOCUMENTATION_OPTIONS = {
|
var DOCUMENTATION_OPTIONS = {
|
||||||
URL_ROOT: './',
|
URL_ROOT: './',
|
||||||
VERSION: '3.0.0',
|
VERSION: '4.0.0',
|
||||||
COLLAPSE_INDEX: false,
|
COLLAPSE_INDEX: false,
|
||||||
FILE_SUFFIX: '.html',
|
FILE_SUFFIX: '.html',
|
||||||
HAS_SOURCE: true
|
HAS_SOURCE: true,
|
||||||
|
SOURCELINK_SUFFIX: ''
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
<script type="text/javascript" src="_static/jquery.js"></script>
|
<script type="text/javascript" src="_static/jquery.js"></script>
|
||||||
@@ -33,8 +34,9 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
|
(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),
|
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();
|
||||||
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
|
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');
|
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
|
||||||
ga('create', 'UA-20116650-4', 'fmtlib.net');
|
ga('create', 'UA-20116650-4', 'fmtlib.net');
|
||||||
ga('send', 'pageview');
|
ga('send', 'pageview');
|
||||||
@@ -48,7 +50,8 @@
|
|||||||
<div class="navbar-content">
|
<div class="navbar-content">
|
||||||
|
|
||||||
<div class="navbar-header">
|
<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="sr-only">Toggle navigation</span>
|
||||||
<span class="icon-bar"></span>
|
<span class="icon-bar"></span>
|
||||||
<span class="icon-bar"></span>
|
<span class="icon-bar"></span>
|
||||||
@@ -61,13 +64,17 @@
|
|||||||
<div class="collapse navbar-collapse">
|
<div class="collapse navbar-collapse">
|
||||||
<ul class="nav navbar-nav">
|
<ul class="nav navbar-nav">
|
||||||
<li class="dropdown">
|
<li class="dropdown">
|
||||||
|
<a href="#" class="dropdown-toggle" data-toggle="dropdown"
|
||||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button"
|
role="button" aria-expanded="false">4.0.0
|
||||||
aria-expanded="false">3.0.0 <span class="caret"></span></a>
|
<span class="caret"></span></a>
|
||||||
<ul class="dropdown-menu" role="menu">
|
<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/3.0.0">3.0.0</a></li>
|
||||||
<li><a href="http://fmtlib.net/1.0.0/">1.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>
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
@@ -90,9 +97,11 @@
|
|||||||
</ul>
|
</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">
|
<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>
|
</div>
|
||||||
<input type="hidden" name="check_keywords" value="yes" />
|
<input type="hidden" name="check_keywords" value="yes" />
|
||||||
<input type="hidden" name="area" value="default" />
|
<input type="hidden" name="area" value="default" />
|
||||||
@@ -105,20 +114,33 @@
|
|||||||
</div>
|
</div>
|
||||||
</nav>
|
</nav>
|
||||||
|
|
||||||
|
|
||||||
<div class="jumbotron">
|
<div class="jumbotron">
|
||||||
<div class="tb-container">
|
<div class="tb-container">
|
||||||
<h1>{fmt}</h1>
|
<h1>{fmt}</h1>
|
||||||
<p class="lead">Small, safe and fast formatting library</p>
|
<p class="lead">Small, safe and fast formatting library</p>
|
||||||
<div class="btn-group" role="group">
|
<div class="btn-group" role="group">
|
||||||
|
|
||||||
<a class="btn btn-success"
|
<a class="btn btn-success"
|
||||||
href="https://github.com/fmtlib/fmt/releases/download/2.0.0/cppformat-2.0.0.zip">
|
href="https://github.com/fmtlib/fmt/releases/download/4.0.0/fmt-4.0.0.zip">
|
||||||
<span class="glyphicon glyphicon-download"></span> Download
|
<span class="glyphicon glyphicon-download"></span> Download
|
||||||
</a>
|
</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">
|
<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>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -140,16 +162,16 @@ alternative to C++ IOStreams.</p>
|
|||||||
<div class="panel panel-default">
|
<div class="panel panel-default">
|
||||||
<div class="panel-heading">What users say:</div>
|
<div class="panel-heading">What users say:</div>
|
||||||
<div class="panel-body">
|
<div class="panel-body">
|
||||||
Thanks for creating this library. It’s been a hole in C++ for a long time.
|
Thanks for creating this library. It’s been a hole in C++ for a long
|
||||||
I’ve used both boost::format and loki::SPrintf, and neither felt like the
|
time. I’ve used both boost::format and loki::SPrintf, and neither felt
|
||||||
right answer. This does.
|
like the right answer. This does.
|
||||||
</div>
|
</div>
|
||||||
</div><div class="section" id="format-api">
|
</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>
|
<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>,
|
<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>.
|
<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
|
The <a class="reference external" href="syntax.html">format string syntax</a> is similar to the one used by
|
||||||
to the one used by <a class="reference external" href="http://docs.python.org/2/library/stdtypes.html#str.format">str.format</a>
|
<a class="reference external" href="http://docs.python.org/2/library/stdtypes.html#str.format">str.format</a>
|
||||||
in Python:</p>
|
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">"The answer is {}"</span><span class="p">,</span> <span class="mi">42</span><span class="p">);</span>
|
<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">"The answer is {}"</span><span class="p">,</span> <span class="mi">42</span><span class="p">);</span>
|
||||||
</pre></div>
|
</pre></div>
|
||||||
@@ -202,8 +224,7 @@ literal operators, they must be made visible with the directive
|
|||||||
</div>
|
</div>
|
||||||
<div class="section" id="write-api">
|
<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>
|
<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
|
<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>
|
||||||
<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>
|
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>
|
<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"><<</span> <span class="s">"The answer in hexadecimal is "</span> <span class="o"><<</span> <span class="n">hex</span><span class="p">(</span><span class="mi">42</span><span class="p">);</span>
|
<span class="n">out</span> <span class="o"><<</span> <span class="s">"The answer in hexadecimal is "</span> <span class="o"><<</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>
|
||||||
<div class="section" id="safety">
|
<div class="section" id="safety">
|
||||||
<span id="id3"></span><h2>Safety<a class="headerlink" href="#safety" title="Permalink to this headline">¶</a></h2>
|
<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,
|
<p>The library is fully type safe, automatic memory management prevents buffer
|
||||||
errors in format strings are reported using exceptions. For example, the code</p>
|
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">"The answer is {:d}"</span><span class="p">,</span> <span class="s">"forty-two"</span><span class="p">);</span>
|
<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">"The answer is {:d}"</span><span class="p">,</span> <span class="s">"forty-two"</span><span class="p">);</span>
|
||||||
</pre></div>
|
</pre></div>
|
||||||
</div>
|
</div>
|
||||||
@@ -231,36 +253,38 @@ formatted into a narrow string. You can use a wide format string instead:</p>
|
|||||||
</pre></div>
|
</pre></div>
|
||||||
</div>
|
</div>
|
||||||
<p>For comparison, writing a wide character to <code class="docutils literal"><span class="pre">std::ostream</span></code> results in
|
<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 ‘ю’ which
|
its numeric value being written to the stream (i.e. 1070 instead of letter ‘ю’
|
||||||
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>
|
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>
|
||||||
<div class="section" id="portability">
|
<div class="section" id="portability">
|
||||||
<span id="id4"></span><h2>Portability<a class="headerlink" href="#portability" title="Permalink to this headline">¶</a></h2>
|
<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
|
<p>The library is highly portable. Here is an incomplete list of operating systems
|
||||||
compilers where it has been tested and known to work:</p>
|
and compilers where it has been tested and known to work:</p>
|
||||||
<ul class="simple">
|
<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>,
|
<li>64-bit (amd64) GNU/Linux with GCC 4.4.3,
|
||||||
4.7.2, 4.8.1 and Intel C++ Compiler (ICC) 14.0.2</li>
|
<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>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>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
|
<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>
|
<a class="reference external" href="https://ci.appveyor.com/project/vitaut/fmt">2015</a></li>
|
||||||
<li>32-bit Windows with Visual C++ 2010</li>
|
<li>32-bit Windows with Visual C++ 2010</li>
|
||||||
</ul>
|
</ul>
|
||||||
<p>Although the library uses C++11 features when available, it also works with older
|
<p>Although the library uses C++11 features when available, it also works with
|
||||||
compilers and standard library implementations. The only thing to keep in mind
|
older compilers and standard library implementations. The only thing to keep in
|
||||||
for C++98 portability:</p>
|
mind for C++98 portability:</p>
|
||||||
<ul class="simple">
|
<ul class="simple">
|
||||||
<li>Variadic templates: minimum GCC 4.4, Clang 2.9 or VS2013. This feature allows
|
<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 Format API to accept an unlimited number of arguments. With older
|
||||||
the maximum is 15.</li>
|
compilers the maximum is 15.</li>
|
||||||
<li>User-defined literals: minimum GCC 4.7, Clang 3.1 or VS2015. The suffixes
|
<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">_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>
|
<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>
|
</ul>
|
||||||
<p>The output of all formatting functions is consistent across platforms. In particular,
|
<p>The output of all formatting functions is consistent across platforms. In
|
||||||
formatting a floating-point infinity always gives <code class="docutils literal"><span class="pre">inf</span></code> while the output
|
particular, formatting a floating-point infinity always gives <code class="docutils literal"><span class="pre">inf</span></code> while the
|
||||||
of <code class="docutils literal"><span class="pre">printf</span></code> is platform-dependent in this case. For example,</p>
|
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">"{}"</span><span class="p">,</span> <span class="n">std</span><span class="o">::</span><span class="n">numeric_limits</span><span class="o"><</span><span class="kt">double</span><span class="o">>::</span><span class="n">infinity</span><span class="p">());</span>
|
<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">"{}"</span><span class="p">,</span> <span class="n">std</span><span class="o">::</span><span class="n">numeric_limits</span><span class="o"><</span><span class="kt">double</span><span class="o">>::</span><span class="n">infinity</span><span class="p">());</span>
|
||||||
</pre></div>
|
</pre></div>
|
||||||
</div>
|
</div>
|
||||||
@@ -268,9 +292,10 @@ of <code class="docutils literal"><span class="pre">printf</span></code> is plat
|
|||||||
</div>
|
</div>
|
||||||
<div class="section" id="ease-of-use">
|
<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>
|
<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
|
<p>fmt has a small self-contained code base with the core library consisting of
|
||||||
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
|
a single header file and a single source file and no external dependencies.
|
||||||
in open-source and commercial projects.</p>
|
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>
|
<a class="btn btn-success" href="https://github.com/fmtlib/fmt">GitHub Repository</a>
|
||||||
|
|
||||||
<div class="section footer">
|
<div class="section footer">
|
||||||
@@ -288,7 +313,7 @@ in open-source and commercial projects.</p>
|
|||||||
|
|
||||||
<div class="footer" role="contentinfo">
|
<div class="footer" role="contentinfo">
|
||||||
© Copyright 2012-2015, Victor Zverovich.
|
© 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>
|
</div>
|
||||||
|
|
||||||
<script src="_static/bootstrap.min.js"></script>
|
<script src="_static/bootstrap.min.js"></script>
|
||||||
|
|||||||
Binary file not shown.
@@ -8,7 +8,7 @@
|
|||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
|
||||||
|
|
||||||
<title>Search — fmt 3.0.0 documentation</title>
|
<title>Search — fmt 4.0.0 documentation</title>
|
||||||
|
|
||||||
<link rel="stylesheet" href="_static/basic.css" type="text/css" />
|
<link rel="stylesheet" href="_static/basic.css" type="text/css" />
|
||||||
<link rel="stylesheet" href="_static/pygments.css" type="text/css" />
|
<link rel="stylesheet" href="_static/pygments.css" type="text/css" />
|
||||||
@@ -17,10 +17,11 @@
|
|||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
var DOCUMENTATION_OPTIONS = {
|
var DOCUMENTATION_OPTIONS = {
|
||||||
URL_ROOT: './',
|
URL_ROOT: './',
|
||||||
VERSION: '3.0.0',
|
VERSION: '4.0.0',
|
||||||
COLLAPSE_INDEX: false,
|
COLLAPSE_INDEX: false,
|
||||||
FILE_SUFFIX: '.html',
|
FILE_SUFFIX: '.html',
|
||||||
HAS_SOURCE: true
|
HAS_SOURCE: true,
|
||||||
|
SOURCELINK_SUFFIX: ''
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
<script type="text/javascript" src="_static/jquery.js"></script>
|
<script type="text/javascript" src="_static/jquery.js"></script>
|
||||||
@@ -40,8 +41,9 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
|
(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),
|
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();
|
||||||
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
|
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');
|
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
|
||||||
ga('create', 'UA-20116650-4', 'fmtlib.net');
|
ga('create', 'UA-20116650-4', 'fmtlib.net');
|
||||||
ga('send', 'pageview');
|
ga('send', 'pageview');
|
||||||
@@ -56,7 +58,8 @@
|
|||||||
<div class="navbar-content">
|
<div class="navbar-content">
|
||||||
|
|
||||||
<div class="navbar-header">
|
<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="sr-only">Toggle navigation</span>
|
||||||
<span class="icon-bar"></span>
|
<span class="icon-bar"></span>
|
||||||
<span class="icon-bar"></span>
|
<span class="icon-bar"></span>
|
||||||
@@ -69,13 +72,17 @@
|
|||||||
<div class="collapse navbar-collapse">
|
<div class="collapse navbar-collapse">
|
||||||
<ul class="nav navbar-nav">
|
<ul class="nav navbar-nav">
|
||||||
<li class="dropdown">
|
<li class="dropdown">
|
||||||
|
<a href="#" class="dropdown-toggle" data-toggle="dropdown"
|
||||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button"
|
role="button" aria-expanded="false">4.0.0
|
||||||
aria-expanded="false">3.0.0 <span class="caret"></span></a>
|
<span class="caret"></span></a>
|
||||||
<ul class="dropdown-menu" role="menu">
|
<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/3.0.0">3.0.0</a></li>
|
||||||
<li><a href="http://fmtlib.net/1.0.0/">1.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>
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
@@ -126,9 +133,11 @@
|
|||||||
containing fewer words won't appear in the result list.
|
containing fewer words won't appear in the result list.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<form class="form-inline" role="search" action="#" method="get">
|
<form class="form-inline" role="search" action="#"
|
||||||
|
method="get">
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<input type="text" name="q" class="form-control" >
|
<input type="text" name="q" class="form-control"
|
||||||
|
>
|
||||||
</div>
|
</div>
|
||||||
<input type="hidden" name="check_keywords" value="yes" />
|
<input type="hidden" name="check_keywords" value="yes" />
|
||||||
<input type="hidden" name="area" value="default" />
|
<input type="hidden" name="area" value="default" />
|
||||||
@@ -149,7 +158,7 @@
|
|||||||
|
|
||||||
<div class="footer" role="contentinfo">
|
<div class="footer" role="contentinfo">
|
||||||
© Copyright 2012-2015, Victor Zverovich.
|
© 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>
|
</div>
|
||||||
|
|
||||||
<script src="_static/bootstrap.min.js"></script>
|
<script src="_static/bootstrap.min.js"></script>
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
@@ -8,7 +8,7 @@
|
|||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
|
||||||
|
|
||||||
<title>Format String Syntax — fmt 3.0.0 documentation</title>
|
<title>Format String Syntax — fmt 4.0.0 documentation</title>
|
||||||
|
|
||||||
<link rel="stylesheet" href="_static/basic.css" type="text/css" />
|
<link rel="stylesheet" href="_static/basic.css" type="text/css" />
|
||||||
<link rel="stylesheet" href="_static/pygments.css" type="text/css" />
|
<link rel="stylesheet" href="_static/pygments.css" type="text/css" />
|
||||||
@@ -17,10 +17,11 @@
|
|||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
var DOCUMENTATION_OPTIONS = {
|
var DOCUMENTATION_OPTIONS = {
|
||||||
URL_ROOT: './',
|
URL_ROOT: './',
|
||||||
VERSION: '3.0.0',
|
VERSION: '4.0.0',
|
||||||
COLLAPSE_INDEX: false,
|
COLLAPSE_INDEX: false,
|
||||||
FILE_SUFFIX: '.html',
|
FILE_SUFFIX: '.html',
|
||||||
HAS_SOURCE: true
|
HAS_SOURCE: true,
|
||||||
|
SOURCELINK_SUFFIX: ''
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
<script type="text/javascript" src="_static/jquery.js"></script>
|
<script type="text/javascript" src="_static/jquery.js"></script>
|
||||||
@@ -34,8 +35,9 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
|
(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),
|
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();
|
||||||
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
|
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');
|
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
|
||||||
ga('create', 'UA-20116650-4', 'fmtlib.net');
|
ga('create', 'UA-20116650-4', 'fmtlib.net');
|
||||||
ga('send', 'pageview');
|
ga('send', 'pageview');
|
||||||
@@ -49,7 +51,8 @@
|
|||||||
<div class="navbar-content">
|
<div class="navbar-content">
|
||||||
|
|
||||||
<div class="navbar-header">
|
<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="sr-only">Toggle navigation</span>
|
||||||
<span class="icon-bar"></span>
|
<span class="icon-bar"></span>
|
||||||
<span class="icon-bar"></span>
|
<span class="icon-bar"></span>
|
||||||
@@ -62,13 +65,17 @@
|
|||||||
<div class="collapse navbar-collapse">
|
<div class="collapse navbar-collapse">
|
||||||
<ul class="nav navbar-nav">
|
<ul class="nav navbar-nav">
|
||||||
<li class="dropdown">
|
<li class="dropdown">
|
||||||
|
<a href="#" class="dropdown-toggle" data-toggle="dropdown"
|
||||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button"
|
role="button" aria-expanded="false">4.0.0
|
||||||
aria-expanded="false">3.0.0 <span class="caret"></span></a>
|
<span class="caret"></span></a>
|
||||||
<ul class="dropdown-menu" role="menu">
|
<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/3.0.0">3.0.0</a></li>
|
||||||
<li><a href="http://fmtlib.net/1.0.0/">1.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>
|
</ul>
|
||||||
</li>
|
</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>
|
</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">
|
<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>
|
</div>
|
||||||
<input type="hidden" name="check_keywords" value="yes" />
|
<input type="hidden" name="check_keywords" value="yes" />
|
||||||
<input type="hidden" name="area" value="default" />
|
<input type="hidden" name="area" value="default" />
|
||||||
@@ -153,12 +163,10 @@ precision and so on. Each value type can define its own “formatting
|
|||||||
mini-language” or interpretation of the <em>format_spec</em>.</p>
|
mini-language” or interpretation of the <em>format_spec</em>.</p>
|
||||||
<p>Most built-in types support a common formatting mini-language, which is
|
<p>Most built-in types support a common formatting mini-language, which is
|
||||||
described in the next section.</p>
|
described in the next section.</p>
|
||||||
<p>A <em>format_spec</em> field can also include nested replacement fields within it.
|
<p>A <em>format_spec</em> field can also include nested replacement fields in certain
|
||||||
These nested replacement fields can contain only an argument index;
|
positions within it. These nested replacement fields can contain only an
|
||||||
format specifications are not allowed. Formatting is performed as if the
|
argument id; format specifications are not allowed. This allows the
|
||||||
replacement fields within the format_spec are substituted before the
|
formatting of a value to be dynamically specified.</p>
|
||||||
<em>format_spec</em> string is interpreted. 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>
|
<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">
|
<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>
|
<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> ::= "+" | "-" | " "
|
<strong id="grammar-token-sign">sign </strong> ::= "+" | "-" | " "
|
||||||
<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> | "{" <a class="reference internal" href="#grammar-token-arg_id"><code class="xref docutils literal"><span class="pre">arg_id</span></code></a> "}"
|
<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> | "{" <a class="reference internal" href="#grammar-token-arg_id"><code class="xref docutils literal"><span class="pre">arg_id</span></code></a> "}"
|
||||||
<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> | "{" <a class="reference internal" href="#grammar-token-arg_id"><code class="xref docutils literal"><span class="pre">arg_id</span></code></a> "}"
|
<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> | "{" <a class="reference internal" href="#grammar-token-arg_id"><code class="xref docutils literal"><span class="pre">arg_id</span></code></a> "}"
|
||||||
<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> | "c" | "e" | "E" | "f" | "F" | "g" | "G" | "p" | "s"
|
<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> | "a" | "A" | "c" | "e" | "E" | "f" | "F" | "g" | "G" | "p" | "s"
|
||||||
<strong id="grammar-token-int_type">int_type </strong> ::= "b" | "B" | "d" | "o" | "x" | "X"
|
<strong id="grammar-token-int_type">int_type </strong> ::= "b" | "B" | "d" | "n" | "o" | "x" | "X"
|
||||||
</pre>
|
</pre>
|
||||||
<p>The <em>fill</em> character can be any character other than ‘{‘ or ‘}’. The presence
|
<p>The <em>fill</em> character can be any character other than ‘{‘ or ‘}’. The presence
|
||||||
of a fill character is signaled by the character following it, which must be
|
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>
|
<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
|
<td>Hexadecimal floating point format. Prints the number in
|
||||||
base 16 with prefix <code class="docutils literal"><span class="pre">"0x"</span></code> and lower-case letters for
|
base 16 with prefix <code class="docutils literal"><span class="pre">"0x"</span></code> and lower-case letters for
|
||||||
digits above 9. Uses ‘p’ 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>
|
||||||
<tr class="row-odd"><td><code class="docutils literal"><span class="pre">'A'</span></code></td>
|
<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
|
<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">
|
<div class="footer" role="contentinfo">
|
||||||
© Copyright 2012-2015, Victor Zverovich.
|
© 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>
|
</div>
|
||||||
|
|
||||||
<script src="_static/bootstrap.min.js"></script>
|
<script src="_static/bootstrap.min.js"></script>
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
|
||||||
|
|
||||||
<title>Usage — fmt 3.0.0 documentation</title>
|
<title>Usage — fmt 4.0.0 documentation</title>
|
||||||
|
|
||||||
<link rel="stylesheet" href="_static/basic.css" type="text/css" />
|
<link rel="stylesheet" href="_static/basic.css" type="text/css" />
|
||||||
<link rel="stylesheet" href="_static/pygments.css" type="text/css" />
|
<link rel="stylesheet" href="_static/pygments.css" type="text/css" />
|
||||||
@@ -17,10 +17,11 @@
|
|||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
var DOCUMENTATION_OPTIONS = {
|
var DOCUMENTATION_OPTIONS = {
|
||||||
URL_ROOT: './',
|
URL_ROOT: './',
|
||||||
VERSION: '3.0.0',
|
VERSION: '4.0.0',
|
||||||
COLLAPSE_INDEX: false,
|
COLLAPSE_INDEX: false,
|
||||||
FILE_SUFFIX: '.html',
|
FILE_SUFFIX: '.html',
|
||||||
HAS_SOURCE: true
|
HAS_SOURCE: true,
|
||||||
|
SOURCELINK_SUFFIX: ''
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
<script type="text/javascript" src="_static/jquery.js"></script>
|
<script type="text/javascript" src="_static/jquery.js"></script>
|
||||||
@@ -35,8 +36,9 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
|
(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),
|
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();
|
||||||
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
|
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');
|
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
|
||||||
ga('create', 'UA-20116650-4', 'fmtlib.net');
|
ga('create', 'UA-20116650-4', 'fmtlib.net');
|
||||||
ga('send', 'pageview');
|
ga('send', 'pageview');
|
||||||
@@ -50,7 +52,8 @@
|
|||||||
<div class="navbar-content">
|
<div class="navbar-content">
|
||||||
|
|
||||||
<div class="navbar-header">
|
<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="sr-only">Toggle navigation</span>
|
||||||
<span class="icon-bar"></span>
|
<span class="icon-bar"></span>
|
||||||
<span class="icon-bar"></span>
|
<span class="icon-bar"></span>
|
||||||
@@ -63,13 +66,17 @@
|
|||||||
<div class="collapse navbar-collapse">
|
<div class="collapse navbar-collapse">
|
||||||
<ul class="nav navbar-nav">
|
<ul class="nav navbar-nav">
|
||||||
<li class="dropdown">
|
<li class="dropdown">
|
||||||
|
<a href="#" class="dropdown-toggle" data-toggle="dropdown"
|
||||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button"
|
role="button" aria-expanded="false">4.0.0
|
||||||
aria-expanded="false">3.0.0 <span class="caret"></span></a>
|
<span class="caret"></span></a>
|
||||||
<ul class="dropdown-menu" role="menu">
|
<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/3.0.0">3.0.0</a></li>
|
||||||
<li><a href="http://fmtlib.net/1.0.0/">1.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>
|
</ul>
|
||||||
</li>
|
</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>
|
</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">
|
<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>
|
</div>
|
||||||
<input type="hidden" name="check_keywords" value="yes" />
|
<input type="hidden" name="check_keywords" value="yes" />
|
||||||
<input type="hidden" name="area" value="default" />
|
<input type="hidden" name="area" value="default" />
|
||||||
@@ -155,14 +165,38 @@ using Visual Studio or msbuild.</p>
|
|||||||
</pre></div>
|
</pre></div>
|
||||||
</div>
|
</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">
|
<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>
|
<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
|
<p>To build the documentation you need the following software installed on your
|
||||||
system:</p>
|
system:</p>
|
||||||
<ul class="simple">
|
<ul>
|
||||||
<li><a class="reference external" href="https://www.python.org/">Python</a> with pip and virtualenv</li>
|
<li><p class="first"><a class="reference external" href="https://www.python.org/">Python</a> with pip and virtualenv</p>
|
||||||
<li><a class="reference external" href="http://www.stack.nl/~dimitri/doxygen/">Doxygen</a></li>
|
</li>
|
||||||
<li><a class="reference external" href="http://lesscss.org/">Less</a> with less-plugin-clean-css</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’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>
|
</ul>
|
||||||
<p>First generate makefiles or project files using CMake as described in
|
<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>
|
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">
|
<div class="section" id="homebrew">
|
||||||
<h2>Homebrew<a class="headerlink" href="#homebrew" title="Permalink to this headline">¶</a></h2>
|
<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>
|
<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>
|
</pre></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -197,7 +231,7 @@ repository.</p>
|
|||||||
|
|
||||||
<div class="footer" role="contentinfo">
|
<div class="footer" role="contentinfo">
|
||||||
© Copyright 2012-2015, Victor Zverovich.
|
© 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>
|
</div>
|
||||||
|
|
||||||
<script src="_static/bootstrap.min.js"></script>
|
<script src="_static/bootstrap.min.js"></script>
|
||||||
|
|||||||
+30
-27
@@ -10,9 +10,9 @@ alternative to C++ IOStreams.
|
|||||||
<div class="panel panel-default">
|
<div class="panel panel-default">
|
||||||
<div class="panel-heading">What users say:</div>
|
<div class="panel-heading">What users say:</div>
|
||||||
<div class="panel-body">
|
<div class="panel-body">
|
||||||
Thanks for creating this library. It’s been a hole in C++ for a long time.
|
Thanks for creating this library. It’s been a hole in C++ for a long
|
||||||
I’ve used both boost::format and loki::SPrintf, and neither felt like the
|
time. I’ve used both boost::format and loki::SPrintf, and neither felt
|
||||||
right answer. This does.
|
like the right answer. This does.
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -24,8 +24,8 @@ Format API
|
|||||||
The replacement-based Format API provides a safe alternative to ``printf``,
|
The replacement-based Format API provides a safe alternative to ``printf``,
|
||||||
``sprintf`` and friends with comparable or `better performance
|
``sprintf`` and friends with comparable or `better performance
|
||||||
<http://zverovich.net/2013/09/07/integer-to-string-conversion-in-cplusplus.html>`_.
|
<http://zverovich.net/2013/09/07/integer-to-string-conversion-in-cplusplus.html>`_.
|
||||||
The `format string syntax <doc/latest/index.html#format-string-syntax>`_ is similar
|
The `format string syntax <syntax.html>`_ is similar to the one used by
|
||||||
to the one used by `str.format <http://docs.python.org/2/library/stdtypes.html#str.format>`_
|
`str.format <http://docs.python.org/2/library/stdtypes.html#str.format>`_
|
||||||
in Python:
|
in Python:
|
||||||
|
|
||||||
.. code:: c++
|
.. code:: c++
|
||||||
@@ -98,8 +98,8 @@ literal operators, they must be made visible with the directive
|
|||||||
Write API
|
Write API
|
||||||
---------
|
---------
|
||||||
|
|
||||||
The concatenation-based Write API (experimental) provides a
|
The concatenation-based Write API (experimental) provides a `fast
|
||||||
`fast <http://zverovich.net/2013/09/07/integer-to-string-conversion-in-cplusplus.html>`_
|
<http://zverovich.net/2013/09/07/integer-to-string-conversion-in-cplusplus.html>`_
|
||||||
stateless alternative to IOStreams:
|
stateless alternative to IOStreams:
|
||||||
|
|
||||||
.. code:: c++
|
.. code:: c++
|
||||||
@@ -112,8 +112,9 @@ stateless alternative to IOStreams:
|
|||||||
Safety
|
Safety
|
||||||
------
|
------
|
||||||
|
|
||||||
The library is fully type safe, automatic memory management prevents buffer overflow,
|
The library is fully type safe, automatic memory management prevents buffer
|
||||||
errors in format strings are reported using exceptions. For example, the code
|
overflow, errors in format strings are reported using exceptions. For example,
|
||||||
|
the code
|
||||||
|
|
||||||
.. code:: c++
|
.. 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');
|
fmt::format(L"Cyrillic letter {}", L'\x42e');
|
||||||
|
|
||||||
For comparison, writing a wide character to ``std::ostream`` results in
|
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
|
its numeric value being written to the stream (i.e. 1070 instead of letter 'ю'
|
||||||
is represented by ``L'\x42e'`` if we use Unicode) which is rarely what is needed.
|
which is represented by ``L'\x42e'`` if we use Unicode) which is rarely what is
|
||||||
|
needed.
|
||||||
|
|
||||||
.. _portability:
|
.. _portability:
|
||||||
|
|
||||||
Portability
|
Portability
|
||||||
-----------
|
-----------
|
||||||
|
|
||||||
The library is highly portable. Here is an incomplete list of operating systems and
|
The library is highly portable. Here is an incomplete list of operating systems
|
||||||
compilers where it has been tested and known to work:
|
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>`_,
|
* 64-bit (amd64) GNU/Linux with GCC 4.4.3,
|
||||||
4.7.2, 4.8.1 and Intel C++ Compiler (ICC) 14.0.2
|
`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
|
* 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
|
* 32-bit Windows with Visual C++ 2010
|
||||||
|
|
||||||
Although the library uses C++11 features when available, it also works with older
|
Although the library uses C++11 features when available, it also works with
|
||||||
compilers and standard library implementations. The only thing to keep in mind
|
older compilers and standard library implementations. The only thing to keep in
|
||||||
for C++98 portability:
|
mind for C++98 portability:
|
||||||
|
|
||||||
* Variadic templates: minimum GCC 4.4, Clang 2.9 or VS2013. This feature allows
|
* 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 Format API to accept an unlimited number of arguments. With older
|
||||||
the maximum is 15.
|
compilers the maximum is 15.
|
||||||
|
|
||||||
* User-defined literals: minimum GCC 4.7, Clang 3.1 or VS2015. The suffixes
|
* User-defined literals: minimum GCC 4.7, Clang 3.1 or VS2015. The suffixes
|
||||||
``_format`` and ``_a`` are functionally equivalent to the functions
|
``_format`` and ``_a`` are functionally equivalent to the functions
|
||||||
``fmt::format`` and ``fmt::arg``.
|
``fmt::format`` and ``fmt::arg``.
|
||||||
|
|
||||||
The output of all formatting functions is consistent across platforms. In particular,
|
The output of all formatting functions is consistent across platforms. In
|
||||||
formatting a floating-point infinity always gives ``inf`` while the output
|
particular, formatting a floating-point infinity always gives ``inf`` while the
|
||||||
of ``printf`` is platform-dependent in this case. For example,
|
output of ``printf`` is platform-dependent in this case. For example,
|
||||||
|
|
||||||
.. code::
|
.. code::
|
||||||
|
|
||||||
@@ -188,10 +191,10 @@ always prints ``inf``.
|
|||||||
Ease of Use
|
Ease of Use
|
||||||
-----------
|
-----------
|
||||||
|
|
||||||
fmt has a small self-contained code base consisting of a single header file
|
fmt has a small self-contained code base with the core library consisting of
|
||||||
and a single source file and no external dependencies. A permissive BSD `license
|
a single header file and a single source file and no external dependencies.
|
||||||
<https://github.com/fmtlib/fmt#license>`_ allows using the library both
|
A permissive BSD `license <https://github.com/fmtlib/fmt#license>`_ allows
|
||||||
in open-source and commercial projects.
|
using the library both in open-source and commercial projects.
|
||||||
|
|
||||||
.. raw:: html
|
.. raw:: html
|
||||||
|
|
||||||
|
|||||||
@@ -49,12 +49,10 @@ mini-language" or interpretation of the *format_spec*.
|
|||||||
Most built-in types support a common formatting mini-language, which is
|
Most built-in types support a common formatting mini-language, which is
|
||||||
described in the next section.
|
described in the next section.
|
||||||
|
|
||||||
A *format_spec* field can also include nested replacement fields within it.
|
A *format_spec* field can also include nested replacement fields in certain
|
||||||
These nested replacement fields can contain only an argument index;
|
positions within it. These nested replacement fields can contain only an
|
||||||
format specifications are not allowed. Formatting is performed as if the
|
argument id; format specifications are not allowed. This allows the
|
||||||
replacement fields within the format_spec are substituted before the
|
formatting of a value to be dynamically specified.
|
||||||
*format_spec* string is interpreted. This allows the formatting of a value
|
|
||||||
to be dynamically specified.
|
|
||||||
|
|
||||||
See the :ref:`formatexamples` section for some examples.
|
See the :ref:`formatexamples` section for some examples.
|
||||||
|
|
||||||
@@ -80,8 +78,8 @@ The general form of a *standard format specifier* is:
|
|||||||
sign: "+" | "-" | " "
|
sign: "+" | "-" | " "
|
||||||
width: `integer` | "{" `arg_id` "}"
|
width: `integer` | "{" `arg_id` "}"
|
||||||
precision: `integer` | "{" `arg_id` "}"
|
precision: `integer` | "{" `arg_id` "}"
|
||||||
type: `int_type` | "c" | "e" | "E" | "f" | "F" | "g" | "G" | "p" | "s"
|
type: `int_type` | "a" | "A" | "c" | "e" | "E" | "f" | "F" | "g" | "G" | "p" | "s"
|
||||||
int_type: "b" | "B" | "d" | "o" | "x" | "X"
|
int_type: "b" | "B" | "d" | "n" | "o" | "x" | "X"
|
||||||
|
|
||||||
The *fill* character can be any character other than '{' or '}'. The presence
|
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
|
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 |
|
| ``'a'`` | Hexadecimal floating point format. Prints the number in |
|
||||||
| | base 16 with prefix ``"0x"`` and lower-case letters for |
|
| | 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 |
|
| ``'A'`` | Same as ``'a'`` except it uses upper-case letters for |
|
||||||
| | the prefix, digits above 9 and to indicate the exponent. |
|
| | the prefix, digits above 9 and to indicate the exponent. |
|
||||||
|
|||||||
@@ -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
|
__ 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
|
Building the documentation
|
||||||
==========================
|
==========================
|
||||||
|
|
||||||
@@ -62,7 +79,11 @@ system:
|
|||||||
|
|
||||||
* `Python <https://www.python.org/>`_ with pip and virtualenv
|
* `Python <https://www.python.org/>`_ with pip and virtualenv
|
||||||
* `Doxygen <http://www.stack.nl/~dimitri/doxygen/>`_
|
* `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
|
First generate makefiles or project files using CMake as described in
|
||||||
the previous section. Then compile the ``doc`` target/project, for example::
|
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/>`_::
|
fmt can be installed on OS X using `Homebrew <http://brew.sh/>`_::
|
||||||
|
|
||||||
brew install cppformat
|
brew install fmt
|
||||||
|
|||||||
@@ -1,26 +1,52 @@
|
|||||||
# Define the fmt library, its includes and the needed defines.
|
# Define the fmt library, its includes and the needed defines.
|
||||||
# format.cc is added to FMT_HEADERS for the header-only configuration.
|
# *.cc are added to FMT_HEADERS for the header-only configuration.
|
||||||
set(FMT_HEADERS format.h format.cc ostream.h ostream.cc time.h)
|
set(FMT_HEADERS container.h format.h format.cc ostream.h ostream.cc printf.h
|
||||||
|
printf.cc string.h time.h)
|
||||||
if (HAVE_OPEN)
|
if (HAVE_OPEN)
|
||||||
set(FMT_HEADERS ${FMT_HEADERS} posix.h)
|
set(FMT_HEADERS ${FMT_HEADERS} posix.h)
|
||||||
set(FMT_SOURCES ${FMT_SOURCES} posix.cc)
|
set(FMT_SOURCES ${FMT_SOURCES} posix.cc)
|
||||||
endif ()
|
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)
|
# Starting with cmake 3.1 the CXX_STANDARD property can be used instead.
|
||||||
if (FMT_CPPFORMAT)
|
# Note: Don't make -std=c++11 public or interface, since it breaks projects
|
||||||
message(WARNING "The cppformat library is deprecated, use fmt instead.")
|
# that use C++14.
|
||||||
add_library(cppformat ${FMT_SOURCES} ${FMT_HEADERS})
|
target_compile_options(fmt PRIVATE ${CPP11_FLAG})
|
||||||
|
if (FMT_PEDANTIC)
|
||||||
|
target_compile_options(fmt PRIVATE ${PEDANTIC_COMPILE_FLAGS})
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
include_directories(fmt INTERFACE
|
target_include_directories(fmt PUBLIC
|
||||||
$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}>
|
$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}>
|
||||||
$<INSTALL_INTERFACE:include>)
|
$<INSTALL_INTERFACE:include>)
|
||||||
|
|
||||||
set_target_properties(fmt PROPERTIES
|
set_target_properties(fmt PROPERTIES
|
||||||
VERSION ${FMT_VERSION} SOVERSION ${CPACK_PACKAGE_VERSION_MAJOR})
|
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.
|
# Install targets.
|
||||||
if (FMT_INSTALL)
|
if (FMT_INSTALL)
|
||||||
include(CMakePackageConfigHelpers)
|
include(CMakePackageConfigHelpers)
|
||||||
@@ -47,18 +73,18 @@ if (FMT_INSTALL)
|
|||||||
${PROJECT_SOURCE_DIR}/support/cmake/fmt-config.cmake.in
|
${PROJECT_SOURCE_DIR}/support/cmake/fmt-config.cmake.in
|
||||||
${project_config}
|
${project_config}
|
||||||
INSTALL_DESTINATION ${FMT_CMAKE_DIR})
|
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 version, config and target files.
|
||||||
install(
|
install(
|
||||||
FILES ${project_config} ${version_config}
|
FILES ${project_config} ${version_config}
|
||||||
DESTINATION ${FMT_CMAKE_DIR})
|
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 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)
|
install(FILES ${FMT_HEADERS} DESTINATION include/fmt)
|
||||||
if (FMT_CPPFORMAT)
|
|
||||||
install(TARGETS cppformat DESTINATION ${FMT_LIB_DIR})
|
|
||||||
endif ()
|
|
||||||
endif ()
|
endif ()
|
||||||
|
|||||||
@@ -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
@@ -41,6 +41,9 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if FMT_USE_WINDOWS_H
|
#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)
|
# if defined(NOMINMAX) || defined(FMT_WIN_MINMAX)
|
||||||
# include <windows.h>
|
# include <windows.h>
|
||||||
# else
|
# else
|
||||||
@@ -50,8 +53,6 @@
|
|||||||
# endif
|
# endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
using fmt::internal::Arg;
|
|
||||||
|
|
||||||
#if FMT_EXCEPTIONS
|
#if FMT_EXCEPTIONS
|
||||||
# define FMT_TRY try
|
# define FMT_TRY try
|
||||||
# define FMT_CATCH(x) catch (x)
|
# define FMT_CATCH(x) catch (x)
|
||||||
@@ -79,6 +80,11 @@ static inline fmt::internal::Null<> strerror_s(char *, std::size_t, ...) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
namespace fmt {
|
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 {
|
namespace {
|
||||||
|
|
||||||
#ifndef _MSC_VER
|
#ifndef _MSC_VER
|
||||||
@@ -100,27 +106,6 @@ inline int fmt_snprintf(char *buffer, size_t size, const char *format, ...) {
|
|||||||
# define FMT_SWPRINTF swprintf
|
# define FMT_SWPRINTF swprintf
|
||||||
#endif // defined(_WIN32) && defined(__MINGW32__) && !defined(__NO_ISOCEXT)
|
#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";
|
const char RESET_COLOR[] = "\x1b[0m";
|
||||||
|
|
||||||
typedef void (*FormatFunc)(Writer &, int, StringRef);
|
typedef void (*FormatFunc)(Writer &, int, StringRef);
|
||||||
@@ -186,7 +171,8 @@ int safe_strerror(
|
|||||||
: error_code_(err_code), buffer_(buf), buffer_size_(buf_size) {}
|
: error_code_(err_code), buffer_(buf), buffer_size_(buf_size) {}
|
||||||
|
|
||||||
int run() {
|
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_));
|
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::fwrite(full_message.data(), full_message.size(), 1, stderr);
|
||||||
std::fputc('\n', 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
|
||||||
|
|
||||||
namespace internal {
|
FMT_FUNC void SystemError::init(
|
||||||
|
|
||||||
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(
|
|
||||||
int err_code, CStringRef format_str, ArgList args) {
|
int err_code, CStringRef format_str, ArgList args) {
|
||||||
error_code_ = err_code;
|
error_code_ = err_code;
|
||||||
MemoryWriter w;
|
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;
|
std::runtime_error &base = *this;
|
||||||
base = std::runtime_error(w.str());
|
base = std::runtime_error(w.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
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,
|
char *buffer, std::size_t size, const char *format,
|
||||||
unsigned width, int precision, T value) {
|
unsigned width, int precision, T value) {
|
||||||
if (width == 0) {
|
if (width == 0) {
|
||||||
@@ -454,7 +237,7 @@ int fmt::internal::CharTraits<char>::format_float(
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
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,
|
wchar_t *buffer, std::size_t size, const wchar_t *format,
|
||||||
unsigned width, int precision, T value) {
|
unsigned width, int precision, T value) {
|
||||||
if (width == 0) {
|
if (width == 0) {
|
||||||
@@ -468,7 +251,7 @@ int fmt::internal::CharTraits<wchar_t>::format_float(
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
const char fmt::internal::BasicData<T>::DIGITS[] =
|
const char internal::BasicData<T>::DIGITS[] =
|
||||||
"0001020304050607080910111213141516171819"
|
"0001020304050607080910111213141516171819"
|
||||||
"2021222324252627282930313233343536373839"
|
"2021222324252627282930313233343536373839"
|
||||||
"4041424344454647484950515253545556575859"
|
"4041424344454647484950515253545556575859"
|
||||||
@@ -487,40 +270,40 @@ const char fmt::internal::BasicData<T>::DIGITS[] =
|
|||||||
factor * 1000000000
|
factor * 1000000000
|
||||||
|
|
||||||
template <typename T>
|
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)
|
0, FMT_POWERS_OF_10(1)
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T>
|
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,
|
0,
|
||||||
FMT_POWERS_OF_10(1),
|
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
|
// Multiply several constants instead of using a single long long constant
|
||||||
// to avoid warnings about C++98 not supporting long long.
|
// 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;
|
(void)type;
|
||||||
if (std::isprint(static_cast<unsigned char>(code))) {
|
if (std::isprint(static_cast<unsigned char>(code))) {
|
||||||
FMT_THROW(fmt::FormatError(
|
FMT_THROW(FormatError(
|
||||||
fmt::format("unknown format code '{}' for {}", code, type)));
|
format("unknown format code '{}' for {}", code, type)));
|
||||||
}
|
}
|
||||||
FMT_THROW(fmt::FormatError(
|
FMT_THROW(FormatError(
|
||||||
fmt::format("unknown format code '\\x{:02x}' for {}",
|
format("unknown format code '\\x{:02x}' for {}",
|
||||||
static_cast<unsigned>(code), type)));
|
static_cast<unsigned>(code), type)));
|
||||||
}
|
}
|
||||||
|
|
||||||
#if FMT_USE_WINDOWS_H
|
#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";
|
static const char ERROR_MSG[] = "cannot convert string from UTF-8 to UTF-16";
|
||||||
if (s.size() > INT_MAX)
|
if (s.size() > INT_MAX)
|
||||||
FMT_THROW(WindowsError(ERROR_INVALID_PARAMETER, ERROR_MSG));
|
FMT_THROW(WindowsError(ERROR_INVALID_PARAMETER, ERROR_MSG));
|
||||||
int s_size = static_cast<int>(s.size());
|
int s_size = static_cast<int>(s.size());
|
||||||
int length = MultiByteToWideChar(
|
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)
|
if (length == 0)
|
||||||
FMT_THROW(WindowsError(GetLastError(), ERROR_MSG));
|
FMT_THROW(WindowsError(GetLastError(), ERROR_MSG));
|
||||||
buffer_.resize(length + 1);
|
buffer_.resize(length + 1);
|
||||||
@@ -531,30 +314,31 @@ FMT_FUNC fmt::internal::UTF8ToUTF16::UTF8ToUTF16(fmt::StringRef s) {
|
|||||||
buffer_[length] = 0;
|
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)) {
|
if (int error_code = convert(s)) {
|
||||||
FMT_THROW(WindowsError(error_code,
|
FMT_THROW(WindowsError(error_code,
|
||||||
"cannot convert string from UTF-16 to UTF-8"));
|
"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)
|
if (s.size() > INT_MAX)
|
||||||
return ERROR_INVALID_PARAMETER;
|
return ERROR_INVALID_PARAMETER;
|
||||||
int s_size = static_cast<int>(s.size());
|
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)
|
if (length == 0)
|
||||||
return GetLastError();
|
return GetLastError();
|
||||||
buffer_.resize(length + 1);
|
buffer_.resize(length + 1);
|
||||||
length = WideCharToMultiByte(
|
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)
|
if (length == 0)
|
||||||
return GetLastError();
|
return GetLastError();
|
||||||
buffer_[length] = 0;
|
buffer_[length] = 0;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
FMT_FUNC void fmt::WindowsError::init(
|
FMT_FUNC void WindowsError::init(
|
||||||
int err_code, CStringRef format_str, ArgList args) {
|
int err_code, CStringRef format_str, ArgList args) {
|
||||||
error_code_ = err_code;
|
error_code_ = err_code;
|
||||||
MemoryWriter w;
|
MemoryWriter w;
|
||||||
@@ -563,17 +347,17 @@ FMT_FUNC void fmt::WindowsError::init(
|
|||||||
base = std::runtime_error(w.str());
|
base = std::runtime_error(w.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
FMT_FUNC void fmt::internal::format_windows_error(
|
FMT_FUNC void internal::format_windows_error(
|
||||||
fmt::Writer &out, int error_code,
|
Writer &out, int error_code, StringRef message) FMT_NOEXCEPT {
|
||||||
fmt::StringRef message) FMT_NOEXCEPT {
|
|
||||||
FMT_TRY {
|
FMT_TRY {
|
||||||
MemoryBuffer<wchar_t, INLINE_BUFFER_SIZE> buffer;
|
MemoryBuffer<wchar_t, INLINE_BUFFER_SIZE> buffer;
|
||||||
buffer.resize(INLINE_BUFFER_SIZE);
|
buffer.resize(INLINE_BUFFER_SIZE);
|
||||||
for (;;) {
|
for (;;) {
|
||||||
wchar_t *system_message = &buffer[0];
|
wchar_t *system_message = &buffer[0];
|
||||||
int result = FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
|
int result = FormatMessageW(
|
||||||
0, error_code, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
|
FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
|
||||||
system_message, static_cast<uint32_t>(buffer.size()), 0);
|
FMT_NULL, error_code, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
|
||||||
|
system_message, static_cast<uint32_t>(buffer.size()), FMT_NULL);
|
||||||
if (result != 0) {
|
if (result != 0) {
|
||||||
UTF16ToUTF8 utf8_message;
|
UTF16ToUTF8 utf8_message;
|
||||||
if (utf8_message.convert(system_message) == ERROR_SUCCESS) {
|
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
|
#endif // FMT_USE_WINDOWS_H
|
||||||
|
|
||||||
FMT_FUNC void fmt::internal::format_system_error(
|
FMT_FUNC void format_system_error(
|
||||||
fmt::Writer &out, int error_code,
|
Writer &out, int error_code, StringRef message) FMT_NOEXCEPT {
|
||||||
fmt::StringRef message) FMT_NOEXCEPT {
|
|
||||||
FMT_TRY {
|
FMT_TRY {
|
||||||
MemoryBuffer<char, INLINE_BUFFER_SIZE> buffer;
|
internal::MemoryBuffer<char, internal::INLINE_BUFFER_SIZE> buffer;
|
||||||
buffer.resize(INLINE_BUFFER_SIZE);
|
buffer.resize(internal::INLINE_BUFFER_SIZE);
|
||||||
for (;;) {
|
for (;;) {
|
||||||
char *system_message = &buffer[0];
|
char *system_message = &buffer[0];
|
||||||
int result = safe_strerror(error_code, system_message, buffer.size());
|
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>
|
template <typename Char>
|
||||||
void fmt::internal::ArgMap<Char>::init(const ArgList &args) {
|
void internal::ArgMap<Char>::init(const ArgList &args) {
|
||||||
if (!map_.empty())
|
if (!map_.empty())
|
||||||
return;
|
return;
|
||||||
typedef internal::NamedArg<Char> NamedArg;
|
typedef internal::NamedArg<Char> NamedArg;
|
||||||
const NamedArg *named_arg = 0;
|
const NamedArg *named_arg = FMT_NULL;
|
||||||
bool use_values =
|
bool use_values =
|
||||||
args.type(ArgList::MAX_PACKED_ARGS - 1) == internal::Arg::NONE;
|
args.type(ArgList::MAX_PACKED_ARGS - 1) == internal::Arg::NONE;
|
||||||
if (use_values) {
|
if (use_values) {
|
||||||
@@ -659,18 +442,18 @@ void fmt::internal::ArgMap<Char>::init(const ArgList &args) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <typename Char>
|
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_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) {
|
unsigned arg_index, const char *&error) {
|
||||||
Arg arg = args_[arg_index];
|
internal::Arg arg = args_[arg_index];
|
||||||
switch (arg.type) {
|
switch (arg.type) {
|
||||||
case Arg::NONE:
|
case internal::Arg::NONE:
|
||||||
error = "argument index out of range";
|
error = "argument index out of range";
|
||||||
break;
|
break;
|
||||||
case Arg::NAMED_ARG:
|
case internal::Arg::NAMED_ARG:
|
||||||
arg = *static_cast<const internal::Arg*>(arg.pointer);
|
arg = *static_cast<const internal::Arg*>(arg.pointer);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@@ -679,203 +462,31 @@ FMT_FUNC Arg fmt::internal::FormatterBase::do_get_arg(
|
|||||||
return arg;
|
return arg;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Char>
|
FMT_FUNC void report_system_error(
|
||||||
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(
|
|
||||||
int error_code, fmt::StringRef message) FMT_NOEXCEPT {
|
int error_code, fmt::StringRef message) FMT_NOEXCEPT {
|
||||||
// 'fmt::' is for bcc32.
|
// '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
|
#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 {
|
int error_code, fmt::StringRef message) FMT_NOEXCEPT {
|
||||||
// 'fmt::' is for bcc32.
|
// 'fmt::' is for bcc32.
|
||||||
fmt::report_error(internal::format_windows_error, error_code, message);
|
report_error(internal::format_windows_error, error_code, message);
|
||||||
}
|
}
|
||||||
#endif
|
#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;
|
MemoryWriter w;
|
||||||
w.write(format_str, args);
|
w.write(format_str, args);
|
||||||
std::fwrite(w.data(), 1, w.size(), f);
|
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);
|
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";
|
char escape[] = "\x1b[30m";
|
||||||
escape[3] = static_cast<char>('0' + c);
|
escape[3] = static_cast<char>('0' + c);
|
||||||
std::fputs(escape, stdout);
|
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);
|
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
|
#ifndef FMT_HEADER_ONLY
|
||||||
|
|
||||||
template struct fmt::internal::BasicData<void>;
|
template struct internal::BasicData<void>;
|
||||||
|
|
||||||
// Explicit instantiations for char.
|
// 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(
|
template FMT_API int internal::CharTraits<char>::format_float(
|
||||||
BasicWriter<char> &writer, CStringRef format);
|
|
||||||
|
|
||||||
template int fmt::internal::CharTraits<char>::format_float(
|
|
||||||
char *buffer, std::size_t size, const char *format,
|
char *buffer, std::size_t size, const char *format,
|
||||||
unsigned width, int precision, double value);
|
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,
|
char *buffer, std::size_t size, const char *format,
|
||||||
unsigned width, int precision, long double value);
|
unsigned width, int precision, long double value);
|
||||||
|
|
||||||
// Explicit instantiations for wchar_t.
|
// 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(
|
template FMT_API int internal::CharTraits<wchar_t>::format_float(
|
||||||
BasicWriter<wchar_t> &writer, WCStringRef format);
|
|
||||||
|
|
||||||
template int fmt::internal::CharTraits<wchar_t>::format_float(
|
|
||||||
wchar_t *buffer, std::size_t size, const wchar_t *format,
|
wchar_t *buffer, std::size_t size, const wchar_t *format,
|
||||||
unsigned width, int precision, double value);
|
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,
|
wchar_t *buffer, std::size_t size, const wchar_t *format,
|
||||||
unsigned width, int precision, long double value);
|
unsigned width, int precision, long double value);
|
||||||
|
|
||||||
#endif // FMT_HEADER_ONLY
|
#endif // FMT_HEADER_ONLY
|
||||||
|
|
||||||
|
} // namespace fmt
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
# pragma warning(pop)
|
# pragma warning(pop)
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
+404
-224
File diff suppressed because it is too large
Load Diff
@@ -4,34 +4,15 @@
|
|||||||
Copyright (c) 2012 - 2016, Victor Zverovich
|
Copyright (c) 2012 - 2016, Victor Zverovich
|
||||||
All rights reserved.
|
All rights reserved.
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
For the license information refer to format.h.
|
||||||
modification, are permitted provided that the following conditions are met:
|
|
||||||
|
|
||||||
1. Redistributions of source code must retain the above copyright notice, this
|
|
||||||
list of conditions and the following disclaimer.
|
|
||||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
|
||||||
this list of conditions and the following disclaimer in the documentation
|
|
||||||
and/or other materials provided with the distribution.
|
|
||||||
|
|
||||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
||||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
||||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
||||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
|
||||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
||||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
||||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
|
||||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
||||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "ostream.h"
|
#include "ostream.h"
|
||||||
|
|
||||||
namespace fmt {
|
namespace fmt {
|
||||||
|
|
||||||
namespace {
|
namespace internal {
|
||||||
// Write the content of w to os.
|
FMT_FUNC void write(std::ostream &os, Writer &w) {
|
||||||
void write(std::ostream &os, Writer &w) {
|
|
||||||
const char *data = w.data();
|
const char *data = w.data();
|
||||||
typedef internal::MakeUnsigned<std::streamsize>::Type UnsignedStreamSize;
|
typedef internal::MakeUnsigned<std::streamsize>::Type UnsignedStreamSize;
|
||||||
UnsignedStreamSize size = w.size();
|
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) {
|
FMT_FUNC void print(std::ostream &os, CStringRef format_str, ArgList args) {
|
||||||
MemoryWriter w;
|
MemoryWriter w;
|
||||||
w.write(format_str, args);
|
w.write(format_str, args);
|
||||||
write(os, w);
|
internal::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());
|
|
||||||
}
|
}
|
||||||
} // namespace fmt
|
} // namespace fmt
|
||||||
|
|||||||
+22
-50
@@ -4,25 +4,7 @@
|
|||||||
Copyright (c) 2012 - 2016, Victor Zverovich
|
Copyright (c) 2012 - 2016, Victor Zverovich
|
||||||
All rights reserved.
|
All rights reserved.
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
For the license information refer to format.h.
|
||||||
modification, are permitted provided that the following conditions are met:
|
|
||||||
|
|
||||||
1. Redistributions of source code must retain the above copyright notice, this
|
|
||||||
list of conditions and the following disclaimer.
|
|
||||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
|
||||||
this list of conditions and the following disclaimer in the documentation
|
|
||||||
and/or other materials provided with the distribution.
|
|
||||||
|
|
||||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
||||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
||||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
||||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
|
||||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
||||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
||||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
|
||||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
||||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef FMT_OSTREAM_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;
|
typedef typename std::basic_streambuf<Char>::traits_type traits_type;
|
||||||
|
|
||||||
Buffer<Char> &buffer_;
|
Buffer<Char> &buffer_;
|
||||||
Char *start_;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
FormatBuf(Buffer<Char> &buffer) : buffer_(buffer), start_(&buffer[0]) {
|
FormatBuf(Buffer<Char> &buffer) : buffer_(buffer) {}
|
||||||
this->setp(start_, start_ + buffer_.capacity());
|
|
||||||
}
|
|
||||||
|
|
||||||
int_type overflow(int_type ch = traits_type::eof()) {
|
protected:
|
||||||
if (!traits_type::eq_int_type(ch, traits_type::eof())) {
|
// The put-area is actually always empty. This makes the implementation
|
||||||
size_t buf_size = size();
|
// simpler and has the advantage that the streambuf and the buffer are always
|
||||||
buffer_.resize(buf_size);
|
// in sync and sputc never writes into uninitialized memory. The obvious
|
||||||
buffer_.reserve(buf_size * 2);
|
// 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];
|
int_type overflow(int_type ch = traits_type::eof()) FMT_OVERRIDE {
|
||||||
start_[buf_size] = traits_type::to_char_type(ch);
|
if (!traits_type::eq_int_type(ch, traits_type::eof()))
|
||||||
this->setp(start_+ buf_size + 1, start_ + buf_size * 2);
|
buffer_.push_back(static_cast<Char>(ch));
|
||||||
}
|
|
||||||
return ch;
|
return ch;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t size() const {
|
std::streamsize xsputn(const Char *s, std::streamsize count) FMT_OVERRIDE {
|
||||||
return to_unsigned(this->pptr() - start_);
|
buffer_.append(s, s + count);
|
||||||
|
return count;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -84,19 +65,22 @@ struct ConvertToIntImpl<T, true> {
|
|||||||
value = sizeof(convert(get<DummyStream>() << get<T>())) == sizeof(No)
|
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
|
} // namespace internal
|
||||||
|
|
||||||
// Formats a value.
|
// Formats a value.
|
||||||
template <typename Char, typename ArgFormatter, typename T>
|
template <typename Char, typename ArgFormatter_, typename T>
|
||||||
void format(BasicFormatter<Char, ArgFormatter> &f,
|
void format_arg(BasicFormatter<Char, ArgFormatter_> &f,
|
||||||
const Char *&format_str, const T &value) {
|
const Char *&format_str, const T &value) {
|
||||||
internal::MemoryBuffer<Char, internal::INLINE_BUFFER_SIZE> buffer;
|
internal::MemoryBuffer<Char, internal::INLINE_BUFFER_SIZE> buffer;
|
||||||
|
|
||||||
internal::FormatBuf<Char> format_buf(buffer);
|
internal::FormatBuf<Char> format_buf(buffer);
|
||||||
std::basic_ostream<Char> output(&format_buf);
|
std::basic_ostream<Char> output(&format_buf);
|
||||||
output << value;
|
output << value;
|
||||||
|
|
||||||
BasicStringRef<Char> str(&buffer[0], format_buf.size());
|
BasicStringRef<Char> str(&buffer[0], buffer.size());
|
||||||
typedef internal::MakeArg< BasicFormatter<Char> > MakeArg;
|
typedef internal::MakeArg< BasicFormatter<Char> > MakeArg;
|
||||||
format_str = f.format(format_str, MakeArg(str));
|
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_API void print(std::ostream &os, CStringRef format_str, ArgList args);
|
||||||
FMT_VARIADIC(void, print, std::ostream &, CStringRef)
|
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
|
} // namespace fmt
|
||||||
|
|
||||||
#ifdef FMT_HEADER_ONLY
|
#ifdef FMT_HEADER_ONLY
|
||||||
|
|||||||
+21
-36
@@ -1,28 +1,10 @@
|
|||||||
/*
|
/*
|
||||||
A C++ interface to POSIX functions.
|
A C++ interface to POSIX functions.
|
||||||
|
|
||||||
Copyright (c) 2014 - 2016, Victor Zverovich
|
Copyright (c) 2012 - 2016, Victor Zverovich
|
||||||
All rights reserved.
|
All rights reserved.
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
For the license information refer to format.h.
|
||||||
modification, are permitted provided that the following conditions are met:
|
|
||||||
|
|
||||||
1. Redistributions of source code must retain the above copyright notice, this
|
|
||||||
list of conditions and the following disclaimer.
|
|
||||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
|
||||||
this list of conditions and the following disclaimer in the documentation
|
|
||||||
and/or other materials provided with the distribution.
|
|
||||||
|
|
||||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
||||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
||||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
||||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
|
||||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
||||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
||||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
|
||||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
||||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// Disable bogus MSVC warnings.
|
// Disable bogus MSVC warnings.
|
||||||
@@ -39,6 +21,9 @@
|
|||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
# include <unistd.h>
|
# include <unistd.h>
|
||||||
#else
|
#else
|
||||||
|
# ifndef WIN32_LEAN_AND_MEAN
|
||||||
|
# define WIN32_LEAN_AND_MEAN
|
||||||
|
# endif
|
||||||
# include <windows.h>
|
# include <windows.h>
|
||||||
# include <io.h>
|
# include <io.h>
|
||||||
|
|
||||||
@@ -90,16 +75,16 @@ fmt::BufferedFile::BufferedFile(
|
|||||||
fmt::CStringRef filename, fmt::CStringRef mode) {
|
fmt::CStringRef filename, fmt::CStringRef mode) {
|
||||||
FMT_RETRY_VAL(file_, FMT_SYSTEM(fopen(filename.c_str(), mode.c_str())), 0);
|
FMT_RETRY_VAL(file_, FMT_SYSTEM(fopen(filename.c_str(), mode.c_str())), 0);
|
||||||
if (!file_)
|
if (!file_)
|
||||||
throw SystemError(errno, "cannot open file {}", filename);
|
FMT_THROW(SystemError(errno, "cannot open file {}", filename));
|
||||||
}
|
}
|
||||||
|
|
||||||
void fmt::BufferedFile::close() {
|
void fmt::BufferedFile::close() {
|
||||||
if (!file_)
|
if (!file_)
|
||||||
return;
|
return;
|
||||||
int result = FMT_SYSTEM(fclose(file_));
|
int result = FMT_SYSTEM(fclose(file_));
|
||||||
file_ = 0;
|
file_ = FMT_NULL;
|
||||||
if (result != 0)
|
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.
|
// 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 fmt::BufferedFile::fileno() const {
|
||||||
int fd = FMT_POSIX_CALL(fileno FMT_ARGS(file_));
|
int fd = FMT_POSIX_CALL(fileno FMT_ARGS(file_));
|
||||||
if (fd == -1)
|
if (fd == -1)
|
||||||
throw SystemError(errno, "cannot get file descriptor");
|
FMT_THROW(SystemError(errno, "cannot get file descriptor"));
|
||||||
return fd;
|
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)));
|
FMT_RETRY(fd_, FMT_POSIX_CALL(open(path.c_str(), oflag, mode)));
|
||||||
#endif
|
#endif
|
||||||
if (fd_ == -1)
|
if (fd_ == -1)
|
||||||
throw SystemError(errno, "cannot open file {}", path);
|
FMT_THROW(SystemError(errno, "cannot open file {}", path));
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt::File::~File() FMT_NOEXCEPT {
|
fmt::File::~File() FMT_NOEXCEPT {
|
||||||
@@ -139,7 +124,7 @@ void fmt::File::close() {
|
|||||||
int result = FMT_POSIX_CALL(close(fd_));
|
int result = FMT_POSIX_CALL(close(fd_));
|
||||||
fd_ = -1;
|
fd_ = -1;
|
||||||
if (result != 0)
|
if (result != 0)
|
||||||
throw SystemError(errno, "cannot close file");
|
FMT_THROW(SystemError(errno, "cannot close file"));
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt::LongLong fmt::File::size() const {
|
fmt::LongLong fmt::File::size() const {
|
||||||
@@ -153,7 +138,7 @@ fmt::LongLong fmt::File::size() const {
|
|||||||
if (size_lower == INVALID_FILE_SIZE) {
|
if (size_lower == INVALID_FILE_SIZE) {
|
||||||
DWORD error = GetLastError();
|
DWORD error = GetLastError();
|
||||||
if (error != NO_ERROR)
|
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;
|
fmt::ULongLong long_size = size_upper;
|
||||||
return (long_size << sizeof(DWORD) * CHAR_BIT) | size_lower;
|
return (long_size << sizeof(DWORD) * CHAR_BIT) | size_lower;
|
||||||
@@ -161,7 +146,7 @@ fmt::LongLong fmt::File::size() const {
|
|||||||
typedef struct stat Stat;
|
typedef struct stat Stat;
|
||||||
Stat file_stat = Stat();
|
Stat file_stat = Stat();
|
||||||
if (FMT_POSIX_CALL(fstat(fd_, &file_stat)) == -1)
|
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),
|
FMT_STATIC_ASSERT(sizeof(fmt::LongLong) >= sizeof(file_stat.st_size),
|
||||||
"return type of File::size is not large enough");
|
"return type of File::size is not large enough");
|
||||||
return file_stat.st_size;
|
return file_stat.st_size;
|
||||||
@@ -172,7 +157,7 @@ std::size_t fmt::File::read(void *buffer, std::size_t count) {
|
|||||||
RWResult result = 0;
|
RWResult result = 0;
|
||||||
FMT_RETRY(result, FMT_POSIX_CALL(read(fd_, buffer, convert_rwcount(count))));
|
FMT_RETRY(result, FMT_POSIX_CALL(read(fd_, buffer, convert_rwcount(count))));
|
||||||
if (result < 0)
|
if (result < 0)
|
||||||
throw SystemError(errno, "cannot read from file");
|
FMT_THROW(SystemError(errno, "cannot read from file"));
|
||||||
return internal::to_unsigned(result);
|
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;
|
RWResult result = 0;
|
||||||
FMT_RETRY(result, FMT_POSIX_CALL(write(fd_, buffer, convert_rwcount(count))));
|
FMT_RETRY(result, FMT_POSIX_CALL(write(fd_, buffer, convert_rwcount(count))));
|
||||||
if (result < 0)
|
if (result < 0)
|
||||||
throw SystemError(errno, "cannot write to file");
|
FMT_THROW(SystemError(errno, "cannot write to file"));
|
||||||
return internal::to_unsigned(result);
|
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
|
// http://pubs.opengroup.org/onlinepubs/009695399/functions/dup.html
|
||||||
int new_fd = FMT_POSIX_CALL(dup(fd));
|
int new_fd = FMT_POSIX_CALL(dup(fd));
|
||||||
if (new_fd == -1)
|
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);
|
return File(new_fd);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -197,8 +182,8 @@ void fmt::File::dup2(int fd) {
|
|||||||
int result = 0;
|
int result = 0;
|
||||||
FMT_RETRY(result, FMT_POSIX_CALL(dup2(fd_, fd)));
|
FMT_RETRY(result, FMT_POSIX_CALL(dup2(fd_, fd)));
|
||||||
if (result == -1) {
|
if (result == -1) {
|
||||||
throw SystemError(errno,
|
FMT_THROW(SystemError(errno,
|
||||||
"cannot duplicate file descriptor {} to {}", fd_, fd);
|
"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));
|
int result = FMT_POSIX_CALL(pipe(fds));
|
||||||
#endif
|
#endif
|
||||||
if (result != 0)
|
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
|
// The following assignments don't throw because read_fd and write_fd
|
||||||
// are closed.
|
// are closed.
|
||||||
read_end = File(fds[0]);
|
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.
|
// Don't retry as fdopen doesn't return EINTR.
|
||||||
FILE *f = FMT_POSIX_CALL(fdopen(fd_, mode));
|
FILE *f = FMT_POSIX_CALL(fdopen(fd_, mode));
|
||||||
if (!f)
|
if (!f)
|
||||||
throw SystemError(errno, "cannot associate stream with file descriptor");
|
FMT_THROW(SystemError(errno, "cannot associate stream with file descriptor"));
|
||||||
BufferedFile file(f);
|
BufferedFile file(f);
|
||||||
fd_ = -1;
|
fd_ = -1;
|
||||||
return file;
|
return file;
|
||||||
@@ -250,7 +235,7 @@ long fmt::getpagesize() {
|
|||||||
#else
|
#else
|
||||||
long size = FMT_POSIX_CALL(sysconf(_SC_PAGESIZE));
|
long size = FMT_POSIX_CALL(sysconf(_SC_PAGESIZE));
|
||||||
if (size < 0)
|
if (size < 0)
|
||||||
throw SystemError(errno, "cannot get memory page size");
|
FMT_THROW(SystemError(errno, "cannot get memory page size"));
|
||||||
return size;
|
return size;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|||||||
+30
-66
@@ -1,34 +1,16 @@
|
|||||||
/*
|
/*
|
||||||
A C++ interface to POSIX functions.
|
A C++ interface to POSIX functions.
|
||||||
|
|
||||||
Copyright (c) 2014 - 2016, Victor Zverovich
|
Copyright (c) 2012 - 2016, Victor Zverovich
|
||||||
All rights reserved.
|
All rights reserved.
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
For the license information refer to format.h.
|
||||||
modification, are permitted provided that the following conditions are met:
|
|
||||||
|
|
||||||
1. Redistributions of source code must retain the above copyright notice, this
|
|
||||||
list of conditions and the following disclaimer.
|
|
||||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
|
||||||
this list of conditions and the following disclaimer in the documentation
|
|
||||||
and/or other materials provided with the distribution.
|
|
||||||
|
|
||||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
||||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
||||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
||||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
|
||||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
||||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
||||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
|
||||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
||||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef FMT_POSIX_H_
|
#ifndef FMT_POSIX_H_
|
||||||
#define FMT_POSIX_H_
|
#define FMT_POSIX_H_
|
||||||
|
|
||||||
#ifdef __MINGW32__
|
#if defined(__MINGW32__) || defined(__CYGWIN__)
|
||||||
// Workaround MinGW bug https://sourceforge.net/p/mingw/bugs/2024/.
|
// Workaround MinGW bug https://sourceforge.net/p/mingw/bugs/2024/.
|
||||||
# undef __STRICT_ANSI__
|
# undef __STRICT_ANSI__
|
||||||
#endif
|
#endif
|
||||||
@@ -41,7 +23,7 @@
|
|||||||
|
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
|
|
||||||
#ifdef __APPLE__
|
#if defined __APPLE__ || defined(__FreeBSD__)
|
||||||
# include <xlocale.h> // for LC_NUMERIC_MASK on OS X
|
# include <xlocale.h> // for LC_NUMERIC_MASK on OS X
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -69,25 +51,6 @@
|
|||||||
# endif
|
# endif
|
||||||
#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
|
// Retries the expression while it evaluates to error_result and errno
|
||||||
// equals to EINTR.
|
// equals to EINTR.
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
@@ -125,10 +88,10 @@ class BufferedFile {
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
// Constructs a BufferedFile object which doesn't represent any file.
|
// 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.
|
// Destroys the object closing the file it represents if any.
|
||||||
~BufferedFile() FMT_NOEXCEPT;
|
FMT_API ~BufferedFile() FMT_NOEXCEPT;
|
||||||
|
|
||||||
#if !FMT_USE_RVALUE_REFERENCES
|
#if !FMT_USE_RVALUE_REFERENCES
|
||||||
// Emulate a move constructor and a move assignment operator if rvalue
|
// Emulate a move constructor and a move assignment operator if rvalue
|
||||||
@@ -147,7 +110,7 @@ public:
|
|||||||
|
|
||||||
// A "move constructor" for moving from an lvalue.
|
// A "move constructor" for moving from an lvalue.
|
||||||
BufferedFile(BufferedFile &f) FMT_NOEXCEPT : file_(f.file_) {
|
BufferedFile(BufferedFile &f) FMT_NOEXCEPT : file_(f.file_) {
|
||||||
f.file_ = 0;
|
f.file_ = FMT_NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
// A "move assignment operator" for moving from a temporary.
|
// A "move assignment operator" for moving from a temporary.
|
||||||
@@ -161,7 +124,7 @@ public:
|
|||||||
BufferedFile &operator=(BufferedFile &other) {
|
BufferedFile &operator=(BufferedFile &other) {
|
||||||
close();
|
close();
|
||||||
file_ = other.file_;
|
file_ = other.file_;
|
||||||
other.file_ = 0;
|
other.file_ = FMT_NULL;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -169,7 +132,7 @@ public:
|
|||||||
// BufferedFile file = BufferedFile(...);
|
// BufferedFile file = BufferedFile(...);
|
||||||
operator Proxy() FMT_NOEXCEPT {
|
operator Proxy() FMT_NOEXCEPT {
|
||||||
Proxy p = {file_};
|
Proxy p = {file_};
|
||||||
file_ = 0;
|
file_ = FMT_NULL;
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -179,29 +142,29 @@ public:
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
BufferedFile(BufferedFile &&other) FMT_NOEXCEPT : file_(other.file_) {
|
BufferedFile(BufferedFile &&other) FMT_NOEXCEPT : file_(other.file_) {
|
||||||
other.file_ = 0;
|
other.file_ = FMT_NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
BufferedFile& operator=(BufferedFile &&other) {
|
BufferedFile& operator=(BufferedFile &&other) {
|
||||||
close();
|
close();
|
||||||
file_ = other.file_;
|
file_ = other.file_;
|
||||||
other.file_ = 0;
|
other.file_ = FMT_NULL;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Opens a file.
|
// Opens a file.
|
||||||
BufferedFile(CStringRef filename, CStringRef mode);
|
FMT_API BufferedFile(CStringRef filename, CStringRef mode);
|
||||||
|
|
||||||
// Closes the file.
|
// Closes the file.
|
||||||
void close();
|
FMT_API void close();
|
||||||
|
|
||||||
// Returns the pointer to a FILE object representing this file.
|
// Returns the pointer to a FILE object representing this file.
|
||||||
FILE *get() const FMT_NOEXCEPT { return file_; }
|
FILE *get() const FMT_NOEXCEPT { return file_; }
|
||||||
|
|
||||||
// We place parentheses around fileno to workaround a bug in some versions
|
// We place parentheses around fileno to workaround a bug in some versions
|
||||||
// of MinGW that define fileno as a macro.
|
// of MinGW that define fileno as a macro.
|
||||||
int (fileno)() const;
|
FMT_API int (fileno)() const;
|
||||||
|
|
||||||
void print(CStringRef format_str, const ArgList &args) {
|
void print(CStringRef format_str, const ArgList &args) {
|
||||||
fmt::print(file_, format_str, args);
|
fmt::print(file_, format_str, args);
|
||||||
@@ -234,7 +197,7 @@ class File {
|
|||||||
File() FMT_NOEXCEPT : fd_(-1) {}
|
File() FMT_NOEXCEPT : fd_(-1) {}
|
||||||
|
|
||||||
// Opens a file and constructs a File object representing this file.
|
// 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
|
#if !FMT_USE_RVALUE_REFERENCES
|
||||||
// Emulate a move constructor and a move assignment operator if rvalue
|
// Emulate a move constructor and a move assignment operator if rvalue
|
||||||
@@ -297,49 +260,50 @@ class File {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Destroys the object closing the file it represents if any.
|
// Destroys the object closing the file it represents if any.
|
||||||
~File() FMT_NOEXCEPT;
|
FMT_API ~File() FMT_NOEXCEPT;
|
||||||
|
|
||||||
// Returns the file descriptor.
|
// Returns the file descriptor.
|
||||||
int descriptor() const FMT_NOEXCEPT { return fd_; }
|
int descriptor() const FMT_NOEXCEPT { return fd_; }
|
||||||
|
|
||||||
// Closes the file.
|
// Closes the file.
|
||||||
void close();
|
FMT_API void close();
|
||||||
|
|
||||||
// Returns the file size. The size has signed type for consistency with
|
// Returns the file size. The size has signed type for consistency with
|
||||||
// stat::st_size.
|
// stat::st_size.
|
||||||
LongLong size() const;
|
FMT_API LongLong size() const;
|
||||||
|
|
||||||
// Attempts to read count bytes from the file into the specified buffer.
|
// 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.
|
// 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
|
// Duplicates a file descriptor with the dup function and returns
|
||||||
// the duplicate as a file object.
|
// 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
|
// Makes fd be the copy of this file descriptor, closing fd first if
|
||||||
// necessary.
|
// necessary.
|
||||||
void dup2(int fd);
|
FMT_API void dup2(int fd);
|
||||||
|
|
||||||
// Makes fd be the copy of this file descriptor, closing fd first if
|
// Makes fd be the copy of this file descriptor, closing fd first if
|
||||||
// necessary.
|
// 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
|
// Creates a pipe setting up read_end and write_end file objects for reading
|
||||||
// and writing respectively.
|
// 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
|
// Creates a BufferedFile object associated with this file and detaches
|
||||||
// this File object from the file.
|
// this File object from the file.
|
||||||
BufferedFile fdopen(const char *mode);
|
FMT_API BufferedFile fdopen(const char *mode);
|
||||||
};
|
};
|
||||||
|
|
||||||
// Returns the memory page size.
|
// Returns the memory page size.
|
||||||
long getpagesize();
|
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
|
# define FMT_LOCALE
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -372,9 +336,9 @@ class Locale {
|
|||||||
public:
|
public:
|
||||||
typedef locale_t Type;
|
typedef locale_t Type;
|
||||||
|
|
||||||
Locale() : locale_(newlocale(LC_NUMERIC_MASK, "C", NULL)) {
|
Locale() : locale_(newlocale(LC_NUMERIC_MASK, "C", FMT_NULL)) {
|
||||||
if (!locale_)
|
if (!locale_)
|
||||||
throw fmt::SystemError(errno, "cannot create locale");
|
FMT_THROW(fmt::SystemError(errno, "cannot create locale"));
|
||||||
}
|
}
|
||||||
~Locale() { freelocale(locale_); }
|
~Locale() { freelocale(locale_); }
|
||||||
|
|
||||||
@@ -383,7 +347,7 @@ class Locale {
|
|||||||
// Converts string to floating-point number and advances str past the end
|
// Converts string to floating-point number and advances str past the end
|
||||||
// of the parsed input.
|
// of the parsed input.
|
||||||
double strtod(const char *&str) const {
|
double strtod(const char *&str) const {
|
||||||
char *end = 0;
|
char *end = FMT_NULL;
|
||||||
double result = strtod_l(str, &end, locale_);
|
double result = strtod_l(str, &end, locale_);
|
||||||
str = end;
|
str = end;
|
||||||
return result;
|
return result;
|
||||||
|
|||||||
@@ -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
|
||||||
@@ -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_
|
||||||
@@ -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
@@ -4,37 +4,25 @@
|
|||||||
Copyright (c) 2012 - 2016, Victor Zverovich
|
Copyright (c) 2012 - 2016, Victor Zverovich
|
||||||
All rights reserved.
|
All rights reserved.
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
For the license information refer to format.h.
|
||||||
modification, are permitted provided that the following conditions are met:
|
|
||||||
|
|
||||||
1. Redistributions of source code must retain the above copyright notice, this
|
|
||||||
list of conditions and the following disclaimer.
|
|
||||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
|
||||||
this list of conditions and the following disclaimer in the documentation
|
|
||||||
and/or other materials provided with the distribution.
|
|
||||||
|
|
||||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
||||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
||||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
||||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
|
||||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
||||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
||||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
|
||||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
||||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef FMT_TIME_H_
|
#ifndef FMT_TIME_H_
|
||||||
#define FMT_TIME_H_
|
#define FMT_TIME_H_
|
||||||
|
|
||||||
#include "fmt/format.h"
|
#include "format.h"
|
||||||
#include <ctime>
|
#include <ctime>
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
# pragma warning(push)
|
||||||
|
# pragma warning(disable: 4702) // unreachable code
|
||||||
|
# pragma warning(disable: 4996) // "deprecated" functions
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace fmt {
|
namespace fmt {
|
||||||
template <typename ArgFormatter>
|
template <typename ArgFormatter>
|
||||||
void format(BasicFormatter<char, ArgFormatter> &f,
|
void format_arg(BasicFormatter<char, ArgFormatter> &f,
|
||||||
const char *&format_str, const std::tm &tm) {
|
const char *&format_str, const std::tm &tm) {
|
||||||
if (*format_str == ':')
|
if (*format_str == ':')
|
||||||
++format_str;
|
++format_str;
|
||||||
const char *end = format_str;
|
const char *end = format_str;
|
||||||
@@ -54,11 +42,102 @@ void format(BasicFormatter<char, ArgFormatter> &f,
|
|||||||
buffer.resize(start + count);
|
buffer.resize(start + count);
|
||||||
break;
|
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;
|
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;
|
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_
|
#endif // FMT_TIME_H_
|
||||||
|
|||||||
@@ -10,22 +10,23 @@ platform = os.environ.get('PLATFORM')
|
|||||||
path = os.environ['PATH']
|
path = os.environ['PATH']
|
||||||
cmake_command = ['cmake', '-DFMT_PEDANTIC=ON', '-DCMAKE_BUILD_TYPE=' + config]
|
cmake_command = ['cmake', '-DFMT_PEDANTIC=ON', '-DCMAKE_BUILD_TYPE=' + config]
|
||||||
if build == 'mingw':
|
if build == 'mingw':
|
||||||
cmake_command.append('-GMinGW Makefiles')
|
cmake_command.append('-GMinGW Makefiles')
|
||||||
build_command = ['mingw32-make', '-j4']
|
build_command = ['mingw32-make', '-j4']
|
||||||
test_command = ['mingw32-make', 'test']
|
test_command = ['mingw32-make', 'test']
|
||||||
# Remove the path to Git bin directory from $PATH because it breaks MinGW config.
|
# Remove the path to Git bin directory from $PATH because it breaks
|
||||||
path = path.replace(r'C:\Program Files (x86)\Git\bin', '')
|
# MinGW config.
|
||||||
os.environ['PATH'] = r'C:\MinGW\bin;' + path
|
path = path.replace(r'C:\Program Files (x86)\Git\bin', '')
|
||||||
|
os.environ['PATH'] = r'C:\MinGW\bin;' + path
|
||||||
else:
|
else:
|
||||||
# Add MSBuild 14.0 to PATH as described in
|
# Add MSBuild 14.0 to PATH as described in
|
||||||
# http://help.appveyor.com/discussions/problems/2229-v140-not-found-on-vs2105rc.
|
# 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
|
os.environ['PATH'] = r'C:\Program Files (x86)\MSBuild\14.0\Bin;' + path
|
||||||
generator = 'Visual Studio 14 2015'
|
generator = 'Visual Studio 14 2015'
|
||||||
if platform == 'x64':
|
if platform == 'x64':
|
||||||
generator += ' Win64'
|
generator += ' Win64'
|
||||||
cmake_command.append('-G' + generator)
|
cmake_command.append('-G' + generator)
|
||||||
build_command = ['cmake', '--build', '.', '--config', config, '--', '/m:4']
|
build_command = ['cmake', '--build', '.', '--config', config, '--', '/m:4']
|
||||||
test_command = ['ctest', '-C', config]
|
test_command = ['ctest', '-C', config]
|
||||||
|
|
||||||
check_call(cmake_command)
|
check_call(cmake_command)
|
||||||
check_call(build_command)
|
check_call(build_command)
|
||||||
|
|||||||
@@ -20,3 +20,7 @@ build_script:
|
|||||||
on_failure:
|
on_failure:
|
||||||
- appveyor PushArtifact Testing/Temporary/LastTest.log
|
- appveyor PushArtifact Testing/Temporary/LastTest.log
|
||||||
- appveyor AddTest test
|
- 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'))
|
||||||
|
|||||||
@@ -20,7 +20,14 @@ if (FMT_USE_CPP11)
|
|||||||
check_cxx_source_compiles("
|
check_cxx_source_compiles("
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
int main() {}" FMT_CPP11_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)
|
set(CPP11_FLAG -std=c++11)
|
||||||
else ()
|
else ()
|
||||||
check_cxx_compiler_flag(-std=gnu++11 HAVE_STD_GNUPP11_FLAG)
|
check_cxx_compiler_flag(-std=gnu++11 HAVE_STD_GNUPP11_FLAG)
|
||||||
@@ -37,6 +44,11 @@ if (FMT_USE_CPP11)
|
|||||||
endif ()
|
endif ()
|
||||||
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})
|
set(CMAKE_REQUIRED_FLAGS ${CPP11_FLAG})
|
||||||
|
|
||||||
# Check if variadic templates are working and not affected by GCC bug 39653:
|
# Check if variadic templates are working and not affected by GCC bug 39653:
|
||||||
|
|||||||
@@ -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())
|
||||||
@@ -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('')
|
||||||
|
|
||||||
|
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())
|
||||||
@@ -6,34 +6,28 @@ import errno, os, re, shutil, sys, tempfile, urllib
|
|||||||
from subprocess import call, check_call, check_output, Popen, PIPE, STDOUT
|
from subprocess import call, check_call, check_output, Popen, PIPE, STDOUT
|
||||||
|
|
||||||
def rmtree_if_exists(dir):
|
def rmtree_if_exists(dir):
|
||||||
try:
|
try:
|
||||||
shutil.rmtree(dir)
|
shutil.rmtree(dir)
|
||||||
except OSError as e:
|
except OSError as e:
|
||||||
if e.errno == errno.ENOENT:
|
if e.errno == errno.ENOENT:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def makedirs_if_not_exist(dir):
|
def makedirs_if_not_exist(dir):
|
||||||
try:
|
try:
|
||||||
os.makedirs(dir)
|
os.makedirs(dir)
|
||||||
except OSError as e:
|
except OSError as e:
|
||||||
if e.errno != errno.EEXIST:
|
if e.errno != errno.EEXIST:
|
||||||
raise
|
raise
|
||||||
|
|
||||||
fmt_dir = os.path.dirname(os.path.dirname(os.path.realpath(__file__)))
|
def install_dependencies():
|
||||||
|
|
||||||
build = os.environ['BUILD']
|
|
||||||
if build == 'Doc':
|
|
||||||
travis = 'TRAVIS' in os.environ
|
|
||||||
# Install dependencies.
|
|
||||||
if travis:
|
|
||||||
branch = os.environ['TRAVIS_BRANCH']
|
branch = os.environ['TRAVIS_BRANCH']
|
||||||
if branch != 'master':
|
if branch != 'master':
|
||||||
print('Branch: ' + branch)
|
print('Branch: ' + branch)
|
||||||
exit(0) # Ignore non-master branches
|
exit(0) # Ignore non-master branches
|
||||||
check_call('curl -s https://deb.nodesource.com/gpgkey/nodesource.gpg.key | ' +
|
check_call('curl -s https://deb.nodesource.com/gpgkey/nodesource.gpg.key ' +
|
||||||
'sudo apt-key add -', shell=True)
|
'| sudo apt-key add -', shell=True)
|
||||||
check_call('echo "deb https://deb.nodesource.com/node_0.10 precise main" | ' +
|
check_call('echo "deb https://deb.nodesource.com/node_0.10 precise main" ' +
|
||||||
'sudo tee /etc/apt/sources.list.d/nodesource.list', shell=True)
|
'| sudo tee /etc/apt/sources.list.d/nodesource.list', shell=True)
|
||||||
check_call(['sudo', 'apt-get', 'update'])
|
check_call(['sudo', 'apt-get', 'update'])
|
||||||
check_call(['sudo', 'apt-get', 'install', 'python-virtualenv', 'nodejs'])
|
check_call(['sudo', 'apt-get', 'install', 'python-virtualenv', 'nodejs'])
|
||||||
check_call(['npm', 'install', '-g', 'less', 'less-plugin-clean-css'])
|
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/' +
|
urllib.urlretrieve('http://mirrors.kernel.org/ubuntu/pool/main/d/doxygen/' +
|
||||||
deb_file, deb_file)
|
deb_file, deb_file)
|
||||||
check_call(['sudo', 'dpkg', '-i', deb_file])
|
check_call(['sudo', 'dpkg', '-i', deb_file])
|
||||||
sys.path.insert(0, os.path.join(fmt_dir, 'doc'))
|
|
||||||
import build
|
fmt_dir = os.path.dirname(os.path.dirname(os.path.realpath(__file__)))
|
||||||
html_dir = build.build_docs()
|
|
||||||
repo = 'fmtlib.github.io'
|
build = os.environ['BUILD']
|
||||||
if travis and 'KEY' not in os.environ:
|
if build == 'Doc':
|
||||||
# Don't update the repo if building on Travis from an account that doesn't
|
travis = 'TRAVIS' in os.environ
|
||||||
# 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:
|
if travis:
|
||||||
cmd += ' https://$KEY@github.com/fmtlib/fmtlib.github.io.git master'
|
install_dependencies()
|
||||||
p = Popen(cmd, shell=True, stdout=PIPE, stderr=STDOUT, cwd=repo)
|
sys.path.insert(0, os.path.join(fmt_dir, 'doc'))
|
||||||
# Print the output without the key.
|
import build
|
||||||
print(p.communicate()[0].replace(os.environ['KEY'], '$KEY'))
|
build.create_build_env()
|
||||||
if p.returncode != 0:
|
html_dir = build.build_docs()
|
||||||
raise CalledProcessError(p.returncode, cmd)
|
repo = 'fmtlib.github.io'
|
||||||
exit(0)
|
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']
|
standard = os.environ['STANDARD']
|
||||||
install_dir = os.path.join(fmt_dir, "_install")
|
install_dir = os.path.join(fmt_dir, "_install")
|
||||||
@@ -83,11 +86,13 @@ test_build_dir = os.path.join(fmt_dir, "_build_test")
|
|||||||
# Configure library.
|
# Configure library.
|
||||||
makedirs_if_not_exist(build_dir)
|
makedirs_if_not_exist(build_dir)
|
||||||
common_cmake_flags = [
|
common_cmake_flags = [
|
||||||
'-DCMAKE_INSTALL_PREFIX=' + install_dir, '-DCMAKE_BUILD_TYPE=' + build
|
'-DCMAKE_INSTALL_PREFIX=' + install_dir, '-DCMAKE_BUILD_TYPE=' + build
|
||||||
]
|
]
|
||||||
extra_cmake_flags = []
|
extra_cmake_flags = []
|
||||||
if standard != '0x':
|
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] +
|
check_call(['cmake', '-DFMT_DOC=OFF', '-DFMT_PEDANTIC=ON', fmt_dir] +
|
||||||
common_cmake_flags + extra_cmake_flags, cwd=build_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 = os.environ.copy()
|
||||||
env['CTEST_OUTPUT_ON_FAILURE'] = '1'
|
env['CTEST_OUTPUT_ON_FAILURE'] = '1'
|
||||||
if call(['make', 'test'], env=env, cwd=build_dir):
|
if call(['make', 'test'], env=env, cwd=build_dir):
|
||||||
with open('Testing/Temporary/LastTest.log', 'r') as f:
|
with open('Testing/Temporary/LastTest.log', 'r') as f:
|
||||||
print(f.read())
|
print(f.read())
|
||||||
sys.exit(-1)
|
sys.exit(-1)
|
||||||
|
|
||||||
# Install library.
|
# Install library.
|
||||||
check_call(['make', 'install'], cwd=build_dir)
|
check_call(['make', 'install'], cwd=build_dir)
|
||||||
|
|||||||
@@ -8,23 +8,23 @@ import shutil, tempfile
|
|||||||
from subprocess import check_output, STDOUT
|
from subprocess import check_output, STDOUT
|
||||||
|
|
||||||
class Git:
|
class Git:
|
||||||
def __init__(self, dir):
|
def __init__(self, dir):
|
||||||
self.dir = dir
|
self.dir = dir
|
||||||
|
|
||||||
def __call__(self, *args):
|
def __call__(self, *args):
|
||||||
output = check_output(['git'] + list(args), cwd=self.dir, stderr=STDOUT)
|
output = check_output(['git'] + list(args), cwd=self.dir, stderr=STDOUT)
|
||||||
print(output)
|
print(output)
|
||||||
return output
|
return output
|
||||||
|
|
||||||
dir = tempfile.mkdtemp()
|
dir = tempfile.mkdtemp()
|
||||||
try:
|
try:
|
||||||
git = Git(dir)
|
git = Git(dir)
|
||||||
git('clone', '-b', 'coverity', 'git@github.com:fmtlib/fmt.git', dir)
|
git('clone', '-b', 'coverity', 'git@github.com:fmtlib/fmt.git', dir)
|
||||||
output = git('merge', '-X', 'theirs', '--no-commit', 'origin/master')
|
output = git('merge', '-X', 'theirs', '--no-commit', 'origin/master')
|
||||||
if 'Fast-forward' not in output:
|
if 'Fast-forward' not in output:
|
||||||
git('reset', 'HEAD', '.travis.yml')
|
git('reset', 'HEAD', '.travis.yml')
|
||||||
git('checkout', '--', '.travis.yml')
|
git('checkout', '--', '.travis.yml')
|
||||||
git('commit', '-m', 'Update coverity branch')
|
git('commit', '-m', 'Update coverity branch')
|
||||||
git('push')
|
git('push')
|
||||||
finally:
|
finally:
|
||||||
shutil.rmtree(dir)
|
shutil.rmtree(dir)
|
||||||
|
|||||||
@@ -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)
|
set(PEDANTIC_COMPILE_FLAGS -Wall -Wextra -Wno-long-long -Wno-variadic-macros)
|
||||||
endif ()
|
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.
|
# Adds a test.
|
||||||
# Usage: add_fmt_test(name srcs...)
|
# Usage: add_fmt_test(name srcs...)
|
||||||
function(add_fmt_test name)
|
function(add_fmt_test name)
|
||||||
add_executable(${name} ${name}.cc ${ARGN})
|
add_fmt_executable(${name} ${name}.cc ${ARGN})
|
||||||
target_link_libraries(${name} test-main)
|
target_link_libraries(${name} test-main)
|
||||||
|
|
||||||
# define if certain c++ features can be used
|
# define if certain c++ features can be used
|
||||||
target_compile_definitions(${name} PRIVATE
|
target_compile_definitions(${name} PRIVATE
|
||||||
FMT_USE_TYPE_TRAITS=$<BOOL:${SUPPORTS_TYPE_TRAITS}>
|
FMT_USE_TYPE_TRAITS=$<BOOL:${SUPPORTS_TYPE_TRAITS}>
|
||||||
@@ -72,13 +80,17 @@ function(add_fmt_test name)
|
|||||||
endfunction()
|
endfunction()
|
||||||
|
|
||||||
add_fmt_test(assert-test)
|
add_fmt_test(assert-test)
|
||||||
|
add_fmt_test(container-test)
|
||||||
add_fmt_test(gtest-extra-test)
|
add_fmt_test(gtest-extra-test)
|
||||||
add_fmt_test(format-test)
|
add_fmt_test(format-test)
|
||||||
add_fmt_test(format-impl-test)
|
add_fmt_test(format-impl-test)
|
||||||
add_fmt_test(ostream-test)
|
add_fmt_test(ostream-test)
|
||||||
add_fmt_test(printf-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(util-test mock-allocator.h)
|
||||||
add_fmt_test(macro-test)
|
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
|
# Enable stricter options for one test to make sure that the header is free of
|
||||||
# warnings.
|
# warnings.
|
||||||
@@ -87,7 +99,8 @@ if (FMT_PEDANTIC AND MSVC)
|
|||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
if (HAVE_OPEN)
|
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_include_directories(posix-mock-test PRIVATE ${PROJECT_SOURCE_DIR})
|
||||||
target_compile_definitions(posix-mock-test PRIVATE FMT_USE_FILE_DESCRIPTORS=1)
|
target_compile_definitions(posix-mock-test PRIVATE FMT_USE_FILE_DESCRIPTORS=1)
|
||||||
target_link_libraries(posix-mock-test gmock)
|
target_link_libraries(posix-mock-test gmock)
|
||||||
@@ -95,7 +108,7 @@ if (HAVE_OPEN)
|
|||||||
add_fmt_test(posix-test)
|
add_fmt_test(posix-test)
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
add_executable(header-only-test
|
add_fmt_executable(header-only-test
|
||||||
header-only-test.cc header-only-test2.cc test-main.cc)
|
header-only-test.cc header-only-test2.cc test-main.cc)
|
||||||
target_link_libraries(header-only-test gmock)
|
target_link_libraries(header-only-test gmock)
|
||||||
if (TARGET fmt-header-only)
|
if (TARGET fmt-header-only)
|
||||||
@@ -109,6 +122,7 @@ endif ()
|
|||||||
check_cxx_compiler_flag(-fno-exceptions HAVE_FNO_EXCEPTIONS_FLAG)
|
check_cxx_compiler_flag(-fno-exceptions HAVE_FNO_EXCEPTIONS_FLAG)
|
||||||
if (HAVE_FNO_EXCEPTIONS_FLAG)
|
if (HAVE_FNO_EXCEPTIONS_FLAG)
|
||||||
add_library(noexception-test ../fmt/format.cc)
|
add_library(noexception-test ../fmt/format.cc)
|
||||||
|
target_include_directories(noexception-test PRIVATE ${PROJECT_SOURCE_DIR})
|
||||||
target_compile_options(noexception-test PRIVATE -fno-exceptions)
|
target_compile_options(noexception-test PRIVATE -fno-exceptions)
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
@@ -116,6 +130,7 @@ if (FMT_PEDANTIC)
|
|||||||
# Test that the library compiles without windows.h.
|
# Test that the library compiles without windows.h.
|
||||||
if (CMAKE_SYSTEM_NAME STREQUAL "Windows")
|
if (CMAKE_SYSTEM_NAME STREQUAL "Windows")
|
||||||
add_library(no-windows-h-test ../fmt/format.cc)
|
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)
|
target_compile_definitions(no-windows-h-test PRIVATE FMT_USE_WINDOWS_H=0)
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
|
|||||||
@@ -5,9 +5,9 @@ project(fmt-test)
|
|||||||
add_subdirectory(../.. fmt)
|
add_subdirectory(../.. fmt)
|
||||||
|
|
||||||
add_executable(library-test "main.cc")
|
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")
|
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 ()
|
endif ()
|
||||||
|
|||||||
@@ -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());
|
||||||
|
}
|
||||||
@@ -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)
|
find_package(FMT REQUIRED)
|
||||||
|
|
||||||
add_executable(library-test main.cc)
|
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)
|
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 ()
|
endif ()
|
||||||
|
|||||||
@@ -26,10 +26,12 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#define FMT_NOEXCEPT
|
#define FMT_NOEXCEPT
|
||||||
|
#undef FMT_SHARED
|
||||||
#include "test-assert.h"
|
#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/format.cc"
|
||||||
|
#include "fmt/printf.cc"
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
@@ -46,7 +48,7 @@ TEST(FormatTest, ArgConverter) {
|
|||||||
Arg arg = Arg();
|
Arg arg = Arg();
|
||||||
arg.type = Arg::LONG_LONG;
|
arg.type = Arg::LONG_LONG;
|
||||||
arg.long_long_value = std::numeric_limits<fmt::LongLong>::max();
|
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);
|
EXPECT_EQ(Arg::LONG_LONG, arg.type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -43,8 +43,23 @@
|
|||||||
// Test that the library compiles if None is defined to 0 as done by xlib.h.
|
// Test that the library compiles if None is defined to 0 as done by xlib.h.
|
||||||
#define None 0
|
#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/format.h"
|
||||||
#include "fmt/time.h"
|
|
||||||
|
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "mock-allocator.h"
|
#include "mock-allocator.h"
|
||||||
@@ -235,7 +250,7 @@ TEST(WriterTest, Allocator) {
|
|||||||
std::size_t size =
|
std::size_t size =
|
||||||
static_cast<std::size_t>(1.5 * fmt::internal::INLINE_BUFFER_SIZE);
|
static_cast<std::size_t>(1.5 * fmt::internal::INLINE_BUFFER_SIZE);
|
||||||
std::vector<char> mem(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)
|
for (int i = 0; i < fmt::internal::INLINE_BUFFER_SIZE + 1; ++i)
|
||||||
w << '*';
|
w << '*';
|
||||||
EXPECT_CALL(alloc, deallocate(&mem[0], size));
|
EXPECT_CALL(alloc, deallocate(&mem[0], size));
|
||||||
@@ -917,7 +932,7 @@ TEST(FormatterTest, RuntimeWidth) {
|
|||||||
FormatError, "number is too big");
|
FormatError, "number is too big");
|
||||||
EXPECT_THROW_MSG(format("{0:{1}}", 0, -1l),
|
EXPECT_THROW_MSG(format("{0:{1}}", 0, -1l),
|
||||||
FormatError, "negative width");
|
FormatError, "negative width");
|
||||||
if (fmt::internal::check(sizeof(long) > sizeof(int))) {
|
if (fmt::internal::const_check(sizeof(long) > sizeof(int))) {
|
||||||
long value = INT_MAX;
|
long value = INT_MAX;
|
||||||
EXPECT_THROW_MSG(format("{0:{1}}", 0, (value + 1)),
|
EXPECT_THROW_MSG(format("{0:{1}}", 0, (value + 1)),
|
||||||
FormatError, "number is too big");
|
FormatError, "number is too big");
|
||||||
@@ -1036,7 +1051,7 @@ TEST(FormatterTest, RuntimePrecision) {
|
|||||||
FormatError, "number is too big");
|
FormatError, "number is too big");
|
||||||
EXPECT_THROW_MSG(format("{0:.{1}}", 0, -1l),
|
EXPECT_THROW_MSG(format("{0:.{1}}", 0, -1l),
|
||||||
FormatError, "negative precision");
|
FormatError, "negative precision");
|
||||||
if (fmt::internal::check(sizeof(long) > sizeof(int))) {
|
if (fmt::internal::const_check(sizeof(long) > sizeof(int))) {
|
||||||
long value = INT_MAX;
|
long value = INT_MAX;
|
||||||
EXPECT_THROW_MSG(format("{0:.{1}}", 0, (value + 1)),
|
EXPECT_THROW_MSG(format("{0:.{1}}", 0, (value + 1)),
|
||||||
FormatError, "number is too big");
|
FormatError, "number is too big");
|
||||||
@@ -1209,13 +1224,24 @@ TEST(FormatterTest, FormatOct) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TEST(FormatterTest, FormatIntLocale) {
|
TEST(FormatterTest, FormatIntLocale) {
|
||||||
#ifndef _WIN32
|
ScopedMock<LocaleMock> mock;
|
||||||
const char *locale = "en_US.utf-8";
|
lconv lc = lconv();
|
||||||
#else
|
char sep[] = "--";
|
||||||
const char *locale = "English_United States";
|
lc.thousands_sep = sep;
|
||||||
#endif
|
EXPECT_CALL(mock, localeconv()).Times(3).WillRepeatedly(testing::Return(&lc));
|
||||||
std::setlocale(LC_ALL, locale);
|
EXPECT_EQ("123", format("{:n}", 123));
|
||||||
EXPECT_EQ("1,234,567", format("{:n}", 1234567));
|
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) {
|
TEST(FormatterTest, FormatFloat) {
|
||||||
@@ -1327,6 +1353,8 @@ TEST(FormatterTest, FormatUCharString) {
|
|||||||
EXPECT_EQ("test", format("{0:s}", str));
|
EXPECT_EQ("test", format("{0:s}", str));
|
||||||
const unsigned char *const_str = str;
|
const unsigned char *const_str = str;
|
||||||
EXPECT_EQ("test", format("{0:s}", const_str));
|
EXPECT_EQ("test", format("{0:s}", const_str));
|
||||||
|
unsigned char *ptr = str;
|
||||||
|
EXPECT_EQ("test", format("{0:s}", ptr));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(FormatterTest, FormatPointer) {
|
TEST(FormatterTest, FormatPointer) {
|
||||||
@@ -1350,7 +1378,7 @@ TEST(FormatterTest, FormatCStringRef) {
|
|||||||
EXPECT_EQ("test", format("{0}", CStringRef("test")));
|
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();
|
f.writer() << d.year() << '-' << d.month() << '-' << d.day();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1363,7 +1391,7 @@ TEST(FormatterTest, FormatCustom) {
|
|||||||
class Answer {};
|
class Answer {};
|
||||||
|
|
||||||
template <typename Char>
|
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";
|
f.writer() << "42";
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1534,13 +1562,25 @@ TEST(FormatTest, Variadic) {
|
|||||||
EXPECT_EQ(L"abc1", format(L"{}c{}", L"ab", 1));
|
EXPECT_EQ(L"abc1", format(L"{}c{}", L"ab", 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(FormatTest, Time) {
|
TEST(FormatTest, JoinArg) {
|
||||||
std::tm tm = std::tm();
|
using fmt::join;
|
||||||
tm.tm_year = 116;
|
int v1[3] = { 1, 2, 3 };
|
||||||
tm.tm_mon = 3;
|
std::vector<float> v2;
|
||||||
tm.tm_mday = 25;
|
v2.push_back(1.2f);
|
||||||
EXPECT_EQ("The date is 2016-04-25.",
|
v2.push_back(3.4f);
|
||||||
fmt::format("The date is {:%Y-%m-%d}.", tm));
|
|
||||||
|
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>
|
template <typename T>
|
||||||
@@ -1644,3 +1684,10 @@ FMT_VARIADIC(void, custom_format, const char *)
|
|||||||
TEST(FormatTest, CustomArgFormatter) {
|
TEST(FormatTest, CustomArgFormatter) {
|
||||||
custom_format("{}", 42);
|
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);
|
||||||
|
}
|
||||||
|
|||||||
@@ -10090,8 +10090,9 @@ class FunctionMockerBase : public UntypedFunctionMockerBase {
|
|||||||
// threads concurrently.
|
// threads concurrently.
|
||||||
Result InvokeWith(const ArgumentTuple& args)
|
Result InvokeWith(const ArgumentTuple& args)
|
||||||
GTEST_LOCK_EXCLUDED_(g_gmock_mutex) {
|
GTEST_LOCK_EXCLUDED_(g_gmock_mutex) {
|
||||||
return static_cast<const ResultHolder*>(
|
const ResultHolder *rh = static_cast<const ResultHolder*>(
|
||||||
this->UntypedInvokeWith(&args))->GetValueAndDelete();
|
this->UntypedInvokeWith(&args));
|
||||||
|
return rh ? rh->GetValueAndDelete() : Result();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Adds and returns a default action spec for this mock function.
|
// Adds and returns a default action spec for this mock function.
|
||||||
|
|||||||
@@ -320,7 +320,7 @@ TEST(StreamingAssertionsTest, EXPECT_WRITE) {
|
|||||||
|
|
||||||
TEST(UtilTest, FormatSystemError) {
|
TEST(UtilTest, FormatSystemError) {
|
||||||
fmt::MemoryWriter out;
|
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"));
|
EXPECT_EQ(out.str(), format_system_error(EDOM, "test message"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -105,6 +105,6 @@ std::string read(File &f, std::size_t count) {
|
|||||||
|
|
||||||
std::string format_system_error(int error_code, fmt::StringRef message) {
|
std::string format_system_error(int error_code, fmt::StringRef message) {
|
||||||
fmt::MemoryWriter out;
|
fmt::MemoryWriter out;
|
||||||
fmt::internal::format_system_error(out, error_code, message);
|
fmt::format_system_error(out, error_code, message);
|
||||||
return out.str();
|
return out.str();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,7 +29,7 @@
|
|||||||
#define FMT_GTEST_EXTRA_H_
|
#define FMT_GTEST_EXTRA_H_
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <gtest/gtest.h>
|
#include <gmock/gmock.h>
|
||||||
|
|
||||||
#include "fmt/format.h"
|
#include "fmt/format.h"
|
||||||
|
|
||||||
@@ -172,4 +172,10 @@ std::string read(fmt::File &f, std::size_t count);
|
|||||||
|
|
||||||
#endif // FMT_USE_FILE_DESCRIPTORS
|
#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_
|
#endif // FMT_GTEST_EXTRA_H_
|
||||||
|
|||||||
@@ -2823,7 +2823,11 @@ inline int IsATTY(int /* fd */) { return 0; }
|
|||||||
inline int IsATTY(int fd) { return _isatty(fd); }
|
inline int IsATTY(int fd) { return _isatty(fd); }
|
||||||
# endif // GTEST_OS_WINDOWS_MOBILE
|
# endif // GTEST_OS_WINDOWS_MOBILE
|
||||||
inline int StrCaseCmp(const char* s1, const char* s2) {
|
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); }
|
inline char* StrDup(const char* src) { return _strdup(src); }
|
||||||
# endif // __BORLANDC__
|
# endif // __BORLANDC__
|
||||||
|
|||||||
@@ -36,8 +36,8 @@ class MockAllocator {
|
|||||||
MockAllocator() {}
|
MockAllocator() {}
|
||||||
MockAllocator(const MockAllocator &) {}
|
MockAllocator(const MockAllocator &) {}
|
||||||
typedef T value_type;
|
typedef T value_type;
|
||||||
MOCK_METHOD1_T(allocate, T* (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));
|
MOCK_METHOD2_T(deallocate, void (T *p, std::size_t n));
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename Allocator>
|
template <typename Allocator>
|
||||||
@@ -78,8 +78,10 @@ class AllocatorRef {
|
|||||||
|
|
||||||
Allocator *get() const { return alloc_; }
|
Allocator *get() const { return alloc_; }
|
||||||
|
|
||||||
value_type* allocate(std::size_t n) { return alloc_->allocate(n); }
|
value_type *allocate(std::size_t n, const value_type *h) {
|
||||||
void deallocate(value_type* p, std::size_t n) { alloc_->deallocate(p, n); }
|
return alloc_->allocate(n, h);
|
||||||
|
}
|
||||||
|
void deallocate(value_type *p, std::size_t n) { alloc_->deallocate(p, n); }
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // FMT_MOCK_ALLOCATOR_H_
|
#endif // FMT_MOCK_ALLOCATOR_H_
|
||||||
|
|||||||
@@ -25,7 +25,7 @@
|
|||||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "fmt/ostream.cc"
|
#include "fmt/ostream.h"
|
||||||
|
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include "gmock/gmock.h"
|
#include "gmock/gmock.h"
|
||||||
@@ -35,13 +35,6 @@
|
|||||||
using fmt::format;
|
using fmt::format;
|
||||||
using fmt::FormatError;
|
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) {
|
std::ostream &operator<<(std::ostream &os, const Date &d) {
|
||||||
os << d.year() << '-' << d.month() << '-' << d.day();
|
os << d.year() << '-' << d.month() << '-' << d.day();
|
||||||
return os;
|
return os;
|
||||||
@@ -128,22 +121,11 @@ TEST(OStreamTest, Print) {
|
|||||||
EXPECT_EQ("Don't panic!", os.str());
|
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) {
|
TEST(OStreamTest, WriteToOStream) {
|
||||||
std::ostringstream os;
|
std::ostringstream os;
|
||||||
fmt::MemoryWriter w;
|
fmt::MemoryWriter w;
|
||||||
w << "foo";
|
w << "foo";
|
||||||
fmt::write(os, w);
|
fmt::internal::write(os, w);
|
||||||
EXPECT_EQ("foo", os.str());
|
EXPECT_EQ("foo", os.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -188,5 +170,5 @@ TEST(OStreamTest, WriteToOStreamMaxSize) {
|
|||||||
data += n;
|
data += n;
|
||||||
size -= static_cast<std::size_t>(n);
|
size -= static_cast<std::size_t>(n);
|
||||||
} while (size != 0);
|
} while (size != 0);
|
||||||
fmt::write(os, w);
|
fmt::internal::write(os, w);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -453,12 +453,6 @@ TEST(BufferedFileTest, FilenoNoRetry) {
|
|||||||
fileno_count = 0;
|
fileno_count = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Mock>
|
|
||||||
struct ScopedMock : testing::StrictMock<Mock> {
|
|
||||||
ScopedMock() { Mock::instance = this; }
|
|
||||||
~ScopedMock() { Mock::instance = 0; }
|
|
||||||
};
|
|
||||||
|
|
||||||
struct TestMock {
|
struct TestMock {
|
||||||
static TestMock *instance;
|
static TestMock *instance;
|
||||||
} *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);
|
return LocaleMock::instance->newlocale(category_mask, locale, base);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef __APPLE__
|
#if defined(__APPLE__) || defined(__FreeBSD__)
|
||||||
typedef int FreeLocaleResult;
|
typedef int FreeLocaleResult;
|
||||||
#else
|
#else
|
||||||
typedef void FreeLocaleResult;
|
typedef void FreeLocaleResult;
|
||||||
|
|||||||
@@ -232,7 +232,7 @@ TEST(FileTest, MoveAssignmentClosesFile) {
|
|||||||
File OpenBufferedFile(int &fd) {
|
File OpenBufferedFile(int &fd) {
|
||||||
File f = open_file();
|
File f = open_file();
|
||||||
fd = f.descriptor();
|
fd = f.descriptor();
|
||||||
return std::move(f);
|
return f;
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(FileTest, MoveFromTemporaryInCtor) {
|
TEST(FileTest, MoveFromTemporaryInCtor) {
|
||||||
|
|||||||
@@ -29,6 +29,7 @@
|
|||||||
#include <climits>
|
#include <climits>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
|
||||||
|
#include "fmt/printf.h"
|
||||||
#include "fmt/format.h"
|
#include "fmt/format.h"
|
||||||
#include "gtest-extra.h"
|
#include "gtest-extra.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
@@ -201,6 +202,8 @@ TEST(PrintfTest, HashFlag) {
|
|||||||
|
|
||||||
TEST(PrintfTest, Width) {
|
TEST(PrintfTest, Width) {
|
||||||
EXPECT_PRINTF(" abc", "%5s", "abc");
|
EXPECT_PRINTF(" abc", "%5s", "abc");
|
||||||
|
EXPECT_PRINTF(" -42", "%5s", "-42");
|
||||||
|
EXPECT_PRINTF(" 0.123456", "%10s", 0.123456);
|
||||||
|
|
||||||
// Width cannot be specified twice.
|
// Width cannot be specified twice.
|
||||||
EXPECT_THROW_MSG(fmt::sprintf("%5-5d", 42), FormatError,
|
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::LongLong signed_value = 0;
|
||||||
fmt::ULongLong unsigned_value = 0;
|
fmt::ULongLong unsigned_value = 0;
|
||||||
// Apply integer promotion to the argument.
|
// Apply integer promotion to the argument.
|
||||||
fmt::ULongLong max = std::numeric_limits<U>::max();
|
using std::numeric_limits;
|
||||||
using fmt::internal::check;
|
fmt::ULongLong max = numeric_limits<U>::max();
|
||||||
if (check(max <= static_cast<unsigned>(std::numeric_limits<int>::max()))) {
|
using fmt::internal::const_check;
|
||||||
|
if (const_check(max <= static_cast<unsigned>(numeric_limits<int>::max()))) {
|
||||||
signed_value = static_cast<int>(value);
|
signed_value = static_cast<int>(value);
|
||||||
unsigned_value = static_cast<unsigned>(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);
|
signed_value = static_cast<unsigned>(value);
|
||||||
unsigned_value = static_cast<unsigned>(value);
|
unsigned_value = static_cast<unsigned>(value);
|
||||||
}
|
}
|
||||||
@@ -379,11 +383,13 @@ TEST(PrintfTest, Bool) {
|
|||||||
TEST(PrintfTest, Int) {
|
TEST(PrintfTest, Int) {
|
||||||
EXPECT_PRINTF("-42", "%d", -42);
|
EXPECT_PRINTF("-42", "%d", -42);
|
||||||
EXPECT_PRINTF("-42", "%i", -42);
|
EXPECT_PRINTF("-42", "%i", -42);
|
||||||
|
EXPECT_PRINTF("-42", "%s", -42);
|
||||||
unsigned u = 0 - 42u;
|
unsigned u = 0 - 42u;
|
||||||
EXPECT_PRINTF(fmt::format("{}", u), "%u", -42);
|
EXPECT_PRINTF(fmt::format("{}", u), "%u", -42);
|
||||||
EXPECT_PRINTF(fmt::format("{:o}", u), "%o", -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("{:X}", u), "%X", -42);
|
EXPECT_PRINTF(fmt::format("{:X}", u), "%X", -42);
|
||||||
|
EXPECT_PRINTF(fmt::format("{}", u), "%s", u);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(PrintfTest, LongLong) {
|
TEST(PrintfTest, LongLong) {
|
||||||
@@ -395,7 +401,11 @@ TEST(PrintfTest, LongLong) {
|
|||||||
|
|
||||||
TEST(PrintfTest, Float) {
|
TEST(PrintfTest, Float) {
|
||||||
EXPECT_PRINTF("392.650000", "%f", 392.65);
|
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.650000", "%F", 392.65);
|
||||||
|
EXPECT_PRINTF("392.65", "%s", 392.65);
|
||||||
char buffer[BUFFER_SIZE];
|
char buffer[BUFFER_SIZE];
|
||||||
safe_sprintf(buffer, "%e", 392.65);
|
safe_sprintf(buffer, "%e", 392.65);
|
||||||
EXPECT_PRINTF(buffer, "%e", 392.65);
|
EXPECT_PRINTF(buffer, "%e", 392.65);
|
||||||
@@ -420,6 +430,7 @@ TEST(PrintfTest, Inf) {
|
|||||||
|
|
||||||
TEST(PrintfTest, Char) {
|
TEST(PrintfTest, Char) {
|
||||||
EXPECT_PRINTF("x", "%c", 'x');
|
EXPECT_PRINTF("x", "%c", 'x');
|
||||||
|
EXPECT_PRINTF("x", "%s", 'x');
|
||||||
int max = std::numeric_limits<int>::max();
|
int max = std::numeric_limits<int>::max();
|
||||||
EXPECT_PRINTF(fmt::format("{}", static_cast<char>(max)), "%c", max);
|
EXPECT_PRINTF(fmt::format("{}", static_cast<char>(max)), "%c", max);
|
||||||
//EXPECT_PRINTF("x", "%lc", L'x');
|
//EXPECT_PRINTF("x", "%lc", L'x');
|
||||||
@@ -438,13 +449,17 @@ TEST(PrintfTest, Pointer) {
|
|||||||
int n;
|
int n;
|
||||||
void *p = &n;
|
void *p = &n;
|
||||||
EXPECT_PRINTF(fmt::format("{}", p), "%p", p);
|
EXPECT_PRINTF(fmt::format("{}", p), "%p", p);
|
||||||
|
EXPECT_PRINTF(fmt::format("{}", p), "%s", p);
|
||||||
p = 0;
|
p = 0;
|
||||||
EXPECT_PRINTF("(nil)", "%p", p);
|
EXPECT_PRINTF("(nil)", "%p", p);
|
||||||
EXPECT_PRINTF(" (nil)", "%10p", p);
|
EXPECT_PRINTF(" (nil)", "%10p", p);
|
||||||
|
EXPECT_PRINTF("(nil)", "%s", p);
|
||||||
|
EXPECT_PRINTF(" (nil)", "%10s", p);
|
||||||
const char *s = "test";
|
const char *s = "test";
|
||||||
EXPECT_PRINTF(fmt::format("{:p}", s), "%p", s);
|
EXPECT_PRINTF(fmt::format("{:p}", s), "%p", s);
|
||||||
const char *null_str = 0;
|
const char *null_str = 0;
|
||||||
EXPECT_PRINTF("(nil)", "%p", null_str);
|
EXPECT_PRINTF("(nil)", "%p", null_str);
|
||||||
|
EXPECT_PRINTF("(null)", "%s", null_str);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(PrintfTest, Location) {
|
TEST(PrintfTest, Location) {
|
||||||
@@ -477,3 +492,20 @@ TEST(PrintfTest, PrintfError) {
|
|||||||
TEST(PrintfTest, WideString) {
|
TEST(PrintfTest, WideString) {
|
||||||
EXPECT_EQ(L"abc", fmt::sprintf(L"%s", L"abc"));
|
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());
|
||||||
|
}
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user